- 多媒体文件其实是个容器(比如mp4是个包装盒,里面可以放mp3/aac, h264视频数据)
- 在容器里有很多流(Stream/Track)
- 每种流是由不同的编码器编码的
- 从流中读取的是包,在一个包中包含着一个或多个帧
常用结构体
AVFormatContext 格式上下文
AVStream 流
AVPacket
打印音视频信息
- avformat_open_input/avformat_close_input
- av_find_input_format
- av_dump_format
要想对一个文件进行分析我们首先要获取到AVFormatContext,通过avformat_open_input函数
int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options);
参数
ps ,AVFormatContext*的地址
url,要处理的文件\设备
AVInputFormat,如果为NULL,就会按照url的后缀自动匹配AVInputFormat
AVDictionary 命令行输入的参数,一般不使用,如果采集视频需要设置编码格式,分辨率,帧率
如何获取AVInputFormat呢?
可以通过av_find_input_format
/**
* Find AVInputFormat based on the short name of the input format.
*/
ff_const59 AVInputFormat *av_find_input_format(const char *short_name);
我们打开mac的麦克风与摄像头
char *devicename="0:0"; //冒号前面是摄像头,冒号后面是麦克风
AVDictionary *options = NULL;
avdevice_register_all();
AVInputFormat * iformat = av_find_input_format("avfoundation");
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "framerate", "30", 0);
av_dict_set(&options, "pixel_format", "yuv420p", 0);
ret = avformat_open_input(&format_context, devicename, iformat, &options);
如果只采集音频 options可以不设置
av_find_input_format 传入的参数avfoundataion/dshow/alsa
avfoundataion mac
dshow windows
alsa linux
av_dump_format 打印输入文件的流信息
#include<stdio.h>
#include<libavutil/log.h>
#include<libavformat/avformat.h>
#include<libavdevice/avdevice.h>
void open_file(){
AVFormatContext *fmt_ctx;
int ret;
char *url = "/Users/yuanxuzhen/study/mac/ffmpeg_demo/output/sync_714251_3900875.mp4";
av_log(NULL, AV_LOG_ERROR, "open_file\n");
ret = avformat_open_input(&fmt_ctx, url, NULL, NULL);
if(ret < 0){
av_log(NULL, AV_LOG_ERROR, "avformat_open_input %s", av_err2str(ret));
goto __ERROR;
}
av_dump_format(fmt_ctx, 0, url, 0);
__ERROR:
if(fmt_ctx) {
avformat_close_input(&fmt_ctx);
}
}
void open_audio(){
av_log(NULL, AV_LOG_ERROR, "open_audio\n");
AVFormatContext *fmt_ctx;
int ret;
char *url = ":0";
AVInputFormat *input_format;
avdevice_register_all(); //注册设备
input_format = av_find_input_format("avfoundation");
if(!input_format){
av_log(NULL, AV_LOG_ERROR, "av_find_input_format error\n");
return;
}
ret = avformat_open_input(&fmt_ctx, url, input_format, NULL);
if(ret < 0){
av_log(NULL, AV_LOG_ERROR, "avformat_open_input %s\n", av_err2str(ret));
goto __ERROR;
}
av_dump_format(fmt_ctx, 0, url, 0);
__ERROR:
if(fmt_ctx) {
avformat_close_input(&fmt_ctx);
}
}
void open_video(){
av_log(NULL, AV_LOG_ERROR, "open_video\n");
AVFormatContext *fmt_ctx;
int ret;
char *url = "0:";
AVInputFormat *input_format;
AVDictionary *options = NULL;
avdevice_register_all(); //注册设备
input_format = av_find_input_format("avfoundation");
if(!input_format){
av_log(NULL, AV_LOG_ERROR, "open_video av_find_input_format error\n");
return;
}
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "framerate", "30", 0);
av_dict_set(&options, "pixel_format", "nv12", 0);
ret = avformat_open_input(&fmt_ctx, url, input_format, &options);
if(ret < 0){
av_log(NULL, AV_LOG_ERROR, "open_video avformat_open_input %s\n", av_err2str(ret));
goto __ERROR;
}
av_dump_format(fmt_ctx, 0, url, 0);
__ERROR:
if(fmt_ctx) {
avformat_close_input(&fmt_ctx);
}
}
void open_video_and_audio(){
av_log(NULL, AV_LOG_ERROR, "open_video_and_audio\n");
AVFormatContext *fmt_ctx;
int ret;
char *url = "0:0";
AVInputFormat *input_format;
AVDictionary *options = NULL;
avdevice_register_all(); //注册设备
input_format = av_find_input_format("avfoundation");
if(!input_format){
av_log(NULL, AV_LOG_ERROR, "open_video_and_audio av_find_input_format error\n");
return;
}
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "framerate", "30", 0);
av_dict_set(&options, "pixel_format", "nv12", 0);
ret = avformat_open_input(&fmt_ctx, url, input_format, &options);
if(ret < 0){
av_log(NULL, AV_LOG_ERROR, "open_video_and_audio avformat_open_input %s\n", av_err2str(ret));
goto __ERROR;
}
av_dump_format(fmt_ctx, 0, url, 0);
__ERROR:
if(fmt_ctx) {
avformat_close_input(&fmt_ctx);
}
}
int main(int argc, char* argv[]){
av_log_set_level(AV_LOG_INFO);
// open_file();
// open_audio();
open_video_and_audio();
return 0;
}
从输出中我们可以看到多媒体的信息。