summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ffmpeg.c98
1 files changed, 83 insertions, 15 deletions
diff --git a/ffmpeg.c b/ffmpeg.c
index 93e3f04..7394e46 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -3337,20 +3337,23 @@ static int need_output(void)
return 0;
}
-static int select_input_file(uint8_t *no_packet)
+static int input_acceptable(InputStream *ist, uint8_t *no_packet)
{
- int64_t ipts_min = INT64_MAX;
- int i, file_index = -1;
-
- for (i = 0; i < nb_input_streams; i++) {
- InputStream *ist = input_streams[i];
- int64_t ipts = ist->pts;
+ av_assert1(!ist->discard);
+ return !no_packet[ist->file_index] &&
+ !input_files[ist->file_index]->eof_reached;
+}
- if (ist->discard || no_packet[ist->file_index])
- continue;
- if (!input_files[ist->file_index]->eof_reached) {
- if (ipts < ipts_min) {
- ipts_min = ipts;
+static int find_graph_input(FilterGraph *graph, uint8_t *no_packet)
+{
+ int i, nb_req_max = 0, file_index = -1;
+
+ for (i = 0; i < graph->nb_inputs; i++) {
+ 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)) {
+ nb_req_max = nb_req;
file_index = ist->file_index;
}
}
@@ -3359,6 +3362,65 @@ static int select_input_file(uint8_t *no_packet)
return file_index;
}
+/**
+ * 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)
+{
+ 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);
+ while (nb_active_out) {
+ opts_min = INT64_MAX;
+ ost_index = -1;
+ for (i = 0; i < nb_output_streams; i++) {
+ 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) {
+ opts_min = opts;
+ ost_index = i;
+ }
+ }
+ if (ost_index < 0)
+ return -1;
+
+ ost = output_streams[ost_index];
+ 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))
+ return ist->file_index;
+ } else {
+ /* ost is connected to a complex filtergraph */
+ av_assert1(ost->filter);
+ ret = av_buffersink_get_buffer_ref(ost->filter->filter, &dummy,
+ AV_BUFFERSINK_FLAG_PEEK);
+ if (ret >= 0)
+ return -2;
+ ret = find_graph_input(ost->filter->graph, no_packet);
+ if (ret >= 0)
+ return ret;
+ }
+ no_frame[ost_index] = 1;
+ nb_active_out--;
+ }
+ return -1;
+}
+
static int check_keyboard_interaction(int64_t cur_time)
{
int i, ret, key;
@@ -3580,12 +3642,13 @@ static int transcode(void)
AVFormatContext *is, *os;
OutputStream *ost;
InputStream *ist;
- uint8_t *no_packet;
+ uint8_t *no_packet, *no_frame;
int no_packet_count = 0;
int64_t timer_start;
- if (!(no_packet = av_mallocz(nb_input_files)))
+ 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)
@@ -3619,8 +3682,12 @@ static int transcode(void)
}
/* select the stream that we must read now */
- file_index = select_input_file(no_packet);
+ file_index = select_input_file(no_packet, no_frame);
/* if none, if is finished */
+ if (file_index == -2) {
+ poll_filters() ;
+ continue;
+ }
if (file_index < 0) {
if (no_packet_count) {
no_packet_count = 0;
@@ -3652,6 +3719,7 @@ static int transcode(void)
ist = input_streams[input_files[file_index]->ist_index + i];
if (ist->decoding_needed)
output_packet(ist, NULL);
+ poll_filters();
}
if (opt_shortest)
OpenPOWER on IntegriCloud