]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blobdiff - libavformat/utils.c
frsh: Export information about the last RTP contract and VRES
[frescor/ffmpeg.git] / libavformat / utils.c
index be8553bc341d062ca9bef910c28b64a89e249f52..bdf168ae93baa6d974f7e799f8bf0a952f696b79 100644 (file)
@@ -258,40 +258,6 @@ AVInputFormat *av_find_input_format(const char *short_name)
 
 /* memory handling */
 
-void av_destruct_packet(AVPacket *pkt)
-{
-    av_free(pkt->data);
-    pkt->data = NULL; pkt->size = 0;
-}
-
-void av_init_packet(AVPacket *pkt)
-{
-    pkt->pts   = AV_NOPTS_VALUE;
-    pkt->dts   = AV_NOPTS_VALUE;
-    pkt->pos   = -1;
-    pkt->duration = 0;
-    pkt->convergence_duration = 0;
-    pkt->flags = 0;
-    pkt->stream_index = 0;
-    pkt->destruct= av_destruct_packet_nofree;
-}
-
-int av_new_packet(AVPacket *pkt, int size)
-{
-    uint8_t *data;
-    if((unsigned)size > (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
-        return AVERROR(ENOMEM);
-    data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
-    if (!data)
-        return AVERROR(ENOMEM);
-    memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
-
-    av_init_packet(pkt);
-    pkt->data = data;
-    pkt->size = size;
-    pkt->destruct = av_destruct_packet;
-    return 0;
-}
 
 int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size)
 {
@@ -306,29 +272,11 @@ int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size)
     if(ret<=0)
         av_free_packet(pkt);
     else
-        pkt->size= ret;
+        av_shrink_packet(pkt, ret);
 
     return ret;
 }
 
-int av_dup_packet(AVPacket *pkt)
-{
-    if (((pkt->destruct == av_destruct_packet_nofree) || (pkt->destruct == NULL)) && pkt->data) {
-        uint8_t *data;
-        /* We duplicate the packet and don't forget to add the padding again. */
-        if((unsigned)pkt->size > (unsigned)pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)
-            return AVERROR(ENOMEM);
-        data = av_malloc(pkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
-        if (!data) {
-            return AVERROR(ENOMEM);
-        }
-        memcpy(data, pkt->data, pkt->size);
-        memset(data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
-        pkt->data = data;
-        pkt->destruct = av_destruct_packet;
-    }
-    return 0;
-}
 
 int av_filename_number_test(const char *filename)
 {
@@ -413,7 +361,7 @@ int av_open_input_stream(AVFormatContext **ic_ptr,
     }
 
     if(!ap->prealloced_context)
-        ic = av_alloc_format_context();
+        ic = avformat_alloc_context();
     else
         ic = *ic_ptr;
     if (!ic) {
@@ -680,8 +628,7 @@ static void compute_frame_duration(int *pnum, int *pden, AVStream *st,
             *pnum = st->codec->time_base.num;
             *pden = st->codec->time_base.den;
             if (pc && pc->repeat_pict) {
-                *pden *= 2;
-                *pnum = (*pnum) * (2 + pc->repeat_pict);
+                *pnum = (*pnum) * (1 + pc->repeat_pict);
             }
         }
         break;
@@ -810,7 +757,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
     // we take the conservative approach and discard both
     // Note, if this is misbehaving for a H.264 file then possibly presentation_delayed is not set correctly.
     if(delay==1 && pkt->dts == pkt->pts && pkt->dts != AV_NOPTS_VALUE && presentation_delayed){
-        av_log(s, AV_LOG_ERROR, "invalid dts/pts combination\n");
+        av_log(s, AV_LOG_WARNING, "invalid dts/pts combination\n");
         pkt->dts= pkt->pts= AV_NOPTS_VALUE;
     }
 
@@ -835,13 +782,33 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
             pkt->dts += offset;
     }
 
+    if (pc && pc->dts_sync_point >= 0) {
+        // we have synchronization info from the parser
+        int64_t den = st->codec->time_base.den * (int64_t) st->time_base.num;
+        if (den > 0) {
+            int64_t num = st->codec->time_base.num * (int64_t) st->time_base.den;
+            if (pkt->dts != AV_NOPTS_VALUE) {
+                // got DTS from the stream, update reference timestamp
+                st->reference_dts = pkt->dts - pc->dts_ref_dts_delta * num / den;
+                pkt->pts = pkt->dts + pc->pts_dts_delta * num / den;
+            } else if (st->reference_dts != AV_NOPTS_VALUE) {
+                // compute DTS based on reference timestamp
+                pkt->dts = st->reference_dts + pc->dts_ref_dts_delta * num / den;
+                pkt->pts = pkt->dts + pc->pts_dts_delta * num / den;
+            }
+            if (pc->dts_sync_point > 0)
+                st->reference_dts = pkt->dts; // new reference
+        }
+    }
+
     /* This may be redundant, but it should not hurt. */
     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);
     /* interpolate PTS and DTS if they are not present */
-    if(delay==0 || (delay==1 && pc)){
+    //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){
         if (presentation_delayed) {
             /* DTS = decompression timestamp */
             /* PTS = presentation timestamp */
@@ -889,7 +856,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
             FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i+1]);
         if(pkt->dts == AV_NOPTS_VALUE)
             pkt->dts= st->pts_buffer[0];
-        if(delay>1){
+        if(st->codec->codec_id == CODEC_ID_H264){ //we skiped it above so we try here
             update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts); // this should happen on the first packet
         }
         if(pkt->dts > st->cur_dts)
@@ -904,15 +871,15 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
     else if (pc) {
         pkt->flags = 0;
         /* keyframe computation */
-            if (pc->pict_type == FF_I_TYPE)
-                pkt->flags |= PKT_FLAG_KEY;
+        if (pc->key_frame == 1)
+            pkt->flags |= PKT_FLAG_KEY;
+        else if (pc->key_frame == -1 && pc->pict_type == FF_I_TYPE)
+            pkt->flags |= PKT_FLAG_KEY;
     }
+    if (pc)
+        pkt->convergence_duration = pc->convergence_duration;
 }
 
-void av_destruct_packet_nofree(AVPacket *pkt)
-{
-    pkt->data = NULL; pkt->size = 0;
-}
 
 static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
 {
@@ -931,11 +898,17 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
                 *pkt = st->cur_pkt; st->cur_pkt.data= NULL;
                 compute_pkt_fields(s, st, NULL, pkt);
                 s->cur_st = NULL;
+                if ((s->iformat->flags & AVFMT_GENERIC_INDEX) &&
+                    (pkt->flags & PKT_FLAG_KEY) && pkt->dts != AV_NOPTS_VALUE) {
+                    ff_reduce_index(s, st->index);
+                    av_add_index_entry(st, pkt->pos, pkt->dts, 0, 0, AVINDEX_KEYFRAME);
+                }
                 break;
             } else if (st->cur_len > 0 && st->discard < AVDISCARD_ALL) {
-                len = av_parser_parse(st->parser, st->codec, &pkt->data, &pkt->size,
-                                      st->cur_ptr, st->cur_len,
-                                      st->cur_pkt.pts, st->cur_pkt.dts);
+                len = av_parser_parse2(st->parser, st->codec, &pkt->data, &pkt->size,
+                                       st->cur_ptr, st->cur_len,
+                                       st->cur_pkt.pts, st->cur_pkt.dts,
+                                       st->cur_pkt.pos);
                 st->cur_pkt.pts = AV_NOPTS_VALUE;
                 st->cur_pkt.dts = AV_NOPTS_VALUE;
                 /* increment read pointer */
@@ -944,13 +917,13 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
 
                 /* return packet if any */
                 if (pkt->size) {
-                    pkt->pos = st->cur_pkt.pos;              // Isn't quite accurate but close.
                 got_packet:
                     pkt->duration = 0;
                     pkt->stream_index = st->index;
                     pkt->pts = st->parser->pts;
                     pkt->dts = st->parser->dts;
-                    pkt->destruct = av_destruct_packet_nofree;
+                    pkt->pos = st->parser->pos;
+                    pkt->destruct = NULL;
                     compute_pkt_fields(s, st, st->parser, pkt);
 
                     if((s->iformat->flags & AVFMT_GENERIC_INDEX) && pkt->flags & PKT_FLAG_KEY){
@@ -977,10 +950,11 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
                 for(i = 0; i < s->nb_streams; i++) {
                     st = s->streams[i];
                     if (st->parser && st->need_parsing) {
-                        av_parser_parse(st->parser, st->codec,
+                        av_parser_parse2(st->parser, st->codec,
                                         &pkt->data, &pkt->size,
                                         NULL, 0,
-                                        AV_NOPTS_VALUE, AV_NOPTS_VALUE);
+                                        AV_NOPTS_VALUE, AV_NOPTS_VALUE,
+                                        AV_NOPTS_VALUE);
                         if (pkt->size)
                             goto got_packet;
                     }
@@ -1154,6 +1128,7 @@ static void av_read_frame_flush(AVFormatContext *s)
         }
         st->last_IP_pts = AV_NOPTS_VALUE;
         st->cur_dts = AV_NOPTS_VALUE; /* we set the current DTS to an unspecified origin */
+        st->reference_dts = AV_NOPTS_VALUE;
         /* fail safe */
         st->cur_ptr = NULL;
         st->cur_len = 0;
@@ -1265,7 +1240,7 @@ int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp,
 
 int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
     AVInputFormat *avif= s->iformat;
-    int64_t pos_min, pos_max, pos, pos_limit;
+    int64_t av_uninit(pos_min), av_uninit(pos_max), pos, pos_limit;
     int64_t ts_min, ts_max, ts;
     int index;
     AVStream *st;
@@ -1293,8 +1268,8 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
             pos_min= e->pos;
             ts_min= e->timestamp;
 #ifdef DEBUG_SEEK
-        av_log(s, AV_LOG_DEBUG, "using cached pos_min=0x%"PRIx64" dts_min=%"PRId64"\n",
-               pos_min,ts_min);
+            av_log(s, AV_LOG_DEBUG, "using cached pos_min=0x%"PRIx64" dts_min=%"PRId64"\n",
+                   pos_min,ts_min);
 #endif
         }else{
             assert(index==0);
@@ -1309,8 +1284,8 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
             ts_max= e->timestamp;
             pos_limit= pos_max - e->min_distance;
 #ifdef DEBUG_SEEK
-        av_log(s, AV_LOG_DEBUG, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64" dts_max=%"PRId64"\n",
-               pos_max,pos_limit, ts_max);
+            av_log(s, AV_LOG_DEBUG, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64" dts_max=%"PRId64"\n",
+                   pos_max,pos_limit, ts_max);
 #endif
         }
     }
@@ -1408,7 +1383,9 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i
         else
             no_change=0;
 #ifdef DEBUG_SEEK
-av_log(s, AV_LOG_DEBUG, "%"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, pos_limit, start_pos, no_change);
+        av_log(s, AV_LOG_DEBUG, "%"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, pos_limit,
+               start_pos, no_change);
 #endif
         if(ts == AV_NOPTS_VALUE){
             av_log(s, AV_LOG_ERROR, "read_timestamp() failed in the middle\n");
@@ -1487,7 +1464,7 @@ static int av_seek_frame_generic(AVFormatContext *s,
                 return ret;
             av_update_cur_dts(s, st, ie->timestamp);
         }else{
-            if ((ret = url_fseek(s->pb, 0, SEEK_SET)) < 0)
+            if ((ret = url_fseek(s->pb, s->data_offset, SEEK_SET)) < 0)
                 return ret;
         }
         for(i=0;; i++) {
@@ -1556,6 +1533,28 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f
         return av_seek_frame_generic(s, stream_index, timestamp, flags);
 }
 
+int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
+{
+    if(min_ts > ts || max_ts < ts)
+        return -1;
+
+    av_read_frame_flush(s);
+
+    if (s->iformat->read_seek2)
+        return s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags);
+
+    if(s->iformat->read_timestamp){
+        //try to seek via read_timestamp()
+    }
+
+    //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));
+
+    // try some generic seek like av_seek_frame_generic() but with new ts semantics
+}
+
 /*******************************************************/
 
 /**
@@ -1842,41 +1841,42 @@ static int has_codec_parameters(AVCodecContext *enc)
     return enc->codec_id != CODEC_ID_NONE && val != 0;
 }
 
-static int try_decode_frame(AVStream *st, const uint8_t *data, int size)
+static int try_decode_frame(AVStream *st, AVPacket *avpkt)
 {
     int16_t *samples;
     AVCodec *codec;
     int got_picture, data_size, ret=0;
     AVFrame picture;
 
-  if(!st->codec->codec){
-    codec = avcodec_find_decoder(st->codec->codec_id);
-    if (!codec)
-        return -1;
-    ret = avcodec_open(st->codec, codec);
-    if (ret < 0)
-        return ret;
-  }
+    if(!st->codec->codec){
+        codec = avcodec_find_decoder(st->codec->codec_id);
+        if (!codec)
+            return -1;
+        ret = avcodec_open(st->codec, codec);
+        if (ret < 0)
+            return ret;
+    }
 
-  if(!has_codec_parameters(st->codec)){
-    switch(st->codec->codec_type) {
-    case CODEC_TYPE_VIDEO:
-        ret = avcodec_decode_video(st->codec, &picture,
-                                   &got_picture, data, size);
-        break;
-    case CODEC_TYPE_AUDIO:
-        data_size = FFMAX(size, AVCODEC_MAX_AUDIO_FRAME_SIZE);
-        samples = av_malloc(data_size);
-        if (!samples)
-            goto fail;
-        ret = avcodec_decode_audio2(st->codec, samples,
-                                    &data_size, data, size);
-        av_free(samples);
-        break;
-    default:
-        break;
+    if(!has_codec_parameters(st->codec)){
+        switch(st->codec->codec_type) {
+        case CODEC_TYPE_VIDEO:
+            avcodec_get_frame_defaults(&picture);
+            ret = avcodec_decode_video2(st->codec, &picture,
+                                        &got_picture, avpkt);
+            break;
+        case CODEC_TYPE_AUDIO:
+            data_size = FFMAX(avpkt->size, AVCODEC_MAX_AUDIO_FRAME_SIZE);
+            samples = av_malloc(data_size);
+            if (!samples)
+                goto fail;
+            ret = avcodec_decode_audio3(st->codec, samples,
+                                        &data_size, avpkt);
+            av_free(samples);
+            break;
+        default:
+            break;
+        }
     }
-  }
  fail:
     return ret;
 }
@@ -1970,7 +1970,9 @@ static int tb_unreliable(AVCodecContext *c){
        || c->time_base.den <    5L*c->time_base.num
 /*       || c->codec_tag == AV_RL32("DIVX")
        || c->codec_tag == AV_RL32("XVID")*/
-       || c->codec_id == CODEC_ID_MPEG2VIDEO)
+       || c->codec_id == CODEC_ID_MPEG2VIDEO
+       || c->codec_id == CODEC_ID_H264
+       )
         return 1;
     return 0;
 }
@@ -1981,6 +1983,7 @@ int av_find_stream_info(AVFormatContext *ic)
     AVStream *st;
     AVPacket pkt1, *pkt;
     int64_t last_dts[MAX_STREAMS];
+    int64_t duration_gcd[MAX_STREAMS]={0};
     int duration_count[MAX_STREAMS]={0};
     double (*duration_error)[MAX_STD_TIMEBASES];
     int64_t old_offset = url_ftell(ic->pb);
@@ -2014,6 +2017,11 @@ int av_find_stream_info(AVFormatContext *ic)
     count = 0;
     read_size = 0;
     for(;;) {
+        if(url_interrupt_cb()){
+            ret= AVERROR(EINTR);
+            break;
+        }
+
         /* check if one codec still needs to be handled */
         for(i=0;i<ic->nb_streams;i++) {
             st = ic->streams[i];
@@ -2074,8 +2082,11 @@ int av_find_stream_info(AVFormatContext *ic)
         read_size += pkt->size;
 
         st = ic->streams[pkt->stream_index];
-        if(codec_info_nb_frames[st->index]>1)
+        if(codec_info_nb_frames[st->index]>1) {
+            if (st->time_base.den > 0 && av_rescale_q(codec_info_duration[st->index], st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration)
+                break;
             codec_info_duration[st->index] += pkt->duration;
+        }
         if (pkt->duration != 0)
             codec_info_nb_frames[st->index]++;
 
@@ -2098,6 +2109,9 @@ int av_find_stream_info(AVFormatContext *ic)
                     duration_error[index][i] += error*error;
                 }
                 duration_count[index]++;
+                // ignore the first 4 values, they might have some random jitter
+                if (duration_count[index] > 3)
+                    duration_gcd[index] = av_gcd(duration_gcd[index], duration);
             }
             if(last == AV_NOPTS_VALUE || duration_count[index]<=1)
                 last_dts[pkt->stream_index]= pkt->dts;
@@ -2131,11 +2145,8 @@ int av_find_stream_info(AVFormatContext *ic)
              st->codec->codec_id == CODEC_ID_PPM ||
              st->codec->codec_id == CODEC_ID_SHORTEN ||
              (st->codec->codec_id == CODEC_ID_MPEG4 && !st->need_parsing))*/)
-            try_decode_frame(st, pkt->data, pkt->size);
+            try_decode_frame(st, pkt);
 
-        if (st->time_base.den > 0 && av_rescale_q(codec_info_duration[st->index], st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) {
-            break;
-        }
         count++;
     }
 
@@ -2151,10 +2162,16 @@ int av_find_stream_info(AVFormatContext *ic)
             if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample)
                 st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
 
+            // 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) && duration_count[i] > 15 && duration_gcd[i] > 1)
+                av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * duration_gcd[i], INT_MAX);
             if(duration_count[i]
                && tb_unreliable(st->codec) /*&&
                //FIXME we should not special-case MPEG-2, but this needs testing with non-MPEG-2 ...
                st->time_base.num*duration_sum[i]/duration_count[i]*101LL > st->time_base.den*/){
+                int num = 0;
                 double best_error= 2*av_q2d(st->time_base);
                 best_error= best_error*best_error*duration_count[i]*1000*12*30;
 
@@ -2164,16 +2181,19 @@ int av_find_stream_info(AVFormatContext *ic)
 //                        av_log(NULL, AV_LOG_ERROR, "%f %f\n", get_std_framerate(j) / 12.0/1001, error);
                     if(error < best_error){
                         best_error= error;
-                        av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, get_std_framerate(j), 12*1001, INT_MAX);
+                        num = get_std_framerate(j);
                     }
                 }
+                // do not increase frame rate by more than 1 % in order to match a standard rate.
+                if (num && (!st->r_frame_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(st->r_frame_rate)))
+                    av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX);
             }
 
             if (!st->r_frame_rate.num){
                 if(    st->codec->time_base.den * (int64_t)st->time_base.num
-                    <= st->codec->time_base.num * (int64_t)st->time_base.den){
+                    <= 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->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;
@@ -2257,13 +2277,17 @@ void av_close_input_stream(AVFormatContext *s)
         av_free(st->index_entries);
         av_free(st->codec->extradata);
         av_free(st->codec);
+#if LIBAVFORMAT_VERSION_INT < (53<<16)
         av_free(st->filename);
+#endif
         av_free(st->priv_data);
         av_free(st);
     }
     for(i=s->nb_programs-1; i>=0; i--) {
+#if LIBAVFORMAT_VERSION_INT < (53<<16)
         av_freep(&s->programs[i]->provider_name);
         av_freep(&s->programs[i]->name);
+#endif
         av_metadata_free(&s->programs[i]->metadata);
         av_freep(&s->programs[i]->stream_index);
         av_freep(&s->programs[i]);
@@ -2272,7 +2296,9 @@ void av_close_input_stream(AVFormatContext *s)
     flush_packet_queue(s);
     av_freep(&s->priv_data);
     while(s->nb_chapters--) {
+#if LIBAVFORMAT_VERSION_INT < (53<<16)
         av_free(s->chapters[s->nb_chapters]->title);
+#endif
         av_metadata_free(&s->chapters[s->nb_chapters]->metadata);
         av_free(s->chapters[s->nb_chapters]);
     }
@@ -2322,6 +2348,7 @@ AVStream *av_new_stream(AVFormatContext *s, int id)
     st->last_IP_pts = AV_NOPTS_VALUE;
     for(i=0; i<MAX_REORDER_DELAY+1; i++)
         st->pts_buffer[i]= AV_NOPTS_VALUE;
+    st->reference_dts = AV_NOPTS_VALUE;
 
     st->sample_aspect_ratio = (AVRational){0,1};
 
@@ -2354,17 +2381,6 @@ AVProgram *av_new_program(AVFormatContext *ac, int id)
     return program;
 }
 
-void av_set_program_name(AVProgram *program, char *provider_name, char *name)
-{
-    assert(!provider_name == !name);
-    if(name){
-        av_free(program->provider_name);
-        av_free(program->         name);
-        program->provider_name = av_strdup(provider_name);
-        program->         name = av_strdup(         name);
-    }
-}
-
 AVChapter *ff_new_chapter(AVFormatContext *s, int id, AVRational time_base, int64_t start, int64_t end, const char *title)
 {
     AVChapter *chapter = NULL;
@@ -2380,8 +2396,10 @@ AVChapter *ff_new_chapter(AVFormatContext *s, int id, AVRational time_base, int6
             return NULL;
         dynarray_add(&s->chapters, &s->nb_chapters, chapter);
     }
+#if LIBAVFORMAT_VERSION_INT < (53<<16)
     av_free(chapter->title);
-    chapter->title = av_strdup(title);
+#endif
+    av_metadata_set(&chapter->metadata, "title", title);
     chapter->id    = id;
     chapter->time_base= time_base;
     chapter->start = start;
@@ -2457,6 +2475,10 @@ int av_write_header(AVFormatContext *s)
             }else
                 st->codec->codec_tag= av_codec_get_tag(s->oformat->codec_tag, st->codec->codec_id);
         }
+
+        if(s->oformat->flags & AVFMT_GLOBALHEADER &&
+            !(st->codec->flags & CODEC_FLAG_GLOBAL_HEADER))
+          av_log(s, AV_LOG_WARNING, "Codec for stream %d does not use global headers but container format requires global headers\n", i);
     }
 
     if (!s->priv_data && s->oformat->priv_data_size > 0) {
@@ -2513,7 +2535,7 @@ static int compute_pkt_fields2(AVStream *st, AVPacket *pkt){
     if (pkt->duration == 0) {
         compute_frame_duration(&num, &den, st, NULL, pkt);
         if (den && num) {
-            pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num);
+            pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den * st->codec->ticks_per_frame, den * (int64_t)st->time_base.num);
         }
     }
 
@@ -2592,10 +2614,8 @@ void ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt,
 
     this_pktl = av_mallocz(sizeof(AVPacketList));
     this_pktl->pkt= *pkt;
-    if(pkt->destruct == av_destruct_packet)
-        pkt->destruct= NULL; // not shared -> must keep original from being freed
-    else
-        av_dup_packet(&this_pktl->pkt);  //shared -> must dup
+    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
 
     next_point = &s->packet_buffer;
     while(*next_point){
@@ -2614,6 +2634,9 @@ int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacket *pkt)
     int64_t left = st2->time_base.num * (int64_t)st ->time_base.den;
     int64_t right= st ->time_base.num * (int64_t)st2->time_base.den;
 
+    if (pkt->dts == AV_NOPTS_VALUE)
+        return 0;
+
     return next->dts * left > pkt->dts * right; //FIXME this can overflow
 }
 
@@ -2676,7 +2699,7 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
     if(compute_pkt_fields2(st, pkt) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
         return -1;
 
-    if(pkt->dts == AV_NOPTS_VALUE)
+    if(pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
         return -1;
 
     for(;;){
@@ -2753,6 +2776,13 @@ void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int i
     }
 }
 
+static void print_fps(double d, const char *postfix){
+    uint64_t v= lrintf(d*100);
+    if     (v% 100      ) av_log(NULL, AV_LOG_INFO, ", %3.2f %s", d, postfix);
+    else if(v%(100*1000)) av_log(NULL, AV_LOG_INFO, ", %1.0f %s", d, postfix);
+    else                  av_log(NULL, AV_LOG_INFO, ", %1.0fk %s", d/1000, postfix);
+}
+
 /* "user interface" functions */
 static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
 {
@@ -2760,14 +2790,15 @@ static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_out
     int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
     AVStream *st = ic->streams[i];
     int g = av_gcd(st->time_base.num, st->time_base.den);
+    AVMetadataTag *lang = av_metadata_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);
     /* the pid is an important information, so we display it */
     /* XXX: add a generic system */
     if (flags & AVFMT_SHOW_IDS)
         av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id);
-    if (strlen(st->language) > 0)
-        av_log(NULL, AV_LOG_INFO, "(%s)", st->language);
+    if (lang)
+        av_log(NULL, AV_LOG_INFO, "(%s)", lang->value);
     av_log(NULL, AV_LOG_DEBUG, ", %d/%d", st->time_base.num/g, st->time_base.den/g);
     av_log(NULL, AV_LOG_INFO, ": %s", buf);
     if (st->sample_aspect_ratio.num && // default
@@ -2783,11 +2814,11 @@ static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_out
     }
     if(st->codec->codec_type == CODEC_TYPE_VIDEO){
         if(st->r_frame_rate.den && st->r_frame_rate.num)
-            av_log(NULL, AV_LOG_INFO, ", %5.2f tb(r)", av_q2d(st->r_frame_rate));
-/*      else if(st->time_base.den && st->time_base.num)
-            av_log(NULL, AV_LOG_INFO, ", %5.2f tb(m)", 1/av_q2d(st->time_base));*/
-        else
-            av_log(NULL, AV_LOG_INFO, ", %5.2f tb(c)", 1/av_q2d(st->codec->time_base));
+            print_fps(av_q2d(st->r_frame_rate), "tbr");
+        if(st->time_base.den && st->time_base.num)
+            print_fps(1/av_q2d(st->time_base), "tbn");
+        if(st->codec->time_base.den && st->codec->time_base.num)
+            print_fps(1/av_q2d(st->codec->time_base), "tbc");
     }
     av_log(NULL, AV_LOG_INFO, "\n");
 }
@@ -2838,8 +2869,10 @@ void dump_format(AVFormatContext *ic,
     if(ic->nb_programs) {
         int j, k;
         for(j=0; j<ic->nb_programs; j++) {
+            AVMetadataTag *name = av_metadata_get(ic->programs[j]->metadata,
+                                                  "name", NULL, 0);
             av_log(NULL, AV_LOG_INFO, "  Program %d %s\n", ic->programs[j]->id,
-                   ic->programs[j]->name ? ic->programs[j]->name : "");
+                   name ? name->value : "");
             for(k=0; k<ic->programs[j]->nb_stream_indexes; k++)
                 dump_stream_format(ic, ic->programs[j]->stream_index[k], index, is_output);
          }
@@ -2905,6 +2938,9 @@ int64_t parse_date(const char *datestr, int duration)
     p = datestr;
     q = NULL;
     if (!duration) {
+        if (!strncasecmp(datestr, "now", len))
+            return (int64_t) now * 1000000;
+
         /* parse the year-month-day part */
         for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
             q = small_strptime(p, date_fmt[i], &dt);