| @@ -71,13 +71,19 @@ typedef struct SchTask { · 70 unmodified lines |
| 71 | int thread_running; | 71 | int thread_running; |
| 72 | } SchTask; | 72 | } SchTask; |
| 73 | | 73 | |
| | 74 | typedef struct SchDecOutput { |
| | 75 | SchedulerNode *dst; |
| | 76 | uint8_t *dst_finished; |
| | 77 | unsigned nb_dst; |
| | 78 | } SchDecOutput; |
| | 79 | |
| 74 | typedef struct SchDec { | 80 | typedef struct SchDec { |
| 75 | const AVClass *class; | 81 | const AVClass *class; |
| 76 | | 82 | |
| 77 | SchedulerNode src; | 83 | SchedulerNode src; |
| 78 | SchedulerNode *dst; | 84 | |
| 79 | uint8_t *dst_finished; | 85 | SchDecOutput *outputs; |
| 80 | unsigned nb_dst; | 86 | unsigned nb_outputs; |
| 81 | | 87 | |
| 82 | SchTask task; | 88 | SchTask task; |
| 83 | // Queue for receiving input packets, one stream. | 89 | // Queue for receiving input packets, one stream. |
| @@ -513,8 +519,14 @@ void sch_free(Scheduler **psch) · 429 unmodified lines |
| 513 | | 519 | |
| 514 | av_thread_message_queue_free(&dec->queue_end_ts); | 520 | av_thread_message_queue_free(&dec->queue_end_ts); |
| 515 | | 521 | |
| 516 | av_freep(&dec->dst); | 522 | for (unsigned j = 0; j < dec->nb_outputs; j++) { |
| 517 | av_freep(&dec->dst_finished); | 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); |
| 518 | | 530 | |
| 519 | av_frame_free(&dec->send_frame); | 531 | av_frame_free(&dec->send_frame); |
| 520 | } | 532 | } |
| @@ -712,14 +724,28 @@ int sch_add_demux_stream(Scheduler *sch, unsigned demux_idx) · 191 unmodified lines |
| 712 | return ret < 0 ? ret : d->nb_streams - 1; | 724 | return ret < 0 ? ret : d->nb_streams - 1; |
| 713 | } | 725 | } |
| 714 | | 726 | |
| | 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 | |
| 715 | static const AVClass sch_dec_class = { | 742 | static const AVClass sch_dec_class = { |
| 716 | .class_name = "SchDec", | 743 | .class_name = "SchDec", |
| 717 | .version = LIBAVUTIL_VERSION_INT, | 744 | .version = LIBAVUTIL_VERSION_INT, |
| 718 | .parent_log_context_offset = offsetof(SchDec, task.func_arg), | 745 | .parent_log_context_offset = offsetof(SchDec, task.func_arg), |
| 719 | }; | 746 | }; |
| 720 | | 747 | |
| 721 | int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx, | 748 | int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx, int send_end_ts) |
| 722 | int send_end_ts) | | |
| 723 | { | 749 | { |
| 724 | const unsigned idx = sch->nb_dec; | 750 | const unsigned idx = sch->nb_dec; |
| 725 | | 751 | |
| @@ -739,6 +765,10 @@ int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx, · 13 unmodified lines |
| 739 | if (!dec->send_frame) | 765 | if (!dec->send_frame) |
| 740 | return AVERROR(ENOMEM); | 766 | return AVERROR(ENOMEM); |
| 741 | | 767 | |
| | 768 | ret = sch_add_dec_output(sch, idx); |
| | 769 | if (ret < 0) |
| | 770 | return ret; |
| | 771 | |
| 742 | ret = queue_alloc(&dec->queue, 1, 0, QUEUE_PACKETS); | 772 | ret = queue_alloc(&dec->queue, 1, 0, QUEUE_PACKETS); |
| 743 | if (ret < 0) | 773 | if (ret < 0) |
| 744 | return ret; | 774 | return ret; |
| @@ -943,15 +973,19 @@ int sch_connect(Scheduler *sch, SchedulerNode src, SchedulerNode dst) · 198 unmodified lines |
| 943 | } | 973 | } |
| 944 | case SCH_NODE_TYPE_DEC: { | 974 | case SCH_NODE_TYPE_DEC: { |
| 945 | SchDec *dec; | 975 | SchDec *dec; |
| | 976 | SchDecOutput *o; |
| 946 | | 977 | |
| 947 | av_assert0(src.idx < sch->nb_dec); | 978 | av_assert0(src.idx < sch->nb_dec); |
| 948 | dec = &sch->dec[src.idx]; | 979 | dec = &sch->dec[src.idx]; |
| 949 | | 980 | |
| 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); |
| 951 | if (ret < 0) | 985 | if (ret < 0) |
| 952 | return ret; | 986 | return ret; |
| 953 | | 987 | |
| 954 | dec->dst[dec->nb_dst - 1] = dst; | 988 | o->dst[o->nb_dst - 1] = dst; |
| 955 | | 989 | |
| 956 | // decoded frames go to filters or encoding | 990 | // decoded frames go to filters or encoding |
| 957 | switch (dst.type) { | 991 | switch (dst.type) { |
| @@ -1417,15 +1451,20 @@ static int start_prepare(Scheduler *sch) · 459 unmodified lines |
| 1417 | "Decoder not connected to a source\n"); | 1451 | "Decoder not connected to a source\n"); |
| 1418 | return AVERROR(EINVAL); | 1452 | return AVERROR(EINVAL); |
| 1419 | } | 1453 | } |
| 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 | } | | |
| 1425 | | 1454 | |
| 1426 | dec->dst_finished = av_calloc(dec->nb_dst, sizeof(*dec->dst_finished)); | 1455 | for (unsigned j = 0; j < dec->nb_outputs; j++) { |
| 1427 | if (!dec->dst_finished) | 1456 | SchDecOutput *o = &dec->outputs[j]; |
| 1428 | return AVERROR(ENOMEM); | 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 | } |
| 1429 | } | 1468 | } |
| 1430 | | 1469 | |
| 1431 | for (unsigned i = 0; i < sch->nb_enc; i++) { | 1470 | for (unsigned i = 0; i < sch->nb_enc; i++) { |
| @@ -2171,21 +2210,26 @@ finish: · 739 unmodified lines |
| 2171 | return AVERROR_EOF; | 2210 | return AVERROR_EOF; |
| 2172 | } | 2211 | } |
| 2173 | | 2212 | |
| 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) |
| 2175 | { | 2215 | { |
| 2176 | SchDec *dec; | 2216 | SchDec *dec; |
| | 2217 | SchDecOutput *o; |
| 2177 | int ret; | 2218 | int ret; |
| 2178 | unsigned nb_done = 0; | 2219 | unsigned nb_done = 0; |
| 2179 | | 2220 | |
| 2180 | av_assert0(dec_idx < sch->nb_dec); | 2221 | av_assert0(dec_idx < sch->nb_dec); |
| 2181 | dec = &sch->dec[dec_idx]; | 2222 | dec = &sch->dec[dec_idx]; |
| 2182 | | 2223 | |
| 2183 | for (unsigned i = 0; i < dec->nb_dst; i++) { | 2224 | av_assert0(out_idx < dec->nb_outputs); |
| 2184 | uint8_t *finished = &dec->dst_finished[i]; | 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]; |
| 2185 | AVFrame *to_send = frame; | 2229 | AVFrame *to_send = frame; |
| 2186 | | 2230 | |
| 2187 | // sending a frame consumes it, so make a temporary reference if needed | 2231 | // 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) { |
| 2189 | to_send = dec->send_frame; | 2233 | to_send = dec->send_frame; |
| 2190 | | 2234 | |
| 2191 | // frame may sometimes contain props only, | 2235 | // frame may sometimes contain props only, |
| @@ -2196,7 +2240,7 @@ int sch_dec_send(Scheduler *sch, unsigned dec_idx, AVFrame *frame) · 4 unmodified lines |
| 2196 | return ret; | 2240 | return ret; |
| 2197 | } | 2241 | } |
| 2198 | | 2242 | |
| 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); |
| 2200 | if (ret < 0) { | 2244 | if (ret < 0) { |
| 2201 | av_frame_unref(to_send); | 2245 | av_frame_unref(to_send); |
| 2202 | if (ret == AVERROR_EOF) { | 2246 | if (ret == AVERROR_EOF) { |
| @@ -2207,7 +2251,7 @@ int sch_dec_send(Scheduler *sch, unsigned dec_idx, AVFrame *frame) · 4 unmodified lines |
| 2207 | } | 2251 | } |
| 2208 | } | 2252 | } |
| 2209 | | 2253 | |
| 2210 | return (nb_done == dec->nb_dst) ? AVERROR_EOF : 0; | 2254 | return (nb_done == o->nb_dst) ? AVERROR_EOF : 0; |
| 2211 | } | 2255 | } |
| 2212 | | 2256 | |
| 2213 | static int dec_done(Scheduler *sch, unsigned dec_idx) | 2257 | 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 |
| 2222 | if (dec->queue_end_ts) | 2266 | if (dec->queue_end_ts) |
| 2223 | av_thread_message_queue_set_err_recv(dec->queue_end_ts, AVERROR_EOF); | 2267 | av_thread_message_queue_set_err_recv(dec->queue_end_ts, AVERROR_EOF); |
| 2224 | | 2268 | |
| 2225 | for (unsigned i = 0; i < dec->nb_dst; i++) { | 2269 | for (unsigned i = 0; i < dec->nb_outputs; i++) { |
| 2226 | int err = dec_send_to_dst(sch, dec->dst[i], &dec->dst_finished[i], NULL); | 2270 | SchDecOutput *o = &dec->outputs[i]; |
| 2227 | if (err < 0 && err != AVERROR_EOF) | 2271 | |
| 2228 | ret = err_merge(ret, err); | 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 | } |
| 2229 | } | 2277 | } |
| 2230 | | 2278 | |
| 2231 | return ret; | 2279 | return ret; |