|
|
|
@ -680,130 +680,6 @@ static void choose_pixel_fmt(AVStream *st, AVCodec *codec) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum CodecID find_codec_or_die(const char *name, enum AVMediaType 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) { |
|
|
|
|
av_log(NULL, AV_LOG_ERROR, "Unknown %s '%s'\n", codec_string, name); |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
if(codec->type != type) { |
|
|
|
|
av_log(NULL, AV_LOG_ERROR, "Invalid %s type '%s'\n", codec_string, name); |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
return codec->id; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static AVCodec *choose_codec(AVFormatContext *s, AVStream *st, enum AVMediaType type, AVDictionary *codec_names) |
|
|
|
|
{ |
|
|
|
|
AVDictionaryEntry *e = NULL; |
|
|
|
|
char *codec_name = NULL; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
while (e = av_dict_get(codec_names, "", e, AV_DICT_IGNORE_SUFFIX)) { |
|
|
|
|
char *p = strchr(e->key, ':'); |
|
|
|
|
|
|
|
|
|
if ((ret = check_stream_specifier(s, st, p ? p + 1 : "")) > 0) |
|
|
|
|
codec_name = e->value; |
|
|
|
|
else if (ret < 0) |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!codec_name) { |
|
|
|
|
if (s->oformat) { |
|
|
|
|
st->codec->codec_id = av_guess_codec(s->oformat, NULL, s->filename, NULL, type); |
|
|
|
|
return avcodec_find_encoder(st->codec->codec_id); |
|
|
|
|
} |
|
|
|
|
} else if (!strcmp(codec_name, "copy")) |
|
|
|
|
st->stream_copy = 1; |
|
|
|
|
else { |
|
|
|
|
st->codec->codec_id = find_codec_or_die(codec_name, type, s->iformat == NULL); |
|
|
|
|
return s->oformat ? avcodec_find_encoder_by_name(codec_name) : |
|
|
|
|
avcodec_find_decoder_by_name(codec_name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static OutputStream *new_output_stream(AVFormatContext *oc, int file_idx, enum AVMediaType type) |
|
|
|
|
{ |
|
|
|
|
OutputStream *ost; |
|
|
|
|
AVStream *st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0); |
|
|
|
|
int idx = oc->nb_streams - 1; |
|
|
|
|
|
|
|
|
|
if (!st) { |
|
|
|
|
av_log(NULL, AV_LOG_ERROR, "Could not alloc stream.\n"); |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
output_streams_for_file[file_idx] = |
|
|
|
|
grow_array(output_streams_for_file[file_idx], |
|
|
|
|
sizeof(*output_streams_for_file[file_idx]), |
|
|
|
|
&nb_output_streams_for_file[file_idx], |
|
|
|
|
oc->nb_streams); |
|
|
|
|
ost = output_streams_for_file[file_idx][idx] = |
|
|
|
|
av_mallocz(sizeof(OutputStream)); |
|
|
|
|
if (!ost) { |
|
|
|
|
fprintf(stderr, "Could not alloc output stream\n"); |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
ost->file_index = file_idx; |
|
|
|
|
ost->index = idx; |
|
|
|
|
ost->st = st; |
|
|
|
|
st->codec->codec_type = type; |
|
|
|
|
ost->enc = choose_codec(oc, st, type, codec_names); |
|
|
|
|
if (ost->enc) { |
|
|
|
|
ost->opts = filter_codec_opts(codec_opts, ost->enc->id, oc, st); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
avcodec_get_context_defaults3(st->codec, ost->enc); |
|
|
|
|
st->codec->codec_type = type; // XXX hack, avcodec_get_context_defaults2() sets type to unknown for stream copy
|
|
|
|
|
|
|
|
|
|
ost->sws_flags = av_get_int(sws_opts, "sws_flags", NULL); |
|
|
|
|
return ost; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int read_ffserver_streams(AVFormatContext *s, const char *filename) |
|
|
|
|
{ |
|
|
|
|
int i, err; |
|
|
|
|
AVFormatContext *ic = NULL; |
|
|
|
|
|
|
|
|
|
err = avformat_open_input(&ic, filename, NULL, NULL); |
|
|
|
|
if (err < 0) |
|
|
|
|
return err; |
|
|
|
|
/* copy stream format */ |
|
|
|
|
for(i=0;i<ic->nb_streams;i++) { |
|
|
|
|
AVStream *st; |
|
|
|
|
OutputStream *ost; |
|
|
|
|
AVCodec *codec; |
|
|
|
|
|
|
|
|
|
codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id); |
|
|
|
|
ost = new_output_stream(s, nb_output_files, codec->type); |
|
|
|
|
st = ost->st; |
|
|
|
|
|
|
|
|
|
// FIXME: a more elegant solution is needed
|
|
|
|
|
memcpy(st, ic->streams[i], sizeof(AVStream)); |
|
|
|
|
st->info = av_malloc(sizeof(*st->info)); |
|
|
|
|
memcpy(st->info, ic->streams[i]->info, sizeof(*st->info)); |
|
|
|
|
avcodec_copy_context(st->codec, ic->streams[i]->codec); |
|
|
|
|
|
|
|
|
|
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !st->stream_copy) |
|
|
|
|
choose_sample_fmt(st, codec); |
|
|
|
|
else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !st->stream_copy) |
|
|
|
|
choose_pixel_fmt(st, codec); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
av_close_input_file(ic); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static double |
|
|
|
|
get_sync_ipts(const OutputStream *ost) |
|
|
|
|
{ |
|
|
|
@ -3118,6 +2994,57 @@ static int opt_input_ts_offset(const char *opt, const char *arg) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum CodecID find_codec_or_die(const char *name, enum AVMediaType 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) { |
|
|
|
|
av_log(NULL, AV_LOG_ERROR, "Unknown %s '%s'\n", codec_string, name); |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
if(codec->type != type) { |
|
|
|
|
av_log(NULL, AV_LOG_ERROR, "Invalid %s type '%s'\n", codec_string, name); |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
return codec->id; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static AVCodec *choose_codec(AVFormatContext *s, AVStream *st, enum AVMediaType type, AVDictionary *codec_names) |
|
|
|
|
{ |
|
|
|
|
AVDictionaryEntry *e = NULL; |
|
|
|
|
char *codec_name = NULL; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
while (e = av_dict_get(codec_names, "", e, AV_DICT_IGNORE_SUFFIX)) { |
|
|
|
|
char *p = strchr(e->key, ':'); |
|
|
|
|
|
|
|
|
|
if ((ret = check_stream_specifier(s, st, p ? p + 1 : "")) > 0) |
|
|
|
|
codec_name = e->value; |
|
|
|
|
else if (ret < 0) |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!codec_name) { |
|
|
|
|
if (s->oformat) { |
|
|
|
|
st->codec->codec_id = av_guess_codec(s->oformat, NULL, s->filename, NULL, type); |
|
|
|
|
return avcodec_find_encoder(st->codec->codec_id); |
|
|
|
|
} |
|
|
|
|
} else if (!strcmp(codec_name, "copy")) |
|
|
|
|
st->stream_copy = 1; |
|
|
|
|
else { |
|
|
|
|
st->codec->codec_id = find_codec_or_die(codec_name, type, s->iformat == NULL); |
|
|
|
|
return s->oformat ? avcodec_find_encoder_by_name(codec_name) : |
|
|
|
|
avcodec_find_decoder_by_name(codec_name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int opt_input_file(const char *opt, const char *filename) |
|
|
|
|
{ |
|
|
|
@ -3361,6 +3288,44 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static OutputStream *new_output_stream(AVFormatContext *oc, int file_idx, enum AVMediaType type) |
|
|
|
|
{ |
|
|
|
|
OutputStream *ost; |
|
|
|
|
AVStream *st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0); |
|
|
|
|
int idx = oc->nb_streams - 1; |
|
|
|
|
|
|
|
|
|
if (!st) { |
|
|
|
|
av_log(NULL, AV_LOG_ERROR, "Could not alloc stream.\n"); |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
output_streams_for_file[file_idx] = |
|
|
|
|
grow_array(output_streams_for_file[file_idx], |
|
|
|
|
sizeof(*output_streams_for_file[file_idx]), |
|
|
|
|
&nb_output_streams_for_file[file_idx], |
|
|
|
|
oc->nb_streams); |
|
|
|
|
ost = output_streams_for_file[file_idx][idx] = |
|
|
|
|
av_mallocz(sizeof(OutputStream)); |
|
|
|
|
if (!ost) { |
|
|
|
|
fprintf(stderr, "Could not alloc output stream\n"); |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
ost->file_index = file_idx; |
|
|
|
|
ost->index = idx; |
|
|
|
|
ost->st = st; |
|
|
|
|
st->codec->codec_type = type; |
|
|
|
|
ost->enc = choose_codec(oc, st, type, codec_names); |
|
|
|
|
if (ost->enc) { |
|
|
|
|
ost->opts = filter_codec_opts(codec_opts, ost->enc->id, oc, st); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
avcodec_get_context_defaults3(st->codec, ost->enc); |
|
|
|
|
st->codec->codec_type = type; // XXX hack, avcodec_get_context_defaults2() sets type to unknown for stream copy
|
|
|
|
|
|
|
|
|
|
ost->sws_flags = av_get_int(sws_opts, "sws_flags", NULL); |
|
|
|
|
return ost; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static OutputStream *new_video_stream(AVFormatContext *oc, int file_idx) |
|
|
|
|
{ |
|
|
|
|
AVStream *st; |
|
|
|
@ -3600,6 +3565,40 @@ static int opt_streamid(const char *opt, const char *arg) |
|
|
|
|
streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
static int read_ffserver_streams(AVFormatContext *s, const char *filename) |
|
|
|
|
{ |
|
|
|
|
int i, err; |
|
|
|
|
AVFormatContext *ic = NULL; |
|
|
|
|
|
|
|
|
|
err = avformat_open_input(&ic, filename, NULL, NULL); |
|
|
|
|
if (err < 0) |
|
|
|
|
return err; |
|
|
|
|
/* copy stream format */ |
|
|
|
|
for(i=0;i<ic->nb_streams;i++) { |
|
|
|
|
AVStream *st; |
|
|
|
|
OutputStream *ost; |
|
|
|
|
AVCodec *codec; |
|
|
|
|
|
|
|
|
|
codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id); |
|
|
|
|
ost = new_output_stream(s, nb_output_files, codec->type); |
|
|
|
|
st = ost->st; |
|
|
|
|
|
|
|
|
|
// FIXME: a more elegant solution is needed
|
|
|
|
|
memcpy(st, ic->streams[i], sizeof(AVStream)); |
|
|
|
|
st->info = av_malloc(sizeof(*st->info)); |
|
|
|
|
memcpy(st->info, ic->streams[i]->info, sizeof(*st->info)); |
|
|
|
|
avcodec_copy_context(st->codec, ic->streams[i]->codec); |
|
|
|
|
|
|
|
|
|
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !st->stream_copy) |
|
|
|
|
choose_sample_fmt(st, codec); |
|
|
|
|
else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !st->stream_copy) |
|
|
|
|
choose_pixel_fmt(st, codec); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
av_close_input_file(ic); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int copy_chapters(int infile, int outfile) |
|
|
|
|
{ |
|
|
|
|