You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Everything downstream of an AVFrame's owner took `UniqueAVFrame&` or
`const UniqueAVFrame&`. That's a constraint on the caller's storage rather
than a statement about what the function does, and it has two costs.
A non-const `UniqueAVFrame&` lets a callee take ownership of the caller's
frame. Both CUDA interfaces did: BetaCudaDeviceInterface moved out of it,
CudaDeviceInterface reassigned it. That is invisible under
SingleStreamDecoder, whose frame is a loop local that dies right after
conversion, but the building-block ops own their frame in a handle that
outlives the call, so the frame gets freed twice.
`const UniqueAVFrame&` doesn't allow the steal, but it still forces anyone
holding a plain AVFrame* -- which is what the ops' tensor handle really is
-- to manufacture a unique_ptr just to make the call, and manufacturing a
second owner for an already-owned object is its own bug factory.
So: functions that only look at a frame now take `const AVFrame&`, and the
one that writes to it takes `AVFrame&`. Ownership stays with whoever
actually owns the frame. Producers (receive_frame) keep `UniqueAVFrame&`
because they really do hand back ownership.
With that, the ops layer needs no ownership sleight-of-hand:
wrap_pointer_to_tensor() gains a deleter parameter, so the one generic
handle covers Demuxer/PacketDecoder/ColorConverter and the FFmpeg types
too, and both bespoke wrap_*_pointer_to_tensor() functions go away.
Demuxer::next_packet() returns UniqueAVPacket rather than a raw pointer
plus a comment telling the caller to free it.
The encoder is left alone: it owns and mutates its frames, and it uses a
null frame as the flush signal, so a reference is the wrong shape there.
0 commit comments