Newer
Older
}
static int opt_frame_aspect_ratio(const char *opt, const char *arg)
{
int x = 0, y = 0;
double ar = 0;
const char *p;
p = strchr(arg, ':');
if (p) {
x = strtol(arg, &end, 10);
if (end == p)
y = strtol(end+1, &end, 10);
if (x > 0 && y > 0)
ar = (double)x / (double)y;
} else
if (!ar) {
fprintf(stderr, "Incorrect aspect ratio specification.\n");
}
frame_aspect_ratio = ar;
}
static int opt_metadata(const char *opt, const char *arg)
{
char *mid= strchr(arg, '=');
if(!mid){
fprintf(stderr, "Missing =\n");
av_dict_set(&metadata, arg, mid, 0);
static int opt_qscale(const char *opt, const char *arg)
video_qscale = parse_number_or_die(opt, arg, OPT_FLOAT, 0, 255);
if (video_qscale <= 0 || video_qscale > 255) {
fprintf(stderr, "qscale must be > 0.0 and <= 255\n");
return AVERROR(EINVAL);
static int opt_top_field_first(const char *opt, const char *arg)
top_field_first = parse_number_or_die(opt, arg, OPT_INT, 0, 1);
return opt_default(opt, arg);
static int opt_thread_count(const char *opt, const char *arg)
thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
if (verbose >= 0)
fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
static int opt_audio_sample_fmt(const char *opt, const char *arg)
if (strcmp(arg, "list")) {
audio_sample_fmt = av_get_sample_fmt(arg);
if (audio_sample_fmt == AV_SAMPLE_FMT_NONE) {
av_log(NULL, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg);
}
} else {
int i;
char fmt_str[128];
for (i = -1; i < AV_SAMPLE_FMT_NB; i++)
printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i));
static int opt_audio_rate(const char *opt, const char *arg)
audio_sample_rate = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
return 0;
static int opt_audio_channels(const char *opt, const char *arg)
audio_channels = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
return 0;
static int opt_video_channel(const char *opt, const char *arg)
Fabrice Bellard
committed
{
av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n");
return opt_default("channel", arg);
Fabrice Bellard
committed
}
static int opt_video_standard(const char *opt, const char *arg)
av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n");
return opt_default("standard", arg);
static int opt_codec(const char *opt, const char *arg)
int *pstream_copy; char **pcodec_name; enum AVMediaType codec_type;
if (!strcmp(opt, "acodec")) { pstream_copy = &audio_stream_copy; pcodec_name = &audio_codec_name; codec_type = AVMEDIA_TYPE_AUDIO; }
else if (!strcmp(opt, "vcodec")) { pstream_copy = &video_stream_copy; pcodec_name = &video_codec_name; codec_type = AVMEDIA_TYPE_VIDEO; }
else if (!strcmp(opt, "scodec")) { pstream_copy = &subtitle_stream_copy; pcodec_name = &subtitle_codec_name; codec_type = AVMEDIA_TYPE_SUBTITLE; }
else if (!strcmp(opt, "dcodec")) { pstream_copy = &data_stream_copy; pcodec_name = &data_codec_name; codec_type = AVMEDIA_TYPE_DATA; }
av_freep(pcodec_name);
if (!strcmp(arg, "copy")) {
Fabrice Bellard
committed
*pstream_copy = 1;
*pcodec_name = av_strdup(arg);
static int opt_codec_tag(const char *opt, const char *arg)
uint32_t *codec_tag;
codec_tag = !strcmp(opt, "atag") ? &audio_codec_tag :
!strcmp(opt, "vtag") ? &video_codec_tag :
!strcmp(opt, "stag") ? &subtitle_codec_tag : NULL;
if (!codec_tag)
return -1;
*codec_tag = strtol(arg, &tail, 0);
if (!tail || *tail)
static int opt_map(const char *opt, const char *arg)
stream_maps = grow_array(stream_maps, sizeof(*stream_maps), &nb_stream_maps, nb_stream_maps + 1);
m = &stream_maps[nb_stream_maps-1];
m->file_index = strtol(arg, &p, 0);
m->stream_index = strtol(p, &p, 0);
if (*p) {
p++;
m->sync_file_index = strtol(p, &p, 0);
if (*p)
p++;
m->sync_stream_index = strtol(p, &p, 0);
} else {
m->sync_file_index = m->file_index;
m->sync_stream_index = m->stream_index;
}
static void parse_meta_type(char *arg, char *type, int *index, char **endptr)
{
*endptr = arg;
if (*arg == ',') {
*type = *(++arg);
switch (*arg) {
case 'g':
break;
case 's':
case 'c':
case 'p':
*index = strtol(++arg, endptr, 0);
break;
default:
fprintf(stderr, "Invalid metadata type %c.\n", *arg);
ffmpeg_exit(1);
}
} else
*type = 'g';
}
static int opt_map_metadata(const char *opt, const char *arg)
Patrice Bensoussan
committed
{
meta_data_maps = grow_array(meta_data_maps, sizeof(*meta_data_maps),
&nb_meta_data_maps, nb_meta_data_maps + 1);
Patrice Bensoussan
committed
m = &meta_data_maps[nb_meta_data_maps - 1][0];
m->file = strtol(arg, &p, 0);
parse_meta_type(p, &m->type, &m->index, &p);
Patrice Bensoussan
committed
if (*p)
p++;
m1 = &meta_data_maps[nb_meta_data_maps - 1][1];
m1->file = strtol(p, &p, 0);
parse_meta_type(p, &m1->type, &m1->index, &p);
Anton Khirnov
committed
if (m->type == 'g' || m1->type == 'g')
metadata_global_autocopy = 0;
Anton Khirnov
committed
if (m->type == 's' || m1->type == 's')
metadata_streams_autocopy = 0;
if (m->type == 'c' || m1->type == 'c')
metadata_chapters_autocopy = 0;
Patrice Bensoussan
committed
}
static int opt_map_meta_data(const char *opt, const char *arg)
{
fprintf(stderr, "-map_meta_data is deprecated and will be removed soon. "
"Use -map_metadata instead.\n");
static int opt_map_chapters(const char *opt, const char *arg)
char *p;
chapter_maps = grow_array(chapter_maps, sizeof(*chapter_maps), &nb_chapter_maps,
nb_chapter_maps + 1);
c = &chapter_maps[nb_chapter_maps - 1];
c->out_file = strtol(arg, &p, 0);
if (*p)
p++;
c->in_file = strtol(p, &p, 0);
static int opt_input_ts_scale(const char *opt, const char *arg)
{
unsigned int stream;
double scale;
char *p;
stream = strtol(arg, &p, 0);
if (*p)
p++;
scale= strtod(p, &p);
if(stream >= MAX_STREAMS)
ffmpeg_exit(1);
ts_scale = grow_array(ts_scale, sizeof(*ts_scale), &nb_ts_scale, stream + 1);
ts_scale[stream] = scale;
static int opt_recording_time(const char *opt, const char *arg)
recording_time = parse_time_or_die(opt, arg, 1);
return 0;
static int opt_start_time(const char *opt, const char *arg)
start_time = parse_time_or_die(opt, arg, 1);
return 0;
static int opt_recording_timestamp(const char *opt, const char *arg)
{
char buf[128];
int64_t recording_timestamp = parse_time_or_die(opt, arg, 0) / 1E6;
struct tm time = *gmtime((time_t*)&recording_timestamp);
strftime(buf, sizeof(buf), "creation_time=%FT%T%z", &time);
opt_metadata("metadata", buf);
av_log(NULL, AV_LOG_WARNING, "%s is deprecated, set the 'creation_time' metadata "
"tag instead.\n", opt);
return 0;
}
static int opt_input_ts_offset(const char *opt, const char *arg)
input_ts_offset = parse_time_or_die(opt, arg, 1);
return 0;
static enum CodecID find_codec_or_die(const char *name, int type, int encoder)
{
const char *codec_string = encoder ? "encoder" : "decoder";
AVCodec *codec;
if(!name)
return CODEC_ID_NONE;
codec = encoder ?
avcodec_find_encoder_by_name(name) :
avcodec_find_decoder_by_name(name);
if(!codec) {
fprintf(stderr, "Unknown %s '%s'\n", codec_string, name);
}
if(codec->type != type) {
fprintf(stderr, "Invalid %s type '%s'\n", codec_string, name);
}
return codec->id;
}
static int opt_input_file(const char *opt, const char *filename)
AVInputFormat *file_iformat = NULL;
Michael Niedermayer
committed
int err, i, ret, rfps, rfps_base;
AVDictionary **opts;
int orig_nb_streams; // number of streams before avformat_find_stream_info
if (last_asked_format) {
if (!(file_iformat = av_find_input_format(last_asked_format))) {
fprintf(stderr, "Unknown input format: '%s'\n", last_asked_format);
last_asked_format = NULL;
}
if (!strcmp(filename, "-"))
filename = "pipe:";
using_stdin |= !strncmp(filename, "pipe:", 5) ||
!strcmp(filename, "/dev/stdin");
ic = avformat_alloc_context();
if (!ic) {
print_error(filename, AVERROR(ENOMEM));
if (audio_sample_rate) {
snprintf(buf, sizeof(buf), "%d", audio_sample_rate);
av_dict_set(&format_opts, "sample_rate", buf, 0);
}
if (audio_channels) {
snprintf(buf, sizeof(buf), "%d", audio_channels);
av_dict_set(&format_opts, "channels", buf, 0);
}
if (frame_rate.num) {
snprintf(buf, sizeof(buf), "%d/%d", frame_rate.num, frame_rate.den);
av_dict_set(&format_opts, "framerate", buf, 0);
}
if (frame_width && frame_height) {
snprintf(buf, sizeof(buf), "%dx%d", frame_width, frame_height);
av_dict_set(&format_opts, "video_size", buf, 0);
}
if (frame_pix_fmt != PIX_FMT_NONE)
av_dict_set(&format_opts, "pixel_format", av_get_pix_fmt_name(frame_pix_fmt), 0);
Janne Grunau
committed
ic->video_codec_id =
find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0);
Janne Grunau
committed
ic->audio_codec_id =
find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0);
Janne Grunau
committed
ic->subtitle_codec_id=
find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0);
if (loop_input) {
av_log(NULL, AV_LOG_WARNING, "-loop_input is deprecated, use -loop 1\n");
ic->loop_input = loop_input;
}
/* open the input file with generic libav function */
err = avformat_open_input(&ic, filename, file_iformat, &format_opts);
print_error(filename, err);
assert_avoptions(format_opts);
Nico Sabbi
committed
if(opt_programid) {
int i, j;
int found=0;
for(i=0; i<ic->nb_streams; i++){
ic->streams[i]->discard= AVDISCARD_ALL;
}
for(i=0; i<ic->nb_programs; i++){
AVProgram *p= ic->programs[i];
if(p->id != opt_programid){
p->discard = AVDISCARD_ALL;
}else{
found=1;
for(j=0; j<p->nb_stream_indexes; j++){
ic->streams[p->stream_index[j]]->discard= AVDISCARD_DEFAULT;
}
}
}
if(!found){
fprintf(stderr, "Specified program id not found\n");
Nico Sabbi
committed
}
/* Set AVCodecContext options for avformat_find_stream_info */
opts = setup_find_stream_info_opts(ic, codec_opts);
orig_nb_streams = ic->nb_streams;
/* If not enough info to get the stream parameters, we decode the
first frames to get it. (used in mpeg case for example) */
ret = avformat_find_stream_info(ic, opts);
if (ret < 0 && verbose >= 0) {
fprintf(stderr, "%s: could not find codec parameters\n", filename);
av_close_input_file(ic);
timestamp = start_time;
/* add the stream start time */
if (ic->start_time != AV_NOPTS_VALUE)
timestamp += ic->start_time;
/* if seeking requested, we execute it */
if (start_time != 0) {
ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
if (ret < 0) {
fprintf(stderr, "%s: could not seek to position %0.3f\n",
filename, (double)timestamp / AV_TIME_BASE);
}
/* reset seek info */
start_time = 0;
}
/* update the current parameters so that they match the one of the input stream */
for(i=0;i<ic->nb_streams;i++) {
AVCodecContext *dec = st->codec;
input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1);
ist = &input_streams[nb_input_streams - 1];
ist->st = st;
ist->file_index = nb_input_files;
ist->discard = 1;
ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st);
if (i < nb_ts_scale)
ist->ts_scale = ts_scale[i];
switch (dec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
ist->dec = avcodec_find_decoder_by_name(audio_codec_name);
if(!ist->dec)
ist->dec = avcodec_find_decoder(dec->codec_id);
case AVMEDIA_TYPE_VIDEO:
ist->dec= avcodec_find_decoder_by_name(video_codec_name);
if(!ist->dec)
ist->dec = avcodec_find_decoder(dec->codec_id);
rfps = ic->streams[i]->r_frame_rate.num;
rfps_base = ic->streams[i]->r_frame_rate.den;
if (dec->lowres) {
dec->flags |= CODEC_FLAG_EMU_EDGE;
Michael Niedermayer
committed
if(me_threshold)
dec->debug |= FF_DEBUG_MV;
if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) {
if (verbose >= 0)
Baptiste Coudurier
committed
fprintf(stderr,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n",
i, (float)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num,
(float)rfps / rfps_base, rfps, rfps_base);
Max Krasnyansky
committed
case AVMEDIA_TYPE_DATA:
break;
case AVMEDIA_TYPE_SUBTITLE:
ist->dec = avcodec_find_decoder_by_name(subtitle_codec_name);
if(!ist->dec)
ist->dec = avcodec_find_decoder(dec->codec_id);
if(subtitle_disable)
Fabrice Bellard
committed
break;
case AVMEDIA_TYPE_ATTACHMENT:
case AVMEDIA_TYPE_UNKNOWN:
break;
default:
if (verbose >= 0)
av_dump_format(ic, nb_input_files, filename, 0);
input_files = grow_array(input_files, sizeof(*input_files), &nb_input_files, nb_input_files + 1);
input_files[nb_input_files - 1].ctx = ic;
input_files[nb_input_files - 1].ist_index = nb_input_streams - ic->nb_streams;
input_files[nb_input_files - 1].ts_offset = input_ts_offset - (copy_ts ? 0 : timestamp);
input_files[nb_input_files - 1].nb_streams = ic->nb_streams;
Max Krasnyansky
committed
top_field_first = -1;
frame_rate = (AVRational){0, 0};
frame_pix_fmt = PIX_FMT_NONE;
frame_height = 0;
frame_width = 0;
audio_sample_rate = 0;
audio_channels = 0;
audio_sample_fmt = AV_SAMPLE_FMT_NONE;
av_freep(&ts_scale);
nb_ts_scale = 0;
for (i = 0; i < orig_nb_streams; i++)
av_dict_free(&opts[i]);
av_freep(&opts);
Baptiste Coudurier
committed
av_freep(&video_codec_name);
av_freep(&audio_codec_name);
av_freep(&subtitle_codec_name);
uninit_opts();
init_opts();
static void check_inputs(int *has_video_ptr,
int *has_audio_ptr,
int *has_subtitle_ptr,
int *has_data_ptr)
Fabrice Bellard
committed
{
int has_video, has_audio, has_subtitle, has_data, i, j;
Fabrice Bellard
committed
AVFormatContext *ic;
has_video = 0;
has_audio = 0;
has_subtitle = 0;
Fabrice Bellard
committed
for(j=0;j<nb_input_files;j++) {
ic = input_files[j].ctx;
Fabrice Bellard
committed
for(i=0;i<ic->nb_streams;i++) {
Michael Niedermayer
committed
AVCodecContext *enc = ic->streams[i]->codec;
Fabrice Bellard
committed
switch(enc->codec_type) {
case AVMEDIA_TYPE_AUDIO:
Fabrice Bellard
committed
has_audio = 1;
break;
case AVMEDIA_TYPE_VIDEO:
Fabrice Bellard
committed
has_video = 1;
break;
case AVMEDIA_TYPE_SUBTITLE:
has_subtitle = 1;
break;
case AVMEDIA_TYPE_DATA:
case AVMEDIA_TYPE_ATTACHMENT:
case AVMEDIA_TYPE_UNKNOWN:
Wolfram Gloger
committed
break;
default:
Fabrice Bellard
committed
}
}
}
*has_video_ptr = has_video;
*has_audio_ptr = has_audio;
*has_subtitle_ptr = has_subtitle;
Fabrice Bellard
committed
}
static void new_video_stream(AVFormatContext *oc, int file_idx)
Fabrice Bellard
committed
AVCodecContext *video_enc;
AVCodec *codec= NULL;
if(!video_stream_copy){
if (video_codec_name) {
codec_id = find_codec_or_die(video_codec_name, AVMEDIA_TYPE_VIDEO, 1);
codec = avcodec_find_encoder_by_name(video_codec_name);
} else {
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
codec = avcodec_find_encoder(codec_id);
}
}
ost = new_output_stream(oc, file_idx, codec);
st = ost->st;
if (!video_stream_copy) {
ost->frame_aspect_ratio = frame_aspect_ratio;
frame_aspect_ratio = 0;
#if CONFIG_AVFILTER
vfilters = NULL;
ost->bitstream_filters = video_bitstream_filters;
Michael Niedermayer
committed
video_bitstream_filters= NULL;
st->codec->thread_count= thread_count;
Michael Niedermayer
committed
video_enc = st->codec;
Fabrice Bellard
committed
if(video_codec_tag)
video_enc->codec_tag= video_codec_tag;
if(oc->oformat->flags & AVFMT_GLOBALHEADER) {
Fabrice Bellard
committed
video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
Michael Niedermayer
committed
video_enc->codec_type = AVMEDIA_TYPE_VIDEO;
Fabrice Bellard
committed
if (video_stream_copy) {
st->stream_copy = 1;
video_enc->sample_aspect_ratio =
st->sample_aspect_ratio = av_d2q(frame_aspect_ratio*frame_height/frame_width, 255);
Fabrice Bellard
committed
} else {
Fabrice Bellard
committed
int i;
if (frame_rate.num)
ost->frame_rate = frame_rate;
Fabrice Bellard
committed
video_enc->codec_id = codec_id;
video_enc->width = frame_width;
video_enc->height = frame_height;
Fabrice Bellard
committed
video_enc->pix_fmt = frame_pix_fmt;
video_enc->bits_per_raw_sample = frame_bits_per_raw_sample;
st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
Fabrice Bellard
committed
if (intra_only)
Fabrice Bellard
committed
video_enc->gop_size = 0;
if (video_qscale || same_quality) {
video_enc->flags |= CODEC_FLAG_QSCALE;
video_enc->global_quality = FF_QP2LAMBDA * video_qscale;
Fabrice Bellard
committed
}
if(intra_matrix)
video_enc->intra_matrix = intra_matrix;
if(inter_matrix)
video_enc->inter_matrix = inter_matrix;
p= video_rc_override_string;
for(i=0; p; i++){
int start, end, q;
int e=sscanf(p, "%d,%d,%d", &start, &end, &q);
if(e!=3){
fprintf(stderr, "error parsing rc_override\n");
Fabrice Bellard
committed
}
video_enc->rc_override=
av_realloc(video_enc->rc_override,
Fabrice Bellard
committed
sizeof(RcOverride)*(i+1));
video_enc->rc_override[i].start_frame= start;
video_enc->rc_override[i].end_frame = end;
if(q>0){
video_enc->rc_override[i].qscale= q;
video_enc->rc_override[i].quality_factor= 1.0;
}
else{
video_enc->rc_override[i].qscale= 0;
video_enc->rc_override[i].quality_factor= -q/100.0;
}
p= strchr(p, '/');
if(p) p++;
}
video_enc->rc_override_count=i;
if (!video_enc->rc_initial_buffer_occupancy)
video_enc->rc_initial_buffer_occupancy = video_enc->rc_buffer_size*3/4;
Fabrice Bellard
committed
video_enc->me_threshold= me_threshold;
video_enc->intra_dc_precision= intra_dc_precision - 8;
if (do_psnr)
video_enc->flags|= CODEC_FLAG_PSNR;
Fabrice Bellard
committed
/* two pass mode */
if (do_pass) {
if (do_pass == 1) {
video_enc->flags |= CODEC_FLAG_PASS1;
} else {
video_enc->flags |= CODEC_FLAG_PASS2;
}
}
if (forced_key_frames)
parse_forced_key_frames(forced_key_frames, ost, video_enc);
Fabrice Bellard
committed
}
if (video_language) {
av_dict_set(&st->metadata, "language", video_language, 0);
av_freep(&video_language);
}
Fabrice Bellard
committed
/* reset some key parameters */
video_disable = 0;
av_freep(&video_codec_name);
av_freep(&forced_key_frames);
Fabrice Bellard
committed
video_stream_copy = 0;
frame_pix_fmt = PIX_FMT_NONE;
Fabrice Bellard
committed
}
static void new_audio_stream(AVFormatContext *oc, int file_idx)
Fabrice Bellard
committed
{
AVStream *st;
AVCodec *codec= NULL;
Fabrice Bellard
committed
AVCodecContext *audio_enc;
if(!audio_stream_copy){
if (audio_codec_name) {
codec_id = find_codec_or_die(audio_codec_name, AVMEDIA_TYPE_AUDIO, 1);
codec = avcodec_find_encoder_by_name(audio_codec_name);
} else {
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_AUDIO);
codec = avcodec_find_encoder(codec_id);
}
}
ost = new_output_stream(oc, file_idx, codec);
st = ost->st;
Michael Niedermayer
committed
ost->bitstream_filters = audio_bitstream_filters;
Michael Niedermayer
committed
audio_bitstream_filters= NULL;
st->codec->thread_count= thread_count;
Michael Niedermayer
committed
audio_enc = st->codec;
audio_enc->codec_type = AVMEDIA_TYPE_AUDIO;
Fabrice Bellard
committed
if(audio_codec_tag)
audio_enc->codec_tag= audio_codec_tag;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
Fabrice Bellard
committed
audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
Fabrice Bellard
committed
if (audio_stream_copy) {
st->stream_copy = 1;
} else {
audio_enc->codec_id = codec_id;
if (audio_qscale > QSCALE_NONE) {
audio_enc->flags |= CODEC_FLAG_QSCALE;
audio_enc->global_quality = FF_QP2LAMBDA * audio_qscale;
if (audio_channels)
audio_enc->channels = audio_channels;
if (audio_sample_fmt != AV_SAMPLE_FMT_NONE)
audio_enc->sample_fmt = audio_sample_fmt;
if (audio_sample_rate)
audio_enc->sample_rate = audio_sample_rate;
Fabrice Bellard
committed
}
if (audio_language) {
av_dict_set(&st->metadata, "language", audio_language, 0);
av_freep(&audio_language);
Fabrice Bellard
committed
}
/* reset some key parameters */
audio_disable = 0;
av_freep(&audio_codec_name);
Fabrice Bellard
committed
audio_stream_copy = 0;
}
static void new_data_stream(AVFormatContext *oc, int file_idx)
{
AVStream *st;
OutputStream *ost;
ost = new_output_stream(oc, file_idx, NULL);
st = ost->st;
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
data_enc = st->codec;
if (!data_stream_copy) {
fprintf(stderr, "Data stream encoding not supported yet (only streamcopy)\n");
ffmpeg_exit(1);
}
data_enc->codec_type = AVMEDIA_TYPE_DATA;
if (data_codec_tag)
data_enc->codec_tag= data_codec_tag;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
data_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if (data_stream_copy) {
st->stream_copy = 1;
}
data_disable = 0;
av_freep(&data_codec_name);
data_stream_copy = 0;
}
static void new_subtitle_stream(AVFormatContext *oc, int file_idx)
Fabrice Bellard
committed
{
AVStream *st;
AVCodec *codec=NULL;
Fabrice Bellard
committed
AVCodecContext *subtitle_enc;
if(!subtitle_stream_copy){
codec_id = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 1);
codec = avcodec_find_encoder_by_name(subtitle_codec_name);
} else {
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_SUBTITLE);
codec = avcodec_find_encoder(codec_id);
}
ost = new_output_stream(oc, file_idx, codec);
st = ost->st;
subtitle_enc = st->codec;
Fabrice Bellard
committed
ost->bitstream_filters = subtitle_bitstream_filters;
subtitle_bitstream_filters= NULL;
subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
if(subtitle_codec_tag)
subtitle_enc->codec_tag= subtitle_codec_tag;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
subtitle_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
Fabrice Bellard
committed
if (subtitle_stream_copy) {
st->stream_copy = 1;
} else {
Fabrice Bellard
committed
}
if (subtitle_language) {
av_dict_set(&st->metadata, "language", subtitle_language, 0);
av_freep(&subtitle_language);
Fabrice Bellard
committed
}
subtitle_disable = 0;
av_freep(&subtitle_codec_name);
Fabrice Bellard
committed
subtitle_stream_copy = 0;
}
Aurelien Jacobs
committed
static int opt_new_stream(const char *opt, const char *arg)
Fabrice Bellard
committed
{
AVFormatContext *oc;
int file_idx = nb_output_files - 1;
Fabrice Bellard
committed
if (nb_output_files <= 0) {
fprintf(stderr, "At least one output file must be specified\n");
Fabrice Bellard
committed
}
oc = output_files[file_idx];
Fabrice Bellard
committed
if (!strcmp(opt, "newvideo" )) new_video_stream (oc, file_idx);
else if (!strcmp(opt, "newaudio" )) new_audio_stream (oc, file_idx);
else if (!strcmp(opt, "newsubtitle")) new_subtitle_stream(oc, file_idx);
else if (!strcmp(opt, "newdata" )) new_data_stream (oc, file_idx);
Aurelien Jacobs
committed
return 0;
/* arg format is "output-stream-index:streamid-value". */
Aurelien Jacobs
committed
static int opt_streamid(const char *opt, const char *arg)
{
int idx;
char *p;
char idx_str[16];
av_strlcpy(idx_str, arg, sizeof(idx_str));
p = strchr(idx_str, ':');
if (!p) {
fprintf(stderr,
"Invalid value '%s' for option '%s', required syntax is 'index:value'\n",
arg, opt);
}
*p++ = '\0';
idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1);
streamid_map = grow_array(streamid_map, sizeof(*streamid_map), &nb_streamid_map, idx+1);
streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX);
Aurelien Jacobs
committed
return 0;
}
Stefano Sabatini
committed
static int opt_output_file(const char *opt, const char *filename)
Fabrice Bellard
committed
{
AVFormatContext *oc;
int err, use_video, use_audio, use_subtitle, use_data;
int input_has_video, input_has_audio, input_has_subtitle, input_has_data;
AVOutputFormat *file_oformat;
if(nb_output_files >= FF_ARRAY_ELEMS(output_files)){
fprintf(stderr, "Too many output files\n");
ffmpeg_exit(1);
}
Stefano Sabatini
committed
err = avformat_alloc_output_context2(&oc, NULL, last_asked_format, filename);
last_asked_format = NULL;
Stefano Sabatini
committed
print_error(filename, err);
file_oformat= oc->oformat;
if (!strcmp(file_oformat->name, "ffm") &&
av_strstart(filename, "http:", NULL)) {
/* special case for files sent to ffserver: we get the stream
parameters from ffserver */
int err = read_ffserver_streams(oc, filename);
if (err < 0) {
print_error(filename, err);
use_video = file_oformat->video_codec != CODEC_ID_NONE || video_stream_copy || video_codec_name;
use_audio = file_oformat->audio_codec != CODEC_ID_NONE || audio_stream_copy || audio_codec_name;
use_subtitle = file_oformat->subtitle_codec != CODEC_ID_NONE || subtitle_stream_copy || subtitle_codec_name;
use_data = data_stream_copy || data_codec_name; /* XXX once generic data codec will be available add a ->data_codec reference and use it here */
Fabrice Bellard
committed
/* disable if no corresponding type found */
check_inputs(&input_has_video,
&input_has_audio,
&input_has_subtitle,
&input_has_data);
if (!input_has_video)
use_video = 0;
if (!input_has_audio)
use_audio = 0;
if (!input_has_subtitle)
use_subtitle = 0;
if (!input_has_data)
use_data = 0;
Fabrice Bellard
committed
/* manual disable */
if (audio_disable) use_audio = 0;
if (video_disable) use_video = 0;
if (subtitle_disable) use_subtitle = 0;
if (use_video) new_video_stream(oc, nb_output_files);
if (use_audio) new_audio_stream(oc, nb_output_files);
if (use_subtitle) new_subtitle_stream(oc, nb_output_files);
if (use_data) new_data_stream(oc, nb_output_files);
av_dict_copy(&oc->metadata, metadata, 0);
av_dict_free(&metadata);
av_dict_copy(&output_opts[nb_output_files], format_opts, 0);
output_files[nb_output_files++] = oc;
Fabrice Bellard
committed
/* check filename in case of an image number is expected */
if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
Michel Bardiaux
committed
if (!av_filename_number_test(oc->filename)) {
print_error(oc->filename, AVERROR(EINVAL));
Fabrice Bellard
committed
}
if (!(oc->oformat->flags & AVFMT_NOFILE)) {
/* test if it already exists to avoid loosing precious files */
filename[1] == ':' ||
av_strstart(filename, "file:", NULL))) {
if (avio_check(filename, 0) == 0) {
if (!using_stdin) {
fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
fflush(stderr);
fprintf(stderr, "Not overwriting - exiting\n");
}
else {
fprintf(stderr,"File '%s' already exists. Exiting.\n", filename);
}
if ((err = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE)) < 0) {
print_error(filename, err);