?? utils.c.svn-base
字號:
break; ret = av_read_packet(ic, pkt); if (ret != 0) break; read_size += pkt->size; st = ic->streams[pkt->stream_index]; if (pkt->pts != AV_NOPTS_VALUE && st->start_time != AV_NOPTS_VALUE) { end_time = pkt->pts; duration = end_time - st->start_time; if (duration > 0) { if (st->duration == AV_NOPTS_VALUE || st->duration < duration) st->duration = duration; } } av_free_packet(pkt); } fill_all_stream_timings(ic); url_fseek(ic->pb, old_offset, SEEK_SET); for(i=0; i<ic->nb_streams; i++){ st= ic->streams[i]; st->cur_dts= st->first_dts; st->last_IP_pts = AV_NOPTS_VALUE; }}static void av_estimate_timings(AVFormatContext *ic, offset_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 = url_fsize(ic->pb); if (file_size < 0) file_size = 0; } ic->file_size = file_size; if ((!strcmp(ic->iformat->name, "mpeg") || !strcmp(ic->iformat->name, "mpegts")) && file_size && !url_is_streamed(ic->pb)) { /* get accurate estimate from the PTSes */ av_estimate_timings_from_pts(ic, old_offset); } else if (av_has_duration(ic)) { /* at least one component has timings - we use them for all the components */ fill_all_stream_timings(ic); } else { /* less precise: use bitrate info */ av_estimate_timings_from_bit_rate(ic); } av_update_stream_timings(ic);#if 0 { int i; AVStream *st; for(i = 0;i < ic->nb_streams; i++) { st = ic->streams[i]; printf("%d: start_time: %0.3f duration: %0.3f\n", i, (double)st->start_time / AV_TIME_BASE, (double)st->duration / AV_TIME_BASE); } printf("stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n", (double)ic->start_time / AV_TIME_BASE, (double)ic->duration / AV_TIME_BASE, ic->bit_rate / 1000); }#endif}static int has_codec_parameters(AVCodecContext *enc){ int val; switch(enc->codec_type) { case CODEC_TYPE_AUDIO: val = enc->sample_rate && enc->channels; if(!enc->frame_size && (enc->codec_id == CODEC_ID_VORBIS || enc->codec_id == CODEC_ID_AAC)) return 0; break; case CODEC_TYPE_VIDEO: val = enc->width && enc->pix_fmt != PIX_FMT_NONE; break; default: val = 1; break; } return enc->codec_id != CODEC_ID_NONE && val != 0;}static int try_decode_frame(AVStream *st, const uint8_t *data, int size){ int16_t *samples; AVCodec *codec; int got_picture, data_size, ret=0; AVFrame picture; if(!st->codec->codec){ codec = avcodec_find_decoder(st->codec->codec_id); if (!codec) return -1; ret = avcodec_open(st->codec, codec); if (ret < 0) return ret; } if(!has_codec_parameters(st->codec)){ switch(st->codec->codec_type) { case CODEC_TYPE_VIDEO: ret = avcodec_decode_video(st->codec, &picture, &got_picture, data, size); break; case CODEC_TYPE_AUDIO: data_size = FFMAX(size, AVCODEC_MAX_AUDIO_FRAME_SIZE); samples = av_malloc(data_size); if (!samples) goto fail; ret = avcodec_decode_audio2(st->codec, samples, &data_size, data, size); av_free(samples); break; default: break; } } fail: return ret;}static int set_codec_from_probe_data(AVStream *st, AVProbeData *pd, int score){ AVInputFormat *fmt; fmt = av_probe_input_format2(pd, 1, &score); if (fmt) { if (strncmp(fmt->name, "mp3", 3) == 0) st->codec->codec_id = CODEC_ID_MP3; else if (strncmp(fmt->name, "ac3", 3) == 0) st->codec->codec_id = CODEC_ID_AC3; } return !!fmt;}unsigned int codec_get_tag(const AVCodecTag *tags, int id){ while (tags->id != CODEC_ID_NONE) { if (tags->id == id) return tags->tag; tags++; } return 0;}enum CodecID codec_get_id(const AVCodecTag *tags, unsigned int tag){ int i; for(i=0; tags[i].id != CODEC_ID_NONE;i++) { if(tag == tags[i].tag) return tags[i].id; } for(i=0; tags[i].id != CODEC_ID_NONE; i++) { if( toupper((tag >> 0)&0xFF) == toupper((tags[i].tag >> 0)&0xFF) && toupper((tag >> 8)&0xFF) == toupper((tags[i].tag >> 8)&0xFF) && toupper((tag >>16)&0xFF) == toupper((tags[i].tag >>16)&0xFF) && toupper((tag >>24)&0xFF) == toupper((tags[i].tag >>24)&0xFF)) return tags[i].id; } return CODEC_ID_NONE;}unsigned int av_codec_get_tag(const AVCodecTag *tags[4], enum CodecID id){ int i; for(i=0; tags && tags[i]; i++){ int tag= codec_get_tag(tags[i], id); if(tag) return tag; } return 0;}enum CodecID av_codec_get_id(const AVCodecTag *tags[4], unsigned int tag){ int i; for(i=0; tags && tags[i]; i++){ enum CodecID id= codec_get_id(tags[i], tag); if(id!=CODEC_ID_NONE) return id; } return CODEC_ID_NONE;}static void compute_chapters_end(AVFormatContext *s){ unsigned int i; for (i=0; i+1<s->nb_chapters; i++) if (s->chapters[i]->end == AV_NOPTS_VALUE) { assert(s->chapters[i]->start <= s->chapters[i+1]->start); assert(!av_cmp_q(s->chapters[i]->time_base, s->chapters[i+1]->time_base)); s->chapters[i]->end = s->chapters[i+1]->start; } if (s->nb_chapters && s->chapters[i]->end == AV_NOPTS_VALUE) { assert(s->start_time != AV_NOPTS_VALUE); assert(s->duration > 0); s->chapters[i]->end = av_rescale_q(s->start_time + s->duration, AV_TIME_BASE_Q, s->chapters[i]->time_base); }}/* absolute maximum size we read until we abort */#define MAX_READ_SIZE 5000000#define MAX_STD_TIMEBASES (60*12+5)static int get_std_framerate(int i){ if(i<60*12) return i*1001; else return ((int[]){24,30,60,12,15})[i-60*12]*1000*12;}/* * Is the time base unreliable. * This is a heuristic to balance between quick acceptance of the values in * the headers vs. some extra checks. * Old DivX and Xvid often have nonsense timebases like 1fps or 2fps. * MPEG-2 commonly misuses field repeat flags to store different framerates. * And there are "variable" fps files this needs to detect as well. */static int tb_unreliable(AVCodecContext *c){ if( c->time_base.den >= 101L*c->time_base.num || c->time_base.den < 5L*c->time_base.num/* || c->codec_tag == ff_get_fourcc("DIVX") || c->codec_tag == ff_get_fourcc("XVID")*/ || c->codec_id == CODEC_ID_MPEG2VIDEO) return 1; return 0;}int av_find_stream_info(AVFormatContext *ic){ int i, count, ret, read_size, j; AVStream *st; AVPacket pkt1, *pkt; int64_t last_dts[MAX_STREAMS]; int duration_count[MAX_STREAMS]={0}; double (*duration_error)[MAX_STD_TIMEBASES]; offset_t old_offset = url_ftell(ic->pb); int64_t codec_info_duration[MAX_STREAMS]={0}; int codec_info_nb_frames[MAX_STREAMS]={0}; AVProbeData probe_data[MAX_STREAMS]; int codec_identified[MAX_STREAMS]={0}; duration_error = av_mallocz(MAX_STREAMS * sizeof(*duration_error)); if (!duration_error) return AVERROR(ENOMEM); for(i=0;i<ic->nb_streams;i++) { st = ic->streams[i]; if(st->codec->codec_type == CODEC_TYPE_VIDEO){/* 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 stuff if (!st->parser) { st->parser = av_parser_init(st->codec->codec_id); if(st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser){ st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; } } } for(i=0;i<MAX_STREAMS;i++){ last_dts[i]= AV_NOPTS_VALUE; } memset(probe_data, 0, sizeof(probe_data)); count = 0; read_size = 0; for(;;) { /* check if one codec still needs to be handled */ for(i=0;i<ic->nb_streams;i++) { st = ic->streams[i]; if (!has_codec_parameters(st->codec)) break; /* variable fps and no guess at the real fps */ if( tb_unreliable(st->codec) && duration_count[i]<20 && st->codec->codec_type == CODEC_TYPE_VIDEO) break; if(st->parser && st->parser->parser->split && !st->codec->extradata) break; if(st->first_dts == AV_NOPTS_VALUE) 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; break; } } /* we did not get all the codec info, but we read too much data */ if (read_size >= MAX_READ_SIZE) { ret = count; break; } /* NOTE: a new stream can be added there if no header in file (AVFMTCTX_NOHEADER) */ ret = av_read_frame_internal(ic, &pkt1); if (ret < 0) { /* EOF or error */ ret = -1; /* we could not have all the codec parameters before EOF */ for(i=0;i<ic->nb_streams;i++) { st = ic->streams[i]; if (!has_codec_parameters(st->codec)){ char buf[256]; avcodec_string(buf, sizeof(buf), st->codec, 0); av_log(ic, AV_LOG_INFO, "Could not find codec parameters (%s)\n", buf); } else { ret = 0; } } break; } pkt= add_to_pktbuf(ic, &pkt1); if(av_dup_packet(pkt) < 0) return AVERROR(ENOMEM); read_size += pkt->size; st = ic->streams[pkt->stream_index]; if(codec_info_nb_frames[st->index]>1) codec_info_duration[st->index] += pkt->duration; if (pkt->duration != 0) codec_info_nb_frames[st->index]++; { int index= pkt->stream_index; int64_t last= last_dts[index]; int64_t duration= pkt->dts - last; if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){ double dur= duration * av_q2d(st->time_base);// if(st->codec->codec_type == CODEC_TYPE_VIDEO)// av_log(NULL, AV_LOG_ERROR, "%f\n", dur); if(duration_count[index] < 2) memset(duration_error[index], 0, sizeof(*duration_error)); for(i=1; i<MAX_STD_TIMEBASES; i++){ int framerate= get_std_framerate(i); int ticks= lrintf(dur*framerate/(1001*12)); double error= dur - ticks*1001*12/(double)framerate; duration_error[index][i] += error*error; } duration_count[index]++; } if(last == AV_NOPTS_VALUE || duration_count[index]<=1) last_dts[pkt->stream_index]= pkt->dts; if (st->codec->codec_id == CODEC_ID_NONE) { AVProbeData *pd = &(probe_data[st->index]); pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE); memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size); pd->buf_size += pkt->size; memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE); } } if(st->parser && st->parser->parser->split && !st->codec->extradata){ int i= st->parser->parser->split(st->codec, pkt->data, pkt->size); if(i){ st->codec->extradata_size= i; st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size); memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_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 (!has_codec_parameters(st->codec) /*&& (st->codec->codec_id == CODEC_ID_FLV1 || st->codec->codec_id == CODEC_ID_H264 || st->codec->codec_id == CODEC_ID_H263 || st->codec->codec_id == CODEC_ID_H261 || st->codec->codec_id == CODEC_ID_VORBIS || st->codec->codec_id == CODEC_ID_MJPEG || st->codec->codec_id == CODEC_ID_PNG || st->codec->codec_id == CODEC_ID_PAM || st->codec->codec_id == CODEC_ID_PGM || st->codec->codec_id == CODEC_ID_PGMYUV || st->codec->codec_id == CODEC_ID_PBM || st->codec->codec_id == CODEC_ID_PPM || st->codec->codec_id == CODEC_ID_SHORTEN || (st->codec->codec_id == CODEC_ID_MPEG4 && !st->need_parsing))*/) try_decode_frame(st, pkt->data, pkt->size); if (st->time_base.den > 0 && av_rescale_q(codec_info_duration[st->index], st->time_base, AV_TIME_BASE_Q) >= ic->max
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -