Currently, the frame-threaded decoding API still supports thread-unsafe
callbacks. If one uses a thread-unsafe get_buffer2() callback,
calls to av_frame_unref() by the decoder are serialized, because
it is presumed that the underlying deallocator is thread-unsafe.
The frame-threaded encoder seems to have been written with this
restriction in mind: It always serializes unreferencing its AVFrames,
although no documentation forces it to do so.
This commit schedules to change this behaviour as soon as thread-unsafe
callbacks are removed. For this reason, the FF_API_THREAD_SAFE_CALLBACKS
define is reused.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
The encode-callback (the callback used by the FF_CODEC_CB_TYPE_ENCODE
encoders) is currently called in two places: encode_simple_internal()
and by the worker threads of frame-threaded encoders.
After the call, some packet properties are set based upon
the corresponding AVFrame properties and the packet is made
refcounted if it isn't already. So there is some code duplication.
There was also non-duplicated code in encode_simple_internal()
which is executed even when using frame-threading. This included
an emms_c() (which is needed for frame-threading, too, if it is
needed for the single-threaded case, because there are allocations
(via av_packet_make_refcounted()) immediately after returning
from the encode-callback).
Furthermore, some further properties are only set in
encode_simple_internal(): For audio, pts and duration are derived
from the corresponding fields of the frame if the encoder does not
have the AV_CODEC_CAP_DELAY set. Yet this is wrong for frame-threaded
encoders, because frame-threading always introduces delay regardless
of whether the underlying codec has said cap. This only worked because
there are no frame-threaded audio encoders.
This commit fixes the code duplication and the above issue by factoring
this code out and reusing it in both places. It would work in case
of audio codecs with frame-threading, because now the values are
derived from the correct AVFrame.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Instead of indicating whether we got a packet by setting
pkt->data and pkt->size to zero.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This is possible, because every given FFCodec has to implement
exactly one of these. Doing so decreases sizeof(FFCodec) and
therefore decreases the size of the binary.
Notice that in case of position-independent code the decrease
is in .data.rel.ro, so that this translates to decreased
memory consumption.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Up until now, codec.h contains both public and private parts
of AVCodec. This exposes the internals of AVCodec to users
and leads them into the temptation of actually using them
and forces us to forward-declare structures and types that
users can't use at all.
This commit changes this by adding a new structure FFCodec to
codec_internal.h that extends AVCodec, i.e. contains the public
AVCodec as first member; the private fields of AVCodec are moved
to this structure, leaving codec.h clean.
Reviewed-by: Anton Khirnov <anton@khirnov.net>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
It is not used here at all; instead, add it where it is used without
including it or any of the arch-specific CPU headers.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
In case the underlying AVCodec has no private class, the private data
of both the main as well as each worker AVCodecContext is just zeroed
(the codec's init function has not been called on any of them and
without a private class there is no way to legitimately set anything
before the aforementioned init function).
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
avcodec_open2() allows to provide options via an AVDictionary;
but it is also allowed to set options by simply setting the value
of the AVCodecContext or via the AVOptions API if the codec has
a private class. Any options provided via an AVDictionary have already
been applied before ff_frame_thread_init(), so in order to copy
all the options from the main AVCodecContext and its private context,
it is enough to av_opt_copy() these options.
The current code does this, but it does more: It also copies the
user-provided AVDictionary and uses it for the initialization of
each of the worker-AVCodecContexts. This is completely unnecessary,
because said options have already been copied from the main context.
Furthermore, these options were also examined to decide if frame
threading should be used for huffman encoding in case this would incur
nondeterminism. This is wrong, because options not set via
an AVDictionary are ignored. Instead inspect the values stored in the
contexts directly. (In order to maintain the current behaviour, the
default value of the "non_deterministic" option has been changed to false,
because the absence of an entry with said key in the AVDictionary
had the consequence of disallowing nondeterminism.)
Finally, the AVDictionary has been removed from the signature of
ff_frame_thread_encoder_init().
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Up until now, when using frame threaded encoding, an AVFrame would be
allocated for every frame to be encoded. These AVFrames would reach the
worker threads via a FIFO of tasks, a structure which contained the
AVFrame as well as an index into an array which gives the place where
the worker thread shall put the returned packet; in addition to that,
said structure also contained several unused fields.
This commit changes this: The AVFrames are now allocated during init in
the array that is up until now only used to return the packets. The
contents to be encoded are put into the AVFrame in the same array
element that is also used to return the packets.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
Up until now, when doing frame thread encoding, each worker thread
tried to allocate an AVPacket for every AVFrame to be encoded; said
packets would then be handed back to the main thread, where the content
of said packet is copied into the packet actually destined for output;
the temporary AVPacket is then freed.
Besides being wasteful this also has another problem: There is a risk of
deadlock, namely if no AVPacket can be allocated at all. The user
doesn't get an error at all in this case and the worker threads will
simply try to allocate a packet again and again. If the user has
supplied enough frames, the user's thread will block until a task has
been completed, which just doesn't happen if no packet can ever be
allocated.
This patch instead modifies the code to allocate the packets during
init; they are then reused again and again.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
Fixes a segfault from av_fifo_size(NULL) that happens in
ff_frame_thread_encoder_free if the fifo couldn't be allocted;
furthermore the mutexes and conditions that are destroyed in
ff_frame_thread_encoder_free are not even initialized at this point,
so don't call said function.
Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
It's the correct dedicated capability reported by supported encoders.
Otherwise, the frame thread path will be used for unsupported encoders
like r210 for no gain.
Reviewed-by: Anton Khirnov <anton@khirnov.net>
Signed-off-by: James Almer <jamrial@gmail.com>
This is the equivalent to what 7d317d4706
did for the codec-specific options.
av_opt_copy has specific handling so it's fine that we already copied
the whole context before.
Signed-off-by: Reimar Döffinger <Reimar.Doeffinger@gmx.de>
Should fix the following tsan warning:
WARNING: ThreadSanitizer: data race (pid=19806)
Read of size 4 at 0x7b84000012f0 by thread T9:
#0 worker src/libavcodec/frame_thread_encoder.c:66 (ffmpeg+0x0000007f349e)
[..]
Previous write of size 4 at 0x7b84000012f0 by main thread (mutexes: write M1395):
#0 ff_frame_thread_encoder_free src/libavcodec/frame_thread_encoder.c:239 (ffmpeg+0x0000007f379e)
[..]
Not actually used in huffyuvenc, but rather in setting the frame
threading.
Example for some files:
context=0: 851974 27226 1137281
context=1,ND=0: 471819 22604 972351
context=1,ND=1: 472875 22673 972582
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>