<div dir="ltr">Hi and apologies for the noob Q's. I've had trouble finding authoritative documentation -- pointers welcome. Meanwhile here's what I THINK the situation is and I would appreciate corrections and/or confirmations!!<div><br></div><div>SHORT VERSION</div><div><br></div><div>- The main libavcodec APIs (avcodec_{send/receive}_{frame/packet}) are *synchronous* (blocking); if you don't want to block, use a thread</div><div>- Almost any non-ancient build of libav* will be "thread friendly", don't use any given "object" from multiple threads at once but otherwise threads are fine</div><div>- Various codecs will use threads and even off-core resources (GPUs, vector units etc), this can be tweaked with things like the thread_count setting, it depends on the specific codec and YMMV</div><div><br></div><div>LONG VERSION</div><div><br></div><div>There are two main reasons to care about threaded/asynchronous use of libavcodec (and libav* in general): not blocking other work (e.g. UI thread), and making the most efficient use of resources.</div><div><br></div><div>*** Not blocking other work: "Just make your own thread"? ***</div><div><br></div><div>For not blocking other work (e.g. keeping a responsive UI while encoding/decoding), it's important to know that calls to avcodec_{send/receive}_{frame/packet} may block for a significant amount of time. This can be confusing because the use of EAGAIN is typically associated with nonblocking operation but that's not the case with this API, where EAGAIN just means "go to the other side of the buffer", but either one side or the other will block until work is done. So, if that's a problem, make a thread that manages the encoding/decoding, keep it separate from your UI thread (or whatever), and use appropriate thread-safe communication between them.</div><div><br></div><div>There WAS a patch submitted to add an explicitly async API to libavcodec (<a href="https://ffmpeg.org/pipermail/ffmpeg-devel/2016-March/191922.html">https://ffmpeg.org/pipermail/ffmpeg-devel/2016-March/191922.html</a>) but as far as I can tell it was rejected, perhaps because an asynchronous API that only some codecs support and which adds complexity to libavcodec internals isn't that useful when apps can just use a thread.</div><div><br></div><div>Incidentally there's no quick way to interrupt encoding/decoding in process but it happens a frame at a time and usually any given frame doesn't take too long. Still be aware that gracefully shutting down an encoding/decoding thread can take a bit of time to finish the frame in progress.</div><div><br></div><div>*** Being efficient: The story is more complicated here? ***</div><div><br></div><div>Decoding video involves several stages of work</div><div>- I/O to read the compressed data (libavformat)</div><div>- CPU to parse the container (libavformat) & embedded bitstream (libavcodec)</div><div>- CPU or GPU work to do actual decompression</div><div>- Possible post-decompression processing (pixel format conversion etc)</div><div>- Display on screen</div><div>(Encoding has analogous stages, I'll focus on decoding for simplicity)</div><div><br></div><div>It makes sense to overlap this work for efficiency. Ideally the disk is fetching one frame, the CPU is parsing the previous frame, the GPU is uncompressing the one before that, and the one before that is shown on the screen. Also within a stage (especially decompression) there may be opportunities for parallelism and using multiple cores.</div><div><br></div><div>I THINK "macro parallelism" across phases is up to the app author. You can use libavformat in one thread and libavcodec in another and push data between them with a queue of some kind. Notably ffmpeg as an app will do this I think?? Also "filter graph" postprocessing in libavfilter can do some things in threads??</div><div><br></div><div>NOTE that there is advice not to overthink or prematurely optimize this. For example most OS are pretty good at prefetching when you're loading from a stream so it may not be that beneficial to run your own I/O thread. YMMV.</div><div><br></div><div>Some codecs are "behind the scenes asynchronous" -- with these codecs if you use avcodec_send_packet() to send in some data they will get started in the background and then you can come back later and call avcodec_receive_frame() and get data right away. Other codecs however will block and do the work synchronously on either the send_packet() end or the receive_frame() end. It's best not to make assumptions, BUT, if you don't have a dedicated codec thread, it can be beneficial to fill the app-to-codec pipeline before switching away to something else in case the codec is able to work in the background??</div><div><br></div><div>In any case "micro parallelism" is well supported within individual codecs.You can set thread_count and thread_type in AVCodecContext and a lot of codecs will internally spin up threads to crunch data faster on multicore machines (and almost all machines are multicore now). This is transparent to the caller for the most part, you just tune those numbers for the best performance.</div><div><br></div><div>ANYWAY that's my understanding based on groveling through Q&A posts and forum threads and doing some experiments, did I get it approximately right??</div><div><br></div><div>-- egnor</div></div>