sws_scale的图像色彩空间转换

阅读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);

代码分析:

  1. 首先获取SwsContext
  2. av_image_alloc根据width, height, pix_fmt初始化linesize[4], data[4]
  3. sws_scale色彩转换,完成yuv到rgb的转换
  4. 将data[0]的数据全部copy到framedata.data()

你可能感兴趣的:(sws_scale的图像色彩空间转换)