46#define SCHEDULE_TOLERANCE (100 * 1000)
382 if (queue_size <= 0) {
447 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
450 for (
unsigned j = 0; j < mux->
nb_streams; j++) {
469 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
472 for (
unsigned j = 0; j < mux->
nb_streams; j++) {
490 memset(&fg->
task, 0,
sizeof(fg->
task));
514 for (
unsigned j = 0; j < d->
nb_streams; j++) {
527 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
530 for (
unsigned j = 0; j < mux->
nb_streams; j++) {
550 for (
unsigned i = 0;
i < sch->
nb_dec;
i++) {
558 for (
unsigned j = 0; j < dec->
nb_outputs; j++) {
573 for (
unsigned i = 0;
i < sch->
nb_enc;
i++) {
619 .class_name =
"Scheduler",
665 .class_name =
"SchMux",
667 .parent_log_context_offset = offsetof(
SchMux, task.func_arg),
671 void *
arg,
int sdp_auto,
unsigned thread_queue_size)
673 const unsigned idx = sch->
nb_mux;
682 mux = &sch->
mux[idx];
702 mux = &sch->
mux[mux_idx];
709 ms = &mux->
streams[stream_idx];
721 .class_name =
"SchDemux",
723 .parent_log_context_offset = offsetof(
SchDemux, task.func_arg),
737 d = &sch->
demux[idx];
759 d = &sch->
demux[demux_idx];
771 dec = &sch->
dec[dec_idx];
781 .class_name =
"SchDec",
783 .parent_log_context_offset = offsetof(
SchDec, task.func_arg),
788 const unsigned idx = sch->
nb_dec;
797 dec = &sch->
dec[idx];
832 .class_name =
"SchEnc",
834 .parent_log_context_offset = offsetof(
SchEnc, task.func_arg),
840 const unsigned idx = sch->
nb_enc;
849 enc = &sch->
enc[idx];
870 .class_name =
"SchFilterGraph",
872 .parent_log_context_offset = offsetof(
SchFilterGraph, task.func_arg),
943 int limiting, uint64_t max_frames)
950 sq = &sch->
sq_enc[sq_idx];
953 enc = &sch->
enc[enc_idx];
967 if (max_frames != INT64_MAX)
1025 dec = &sch->
dec[
src.idx];
1053 enc = &sch->
enc[
dst.idx];
1080 enc = &sch->
enc[
dst.idx];
1107 enc = &sch->
enc[
src.idx];
1133 dec = &sch->
dec[
dst.idx];
1161 int min_stream = -1;
1185 if (min_stream >= 0) {
1237 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
1252 size_t data_threshold,
int max_packets)
1258 mux = &sch->
mux[mux_idx];
1261 ms = &mux->
streams[stream_idx];
1273 mux = &sch->
mux[mux_idx];
1300 mux = &sch->
mux[mux_idx];
1303 ms = &mux->
streams[stream_idx];
1338 switch (
dst->type) {
1340 dec = &sch->
dec[
dst->idx];
1347 enc = &sch->
enc[
dst->idx];
1389 dec = &sch->
dec[
src.idx];
1425 switch (
dst->type) {
1449 int have_unchoked = 0;
1461#define RESET_WAITER(field) \
1463 for (unsigned i = 0; i < sch->nb_##field; i++) { \
1464 SchWaiter *w = &sch->field[i].waiter; \
1465 w->choked_prev = atomic_load(&w->choked); \
1466 w->choked_next = 1; \
1475 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
1478 for (
unsigned j = 0; j < mux->
nb_streams; j++) {
1504 for (
unsigned j = 0; j < fg->
nb_inputs; j++) {
1512#define UNCHOKE_ONCE(field) \
1514 for (unsigned i = 0; !have_unchoked && i < sch->nb_##field; i++) { \
1515 SchWaiter *w = &sch->field[i].waiter; \
1516 if (!sch->field[i].task_exited) { \
1517 w->choked_next = 0; \
1518 have_unchoked = 1; \
1527#define UPDATE_WAITER(field) \
1529 for (unsigned i = 0; i < sch->nb_##field; i++) { \
1530 SchWaiter *w = &sch->field[i].waiter; \
1531 if (w->choked_prev != w->choked_next) { \
1532 waiter_set(w, w->choked_next); \
1533 if (offsetof(Scheduler, field) == offsetof(Scheduler, demux)) \
1534 choke_demux(sch, i, w->choked_next); \
1575 unsigned nb_filters_stack = 0;
1577 memset(filters_visited, 0, sch->
nb_filters *
sizeof(*filters_visited));
1601 av_assert0(nb_filters_stack < sch->nb_filters);
1602 filters_stack[nb_filters_stack++] =
src;
1610 if (nb_filters_stack) {
1611 src = filters_stack[--nb_filters_stack];
1620 uint8_t *filters_visited =
NULL;
1629 if (!filters_visited)
1633 if (!filters_stack) {
1641 filters_visited, filters_stack);
1661 for (
unsigned j = 0; j < d->
nb_streams; j++) {
1666 "Demuxer stream %u not connected to any sink\n", j);
1676 for (
unsigned i = 0;
i < sch->
nb_dec;
i++) {
1681 "Decoder not connected to a source\n");
1685 for (
unsigned j = 0; j < dec->
nb_outputs; j++) {
1690 "Decoder output %u not connected to any sink\n", j);
1700 for (
unsigned i = 0;
i < sch->
nb_enc;
i++) {
1705 "Encoder not connected to a source\n");
1710 "Encoder not connected to any sink\n");
1719 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
1722 for (
unsigned j = 0; j < mux->
nb_streams; j++) {
1727 "Muxer stream #%u not connected to a source\n", j);
1741 for (
unsigned j = 0; j < fg->
nb_inputs; j++) {
1746 "Filtergraph input %u not connected to a source\n", j);
1751 for (
unsigned j = 0; j < fg->
nb_outputs; j++) {
1756 "Filtergraph %u output %u not connected to a sink\n",
i, j);
1781 for (
unsigned i = 0;
i < sch->
nb_mux;
i++) {
1791 for (
unsigned i = 0;
i < sch->
nb_enc;
i++) {
1807 for (
unsigned i = 0;
i < sch->
nb_dec;
i++) {
1846 struct timespec tv = { .tv_sec = timeout_us / 1000000,
1847 .tv_nsec = (timeout_us % 1000000) * 1000 };
1917 for (
unsigned i = 0;
i < enc->
nb_dst;
i++) {
1949 ret = (ret ==
AVERROR(EAGAIN)) ? 0 : ret;
1991 if (!
frame->buf[0]) {
1997 return (enc->
sq_idx[0] >= 0) ?
2010 size_t pkt_size =
pkt ?
pkt->size : 0;
2012 size_t max_packets = thresh_reached ? q->
max_packets : SIZE_MAX;
2013 size_t new_size =
FFMIN(2 * packets, max_packets);
2015 if (new_size <= packets) {
2017 "Too many packets buffered for output stream.\n");
2056 queued = ret < 0 ? ret : 1;
2064 goto update_schedule;
2135 unsigned nb_done = 0;
2137 for (
unsigned i = 0;
i < ds->
nb_dst;
i++) {
2173 for (
unsigned j = 0; j < ds->
nb_dst; j++) {
2181 dec = &sch->
dec[
dst->idx];
2202 pkt->pts = max_end_ts.
ts;
2203 pkt->time_base = max_end_ts.
tb;
2215 d = &sch->
demux[demux_idx];
2222 if (
pkt->stream_index == -1)
2255 int ret, stream_idx;
2258 mux = &sch->
mux[mux_idx];
2261 pkt->stream_index = stream_idx;
2270 mux = &sch->
mux[mux_idx];
2290 mux = &sch->
mux[mux_idx];
2293 ms = &mux->
streams[stream_idx];
2342 dec = &sch->
dec[dec_idx];
2448 unsigned nb_done = 0;
2451 dec = &sch->
dec[dec_idx];
2456 for (
unsigned i = 0;
i < o->
nb_dst;
i++) {
2501 for (
unsigned j = 0; j < o->
nb_dst; j++) {
2517 enc = &sch->
enc[enc_idx];
2561 enc = &sch->
enc[enc_idx];
2563 for (
unsigned i = 0;
i < enc->
nb_dst;
i++) {
2595 for (
unsigned i = 0;
i < enc->
nb_dst;
i++) {
2645 else if (ret >= 0) {
2664 fi = &fg->
inputs[in_idx];
2759 switch (node.
type) {
2779 "Task finished with error: %s\n",
av_err2str(ret));
2796 "Terminating thread with error: %s\n",
av_err2str(ret));
2799 "Terminating thread with success\n");
2801 return (
void*)(intptr_t)ret;
2820 return (intptr_t)thread_ret;
2844 for (
unsigned i = 0;
i < sch->
nb_dec;
i++)
2856 for (
unsigned i = 0;
i < sch->
nb_dec;
i++) {
2870 for (
unsigned i = 0;
i < sch->
nb_enc;
i++) {
2877 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)
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 av_container_fifo_write(AVContainerFifo *cf, void *obj, unsigned flags)
Write the contents of obj to the FIFO.
void av_container_fifo_free(AVContainerFifo **pcf)
Free a AVContainerFifo and everything in it.
int av_container_fifo_read(AVContainerFifo *cf, void *obj, unsigned flags)
Read the next available object from the FIFO into obj.
size_t av_container_fifo_can_read(const AVContainerFifo *cf)
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.
AVContainerFifo * av_container_fifo_alloc_avpacket(unsigned flags)
Allocate an AVContainerFifo instance for AVPacket.
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.
AVContainerFifo is a FIFO for "containers" - dynamically allocated reusable structs (e....
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.
AVContainerFifo * overflow
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)
static AVFormatContext * ctx
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.