fftools/ffmpeg: remove the input_streams global

Replace it with an array of streams in each InputFile. This is a more
accurate reflection of the actual relationship between InputStream and
InputFile.

Analogous to what was previously done to output streams in
7ef7a22251.
This commit is contained in:
Anton Khirnov
2022-11-17 09:49:27 +01:00
parent 86e2ffedfe
commit fd8bf8d3b5
6 changed files with 161 additions and 144 deletions

View File

@@ -141,8 +141,6 @@ unsigned nb_output_dumped = 0;
static BenchmarkTimeStamps current_time; static BenchmarkTimeStamps current_time;
AVIOContext *progress_avio = NULL; AVIOContext *progress_avio = NULL;
InputStream **input_streams = NULL;
int nb_input_streams = 0;
InputFile **input_files = NULL; InputFile **input_files = NULL;
int nb_input_files = 0; int nb_input_files = 0;
@@ -279,7 +277,7 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts)
video frames could be accumulating in the filter graph while a filter video frames could be accumulating in the filter graph while a filter
(possibly overlay) is desperately waiting for a subtitle frame. */ (possibly overlay) is desperately waiting for a subtitle frame. */
for (i = 0; i < infile->nb_streams; i++) { for (i = 0; i < infile->nb_streams; i++) {
InputStream *ist2 = input_streams[infile->ist_index + i]; InputStream *ist2 = infile->streams[i];
if (!ist2->sub2video.frame) if (!ist2->sub2video.frame)
continue; continue;
/* subtitles seem to be usually muxed ahead of other streams; /* subtitles seem to be usually muxed ahead of other streams;
@@ -502,28 +500,6 @@ static int decode_interrupt_cb(void *ctx)
const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
static void ist_free(InputStream **pist)
{
InputStream *ist = *pist;
if (!ist)
return;
av_frame_free(&ist->decoded_frame);
av_packet_free(&ist->pkt);
av_dict_free(&ist->decoder_opts);
avsubtitle_free(&ist->prev_sub.subtitle);
av_frame_free(&ist->sub2video.frame);
av_freep(&ist->filters);
av_freep(&ist->hwaccel_device);
av_freep(&ist->dts_buffer);
avcodec_free_context(&ist->dec_ctx);
avcodec_parameters_free(&ist->par);
av_freep(pist);
}
static void ffmpeg_cleanup(int ret) static void ffmpeg_cleanup(int ret)
{ {
int i, j; int i, j;
@@ -580,9 +556,6 @@ static void ffmpeg_cleanup(int ret)
for (i = 0; i < nb_input_files; i++) for (i = 0; i < nb_input_files; i++)
ifile_close(&input_files[i]); ifile_close(&input_files[i]);
for (i = 0; i < nb_input_streams; i++)
ist_free(&input_streams[i]);
if (vstats_file) { if (vstats_file) {
if (fclose(vstats_file)) if (fclose(vstats_file))
av_log(NULL, AV_LOG_ERROR, av_log(NULL, AV_LOG_ERROR,
@@ -592,7 +565,6 @@ static void ffmpeg_cleanup(int ret)
av_freep(&vstats_filename); av_freep(&vstats_filename);
av_freep(&filter_nbthreads); av_freep(&filter_nbthreads);
av_freep(&input_streams);
av_freep(&input_files); av_freep(&input_files);
av_freep(&output_files); av_freep(&output_files);
@@ -628,6 +600,22 @@ static OutputStream *ost_iter(OutputStream *prev)
return NULL; return NULL;
} }
InputStream *ist_iter(InputStream *prev)
{
int if_idx = prev ? prev->file_index : 0;
int ist_idx = prev ? prev->st->index + 1 : 0;
for (; if_idx < nb_input_files; if_idx++) {
InputFile *f = input_files[if_idx];
if (ist_idx < f->nb_streams)
return f->streams[ist_idx];
ist_idx = 0;
}
return NULL;
}
void remove_avoptions(AVDictionary **a, AVDictionary *b) void remove_avoptions(AVDictionary **a, AVDictionary *b)
{ {
const AVDictionaryEntry *t = NULL; const AVDictionaryEntry *t = NULL;
@@ -1410,7 +1398,7 @@ static void print_final_stats(int64_t total_size)
i, f->ctx->url); i, f->ctx->url);
for (j = 0; j < f->nb_streams; j++) { for (j = 0; j < f->nb_streams; j++) {
InputStream *ist = input_streams[f->ist_index + j]; InputStream *ist = f->streams[j];
enum AVMediaType type = ist->par->codec_type; enum AVMediaType type = ist->par->codec_type;
total_size += ist->data_size; total_size += ist->data_size;
@@ -2541,10 +2529,9 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat
return *p; return *p;
} }
static int init_input_stream(int ist_index, char *error, int error_len) static int init_input_stream(InputStream *ist, char *error, int error_len)
{ {
int ret; int ret;
InputStream *ist = input_streams[ist_index];
if (ist->decoding_needed) { if (ist->decoding_needed) {
const AVCodec *codec = ist->dec; const AVCodec *codec = ist->dec;
@@ -3163,12 +3150,12 @@ static int transcode_init(void)
InputFile *ifile = input_files[i]; InputFile *ifile = input_files[i];
if (ifile->readrate || ifile->rate_emu) if (ifile->readrate || ifile->rate_emu)
for (j = 0; j < ifile->nb_streams; j++) for (j = 0; j < ifile->nb_streams; j++)
input_streams[j + ifile->ist_index]->start = av_gettime_relative(); ifile->streams[j]->start = av_gettime_relative();
} }
/* init input streams */ /* init input streams */
for (i = 0; i < nb_input_streams; i++) for (ist = ist_iter(NULL); ist; ist = ist_iter(ist))
if ((ret = init_input_stream(i, error, sizeof(error))) < 0) if ((ret = init_input_stream(ist, error, sizeof(error))) < 0)
goto dump_format; goto dump_format;
/* /*
@@ -3199,7 +3186,7 @@ static int transcode_init(void)
int discard = AVDISCARD_ALL; int discard = AVDISCARD_ALL;
for (k = 0; k < p->nb_stream_indexes; k++) for (k = 0; k < p->nb_stream_indexes; k++)
if (!input_streams[ifile->ist_index + p->stream_index[k]]->discard) { if (!ifile->streams[p->stream_index[k]]->discard) {
discard = AVDISCARD_DEFAULT; discard = AVDISCARD_DEFAULT;
break; break;
} }
@@ -3210,9 +3197,7 @@ static int transcode_init(void)
dump_format: dump_format:
/* dump the stream mapping */ /* dump the stream mapping */
av_log(NULL, AV_LOG_INFO, "Stream mapping:\n"); av_log(NULL, AV_LOG_INFO, "Stream mapping:\n");
for (i = 0; i < nb_input_streams; i++) { for (ist = ist_iter(NULL); ist; ist = ist_iter(ist)) {
ist = input_streams[i];
for (j = 0; j < ist->nb_filters; j++) { for (j = 0; j < ist->nb_filters; j++) {
if (!filtergraph_is_simple(ist->filters[j]->graph)) { if (!filtergraph_is_simple(ist->filters[j]->graph)) {
av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s", av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s",
@@ -3416,7 +3401,7 @@ static int check_keyboard_interaction(int64_t cur_time)
if (key == 'd' || key == 'D'){ if (key == 'd' || key == 'D'){
int debug=0; int debug=0;
if(key == 'D') { if(key == 'D') {
debug = input_streams[0]->dec_ctx->debug << 1; debug = ist_iter(NULL)->dec_ctx->debug << 1;
if(!debug) debug = 1; if(!debug) debug = 1;
while (debug & FF_DEBUG_DCT_COEFF) //unsupported, would just crash while (debug & FF_DEBUG_DCT_COEFF) //unsupported, would just crash
debug += debug; debug += debug;
@@ -3434,9 +3419,8 @@ static int check_keyboard_interaction(int64_t cur_time)
if (k <= 0 || sscanf(buf, "%d", &debug)!=1) if (k <= 0 || sscanf(buf, "%d", &debug)!=1)
fprintf(stderr,"error parsing debug value\n"); fprintf(stderr,"error parsing debug value\n");
} }
for(i=0;i<nb_input_streams;i++) { for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist))
input_streams[i]->dec_ctx->debug = debug; ist->dec_ctx->debug = debug;
}
for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
if (ost->enc_ctx) if (ost->enc_ctx)
ost->enc_ctx->debug = debug; ost->enc_ctx->debug = debug;
@@ -3480,7 +3464,7 @@ static void reset_eagain(void)
static void decode_flush(InputFile *ifile) static void decode_flush(InputFile *ifile)
{ {
for (int i = 0; i < ifile->nb_streams; i++) { for (int i = 0; i < ifile->nb_streams; i++) {
InputStream *ist = input_streams[ifile->ist_index + i]; InputStream *ist = ifile->streams[i];
int ret; int ret;
if (!ist->processing_needed) if (!ist->processing_needed)
@@ -3627,7 +3611,7 @@ static int process_input(int file_index)
} }
for (i = 0; i < ifile->nb_streams; i++) { for (i = 0; i < ifile->nb_streams; i++) {
ist = input_streams[ifile->ist_index + i]; ist = ifile->streams[i];
if (ist->processing_needed) { if (ist->processing_needed) {
ret = process_input_packet(ist, NULL, 0); ret = process_input_packet(ist, NULL, 0);
if (ret>0) if (ret>0)
@@ -3650,7 +3634,7 @@ static int process_input(int file_index)
reset_eagain(); reset_eagain();
ist = input_streams[ifile->ist_index + pkt->stream_index]; ist = ifile->streams[pkt->stream_index];
ist->data_size += pkt->size; ist->data_size += pkt->size;
ist->nb_packets++; ist->nb_packets++;
@@ -3682,8 +3666,8 @@ static int process_input(int file_index)
ts_discontinuity_process(ifile, ist, pkt); ts_discontinuity_process(ifile, ist, pkt);
if (debug_ts) { if (debug_ts) {
av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s off:%s off_time:%s\n", av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s off:%s off_time:%s\n",
ifile->ist_index + pkt->stream_index, ifile->index, pkt->stream_index,
av_get_media_type_string(ist->par->codec_type), av_get_media_type_string(ist->par->codec_type),
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base),
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base),
@@ -3887,8 +3871,7 @@ static int transcode(void)
} }
/* at the end of stream, we must flush the decoder buffers */ /* at the end of stream, we must flush the decoder buffers */
for (i = 0; i < nb_input_streams; i++) { for (ist = ist_iter(NULL); ist; ist = ist_iter(ist)) {
ist = input_streams[i];
if (!input_files[ist->file_index]->eof_reached) { if (!input_files[ist->file_index]->eof_reached) {
process_input_packet(ist, NULL, 0); process_input_packet(ist, NULL, 0);
} }
@@ -3924,8 +3907,7 @@ static int transcode(void)
} }
/* close each decoder */ /* close each decoder */
for (i = 0; i < nb_input_streams; i++) { for (ist = ist_iter(NULL); ist; ist = ist_iter(ist)) {
ist = input_streams[i];
if (ist->decoding_needed) { if (ist->decoding_needed) {
avcodec_close(ist->dec_ctx); avcodec_close(ist->dec_ctx);
} }

View File

@@ -437,7 +437,6 @@ typedef struct InputFile {
AVFormatContext *ctx; AVFormatContext *ctx;
int eof_reached; /* true if eof reached */ int eof_reached; /* true if eof reached */
int eagain; /* true if last read attempt returned EAGAIN */ int eagain; /* true if last read attempt returned EAGAIN */
int ist_index; /* index of first stream in input_streams */
int64_t input_ts_offset; int64_t input_ts_offset;
int input_sync_ref; int input_sync_ref;
/** /**
@@ -452,8 +451,13 @@ typedef struct InputFile {
int64_t last_ts; int64_t last_ts;
int64_t start_time; /* user-specified start time in AV_TIME_BASE or AV_NOPTS_VALUE */ int64_t start_time; /* user-specified start time in AV_TIME_BASE or AV_NOPTS_VALUE */
int64_t recording_time; int64_t recording_time;
int nb_streams; /* number of stream that ffmpeg is aware of; may be different
from ctx.nb_streams if new streams appear during av_read_frame() */ /* streams that ffmpeg is aware of;
* there may be extra streams in ctx that are not mapped to an InputStream
* if new streams appear dynamically during demuxing */
InputStream **streams;
int nb_streams;
int rate_emu; int rate_emu;
float readrate; float readrate;
int accurate_seek; int accurate_seek;
@@ -629,8 +633,6 @@ typedef struct OutputFile {
int bitexact; int bitexact;
} OutputFile; } OutputFile;
extern InputStream **input_streams;
extern int nb_input_streams;
extern InputFile **input_files; extern InputFile **input_files;
extern int nb_input_files; extern int nb_input_files;
@@ -766,6 +768,10 @@ void ifile_close(InputFile **f);
*/ */
int ifile_get_packet(InputFile *f, AVPacket **pkt); int ifile_get_packet(InputFile *f, AVPacket **pkt);
/* iterate over all input streams in all input files;
* pass NULL to start iteration */
InputStream *ist_iter(InputStream *prev);
#define SPECIFIER_OPT_FMT_str "%s" #define SPECIFIER_OPT_FMT_str "%s"
#define SPECIFIER_OPT_FMT_i "%i" #define SPECIFIER_OPT_FMT_i "%i"
#define SPECIFIER_OPT_FMT_i64 "%"PRId64 #define SPECIFIER_OPT_FMT_i64 "%"PRId64

View File

@@ -140,13 +140,13 @@ static int seek_to_start(Demuxer *d)
return ret; return ret;
got_durations++; got_durations++;
ist = input_streams[ifile->ist_index + dur.stream_idx]; ist = ifile->streams[dur.stream_idx];
ifile_duration_update(d, ist, dur.duration); ifile_duration_update(d, ist, dur.duration);
} }
} else { } else {
for (int i = 0; i < ifile->nb_streams; i++) { for (int i = 0; i < ifile->nb_streams; i++) {
int64_t duration = 0; int64_t duration = 0;
ist = input_streams[ifile->ist_index + i]; ist = ifile->streams[i];
if (ist->framerate.num) { if (ist->framerate.num) {
duration = av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base); duration = av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base);
@@ -169,14 +169,14 @@ static int seek_to_start(Demuxer *d)
static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict) static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict)
{ {
InputFile *ifile = &d->f; InputFile *ifile = &d->f;
InputStream *ist = input_streams[ifile->ist_index + pkt->stream_index]; InputStream *ist = ifile->streams[pkt->stream_index];
const int64_t start_time = ifile->start_time_effective; const int64_t start_time = ifile->start_time_effective;
int64_t duration; int64_t duration;
if (debug_ts) { if (debug_ts) {
av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d type:%s " av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d:%d type:%s "
"pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s\n", "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s\n",
ifile->ist_index + pkt->stream_index, ifile->index, pkt->stream_index,
av_get_media_type_string(ist->st->codecpar->codec_type), av_get_media_type_string(ist->st->codecpar->codec_type),
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base),
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base),
@@ -381,7 +381,7 @@ static int thread_start(Demuxer *d)
int nb_audio_dec = 0; int nb_audio_dec = 0;
for (int i = 0; i < f->nb_streams; i++) { for (int i = 0; i < f->nb_streams; i++) {
InputStream *ist = input_streams[f->ist_index + i]; InputStream *ist = f->streams[i];
nb_audio_dec += !!(ist->decoding_needed && nb_audio_dec += !!(ist->decoding_needed &&
ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO); ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO);
} }
@@ -428,7 +428,7 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt)
); );
float scale = f->rate_emu ? 1.0 : f->readrate; float scale = f->rate_emu ? 1.0 : f->readrate;
for (i = 0; i < f->nb_streams; i++) { for (i = 0; i < f->nb_streams; i++) {
InputStream *ist = input_streams[f->ist_index + i]; InputStream *ist = f->streams[i];
int64_t stream_ts_offset, pts, now; int64_t stream_ts_offset, pts, now;
if (!ist->nb_packets || (ist->decoding_needed && !ist->got_output)) continue; if (!ist->nb_packets || (ist->decoding_needed && !ist->got_output)) continue;
stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start); stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start);
@@ -447,13 +447,35 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt)
if (msg.looping) if (msg.looping)
return 1; return 1;
ist = input_streams[f->ist_index + msg.pkt->stream_index]; ist = f->streams[msg.pkt->stream_index];
ist->last_pkt_repeat_pict = msg.repeat_pict; ist->last_pkt_repeat_pict = msg.repeat_pict;
*pkt = msg.pkt; *pkt = msg.pkt;
return 0; return 0;
} }
static void ist_free(InputStream **pist)
{
InputStream *ist = *pist;
if (!ist)
return;
av_frame_free(&ist->decoded_frame);
av_packet_free(&ist->pkt);
av_dict_free(&ist->decoder_opts);
avsubtitle_free(&ist->prev_sub.subtitle);
av_frame_free(&ist->sub2video.frame);
av_freep(&ist->filters);
av_freep(&ist->hwaccel_device);
av_freep(&ist->dts_buffer);
avcodec_free_context(&ist->dec_ctx);
avcodec_parameters_free(&ist->par);
av_freep(pist);
}
void ifile_close(InputFile **pf) void ifile_close(InputFile **pf)
{ {
InputFile *f = *pf; InputFile *f = *pf;
@@ -464,6 +486,10 @@ void ifile_close(InputFile **pf)
thread_stop(d); thread_stop(d);
for (int i = 0; i < f->nb_streams; i++)
ist_free(&f->streams[i]);
av_freep(&f->streams);
avformat_close_input(&f->ctx); avformat_close_input(&f->ctx);
av_freep(pf); av_freep(pf);
@@ -562,10 +588,11 @@ static void add_display_matrix_to_stream(const OptionsContext *o,
vflip_set ? vflip : 0); vflip_set ? vflip : 0);
} }
/* Add all the streams from the given input file to the global /* Add all the streams from the given input file to the demuxer */
* list of input streams. */ static void add_input_streams(const OptionsContext *o, Demuxer *d)
static void add_input_streams(const OptionsContext *o, AVFormatContext *ic)
{ {
InputFile *f = &d->f;
AVFormatContext *ic = f->ctx;
int i, ret; int i, ret;
for (i = 0; i < ic->nb_streams; i++) { for (i = 0; i < ic->nb_streams; i++) {
@@ -582,9 +609,9 @@ static void add_input_streams(const OptionsContext *o, AVFormatContext *ic)
const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL, const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL,
0, AV_OPT_SEARCH_FAKE_OBJ); 0, AV_OPT_SEARCH_FAKE_OBJ);
ist = ALLOC_ARRAY_ELEM(input_streams, nb_input_streams); ist = ALLOC_ARRAY_ELEM(f->streams, f->nb_streams);
ist->st = st; ist->st = st;
ist->file_index = nb_input_files; ist->file_index = f->index;
ist->discard = 1; ist->discard = 1;
st->discard = AVDISCARD_ALL; st->discard = AVDISCARD_ALL;
ist->nb_samples = 0; ist->nb_samples = 0;
@@ -1017,24 +1044,16 @@ int ifile_open(const OptionsContext *o, const char *filename)
} }
} }
/* update the current parameters so that they match the one of the input stream */
add_input_streams(o, ic);
/* dump the file content */
av_dump_format(ic, nb_input_files, filename, 0);
d = allocate_array_elem(&input_files, sizeof(*d), &nb_input_files); d = allocate_array_elem(&input_files, sizeof(*d), &nb_input_files);
f = &d->f; f = &d->f;
f->ctx = ic; f->ctx = ic;
f->index = nb_input_files - 1; f->index = nb_input_files - 1;
f->ist_index = nb_input_streams - ic->nb_streams;
f->start_time = start_time; f->start_time = start_time;
f->recording_time = recording_time; f->recording_time = recording_time;
f->input_sync_ref = o->input_sync_ref; f->input_sync_ref = o->input_sync_ref;
f->input_ts_offset = o->input_ts_offset; f->input_ts_offset = o->input_ts_offset;
f->ts_offset = o->input_ts_offset - (copy_ts ? (start_at_zero && ic->start_time != AV_NOPTS_VALUE ? ic->start_time : 0) : timestamp); f->ts_offset = o->input_ts_offset - (copy_ts ? (start_at_zero && ic->start_time != AV_NOPTS_VALUE ? ic->start_time : 0) : timestamp);
f->nb_streams = ic->nb_streams;
f->rate_emu = o->rate_emu; f->rate_emu = o->rate_emu;
f->accurate_seek = o->accurate_seek; f->accurate_seek = o->accurate_seek;
d->loop = o->loop; d->loop = o->loop;
@@ -1053,11 +1072,17 @@ int ifile_open(const OptionsContext *o, const char *filename)
d->thread_queue_size = o->thread_queue_size; d->thread_queue_size = o->thread_queue_size;
/* update the current parameters so that they match the one of the input stream */
add_input_streams(o, d);
/* dump the file content */
av_dump_format(ic, f->index, filename, 0);
/* check if all codec options have been used */ /* check if all codec options have been used */
unused_opts = strip_specifiers(o->g->codec_opts); unused_opts = strip_specifiers(o->g->codec_opts);
for (i = f->ist_index; i < nb_input_streams; i++) { for (i = 0; i < f->nb_streams; i++) {
e = NULL; e = NULL;
while ((e = av_dict_get(input_streams[i]->decoder_opts, "", e, while ((e = av_dict_get(f->streams[i]->decoder_opts, "", e,
AV_DICT_IGNORE_SUFFIX))) AV_DICT_IGNORE_SUFFIX)))
av_dict_set(&unused_opts, e->key, NULL, 0); av_dict_set(&unused_opts, e->key, NULL, 0);
} }

View File

@@ -271,7 +271,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
"matches no streams.\n", p, fg->graph_desc); "matches no streams.\n", p, fg->graph_desc);
exit_program(1); exit_program(1);
} }
ist = input_streams[input_files[file_idx]->ist_index + st->index]; ist = input_files[file_idx]->streams[st->index];
if (ist->user_set_discard == AVDISCARD_ALL) { if (ist->user_set_discard == AVDISCARD_ALL) {
av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s "
"matches a disabled input stream.\n", p, fg->graph_desc); "matches a disabled input stream.\n", p, fg->graph_desc);
@@ -279,14 +279,13 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
} }
} else { } else {
/* find the first unused stream of corresponding type */ /* find the first unused stream of corresponding type */
for (i = 0; i < nb_input_streams; i++) { for (ist = ist_iter(NULL); ist; ist = ist_iter(ist)) {
ist = input_streams[i];
if (ist->user_set_discard == AVDISCARD_ALL) if (ist->user_set_discard == AVDISCARD_ALL)
continue; continue;
if (ist->dec_ctx->codec_type == type && ist->discard) if (ist->dec_ctx->codec_type == type && ist->discard)
break; break;
} }
if (i == nb_input_streams) { if (!ist) {
av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for " av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for "
"unlabeled input pad %d on filter %s\n", in->pad_idx, "unlabeled input pad %d on filter %s\n", in->pad_idx,
in->filter_ctx->name); in->filter_ctx->name);

View File

@@ -171,7 +171,7 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV
} }
static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o,
enum AVMediaType type, int source_index) enum AVMediaType type, InputStream *ist)
{ {
AVFormatContext *oc = mux->fc; AVFormatContext *oc = mux->fc;
MuxStream *ms; MuxStream *ms;
@@ -354,8 +354,8 @@ static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o,
if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24) if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24)
av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0); av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0);
if (source_index >= 0) { if (ist) {
ost->ist = input_streams[source_index]; ost->ist = ist;
ost->ist->discard = 0; ost->ist->discard = 0;
ost->ist->st->discard = ost->ist->user_set_discard; ost->ist->st->discard = ost->ist->user_set_discard;
} }
@@ -419,14 +419,14 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str)
} }
} }
static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, int source_index) static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, InputStream *ist)
{ {
AVFormatContext *oc = mux->fc; AVFormatContext *oc = mux->fc;
AVStream *st; AVStream *st;
OutputStream *ost; OutputStream *ost;
char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL; char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL;
ost = new_output_stream(mux, o, AVMEDIA_TYPE_VIDEO, source_index); ost = new_output_stream(mux, o, AVMEDIA_TYPE_VIDEO, ist);
st = ost->st; st = ost->st;
MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st);
@@ -657,13 +657,13 @@ static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, int s
return ost; return ost;
} }
static OutputStream *new_audio_stream(Muxer *mux, const OptionsContext *o, int source_index) static OutputStream *new_audio_stream(Muxer *mux, const OptionsContext *o, InputStream *ist)
{ {
AVFormatContext *oc = mux->fc; AVFormatContext *oc = mux->fc;
AVStream *st; AVStream *st;
OutputStream *ost; OutputStream *ost;
ost = new_output_stream(mux, o, AVMEDIA_TYPE_AUDIO, source_index); ost = new_output_stream(mux, o, AVMEDIA_TYPE_AUDIO, ist);
st = ost->st; st = ost->st;
@@ -755,11 +755,11 @@ static OutputStream *new_audio_stream(Muxer *mux, const OptionsContext *o, int s
return ost; return ost;
} }
static OutputStream *new_data_stream(Muxer *mux, const OptionsContext *o, int source_index) static OutputStream *new_data_stream(Muxer *mux, const OptionsContext *o, InputStream *ist)
{ {
OutputStream *ost; OutputStream *ost;
ost = new_output_stream(mux, o, AVMEDIA_TYPE_DATA, source_index); ost = new_output_stream(mux, o, AVMEDIA_TYPE_DATA, ist);
if (ost->enc_ctx) { if (ost->enc_ctx) {
av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n");
exit_program(1); exit_program(1);
@@ -768,11 +768,11 @@ static OutputStream *new_data_stream(Muxer *mux, const OptionsContext *o, int so
return ost; return ost;
} }
static OutputStream *new_unknown_stream(Muxer *mux, const OptionsContext *o, int source_index) static OutputStream *new_unknown_stream(Muxer *mux, const OptionsContext *o, InputStream *ist)
{ {
OutputStream *ost; OutputStream *ost;
ost = new_output_stream(mux, o, AVMEDIA_TYPE_UNKNOWN, source_index); ost = new_output_stream(mux, o, AVMEDIA_TYPE_UNKNOWN, ist);
if (ost->enc_ctx) { if (ost->enc_ctx) {
av_log(NULL, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n"); av_log(NULL, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n");
exit_program(1); exit_program(1);
@@ -781,19 +781,19 @@ static OutputStream *new_unknown_stream(Muxer *mux, const OptionsContext *o, int
return ost; return ost;
} }
static OutputStream *new_attachment_stream(Muxer *mux, const OptionsContext *o, int source_index) static OutputStream *new_attachment_stream(Muxer *mux, const OptionsContext *o, InputStream *ist)
{ {
OutputStream *ost = new_output_stream(mux, o, AVMEDIA_TYPE_ATTACHMENT, source_index); OutputStream *ost = new_output_stream(mux, o, AVMEDIA_TYPE_ATTACHMENT, ist);
ost->finished = 1; ost->finished = 1;
return ost; return ost;
} }
static OutputStream *new_subtitle_stream(Muxer *mux, const OptionsContext *o, int source_index) static OutputStream *new_subtitle_stream(Muxer *mux, const OptionsContext *o, InputStream *ist)
{ {
AVStream *st; AVStream *st;
OutputStream *ost; OutputStream *ost;
ost = new_output_stream(mux, o, AVMEDIA_TYPE_SUBTITLE, source_index); ost = new_output_stream(mux, o, AVMEDIA_TYPE_SUBTITLE, ist);
st = ost->st; st = ost->st;
if (ost->enc_ctx) { if (ost->enc_ctx) {
@@ -816,8 +816,8 @@ static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o,
OutputStream *ost; OutputStream *ost;
switch (ofilter->type) { switch (ofilter->type) {
case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(mux, o, -1); break; case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(mux, o, NULL); break;
case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(mux, o, -1); break; case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(mux, o, NULL); break;
default: default:
av_log(NULL, AV_LOG_FATAL, "Only video and audio filters are supported " av_log(NULL, AV_LOG_FATAL, "Only video and audio filters are supported "
"currently.\n"); "currently.\n");
@@ -854,8 +854,8 @@ static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o,
static void map_auto_video(Muxer *mux, const OptionsContext *o) static void map_auto_video(Muxer *mux, const OptionsContext *o)
{ {
AVFormatContext *oc = mux->fc; AVFormatContext *oc = mux->fc;
InputStream *ist; InputStream *best_ist = NULL;
int best_score = 0, idx = -1; int best_score = 0;
int qcr; int qcr;
/* video: highest resolution */ /* video: highest resolution */
@@ -865,10 +865,11 @@ static void map_auto_video(Muxer *mux, const OptionsContext *o)
qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0); qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0);
for (int j = 0; j < nb_input_files; j++) { for (int j = 0; j < nb_input_files; j++) {
InputFile *ifile = input_files[j]; InputFile *ifile = input_files[j];
int file_best_score = 0, file_best_idx = -1; InputStream *file_best_ist = NULL;
int file_best_score = 0;
for (int i = 0; i < ifile->nb_streams; i++) { for (int i = 0; i < ifile->nb_streams; i++) {
InputStream *ist = ifile->streams[i];
int score; int score;
ist = input_streams[ifile->ist_index + i];
if (ist->user_set_discard == AVDISCARD_ALL || if (ist->user_set_discard == AVDISCARD_ALL ||
ist->st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) ist->st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
@@ -884,27 +885,28 @@ static void map_auto_video(Muxer *mux, const OptionsContext *o)
if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
continue; continue;
file_best_score = score; file_best_score = score;
file_best_idx = ifile->ist_index + i; file_best_ist = ist;
} }
} }
if (file_best_idx >= 0) { if (file_best_ist) {
if((qcr == MKTAG('A', 'P', 'I', 'C')) || !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) if((qcr == MKTAG('A', 'P', 'I', 'C')) ||
file_best_score -= 5000000*!!(input_streams[file_best_idx]->st->disposition & AV_DISPOSITION_DEFAULT); !(file_best_ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
file_best_score -= 5000000*!!(file_best_ist->st->disposition & AV_DISPOSITION_DEFAULT);
if (file_best_score > best_score) { if (file_best_score > best_score) {
best_score = file_best_score; best_score = file_best_score;
idx = file_best_idx; best_ist = file_best_ist;
} }
} }
} }
if (idx >= 0) if (best_ist)
new_video_stream(mux, o, idx); new_video_stream(mux, o, best_ist);
} }
static void map_auto_audio(Muxer *mux, const OptionsContext *o) static void map_auto_audio(Muxer *mux, const OptionsContext *o)
{ {
AVFormatContext *oc = mux->fc; AVFormatContext *oc = mux->fc;
InputStream *ist; InputStream *best_ist = NULL;
int best_score = 0, idx = -1; int best_score = 0;
/* audio: most channels */ /* audio: most channels */
if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_AUDIO) == AV_CODEC_ID_NONE) if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_AUDIO) == AV_CODEC_ID_NONE)
@@ -912,10 +914,11 @@ static void map_auto_audio(Muxer *mux, const OptionsContext *o)
for (int j = 0; j < nb_input_files; j++) { for (int j = 0; j < nb_input_files; j++) {
InputFile *ifile = input_files[j]; InputFile *ifile = input_files[j];
int file_best_score = 0, file_best_idx = -1; InputStream *file_best_ist = NULL;
int file_best_score = 0;
for (int i = 0; i < ifile->nb_streams; i++) { for (int i = 0; i < ifile->nb_streams; i++) {
InputStream *ist = ifile->streams[i];
int score; int score;
ist = input_streams[ifile->ist_index + i];
if (ist->user_set_discard == AVDISCARD_ALL || if (ist->user_set_discard == AVDISCARD_ALL ||
ist->st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) ist->st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
@@ -926,19 +929,19 @@ static void map_auto_audio(Muxer *mux, const OptionsContext *o)
+ 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT);
if (score > file_best_score) { if (score > file_best_score) {
file_best_score = score; file_best_score = score;
file_best_idx = ifile->ist_index + i; file_best_ist = ist;
} }
} }
if (file_best_idx >= 0) { if (file_best_ist) {
file_best_score -= 5000000*!!(input_streams[file_best_idx]->st->disposition & AV_DISPOSITION_DEFAULT); file_best_score -= 5000000*!!(file_best_ist->st->disposition & AV_DISPOSITION_DEFAULT);
if (file_best_score > best_score) { if (file_best_score > best_score) {
best_score = file_best_score; best_score = file_best_score;
idx = file_best_idx; best_ist = file_best_ist;
} }
} }
} }
if (idx >= 0) if (best_ist)
new_audio_stream(mux, o, idx); new_audio_stream(mux, o, best_ist);
} }
static void map_auto_subtitle(Muxer *mux, const OptionsContext *o) static void map_auto_subtitle(Muxer *mux, const OptionsContext *o)
@@ -951,15 +954,15 @@ static void map_auto_subtitle(Muxer *mux, const OptionsContext *o)
if (!avcodec_find_encoder(oc->oformat->subtitle_codec) && !subtitle_codec_name) if (!avcodec_find_encoder(oc->oformat->subtitle_codec) && !subtitle_codec_name)
return; return;
for (int i = 0; i < nb_input_streams; i++) for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist))
if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
AVCodecDescriptor const *input_descriptor = AVCodecDescriptor const *input_descriptor =
avcodec_descriptor_get(input_streams[i]->st->codecpar->codec_id); avcodec_descriptor_get(ist->st->codecpar->codec_id);
AVCodecDescriptor const *output_descriptor = NULL; AVCodecDescriptor const *output_descriptor = NULL;
AVCodec const *output_codec = AVCodec const *output_codec =
avcodec_find_encoder(oc->oformat->subtitle_codec); avcodec_find_encoder(oc->oformat->subtitle_codec);
int input_props = 0, output_props = 0; int input_props = 0, output_props = 0;
if (input_streams[i]->user_set_discard == AVDISCARD_ALL) if (ist->user_set_discard == AVDISCARD_ALL)
continue; continue;
if (output_codec) if (output_codec)
output_descriptor = avcodec_descriptor_get(output_codec->id); output_descriptor = avcodec_descriptor_get(output_codec->id);
@@ -973,7 +976,7 @@ static void map_auto_subtitle(Muxer *mux, const OptionsContext *o)
input_descriptor && output_descriptor && input_descriptor && output_descriptor &&
(!input_descriptor->props || (!input_descriptor->props ||
!output_descriptor->props)) { !output_descriptor->props)) {
new_subtitle_stream(mux, o, i); new_subtitle_stream(mux, o, ist);
break; break;
} }
} }
@@ -984,12 +987,16 @@ static void map_auto_data(Muxer *mux, const OptionsContext *o)
AVFormatContext *oc = mux->fc; AVFormatContext *oc = mux->fc;
/* Data only if codec id match */ /* Data only if codec id match */
enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_DATA); enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_DATA);
for (int i = 0; codec_id != AV_CODEC_ID_NONE && i < nb_input_streams; i++) {
if (input_streams[i]->user_set_discard == AVDISCARD_ALL) if (codec_id == AV_CODEC_ID_NONE)
return;
for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) {
if (ist->user_set_discard == AVDISCARD_ALL)
continue; continue;
if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_DATA if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA &&
&& input_streams[i]->st->codecpar->codec_id == codec_id ) ist->st->codecpar->codec_id == codec_id )
new_data_stream(mux, o, i); new_data_stream(mux, o, ist);
} }
} }
@@ -1023,9 +1030,7 @@ loop_end:
} }
init_output_filter(ofilter, o, mux); init_output_filter(ofilter, o, mux);
} else { } else {
int src_idx = input_files[map->file_index]->ist_index + map->stream_index; ist = input_files[map->file_index]->streams[map->stream_index];
ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index];
if (ist->user_set_discard == AVDISCARD_ALL) { if (ist->user_set_discard == AVDISCARD_ALL) {
av_log(NULL, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n", av_log(NULL, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n",
map->file_index, map->stream_index); map->file_index, map->stream_index);
@@ -1041,14 +1046,14 @@ loop_end:
return; return;
switch (ist->st->codecpar->codec_type) { switch (ist->st->codecpar->codec_type) {
case AVMEDIA_TYPE_VIDEO: new_video_stream (mux, o, src_idx); break; case AVMEDIA_TYPE_VIDEO: new_video_stream (mux, o, ist); break;
case AVMEDIA_TYPE_AUDIO: new_audio_stream (mux, o, src_idx); break; case AVMEDIA_TYPE_AUDIO: new_audio_stream (mux, o, ist); break;
case AVMEDIA_TYPE_SUBTITLE: new_subtitle_stream (mux, o, src_idx); break; case AVMEDIA_TYPE_SUBTITLE: new_subtitle_stream (mux, o, ist); break;
case AVMEDIA_TYPE_DATA: new_data_stream (mux, o, src_idx); break; case AVMEDIA_TYPE_DATA: new_data_stream (mux, o, ist); break;
case AVMEDIA_TYPE_ATTACHMENT: new_attachment_stream(mux, o, src_idx); break; case AVMEDIA_TYPE_ATTACHMENT: new_attachment_stream(mux, o, ist); break;
case AVMEDIA_TYPE_UNKNOWN: case AVMEDIA_TYPE_UNKNOWN:
if (copy_unknown_streams) { if (copy_unknown_streams) {
new_unknown_stream (mux, o, src_idx); new_unknown_stream (mux, o, ist);
break; break;
} }
default: default:
@@ -1096,7 +1101,7 @@ static void of_add_attachments(Muxer *mux, const OptionsContext *o)
avio_read(pb, attachment, len); avio_read(pb, attachment, len);
memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
ost = new_attachment_stream(mux, o, -1); ost = new_attachment_stream(mux, o, NULL);
ost->attachment_filename = o->attachments[i]; ost->attachment_filename = o->attachments[i];
ost->st->codecpar->extradata = attachment; ost->st->codecpar->extradata = attachment;
ost->st->codecpar->extradata_size = len; ost->st->codecpar->extradata_size = len;

View File

@@ -417,7 +417,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg)
if (check_stream_specifier(input_files[file_idx]->ctx, input_files[file_idx]->ctx->streams[i], if (check_stream_specifier(input_files[file_idx]->ctx, input_files[file_idx]->ctx->streams[i],
*p == ':' ? p + 1 : p) <= 0) *p == ':' ? p + 1 : p) <= 0)
continue; continue;
if (input_streams[input_files[file_idx]->ist_index + i]->user_set_discard == AVDISCARD_ALL) { if (input_files[file_idx]->streams[i]->user_set_discard == AVDISCARD_ALL) {
disabled = 1; disabled = 1;
continue; continue;
} }
@@ -523,7 +523,7 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg)
if (allow_unused = strchr(mapchan, '?')) if (allow_unused = strchr(mapchan, '?'))
*allow_unused = 0; *allow_unused = 0;
if (m->channel_idx < 0 || m->channel_idx >= st->codecpar->ch_layout.nb_channels || if (m->channel_idx < 0 || m->channel_idx >= st->codecpar->ch_layout.nb_channels ||
input_streams[input_files[m->file_idx]->ist_index + m->stream_idx]->user_set_discard == AVDISCARD_ALL) { input_files[m->file_idx]->streams[m->stream_idx]->user_set_discard == AVDISCARD_ALL) {
if (allow_unused) { if (allow_unused) {
av_log(NULL, AV_LOG_VERBOSE, "mapchan: invalid audio channel #%d.%d.%d\n", av_log(NULL, AV_LOG_VERBOSE, "mapchan: invalid audio channel #%d.%d.%d\n",
m->file_idx, m->stream_idx, m->channel_idx); m->file_idx, m->stream_idx, m->channel_idx);