X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=d1647d2a06fff07380add546d9e94534b39b1b09;hb=2e11268ea9812cec9ca334c8c0e825dcfb64bef9;hp=5d164c5d5a26948cccdabd32c64c5d01fb9ece0f;hpb=ccd425e7993ef0e76da7bf10c566d33f7acc7c6d;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index 5d164c5d5a2..d1647d2a06f 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "avformat.h" -#include "opt.h" -#include "avstring.h" +#include "libavcodec/opt.h" +#include "libavutil/avstring.h" #include "riff.h" #include #include @@ -293,6 +293,24 @@ AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened){ return av_probe_input_format2(pd, is_opened, &score); } +static int set_codec_from_probe_data(AVStream *st, AVProbeData *pd, int score) +{ + AVInputFormat *fmt; + fmt = av_probe_input_format2(pd, 1, &score); + + if (fmt) { + if (!strcmp(fmt->name, "mp3")) + st->codec->codec_id = CODEC_ID_MP3; + else if (!strcmp(fmt->name, "ac3")) + st->codec->codec_id = CODEC_ID_AC3; + else if (!strcmp(fmt->name, "mpegvideo")) + st->codec->codec_id = CODEC_ID_MPEG2VIDEO; + else if (!strcmp(fmt->name, "h264")) + st->codec->codec_id = CODEC_ID_H264; + } + return !!fmt; +} + /************************************************************/ /* input media file */ @@ -326,6 +344,8 @@ static const AVOption options[]={ {"cryptokey", "decryption key", OFFSET(key), FF_OPT_TYPE_BINARY, 0, 0, 0, D}, {"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), FF_OPT_TYPE_INT, 1<<20, 0, INT_MAX, D}, {"rtbufsize", "max memory used for buffering real-time frames", OFFSET(max_picture_buffer), FF_OPT_TYPE_INT, 3041280, 0, INT_MAX, D}, /* defaults to 1s of 15fps 352x288 YUYV422 video */ +{"fdebug", "print specific debug info", OFFSET(debug), FF_OPT_TYPE_FLAGS, DEFAULT, 0, INT_MAX, E|D, "fdebug"}, +{"ts", NULL, 0, FF_OPT_TYPE_CONST, FF_FDEBUG_TS, INT_MIN, INT_MAX, E|D, "fdebug"}, {NULL}, }; @@ -392,9 +412,11 @@ int av_open_input_stream(AVFormatContext **ic_ptr, ic->priv_data = NULL; } - err = ic->iformat->read_header(ic, ap); - if (err < 0) - goto fail; + if (ic->iformat->read_header) { + err = ic->iformat->read_header(ic, ap); + if (err < 0) + goto fail; + } if (pb && !ic->data_offset) ic->data_offset = url_ftell(ic->pb); @@ -403,7 +425,16 @@ int av_open_input_stream(AVFormatContext **ic_ptr, return 0; fail: if (ic) { + int i; av_freep(&ic->priv_data); + for(i=0;inb_streams;i++) { + AVStream *st = ic->streams[i]; + if (st) { + av_free(st->priv_data); + av_free(st->codec->extradata); + } + av_free(st); + } } av_free(ic); *ic_ptr = NULL; @@ -493,29 +524,79 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, /*******************************************************/ +static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt){ + AVPacketList *pktl; + AVPacketList **plast_pktl= packet_buffer; + + while(*plast_pktl) plast_pktl= &(*plast_pktl)->next; //FIXME maybe maintain pointer to the last? + + pktl = av_mallocz(sizeof(AVPacketList)); + if (!pktl) + return NULL; + + /* add the packet in the buffered packet list */ + *plast_pktl = pktl; + pktl->pkt= *pkt; + return &pktl->pkt; +} + int av_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret; AVStream *st; - av_init_packet(pkt); - ret= s->iformat->read_packet(s, pkt); - if (ret < 0) - return ret; - st= s->streams[pkt->stream_index]; - switch(st->codec->codec_type){ - case CODEC_TYPE_VIDEO: - if(s->video_codec_id) st->codec->codec_id= s->video_codec_id; - break; - case CODEC_TYPE_AUDIO: - if(s->audio_codec_id) st->codec->codec_id= s->audio_codec_id; - break; - case CODEC_TYPE_SUBTITLE: - if(s->subtitle_codec_id)st->codec->codec_id= s->subtitle_codec_id; - break; - } + for(;;){ + AVPacketList *pktl = s->raw_packet_buffer; - return ret; + if (pktl) { + *pkt = pktl->pkt; + if(s->streams[pkt->stream_index]->codec->codec_id != CODEC_ID_PROBE){ + s->raw_packet_buffer = pktl->next; + av_free(pktl); + return 0; + } + } + + av_init_packet(pkt); + ret= s->iformat->read_packet(s, pkt); + if (ret < 0) + return ret; + st= s->streams[pkt->stream_index]; + + switch(st->codec->codec_type){ + case CODEC_TYPE_VIDEO: + if(s->video_codec_id) st->codec->codec_id= s->video_codec_id; + break; + case CODEC_TYPE_AUDIO: + if(s->audio_codec_id) st->codec->codec_id= s->audio_codec_id; + break; + case CODEC_TYPE_SUBTITLE: + if(s->subtitle_codec_id)st->codec->codec_id= s->subtitle_codec_id; + break; + } + + if(!pktl && st->codec->codec_id!=CODEC_ID_PROBE) + return ret; + + add_to_pktbuf(&s->raw_packet_buffer, pkt); + + if(st->codec->codec_id == CODEC_ID_PROBE){ + AVProbeData *pd = &st->probe_data; + + pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE); + memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size); + pd->buf_size += pkt->size; + memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE); + + if(av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)){ + set_codec_from_probe_data(st, pd, 1); + if(st->codec->codec_id != CODEC_ID_PROBE){ + pd->buf_size=0; + av_freep(&pd->buf); + } + } + } + } } /**********************************************************/ @@ -527,6 +608,9 @@ static int get_audio_frame_size(AVCodecContext *enc, int size) { int frame_size; + if(enc->codec_id == CODEC_ID_VORBIS) + return -1; + if (enc->frame_size <= 1) { int bits_per_sample = av_get_bits_per_sample(enc->codec_id); @@ -611,7 +695,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, AVStream *st= s->streams[stream_index]; AVPacketList *pktl= s->packet_buffer; - if(st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE) + if(st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE || st->cur_dts == AV_NOPTS_VALUE) return; st->first_dts= dts - st->cur_dts; @@ -637,20 +721,37 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, static void update_initial_durations(AVFormatContext *s, AVStream *st, AVPacket *pkt) { AVPacketList *pktl= s->packet_buffer; + int64_t cur_dts= 0; - assert(pkt->duration && !st->cur_dts); + if(st->first_dts != AV_NOPTS_VALUE){ + cur_dts= st->first_dts; + for(; pktl; pktl= pktl->next){ + if(pktl->pkt.stream_index == pkt->stream_index){ + if(pktl->pkt.pts != pktl->pkt.dts || pktl->pkt.dts != AV_NOPTS_VALUE || pktl->pkt.duration) + break; + cur_dts -= pkt->duration; + } + } + pktl= s->packet_buffer; + st->first_dts = cur_dts; + }else if(st->cur_dts) + return; for(; pktl; pktl= pktl->next){ if(pktl->pkt.stream_index != pkt->stream_index) continue; if(pktl->pkt.pts == pktl->pkt.dts && pktl->pkt.dts == AV_NOPTS_VALUE && !pktl->pkt.duration){ - pktl->pkt.pts= pktl->pkt.dts= st->cur_dts; - st->cur_dts += pkt->duration; + pktl->pkt.dts= cur_dts; + if(!st->codec->has_b_frames) + pktl->pkt.pts= cur_dts; + cur_dts += pkt->duration; pktl->pkt.duration= pkt->duration; }else break; } + if(st->first_dts == AV_NOPTS_VALUE) + st->cur_dts= cur_dts; } static void compute_pkt_fields(AVFormatContext *s, AVStream *st, @@ -669,7 +770,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, if (den && num) { pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num); - if(st->cur_dts == 0 && pkt->duration != 0) + if(pkt->duration != 0 && s->packet_buffer) update_initial_durations(s, st, pkt); } } @@ -697,13 +798,9 @@ 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; - if(st->cur_dts == AV_NOPTS_VALUE){ - st->cur_dts = 0; //FIXME maybe set it to 0 during init - } - // 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); /* interpolate PTS and DTS if they are not present */ - if(delay <=1){ + if(delay==0 || (delay==1 && pc)){ if (presentation_delayed) { /* DTS = decompression timestamp */ /* PTS = presentation timestamp */ @@ -717,7 +814,8 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, of the frame we are displaying, i.e. the last I- or P-frame */ if (st->last_IP_duration == 0) st->last_IP_duration = pkt->duration; - st->cur_dts = pkt->dts + st->last_IP_duration; + if(pkt->dts != AV_NOPTS_VALUE) + st->cur_dts = pkt->dts + st->last_IP_duration; st->last_IP_duration = pkt->duration; st->last_IP_pts= pkt->pts; /* cannot compute PTS if not present (we can compute it only @@ -739,7 +837,8 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, if(pkt->pts == AV_NOPTS_VALUE) pkt->pts = st->cur_dts; pkt->dts = pkt->pts; - st->cur_dts = pkt->pts + pkt->duration; + if(pkt->pts != AV_NOPTS_VALUE) + st->cur_dts = pkt->pts + pkt->duration; } } @@ -850,13 +949,26 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) return ret; } - st = s->streams[s->cur_pkt.stream_index]; - if(st->codec->debug & FF_DEBUG_PTS) - av_log(s, AV_LOG_DEBUG, "av_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d\n", + if(s->cur_pkt.pts != AV_NOPTS_VALUE && + s->cur_pkt.dts != AV_NOPTS_VALUE && + s->cur_pkt.pts < s->cur_pkt.dts){ + av_log(s, AV_LOG_WARNING, "Invalid timestamps stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d\n", s->cur_pkt.stream_index, s->cur_pkt.pts, s->cur_pkt.dts, s->cur_pkt.size); +// av_free_packet(&s->cur_pkt); +// return -1; + } + + st = s->streams[s->cur_pkt.stream_index]; + if(s->debug & FF_FDEBUG_TS) + av_log(s, AV_LOG_DEBUG, "av_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, flags=%d\n", + s->cur_pkt.stream_index, + s->cur_pkt.pts, + s->cur_pkt.dts, + s->cur_pkt.size, + s->cur_pkt.flags); s->cur_st = st; s->cur_ptr = s->cur_pkt.data; @@ -870,38 +982,23 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; } if(st->parser && (s->iformat->flags & AVFMT_GENERIC_INDEX)){ - st->parser->last_frame_offset= + st->parser->next_frame_offset= st->parser->cur_offset= s->cur_pkt.pos; } } } } - if(st->codec->debug & FF_DEBUG_PTS) - av_log(s, AV_LOG_DEBUG, "av_read_frame_internal stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d\n", + if(s->debug & FF_FDEBUG_TS) + av_log(s, AV_LOG_DEBUG, "av_read_frame_internal stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, flags=%d\n", pkt->stream_index, pkt->pts, pkt->dts, - pkt->size); + pkt->size, + pkt->flags); return 0; } -static AVPacket *add_to_pktbuf(AVFormatContext *s, AVPacket *pkt){ - AVPacketList *pktl= s->packet_buffer; - AVPacketList **plast_pktl= &s->packet_buffer; - - while(*plast_pktl) plast_pktl= &(*plast_pktl)->next; //FIXME maybe maintain pointer to the last? - - pktl = av_mallocz(sizeof(AVPacketList)); - if (!pktl) - return NULL; - - /* add the packet in the buffered packet list */ - *plast_pktl = pktl; - pktl->pkt= *pkt; - return &pktl->pkt; -} - int av_read_frame(AVFormatContext *s, AVPacket *pkt) { AVPacketList *pktl; @@ -946,7 +1043,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) return ret; } - if(av_dup_packet(add_to_pktbuf(s, pkt)) < 0) + if(av_dup_packet(add_to_pktbuf(&s->packet_buffer, pkt)) < 0) return AVERROR(ENOMEM); }else{ assert(!s->packet_buffer); @@ -975,6 +1072,7 @@ static void flush_packet_queue(AVFormatContext *s) int av_find_default_stream_index(AVFormatContext *s) { + int first_audio_index = -1; int i; AVStream *st; @@ -985,8 +1083,10 @@ int av_find_default_stream_index(AVFormatContext *s) if (st->codec->codec_type == CODEC_TYPE_VIDEO) { return i; } + if (first_audio_index < 0 && st->codec->codec_type == CODEC_TYPE_AUDIO) + first_audio_index = i; } - return 0; + return first_audio_index >= 0 ? first_audio_index : 0; } /** @@ -1330,7 +1430,7 @@ static int av_seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, static int av_seek_frame_generic(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { - int index; + int index, ret; AVStream *st; AVIndexEntry *ie; @@ -1342,13 +1442,16 @@ static int av_seek_frame_generic(AVFormatContext *s, int i; AVPacket pkt; - if(st->index_entries && st->nb_index_entries){ + if(st->nb_index_entries){ + assert(st->index_entries); ie= &st->index_entries[st->nb_index_entries-1]; - url_fseek(s->pb, ie->pos, SEEK_SET); + if ((ret = url_fseek(s->pb, ie->pos, SEEK_SET)) < 0) + return ret; av_update_cur_dts(s, st, ie->timestamp); - }else - url_fseek(s->pb, 0, SEEK_SET); - + }else{ + if ((ret = url_fseek(s->pb, 0, SEEK_SET)) < 0) + return ret; + } for(i=0;; i++) { int ret = av_read_frame(s, &pkt); if(ret<0) @@ -1370,8 +1473,8 @@ static int av_seek_frame_generic(AVFormatContext *s, return 0; } ie = &st->index_entries[index]; - url_fseek(s->pb, ie->pos, SEEK_SET); - + if ((ret = url_fseek(s->pb, ie->pos, SEEK_SET)) < 0) + return ret; av_update_cur_dts(s, st, ie->timestamp); return 0; @@ -1681,7 +1784,11 @@ static int has_codec_parameters(AVCodecContext *enc) int val; switch(enc->codec_type) { case CODEC_TYPE_AUDIO: - val = enc->sample_rate; + val = enc->sample_rate && enc->channels; + if(!enc->frame_size && + (enc->codec_id == CODEC_ID_VORBIS || + enc->codec_id == CODEC_ID_AAC)) + return 0; break; case CODEC_TYPE_VIDEO: val = enc->width && enc->pix_fmt != PIX_FMT_NONE; @@ -1732,20 +1839,6 @@ static int try_decode_frame(AVStream *st, const uint8_t *data, int size) return ret; } -static int set_codec_from_probe_data(AVStream *st, AVProbeData *pd, int score) -{ - AVInputFormat *fmt; - fmt = av_probe_input_format2(pd, 1, &score); - - if (fmt) { - if (strncmp(fmt->name, "mp3", 3) == 0) - st->codec->codec_id = CODEC_ID_MP3; - else if (strncmp(fmt->name, "ac3", 3) == 0) - st->codec->codec_id = CODEC_ID_AC3; - } - return !!fmt; -} - unsigned int codec_get_tag(const AVCodecTag *tags, int id) { while (tags->id != CODEC_ID_NONE) { @@ -1793,6 +1886,26 @@ enum CodecID av_codec_get_id(const AVCodecTag *tags[4], unsigned int tag) return CODEC_ID_NONE; } +static void compute_chapters_end(AVFormatContext *s) +{ + unsigned int i; + + for (i=0; i+1nb_chapters; i++) + if (s->chapters[i]->end == AV_NOPTS_VALUE) { + assert(s->chapters[i]->start <= s->chapters[i+1]->start); + assert(!av_cmp_q(s->chapters[i]->time_base, s->chapters[i+1]->time_base)); + s->chapters[i]->end = s->chapters[i+1]->start; + } + + if (s->nb_chapters && s->chapters[i]->end == AV_NOPTS_VALUE) { + assert(s->start_time != AV_NOPTS_VALUE); + assert(s->duration > 0); + s->chapters[i]->end = av_rescale_q(s->start_time + s->duration, + AV_TIME_BASE_Q, + s->chapters[i]->time_base); + } +} + /* absolute maximum size we read until we abort */ #define MAX_READ_SIZE 5000000 @@ -1831,8 +1944,6 @@ int av_find_stream_info(AVFormatContext *ic) offset_t old_offset = url_ftell(ic->pb); int64_t codec_info_duration[MAX_STREAMS]={0}; int codec_info_nb_frames[MAX_STREAMS]={0}; - AVProbeData probe_data[MAX_STREAMS]; - int codec_identified[MAX_STREAMS]={0}; duration_error = av_mallocz(MAX_STREAMS * sizeof(*duration_error)); if (!duration_error) return AVERROR(ENOMEM); @@ -1858,7 +1969,6 @@ int av_find_stream_info(AVFormatContext *ic) last_dts[i]= AV_NOPTS_VALUE; } - memset(probe_data, 0, sizeof(probe_data)); count = 0; read_size = 0; for(;;) { @@ -1911,9 +2021,11 @@ int av_find_stream_info(AVFormatContext *ic) break; } - pkt= add_to_pktbuf(ic, &pkt1); - if(av_dup_packet(pkt) < 0) + pkt= add_to_pktbuf(&ic->packet_buffer, &pkt1); + if(av_dup_packet(pkt) < 0) { + av_free(duration_error); return AVERROR(ENOMEM); + } read_size += pkt->size; @@ -1945,14 +2057,6 @@ int av_find_stream_info(AVFormatContext *ic) } if(last == AV_NOPTS_VALUE || duration_count[index]<=1) last_dts[pkt->stream_index]= pkt->dts; - - if (st->codec->codec_id == CODEC_ID_NONE) { - AVProbeData *pd = &(probe_data[st->index]); - pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE); - memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size); - pd->buf_size += pkt->size; - memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE); - } } if(st->parser && st->parser->parser->split && !st->codec->extradata){ int i= st->parser->parser->split(st->codec, pkt->data, pkt->size); @@ -2032,12 +2136,6 @@ int av_find_stream_info(AVFormatContext *ic) } } }else if(st->codec->codec_type == CODEC_TYPE_AUDIO) { - if (st->codec->codec_id == CODEC_ID_NONE && probe_data[st->index].buf_size > 0) { - codec_identified[st->index] = set_codec_from_probe_data(st, &(probe_data[st->index]), 1); - if (codec_identified[st->index]) { - st->need_parsing = AVSTREAM_PARSE_FULL; - } - } if(!st->codec->bits_per_sample) st->codec->bits_per_sample= av_get_bits_per_sample(st->codec->codec_id); } @@ -2045,23 +2143,7 @@ int av_find_stream_info(AVFormatContext *ic) av_estimate_timings(ic, old_offset); - for(i=0;inb_streams;i++) { - st = ic->streams[i]; - if (codec_identified[st->index]) - break; - } - //FIXME this is a mess - if(i!=ic->nb_streams){ - av_read_frame_flush(ic); - for(i=0;inb_streams;i++) { - st = ic->streams[i]; - if (codec_identified[st->index]) { - av_seek_frame(ic, st->index, 0.0, 0); - } - st->cur_dts= st->first_dts; - } - url_fseek(ic->pb, ic->data_offset, SEEK_SET); - } + compute_chapters_end(ic); #if 0 /* correct DTS for B-frame streams with no timestamps */ @@ -2089,9 +2171,6 @@ int av_find_stream_info(AVFormatContext *ic) #endif av_free(duration_error); - for(i=0;icodec->extradata); av_free(st->codec); av_free(st->filename); + av_free(st->priv_data); av_free(st); } for(i=s->nb_programs-1; i>=0; i--) { @@ -2148,6 +2228,11 @@ void av_close_input_stream(AVFormatContext *s) av_freep(&s->programs); flush_packet_queue(s); av_freep(&s->priv_data); + while(s->nb_chapters--) { + av_free(s->chapters[s->nb_chapters]->title); + av_free(s->chapters[s->nb_chapters]); + } + av_freep(&s->chapters); av_free(s); } @@ -2180,7 +2265,11 @@ AVStream *av_new_stream(AVFormatContext *s, int id) st->id = id; st->start_time = AV_NOPTS_VALUE; st->duration = AV_NOPTS_VALUE; - st->cur_dts = AV_NOPTS_VALUE; + /* we set the current DTS to 0 so that formats without any timestamps + 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->first_dts = AV_NOPTS_VALUE; /* default pts setting is MPEG-like */ @@ -2229,6 +2318,30 @@ void av_set_program_name(AVProgram *program, char *provider_name, char *name) } } +AVChapter *ff_new_chapter(AVFormatContext *s, int id, AVRational time_base, int64_t start, int64_t end, const char *title) +{ + AVChapter *chapter = NULL; + int i; + + for(i=0; inb_chapters; i++) + if(s->chapters[i]->id == id) + chapter = s->chapters[i]; + + if(!chapter){ + chapter= av_mallocz(sizeof(AVChapter)); + if(!chapter) + return NULL; + dynarray_add(&s->chapters, &s->nb_chapters, chapter); + } + av_free(chapter->title); + chapter->title = av_strdup(title); + chapter->id = id; + chapter->time_base= time_base; + chapter->start = start; + chapter->end = end; + + return chapter; +} /************************************************************/ /* output media file */ @@ -2346,6 +2459,9 @@ static int compute_pkt_fields2(AVStream *st, AVPacket *pkt){ } } + if(pkt->pts == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && delay==0) + pkt->pts= pkt->dts; + //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){ pkt->dts= @@ -2365,11 +2481,11 @@ static int compute_pkt_fields2(AVStream *st, AVPacket *pkt){ } if(st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && st->cur_dts >= pkt->dts){ - av_log(NULL, AV_LOG_ERROR, "error, non monotone timestamps %"PRId64" >= %"PRId64"\n", st->cur_dts, pkt->dts); + av_log(st->codec, AV_LOG_ERROR, "error, non monotone timestamps %"PRId64" >= %"PRId64"\n", st->cur_dts, pkt->dts); return -1; } if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts){ - av_log(NULL, AV_LOG_ERROR, "error, pts < dts\n"); + av_log(st->codec, AV_LOG_ERROR, "error, pts < dts\n"); return -1; } @@ -2412,9 +2528,8 @@ static void truncate_ts(AVStream *st, AVPacket *pkt){ int av_write_frame(AVFormatContext *s, AVPacket *pkt) { - int ret; + int ret = compute_pkt_fields2(s->streams[pkt->stream_index], pkt); - ret=compute_pkt_fields2(s->streams[pkt->stream_index], pkt); if(ret<0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) return ret; @@ -2466,7 +2581,7 @@ int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pk pktl= pktl->next; } - if(s->nb_streams == stream_count || (flush && stream_count)){ + if(stream_count && (s->nb_streams == stream_count || flush)){ pktl= s->packet_buffer; *out= pktl->pkt; @@ -3041,9 +3156,13 @@ void url_split(char *proto, int proto_size, void av_set_pts_info(AVStream *s, int pts_wrap_bits, int pts_num, int pts_den) { + unsigned int gcd= ff_gcd(pts_num, pts_den); s->pts_wrap_bits = pts_wrap_bits; - s->time_base.num = pts_num; - s->time_base.den = pts_den; + s->time_base.num = pts_num/gcd; + s->time_base.den = pts_den/gcd; + + if(gcd>1) + av_log(NULL, AV_LOG_DEBUG, "st:%d removing common factor %d from timebase\n", s->index, gcd); } /* fraction handling */