X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=dbe1a6359ef5bd7f29b47565e5b06933fa4d7b71;hb=cb66db801040f2ef764caf7978a50ac0edc7eabb;hp=b03615983f58a461fb8ac7ddc2cb43620b8e31b4;hpb=042f9d62ca42a6ca26ef6ff23c6078c9ecc90c18;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index b03615983f5..dbe1a6359ef 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -80,7 +80,7 @@ const char *avformat_license(void) * @param num must be >= 0 * @param den must be >= 1 */ -static void av_frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den) +static void frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den) { num += (den >> 1); if (num >= den) { @@ -98,7 +98,7 @@ static void av_frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den) * @param f fractional number * @param incr increment, can be positive or negative */ -static void av_frac_add(AVFrac *f, int64_t incr) +static void frac_add(AVFrac *f, int64_t incr) { int64_t num, den; @@ -369,6 +369,7 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeDa { "dts" , CODEC_ID_DTS , AVMEDIA_TYPE_AUDIO }, { "eac3" , CODEC_ID_EAC3 , AVMEDIA_TYPE_AUDIO }, { "h264" , CODEC_ID_H264 , AVMEDIA_TYPE_VIDEO }, + { "loas" , CODEC_ID_AAC_LATM , AVMEDIA_TYPE_AUDIO }, { "m4v" , CODEC_ID_MPEG4 , AVMEDIA_TYPE_VIDEO }, { "mp3" , CODEC_ID_MP3 , AVMEDIA_TYPE_AUDIO }, { "mpegvideo", CODEC_ID_MPEG2VIDEO, AVMEDIA_TYPE_VIDEO }, @@ -522,17 +523,23 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, return AVERROR(EINVAL); } - for(probe_size= PROBE_BUF_MIN; probe_size<=max_probe_size && !*fmt && ret >= 0; + for(probe_size= PROBE_BUF_MIN; probe_size<=max_probe_size && !*fmt; probe_size = FFMIN(probe_size<<1, FFMAX(max_probe_size, probe_size+1))) { - int ret, score = probe_size < max_probe_size ? AVPROBE_SCORE_MAX/4 : 0; + int score = probe_size < max_probe_size ? AVPROBE_SCORE_MAX/4 : 0; int buf_offset = (probe_size == PROBE_BUF_MIN) ? 0 : probe_size>>1; + void *buftmp; if (probe_size < offset) { continue; } /* read probe data */ - buf = av_realloc(buf, probe_size + AVPROBE_PADDING_SIZE); + buftmp = av_realloc(buf, probe_size + AVPROBE_PADDING_SIZE); + if(!buftmp){ + av_free(buf); + return AVERROR(ENOMEM); + } + buf=buftmp; if ((ret = avio_read(pb, buf + buf_offset, probe_size - buf_offset)) < 0) { /* fail if error was not end of file, otherwise, lower score */ if (ret != AVERROR_EOF) { @@ -609,7 +616,7 @@ static int init_input(AVFormatContext *s, const char *filename) return 0; if ((ret = avio_open(&s->pb, filename, AVIO_FLAG_READ)) < 0) - return ret; + return ret; if (s->iformat) return 0; return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, 0); @@ -738,8 +745,17 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt) continue; } + if ((s->flags & AVFMT_FLAG_DISCARD_CORRUPT) && + (pkt->flags & AV_PKT_FLAG_CORRUPT)) { + av_log(s, AV_LOG_WARNING, + "Dropped corrupted packet (stream = %d)\n", + pkt->stream_index); + continue; + } + if(!(s->flags & AVFMT_FLAG_KEEP_SIDE_DATA)) av_packet_merge_side_data(pkt); + st= s->streams[pkt->stream_index]; switch(st->codec->codec_type){ @@ -1116,7 +1132,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, } -static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) +static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) { AVStream *st; int len, ret, i; @@ -1130,7 +1146,10 @@ static int av_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) && @@ -1165,7 +1184,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) st->cur_pkt.data = NULL; assert(st->cur_len == 0); }else{ - pkt->destruct = NULL; + pkt->destruct = NULL; } compute_pkt_fields(s, st, st->parser, pkt); @@ -1236,6 +1255,9 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) { st->parser = av_parser_init(st->codec->codec_id); if (!st->parser) { + av_log(s, AV_LOG_WARNING, "parser not found for codec " + "%s, packets or times may be invalid.\n", + avcodec_get_name(st->codec->codec_id)); /* no parser available: just output the raw packets */ st->need_parsing = AVSTREAM_PARSE_NONE; }else if(st->need_parsing == AVSTREAM_PARSE_HEADERS){ @@ -1247,7 +1269,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) } } if(s->debug & FF_FDEBUG_TS) - av_log(s, AV_LOG_DEBUG, "av_read_frame_internal stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n", + av_log(s, AV_LOG_DEBUG, "read_frame_internal stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n", pkt->stream_index, pkt->pts, pkt->dts, @@ -1293,7 +1315,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) } } if(genpts){ - int ret= av_read_frame_internal(s, pkt); + int ret= read_frame_internal(s, pkt); if(ret<0){ if(pktl && ret != AVERROR(EAGAIN)){ eof=1; @@ -1307,7 +1329,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) return AVERROR(ENOMEM); }else{ assert(!s->packet_buffer); - return av_read_frame_internal(s, pkt); + return read_frame_internal(s, pkt); } } } @@ -1679,7 +1701,7 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i return pos; } -static int av_seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags){ +static int seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags){ int64_t pos_min, pos_max; #if 0 AVStream *st; @@ -1704,7 +1726,7 @@ static int av_seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, return 0; } -static int av_seek_frame_generic(AVFormatContext *s, +static int seek_frame_generic(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { int index; @@ -1772,7 +1794,7 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f ff_read_frame_flush(s); if(flags & AVSEEK_FLAG_BYTE) - return av_seek_frame_byte(s, stream_index, timestamp, flags); + return seek_frame_byte(s, stream_index, timestamp, flags); if(stream_index < 0){ stream_index= av_find_default_stream_index(s); @@ -1780,7 +1802,7 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f return -1; st= s->streams[stream_index]; - /* timestamp for default must be expressed in AV_TIME_BASE units */ + /* timestamp for default must be expressed in AV_TIME_BASE units */ timestamp = av_rescale(timestamp, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num); } @@ -1796,7 +1818,7 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f if(s->iformat->read_timestamp && !(s->iformat->flags & AVFMT_NOBINSEARCH)) return av_seek_frame_binary(s, stream_index, timestamp, flags); else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) - return av_seek_frame_generic(s, stream_index, timestamp, flags); + return seek_frame_generic(s, stream_index, timestamp, flags); else return -1; } @@ -1820,7 +1842,7 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int 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 av_seek_frame_generic() but with new ts semantics + // try some generic seek like seek_frame_generic() but with new ts semantics } /*******************************************************/ @@ -1830,7 +1852,7 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int * * @return TRUE if the stream has accurate duration for at least one component. */ -static int av_has_duration(AVFormatContext *ic) +static int has_duration(AVFormatContext *ic) { int i; AVStream *st; @@ -1848,7 +1870,7 @@ static int av_has_duration(AVFormatContext *ic) * * Also computes the global bitrate if possible. */ -static void av_update_stream_timings(AVFormatContext *ic) +static void update_stream_timings(AVFormatContext *ic) { int64_t start_time, start_time1, start_time_text, end_time, end_time1; int64_t duration, duration1; @@ -1906,7 +1928,7 @@ static void fill_all_stream_timings(AVFormatContext *ic) int i; AVStream *st; - av_update_stream_timings(ic); + update_stream_timings(ic); for(i = 0;i < ic->nb_streams; i++) { st = ic->streams[i]; if (st->start_time == AV_NOPTS_VALUE) { @@ -1918,7 +1940,7 @@ static void fill_all_stream_timings(AVFormatContext *ic) } } -static void av_estimate_timings_from_bit_rate(AVFormatContext *ic) +static void estimate_timings_from_bit_rate(AVFormatContext *ic) { int64_t filesize, duration; int bit_rate, i; @@ -1955,7 +1977,7 @@ static void av_estimate_timings_from_bit_rate(AVFormatContext *ic) #define DURATION_MAX_RETRY 3 /* only usable for MPEG-PS streams */ -static void av_estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) +static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) { AVPacket pkt1, *pkt = &pkt1; AVStream *st; @@ -1972,7 +1994,7 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset for (i=0; inb_streams; i++) { st = ic->streams[i]; if (st->start_time == AV_NOPTS_VALUE && st->first_dts == AV_NOPTS_VALUE) - av_log(st->codec, AV_LOG_WARNING, "start time is not set in av_estimate_timings_from_pts\n"); + av_log(st->codec, AV_LOG_WARNING, "start time is not set in estimate_timings_from_pts\n"); if (st->parser) { av_parser_close(st->parser); @@ -1986,39 +2008,40 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset filesize = ic->file_size; end_time = AV_NOPTS_VALUE; do{ - offset = filesize - (DURATION_MAX_READ_SIZE<pb, offset, SEEK_SET); - read_size = 0; - for(;;) { - if (read_size >= DURATION_MAX_READ_SIZE<<(FFMAX(retry-1,0))) - break; + avio_seek(ic->pb, offset, SEEK_SET); + read_size = 0; + for(;;) { + if (read_size >= DURATION_MAX_READ_SIZE<<(FFMAX(retry-1,0))) + break; - do{ - ret = av_read_packet(ic, pkt); - }while(ret == AVERROR(EAGAIN)); - 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 || - st->first_dts != AV_NOPTS_VALUE)) { - duration = end_time = pkt->pts; - if (st->start_time != AV_NOPTS_VALUE) duration -= st->start_time; - else duration -= st->first_dts; - if (duration < 0) - duration += 1LL<pts_wrap_bits; - if (duration > 0) { - if (st->duration == AV_NOPTS_VALUE || - st->duration < duration) - st->duration = duration; + do { + ret = av_read_packet(ic, pkt); + } while(ret == AVERROR(EAGAIN)); + 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 || + st->first_dts != AV_NOPTS_VALUE)) { + duration = end_time = pkt->pts; + if (st->start_time != AV_NOPTS_VALUE) + duration -= st->start_time; + else + duration -= st->first_dts; + if (duration < 0) + duration += 1LL<pts_wrap_bits; + if (duration > 0) { + if (st->duration == AV_NOPTS_VALUE || st->duration < duration) + st->duration = duration; + } } + av_free_packet(pkt); } - av_free_packet(pkt); - } }while( end_time==AV_NOPTS_VALUE && filesize > (DURATION_MAX_READ_SIZE<iformat->name, "mpegts")) && file_size && ic->pb->seekable) { /* get accurate estimate from the PTSes */ - av_estimate_timings_from_pts(ic, old_offset); - } else if (av_has_duration(ic)) { + estimate_timings_from_pts(ic, old_offset); + } else if (has_duration(ic)) { /* at least one component has timings - we use them for all the components */ fill_all_stream_timings(ic); } else { av_log(ic, AV_LOG_WARNING, "Estimating duration from bitrate, this may be inaccurate\n"); /* less precise: use bitrate info */ - av_estimate_timings_from_bit_rate(ic); + estimate_timings_from_bit_rate(ic); } - av_update_stream_timings(ic); + update_stream_timings(ic); -#if 0 { int i; AVStream av_unused *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); + av_dlog(ic, "%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); + av_dlog(ic, "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) +static int has_codec_parameters(AVCodecContext *avctx) { int val; - switch(enc->codec_type) { + switch (avctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - val = enc->sample_rate && enc->channels && enc->sample_fmt != AV_SAMPLE_FMT_NONE; - if(!enc->frame_size && - (enc->codec_id == CODEC_ID_VORBIS || - enc->codec_id == CODEC_ID_AAC || - enc->codec_id == CODEC_ID_MP1 || - enc->codec_id == CODEC_ID_MP2 || - enc->codec_id == CODEC_ID_MP3 || - enc->codec_id == CODEC_ID_SPEEX || - enc->codec_id == CODEC_ID_CELT)) + 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)) return 0; break; case AVMEDIA_TYPE_VIDEO: - val = enc->width && enc->pix_fmt != PIX_FMT_NONE; + 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; } - return enc->codec_id != CODEC_ID_NONE && val != 0; + return avctx->codec_id != CODEC_ID_NONE && val != 0; } static int has_decode_delay_been_guessed(AVStream *st) @@ -2336,7 +2359,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) { @@ -2359,7 +2382,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) /* NOTE: a new stream can be added there if no header in file (AVFMTCTX_NOHEADER) */ - ret = av_read_frame_internal(ic, &pkt1); + ret = read_frame_internal(ic, &pkt1); if (ret == AVERROR(EAGAIN)) continue; @@ -2519,7 +2542,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) } } - av_estimate_timings(ic, old_offset); + estimate_timings(ic, old_offset); compute_chapters_end(ic); @@ -2554,14 +2577,20 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) return ret; } -static AVProgram *find_program_from_stream(AVFormatContext *ic, int s) +AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s) { int i, j; - for (i = 0; i < ic->nb_programs; i++) - for (j = 0; j < ic->programs[i]->nb_stream_indexes; j++) - if (ic->programs[i]->stream_index[j] == s) - return ic->programs[i]; + for (i = 0; i < ic->nb_programs; i++) { + if (ic->programs[i] == last) { + last = NULL; + } else { + if (!last) + for (j = 0; j < ic->programs[i]->nb_stream_indexes; j++) + if (ic->programs[i]->stream_index[j] == s) + return ic->programs[i]; + } + } return NULL; } @@ -2578,7 +2607,7 @@ int av_find_best_stream(AVFormatContext *ic, AVCodec *decoder = NULL, *best_decoder = NULL; if (related_stream >= 0 && wanted_stream_nb < 0) { - AVProgram *p = find_program_from_stream(ic, related_stream); + AVProgram *p = av_find_program_from_stream(ic, NULL, related_stream); if (p) { program = p->stream_index; nb_streams = p->nb_stream_indexes; @@ -2929,6 +2958,9 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) av_dict_copy(&tmp, *options, 0); if ((ret = av_opt_set_dict(s, &tmp)) < 0) goto fail; + if (s->priv_data && s->oformat->priv_class && *(const AVClass**)s->priv_data==s->oformat->priv_class && + (ret = av_opt_set_dict(s->priv_data, &tmp)) < 0) + goto fail; // some sanity checks if (s->nb_streams == 0 && !(s->oformat->flags & AVFMT_NOSTREAMS)) { @@ -3039,7 +3071,7 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) ret = AVERROR_INVALIDDATA; goto fail; } - av_frac_init(&st->pts, 0, 0, den); + frac_init(&st->pts, 0, 0, den); } } @@ -3117,11 +3149,11 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt){ likely equal to the encoder delay, but it would be better if we had the real timestamps from the encoder */ if (frame_size >= 0 && (pkt->size || st->pts.num!=st->pts.den>>1 || st->pts.val)) { - av_frac_add(&st->pts, (int64_t)st->time_base.den * frame_size); + frac_add(&st->pts, (int64_t)st->time_base.den * frame_size); } break; case AVMEDIA_TYPE_VIDEO: - av_frac_add(&st->pts, (int64_t)st->time_base.den * st->codec->time_base.num); + frac_add(&st->pts, (int64_t)st->time_base.den * st->codec->time_base.num); break; default: break; @@ -3193,17 +3225,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; @@ -3230,7 +3289,7 @@ int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pk * @return 1 if a packet was output, 0 if no packet could be output, * < 0 if an error occurred */ -static int av_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush){ +static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush){ if(s->oformat->interleave_packet) return s->oformat->interleave_packet(s, out, in, flush); else @@ -3255,7 +3314,7 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){ for(;;){ AVPacket opkt; - int ret= av_interleave_packet(s, &opkt, pkt, 0); + int ret= interleave_packet(s, &opkt, pkt, 0); if(ret<=0) //FIXME cleanup needed for ret<0 ? return ret; @@ -3279,7 +3338,7 @@ int av_write_trailer(AVFormatContext *s) for(;;){ AVPacket pkt; - ret= av_interleave_packet(s, &pkt, NULL, 1); + ret= interleave_packet(s, &pkt, NULL, 1); if(ret<0) //FIXME cleanup needed for ret<0 ? goto fail; if(!ret) @@ -3399,7 +3458,7 @@ static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_out st->codec->width*st->sample_aspect_ratio.num, st->codec->height*st->sample_aspect_ratio.den, 1024*1024); - av_log(NULL, AV_LOG_INFO, ", PAR %d:%d DAR %d:%d", + av_log(NULL, AV_LOG_INFO, ", SAR %d:%d DAR %d:%d", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, display_aspect_ratio.num, display_aspect_ratio.den); } @@ -4023,3 +4082,17 @@ int64_t ff_iso8601_to_unix_time(const char *datestr) return 0; #endif } + +int avformat_query_codec(AVOutputFormat *ofmt, enum CodecID codec_id, int std_compliance) +{ + if (ofmt) { + if (ofmt->query_codec) + return ofmt->query_codec(codec_id, std_compliance); + else if (ofmt->codec_tag) + return !!av_codec_get_tag(ofmt->codec_tag, codec_id); + else if (codec_id == ofmt->video_codec || codec_id == ofmt->audio_codec || + codec_id == ofmt->subtitle_codec) + return 1; + } + return AVERROR_PATCHWELCOME; +}