|
|
|
@ -262,6 +262,7 @@ typedef struct InputStream { |
|
|
|
|
typedef struct InputFile { |
|
|
|
|
AVFormatContext *ctx; |
|
|
|
|
int eof_reached; /* true if eof reached */ |
|
|
|
|
int unavailable; /* true if the file is unavailable (possibly temporarily) */ |
|
|
|
|
int ist_index; /* index of first stream in input_streams */ |
|
|
|
|
int64_t ts_offset; |
|
|
|
|
int nb_streams; /* number of stream that ffmpeg is aware of; may be different
|
|
|
|
@ -325,6 +326,7 @@ typedef struct OutputStream { |
|
|
|
|
double swr_dither_scale; |
|
|
|
|
AVDictionary *opts; |
|
|
|
|
int is_past_recording_time; |
|
|
|
|
int unavailable; /* true if the steram is unavailable (possibly temporarily) */ |
|
|
|
|
int stream_copy; |
|
|
|
|
const char *attachment_filename; |
|
|
|
|
int copy_initial_nonkeyframes; |
|
|
|
@ -3337,14 +3339,14 @@ static int need_output(void) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int input_acceptable(InputStream *ist, uint8_t *no_packet) |
|
|
|
|
static int input_acceptable(InputStream *ist) |
|
|
|
|
{ |
|
|
|
|
av_assert1(!ist->discard); |
|
|
|
|
return !no_packet[ist->file_index] && |
|
|
|
|
return !input_files[ist->file_index]->unavailable && |
|
|
|
|
!input_files[ist->file_index]->eof_reached; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int find_graph_input(FilterGraph *graph, uint8_t *no_packet) |
|
|
|
|
static int find_graph_input(FilterGraph *graph) |
|
|
|
|
{ |
|
|
|
|
int i, nb_req_max = 0, file_index = -1; |
|
|
|
|
|
|
|
|
@ -3352,7 +3354,7 @@ static int find_graph_input(FilterGraph *graph, uint8_t *no_packet) |
|
|
|
|
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, no_packet)) { |
|
|
|
|
if (input_acceptable(ist)) { |
|
|
|
|
nb_req_max = nb_req; |
|
|
|
|
file_index = ist->file_index; |
|
|
|
|
} |
|
|
|
@ -3365,23 +3367,20 @@ static int find_graph_input(FilterGraph *graph, uint8_t *no_packet) |
|
|
|
|
/**
|
|
|
|
|
* Select the input file to read from. |
|
|
|
|
* |
|
|
|
|
* @param no_packet array of booleans, one per input file; |
|
|
|
|
* if set, the input file must not be considered |
|
|
|
|
* @param no_frame array of boolean, one per output stream; |
|
|
|
|
* if set, the stream must not be considered; |
|
|
|
|
* for internal use |
|
|
|
|
* @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(uint8_t *no_packet, uint8_t *no_frame) |
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
memset(no_frame, 0, nb_output_streams); |
|
|
|
|
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; |
|
|
|
@ -3389,8 +3388,7 @@ static int select_input_file(uint8_t *no_packet, uint8_t *no_frame) |
|
|
|
|
OutputStream *ost = output_streams[i]; |
|
|
|
|
int64_t opts = av_rescale_q(ost->st->cur_dts, ost->st->time_base, |
|
|
|
|
AV_TIME_BASE_Q); |
|
|
|
|
if (!no_frame[i] && !ost->is_past_recording_time && |
|
|
|
|
opts < opts_min) { |
|
|
|
|
if (!ost->unavailable && opts < opts_min) { |
|
|
|
|
opts_min = opts; |
|
|
|
|
ost_index = i; |
|
|
|
|
} |
|
|
|
@ -3402,7 +3400,7 @@ static int select_input_file(uint8_t *no_packet, uint8_t *no_frame) |
|
|
|
|
if (ost->source_index >= 0) { |
|
|
|
|
/* ost is directly connected to an input */ |
|
|
|
|
InputStream *ist = input_streams[ost->source_index]; |
|
|
|
|
if (input_acceptable(ist, no_packet)) |
|
|
|
|
if (input_acceptable(ist)) |
|
|
|
|
return ist->file_index; |
|
|
|
|
} else { |
|
|
|
|
/* ost is connected to a complex filtergraph */ |
|
|
|
@ -3411,11 +3409,11 @@ static int select_input_file(uint8_t *no_packet, uint8_t *no_frame) |
|
|
|
|
AV_BUFFERSINK_FLAG_PEEK); |
|
|
|
|
if (ret >= 0) |
|
|
|
|
return -2; |
|
|
|
|
ret = find_graph_input(ost->filter->graph, no_packet); |
|
|
|
|
ret = find_graph_input(ost->filter->graph); |
|
|
|
|
if (ret >= 0) |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
no_frame[ost_index] = 1; |
|
|
|
|
ost->unavailable = 1; |
|
|
|
|
nb_active_out--; |
|
|
|
|
} |
|
|
|
|
return -1; |
|
|
|
@ -3642,14 +3640,9 @@ static int transcode(void) |
|
|
|
|
AVFormatContext *is, *os; |
|
|
|
|
OutputStream *ost; |
|
|
|
|
InputStream *ist; |
|
|
|
|
uint8_t *no_packet, *no_frame; |
|
|
|
|
int no_packet_count = 0; |
|
|
|
|
int64_t timer_start; |
|
|
|
|
|
|
|
|
|
if (!(no_packet = av_mallocz(nb_input_files + nb_output_streams))) |
|
|
|
|
exit_program(1); |
|
|
|
|
no_frame = no_packet + nb_input_files; |
|
|
|
|
|
|
|
|
|
ret = transcode_init(); |
|
|
|
|
if (ret < 0) |
|
|
|
|
goto fail; |
|
|
|
@ -3682,7 +3675,7 @@ static int transcode(void) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* select the stream that we must read now */ |
|
|
|
|
file_index = select_input_file(no_packet, no_frame); |
|
|
|
|
file_index = select_input_file(); |
|
|
|
|
/* if none, if is finished */ |
|
|
|
|
if (file_index == -2) { |
|
|
|
|
poll_filters() ; |
|
|
|
@ -3691,7 +3684,8 @@ static int transcode(void) |
|
|
|
|
if (file_index < 0) { |
|
|
|
|
if (no_packet_count) { |
|
|
|
|
no_packet_count = 0; |
|
|
|
|
memset(no_packet, 0, nb_input_files); |
|
|
|
|
for (i = 0; i < nb_input_files; i++) |
|
|
|
|
input_files[i]->unavailable = 0; |
|
|
|
|
av_usleep(10000); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
@ -3703,7 +3697,7 @@ static int transcode(void) |
|
|
|
|
ret = get_input_packet(input_files[file_index], &pkt); |
|
|
|
|
|
|
|
|
|
if (ret == AVERROR(EAGAIN)) { |
|
|
|
|
no_packet[file_index] = 1; |
|
|
|
|
input_files[file_index]->unavailable = 1; |
|
|
|
|
no_packet_count++; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
@ -3729,7 +3723,8 @@ static int transcode(void) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
no_packet_count = 0; |
|
|
|
|
memset(no_packet, 0, nb_input_files); |
|
|
|
|
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, |
|
|
|
@ -3866,7 +3861,6 @@ static int transcode(void) |
|
|
|
|
ret = 0; |
|
|
|
|
|
|
|
|
|
fail: |
|
|
|
|
av_freep(&no_packet); |
|
|
|
|
#if HAVE_PTHREADS |
|
|
|
|
free_input_threads(); |
|
|
|
|
#endif |
|
|
|
|