X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=d98a17aedaf1cb4dd59c82f2a4e55ad23a59cbbd;hb=41f55277fafeec4f1b3202967bd0ab120948dd69;hp=1017d527d897423b733c21c2025f86a3e39ca199;hpb=aebb56e1844d61965c97e95534c3ae0da69df028;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index 1017d527d89..d98a17aedaf 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -405,6 +405,7 @@ static AVDictionary *convert_format_parameters(AVFormatParameters *ap) if (!ap) return NULL; + AV_NOWARN_DEPRECATED( if (ap->time_base.num) { snprintf(buf, sizeof(buf), "%d/%d", ap->time_base.den, ap->time_base.num); av_dict_set(&opts, "framerate", buf, 0); @@ -437,6 +438,7 @@ static AVDictionary *convert_format_parameters(AVFormatParameters *ap) if (ap->initial_pause) { av_dict_set(&opts, "initial_pause", "1", 0); } + ) return opts; } @@ -458,10 +460,12 @@ int av_open_input_stream(AVFormatContext **ic_ptr, } opts = convert_format_parameters(ap); + AV_NOWARN_DEPRECATED( if(!ap->prealloced_context) *ic_ptr = ic = avformat_alloc_context(); else ic = *ic_ptr; + ) if (!ic) { err = AVERROR(ENOMEM); goto fail; @@ -476,8 +480,8 @@ int av_open_input_stream(AVFormatContext **ic_ptr, goto fail; ic->pb = ic->pb ? ic->pb : pb; // don't leak custom pb if it wasn't set above - *ic_ptr = ic; fail: + *ic_ptr = ic; av_dict_free(&opts); return err; } @@ -585,8 +589,10 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, int err; AVDictionary *opts = convert_format_parameters(ap); + AV_NOWARN_DEPRECATED( if (!ap || !ap->prealloced_context) *ic_ptr = NULL; + ) err = avformat_open_input(ic_ptr, filename, fmt, &opts); @@ -887,6 +893,7 @@ static int is_intra_only(AVCodecContext *enc){ case CODEC_ID_MJPEG: case CODEC_ID_MJPEGB: case CODEC_ID_LJPEG: + case CODEC_ID_PRORES: case CODEC_ID_RAWVIDEO: case CODEC_ID_DVVIDEO: case CODEC_ID_HUFFYUV: @@ -999,8 +1006,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, pc && pc->pict_type != AV_PICTURE_TYPE_B) presentation_delayed = 1; - if(pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && pkt->dts > pkt->pts && st->pts_wrap_bits<63 - /*&& pkt->dts-(1LL<pts_wrap_bits) < pkt->pts*/){ + if(pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && pkt->dts - (1LL<<(st->pts_wrap_bits-1)) > pkt->pts && st->pts_wrap_bits<63){ pkt->dts -= 1LL<pts_wrap_bits; } @@ -1008,7 +1014,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, // we take the conservative approach and discard both // Note, if this is misbehaving for a H.264 file then possibly presentation_delayed is not set correctly. if(delay==1 && pkt->dts == pkt->pts && pkt->dts != AV_NOPTS_VALUE && presentation_delayed){ - av_log(s, AV_LOG_DEBUG, "invalid dts/pts combination\n"); + av_log(s, AV_LOG_DEBUG, "invalid dts/pts combination %"PRIi64"\n", pkt->dts); pkt->dts= pkt->pts= AV_NOPTS_VALUE; } @@ -1146,7 +1152,10 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) if (!st->need_parsing || !st->parser) { /* no parsing needed: we just output the packet as is */ /* raw data support */ - *pkt = st->cur_pkt; st->cur_pkt.data= NULL; + *pkt = st->cur_pkt; + st->cur_pkt.data= NULL; + st->cur_pkt.side_data_elems = 0; + st->cur_pkt.side_data = NULL; compute_pkt_fields(s, st, NULL, pkt); s->cur_st = NULL; if ((s->iformat->flags & AVFMT_GENERIC_INDEX) && @@ -1739,8 +1748,8 @@ static int seek_frame_generic(AVFormatContext *s, return -1; if(index < 0 || index==st->nb_index_entries-1){ - int i; AVPacket pkt; + int nonkey=0; if(st->nb_index_entries){ assert(st->index_entries); @@ -1752,17 +1761,21 @@ static int seek_frame_generic(AVFormatContext *s, if ((ret = avio_seek(s->pb, s->data_offset, SEEK_SET)) < 0) return ret; } - for(i=0;; i++) { - int ret; + for (;;) { + int read_status; do{ - ret = av_read_frame(s, &pkt); - }while(ret == AVERROR(EAGAIN)); - if(ret<0) + read_status = av_read_frame(s, &pkt); + } while (read_status == AVERROR(EAGAIN)); + if (read_status < 0) break; av_free_packet(&pkt); - if(stream_index == pkt.stream_index){ - if((pkt.flags & AV_PKT_FLAG_KEY) && pkt.dts > timestamp) + if(stream_index == pkt.stream_index && pkt.dts > timestamp){ + if(pkt.flags & AV_PKT_FLAG_KEY) break; + if(nonkey++ > 1000){ + av_log(s, AV_LOG_ERROR,"seek_frame_generic failed as this stream seems to contain no keyframes after the target timestamp, %d non keyframes found\n", nonkey); + break; + } } } index = av_index_search_timestamp(st, timestamp, flags); @@ -1771,10 +1784,12 @@ static int seek_frame_generic(AVFormatContext *s, return -1; ff_read_frame_flush(s); + AV_NOWARN_DEPRECATED( if (s->iformat->read_seek){ if(s->iformat->read_seek(s, stream_index, timestamp, flags) >= 0) return 0; } + ) ie = &st->index_entries[index]; if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0) return ret; @@ -1804,10 +1819,12 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f } /* first, we try the format specific seek */ + AV_NOWARN_DEPRECATED( if (s->iformat->read_seek) ret = s->iformat->read_seek(s, stream_index, timestamp, flags); else ret = -1; + ) if (ret >= 0) { return 0; } @@ -1836,8 +1853,10 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int //Fallback to old API if new is not implemented but old is //Note the old has somewat different sematics + AV_NOWARN_DEPRECATED( if(s->iformat->read_seek || 1) return av_seek_frame(s, stream_index, ts, flags | (ts - min_ts > (uint64_t)(max_ts - ts) ? AVSEEK_FLAG_BACKWARD : 0)); + ) // try some generic seek like seek_frame_generic() but with new ts semantics } @@ -1853,6 +1872,8 @@ static int has_duration(AVFormatContext *ic) { int i; AVStream *st; + if(ic->duration != AV_NOPTS_VALUE) + return 1; for(i = 0;i < ic->nb_streams; i++) { st = ic->streams[i]; @@ -1882,7 +1903,7 @@ static void update_stream_timings(AVFormatContext *ic) st = ic->streams[i]; if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) { start_time1= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q); - if (st->codec->codec_id == CODEC_ID_DVB_TELETEXT) { + if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { if (start_time1 < start_time_text) start_time_text = start_time1; } else @@ -1910,14 +1931,14 @@ static void update_stream_timings(AVFormatContext *ic) duration = end_time - start_time; } } - if (duration != INT64_MIN) { + if (duration != INT64_MIN && ic->duration == AV_NOPTS_VALUE) { ic->duration = duration; - if (ic->file_size > 0) { + } + if (ic->file_size > 0 && ic->duration != AV_NOPTS_VALUE) { /* compute the bitrate */ ic->bit_rate = (double)ic->file_size * 8.0 * AV_TIME_BASE / (double)ic->duration; } - } } static void fill_all_stream_timings(AVFormatContext *ic) @@ -2106,19 +2127,21 @@ static int has_codec_parameters(AVCodecContext *avctx) switch (avctx->codec_type) { case AVMEDIA_TYPE_AUDIO: val = avctx->sample_rate && avctx->channels && avctx->sample_fmt != AV_SAMPLE_FMT_NONE; - if(!avctx->frame_size && - (avctx->codec_id == CODEC_ID_VORBIS || - avctx->codec_id == CODEC_ID_AAC || - avctx->codec_id == CODEC_ID_MP1 || - avctx->codec_id == CODEC_ID_MP2 || - avctx->codec_id == CODEC_ID_MP3 || - avctx->codec_id == CODEC_ID_SPEEX || - avctx->codec_id == CODEC_ID_CELT)) + if (!avctx->frame_size && + (avctx->codec_id == CODEC_ID_VORBIS || + avctx->codec_id == CODEC_ID_AAC || + avctx->codec_id == CODEC_ID_MP1 || + avctx->codec_id == CODEC_ID_MP2 || + avctx->codec_id == CODEC_ID_MP3 || + avctx->codec_id == CODEC_ID_SPEEX || + avctx->codec_id == CODEC_ID_CELT)) return 0; break; case AVMEDIA_TYPE_VIDEO: val = avctx->width && avctx->pix_fmt != PIX_FMT_NONE; break; + case AVMEDIA_TYPE_DATA: + if(avctx->codec_id == CODEC_ID_NONE) return 1; default: val = 1; break; @@ -2281,15 +2304,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) for(i=0;inb_streams;i++) { AVCodec *codec; st = ic->streams[i]; - if (st->codec->codec_id == CODEC_ID_AAC && st->codec->extradata_size) { - // We need to discard these since they can be plain wrong for - // backwards compatible HE-AAC signaling. - // But when we have no extradata we need to keep them or we can't - // play anything at all. - st->codec->sample_rate = 0; - st->codec->frame_size = 0; - st->codec->channels = 0; - } if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO || st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { @@ -2315,8 +2329,15 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) //try to just open decoders, in case this is enough to get parameters if(!has_codec_parameters(st->codec)){ - if (codec && !st->codec->codec) - avcodec_open2(st->codec, codec, options ? &options[i] : NULL); + if (codec && !st->codec->codec){ + AVDictionary *tmp = NULL; + if (options){ + av_dict_copy(&tmp, options[i], 0); + av_dict_set(&tmp, "threads", 0, 0); + } + avcodec_open2(st->codec, codec, options ? &tmp : NULL); + av_dict_free(&tmp); + } } } @@ -2354,7 +2375,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) break; if(st->parser && st->parser->parser->split && !st->codec->extradata) break; - if(st->first_dts == AV_NOPTS_VALUE) + if(st->first_dts == AV_NOPTS_VALUE && (st->codec->codec_type == AVMEDIA_TYPE_VIDEO || st->codec->codec_type == AVMEDIA_TYPE_AUDIO)) break; } if (i == ic->nb_streams) { @@ -2414,20 +2435,22 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) } { int64_t last = st->info->last_dts; - 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(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && pkt->dts > last){ + double dts= pkt->dts * av_q2d(st->time_base); + int64_t duration= pkt->dts - last; // if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) // av_log(NULL, AV_LOG_ERROR, "%f\n", dur); - if (st->info->duration_count < 2) - memset(st->info->duration_error, 0, sizeof(st->info->duration_error)); - for (i=1; iinfo->duration_error); i++) { + for (i=1; iinfo->duration_error[0][0]); i++) { int framerate= get_std_framerate(i); - int ticks= lrintf(dur*framerate/(1001*12)); - double error= dur - ticks*1001*12/(double)framerate; - st->info->duration_error[i] += error*error; + double sdts= dts*framerate/(1001*12); + for(j=0; j<2; j++){ + int ticks= lrintf(sdts+j*0.5); + double error= sdts - ticks + j*0.5; + st->info->duration_error[j][0][i] += error; + st->info->duration_error[j][1][i] += error*error; + } } st->info->duration_count++; // ignore the first 4 values, they might have some random jitter @@ -2491,16 +2514,24 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) //FIXME we should not special-case MPEG-2, but this needs testing with non-MPEG-2 ... st->time_base.num*duration_sum[i]/st->info->duration_count*101LL > st->time_base.den*/){ int num = 0; - double best_error= 2*av_q2d(st->time_base); - best_error = best_error*best_error*st->info->duration_count*1000*12*30; - - for (j=1; jinfo->duration_error); j++) { - double error = st->info->duration_error[j] * get_std_framerate(j); -// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) -// av_log(NULL, AV_LOG_ERROR, "%f %f\n", get_std_framerate(j) / 12.0/1001, error); - if(error < best_error){ - best_error= error; - num = get_std_framerate(j); + double best_error= 0.01; + + for (j=1; jinfo->duration_error[0][0]); j++) { + int k; + + if(st->info->codec_info_duration && st->info->codec_info_duration*av_q2d(st->time_base) < (1001*12.0)/get_std_framerate(j)) + continue; + for(k=0; k<2; k++){ + int n= st->info->duration_count; + double a= st->info->duration_error[k][0][j] / n; + double error= st->info->duration_error[k][1][j]/n - a*a; + + if(error < best_error && best_error> 0.000000001){ + best_error= error; + num = get_std_framerate(j); + } + if(error < 0.02) + av_log(NULL, AV_LOG_DEBUG, "rfps: %f %f\n", get_std_framerate(j) / 12.0/1001, error); } } // do not increase frame rate by more than 1 % in order to match a standard rate. @@ -2687,13 +2718,13 @@ void avformat_free_context(AVFormatContext *s) av_free_packet(&st->cur_pkt); } av_dict_free(&st->metadata); - av_free(st->index_entries); - av_free(st->codec->extradata); - av_free(st->codec->subtitle_header); - av_free(st->codec); - av_free(st->priv_data); - av_free(st->info); - av_free(st); + av_freep(&st->index_entries); + av_freep(&st->codec->extradata); + av_freep(&st->codec->subtitle_header); + av_freep(&st->codec); + av_freep(&st->priv_data); + av_freep(&st->info); + av_freep(&st); } for(i=s->nb_programs-1; i>=0; i--) { av_dict_free(&s->programs[i]->metadata); @@ -2704,7 +2735,7 @@ void avformat_free_context(AVFormatContext *s) av_freep(&s->priv_data); while(s->nb_chapters--) { av_dict_free(&s->chapters[s->nb_chapters]->metadata); - av_free(s->chapters[s->nb_chapters]); + av_freep(&s->chapters[s->nb_chapters]); } av_freep(&s->chapters); av_dict_free(&s->metadata); @@ -2989,7 +3020,9 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) ret = AVERROR(EINVAL); goto fail; } - if(av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)){ + if(av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio) + && FFABS(av_q2d(st->sample_aspect_ratio) - av_q2d(st->codec->sample_aspect_ratio)) > 0.004*av_q2d(st->sample_aspect_ratio) + ){ av_log(s, AV_LOG_ERROR, "Aspect ratio mismatch between encoder and muxer layer\n"); ret = AVERROR(EINVAL); goto fail; @@ -3220,17 +3253,44 @@ static int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacke int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){ AVPacketList *pktl; - int stream_count=0; + int stream_count=0, noninterleaved_count=0; + int64_t delta_dts_max = 0; int i; if(pkt){ ff_interleave_add_packet(s, pkt, ff_interleave_compare_dts); } - for(i=0; i < s->nb_streams; i++) - stream_count+= !!s->streams[i]->last_in_packet_buffer; + for(i=0; i < s->nb_streams; i++) { + if (s->streams[i]->last_in_packet_buffer) { + ++stream_count; + } else if(s->streams[i]->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { + ++noninterleaved_count; + } + } - if(stream_count && (s->nb_streams == stream_count || flush)){ + if (s->nb_streams == stream_count) { + flush = 1; + } else if (!flush){ + for(i=0; i < s->nb_streams; i++) { + if (s->streams[i]->last_in_packet_buffer) { + int64_t delta_dts = + av_rescale_q(s->streams[i]->last_in_packet_buffer->pkt.dts, + s->streams[i]->time_base, + AV_TIME_BASE_Q) - + av_rescale_q(s->packet_buffer->pkt.dts, + s->streams[s->packet_buffer->pkt.stream_index]->time_base, + AV_TIME_BASE_Q); + delta_dts_max= FFMAX(delta_dts_max, delta_dts); + } + } + if(s->nb_streams == stream_count+noninterleaved_count && + delta_dts_max > 20*AV_TIME_BASE) { + av_log(s, AV_LOG_DEBUG, "flushing with %d noninterleaved\n", noninterleaved_count); + flush = 1; + } + } + if(stream_count && flush){ pktl= s->packet_buffer; *out= pktl->pkt; @@ -3295,8 +3355,8 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){ if(ret<0) return ret; - if(url_ferror(s->pb)) - return url_ferror(s->pb); + if(s->pb && s->pb->error) + return s->pb->error; } } @@ -3320,7 +3380,7 @@ int av_write_trailer(AVFormatContext *s) if(ret<0) goto fail; - if(url_ferror(s->pb)) + if(s->pb && s->pb->error) goto fail; } @@ -3328,7 +3388,7 @@ int av_write_trailer(AVFormatContext *s) ret = s->oformat->write_trailer(s); fail: if(ret == 0) - ret=url_ferror(s->pb); + ret = s->pb ? s->pb->error : 0; for(i=0;inb_streams;i++) { av_freep(&s->streams[i]->priv_data); av_freep(&s->streams[i]->index_entries); @@ -3410,7 +3470,7 @@ static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_out int g = av_gcd(st->time_base.num, st->time_base.den); AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); avcodec_string(buf, sizeof(buf), st->codec, is_output); - av_log(NULL, AV_LOG_INFO, " Stream #%d.%d", index, i); + av_log(NULL, AV_LOG_INFO, " Stream #%d:%d", index, i); /* the pid is an important information, so we display it */ /* XXX: add a generic system */ if (flags & AVFMT_SHOW_IDS) @@ -3480,7 +3540,7 @@ void av_dump_format(AVFormatContext *ic, int is_output) { int i; - uint8_t *printed = av_mallocz(ic->nb_streams); + uint8_t *printed = ic->nb_streams ? av_mallocz(ic->nb_streams) : NULL; if (ic->nb_streams && !printed) return;