• FFmpeg封装函数avformat_open_input()


    FFmpeg在调用avformat_open_input()之后,可能码流信息不够完整,可以使用avformat_find_stream_info()获取更多的码流信息。比如获取视频帧率、视频宽高,重新计算最大分析时长,打开解码器解码获取codec数据。

    函数原型如下:

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

    参数类型:

    ic:AVFormatContext结构体的指针。该参数用于存储打开的媒体文件的信息。
    当该函数成功返回时,AVFormatContext结构体中将存储媒体文件的相关信息。

    options:AVDictionary是一个结构体,是一对键值对key/value,经常使用AVDictionary设置或读取内部参数。

    1. int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
    2. {
    3. /*** 第一部分:申明一些局部变量,并初始化 ***/
    4. int i, count = 0, ret = 0, j;
    5. int64_t read_size;
    6. AVStream *st;
    7. AVCodecContext *avctx;
    8. AVPacket pkt1, *pkt;
    9. // 获取已消费完毕的数据对应于文件偏移量,注意不是已读取数据对应文件偏移量
    10. int64_t old_offset = avio_tell(ic->pb);
    11. // new streams might appear, no options for those
    12. // 在avformat_open_input函数中可能已经new出AVStream,nb_streams也对应流个数
    13. int orig_nb_streams = ic->nb_streams;
    14. int flush_codecs;
    15. // 在AVFormatContext初始化中已经设置该值为默认值0
    16. int64_t max_analyze_duration = ic->max_analyze_duration;
    17. int64_t max_stream_analyze_duration;
    18. int64_t max_subtitle_analyze_duration;
    19. // 在AVFormatContext初始化中已经设置该值为默认值为5000000
    20. int64_t probesize = ic->probesize;
    21. int eof_reached = 0;
    22. // 若在avformat_open_input分析输入封装格式时,会读取文件头部来看是否存在流来给missing_streams赋值
    23. int *missing_streams = av_opt_ptr(ic->iformat->priv_class, ic->priv_data, "missing_streams");
    24. flush_codecs = probesize > 0;
    25. av_opt_set(ic, "skip_clear", "1", AV_OPT_SEARCH_CHILDREN);
    26. // 由于max_analyze_duration大概率为0(因为被初始化为0,中间被修改的概率比较小),因此一般情况下,会进入if(){...}语句中执行
    27. max_stream_analyze_duration = max_analyze_duration;
    28. max_subtitle_analyze_duration = max_analyze_duration;
    29. if (!max_analyze_duration) {
    30. // 分析流的最大时长和分析文件的最大时长均设置为5倍AV_TIME_BASE, AV_TIME_BASE为1000000,而max_stream_analyze_duration和max_analyze_duration单位刚好为微妙,结合起来正好描述为5s重
    31. max_stream_analyze_duration =
    32. max_analyze_duration = 5*AV_TIME_BASE;
    33. // 同理,分析字幕时的时长为30s
    34. max_subtitle_analyze_duration = 30*AV_TIME_BASE;
    35. // 如果是flv文件格式,流分析时长延长到90s
    36. if (!strcmp(ic->iformat->name, "flv"))
    37. max_stream_analyze_duration = 90*AV_TIME_BASE;
    38. // 如果是mpeg格式,mpegts格式,流分析时长为7s
    39. if (!strcmp(ic->iformat->name, "mpeg") || !strcmp(ic->iformat->name, "mpegts"))
    40. max_stream_analyze_duration = 7*AV_TIME_BASE;
    41. }
    42. // 如果AVIOContext已经存在,那么也许已经读取了数据,这儿输出当前io读取情况。
    43. // avio_tell(ic->pb)输出已读取并处理完的数据偏移位置(文件偏移量),
    44. // bytes_read为已读取数据字节数,seek_count是已经做过多少次seek操作, nb_streams为流个数
    45. if (ic->pb)
    46. av_log(ic, AV_LOG_DEBUG, "Before avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d nb_streams:%d\n",
    47. avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count, ic->nb_streams);
    48. // 第一个for循环,做什么的?
    49. // 赋值AVStream->AVStreamInternal编码器参数值,并通过打开流的解码器来验证这些参数值是否正确
    50. for (i = 0; i < ic->nb_streams; i++) {
    51. const AVCodec *codec;
    52. AVDictionary *thread_opt = NULL;
    53. st = ic->streams[i];
    54. avctx = st->internal->avctx;
    55. // 在文件格式读取文件头的函数中,会解析并给AVStream->time_base时间基赋值
    56. // 复制时间基到AVStream->AVStreamInternal->AVCodecContext->time_base中
    57. if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
    58. st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
    59. /* if (!st->time_base.num)
    60. st->time_base = */
    61. if (!avctx->time_base.num)
    62. avctx->time_base = st->time_base;
    63. }
    64. // 外部用户修改了AVStream的AVCodecContext,那么这儿保持AVStream的AVCodecParameters中
    65. // codec_id, codec_type, AVStream的AVStreamInternal中的orig_codec_id,与AVStream的
    66. // AVCodecContext中的数据保持一致。
    67. /* check if the caller has overridden the codec id */
    68. #if FF_API_LAVF_AVCTX
    69. FF_DISABLE_DEPRECATION_WARNINGS
    70. if (st->codec->codec_id != st->internal->orig_codec_id) {
    71. st->codecpar->codec_id = st->codec->codec_id;
    72. st->codecpar->codec_type = st->codec->codec_type;
    73. st->internal->orig_codec_id = st->codec->codec_id;
    74. }
    75. FF_ENABLE_DEPRECATION_WARNINGS
    76. #endif
    77. // 查看流分析需不需要解析器,解析器用来从流中分离出单独的视频帧和音频帧
    78. // only for the split stuff
    79. if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE) && st->request_probe <= 0) {
    80. st->parser = av_parser_init(st->codecpar->codec_id);
    81. if (st->parser) {
    82. if (st->need_parsing == AVSTREAM_PARSE_HEADERS) {
    83. st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
    84. } else if (st->need_parsing == AVSTREAM_PARSE_FULL_RAW) {
    85. st->parser->flags |= PARSER_FLAG_USE_CODEC_TS;
    86. }
    87. } else if (st->need_parsing) {
    88. av_log(ic, AV_LOG_VERBOSE, "parser not found for codec "
    89. "%s, packets or times may be invalid.\n",
    90. avcodec_get_name(st->codecpar->codec_id));
    91. }
    92. }
    93. // 确保AVStream->AVStreaminternal中关于编解码器的相关参数正确
    94. if (st->codecpar->codec_id != st->internal->orig_codec_id)
    95. st->internal->orig_codec_id = st->codecpar->codec_id;
    96. ret = avcodec_parameters_to_context(avctx, st->codecpar); // 复制编解码器参数
    97. if (ret < 0)
    98. goto find_stream_info_err;
    99. if (st->request_probe <= 0)
    100. st->internal->avctx_inited = 1; // 设置初始化标志位
    101. // 查找解码器
    102. codec = find_probe_decoder(ic, st, st->codecpar->codec_id);
    103. // 设置解码线程为1
    104. /* Force thread count to 1 since the H.264 decoder will not extract
    105. * SPS and PPS to extradata during multi-threaded decoding. */
    106. av_dict_set(options ? &options[i] : &thread_opt, "threads", "1", 0);
    107. if (ic->codec_whitelist)
    108. av_dict_set(options ? &options[i] : &thread_opt, "codec_whitelist", ic->codec_whitelist, 0);
    109. // 对于字幕流,尝试打开解码器,确保字幕头是否正确的设置
    110. /* Ensure that subtitle_header is properly set. */
    111. if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE
    112. && codec && !avctx->codec) {
    113. if (avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt) < 0)
    114. av_log(ic, AV_LOG_WARNING,
    115. "Failed to open codec in %s\n",__FUNCTION__);
    116. }
    117. // 尝试打开解码器,看是否已获得足够的编解码参数
    118. // Try to just open decoders, in case this is enough to get parameters.
    119. if (!has_codec_parameters(st, NULL) && st->request_probe <= 0) {
    120. if (codec && !avctx->codec)
    121. if (avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt) < 0)
    122. av_log(ic, AV_LOG_WARNING,
    123. "Failed to open codec in %s\n",__FUNCTION__);
    124. }
    125. if (!options)
    126. av_dict_free(&thread_opt);
    127. }
    128. // 第二个for循环,做什么的?
    129. // 给AVStream内部使用的info结构体的一些成员赋初始值,这几个成员用于平均帧率估计
    130. for (i = 0; i < ic->nb_streams; i++) {
    131. #if FF_API_R_FRAME_RATE
    132. ic->streams[i]->info->last_dts = AV_NOPTS_VALUE;
    133. #endif
    134. ic->streams[i]->info->fps_first_dts = AV_NOPTS_VALUE;
    135. ic->streams[i]->info->fps_last_dts = AV_NOPTS_VALUE;
    136. }
    137. // 第三个for循环,死循环,做什么的?
    138. //
    139. read_size = 0;
    140. for (;;) {
    141. int analyzed_all_streams;
    142. // 检测是否有外部中断,可以帮助快速退出循环,终止程序运行,ic->interrupt_callback
    143. // 由用户定义,因此,何时需要终止程序是受用户支配的。
    144. if (ff_check_interrupt(&ic->interrupt_callback)) {
    145. ret = AVERROR_EXIT;
    146. av_log(ic, AV_LOG_DEBUG, "interrupted\n");
    147. break;
    148. }
    149. //
    150. /* check if one codec still needs to be handled */
    151. for (i = 0; i < ic->nb_streams; i++) {
    152. int fps_analyze_framecount = 20;
    153. int count;
    154. st = ic->streams[i];
    155. if (!has_codec_parameters(st, NULL))
    156. break;
    157. /* If the timebase is coarse (like the usual millisecond precision
    158. * of mkv), we need to analyze more frames to reliably arrive at
    159. * the correct fps. */
    160. if (av_q2d(st->time_base) > 0.0005)
    161. fps_analyze_framecount *= 2;
    162. if (!tb_unreliable(st->internal->avctx))
    163. fps_analyze_framecount = 0;
    164. if (ic->fps_probe_size >= 0)
    165. fps_analyze_framecount = ic->fps_probe_size;
    166. if (st->disposition & AV_DISPOSITION_ATTACHED_PIC)
    167. fps_analyze_framecount = 0;
    168. /* variable fps and no guess at the real fps */
    169. count = (ic->iformat->flags & AVFMT_NOTIMESTAMPS) ?
    170. st->info->codec_info_duration_fields/2 :
    171. st->info->duration_count;
    172. if (!(st->r_frame_rate.num && st->avg_frame_rate.num) &&
    173. st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
    174. if (count < fps_analyze_framecount)
    175. break;
    176. }
    177. // Look at the first 3 frames if there is evidence of frame delay
    178. // but the decoder delay is not set.
    179. if (st->info->frame_delay_evidence && count < 2 && st->internal->avctx->has_b_frames == 0)
    180. break;
    181. if (!st->internal->avctx->extradata &&
    182. (!st->internal->extract_extradata.inited ||
    183. st->internal->extract_extradata.bsf) &&
    184. extract_extradata_check(st))
    185. break;
    186. if (st->first_dts == AV_NOPTS_VALUE &&
    187. !(ic->iformat->flags & AVFMT_NOTIMESTAMPS) &&
    188. st->codec_info_nb_frames < ((st->disposition & AV_DISPOSITION_ATTACHED_PIC) ? 1 : ic->max_ts_probe) &&
    189. (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
    190. st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO))
    191. break;
    192. }
    193. analyzed_all_streams = 0;
    194. if (!missing_streams || !*missing_streams)
    195. if (i == ic->nb_streams) {
    196. analyzed_all_streams = 1;
    197. /* NOTE: If the format has no header, then we need to read some
    198. * packets to get most of the streams, so we cannot stop here. */
    199. if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) {
    200. /* If we found the info for all the codecs, we can stop. */
    201. ret = count;
    202. av_log(ic, AV_LOG_DEBUG, "All info found\n");
    203. flush_codecs = 0;
    204. break;
    205. }
    206. }
    207. /* We did not get all the codec info, but we read too much data. */
    208. if (read_size >= probesize) {
    209. ret = count;
    210. av_log(ic, AV_LOG_DEBUG,
    211. "Probe buffer size limit of %"PRId64" bytes reached\n", probesize);
    212. for (i = 0; i < ic->nb_streams; i++)
    213. if (!ic->streams[i]->r_frame_rate.num &&
    214. ic->streams[i]->info->duration_count <= 1 &&
    215. ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
    216. strcmp(ic->iformat->name, "image2"))
    217. av_log(ic, AV_LOG_WARNING,
    218. "Stream #%d: not enough frames to estimate rate; "
    219. "consider increasing probesize\n", i);
    220. break;
    221. }
    222. /* NOTE: A new stream can be added there if no header in file
    223. * (AVFMTCTX_NOHEADER). */
    224. ret = read_frame_internal(ic, &pkt1);
    225. if (ret == AVERROR(EAGAIN))
    226. continue;
    227. if (ret < 0) {
    228. /* EOF or error*/
    229. eof_reached = 1;
    230. break;
    231. }
    232. pkt = &pkt1;
    233. if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) {
    234. ret = ff_packet_list_put(&ic->internal->packet_buffer,
    235. &ic->internal->packet_buffer_end,
    236. pkt, 0);
    237. if (ret < 0)
    238. goto find_stream_info_err;
    239. }
    240. st = ic->streams[pkt->stream_index];
    241. if (!(st->disposition & AV_DISPOSITION_ATTACHED_PIC))
    242. read_size += pkt->size;
    243. avctx = st->internal->avctx;
    244. if (!st->internal->avctx_inited) {
    245. ret = avcodec_parameters_to_context(avctx, st->codecpar);
    246. if (ret < 0)
    247. goto find_stream_info_err;
    248. st->internal->avctx_inited = 1;
    249. }
    250. if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) {
    251. /* check for non-increasing dts */
    252. if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
    253. st->info->fps_last_dts >= pkt->dts) {
    254. av_log(ic, AV_LOG_DEBUG,
    255. "Non-increasing DTS in stream %d: packet %d with DTS "
    256. "%"PRId64", packet %d with DTS %"PRId64"\n",
    257. st->index, st->info->fps_last_dts_idx,
    258. st->info->fps_last_dts, st->codec_info_nb_frames,
    259. pkt->dts);
    260. st->info->fps_first_dts =
    261. st->info->fps_last_dts = AV_NOPTS_VALUE;
    262. }
    263. /* Check for a discontinuity in dts. If the difference in dts
    264. * is more than 1000 times the average packet duration in the
    265. * sequence, we treat it as a discontinuity. */
    266. if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
    267. st->info->fps_last_dts_idx > st->info->fps_first_dts_idx &&
    268. (pkt->dts - st->info->fps_last_dts) / 1000 >
    269. (st->info->fps_last_dts - (uint64_t)st->info->fps_first_dts) /
    270. (st->info->fps_last_dts_idx - st->info->fps_first_dts_idx)) {
    271. av_log(ic, AV_LOG_WARNING,
    272. "DTS discontinuity in stream %d: packet %d with DTS "
    273. "%"PRId64", packet %d with DTS %"PRId64"\n",
    274. st->index, st->info->fps_last_dts_idx,
    275. st->info->fps_last_dts, st->codec_info_nb_frames,
    276. pkt->dts);
    277. st->info->fps_first_dts =
    278. st->info->fps_last_dts = AV_NOPTS_VALUE;
    279. }
    280. /* update stored dts values */
    281. if (st->info->fps_first_dts == AV_NOPTS_VALUE) {
    282. st->info->fps_first_dts = pkt->dts;
    283. st->info->fps_first_dts_idx = st->codec_info_nb_frames;
    284. }
    285. st->info->fps_last_dts = pkt->dts;
    286. st->info->fps_last_dts_idx = st->codec_info_nb_frames;
    287. }
    288. if (st->codec_info_nb_frames>1) {
    289. int64_t t = 0;
    290. int64_t limit;
    291. if (st->time_base.den > 0)
    292. t = av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q);
    293. if (st->avg_frame_rate.num > 0)
    294. t = FFMAX(t, av_rescale_q(st->codec_info_nb_frames, av_inv_q(st->avg_frame_rate), AV_TIME_BASE_Q));
    295. if ( t == 0
    296. && st->codec_info_nb_frames>30
    297. && st->info->fps_first_dts != AV_NOPTS_VALUE
    298. && st->info->fps_last_dts != AV_NOPTS_VALUE)
    299. t = FFMAX(t, av_rescale_q(st->info->fps_last_dts - st->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q));
    300. if (analyzed_all_streams) limit = max_analyze_duration;
    301. else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) limit = max_subtitle_analyze_duration;
    302. else limit = max_stream_analyze_duration;
    303. if (t >= limit) {
    304. av_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %"PRId64" reached at %"PRId64" microseconds st:%d\n",
    305. limit,
    306. t, pkt->stream_index);
    307. if (ic->flags & AVFMT_FLAG_NOBUFFER)
    308. av_packet_unref(pkt);
    309. break;
    310. }
    311. if (pkt->duration) {
    312. if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE && pkt->pts != AV_NOPTS_VALUE && pkt->pts >= st->start_time) {
    313. st->info->codec_info_duration = FFMIN(pkt->pts - st->start_time, st->info->codec_info_duration + pkt->duration);
    314. } else
    315. st->info->codec_info_duration += pkt->duration;
    316. st->info->codec_info_duration_fields += st->parser && st->need_parsing && avctx->ticks_per_frame ==2 ? st->parser->repeat_pict + 1 : 2;
    317. }
    318. }
    319. if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
    320. #if FF_API_R_FRAME_RATE
    321. ff_rfps_add_frame(ic, st, pkt->dts);
    322. #endif
    323. if (pkt->dts != pkt->pts && pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE)
    324. st->info->frame_delay_evidence = 1;
    325. }
    326. if (!st->internal->avctx->extradata) {
    327. ret = extract_extradata(st, pkt);
    328. if (ret < 0)
    329. goto find_stream_info_err;
    330. }
    331. /* If still no information, we try to open the codec and to
    332. * decompress the frame. We try to avoid that in most cases as
    333. * it takes longer and uses more memory. For MPEG-4, we need to
    334. * decompress for QuickTime.
    335. *
    336. * If AV_CODEC_CAP_CHANNEL_CONF is set this will force decoding of at
    337. * least one frame of codec data, this makes sure the codec initializes
    338. * the channel configuration and does not only trust the values from
    339. * the container. */
    340. try_decode_frame(ic, st, pkt,
    341. (options && i < orig_nb_streams) ? &options[i] : NULL);
    342. if (ic->flags & AVFMT_FLAG_NOBUFFER)
    343. av_packet_unref(pkt);
    344. st->codec_info_nb_frames++;
    345. count++;
    346. }
    347. if (eof_reached) {
    348. int stream_index;
    349. for (stream_index = 0; stream_index < ic->nb_streams; stream_index++) {
    350. st = ic->streams[stream_index];
    351. avctx = st->internal->avctx;
    352. if (!has_codec_parameters(st, NULL)) {
    353. const AVCodec *codec = find_probe_decoder(ic, st, st->codecpar->codec_id);
    354. if (codec && !avctx->codec) {
    355. AVDictionary *opts = NULL;
    356. if (ic->codec_whitelist)
    357. av_dict_set(&opts, "codec_whitelist", ic->codec_whitelist, 0);
    358. if (avcodec_open2(avctx, codec, (options && stream_index < orig_nb_streams) ? &options[stream_index] : &opts) < 0)
    359. av_log(ic, AV_LOG_WARNING,
    360. "Failed to open codec in %s\n",__FUNCTION__);
    361. av_dict_free(&opts);
    362. }
    363. }
    364. // EOF already reached while reading the stream above.
    365. // So continue with reoordering DTS with whatever delay we have.
    366. if (ic->internal->packet_buffer && !has_decode_delay_been_guessed(st)) {
    367. update_dts_from_pts(ic, stream_index, ic->internal->packet_buffer);
    368. }
    369. }
    370. }
    371. if (flush_codecs) {
    372. AVPacket empty_pkt = { 0 };
    373. int err = 0;
    374. av_init_packet(&empty_pkt);
    375. for (i = 0; i < ic->nb_streams; i++) {
    376. st = ic->streams[i];
    377. /* flush the decoders */
    378. if (st->info->found_decoder == 1) {
    379. do {
    380. err = try_decode_frame(ic, st, &empty_pkt,
    381. (options && i < orig_nb_streams)
    382. ? &options[i] : NULL);
    383. } while (err > 0 && !has_codec_parameters(st, NULL));
    384. if (err < 0) {
    385. av_log(ic, AV_LOG_INFO,
    386. "decoding for stream %d failed\n", st->index);
    387. }
    388. }
    389. }
    390. }
    391. ff_rfps_calculate(ic);
    392. for (i = 0; i < ic->nb_streams; i++) {
    393. st = ic->streams[i];
    394. avctx = st->internal->avctx;
    395. if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
    396. if (avctx->codec_id == AV_CODEC_ID_RAWVIDEO && !avctx->codec_tag && !avctx->bits_per_coded_sample) {
    397. uint32_t tag= avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt);
    398. if (avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), tag) == avctx->pix_fmt)
    399. avctx->codec_tag= tag;
    400. }
    401. /* estimate average framerate if not set by demuxer */
    402. if (st->info->codec_info_duration_fields &&
    403. !st->avg_frame_rate.num &&
    404. st->info->codec_info_duration) {
    405. int best_fps = 0;
    406. double best_error = 0.01;
    407. AVRational codec_frame_rate = avctx->framerate;
    408. if (st->info->codec_info_duration >= INT64_MAX / st->time_base.num / 2||
    409. st->info->codec_info_duration_fields >= INT64_MAX / st->time_base.den ||
    410. st->info->codec_info_duration < 0)
    411. continue;
    412. av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
    413. st->info->codec_info_duration_fields * (int64_t) st->time_base.den,
    414. st->info->codec_info_duration * 2 * (int64_t) st->time_base.num, 60000);
    415. /* Round guessed framerate to a "standard" framerate if it's
    416. * within 1% of the original estimate. */
    417. for (j = 0; j < MAX_STD_TIMEBASES; j++) {
    418. AVRational std_fps = { get_std_framerate(j), 12 * 1001 };
    419. double error = fabs(av_q2d(st->avg_frame_rate) /
    420. av_q2d(std_fps) - 1);
    421. if (error < best_error) {
    422. best_error = error;
    423. best_fps = std_fps.num;
    424. }
    425. if (ic->internal->prefer_codec_framerate && codec_frame_rate.num > 0 && codec_frame_rate.den > 0) {
    426. error = fabs(av_q2d(codec_frame_rate) /
    427. av_q2d(std_fps) - 1);
    428. if (error < best_error) {
    429. best_error = error;
    430. best_fps = std_fps.num;
    431. }
    432. }
    433. }
    434. if (best_fps)
    435. av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
    436. best_fps, 12 * 1001, INT_MAX);
    437. }
    438. if (!st->r_frame_rate.num) {
    439. if ( avctx->time_base.den * (int64_t) st->time_base.num
    440. <= avctx->time_base.num * avctx->ticks_per_frame * (int64_t) st->time_base.den) {
    441. av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
    442. avctx->time_base.den, (int64_t)avctx->time_base.num * avctx->ticks_per_frame, INT_MAX);
    443. } else {
    444. st->r_frame_rate.num = st->time_base.den;
    445. st->r_frame_rate.den = st->time_base.num;
    446. }
    447. }
    448. if (st->display_aspect_ratio.num && st->display_aspect_ratio.den) {
    449. AVRational hw_ratio = { avctx->height, avctx->width };
    450. st->sample_aspect_ratio = av_mul_q(st->display_aspect_ratio,
    451. hw_ratio);
    452. }
    453. } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
    454. if (!avctx->bits_per_coded_sample)
    455. avctx->bits_per_coded_sample =
    456. av_get_bits_per_sample(avctx->codec_id);
    457. // set stream disposition based on audio service type
    458. switch (avctx->audio_service_type) {
    459. case AV_AUDIO_SERVICE_TYPE_EFFECTS:
    460. st->disposition = AV_DISPOSITION_CLEAN_EFFECTS;
    461. break;
    462. case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED:
    463. st->disposition = AV_DISPOSITION_VISUAL_IMPAIRED;
    464. break;
    465. case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED:
    466. st->disposition = AV_DISPOSITION_HEARING_IMPAIRED;
    467. break;
    468. case AV_AUDIO_SERVICE_TYPE_COMMENTARY:
    469. st->disposition = AV_DISPOSITION_COMMENT;
    470. break;
    471. case AV_AUDIO_SERVICE_TYPE_KARAOKE:
    472. st->disposition = AV_DISPOSITION_KARAOKE;
    473. break;
    474. }
    475. }
    476. }
    477. if (probesize)
    478. estimate_timings(ic, old_offset);
    479. av_opt_set(ic, "skip_clear", "0", AV_OPT_SEARCH_CHILDREN);
    480. if (ret >= 0 && ic->nb_streams)
    481. /* We could not have all the codec parameters before EOF. */
    482. ret = -1;
    483. for (i = 0; i < ic->nb_streams; i++) {
    484. const char *errmsg;
    485. st = ic->streams[i];
    486. /* if no packet was ever seen, update context now for has_codec_parameters */
    487. if (!st->internal->avctx_inited) {
    488. if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
    489. st->codecpar->format == AV_SAMPLE_FMT_NONE)
    490. st->codecpar->format = st->internal->avctx->sample_fmt;
    491. ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar);
    492. if (ret < 0)
    493. goto find_stream_info_err;
    494. }
    495. if (!has_codec_parameters(st, &errmsg)) {
    496. char buf[256];
    497. avcodec_string(buf, sizeof(buf), st->internal->avctx, 0);
    498. av_log(ic, AV_LOG_WARNING,
    499. "Could not find codec parameters for stream %d (%s): %s\n"
    500. "Consider increasing the value for the 'analyzeduration' and 'probesize' options\n",
    501. i, buf, errmsg);
    502. } else {
    503. ret = 0;
    504. }
    505. }
    506. compute_chapters_end(ic);
    507. /* update the stream parameters from the internal codec contexts */
    508. for (i = 0; i < ic->nb_streams; i++) {
    509. st = ic->streams[i];
    510. if (st->internal->avctx_inited) {
    511. int orig_w = st->codecpar->width;
    512. int orig_h = st->codecpar->height;
    513. ret = avcodec_parameters_from_context(st->codecpar, st->internal->avctx);
    514. if (ret < 0)
    515. goto find_stream_info_err;
    516. #if FF_API_LOWRES
    517. // The decoder might reduce the video size by the lowres factor.
    518. if (st->internal->avctx->lowres && orig_w) {
    519. st->codecpar->width = orig_w;
    520. st->codecpar->height = orig_h;
    521. }
    522. #endif
    523. }
    524. #if FF_API_LAVF_AVCTX
    525. FF_DISABLE_DEPRECATION_WARNINGS
    526. ret = avcodec_parameters_to_context(st->codec, st->codecpar);
    527. if (ret < 0)
    528. goto find_stream_info_err;
    529. #if FF_API_LOWRES
    530. // The old API (AVStream.codec) "requires" the resolution to be adjusted
    531. // by the lowres factor.
    532. if (st->internal->avctx->lowres && st->internal->avctx->width) {
    533. st->codec->lowres = st->internal->avctx->lowres;
    534. st->codec->width = st->internal->avctx->width;
    535. st->codec->height = st->internal->avctx->height;
    536. }
    537. #endif
    538. if (st->codec->codec_tag != MKTAG('t','m','c','d')) {
    539. st->codec->time_base = st->internal->avctx->time_base;
    540. st->codec->ticks_per_frame = st->internal->avctx->ticks_per_frame;
    541. }
    542. st->codec->framerate = st->avg_frame_rate;
    543. if (st->internal->avctx->subtitle_header) {
    544. st->codec->subtitle_header = av_malloc(st->internal->avctx->subtitle_header_size);
    545. if (!st->codec->subtitle_header)
    546. goto find_stream_info_err;
    547. st->codec->subtitle_header_size = st->internal->avctx->subtitle_header_size;
    548. memcpy(st->codec->subtitle_header, st->internal->avctx->subtitle_header,
    549. st->codec->subtitle_header_size);
    550. }
    551. // Fields unavailable in AVCodecParameters
    552. st->codec->coded_width = st->internal->avctx->coded_width;
    553. st->codec->coded_height = st->internal->avctx->coded_height;
    554. st->codec->properties = st->internal->avctx->properties;
    555. FF_ENABLE_DEPRECATION_WARNINGS
    556. #endif
    557. st->internal->avctx_inited = 0;
    558. }
    559. find_stream_info_err:
    560. for (i = 0; i < ic->nb_streams; i++) {
    561. st = ic->streams[i];
    562. if (st->info)
    563. av_freep(&st->info->duration_error);
    564. avcodec_close(ic->streams[i]->internal->avctx);
    565. av_freep(&ic->streams[i]->info);
    566. av_bsf_free(&ic->streams[i]->internal->extract_extradata.bsf);
    567. av_packet_free(&ic->streams[i]->internal->extract_extradata.pkt);
    568. }
    569. if (ic->pb)
    570. av_log(ic, AV_LOG_DEBUG, "After avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d frames:%d\n",
    571. avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count, count);
    572. return ret;
    573. }

    --------------------------------------------------------------

    本函数中,先对一部分数据进行声明和初始化,然后有多个类似于for (i = 0; i < ic->nb_streams; i++) {...}的循环处理,还有一个for(;;)死循环的处理。接下来就对整个过程做一个比较详细的分析:

    1 局部变量的申明,以及数据初始化:
          1)int64_t old_offset  = avio_tell(ic->pb);   保存当前文件偏移量,由于avformat_open_input()函数中已经打开文件,并且读取了文件头,因此,文件偏移已经不为0,此时,该变量保存当前的文件偏移
          2)int orig_nb_streams = ic->nb_streams; 保存avformat_open_input()读取文件头时获取的文件中流的个数,注意对于flv这种格式这个值为0.
          3)int64_t max_analyze_duration = ic->max_analyze_duration; 保存最大的分析时长,ic->max_analyze_duration在构建AVFormatContext过程中被初始化为0,单位微妙
          4)int64_t probesize = ic->probesize; 保存进行探测的数据大小,在AVFormatContext初始化中已经设置该值为默认值为5000000,5MB大小。
          5)int *missing_streams = av_opt_ptr(ic->iformat->priv_class, ic->priv_data, "missing_streams"); 保存文件中是否存在流的指示。FFMPEG4.1源码分析之 媒体打开函数avformat_open_input()中分析了flv_read_header()函数中就对该值进行了阐述,该值不为0,表示有音视频流的存在,为0表示不存在音视频流。
          6) 流分析最大时长,最大分析时长,字幕分析时长的计算:分析时长的基本单位是微妙,而AV_TIME_BASE是1000000,那么可以由源码得知:通用情况下,流分析最大时长和最大分析时长为5*AV_TIME_BASE,即5s,字幕分析时长为30*AV_TIME_BASE,即30s;特殊情况下,比如文件格式为flv格式,那么流分析最大时长更新为90*AV_TIME_BASE,即90s,如果文件格式为mpeg或者是mpegts格式,那么流分析最大时长更新为7*AV_TIME_BASE,即7s。

    2 第一次for循环遍历每个流:

         1)复制时间基到AVStream->AVStreamInternal->AVCodecContext->time_base: 在文件格式读取文件头的函数中,会解析并给AVStream->time_base时间基赋值,此处将该时间基复制一份到AVStream->AVStreamInternal->AVCodecContext->time_base中,因为后续的解码,解码器使用AVStream->AVStreamInternal中的数据。
         2)检查用户是否修改了解码器:外部用户修改了AVStream->AVCodecContext中的编解码器,那么这儿保持AVStream->AVCodecParameters->codec_id, codec_type, AVStream->AVStreamInternal->orig_codec_id与修改后的一致。
         3)创建流的解析器:解析器用来从原始码流中分离出单独的一帧视频或音频,按需创建。
         4)检查AVStream->AVStreaminternal中的编解码参数都被合理赋值:一方面是AVStream->AVStreaminternal->orig_codec_id要赋值为AVStream->codecpar->codec_id,AVStream->codecpar->codec_id在媒体打开函数avformat_open_input()中已经通过文件格式读取文件头的函数获知到正确的codec_id;另一方面AVStream->AVStreaminternal->AVCodecContext编解码器上下文从AVStream->AVCodecParamters中拷贝一份编解码参数,因为文件格式读取文件头的函数会分析文件头并给AVStream->AVCodecParamters赋值。
         5)查找解码器,并打开解码器,从而对上述的解码器参数是否正确进行预判。
         6)总结:由上分析可知,第一次for循环遍历流,目的在于给流的AVStream->AVStreamInternal中的编码器相关参数赋值(时间戳time_base,编码器orig_codec_id,编码器上下文结构avctx);然后找到每个流的解码器,通过打开解码器是否成功来验证上述赋值的编解码器参数是否正确。

    2 第二次for循环遍历每个流:

        本次遍历是对AVStream->info结构体的部分成员赋初始值,该结构体用于存储流信息,且仅供avformat_find_stream_info()函数使用。此次赋值的几个变量是用来进行平均帧率估计的参数。

    3 第三次for循环,for(;;)死循环:

            使用ff_check_interrupt(&ic->interrupt_callback) 检测是否有外部中断,可以帮助快速退出循环,终止程序运行,ic->interrupt_callback由用户定义,并在构建AVFormatContext对象时传入,因此,何时需要终止程序是受用户支配的。

  • 相关阅读:
    Speedpdf在线转换教你如何XPS转PDF格式
    【ai】李沐 动手深度学学v2 环境安装:anaconda3、pycharm、d2
    百度云原生产品 6 月刊 | CCE 节点组支持配置多个备选机型、CCR 新增镜像加速功能
    leetcode:1648. 销售价值减少的颜色球【二分找边界】
    【编程题】【Scratch三级】2021.12跳高比赛
    Docker 与 K8S学习笔记(二十二)—— 高效使用kubectl的小技巧
    weixin支付
    dashboard中虚拟机冷迁移失败后虚拟机回退到正常状态流程、openstack数据库中修改虚拟机信息流程
    武汉新时标文化传媒有限公司短视频内容该怎么样去运营?
    Qt Core篇 后端上位机界面开发
  • 原文地址:https://blog.csdn.net/weixin_44651073/article/details/136610362