您当前的位置: 首页 > 

鱼儿-1226

暂无认证

  • 0浏览

    0关注

    1100博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

FFmpeg使用流程

鱼儿-1226 发布时间:2020-08-06 10:21:52 ,浏览量:0

一、FFMPeg一般流程:

1、av_register_all();//注册所有文件格式和编解码库

2、avformat_network_init();//打开网络视频流

3、av_open_input_file();//读取文件头部把信息保存到AVFormatContext结构体

4、av_find_stream_info();//为pFormatCtx->streams填充上正确的信息

5、CODEC_TYPE_VIDEO;//通过判断得到视频流类型

6、avcodec_find_decoder();//查找解码器

7、avcodec_open();//打开编解码器

8、avcodec_alloc_frame();//分配空间保存帧数据

9、av_read_frame();//不断从流中提取帧数据

10、avcodec_decode_video();//解码视频流

11、avcodec_close();//关闭解码器

12、avformat_close_input_file();//关闭输入文件

 

二、详解:

1、AVCodecContext:描述编解码器上下文的数据结构,包含编解码器需要的参数信息(位于:avcodec.h)

typedef struct AVCodecContext {

     ..... } AVCodecContext;

说明:

单纯使用libavcodec,参数信息需要调用者进行初始化;使用整个FFMPEG库,在调用avformat_open_input和avformat_find_stream_info时根据文件头信息及媒体流内头部信息初始化。

2、AVStream:描述一个媒体流(存储视频/音频流信息的结构体,位于:avformat.h) typedef struct AVStream {     ...... } AVStream;

 

 

主要变量:

int index:标识视频/音频流

AVCodecContext *codec:视频/音频流的AVCodecContext

AVRational time_base:时间基准,真正的时间 =PTS*time_base

int64_t duration:该视频/音频流时间长度

AVDictionary *metadata:元数据信息

AVRational avg_frame_rate:帧率

AVPacket attached_pic:附加图片

3、AVFormatContext:描述媒体文件或媒体流构成和基本信息(包含码流参数较多,位于:avformat.h) typedef struct AVFormatContext { ...... } AVFormatContext;

 

AVFormatContext是一个很重要的数据结构,很多函数会使用它作为参数;是FFMPEG解封装(flv,mp4,rmvb,avi)功能的结构体。

主要变量:

struct AVInputFormat *iformat:输入数据的封装格式

AVIOContext *pb:输入数据缓存

unsigned int nb_streams:音视频流个数

AVStream **streams:音视频流

char filename[1024]:文件名

int64_t duration:时长(单位:us)

int bit_rate:比特率

AVDictionary *metadata:元数据

4、AVPacket:存储压缩编码数据相关信息的结构体(位于:avformat.h)

typedef struct AVPacket {    ......           } AVPacket;

 

 

主要变量:

uint8_t *data:压缩编码数据,一个AVPacket的data通常对应一个NAL。

int   size:data的大小

int64_t pts:显示时间戳

int64_t dts:解码时间戳

int   stream_index:标识该AVPacket所属的视频/音频流。

 

三、API 1、int avformat_open_input(AVFormatContext **ic_ptr,const char *filename,AVInputFormat *fmt,AVDictionary **options); 作用:打开文件或URL,并使基于字节流的底层输入模块得到初始化;解析多媒体文件或多媒体流的头信息,创建AVFormatContext结构并填充其中的关键字段,依次为各个原始流建立AVStream结构。 参数: ic_ptr:用于返回avformat_open_input内部构造的一个AVFormatContext结构体。 filename:指定文件名。 fmt:用于显式指定输入文件的格式,如果设为空则自动判断其输入格式。 options:传入的附加参数。

 

说明:这个函数通过解析多媒体文件或流的头信息及其他辅助数据,能够获取足够多的关于文件、流和编解码器的信息,但任何一种多媒体格式提供的信息都是有限的,而且不同的多媒体软件制作对头信息的设置各有不同,另外这些软件在产生多媒体内容时难免引入错误,这种情况下并不能保证获取到所有需要的信息,这是就要考虑另一个函数:avformat_find_stream_info。

 

2、int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

作用:用于获取必要的编解码器参数。需要得到各媒体流对应编解码器的类型和id,这是两个定义在avutils.h和avcodec.h中的枚举: enum AVMediaType {      AVMEDIA_TYPE_UNKNOWN = -1,      AVMEDIA_TYPE_VIDEO,      AVMEDIA_TYPE_AUDIO,      AVMEDIA_TYPE_DATA,      AVMEDIA_TYPE_SUBTITLE,      AVMEDIA_TYPE_ATTACHMENT,      AVMEDIA_TYPE_NB };

enum CodecID {      CODEC_ID_NONE,      CODEC_ID_MPEG1VIDEO,      CODEC_ID_MPEG2VIDEO,      CODEC_ID_MPEG2VIDEO_XVMC,      CODEC_ID_H261,      CODEC_ID_H263,

CODEC_ID_H264,      ...

};

 

若媒体格式的数据流具有完整头信息,可以通过avformat_open_input得到编解码器的类型和id;否则,需要通过avformat_find_stream_info函数获取。此外,对于音频编解码器,时间基准、采样率、声道数、位宽、帧长度与视频编解码器图像大小、色彩空间等也需要从avformat_find_stream_info函数得到。 3、int av_read_frame(AVFormatContext *s, AVPacket *pkt);

作用:用于从多媒体文件或多媒体流中读取媒体数据,数据由AVPacket结构pkt来存放。对于音频数据,若是固定比特率,则pkt中装载一个或多个音频帧;若为可变比特率,则pkt中装载一个音频帧。对于视频数据,pkt中装载有一个视频帧。注:当再次调用本函数之前,需使用av_free_packet释放pkt所占用的资源。

4、int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);

作用:通过改变媒体文件的读写指针来实现对媒体文件的随机访问,大多源于媒体播放器的快进、快退等功能。  

参数: s:AVFormatContext指针,avformat_open_input返回得到。 stream_index:指定媒体流。 timestamp:时间标签。。 flags:定位方式。

5、void av_close_input_file(AVFormatContext *s); 作用:关闭媒体文件,释放资源,关闭物理IO。

6、AVCodec *avcodec_find_decoder(enum CodecID id);    AVCodec *avcodec_find_decoder_by_name(const char *name); 作用:根据指定解码器ID或者解码器名称查找相应的解码器并返回AVCodec *。

 

7、int avcodec_open(AVCodecContext *avctx, AVCodec *codec); 作用:根据输入的AVCodec指针具体化AVCodecContext结构。在调用该函数之前,首先调用avcodec_alloc_context分配一个AVCodecContext结构,或调用avformat_open_input获取媒体文件中对应媒体流的AVCodecContext结构;此外,通过avcodec_find_decoder获取AVCodec结构。

 

8、int avcodec_decode_video2(AVCodecContext *avctx,AVFrame *picture,int *got_picture_ptr,AVPacket *avpkt);

作用:解码视频帧。

参数:

avctx:解码器上下文。

picture:输出数据。

got_picture_ptr:指示是否有解码数据输出。

avpkt:输入数据。

9、int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt);

作用:解码音频帧。输入数据在AVPacket结构中,输出数据在frame中,got_frame_ptr表示是否有数据输出。

 

参数:

avctx:解码器上下文。

frame:输出数据。

got_frame_ptr:指示是否有解码数据输出。

avpkt:输入数据。

10、int avcodec_close(AVCodecContext *avctx); 作用:关闭解码器,释放avcodec_open中分配的资源。         

三、大体代码流程

 

[cpp] view plain copy

  1. int main(int argc, char **argv)  
  2. {  
  3.     AVFormatContext* pCtx = NULL;  
  4.     AVCodecContext *pCodecCtx = NULL;  
  5.     AVCodec *pCodec = NULL;  
  6.     AVPacket packet;  
  7.     AVFrame *pFrame = NULL;  
  8.     FILE *fpo1 = NULL;  
  9.     FILE *fpo2 = NULL;  
  10.     int nframe;  
  11.     int err;  
  12.     int got_picture;  
  13.     int picwidth, picheight, linesize;  
  14.     unsigned char *pBuf;  
  15.     int i;  
  16.     int64_t timestamp;  
  17.     struct options opt;  
  18.     int usefo = 0;  
  19.     struct audio_dsp dsp;  
  20.     int dusecs;  
  21.     float usecs1 = 0;  
  22.     float usecs2 = 0;  
  23.     struct timeval elapsed1, elapsed2;  
  24.     int decoded = 0;  
  25.   
  26.     av_register_all();  
  27.     av_log_set_callback(log_callback);  
  28.     av_log_set_level(50);  
  29.   
  30.     err = avformat_open_input(&pCtx, opt.finput, 0, 0);  
  31.     if (err codec->extradata_size; i++){  
  32.             if (i%16 == 0) printf("\n");  
  33.             printf("%2x ", pCtx->streams[opt.streamId]->codec->extradata[i]);  
  34.         }  
  35.     }  
  36.   
  37.     / *Try to open output file*/  
  38.     if (strlen(opt.foutput1) && strlen(opt.foutput2))  
  39.     {  
  40.         fpo1 = fopen(opt.foutput1, "wb");  
  41.         fpo2 = fopen(opt.foutput2, "wb");  
  42.         if (!fpo1 || !fpo2){  
  43.             printf("\n->error Open output file.\n");  
  44.             goto fail;  
  45.         }  
  46.         usefo = 1;  
  47.     }else{  
  48.         usefo = 0;  
  49.     }  
  50.   
  51.     if (opt.streamId >= pCtx->nb_streams){  
  52.         printf("\n->StreamId\tERROR\n");  
  53.         goto fail;  
  54.     }  
  55.   
  56.     if (opt.lstart > 0){  
  57.         err = av_seek_frame(pCtx, opt.streamId, opt.lstart, AVSEEK_FLAG_ANY);  
  58.         if (err streams[opt.streamId]->codec;  
  59.    
  60.         if (opt.thread_count  0 ){  
  61.             pCodecCtx->thread_count = opt.thread_count;  
  62.             pCodecCtx->thread_type = FF_THREAD_FRAME;  
  63.         }  
  64.         pCodec = avcodec_find_decoder(pCodecCtx->codec_id);  
  65.         if (!pCodec){  
  66.             printf("\n->Can't find decoder!\n");  
  67.             goto fail;  
  68.         }  
  69.         err = avcodec_open2(pCodecCtx, pCodec, 0);  
  70.         if (err channels;  
  71.             dsp.speed = pCodecCtx->sample_rate;  
  72.             dsp.format = map_formats(pCodecCtx->sample_fmt);  
  73.             if (set_audio(&dsp) 
关注
打赏
1604459285
查看更多评论
立即登录/注册

微信扫码登录

0.0411s