/** * Read packets of a media file to get stream information. This * is useful for file formats with no headers such as MPEG. This * function also computes the real framerate in case of MPEG-2 repeat * frame mode. * The logical file position is not changed by this function; * examined packets may be buffered for later processing. * ... */ intavformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
for (;;) { int analyzed_all_streams; //break1: 检查是否被打断(或者说取消了继续探测),如果是,直接 break 退出 if (ff_check_interrupt(&ic->interrupt_callback)) { ret = AVERROR_EXIT; av_log(ic, AV_LOG_DEBUG, "interrupted\n"); break; }
/* check if one codec still needs to be handled */ //这个 for-loop 里做了一些对流信息的检测,如果循环能正常结束, //说明流信息的探测基本完成,这时 i == ic->nb_streams; //如果中间被 break 了,也就是说某个流的信息还没有完全得到, //此时 i < ic->nb_streams 的。 //(第一次执行的时候,因为还没有流,所以会直接跳过) for (i = 0; i < ic->nb_streams; i++) { int fps_analyze_framecount = 20; int count;
st = ic->streams[i]; //codec信息是否完整 if (!has_codec_parameters(st, NULL)) break; /* If the timebase is coarse (like the usual millisecond precision * of mkv), we need to analyze more frames to reliably arrive at * the correct fps. */ if (av_q2d(st->time_base) > 0.0005) fps_analyze_framecount *= 2; if (!tb_unreliable(st->internal->avctx)) fps_analyze_framecount = 0; if (ic->fps_probe_size >= 0) fps_analyze_framecount = ic->fps_probe_size; if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) fps_analyze_framecount = 0; /* variable fps and no guess at the real fps */ count = (ic->iformat->flags & AVFMT_NOTIMESTAMPS) ? st->info->codec_info_duration_fields/2 : st->info->duration_count; if (!(st->r_frame_rate.num && st->avg_frame_rate.num) && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (count < fps_analyze_framecount) break; } // Look at the first 3 frames if there is evidence of frame delay // but the decoder delay is not set. if (st->info->frame_delay_evidence && count < 2 && st->internal->avctx->has_b_frames == 0) break; if (!st->internal->avctx->extradata && (!st->internal->extract_extradata.inited || st->internal->extract_extradata.bsf) && extract_extradata_check(st)) break; if (st->first_dts == AV_NOPTS_VALUE && !(ic->iformat->flags & AVFMT_NOTIMESTAMPS) && st->codec_info_nb_frames < ((st->disposition & AV_DISPOSITION_ATTACHED_PIC) ? 1 : ic->max_ts_probe) && (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)) break; } analyzed_all_streams = 0; //上面提到的 missing_streams 起到作用了,判断是否所有流都找到了 if (!missing_streams || !*missing_streams) //上面也提到了,i == ic->nb_streams 时,说明所有的流,以及流信息都没有问题了 if (i == ic->nb_streams) { analyzed_all_streams = 1; /* NOTE: If the format has no header, then we need to read some * packets to get most of the streams, so we cannot stop here. */ //如果是有头的封装格式,直接break退出了,如果是像 MPEG 这种没有头的封装格式,需要解析更多的 packets 来探测。 if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) { /* If we found the info for all the codecs, we can stop. */ ret = count; av_log(ic, AV_LOG_DEBUG, "All info found\n"); flush_codecs = 0; //break2: 所有的流以及流信息都没有问题,正常退出 for 循环 break; } }
//走到这里,说明还有些流没探测出来,或者有些流信息还没完善。
/* We did not get all the codec info, but we read too much data. */ //虽然流信息还没完全探测出来,如果已读取到的大小超过了设定的 probesize,也会退出 if (read_size >= probesize) { ret = count; for (i = 0; i < ic->nb_streams; i++) if (!ic->streams[i]->r_frame_rate.num && ic->streams[i]->info->duration_count <= 1 && ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && strcmp(ic->iformat->name, "image2")) av_log(ic, AV_LOG_WARNING, "Stream #%d: not enough frames to estimate rate; " "consider increasing probesize\n", i); //break3: 读取到的大小超过了设定的 probesize,退出 break; }
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { #if FF_API_R_FRAME_RATE ff_rfps_add_frame(ic, st, pkt->dts); #endif if (pkt->dts != pkt->pts && pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE) st->info->frame_delay_evidence = 1; } if (!st->internal->avctx->extradata) { ret = extract_extradata(st, pkt); if (ret < 0) goto find_stream_info_err; }
/* If still no information, we try to open the codec and to * decompress the frame. We try to avoid that in most cases as * it takes longer and uses more memory. For MPEG-4, we need to * decompress for QuickTime. * * If AV_CODEC_CAP_CHANNEL_CONF is set this will force decoding of at * least one frame of codec data, this makes sure the codec initializes * the channel configuration and does not only trust the values from * the container. */
>smallest probe_size = sizeof(FLV header) + sizeof(script tag) + sizeof(audio tag of AAC sequence header) + sizeof(audio tag of AAC raw data) + sizeof(video tag of H.264 sequence header) + sizeof(video tag of H.264 NALU data)