LibMedia: Make video frames ref-counted
Video frames are about to be shared between the decoder, the data provider, the display sink, and Web painting code. Passing them by value keeps ownership tied to the old bitmap-shaped pipeline and makes later lifetime changes harder to reason about. Make VideoFrame ref-counted and return NonnullRefPtr from the decoder and media queues. This changes ownership only: a VideoFrame still wraps an ImmutableBitmap at this point, so playback behavior remains unchanged while later commits can move storage and painting independently.
This commit is contained in:
parent
ee4f9ef82c
commit
a659c55504
6 changed files with 10 additions and 8 deletions
|
|
@ -144,7 +144,7 @@ void FFmpegVideoDecoder::signal_end_of_stream()
|
|||
VERIFY(result == 0 || result == AVERROR_EOF);
|
||||
}
|
||||
|
||||
DecoderErrorOr<NonnullOwnPtr<VideoFrame>> FFmpegVideoDecoder::get_decoded_frame(CodingIndependentCodePoints const& container_cicp)
|
||||
DecoderErrorOr<NonnullRefPtr<VideoFrame>> FFmpegVideoDecoder::get_decoded_frame(CodingIndependentCodePoints const& container_cicp)
|
||||
{
|
||||
auto result = avcodec_receive_frame(m_codec_context, m_frame);
|
||||
|
||||
|
|
@ -249,7 +249,7 @@ DecoderErrorOr<NonnullOwnPtr<VideoFrame>> FFmpegVideoDecoder::get_decoded_frame(
|
|||
|
||||
auto bitmap = DECODER_TRY_ALLOC(Gfx::ImmutableBitmap::create_from_yuv(move(yuv_data)));
|
||||
|
||||
return DECODER_TRY_ALLOC(try_make<VideoFrame>(timestamp, duration, size, bit_depth, cicp, move(bitmap)));
|
||||
return DECODER_TRY_ALLOC(try_make_ref_counted<VideoFrame>(timestamp, duration, size, bit_depth, cicp, move(bitmap)));
|
||||
}
|
||||
case AVERROR(EAGAIN):
|
||||
return DecoderError::with_description(DecoderErrorCategory::NeedsMoreInput, "FFmpeg decoder has no frames available, send more input"sv);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public:
|
|||
|
||||
virtual DecoderErrorOr<void> receive_coded_data(AK::Duration timestamp, AK::Duration duration, ReadonlyBytes coded_data) override;
|
||||
virtual void signal_end_of_stream() override;
|
||||
virtual DecoderErrorOr<NonnullOwnPtr<VideoFrame>> get_decoded_frame(CodingIndependentCodePoints const& container_cicp) override;
|
||||
virtual DecoderErrorOr<NonnullRefPtr<VideoFrame>> get_decoded_frame(CodingIndependentCodePoints const& container_cicp) override;
|
||||
|
||||
virtual void flush() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ void VideoDataProvider::ThreadData::dispatch_frame_end_time(CodedFrame const& fr
|
|||
});
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::queue_frame(NonnullOwnPtr<VideoFrame> const& frame)
|
||||
void VideoDataProvider::ThreadData::queue_frame(NonnullRefPtr<VideoFrame> const& frame)
|
||||
{
|
||||
m_queue.enqueue(TimedImage(frame->timestamp(), frame->immutable_bitmap()));
|
||||
}
|
||||
|
|
@ -391,7 +391,7 @@ bool VideoDataProvider::ThreadData::handle_seek()
|
|||
|
||||
auto new_seek_id = m_seek_id.load();
|
||||
auto found_desired_keyframe = false;
|
||||
OwnPtr<VideoFrame> last_frame;
|
||||
RefPtr<VideoFrame> last_frame;
|
||||
|
||||
while (new_seek_id == seek_id) {
|
||||
auto coded_frame_result = m_demuxer->get_next_sample_for_track(m_track);
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ private:
|
|||
template<typename Invokee>
|
||||
void invoke_on_main_thread(Invokee);
|
||||
void dispatch_frame_end_time(CodedFrame const&);
|
||||
void queue_frame(NonnullOwnPtr<VideoFrame> const&);
|
||||
void queue_frame(NonnullRefPtr<VideoFrame> const&);
|
||||
void dispatch_error(DecoderError&&);
|
||||
bool handle_seek();
|
||||
template<typename Callback>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/Time.h>
|
||||
#include <LibMedia/Color/CodingIndependentCodePoints.h>
|
||||
|
||||
|
|
@ -22,7 +23,7 @@ public:
|
|||
virtual DecoderErrorOr<void> receive_coded_data(AK::Duration timestamp, AK::Duration duration, ReadonlyBytes coded_data) = 0;
|
||||
DecoderErrorOr<void> receive_coded_data(AK::Duration timestamp, AK::Duration duration, ByteBuffer const& coded_data) { return receive_coded_data(timestamp, duration, coded_data.span()); }
|
||||
virtual void signal_end_of_stream() = 0;
|
||||
virtual DecoderErrorOr<NonnullOwnPtr<VideoFrame>> get_decoded_frame(CodingIndependentCodePoints const& container_cicp) = 0;
|
||||
virtual DecoderErrorOr<NonnullRefPtr<VideoFrame>> get_decoded_frame(CodingIndependentCodePoints const& container_cicp) = 0;
|
||||
|
||||
virtual void flush() = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/AtomicRefCounted.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/Time.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
|
|
@ -15,7 +16,7 @@
|
|||
|
||||
namespace Media {
|
||||
|
||||
class MEDIA_API VideoFrame final {
|
||||
class MEDIA_API VideoFrame final : public AtomicRefCounted<VideoFrame> {
|
||||
|
||||
public:
|
||||
VideoFrame(
|
||||
|
|
|
|||
Loading…
Reference in a new issue