FFmpeg使用流程
来源:互联网 发布:mac结构图app免费 编辑:程序博客网 时间:2024/05/22 08:12
一、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所属的视频/音频流。
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中分配的资源。
三、大体代码流程
int main(int argc, char **argv){ AVFormatContext* pCtx = NULL; AVCodecContext *pCodecCtx = NULL; AVCodec *pCodec = NULL; AVPacket packet; AVFrame *pFrame = NULL; FILE *fpo1 = NULL; FILE *fpo2 = NULL; int nframe; int err; int got_picture; int picwidth, picheight, linesize; unsigned char *pBuf; int i; int64_t timestamp; struct options opt; int usefo = 0; struct audio_dsp dsp; int dusecs; float usecs1 = 0; float usecs2 = 0; struct timeval elapsed1, elapsed2; int decoded = 0; av_register_all(); av_log_set_callback(log_callback); av_log_set_level(50); err = avformat_open_input(&pCtx, opt.finput, 0, 0); if (err < 0){ printf("\n->(avformat_open_input)\tERROR:\t%d\n", err); goto fail; } err = avformat_find_stream_info(pCtx, 0); if (err < 0){ printf("\n->(avformat_find_stream_info)\tERROR:\t%d\n", err); goto fail; } if (opt.streamId < 0){ av_dump_format(pCtx, 0, pCtx->filename, 0); goto fail; }else{ for (i = 0; i < pCtx->streams[opt.streamId]->codec->extradata_size; i++){ if (i%16 == 0) printf("\n"); printf("%2x ", pCtx->streams[opt.streamId]->codec->extradata[i]); } } / *Try to open output file*/ if (strlen(opt.foutput1) && strlen(opt.foutput2)) { fpo1 = fopen(opt.foutput1, "wb"); fpo2 = fopen(opt.foutput2, "wb"); if (!fpo1 || !fpo2){ printf("\n->error Open output file.\n"); goto fail; } usefo = 1; }else{ usefo = 0; } if (opt.streamId >= pCtx->nb_streams){ printf("\n->StreamId\tERROR\n"); goto fail; } if (opt.lstart > 0){ err = av_seek_frame(pCtx, opt.streamId, opt.lstart, AVSEEK_FLAG_ANY); if (err < 0) { printf("\n->(av_seek_frame)\tERROR:\t%d\n", err); goto fail; } } / *Config decoder*/ if (!opt.nodec){ /* prepare codec */ pCodecCtx = pCtx->streams[opt.streamId]->codec; if (opt.thread_count <= 16 && opt.thread_count > 0 ){ pCodecCtx->thread_count = opt.thread_count; pCodecCtx->thread_type = FF_THREAD_FRAME; } pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (!pCodec){ printf("\n->Can't find decoder!\n"); goto fail; } err = avcodec_open2(pCodecCtx, pCodec, 0); if (err < 0){ printf("\n->(avcodec_open)\tERROR:\t%d\n", err); goto fail; } pFrame = avcodec_alloc_frame(); / *Ready audio device* / if (opt.bplay){ / *Audio device* / dsp.audio_fd = open(OSS_DEVICE, O_WRONLY); if (dsp.audio_fd == -1){ printf("\n-> Can't find audio device\n"); goto fail; } dsp.channels = pCodecCtx->channels; dsp.speed = pCodecCtx->sample_rate; dsp.format = map_formats(pCodecCtx->sample_fmt); if (set_audio(&dsp) < 0){ printf("\n-> Can't set audio device\n"); goto fail; } } } nframe = 0; while(nframe < opt.frames || opt.frames == -1) { gettimeofday(&elapsed1, NULL); err = av_read_frame(pCtx, &packet); if (err < 0){ printf("\n->(av_read_frame)\tERROR:\t%d\n", err); break; } } if (!opt.nodec && pCodecCtx) { avcodec_close(pCodecCtx); } fail: if (pCtx){ avformat_close_input(&pCtx); } if (fpo1){ fclose(fpo1); } if (fpo2){ fclose(fpo2); } if (!pFrame){ av_free(pFrame); } if (!usefo && (dsp.audio_fd != -1)){ close(dsp.audio_fd); } return 0;}
- ffmpeg 音频使用流程
- FFmpeg使用流程
- FFMEG开发教程--(01)ffmpeg基本使用流程
- FFMpeg的解码流程
- FFMpeg的解码流程
- FFMPEG解码流程
- ffmpeg解码流程
- ffmpeg解码流程
- FFMpeg的解码流程
- ffmpeg解码流程
- FFMPEG解码流程
- FFMpeg的解码流程
- ffmpeg播放流程讲解
- FFMPEG解码流程
- ffmpeg解码流程 .
- ffmpeg解码流程
- ffmpeg解码流程
- FFMpeg的解码流程
- 《张志俊揭秘太极拳》读书摘编
- OpenCL异构并行计算编程笔记(1):平台、设备与上下文
- poll机制分析--转韦东山
- 欢迎使用CSDN-markdown编辑器
- 2016 广联达面试题4
- FFmpeg使用流程
- Jam's balance
- udp如何实现可靠性传输?
- BGRABitmap图像操作8:纹理,前面椭圆外加一圆角长方形
- IT--linux--命令行安装chrome
- poj 2449 Remmarguts' Date(最短路+A*)
- 2016年湖南省第十二届大学生计算机程序设计竞赛
- linux下autotools的使用流程
- Servlet的多线程和线程安全