ffmpeg rgb与yuv的转换

ffmpeg里的libswscale库用于图像数据格式的转换.

AVFrame 类型对象用于描述非压缩的音视频数据信息, 此对象本身不提供存储音视频数据的缓冲区,只用于记录数据格式,图像分辨率,数据缓冲区地址等信息.

typedef struct AVFrame {
    #define AV_NUM_DATA_POINTERS 8
    uint8_t *data[AV_NUM_DATA_POINTERS]; //此指针数组是用于存放数据缓冲区地址,因有可能是平面的数据,所有用了多个指针变量存放不同分量的数据缓冲区
    int linesize[AV_NUM_DATA_POINTERS]; //存放每个缓冲区的一行数据的字节数
	...
}AVFrame

所用的函数说明:

AVFrame *av_frame_alloc(void); //用于动态创建一个AVFrame对象

//因AVFrame本身不提供存储数据的缓冲区,所以需要创建出数据缓冲区后再使用下面函数配置AVFrame对象
int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],
                         const uint8_t *src,
                         enum AVPixelFormat pix_fmt, int width, int height, int align);



struct SwsContext; //此类型对象用于描述原数据格式及目标格式, 原分辨率及目标分辨率等.

// sws_getContext函数根据指定的参数生成一个SwsContext对象
struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
                                  int dstW, int dstH, enum AVPixelFormat dstFormat,
                                  int flags, SwsFilter *srcFilter,
                                  SwsFilter *dstFilter, const double *param);
// flags参数是原分辨率与目标分辨率不一致时使用哪种算法来调整.
// srcFilter, dstFilter设置原图形及生成的图像使用的过滤算法. 不会可设为NULL
// param参数指定调整图像缩放的算法. 可设为NULL使用默认算法.

int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
              const int srcStride[], int srcSliceY, int srcSliceH,
              uint8_t *const dst[], const int dstStride[]);
// c参数指定使用包含图像数据格式转换信息的struct SwsContext对象
// srcSlice参数用于指定的原图像数据缓冲区地址
// srcStride参数用于指定原数据缓冲区一行数据的大小
// srcSliceY参数用于指定从原图像的第几行开始转换
// srcSliceH参数用于指定转换到原图像的第几行.
// dst参数用于指定存放生成图像数据的缓冲区地址
// dstStride参数指定存放生成图像的一行数据大小的缓冲区


用法, 如yuv422转换成420p:

1. 创建AVFrame对象
    AVFrame  *frm422 = av_frame_alloc();
    AVFrame  *frm420p = av_frame_alloc();

2. 绑定数据缓冲区
    av_image_fill_arrays(frm422->data, frm422->linesize, buf_422, AV_PIX_FMT_YUYV422, w, h, 16);
    av_image_fill_arrays(frm420p->data, frm420p->linesize, buf_420p, AV_PIX_FMT_YUV420P, w, h, 16);

3. 指定原数据格式,分辨率及目标数据格式,分辨率
    struct SwsContext *sws = sws_getContext(w, h, AV_PIX_FMT_YUYV422, w,h, AV_PIX_FMT_YUV420P,
                                            SWS_BILINEAR, NULL, NULL, NULL);

4. 转换并调整分辨率
    int ret = sws_scale(sws, frm422->data, frm422->linesize, 0, h, frm420p->data, frm420p->linesize);

5. 回收空间
    av_frame_free(&frm422);
    av_frame_free(&frm420p);
    sws_freeContext(sws);

________________________________________________________-
用法, argb转换成yuv420p:

int MyDataCovert::argb32Toyuv420p(uint8_t *buf_argb, uint8_t *buf_420p, int w, int h)
{
    AVFrame  *frmArgb = av_frame_alloc();
    AVFrame  *frm420p = av_frame_alloc();

    //绑定数据缓冲区
    avpicture_fill((AVPicture *)frmArgb, buf_argb, AV_PIX_FMT_BGRA, w, h);
    avpicture_fill((AVPicture *)frm420p, buf_420p, AV_PIX_FMT_YUV420P, w, h);

    //指定原数据格式,分辨率及目标数据格式,分辨率
    struct SwsContext *sws = sws_getContext(w, h, AV_PIX_FMT_BGRA, w,h, AV_PIX_FMT_YUV420P,
                                            SWS_BILINEAR, NULL, NULL, NULL);

    //转换
    int ret = sws_scale(sws, frmArgb->data, frmArgb->linesize, 0, h, frm420p->data, frm420p->linesize);
    av_frame_free(&frmArgb);
    av_frame_free(&frm420p);
    sws_freeContext(sws);
    return  (ret == h) ? 0 : -1;
}

你可能感兴趣的:(ffmpeg)