学习记录:RGBA格式数据加边框
生活随笔
收集整理的這篇文章主要介紹了
学习记录:RGBA格式数据加边框
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
項目場景:
最近學習使用ffmpeg在做一個視頻縮略圖的例子。在這里做一個記錄。 在網上找了很多資料,加邊框都是更改圖片外圍數據,這樣圖片會缺失一部分,不太符合我的需求。 按照這個思路,下面是一種實現在原始圖片的基礎上,在外部添加一個框。參考大神的文章:https://blog.csdn.net/leixiaohua1020/article/details/15811977
需求描述:
- 需要獲取指定時間點處的視頻縮略圖。
- 縮略圖需要保持原有的長寬比列,縮放至480x360,缺失的部分使用純色填充。
實現計劃:
具體實現:
1.計算縮放后的視頻分辨率
//視頻原始大小 m_VideoWidth = pCodecCtx->width; m_VideoHeight = pCodecCtx->height;//calculate //m_width 和 m_height 是用戶規定的大小,這里設置為480x360 //m_SwsWidth 和 m_SwsHeight是視頻縮放后的大小 if (m_VideoWidth <= m_width && m_VideoHeight <= m_height) {m_SwsWidth = m_VideoWidth;m_SwsHeight = m_VideoHeight; }else if(m_VideoWidth <= m_width && m_VideoHeight > m_height) {float cc_h = (double)m_VideoHeight / m_height;m_SwsHeight = m_height;m_SwsWidth = m_VideoWidth / cc_h; }else if(m_VideoWidth > m_width && m_VideoHeight <= m_height) {float cc_w = (double)m_VideoWidth / m_width;m_SwsWidth = m_width;m_SwsHeight = m_VideoHeight / cc_w; }else{//m_VideoWidth > m_width && m_VideoHeight > m_heightfloat cc_w = (double)m_VideoWidth / m_width;float cc_h = (double)m_VideoHeight / m_height;if(cc_w >= cc_h){m_SwsWidth = m_width;m_SwsHeight = m_VideoHeight / cc_w;}else{m_SwsHeight = m_height;m_SwsWidth = m_VideoWidth / cc_h;} }printf("video:width = %d, height = %d.\n", m_VideoWidth, m_VideoHeight); printf("user:width = %d, height = %d.\n", m_width, m_height); printf("SWS:width = %d, height = %d.\n", m_SwsWidth, m_SwsHeight);2.由于我使用的是ffmpeg 4.3.2版本,所以解碼過程如下:
AVPacket packet; AVFrame *frame;frame = av_frame_alloc();/* read all packets */while (1) {if ((ret = av_read_frame(fmt_ctx, &packet)) < 0)break;if (packet.stream_index == video_stream_index) {ret = avcodec_send_packet(dec_ctx, &packet);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Error while sending a packet to the decoder\n");break;}while (ret >= 0) {ret = avcodec_receive_frame(dec_ctx, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {break;} else if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Error while receiving a frame from the decoder\n");goto end;}//這里我們拿到了一包解碼后的數據frame.av_frame_unref(frame);}}av_packet_unref(&packet);}3.使用swscale進行格式轉換和縮放。
AVFrame *pRgba = av_frame_alloc();int video_size = av_image_get_buffer_size(AV_PIX_FMT_RGBA, m_SwsWidth, m_SwsHeight, 1); uint8_t * picture_buf = (uint8_t *)av_malloc(video_size); //picture_buf 指向pRgba的data av_image_fill_arrays(pRgba->data, pRgba->linesize, picture_buf, AV_PIX_FMT_RGBA, m_SwsWidth, m_SwsHeight, 1); //視頻像素數據格式轉換上下文 SwsContext *sws_ctx = sws_getContext(dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, /*INPUT W H FMT*/m_SwsWidth, m_SwsHeight, AV_PIX_FMT_RGBA, /*OUTPUT W H FMT*/SWS_BICUBIC, /*拉伸算法*/NULL, NULL, NULL); /*其他參數*/ //將AVFrame轉成視頻像素數YUV420P格式 sws_scale(sws_ctx, (const uint8_t * const *)frame->data, frame->linesize,0, dec_ctx->height, pRgba->data, pRgba->linesize); sws_freeContext(sws_ctx); av_frame_free(&pRgba);4.拿到picture_buf后,需要進行判斷并填充。測試視頻為3840x2160
了解rgba數據格式,參考:[FFmpeg] RGBA 和 YUV 存儲方式
-
m_width == m_SwsWidth && m_height == m_SwsHeight:
這個是最簡單的,不需要任何處理。 -
m_width == m_SwsWidth && m_height > m_SwsHeight:
寬度相同,但是高度不匹配,需要對上下分別填充 m_width * (m_height - m_SwsHeight)/2 邊框。
原圖縮放后:
加上邊框后:
- m_width > m_SwsWidth && m_height == m_SwsHeight:
高度相同,但是寬度不匹配,需要對左右分別填充 (m_width - m_SwsWidth )/2 * m_height 邊框。
- m_width > m_SwsWidth && m_height > m_SwsHeight:
寬度和高度不匹配,需要對上下m_width * (m_height - m_SwsHeight)/2 邊框,左右 (m_width - m_SwsWidth )/2 * m_SwsHeight。
總結
以上是生活随笔為你收集整理的学习记录:RGBA格式数据加边框的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python连接ALM
- 下一篇: 高可用集群下的负载均衡(7):hapro