利用ffmpeg进行图像数据格式的转换以及图片的缩放应用中,主要用到了swscale.h文件中的三个函数,分别是:

  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);
  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[]);
  void sws_freeContext(struct SwsContext *swsContext);

sws_getContext函数可以看做是初始化函数,它的参数定义分别为:

int srcW,int srcH 为原始图像数据的高和宽;

 int dstW,int dstH 为输出图像数据的高和宽;

enum AVPixelFormat srcFormat 为输入和输出图片数据的类型;eg:AV_PIX_FMT_YUV420、PAV_PIX_FMT_RGB24;

int flags 为scale算法种类;eg:SWS_BICUBIC、SWS_BICUBLIN、SWS_POINT、SWS_SINC;

SwsFilter *srcFilter ,SwsFilter *dstFilter,const double *param 可以不用管,全为NULL即可;

sws_scale函数则为执行函数,它的参数定义分别为:

struct SwsContext *c 为sws_getContext函数返回的值;

const uint8_t *const srcSlice[],uint8_t *const dst[] 为输入输出图像数据各颜色通道的buffer指针数组;

const int srcStride[],const int dstStride[] 为输入输出图像数据各颜色通道每行存储的字节数数组;

int srcSliceY 为从输入图像数据的第多少列开始逐行扫描,通常设为0;

     int srcSliceH 为需要扫描多少行,通常为输入图像数据的高度;

 sws_freeContext函数为结束函数,它的参数即为sws_getContext函数返回的值;

做一个实际缩放YUV420函数打包实例如下:

int ScaleImg(AVCodecContext *pCodecCtx,AVFrame *src_picture,AVFrame *dst_picture,int nDstH ,int nDstW )
{
  int i ;
  int nSrcStride[3];
  int nDstStride[3];
  int nSrcH = pCodecCtx->height;
  int nSrcW = pCodecCtx->width;
  struct SwsContext* m_pSwsContext;   uint8_t *pSrcBuff[3] = {src_picture->data[0],src_picture->data[1], src_picture->data[2]};   nSrcStride[0] = nSrcW ;
  nSrcStride[1] = nSrcW/2 ;
  nSrcStride[2] = nSrcW/2 ;   dst_picture->linesize[0] = nDstW;
  dst_picture->linesize[1] = nDstW / 2;
  dst_picture->linesize[2] = nDstW / 2;   printf("nSrcW%d\n",nSrcW);   m_pSwsContext = sws_getContext(nSrcW, nSrcH, PIX_FMT_YUV420P,
                   nDstW, nDstH, PIX_FMT_YUV420P,
                     SWS_BICUBIC,
                     NULL, NULL, NULL);   if (NULL == m_pSwsContext)
  {
    printf("ffmpeg get context error!\n");
    exit (-1);
  }
  sws_scale(m_pSwsContext, src_picture->data,src_picture->linesize, 0, pCodecCtx->height,dst_picture->data,dst_picture->linesize);   printf("line0:%d line1:%d line2:%d\n",dst_picture->linesize[0] ,dst_picture->linesize[1] ,dst_picture->linesize[2]);
  sws_freeContext(m_pSwsContext);   return 1 ;
}

函数很简单,申请环境初始指针,后缩放即可。读到此文的朋友,这个函数可以直接拷贝使用哟。如果有疑问可以留言或者邮件:leoluopy@gmail.com

RGB的缩放可以参考下面:

int ScaleYUVImgToRGB(int nSrcW,int nSrcH ,uint8_t* src_data,int *linesize,int nDstW ,int nDstH )
{
int i ; int ret ; FILE *nRGB_file ; AVFrame *nDst_picture ;
struct SwsContext* m_pSwsContext; nDst_picture = avcodec_alloc_frame();
if (!nDst_picture){
printf("nDst_picture avcodec_alloc_frame failed\n");
exit(1);
}
if(avpicture_alloc((AVPicture *)nDst_picture,PIX_FMT_RGB24,nDstW, nDstH)<0){
printf("dst_picture avpicture_alloc failed\n");
exit(1);
}
m_pSwsContext = sws_getContext(nSrcW, nSrcH, PIX_FMT_YUV420P,
nDstW, nDstH, PIX_FMT_RGB24,
SWS_BICUBIC,
NULL, NULL, NULL); if (NULL == m_pSwsContext)
{
printf("ffmpeg get context error!\n");
exit (-1);
} ret = sws_scale(m_pSwsContext, src_data,linesize, 0,nSrcH,nDst_picture->data,nDst_picture->linesize); nRGB_file = fopen("..\\YUV_STREAM\\RGBFile.rgb","ab+");
fwrite(nDst_picture->data[0],nDstW*nDstH*3,1,nRGB_file);
fclose(nRGB_file); sws_freeContext(m_pSwsContext);
avpicture_free((AVPicture *)nDst_picture); return 0;
}

参数data  和 linesize 参考yuv平面指针即可。

同时如果不想使用AVPicture结构的话,可以参考下面的:(注意不同图像类型,linesize一定要写对)

char* H264Decoder_c::ScaleYUVImgToRGB(int nSrcW,int nSrcH ,uint8_t** src_data,int *linesize,int nDstW ,int nDstH )
{
int i ; int ret ; FILE *nRGB_file ; struct SwsContext* m_pSwsContext;
char* out_Img[3];
int out_linesize[3];
out_linesize[0] = 2*nDstW ; //out_linesize[1] = nDstW ;out_linesize[2] = nDstW ;
out_Img[0] = g_RGBImg ; m_pSwsContext = sws_getContext(nSrcW, nSrcH, PIX_FMT_YUV420P,
nDstW, nDstH, PIX_FMT_RGB565,
SWS_BICUBIC,
NULL, NULL, NULL); if (NULL == m_pSwsContext)
{
printf("ffmpeg get context error!\n");
exit (-1);
} ret = sws_scale(m_pSwsContext, src_data,linesize, 0,nSrcH,(uint8_t**)out_Img,out_linesize);
#if 0
nRGB_file = fopen("./RGBFile.rgb","ab+");
fwrite(out_Img[0],nDstW*nDstH*2,1,nRGB_file);
fclose(nRGB_file); #endif sws_freeContext(m_pSwsContext); return out_Img[0];
}

目的位图的空间申请:

注意:上面的缩放函数如果直接使用而在没有解码成功或者没有申请目的位图空间时,将报段错误。

原因:没有解码成功,位图源地址将是指向空的地址,目的位图地址同样。

申请目的位图的方式:

dst_picture = avcodec_alloc_frame();
if (!dst_picture){
  return ;
}
if(avpicture_alloc((AVPicture *)dst_picture, c->pix_fmt,c->width*2, c->height*2)<0){
  printf("dst_picture allocate failed\n");
  exit(1);
}

初始化后即可以用于缩放了。

图像的内存Dump方法:

上文已经比较详细的阐述了ffmpeg的解码以及缩放原理及流程,然而在实际运用环境中,无论是从实时播放或者是从历史回放来看,我们需要的是像素位图,而不是ffmpeg的结构体。那么怎么转换呢?下文介绍了相关的内容。

作为实际运用环境中,像素位图格式,笔者使用的是比较常用的YUV格式。

编解码图像格式

          承接上文继续,在大部分现场环境下,为了节省传送带宽以及提高系统工作效率,视频原始位图格式以及解码后展示格式一般使用YUV420。
          其中YV12以及IYUV是最常见的格式。
          简单的说,YUV格式又分为平面格式以及打包格式。他们各有利弊。本文使用的是YUV平面格式即三通道分别使用不同入口地址存储,这样的好处是,与ffmpeg解码接口方面,AVFrame中数据结构可以便捷拷贝图像信息。

YV12:

IYUV

 
这里做简单的叙述:详细可以参考:

http://blog.csdn.net/searchsun/article/details/2443867

如何Dump

  好了,对YUV格式又初步了解后,下面介绍如果导出这像素位图数据。ffmpeg将图像的亮度以及色差信息保存在AVFrame中的data[0]、data[1]、data[2]中。

  详细参考:

AVFrame和AVPicture对比:

http://yul100887.blog.163.com/blog/static/200336135201211143525930/

所有操作均是针对这三个指针展开的,如下:

pgm_save(picture->data[0], picture->linesize[0], //Y
c->width, c->height, outfilename);
pgm_save(picture->data[1], picture->linesize[1],
c->width/2, c->height/2, outfilename); //U
pgm_save(picture->data[2], picture->linesize[2],
c->width/2, c->height/2, outfilename); //V
void pgm_save(unsigned char *buf,int wrap, int xsize,int ysize,char *filename)
{
FILE *f;
int i;   f=fopen(filename,"ab+");
  for(i=0;i<ysize;i++)
  {
    fwrite(buf + i * wrap, 1, xsize, f );
  }
  fclose(f);
}

代码对YUV三个像素通道分开dump,读者可以根据自己的需要对函数进行包装。data[0] 是亮度信息入口指针,同时传入图像长宽,以及存储内存区域行宽。 data[1]  data[2] 类似。

最后需要注意的是:linesize总是容易被遗忘,livesize[0]=height ,livesize[1]=height/2 ,livesize[2]=height /2,

==================================================================================

原帖地址:http://blog.csdn.net/gubenpeiyuan/article/details/19548019?utm_source=tuicool

其参考地址:

参考文章:

使用ffmpeg进行图像格式转换及缩放

http://blog.csdn.net/skys_broyal/article/details/10337147

AVFrame和AVPicture对比:

http://yul100887.blog.163.com/blog/static/200336135201211143525930/

FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)

http://blog.csdn.net/leixiaohua1020/article/details/14215391

ffmpeg编解码H264

http://blog.csdn.net/chinabinlang/article/details/7088590

h264检测是I帧还是P帧

http://blog.csdn.net/zgyulongfei/article/details/7558031

最简单的基于FFmpeg的Swscale示例(YUV转RGB)

/**
* 最简单的基于FFmpeg的Swscale示例
* Simplest FFmpeg Swscale
*
* 雷霄骅 Lei Xiaohua
* leixiaohua1020@126.com
* 中国传媒大学/数字电视技术
* Communication University of China / Digital TV Technology
* http://blog.csdn.net/leixiaohua1020
*
* 本程序使用libswscale对像素数据进行缩放转换等处理。
* 是最简单的libswscale的教程。
*
* This software uses libswscale to scale / convert pixels.
* It the simplest tutorial about libswscale.
*/ #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=,src_h=;
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=,dst_h=;
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[];
int src_linesize[]; uint8_t *dst_data[];
int dst_linesize[]; int rescale_method=SWS_BICUBIC;
struct SwsContext *img_convert_ctx;
uint8_t *temp_buffer=(uint8_t *)malloc(src_w*src_h*src_bpp/); int frame_idx=;
int ret=;
ret= av_image_alloc(src_data, src_linesize,src_w, src_h, src_pixfmt, );
if (ret< ) {
printf( "Could not allocate source image\n");
return -;
}
ret = av_image_alloc(dst_data, dst_linesize,dst_w, dst_h, dst_pixfmt, );
if (ret< ) {
printf( "Could not allocate destination image\n");
return -;
}
//-----------------------------
//Init Method 1
img_convert_ctx =sws_alloc_context();
//Show AVOption
av_opt_show2(img_convert_ctx,stdout,AV_OPT_FLAG_VIDEO_PARAM,NULL);
//Set Value
av_opt_set_int(img_convert_ctx,"sws_flags",SWS_BICUBIC|SWS_PRINT_INFO,NULL);
av_opt_set_int(img_convert_ctx,"srcw",src_w,NULL);
av_opt_set_int(img_convert_ctx,"srch",src_h,NULL);
av_opt_set_int(img_convert_ctx,"src_format",src_pixfmt,NULL);
//'0' for MPEG (Y:0-235);'1' for JPEG (Y:0-255)
av_opt_set_int(img_convert_ctx,"src_range",,NULL);
av_opt_set_int(img_convert_ctx,"dstw",dst_w,NULL);
av_opt_set_int(img_convert_ctx,"dsth",dst_h,NULL);
av_opt_set_int(img_convert_ctx,"dst_format",dst_pixfmt,NULL);
av_opt_set_int(img_convert_ctx,"dst_range",,NULL);
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()
{
if (fread(temp_buffer, , src_w*src_h*src_bpp/, src_file) != src_w*src_h*src_bpp/){
break;
} switch(src_pixfmt){
case AV_PIX_FMT_GRAY8:{
memcpy(src_data[],temp_buffer,src_w*src_h);
break;
}
case AV_PIX_FMT_YUV420P:{
memcpy(src_data[],temp_buffer,src_w*src_h); //Y
memcpy(src_data[],temp_buffer+src_w*src_h,src_w*src_h/); //U
memcpy(src_data[],temp_buffer+src_w*src_h*/,src_w*src_h/); //V
break;
}
case AV_PIX_FMT_YUV422P:{
memcpy(src_data[],temp_buffer,src_w*src_h); //Y
memcpy(src_data[],temp_buffer+src_w*src_h,src_w*src_h/); //U
memcpy(src_data[],temp_buffer+src_w*src_h*/,src_w*src_h/); //V
break;
}
case AV_PIX_FMT_YUV444P:{
memcpy(src_data[],temp_buffer,src_w*src_h); //Y
memcpy(src_data[],temp_buffer+src_w*src_h,src_w*src_h); //U
memcpy(src_data[],temp_buffer+src_w*src_h*,src_w*src_h); //V
break;
}
case AV_PIX_FMT_YUYV422:{
memcpy(src_data[],temp_buffer,src_w*src_h*); //Packed
break;
}
case AV_PIX_FMT_RGB24:{
memcpy(src_data[],temp_buffer,src_w*src_h*); //Packed
break;
}
default:{
printf("Not Support Input Pixel Format.\n");
break;
}
} sws_scale(img_convert_ctx, src_data, src_linesize, , 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[],,dst_w*dst_h,dst_file);
break;
}
case AV_PIX_FMT_YUV420P:{
fwrite(dst_data[],,dst_w*dst_h,dst_file); //Y
fwrite(dst_data[],,dst_w*dst_h/,dst_file); //U
fwrite(dst_data[],,dst_w*dst_h/,dst_file); //V
break;
}
case AV_PIX_FMT_YUV422P:{
fwrite(dst_data[],,dst_w*dst_h,dst_file); //Y
fwrite(dst_data[],,dst_w*dst_h/,dst_file); //U
fwrite(dst_data[],,dst_w*dst_h/,dst_file); //V
break;
}
case AV_PIX_FMT_YUV444P:{
fwrite(dst_data[],,dst_w*dst_h,dst_file); //Y
fwrite(dst_data[],,dst_w*dst_h,dst_file); //U
fwrite(dst_data[],,dst_w*dst_h,dst_file); //V
break;
}
case AV_PIX_FMT_YUYV422:{
fwrite(dst_data[],,dst_w*dst_h*,dst_file); //Packed
break;
}
case AV_PIX_FMT_RGB24:{
fwrite(dst_data[],,dst_w*dst_h*,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[]);
av_freep(&dst_data[]); return ;
}

FFmpeg缩放swscale详解 <转>的更多相关文章

  1. ffmpeg命令参数详解

    ffmpeg命令参数详解 http://linux.51yip.com/search/ffmpeg ffmpeg图片加滤镜效果 参考:https://cloud.tencent.com/develop ...

  2. OpenGL的glScalef缩放变换函数详解

    glScalef是openGL中的模型缩放函数,就是把当前矩阵与一个表示延各个轴对物体进行拉伸.压缩.反射的矩阵相乘.这个物体的每个点的x,y,z坐标与对应的xyz参数相乘. 先看函数定义void g ...

  3. android的ScaleGestureDetector缩放类详解

    文章由多出组合,它们来自: http://elvajxw.iteye.com/blog/1308452 http://www.cnblogs.com/lknlfy/archive/2012/03/11 ...

  4. FFmpeg av_seek_frame规律详解

    本帖最后由 TangMonk 于 2016-7-27 10:26 编辑 1 av_seek_frame对视频进行跳转规律 1.1 flags参数 #define AVSEEK_FLAG_BACKWAR ...

  5. Echarts dataZoom缩放功能参数详解:

    dataZoom=[ //区域缩放 { id: 'dataZoomX', show:true, //是否显示 组件.如果设置为 false,不会显示,但是数据过滤的功能还存在. backgroundC ...

  6. ffmpeg 详解

    来源:http://blog.itpub.net/9399028/viewspace-1242300/ FFMPEG详解   认识FFMPEG FFMPEG堪称自由软件中最完备的一套多媒体支持库,它几 ...

  7. ffmpeg播放器实现详解 - 视频显示

    ffplay是ffmpeg源码中一个自带的开源播放器实例,同时支持本地视频文件的播放以及在线流媒体播放,功能非常强大. FFplay: FFplay is a very simple and port ...

  8. FFmpeg开发笔记(五):ffmpeg解码的基本流程详解(ffmpeg3新解码api)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  9. CSS3属性transform详解之(旋转:rotate,缩放:scale,倾斜:skew,移动:translate)

    CSS3属性transform详解之(旋转:rotate,缩放:scale,倾斜:skew,移动:translate)   在CSS3中,可以利用transform功能来实现文字或图像的旋转.缩放.倾 ...

随机推荐

  1. python倒计时

    #coding=utf-8 #!/usr/bin/env python import datetime,time i=3 while i==3: spring=datetime.datetime(20 ...

  2. Android Fragment详解(六):Fragement示例

    把条目添加到动作栏 你的fragment们可以向activity的菜单(按Manu键时出现的东西)添加项,同时也可向动作栏(界面中顶部的那个区域)添加条目,这都需通过实现方法onCreateOptio ...

  3. timed out waiting for input: auto-logout

    The ssh "timed out waiting for input: auto-logout" messages is generated by ssh upon reach ...

  4. DevExpress ASPxHtmlEditor控件格式化并导出Word (修复中文字体导出丢失)

    在前台页面中先插入一个ASPxHtmlEditor控件,名为ASPxHtmlEditor1. 我用的Dev版本为14.1 格式化文本 在后台插入如下代码  1     const string css ...

  5. 一个Banner广告收缩效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 《第一行代码》学习笔记6-活动Activity(4)

    1.SecondActivity不是主活动,故不需要配置标签里的内容. 2.Intent是Android程序中各组件之间进行交互的一种重要方式,一般可被用于 启动活动,启动服务,以及发送广播等.Int ...

  7. 诡异的SpriteKit 游戏查错

    在Endless Runner 游戏中,做了一些atlas后,发现有个问题,当player跳跃起来的时候,发现他没有动画了,被默认的X图片代替.原来的图像是这样的. 在增加了一些动画后,我的效果就成这 ...

  8. ORACLE SQL 组函数【weber出品必属精品】

    组函数:对一组数据进行加工,每组数据返回一个值 常用的组函数:count()  avg()  max()   min()  sum()   count()函数  1. count(*) :返回总共的行 ...

  9. C#设置textboox只能输入数字`

    1.在闪电KeyPress事件中添加 private void textBox_pwmx_fre_KeyPress(object sender, KeyPressEventArgs e) { //如果 ...

  10. MFC软件工程架构模型-模式窗口-非模式窗口

    1. SDI单文档界面: MDI多文档界面.有多个"关闭-最大化-最小化"等这样的窗口嵌套 基于对话框的软件模型 2.模式对话框和非模式对话框 模式对话框:使用DoMoel(),弹 ...