45#define SCHEDULE_TOLERANCE (100 * 1000)
377 if (queue_size <= 0) {
442 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
445 for (
unsigned j = 0; j < mux->
nb_streams; j++) {
464 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
467 for (
unsigned j = 0; j < mux->
nb_streams; j++) {
485 memset(&fg->
task, 0,
sizeof(fg->
task));
509 for (
unsigned j = 0; j < d->
nb_streams; j++) {
522 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
525 for (
unsigned j = 0; j < mux->
nb_streams; j++) {
545 for (
unsigned i = 0;
i < sch->
nb_dec;
i++) {
552 for (
unsigned j = 0; j < dec->
nb_outputs; j++) {
565 for (
unsigned i = 0;
i < sch->
nb_enc;
i++) {
611 .class_name =
"Scheduler",
657 .class_name =
"SchMux",
659 .parent_log_context_offset = offsetof(
SchMux, task.func_arg),
663 void *
arg,
int sdp_auto,
unsigned thread_queue_size)
665 const unsigned idx = sch->
nb_mux;
674 mux = &sch->
mux[idx];
694 mux = &sch->
mux[mux_idx];
701 ms = &mux->
streams[stream_idx];
713 .class_name =
"SchDemux",
715 .parent_log_context_offset = offsetof(
SchDemux, task.func_arg),
729 d = &sch->
demux[idx];
751 d = &sch->
demux[demux_idx];
763 dec = &sch->
dec[dec_idx];
773 .class_name =
"SchDec",
775 .parent_log_context_offset = offsetof(
SchDec, task.func_arg),
780 const unsigned idx = sch->
nb_dec;
789 dec = &sch->
dec[idx];
816 .class_name =
"SchEnc",
818 .parent_log_context_offset = offsetof(
SchEnc, task.func_arg),
824 const unsigned idx = sch->
nb_enc;
833 enc = &sch->
enc[idx];
854 .class_name =
"SchFilterGraph",
856 .parent_log_context_offset = offsetof(
SchFilterGraph, task.func_arg),
927 int limiting, uint64_t max_frames)
934 sq = &sch->
sq_enc[sq_idx];
937 enc = &sch->
enc[enc_idx];
951 if (max_frames != INT64_MAX)
1009 dec = &sch->
dec[
src.idx];
1037 enc = &sch->
enc[
dst.idx];
1064 enc = &sch->
enc[
dst.idx];
1091 enc = &sch->
enc[
src.idx];
1117 dec = &sch->
dec[
dst.idx];
1145 int min_stream = -1;
1169 if (min_stream >= 0) {
1221 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
1236 size_t data_threshold,
int max_packets)
1242 mux = &sch->
mux[mux_idx];
1245 ms = &mux->
streams[stream_idx];
1257 mux = &sch->
mux[mux_idx];
1284 mux = &sch->
mux[mux_idx];
1287 ms = &mux->
streams[stream_idx];
1321 switch (
dst->type) {
1323 dec = &sch->
dec[
dst->idx];
1328 enc = &sch->
enc[
dst->idx];
1401 switch (
dst->type) {
1425 int have_unchoked = 0;
1437#define RESET_WAITER(field) \
1439 for (unsigned i = 0; i < sch->nb_##field; i++) { \
1440 SchWaiter *w = &sch->field[i].waiter; \
1441 w->choked_prev = atomic_load(&w->choked); \
1442 w->choked_next = 1; \
1450 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
1453 for (
unsigned j = 0; j < mux->
nb_streams; j++) {
1476 for (
unsigned j = 0; j < fg->
nb_inputs; j++) {
1484#define UNCHOKE_ONCE(field) \
1486 for (unsigned i = 0; !have_unchoked && i < sch->nb_##field; i++) { \
1487 SchWaiter *w = &sch->field[i].waiter; \
1488 if (!sch->field[i].task_exited) { \
1489 w->choked_next = 0; \
1490 have_unchoked = 1; \
1499#define UPDATE_WAITER(field) \
1501 for (unsigned i = 0; i < sch->nb_##field; i++) { \
1502 SchWaiter *w = &sch->field[i].waiter; \
1503 if (w->choked_prev != w->choked_next) { \
1504 waiter_set(w, w->choked_next); \
1505 if (offsetof(Scheduler, field) == offsetof(Scheduler, demux)) \
1506 choke_demux(sch, i, w->choked_next); \
1546 unsigned nb_filters_stack = 0;
1548 memset(filters_visited, 0, sch->
nb_filters *
sizeof(*filters_visited));
1572 av_assert0(nb_filters_stack < sch->nb_filters);
1573 filters_stack[nb_filters_stack++] =
src;
1581 if (nb_filters_stack) {
1582 src = filters_stack[--nb_filters_stack];
1591 uint8_t *filters_visited =
NULL;
1600 if (!filters_visited)
1604 if (!filters_stack) {
1612 filters_visited, filters_stack);
1632 for (
unsigned j = 0; j < d->
nb_streams; j++) {
1637 "Demuxer stream %u not connected to any sink\n", j);
1647 for (
unsigned i = 0;
i < sch->
nb_dec;
i++) {
1652 "Decoder not connected to a source\n");
1656 for (
unsigned j = 0; j < dec->
nb_outputs; j++) {
1661 "Decoder output %u not connected to any sink\n", j);
1671 for (
unsigned i = 0;
i < sch->
nb_enc;
i++) {
1676 "Encoder not connected to a source\n");
1681 "Encoder not connected to any sink\n");
1690 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
1693 for (
unsigned j = 0; j < mux->
nb_streams; j++) {
1698 "Muxer stream #%u not connected to a source\n", j);
1712 for (
unsigned j = 0; j < fg->
nb_inputs; j++) {
1717 "Filtergraph input %u not connected to a source\n", j);
1722 for (
unsigned j = 0; j < fg->
nb_outputs; j++) {
1727 "Filtergraph %u output %u not connected to a sink\n",
i, j);
1752 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
1762 for (
unsigned i = 0;
i < sch->
nb_enc;
i++) {
1778 for (
unsigned i = 0;
i < sch->
nb_dec;
i++) {
1817 struct timespec tv = { .tv_sec = timeout_us / 1000000,
1818 .tv_nsec = (timeout_us % 1000000) * 1000 };
1888 for (
unsigned i = 0;
i < enc->
nb_dst;
i++) {
1920 ret = (ret ==
AVERROR(EAGAIN)) ? 0 : ret;
1962 if (!
frame->buf[0]) {
1968 return (enc->
sq_idx[0] >= 0) ?
1981 size_t pkt_size =
pkt ?
pkt->size : 0;
1983 size_t max_packets = thresh_reached ? q->
max_packets : SIZE_MAX;
1984 size_t new_size =
FFMIN(2 * packets, max_packets);
1986 if (new_size <= packets) {
1988 "Too many packets buffered for output stream.\n");
2027 queued = ret < 0 ? ret : 1;
2035 goto update_schedule;
2106 unsigned nb_done = 0;
2108 for (
unsigned i = 0;
i < ds->
nb_dst;
i++) {
2144 for (
unsigned j = 0; j < ds->
nb_dst; j++) {
2152 dec = &sch->
dec[
dst->idx];
2173 pkt->pts = max_end_ts.
ts;
2174 pkt->time_base = max_end_ts.
tb;
2186 d = &sch->
demux[demux_idx];
2193 if (
pkt->stream_index == -1)
2226 int ret, stream_idx;
2229 mux = &sch->
mux[mux_idx];
2232 pkt->stream_index = stream_idx;
2241 mux = &sch->
mux[mux_idx];
2261 mux = &sch->
mux[mux_idx];
2264 ms = &mux->
streams[stream_idx];
2313 dec = &sch->
dec[dec_idx];
2395 unsigned nb_done = 0;
2398 dec = &sch->
dec[dec_idx];
2403 for (
unsigned i = 0;
i < o->
nb_dst;
i++) {
2448 for (
unsigned j = 0; j < o->
nb_dst; j++) {
2464 enc = &sch->
enc[enc_idx];
2508 enc = &sch->
enc[enc_idx];
2510 for (
unsigned i = 0;
i < enc->
nb_dst;
i++) {
2542 for (
unsigned i = 0;
i < enc->
nb_dst;
i++) {
2592 else if (ret >= 0) {
2611 fi = &fg->
inputs[in_idx];
2706 switch (node.
type) {
2726 "Task finished with error: %s\n",
av_err2str(ret));
2743 "Terminating thread with error: %s\n",
av_err2str(ret));
2746 "Terminating thread with success\n");
2748 return (
void*)(intptr_t)ret;
2767 return (intptr_t)thread_ret;
2800 for (
unsigned i = 0;
i < sch->
nb_dec;
i++) {
2814 for (
unsigned i = 0;
i < sch->
nb_enc;
i++) {
2821 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
#define filters(fmt, type, inverse, clp, inverset, clip, one, clip_fn, packed)
static AVFormatContext * ctx
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
#define flags(name, subs,...)
#define i(width, name, range_min, range_max)
#define GROW_ARRAY(array, nb_elems)
int(* init)(AVBSFContext *ctx)
#define atomic_store(object, desired)
intptr_t atomic_int_least64_t
#define atomic_load(object)
#define atomic_init(obj, value)
static int filter_done(Scheduler *sch, unsigned fg_idx)
int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx, int send_end_ts)
Add a decoder to the scheduler.
int sch_filter_send(Scheduler *sch, unsigned fg_idx, unsigned out_idx, AVFrame *frame)
Called by filtergraph tasks to send a filtered frame or EOF to consumers.
static int demux_send_for_stream(Scheduler *sch, SchDemux *d, SchDemuxStream *ds, AVPacket *pkt, unsigned flags)
static void unchoke_downstream(Scheduler *sch, SchedulerNode *dst)
static int enc_done(Scheduler *sch, unsigned enc_idx)
static int64_t progressing_dts(const Scheduler *sch, int count_finished)
#define SCHEDULE_TOLERANCE
Scheduler * sch_alloc(void)
int sch_add_filtergraph(Scheduler *sch, unsigned nb_inputs, unsigned nb_outputs, SchThreadFunc func, void *ctx)
Add a filtergraph to the scheduler.
void sch_filter_receive_finish(Scheduler *sch, unsigned fg_idx, unsigned in_idx)
Called by filter tasks to signal that a filter input will no longer accept input.
int sch_demux_send(Scheduler *sch, unsigned demux_idx, AVPacket *pkt, unsigned flags)
Called by demuxer tasks to communicate with their downstreams.
static void task_init(Scheduler *sch, SchTask *task, enum SchedulerNodeType type, unsigned idx, SchThreadFunc func, void *func_arg)
int sch_mux_sub_heartbeat_add(Scheduler *sch, unsigned mux_idx, unsigned stream_idx, unsigned dec_idx)
int sch_start(Scheduler *sch)
#define RESET_WAITER(field)
static int dec_done(Scheduler *sch, unsigned dec_idx)
static int waiter_wait(Scheduler *sch, SchWaiter *w)
Wait until this task is allowed to proceed.
static int dec_send_to_dst(Scheduler *sch, const SchedulerNode dst, uint8_t *dst_finished, AVFrame *frame)
#define UPDATE_WAITER(field)
void sch_remove_filtergraph(Scheduler *sch, int idx)
int sch_add_dec_output(Scheduler *sch, unsigned dec_idx)
Add another output to decoder (e.g.
static int send_to_enc_thread(Scheduler *sch, SchEnc *enc, AVFrame *frame)
static void waiter_uninit(SchWaiter *w)
int sch_mux_stream_ready(Scheduler *sch, unsigned mux_idx, unsigned stream_idx)
Signal to the scheduler that the specified muxed stream is initialized and ready.
static SchedulerNode src_filtergraph(const Scheduler *sch, SchedulerNode src)
static const AVClass sch_enc_class
static void waiter_set(SchWaiter *w, int choked)
static int demux_flush(Scheduler *sch, SchDemux *d, AVPacket *pkt)
int print_sdp(const char *filename)
int sch_stop(Scheduler *sch, int64_t *finish_ts)
void sch_mux_receive_finish(Scheduler *sch, unsigned mux_idx, unsigned stream_idx)
Called by muxer tasks to signal that a stream will no longer accept input.
int sch_dec_send(Scheduler *sch, unsigned dec_idx, unsigned out_idx, AVFrame *frame)
Called by decoder tasks to send a decoded frame downstream.
static int check_acyclic(Scheduler *sch)
static void choke_demux(const Scheduler *sch, int demux_id, int choked)
static void * task_wrapper(void *arg)
static int task_start(SchTask *task)
static int start_prepare(Scheduler *sch)
int sch_add_sq_enc(Scheduler *sch, uint64_t buf_size_us, void *logctx)
Add an pre-encoding sync queue to the scheduler.
static const AVClass scheduler_class
int sch_enc_receive(Scheduler *sch, unsigned enc_idx, AVFrame *frame)
Called by encoder tasks to obtain frames for encoding.
static int send_to_enc_sq(Scheduler *sch, SchEnc *enc, AVFrame *frame)
int sch_sq_add_enc(Scheduler *sch, unsigned sq_idx, unsigned enc_idx, int limiting, uint64_t max_frames)
int sch_wait(Scheduler *sch, uint64_t timeout_us, int64_t *transcode_ts)
Wait until transcoding terminates or the specified timeout elapses.
static int mux_queue_packet(SchMux *mux, SchMuxStream *ms, AVPacket *pkt)
void sch_mux_stream_buffering(Scheduler *sch, unsigned mux_idx, unsigned stream_idx, size_t data_threshold, int max_packets)
Configure limits on packet buffering performed before the muxer task is started.
static int check_acyclic_for_output(const Scheduler *sch, SchedulerNode src, uint8_t *filters_visited, SchedulerNode *filters_stack)
static int queue_alloc(ThreadQueue **ptq, unsigned nb_streams, unsigned queue_size, enum QueueType type)
static int enc_open(Scheduler *sch, SchEnc *enc, const AVFrame *frame)
static int mux_task_start(SchMux *mux)
int sch_enc_send(Scheduler *sch, unsigned enc_idx, AVPacket *pkt)
Called by encoder tasks to send encoded packets downstream.
static int mux_done(Scheduler *sch, unsigned mux_idx)
int sch_add_enc(Scheduler *sch, SchThreadFunc func, void *ctx, int(*open_cb)(void *opaque, const AVFrame *frame))
Add an encoder to the scheduler.
int sch_sdp_filename(Scheduler *sch, const char *sdp_filename)
Set the file path for the SDP.
static const AVClass sch_fg_class
static int task_stop(Scheduler *sch, SchTask *task)
static int demux_done(Scheduler *sch, unsigned demux_idx)
int sch_filter_receive(Scheduler *sch, unsigned fg_idx, unsigned *in_idx, AVFrame *frame)
Called by filtergraph tasks to obtain frames for filtering.
void sch_filter_choke_inputs(Scheduler *sch, unsigned fg_idx)
Called by filtergraph tasks to choke all filter inputs, preventing them from receiving more frames un...
int sch_add_demux_stream(Scheduler *sch, unsigned demux_idx)
Add a demuxed stream for a previously added demuxer.
int sch_connect(Scheduler *sch, SchedulerNode src, SchedulerNode dst)
int sch_filter_command(Scheduler *sch, unsigned fg_idx, AVFrame *frame)
static int64_t trailing_dts(const Scheduler *sch)
int sch_dec_receive(Scheduler *sch, unsigned dec_idx, AVPacket *pkt)
Called by decoder tasks to receive a packet for decoding.
int sch_add_demux(Scheduler *sch, SchThreadFunc func, void *ctx)
Add a demuxer to the scheduler.
static int enc_send_to_dst(Scheduler *sch, const SchedulerNode dst, uint8_t *dst_finished, AVPacket *pkt)
int sch_add_mux(Scheduler *sch, SchThreadFunc func, int(*init)(void *), void *arg, int sdp_auto, unsigned thread_queue_size)
Add a muxer to the scheduler.
int sch_mux_sub_heartbeat(Scheduler *sch, unsigned mux_idx, unsigned stream_idx, const AVPacket *pkt)
static int send_to_filter(Scheduler *sch, SchFilterGraph *fg, unsigned in_idx, AVFrame *frame)
static const AVClass sch_mux_class
static int demux_stream_send_to_dst(Scheduler *sch, const SchedulerNode dst, uint8_t *dst_finished, AVPacket *pkt, unsigned flags)
static const AVClass sch_dec_class
static int send_to_mux(Scheduler *sch, SchMux *mux, unsigned stream_idx, AVPacket *pkt)
static void schedule_update_locked(Scheduler *sch)
int sch_mux_receive(Scheduler *sch, unsigned mux_idx, AVPacket *pkt)
Called by muxer tasks to obtain packets for muxing.
static int send_to_enc(Scheduler *sch, SchEnc *enc, AVFrame *frame)
static int task_cleanup(Scheduler *sch, SchedulerNode node)
int sch_add_mux_stream(Scheduler *sch, unsigned mux_idx)
Add a muxed stream for a previously added muxer.
void sch_free(Scheduler **psch)
static int waiter_init(SchWaiter *w)
#define UNCHOKE_ONCE(field)
static int mux_init(Scheduler *sch, SchMux *mux)
static void unchoke_for_stream(Scheduler *sch, SchedulerNode src, int flags)
static const AVClass sch_demux_class
int(* SchThreadFunc)(void *arg)
#define DEFAULT_PACKET_THREAD_QUEUE_SIZE
Default size of a packet thread queue.
#define DEFAULT_FRAME_THREAD_QUEUE_SIZE
Default size of a frame thread queue.
@ DEMUX_SEND_STREAMCOPY_EOF
Treat the packet as an EOF for SCH_NODE_TYPE_MUX destinations send normally to other types.
@ SCH_NODE_TYPE_FILTER_OUT
@ SCH_NODE_TYPE_FILTER_IN
static int err_merge(int err0, int err1)
Merge two return codes - return one of the error codes if at least one of them was negative,...
static unsigned int nb_streams
reference-counted frame API
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
Copy only "properties" fields from src to dst.
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
#define AVERROR_BUFFER_TOO_SMALL
Buffer too small.
#define AVERROR_EOF
End of file.
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
size_t av_fifo_can_write(const AVFifo *f)
size_t av_fifo_can_read(const AVFifo *f)
int av_fifo_peek(const AVFifo *f, void *buf, size_t nb_elems, size_t offset)
Read data from a FIFO without modifying FIFO state.
int av_fifo_grow2(AVFifo *f, size_t inc)
Enlarge an AVFifo.
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare two timestamps each in its own time base.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
#define AV_NOPTS_VALUE
Undefined timestamp value.
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
#define LIBAVUTIL_VERSION_INT
int(* func)(AVBPrint *dst, const char *in, const char *arg)
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
static av_always_inline int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Describe the class of an AVClass context structure.
This structure describes decoded (raw) audio or video data.
This structure stores compressed data.
int max_packets
Maximum number of packets in fifo.
AVFifo * fifo
Queue for buffering the packets before the muxer task can be started.
AVThreadMessageQueue * queue_end_ts
int(* open_cb)(void *opaque, const AVFrame *frame)
unsigned nb_inputs_finished_receive
unsigned nb_inputs_finished_send
unsigned * sub_heartbeat_dst
unsigned nb_sub_heartbeat_dst
PreMuxQueue pre_mux_queue
unsigned nb_streams_ready
atomic_int mux_started
Set to 1 after starting the muxer task and flushing the pre-muxing queues.
AVPacket * sub_heartbeat_pkt
enum SchedulerNodeType type
atomic_int_least64_t last_dts
pthread_cond_t finish_cond
enum SchedulerState state
pthread_mutex_t schedule_lock
pthread_mutex_t finish_lock
pthread_mutex_t mux_ready_lock
A sync queue provides timestamp synchronization between multiple streams.
int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame)
Submit a frame for the stream with index stream_idx.
void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx, uint64_t frames)
Limit the number of output frames for stream with index stream_idx to max_frames.
int sq_receive(SyncQueue *sq, int stream_idx, SyncQueueFrame frame)
Read a frame from the queue.
void sq_free(SyncQueue **psq)
void sq_frame_samples(SyncQueue *sq, unsigned int stream_idx, int frame_samples)
Set a constant output audio frame size, in samples.
int sq_add_stream(SyncQueue *sq, int limiting)
Add a new stream to the sync queue.
SyncQueue * sq_alloc(enum SyncQueueType type, int64_t buf_size_us, void *logctx)
Allocate a sync queue of the given type.
#define av_malloc_array(a, b)
ThreadQueue * tq_alloc(unsigned int nb_streams, size_t queue_size, enum ThreadQueueType type)
Allocate a queue for sending data between threads.
void tq_send_finish(ThreadQueue *tq, unsigned int stream_idx)
Mark the given stream finished from the sending side.
int tq_send(ThreadQueue *tq, unsigned int stream_idx, void *data)
Send an item for the given stream to the queue.
void tq_choke(ThreadQueue *tq, int choked)
Prevent further reads from the thread queue until it is unchoked.
int tq_receive(ThreadQueue *tq, int *stream_idx, void *data, int flags)
Read the next item from the queue.
void tq_free(ThreadQueue **ptq)
void tq_receive_finish(ThreadQueue *tq, unsigned int stream_idx)
Mark the given stream finished from the receiving side.
@ THREAD_QUEUE_FLAG_NO_BLOCK
int av_thread_message_queue_recv(AVThreadMessageQueue *mq, void *msg, unsigned flags)
Receive a message from the queue.
int av_thread_message_queue_alloc(AVThreadMessageQueue **mq, unsigned nelem, unsigned elsize)
Allocate a new message queue.
void av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq, int err)
Set the receiving error code.
int av_thread_message_queue_send(AVThreadMessageQueue *mq, void *msg, unsigned flags)
Send a message on the queue.
void av_thread_message_queue_free(AVThreadMessageQueue **mq)
Free a message queue.
int64_t av_gettime(void)
Get the current time in microseconds.