]> git.sesse.net Git - ffmpeg/blobdiff - avconv.c
h264: only allow ending a field/starting a new one before finish_setup()
[ffmpeg] / avconv.c
index 319823b056642b481e9cca70959bf17ae80311b8..2e3bde925ecbd291297f7429eed0518602ddd4fe 100644 (file)
--- a/avconv.c
+++ b/avconv.c
@@ -1,6 +1,6 @@
 /*
  * avconv main
- * Copyright (c) 2000-2011 The libav developers.
+ * Copyright (c) 2000-2011 The Libav developers
  *
  * This file is part of Libav.
  *
@@ -175,16 +175,16 @@ static void avconv_cleanup(int ret)
     }
     for (i = 0; i < nb_output_streams; i++) {
         OutputStream *ost = output_streams[i];
-        AVBitStreamFilterContext *bsfc = ost->bitstream_filters;
-        while (bsfc) {
-            AVBitStreamFilterContext *next = bsfc->next;
-            av_bitstream_filter_close(bsfc);
-            bsfc = next;
-        }
-        ost->bitstream_filters = NULL;
+
+        for (j = 0; j < ost->nb_bitstream_filters; j++)
+            av_bsf_free(&ost->bsf_ctx[j]);
+        av_freep(&ost->bsf_ctx);
+        av_freep(&ost->bitstream_filters);
+
         av_frame_free(&ost->filtered_frame);
 
         av_parser_close(ost->parser);
+        avcodec_free_context(&ost->parser_avctx);
 
         av_freep(&ost->forced_keyframes);
         av_freep(&ost->avfilter);
@@ -249,16 +249,15 @@ static void abort_codec_experimental(AVCodec *c, int encoder)
             "results.\nAdd '-strict experimental' if you want to use it.\n",
             codec_string, c->name);
     codec = encoder ? avcodec_find_encoder(c->id) : avcodec_find_decoder(c->id);
-    if (!(codec->capabilities & CODEC_CAP_EXPERIMENTAL))
+    if (!(codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL))
         av_log(NULL, AV_LOG_FATAL, "Or use the non experimental %s '%s'.\n",
                codec_string, codec->name);
     exit_program(1);
 }
 
-static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
+static void write_packet(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
 {
-    AVBitStreamFilterContext *bsfc = ost->bitstream_filters;
-    AVCodecContext          *avctx = ost->encoding_needed ? ost->enc_ctx : ost->st->codec;
+    AVStream *st = ost->st;
     int ret;
 
     /*
@@ -268,42 +267,22 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
      * Counting encoded video frames needs to be done separately because of
      * reordering, see do_video_out()
      */
-    if (!(avctx->codec_type == AVMEDIA_TYPE_VIDEO && avctx->codec)) {
+    if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed)) {
         if (ost->frame_number >= ost->max_frames) {
-            av_free_packet(pkt);
+            av_packet_unref(pkt);
             return;
         }
         ost->frame_number++;
     }
-    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR,
                                               NULL);
         ost->quality = sd ? *(int *)sd : -1;
-    }
 
-    while (bsfc) {
-        AVPacket new_pkt = *pkt;
-        int a = av_bitstream_filter_filter(bsfc, avctx, NULL,
-                                           &new_pkt.data, &new_pkt.size,
-                                           pkt->data, pkt->size,
-                                           pkt->flags & AV_PKT_FLAG_KEY);
-        if (a > 0) {
-            av_free_packet(pkt);
-            new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size,
-                                           av_buffer_default_free, NULL, 0);
-            if (!new_pkt.buf)
-                exit_program(1);
-        } else if (a < 0) {
-            av_log(NULL, AV_LOG_ERROR, "%s failed for stream %d, codec %s",
-                   bsfc->filter->name, pkt->stream_index,
-                   avctx->codec ? avctx->codec->name : "copy");
-            print_error("", a);
-            if (exit_on_error)
-                exit_program(1);
+        if (ost->frame_rate.num) {
+            pkt->duration = av_rescale_q(1, av_inv_q(ost->frame_rate),
+                                         ost->st->time_base);
         }
-        *pkt = new_pkt;
-
-        bsfc = bsfc->next;
     }
 
     if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS) &&
@@ -336,6 +315,49 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
     }
 }
 
+static void output_packet(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
+{
+    int ret = 0;
+
+    /* apply the output bitstream filters, if any */
+    if (ost->nb_bitstream_filters) {
+        int idx;
+
+        ret = av_bsf_send_packet(ost->bsf_ctx[0], pkt);
+        if (ret < 0)
+            goto finish;
+
+        idx = 1;
+        while (idx) {
+            /* get a packet from the previous filter up the chain */
+            ret = av_bsf_receive_packet(ost->bsf_ctx[idx - 1], pkt);
+            if (ret == AVERROR(EAGAIN)) {
+                ret = 0;
+                idx--;
+                continue;
+            } else if (ret < 0)
+                goto finish;
+
+            /* send it to the next filter down the chain or to the muxer */
+            if (idx < ost->nb_bitstream_filters) {
+                ret = av_bsf_send_packet(ost->bsf_ctx[idx], pkt);
+                if (ret < 0)
+                    goto finish;
+                idx++;
+            } else
+                write_packet(s, pkt, ost);
+        }
+    } else
+        write_packet(s, pkt, ost);
+
+finish:
+    if (ret < 0 && ret != AVERROR_EOF) {
+        av_log(NULL, AV_LOG_FATAL, "Error applying bitstream filters to an output "
+               "packet for stream #%d:%d.\n", ost->file_index, ost->index);
+        exit_program(1);
+    }
+}
+
 static int check_recording_time(OutputStream *ost)
 {
     OutputFile *of = output_files[ost->file_index];
@@ -354,7 +376,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
 {
     AVCodecContext *enc = ost->enc_ctx;
     AVPacket pkt;
-    int got_packet = 0;
+    int ret;
 
     av_init_packet(&pkt);
     pkt.data = NULL;
@@ -367,15 +389,25 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
     ost->samples_encoded += frame->nb_samples;
     ost->frames_encoded++;
 
-    if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) {
-        av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
-        exit_program(1);
-    }
+    ret = avcodec_send_frame(enc, frame);
+    if (ret < 0)
+        goto error;
+
+    while (1) {
+        ret = avcodec_receive_packet(enc, &pkt);
+        if (ret == AVERROR(EAGAIN))
+            break;
+        if (ret < 0)
+            goto error;
 
-    if (got_packet) {
         av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base);
-        write_frame(s, &pkt, ost);
+        output_packet(s, &pkt, ost);
     }
+
+    return;
+error:
+    av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
+    exit_program(1);
 }
 
 static void do_subtitle_out(AVFormatContext *s,
@@ -443,7 +475,7 @@ static void do_subtitle_out(AVFormatContext *s,
             else
                 pkt.pts += 90 * sub->end_display_time;
         }
-        write_frame(s, &pkt, ost);
+        output_packet(s, &pkt, ost);
     }
 }
 
@@ -488,70 +520,62 @@ static void do_video_out(AVFormatContext *s,
     if (ost->frame_number >= ost->max_frames)
         return;
 
-    if (s->oformat->flags & AVFMT_RAWPICTURE &&
-        enc->codec->id == AV_CODEC_ID_RAWVIDEO) {
-        /* raw pictures are written as AVPicture structure to
-           avoid any copies. We support temporarily the older
-           method. */
-#if FF_API_CODED_FRAME
-FF_DISABLE_DEPRECATION_WARNINGS
-        enc->coded_frame->interlaced_frame = in_picture->interlaced_frame;
-        enc->coded_frame->top_field_first  = in_picture->top_field_first;
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
-        pkt.data   = (uint8_t *)in_picture;
-        pkt.size   =  sizeof(AVPicture);
-        pkt.pts    = av_rescale_q(in_picture->pts, enc->time_base, ost->st->time_base);
-        pkt.flags |= AV_PKT_FLAG_KEY;
+    if (enc->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) &&
+        ost->top_field_first >= 0)
+        in_picture->top_field_first = !!ost->top_field_first;
 
-        write_frame(s, &pkt, ost);
-    } else {
-        int got_packet;
+    in_picture->quality = enc->global_quality;
+    in_picture->pict_type = 0;
+    if (ost->forced_kf_index < ost->forced_kf_count &&
+        in_picture->pts >= ost->forced_kf_pts[ost->forced_kf_index]) {
+        in_picture->pict_type = AV_PICTURE_TYPE_I;
+        ost->forced_kf_index++;
+    }
 
-        if (enc->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME) &&
-            ost->top_field_first >= 0)
-            in_picture->top_field_first = !!ost->top_field_first;
+    ost->frames_encoded++;
 
-        in_picture->quality = enc->global_quality;
-        in_picture->pict_type = 0;
-        if (ost->forced_kf_index < ost->forced_kf_count &&
-            in_picture->pts >= ost->forced_kf_pts[ost->forced_kf_index]) {
-            in_picture->pict_type = AV_PICTURE_TYPE_I;
-            ost->forced_kf_index++;
-        }
+    ret = avcodec_send_frame(enc, in_picture);
+    if (ret < 0)
+        goto error;
 
-        ost->frames_encoded++;
+    /*
+     * For video, there may be reordering, so we can't throw away frames on
+     * encoder flush, we need to limit them here, before they go into encoder.
+     */
+    ost->frame_number++;
 
-        ret = avcodec_encode_video2(enc, &pkt, in_picture, &got_packet);
-        if (ret < 0) {
-            av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
-            exit_program(1);
-        }
+    while (1) {
+        ret = avcodec_receive_packet(enc, &pkt);
+        if (ret == AVERROR(EAGAIN))
+            break;
+        if (ret < 0)
+            goto error;
 
-        if (got_packet) {
-            av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base);
-            write_frame(s, &pkt, ost);
-            *frame_size = pkt.size;
+        av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base);
+        output_packet(s, &pkt, ost);
+        *frame_size = pkt.size;
 
-            /* if two pass, output log */
-            if (ost->logfile && enc->stats_out) {
-                fprintf(ost->logfile, "%s", enc->stats_out);
-            }
+        /* if two pass, output log */
+        if (ost->logfile && enc->stats_out) {
+            fprintf(ost->logfile, "%s", enc->stats_out);
         }
+
+        ost->sync_opts++;
     }
-    ost->sync_opts++;
-    /*
-     * For video, number of frames in == number of packets out.
-     * But there may be reordering, so we can't throw away frames on encoder
-     * flush, we need to limit them here, before they go into encoder.
-     */
-    ost->frame_number++;
+
+    return;
+error:
+    av_assert0(ret != AVERROR(EAGAIN) && ret != AVERROR_EOF);
+    av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
+    exit_program(1);
 }
 
+#if FF_API_CODED_FRAME && FF_API_ERROR_FRAME
 static double psnr(double d)
 {
     return -10.0 * log(d) / log(10.0);
 }
+#endif
 
 static void do_video_stats(OutputStream *ost, int frame_size)
 {
@@ -574,9 +598,9 @@ static void do_video_stats(OutputStream *ost, int frame_size)
         fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number,
                 ost->quality / (float)FF_QP2LAMBDA);
 
-#if FF_API_CODED_FRAME
+#if FF_API_CODED_FRAME && FF_API_ERROR_FRAME
 FF_DISABLE_DEPRECATION_WARNINGS
-        if (enc->flags&CODEC_FLAG_PSNR)
+        if (enc->flags & AV_CODEC_FLAG_PSNR)
             fprintf(vstats_file, "PSNR= %6.2f ", psnr(enc->coded_frame->error[0] / (enc->width * enc->height * 255.0 * 255.0)));
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
@@ -614,7 +638,7 @@ static int poll_filter(OutputStream *ost)
     filtered_frame = ost->filtered_frame;
 
     if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
-        !(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE))
+        !(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE))
         ret = av_buffersink_get_samples(ost->filter->filter, filtered_frame,
                                          ost->enc_ctx->frame_size);
     else
@@ -889,9 +913,9 @@ static void print_report(int is_last_report, int64_t timer_start)
                     snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%X", (int)lrintf(log2(qp_histogram[j] + 1)));
             }
 
-#if FF_API_CODED_FRAME
+#if FF_API_CODED_FRAME && FF_API_ERROR_FRAME
 FF_DISABLE_DEPRECATION_WARNINGS
-            if (enc->flags&CODEC_FLAG_PSNR) {
+            if (enc->flags & AV_CODEC_FLAG_PSNR) {
                 int j;
                 double error, error_sum = 0;
                 double scale, scale_sum = 0;
@@ -959,47 +983,46 @@ static void flush_encoders(void)
 
         if (enc->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1)
             continue;
-        if (enc->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == AV_CODEC_ID_RAWVIDEO)
+
+        if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO)
             continue;
 
+        avcodec_send_frame(enc, NULL);
+
         for (;;) {
-            int (*encode)(AVCodecContext*, AVPacket*, const AVFrame*, int*) = NULL;
-            const char *desc;
+            const char *desc = NULL;
 
             switch (enc->codec_type) {
             case AVMEDIA_TYPE_AUDIO:
-                encode = avcodec_encode_audio2;
                 desc   = "Audio";
                 break;
             case AVMEDIA_TYPE_VIDEO:
-                encode = avcodec_encode_video2;
                 desc   = "Video";
                 break;
             default:
-                stop_encoding = 1;
+                av_assert0(0);
             }
 
-            if (encode) {
+            if (1) {
                 AVPacket pkt;
-                int got_packet;
                 av_init_packet(&pkt);
                 pkt.data = NULL;
                 pkt.size = 0;
 
-                ret = encode(enc, &pkt, NULL, &got_packet);
-                if (ret < 0) {
+                ret = avcodec_receive_packet(enc, &pkt);
+                if (ret < 0 && ret != AVERROR_EOF) {
                     av_log(NULL, AV_LOG_FATAL, "%s encoding failed\n", desc);
                     exit_program(1);
                 }
                 if (ost->logfile && enc->stats_out) {
                     fprintf(ost->logfile, "%s", enc->stats_out);
                 }
-                if (!got_packet) {
+                if (ret == AVERROR_EOF) {
                     stop_encoding = 1;
                     break;
                 }
                 av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base);
-                write_frame(os, &pkt, ost);
+                output_packet(os, &pkt, ost);
             }
 
             if (stop_encoding)
@@ -1079,7 +1102,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
        && ost->enc_ctx->codec_id != AV_CODEC_ID_MPEG2VIDEO
        && ost->enc_ctx->codec_id != AV_CODEC_ID_VC1
        ) {
-        if (av_parser_change(ost->parser, ost->st->codec,
+        if (av_parser_change(ost->parser, ost->parser_avctx,
                              &opkt.data, &opkt.size,
                              pkt->data, pkt->size,
                              pkt->flags & AV_PKT_FLAG_KEY)) {
@@ -1092,7 +1115,34 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
         opkt.size = pkt->size;
     }
 
-    write_frame(of->ctx, &opkt, ost);
+    output_packet(of->ctx, &opkt, ost);
+}
+
+// This does not quite work like avcodec_decode_audio4/avcodec_decode_video2.
+// There is the following difference: if you got a frame, you must call
+// it again with pkt=NULL. pkt==NULL is treated differently from pkt.size==0
+// (pkt==NULL means get more output, pkt.size==0 is a flush/drain packet)
+static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt)
+{
+    int ret;
+
+    *got_frame = 0;
+
+    if (pkt) {
+        ret = avcodec_send_packet(avctx, pkt);
+        // In particular, we don't expect AVERROR(EAGAIN), because we read all
+        // decoded frames with avcodec_receive_frame() until done.
+        if (ret < 0)
+            return ret == AVERROR_EOF ? 0 : ret;
+    }
+
+    ret = avcodec_receive_frame(avctx, frame);
+    if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
+        return ret;
+    if (ret >= 0)
+        *got_frame = 1;
+
+    return 0;
 }
 
 int guess_input_channel_layout(InputStream *ist)
@@ -1107,7 +1157,7 @@ int guess_input_channel_layout(InputStream *ist)
             return 0;
         av_get_channel_layout_string(layout_name, sizeof(layout_name),
                                      dec->channels, dec->channel_layout);
-        av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for  Input Stream "
+        av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream "
                "#%d.%d : %s\n", ist->file_index, ist->st->index, layout_name);
     }
     return 1;
@@ -1125,7 +1175,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
         return AVERROR(ENOMEM);
     decoded_frame = ist->decoded_frame;
 
-    ret = avcodec_decode_audio4(avctx, decoded_frame, got_output, pkt);
+    ret = decode(avctx, decoded_frame, got_output, pkt);
     if (!*got_output || ret < 0)
         return ret;
 
@@ -1136,9 +1186,9 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
        the decoder could be delaying output by a packet or more. */
     if (decoded_frame->pts != AV_NOPTS_VALUE)
         ist->next_dts = decoded_frame->pts;
-    else if (pkt->pts != AV_NOPTS_VALUE)
+    else if (pkt && pkt->pts != AV_NOPTS_VALUE) {
         decoded_frame->pts = pkt->pts;
-    pkt->pts           = AV_NOPTS_VALUE;
+    }
 
     resample_changed = ist->resample_sample_fmt     != decoded_frame->format         ||
                        ist->resample_channels       != avctx->channels               ||
@@ -1185,6 +1235,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
         decoded_frame->pts = av_rescale_q(decoded_frame->pts,
                                           ist->st->time_base,
                                           (AVRational){1, avctx->sample_rate});
+    ist->nb_samples = decoded_frame->nb_samples;
     for (i = 0; i < ist->nb_filters; i++) {
         if (i < ist->nb_filters - 1) {
             f = ist->filter_frame;
@@ -1215,8 +1266,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
         return AVERROR(ENOMEM);
     decoded_frame = ist->decoded_frame;
 
-    ret = avcodec_decode_video2(ist->dec_ctx,
-                                decoded_frame, got_output, pkt);
+    ret = decode(ist->dec_ctx, decoded_frame, got_output, pkt);
     if (!*got_output || ret < 0)
         return ret;
 
@@ -1231,7 +1281,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
 
     decoded_frame->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pkt_pts,
                                            decoded_frame->pkt_dts);
-    pkt->size = 0;
 
     if (ist->st->sample_aspect_ratio.num)
         decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
@@ -1247,7 +1296,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
                decoded_frame->width, decoded_frame->height, av_get_pix_fmt_name(decoded_frame->format));
 
         ret = poll_filters();
-        if (ret < 0 && (ret != AVERROR_EOF && ret != AVERROR(EAGAIN))) {
+        if (ret < 0 && ret != AVERROR_EOF) {
             char errbuf[128];
             av_strerror(ret, errbuf, sizeof(errbuf));
 
@@ -1323,10 +1372,10 @@ static int send_filter_eof(InputStream *ist)
 }
 
 /* pkt = NULL means EOF (needed to flush decoder buffers) */
-static void process_input_packet(InputStream *ist, const AVPacket *pkt)
+static void process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof)
 {
     int i;
-    int got_output;
+    int repeating = 0;
     AVPacket avpkt;
 
     if (ist->next_dts == AV_NOPTS_VALUE)
@@ -1337,36 +1386,31 @@ static void process_input_packet(InputStream *ist, const AVPacket *pkt)
         av_init_packet(&avpkt);
         avpkt.data = NULL;
         avpkt.size = 0;
-        goto handle_eof;
     } else {
         avpkt = *pkt;
     }
 
-    if (pkt->dts != AV_NOPTS_VALUE)
+    if (pkt && pkt->dts != AV_NOPTS_VALUE)
         ist->next_dts = ist->last_dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
 
     // while we have more to decode or while the decoder did output something on EOF
-    while (ist->decoding_needed && (avpkt.size > 0 || (!pkt && got_output))) {
+    while (ist->decoding_needed && (!pkt || avpkt.size > 0)) {
         int ret = 0;
-    handle_eof:
+        int got_output = 0;
 
-        ist->last_dts = ist->next_dts;
-
-        if (avpkt.size && avpkt.size != pkt->size &&
-            !(ist->dec->capabilities & CODEC_CAP_SUBFRAMES)) {
-            av_log(NULL, ist->showed_multi_packet_warning ? AV_LOG_VERBOSE : AV_LOG_WARNING,
-                   "Multiple frames in a packet from stream %d\n", pkt->stream_index);
-            ist->showed_multi_packet_warning = 1;
-        }
+        if (!repeating)
+            ist->last_dts = ist->next_dts;
 
         switch (ist->dec_ctx->codec_type) {
         case AVMEDIA_TYPE_AUDIO:
-            ret = decode_audio    (ist, &avpkt, &got_output);
+            ret = decode_audio    (ist, repeating ? NULL : &avpkt, &got_output);
             break;
         case AVMEDIA_TYPE_VIDEO:
-            ret = decode_video    (ist, &avpkt, &got_output);
-            if (avpkt.duration)
-                ist->next_dts += av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q);
+            ret = decode_video    (ist, repeating ? NULL : &avpkt, &got_output);
+            if (repeating && !got_output)
+                ;
+            else if (pkt && pkt->duration)
+                ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
             else if (ist->st->avg_frame_rate.num)
                 ist->next_dts += av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate),
                                               AV_TIME_BASE_Q);
@@ -1377,6 +1421,8 @@ static void process_input_packet(InputStream *ist, const AVPacket *pkt)
             }
             break;
         case AVMEDIA_TYPE_SUBTITLE:
+            if (repeating)
+                break;
             ret = transcode_subtitles(ist, &avpkt, &got_output);
             break;
         default:
@@ -1391,18 +1437,15 @@ static void process_input_packet(InputStream *ist, const AVPacket *pkt)
             break;
         }
 
-        // touch data and size only if not EOF
-        if (pkt) {
-            avpkt.data += ret;
-            avpkt.size -= ret;
-        }
-        if (!got_output) {
-            continue;
-        }
+        if (!got_output)
+            break;
+
+        repeating = 1;
     }
 
     /* after flushing, send an EOF on all the filter inputs attached to the stream */
-    if (!pkt && ist->decoding_needed) {
+    /* except when looping we need to flush but not to send an EOF */
+    if (!pkt && ist->decoding_needed && !no_eof) {
         int ret = send_filter_eof(ist);
         if (ret < 0) {
             av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n");
@@ -1575,6 +1618,51 @@ static InputStream *get_input_stream(OutputStream *ost)
     return NULL;
 }
 
+static int init_output_bsfs(OutputStream *ost)
+{
+    AVBSFContext *ctx;
+    int i, ret;
+
+    if (!ost->nb_bitstream_filters)
+        return 0;
+
+    ost->bsf_ctx = av_mallocz_array(ost->nb_bitstream_filters, sizeof(*ost->bsf_ctx));
+    if (!ost->bsf_ctx)
+        return AVERROR(ENOMEM);
+
+    for (i = 0; i < ost->nb_bitstream_filters; i++) {
+        ret = av_bsf_alloc(ost->bitstream_filters[i], &ctx);
+        if (ret < 0) {
+            av_log(NULL, AV_LOG_ERROR, "Error allocating a bitstream filter context\n");
+            return ret;
+        }
+        ost->bsf_ctx[i] = ctx;
+
+        ret = avcodec_parameters_copy(ctx->par_in,
+                                      i ? ost->bsf_ctx[i - 1]->par_out : ost->st->codecpar);
+        if (ret < 0)
+            return ret;
+
+        ctx->time_base_in = i ? ost->bsf_ctx[i - 1]->time_base_out : ost->st->time_base;
+
+        ret = av_bsf_init(ctx);
+        if (ret < 0) {
+            av_log(NULL, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n",
+                   ost->bitstream_filters[i]->name);
+            return ret;
+        }
+    }
+
+    ctx = ost->bsf_ctx[ost->nb_bitstream_filters - 1];
+    ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out);
+    if (ret < 0)
+        return ret;
+
+    ost->st->time_base = ctx->time_base_out;
+
+    return 0;
+}
+
 static int init_output_stream(OutputStream *ost, char *error, int error_len)
 {
     int ret = 0;
@@ -1595,7 +1683,12 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
         }
         if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0))
             av_dict_set(&ost->encoder_opts, "threads", "auto", 0);
-        av_dict_set(&ost->encoder_opts, "side_data_only_packets", "1", 0);
+
+        if (ost->filter && ost->filter->filter->inputs[0]->hw_frames_ctx) {
+            ost->enc_ctx->hw_frames_ctx = av_buffer_ref(ost->filter->filter->inputs[0]->hw_frames_ctx);
+            if (!ost->enc_ctx->hw_frames_ctx)
+                return AVERROR(ENOMEM);
+        }
 
         if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) {
             if (ret == AVERROR_EXPERIMENTAL)
@@ -1611,21 +1704,57 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
             av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low."
                                          "It takes bits/s as argument, not kbits/s\n");
 
-        ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx);
+        ret = avcodec_parameters_from_context(ost->st->codecpar, ost->enc_ctx);
         if (ret < 0) {
             av_log(NULL, AV_LOG_FATAL,
                    "Error initializing the output stream codec context.\n");
             exit_program(1);
         }
 
+        if (ost->enc_ctx->nb_coded_side_data) {
+            int i;
+
+            ost->st->side_data = av_realloc_array(NULL, ost->enc_ctx->nb_coded_side_data,
+                                                  sizeof(*ost->st->side_data));
+            if (!ost->st->side_data)
+                return AVERROR(ENOMEM);
+
+            for (i = 0; i < ost->enc_ctx->nb_coded_side_data; i++) {
+                const AVPacketSideData *sd_src = &ost->enc_ctx->coded_side_data[i];
+                AVPacketSideData *sd_dst = &ost->st->side_data[i];
+
+                sd_dst->data = av_malloc(sd_src->size);
+                if (!sd_dst->data)
+                    return AVERROR(ENOMEM);
+                memcpy(sd_dst->data, sd_src->data, sd_src->size);
+                sd_dst->size = sd_src->size;
+                sd_dst->type = sd_src->type;
+                ost->st->nb_side_data++;
+            }
+        }
+
         ost->st->time_base = ost->enc_ctx->time_base;
     } else {
         ret = av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts);
         if (ret < 0)
             return ret;
-        ost->st->time_base = ost->st->codec->time_base;
+
+        /*
+         * FIXME: will the codec context used by the parser during streamcopy
+         * This should go away with the new parser API.
+         */
+        ret = avcodec_parameters_to_context(ost->parser_avctx, ost->st->codecpar);
+        if (ret < 0)
+            return ret;
     }
 
+    /* initialize bitstream filters for the output stream
+     * needs to be done here, because the codec id for streamcopy is not
+     * known until now */
+    ret = init_output_bsfs(ost);
+    if (ret < 0)
+        return ret;
+
     return ret;
 }
 
@@ -1707,8 +1836,6 @@ static int transcode_init(void)
 
     /* for each output stream, we compute the right encoding parameters */
     for (i = 0; i < nb_output_streams; i++) {
-        AVCodecContext *enc_ctx;
-        AVCodecContext *dec_ctx = NULL;
         ost = output_streams[i];
         oc  = output_files[ost->file_index]->ctx;
         ist = get_input_stream(ost);
@@ -1716,56 +1843,49 @@ static int transcode_init(void)
         if (ost->attachment_filename)
             continue;
 
-        enc_ctx = ost->stream_copy ? ost->st->codec : ost->enc_ctx;
-
         if (ist) {
-            dec_ctx = ist->dec_ctx;
-
             ost->st->disposition          = ist->st->disposition;
-            enc_ctx->bits_per_raw_sample    = dec_ctx->bits_per_raw_sample;
-            enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location;
         }
 
         if (ost->stream_copy) {
+            AVCodecParameters *par_dst = ost->st->codecpar;
+            AVCodecParameters *par_src = ist->st->codecpar;
             AVRational sar;
             uint64_t extra_size;
 
             av_assert0(ist && !ost->filter);
 
-            extra_size = (uint64_t)dec_ctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE;
+            extra_size = (uint64_t)par_src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE;
 
             if (extra_size > INT_MAX) {
                 return AVERROR(EINVAL);
             }
 
             /* if stream_copy is selected, no need to decode or encode */
-            enc_ctx->codec_id   = dec_ctx->codec_id;
-            enc_ctx->codec_type = dec_ctx->codec_type;
+            par_dst->codec_id   = par_src->codec_id;
+            par_dst->codec_type = par_src->codec_type;
 
-            if (!enc_ctx->codec_tag) {
+            if (!par_dst->codec_tag) {
                 if (!oc->oformat->codec_tag ||
-                     av_codec_get_id (oc->oformat->codec_tag, dec_ctx->codec_tag) == enc_ctx->codec_id ||
-                     av_codec_get_tag(oc->oformat->codec_tag, dec_ctx->codec_id) <= 0)
-                    enc_ctx->codec_tag = dec_ctx->codec_tag;
+                     av_codec_get_id (oc->oformat->codec_tag, par_src->codec_tag) == par_dst->codec_id ||
+                     av_codec_get_tag(oc->oformat->codec_tag, par_src->codec_id) <= 0)
+                    par_dst->codec_tag = par_src->codec_tag;
             }
 
-            enc_ctx->bit_rate       = dec_ctx->bit_rate;
-            enc_ctx->rc_max_rate    = dec_ctx->rc_max_rate;
-            enc_ctx->rc_buffer_size = dec_ctx->rc_buffer_size;
-            enc_ctx->field_order    = dec_ctx->field_order;
-            enc_ctx->extradata      = av_mallocz(extra_size);
-            if (!enc_ctx->extradata) {
-                return AVERROR(ENOMEM);
+            par_dst->bit_rate        = par_src->bit_rate;
+            par_dst->field_order     = par_src->field_order;
+            par_dst->chroma_location = par_src->chroma_location;
+            if (par_src->extradata != NULL) {
+                par_dst->extradata = av_mallocz(extra_size);
+                if (!par_dst->extradata) {
+                    return AVERROR(ENOMEM);
+                }
+                memcpy(par_dst->extradata, par_src->extradata,
+                       par_src->extradata_size);
+                par_dst->extradata_size = par_src->extradata_size;
             }
-            memcpy(enc_ctx->extradata, dec_ctx->extradata, dec_ctx->extradata_size);
-            enc_ctx->extradata_size = dec_ctx->extradata_size;
-            if (!copy_tb) {
-                enc_ctx->time_base      = dec_ctx->time_base;
-                enc_ctx->time_base.num *= dec_ctx->ticks_per_frame;
-                av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den,
-                          enc_ctx->time_base.num, enc_ctx->time_base.den, INT_MAX);
-            } else
-                enc_ctx->time_base = ist->st->time_base;
+
+            ost->st->time_base = ist->st->time_base;
 
             if (ist->st->nb_side_data) {
                 ost->st->side_data = av_realloc_array(NULL, ist->st->nb_side_data,
@@ -1787,37 +1907,37 @@ static int transcode_init(void)
                 }
             }
 
-            ost->parser = av_parser_init(enc_ctx->codec_id);
+            ost->parser = av_parser_init(par_dst->codec_id);
+            ost->parser_avctx = avcodec_alloc_context3(NULL);
+            if (!ost->parser_avctx)
+                return AVERROR(ENOMEM);
 
-            switch (enc_ctx->codec_type) {
+            switch (par_dst->codec_type) {
             case AVMEDIA_TYPE_AUDIO:
                 if (audio_volume != 256) {
                     av_log(NULL, AV_LOG_FATAL, "-acodec copy and -vol are incompatible (frames are not decoded)\n");
                     exit_program(1);
                 }
-                enc_ctx->channel_layout     = dec_ctx->channel_layout;
-                enc_ctx->sample_rate        = dec_ctx->sample_rate;
-                enc_ctx->channels           = dec_ctx->channels;
-                enc_ctx->frame_size         = dec_ctx->frame_size;
-                enc_ctx->audio_service_type = dec_ctx->audio_service_type;
-                enc_ctx->block_align        = dec_ctx->block_align;
+                par_dst->channel_layout     = par_src->channel_layout;
+                par_dst->sample_rate        = par_src->sample_rate;
+                par_dst->channels           = par_src->channels;
+                par_dst->block_align        = par_src->block_align;
                 break;
             case AVMEDIA_TYPE_VIDEO:
-                enc_ctx->pix_fmt            = dec_ctx->pix_fmt;
-                enc_ctx->width              = dec_ctx->width;
-                enc_ctx->height             = dec_ctx->height;
-                enc_ctx->has_b_frames       = dec_ctx->has_b_frames;
+                par_dst->format             = par_src->format;
+                par_dst->width              = par_src->width;
+                par_dst->height             = par_src->height;
                 if (ost->frame_aspect_ratio)
-                    sar = av_d2q(ost->frame_aspect_ratio * enc_ctx->height / enc_ctx->width, 255);
+                    sar = av_d2q(ost->frame_aspect_ratio * par_dst->height / par_dst->width, 255);
                 else if (ist->st->sample_aspect_ratio.num)
                     sar = ist->st->sample_aspect_ratio;
                 else
-                    sar = dec_ctx->sample_aspect_ratio;
-                ost->st->sample_aspect_ratio = enc_ctx->sample_aspect_ratio = sar;
+                    sar = par_src->sample_aspect_ratio;
+                ost->st->sample_aspect_ratio = par_dst->sample_aspect_ratio = sar;
                 break;
             case AVMEDIA_TYPE_SUBTITLE:
-                enc_ctx->width  = dec_ctx->width;
-                enc_ctx->height = dec_ctx->height;
+                par_dst->width  = par_src->width;
+                par_dst->height = par_src->height;
                 break;
             case AVMEDIA_TYPE_DATA:
             case AVMEDIA_TYPE_ATTACHMENT:
@@ -1826,6 +1946,9 @@ static int transcode_init(void)
                 abort();
             }
         } else {
+            AVCodecContext *enc_ctx = ost->enc_ctx;
+            AVCodecContext *dec_ctx = NULL;
+
             if (!ost->enc) {
                 /* should only happen when a default codec is not present. */
                 snprintf(error, sizeof(error), "Automatic encoder selection "
@@ -1839,6 +1962,13 @@ static int transcode_init(void)
 
             set_encoder_id(output_files[ost->file_index], ost);
 
+            if (ist) {
+                dec_ctx = ist->dec_ctx;
+
+                enc_ctx->bits_per_raw_sample    = dec_ctx->bits_per_raw_sample;
+                enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location;
+            }
+
             /*
              * We want CFR output if and only if one of those is true:
              * 1) user specified output framerate with -r
@@ -1873,6 +2003,11 @@ static int transcode_init(void)
                 }
             }
 
+#if CONFIG_LIBMFX
+            if (qsv_transcode_init(ost))
+                exit_program(1);
+#endif
+
             if (!ost->filter &&
                 (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
                  enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO)) {
@@ -1926,6 +2061,11 @@ static int transcode_init(void)
         }
     }
 
+    /* init input streams */
+    for (i = 0; i < nb_input_streams; i++)
+        if ((ret = init_input_stream(i, error, sizeof(error))) < 0)
+            goto dump_format;
+
     /* open each encoder */
     for (i = 0; i < nb_output_streams; i++) {
         ret = init_output_stream(output_streams[i], error, sizeof(error));
@@ -1933,10 +2073,6 @@ static int transcode_init(void)
             goto dump_format;
     }
 
-    /* init input streams */
-    for (i = 0; i < nb_input_streams; i++)
-        if ((ret = init_input_stream(i, error, sizeof(error))) < 0)
-            goto dump_format;
 
     /* discard unused programs */
     for (i = 0; i < nb_input_files; i++) {
@@ -2146,7 +2282,6 @@ static void *input_thread(void *arg)
         while (!av_fifo_space(f->fifo))
             pthread_cond_wait(&f->fifo_cond, &f->fifo_lock);
 
-        av_dup_packet(&pkt);
         av_fifo_generic_write(f->fifo, &pkt, sizeof(pkt), NULL);
 
         pthread_mutex_unlock(&f->fifo_lock);
@@ -2175,7 +2310,7 @@ static void free_input_threads(void)
         pthread_mutex_lock(&f->fifo_lock);
         while (av_fifo_size(f->fifo)) {
             av_fifo_generic_read(f->fifo, &pkt, sizeof(pkt), NULL);
-            av_free_packet(&pkt);
+            av_packet_unref(&pkt);
         }
         pthread_cond_signal(&f->fifo_cond);
         pthread_mutex_unlock(&f->fifo_lock);
@@ -2185,7 +2320,7 @@ static void free_input_threads(void)
 
         while (av_fifo_size(f->fifo)) {
             av_fifo_generic_read(f->fifo, &pkt, sizeof(pkt), NULL);
-            av_free_packet(&pkt);
+            av_packet_unref(&pkt);
         }
         av_fifo_free(f->fifo);
     }
@@ -2271,6 +2406,87 @@ static void reset_eagain(void)
         input_files[i]->eagain = 0;
 }
 
+// set duration to max(tmp, duration) in a proper time base and return duration's time_base
+static AVRational duration_max(int64_t tmp, int64_t *duration, AVRational tmp_time_base,
+                                AVRational time_base)
+{
+    int ret;
+
+    if (!*duration) {
+        *duration = tmp;
+        return tmp_time_base;
+    }
+
+    ret = av_compare_ts(*duration, time_base, tmp, tmp_time_base);
+    if (ret < 0) {
+        *duration = tmp;
+        return tmp_time_base;
+    }
+
+    return time_base;
+}
+
+static int seek_to_start(InputFile *ifile, AVFormatContext *is)
+{
+    InputStream *ist;
+    AVCodecContext *avctx;
+    int i, ret, has_audio = 0;
+    int64_t duration = 0;
+
+    ret = av_seek_frame(is, -1, is->start_time, 0);
+    if (ret < 0)
+        return ret;
+
+    for (i = 0; i < ifile->nb_streams; i++) {
+        ist   = input_streams[ifile->ist_index + i];
+        avctx = ist->dec_ctx;
+
+        // flush decoders
+        if (ist->decoding_needed) {
+            process_input_packet(ist, NULL, 1);
+            avcodec_flush_buffers(avctx);
+        }
+
+        /* duration is the length of the last frame in a stream
+         * when audio stream is present we don't care about
+         * last video frame length because it's not defined exactly */
+        if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && ist->nb_samples)
+            has_audio = 1;
+    }
+
+    for (i = 0; i < ifile->nb_streams; i++) {
+        ist   = input_streams[ifile->ist_index + i];
+        avctx = ist->dec_ctx;
+
+        if (has_audio) {
+            if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && ist->nb_samples) {
+                AVRational sample_rate = {1, avctx->sample_rate};
+
+                duration = av_rescale_q(ist->nb_samples, sample_rate, ist->st->time_base);
+            } else
+                continue;
+        } else {
+            if (ist->framerate.num) {
+                duration = av_rescale_q(1, ist->framerate, ist->st->time_base);
+            } else if (ist->st->avg_frame_rate.num) {
+                duration = av_rescale_q(1, ist->st->avg_frame_rate, ist->st->time_base);
+            } else duration = 1;
+        }
+        if (!ifile->duration)
+            ifile->time_base = ist->st->time_base;
+        /* the total duration of the stream, max_pts - min_pts is
+         * the duration of the stream without the last frame */
+        duration += ist->max_pts - ist->min_pts;
+        ifile->time_base = duration_max(duration, &ifile->duration, ist->st->time_base,
+                                        ifile->time_base);
+    }
+
+    if (ifile->loop > 0)
+        ifile->loop--;
+
+    return ret;
+}
+
 /*
  * Read one packet from an input file and send it for
  * - decoding -> lavfi (audio/video)
@@ -2290,6 +2506,7 @@ static int process_input(void)
     InputStream *ist;
     AVPacket pkt;
     int ret, i, j;
+    int64_t duration;
 
     /* select the stream that we must read now */
     ifile = select_input_file();
@@ -2311,6 +2528,11 @@ static int process_input(void)
         ifile->eagain = 1;
         return ret;
     }
+    if (ret < 0 && ifile->loop) {
+        if ((ret = seek_to_start(ifile, is)) < 0)
+            return ret;
+        ret = get_input_packet(ifile, &pkt);
+    }
     if (ret < 0) {
         if (ret != AVERROR_EOF) {
             print_error(is->filename, ret);
@@ -2322,7 +2544,7 @@ static int process_input(void)
         for (i = 0; i < ifile->nb_streams; i++) {
             ist = input_streams[ifile->ist_index + i];
             if (ist->decoding_needed)
-                process_input_packet(ist, NULL);
+                process_input_packet(ist, NULL, 0);
 
             /* mark all outputs that don't go through lavfi as finished */
             for (j = 0; j < nb_output_streams; j++) {
@@ -2401,11 +2623,20 @@ static int process_input(void)
                 pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
         }
     }
+    duration = av_rescale_q(ifile->duration, ifile->time_base, ist->st->time_base);
+    if (pkt.pts != AV_NOPTS_VALUE) {
+        pkt.pts += duration;
+        ist->max_pts = FFMAX(pkt.pts, ist->max_pts);
+        ist->min_pts = FFMIN(pkt.pts, ist->min_pts);
+    }
+
+    if (pkt.dts != AV_NOPTS_VALUE)
+        pkt.dts += duration;
 
-    process_input_packet(ist, &pkt);
+    process_input_packet(ist, &pkt, 0);
 
 discard_packet:
-    av_free_packet(&pkt);
+    av_packet_unref(&pkt);
 
     return 0;
 }
@@ -2450,16 +2681,12 @@ static int transcode(void)
         }
 
         ret = poll_filters();
-        if (ret < 0) {
-            if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) {
-                continue;
-            } else {
-                char errbuf[128];
-                av_strerror(ret, errbuf, sizeof(errbuf));
+        if (ret < 0 && ret != AVERROR_EOF) {
+            char errbuf[128];
+            av_strerror(ret, errbuf, sizeof(errbuf));
 
-                av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf);
-                break;
-            }
+            av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf);
+            break;
         }
 
         /* dump report by using the output first video and audio streams */
@@ -2473,7 +2700,7 @@ static int transcode(void)
     for (i = 0; i < nb_input_streams; i++) {
         ist = input_streams[i];
         if (!input_files[ist->file_index]->eof_reached && ist->decoding_needed) {
-            process_input_packet(ist, NULL);
+            process_input_packet(ist, NULL, 0);
         }
     }
     poll_filters();
@@ -2508,6 +2735,8 @@ static int transcode(void)
         }
     }
 
+    av_buffer_unref(&hw_device_ctx);
+
     /* finished ! */
     ret = 0;