阅读ffmpegthumbnailer的代码,其中MovieDecoder::getScaledVideoFrame,将解码出来的avFrame送给filter,其中有rgb24这个format filter,经过这个转换,然后copy到VideoFrame的frameData中:
videoFrame.frameData.resize(videoFrame.lineSize * videoFrame.height);
memcpy((videoFrame.frameData.data()), res->data[0], videoFrame.frameData.size());
单从代码来看,这个地方直接拷贝的res->data[0]给videoFrame.frameData.data(),没有处理res->data[1],res->data[2],所以直观判断,这里已经是全部的数据了。
所以根据这一点,实现了下面的函数,通过sw_scale进行格式转换,不用再走过多的filter。还有一种思路,就是实现一个yuv到rgb的转换函数,把m_pFrame中的数据直接写到VideoFrame的frameData中,这个效率应该是最高的。
videoFrame.width = m_pFrame->width;
videoFrame.height = m_pFrame->height;
int linesize[4];
uint8_t* data[4];
struct SwsContext *swsContext = NULL;
swsContext = sws_getContext(m_pFrame->width, m_pFrame->height, AVPixelFormat(m_pFrame->format),
videoFrame.width, videoFrame.height, AV_PIX_FMT_RGB24,
SWS_BILINEAR, NULL, NULL, NULL);
av_image_alloc(data, linesize, videoFrame.width, videoFrame.height, AV_PIX_FMT_RGB24, 1);
sws_scale(swsContext, m_pFrame->data, m_pFrame->linesize, 0, m_pFrame->height, data, linesize);
videoFrame.lineSize = linesize[0];
videoFrame.frameData.resize(videoFrame.lineSize * videoFrame.height);
memcpy(videoFrame.frameData.data(), data[0], videoFrame.frameData.size());
sws_freeContext(swsContext);
avpicture_free((AVPicture *)data);
代码分析:
- 首先获取SwsContext
- av_image_alloc根据width, height, pix_fmt初始化linesize[4], data[4]
- sws_scale色彩转换,完成yuv到rgb的转换
- 将data[0]的数据全部copy到framedata.data()
网友评论