Newer
Older
snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d",
ist->file_index, ist->st->index);
return AVERROR(EINVAL);
}
assert_codec_experimental(ist->st->codec, 0);
assert_avoptions(ist->opts);
}
ist->next_pts = AV_NOPTS_VALUE;
ist->is_start = 1;
return 0;
}
static InputStream *get_input_stream(OutputStream *ost)
{
if (ost->source_index >= 0)
return input_streams[ost->source_index];
return NULL;
}
static void parse_forced_key_frames(char *kf, OutputStream *ost,
AVCodecContext *avctx)
{
char *p;
int n = 1, i;
int64_t t;
for (p = kf; *p; p++)
if (*p == ',')
n++;
ost->forced_kf_count = n;
ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n);
if (!ost->forced_kf_pts) {
av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
exit_program(1);
}
char *next = strchr(p, ',');
if (next)
*next++ = 0;
t = parse_time_or_die("force_key_frames", p, 1);
ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
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 int transcode_init(void)
int ret = 0, i, j, k;
OutputStream *ost;
char error[1024];
int want_sdp = 1;
/* 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();
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);
/* 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;
codec = ost->st->codec;
if (ist) {
icodec = ist->st->codec;
ost->st->disposition = ist->st->disposition;
codec->bits_per_raw_sample = icodec->bits_per_raw_sample;
codec->chroma_sample_location = icodec->chroma_sample_location;
}
Evgeniy Stepanov
committed
if (ost->stream_copy) {
uint64_t extra_size;
av_assert0(ist && !ost->filter);
extra_size = (uint64_t)icodec->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 */
codec->codec_id = icodec->codec_id;
codec->codec_type = icodec->codec_type;
Michael Niedermayer
committed
if (!codec->codec_tag) {
if (!oc->oformat->codec_tag ||
av_codec_get_id (oc->oformat->codec_tag, icodec->codec_tag) == codec->codec_id ||
av_codec_get_tag(oc->oformat->codec_tag, icodec->codec_id) <= 0)
Michael Niedermayer
committed
codec->codec_tag = icodec->codec_tag;
}
codec->bit_rate = icodec->bit_rate;
codec->rc_max_rate = icodec->rc_max_rate;
codec->rc_buffer_size = icodec->rc_buffer_size;
codec->field_order = icodec->field_order;
codec->extradata = av_mallocz(extra_size);
if (!codec->extradata) {
return AVERROR(ENOMEM);
memcpy(codec->extradata, icodec->extradata, icodec->extradata_size);
codec->extradata_size= icodec->extradata_size;
codec->bits_per_coded_sample = icodec->bits_per_coded_sample;
codec->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")) {
Michael Niedermayer
committed
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(icodec->time_base)
&& av_q2d(ist->st->time_base) < 1.0/500 && av_q2d(icodec->time_base) < 1.0/500
|| copy_tb==2){
codec->time_base.num = ist->st->r_frame_rate.den;
codec->time_base.den = 2*ist->st->r_frame_rate.num;
codec->ticks_per_frame = 2;
} else if ( copy_tb<0 && av_q2d(icodec->time_base)*icodec->ticks_per_frame > 2*av_q2d(ist->st->time_base)
Michael Niedermayer
committed
&& av_q2d(ist->st->time_base) < 1.0/500
|| copy_tb==0){
codec->time_base = icodec->time_base;
codec->time_base.num *= icodec->ticks_per_frame;
codec->time_base.den *= 2;
codec->ticks_per_frame = 2;
Michael Niedermayer
committed
} 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")
) {
Michael Niedermayer
committed
if( copy_tb<0 && av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base)
&& av_q2d(ist->st->time_base) < 1.0/500
|| copy_tb==0){
codec->time_base = icodec->time_base;
codec->time_base.num *= icodec->ticks_per_frame;
}
}
if(ost->frame_rate.num)
codec->time_base = av_inv_q(ost->frame_rate);
av_reduce(&codec->time_base.num, &codec->time_base.den,
codec->time_base.num, codec->time_base.den, INT_MAX);
switch (codec->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");
codec->channel_layout = icodec->channel_layout;
codec->sample_rate = icodec->sample_rate;
codec->channels = icodec->channels;
codec->frame_size = icodec->frame_size;
codec->audio_service_type = icodec->audio_service_type;
codec->block_align = icodec->block_align;
if((codec->block_align == 1 || codec->block_align == 1152) && codec->codec_id == CODEC_ID_MP3)
codec->block_align= 0;
if(codec->codec_id == CODEC_ID_AC3)
codec->block_align= 0;
break;
case AVMEDIA_TYPE_VIDEO:
codec->pix_fmt = icodec->pix_fmt;
codec->width = icodec->width;
codec->height = icodec->height;
codec->has_b_frames = icodec->has_b_frames;
if (!codec->sample_aspect_ratio.num) {
codec->sample_aspect_ratio =
ost->st->sample_aspect_ratio =
ist->st->sample_aspect_ratio.num ? ist->st->sample_aspect_ratio :
ist->st->codec->sample_aspect_ratio.num ?
ist->st->codec->sample_aspect_ratio : (AVRational){0, 1};
}
ost->st->avg_frame_rate = ist->st->avg_frame_rate;
break;
case AVMEDIA_TYPE_SUBTITLE:
codec->width = icodec->width;
codec->height = icodec->height;
Fabrice Bellard
committed
break;
case AVMEDIA_TYPE_ATTACHMENT:
default:
}
} else {
ost->enc = avcodec_find_encoder(codec->codec_id);
/* 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;
}
if (ist)
ist->decoding_needed = 1;
ost->encoding_needed = 1;
Michael Niedermayer
committed
if (!ost->filter &&
(codec->codec_type == AVMEDIA_TYPE_VIDEO ||
codec->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");
exit(1);
}
}
Michael Niedermayer
committed
if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
if (ost->filter && !ost->frame_rate.num)
ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter);
Michael Niedermayer
committed
if (ist && !ost->frame_rate.num)
ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25, 1};
// ost->frame_rate = ist->st->avg_frame_rate.num ? ist->st->avg_frame_rate : (AVRational){25, 1};
Michael Niedermayer
committed
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];
}
}
switch (codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
codec->sample_fmt = ost->filter->filter->inputs[0]->format;
codec->sample_rate = ost->filter->filter->inputs[0]->sample_rate;
codec->channel_layout = ost->filter->filter->inputs[0]->channel_layout;
codec->channels = av_get_channel_layout_nb_channels(codec->channel_layout);
codec->time_base = (AVRational){ 1, codec->sample_rate };
break;
case AVMEDIA_TYPE_VIDEO:
codec->time_base = av_inv_q(ost->frame_rate);
if (ost->filter && !(codec->time_base.num && codec->time_base.den))
codec->time_base = ost->filter->filter->inputs[0]->time_base;
if ( av_q2d(codec->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH
&& (video_sync_method == VSYNC_CFR || (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");
Michael Niedermayer
committed
}
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,
codec->time_base);
codec->width = ost->filter->filter->inputs[0]->w;
codec->height = ost->filter->filter->inputs[0]->h;
codec->sample_aspect_ratio = ost->st->sample_aspect_ratio =
ost->frame_aspect_ratio ? // overridden by the -aspect cli option
av_d2q(ost->frame_aspect_ratio * codec->height/codec->width, 255) :
ost->filter->filter->inputs[0]->sample_aspect_ratio;
codec->pix_fmt = ost->filter->filter->inputs[0]->format;
if (!icodec ||
codec->width != icodec->width ||
codec->height != icodec->height ||
codec->pix_fmt != icodec->pix_fmt) {
codec->bits_per_raw_sample = frame_bits_per_raw_sample;
if (ost->forced_keyframes)
parse_forced_key_frames(ost->forced_keyframes, ost,
ost->st->codec);
break;
case AVMEDIA_TYPE_SUBTITLE:
codec->time_base = (AVRational){1, 1000};
Fabrice Bellard
committed
break;
default:
Fabrice Bellard
committed
break;
/* two pass mode */
if (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2)) {
char logfilename[1024];
FILE *f;
snprintf(logfilename, sizeof(logfilename), "%s-%d.log",
pass_logfilename_prefix ? pass_logfilename_prefix : DEFAULT_PASS_LOGFILENAME_PREFIX,
i);
if (!strcmp(ost->enc->name, "libx264")) {
av_dict_set(&ost->opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE);
} else {
if (codec->flags & CODEC_FLAG_PASS2) {
char *logbuffer;
size_t logbuffer_size;
if (cmdutils_read_file(logfilename, &logbuffer, &logbuffer_size) < 0) {
av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n",
exit_program(1);
}
codec->stats_in = logbuffer;
}
if (codec->flags & CODEC_FLAG_PASS1) {
f = fopen(logfilename, "wb");
if (!f) {
av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n",
logfilename, strerror(errno));
exit_program(1);
}
ost->logfile = f;
}
for (i = 0; i < nb_output_streams; i++) {
ost = output_streams[i];
AVCodec *codec = ost->enc;
AVCodecContext *dec = NULL;
if ((ist = get_input_stream(ost)))
dec = ist->st->codec;
if (dec && dec->subtitle_header) {
/* ASS code assumes this buffer is null terminated so add extra byte. */
ost->st->codec->subtitle_header = av_mallocz(dec->subtitle_header_size + 1);
if (!ost->st->codec->subtitle_header) {
ret = AVERROR(ENOMEM);
goto dump_format;
}
memcpy(ost->st->codec->subtitle_header, dec->subtitle_header, dec->subtitle_header_size);
ost->st->codec->subtitle_header_size = dec->subtitle_header_size;
}
Michael Niedermayer
committed
if (!av_dict_get(ost->opts, "threads", NULL, 0))
av_dict_set(&ost->opts, "threads", "auto", 0);
if (avcodec_open2(ost->st->codec, codec, &ost->opts) < 0) {
snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d:%d - maybe incorrect parameters such as bit_rate, rate, width or height",
ret = AVERROR(EINVAL);
goto dump_format;
if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
!(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE))
av_buffersink_set_frame_size(ost->filter->filter,
ost->st->codec->frame_size);
assert_codec_experimental(ost->st->codec, 1);
assert_avoptions(ost->opts);
if (ost->st->codec->bit_rate && ost->st->codec->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");
Michael Niedermayer
committed
extra_size += ost->st->codec->extradata_size;
if (ost->st->codec->me_threshold)
input_streams[ost->source_index]->st->codec->debug |= FF_DEBUG_MV;
/* init input streams */
for (i = 0; i < nb_input_streams; i++)
if ((ret = init_input_stream(i, error, sizeof(error))) < 0)
/* discard unused programs */
for (i = 0; i < nb_input_files; i++) {
InputFile *ifile = input_files[i];
for (j = 0; j < ifile->ctx->nb_programs; j++) {
AVProgram *p = ifile->ctx->programs[j];
int discard = AVDISCARD_ALL;
for (k = 0; k < p->nb_stream_indexes; k++)
if (!input_streams[ifile->ist_index + p->stream_index[k]]->discard) {
discard = AVDISCARD_DEFAULT;
break;
}
p->discard = discard;
Anton Khirnov
committed
for (i = 0; i < nb_output_files; i++) {
oc = output_files[i]->ctx;
oc->interrupt_callback = int_cb;
if ((ret = avformat_write_header(oc, &output_files[i]->opts)) < 0) {
char errbuf[128];
const char *errbuf_ptr = errbuf;
if (av_strerror(ret, errbuf, sizeof(errbuf)) < 0)
errbuf_ptr = strerror(AVUNERROR(ret));
snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?): %s", i, errbuf_ptr);
ret = AVERROR(EINVAL);
goto dump_format;
}
// assert_avoptions(output_files[i]->opts);
if (strcmp(oc->oformat->name, "rtp")) {
want_sdp = 0;
}
}
dump_format:
/* dump the file output parameters - cannot be done before in case
of stream copy */
for (i = 0; i < nb_output_files; i++) {
av_dump_format(output_files[i]->ctx, i, output_files[i]->ctx->filename, 1);
}
/* dump the stream mapping */
av_log(NULL, AV_LOG_INFO, "Stream mapping:\n");
for (i = 0; i < nb_input_streams; i++) {
ist = input_streams[i];
for (j = 0; j < ist->nb_filters; j++) {
if (ist->filters[j]->graph->graph_desc) {
av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s",
ist->file_index, ist->st->index, ist->dec ? ist->dec->name : "?",
ist->filters[j]->name);
if (nb_filtergraphs > 1)
av_log(NULL, AV_LOG_INFO, " (graph %d)", ist->filters[j]->graph->index);
av_log(NULL, AV_LOG_INFO, "\n");
}
}
}
for (i = 0; i < nb_output_streams; i++) {
ost = output_streams[i];
if (ost->attachment_filename) {
/* an attached file */
av_log(NULL, AV_LOG_INFO, " File %s -> Stream #%d:%d\n",
ost->attachment_filename, ost->file_index, ost->index);
continue;
if (ost->filter && ost->filter->graph->graph_desc) {
/* output from a complex graph */
av_log(NULL, AV_LOG_INFO, " %s", ost->filter->name);
if (nb_filtergraphs > 1)
av_log(NULL, AV_LOG_INFO, " (graph %d)", ost->filter->graph->index);
av_log(NULL, AV_LOG_INFO, " -> Stream #%d:%d (%s)\n", ost->file_index,
ost->index, ost->enc ? ost->enc->name : "?");
continue;
}
av_log(NULL, AV_LOG_INFO, " Stream #%d:%d -> #%d:%d",
input_streams[ost->source_index]->file_index,
input_streams[ost->source_index]->st->index,
ost->file_index,
ost->index);
if (ost->sync_ist != input_streams[ost->source_index])
av_log(NULL, AV_LOG_INFO, " [sync #%d:%d]",
ost->sync_ist->file_index,
ost->sync_ist->st->index);
if (ost->stream_copy)
av_log(NULL, AV_LOG_INFO, " (copy)");
else
av_log(NULL, AV_LOG_INFO, " (%s -> %s)", input_streams[ost->source_index]->dec ?
input_streams[ost->source_index]->dec->name : "?",
ost->enc ? ost->enc->name : "?");
av_log(NULL, AV_LOG_INFO, "\n");
}
if (ret) {
av_log(NULL, AV_LOG_ERROR, "%s\n", error);
return ret;
}
if (want_sdp) {
print_sdp();
return 0;
}
/**
* @return 1 if there are still streams where more output is wanted,
* 0 otherwise
*/
static int need_output(void)
{
int i;
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
OutputFile *of = output_files[ost->file_index];
AVFormatContext *os = output_files[ost->file_index]->ctx;
if (ost->is_past_recording_time ||
(os->pb && avio_tell(os->pb) >= of->limit_filesize))
continue;
if (ost->frame_number >= ost->max_frames) {
int j;
for (j = 0; j < of->ctx->nb_streams; j++)
output_streams[of->ost_index + j]->is_past_recording_time = 1;
continue;
}
return 1;
}
return 0;
}
static int input_acceptable(InputStream *ist)
av_assert1(!ist->discard);
return !input_files[ist->file_index]->unavailable &&
!input_files[ist->file_index]->eof_reached;
}
static int find_graph_input(FilterGraph *graph)
{
int i, nb_req_max = 0, file_index = -1;
for (i = 0; i < graph->nb_inputs; i++) {
int nb_req = av_buffersrc_get_nb_failed_requests(graph->inputs[i]->filter);
if (nb_req > nb_req_max) {
InputStream *ist = graph->inputs[i]->ist;
if (input_acceptable(ist)) {
file_index = ist->file_index;
}
}
}
return file_index;
}
/**
* Select the input file to read from.
*
* @return >=0 index of the input file to use;
* -1 if no file is acceptable;
* -2 to read from filters without reading from a file
*/
static int select_input_file(void)
{
int i, ret, nb_active_out = nb_output_streams, ost_index = -1;
int64_t opts_min;
OutputStream *ost;
AVFilterBufferRef *dummy;
for (i = 0; i < nb_output_streams; i++)
nb_active_out -= output_streams[i]->unavailable =
output_streams[i]->is_past_recording_time;
while (nb_active_out) {
opts_min = INT64_MAX;
ost_index = -1;
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
int64_t opts = av_rescale_q(ost->st->cur_dts, ost->st->time_base,
AV_TIME_BASE_Q);
if (!ost->unavailable && opts < opts_min) {
opts_min = opts;
ost_index = i;
}
}
if (ost_index < 0)
return -1;
ost = output_streams[ost_index];
if (ost->source_index >= 0) {
/* ost is directly connected to an input */
InputStream *ist = input_streams[ost->source_index];
if (input_acceptable(ist))
return ist->file_index;
} else {
/* ost is connected to a complex filtergraph */
av_assert1(ost->filter);
ret = av_buffersink_get_buffer_ref(ost->filter->filter, &dummy,
AV_BUFFERSINK_FLAG_PEEK);
if (ret >= 0)
return -2;
ret = find_graph_input(ost->filter->graph);
if (ret >= 0)
return ret;
}
ost->unavailable = 1;
nb_active_out--;
}
return -1;
}
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
static int check_keyboard_interaction(int64_t cur_time)
{
int i, ret, key;
static int64_t last_time;
if (received_nb_signals)
return AVERROR_EXIT;
/* read_key() returns 0 on EOF */
if(cur_time - last_time >= 100000 && !run_as_daemon){
key = read_key();
last_time = cur_time;
}else
key = -1;
if (key == 'q')
return AVERROR_EXIT;
if (key == '+') av_log_set_level(av_log_get_level()+10);
if (key == '-') av_log_set_level(av_log_get_level()-10);
if (key == 's') qp_hist ^= 1;
if (key == 'h'){
if (do_hex_dump){
do_hex_dump = do_pkt_dump = 0;
} else if(do_pkt_dump){
do_hex_dump = 1;
} else
do_pkt_dump = 1;
av_log_set_level(AV_LOG_DEBUG);
}
if (key == 'c' || key == 'C'){
char buf[4096], target[64], command[256], arg[256] = {0};
double time;
int k, n = 0;
fprintf(stderr, "\nEnter command: <target> <time> <command>[ <argument>]\n");
i = 0;
while ((k = read_key()) != '\n' && k != '\r' && i < sizeof(buf)-1)
if (k > 0)
buf[i++] = k;
buf[i] = 0;
if (k > 0 &&
(n = sscanf(buf, "%63[^ ] %lf %255[^ ] %255[^\n]", target, &time, command, arg)) >= 3) {
av_log(NULL, AV_LOG_DEBUG, "Processing command target:%s time:%f command:%s arg:%s",
target, time, command, arg);
for (i = 0; i < nb_filtergraphs; i++) {
FilterGraph *fg = filtergraphs[i];
if (fg->graph) {
if (time < 0) {
ret = avfilter_graph_send_command(fg->graph, target, command, arg, buf, sizeof(buf),
key == 'c' ? AVFILTER_CMD_FLAG_ONE : 0);
fprintf(stderr, "Command reply for stream %d: ret:%d res:%s\n", i, ret, buf);
} else {
ret = avfilter_graph_queue_command(fg->graph, target, command, arg, 0, time);
}
}
}
} else {
av_log(NULL, AV_LOG_ERROR,
"Parse error, at least 3 arguments were expected, "
"only %d given in string '%s'\n", n, buf);
}
}
if (key == 'd' || key == 'D'){
int debug=0;
if(key == 'D') {
debug = input_streams[0]->st->codec->debug<<1;
if(!debug) debug = 1;
while(debug & (FF_DEBUG_DCT_COEFF|FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) //unsupported, would just crash
debug += debug;
}else
if(scanf("%d", &debug)!=1)
fprintf(stderr,"error parsing debug value\n");
for(i=0;i<nb_input_streams;i++) {
input_streams[i]->st->codec->debug = debug;
}
for(i=0;i<nb_output_streams;i++) {
OutputStream *ost = output_streams[i];
ost->st->codec->debug = debug;
}
if(debug) av_log_set_level(AV_LOG_DEBUG);
fprintf(stderr,"debug=%d\n", debug);
}
if (key == '?'){
fprintf(stderr, "key function\n"
"? show this help\n"
"+ increase verbosity\n"
"- decrease verbosity\n"
"c Send command to filtergraph\n"
"D cycle through available debug modes\n"
"h dump packets/hex press to cycle through the 3 states\n"
"q quit\n"
"s Show QP histogram\n"
);
}
return 0;
}
static void *input_thread(void *arg)
{
InputFile *f = arg;
int ret = 0;
while (!transcoding_finished && ret >= 0) {
AVPacket pkt;
ret = av_read_frame(f->ctx, &pkt);
if (ret == AVERROR(EAGAIN)) {
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
ret = 0;
continue;
} else if (ret < 0)
break;
pthread_mutex_lock(&f->fifo_lock);
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);
}
f->finished = 1;
return NULL;
}
static void free_input_threads(void)
{
int i;
if (nb_input_files == 1)
return;
transcoding_finished = 1;
for (i = 0; i < nb_input_files; i++) {
InputFile *f = input_files[i];
AVPacket pkt;
if (!f->fifo || f->joined)
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
continue;
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);
}
pthread_cond_signal(&f->fifo_cond);
pthread_mutex_unlock(&f->fifo_lock);
pthread_join(f->thread, NULL);
f->joined = 1;
while (av_fifo_size(f->fifo)) {
av_fifo_generic_read(f->fifo, &pkt, sizeof(pkt), NULL);
av_free_packet(&pkt);
}
av_fifo_free(f->fifo);
}
}
static int init_input_threads(void)
{
int i, ret;
if (nb_input_files == 1)
return 0;
for (i = 0; i < nb_input_files; i++) {
InputFile *f = input_files[i];
if (!(f->fifo = av_fifo_alloc(8*sizeof(AVPacket))))
return AVERROR(ENOMEM);
pthread_mutex_init(&f->fifo_lock, NULL);
pthread_cond_init (&f->fifo_cond, NULL);
if ((ret = pthread_create(&f->thread, NULL, input_thread, f)))
return AVERROR(ret);
}
return 0;
}
static int get_input_packet_mt(InputFile *f, AVPacket *pkt)
{
int ret = 0;
pthread_mutex_lock(&f->fifo_lock);
if (av_fifo_size(f->fifo)) {
av_fifo_generic_read(f->fifo, pkt, sizeof(*pkt), NULL);
pthread_cond_signal(&f->fifo_cond);
} else {
if (f->finished)
ret = AVERROR_EOF;
else
ret = AVERROR(EAGAIN);
}
pthread_mutex_unlock(&f->fifo_lock);
return ret;
}
#endif
static int get_input_packet(InputFile *f, AVPacket *pkt)
{
if (nb_input_files > 1)
return get_input_packet_mt(f, pkt);
#endif
return av_read_frame(f->ctx, pkt);
}
/*
* The following code is the main loop of the file converter
*/
static int transcode(void)
{
int ret, i;
AVFormatContext *is, *os;
OutputStream *ost;
InputStream *ist;
int no_packet_count = 0;
int64_t timer_start;
ret = transcode_init();
if (ret < 0)
goto fail;
if (stdin_interaction) {
av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");
Leon van Stuivenberg
committed
}
timer_start = av_gettime();
if ((ret = init_input_threads()) < 0)
goto fail;
#endif
for (; received_sigterm == 0;) {
int file_index, ist_index;
Michael Niedermayer
committed
int64_t cur_time= av_gettime();
/* if 'q' pressed, exits */
if (stdin_interaction)
if (check_keyboard_interaction(cur_time) < 0)
break;
/* check if there's any stream where output is still needed */
if (!need_output()) {
av_log(NULL, AV_LOG_VERBOSE, "No more output streams to write to, finishing.\n");
/* select the stream that we must read now */
file_index = select_input_file();
if (file_index == -2) {
poll_filters() ;
continue;
}
if (file_index < 0) {
if (no_packet_count) {
no_packet_count = 0;
for (i = 0; i < nb_input_files; i++)
input_files[i]->unavailable = 0;
continue;
}
av_log(NULL, AV_LOG_VERBOSE, "No more inputs to read from, finishing.\n");
Fabrice Bellard
committed
}
is = input_files[file_index]->ctx;
ret = get_input_packet(input_files[file_index], &pkt);
if (ret == AVERROR(EAGAIN)) {
input_files[file_index]->unavailable = 1;
no_packet_count++;
if (ret != AVERROR_EOF) {
print_error(is->filename, ret);
if (exit_on_error)
exit_program(1);
}
input_files[file_index]->eof_reached = 1;
for (i = 0; i < input_files[file_index]->nb_streams; i++) {
ist = input_streams[input_files[file_index]->ist_index + i];
if (ist->decoding_needed)
output_packet(ist, NULL);
if (opt_shortest)
break;
else
continue;
for (i = 0; i < nb_input_files; i++)
input_files[i]->unavailable = 0;
if (do_pkt_dump) {
av_pkt_dump_log2(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump,
is->streams[pkt.stream_index]);
Fabrice Bellard
committed
}
/* the following test is needed in case new streams appear
dynamically in stream : we ignore them */
if (pkt.stream_index >= input_files[file_index]->nb_streams) {
report_new_stream(file_index, &pkt);
ist_index = input_files[file_index]->ist_index + pkt.stream_index;
ist = input_streams[ist_index];
if (ist->discard)
goto discard_packet;
if(!ist->wrap_correction_done && input_files[file_index]->ctx->start_time != AV_NOPTS_VALUE && ist->st->pts_wrap_bits < 64){
uint64_t stime = av_rescale_q(input_files[file_index]->ctx->start_time, AV_TIME_BASE_Q, ist->st->time_base);
uint64_t stime2= stime + (1LL<<ist->st->pts_wrap_bits);
ist->wrap_correction_done = 1;
if(pkt.dts != AV_NOPTS_VALUE && pkt.dts > stime && pkt.dts - stime > stime2 - pkt.dts) {
pkt.dts -= 1LL<<ist->st->pts_wrap_bits;
ist->wrap_correction_done = 0;
}
if(pkt.pts != AV_NOPTS_VALUE && pkt.pts > stime && pkt.pts - stime > stime2 - pkt.pts) {
pkt.pts -= 1LL<<ist->st->pts_wrap_bits;
ist->wrap_correction_done = 0;
}
}
Michael Niedermayer
committed
if (pkt.dts != AV_NOPTS_VALUE)
pkt.dts += av_rescale_q(input_files[ist->file_index]->ts_offset, AV_TIME_BASE_Q, ist->st->time_base);
Michael Niedermayer
committed
if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts += av_rescale_q(input_files[ist->file_index]->ts_offset, AV_TIME_BASE_Q, ist->st->time_base);
Michael Niedermayer
committed
if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts *= ist->ts_scale;
if (pkt.dts != AV_NOPTS_VALUE)
pkt.dts *= ist->ts_scale;
if (debug_ts) {
av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d type:%s "
"next_dts:%s next_dts_time:%s next_pts:%s next_pts_time:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%"PRId64"\n",
ist_index, av_get_media_type_string(ist->st->codec->codec_type),
av_ts2str(ist->next_dts), av_ts2timestr(ist->next_dts, &AV_TIME_BASE_Q),
av_ts2str(ist->next_pts), av_ts2timestr(ist->next_pts, &AV_TIME_BASE_Q),
av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base),
av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base),
input_files[ist->file_index]->ts_offset);
if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && !copy_ts) {
int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q);
int64_t delta = pkt_dts - ist->next_dts;
if (is->iformat->flags & AVFMT_TS_DISCONT) {
if(delta < -1LL*dts_delta_threshold*AV_TIME_BASE ||
(delta > 1LL*dts_delta_threshold*AV_TIME_BASE &&
ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) ||
pkt_dts+1<ist->pts){
input_files[ist->file_index]->ts_offset -= delta;
av_log(NULL, AV_LOG_DEBUG,
"timestamp discontinuity %"PRId64", new offset= %"PRId64"\n",
delta, input_files[ist->file_index]->ts_offset);
Michael Niedermayer
committed
pkt.dts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
if (pkt.pts != AV_NOPTS_VALUE)
Michael Niedermayer
committed
pkt.pts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
} else {
if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE ||
(delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) ||