diff options
Diffstat (limited to 'libavformat/utils.c')
-rw-r--r-- | libavformat/utils.c | 892 |
1 files changed, 673 insertions, 219 deletions
diff --git a/libavformat/utils.c b/libavformat/utils.c index 658da8f951..fd9e4d5309 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1,21 +1,21 @@ /* - * various utility functions for use within Libav + * various utility functions for use within FFmpeg * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,7 +25,9 @@ #include "avio_internal.h" #include "internal.h" #include "libavcodec/internal.h" +#include "libavcodec/raw.h" #include "libavcodec/bytestream.h" +#include "libavutil/avassert.h" #include "libavutil/opt.h" #include "libavutil/dict.h" #include "libavutil/pixdesc.h" @@ -50,23 +52,30 @@ /** * @file - * various utility functions for use within Libav + * various utility functions for use within FFmpeg */ unsigned avformat_version(void) { + av_assert0(LIBAVFORMAT_VERSION_MICRO >= 100); return LIBAVFORMAT_VERSION_INT; } const char *avformat_configuration(void) { - return LIBAV_CONFIGURATION; + return FFMPEG_CONFIGURATION; } const char *avformat_license(void) { #define LICENSE_PREFIX "libavformat license: " - return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; +} + +#define RELATIVE_TS_BASE (INT64_MAX - (1LL<<48)) + +static int is_relative(int64_t ts) { + return ts > (RELATIVE_TS_BASE - (1LL<<48)); } /* fraction handling */ @@ -265,10 +274,33 @@ AVInputFormat *av_find_input_format(const char *short_name) return NULL; } +int ffio_limit(AVIOContext *s, int size) +{ + if(s->maxsize>=0){ + int64_t remaining= s->maxsize - avio_tell(s); + if(remaining < size){ + int64_t newsize= avio_size(s); + if(!s->maxsize || s->maxsize<newsize) + s->maxsize= newsize - !newsize; + remaining= s->maxsize - avio_tell(s); + remaining= FFMAX(remaining, 0); + } + + if(s->maxsize>=0 && remaining+1 < size){ + av_log(0, AV_LOG_ERROR, "Truncating packet of size %d to %"PRId64"\n", size, remaining+1); + size= remaining+1; + } + } + return size; +} int av_get_packet(AVIOContext *s, AVPacket *pkt, int size) { - int ret= av_new_packet(pkt, size); + int ret; + int orig_size = size; + size= ffio_limit(s, size); + + ret= av_new_packet(pkt, size); if(ret<0) return ret; @@ -280,6 +312,8 @@ int av_get_packet(AVIOContext *s, AVPacket *pkt, int size) av_free_packet(pkt); else av_shrink_packet(pkt, ret); + if (pkt->size < orig_size) + pkt->flags |= AV_PKT_FLAG_CORRUPT; return ret; } @@ -306,19 +340,19 @@ int av_filename_number_test(const char *filename) return filename && (av_get_frame_filename(buf, sizeof(buf), filename, 1)>=0); } -AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max) +AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret) { AVProbeData lpd = *pd; AVInputFormat *fmt1 = NULL, *fmt; - int score, id3 = 0; + int score, nodat = 0, score_max=0; if (lpd.buf_size > 10 && ff_id3v2_match(lpd.buf, ID3v2_DEFAULT_MAGIC)) { int id3len = ff_id3v2_tag_len(lpd.buf); if (lpd.buf_size > id3len + 16) { lpd.buf += id3len; lpd.buf_size -= id3len; - } - id3 = 1; + }else + nodat = 1; } fmt = NULL; @@ -328,44 +362,41 @@ AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score score = 0; if (fmt1->read_probe) { score = fmt1->read_probe(&lpd); + if(fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions)) + score = FFMAX(score, nodat ? AVPROBE_SCORE_MAX/4-1 : 1); } else if (fmt1->extensions) { if (av_match_ext(lpd.filename, fmt1->extensions)) { score = 50; } } - if (score > *score_max) { - *score_max = score; + if (score > score_max) { + score_max = score; fmt = fmt1; - }else if (score == *score_max) + }else if (score == score_max) fmt = NULL; } - - /* a hack for files with huge id3v2 tags -- try to guess by file extension. */ - if (!fmt && is_opened && *score_max < AVPROBE_SCORE_MAX/4) { - while ((fmt = av_iformat_next(fmt))) - if (fmt->extensions && av_match_ext(lpd.filename, fmt->extensions)) { - *score_max = AVPROBE_SCORE_MAX/4; - break; - } - } - - if (!fmt && id3 && *score_max < AVPROBE_SCORE_MAX/4-1) { - while ((fmt = av_iformat_next(fmt))) - if (fmt->extensions && av_match_ext("mp3", fmt->extensions)) { - *score_max = AVPROBE_SCORE_MAX/4-1; - break; - } - } + *score_ret= score_max; return fmt; } +AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max) +{ + int score_ret; + AVInputFormat *fmt= av_probe_input_format3(pd, is_opened, &score_ret); + if(score_ret > *score_max){ + *score_max= score_ret; + return fmt; + }else + return NULL; +} + AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened){ int score=0; return av_probe_input_format2(pd, is_opened, &score); } -static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeData *pd, int score) +static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeData *pd) { static const struct { const char *name; enum CodecID id; enum AVMediaType type; @@ -375,12 +406,14 @@ 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 }, { 0 } }; - AVInputFormat *fmt = av_probe_input_format2(pd, 1, &score); + int score; + AVInputFormat *fmt = av_probe_input_format3(pd, 1, &score); if (fmt) { int i; @@ -394,12 +427,28 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeDa } } } - return !!fmt; + return score; } /************************************************************/ /* input media file */ +int av_demuxer_open(AVFormatContext *ic){ + int err; + + if (ic->iformat->read_header) { + err = ic->iformat->read_header(ic); + if (err < 0) + return err; + } + + if (ic->pb && !ic->data_offset) + ic->data_offset = avio_tell(ic->pb); + + return 0; +} + + /** size of probe buffer, for guessing file type from file contents */ #define PROBE_BUF_MIN 2048 #define PROBE_BUF_MAX (1<<20) @@ -428,13 +477,19 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, probe_size = FFMIN(probe_size<<1, FFMAX(max_probe_size, probe_size+1))) { 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) { @@ -453,9 +508,9 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, *fmt = av_probe_input_format2(&pd, 1, &score); if(*fmt){ if(score <= AVPROBE_SCORE_MAX/4){ //this can only be true in the last iteration - av_log(logctx, AV_LOG_WARNING, "Format detected only with low score of %d, misdetection possible!\n", score); + av_log(logctx, AV_LOG_WARNING, "Format %s detected only with low score of %d, misdetection possible!\n", (*fmt)->name, score); }else - av_log(logctx, AV_LOG_DEBUG, "Probed with size=%d and score=%d\n", probe_size, score); + av_log(logctx, AV_LOG_DEBUG, "Format %s probed with size=%d and score=%d\n", (*fmt)->name, probe_size, score); } } @@ -482,7 +537,8 @@ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **o if (!s->iformat) return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, s->probesize); else if (s->iformat->flags & AVFMT_NOFILE) - return AVERROR(EINVAL); + av_log(s, AV_LOG_WARNING, "Custom AVIOContext makes no sense and " + "will be ignored with AVFMT_NOFILE format.\n"); return 0; } @@ -490,7 +546,7 @@ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **o (!s->iformat && (s->iformat = av_probe_input_format(&pd, 0)))) return 0; - if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ, + if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ | s->avio_flags, &s->interrupt_callback, options)) < 0) return ret; if (s->iformat) @@ -536,6 +592,10 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma if (!s && !(s = avformat_alloc_context())) return AVERROR(ENOMEM); + if (!s->av_class){ + av_log(0, AV_LOG_ERROR, "Input context has not been properly allocated by avformat_alloc_context() and is not NULL either\n"); + return AVERROR(EINVAL); + } if (fmt) s->iformat = fmt; @@ -577,7 +637,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma if (s->pb) ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); - if (s->iformat->read_header) + if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header) if ((ret = s->iformat->read_header(s)) < 0) goto fail; @@ -588,7 +648,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma queue_attached_pictures(s); - if (s->pb && !s->data_offset) + if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->pb && !s->data_offset) s->data_offset = avio_tell(s->pb); s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; @@ -622,12 +682,7 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) if (pktl) { *pkt = pktl->pkt; - if(s->streams[pkt->stream_index]->codec->codec_id != CODEC_ID_PROBE || - !s->streams[pkt->stream_index]->probe_packets || - s->raw_packet_buffer_remaining_size < pkt->size){ - AVProbeData *pd = &s->streams[pkt->stream_index]->probe_data; - av_freep(&pd->buf); - pd->buf_size = 0; + if(s->streams[pkt->stream_index]->request_probe <= 0){ s->raw_packet_buffer = pktl->next; s->raw_packet_buffer_remaining_size += pkt->size; av_free(pktl); @@ -641,7 +696,8 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) if (!pktl || ret == AVERROR(EAGAIN)) return ret; for (i = 0; i < s->nb_streams; i++) - s->streams[i]->probe_packets = 0; + if(s->streams[i]->request_probe > 0) + s->streams[i]->request_probe = -1; continue; } @@ -654,6 +710,14 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) continue; } + if(!(s->flags & AVFMT_FLAG_KEEP_SIDE_DATA)) + av_packet_merge_side_data(pkt); + + if(pkt->stream_index >= (unsigned)s->nb_streams){ + av_log(s, AV_LOG_ERROR, "Invalid stream index %d\n", pkt->stream_index); + continue; + } + st= s->streams[pkt->stream_index]; switch(st->codec->codec_type){ @@ -668,16 +732,16 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) break; } - if(!pktl && (st->codec->codec_id != CODEC_ID_PROBE || - !st->probe_packets)) + if(!pktl && st->request_probe <= 0) return ret; add_to_pktbuf(&s->raw_packet_buffer, pkt, &s->raw_packet_buffer_end); s->raw_packet_buffer_remaining_size -= pkt->size; - if(st->codec->codec_id == CODEC_ID_PROBE){ + if(st->request_probe>0){ AVProbeData *pd = &st->probe_data; - av_log(s, AV_LOG_DEBUG, "probing stream %d\n", st->index); + int end; + av_log(s, AV_LOG_DEBUG, "probing stream %d pp:%d\n", st->index, st->probe_packets); --st->probe_packets; pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE); @@ -685,13 +749,20 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) pd->buf_size += pkt->size; memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE); - if(av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)){ - //FIXME we do not reduce score to 0 for the case of running out of buffer space in bytes - set_codec_from_probe_data(s, st, pd, st->probe_packets > 0 ? AVPROBE_SCORE_MAX/4 : 0); - if(st->codec->codec_id != CODEC_ID_PROBE){ + end= s->raw_packet_buffer_remaining_size <= 0 + || st->probe_packets<=0; + + if(end || av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)){ + int score= set_codec_from_probe_data(s, st, pd); + if( (st->codec->codec_id != CODEC_ID_NONE && score > AVPROBE_SCORE_MAX/4) + || end){ pd->buf_size=0; av_freep(&pd->buf); + st->request_probe= -1; + if(st->codec->codec_id != CODEC_ID_NONE){ av_log(s, AV_LOG_DEBUG, "probed stream %d\n", st->index); + }else + av_log(s, AV_LOG_WARNING, "probed stream %d failed\n", st->index); } } } @@ -708,6 +779,17 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt) /**********************************************************/ +static int determinable_frame_size(AVCodecContext *avctx) +{ + if (/*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_CELT*/) + return 1; + return 0; +} + /** * Get the number of samples of an audio frame. Return -1 on error. */ @@ -742,7 +824,7 @@ static void compute_frame_duration(int *pnum, int *pden, AVStream *st, *pden = 0; switch(st->codec->codec_type) { case AVMEDIA_TYPE_VIDEO: - if (st->r_frame_rate.num) { + if (st->r_frame_rate.num && !pc) { *pnum = st->r_frame_rate.den; *pden = st->r_frame_rate.num; } else if(st->time_base.num*1000LL > st->time_base.den) { @@ -783,6 +865,7 @@ static int is_intra_only(AVCodecContext *enc){ case CODEC_ID_LJPEG: case CODEC_ID_PRORES: case CODEC_ID_RAWVIDEO: + case CODEC_ID_V210: case CODEC_ID_DVVIDEO: case CODEC_ID_HUFFYUV: case CODEC_ID_FFVHUFF: @@ -791,6 +874,7 @@ static int is_intra_only(AVCodecContext *enc){ case CODEC_ID_VCR1: case CODEC_ID_DNXHD: case CODEC_ID_JPEG2000: + case CODEC_ID_UTVIDEO: return 1; default: break; } @@ -798,27 +882,38 @@ static int is_intra_only(AVCodecContext *enc){ return 0; } +static AVPacketList *get_next_pkt(AVFormatContext *s, AVStream *st, AVPacketList *pktl) +{ + if (pktl->next) + return pktl->next; + if (pktl == s->parse_queue_end) + return s->packet_buffer; + return NULL; +} + static void update_initial_timestamps(AVFormatContext *s, int stream_index, int64_t dts, int64_t pts) { AVStream *st= s->streams[stream_index]; - AVPacketList *pktl= s->packet_buffer; + AVPacketList *pktl= s->parse_queue ? s->parse_queue : s->packet_buffer; - if(st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE || st->cur_dts == AV_NOPTS_VALUE) + if(st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE || st->cur_dts == AV_NOPTS_VALUE || is_relative(dts)) return; - st->first_dts= dts - st->cur_dts; + st->first_dts= dts - (st->cur_dts - RELATIVE_TS_BASE); st->cur_dts= dts; - for(; pktl; pktl= pktl->next){ + if (is_relative(pts)) + pts += st->first_dts - RELATIVE_TS_BASE; + + for(; pktl; pktl= get_next_pkt(s, st, pktl)){ if(pktl->pkt.stream_index != stream_index) continue; - //FIXME think more about this check - if(pktl->pkt.pts != AV_NOPTS_VALUE && pktl->pkt.pts == pktl->pkt.dts) - pktl->pkt.pts += st->first_dts; + if(is_relative(pktl->pkt.pts)) + pktl->pkt.pts += st->first_dts - RELATIVE_TS_BASE; - if(pktl->pkt.dts != AV_NOPTS_VALUE) - pktl->pkt.dts += st->first_dts; + if(is_relative(pktl->pkt.dts)) + pktl->pkt.dts += st->first_dts - RELATIVE_TS_BASE; if(st->start_time == AV_NOPTS_VALUE && pktl->pkt.pts != AV_NOPTS_VALUE) st->start_time= pktl->pkt.pts; @@ -830,38 +925,38 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, static void update_initial_durations(AVFormatContext *s, AVStream *st, int stream_index, int duration) { - AVPacketList *pktl= s->packet_buffer; - int64_t cur_dts= 0; + AVPacketList *pktl= s->parse_queue ? s->parse_queue : s->packet_buffer; + int64_t cur_dts= RELATIVE_TS_BASE; if(st->first_dts != AV_NOPTS_VALUE){ cur_dts= st->first_dts; - for(; pktl; pktl= pktl->next){ + for(; pktl; pktl= get_next_pkt(s, st, pktl)){ if(pktl->pkt.stream_index == stream_index){ if(pktl->pkt.pts != pktl->pkt.dts || pktl->pkt.dts != AV_NOPTS_VALUE || pktl->pkt.duration) break; cur_dts -= duration; } } - pktl= s->packet_buffer; + pktl= s->parse_queue ? s->parse_queue : s->packet_buffer; st->first_dts = cur_dts; - }else if(st->cur_dts) + }else if(st->cur_dts != RELATIVE_TS_BASE) return; - for(; pktl; pktl= pktl->next){ + for(; pktl; pktl= get_next_pkt(s, st, pktl)){ if(pktl->pkt.stream_index != stream_index) continue; - if(pktl->pkt.pts == pktl->pkt.dts && pktl->pkt.dts == AV_NOPTS_VALUE + if(pktl->pkt.pts == pktl->pkt.dts && (pktl->pkt.dts == AV_NOPTS_VALUE || pktl->pkt.dts == st->first_dts) && !pktl->pkt.duration){ pktl->pkt.dts= cur_dts; if(!st->codec->has_b_frames) pktl->pkt.pts= cur_dts; - cur_dts += duration; - if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) +// if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) pktl->pkt.duration = duration; }else break; + cur_dts = pktl->pkt.dts + pktl->pkt.duration; } - if(st->first_dts == AV_NOPTS_VALUE) + if(!pktl) st->cur_dts= cur_dts; } @@ -877,6 +972,10 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, if((s->flags & AVFMT_FLAG_IGNDTS) && pkt->pts != AV_NOPTS_VALUE) pkt->dts= AV_NOPTS_VALUE; + if (st->codec->codec_id != CODEC_ID_H264 && pc && pc->pict_type == AV_PICTURE_TYPE_B) + //FIXME Set low_delay = 0 when has_b_frames = 1 + st->codec->has_b_frames = 1; + /* do we have a video B-frame ? */ delay= st->codec->has_b_frames; presentation_delayed = 0; @@ -887,8 +986,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<<st->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<<st->pts_wrap_bits; } @@ -896,19 +994,18 @@ 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"); - pkt->dts= pkt->pts= AV_NOPTS_VALUE; + av_log(s, AV_LOG_DEBUG, "invalid dts/pts combination %"PRIi64"\n", pkt->dts); + pkt->dts= AV_NOPTS_VALUE; } - if (pkt->duration == 0 && st->codec->codec_type != AVMEDIA_TYPE_AUDIO) { + if (pkt->duration == 0) { compute_frame_duration(&num, &den, st, pc, pkt); if (den && num) { pkt->duration = av_rescale_rnd(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num, AV_ROUND_DOWN); - - if(pkt->duration != 0 && s->packet_buffer) - update_initial_durations(s, st, pkt->stream_index, pkt->duration); } } + if(pkt->duration != 0 && (s->packet_buffer || s->parse_queue)) + update_initial_durations(s, st, pkt->stream_index, pkt->duration); /* correct timestamps with byte offset if demuxers only have timestamps on packet boundaries */ @@ -944,7 +1041,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts > pkt->dts) presentation_delayed = 1; -// av_log(NULL, AV_LOG_DEBUG, "IN delayed:%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64" st:%d pc:%p\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts, pkt->stream_index, pc); +// av_log(NULL, AV_LOG_DEBUG, "IN delayed:%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64" st:%d pc:%p duration:%d\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts, pkt->stream_index, pc, pkt->duration); /* interpolate PTS and DTS if they are not present */ //We skip H264 currently because delay and has_b_frames are not reliably set if((delay==0 || (delay==1 && pc)) && st->codec->codec_id != CODEC_ID_H264){ @@ -969,35 +1066,31 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, by knowing the future */ } else if (pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || - pkt->duration || - st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + pkt->duration ) { int duration = pkt->duration; - if (!duration && st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - compute_frame_duration(&num, &den, st, pc, pkt); - if (den && num) { - duration = av_rescale_rnd(1, num * (int64_t)st->time_base.den, - den * (int64_t)st->time_base.num, - AV_ROUND_DOWN); - if (duration != 0 && s->packet_buffer) { - update_initial_durations(s, st, pkt->stream_index, - duration); - } + + if(pkt->pts != AV_NOPTS_VALUE && duration){ + int64_t old_diff= FFABS(st->cur_dts - duration - pkt->pts); + int64_t new_diff= FFABS(st->cur_dts - pkt->pts); + if( old_diff < new_diff && old_diff < (duration>>3) + && (!strcmp(s->iformat->name, "mpeg") || + !strcmp(s->iformat->name, "mpegts"))){ + pkt->pts += duration; + av_log(s, AV_LOG_WARNING, "Adjusting PTS forward\n"); + // av_log(NULL, AV_LOG_DEBUG, "id:%d old:%"PRId64" new:%"PRId64" dur:%d cur:%"PRId64" size:%d\n", pkt->stream_index, old_diff, new_diff, pkt->duration, st->cur_dts, pkt->size); } } - if (pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || - duration) { - /* presentation is not delayed : PTS and DTS are the same */ - if (pkt->pts == AV_NOPTS_VALUE) - pkt->pts = pkt->dts; - update_initial_timestamps(s, pkt->stream_index, pkt->pts, - pkt->pts); - if (pkt->pts == AV_NOPTS_VALUE) - pkt->pts = st->cur_dts; - pkt->dts = pkt->pts; - if (pkt->pts != AV_NOPTS_VALUE) - st->cur_dts = pkt->pts + duration; - } + /* presentation is not delayed : PTS and DTS are the same */ + if (pkt->pts == AV_NOPTS_VALUE) + pkt->pts = pkt->dts; + update_initial_timestamps(s, pkt->stream_index, pkt->pts, + pkt->pts); + if (pkt->pts == AV_NOPTS_VALUE) + pkt->pts = st->cur_dts; + pkt->dts = pkt->pts; + if (pkt->pts != AV_NOPTS_VALUE) + st->cur_dts = pkt->pts + duration; } } @@ -1051,6 +1144,9 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) av_init_packet(&flush_pkt); pkt = &flush_pkt; got_output = 1; + } else if (!size && st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) { + // preserve 0-size sync packets + compute_pkt_fields(s, st, st->parser, pkt); } while (size > 0 || (pkt == &flush_pkt && got_output)) { @@ -1102,8 +1198,9 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) if ((s->iformat->flags & AVFMT_GENERIC_INDEX) && out_pkt.flags & AV_PKT_FLAG_KEY) { + int64_t pos= (st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) ? out_pkt.pos : st->parser->frame_offset; ff_reduce_index(s, st->index); - av_add_index_entry(st, st->parser->frame_offset, out_pkt.dts, + av_add_index_entry(st, pos, out_pkt.dts, 0, 0, AVINDEX_KEYFRAME); } @@ -1197,6 +1294,9 @@ static int 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_VERBOSE, "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) { @@ -1223,6 +1323,12 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) /* free packet */ av_free_packet(&cur_pkt); } + if (pkt->flags & AV_PKT_FLAG_KEY) + st->skip_to_keyframe = 0; + if (st->skip_to_keyframe) { + av_free_packet(&cur_pkt); + got_packet = 0; + } } if (!got_packet && s->parse_queue) @@ -1244,15 +1350,17 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) { const int genpts = s->flags & AVFMT_FLAG_GENPTS; int eof = 0; + int ret; - if (!genpts) - return s->packet_buffer ? read_from_packet_buffer(&s->packet_buffer, + if (!genpts) { + ret = s->packet_buffer ? read_from_packet_buffer(&s->packet_buffer, &s->packet_buffer_end, pkt) : read_frame_internal(s, pkt); + goto return_packet; + } for (;;) { - int ret; AVPacketList *pktl = s->packet_buffer; if (pktl) { @@ -1260,22 +1368,40 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) if (next_pkt->dts != AV_NOPTS_VALUE) { int wrap_bits = s->streams[next_pkt->stream_index]->pts_wrap_bits; + // last dts seen for this stream. if any of packets following + // current one had no dts, we will set this to AV_NOPTS_VALUE. + int64_t last_dts = next_pkt->dts; while (pktl && next_pkt->pts == AV_NOPTS_VALUE) { if (pktl->pkt.stream_index == next_pkt->stream_index && - (av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2LL << (wrap_bits - 1)) < 0) && - av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2LL << (wrap_bits - 1))) { //not b frame - next_pkt->pts = pktl->pkt.dts; + (av_compare_mod(next_pkt->dts, pktl->pkt.dts, 2LL << (wrap_bits - 1)) < 0)) { + if (av_compare_mod(pktl->pkt.pts, pktl->pkt.dts, 2LL << (wrap_bits - 1))) { //not b frame + next_pkt->pts = pktl->pkt.dts; + } + if (last_dts != AV_NOPTS_VALUE) { + // Once last dts was set to AV_NOPTS_VALUE, we don't change it. + last_dts = pktl->pkt.dts; + } } pktl = pktl->next; } + if (eof && next_pkt->pts == AV_NOPTS_VALUE && last_dts != AV_NOPTS_VALUE) { + // Fixing the last reference frame had none pts issue (For MXF etc). + // We only do this when + // 1. eof. + // 2. we are not able to resolve a pts value for current packet. + // 3. the packets for this stream at the end of the files had valid dts. + next_pkt->pts = last_dts + next_pkt->duration; + } pktl = s->packet_buffer; } /* read packet from packet buffer, if there is data */ if (!(next_pkt->pts == AV_NOPTS_VALUE && - next_pkt->dts != AV_NOPTS_VALUE && !eof)) - return read_from_packet_buffer(&s->packet_buffer, + next_pkt->dts != AV_NOPTS_VALUE && !eof)) { + ret = read_from_packet_buffer(&s->packet_buffer, &s->packet_buffer_end, pkt); + goto return_packet; + } } ret = read_frame_internal(s, pkt); @@ -1291,6 +1417,13 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) &s->packet_buffer_end)) < 0) return AVERROR(ENOMEM); } + +return_packet: + if (is_relative(pkt->dts)) + pkt->dts -= RELATIVE_TS_BASE; + if (is_relative(pkt->pts)) + pkt->pts -= RELATIVE_TS_BASE; + return ret; } /* XXX: suppress the packet queue */ @@ -1345,7 +1478,8 @@ void ff_read_frame_flush(AVFormatContext *s) st->parser = NULL; } st->last_IP_pts = AV_NOPTS_VALUE; - st->cur_dts = AV_NOPTS_VALUE; /* we set the current DTS to an unspecified origin */ + if(st->first_dts == AV_NOPTS_VALUE) st->cur_dts = RELATIVE_TS_BASE; + else st->cur_dts = AV_NOPTS_VALUE; /* we set the current DTS to an unspecified origin */ st->reference_dts = AV_NOPTS_VALUE; st->probe_packets = MAX_PROBE_PACKETS; @@ -1392,6 +1526,9 @@ int ff_add_index_entry(AVIndexEntry **index_entries, if((unsigned)*nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry)) return -1; + if (is_relative(timestamp)) //FIXME this maintains previous behavior but we should shift by the correct offset once known + timestamp -= RELATIVE_TS_BASE; + entries = av_fast_realloc(*index_entries, index_entries_allocated_size, (*nb_index_entries + 1) * @@ -1532,6 +1669,7 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts if ((ret = avio_seek(s->pb, pos, SEEK_SET)) < 0) return ret; + ff_read_frame_flush(s); ff_update_cur_dts(s, st, ts); return 0; @@ -1555,6 +1693,11 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, return -1; } + if(ts_min >= target_ts){ + *ts_ret= ts_min; + return pos_min; + } + if(ts_max == AV_NOPTS_VALUE){ int step= 1024; filesize = avio_size(s->pb); @@ -1580,6 +1723,11 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, pos_limit= pos_max; } + if(ts_max <= target_ts){ + *ts_ret= ts_max; + return pos_max; + } + if(ts_min > ts_max){ return -1; }else if(ts_min == ts_max){ @@ -1637,12 +1785,14 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max; ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max; +#if 0 pos_min = pos; ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX); pos_min++; ts_max = read_timestamp(s, stream_index, &pos_min, INT64_MAX); av_dlog(s, "pos=0x%"PRIx64" %"PRId64"<=%"PRId64"<=%"PRId64"\n", pos, ts_min, target_ts, ts_max); +#endif *ts_ret= ts; return pos; } @@ -1678,6 +1828,7 @@ static int seek_frame_generic(AVFormatContext *s, if(index < 0 || index==st->nb_index_entries-1){ AVPacket pkt; + int nonkey=0; if(st->nb_index_entries){ assert(st->index_entries); @@ -1697,9 +1848,13 @@ static int seek_frame_generic(AVFormatContext *s, 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 && st->codec->codec_id != CODEC_ID_CDGRAPHICS){ + 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); @@ -1708,10 +1863,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; @@ -1744,11 +1901,13 @@ static int seek_frame_internal(AVFormatContext *s, int stream_index, } /* first, we try the format specific seek */ + AV_NOWARN_DEPRECATED( if (s->iformat->read_seek) { ff_read_frame_flush(s); ret = s->iformat->read_seek(s, stream_index, timestamp, flags); } else ret = -1; + ) if (ret >= 0) { return 0; } @@ -1795,8 +1954,18 @@ 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 - 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)); + AV_NOWARN_DEPRECATED( + if (s->iformat->read_seek || 1) { + int dir = (ts - min_ts > (uint64_t)(max_ts - ts) ? AVSEEK_FLAG_BACKWARD : 0); + int ret = av_seek_frame(s, stream_index, ts, flags | dir); + if (ret<0 && ts != min_ts && max_ts != ts) { + ret = av_seek_frame(s, stream_index, dir ? max_ts : min_ts, flags | dir); + if (ret >= 0) + ret = av_seek_frame(s, stream_index, ts, flags | (dir^AVSEEK_FLAG_BACKWARD)); + } + return ret; + } + ) // try some generic seek like seek_frame_generic() but with new ts semantics } @@ -1830,18 +1999,23 @@ static int has_duration(AVFormatContext *ic) */ static void update_stream_timings(AVFormatContext *ic) { - int64_t start_time, start_time1, end_time, end_time1; + int64_t start_time, start_time1, start_time_text, end_time, end_time1; int64_t duration, duration1, filesize; int i; AVStream *st; start_time = INT64_MAX; + start_time_text = INT64_MAX; end_time = INT64_MIN; duration = INT64_MIN; for(i = 0;i < ic->nb_streams; i++) { 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_type == AVMEDIA_TYPE_SUBTITLE) { + if (start_time1 < start_time_text) + start_time_text = start_time1; + } else start_time = FFMIN(start_time, start_time1); if (st->duration != AV_NOPTS_VALUE) { end_time1 = start_time1 @@ -1854,19 +2028,21 @@ static void update_stream_timings(AVFormatContext *ic) duration = FFMAX(duration, duration1); } } + if (start_time == INT64_MAX || (start_time > start_time_text && start_time - start_time_text < AV_TIME_BASE)) + start_time = start_time_text; if (start_time != INT64_MAX) { ic->start_time = start_time; if (end_time != INT64_MIN) duration = FFMAX(duration, end_time - start_time); } - if (duration != INT64_MIN) { + if (duration != INT64_MIN && ic->duration == AV_NOPTS_VALUE) { ic->duration = duration; - if (ic->pb && (filesize = avio_size(ic->pb)) > 0) { + } + if (ic->pb && (filesize = avio_size(ic->pb)) > 0 && ic->duration != AV_NOPTS_VALUE) { /* compute the bitrate */ ic->bit_rate = (double)filesize * 8.0 * AV_TIME_BASE / (double)ic->duration; } - } } static void fill_all_stream_timings(AVFormatContext *ic) @@ -2050,6 +2226,8 @@ static int has_codec_parameters(AVStream *st) switch (avctx->codec_type) { case AVMEDIA_TYPE_AUDIO: val = avctx->sample_rate && avctx->channels; + if (!avctx->frame_size && determinable_frame_size(avctx)) + return 0; if (st->info->found_decoder >= 0 && avctx->sample_fmt == AV_SAMPLE_FMT_NONE) return 0; break; @@ -2058,6 +2236,8 @@ static int has_codec_parameters(AVStream *st) if (st->info->found_decoder >= 0 && avctx->pix_fmt == PIX_FMT_NONE) return 0; break; + case AVMEDIA_TYPE_DATA: + if(avctx->codec_id == CODEC_ID_NONE) return 1; default: val = 1; break; @@ -2133,6 +2313,8 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option ret = got_picture; } } + if(!pkt.data && !got_picture) + return -1; return ret; } @@ -2226,6 +2408,13 @@ static int tb_unreliable(AVCodecContext *c){ return 0; } +#if FF_API_FORMAT_PARAMETERS +int av_find_stream_info(AVFormatContext *ic) +{ + return avformat_find_stream_info(ic, NULL); +} +#endif + int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) { int i, count, ret, read_size, j; @@ -2233,12 +2422,23 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) AVPacket pkt1, *pkt; int64_t old_offset = avio_tell(ic->pb); int orig_nb_streams = ic->nb_streams; // new streams might appear, no options for those + int flush_codecs = 1; + + if(ic->pb) + av_log(ic, AV_LOG_DEBUG, "File position before avformat_find_stream_info() is %"PRId64"\n", avio_tell(ic->pb)); for(i=0;i<ic->nb_streams;i++) { 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 stuff if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE)) { st->parser = av_parser_init(st->codec->codec_id); @@ -2316,6 +2516,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) /* 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; } } @@ -2323,6 +2524,12 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (read_size >= ic->probesize) { ret = count; av_log(ic, AV_LOG_DEBUG, "Probe buffer size limit %d reached\n", ic->probesize); + for (i = 0; i < ic->nb_streams; i++) + if (!ic->streams[i]->r_frame_rate.num && + ic->streams[i]->info->duration_count <= 1) + av_log(ic, AV_LOG_WARNING, + "Stream #%d: not enough frames to estimate rate; " + "consider increasing probesize\n", i); break; } @@ -2334,35 +2541,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (ret < 0) { /* EOF or error*/ - AVPacket empty_pkt = { 0 }; - int err = 0; - av_init_packet(&empty_pkt); - - ret = -1; /* we could not have all the codec parameters before EOF */ - 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(st, &empty_pkt, - (options && i < orig_nb_streams) ? - &options[i] : NULL); - } while (err > 0 && !has_codec_parameters(st)); - } - - if (err < 0) { - av_log(ic, AV_LOG_WARNING, - "decoding for stream %d failed\n", st->index); - } else if (!has_codec_parameters(st)) { - char buf[256]; - avcodec_string(buf, sizeof(buf), st->codec, 0); - av_log(ic, AV_LOG_WARNING, - "Could not find codec parameters (%s)\n", buf); - } else { - ret = 0; - } - } break; } @@ -2374,8 +2552,14 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) st = ic->streams[pkt->stream_index]; if (st->codec_info_nb_frames>1) { - if (av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) { - av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n"); + 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, (AVRational){st->avg_frame_rate.den, st->avg_frame_rate.num}, AV_TIME_BASE_Q)); + + if (t >= ic->max_analyze_duration) { + av_log(ic, AV_LOG_WARNING, "max_analyze_duration %d reached at %"PRId64"\n", ic->max_analyze_duration, t); break; } st->info->codec_info_duration += pkt->duration; @@ -2384,18 +2568,20 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) int64_t last = st->info->last_dts; if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && pkt->dts > last){ + double dts= (is_relative(pkt->dts) ? pkt->dts - RELATIVE_TS_BASE : pkt->dts) * av_q2d(st->time_base); int64_t duration= pkt->dts - last; - double dur= duration * av_q2d(st->time_base); -// 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; i<FF_ARRAY_ELEMS(st->info->duration_error); i++) { +// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) +// av_log(NULL, AV_LOG_ERROR, "%f\n", dts); + for (i=1; i<FF_ARRAY_ELEMS(st->info->duration_error[0][0]); i++) { int framerate= get_std_framerate(i); - int ticks= lrintf(dur*framerate/(1001*12)); - double error = dur - (double)ticks*1001*12 / 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 @@ -2432,6 +2618,40 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) count++; } + if (flush_codecs) { + AVPacket empty_pkt = { 0 }; + int err = 0; + av_init_packet(&empty_pkt); + + ret = -1; /* we could not have all the codec parameters before EOF */ + 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(st, &empty_pkt, + (options && i < orig_nb_streams) ? + &options[i] : NULL); + } while (err > 0 && !has_codec_parameters(st)); + + if (err < 0) { + av_log(ic, AV_LOG_INFO, + "decoding for stream %d failed\n", st->index); + } + } + + if (!has_codec_parameters(st)){ + char buf[256]; + avcodec_string(buf, sizeof(buf), st->codec, 0); + av_log(ic, AV_LOG_WARNING, + "Could not find codec parameters (%s)\n", buf); + } else { + ret = 0; + } + } + } + // close codecs which were opened in try_decode_frame() for(i=0;i<ic->nb_streams;i++) { st = ic->streams[i]; @@ -2440,6 +2660,12 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) 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 == 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(ff_find_pix_fmt(ff_raw_pix_fmt_tags, tag) == st->codec->pix_fmt) + st->codec->codec_tag= tag; + } + if (st->codec_info_nb_frames>2 && !st->avg_frame_rate.num && st->info->codec_info_duration) av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, (st->codec_info_nb_frames-2)*(int64_t)st->time_base.den, @@ -2447,29 +2673,50 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) // the check for tb_unreliable() is not completely correct, since this is not about handling // a unreliable/inexact time base, but a time base that is finer than necessary, as e.g. // ipmovie.c produces. - if (tb_unreliable(st->codec) && st->info->duration_count > 15 && st->info->duration_gcd > 1 && !st->r_frame_rate.num) + if (tb_unreliable(st->codec) && st->info->duration_count > 15 && st->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num) av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->info->duration_gcd, INT_MAX); if (st->info->duration_count && !st->r_frame_rate.num && tb_unreliable(st->codec) /*&& //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; j<FF_ARRAY_ELEMS(st->info->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; j<FF_ARRAY_ELEMS(st->info->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; + if(!st->info->codec_info_duration && 1.0 < (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. if (num && (!st->r_frame_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(st->r_frame_rate))) av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 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); @@ -2499,17 +2746,25 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) ic->streams[i]->codec->thread_count = 0; av_freep(&ic->streams[i]->info); } + if(ic->pb) + av_log(ic, AV_LOG_DEBUG, "File position after avformat_find_stream_info() is %"PRId64"\n", avio_tell(ic->pb)); 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; } @@ -2526,7 +2781,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; @@ -2604,13 +2859,13 @@ void avformat_free_context(AVFormatContext *s) if (st->attached_pic.data) av_free_packet(&st->attached_pic); 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); @@ -2621,7 +2876,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); @@ -2639,10 +2894,10 @@ void av_close_input_file(AVFormatContext *s) void avformat_close_input(AVFormatContext **ps) { AVFormatContext *s = *ps; - AVIOContext *pb = (s->iformat->flags & AVFMT_NOFILE) || (s->flags & AVFMT_FLAG_CUSTOM_IO) ? + AVIOContext *pb = (s->iformat && (s->iformat->flags & AVFMT_NOFILE)) || (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb; flush_packet_queue(s); - if (s->iformat->read_close) + if (s->iformat && (s->iformat->read_close)) s->iformat->read_close(s); avformat_free_context(s); *ps = NULL; @@ -2650,6 +2905,16 @@ void avformat_close_input(AVFormatContext **ps) avio_close(pb); } +#if FF_API_NEW_STREAM +AVStream *av_new_stream(AVFormatContext *s, int id) +{ + AVStream *st = avformat_new_stream(s, NULL); + if (st) + st->id = id; + return st; +} +#endif + AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c) { AVStream *st; @@ -2670,6 +2935,7 @@ AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c) av_free(st); return NULL; } + st->info->last_dts = AV_NOPTS_VALUE; st->codec = avcodec_alloc_context3(c); if (s->iformat) { @@ -2683,7 +2949,7 @@ AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c) but durations get some timestamps, formats with some unknown timestamps have their first few packets buffered and the timestamps corrected before they are returned to the user */ - st->cur_dts = 0; + st->cur_dts = s->iformat ? RELATIVE_TS_BASE : 0; st->first_dts = AV_NOPTS_VALUE; st->probe_packets = MAX_PROBE_PACKETS; @@ -2750,6 +3016,69 @@ AVChapter *avpriv_new_chapter(AVFormatContext *s, int id, AVRational time_base, /************************************************************/ /* output media file */ +int avformat_alloc_output_context2(AVFormatContext **avctx, AVOutputFormat *oformat, + const char *format, const char *filename) +{ + AVFormatContext *s = avformat_alloc_context(); + int ret = 0; + + *avctx = NULL; + if (!s) + goto nomem; + + if (!oformat) { + if (format) { + oformat = av_guess_format(format, NULL, NULL); + if (!oformat) { + av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format); + ret = AVERROR(EINVAL); + goto error; + } + } else { + oformat = av_guess_format(NULL, filename, NULL); + if (!oformat) { + ret = AVERROR(EINVAL); + av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n", + filename); + goto error; + } + } + } + + s->oformat = oformat; + if (s->oformat->priv_data_size > 0) { + s->priv_data = av_mallocz(s->oformat->priv_data_size); + if (!s->priv_data) + goto nomem; + if (s->oformat->priv_class) { + *(const AVClass**)s->priv_data= s->oformat->priv_class; + av_opt_set_defaults(s->priv_data); + } + } else + s->priv_data = NULL; + + if (filename) + av_strlcpy(s->filename, filename, sizeof(s->filename)); + *avctx = s; + return 0; +nomem: + av_log(s, AV_LOG_ERROR, "Out of memory\n"); + ret = AVERROR(ENOMEM); +error: + avformat_free_context(s); + return ret; +} + +#if FF_API_ALLOC_OUTPUT_CONTEXT +AVFormatContext *avformat_alloc_output_context(const char *format, + AVOutputFormat *oformat, const char *filename) +{ + AVFormatContext *avctx; + int ret = avformat_alloc_output_context2(&avctx, oformat, format, filename); + return ret < 0 ? NULL : avctx; +} +#endif + static int validate_codec_tag(AVFormatContext *s, AVStream *st) { const AVCodecTag *avctag; @@ -2793,6 +3122,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)) { @@ -2826,7 +3158,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 muxer " "(%d/%d) and encoder layer (%d/%d)\n", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, @@ -2929,9 +3263,6 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt){ av_dlog(s, "compute_pkt_fields2: pts:%"PRId64" dts:%"PRId64" cur_dts:%"PRId64" b:%d size:%d st:%d\n", pkt->pts, pkt->dts, st->cur_dts, delay, pkt->size, pkt->stream_index); -/* if(pkt->pts == AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE) - return AVERROR(EINVAL);*/ - /* duration field */ if (pkt->duration == 0) { compute_frame_duration(&num, &den, st, NULL, pkt); @@ -2945,6 +3276,11 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt){ //XXX/FIXME this is a temporary hack until all encoders output pts if((pkt->pts == 0 || pkt->pts == AV_NOPTS_VALUE) && pkt->dts == AV_NOPTS_VALUE && !delay){ + static int warned; + if (!warned) { + av_log(s, AV_LOG_WARNING, "Encoder did not produce proper pts, making some up.\n"); + warned = 1; + } pkt->dts= // pkt->pts= st->cur_dts; pkt->pts= st->pts.val; @@ -2961,14 +3297,14 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt){ pkt->dts= st->pts_buffer[0]; } - if(st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && st->cur_dts >= pkt->dts){ + if(st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && ((!(s->oformat->flags & AVFMT_TS_NONSTRICT) && st->cur_dts >= pkt->dts) || st->cur_dts > pkt->dts)){ av_log(s, AV_LOG_ERROR, "Application provided invalid, non monotonically increasing dts to muxer in stream %d: %"PRId64" >= %"PRId64"\n", st->index, st->cur_dts, pkt->dts); return AVERROR(EINVAL); } if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts){ - av_log(s, AV_LOG_ERROR, "pts < dts in stream %d\n", st->index); + av_log(s, AV_LOG_ERROR, "pts (%"PRId64") < dts (%"PRId64") in stream %d\n", pkt->pts, pkt->dts, st->index); return AVERROR(EINVAL); } @@ -3019,27 +3355,51 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) return ret; } -void ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, +#define CHUNK_START 0x1000 + +int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, int (*compare)(AVFormatContext *, AVPacket *, AVPacket *)) { AVPacketList **next_point, *this_pktl; + AVStream *st= s->streams[pkt->stream_index]; + int chunked= s->max_chunk_size || s->max_chunk_duration; this_pktl = av_mallocz(sizeof(AVPacketList)); + if (!this_pktl) + return AVERROR(ENOMEM); this_pktl->pkt= *pkt; pkt->destruct= NULL; // do not free original but only the copy av_dup_packet(&this_pktl->pkt); // duplicate the packet if it uses non-alloced memory if(s->streams[pkt->stream_index]->last_in_packet_buffer){ - next_point = &(s->streams[pkt->stream_index]->last_in_packet_buffer->next); - }else + next_point = &(st->last_in_packet_buffer->next); + }else{ next_point = &s->packet_buffer; + } if(*next_point){ + if(chunked){ + uint64_t max= av_rescale_q(s->max_chunk_duration, AV_TIME_BASE_Q, st->time_base); + if( st->interleaver_chunk_size + pkt->size <= s->max_chunk_size-1U + && st->interleaver_chunk_duration + pkt->duration <= max-1U){ + st->interleaver_chunk_size += pkt->size; + st->interleaver_chunk_duration += pkt->duration; + goto next_non_null; + }else{ + st->interleaver_chunk_size = + st->interleaver_chunk_duration = 0; + this_pktl->pkt.flags |= CHUNK_START; + } + } + if(compare(s, &s->packet_buffer_end->pkt, pkt)){ - while(!compare(s, &(*next_point)->pkt, pkt)){ + while( *next_point + && ((chunked && !((*next_point)->pkt.flags&CHUNK_START)) + || !compare(s, &(*next_point)->pkt, pkt))){ next_point= &(*next_point)->next; } - goto next_non_null; + if(*next_point) + goto next_non_null; }else{ next_point = &(s->packet_buffer_end->next); } @@ -3053,6 +3413,7 @@ next_non_null: s->streams[pkt->stream_index]->last_in_packet_buffer= *next_point= this_pktl; + return 0; } static int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacket *pkt) @@ -3061,6 +3422,16 @@ static int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacke AVStream *st2= s->streams[ next->stream_index]; int comp = av_compare_ts(next->dts, st2->time_base, pkt->dts, st->time_base); + if(s->audio_preload && ((st->codec->codec_type == AVMEDIA_TYPE_AUDIO) != (st2->codec->codec_type == AVMEDIA_TYPE_AUDIO))){ + int64_t ts = av_rescale_q(pkt ->dts, st ->time_base, AV_TIME_BASE_Q) - s->audio_preload*(st ->codec->codec_type == AVMEDIA_TYPE_AUDIO); + int64_t ts2= av_rescale_q(next->dts, st2->time_base, AV_TIME_BASE_Q) - s->audio_preload*(st2->codec->codec_type == AVMEDIA_TYPE_AUDIO); + if(ts == ts2){ + ts= ( pkt ->dts* st->time_base.num*AV_TIME_BASE - s->audio_preload*(int64_t)(st ->codec->codec_type == AVMEDIA_TYPE_AUDIO)* st->time_base.den)*st2->time_base.den + -( next->dts*st2->time_base.num*AV_TIME_BASE - s->audio_preload*(int64_t)(st2->codec->codec_type == AVMEDIA_TYPE_AUDIO)*st2->time_base.den)* st->time_base.den; + ts2=0; + } + comp= (ts>ts2) - (ts<ts2); + } if (comp == 0) return pkt->stream_index < next->stream_index; @@ -3071,17 +3442,46 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) { AVPacketList *pktl; - int stream_count=0; - int i; + int stream_count=0, noninterleaved_count=0; + int64_t delta_dts_max = 0; + int i, ret; if(pkt){ - ff_interleave_add_packet(s, pkt, ff_interleave_compare_dts); + ret = ff_interleave_add_packet(s, pkt, ff_interleave_compare_dts); + if (ret < 0) + return ret; } - 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; @@ -3163,6 +3563,8 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){ if(ret<0) return ret; + if(s->pb && s->pb->error) + return s->pb->error; } } @@ -3186,11 +3588,17 @@ int av_write_trailer(AVFormatContext *s) if(ret<0) goto fail; + if(s->pb && s->pb->error) + goto fail; } if(s->oformat->write_trailer) ret = s->oformat->write_trailer(s); fail: + if (s->pb) + avio_flush(s->pb); + if(ret == 0) + ret = s->pb ? s->pb->error : 0; for(i=0;i<s->nb_streams;i++) { av_freep(&s->streams[i]->priv_data); av_freep(&s->streams[i]->index_entries); @@ -3201,6 +3609,15 @@ fail: return ret; } +int av_get_output_timestamp(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall) +{ + if (!s->oformat || !s->oformat->get_output_timestamp) + return AVERROR(ENOSYS); + s->oformat->get_output_timestamp(s, stream, dts, wall); + return 0; +} + void ff_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx) { int i, j; @@ -3243,8 +3660,21 @@ static void dump_metadata(void *ctx, AVDictionary *m, const char *indent) av_log(ctx, AV_LOG_INFO, "%sMetadata:\n", indent); while((tag=av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) { - if(strcmp("language", tag->key)) - av_log(ctx, AV_LOG_INFO, "%s %-16s: %s\n", indent, tag->key, tag->value); + if(strcmp("language", tag->key)){ + const char *p = tag->value; + av_log(ctx, AV_LOG_INFO, "%s %-16s: ", indent, tag->key); + while(*p) { + char tmp[256]; + size_t len = strcspn(p, "\xd\xa"); + av_strlcpy(tmp, p, FFMIN(sizeof(tmp), len+1)); + av_log(ctx, AV_LOG_INFO, "%s", tmp); + p += len; + if (*p == 0xd) av_log(ctx, AV_LOG_INFO, " "); + if (*p == 0xa) av_log(ctx, AV_LOG_INFO, "\n%s %-16s: ", indent, ""); + if (*p) p++; + } + av_log(ctx, AV_LOG_INFO, "\n"); + } } } } @@ -3258,7 +3688,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) @@ -3274,7 +3704,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); } @@ -3523,11 +3953,27 @@ static void pkt_dump_internal(void *avcl, FILE *f, int level, AVPacket *pkt, int av_hex_dump(f, pkt->data, pkt->size); } +#if FF_API_PKT_DUMP +void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload) +{ + AVRational tb = { 1, AV_TIME_BASE }; + pkt_dump_internal(NULL, f, 0, pkt, dump_payload, tb); +} +#endif + void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st) { pkt_dump_internal(NULL, f, 0, pkt, dump_payload, st->time_base); } +#if FF_API_PKT_DUMP +void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, int dump_payload) +{ + AVRational tb = { 1, AV_TIME_BASE }; + pkt_dump_internal(avcl, NULL, level, pkt, dump_payload, tb); +} +#endif + void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload, AVStream *st) { @@ -3644,6 +4090,14 @@ int ff_hex_to_data(uint8_t *data, const char *p) return len; } +#if FF_API_SET_PTS_INFO +void av_set_pts_info(AVStream *s, int pts_wrap_bits, + unsigned int pts_num, unsigned int pts_den) +{ + avpriv_set_pts_info(s, pts_wrap_bits, pts_num, pts_den); +} +#endif + void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den) { |