]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/utils.c
flvdec: follow packets backward until a valid last timestamp is found
[ffmpeg] / libavformat / utils.c
index 3630c6f93f3a1976cc0f3aa8b3a46e2c3d00aa43..3807954e21250b064582a54556ee074573283f97 100644 (file)
@@ -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"
@@ -36,6 +38,7 @@
 #include "libavutil/mathematics.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/time.h"
+#include "libavutil/timestamp.h"
 #include "riff.h"
 #include "audiointerleave.h"
 #include "url.h"
 
 /**
  * @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 */
@@ -217,7 +227,7 @@ AVOutputFormat *av_guess_format(const char *short_name, const char *filename,
     score_max = 0;
     while ((fmt = av_oformat_next(fmt))) {
         score = 0;
-        if (fmt->name && short_name && !av_strcasecmp(fmt->name, short_name))
+        if (fmt->name && short_name && match_format(short_name, fmt->name))
             score += 100;
         if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
             score += 10;
@@ -264,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;
@@ -279,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;
 }
@@ -305,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;
@@ -327,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;
@@ -374,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;
@@ -393,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)
@@ -427,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) {
@@ -452,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);
         }
     }
 
@@ -481,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;
     }
 
@@ -489,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)
@@ -535,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;
 
@@ -576,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;
 
@@ -587,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;
@@ -613,27 +674,39 @@ fail:
 
 static void probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
 {
-    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;
 
         if (pkt) {
-            pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE);
+            uint8_t *new_buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE);
+            if(!new_buf)
+                goto no_packet;
+            pd->buf = new_buf;
             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);
         } else {
+no_packet:
             st->probe_packets = 0;
         }
 
-        if (!st->probe_packets ||
-            av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)) {
-            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);
-                av_log(s, AV_LOG_DEBUG, "probed stream %d\n", st->index);
+                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);
             }
         }
     }
@@ -650,15 +723,7 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
         if (pktl) {
             *pkt = pktl->pkt;
             st = s->streams[pkt->stream_index];
-            if (st->codec->codec_id != CODEC_ID_PROBE || !st->probe_packets ||
-                s->raw_packet_buffer_remaining_size < pkt->size) {
-                AVProbeData *pd;
-                if (st->probe_packets) {
-                    probe_codec(s, st, NULL);
-                }
-                pd = &st->probe_data;
-                av_freep(&pd->buf);
-                pd->buf_size = 0;
+            if(st->request_probe <= 0){
                 s->raw_packet_buffer = pktl->next;
                 s->raw_packet_buffer_remaining_size += pkt->size;
                 av_free(pktl);
@@ -676,6 +741,7 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
                 if (st->probe_packets) {
                     probe_codec(s, st, NULL);
                 }
+                av_assert0(st->request_probe <= 0);
             }
             continue;
         }
@@ -689,6 +755,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){
@@ -703,8 +777,7 @@ 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);
@@ -724,6 +797,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.
  */
@@ -758,9 +842,9 @@ static void compute_frame_duration(int *pnum, int *pden, AVStream *st,
     *pden = 0;
     switch(st->codec->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
-        if (st->avg_frame_rate.num) {
-            *pnum = st->avg_frame_rate.den;
-            *pden = st->avg_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) {
             *pnum = st->time_base.num;
             *pden = st->time_base.den;
@@ -799,6 +883,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:
@@ -808,6 +893,7 @@ static int is_intra_only(AVCodecContext *enc){
         case CODEC_ID_DNXHD:
         case CODEC_ID_JPEG2000:
         case CODEC_ID_MDEC:
+        case CODEC_ID_UTVIDEO:
             return 1;
         default: break;
         }
@@ -815,27 +901,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;
@@ -847,38 +944,46 @@ 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;
+        if(pktl && pktl->pkt.dts != st->first_dts) {
+            av_log(s, AV_LOG_DEBUG, "first_dts %s not matching first dts %s in que\n", av_ts2str(st->first_dts), av_ts2str(pktl->pkt.dts));
+            return;
+        }
+        if(!pktl) {
+            av_log(s, AV_LOG_DEBUG, "first_dts %s but no packet with dts in ques\n", av_ts2str(st->first_dts));
+            return;
+        }
+        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;
 }
 
@@ -894,6 +999,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;
@@ -904,8 +1013,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;
     }
 
@@ -913,19 +1021,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 */
@@ -961,7 +1068,8 @@ 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:%s, dts:%s cur_dts:%s st:%d pc:%p duration:%d\n",
+//           presentation_delayed, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(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){
@@ -986,35 +1094,33 @@ 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)
+                   && st->codec->codec_type == AVMEDIA_TYPE_VIDEO
+                   && (!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:%s size:%d\n",
+//                           pkt->stream_index, old_diff, new_diff, pkt->duration, av_ts2str(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;
         }
     }
 
@@ -1031,7 +1137,8 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
             st->cur_dts = pkt->dts;
     }
 
-//    av_log(NULL, AV_LOG_ERROR, "OUTdelayed:%d/%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64"\n", presentation_delayed, delay, pkt->pts, pkt->dts, st->cur_dts);
+//    av_log(NULL, AV_LOG_ERROR, "OUTdelayed:%d/%d pts:%s, dts:%s cur_dts:%s\n",
+//           presentation_delayed, delay, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts));
 
     /* update flags */
     if(is_intra_only(st->codec))
@@ -1068,6 +1175,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)) {
@@ -1079,6 +1189,7 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
                                pkt->pts, pkt->dts, pkt->pos);
 
         pkt->pts = pkt->dts = AV_NOPTS_VALUE;
+        pkt->pos = -1;
         /* increment read pointer */
         data += len;
         size -= len;
@@ -1110,19 +1221,18 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
         out_pkt.dts = st->parser->dts;
         out_pkt.pos = st->parser->pos;
 
+        if(st->need_parsing == AVSTREAM_PARSE_FULL_RAW)
+            out_pkt.pos = st->parser->frame_offset;
+
         if (st->parser->key_frame == 1 ||
             (st->parser->key_frame == -1 &&
              st->parser->pict_type == AV_PICTURE_TYPE_I))
             out_pkt.flags |= AV_PKT_FLAG_KEY;
 
-        compute_pkt_fields(s, st, st->parser, &out_pkt);
+        if(st->parser->key_frame == -1 && st->parser->pict_type==AV_PICTURE_TYPE_NONE && (pkt->flags&AV_PKT_FLAG_KEY))
+            out_pkt.flags |= AV_PKT_FLAG_KEY;
 
-        if ((s->iformat->flags & AVFMT_GENERIC_INDEX) &&
-            out_pkt.flags & AV_PKT_FLAG_KEY) {
-            ff_reduce_index(s, st->index);
-            av_add_index_entry(st, st->parser->frame_offset, out_pkt.dts,
-                               0, 0, AVINDEX_KEYFRAME);
-        }
+        compute_pkt_fields(s, st, st->parser, &out_pkt);
 
         if (out_pkt.data == pkt->data && out_pkt.size == pkt->size) {
             out_pkt.destruct = pkt->destruct;
@@ -1196,17 +1306,17 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
         if (cur_pkt.pts != AV_NOPTS_VALUE &&
             cur_pkt.dts != AV_NOPTS_VALUE &&
             cur_pkt.pts < cur_pkt.dts) {
-            av_log(s, AV_LOG_WARNING, "Invalid timestamps stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d\n",
+            av_log(s, AV_LOG_WARNING, "Invalid timestamps stream=%d, pts=%s, dts=%s, size=%d\n",
                    cur_pkt.stream_index,
-                   cur_pkt.pts,
-                   cur_pkt.dts,
+                   av_ts2str(cur_pkt.pts),
+                   av_ts2str(cur_pkt.dts),
                    cur_pkt.size);
         }
         if (s->debug & FF_FDEBUG_TS)
-            av_log(s, AV_LOG_DEBUG, "ff_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n",
+            av_log(s, AV_LOG_DEBUG, "ff_read_packet stream=%d, pts=%s, dts=%s, size=%d, duration=%d, flags=%d\n",
                    cur_pkt.stream_index,
-                   cur_pkt.pts,
-                   cur_pkt.dts,
+                   av_ts2str(cur_pkt.pts),
+                   av_ts2str(cur_pkt.dts),
                    cur_pkt.size,
                    cur_pkt.duration,
                    cur_pkt.flags);
@@ -1214,12 +1324,17 @@ 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) {
                 st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
             } else if(st->need_parsing == AVSTREAM_PARSE_FULL_ONCE) {
                 st->parser->flags |= PARSER_FLAG_ONCE;
+            } else if(st->need_parsing == AVSTREAM_PARSE_FULL_RAW) {
+                st->parser->flags |= PARSER_FLAG_USE_CODEC_TS;
             }
         }
 
@@ -1240,16 +1355,22 @@ 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)
         ret = read_from_packet_buffer(&s->parse_queue, &s->parse_queue_end, pkt);
 
     if(s->debug & FF_FDEBUG_TS)
-        av_log(s, AV_LOG_DEBUG, "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=%s, dts=%s, size=%d, duration=%d, flags=%d\n",
             pkt->stream_index,
-            pkt->pts,
-            pkt->dts,
+            av_ts2str(pkt->pts),
+            av_ts2str(pkt->dts),
             pkt->size,
             pkt->duration,
             pkt->flags);
@@ -1261,15 +1382,18 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
 {
     const int genpts = s->flags & AVFMT_FLAG_GENPTS;
     int          eof = 0;
+    int ret;
+    AVStream *st;
 
-    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) {
@@ -1277,22 +1401,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);
@@ -1308,6 +1450,28 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
                           &s->packet_buffer_end)) < 0)
             return AVERROR(ENOMEM);
     }
+
+return_packet:
+
+    st = s->streams[pkt->stream_index];
+    if (st->skip_samples) {
+        uint8_t *p = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
+        AV_WL32(p, st->skip_samples);
+        av_log(s, AV_LOG_DEBUG, "demuxer injecting skip %d\n", st->skip_samples);
+        st->skip_samples = 0;
+    }
+
+    if ((s->iformat->flags & AVFMT_GENERIC_INDEX) && pkt->flags & AV_PKT_FLAG_KEY) {
+        ff_reduce_index(s, st->index);
+        av_add_index_entry(st, pkt->pos, pkt->dts, 0, 0, AVINDEX_KEYFRAME);
+    }
+
+    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 */
@@ -1362,7 +1526,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;
@@ -1409,6 +1574,12 @@ int ff_add_index_entry(AVIndexEntry **index_entries,
     if((unsigned)*nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
         return -1;
 
+    if(timestamp == AV_NOPTS_VALUE)
+        return AVERROR(EINVAL);
+
+    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) *
@@ -1505,7 +1676,7 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
     if (stream_index < 0)
         return -1;
 
-    av_dlog(s, "read_seek: %d %"PRId64"\n", stream_index, target_ts);
+    av_dlog(s, "read_seek: %d %s\n", stream_index, av_ts2str(target_ts));
 
     ts_max=
     ts_min= AV_NOPTS_VALUE;
@@ -1522,8 +1693,8 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
         if(e->timestamp <= target_ts || e->pos == e->min_distance){
             pos_min= e->pos;
             ts_min= e->timestamp;
-            av_dlog(s, "using cached pos_min=0x%"PRIx64" dts_min=%"PRId64"\n",
-                    pos_min,ts_min);
+            av_dlog(s, "using cached pos_min=0x%"PRIx64" dts_min=%s\n",
+                    pos_min, av_ts2str(ts_min));
         }else{
             assert(index==0);
         }
@@ -1536,8 +1707,8 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
             pos_max= e->pos;
             ts_max= e->timestamp;
             pos_limit= pos_max - e->min_distance;
-            av_dlog(s, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64" dts_max=%"PRId64"\n",
-                    pos_max,pos_limit, ts_max);
+            av_dlog(s, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64" dts_max=%s\n",
+                    pos_max, pos_limit, av_ts2str(ts_max));
         }
     }
 
@@ -1549,6 +1720,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;
@@ -1563,7 +1735,7 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
     int64_t start_pos, filesize;
     int no_change;
 
-    av_dlog(s, "gen_seek: %d %"PRId64"\n", stream_index, target_ts);
+    av_dlog(s, "gen_seek: %d %s\n", stream_index, av_ts2str(target_ts));
 
     if(ts_min == AV_NOPTS_VALUE){
         pos_min = s->data_offset;
@@ -1572,6 +1744,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);
@@ -1597,6 +1774,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){
@@ -1605,8 +1787,8 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
 
     no_change=0;
     while (pos_min < pos_limit) {
-        av_dlog(s, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%"PRId64" dts_max=%"PRId64"\n",
-                pos_min, pos_max, ts_min, ts_max);
+        av_dlog(s, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%s dts_max=%s\n",
+                pos_min, pos_max, av_ts2str(ts_min), av_ts2str(ts_max));
         assert(pos_limit <= pos_max);
 
         if(no_change==0){
@@ -1633,8 +1815,9 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
             no_change++;
         else
             no_change=0;
-        av_dlog(s, "%"PRId64" %"PRId64" %"PRId64" / %"PRId64" %"PRId64" %"PRId64" target:%"PRId64" limit:%"PRId64" start:%"PRId64" noc:%d\n",
-                pos_min, pos, pos_max, ts_min, ts, ts_max, target_ts,
+        av_dlog(s, "%"PRId64" %"PRId64" %"PRId64" / %s %s %s target:%s limit:%"PRId64" start:%"PRId64" noc:%d\n",
+                pos_min, pos, pos_max,
+                av_ts2str(ts_min), av_ts2str(ts), av_ts2str(ts_max), av_ts2str(target_ts),
                 pos_limit, start_pos, no_change);
         if(ts == AV_NOPTS_VALUE){
             av_log(s, AV_LOG_ERROR, "read_timestamp() failed in the middle\n");
@@ -1654,12 +1837,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);
+    av_dlog(s, "pos=0x%"PRIx64" %s<=%s<=%s\n",
+            pos, av_ts2str(ts_min), av_ts2str(target_ts), av_ts2str(ts_max));
+#endif
     *ts_ret= ts;
     return pos;
 }
@@ -1695,6 +1880,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);
@@ -1714,9 +1900,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);
@@ -1725,10 +1915,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;
@@ -1761,11 +1953,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;
     }
@@ -1812,8 +2006,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
 }
@@ -1847,19 +2051,24 @@ 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);
-            start_time = FFMIN(start_time, start_time1);
+            if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE || st->codec->codec_type == AVMEDIA_TYPE_DATA) {
+                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
                           + av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
@@ -1871,19 +2080,24 @@ 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;
+    else if(start_time > start_time_text)
+        av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream starttime %f\n", start_time_text / (float)AV_TIME_BASE);
+
     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)
@@ -2033,14 +2247,17 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
         file_size && ic->pb->seekable) {
         /* get accurate estimate from the PTSes */
         estimate_timings_from_pts(ic, old_offset);
+        ic->duration_estimation_method = AVFMT_DURATION_FROM_PTS;
     } else if (has_duration(ic)) {
         /* at least one component has timings - we use them for all
            the components */
         fill_all_stream_timings(ic);
+        ic->duration_estimation_method = AVFMT_DURATION_FROM_STREAM;
     } else {
         av_log(ic, AV_LOG_WARNING, "Estimating duration from bitrate, this may be inaccurate\n");
         /* less precise: use bitrate info */
         estimate_timings_from_bit_rate(ic);
+        ic->duration_estimation_method = AVFMT_DURATION_FROM_BITRATE;
     }
     update_stream_timings(ic);
 
@@ -2060,32 +2277,56 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
     }
 }
 
-static int has_codec_parameters(AVStream *st)
+static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
 {
     AVCodecContext *avctx = st->codec;
-    int val;
+
+#define FAIL(errmsg) do {                                         \
+        if (errmsg_ptr)                                           \
+            *errmsg_ptr = errmsg;                                 \
+        return 0;                                                 \
+    } while (0)
+
     switch (avctx->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
-        val = avctx->sample_rate && avctx->channels;
+        if (!avctx->frame_size && determinable_frame_size(avctx))
+            FAIL("unspecified sample size");
         if (st->info->found_decoder >= 0 && avctx->sample_fmt == AV_SAMPLE_FMT_NONE)
-            return 0;
+            FAIL("unspecified sample format");
+        if (!avctx->sample_rate)
+            FAIL("unspecified sample rate");
+        if (!avctx->channels)
+            FAIL("unspecified number of channels");
         break;
     case AVMEDIA_TYPE_VIDEO:
-        val = avctx->width;
+        if (!avctx->width)
+            FAIL("unspecified size");
         if (st->info->found_decoder >= 0 && avctx->pix_fmt == PIX_FMT_NONE)
-            return 0;
-        break;
-    default:
-        val = 1;
+            FAIL("unspecified pixel format");
         break;
+    case AVMEDIA_TYPE_DATA:
+        if(avctx->codec_id == CODEC_ID_NONE) return 1;
     }
-    return avctx->codec_id != CODEC_ID_NONE && val != 0;
+
+    if (avctx->codec_id == CODEC_ID_NONE)
+        FAIL("unknown codec");
+    return 1;
 }
 
 static int has_decode_delay_been_guessed(AVStream *st)
 {
-    return st->codec->codec_id != CODEC_ID_H264 ||
-        st->info->nb_decoded_frames >= 6;
+    if(st->codec->codec_id != CODEC_ID_H264) return 1;
+#if CONFIG_H264_DECODER
+    if(st->codec->has_b_frames &&
+       avpriv_h264_has_num_reorder_frames(st->codec) == st->codec->has_b_frames)
+        return 1;
+#endif
+    if(st->codec->has_b_frames<3)
+        return st->info->nb_decoded_frames >= 6;
+    else if(st->codec->has_b_frames<4)
+        return st->info->nb_decoded_frames >= 18;
+    else
+        return st->info->nb_decoded_frames >= 20;
 }
 
 /* returns 1 or 0 if or if not decoded data was returned, or a negative error */
@@ -2126,7 +2367,7 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option
 
     while ((pkt.size > 0 || (!pkt.data && got_picture)) &&
            ret >= 0 &&
-           (!has_codec_parameters(st)         ||
+           (!has_codec_parameters(st, NULL)   ||
            !has_decode_delay_been_guessed(st) ||
            (!st->codec_info_nb_frames && st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) {
         got_picture = 0;
@@ -2150,6 +2391,8 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option
             ret       = got_picture;
         }
     }
+    if(!pkt.data && !got_picture)
+        return -1;
     return ret;
 }
 
@@ -2219,8 +2462,8 @@ static void compute_chapters_end(AVFormatContext *s)
 }
 
 static int get_std_framerate(int i){
-    if(i<60*12) return i*1001;
-    else        return ((const int[]){24,30,60,12,15})[i-60*12]*1000*12;
+    if(i<60*12) return (i+1)*1001;
+    else        return ((const int[]){24,30,60,12,15,48})[i-60*12]*1000*12;
 }
 
 /*
@@ -2243,6 +2486,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;
@@ -2250,17 +2500,36 @@ 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 = ic->probesize > 0;
+
+    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);
-            if(st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser){
-                st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
+            if(st->parser){
+                if(st->need_parsing == AVSTREAM_PARSE_HEADERS){
+                    st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
+                } else if(st->need_parsing == AVSTREAM_PARSE_FULL_RAW) {
+                    st->parser->flags |= PARSER_FLAG_USE_CODEC_TS;
+                }
+            } else if (st->need_parsing) {
+                av_log(ic, AV_LOG_VERBOSE, "parser not found for codec "
+                       "%s, packets or times may be invalid.\n",
+                       avcodec_get_name(st->codec->codec_id));
             }
         }
         codec = st->codec->codec ? st->codec->codec :
@@ -2277,7 +2546,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
                               : &thread_opt);
 
         //try to just open decoders, in case this is enough to get parameters
-        if (!has_codec_parameters(st)) {
+        if (!has_codec_parameters(st, NULL)) {
             if (codec && !st->codec->codec)
                 avcodec_open2(st->codec, codec, options ? &options[i]
                               : &thread_opt);
@@ -2308,7 +2577,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             int fps_analyze_framecount = 20;
 
             st = ic->streams[i];
-            if (!has_codec_parameters(st))
+            if (!has_codec_parameters(st, NULL))
                 break;
             /* if the timebase is coarse (like the usual millisecond precision
                of mkv), we need to analyze more frames to reliably arrive at
@@ -2318,8 +2587,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             if (ic->fps_probe_size >= 0)
                 fps_analyze_framecount = ic->fps_probe_size;
             /* variable fps and no guess at the real fps */
-            if(   tb_unreliable(st->codec) && !st->avg_frame_rate.num
-               && st->codec_info_nb_frames < fps_analyze_framecount
+            if(   tb_unreliable(st->codec) && !(st->r_frame_rate.num && st->avg_frame_rate.num)
+               && st->info->duration_count < fps_analyze_framecount
                && st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
                 break;
             if(st->parser && st->parser->parser->split && !st->codec->extradata)
@@ -2337,6 +2606,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;
             }
         }
@@ -2344,6 +2614,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;
         }
 
@@ -2355,35 +2631,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;
         }
 
@@ -2403,7 +2650,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             /* check for non-increasing dts */
             if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
                 st->info->fps_last_dts >= pkt->dts) {
-                av_log(ic, AV_LOG_WARNING, "Non-increasing DTS in stream %d: "
+                av_log(ic, AV_LOG_DEBUG, "Non-increasing DTS in stream %d: "
                        "packet %d with DTS %"PRId64", packet %d with DTS "
                        "%"PRId64"\n", st->index, st->info->fps_last_dts_idx,
                        st->info->fps_last_dts, st->codec_info_nb_frames, pkt->dts);
@@ -2417,29 +2664,39 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             }
             st->info->fps_last_dts = pkt->dts;
             st->info->fps_last_dts_idx = st->codec_info_nb_frames;
-
-            /* check max_analyze_duration */
-            if (av_rescale_q(pkt->dts - st->info->fps_first_dts, st->time_base,
-                             AV_TIME_BASE_Q) >= ic->max_analyze_duration) {
-                av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n");
+        }
+        if (st->codec_info_nb_frames>1) {
+            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;
         }
 #if FF_API_R_FRAME_RATE
         {
             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->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=0; 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
@@ -2477,6 +2734,44 @@ 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++) {
+            const char *errmsg;
+
+            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, NULL));
+
+                if (err < 0) {
+                    av_log(ic, AV_LOG_INFO,
+                        "decoding for stream %d failed\n", st->index);
+                }
+            }
+
+            if (!has_codec_parameters(st, &errmsg)) {
+                char buf[256];
+                avcodec_string(buf, sizeof(buf), st->codec, 0);
+                av_log(ic, AV_LOG_WARNING,
+                       "Could not find codec parameters for stream %d (%s): %s\n"
+                       "Consider increasing the value for the 'analyzeduration' and 'probesize' options\n",
+                       i, buf, errmsg);
+            } else {
+                ret = 0;
+            }
+        }
+    }
+
     // close codecs which were opened in try_decode_frame()
     for(i=0;i<ic->nb_streams;i++) {
         st = ic->streams[i];
@@ -2485,16 +2780,20 @@ 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;
+            }
+
             /* estimate average framerate if not set by demuxer */
-            if (!st->avg_frame_rate.num && st->info->fps_last_dts != st->info->fps_first_dts) {
-                int64_t delta_dts = st->info->fps_last_dts - st->info->fps_first_dts;
-                int delta_packets = st->info->fps_last_dts_idx - st->info->fps_first_dts_idx;
+            if (st->codec_info_nb_frames>2 && !st->avg_frame_rate.num && st->info->codec_info_duration) {
                 int      best_fps = 0;
                 double best_error = 0.01;
 
                 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
-                          delta_packets*(int64_t)st->time_base.den,
-                          delta_dts*(int64_t)st->time_base.num, 60000);
+                          (st->codec_info_nb_frames-2)*(int64_t)st->time_base.den,
+                          st->info->codec_info_duration*(int64_t)st->time_base.num, 60000);
 
                 /* round guessed framerate to a "standard" framerate if it's
                  * within 1% of the original estimate*/
@@ -2512,30 +2811,51 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
                               best_fps, 12*1001, INT_MAX);
                 }
             }
-#if FF_API_R_FRAME_RATE
             // 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)) {
                 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(error < best_error){
-                        best_error= error;
-                        num = get_std_framerate(j);
+                double best_error= 0.01;
+
+                for (j=0; 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);
             }
-#endif
+
+            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);
@@ -2555,6 +2875,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
         }
     }
 
+    if(ic->probesize)
     estimate_timings(ic, old_offset);
 
     compute_chapters_end(ic);
@@ -2565,17 +2886,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;
 }
 
@@ -2592,7 +2921,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;
@@ -2670,13 +2999,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);
@@ -2687,7 +3016,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);
@@ -2705,10 +3034,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;
@@ -2716,6 +3045,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;
@@ -2736,6 +3075,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) {
@@ -2749,7 +3089,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;
 
@@ -2816,6 +3156,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;
@@ -2859,6 +3262,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)) {
@@ -2892,7 +3298,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,
@@ -2905,17 +3313,21 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
         }
 
         if(s->oformat->codec_tag){
-            if(st->codec->codec_tag && st->codec->codec_id == CODEC_ID_RAWVIDEO && av_codec_get_tag(s->oformat->codec_tag, st->codec->codec_id) == 0 && !validate_codec_tag(s, st)){
-                //the current rawvideo encoding system ends up setting the wrong codec_tag for avi, we override it here
+            if(   st->codec->codec_tag
+               && st->codec->codec_id == CODEC_ID_RAWVIDEO
+               && (av_codec_get_tag(s->oformat->codec_tag, st->codec->codec_id) == 0 || av_codec_get_tag(s->oformat->codec_tag, st->codec->codec_id) ==MKTAG('r', 'a', 'w', ' '))
+               && !validate_codec_tag(s, st)){
+                //the current rawvideo encoding system ends up setting the wrong codec_tag for avi/mov, we override it here
                 st->codec->codec_tag= 0;
             }
             if(st->codec->codec_tag){
                 if (!validate_codec_tag(s, st)) {
-                    char tagbuf[32];
+                    char tagbuf[32], cortag[32];
                     av_get_codec_tag_string(tagbuf, sizeof(tagbuf), st->codec->codec_tag);
+                    av_get_codec_tag_string(cortag, sizeof(cortag), av_codec_get_tag(s->oformat->codec_tag, st->codec->codec_id));
                     av_log(s, AV_LOG_ERROR,
-                           "Tag %s/0x%08x incompatible with output codec id '%d'\n",
-                           tagbuf, st->codec->codec_tag, st->codec->codec_id);
+                           "Tag %s/0x%08x incompatible with output codec id '%d' (%s)\n",
+                           tagbuf, st->codec->codec_tag, st->codec->codec_id, cortag);
                     ret = AVERROR_INVALIDDATA;
                     goto fail;
                 }
@@ -2992,11 +3404,8 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt){
     int delay = FFMAX(st->codec->has_b_frames, !!st->codec->max_b_frames);
     int num, den, frame_size, i;
 
-    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);*/
+    av_dlog(s, "compute_pkt_fields2: pts:%s dts:%s cur_dts:%s b:%d size:%d st:%d\n",
+            av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts), delay, pkt->size, pkt->stream_index);
 
     /* duration field */
     if (pkt->duration == 0) {
@@ -3011,6 +3420,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;
@@ -3031,16 +3445,17 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt){
         ((!(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);
+               "Application provided invalid, non monotonically increasing dts to muxer in stream %d: %s >= %s\n",
+               st->index, av_ts2str(st->cur_dts), av_ts2str(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 (%s) < dts (%s) in stream %d\n",
+               av_ts2str(pkt->pts), av_ts2str(pkt->dts), st->index);
         return AVERROR(EINVAL);
     }
 
-//    av_log(s, AV_LOG_DEBUG, "av_write_frame: pts2:%"PRId64" dts2:%"PRId64"\n", pkt->pts, pkt->dts);
+//    av_log(s, AV_LOG_DEBUG, "av_write_frame: pts2:%s dts2:%s\n", av_ts2str(pkt->pts), av_ts2str(pkt->dts));
     st->cur_dts= pkt->dts;
     st->pts.val= pkt->dts;
 
@@ -3087,27 +3502,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);
         }
@@ -3121,6 +3560,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)
@@ -3129,6 +3569,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;
@@ -3139,17 +3589,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;
 
@@ -3204,8 +3683,8 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
         if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->size==0)
             return 0;
 
-        av_dlog(s, "av_interleaved_write_frame size:%d dts:%"PRId64" pts:%"PRId64"\n",
-                pkt->size, pkt->dts, pkt->pts);
+        av_dlog(s, "av_interleaved_write_frame size:%d dts:%s pts:%s\n",
+                pkt->size, av_ts2str(pkt->dts), av_ts2str(pkt->pts));
         if((ret = compute_pkt_fields2(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
             return ret;
 
@@ -3231,6 +3710,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;
     }
 }
 
@@ -3254,11 +3735,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);
@@ -3269,6 +3756,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;
@@ -3311,8 +3807,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");
+            }
         }
     }
 }
@@ -3326,7 +3835,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)
@@ -3342,7 +3851,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);
     }
@@ -3593,11 +4102,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)
 {
@@ -3611,7 +4136,7 @@ void av_url_split(char *proto, int proto_size,
                   char *path, int path_size,
                   const char *url)
 {
-    const char *p, *ls, *at, *col, *brk;
+    const char *p, *ls, *ls2, *at, *col, *brk;
 
     if (port_ptr)               *port_ptr = -1;
     if (proto_size > 0)         proto[0] = 0;
@@ -3633,8 +4158,11 @@ void av_url_split(char *proto, int proto_size,
 
     /* separate path from hostname */
     ls = strchr(p, '/');
+    ls2 = strchr(p, '?');
     if(!ls)
-        ls = strchr(p, '?');
+        ls = ls2;
+    else if (ls && ls2)
+        ls = FFMIN(ls, ls2);
     if(ls)
         av_strlcpy(path, ls, path_size);
     else
@@ -3714,6 +4242,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)
 {
@@ -3725,10 +4261,11 @@ void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits,
         av_log(NULL, AV_LOG_WARNING, "st:%d has too large timebase, reducing\n", s->index);
 
     if(new_tb.num <= 0 || new_tb.den <= 0) {
-        av_log(NULL, AV_LOG_ERROR, "Ignoring attempt to set invalid timebase for st:%d\n", s->index);
+        av_log(NULL, AV_LOG_ERROR, "Ignoring attempt to set invalid timebase %d/%d for st:%d\n", new_tb.num, new_tb.den, s->index);
         return;
     }
     s->time_base = new_tb;
+    av_codec_set_pkt_timebase(s->codec, new_tb);
     s->pts_wrap_bits = pts_wrap_bits;
 }
 
@@ -4012,3 +4549,87 @@ const struct AVCodecTag *avformat_get_riff_audio_tags(void)
 {
     return ff_codec_wav_tags;
 }
+
+AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame)
+{
+    AVRational undef = {0, 1};
+    AVRational stream_sample_aspect_ratio = stream ? stream->sample_aspect_ratio : undef;
+    AVRational codec_sample_aspect_ratio  = stream && stream->codec ? stream->codec->sample_aspect_ratio : undef;
+    AVRational frame_sample_aspect_ratio  = frame  ? frame->sample_aspect_ratio  : codec_sample_aspect_ratio;
+
+    av_reduce(&stream_sample_aspect_ratio.num, &stream_sample_aspect_ratio.den,
+               stream_sample_aspect_ratio.num,  stream_sample_aspect_ratio.den, INT_MAX);
+    if (stream_sample_aspect_ratio.num <= 0 || stream_sample_aspect_ratio.den <= 0)
+        stream_sample_aspect_ratio = undef;
+
+    av_reduce(&frame_sample_aspect_ratio.num, &frame_sample_aspect_ratio.den,
+               frame_sample_aspect_ratio.num,  frame_sample_aspect_ratio.den, INT_MAX);
+    if (frame_sample_aspect_ratio.num <= 0 || frame_sample_aspect_ratio.den <= 0)
+        frame_sample_aspect_ratio = undef;
+
+    if (stream_sample_aspect_ratio.num)
+        return stream_sample_aspect_ratio;
+    else
+        return frame_sample_aspect_ratio;
+}
+
+int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
+                                    const char *spec)
+{
+    if (*spec <= '9' && *spec >= '0') /* opt:index */
+        return strtol(spec, NULL, 0) == st->index;
+    else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd' ||
+             *spec == 't') { /* opt:[vasdt] */
+        enum AVMediaType type;
+
+        switch (*spec++) {
+        case 'v': type = AVMEDIA_TYPE_VIDEO;      break;
+        case 'a': type = AVMEDIA_TYPE_AUDIO;      break;
+        case 's': type = AVMEDIA_TYPE_SUBTITLE;   break;
+        case 'd': type = AVMEDIA_TYPE_DATA;       break;
+        case 't': type = AVMEDIA_TYPE_ATTACHMENT; break;
+        default:  av_assert0(0);
+        }
+        if (type != st->codec->codec_type)
+            return 0;
+        if (*spec++ == ':') { /* possibly followed by :index */
+            int i, index = strtol(spec, NULL, 0);
+            for (i = 0; i < s->nb_streams; i++)
+                if (s->streams[i]->codec->codec_type == type && index-- == 0)
+                   return i == st->index;
+            return 0;
+        }
+        return 1;
+    } else if (*spec == 'p' && *(spec + 1) == ':') {
+        int prog_id, i, j;
+        char *endptr;
+        spec += 2;
+        prog_id = strtol(spec, &endptr, 0);
+        for (i = 0; i < s->nb_programs; i++) {
+            if (s->programs[i]->id != prog_id)
+                continue;
+
+            if (*endptr++ == ':') {
+                int stream_idx = strtol(endptr, NULL, 0);
+                return stream_idx >= 0 &&
+                    stream_idx < s->programs[i]->nb_stream_indexes &&
+                    st->index == s->programs[i]->stream_index[stream_idx];
+            }
+
+            for (j = 0; j < s->programs[i]->nb_stream_indexes; j++)
+                if (st->index == s->programs[i]->stream_index[j])
+                    return 1;
+        }
+        return 0;
+    } else if (*spec == '#') {
+        int sid;
+        char *endptr;
+        sid = strtol(spec + 1, &endptr, 0);
+        if (!*endptr)
+            return st->id == sid;
+    } else if (!*spec) /* empty specifier, matches everything */
+        return 1;
+
+    av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec);
+    return AVERROR(EINVAL);
+}