Newer
Older
if (ist->dec_ctx->codec_id == AV_CODEC_ID_H264) {
ist->st->codec->has_b_frames = ist->dec_ctx->has_b_frames;
} else
av_log_ask_for_sample(
ist->dec_ctx,
"has_b_frames is larger in decoder than demuxer %d > %d ",
ist->dec_ctx->has_b_frames,
ist->st->codec->has_b_frames
);
}
if (*got_output || ret<0)
decode_error_stat[ret<0] ++;
if (ret < 0 && exit_on_error)
exit_program(1);
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)
ist->next_pts = ist->pts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q);
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);
if (*got_output || ret<0)
decode_error_stat[ret<0] ++;
if (ret < 0 && exit_on_error)
exit_program(1);
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++) {
#if 1
ret = av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0);
#else
ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL);
#endif
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)
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;
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;
Fabrice Bellard
committed
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 */
if (!pkt && ist->decoding_needed && !got_output) {
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++;
}
}
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);
Anton Khirnov
committed
av_freep(&avc);
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
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;
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
}
continue;
}
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");
}
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)
{
int64_t va = *(int64_t *)a, vb = *(int64_t *)b;
return va < vb ? -1 : va > vb ? +1 : 0;
}
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];
AVStream *st = file->ctx->streams[pkt->stream_index];
if (pkt->stream_index < file->nb_streams_warn)
return;
av_log(file->ctx, AV_LOG_WARNING,
"New %s stream %d:%d at pos:%"PRId64" and DTS:%ss\n",
av_get_media_type_string(st->codec->codec_type),
input_index, pkt->stream_index,
pkt->pos, av_ts2timestr(pkt->dts, &st->time_base));
file->nb_streams_warn = pkt->stream_index + 1;
static void set_encoder_id(OutputFile *of, OutputStream *ost)
{
AVDictionaryEntry *e;
uint8_t *encoder_string;
int encoder_string_len;
int format_flags = 0;
int codec_flags = 0;
Michael Niedermayer
committed
if (av_dict_get(ost->st->metadata, "encoder", NULL, 0))
return;
e = av_dict_get(of->opts, "fflags", NULL, 0);
if (e) {
const AVOption *o = av_opt_find(of->ctx, "fflags", NULL, 0, 0);
if (!o)
return;
av_opt_eval_flags(of->ctx, o, e->value, &format_flags);
}
e = av_dict_get(ost->encoder_opts, "flags", NULL, 0);
if (e) {
const AVOption *o = av_opt_find(ost->enc_ctx, "flags", NULL, 0, 0);
if (!o)
return;
av_opt_eval_flags(ost->enc_ctx, o, e->value, &codec_flags);
encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(ost->enc->name) + 2;
encoder_string = av_mallocz(encoder_string_len);
if (!encoder_string)
exit_program(1);
if (!(format_flags & AVFMT_FLAG_BITEXACT) && !(codec_flags & CODEC_FLAG_BITEXACT))
av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len);
else
av_strlcpy(encoder_string, "Lavc ", encoder_string_len);
av_strlcat(encoder_string, ost->enc->name, encoder_string_len);
av_dict_set(&ost->st->metadata, "encoder", encoder_string,
AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
}
static int transcode_init(void)
int ret = 0, i, j, k;
OutputStream *ost;
char error[1024] = {0};
for (i = 0; i < nb_filtergraphs; i++) {
FilterGraph *fg = filtergraphs[i];
for (j = 0; j < fg->nb_outputs; j++) {
OutputFilter *ofilter = fg->outputs[j];
Michael Niedermayer
committed
if (!ofilter->ost || ofilter->ost->source_index >= 0)
continue;
if (fg->nb_inputs != 1)
continue;
for (k = nb_input_streams-1; k >= 0 ; k--)
if (fg->inputs[0]->ist == input_streams[k])
break;
ofilter->ost->source_index = k;
}
}
/* init framerate emulation */
for (i = 0; i < nb_input_files; i++) {
InputFile *ifile = input_files[i];
if (ifile->rate_emu)
for (j = 0; j < ifile->nb_streams; j++)
input_streams[j + ifile->ist_index]->start = av_gettime_relative();
Patrice Bensoussan
committed
/* output stream init */
for (i = 0; i < nb_output_files; i++) {
oc = output_files[i]->ctx;
if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) {
av_dump_format(oc, i, oc->filename, 1);
av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", i);
return AVERROR(EINVAL);
Patrice Bensoussan
committed
/* init complex filtergraphs */
for (i = 0; i < nb_filtergraphs; i++)
if ((ret = avfilter_graph_config(filtergraphs[i]->graph, NULL)) < 0)
return ret;
/* for each output stream, we compute the right encoding parameters */
for (i = 0; i < nb_output_streams; i++) {
ost = output_streams[i];
oc = output_files[ost->file_index]->ctx;
ist = get_input_stream(ost);
if (ost->attachment_filename)
continue;
enc_ctx = ost->stream_copy ? ost->st->codec : ost->enc_ctx;
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;
Michael Niedermayer
committed
} else {
for (j=0; j<oc->nb_streams; j++) {
AVStream *st = oc->streams[j];
if (st != ost->st && st->codec->codec_type == enc_ctx->codec_type)
Michael Niedermayer
committed
break;
}
if (j == oc->nb_streams)
if (enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO || enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
Michael Niedermayer
committed
ost->st->disposition = AV_DISPOSITION_DEFAULT;
uint64_t extra_size;
av_assert0(ist && !ost->filter);
extra_size = (uint64_t)dec_ctx->extradata_size + FF_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;
unsigned int 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_tag2(oc->oformat->codec_tag, dec_ctx->codec_id, &codec_tag))
enc_ctx->codec_tag = dec_ctx->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;
if (dec_ctx->extradata_size) {
enc_ctx->extradata = av_mallocz(extra_size);
if (!enc_ctx->extradata) {
return AVERROR(ENOMEM);
}
memcpy(enc_ctx->extradata, dec_ctx->extradata, dec_ctx->extradata_size);
enc_ctx->extradata_size= dec_ctx->extradata_size;
enc_ctx->bits_per_coded_sample = dec_ctx->bits_per_coded_sample;
enc_ctx->time_base = ist->st->time_base;
/*
* Avi is a special case here because it supports variable fps but
* having the fps and timebase differe significantly adds quite some
* overhead
*/
if(!strcmp(oc->oformat->name, "avi")) {
if ( copy_tb<0 && av_q2d(ist->st->r_frame_rate) >= av_q2d(ist->st->avg_frame_rate)
&& 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(ist->st->time_base)
&& 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(dec_ctx->time_base)
&& av_q2d(ist->st->time_base) < 1.0/500 && av_q2d(dec_ctx->time_base) < 1.0/500
enc_ctx->time_base.num = ist->st->r_frame_rate.den;
enc_ctx->time_base.den = 2*ist->st->r_frame_rate.num;
enc_ctx->ticks_per_frame = 2;
} else if ( copy_tb<0 && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > 2*av_q2d(ist->st->time_base)
&& av_q2d(ist->st->time_base) < 1.0/500
|| copy_tb==0){
enc_ctx->time_base = dec_ctx->time_base;
enc_ctx->time_base.num *= dec_ctx->ticks_per_frame;
enc_ctx->time_base.den *= 2;
enc_ctx->ticks_per_frame = 2;
}
} else if(!(oc->oformat->flags & AVFMT_VARIABLE_FPS)
&& strcmp(oc->oformat->name, "mov") && strcmp(oc->oformat->name, "mp4") && strcmp(oc->oformat->name, "3gp")
&& strcmp(oc->oformat->name, "3g2") && strcmp(oc->oformat->name, "psp") && strcmp(oc->oformat->name, "ipod")
&& strcmp(oc->oformat->name, "f4v")
if( copy_tb<0 && dec_ctx->time_base.den
&& av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > av_q2d(ist->st->time_base)
&& av_q2d(ist->st->time_base) < 1.0/500
|| copy_tb==0){
enc_ctx->time_base = dec_ctx->time_base;
enc_ctx->time_base.num *= dec_ctx->ticks_per_frame;
if ( enc_ctx->codec_tag == AV_RL32("tmcd")
&& dec_ctx->time_base.num < dec_ctx->time_base.den
&& dec_ctx->time_base.num > 0
&& 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) {
enc_ctx->time_base = dec_ctx->time_base;
if (ist && !ost->frame_rate.num)
ost->frame_rate = ist->framerate;
if(ost->frame_rate.num)
enc_ctx->time_base = av_inv_q(ost->frame_rate);
av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den,
enc_ctx->time_base.num, enc_ctx->time_base.den, INT_MAX);
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);
Michael Niedermayer
committed
ost->st->nb_side_data = 0;
for (j = 0; j < ist->st->nb_side_data; j++) {
const AVPacketSideData *sd_src = &ist->st->side_data[j];
Michael Niedermayer
committed
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(enc_ctx->codec_id);
case AVMEDIA_TYPE_AUDIO:
av_log(NULL, AV_LOG_FATAL, "-acodec copy and -vol are incompatible (frames are not decoded)\n");
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;
enc_ctx->initial_padding = dec_ctx->delay;
#if FF_API_AUDIOENC_DELAY
enc_ctx->delay = dec_ctx->delay;
if((enc_ctx->block_align == 1 || enc_ctx->block_align == 1152 || enc_ctx->block_align == 576) && enc_ctx->codec_id == AV_CODEC_ID_MP3)
enc_ctx->block_align= 0;
if(enc_ctx->codec_id == AV_CODEC_ID_AC3)
enc_ctx->block_align= 0;
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;
if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option
av_mul_q(ost->frame_aspect_ratio,
(AVRational){ enc_ctx->height, enc_ctx->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 = dec_ctx->sample_aspect_ratio;
ost->st->sample_aspect_ratio = enc_ctx->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:
enc_ctx->width = dec_ctx->width;
enc_ctx->height = dec_ctx->height;
case AVMEDIA_TYPE_UNKNOWN:
case AVMEDIA_TYPE_DATA:
case AVMEDIA_TYPE_ATTACHMENT:
break;
default:
abort();
}
} else {
ost->enc = avcodec_find_encoder(enc_ctx->codec_id);
if (!ost->enc) {
/* should only happen when a default codec is not present. */
snprintf(error, sizeof(error), "Encoder (codec %s) not found for output stream #%d:%d",
avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index);
ret = AVERROR(EINVAL);
goto dump_format;
Michael Niedermayer
committed
ist->decoding_needed |= DECODING_FOR_OST;
ost->encoding_needed = 1;
set_encoder_id(output_files[ost->file_index], ost);
(enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO)) {
FilterGraph *fg;
fg = init_simple_filtergraph(ist, ost);
if (configure_filtergraph(fg)) {
av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
if (!ost->frame_rate.num)
ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter);
if (ist && !ost->frame_rate.num)
ost->frame_rate = ist->framerate;
if (ist && !ost->frame_rate.num)
ost->frame_rate = ist->st->r_frame_rate;
if (ist && !ost->frame_rate.num) {
ost->frame_rate = (AVRational){25, 1};
av_log(NULL, AV_LOG_WARNING,
"No information "
"about the input framerate is available. Falling "
"back to a default value of 25fps for output stream #%d:%d. Use the -r option "
"if you want a different framerate.\n",
ost->file_index, ost->index);
}
// ost->frame_rate = ist->st->avg_frame_rate.num ? ist->st->avg_frame_rate : (AVRational){25, 1};
if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) {
int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
ost->frame_rate = ost->enc->supported_framerates[idx];
}
// reduce frame rate for mpeg4 to be within the spec limits
if (enc_ctx->codec_id == AV_CODEC_ID_MPEG4) {
av_reduce(&ost->frame_rate.num, &ost->frame_rate.den,
ost->frame_rate.num, ost->frame_rate.den, 65535);
}
enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format;
enc_ctx->sample_rate = ost->filter->filter->inputs[0]->sample_rate;
enc_ctx->channel_layout = ost->filter->filter->inputs[0]->channel_layout;
enc_ctx->channels = avfilter_link_get_channels(ost->filter->filter->inputs[0]);
enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate };
break;
case AVMEDIA_TYPE_VIDEO:
enc_ctx->time_base = av_inv_q(ost->frame_rate);
if (!(enc_ctx->time_base.num && enc_ctx->time_base.den))
enc_ctx->time_base = ost->filter->filter->inputs[0]->time_base;
if ( av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH
Michael Niedermayer
committed
&& (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){
av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n"
"Please consider specifying a lower framerate, a different muxer or -vsync 2\n");
}
for (j = 0; j < ost->forced_kf_count; j++)
ost->forced_kf_pts[j] = av_rescale_q(ost->forced_kf_pts[j],
AV_TIME_BASE_Q,
enc_ctx->time_base);
enc_ctx->width = ost->filter->filter->inputs[0]->w;
enc_ctx->height = ost->filter->filter->inputs[0]->h;
enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio =
ost->frame_aspect_ratio.num ? // overridden by the -aspect cli option
av_mul_q(ost->frame_aspect_ratio, (AVRational){ enc_ctx->height, enc_ctx->width }) :
ost->filter->filter->inputs[0]->sample_aspect_ratio;
if (!strncmp(ost->enc->name, "libx264", 7) &&
enc_ctx->pix_fmt == AV_PIX_FMT_NONE &&
ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P)
Stefano Sabatini
committed
av_log(NULL, AV_LOG_WARNING,
"No pixel format specified, %s for H.264 encoding chosen.\n"
"Use -pix_fmt yuv420p for compatibility with outdated media players.\n",
av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format));
Carl Eugen Hoyos
committed
if (!strncmp(ost->enc->name, "mpeg2video", 10) &&
enc_ctx->pix_fmt == AV_PIX_FMT_NONE &&
Carl Eugen Hoyos
committed
ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P)
av_log(NULL, AV_LOG_WARNING,
"No pixel format specified, %s for MPEG-2 encoding chosen.\n"
"Use -pix_fmt yuv420p for compatibility with outdated media players.\n",
av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format));
enc_ctx->pix_fmt = ost->filter->filter->inputs[0]->format;
ost->st->avg_frame_rate = ost->frame_rate;
if (!dec_ctx ||
enc_ctx->width != dec_ctx->width ||
enc_ctx->height != dec_ctx->height ||
enc_ctx->pix_fmt != dec_ctx->pix_fmt) {
enc_ctx->bits_per_raw_sample = frame_bits_per_raw_sample;
if (ost->forced_keyframes) {
if (!strncmp(ost->forced_keyframes, "expr:", 5)) {
ret = av_expr_parse(&ost->forced_keyframes_pexpr, ost->forced_keyframes+5,
forced_keyframes_const_names, NULL, NULL, NULL, NULL, 0, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR,
"Invalid force_key_frames expression '%s'\n", ost->forced_keyframes+5);
return ret;
}
ost->forced_keyframes_expr_const_values[FKF_N] = 0;
ost->forced_keyframes_expr_const_values[FKF_N_FORCED] = 0;
ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N] = NAN;
ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T] = NAN;
// Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes',
// parse it only for static kf timings
} else if(strncmp(ost->forced_keyframes, "source", 6)) {
parse_forced_key_frames(ost->forced_keyframes, ost, ost->enc_ctx);
break;
case AVMEDIA_TYPE_SUBTITLE:
enc_ctx->time_base = (AVRational){1, 1000};
if (!enc_ctx->width) {