]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/utils.c
cosmetics: indentation
[ffmpeg] / libavformat / utils.c
index 4677a11d320dfa97da229e3db54903d3e7191a4b..658da8f951003b02b417cd54d761406bcc84f5f6 100644 (file)
@@ -480,7 +480,7 @@ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **o
     if (s->pb) {
         s->flags |= AVFMT_FLAG_CUSTOM_IO;
         if (!s->iformat)
-            return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, 0);
+            return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, s->probesize);
         else if (s->iformat->flags & AVFMT_NOFILE)
             return AVERROR(EINVAL);
         return 0;
@@ -495,7 +495,7 @@ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **o
         return ret;
     if (s->iformat)
         return 0;
-    return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, 0);
+    return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, s->probesize);
 }
 
 static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt,
@@ -515,10 +515,22 @@ static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt,
     return &pktl->pkt;
 }
 
+static void queue_attached_pictures(AVFormatContext *s)
+{
+    int i;
+    for (i = 0; i < s->nb_streams; i++)
+        if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC &&
+            s->streams[i]->discard < AVDISCARD_ALL) {
+            AVPacket copy = s->streams[i]->attached_pic;
+            copy.destruct = NULL;
+            add_to_pktbuf(&s->raw_packet_buffer, &copy, &s->raw_packet_buffer_end);
+        }
+}
+
 int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
 {
     AVFormatContext *s = *ps;
-    int i, ret = 0;
+    int ret = 0;
     AVDictionary *tmp = NULL;
     ID3v2ExtraMeta *id3v2_extra_meta = NULL;
 
@@ -574,13 +586,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
         goto fail;
     ff_id3v2_free_extra_meta(&id3v2_extra_meta);
 
-    /* queue attached pictures */
-    for (i = 0; i < s->nb_streams; i++)
-        if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) {
-            AVPacket copy = s->streams[i]->attached_pic;
-            copy.destruct = NULL;
-            add_to_pktbuf(&s->raw_packet_buffer, &copy, &s->raw_packet_buffer_end);
-        }
+    queue_attached_pictures(s);
 
     if (s->pb && !s->data_offset)
         s->data_offset = avio_tell(s->pb);
@@ -606,7 +612,7 @@ fail:
 
 /*******************************************************/
 
-int av_read_packet(AVFormatContext *s, AVPacket *pkt)
+int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     int ret, i;
     AVStream *st;
@@ -692,32 +698,35 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt)
     }
 }
 
+#if FF_API_READ_PACKET
+int av_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    return ff_read_packet(s, pkt);
+}
+#endif
+
+
 /**********************************************************/
 
 /**
  * Get the number of samples of an audio frame. Return -1 on error.
  */
-static int get_audio_frame_size(AVCodecContext *enc, int size)
+static int get_audio_frame_size(AVCodecContext *enc, int size, int mux)
 {
     int frame_size;
 
-    if (enc->frame_size <= 1) {
-        int bits_per_sample = av_get_bits_per_sample(enc->codec_id);
+    /* give frame_size priority if demuxing */
+    if (!mux && enc->frame_size > 1)
+        return enc->frame_size;
 
-        if (bits_per_sample) {
-            if (enc->channels == 0)
-                return -1;
-            frame_size = (size << 3) / (bits_per_sample * enc->channels);
-        } else {
-            /* used for example by ADPCM codecs */
-            if (enc->bit_rate == 0)
-                return -1;
-            frame_size = ((int64_t)size * 8 * enc->sample_rate) / enc->bit_rate;
-        }
-    } else {
-        frame_size = enc->frame_size;
-    }
-    return frame_size;
+    if ((frame_size = av_get_audio_frame_duration(enc, size)) > 0)
+        return frame_size;
+
+    /* fallback to using frame_size if muxing */
+    if (enc->frame_size > 1)
+        return enc->frame_size;
+
+    return -1;
 }
 
 
@@ -753,7 +762,7 @@ static void compute_frame_duration(int *pnum, int *pden, AVStream *st,
         }
         break;
     case AVMEDIA_TYPE_AUDIO:
-        frame_size = get_audio_frame_size(st->codec, pkt->size);
+        frame_size = get_audio_frame_size(st->codec, pkt->size, 0);
         if (frame_size <= 0 || st->codec->sample_rate <= 0)
             break;
         *pnum = frame_size;
@@ -818,7 +827,8 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index,
         st->start_time = pts;
 }
 
-static void update_initial_durations(AVFormatContext *s, AVStream *st, AVPacket *pkt)
+static void update_initial_durations(AVFormatContext *s, AVStream *st,
+                                     int stream_index, int duration)
 {
     AVPacketList *pktl= s->packet_buffer;
     int64_t cur_dts= 0;
@@ -826,10 +836,10 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, AVPacket
     if(st->first_dts != AV_NOPTS_VALUE){
         cur_dts= st->first_dts;
         for(; pktl; pktl= pktl->next){
-            if(pktl->pkt.stream_index == pkt->stream_index){
+            if(pktl->pkt.stream_index == stream_index){
                 if(pktl->pkt.pts != pktl->pkt.dts || pktl->pkt.dts != AV_NOPTS_VALUE || pktl->pkt.duration)
                     break;
-                cur_dts -= pkt->duration;
+                cur_dts -= duration;
             }
         }
         pktl= s->packet_buffer;
@@ -838,15 +848,16 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, AVPacket
         return;
 
     for(; pktl; pktl= pktl->next){
-        if(pktl->pkt.stream_index != pkt->stream_index)
+        if(pktl->pkt.stream_index != stream_index)
             continue;
         if(pktl->pkt.pts == pktl->pkt.dts && pktl->pkt.dts == AV_NOPTS_VALUE
            && !pktl->pkt.duration){
             pktl->pkt.dts= cur_dts;
             if(!st->codec->has_b_frames)
                 pktl->pkt.pts= cur_dts;
-            cur_dts += pkt->duration;
-            pktl->pkt.duration= pkt->duration;
+            cur_dts += duration;
+            if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+                pktl->pkt.duration = duration;
         }else
             break;
     }
@@ -889,13 +900,13 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
         pkt->dts= pkt->pts= AV_NOPTS_VALUE;
     }
 
-    if (pkt->duration == 0) {
+    if (pkt->duration == 0 && st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
         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);
+                update_initial_durations(s, st, pkt->stream_index, pkt->duration);
         }
     }
 
@@ -956,25 +967,37 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
             st->last_IP_pts= pkt->pts;
             /* cannot compute PTS if not present (we can compute it only
             by knowing the future */
-        } else if(pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || pkt->duration){
-            if(pkt->pts != AV_NOPTS_VALUE && pkt->duration){
-                int64_t old_diff= FFABS(st->cur_dts - pkt->duration - pkt->pts);
-                int64_t new_diff= FFABS(st->cur_dts - pkt->pts);
-                if(old_diff < new_diff && old_diff < (pkt->duration>>3)){
-                    pkt->pts += pkt->duration;
-    //                av_log(NULL, AV_LOG_DEBUG, "id:%d old:%"PRId64" new:%"PRId64" dur:%d cur:%"PRId64" size:%d\n", pkt->stream_index, old_diff, new_diff, pkt->duration, st->cur_dts, pkt->size);
+        } else if (pkt->pts != AV_NOPTS_VALUE ||
+                   pkt->dts != AV_NOPTS_VALUE ||
+                   pkt->duration              ||
+                   st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+            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);
+                    }
                 }
             }
 
-            /* 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 + pkt->duration;
+            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;
+            }
         }
     }
 
@@ -1136,7 +1159,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
         AVPacket cur_pkt;
 
         /* read next packet */
-        ret = av_read_packet(s, &cur_pkt);
+        ret = ff_read_packet(s, &cur_pkt);
         if (ret < 0) {
             if (ret == AVERROR(EAGAIN))
                 return ret;
@@ -1163,7 +1186,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
                    cur_pkt.size);
         }
         if (s->debug & FF_FDEBUG_TS)
-            av_log(s, AV_LOG_DEBUG, "av_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=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n",
                    cur_pkt.stream_index,
                    cur_pkt.pts,
                    cur_pkt.dts,
@@ -1293,7 +1316,8 @@ int av_find_default_stream_index(AVFormatContext *s)
         return -1;
     for(i = 0; i < s->nb_streams; i++) {
         st = s->streams[i];
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+            !(st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
             return i;
         }
         if (first_audio_index < 0 && st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
@@ -1625,14 +1649,6 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
 
 static int seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags){
     int64_t pos_min, pos_max;
-#if 0
-    AVStream *st;
-
-    if (stream_index < 0)
-        return -1;
-
-    st= s->streams[stream_index];
-#endif
 
     pos_min = s->data_offset;
     pos_max = avio_size(s->pb) - 1;
@@ -1642,9 +1658,6 @@ static int seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, in
 
     avio_seek(s->pb, pos, SEEK_SET);
 
-#if 0
-    av_update_cur_dts(s, st, ts);
-#endif
     return 0;
 }
 
@@ -1707,7 +1720,8 @@ static int seek_frame_generic(AVFormatContext *s,
     return 0;
 }
 
-int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
+static int seek_frame_internal(AVFormatContext *s, int stream_index,
+                               int64_t timestamp, int flags)
 {
     int ret;
     AVStream *st;
@@ -1750,14 +1764,29 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f
         return -1;
 }
 
+int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
+{
+    int ret = seek_frame_internal(s, stream_index, timestamp, flags);
+
+    if (ret >= 0)
+        queue_attached_pictures(s);
+
+    return ret;
+}
+
 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;
 
     if (s->iformat->read_seek2) {
+        int ret;
         ff_read_frame_flush(s);
-        return s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags);
+        ret = s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags);
+
+        if (ret >= 0)
+            queue_attached_pictures(s);
+        return ret;
     }
 
     if(s->iformat->read_timestamp){
@@ -1789,6 +1818,8 @@ static int has_duration(AVFormatContext *ic)
         if (st->duration != AV_NOPTS_VALUE)
             return 1;
     }
+    if (ic->duration != AV_NOPTS_VALUE)
+        return 1;
     return 0;
 }
 
@@ -1930,7 +1961,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
                 break;
 
             do {
-                ret = av_read_packet(ic, pkt);
+                ret = ff_read_packet(ic, pkt);
             } while(ret == AVERROR(EAGAIN));
             if (ret != 0)
                 break;
@@ -2012,18 +2043,20 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
     }
 }
 
-static int has_codec_parameters(AVCodecContext *avctx)
+static int has_codec_parameters(AVStream *st)
 {
+    AVCodecContext *avctx = st->codec;
     int val;
     switch (avctx->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
-        val = avctx->sample_rate && avctx->channels && avctx->sample_fmt != AV_SAMPLE_FMT_NONE;
-        if (!avctx->frame_size &&
-             avctx->codec_id == CODEC_ID_CELT))
+        val = avctx->sample_rate && avctx->channels;
+        if (st->info->found_decoder >= 0 && avctx->sample_fmt == AV_SAMPLE_FMT_NONE)
             return 0;
         break;
     case AVMEDIA_TYPE_VIDEO:
-        val = avctx->width && avctx->pix_fmt != PIX_FMT_NONE;
+        val = avctx->width;
+        if (st->info->found_decoder >= 0 && avctx->pix_fmt == PIX_FMT_NONE)
+            return 0;
         break;
     default:
         val = 1;
@@ -2046,14 +2079,16 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option
     AVFrame picture;
     AVPacket pkt = *avpkt;
 
-    if (!avcodec_is_open(st->codec)) {
+    if (!avcodec_is_open(st->codec) && !st->info->found_decoder) {
         AVDictionary *thread_opt = NULL;
 
         codec = st->codec->codec ? st->codec->codec :
                                    avcodec_find_decoder(st->codec->codec_id);
 
-        if (!codec)
+        if (!codec) {
+            st->info->found_decoder = -1;
             return -1;
+        }
 
         /* force thread count to 1 since the h264 decoder will not extract SPS
          *  and PPS to extradata during multi-threaded decoding */
@@ -2061,13 +2096,20 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option
         ret = avcodec_open2(st->codec, codec, options ? options : &thread_opt);
         if (!options)
             av_dict_free(&thread_opt);
-        if (ret < 0)
+        if (ret < 0) {
+            st->info->found_decoder = -1;
             return ret;
-    }
+        }
+        st->info->found_decoder = 1;
+    } else if (!st->info->found_decoder)
+        st->info->found_decoder = 1;
+
+    if (st->info->found_decoder < 0)
+        return -1;
 
     while ((pkt.size > 0 || (!pkt.data && got_picture)) &&
            ret >= 0 &&
-           (!has_codec_parameters(st->codec)  ||
+           (!has_codec_parameters(st)         ||
            !has_decode_delay_been_guessed(st) ||
            (!st->codec_info_nb_frames && st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) {
         got_picture = 0;
@@ -2218,7 +2260,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->codec)){
+        if (!has_codec_parameters(st)) {
             if (codec && !st->codec->codec)
                 avcodec_open2(st->codec, codec, options ? &options[i]
                               : &thread_opt);
@@ -2245,7 +2287,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             int fps_analyze_framecount = 20;
 
             st = ic->streams[i];
-            if (!has_codec_parameters(st->codec))
+            if (!has_codec_parameters(st))
                 break;
             /* if the timebase is coarse (like the usual millisecond precision
                of mkv), we need to analyze more frames to reliably arrive at
@@ -2261,7 +2303,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
                 break;
             if(st->parser && st->parser->parser->split && !st->codec->extradata)
                 break;
-            if(st->first_dts == AV_NOPTS_VALUE)
+            if (st->first_dts == AV_NOPTS_VALUE &&
+                (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
+                 st->codec->codec_type == AVMEDIA_TYPE_AUDIO))
                 break;
         }
         if (i == ic->nb_streams) {
@@ -2291,7 +2335,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
         if (ret < 0) {
             /* EOF or error*/
             AVPacket empty_pkt = { 0 };
-            int err;
+            int err = 0;
             av_init_packet(&empty_pkt);
 
             ret = -1; /* we could not have all the codec parameters before EOF */
@@ -2299,16 +2343,18 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
                 st = ic->streams[i];
 
                 /* flush the decoders */
-                do {
-                    err = try_decode_frame(st, &empty_pkt,
-                                           (options && i < orig_nb_streams) ?
-                                           &options[i] : NULL);
-                } while (err > 0 && !has_codec_parameters(st->codec));
+                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->codec)){
+                } else if (!has_codec_parameters(st)) {
                     char buf[256];
                     avcodec_string(buf, sizeof(buf), st->codec, 0);
                     av_log(ic, AV_LOG_WARNING,
@@ -2328,7 +2374,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
 
         st = ic->streams[pkt->stream_index];
         if (st->codec_info_nb_frames>1) {
-            if (st->time_base.den > 0 && av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) {
+            if (av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) {
                 av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n");
                 break;
             }
@@ -2393,11 +2439,11 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
     }
     for(i=0;i<ic->nb_streams;i++) {
         st = ic->streams[i];
-        if (st->codec_info_nb_frames>2 && !st->avg_frame_rate.num && st->info->codec_info_duration)
-            av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
-                     (st->codec_info_nb_frames-2)*(int64_t)st->time_base.den,
-                      st->info->codec_info_duration*(int64_t)st->time_base.num, 60000);
         if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+            if (st->codec_info_nb_frames>2 && !st->avg_frame_rate.num && st->info->codec_info_duration)
+                av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
+                          (st->codec_info_nb_frames-2)*(int64_t)st->time_base.den,
+                          st->info->codec_info_duration*(int64_t)st->time_base.num, 60000);
             // 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.
@@ -2447,31 +2493,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
 
     compute_chapters_end(ic);
 
-#if 0
-    /* correct DTS for B-frame streams with no timestamps */
-    for(i=0;i<ic->nb_streams;i++) {
-        st = ic->streams[i];
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-            if(b-frames){
-                ppktl = &ic->packet_buffer;
-                while(ppkt1){
-                    if(ppkt1->stream_index != i)
-                        continue;
-                    if(ppkt1->pkt->dts < 0)
-                        break;
-                    if(ppkt1->pkt->pts != AV_NOPTS_VALUE)
-                        break;
-                    ppkt1->pkt->dts -= delta;
-                    ppkt1= ppkt1->next;
-                }
-                if(ppkt1)
-                    continue;
-                st->cur_dts -= delta;
-            }
-        }
-    }
-#endif
-
  find_stream_info_err:
     for (i=0; i < ic->nb_streams; i++) {
         if (ic->streams[i]->codec)
@@ -2958,7 +2979,7 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt){
     /* update pts */
     switch (st->codec->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
-        frame_size = get_audio_frame_size(st->codec, pkt->size);
+        frame_size = get_audio_frame_size(st->codec, pkt->size, 1);
 
         /* HACK/FIXME, we skip the initial 0 size packets as they are most
            likely equal to the encoder delay, but it would be better if we
@@ -3046,7 +3067,9 @@ static int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacke
     return comp > 0;
 }
 
-int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){
+int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out,
+                                 AVPacket *pkt, int flush)
+{
     AVPacketList *pktl;
     int stream_count=0;
     int i;
@@ -3076,6 +3099,14 @@ int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pk
     }
 }
 
+#if FF_API_INTERLEAVE_PACKET
+int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out,
+                                 AVPacket *pkt, int flush)
+{
+    return ff_interleave_packet_per_dts(s, out, pkt, flush);
+}
+#endif
+
 /**
  * Interleave an AVPacket correctly so it can be muxed.
  * @param out the interleaved packet will be output here
@@ -3092,28 +3123,34 @@ static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, in
             av_free_packet(in);
         return ret;
     } else
-        return av_interleave_packet_per_dts(s, out, in, flush);
+        return ff_interleave_packet_per_dts(s, out, in, flush);
 }
 
 int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
-    AVStream *st= s->streams[ pkt->stream_index];
-    int ret;
+    int ret, flush = 0;
 
-    //FIXME/XXX/HACK drop zero sized packets
-    if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->size==0)
-        return 0;
+    if (pkt) {
+        AVStream *st= s->streams[ pkt->stream_index];
 
-    av_dlog(s, "av_interleaved_write_frame size:%d dts:%"PRId64" pts:%"PRId64"\n",
-            pkt->size, pkt->dts, pkt->pts);
-    if((ret = compute_pkt_fields2(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
-        return ret;
+        //FIXME/XXX/HACK drop zero sized packets
+        if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->size==0)
+            return 0;
 
-    if(pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
-        return AVERROR(EINVAL);
+        av_dlog(s, "av_interleaved_write_frame size:%d dts:%"PRId64" pts:%"PRId64"\n",
+                pkt->size, pkt->dts, pkt->pts);
+        if((ret = compute_pkt_fields2(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
+            return ret;
+
+        if(pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
+            return AVERROR(EINVAL);
+    } else {
+        av_dlog(s, "av_interleaved_write_frame FLUSH\n");
+        flush = 1;
+    }
 
     for(;;){
         AVPacket opkt;
-        int ret= interleave_packet(s, &opkt, pkt, 0);
+        int ret= interleave_packet(s, &opkt, pkt, flush);
         if(ret<=0) //FIXME cleanup needed for ret<0 ?
             return ret;
 
@@ -3630,7 +3667,7 @@ int ff_url_join(char *str, int size, const char *proto,
                 int port, const char *fmt, ...)
 {
 #if CONFIG_NETWORK
-    struct addrinfo hints, *ai;
+    struct addrinfo hints = { 0 }, *ai;
 #endif
 
     str[0] = '\0';
@@ -3641,7 +3678,6 @@ int ff_url_join(char *str, int size, const char *proto,
 #if CONFIG_NETWORK && defined(AF_INET6)
     /* Determine if hostname is a numerical IPv6 address,
      * properly escape it within [] in that case. */
-    memset(&hints, 0, sizeof(hints));
     hints.ai_flags = AI_NUMERICHOST;
     if (!getaddrinfo(hostname, NULL, &hints, &ai)) {
         if (ai->ai_family == AF_INET6) {