Newer
Older
Marton Balint
committed
check_decode_result(ist, got_output, ret);
if (!*got_output || ret < 0)
return ret;
ist->samples_decoded += decoded_frame->nb_samples;
ist->frames_decoded++;
#if 1
/* increment next_dts to use for the case where the input stream does not
have timestamps or there are multiple frames in the packet */
ist->next_pts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) /
avctx->sample_rate;
ist->next_dts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) /
avctx->sample_rate;
#endif
resample_changed = ist->resample_sample_fmt != decoded_frame->format ||
ist->resample_channels != avctx->channels ||
ist->resample_channel_layout != decoded_frame->channel_layout ||
ist->resample_sample_rate != decoded_frame->sample_rate;
if (resample_changed) {
char layout1[64], layout2[64];
if (!guess_input_channel_layout(ist)) {
av_log(NULL, AV_LOG_FATAL, "Unable to find default channel "
"layout for Input Stream #%d.%d\n", ist->file_index,
ist->st->index);
}
decoded_frame->channel_layout = avctx->channel_layout;
av_get_channel_layout_string(layout1, sizeof(layout1), ist->resample_channels,
ist->resample_channel_layout);
av_get_channel_layout_string(layout2, sizeof(layout2), avctx->channels,
decoded_frame->channel_layout);
av_log(NULL, AV_LOG_INFO,
"Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d chl:%s to rate:%d fmt:%s ch:%d chl:%s\n",
ist->file_index, ist->st->index,
ist->resample_sample_rate, av_get_sample_fmt_name(ist->resample_sample_fmt),
ist->resample_channels, layout1,
decoded_frame->sample_rate, av_get_sample_fmt_name(decoded_frame->format),
avctx->channels, layout2);
ist->resample_sample_fmt = decoded_frame->format;
ist->resample_sample_rate = decoded_frame->sample_rate;
ist->resample_channel_layout = decoded_frame->channel_layout;
ist->resample_channels = avctx->channels;
for (i = 0; i < nb_filtergraphs; i++)
if (ist_in_filtergraph(filtergraphs[i], ist)) {
FilterGraph *fg = filtergraphs[i];
if (configure_filtergraph(fg) < 0) {
av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n");
exit_program(1);
/* if the decoder provides a pts, use it instead of the last packet pts.
the decoder could be delaying output by a packet or more. */
if (decoded_frame->pts != AV_NOPTS_VALUE) {
ist->dts = ist->next_dts = ist->pts = ist->next_pts = av_rescale_q(decoded_frame->pts, avctx->time_base, AV_TIME_BASE_Q);
decoded_frame_tb = avctx->time_base;
} else if (decoded_frame->pkt_pts != AV_NOPTS_VALUE) {
decoded_frame->pts = decoded_frame->pkt_pts;
decoded_frame_tb = ist->st->time_base;
} else if (pkt->pts != AV_NOPTS_VALUE) {
decoded_frame->pts = pkt->pts;
decoded_frame_tb = ist->st->time_base;
}else {
decoded_frame->pts = ist->dts;
decoded_frame_tb = AV_TIME_BASE_Q;
}
pkt->pts = AV_NOPTS_VALUE;
if (decoded_frame->pts != AV_NOPTS_VALUE)
decoded_frame->pts = av_rescale_delta(decoded_frame_tb, decoded_frame->pts,
(AVRational){1, avctx->sample_rate}, decoded_frame->nb_samples, &ist->filter_in_rescale_delta_last,
(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;
err = av_frame_ref(f, decoded_frame);
if (err < 0)
break;
} else
f = decoded_frame;
err = av_buffersrc_add_frame_flags(ist->filters[i]->filter, f,
if (err == AVERROR_EOF)
err = 0; /* ignore */
if (err < 0)
break;
}
decoded_frame->pts = AV_NOPTS_VALUE;
av_frame_unref(ist->filter_frame);
av_frame_unref(decoded_frame);
return err < 0 ? err : ret;
static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
AVFrame *decoded_frame, *f;
int i, ret = 0, err = 0, resample_changed;
int64_t best_effort_timestamp;
AVRational *frame_sample_aspect;
if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc()))
return AVERROR(ENOMEM);
if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc()))
return AVERROR(ENOMEM);
decoded_frame = ist->decoded_frame;
pkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base);
update_benchmark(NULL);
ret = avcodec_decode_video2(ist->dec_ctx,
decoded_frame, got_output, pkt);
update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index);
// The following line may be required in some cases where there is no parser
// or the parser does not has_b_frames correctly
if (ist->st->codecpar->video_delay < ist->dec_ctx->has_b_frames) {
if (ist->dec_ctx->codec_id == AV_CODEC_ID_H264) {
ist->st->codecpar->video_delay = ist->dec_ctx->has_b_frames;
av_log(ist->dec_ctx, AV_LOG_WARNING,
"video_delay is larger in decoder than demuxer %d > %d.\n"
"If you want to help, upload a sample "
"of this file to ftp://upload.ffmpeg.org/incoming/ "
"and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)",
ist->dec_ctx->has_b_frames,
}
Marton Balint
committed
check_decode_result(ist, got_output, ret);
Michael Niedermayer
committed
if (*got_output && ret >= 0) {
if (ist->dec_ctx->width != decoded_frame->width ||
ist->dec_ctx->height != decoded_frame->height ||
ist->dec_ctx->pix_fmt != decoded_frame->format) {
av_log(NULL, AV_LOG_DEBUG, "Frame parameters mismatch context %d,%d,%d != %d,%d,%d\n",
decoded_frame->width,
decoded_frame->height,
decoded_frame->format,
ist->dec_ctx->width,
ist->dec_ctx->height,
ist->dec_ctx->pix_fmt);
}
}
if (!*got_output || ret < 0)
return ret;
if(ist->top_field_first>=0)
decoded_frame->top_field_first = ist->top_field_first;
ist->frames_decoded++;
if (ist->hwaccel_retrieve_data && decoded_frame->format == ist->hwaccel_pix_fmt) {
err = ist->hwaccel_retrieve_data(ist->dec_ctx, decoded_frame);
if (err < 0)
goto fail;
}
ist->hwaccel_retrieved_pix_fmt = decoded_frame->format;
best_effort_timestamp= av_frame_get_best_effort_timestamp(decoded_frame);
if(best_effort_timestamp != AV_NOPTS_VALUE) {
int64_t ts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q);
if (ts != AV_NOPTS_VALUE)
ist->next_pts = ist->pts = ts;
}
if (debug_ts) {
av_log(NULL, AV_LOG_INFO, "decoder -> ist_index:%d type:video "
"frame_pts:%s frame_pts_time:%s best_effort_ts:%"PRId64" best_effort_ts_time:%s keyframe:%d frame_type:%d time_base:%d/%d\n",
ist->st->index, av_ts2str(decoded_frame->pts),
av_ts2timestr(decoded_frame->pts, &ist->st->time_base),
best_effort_timestamp,
av_ts2timestr(best_effort_timestamp, &ist->st->time_base),
decoded_frame->key_frame, decoded_frame->pict_type,
ist->st->time_base.num, ist->st->time_base.den);
if (ist->st->sample_aspect_ratio.num)
decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
resample_changed = ist->resample_width != decoded_frame->width ||
ist->resample_height != decoded_frame->height ||
ist->resample_pix_fmt != decoded_frame->format;
if (resample_changed) {
av_log(NULL, AV_LOG_INFO,
"Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",
ist->file_index, ist->st->index,
ist->resample_width, ist->resample_height, av_get_pix_fmt_name(ist->resample_pix_fmt),
decoded_frame->width, decoded_frame->height, av_get_pix_fmt_name(decoded_frame->format));
ist->resample_width = decoded_frame->width;
ist->resample_height = decoded_frame->height;
ist->resample_pix_fmt = decoded_frame->format;
for (i = 0; i < nb_filtergraphs; i++) {
if (ist_in_filtergraph(filtergraphs[i], ist) && ist->reinit_filters &&
configure_filtergraph(filtergraphs[i]) < 0) {
av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n");
frame_sample_aspect= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "sample_aspect_ratio");
for (i = 0; i < ist->nb_filters; i++) {
if (!frame_sample_aspect->num)
*frame_sample_aspect = ist->st->sample_aspect_ratio;
if (i < ist->nb_filters - 1) {
f = ist->filter_frame;
err = av_frame_ref(f, decoded_frame);
if (err < 0)
break;
Stefano Sabatini
committed
ret = av_buffersrc_add_frame_flags(ist->filters[i]->filter, f, AV_BUFFERSRC_FLAG_PUSH);
if (ret == AVERROR_EOF) {
ret = 0; /* ignore */
} else if (ret < 0) {
Stefano Sabatini
committed
av_log(NULL, AV_LOG_FATAL,
"Failed to inject frame into filter network: %s\n", av_err2str(ret));
exit_program(1);
av_frame_unref(ist->filter_frame);
av_frame_unref(decoded_frame);
return err < 0 ? err : ret;
static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
AVSubtitle subtitle;
int i, ret = avcodec_decode_subtitle2(ist->dec_ctx,
&subtitle, got_output, pkt);
Marton Balint
committed
check_decode_result(NULL, got_output, ret);
if (ret < 0 || !*got_output) {
if (!pkt->size)
sub2video_flush(ist);
return ret;
Leon van Stuivenberg
committed
}
if (ist->fix_sub_duration) {
Marton Balint
committed
int end = 1;
if (ist->prev_sub.got_output) {
Marton Balint
committed
end = av_rescale(subtitle.pts - ist->prev_sub.subtitle.pts,
1000, AV_TIME_BASE);
if (end < ist->prev_sub.subtitle.end_display_time) {
Michael Niedermayer
committed
av_log(ist->dec_ctx, AV_LOG_DEBUG,
Marton Balint
committed
"Subtitle duration reduced from %d to %d%s\n",
ist->prev_sub.subtitle.end_display_time, end,
end <= 0 ? ", dropping it" : "");
ist->prev_sub.subtitle.end_display_time = end;
}
}
FFSWAP(int, *got_output, ist->prev_sub.got_output);
FFSWAP(int, ret, ist->prev_sub.ret);
FFSWAP(AVSubtitle, subtitle, ist->prev_sub.subtitle);
Marton Balint
committed
if (end <= 0)
goto out;
if (!*got_output)
return ret;
sub2video_update(ist, &subtitle);
if (!subtitle.num_rects)
ist->frames_decoded++;
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
if (!check_output_constraints(ist, ost) || !ost->encoding_needed
|| ost->enc->type != AVMEDIA_TYPE_SUBTITLE)
do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle);
avsubtitle_free(&subtitle);
return ret;
static int send_filter_eof(InputStream *ist)
{
int i, ret;
for (i = 0; i < ist->nb_filters; i++) {
ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL);
if (ret < 0)
return ret;
}
return 0;
}
/* pkt = NULL means EOF (needed to flush decoder buffers) */
static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof)
Michael Niedermayer
committed
int got_output = 0;
if (!ist->saw_first_ts) {
Michael Niedermayer
committed
ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
if (pkt && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) {
ist->dts += av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);
ist->pts = ist->dts; //unused but better to set it to a value thats not totally wrong
ist->saw_first_ts = 1;
}
if (ist->next_dts == AV_NOPTS_VALUE)
ist->next_dts = ist->dts;
if (ist->next_pts == AV_NOPTS_VALUE)
ist->next_pts = ist->pts;
Michael Niedermayer
committed
if (!pkt) {
/* EOF handling */
av_init_packet(&avpkt);
avpkt.data = NULL;
avpkt.size = 0;
goto handle_eof;
} else {
avpkt = *pkt;
}
if (pkt->dts != AV_NOPTS_VALUE) {
ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
Michael Niedermayer
committed
if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed)
ist->next_pts = ist->pts = ist->dts;
// 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))) {
ist->pts = ist->next_pts;
ist->dts = ist->next_dts;
switch (ist->dec_ctx->codec_type) {
case AVMEDIA_TYPE_AUDIO:
ret = decode_audio (ist, &avpkt, &got_output);
break;
case AVMEDIA_TYPE_VIDEO:
ret = decode_video (ist, &avpkt, &got_output);
if (avpkt.duration) {
duration = av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q);
} else if(ist->dec_ctx->framerate.num != 0 && ist->dec_ctx->framerate.den != 0) {
int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict+1 : ist->dec_ctx->ticks_per_frame;
duration = ((int64_t)AV_TIME_BASE *
ist->dec_ctx->framerate.den * ticks) /
ist->dec_ctx->framerate.num / ist->dec_ctx->ticks_per_frame;
} else
duration = 0;
if(ist->dts != AV_NOPTS_VALUE && duration) {
ist->next_dts += duration;
}else
ist->next_dts = AV_NOPTS_VALUE;
Fabrice Bellard
committed
if (got_output)
ist->next_pts += duration; //FIXME the duration is not correct in some cases
break;
case AVMEDIA_TYPE_SUBTITLE:
ret = transcode_subtitles(ist, &avpkt, &got_output);
break;
Fabrice Bellard
committed
}
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n",
ist->file_index, ist->st->index, av_err2str(ret));
if (exit_on_error)
exit_program(1);
break;
}
Michael Niedermayer
committed
avpkt.dts=
avpkt.pts= AV_NOPTS_VALUE;
// touch data and size only if not EOF
if (pkt) {
Michael Niedermayer
committed
if(ist->dec_ctx->codec_type != AVMEDIA_TYPE_AUDIO)
avpkt.data += ret;
avpkt.size -= ret;
if (!got_output) {
if (got_output && !pkt)
break;
/* after flushing, send an EOF on all the filter inputs attached to the stream */
/* except when looping we need to flush but not to send an EOF */
if (!pkt && ist->decoding_needed && !got_output && !no_eof) {
int ret = send_filter_eof(ist);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n");
exit_program(1);
}
}
/* handle stream copy */
if (!ist->decoding_needed) {
ist->dts = ist->next_dts;
switch (ist->dec_ctx->codec_type) {
case AVMEDIA_TYPE_AUDIO:
ist->next_dts += ((int64_t)AV_TIME_BASE * ist->dec_ctx->frame_size) /
ist->dec_ctx->sample_rate;
break;
case AVMEDIA_TYPE_VIDEO:
if (ist->framerate.num) {
Carl Eugen Hoyos
committed
// TODO: Remove work-around for c99-to-c89 issue 7
AVRational time_base_q = AV_TIME_BASE_Q;
int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate));
ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q);
} else if (pkt->duration) {
ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
} else if(ist->dec_ctx->framerate.num != 0) {
int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict + 1 : ist->dec_ctx->ticks_per_frame;
ist->next_dts += ((int64_t)AV_TIME_BASE *
ist->dec_ctx->framerate.den * ticks) /
ist->dec_ctx->framerate.num / ist->dec_ctx->ticks_per_frame;
ist->pts = ist->dts;
ist->next_pts = ist->next_dts;
for (i = 0; pkt && i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
Michael Niedermayer
committed
if (!check_output_constraints(ist, ost) || ost->encoding_needed)
continue;
Todd Kirby
committed
do_streamcopy(ist, ost, pkt);
}
Fabrice Bellard
committed
return got_output;
static void print_sdp(void)
char sdp[16384];
Anton Khirnov
committed
int i;
AVFormatContext **avc = av_malloc_array(nb_output_files, sizeof(*avc));
Anton Khirnov
committed
if (!avc)
for (i = 0, j = 0; i < nb_output_files; i++) {
if (!strcmp(output_files[i]->ctx->oformat->name, "rtp")) {
avc[j] = output_files[i]->ctx;
j++;
}
}
Simon Thelen
committed
if (!j)
goto fail;
av_sdp_create(avc, j, sdp, sizeof(sdp));
if (!sdp_filename) {
printf("SDP:\n%s\n", sdp);
fflush(stdout);
} else {
if (avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL) < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename);
} else {
avio_printf(sdp_pb, "SDP:\n%s", sdp);
avio_closep(&sdp_pb);
av_freep(&sdp_filename);
Simon Thelen
committed
fail:
Anton Khirnov
committed
av_freep(&avc);
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt)
{
int i;
for (i = 0; hwaccels[i].name; i++)
if (hwaccels[i].pix_fmt == pix_fmt)
return &hwaccels[i];
return NULL;
}
static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts)
{
InputStream *ist = s->opaque;
const enum AVPixelFormat *p;
int ret;
for (p = pix_fmts; *p != -1; p++) {
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p);
const HWAccel *hwaccel;
if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
break;
hwaccel = get_hwaccel(*p);
if (!hwaccel ||
(ist->active_hwaccel_id && ist->active_hwaccel_id != hwaccel->id) ||
(ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != hwaccel->id))
continue;
ret = hwaccel->init(s);
if (ret < 0) {
if (ist->hwaccel_id == hwaccel->id) {
av_log(NULL, AV_LOG_FATAL,
"%s hwaccel requested for input stream #%d:%d, "
"but cannot be initialized.\n", hwaccel->name,
ist->file_index, ist->st->index);
return AV_PIX_FMT_NONE;
if (ist->hw_frames_ctx) {
s->hw_frames_ctx = av_buffer_ref(ist->hw_frames_ctx);
if (!s->hw_frames_ctx)
return AV_PIX_FMT_NONE;
}
ist->active_hwaccel_id = hwaccel->id;
ist->hwaccel_pix_fmt = *p;
break;
}
return *p;
}
static int get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
{
InputStream *ist = s->opaque;
if (ist->hwaccel_get_buffer && frame->format == ist->hwaccel_pix_fmt)
return ist->hwaccel_get_buffer(s, frame, flags);
return avcodec_default_get_buffer2(s, frame, flags);
}
static int init_input_stream(int ist_index, char *error, int error_len)
InputStream *ist = input_streams[ist_index];
if (ist->decoding_needed) {
AVCodec *codec = ist->dec;
if (!codec) {
snprintf(error, error_len, "Decoder (codec %s) not found for input stream #%d:%d",
avcodec_get_name(ist->dec_ctx->codec_id), ist->file_index, ist->st->index);
ist->dec_ctx->opaque = ist;
ist->dec_ctx->get_format = get_format;
ist->dec_ctx->get_buffer2 = get_buffer;
ist->dec_ctx->thread_safe_callbacks = 1;
av_opt_set_int(ist->dec_ctx, "refcounted_frames", 1, 0);
Michael Niedermayer
committed
if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE &&
(ist->decoding_needed & DECODING_FOR_OST)) {
av_dict_set(&ist->decoder_opts, "compute_edt", "1", AV_DICT_DONT_OVERWRITE);
Michael Niedermayer
committed
if (ist->decoding_needed & DECODING_FOR_FILTER)
av_log(NULL, AV_LOG_WARNING, "Warning using DVB subtitles for filtering and output at the same time is not fully supported, also see -compute_edt [0|1]\n");
}
av_dict_set(&ist->decoder_opts, "sub_text_format", "ass", AV_DICT_DONT_OVERWRITE);
/* Useful for subtitles retiming by lavf (FIXME), skipping samples in
* audio, and video decoders such as cuvid or mediacodec */
av_codec_set_pkt_timebase(ist->dec_ctx, ist->st->time_base);
if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0))
av_dict_set(&ist->decoder_opts, "threads", "auto", 0);
if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) {
if (ret == AVERROR_EXPERIMENTAL)
abort_codec_experimental(codec, 0);
snprintf(error, error_len,
"Error while opening decoder for input stream "
"#%d:%d : %s",
ist->file_index, ist->st->index, av_err2str(ret));
assert_avoptions(ist->decoder_opts);
ist->next_pts = AV_NOPTS_VALUE;
ist->next_dts = AV_NOPTS_VALUE;
static InputStream *get_input_stream(OutputStream *ost)
if (ost->source_index >= 0)
return input_streams[ost->source_index];
return NULL;
static int compare_int64(const void *a, const void *b)
{
Ganesh Ajjanagadde
committed
return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b);
static int init_output_bsfs(OutputStream *ost)
{
AVBSFContext *ctx;
int i, ret;
if (!ost->nb_bitstream_filters)
return 0;
for (i = 0; i < ost->nb_bitstream_filters; i++) {
ctx = ost->bsf_ctx[i];
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->bsf_ctx[i]->filter->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;
}
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
static int init_output_stream_streamcopy(OutputStream *ost)
{
OutputFile *of = output_files[ost->file_index];
InputStream *ist = get_input_stream(ost);
AVCodecParameters *par_dst = ost->st->codecpar;
AVCodecParameters *par_src = ost->ref_par;
AVRational sar;
int i, ret;
uint64_t extra_size;
av_assert0(ist && !ost->filter);
avcodec_parameters_to_context(ost->enc_ctx, ist->st->codecpar);
ret = av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL,
"Error setting up codec context options.\n");
return ret;
}
avcodec_parameters_from_context(par_src, ost->enc_ctx);
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 */
par_dst->codec_id = par_src->codec_id;
par_dst->codec_type = par_src->codec_type;
if (!par_dst->codec_tag) {
unsigned int codec_tag;
if (!of->ctx->oformat->codec_tag ||
av_codec_get_id (of->ctx->oformat->codec_tag, par_src->codec_tag) == par_dst->codec_id ||
!av_codec_get_tag2(of->ctx->oformat->codec_tag, par_src->codec_id, &codec_tag))
par_dst->codec_tag = par_src->codec_tag;
}
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_size) {
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;
}
par_dst->bits_per_coded_sample = par_src->bits_per_coded_sample;
par_dst->bits_per_raw_sample = par_src->bits_per_raw_sample;
if (!ost->frame_rate.num)
ost->frame_rate = ist->framerate;
ost->st->avg_frame_rate = ost->frame_rate;
ret = avformat_transfer_internal_stream_timing_info(of->ctx->oformat, ost->st, ist->st, copy_tb);
if (ret < 0)
return ret;
// copy timebase while removing common factors
ost->st->time_base = av_add_q(av_stream_get_codec_timebase(ost->st), (AVRational){0, 1});
if (ist->st->nb_side_data) {
ost->st->side_data = av_realloc_array(NULL, ist->st->nb_side_data,
sizeof(*ist->st->side_data));
if (!ost->st->side_data)
return AVERROR(ENOMEM);
ost->st->nb_side_data = 0;
for (i = 0; i < ist->st->nb_side_data; i++) {
const AVPacketSideData *sd_src = &ist->st->side_data[i];
AVPacketSideData *sd_dst = &ost->st->side_data[ost->st->nb_side_data];
if (ost->rotate_overridden && sd_src->type == AV_PKT_DATA_DISPLAYMATRIX)
continue;
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->parser = av_parser_init(par_dst->codec_id);
ost->parser_avctx = avcodec_alloc_context3(NULL);
if (!ost->parser_avctx)
return AVERROR(ENOMEM);
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);
}
par_dst->channel_layout = par_src->channel_layout;
par_dst->sample_rate = par_src->sample_rate;
par_dst->channels = par_src->channels;
par_dst->frame_size = par_src->frame_size;
par_dst->block_align = par_src->block_align;
par_dst->initial_padding = par_src->initial_padding;
par_dst->trailing_padding = par_src->trailing_padding;
par_dst->profile = par_src->profile;
if((par_dst->block_align == 1 || par_dst->block_align == 1152 || par_dst->block_align == 576) && par_dst->codec_id == AV_CODEC_ID_MP3)
par_dst->block_align= 0;
if(par_dst->codec_id == AV_CODEC_ID_AC3)
par_dst->block_align= 0;
break;
case AVMEDIA_TYPE_VIDEO:
par_dst->format = par_src->format;
par_dst->color_space = par_src->color_space;
par_dst->color_range = par_src->color_range;
par_dst->color_primaries = par_src->color_primaries;
par_dst->color_trc = par_src->color_trc;
par_dst->width = par_src->width;
par_dst->height = par_src->height;
par_dst->video_delay = par_src->video_delay;
par_dst->profile = par_src->profile;
if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option
sar =
av_mul_q(ost->frame_aspect_ratio,
(AVRational){ par_dst->height, par_dst->width });
av_log(NULL, AV_LOG_WARNING, "Overriding aspect ratio "
"with stream copy may produce invalid files\n");
}
else if (ist->st->sample_aspect_ratio.num)
sar = ist->st->sample_aspect_ratio;
else
sar = par_src->sample_aspect_ratio;
ost->st->sample_aspect_ratio = par_dst->sample_aspect_ratio = sar;
ost->st->avg_frame_rate = ist->st->avg_frame_rate;
ost->st->r_frame_rate = ist->st->r_frame_rate;
break;
case AVMEDIA_TYPE_SUBTITLE:
par_dst->width = par_src->width;
par_dst->height = par_src->height;
break;
case AVMEDIA_TYPE_UNKNOWN:
case AVMEDIA_TYPE_DATA:
case AVMEDIA_TYPE_ATTACHMENT:
break;
default:
abort();
}
return 0;
}
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
static int init_output_stream(OutputStream *ost, char *error, int error_len)
{
int ret = 0;
if (ost->encoding_needed) {
AVCodec *codec = ost->enc;
AVCodecContext *dec = NULL;
InputStream *ist;
if ((ist = get_input_stream(ost)))
dec = ist->dec_ctx;
if (dec && dec->subtitle_header) {
/* ASS code assumes this buffer is null terminated so add extra byte. */
ost->enc_ctx->subtitle_header = av_mallocz(dec->subtitle_header_size + 1);
if (!ost->enc_ctx->subtitle_header)
return AVERROR(ENOMEM);
memcpy(ost->enc_ctx->subtitle_header, dec->subtitle_header, dec->subtitle_header_size);
ost->enc_ctx->subtitle_header_size = dec->subtitle_header_size;
}
if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0))
av_dict_set(&ost->encoder_opts, "threads", "auto", 0);
Michael Niedermayer
committed
if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
!codec->defaults &&
!av_dict_get(ost->encoder_opts, "b", NULL, 0) &&
!av_dict_get(ost->encoder_opts, "ab", NULL, 0))
av_dict_set(&ost->encoder_opts, "b", "128000", 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)
abort_codec_experimental(codec, 1);
snprintf(error, error_len,
"Error while opening encoder for output stream #%d:%d - "
"maybe incorrect parameters such as bit_rate, rate, width or height",
ost->file_index, ost->index);
return ret;
}
if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
!(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE))
av_buffersink_set_frame_size(ost->filter->filter,
ost->enc_ctx->frame_size);
assert_avoptions(ost->encoder_opts);
if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000)
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_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);
}
* FIXME: ost->st->codec should't be needed here anymore.
*/
ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx);
if (ret < 0)
return ret;
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
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++;
}
}
// copy timebase while removing common factors
ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1});
ost->st->codec->codec= ost->enc_ctx->codec;
} else if (ost->stream_copy) {
ret = init_output_stream_streamcopy(ost);
if (ret < 0)
return ret;
* 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);
/* 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;
}
static void parse_forced_key_frames(char *kf, OutputStream *ost,
AVCodecContext *avctx)
int n = 1, i, size, index = 0;
int64_t t, *pts;
for (p = kf; *p; p++)
if (*p == ',')
n++;
pts = av_malloc_array(size, sizeof(*pts));
av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
char *next = strchr(p, ',');
if (next)
*next++ = 0;
if (!memcmp(p, "chapters", 8)) {
AVFormatContext *avf = output_files[ost->file_index]->ctx;
int j;
if (avf->nb_chapters > INT_MAX - size ||
!(pts = av_realloc_f(pts, size += avf->nb_chapters - 1,
sizeof(*pts)))) {
av_log(NULL, AV_LOG_FATAL,
"Could not allocate forced key frames array.\n");
exit_program(1);
}
t = p[8] ? parse_time_or_die("force_key_frames", p + 8, 1) : 0;
t = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
for (j = 0; j < avf->nb_chapters; j++) {
AVChapter *c = avf->chapters[j];
av_assert1(index < size);
pts[index++] = av_rescale_q(c->start, c->time_base,
avctx->time_base) + t;
}
} else {
t = parse_time_or_die("force_key_frames", p, 1);
av_assert1(index < size);
pts[index++] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
}
av_assert0(index == size);
qsort(pts, size, sizeof(*pts), compare_int64);
ost->forced_kf_count = size;
ost->forced_kf_pts = pts;
static void report_new_stream(int input_index, AVPacket *pkt)
InputFile *file = input_files[input_index];