从YUV420p数据构造AVFrame

论坛 期权论坛 脚本     
匿名网站用户   2020-12-21 08:15   35   0

前言

书接上文,发现 YUV420p各个通道不一致的问题后。就猜测FFmpeg里面应该对这点做了处理了吧

自己构造AVFrame

ffmepg里面的demo,encode_video.c,里面已经有了,我稍微修改了下。
网上很多构造AVFrame视频帧的代码已经过时了。

void ProducerScreenCapture::appendYuvFrame(char *yData,int yPerRowBytes,
                    char *uData,int uPerRowBytes,
                    char *vData,int vPerRowBytes,
                    int frameWidth,int frameHeight)
{
    AVFrame *t_pFrame = av_frame_alloc();//av_frame_free()
    t_pFrame->width = frameWidth;
    t_pFrame->height = frameHeight;
    t_pFrame->format = AV_PIX_FMT_YUV420P;
    int t_ret = av_frame_get_buffer(t_pFrame,32);//申请了AVFrame的内存
    if(t_ret < 0)
    {
        qDebug()<<"robin:av_frame_get_buffer,Could not allocate the video frame data";
        return;
    }
    av_frame_make_writable(t_pFrame);


    av_image_copy_plane(t_pFrame->data[0],t_pFrame->linesize[0],(const uint8_t*)yData,yPerRowBytes,yPerRowBytes,frameHeight);
    av_image_copy_plane(t_pFrame->data[1],t_pFrame->linesize[1],(const uint8_t*)uData,uPerRowBytes,yPerRowBytes / 2,frameHeight);
    av_image_copy_plane(t_pFrame->data[2],t_pFrame->linesize[2],(const uint8_t*)vData,vPerRowBytes,yPerRowBytes / 2,frameHeight);

... 保存起来

发现一个函数av_image_copy_plane,很是不明白。

/**
 * Copy image plane from src to dst.
 * That is, copy "height" number of lines of "bytewidth" bytes each.
 * The first byte of each successive line is separated by *_linesize
 * bytes.
 *
 * bytewidth must be contained by both absolute values of dst_linesize
 * and src_linesize, otherwise the function behavior is undefined.
 *
 * @param dst_linesize linesize for the image plane in dst
 * @param src_linesize linesize for the image plane in src
 */
void av_image_copy_plane(uint8_t       *dst, int dst_linesize,
                         const uint8_t *src, int src_linesize,
                         int bytewidth, int height);

看了函数说明还是不太明白
后来,看了源代码,就知道了

void av_image_copy_plane(uint8_t       *dst, int dst_linesize,
                           const uint8_t *src, int src_linesize,
                           int bytewidth, int height)
  {
      image_copy_plane(dst, dst_linesize, src, src_linesize, bytewidth, height);
  }
******************************************
******************************************
static void image_copy_plane(uint8_t *dst, ptrdiff_t dst_linesize,
const uint8_t *src, ptrdiff_t src_linesize,
ptrdiff_t bytewidth, int height)
{
   if (!dst || !src)
       return;
   av_assert0(abs(src_linesize) >= bytewidth);
   av_assert0(abs(dst_linesize) >= bytewidth);
   for (;height > 0; height--) {
       memcpy(dst, src, bytewidth);
       dst += dst_linesize;
       src += src_linesize;
   }
}

void av_image_copy_plane(uint8_t       *dst, int dst_linesize,
                           const uint8_t *src, int src_linesize,
                           int bytewidth, int height)

其中 bytewidth 才是每次实际要复制的数据长度。
而 dst_linesize 和 src_linesize 则是为了内存对齐数据而存在的。
从这里可以看出,内存数据的循环复制还是免不了啊。^o^

总结

AVFrame 进化了这么些年,现在已经提供了更简洁的方式申请内存空间
av_image_copy_plane,提供了通道数据的复制功能。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP