YUV数据格式

YUV格式有两大类:planar和packed。
对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。

对于packed的YUV格式,每个像素点的Y,U,V是连续交存储的。


YUV码流的存储格式其实与其采样的方式密切相关,主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0

用三个图来直观地表示采集的方式吧,以黑点表示采样该像素点的Y分量,以空心圆圈表示采用该像素点的UV分量。

 

YUV数据格式

先记住下面这段话,以后提取每个像素的YUV分量会用到。

  1. YUV 4:4:4采样,每一个Y对应一组UV分量。
  2. YUV 4:2:2采样,每两个Y共用一组UV分量。 
  3. YUV 4:2:0采样,每四个Y共用一组UV分量。 


在FFmpeg中,图像原始数据包括两种:planar和packed。planar就是将几个分量分开存,比如YUV420中,data[0]专门存Y,data[1]专门存U,data[2]专门存V。而packed则是打包存,所有数据都存在data[0]中.

AVFrame *src_frame = av_frame_alloc();
AVFrame *dst_frame = av_frame_alloc();
if (src_frame == NULL || dst_frame == NULL) {
    ALOGE("av_frame_alloc fail\n");
    return;
}
// 计算这个格式的图片,需要多少字节来存储

AVPixelFormat src_fmt = AV_PIX_FMT_YUV420P;
AVPixelFormat dst_fmt = AV_PIX_FMT_YUYV422;
int src_bytes_num = av_image_get_buffer_size(src_fmt, width, height, 1);
int dst_bytes_num = av_image_get_buffer_size(dst_fmt, width, height, 1);

// 申请空间来存放图片数据, 包含源数据和目标数据
uint8_t *src_buff = (uint8_t *) av_malloc(src_bytes_num);
uint8_t *dst_buff = (uint8_t *) av_malloc(dst_bytes_num);

//av_frame_alloc函数,只是为这个AVFrame结构体分配了内存,而该类型的指针指向的内存还没分配
//通过av_image_fill_arrays把av_malloc得到的内存和AVFrame关联起来
av_image_fill_arrays(src_frame->data, src_frame->linesize, src_buff, AV_PIX_FMT_RGBA,
                     width, height, 1);
av_image_fill_arrays(dst_frame->data, dst_frame->linesize, dst_buff, AV_PIX_FMT_RGBA,
                     width, height, 1);

ALOGE("%d %d %d", src_frame->linesize[0], src_frame->linesize[1], src_frame->linesize[2]);
ALOGE("%d %d %d", dst_frame->linesize[0], dst_frame->linesize[1], dst_frame->linesize[2]);