FFmpeg部分函数解析

版权声明:本文为博主原创文章,转载请标明出处! https://blog.csdn.net/qq_27396861/article/details/54429706
> 处理音频和视频的基本流程:

基本上来说,处理视频和音频流是很容易的:(瞎扯。。。)
10 从 video.avi 文件中打开视频流 video_stream
20 从视频流中读取包到帧中
30 如果这个帧还不完整,跳到 20
40 对这个帧进行一些操作
50 跳回到 20

1)av_register_all()

ffmpeg注册复用器,编码器等的函数av_register_all()。该函数在所有基于ffmpeg的应用程序中几乎都是第一个被调用的。只有调用了该函数,才能使用复用器,编码器等。

2)avformat_open_input()

- //参数ps包含一切媒体相关的上下文结构,有它就有了一切,本函数如果打开媒体成功,
- //会返回一个AVFormatContext的实例.
- //参数filename是媒体文件名或URL.
- //参数fmt是要打开的媒体格式的操作结构,因为是读,所以是inputFormat.此处可以
- //传入一个调用者定义的inputFormat,对应命令行中的 -f xxx段,如果指定了它,
- //在打开文件中就不会探测文件的实际格式了,以它为准了.
- //参数options是对某种格式的一些操作,是为了在命令行中可以对不同的格式传入
- //特殊的操作参数而建的, 为了了解流程,完全可以无视它.
- int avformat_open_input(AVFormatContext **ps,
-                         const char *filename,
-                         AVInputFormat *fmt,
-                         AVDictionary **options)

3)avformat_find_stream_info  读取一部分视音频数据并且获得一些相关的信息

由于avformat_find_stream_info()代码比较长,难以全部分析,在这里只能简单记录一下它的要点。该函数主要用于给每个媒体流(音频/视频)的AVStream结构体赋值。我们大致浏览一下这个函数的代码,会发现它其实已经实现了解码器的查找,解码器的打开,视音频帧的读取,视音频帧的解码等工作。换句话说,该函数实际上已经“走通”的解码的整个流程。下面看一下除了成员变量赋值之外,该函数的几个关键流程。
1.查找解码器:find_decoder()
2.打开解码器:avcodec_open2()
3.读取完整的一帧压缩编码的数据:read_frame_internal()
注:av_read_frame()内部实际上就是调用的read_frame_internal()。
4.解码一些压缩编码数据:try_decode_frame()

4) avcodec_find_encoder()和avcodec_find_decoder()。avcodec_find_encoder()用于查找FFmpeg的编码器,avcodec_find_decoder()用于查找FFmpeg的解码器。

5) FFmpeg的avcodec_open2()函数。该函数用于初始化一个视音频编解码器的AVCodecContext。avcodec_open2()的声明位于libavcodec\avcodec.h

/*
avctx:需要初始化的AVCodecContext。
codec:输入的AVCodec
options:一些选项。例如使用libx264编码的时候,“preset”,“tune”等都可以通过该参数设置。 
*/
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

6) FFmpeg中的图像处理(缩放,YUV/RGB格式转换)类库libswsscale的源代码。libswscale是一个主要用于处理图片像素数据的类库。可以完成图片像素格式的转换,图片的拉伸等工作。

libswscale常用的函数数量很少,一般情况下就3个:

sws_getContext():初始化一个SwsContext。

sws_scale():处理图像数据。

sws_freeContext():释放一个SwsContext。

其中sws_getContext()也可以用sws_getCachedContext()取代。

尽管libswscale从表面上看常用函数的个数不多,它的内部却有一个大大的“世界”。做为一个几乎“万能”的图片像素数据处理类库,它的内部包含了大量的代码。

从sws_getContext()的定义中可以看出,它首先调用了一个函数sws_alloc_context()用于给SwsContext分配内存。然后将传入的源图像,目标图像的宽高,像素格式,以及标志位分别赋值给该SwsContext相应的字段。最后调用一个函数sws_init_context()完成初始化工作。


- 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);
该函数包含以下参数:
srcW:源图像的宽
srcH:源图像的高
srcFormat:源图像的像素格式
dstW:目标图像的宽
dstH:目标图像的高
dstFormat:目标图像的像素格式
flags:设定图像拉伸使用的算法
成功执行的话返回生成的SwsContext,否则返回NULL。

7)

int avpicture_fill(AVPicture *picture, uint8_t *ptr,int pix_fmt, int width, int height);

这个函数的使用本质上是为已经分配的空间的结构体AVPicture挂上一段用于保存数据的空间,这个结构体中有一个指针数组data[4],挂在这个数组里。一般我们这么使用:
1) pFrameRGB = avcodec_alloc_frame();

2) numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height);
      buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

3) avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,pCodecCtx->width, pCodecCtx->height);
以上就是为pFrameRGB挂上buffer。这个buffer是用于存缓冲数据的。

8) av_read_frame()的作用是读取码流中的音频若干帧或者视频一帧。例如,解码视频的时候,每解码一个视频帧,需要先调用 av_read_frame()获得一帧视频的压缩数据,然后才能对该数据进行解码(例如H.264中一帧压缩数据通常对应一个NAL)。

通过av_read_packet(***),读取一个包,需要说明的是此函数必须是包含整数帧的,不存在半帧的情况,以ts流为例,是读取一个完整的PES包(一个完整pes包包含若干视频或音频es包),读取完毕后,通过av_parser_parse2(***)分析出视频一帧(或音频若干帧),返回,下次进入循环的时候,如果上次的数据没有完全取完,则st = s->cur_st;不会是NULL,即再此进入av_parser_parse2(***)流程,而不是下面的av_read_packet(**)流程,这样就保证了,如果读取一次包含了N帧视频数据(以视频为例),则调用av_read_frame(***)N次都不会去读数据,而是返回第一次读取的数据,直到全部解析完毕。

9) avcodec_decode_video2()的作用是解码一帧视频数据。输入一个压缩编码的结构体AVPacket,输出一个解码后的结构体AVFrame。该函数的声明位于libavcodec\avcodec.h

- int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
-                          int *got_picture_ptr,
-                          const AVPacket *avpkt);

9) sws_scale()是用于转换像素的函数。它的声明位于libswscale\swscale.h

/*
srcSlice: 数据的来源
srcStride: 行数
srcSliceY: 一般为0,表示第一行
srcSliceH: 高度
dst: 输出的数据
*/
- 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[]);






































猜你喜欢

转载自blog.csdn.net/qq_27396861/article/details/54429706
今日推荐