FFMPEG--图像处理Swscale
来源:互联网 发布:joel说软件 pdf 编辑:程序博客网 时间:2024/06/10 23:41
SwsContext可用于缩放yuv/rgb图像的大小或者改变其像素点颜色空间格式。
初始化
Libswscale使用起来很方便,最主要的函数只有3个:
(1) sws_getContext():使用参数初始化SwsContext结构体。
(2) sws_scale():转换一帧图像。
(3) sws_freeContext():释放SwsContext结构体。
其中sws_getContext()也可以用另一个接口函数sws_getCachedContext()取代。
像素格式
(1)后缀带P的如yuv420p,则y/u/v分别存放在AVFrame.data[0]/data[1]/data[2]。
(2)后缀不带P的如rgb24,则rgb数据都存放在AVFrame.data[0]中。
AVFrame
本文实例是通过将图像读取到AVFrame中,然后在进行swscale处理的,所以这里介绍下AVFrame的初始化及处理
注意,我们操作yuv数据时,要根据像素格式,响应的访问avFrame.data[0/1/2],以获取正确的yuv数据。
//初始化源图AVFrame结构 AVFrame* ptFrameSrc= av_frame_alloc(); int dwSrcPictureSize = avpicture_get_size(em_Src_Pix_fmt, dwSrc_Width, dwSrc_Height); //上边的只是alloc了一个AVFrame的结构体,真正数据存放在pbySrcBuf中 uint8_t* pbySrcBuf = (uint8_t*)av_malloc(dwSrcPictureSize); avpicture_fill((AVPicture *)ptFrameSrc, pbySrcBuf, em_Src_Pix_fmt, dwSrc_Width, dwSrc_Height);
示例
#include <stdio.h>extern "C"{#include <libswscale/swscale.h>#include <libavutil/opt.h>#include <libavutil/imgutils.h>#include <libavutil/frame.h>#include <libavcodec/avcodec.h>};#define _SRC_WIDTH 1920#define _SRC_HEIGHT 1080#define _DST_WIDTH 1280#define _DST_HEIGHT 720#define _SRC_FILE_NAME "1080P.420pyuv"#define _DST_FILE_NAME "720P.422pyuv"#define ASSERT(X) if(!(X)){printf("####[%s:%d]assert failed:%s\n", __FUNCTION__, __LINE__, #X);}int main(){ //源图像信息 const int dwSrc_Width = _SRC_WIDTH; const int dwSrc_Height =_SRC_HEIGHT; enum AVPixelFormat em_Src_Pix_fmt = AV_PIX_FMT_YUV420P; int dwSrc_YSize = dwSrc_Width * dwSrc_Height; int dwSrc_UVSize = dwSrc_YSize/4; //初始化源图AVFrame结构 AVFrame* ptFrameSrc= av_frame_alloc(); int dwSrcPictureSize = avpicture_get_size(em_Src_Pix_fmt, dwSrc_Width, dwSrc_Height); //上边的只是alloc了一个AVFrame的结构体,真正数据存放在pbySrcBuf中 uint8_t* pbySrcBuf = (uint8_t*)av_malloc(dwSrcPictureSize); avpicture_fill((AVPicture *)ptFrameSrc, pbySrcBuf, em_Src_Pix_fmt, dwSrc_Width, dwSrc_Height); FILE* pf_Src = fopen(_SRC_FILE_NAME, "rb"); ASSERT(pf_Src != NULL); //目的图像信息 const int dwDst_Width = _DST_WIDTH; const int dwDst_Height = _DST_HEIGHT; enum AVPixelFormat em_Dst_Pix_fmt = AV_PIX_FMT_RGB24; int dwDst_YSize = dwDst_Width * dwDst_Height; int dwDst_UVSize = dwDst_YSize; //初始化目的图像AVFrame结构 AVFrame* ptFrameDst= av_frame_alloc(); int dwDstPictureSize = avpicture_get_size(em_Dst_Pix_fmt, dwDst_Width, dwDst_Height); printf("dwDstPictureSize:%d\n", dwDstPictureSize); uint8_t* pbyDstBuf = (uint8_t*)av_malloc(dwDstPictureSize); avpicture_fill((AVPicture *)ptFrameDst, pbyDstBuf, em_Dst_Pix_fmt, dwDst_Width, dwDst_Height); printf("Dst:(w:%d, h:%d), line0:%d, lin1:%d, line2:%d\n", ptFrameDst->width, ptFrameDst->height, ptFrameDst->linesize[0], ptFrameDst->linesize[1], ptFrameDst->linesize[2]); printf("Dst: data0-%p,%p, data1-%p,%p, data2-%p\n", ptFrameDst->data[0], ptFrameDst->data[0] + dwDst_YSize, ptFrameDst->data[1], ptFrameDst->data[1] + dwDst_YSize/2, ptFrameDst->data[2]); FILE* pf_Dst = fopen(_DST_FILE_NAME, "wb"); ASSERT(pf_Dst != NULL); //获取SwsContext struct SwsContext* ptImgConvertCtx = sws_getContext(dwSrc_Width, dwSrc_Height, em_Src_Pix_fmt, \ dwDst_Width, dwDst_Height, em_Dst_Pix_fmt, SWS_BICUBIC, NULL, NULL, NULL); ASSERT(ptImgConvertCtx != NULL); int dwCnt = 0; for(;;) { //一帧AV_PIX_FMT_YUV420P图像的大小dwSrc_YSize*3/2, 而且这里的data[0] data[1] data[2]必定是连续的 ASSERT((ptFrameSrc->data[1]) == (ptFrameSrc->data[0] + dwSrc_YSize)); ASSERT((ptFrameSrc->data[2]) == (ptFrameSrc->data[1] + dwSrc_YSize/4)); int dwRWSize = fread(ptFrameSrc->data[0], 1, dwSrc_YSize, pf_Src); dwRWSize += fread(ptFrameSrc->data[1], 1, dwSrc_UVSize, pf_Src); dwRWSize += fread(ptFrameSrc->data[2], 1, dwSrc_UVSize, pf_Src); if (dwRWSize <=0) { if (feof(pf_Src)) { fclose(pf_Src); fclose(pf_Dst); pf_Src = NULL; pf_Dst = NULL; av_log(NULL, AV_LOG_INFO, "end of src file\n"); break; } } dwCnt++; if (!ptFrameSrc->height) { //很奇怪的是avpicture_fill仅设置了ptFraemSrc的data和linesize, 并没有设置ptFrameSrc的宽高值, ptFrameSrc->height = dwSrc_Height; } //sws处理 sws_scale(ptImgConvertCtx, (const uint8_t* const*)ptFrameSrc->data, ptFrameSrc->linesize, 0, ptFrameSrc->height, ptFrameDst->data, ptFrameDst->linesize); dwRWSize = fwrite(ptFrameDst->data[0], 1, dwDst_YSize*3, pf_Dst); //dwRWSize = fwrite(ptFrameDst->data[1], 1, dwDst_UVSize, pf_Dst); //dwRWSize = fwrite(ptFrameDst->data[2], 1, dwDst_UVSize, pf_Dst); fflush(pf_Dst); } av_frame_free(&ptFrameSrc); //记得释放 av_frame_free(&ptFrameDst); sws_freeContext(ptImgConvertCtx);}
雷神的一个相关文章给了另外的操作swscale的方式,我这里复制下来,想看原文的可以通过最后的连接看:
#include <stdio.h> extern "C" { #include "libswscale/swscale.h" #include "libavutil/opt.h" #include "libavutil/imgutils.h" }int main(int argc, char* argv[]) { //Parameters FILE *src_file =fopen("sintel_480x272_yuv420p.yuv", "rb"); const int src_w=480,src_h=272; AVPixelFormat src_pixfmt=AV_PIX_FMT_YUV420P; int src_bpp=av_get_bits_per_pixel(av_pix_fmt_desc_get(src_pixfmt)); FILE *dst_file = fopen("sintel_1280x720_rgb24.rgb", "wb"); const int dst_w=1280,dst_h=720; AVPixelFormat dst_pixfmt=AV_PIX_FMT_RGB24; int dst_bpp=av_get_bits_per_pixel(av_pix_fmt_desc_get(dst_pixfmt)); //Structures uint8_t *src_data[4]; int src_linesize[4]; uint8_t *dst_data[4]; int dst_linesize[4]; int rescale_method=SWS_BICUBIC; struct SwsContext *img_convert_ctx; uint8_t *temp_buffer=(uint8_t *)malloc(src_w*src_h*src_bpp/8); int frame_idx=0; int ret=0; ret= av_image_alloc(src_data, src_linesize,src_w, src_h, src_pixfmt, 1); if (ret< 0) { printf( "Could not allocate source image\n"); return -1; } ret = av_image_alloc(dst_data, dst_linesize,dst_w, dst_h, dst_pixfmt, 1); if (ret< 0) { printf( "Could not allocate destination image\n"); return -1; } //----------------------------- //Init Method 1 img_convert_ctx =sws_alloc_context(); //Show AVOption av_opt_show2(img_convert_ctx,stdout,AV_OPT_FLAG_VIDEO_PARAM,0); //Set Value av_opt_set_int(img_convert_ctx,"sws_flags",SWS_BICUBIC|SWS_PRINT_INFO,0); av_opt_set_int(img_convert_ctx,"srcw",src_w,0); av_opt_set_int(img_convert_ctx,"srch",src_h,0); av_opt_set_int(img_convert_ctx,"src_format",src_pixfmt,0); //'0' for MPEG (Y:0-235);'1' for JPEG (Y:0-255) av_opt_set_int(img_convert_ctx,"src_range",1,0); av_opt_set_int(img_convert_ctx,"dstw",dst_w,0); av_opt_set_int(img_convert_ctx,"dsth",dst_h,0); av_opt_set_int(img_convert_ctx,"dst_format",dst_pixfmt,0); av_opt_set_int(img_convert_ctx,"dst_range",1,0); sws_init_context(img_convert_ctx,NULL,NULL); //Init Method 2 //img_convert_ctx = sws_getContext(src_w, src_h,src_pixfmt, dst_w, dst_h, dst_pixfmt, // rescale_method, NULL, NULL, NULL); //----------------------------- /* //Colorspace ret=sws_setColorspaceDetails(img_convert_ctx,sws_getCoefficients(SWS_CS_ITU601),0, sws_getCoefficients(SWS_CS_ITU709),0, 0, 1 << 16, 1 << 16); if (ret==-1) { printf( "Colorspace not support.\n"); return -1; } */ while(1) { if (fread(temp_buffer, 1, src_w*src_h*src_bpp/8, src_file) != src_w*src_h*src_bpp/8){ break; } switch(src_pixfmt){ case AV_PIX_FMT_GRAY8:{ memcpy(src_data[0],temp_buffer,src_w*src_h); break; } case AV_PIX_FMT_YUV420P:{ memcpy(src_data[0],temp_buffer,src_w*src_h); //Y memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h/4); //U memcpy(src_data[2],temp_buffer+src_w*src_h*5/4,src_w*src_h/4); //V break; } case AV_PIX_FMT_YUV422P:{ memcpy(src_data[0],temp_buffer,src_w*src_h); //Y memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h/2); //U memcpy(src_data[2],temp_buffer+src_w*src_h*3/2,src_w*src_h/2); //V break; } case AV_PIX_FMT_YUV444P:{ memcpy(src_data[0],temp_buffer,src_w*src_h); //Y memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h); //U memcpy(src_data[2],temp_buffer+src_w*src_h*2,src_w*src_h); //V break; } case AV_PIX_FMT_YUYV422:{ memcpy(src_data[0],temp_buffer,src_w*src_h*2); //Packed break; } case AV_PIX_FMT_RGB24:{ memcpy(src_data[0],temp_buffer,src_w*src_h*3); //Packed break; } default:{ printf("Not Support Input Pixel Format.\n"); break; } } sws_scale(img_convert_ctx, src_data, src_linesize, 0, src_h, dst_data, dst_linesize); printf("Finish process frame %5d\n",frame_idx); frame_idx++; switch(dst_pixfmt){ case AV_PIX_FMT_GRAY8:{ fwrite(dst_data[0],1,dst_w*dst_h,dst_file); break; } case AV_PIX_FMT_YUV420P:{ fwrite(dst_data[0],1,dst_w*dst_h,dst_file); //Y fwrite(dst_data[1],1,dst_w*dst_h/4,dst_file); //U fwrite(dst_data[2],1,dst_w*dst_h/4,dst_file); //V break; } case AV_PIX_FMT_YUV422P:{ fwrite(dst_data[0],1,dst_w*dst_h,dst_file); //Y fwrite(dst_data[1],1,dst_w*dst_h/2,dst_file); //U fwrite(dst_data[2],1,dst_w*dst_h/2,dst_file); //V break; } case AV_PIX_FMT_YUV444P:{ fwrite(dst_data[0],1,dst_w*dst_h,dst_file); //Y fwrite(dst_data[1],1,dst_w*dst_h,dst_file); //U fwrite(dst_data[2],1,dst_w*dst_h,dst_file); //V break; } case AV_PIX_FMT_YUYV422:{ fwrite(dst_data[0],1,dst_w*dst_h*2,dst_file); //Packed break; } case AV_PIX_FMT_RGB24:{ fwrite(dst_data[0],1,dst_w*dst_h*3,dst_file); //Packed break; } default:{ printf("Not Support Output Pixel Format.\n"); break; } } } sws_freeContext(img_convert_ctx); free(temp_buffer); fclose(dst_file); av_freep(&src_data[0]); av_freep(&dst_data[0]); return 0; }
本文主要参考雷神的三篇文档:
最简单的基于FFmpeg的libswscale的示例(YUV转RGB)
FFmpeg源代码简单分析:libswscale的sws_scale()
FFmpeg源代码简单分析:libswscale的sws_getContext()
阅读全文
0 0
- FFMPEG--图像处理Swscale
- 【图像处理】FFmpeg解码H264及swscale缩放详解
- ffmpeg swscale 的用法
- FFmpeg缩放swscale函数
- FFmpeg缩放swscale函数
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- ffmpeg 中 swscale 的用法
- ffmpeg中swscale 的用法
- ffmpeg 中 swscale 的用法
- ffmpeg 中 swscale 的用法
- 网格顶点法向的计算(基于面平均方法)
- 图解扩展kmp--by boshi
- Shell基础
- 快速排序算法的理解
- Android APP压力测试环境搭建
- FFMPEG--图像处理Swscale
- 使用CocoaPods管理依赖库
- 错误ERR_INCOMPLETE_CHUNKED_ENCODING解决方法
- ONVIF协议网络摄像机(IPC)客户端程序开发(11):设备能力
- python IDLE或shell中切换路径 使用
- apue 第九章 进程组 会话
- (转)CTA大佬Winton创始人:人工智能会颠覆传统投资吗?
- Jquery第一篇【介绍Jquery、回顾JavaScript代码、JS对象与JQ对象的区别】
- 算法作业_22(2017.5.18第十三周)