History

fftools/ffmpeg_sched: allow decoders to have multiple outputs

Will be useful for multilayer video.

Anton Khirnov committed 2 years ago

Commit 68c198f1 parent aef221b6 files · +100 −41Browse files

Showing the changes to fftools (6 of 6 files). Show all

Unified · Split

6 files
  1. fftools/ffmpeg_dec.c +5 −5
  2. fftools/ffmpeg_demux.c +1 −1
  3. fftools/ffmpeg_filter.c +2 −2
  4. fftools/ffmpeg_mux_init.c +1 −1
  5. fftools/ffmpeg_sched.c +75 −27
  6. fftools/ffmpeg_sched.h +16 −5
fftools/ffmpeg_dec.c+5−5
@@ -578,7 +578,7 @@ static int process_subtitle(DecoderPriv *dp, AVFrame *frame) · 577 unmodified lines
578578 if (!subtitle)
579579 return 0;
580580
581− ret = sch_dec_send(dp->sch, dp->sch_idx, frame);
581+ ret = sch_dec_send(dp->sch, dp->sch_idx, 0, frame);
582582 if (ret < 0)
583583 av_frame_unref(frame);
584584
@@ -620,7 +620,7 @@ static int transcode_subtitles(DecoderPriv *dp, const AVPacket *pkt, · 35 unmodified lines
620620 frame->time_base = pkt->time_base;
621621 frame->opaque = (void*)(intptr_t)FRAME_OPAQUE_SUB_HEARTBEAT;
622622
623− ret = sch_dec_send(dp->sch, dp->sch_idx, frame);
623+ ret = sch_dec_send(dp->sch, dp->sch_idx, 0, frame);
624624 return ret == AVERROR_EOF ? AVERROR_EXIT : ret;
625625 } else if (pkt && (intptr_t)pkt->opaque == PKT_OPAQUE_FIX_SUB_DURATION) {
626626 return fix_sub_duration_heartbeat(dp, av_rescale_q(pkt->pts, pkt->time_base,
@@ -773,7 +773,7 @@ static int packet_decode(DecoderPriv *dp, AVPacket *pkt, AVFrame *frame) · 146 unmodified lines
773773
774774 dp->dec.frames_decoded++;
775775
776− ret = sch_dec_send(dp->sch, dp->sch_idx, frame);
776+ ret = sch_dec_send(dp->sch, dp->sch_idx, 0, frame);
777777 if (ret < 0) {
778778 av_frame_unref(frame);
779779 return ret == AVERROR_EOF ? AVERROR_EXIT : ret;
@@ -951,7 +951,7 @@ static int decoder_thread(void *arg) · 171 unmodified lines
951951 dp->last_frame_pts + dp->last_frame_duration_est;
952952 dt.frame->time_base = dp->last_frame_tb;
953953
954− ret = sch_dec_send(dp->sch, dp->sch_idx, dt.frame);
954+ ret = sch_dec_send(dp->sch, dp->sch_idx, 0, dt.frame);
955955 if (ret < 0 && ret != AVERROR_EOF) {
956956 av_log(dp, AV_LOG_FATAL,
957957 "Error signalling EOF timestamp: %s\n", av_err2str(ret));
@@ -1355,7 +1355,7 @@ int dec_create(const OptionsContext *o, const char *arg, Scheduler *sch) · 397 unmodified lines
13551355 return ret;
13561356 enc_idx = ret;
13571357
1358− ret = sch_connect(sch, SCH_ENC(enc_idx), SCH_DEC(dp->sch_idx));
1358+ ret = sch_connect(sch, SCH_ENC(enc_idx), SCH_DEC_IN(dp->sch_idx));
13591359 if (ret < 0)
13601360 return ret;
13611361
fftools/ffmpeg_demux.c+1−1
@@ -954,7 +954,7 @@ static int ist_use(InputStream *ist, int decoding_needed) · 953 unmodified lines
954954 ds->sch_idx_dec = ret;
955955
956956 ret = sch_connect(d->sch, SCH_DSTREAM(d->f.index, ds->sch_idx_stream),
957− SCH_DEC(ds->sch_idx_dec));
957+ SCH_DEC_IN(ds->sch_idx_dec));
958958 if (ret < 0)
959959 return ret;
960960
fftools/ffmpeg_filter.c+2−2
@@ -686,7 +686,7 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist) · 685 unmodified lines
686686 if (dec_idx < 0)
687687 return dec_idx;
688688
689− ret = sch_connect(fgp->sch, SCH_DEC(dec_idx),
689+ ret = sch_connect(fgp->sch, SCH_DEC_OUT(dec_idx, 0),
690690 SCH_FILTER_IN(fgp->sch_idx, ifp->index));
691691 if (ret < 0)
692692 return ret;
@@ -732,7 +732,7 @@ static int ifilter_bind_dec(InputFilterPriv *ifp, Decoder *dec) · 39 unmodified lines
732732 if (dec_idx < 0)
733733 return dec_idx;
734734
735− ret = sch_connect(fgp->sch, SCH_DEC(dec_idx),
735+ ret = sch_connect(fgp->sch, SCH_DEC_OUT(dec_idx, 0),
736736 SCH_FILTER_IN(fgp->sch_idx, ifp->index));
737737 if (ret < 0)
738738 return ret;
fftools/ffmpeg_mux_init.c+1−1
@@ -1511,7 +1511,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, · 1510 unmodified lines
15111511 ms->sch_idx_src = sched_idx;
15121512
15131513 if (ost->enc) {
1514− ret = sch_connect(mux->sch, SCH_DEC(sched_idx),
1514+ ret = sch_connect(mux->sch, SCH_DEC_OUT(sched_idx, 0),
15151515 SCH_ENC(ms->sch_idx_enc));
15161516 if (ret < 0)
15171517 goto fail;
fftools/ffmpeg_sched.c+75−27
@@ -71,13 +71,19 @@ typedef struct SchTask { · 70 unmodified lines
7171 int thread_running;
7272 } SchTask;
7373
74+typedef struct SchDecOutput {
75+ SchedulerNode *dst;
76+ uint8_t *dst_finished;
77+ unsigned nb_dst;
78+} SchDecOutput;
79+
7480 typedef struct SchDec {
7581 const AVClass *class;
7682
7783 SchedulerNode src;
78− SchedulerNode *dst;
79− uint8_t *dst_finished;
80− unsigned nb_dst;
84+
85+ SchDecOutput *outputs;
86+ unsigned nb_outputs;
8187
8288 SchTask task;
8389 // Queue for receiving input packets, one stream.
@@ -513,8 +519,14 @@ void sch_free(Scheduler **psch) · 429 unmodified lines
513519
514520 av_thread_message_queue_free(&dec->queue_end_ts);
515521
516− av_freep(&dec->dst);
517− av_freep(&dec->dst_finished);
522+ for (unsigned j = 0; j < dec->nb_outputs; j++) {
523+ SchDecOutput *o = &dec->outputs[j];
524+
525+ av_freep(&o->dst);
526+ av_freep(&o->dst_finished);
527+ }
528+
529+ av_freep(&dec->outputs);
518530
519531 av_frame_free(&dec->send_frame);
520532 }
@@ -712,14 +724,28 @@ int sch_add_demux_stream(Scheduler *sch, unsigned demux_idx) · 191 unmodified lines
712724 return ret < 0 ? ret : d->nb_streams - 1;
713725 }
714726
727+int sch_add_dec_output(Scheduler *sch, unsigned dec_idx)
728+{
729+ SchDec *dec;
730+ int ret;
731+
732+ av_assert0(dec_idx < sch->nb_dec);
733+ dec = &sch->dec[dec_idx];
734+
735+ ret = GROW_ARRAY(dec->outputs, dec->nb_outputs);
736+ if (ret < 0)
737+ return ret;
738+
739+ return dec->nb_outputs - 1;
740+}
741+
715742 static const AVClass sch_dec_class = {
716743 .class_name = "SchDec",
717744 .version = LIBAVUTIL_VERSION_INT,
718745 .parent_log_context_offset = offsetof(SchDec, task.func_arg),
719746 };
720747
721−int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx,
722− int send_end_ts)
748+int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx, int send_end_ts)
723749 {
724750 const unsigned idx = sch->nb_dec;
725751
@@ -739,6 +765,10 @@ int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx, · 13 unmodified lines
739765 if (!dec->send_frame)
740766 return AVERROR(ENOMEM);
741767
768+ ret = sch_add_dec_output(sch, idx);
769+ if (ret < 0)
770+ return ret;
771+
742772 ret = queue_alloc(&dec->queue, 1, 0, QUEUE_PACKETS);
743773 if (ret < 0)
744774 return ret;
@@ -943,15 +973,19 @@ int sch_connect(Scheduler *sch, SchedulerNode src, SchedulerNode dst) · 198 unmodified lines
943973 }
944974 case SCH_NODE_TYPE_DEC: {
945975 SchDec *dec;
976+ SchDecOutput *o;
946977
947978 av_assert0(src.idx < sch->nb_dec);
948979 dec = &sch->dec[src.idx];
949980
950− ret = GROW_ARRAY(dec->dst, dec->nb_dst);
981+ av_assert0(src.idx_stream < dec->nb_outputs);
982+ o = &dec->outputs[src.idx_stream];
983+
984+ ret = GROW_ARRAY(o->dst, o->nb_dst);
951985 if (ret < 0)
952986 return ret;
953987
954− dec->dst[dec->nb_dst - 1] = dst;
988+ o->dst[o->nb_dst - 1] = dst;
955989
956990 // decoded frames go to filters or encoding
957991 switch (dst.type) {
@@ -1417,15 +1451,20 @@ static int start_prepare(Scheduler *sch) · 459 unmodified lines
14171451 "Decoder not connected to a source\n");
14181452 return AVERROR(EINVAL);
14191453 }
1420− if (!dec->nb_dst) {
1421− av_log(dec, AV_LOG_ERROR,
1422− "Decoder not connected to any sink\n");
1423− return AVERROR(EINVAL);
1424− }
14251454
1426− dec->dst_finished = av_calloc(dec->nb_dst, sizeof(*dec->dst_finished));
1427− if (!dec->dst_finished)
1428− return AVERROR(ENOMEM);
1455+ for (unsigned j = 0; j < dec->nb_outputs; j++) {
1456+ SchDecOutput *o = &dec->outputs[j];
1457+
1458+ if (!o->nb_dst) {
1459+ av_log(dec, AV_LOG_ERROR,
1460+ "Decoder output %u not connected to any sink\n", j);
1461+ return AVERROR(EINVAL);
1462+ }
1463+
1464+ o->dst_finished = av_calloc(o->nb_dst, sizeof(*o->dst_finished));
1465+ if (!o->dst_finished)
1466+ return AVERROR(ENOMEM);
1467+ }
14291468 }
14301469
14311470 for (unsigned i = 0; i < sch->nb_enc; i++) {
@@ -2171,21 +2210,26 @@ finish: · 739 unmodified lines
21712210 return AVERROR_EOF;
21722211 }
21732212
2174−int sch_dec_send(Scheduler *sch, unsigned dec_idx, AVFrame *frame)
2213+int sch_dec_send(Scheduler *sch, unsigned dec_idx,
2214+ unsigned out_idx, AVFrame *frame)
21752215 {
21762216 SchDec *dec;
2217+ SchDecOutput *o;
21772218 int ret;
21782219 unsigned nb_done = 0;
21792220
21802221 av_assert0(dec_idx < sch->nb_dec);
21812222 dec = &sch->dec[dec_idx];
21822223
2183− for (unsigned i = 0; i < dec->nb_dst; i++) {
2184− uint8_t *finished = &dec->dst_finished[i];
2224+ av_assert0(out_idx < dec->nb_outputs);
2225+ o = &dec->outputs[out_idx];
2226+
2227+ for (unsigned i = 0; i < o->nb_dst; i++) {
2228+ uint8_t *finished = &o->dst_finished[i];
21852229 AVFrame *to_send = frame;
21862230
21872231 // sending a frame consumes it, so make a temporary reference if needed
2188− if (i < dec->nb_dst - 1) {
2232+ if (i < o->nb_dst - 1) {
21892233 to_send = dec->send_frame;
21902234
21912235 // frame may sometimes contain props only,
@@ -2196,7 +2240,7 @@ int sch_dec_send(Scheduler *sch, unsigned dec_idx, AVFrame *frame) · 4 unmodified lines
21962240 return ret;
21972241 }
21982242
2199− ret = dec_send_to_dst(sch, dec->dst[i], finished, to_send);
2243+ ret = dec_send_to_dst(sch, o->dst[i], finished, to_send);
22002244 if (ret < 0) {
22012245 av_frame_unref(to_send);
22022246 if (ret == AVERROR_EOF) {
@@ -2207,7 +2251,7 @@ int sch_dec_send(Scheduler *sch, unsigned dec_idx, AVFrame *frame) · 4 unmodified lines
22072251 }
22082252 }
22092253
2210− return (nb_done == dec->nb_dst) ? AVERROR_EOF : 0;
2254+ return (nb_done == o->nb_dst) ? AVERROR_EOF : 0;
22112255 }
22122256
22132257 static int dec_done(Scheduler *sch, unsigned dec_idx)
@@ -2222,10 +2266,14 @@ static int dec_done(Scheduler *sch, unsigned dec_idx) · 8 unmodified lines
22222266 if (dec->queue_end_ts)
22232267 av_thread_message_queue_set_err_recv(dec->queue_end_ts, AVERROR_EOF);
22242268
2225− for (unsigned i = 0; i < dec->nb_dst; i++) {
2226− int err = dec_send_to_dst(sch, dec->dst[i], &dec->dst_finished[i], NULL);
2227− if (err < 0 && err != AVERROR_EOF)
2228− ret = err_merge(ret, err);
2269+ for (unsigned i = 0; i < dec->nb_outputs; i++) {
2270+ SchDecOutput *o = &dec->outputs[i];
2271+
2272+ for (unsigned j = 0; j < o->nb_dst; j++) {
2273+ int err = dec_send_to_dst(sch, o->dst[j], &o->dst_finished[j], NULL);
2274+ if (err < 0 && err != AVERROR_EOF)
2275+ ret = err_merge(ret, err);
2276+ }
22292277 }
22302278
22312279 return ret;
fftools/ffmpeg_sched.h+16−5
@@ -114,9 +114,12 @@ typedef int (*SchThreadFunc)(void *arg); · 113 unmodified lines
114114 #define SCH_MSTREAM(file, stream) \
115115 (SchedulerNode){ .type = SCH_NODE_TYPE_MUX, \
116116 .idx = file, .idx_stream = stream }
117−#define SCH_DEC(decoder) \
117+#define SCH_DEC_IN(decoder) \
118118 (SchedulerNode){ .type = SCH_NODE_TYPE_DEC, \
119− .idx = decoder }
119+ .idx = decoder }
120+#define SCH_DEC_OUT(decoder, out_idx) \
121+ (SchedulerNode){ .type = SCH_NODE_TYPE_DEC, \
122+ .idx = decoder, .idx_stream = out_idx }
120123 #define SCH_ENC(encoder) \
121124 (SchedulerNode){ .type = SCH_NODE_TYPE_ENC, \
122125 .idx = encoder }
@@ -178,8 +181,15 @@ int sch_add_demux_stream(Scheduler *sch, unsigned demux_idx); · 55 unmodified lines
178181 * @retval ">=0" Index of the newly-created decoder.
179182 * @retval "<0" Error code.
180183 */
181−int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx,
182− int send_end_ts);
184+int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx, int send_end_ts);
185+
186+/**
187+ * Add another output to decoder (e.g. for multiview video).
188+ *
189+ * @retval ">=0" Index of the newly-added decoder output.
190+ * @retval "<0" Error code.
191+ */
192+int sch_add_dec_output(Scheduler *sch, unsigned dec_idx);
183193
184194 /**
185195 * Add a filtergraph to the scheduler.
@@ -379,7 +389,8 @@ int sch_dec_receive(Scheduler *sch, unsigned dec_idx, struct AVPacket *pkt); · 193 unmodified lines
379389 * @retval AVERROR_EOF all consumers are done, should terminate decoding
380390 * @retval "another negative error code" other failure
381391 */
382−int sch_dec_send(Scheduler *sch, unsigned dec_idx, struct AVFrame *frame);
392+int sch_dec_send(Scheduler *sch, unsigned dec_idx,
393+ unsigned out_idx, struct AVFrame *frame);
383394
384395 /**
385396 * Called by filtergraph tasks to obtain frames for filtering. Will wait for a

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t