音视频开发-FFplay视频播放流程( 二 )


打开输入文件
err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);创建好avformat上下文后 , 就打开is->filename指定的文件(或流) , 其中第三个和第四个参数可以传NULL , 由ffmpeg自动侦测待输入流的文件格式 , 也可以通过is->iformat手动指定 , format_opts参数表示设置的特殊属性 。
通过调用avformat_open_input函数 , 我们可以得到输入流的一个基本信息 。我们可以通过调用av_dump_format(ic, 0, is->filename, 0);来输出解析后的码流信息 , 可以得到如下数据:
Input #0, mpegts, from '/home/nfer/bak/cw880-latency.ts':0B f=0/0Duration: N/A, bitrate: N/AProgram 1Stream #0:0[0x68]:Video:h264 ([27][0][0][0] / 0x001B), 90k tbnStream #0:1[0x67]:Audio:aac([15][0][0][0] / 0x000F), 0 channels即 , 可以解析出
² 封装格式是mpegts , 包含两路数据流
² 流1的PID是0x68 , 类型是视频 , 编码格式是H264
² 流2的PID是0x67 , 类型是音频 , 编码格式是AAC
但是只有这些信息可定无法解码 , 比如视频的宽高比、图像编码格式(YUV or RGB …)、音频采样率、音频声道数量等等 , 以及Duration、bitrate等信息 。这些信息都需要通过其他函数来解析 。
解析码流信息
err = avformat_find_stream_info(ic, opts);因为avformat_open_input函数只能解析出一些基本的码流信息 , 不足以满足解码的要求 , 因此我们调用avformat_find_stream_info函数来尽量的解析出所有的和输入流相关的信息 。
解析码流的内部实现我们不在此处讨论 , 先看一看调用后该函数后解析出来的信息(同样采用av_dump_format来输出):
Input #0, mpegts, from '/home/nfer/bak/cw880-latency.ts':0B f=0/0Duration: 00:02:53.73, start: 2051.276989, bitrate: 1983 kb/sProgram 1Stream #0:0[0x68]: Video: h264 (Baseline) ([27][0][0][0] / 0x001B), yuv420p, 1280x720, 30 tbr, 90k tbn, 180k tbcStream #0:1[0x67]: Audio: aac ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp,72 kb/s对比上一步获取的信息 , 我们可以看到新解析出来的信息:
² 码流信息;节目时长00:02:53.73 , 开始播放时间2051.276989 , 码率1983 kb/s
² 视频信息:色彩空间YUV420p , 分辨率1280x720 , 帧率30 , 文件层的时间精度90k , 视频层的时间精度180K
² 音频信息:采样率48000 , 立体声stereo , 音频采样格式fltp(float, planar) , 音频比特率72 kb/s
需要注意的是 , 该函数是一个阻塞操作 , 即默认情况下会在该函数中阻塞5s 。具体的实现是在avformat_open_input函数中有一个for(;;) 循环 , 其中的一个break条件如下:
if (t >= ic->max_analyze_duration) {undefinedav_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %d reached at %"PRId64" microsecondsn", ic->max_analyze_duration, t);break;}而ic->max_analyze_duration的默认值定义在options_table.h文件中 , 即默认的参数表:
{"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT, {.i64 = 5*AV_TIME_BASE }, 0, INT_MAX, D}, #define AV_TIME_BASE1000000<--file: avutil.h, line: 229如果觉得这个默认的5s阻塞时间太长 , 或者甚至觉得完全没有必要 , 即我们可以手动的设置各种解码的参数 , 那么可以通过下面的方法将ic->max_analyze_duration的值修改为1s:
ic = avformat_alloc_context();ic->interrupt_callback.callback = decode_interrupt_cb;ic->interrupt_callback.opaque = is;//add by Nferic->max_analyze_duration =1*1000*1000;av_log(NULL, AV_LOG_ERROR, "ic->max_analyze_duration %d.n", ic->max_analyze_duration);err = avformat_open_input(&ic, is->filename, is->iformat, &ffp->format_opts);注:红色部分为添加的代码
相关视频推荐
linux中FFmpeg常用结构体及ffplay框架分析_哔哩哔哩_bilibili
音视频开发第一个项目-FFmpeg播放器开发|FFmpeg播放器框架讲解 , 代码实现视频播放 , 如何同时解码多路视频 , FFmpeg内存对齐花屏问题剖析_哔哩哔哩_bilibili
学习地址:【免费】
FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发-学习视频教程-腾讯课堂
需要更多ffmpeg/webrtc..音视频流媒体开发学习资料加群812855908领取


推荐阅读