ffmpeg: add a wrapper for output AVFormatContexts and merge output_opts into it
This commit is contained in:
parent
0ea58d7115
commit
61b933f554
80
ffmpeg.c
80
ffmpeg.c
@ -114,10 +114,6 @@ static const OptionDef options[];
|
|||||||
static const char *last_asked_format = NULL;
|
static const char *last_asked_format = NULL;
|
||||||
static AVDictionary *ts_scale;
|
static AVDictionary *ts_scale;
|
||||||
|
|
||||||
static AVFormatContext *output_files[MAX_FILES];
|
|
||||||
static AVDictionary *output_opts[MAX_FILES];
|
|
||||||
static int nb_output_files = 0;
|
|
||||||
|
|
||||||
static StreamMap *stream_maps = NULL;
|
static StreamMap *stream_maps = NULL;
|
||||||
static int nb_stream_maps;
|
static int nb_stream_maps;
|
||||||
|
|
||||||
@ -333,11 +329,19 @@ typedef struct InputFile {
|
|||||||
static struct termios oldtty;
|
static struct termios oldtty;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct OutputFile {
|
||||||
|
AVFormatContext *ctx;
|
||||||
|
AVDictionary *opts;
|
||||||
|
} OutputFile;
|
||||||
|
|
||||||
static InputStream *input_streams = NULL;
|
static InputStream *input_streams = NULL;
|
||||||
static int nb_input_streams = 0;
|
static int nb_input_streams = 0;
|
||||||
static InputFile *input_files = NULL;
|
static InputFile *input_files = NULL;
|
||||||
static int nb_input_files = 0;
|
static int nb_input_files = 0;
|
||||||
|
|
||||||
|
static OutputFile *output_files = NULL;
|
||||||
|
static int nb_output_files = 0;
|
||||||
|
|
||||||
#if CONFIG_AVFILTER
|
#if CONFIG_AVFILTER
|
||||||
|
|
||||||
static int configure_video_filters(InputStream *ist, OutputStream *ost)
|
static int configure_video_filters(InputStream *ist, OutputStream *ost)
|
||||||
@ -517,12 +521,12 @@ static int exit_program(int ret)
|
|||||||
|
|
||||||
/* close files */
|
/* close files */
|
||||||
for(i=0;i<nb_output_files;i++) {
|
for(i=0;i<nb_output_files;i++) {
|
||||||
AVFormatContext *s = output_files[i];
|
AVFormatContext *s = output_files[i].ctx;
|
||||||
if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
|
if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
|
||||||
avio_close(s->pb);
|
avio_close(s->pb);
|
||||||
avformat_free_context(s);
|
avformat_free_context(s);
|
||||||
av_free(output_streams_for_file[i]);
|
av_free(output_streams_for_file[i]);
|
||||||
av_dict_free(&output_opts[i]);
|
av_dict_free(&output_files[i].opts);
|
||||||
}
|
}
|
||||||
for(i=0;i<nb_input_files;i++) {
|
for(i=0;i<nb_input_files;i++) {
|
||||||
av_close_input_file(input_files[i].ctx);
|
av_close_input_file(input_files[i].ctx);
|
||||||
@ -542,6 +546,7 @@ static int exit_program(int ret)
|
|||||||
|
|
||||||
av_freep(&input_streams);
|
av_freep(&input_streams);
|
||||||
av_freep(&input_files);
|
av_freep(&input_files);
|
||||||
|
av_freep(&output_files);
|
||||||
|
|
||||||
uninit_opts();
|
uninit_opts();
|
||||||
av_free(audio_buf);
|
av_free(audio_buf);
|
||||||
@ -1308,7 +1313,7 @@ static void do_video_stats(AVFormatContext *os, OutputStream *ost,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_report(AVFormatContext **output_files,
|
static void print_report(OutputFile *output_files,
|
||||||
OutputStream **ost_table, int nb_ostreams,
|
OutputStream **ost_table, int nb_ostreams,
|
||||||
int is_last_report)
|
int is_last_report)
|
||||||
{
|
{
|
||||||
@ -1337,7 +1342,7 @@ static void print_report(AVFormatContext **output_files,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
oc = output_files[0];
|
oc = output_files[0].ctx;
|
||||||
|
|
||||||
total_size = avio_size(oc->pb);
|
total_size = avio_size(oc->pb);
|
||||||
if(total_size<0) // FIXME improve avio_size() so it works with non seekable output too
|
if(total_size<0) // FIXME improve avio_size() so it works with non seekable output too
|
||||||
@ -1663,7 +1668,7 @@ static int output_packet(InputStream *ist, int ist_index,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
os = output_files[ost->file_index];
|
os = output_files[ost->file_index].ctx;
|
||||||
|
|
||||||
/* set the input output pts pairs */
|
/* set the input output pts pairs */
|
||||||
//ost->sync_ipts = (double)(ist->pts + input_files[ist->file_index].ts_offset - start_time)/ AV_TIME_BASE;
|
//ost->sync_ipts = (double)(ist->pts + input_files[ist->file_index].ts_offset - start_time)/ AV_TIME_BASE;
|
||||||
@ -1784,7 +1789,7 @@ static int output_packet(InputStream *ist, int ist_index,
|
|||||||
ost = ost_table[i];
|
ost = ost_table[i];
|
||||||
if (ost->source_index == ist_index) {
|
if (ost->source_index == ist_index) {
|
||||||
AVCodecContext *enc= ost->st->codec;
|
AVCodecContext *enc= ost->st->codec;
|
||||||
os = output_files[ost->file_index];
|
os = output_files[ost->file_index].ctx;
|
||||||
|
|
||||||
if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <=1)
|
if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <=1)
|
||||||
continue;
|
continue;
|
||||||
@ -1865,19 +1870,27 @@ static int output_packet(InputStream *ist, int ist_index,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_sdp(AVFormatContext **avc, int n)
|
static void print_sdp(OutputFile *output_files, int n)
|
||||||
{
|
{
|
||||||
char sdp[2048];
|
char sdp[2048];
|
||||||
|
int i;
|
||||||
|
AVFormatContext **avc = av_malloc(sizeof(*avc)*n);
|
||||||
|
|
||||||
|
if (!avc)
|
||||||
|
exit_program(1);
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
avc[i] = output_files[i].ctx;
|
||||||
|
|
||||||
av_sdp_create(avc, n, sdp, sizeof(sdp));
|
av_sdp_create(avc, n, sdp, sizeof(sdp));
|
||||||
printf("SDP:\n%s\n", sdp);
|
printf("SDP:\n%s\n", sdp);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
av_freep(&avc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following code is the main loop of the file converter
|
* The following code is the main loop of the file converter
|
||||||
*/
|
*/
|
||||||
static int transcode(AVFormatContext **output_files,
|
static int transcode(OutputFile *output_files,
|
||||||
int nb_output_files,
|
int nb_output_files,
|
||||||
InputFile *input_files,
|
InputFile *input_files,
|
||||||
int nb_input_files)
|
int nb_input_files)
|
||||||
@ -1903,9 +1916,9 @@ static int transcode(AVFormatContext **output_files,
|
|||||||
/* output stream init */
|
/* output stream init */
|
||||||
nb_ostreams = 0;
|
nb_ostreams = 0;
|
||||||
for(i=0;i<nb_output_files;i++) {
|
for(i=0;i<nb_output_files;i++) {
|
||||||
os = output_files[i];
|
os = output_files[i].ctx;
|
||||||
if (!os->nb_streams && !(os->oformat->flags & AVFMT_NOSTREAMS)) {
|
if (!os->nb_streams && !(os->oformat->flags & AVFMT_NOSTREAMS)) {
|
||||||
av_dump_format(output_files[i], i, output_files[i]->filename, 1);
|
av_dump_format(os, i, os->filename, 1);
|
||||||
fprintf(stderr, "Output file #%d does not contain any stream\n", i);
|
fprintf(stderr, "Output file #%d does not contain any stream\n", i);
|
||||||
ret = AVERROR(EINVAL);
|
ret = AVERROR(EINVAL);
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1918,7 +1931,7 @@ static int transcode(AVFormatContext **output_files,
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
for(k=0;k<nb_output_files;k++) {
|
for(k=0;k<nb_output_files;k++) {
|
||||||
os = output_files[k];
|
os = output_files[k].ctx;
|
||||||
for(i=0;i<os->nb_streams;i++,n++) {
|
for(i=0;i<os->nb_streams;i++,n++) {
|
||||||
nb_streams[os->streams[i]->codec->codec_type]++;
|
nb_streams[os->streams[i]->codec->codec_type]++;
|
||||||
}
|
}
|
||||||
@ -1955,7 +1968,7 @@ static int transcode(AVFormatContext **output_files,
|
|||||||
}
|
}
|
||||||
n = 0;
|
n = 0;
|
||||||
for(k=0;k<nb_output_files;k++) {
|
for(k=0;k<nb_output_files;k++) {
|
||||||
os = output_files[k];
|
os = output_files[k].ctx;
|
||||||
for (i = 0; i < os->nb_streams; i++, n++)
|
for (i = 0; i < os->nb_streams; i++, n++)
|
||||||
ost_table[n] = output_streams_for_file[k][i];
|
ost_table[n] = output_streams_for_file[k][i];
|
||||||
}
|
}
|
||||||
@ -1963,7 +1976,7 @@ static int transcode(AVFormatContext **output_files,
|
|||||||
/* for each output stream, we compute the right encoding parameters */
|
/* for each output stream, we compute the right encoding parameters */
|
||||||
for(i=0;i<nb_ostreams;i++) {
|
for(i=0;i<nb_ostreams;i++) {
|
||||||
ost = ost_table[i];
|
ost = ost_table[i];
|
||||||
os = output_files[ost->file_index];
|
os = output_files[ost->file_index].ctx;
|
||||||
ist = &input_streams[ost->source_index];
|
ist = &input_streams[ost->source_index];
|
||||||
|
|
||||||
codec = ost->st->codec;
|
codec = ost->st->codec;
|
||||||
@ -2255,15 +2268,15 @@ static int transcode(AVFormatContext **output_files,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* open files and write file headers */
|
/* open files and write file headers */
|
||||||
for(i=0;i<nb_output_files;i++) {
|
for (i = 0; i < nb_output_files; i++) {
|
||||||
os = output_files[i];
|
os = output_files[i].ctx;
|
||||||
if (avformat_write_header(os, &output_opts[i]) < 0) {
|
if (avformat_write_header(os, &output_files[i].opts) < 0) {
|
||||||
snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i);
|
snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i);
|
||||||
ret = AVERROR(EINVAL);
|
ret = AVERROR(EINVAL);
|
||||||
goto dump_format;
|
goto dump_format;
|
||||||
}
|
}
|
||||||
// assert_avoptions(output_opts[i]);
|
// assert_avoptions(output_files[i].opts);
|
||||||
if (strcmp(output_files[i]->oformat->name, "rtp")) {
|
if (strcmp(os->oformat->name, "rtp")) {
|
||||||
want_sdp = 0;
|
want_sdp = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2272,7 +2285,7 @@ static int transcode(AVFormatContext **output_files,
|
|||||||
/* dump the file output parameters - cannot be done before in case
|
/* dump the file output parameters - cannot be done before in case
|
||||||
of stream copy */
|
of stream copy */
|
||||||
for(i=0;i<nb_output_files;i++) {
|
for(i=0;i<nb_output_files;i++) {
|
||||||
av_dump_format(output_files[i], i, output_files[i]->filename, 1);
|
av_dump_format(output_files[i].ctx, i, output_files[i].ctx->filename, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dump the stream mapping */
|
/* dump the stream mapping */
|
||||||
@ -2408,7 +2421,7 @@ static int transcode(AVFormatContext **output_files,
|
|||||||
int64_t ipts;
|
int64_t ipts;
|
||||||
double opts;
|
double opts;
|
||||||
ost = ost_table[i];
|
ost = ost_table[i];
|
||||||
os = output_files[ost->file_index];
|
os = output_files[ost->file_index].ctx;
|
||||||
ist = &input_streams[ost->source_index];
|
ist = &input_streams[ost->source_index];
|
||||||
if(ist->is_past_recording_time || no_packet[ist->file_index])
|
if(ist->is_past_recording_time || no_packet[ist->file_index])
|
||||||
continue;
|
continue;
|
||||||
@ -2441,7 +2454,7 @@ static int transcode(AVFormatContext **output_files,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* finish if limit size exhausted */
|
/* finish if limit size exhausted */
|
||||||
if (limit_filesize != 0 && limit_filesize <= avio_tell(output_files[0]->pb))
|
if (limit_filesize != 0 && limit_filesize <= avio_tell(output_files[0].ctx->pb))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* read a frame from it and output it in the fifo */
|
/* read a frame from it and output it in the fifo */
|
||||||
@ -2538,7 +2551,7 @@ static int transcode(AVFormatContext **output_files,
|
|||||||
|
|
||||||
/* write the trailer if needed and close file */
|
/* write the trailer if needed and close file */
|
||||||
for(i=0;i<nb_output_files;i++) {
|
for(i=0;i<nb_output_files;i++) {
|
||||||
os = output_files[i];
|
os = output_files[i].ctx;
|
||||||
av_write_trailer(os);
|
av_write_trailer(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3622,7 +3635,7 @@ static int read_ffserver_streams(AVFormatContext *s, const char *filename)
|
|||||||
static int copy_chapters(int infile, int outfile)
|
static int copy_chapters(int infile, int outfile)
|
||||||
{
|
{
|
||||||
AVFormatContext *is = input_files[infile].ctx;
|
AVFormatContext *is = input_files[infile].ctx;
|
||||||
AVFormatContext *os = output_files[outfile];
|
AVFormatContext *os = output_files[outfile].ctx;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < is->nb_chapters; i++) {
|
for (i = 0; i < is->nb_chapters; i++) {
|
||||||
@ -3667,11 +3680,6 @@ static int opt_output_file(const char *opt, const char *filename)
|
|||||||
OutputStream *ost;
|
OutputStream *ost;
|
||||||
InputStream *ist;
|
InputStream *ist;
|
||||||
|
|
||||||
if(nb_output_files >= FF_ARRAY_ELEMS(output_files)){
|
|
||||||
fprintf(stderr, "Too many output files\n");
|
|
||||||
exit_program(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(filename, "-"))
|
if (!strcmp(filename, "-"))
|
||||||
filename = "pipe:";
|
filename = "pipe:";
|
||||||
|
|
||||||
@ -3768,8 +3776,12 @@ static int opt_output_file(const char *opt, const char *filename)
|
|||||||
av_dict_copy(&oc->metadata, metadata, 0);
|
av_dict_copy(&oc->metadata, metadata, 0);
|
||||||
av_dict_free(&metadata);
|
av_dict_free(&metadata);
|
||||||
|
|
||||||
av_dict_copy(&output_opts[nb_output_files], format_opts, 0);
|
|
||||||
output_files[nb_output_files++] = oc;
|
if (nb_output_files == MAX_FILES)
|
||||||
|
exit_program(1); /* a temporary hack until all the other MAX_FILES-sized arrays are removed */
|
||||||
|
output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1);
|
||||||
|
output_files[nb_output_files - 1].ctx = oc;
|
||||||
|
av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0);
|
||||||
|
|
||||||
/* check filename in case of an image number is expected */
|
/* check filename in case of an image number is expected */
|
||||||
if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
|
if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
|
||||||
|
Loading…
Reference in New Issue
Block a user