参考博客:https://blog.csdn.net/leixiaohua1020/article/details/44084321


int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
{int i, count, ret = 0, j;int64_t read_size;AVStream *st;AVPacket pkt1, *pkt;int64_t old_offset  = avio_tell(ic->pb);// new streams might appear, no options for thoseint orig_nb_streams = ic->nb_streams;int flush_codecs;int64_t max_analyze_duration = ic->max_analyze_duration2;int64_t probesize = ic->probesize2;//最大分析时长处理if (!max_analyze_duration)max_analyze_duration = ic->max_analyze_duration;
//probesize处理if (ic->probesize)probesize = ic->probesize;flush_codecs = probesize > 0;av_opt_set(ic, "skip_clear", "1", AV_OPT_SEARCH_CHILDREN);//最大分析时长处理if (!max_analyze_duration) {if (!strcmp(ic->iformat->name, "flv") && !(ic->ctx_flags & AVFMTCTX_NOHEADER)) {max_analyze_duration = 10*AV_TIME_BASE;} elsemax_analyze_duration = 5*AV_TIME_BASE;}if (ic->pb)av_log(ic, AV_LOG_DEBUG, "Before avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d\n",avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count);for (i = 0; i < ic->nb_streams; i++) {const AVCodec *codec;AVDictionary *thread_opt = NULL;st = ic->streams[i];if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
/*            if (!st->time_base.num)st->time_base = */if (!st->codec->time_base.num)st->codec->time_base = st->time_base;}// only for the split stuffif (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE)) {st->parser = av_parser_init(st->codec->codec_id);if (st->parser) {if (st->need_parsing == AVSTREAM_PARSE_HEADERS) {st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;} else if (st->need_parsing == AVSTREAM_PARSE_FULL_RAW) {st->parser->flags |= PARSER_FLAG_USE_CODEC_TS;}} else if (st->need_parsing) {av_log(ic, AV_LOG_VERBOSE, "parser not found for codec ""%s, packets or times may be invalid.\n",avcodec_get_name(st->codec->codec_id));}}//寻找解码器codec = find_decoder(ic, st, st->codec->codec_id);/* Force thread count to 1 since the H.264 decoder will not extract* SPS and PPS to extradata during multi-threaded decoding. */av_dict_set(options ? &options[i] : &thread_opt, "threads", "1", 0);if (ic->codec_whitelist)av_dict_set(options ? &options[i] : &thread_opt, "codec_whitelist", ic->codec_whitelist, 0);/* Ensure that subtitle_header is properly set. *///subtitleif (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE&& codec && !st->codec->codec) {//调用avcodec_open2解码器if (avcodec_open2(st->codec, codec, options ? &options[i] : &thread_opt) < 0)av_log(ic, AV_LOG_WARNING,"Failed to open codec in av_find_stream_info\n");}// Try to just open decoders, in case this is enough to get parameters.if (!has_codec_parameters(st, NULL) && st->request_probe <= 0) {if (codec && !st->codec->codec)if (avcodec_open2(st->codec, codec, options ? &options[i] : &thread_opt) < 0)av_log(ic, AV_LOG_WARNING,"Failed to open codec in av_find_stream_info\n");}if (!options)av_dict_free(&thread_opt);}for (i = 0; i < ic->nb_streams; i++) {
#if FF_API_R_FRAME_RATEic->streams[i]->info->last_dts = AV_NOPTS_VALUE;
#endific->streams[i]->info->fps_first_dts = AV_NOPTS_VALUE;ic->streams[i]->info->fps_last_dts  = AV_NOPTS_VALUE;}count     = 0;read_size = 0;for (;;) {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 (i = 0; i < ic->nb_streams; i++) {int fps_analyze_framecount = 20;st = ic->streams[i];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->codec))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 */if (!(st->r_frame_rate.num && st->avg_frame_rate.num) &&st->info->duration_count < fps_analyze_framecount &&st->codec->codec_type == AVMEDIA_TYPE_VIDEO)break;if (st->parser && st->parser->parser->split &&!st->codec->extradata)break;if (st->first_dts == AV_NOPTS_VALUE &&!(ic->iformat->flags & AVFMT_NOTIMESTAMPS) &&st->codec_info_nb_frames < ic->max_ts_probe &&(st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||st->codec->codec_type == AVMEDIA_TYPE_AUDIO))break;}if (i == ic->nb_streams) {/* 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. */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;break;}}/* We did not get all the codec info, but we read too much data. *///未获取所有的码流信息if (read_size >= probesize) {ret = count;av_log(ic, AV_LOG_DEBUG,"Probe buffer size limit of %"PRId64" bytes reached\n", probesize);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]->codec->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);break;}/* NOTE: A new stream can be added there if no header in file* (AVFMTCTX_NOHEADER). *///读取帧数据--压缩帧数据ret = read_frame_internal(ic, &pkt1);if (ret == AVERROR(EAGAIN))continue;if (ret < 0) {/* EOF or error*/break;}//容错机制if (ic->flags & AVFMT_FLAG_NOBUFFER)free_packet_buffer(&ic->packet_buffer, &ic->packet_buffer_end);{pkt = add_to_pktbuf(&ic->packet_buffer, &pkt1,&ic->packet_buffer_end);if (!pkt) {ret = AVERROR(ENOMEM);goto find_stream_info_err;}if ((ret = av_dup_packet(pkt)) < 0)goto find_stream_info_err;}st = ic->streams[pkt->stream_index];if (!(st->disposition & AV_DISPOSITION_ATTACHED_PIC))read_size += pkt->size;if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) {/* check for non-increasing dts */if (st->info->fps_last_dts != AV_NOPTS_VALUE &&st->info->fps_last_dts >= pkt->dts) {av_log(ic, AV_LOG_DEBUG,"Non-increasing DTS in stream %d: packet %d with DTS ""%"PRId64", packet %d with DTS %"PRId64"\n",st->index, st->info->fps_last_dts_idx,st->info->fps_last_dts, st->codec_info_nb_frames,pkt->dts);st->info->fps_first_dts =st->info->fps_last_dts  = AV_NOPTS_VALUE;}/* Check for a discontinuity in dts. If the difference in dts* is more than 1000 times the average packet duration in the* sequence, we treat it as a discontinuity. */if (st->info->fps_last_dts != AV_NOPTS_VALUE &&st->info->fps_last_dts_idx > st->info->fps_first_dts_idx &&(pkt->dts - st->info->fps_last_dts) / 1000 >(st->info->fps_last_dts     - st->info->fps_first_dts) /(st->info->fps_last_dts_idx - st->info->fps_first_dts_idx)) {av_log(ic, AV_LOG_WARNING,"DTS discontinuity in stream %d: packet %d with DTS ""%"PRId64", packet %d with DTS %"PRId64"\n",st->index, st->info->fps_last_dts_idx,st->info->fps_last_dts, st->codec_info_nb_frames,pkt->dts);st->info->fps_first_dts =st->info->fps_last_dts  = AV_NOPTS_VALUE;}/* update stored dts values */if (st->info->fps_first_dts == AV_NOPTS_VALUE) {st->info->fps_first_dts     = pkt->dts;st->info->fps_first_dts_idx = st->codec_info_nb_frames;}st->info->fps_last_dts     = pkt->dts;st->info->fps_last_dts_idx = st->codec_info_nb_frames;}if (st->codec_info_nb_frames>1) {int64_t t = 0;if (st->time_base.den > 0)t = av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q);if (st->avg_frame_rate.num > 0)t = FFMAX(t, av_rescale_q(st->codec_info_nb_frames, av_inv_q(st->avg_frame_rate), AV_TIME_BASE_Q));if (   t == 0&& st->codec_info_nb_frames>30&& st->info->fps_first_dts != AV_NOPTS_VALUE&& st->info->fps_last_dts  != AV_NOPTS_VALUE)t = FFMAX(t, av_rescale_q(st->info->fps_last_dts - st->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q));if (t >= max_analyze_duration) {av_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %"PRId64" reached at %"PRId64" microseconds\n",max_analyze_duration,t);if (ic->flags & AVFMT_FLAG_NOBUFFER)av_packet_unref(pkt);break;}if (pkt->duration) {st->info->codec_info_duration        += pkt->duration;st->info->codec_info_duration_fields += st->parser && st->need_parsing && st->codec->ticks_per_frame ==2 ? st->parser->repeat_pict + 1 : 2;}}
#if FF_API_R_FRAME_RATEif (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)ff_rfps_add_frame(ic, st, pkt->dts);
#endifif (st->parser && st->parser->parser->split && !st->codec->extradata) {int i = st->parser->parser->split(st->codec, pkt->data, pkt->size);if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) {if (ff_alloc_extradata(st->codec, i))return AVERROR(ENOMEM);memcpy(st->codec->extradata, pkt->data,st->codec->extradata_size);}}/* 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 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. */try_decode_frame(ic, st, pkt,(options && i < orig_nb_streams) ? &options[i] : NULL);if (ic->flags & AVFMT_FLAG_NOBUFFER)av_packet_unref(pkt);st->codec_info_nb_frames++;count++;}if (flush_codecs) {AVPacket empty_pkt = { 0 };int err = 0;av_init_packet(&empty_pkt);for (i = 0; i < ic->nb_streams; i++) {st = ic->streams[i];/* flush the decoders *///尝试解码帧数据if (st->info->found_decoder == 1) {do {err = try_decode_frame(ic, st, &empty_pkt,(options && i < orig_nb_streams)? &options[i] : NULL);} while (err > 0 && !has_codec_parameters(st, NULL));if (err < 0) {av_log(ic, AV_LOG_INFO,"decoding for stream %d failed\n", st->index);}}}}// close codecs which were opened in try_decode_frame()for (i = 0; i < ic->nb_streams; i++) {st = ic->streams[i];avcodec_close(st->codec);}ff_rfps_calculate(ic);for (i = 0; i < ic->nb_streams; i++) {st = ic->streams[i];if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {if (st->codec->codec_id == AV_CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample) {uint32_t tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);if (avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), tag) == st->codec->pix_fmt)st->codec->codec_tag= tag;}/* estimate average framerate if not set by demuxer */if (st->info->codec_info_duration_fields &&!st->avg_frame_rate.num &&st->info->codec_info_duration) {int best_fps      = 0;double best_error = 0.01;if (st->info->codec_info_duration        >= INT64_MAX / st->time_base.num / 2||st->info->codec_info_duration_fields >= INT64_MAX / st->time_base.den ||st->info->codec_info_duration        < 0)continue;av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,st->info->codec_info_duration_fields * (int64_t) st->time_base.den,st->info->codec_info_duration * 2 * (int64_t) st->time_base.num, 60000);/* Round guessed framerate to a "standard" framerate if it's* within 1% of the original estimate. */for (j = 0; j < MAX_STD_TIMEBASES; j++) {AVRational std_fps = { get_std_framerate(j), 12 * 1001 };double error       = fabs(av_q2d(st->avg_frame_rate) /av_q2d(std_fps) - 1);if (error < best_error) {best_error = error;best_fps   = std_fps.num;}}if (best_fps)av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,best_fps, 12 * 1001, INT_MAX);}if (!st->r_frame_rate.num) {if (    st->codec->time_base.den * (int64_t) st->time_base.num<= st->codec->time_base.num * st->codec->ticks_per_frame * (int64_t) st->time_base.den) {st->r_frame_rate.num = st->codec->time_base.den;st->r_frame_rate.den = st->codec->time_base.num * st->codec->ticks_per_frame;} else {st->r_frame_rate.num = st->time_base.den;st->r_frame_rate.den = st->time_base.num;}}} else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {if (!st->codec->bits_per_coded_sample)st->codec->bits_per_coded_sample =av_get_bits_per_sample(st->codec->codec_id);// set stream disposition based on audio service typeswitch (st->codec->audio_service_type) {case AV_AUDIO_SERVICE_TYPE_EFFECTS:st->disposition = AV_DISPOSITION_CLEAN_EFFECTS;break;case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED:st->disposition = AV_DISPOSITION_VISUAL_IMPAIRED;break;case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED:st->disposition = AV_DISPOSITION_HEARING_IMPAIRED;break;case AV_AUDIO_SERVICE_TYPE_COMMENTARY:st->disposition = AV_DISPOSITION_COMMENT;break;case AV_AUDIO_SERVICE_TYPE_KARAOKE:st->disposition = AV_DISPOSITION_KARAOKE;break;}}}if (probesize)estimate_timings(ic, old_offset);av_opt_set(ic, "skip_clear", "0", AV_OPT_SEARCH_CHILDREN);if (ret >= 0 && ic->nb_streams)/* We could not have all the codec parameters before EOF. */ret = -1;for (i = 0; i < ic->nb_streams; i++) {const char *errmsg;st = ic->streams[i];if (!has_codec_parameters(st, &errmsg)) {char buf[256];avcodec_string(buf, sizeof(buf), st->codec, 0);av_log(ic, AV_LOG_WARNING,"Could not find codec parameters for stream %d (%s): %s\n""Consider increasing the value for the 'analyzeduration' and 'probesize' options\n",i, buf, errmsg);} else {ret = 0;}}compute_chapters_end(ic);find_stream_info_err:for (i = 0; i < ic->nb_streams; i++) {st = ic->streams[i];if (ic->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)ic->streams[i]->codec->thread_count = 0;if (st->info)av_freep(&st->info->duration_error);av_freep(&ic->streams[i]->info);}if (ic->pb)av_log(ic, AV_LOG_DEBUG, "After avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d frames:%d\n",avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count, count);return ret;
}//---------------------------------------------//find_decoder函数查找解码器
static const AVCodec *find_decoder(AVFormatContext *s, const AVStream *st, enum AVCodecID codec_id)
{
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGSif (st->codec->codec)return st->codec->codec;
FF_ENABLE_DEPRECATION_WARNINGS
#endifswitch (st->codecpar->codec_type) {//codec_type指示类型case AVMEDIA_TYPE_VIDEO://video类型if (s->video_codec)    return s->video_codec;break;case AVMEDIA_TYPE_AUDIO://audio类型if (s->audio_codec)    return s->audio_codec;break;case AVMEDIA_TYPE_SUBTITLE://字幕类型if (s->subtitle_codec) return s->subtitle_codec;break;}//如果codec已经存在,则不做处理,直接返回//如果codec不存在,则调用avcodec_find_decoder函数进行解码器的查找return avcodec_find_decoder(codec_id);
}//------------------------------------/* returns 1 or 0 if or if not decoded data was returned, or a negative error */
static int try_decode_frame(AVFormatContext *s, AVStream *st,const AVPacket *avpkt, AVDictionary **options)
{//尝试解码帧数据AVCodecContext *avctx = st->internal->avctx;const AVCodec *codec;int got_picture = 1, ret = 0;AVFrame *frame = av_frame_alloc();AVSubtitle subtitle;AVPacket pkt = *avpkt;int do_skip_frame = 0;enum AVDiscard skip_frame;//!frameif (!frame)return AVERROR(ENOMEM);//判断解码器是否打开&其他的判断if (!avcodec_is_open(avctx) &&st->internal->info->found_decoder <= 0 &&(st->codecpar->codec_id != -st->internal->info->found_decoder || !st->codecpar->codec_id)) {AVDictionary *thread_opt = NULL;//调用find_probe_decoder函数进行查找codec = find_probe_decoder(s, st, st->codecpar->codec_id);if (!codec) {st->internal->info->found_decoder = -st->codecpar->codec_id;ret                     = -1;goto fail;}/* Force thread count to 1 since the H.264 decoder will not extract* SPS and PPS to extradata during multi-threaded decoding. *///线程设置为1av_dict_set(options ? options : &thread_opt, "threads", "1", 0);/* Force lowres to 0. The decoder might reduce the video size by the* lowres factor, and we don't want that propagated to the stream's* codecpar *///lowres设置为0av_dict_set(options ? options : &thread_opt, "lowres", "0", 0);if (s->codec_whitelist)av_dict_set(options ? options : &thread_opt, "codec_whitelist", s->codec_whitelist, 0);ret = avcodec_open2(avctx, codec, options ? options : &thread_opt);if (!options)av_dict_free(&thread_opt);if (ret < 0) {st->internal->info->found_decoder = -avctx->codec_id;goto fail;}st->internal->info->found_decoder = 1;} else if (!st->internal->info->found_decoder)st->internal->info->found_decoder = 1;if (st->internal->info->found_decoder < 0) {ret = -1;goto fail;}if (avpriv_codec_get_cap_skip_frame_fill_param(avctx->codec)) {do_skip_frame = 1;skip_frame = avctx->skip_frame;avctx->skip_frame = AVDISCARD_ALL;}while ((pkt.size > 0 || (!pkt.data && got_picture)) &&ret >= 0 &&//has_codec_parameters()函数被用来判断AVStream中的成员变量是否都已经设置完毕(!has_codec_parameters(st, NULL) || !has_decode_delay_been_guessed(st) ||(!st->codec_info_nb_frames &&(avctx->codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF)))) {got_picture = 0;//如果是视频/音频类型if (avctx->codec_type == AVMEDIA_TYPE_VIDEO ||avctx->codec_type == AVMEDIA_TYPE_AUDIO) {ret = avcodec_send_packet(avctx, &pkt);if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)break;if (ret >= 0)pkt.size = 0;ret = avcodec_receive_frame(avctx, frame);if (ret >= 0)got_picture = 1;if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)ret = 0;//如果是字幕类型} else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {ret = avcodec_decode_subtitle2(avctx, &subtitle,&got_picture, &pkt);if (got_picture)avsubtitle_free(&subtitle);if (ret >= 0)pkt.size = 0;}if (ret >= 0) {if (got_picture)st->internal->nb_decoded_frames++;ret       = got_picture;}}if (!pkt.data && !got_picture)ret = -1;fail:if (do_skip_frame) {avctx->skip_frame = skip_frame;}av_frame_free(&frame);return ret;
}static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
{AVCodecContext *avctx = st->internal->avctx;#define FAIL(errmsg) do {                                         \if (errmsg_ptr)                                           \*errmsg_ptr = errmsg;                                 \return 0;                                                 \} while (0)//未知类型if (   avctx->codec_id == AV_CODEC_ID_NONE&& avctx->codec_type != AVMEDIA_TYPE_DATA)FAIL("unknown codec");
//switch实现判断switch (avctx->codec_type) {case AVMEDIA_TYPE_AUDIO://音频类型if (!avctx->frame_size && determinable_frame_size(avctx))FAIL("unspecified frame size");//帧尺寸if (st->internal->info->found_decoder >= 0 &&avctx->sample_fmt == AV_SAMPLE_FMT_NONE)FAIL("unspecified sample format");//格式if (!avctx->sample_rate)FAIL("unspecified sample rate");//码率if (!avctx->channels)FAIL("unspecified number of channels");//声道if (st->internal->info->found_decoder >= 0 && !st->internal->nb_decoded_frames && avctx->codec_id == AV_CODEC_ID_DTS)FAIL("no decodable DTS frames");//DTS帧break;case AVMEDIA_TYPE_VIDEO://视频if (!avctx->width)FAIL("unspecified size");if (st->internal->info->found_decoder >= 0 && avctx->pix_fmt == AV_PIX_FMT_NONE)FAIL("unspecified pixel format");if (st->codecpar->codec_id == AV_CODEC_ID_RV30 || st->codecpar->codec_id == AV_CODEC_ID_RV40)if (!st->sample_aspect_ratio.num && !st->codecpar->sample_aspect_ratio.num && !st->codec_info_nb_frames)FAIL("no frame in rv30/40 and no sar");break;case AVMEDIA_TYPE_SUBTITLE:if (avctx->codec_id == AV_CODEC_ID_HDMV_PGS_SUBTITLE && !avctx->width)FAIL("unspecified size");break;case AVMEDIA_TYPE_DATA:if (avctx->codec_id == AV_CODEC_ID_NONE) return 1;}return 1;
}static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
{int64_t file_size;/* get the file size, if possible */if (ic->iformat->flags & AVFMT_NOFILE) {file_size = 0;} else {file_size = avio_size(ic->pb);file_size = FFMAX(0, file_size);}if ((!strcmp(ic->iformat->name, "mpeg") ||!strcmp(ic->iformat->name, "mpegts")) &&file_size && (ic->pb->seekable & AVIO_SEEKABLE_NORMAL)) {/* get accurate estimate from the PTSes *///从PTSes进行精确评估estimate_timings_from_pts(ic, old_offset);ic->duration_estimation_method = AVFMT_DURATION_FROM_PTS;} else if (has_duration(ic)) {/* at least one component has timings - we use them for all* the components *///如果一个元素有timings,则将其应用于所有的fill_all_stream_timings(ic);/* nut demuxer estimate the duration from PTS *///从PTS估算时间   nut解封转if(!strcmp(ic->iformat->name, "nut"))ic->duration_estimation_method = AVFMT_DURATION_FROM_PTS;elseic->duration_estimation_method = AVFMT_DURATION_FROM_STREAM;//流} else {/* less precise: use bitrate info *///低精度:使用比特率信息estimate_timings_from_bit_rate(ic);ic->duration_estimation_method = AVFMT_DURATION_FROM_BITRATE;}update_stream_timings(ic);for (unsigned i = 0; i < ic->nb_streams; i++) {AVStream *st = ic->streams[i];if (st->time_base.den)av_log(ic, AV_LOG_TRACE, "stream %u: start_time: %s duration: %s\n", i,av_ts2timestr(st->start_time, &st->time_base),av_ts2timestr(st->duration, &st->time_base));}av_log(ic, AV_LOG_TRACE,"format: start_time: %s duration: %s (estimate from %s) bitrate=%"PRId64" kb/s\n",av_ts2timestr(ic->start_time, &AV_TIME_BASE_Q),av_ts2timestr(ic->duration, &AV_TIME_BASE_Q),duration_estimate_name(ic->duration_estimation_method),(int64_t)ic->bit_rate / 1000);
}//-----------------------------------------------static void estimate_timings_from_bit_rate(AVFormatContext *ic)
{int64_t filesize, duration;int i, show_warning = 0;AVStream *st;/* if bit_rate is already set, we believe it *///比特率if (ic->bit_rate <= 0) {int64_t bit_rate = 0;for (i = 0; i < ic->nb_streams; i++) {st = ic->streams[i];if (st->codecpar->bit_rate <= 0 && st->internal->avctx->bit_rate > 0)st->codecpar->bit_rate = st->internal->avctx->bit_rate;if (st->codecpar->bit_rate > 0) {if (INT64_MAX - st->codecpar->bit_rate < bit_rate) {bit_rate = 0;break;}bit_rate += st->codecpar->bit_rate;//累加} else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->codec_info_nb_frames > 1) {// If we have a videostream with packets but without a bitrate// then consider the sum not knownbit_rate = 0;break;}}ic->bit_rate = bit_rate;}/* if duration is already set, we believe it *///durationif (ic->duration == AV_NOPTS_VALUE &&ic->bit_rate != 0) {filesize = ic->pb ? avio_size(ic->pb) : 0;if (filesize > ic->internal->data_offset) {filesize -= ic->internal->data_offset;for (i = 0; i < ic->nb_streams; i++) {st      = ic->streams[i];if (   st->time_base.num <= INT64_MAX / ic->bit_rate&& st->duration == AV_NOPTS_VALUE) {//计算duration//av_rescale所实现的功能是什么?计算的细节?duration = av_rescale(filesize, 8LL * st->time_base.den,ic->bit_rate *(int64_t) st->time_base.num);st->duration = duration;show_warning = 1;}}}}if (show_warning)av_log(ic, AV_LOG_WARNING,"Estimating duration from bitrate, this may be inaccurate\n");
}

FFmpeg源代码简单学习:avformat_find_stream_info()相关推荐

  1. ffmpeg 源代码简单学习 : avcodec_decode_video2()

    参考博客:https://blog.csdn.net/leixiaohua1020/article/details/12679719 int attribute_align_arg avcodec_d ...

  2. FFmpeg源代码简单分析:avformat_find_stream_info()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  3. FFmpeg源代码简单分析:libavdevice的gdigrab

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  4. FFmpeg源代码简单分析:libavdevice的avdevice_register_all()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  5. FFmpeg源代码简单分析:configure

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  6. FFmpeg源代码简单分析:makefile

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  7. FFmpeg源代码简单分析:libswscale的sws_getContext()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  8. FFmpeg源代码简单分析:结构体成员管理系统-AVOption

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. FFmpeg源代码简单分析:结构体成员管理系统-AVClass

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

最新文章

  1. 每日一皮:男同胞们小心,连视频直播都被东南亚邪术控制了...
  2. 分页数据的新展示方式---瀑布流
  3. 单点效率测试工具:F8秒表
  4. 第7周项目实践 1 队列算法库的建立
  5. 2016年11月2日——jQuery源码学习笔记
  6. Android线程间通信之handler
  7. 分享一个CSS3和jQuery实现的模糊显示效果 - 帮助你的访问用户更好的阅读内容
  8. 滞后分析rstudio_使用RStudio进行A / B测试分析
  9. NILMTK——因子隐马尔可夫之隐马尔可夫
  10. ae连续流动的线条_贡献 | AE片头制作绝对经验
  11. 活动推荐|互联网3.0与区块链新时代论坛(北京)
  12. 不会延期!iPhone 12S预计如期在9月发售:升级三星LTPO屏幕
  13. 基于OpenCV实现图像线性变化
  14. 麦克风增强软件_麦克风电流声去除方法(不花一分钱去电流声)
  15. java 实现poi方式读取word文件内容
  16. Fw cs6破解版下载 准备学前端的同学们应该会用到的神器
  17. Word文档转PDF的方法有哪些?我们如何Word转PDF?
  18. 第 4 代 4 端口 HDMI/DVI 分配器龙迅LT86104SXE
  19. 微信营销解密个人分析
  20. 等级保护测评备案业务中十个常见问题解答

热门文章

  1. jmeter压测数据库
  2. 英雄对决服务器未响应,lol点开始游戏没反应怎么办 完整解决办法一览
  3. 医疗和牙科3D打印的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  4. Java桌面应用程序
  5. 源码:批量修改喜马拉雅下载节目的文件名
  6. 51单片机入门——Keil uVision4的使用
  7. 因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?Link ID=135170 中的 about_Execution_Policies
  8. 牛客网网易机试模拟题(Android)记录
  9. storj for windows 主网挖矿指南
  10. 计算机模拟仿真实例,计算机模拟仿真系统,computer simulation system,音标,读音,翻译,英文例句,英语词典...