LibMedia: Rename some folders/identifiers for the upcoming refactor
- Provider -> producer - (Audio|Video)DataProvider -> Decoded(Audio|Video)Producer - MediaTimeProvider remains suffixed Provider, moves out of the Providers folder to the root of LibMedia This brings the naming more in line with the intended split functionality split between different nodes in the pipeline.
This commit is contained in:
parent
03989a5819
commit
eeff03c980
27 changed files with 244 additions and 244 deletions
|
|
@ -4,6 +4,7 @@ set(SOURCES
|
|||
Audio/AudioDevices.cpp
|
||||
Containers/Matroska/MatroskaDemuxer.cpp
|
||||
Containers/Matroska/Reader.cpp
|
||||
GenericTimeProvider.cpp
|
||||
IncrementallyPopulatedStream.cpp
|
||||
PlaybackManager.cpp
|
||||
PlaybackStates/StartingStateHandler.cpp
|
||||
|
|
@ -11,9 +12,8 @@ set(SOURCES
|
|||
PlaybackStates/PlaybackStateHandler.cpp
|
||||
PlaybackStates/ResumingStateHandler.cpp
|
||||
Processors/AudioMixer.cpp
|
||||
Providers/AudioDataProvider.cpp
|
||||
Providers/GenericTimeProvider.cpp
|
||||
Providers/VideoDataProvider.cpp
|
||||
Producers/DecodedAudioProducer.cpp
|
||||
Producers/DecodedVideoProducer.cpp
|
||||
Sinks/AudioPlaybackSink.cpp
|
||||
Sinks/DisplayingVideoSink.cpp
|
||||
TimeRanges.cpp
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
namespace Media {
|
||||
|
||||
class CodedFrame;
|
||||
class AudioDataProvider;
|
||||
class DecodedAudioProducer;
|
||||
class AudioDecoder;
|
||||
class AudioMixer;
|
||||
class AudioPlaybackSink;
|
||||
|
|
@ -26,7 +26,7 @@ class MediaTimeProvider;
|
|||
class PlaybackManager;
|
||||
class ReadonlyBytesCursor;
|
||||
class Track;
|
||||
class VideoDataProvider;
|
||||
class DecodedVideoProducer;
|
||||
class VideoDecoder;
|
||||
class VideoFrame;
|
||||
class VideoSink;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibMedia/Providers/MediaTimeProvider.h>
|
||||
#include "MediaTimeProvider.h"
|
||||
|
||||
namespace Media {
|
||||
|
||||
|
|
@ -7,11 +7,11 @@
|
|||
#include <LibMedia/Containers/Matroska/MatroskaDemuxer.h>
|
||||
#include <LibMedia/Demuxer.h>
|
||||
#include <LibMedia/FFmpeg/FFmpegDemuxer.h>
|
||||
#include <LibMedia/GenericTimeProvider.h>
|
||||
#include <LibMedia/PlaybackStates/StartingStateHandler.h>
|
||||
#include <LibMedia/Processors/AudioMixer.h>
|
||||
#include <LibMedia/Providers/AudioDataProvider.h>
|
||||
#include <LibMedia/Providers/GenericTimeProvider.h>
|
||||
#include <LibMedia/Providers/VideoDataProvider.h>
|
||||
#include <LibMedia/Producers/DecodedAudioProducer.h>
|
||||
#include <LibMedia/Producers/DecodedVideoProducer.h>
|
||||
#include <LibMedia/Sinks/AudioPlaybackSink.h>
|
||||
#include <LibMedia/Sinks/DisplayingVideoSink.h>
|
||||
#include <LibMedia/Track.h>
|
||||
|
|
@ -31,7 +31,7 @@ DecoderErrorOr<NonnullRefPtr<Demuxer>> PlaybackManager::create_demuxer_for_strea
|
|||
|
||||
DecoderErrorOr<void> PlaybackManager::prepare_playback_from_demuxer(WeakPlaybackManager const& self, NonnullRefPtr<Demuxer> const& demuxer, NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop_reference)
|
||||
{
|
||||
// Create the video tracks and their data providers.
|
||||
// Create the video tracks and their producers.
|
||||
auto all_video_tracks = TRY(demuxer->get_tracks_for_type(TrackType::Video));
|
||||
|
||||
auto supported_video_tracks = VideoTracks();
|
||||
|
|
@ -39,16 +39,16 @@ DecoderErrorOr<void> PlaybackManager::prepare_playback_from_demuxer(WeakPlayback
|
|||
supported_video_tracks.ensure_capacity(all_video_tracks.size());
|
||||
supported_video_track_datas.ensure_capacity(all_video_tracks.size());
|
||||
for (auto const& track : all_video_tracks) {
|
||||
auto video_data_provider_result = VideoDataProvider::try_create(main_thread_event_loop_reference, demuxer, track);
|
||||
if (video_data_provider_result.is_error())
|
||||
auto video_producer_result = DecodedVideoProducer::try_create(main_thread_event_loop_reference, demuxer, track);
|
||||
if (video_producer_result.is_error())
|
||||
continue;
|
||||
supported_video_tracks.append(track);
|
||||
supported_video_track_datas.empend(VideoTrackData(track, video_data_provider_result.release_value(), nullptr));
|
||||
supported_video_track_datas.empend(VideoTrackData(track, video_producer_result.release_value(), nullptr));
|
||||
}
|
||||
supported_video_tracks.shrink_to_fit();
|
||||
supported_video_track_datas.shrink_to_fit();
|
||||
|
||||
// Create all the audio tracks, their data providers, and the audio output.
|
||||
// Create all the audio tracks, their producers, and the audio output.
|
||||
auto all_audio_tracks = TRY(demuxer->get_tracks_for_type(TrackType::Audio));
|
||||
|
||||
auto supported_audio_tracks = AudioTracks();
|
||||
|
|
@ -56,12 +56,12 @@ DecoderErrorOr<void> PlaybackManager::prepare_playback_from_demuxer(WeakPlayback
|
|||
supported_audio_tracks.ensure_capacity(all_audio_tracks.size());
|
||||
supported_audio_track_datas.ensure_capacity(all_audio_tracks.size());
|
||||
for (auto const& track : all_audio_tracks) {
|
||||
auto audio_data_provider_result = AudioDataProvider::try_create(main_thread_event_loop_reference, demuxer, track);
|
||||
if (audio_data_provider_result.is_error())
|
||||
auto audio_producer_result = DecodedAudioProducer::try_create(main_thread_event_loop_reference, demuxer, track);
|
||||
if (audio_producer_result.is_error())
|
||||
continue;
|
||||
auto audio_data_provider = audio_data_provider_result.release_value();
|
||||
auto audio_producer = audio_producer_result.release_value();
|
||||
supported_audio_tracks.append(track);
|
||||
supported_audio_track_datas.empend(AudioTrackData(track, move(audio_data_provider)));
|
||||
supported_audio_track_datas.empend(AudioTrackData(track, move(audio_producer)));
|
||||
}
|
||||
supported_audio_tracks.shrink_to_fit();
|
||||
supported_audio_track_datas.shrink_to_fit();
|
||||
|
|
@ -113,7 +113,7 @@ DecoderErrorOr<void> PlaybackManager::prepare_playback_from_demuxer(WeakPlayback
|
|||
self->m_start_time_realtime = start_time_realtime;
|
||||
self->check_for_duration_change(duration);
|
||||
|
||||
self->set_up_data_providers();
|
||||
self->set_up_producers();
|
||||
|
||||
if (!self->m_audio_output_disabled && !self->m_audio_sink && !self->m_audio_tracks.is_empty()) {
|
||||
self->m_audio_mixer = MUST(AudioMixer::try_create());
|
||||
|
|
@ -213,11 +213,11 @@ WeakPlaybackManager PlaybackManager::weak()
|
|||
return WeakPlaybackManager(m_weak_link);
|
||||
}
|
||||
|
||||
void PlaybackManager::set_up_data_providers()
|
||||
void PlaybackManager::set_up_producers()
|
||||
{
|
||||
for (auto const& video_track_data : m_video_track_datas) {
|
||||
auto track = video_track_data.track;
|
||||
video_track_data.provider->set_error_handler([self = weak(), track](DecoderError&& error) {
|
||||
video_track_data.producer->set_error_handler([self = weak(), track](DecoderError&& error) {
|
||||
if (!self)
|
||||
return;
|
||||
if (error.category() == DecoderErrorCategory::EndOfStream) {
|
||||
|
|
@ -226,12 +226,12 @@ void PlaybackManager::set_up_data_providers()
|
|||
}
|
||||
self->dispatch_error(move(error));
|
||||
});
|
||||
video_track_data.provider->set_duration_change_handler([self = weak()](AK::Duration time) {
|
||||
video_track_data.producer->set_duration_change_handler([self = weak()](AK::Duration time) {
|
||||
if (!self)
|
||||
return;
|
||||
self->check_for_duration_change(time);
|
||||
});
|
||||
video_track_data.provider->set_frames_queue_is_full_handler([self = weak(), track] {
|
||||
video_track_data.producer->set_frames_queue_is_full_handler([self = weak(), track] {
|
||||
if (!self)
|
||||
return;
|
||||
self->track_stopped_buffering(track);
|
||||
|
|
@ -240,7 +240,7 @@ void PlaybackManager::set_up_data_providers()
|
|||
|
||||
for (auto const& audio_track_data : m_audio_track_datas) {
|
||||
auto track = audio_track_data.track;
|
||||
audio_track_data.provider->set_error_handler([self = weak(), track](DecoderError&& error) {
|
||||
audio_track_data.producer->set_error_handler([self = weak(), track](DecoderError&& error) {
|
||||
if (!self)
|
||||
return;
|
||||
if (error.category() == DecoderErrorCategory::EndOfStream) {
|
||||
|
|
@ -249,12 +249,12 @@ void PlaybackManager::set_up_data_providers()
|
|||
}
|
||||
self->dispatch_error(move(error));
|
||||
});
|
||||
audio_track_data.provider->set_duration_change_handler([self = weak()](AK::Duration time) {
|
||||
audio_track_data.producer->set_duration_change_handler([self = weak()](AK::Duration time) {
|
||||
if (!self)
|
||||
return;
|
||||
self->check_for_duration_change(time);
|
||||
});
|
||||
audio_track_data.provider->set_queue_is_full_handler([self = weak(), track] {
|
||||
audio_track_data.producer->set_queue_is_full_handler([self = weak(), track] {
|
||||
if (!self)
|
||||
return;
|
||||
self->track_stopped_buffering(track);
|
||||
|
|
@ -324,7 +324,7 @@ NonnullRefPtr<DisplayingVideoSink> PlaybackManager::get_or_create_the_displaying
|
|||
auto& track_data = get_video_data_for_track(track);
|
||||
if (track_data.display == nullptr) {
|
||||
track_data.display = MUST(Media::DisplayingVideoSink::try_create(m_time_provider));
|
||||
track_data.display->set_provider(track, track_data.provider);
|
||||
track_data.display->set_producer(track, track_data.producer);
|
||||
track_data.display->m_on_start_buffering = [this, track] {
|
||||
track_started_buffering(track);
|
||||
};
|
||||
|
|
@ -332,7 +332,7 @@ NonnullRefPtr<DisplayingVideoSink> PlaybackManager::get_or_create_the_displaying
|
|||
m_handler->on_track_enabled(track);
|
||||
}
|
||||
|
||||
VERIFY(track_data.display->provider(track) == track_data.provider);
|
||||
VERIFY(track_data.display->producer(track) == track_data.producer);
|
||||
return *track_data.display;
|
||||
}
|
||||
|
||||
|
|
@ -340,7 +340,7 @@ void PlaybackManager::remove_the_displaying_video_sink_for_track(Track const& tr
|
|||
{
|
||||
auto& track_data = get_video_data_for_track(track);
|
||||
VERIFY(track_data.display);
|
||||
track_data.display->set_provider(track, nullptr);
|
||||
track_data.display->set_producer(track, nullptr);
|
||||
track_data.display = nullptr;
|
||||
track_stopped_buffering(track);
|
||||
m_handler->on_track_disabled(track);
|
||||
|
|
@ -352,8 +352,8 @@ void PlaybackManager::enable_an_audio_track(Track const& track)
|
|||
VERIFY(!track_data.enabled);
|
||||
track_data.enabled = true;
|
||||
if (m_audio_mixer) {
|
||||
VERIFY(m_audio_mixer->provider(track) == nullptr);
|
||||
m_audio_mixer->set_provider(track, track_data.provider);
|
||||
VERIFY(m_audio_mixer->producer(track) == nullptr);
|
||||
m_audio_mixer->set_producer(track, track_data.producer);
|
||||
m_tracks_still_buffering.set(track);
|
||||
}
|
||||
m_handler->on_track_enabled(track);
|
||||
|
|
@ -364,8 +364,8 @@ void PlaybackManager::disable_an_audio_track(Track const& track)
|
|||
auto& track_data = get_audio_data_for_track(track);
|
||||
VERIFY(track_data.enabled);
|
||||
if (m_audio_mixer) {
|
||||
VERIFY(m_audio_mixer->provider(track) == track_data.provider);
|
||||
m_audio_mixer->set_provider(track, nullptr);
|
||||
VERIFY(m_audio_mixer->producer(track) == track_data.producer);
|
||||
m_audio_mixer->set_producer(track, nullptr);
|
||||
}
|
||||
track_data.enabled = false;
|
||||
track_stopped_buffering(track);
|
||||
|
|
@ -384,7 +384,7 @@ bool PlaybackManager::track_is_enabled(Track const& track) const
|
|||
if (!track_data.enabled)
|
||||
return false;
|
||||
if (m_audio_mixer)
|
||||
VERIFY(track_data.provider == m_audio_mixer->provider(track));
|
||||
VERIFY(track_data.producer == m_audio_mixer->producer(track));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -435,7 +435,7 @@ TimeRanges PlaybackManager::buffered_time_ranges() const
|
|||
if (!track_is_enabled(track_data.track))
|
||||
continue;
|
||||
|
||||
auto range = track_data.provider->buffered_time_ranges();
|
||||
auto range = track_data.producer->buffered_time_ranges();
|
||||
if (intersection.is_empty()) {
|
||||
intersection = range;
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
#include <LibMedia/DecoderError.h>
|
||||
#include <LibMedia/Export.h>
|
||||
#include <LibMedia/Forward.h>
|
||||
#include <LibMedia/MediaTimeProvider.h>
|
||||
#include <LibMedia/PlaybackStates/Forward.h>
|
||||
#include <LibMedia/PlaybackStates/PlaybackState.h>
|
||||
#include <LibMedia/Providers/MediaTimeProvider.h>
|
||||
#include <LibMedia/TimeRanges.h>
|
||||
#include <LibMedia/Track.h>
|
||||
#include <LibSync/Mutex.h>
|
||||
|
|
@ -107,14 +107,14 @@ public:
|
|||
private:
|
||||
struct VideoTrackData {
|
||||
Track track;
|
||||
NonnullRefPtr<VideoDataProvider> provider;
|
||||
NonnullRefPtr<DecodedVideoProducer> producer;
|
||||
RefPtr<DisplayingVideoSink> display;
|
||||
};
|
||||
using VideoTrackDatas = Vector<VideoTrackData, EXPECTED_VIDEO_TRACK_COUNT>;
|
||||
|
||||
struct AudioTrackData {
|
||||
Track track;
|
||||
NonnullRefPtr<AudioDataProvider> provider;
|
||||
NonnullRefPtr<DecodedAudioProducer> producer;
|
||||
bool enabled { false };
|
||||
};
|
||||
using AudioTrackDatas = Vector<AudioTrackData, EXPECTED_AUDIO_TRACK_COUNT>;
|
||||
|
|
@ -124,7 +124,7 @@ private:
|
|||
void set_time_provider(NonnullRefPtr<MediaTimeProvider> const&);
|
||||
void disable_audio();
|
||||
|
||||
void set_up_data_providers();
|
||||
void set_up_producers();
|
||||
void track_started_buffering(Track const&);
|
||||
void track_stopped_buffering(Track const&);
|
||||
void check_for_duration_change(AK::Duration);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ void PlaybackStateHandler::on_track_enabled(Track const& track)
|
|||
auto& track_data = manager().get_video_data_for_track(track);
|
||||
VERIFY(track_data.display != nullptr);
|
||||
track_data.display->pause_updates();
|
||||
track_data.provider->seek(manager().current_time(), SeekMode::Accurate, [display = NonnullRefPtr(*track_data.display)](AK::Duration) {
|
||||
track_data.producer->seek(manager().current_time(), SeekMode::Accurate, [display = NonnullRefPtr(*track_data.display)](AK::Duration) {
|
||||
display->resume_updates();
|
||||
});
|
||||
return;
|
||||
|
|
@ -33,7 +33,7 @@ void PlaybackStateHandler::on_track_enabled(Track const& track)
|
|||
auto& track_data = manager().get_audio_data_for_track(track);
|
||||
if (!manager().m_audio_mixer)
|
||||
return;
|
||||
track_data.provider->seek(manager().current_time(), nullptr);
|
||||
track_data.producer->seek(manager().current_time(), nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
#include <LibMedia/PlaybackManager.h>
|
||||
#include <LibMedia/PlaybackStates/Forward.h>
|
||||
#include <LibMedia/PlaybackStates/ResumingStateHandler.h>
|
||||
#include <LibMedia/Providers/AudioDataProvider.h>
|
||||
#include <LibMedia/Providers/VideoDataProvider.h>
|
||||
#include <LibMedia/Producers/DecodedAudioProducer.h>
|
||||
#include <LibMedia/Producers/DecodedVideoProducer.h>
|
||||
#include <LibMedia/SeekMode.h>
|
||||
#include <LibMedia/Sinks/AudioPlaybackSink.h>
|
||||
#include <LibMedia/Sinks/DisplayingVideoSink.h>
|
||||
|
|
@ -76,14 +76,14 @@ public:
|
|||
{
|
||||
if (track.type() == TrackType::Video) {
|
||||
auto& track_data = manager().get_video_data_for_track(track);
|
||||
track_data.provider->seek(m_target_timestamp, SeekMode::Accurate, nullptr);
|
||||
track_data.producer->seek(m_target_timestamp, SeekMode::Accurate, nullptr);
|
||||
end_video_seek(track);
|
||||
return;
|
||||
}
|
||||
|
||||
VERIFY(track.type() == TrackType::Audio);
|
||||
auto& track_data = manager().get_audio_data_for_track(track);
|
||||
track_data.provider->seek(m_target_timestamp, nullptr);
|
||||
track_data.producer->seek(m_target_timestamp, nullptr);
|
||||
end_audio_seek(track);
|
||||
}
|
||||
|
||||
|
|
@ -120,10 +120,10 @@ private:
|
|||
|
||||
m_video_seeks_pending.set(track);
|
||||
track_data.display->pause_updates();
|
||||
track_data.provider->seek(m_target_timestamp, m_mode, [this, weak_manager = manager().weak(), track](AK::Duration provider_timestamp) {
|
||||
track_data.producer->seek(m_target_timestamp, m_mode, [this, weak_manager = manager().weak(), track](AK::Duration producer_timestamp) {
|
||||
if (!weak_manager)
|
||||
return;
|
||||
m_chosen_timestamp = max(m_chosen_timestamp, provider_timestamp);
|
||||
m_chosen_timestamp = max(m_chosen_timestamp, producer_timestamp);
|
||||
end_video_seek(track);
|
||||
});
|
||||
}
|
||||
|
|
@ -145,7 +145,7 @@ private:
|
|||
|
||||
m_audio_seeks_pending.set(track);
|
||||
|
||||
track_data.provider->seek(m_chosen_timestamp, [this, weak_manager = manager().weak(), track]() {
|
||||
track_data.producer->seek(m_chosen_timestamp, [this, weak_manager = manager().weak(), track]() {
|
||||
if (!weak_manager)
|
||||
return;
|
||||
end_audio_seek(track);
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
#include <LibMedia/PlaybackStates/Forward.h>
|
||||
#include <LibMedia/PlaybackStates/SeekingStateHandler.h>
|
||||
#include <LibMedia/Processors/AudioMixer.h>
|
||||
#include <LibMedia/Providers/AudioDataProvider.h>
|
||||
#include <LibMedia/Providers/VideoDataProvider.h>
|
||||
#include <LibMedia/Producers/DecodedAudioProducer.h>
|
||||
#include <LibMedia/Producers/DecodedVideoProducer.h>
|
||||
|
||||
namespace Media {
|
||||
|
||||
|
|
@ -26,17 +26,17 @@ public:
|
|||
virtual void on_enter() override
|
||||
{
|
||||
for (auto& video_track_data : manager().m_video_track_datas)
|
||||
video_track_data.provider->suspend();
|
||||
video_track_data.producer->suspend();
|
||||
for (auto& audio_track_data : manager().m_audio_track_datas)
|
||||
audio_track_data.provider->suspend();
|
||||
audio_track_data.producer->suspend();
|
||||
}
|
||||
|
||||
virtual void on_exit() override
|
||||
{
|
||||
for (auto& video_track_data : manager().m_video_track_datas)
|
||||
video_track_data.provider->resume();
|
||||
video_track_data.producer->resume();
|
||||
for (auto& audio_track_data : manager().m_audio_track_datas)
|
||||
audio_track_data.provider->resume();
|
||||
audio_track_data.producer->resume();
|
||||
}
|
||||
|
||||
virtual void play() override
|
||||
|
|
@ -73,13 +73,13 @@ public:
|
|||
auto& track_data = manager().get_video_data_for_track(track);
|
||||
VERIFY(track_data.display != nullptr);
|
||||
track_data.display->pause_updates();
|
||||
track_data.provider->resume();
|
||||
track_data.provider->seek(manager().current_time(), SeekMode::Accurate, [manager = manager().weak(), provider = track_data.provider, display = track_data.display](AK::Duration) {
|
||||
track_data.producer->resume();
|
||||
track_data.producer->seek(manager().current_time(), SeekMode::Accurate, [manager = manager().weak(), producer = track_data.producer, display = track_data.display](AK::Duration) {
|
||||
if (!manager)
|
||||
return;
|
||||
display->resume_updates();
|
||||
if (manager->state() != PlaybackState::Buffering)
|
||||
provider->suspend();
|
||||
producer->suspend();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
@ -88,12 +88,12 @@ public:
|
|||
auto& track_data = manager().get_audio_data_for_track(track);
|
||||
if (!manager().m_audio_mixer)
|
||||
return;
|
||||
track_data.provider->resume();
|
||||
track_data.provider->seek(manager().current_time(), [manager = manager().weak(), provider = track_data.provider] {
|
||||
track_data.producer->resume();
|
||||
track_data.producer->seek(manager().current_time(), [manager = manager().weak(), producer = track_data.producer] {
|
||||
if (!manager)
|
||||
return;
|
||||
if (manager->state() == PlaybackState::Suspended)
|
||||
provider->suspend();
|
||||
producer->suspend();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <LibMedia/Processors/AudioMixer.h>
|
||||
#include <LibMedia/Providers/AudioDataProvider.h>
|
||||
#include <LibMedia/Producers/DecodedAudioProducer.h>
|
||||
|
||||
namespace Media {
|
||||
|
||||
|
|
@ -21,29 +21,29 @@ AudioMixer::AudioMixer()
|
|||
{
|
||||
}
|
||||
|
||||
void AudioMixer::set_provider(Track const& track, RefPtr<AudioDataProvider> const& provider)
|
||||
void AudioMixer::set_producer(Track const& track, RefPtr<DecodedAudioProducer> const& producer)
|
||||
{
|
||||
Sync::MutexLocker locker { m_mutex };
|
||||
m_track_mixing_datas.remove(track);
|
||||
if (provider == nullptr)
|
||||
if (producer == nullptr)
|
||||
return;
|
||||
|
||||
// The provider must have its output sample specification set before it starts decoding, or
|
||||
// The producer must have its output sample specification set before it starts decoding, or
|
||||
// we'll drop some samples due to a mismatch.
|
||||
m_track_mixing_datas.set(track, TrackMixingData(*provider));
|
||||
m_track_mixing_datas.set(track, TrackMixingData(*producer));
|
||||
|
||||
if (m_sample_specification.is_valid()) {
|
||||
provider->set_output_sample_specification(m_sample_specification);
|
||||
provider->start();
|
||||
producer->set_output_sample_specification(m_sample_specification);
|
||||
producer->start();
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<AudioDataProvider> AudioMixer::provider(Track const& track) const
|
||||
RefPtr<DecodedAudioProducer> AudioMixer::producer(Track const& track) const
|
||||
{
|
||||
auto mixing_data = m_track_mixing_datas.get(track);
|
||||
if (!mixing_data.has_value())
|
||||
return nullptr;
|
||||
return mixing_data->provider;
|
||||
return mixing_data->producer;
|
||||
}
|
||||
|
||||
void AudioMixer::set_sample_specification(Audio::SampleSpecification sample_specification)
|
||||
|
|
@ -52,8 +52,8 @@ void AudioMixer::set_sample_specification(Audio::SampleSpecification sample_spec
|
|||
m_sample_specification = sample_specification;
|
||||
|
||||
for (auto& [track, track_data] : m_track_mixing_datas) {
|
||||
track_data.provider->set_output_sample_specification(m_sample_specification);
|
||||
track_data.provider->start();
|
||||
track_data.producer->set_output_sample_specification(m_sample_specification);
|
||||
track_data.producer->start();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,13 +84,13 @@ bool AudioMixer::mix_one_block_into(AudioBlock& out_block)
|
|||
auto buffering = false;
|
||||
auto any_track_has_fresh_data = false;
|
||||
for (auto& [track, track_data] : m_track_mixing_datas) {
|
||||
auto available_end = track_data.provider->queue_end_sample();
|
||||
auto available_end = track_data.producer->queue_end_sample();
|
||||
// A newly-enabled track has no data at the current mix position yet; skip it for clamping so
|
||||
// the mixer doesn't stall waiting for it to catch up.
|
||||
if (available_end <= buffer_start) {
|
||||
track_data.current_block.clear();
|
||||
while (true) {
|
||||
auto block = track_data.provider->retrieve_block();
|
||||
auto block = track_data.producer->retrieve_block();
|
||||
if (block.is_empty())
|
||||
break;
|
||||
if (block.end_timestamp_in_samples() >= buffer_start) {
|
||||
|
|
@ -105,7 +105,7 @@ bool AudioMixer::mix_one_block_into(AudioBlock& out_block)
|
|||
any_track_has_fresh_data = true;
|
||||
if (available_end < samples_end) {
|
||||
samples_end = available_end;
|
||||
if (track_data.provider->is_blocked())
|
||||
if (track_data.producer->is_blocked())
|
||||
buffering = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -117,7 +117,7 @@ bool AudioMixer::mix_one_block_into(AudioBlock& out_block)
|
|||
if (!buffering) {
|
||||
track_data.buffering = false;
|
||||
} else {
|
||||
if (!track_data.provider->is_blocked())
|
||||
if (!track_data.producer->is_blocked())
|
||||
continue;
|
||||
if (track_data.buffering)
|
||||
continue;
|
||||
|
|
@ -146,7 +146,7 @@ bool AudioMixer::mix_one_block_into(AudioBlock& out_block)
|
|||
auto next_sample = buffer_start;
|
||||
|
||||
auto go_to_next_block = [&] {
|
||||
auto new_block = track_data.provider->retrieve_block();
|
||||
auto new_block = track_data.producer->retrieve_block();
|
||||
if (new_block.is_empty())
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include <LibMedia/AudioBlock.h>
|
||||
#include <LibMedia/Export.h>
|
||||
#include <LibMedia/Forward.h>
|
||||
#include <LibMedia/Providers/AudioDataProvider.h>
|
||||
#include <LibMedia/Producers/DecodedAudioProducer.h>
|
||||
#include <LibMedia/Sinks/AudioSink.h>
|
||||
#include <LibMedia/Track.h>
|
||||
#include <LibSync/Mutex.h>
|
||||
|
|
@ -30,8 +30,8 @@ public:
|
|||
AudioMixer();
|
||||
virtual ~AudioMixer() override = default;
|
||||
|
||||
virtual void set_provider(Track const&, RefPtr<AudioDataProvider> const&) override;
|
||||
virtual RefPtr<AudioDataProvider> provider(Track const&) const override;
|
||||
virtual void set_producer(Track const&, RefPtr<DecodedAudioProducer> const&) override;
|
||||
virtual RefPtr<DecodedAudioProducer> producer(Track const&) const override;
|
||||
|
||||
void set_sample_specification(Audio::SampleSpecification);
|
||||
Audio::SampleSpecification sample_specification() const;
|
||||
|
|
@ -44,12 +44,12 @@ public:
|
|||
|
||||
private:
|
||||
struct TrackMixingData {
|
||||
TrackMixingData(NonnullRefPtr<AudioDataProvider> const& provider)
|
||||
: provider(provider)
|
||||
TrackMixingData(NonnullRefPtr<DecodedAudioProducer> const& producer)
|
||||
: producer(producer)
|
||||
{
|
||||
}
|
||||
|
||||
NonnullRefPtr<AudioDataProvider> provider;
|
||||
NonnullRefPtr<DecodedAudioProducer> producer;
|
||||
AudioBlock current_block;
|
||||
bool buffering { false };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,19 +14,19 @@
|
|||
#include <LibSync/Mutex.h>
|
||||
#include <LibThreading/Thread.h>
|
||||
|
||||
#include "AudioDataProvider.h"
|
||||
#include "DecodedAudioProducer.h"
|
||||
|
||||
namespace Media {
|
||||
|
||||
DecoderErrorOr<NonnullRefPtr<AudioDataProvider>> AudioDataProvider::try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track)
|
||||
DecoderErrorOr<NonnullRefPtr<DecodedAudioProducer>> DecodedAudioProducer::try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track)
|
||||
{
|
||||
auto converter = DECODER_TRY_ALLOC(FFmpeg::FFmpegAudioConverter::try_create());
|
||||
|
||||
TRY(demuxer->create_context_for_track(track));
|
||||
auto duration = TRY(demuxer->duration_of_track(track));
|
||||
auto thread_data = DECODER_TRY_ALLOC(try_make_ref_counted<AudioDataProvider::ThreadData>(main_thread_event_loop, demuxer, track, duration, move(converter)));
|
||||
auto thread_data = DECODER_TRY_ALLOC(try_make_ref_counted<DecodedAudioProducer::ThreadData>(main_thread_event_loop, demuxer, track, duration, move(converter)));
|
||||
TRY(thread_data->create_decoder());
|
||||
auto provider = DECODER_TRY_ALLOC(try_make_ref_counted<AudioDataProvider>(thread_data));
|
||||
auto producer = DECODER_TRY_ALLOC(try_make_ref_counted<DecodedAudioProducer>(thread_data));
|
||||
|
||||
auto thread = DECODER_TRY_ALLOC(Threading::Thread::try_create("Audio Decoder"sv, [thread_data]() -> int {
|
||||
thread_data->wait_for_start();
|
||||
|
|
@ -41,86 +41,86 @@ DecoderErrorOr<NonnullRefPtr<AudioDataProvider>> AudioDataProvider::try_create(N
|
|||
thread->start();
|
||||
thread->detach();
|
||||
|
||||
return provider;
|
||||
return producer;
|
||||
}
|
||||
|
||||
AudioDataProvider::AudioDataProvider(NonnullRefPtr<ThreadData> const& thread_data)
|
||||
DecodedAudioProducer::DecodedAudioProducer(NonnullRefPtr<ThreadData> const& thread_data)
|
||||
: m_thread_data(thread_data)
|
||||
{
|
||||
}
|
||||
|
||||
AudioDataProvider::~AudioDataProvider()
|
||||
DecodedAudioProducer::~DecodedAudioProducer()
|
||||
{
|
||||
m_thread_data->exit();
|
||||
}
|
||||
|
||||
void AudioDataProvider::set_error_handler(ErrorHandler&& handler)
|
||||
void DecodedAudioProducer::set_error_handler(ErrorHandler&& handler)
|
||||
{
|
||||
m_thread_data->set_error_handler(move(handler));
|
||||
}
|
||||
|
||||
void AudioDataProvider::set_duration_change_handler(BlockEndTimeHandler&& handler)
|
||||
void DecodedAudioProducer::set_duration_change_handler(BlockEndTimeHandler&& handler)
|
||||
{
|
||||
m_thread_data->set_duration_change_handler(move(handler));
|
||||
}
|
||||
|
||||
void AudioDataProvider::set_queue_is_full_handler(QueueIsFullHandler&& handler)
|
||||
void DecodedAudioProducer::set_queue_is_full_handler(QueueIsFullHandler&& handler)
|
||||
{
|
||||
m_thread_data->set_queue_is_full_handler(move(handler));
|
||||
}
|
||||
|
||||
void AudioDataProvider::set_output_sample_specification(Audio::SampleSpecification sample_specification)
|
||||
void DecodedAudioProducer::set_output_sample_specification(Audio::SampleSpecification sample_specification)
|
||||
{
|
||||
m_thread_data->set_output_sample_specification(sample_specification);
|
||||
}
|
||||
|
||||
void AudioDataProvider::start()
|
||||
void DecodedAudioProducer::start()
|
||||
{
|
||||
m_thread_data->start();
|
||||
}
|
||||
|
||||
void AudioDataProvider::suspend()
|
||||
void DecodedAudioProducer::suspend()
|
||||
{
|
||||
m_thread_data->suspend();
|
||||
}
|
||||
|
||||
void AudioDataProvider::resume()
|
||||
void DecodedAudioProducer::resume()
|
||||
{
|
||||
m_thread_data->resume();
|
||||
}
|
||||
|
||||
void AudioDataProvider::seek(AK::Duration timestamp, SeekCompletionHandler&& completion_handler)
|
||||
void DecodedAudioProducer::seek(AK::Duration timestamp, SeekCompletionHandler&& completion_handler)
|
||||
{
|
||||
m_thread_data->seek(timestamp, move(completion_handler));
|
||||
}
|
||||
|
||||
bool AudioDataProvider::is_blocked() const
|
||||
bool DecodedAudioProducer::is_blocked() const
|
||||
{
|
||||
return m_thread_data->is_blocked();
|
||||
}
|
||||
|
||||
i64 AudioDataProvider::queue_end_sample() const
|
||||
i64 DecodedAudioProducer::queue_end_sample() const
|
||||
{
|
||||
return m_thread_data->queue_end_sample();
|
||||
}
|
||||
|
||||
TimeRanges AudioDataProvider::buffered_time_ranges() const
|
||||
TimeRanges DecodedAudioProducer::buffered_time_ranges() const
|
||||
{
|
||||
return m_thread_data->buffered_time_ranges();
|
||||
}
|
||||
|
||||
bool AudioDataProvider::ThreadData::is_blocked() const
|
||||
bool DecodedAudioProducer::ThreadData::is_blocked() const
|
||||
{
|
||||
return m_demuxer->is_read_blocked_for_track(m_track);
|
||||
}
|
||||
|
||||
i64 AudioDataProvider::ThreadData::queue_end_sample() const
|
||||
i64 DecodedAudioProducer::ThreadData::queue_end_sample() const
|
||||
{
|
||||
auto locker = take_lock();
|
||||
return m_queue_end_sample;
|
||||
}
|
||||
|
||||
AudioDataProvider::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track, AK::Duration duration, NonnullOwnPtr<Audio::AudioConverter>&& converter)
|
||||
DecodedAudioProducer::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track, AK::Duration duration, NonnullOwnPtr<Audio::AudioConverter>&& converter)
|
||||
: m_main_thread_event_loop(main_thread_event_loop)
|
||||
, m_demuxer(demuxer)
|
||||
, m_track(track)
|
||||
|
|
@ -129,29 +129,29 @@ AudioDataProvider::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopRefer
|
|||
{
|
||||
}
|
||||
|
||||
AudioDataProvider::ThreadData::~ThreadData() = default;
|
||||
DecodedAudioProducer::ThreadData::~ThreadData() = default;
|
||||
|
||||
void AudioDataProvider::ThreadData::set_error_handler(ErrorHandler&& handler)
|
||||
void DecodedAudioProducer::ThreadData::set_error_handler(ErrorHandler&& handler)
|
||||
{
|
||||
m_error_handler = move(handler);
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::set_duration_change_handler(BlockEndTimeHandler&& handler)
|
||||
void DecodedAudioProducer::ThreadData::set_duration_change_handler(BlockEndTimeHandler&& handler)
|
||||
{
|
||||
m_duration_change_handler = move(handler);
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::set_queue_is_full_handler(QueueIsFullHandler&& handler)
|
||||
void DecodedAudioProducer::ThreadData::set_queue_is_full_handler(QueueIsFullHandler&& handler)
|
||||
{
|
||||
m_queue_is_full_handler = move(handler);
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::set_output_sample_specification(Audio::SampleSpecification sample_specification)
|
||||
void DecodedAudioProducer::ThreadData::set_output_sample_specification(Audio::SampleSpecification sample_specification)
|
||||
{
|
||||
m_converter->set_output_sample_specification(sample_specification).release_value_but_fixme_should_propagate_errors();
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::start()
|
||||
void DecodedAudioProducer::ThreadData::start()
|
||||
{
|
||||
auto locker = take_lock();
|
||||
if (m_requested_state != RequestedState::None)
|
||||
|
|
@ -160,7 +160,7 @@ void AudioDataProvider::ThreadData::start()
|
|||
wake();
|
||||
}
|
||||
|
||||
DecoderErrorOr<void> AudioDataProvider::ThreadData::create_decoder()
|
||||
DecoderErrorOr<void> DecodedAudioProducer::ThreadData::create_decoder()
|
||||
{
|
||||
auto codec_id = TRY(m_demuxer->get_codec_id_for_track(m_track));
|
||||
auto const& sample_specification = m_track.audio_data().sample_specification;
|
||||
|
|
@ -169,7 +169,7 @@ DecoderErrorOr<void> AudioDataProvider::ThreadData::create_decoder()
|
|||
return {};
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::suspend()
|
||||
void DecodedAudioProducer::ThreadData::suspend()
|
||||
{
|
||||
auto locker = take_lock();
|
||||
VERIFY(m_requested_state != RequestedState::Exit);
|
||||
|
|
@ -177,7 +177,7 @@ void AudioDataProvider::ThreadData::suspend()
|
|||
wake();
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::resume()
|
||||
void DecodedAudioProducer::ThreadData::resume()
|
||||
{
|
||||
auto locker = take_lock();
|
||||
VERIFY(m_requested_state != RequestedState::Exit);
|
||||
|
|
@ -185,14 +185,14 @@ void AudioDataProvider::ThreadData::resume()
|
|||
wake();
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::exit()
|
||||
void DecodedAudioProducer::ThreadData::exit()
|
||||
{
|
||||
auto locker = take_lock();
|
||||
m_requested_state = RequestedState::Exit;
|
||||
wake();
|
||||
}
|
||||
|
||||
AudioBlock AudioDataProvider::retrieve_block()
|
||||
AudioBlock DecodedAudioProducer::retrieve_block()
|
||||
{
|
||||
auto locker = m_thread_data->take_lock();
|
||||
if (m_thread_data->queue().is_empty())
|
||||
|
|
@ -202,7 +202,7 @@ AudioBlock AudioDataProvider::retrieve_block()
|
|||
return result;
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::seek(AK::Duration timestamp, SeekCompletionHandler&& completion_handler)
|
||||
void DecodedAudioProducer::ThreadData::seek(AK::Duration timestamp, SeekCompletionHandler&& completion_handler)
|
||||
{
|
||||
auto locker = take_lock();
|
||||
m_seek_completion_handler = move(completion_handler);
|
||||
|
|
@ -212,25 +212,25 @@ void AudioDataProvider::ThreadData::seek(AK::Duration timestamp, SeekCompletionH
|
|||
wake();
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::wait_for_start()
|
||||
void DecodedAudioProducer::ThreadData::wait_for_start()
|
||||
{
|
||||
auto locker = take_lock();
|
||||
while (m_requested_state == RequestedState::None)
|
||||
m_wait_condition.wait();
|
||||
}
|
||||
|
||||
bool AudioDataProvider::ThreadData::should_thread_exit_while_locked() const
|
||||
bool DecodedAudioProducer::ThreadData::should_thread_exit_while_locked() const
|
||||
{
|
||||
return m_requested_state == RequestedState::Exit;
|
||||
}
|
||||
|
||||
bool AudioDataProvider::ThreadData::should_thread_exit() const
|
||||
bool DecodedAudioProducer::ThreadData::should_thread_exit() const
|
||||
{
|
||||
auto locker = take_lock();
|
||||
return should_thread_exit_while_locked();
|
||||
}
|
||||
|
||||
bool AudioDataProvider::ThreadData::handle_suspension()
|
||||
bool DecodedAudioProducer::ThreadData::handle_suspension()
|
||||
{
|
||||
{
|
||||
auto locker = take_lock();
|
||||
|
|
@ -268,7 +268,7 @@ bool AudioDataProvider::ThreadData::handle_suspension()
|
|||
}
|
||||
|
||||
template<typename Invokee>
|
||||
void AudioDataProvider::ThreadData::invoke_on_main_thread_while_locked(Invokee invokee)
|
||||
void DecodedAudioProducer::ThreadData::invoke_on_main_thread_while_locked(Invokee invokee)
|
||||
{
|
||||
if (m_requested_state == RequestedState::Exit)
|
||||
return;
|
||||
|
|
@ -281,13 +281,13 @@ void AudioDataProvider::ThreadData::invoke_on_main_thread_while_locked(Invokee i
|
|||
}
|
||||
|
||||
template<typename Invokee>
|
||||
void AudioDataProvider::ThreadData::invoke_on_main_thread(Invokee invokee)
|
||||
void DecodedAudioProducer::ThreadData::invoke_on_main_thread(Invokee invokee)
|
||||
{
|
||||
auto locker = take_lock();
|
||||
invoke_on_main_thread_while_locked(move(invokee));
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::dispatch_block_end_time(AudioBlock const& block)
|
||||
void DecodedAudioProducer::ThreadData::dispatch_block_end_time(AudioBlock const& block)
|
||||
{
|
||||
auto end_time = block.end_timestamp();
|
||||
if (end_time < m_duration)
|
||||
|
|
@ -299,13 +299,13 @@ void AudioDataProvider::ThreadData::dispatch_block_end_time(AudioBlock const& bl
|
|||
});
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::clear_queue()
|
||||
void DecodedAudioProducer::ThreadData::clear_queue()
|
||||
{
|
||||
m_queue.clear();
|
||||
m_queue_end_sample = 0;
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::queue_block(AudioBlock&& block)
|
||||
void DecodedAudioProducer::ThreadData::queue_block(AudioBlock&& block)
|
||||
{
|
||||
// FIXME: Specify trailing samples in the demuxer, and drop them here or in the audio decoder implementation.
|
||||
|
||||
|
|
@ -316,7 +316,7 @@ void AudioDataProvider::ThreadData::queue_block(AudioBlock&& block)
|
|||
VERIFY(!m_queue.tail().is_empty());
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::dispatch_error(DecoderError&& error)
|
||||
void DecodedAudioProducer::ThreadData::dispatch_error(DecoderError&& error)
|
||||
{
|
||||
if (error.category() == DecoderErrorCategory::Aborted)
|
||||
return;
|
||||
|
|
@ -324,13 +324,13 @@ void AudioDataProvider::ThreadData::dispatch_error(DecoderError&& error)
|
|||
m_error_handler(move(error));
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::flush_decoder()
|
||||
void DecodedAudioProducer::ThreadData::flush_decoder()
|
||||
{
|
||||
m_decoder->flush();
|
||||
m_last_sample = NumericLimits<i64>::min();
|
||||
}
|
||||
|
||||
DecoderErrorOr<void> AudioDataProvider::ThreadData::retrieve_next_block(AudioBlock& block)
|
||||
DecoderErrorOr<void> DecodedAudioProducer::ThreadData::retrieve_next_block(AudioBlock& block)
|
||||
{
|
||||
TRY(m_decoder->write_next_block(block));
|
||||
|
||||
|
|
@ -345,7 +345,7 @@ DecoderErrorOr<void> AudioDataProvider::ThreadData::retrieve_next_block(AudioBlo
|
|||
}
|
||||
|
||||
template<typename Callback>
|
||||
void AudioDataProvider::ThreadData::process_seek_on_main_thread(u32 seek_id, Callback callback)
|
||||
void DecodedAudioProducer::ThreadData::process_seek_on_main_thread(u32 seek_id, Callback callback)
|
||||
{
|
||||
m_last_processed_seek_id = seek_id;
|
||||
invoke_on_main_thread_while_locked([seek_id, callback = move(callback)](auto& self) mutable {
|
||||
|
|
@ -355,7 +355,7 @@ void AudioDataProvider::ThreadData::process_seek_on_main_thread(u32 seek_id, Cal
|
|||
});
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::resolve_seek(u32 seek_id)
|
||||
void DecodedAudioProducer::ThreadData::resolve_seek(u32 seek_id)
|
||||
{
|
||||
m_is_in_error_state = false;
|
||||
process_seek_on_main_thread(seek_id, [](auto& self) {
|
||||
|
|
@ -365,7 +365,7 @@ void AudioDataProvider::ThreadData::resolve_seek(u32 seek_id)
|
|||
});
|
||||
}
|
||||
|
||||
bool AudioDataProvider::ThreadData::handle_seek()
|
||||
bool DecodedAudioProducer::ThreadData::handle_seek()
|
||||
{
|
||||
VERIFY(m_decoder);
|
||||
|
||||
|
|
@ -470,7 +470,7 @@ bool AudioDataProvider::ThreadData::handle_seek()
|
|||
}
|
||||
}
|
||||
|
||||
void AudioDataProvider::ThreadData::push_data_and_decode_a_block()
|
||||
void DecodedAudioProducer::ThreadData::push_data_and_decode_a_block()
|
||||
{
|
||||
VERIFY(m_decoder);
|
||||
|
||||
|
|
@ -483,7 +483,7 @@ void AudioDataProvider::ThreadData::push_data_and_decode_a_block()
|
|||
});
|
||||
}
|
||||
|
||||
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Audio Data Provider: Encountered an error, waiting for a seek to start decoding again...");
|
||||
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Decoded Audio Producer: Encountered an error, waiting for a seek to start decoding again...");
|
||||
while (m_is_in_error_state) {
|
||||
if (handle_seek())
|
||||
break;
|
||||
|
|
@ -555,7 +555,7 @@ void AudioDataProvider::ThreadData::push_data_and_decode_a_block()
|
|||
}
|
||||
}
|
||||
|
||||
TimeRanges AudioDataProvider::ThreadData::buffered_time_ranges() const
|
||||
TimeRanges DecodedAudioProducer::ThreadData::buffered_time_ranges() const
|
||||
{
|
||||
return m_demuxer->buffered_time_ranges();
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
namespace Media {
|
||||
|
||||
// Retrieves coded data from a demuxer and decodes it asynchronously into audio samples to push to an AudioSink.
|
||||
class MEDIA_API AudioDataProvider final : public AtomicRefCounted<AudioDataProvider> {
|
||||
class MEDIA_API DecodedAudioProducer final : public AtomicRefCounted<DecodedAudioProducer> {
|
||||
class ThreadData;
|
||||
|
||||
public:
|
||||
|
|
@ -39,9 +39,9 @@ public:
|
|||
using SeekCompletionHandler = Function<void()>;
|
||||
using QueueIsFullHandler = Function<void()>;
|
||||
|
||||
static DecoderErrorOr<NonnullRefPtr<AudioDataProvider>> try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track);
|
||||
AudioDataProvider(NonnullRefPtr<ThreadData> const&);
|
||||
~AudioDataProvider();
|
||||
static DecoderErrorOr<NonnullRefPtr<DecodedAudioProducer>> try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track);
|
||||
DecodedAudioProducer(NonnullRefPtr<ThreadData> const&);
|
||||
~DecodedAudioProducer();
|
||||
|
||||
void set_error_handler(ErrorHandler&&);
|
||||
void set_duration_change_handler(BlockEndTimeHandler&&);
|
||||
|
|
@ -7,23 +7,23 @@
|
|||
#include <LibCore/EventLoop.h>
|
||||
#include <LibMedia/Demuxer.h>
|
||||
#include <LibMedia/FFmpeg/FFmpegVideoDecoder.h>
|
||||
#include <LibMedia/Providers/MediaTimeProvider.h>
|
||||
#include <LibMedia/MediaTimeProvider.h>
|
||||
#include <LibMedia/Sinks/VideoSink.h>
|
||||
#include <LibMedia/VideoDecoder.h>
|
||||
#include <LibMedia/VideoFrame.h>
|
||||
#include <LibThreading/Thread.h>
|
||||
|
||||
#include "VideoDataProvider.h"
|
||||
#include "DecodedVideoProducer.h"
|
||||
|
||||
namespace Media {
|
||||
|
||||
DecoderErrorOr<NonnullRefPtr<VideoDataProvider>> VideoDataProvider::try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track, RefPtr<MediaTimeProvider> const& time_provider)
|
||||
DecoderErrorOr<NonnullRefPtr<DecodedVideoProducer>> DecodedVideoProducer::try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track, RefPtr<MediaTimeProvider> const& time_provider)
|
||||
{
|
||||
TRY(demuxer->create_context_for_track(track));
|
||||
auto duration = TRY(demuxer->duration_of_track(track));
|
||||
auto thread_data = DECODER_TRY_ALLOC(try_make_ref_counted<VideoDataProvider::ThreadData>(main_thread_event_loop, demuxer, track, duration, time_provider));
|
||||
auto thread_data = DECODER_TRY_ALLOC(try_make_ref_counted<DecodedVideoProducer::ThreadData>(main_thread_event_loop, demuxer, track, duration, time_provider));
|
||||
TRY(thread_data->create_decoder());
|
||||
auto provider = DECODER_TRY_ALLOC(try_make_ref_counted<VideoDataProvider>(thread_data));
|
||||
auto producer = DECODER_TRY_ALLOC(try_make_ref_counted<DecodedVideoProducer>(thread_data));
|
||||
|
||||
auto thread = DECODER_TRY_ALLOC(Threading::Thread::try_create("Video Decoder"sv, [thread_data]() -> int {
|
||||
thread_data->wait_for_start();
|
||||
|
|
@ -38,50 +38,50 @@ DecoderErrorOr<NonnullRefPtr<VideoDataProvider>> VideoDataProvider::try_create(N
|
|||
thread->start();
|
||||
thread->detach();
|
||||
|
||||
return provider;
|
||||
return producer;
|
||||
}
|
||||
|
||||
VideoDataProvider::VideoDataProvider(NonnullRefPtr<ThreadData> const& thread_state)
|
||||
DecodedVideoProducer::DecodedVideoProducer(NonnullRefPtr<ThreadData> const& thread_state)
|
||||
: m_thread_data(thread_state)
|
||||
{
|
||||
}
|
||||
|
||||
VideoDataProvider::~VideoDataProvider()
|
||||
DecodedVideoProducer::~DecodedVideoProducer()
|
||||
{
|
||||
m_thread_data->exit();
|
||||
}
|
||||
|
||||
void VideoDataProvider::set_error_handler(ErrorHandler&& handler)
|
||||
void DecodedVideoProducer::set_error_handler(ErrorHandler&& handler)
|
||||
{
|
||||
m_thread_data->set_error_handler(move(handler));
|
||||
}
|
||||
|
||||
void VideoDataProvider::set_duration_change_handler(FrameEndTimeHandler&& handler)
|
||||
void DecodedVideoProducer::set_duration_change_handler(FrameEndTimeHandler&& handler)
|
||||
{
|
||||
m_thread_data->set_duration_change_handler(move(handler));
|
||||
}
|
||||
|
||||
void VideoDataProvider::start()
|
||||
void DecodedVideoProducer::start()
|
||||
{
|
||||
m_thread_data->start();
|
||||
}
|
||||
|
||||
void VideoDataProvider::suspend()
|
||||
void DecodedVideoProducer::suspend()
|
||||
{
|
||||
m_thread_data->suspend();
|
||||
}
|
||||
|
||||
void VideoDataProvider::resume()
|
||||
void DecodedVideoProducer::resume()
|
||||
{
|
||||
m_thread_data->resume();
|
||||
}
|
||||
|
||||
void VideoDataProvider::set_frames_queue_is_full_handler(FramesQueueIsFullHandler&& handler)
|
||||
void DecodedVideoProducer::set_frames_queue_is_full_handler(FramesQueueIsFullHandler&& handler)
|
||||
{
|
||||
m_thread_data->set_frames_queue_is_full_handler(move(handler));
|
||||
}
|
||||
|
||||
RefPtr<VideoFrame> VideoDataProvider::retrieve_frame()
|
||||
RefPtr<VideoFrame> DecodedVideoProducer::retrieve_frame()
|
||||
{
|
||||
auto locker = m_thread_data->take_lock();
|
||||
if (m_thread_data->queue().is_empty())
|
||||
|
|
@ -91,12 +91,12 @@ RefPtr<VideoFrame> VideoDataProvider::retrieve_frame()
|
|||
return result;
|
||||
}
|
||||
|
||||
void VideoDataProvider::seek(AK::Duration timestamp, SeekMode seek_mode, SeekCompletionHandler&& completion_handler)
|
||||
void DecodedVideoProducer::seek(AK::Duration timestamp, SeekMode seek_mode, SeekCompletionHandler&& completion_handler)
|
||||
{
|
||||
m_thread_data->seek(timestamp, seek_mode, move(completion_handler));
|
||||
}
|
||||
|
||||
VideoDataProvider::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track, AK::Duration duration, RefPtr<MediaTimeProvider> const& time_provider)
|
||||
DecodedVideoProducer::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track, AK::Duration duration, RefPtr<MediaTimeProvider> const& time_provider)
|
||||
: m_main_thread_event_loop(main_thread_event_loop)
|
||||
, m_demuxer(demuxer)
|
||||
, m_track(track)
|
||||
|
|
@ -105,7 +105,7 @@ VideoDataProvider::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopRefer
|
|||
{
|
||||
}
|
||||
|
||||
DecoderErrorOr<void> VideoDataProvider::ThreadData::create_decoder()
|
||||
DecoderErrorOr<void> DecodedVideoProducer::ThreadData::create_decoder()
|
||||
{
|
||||
auto codec_id = TRY(m_demuxer->get_codec_id_for_track(m_track));
|
||||
auto codec_initialization_data = TRY(m_demuxer->get_codec_initialization_data_for_track(m_track));
|
||||
|
|
@ -113,24 +113,24 @@ DecoderErrorOr<void> VideoDataProvider::ThreadData::create_decoder()
|
|||
return {};
|
||||
}
|
||||
|
||||
bool VideoDataProvider::is_blocked() const
|
||||
bool DecodedVideoProducer::is_blocked() const
|
||||
{
|
||||
return m_thread_data->is_blocked();
|
||||
}
|
||||
|
||||
TimeRanges VideoDataProvider::buffered_time_ranges() const
|
||||
TimeRanges DecodedVideoProducer::buffered_time_ranges() const
|
||||
{
|
||||
return m_thread_data->buffered_time_ranges();
|
||||
}
|
||||
|
||||
VideoDataProvider::ThreadData::~ThreadData() = default;
|
||||
DecodedVideoProducer::ThreadData::~ThreadData() = default;
|
||||
|
||||
void VideoDataProvider::ThreadData::set_error_handler(ErrorHandler&& handler)
|
||||
void DecodedVideoProducer::ThreadData::set_error_handler(ErrorHandler&& handler)
|
||||
{
|
||||
m_error_handler = move(handler);
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::start()
|
||||
void DecodedVideoProducer::ThreadData::start()
|
||||
{
|
||||
auto locker = take_lock();
|
||||
if (m_requested_state != RequestedState::None)
|
||||
|
|
@ -139,17 +139,17 @@ void VideoDataProvider::ThreadData::start()
|
|||
wake();
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::set_duration_change_handler(FrameEndTimeHandler&& handler)
|
||||
void DecodedVideoProducer::ThreadData::set_duration_change_handler(FrameEndTimeHandler&& handler)
|
||||
{
|
||||
m_duration_change_handler = move(handler);
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::set_frames_queue_is_full_handler(FramesQueueIsFullHandler&& handler)
|
||||
void DecodedVideoProducer::ThreadData::set_frames_queue_is_full_handler(FramesQueueIsFullHandler&& handler)
|
||||
{
|
||||
m_frames_queue_is_full_handler = move(handler);
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::suspend()
|
||||
void DecodedVideoProducer::ThreadData::suspend()
|
||||
{
|
||||
auto locker = take_lock();
|
||||
VERIFY(m_requested_state != RequestedState::Exit);
|
||||
|
|
@ -157,7 +157,7 @@ void VideoDataProvider::ThreadData::suspend()
|
|||
wake();
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::resume()
|
||||
void DecodedVideoProducer::ThreadData::resume()
|
||||
{
|
||||
auto locker = take_lock();
|
||||
VERIFY(m_requested_state != RequestedState::Exit);
|
||||
|
|
@ -165,24 +165,24 @@ void VideoDataProvider::ThreadData::resume()
|
|||
wake();
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::exit()
|
||||
void DecodedVideoProducer::ThreadData::exit()
|
||||
{
|
||||
auto locker = take_lock();
|
||||
m_requested_state = RequestedState::Exit;
|
||||
wake();
|
||||
}
|
||||
|
||||
VideoDataProvider::FrameQueue& VideoDataProvider::ThreadData::queue()
|
||||
DecodedVideoProducer::FrameQueue& DecodedVideoProducer::ThreadData::queue()
|
||||
{
|
||||
return m_queue;
|
||||
}
|
||||
|
||||
NonnullRefPtr<VideoFrame> VideoDataProvider::ThreadData::take_frame()
|
||||
NonnullRefPtr<VideoFrame> DecodedVideoProducer::ThreadData::take_frame()
|
||||
{
|
||||
return m_queue.dequeue();
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::seek(AK::Duration timestamp, SeekMode seek_mode, SeekCompletionHandler&& completion_handler)
|
||||
void DecodedVideoProducer::ThreadData::seek(AK::Duration timestamp, SeekMode seek_mode, SeekCompletionHandler&& completion_handler)
|
||||
{
|
||||
auto locker = take_lock();
|
||||
m_seek_id++;
|
||||
|
|
@ -193,26 +193,26 @@ void VideoDataProvider::ThreadData::seek(AK::Duration timestamp, SeekMode seek_m
|
|||
wake();
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::wait_for_start()
|
||||
void DecodedVideoProducer::ThreadData::wait_for_start()
|
||||
{
|
||||
auto locker = take_lock();
|
||||
while (m_requested_state == RequestedState::None)
|
||||
m_wait_condition.wait();
|
||||
}
|
||||
|
||||
bool VideoDataProvider::ThreadData::should_thread_exit_while_locked() const
|
||||
bool DecodedVideoProducer::ThreadData::should_thread_exit_while_locked() const
|
||||
{
|
||||
return m_requested_state == RequestedState::Exit;
|
||||
}
|
||||
|
||||
bool VideoDataProvider::ThreadData::should_thread_exit() const
|
||||
bool DecodedVideoProducer::ThreadData::should_thread_exit() const
|
||||
{
|
||||
auto locker = take_lock();
|
||||
return should_thread_exit_while_locked();
|
||||
}
|
||||
|
||||
template<typename Invokee>
|
||||
void VideoDataProvider::ThreadData::invoke_on_main_thread_while_locked(Invokee invokee)
|
||||
void DecodedVideoProducer::ThreadData::invoke_on_main_thread_while_locked(Invokee invokee)
|
||||
{
|
||||
if (m_requested_state == RequestedState::Exit)
|
||||
return;
|
||||
|
|
@ -224,7 +224,7 @@ void VideoDataProvider::ThreadData::invoke_on_main_thread_while_locked(Invokee i
|
|||
});
|
||||
}
|
||||
|
||||
bool VideoDataProvider::ThreadData::handle_suspension()
|
||||
bool DecodedVideoProducer::ThreadData::handle_suspension()
|
||||
{
|
||||
{
|
||||
auto locker = take_lock();
|
||||
|
|
@ -262,13 +262,13 @@ bool VideoDataProvider::ThreadData::handle_suspension()
|
|||
}
|
||||
|
||||
template<typename Invokee>
|
||||
void VideoDataProvider::ThreadData::invoke_on_main_thread(Invokee invokee)
|
||||
void DecodedVideoProducer::ThreadData::invoke_on_main_thread(Invokee invokee)
|
||||
{
|
||||
auto locker = take_lock();
|
||||
invoke_on_main_thread_while_locked(move(invokee));
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::dispatch_frame_end_time(CodedFrame const& frame)
|
||||
void DecodedVideoProducer::ThreadData::dispatch_frame_end_time(CodedFrame const& frame)
|
||||
{
|
||||
auto end_time = frame.timestamp() + frame.duration();
|
||||
if (end_time < m_duration)
|
||||
|
|
@ -280,12 +280,12 @@ void VideoDataProvider::ThreadData::dispatch_frame_end_time(CodedFrame const& fr
|
|||
});
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::queue_frame(NonnullRefPtr<VideoFrame> const& frame)
|
||||
void DecodedVideoProducer::ThreadData::queue_frame(NonnullRefPtr<VideoFrame> const& frame)
|
||||
{
|
||||
m_queue.enqueue(frame);
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::dispatch_error(DecoderError&& error)
|
||||
void DecodedVideoProducer::ThreadData::dispatch_error(DecoderError&& error)
|
||||
{
|
||||
if (error.category() == DecoderErrorCategory::Aborted)
|
||||
return;
|
||||
|
|
@ -294,7 +294,7 @@ void VideoDataProvider::ThreadData::dispatch_error(DecoderError&& error)
|
|||
}
|
||||
|
||||
template<typename Callback>
|
||||
void VideoDataProvider::ThreadData::process_seek_on_main_thread(u32 seek_id, Callback callback)
|
||||
void DecodedVideoProducer::ThreadData::process_seek_on_main_thread(u32 seek_id, Callback callback)
|
||||
{
|
||||
m_last_processed_seek_id = seek_id;
|
||||
invoke_on_main_thread_while_locked([seek_id, callback = move(callback)](auto& self) mutable {
|
||||
|
|
@ -304,7 +304,7 @@ void VideoDataProvider::ThreadData::process_seek_on_main_thread(u32 seek_id, Cal
|
|||
});
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::resolve_seek(u32 seek_id, AK::Duration const& timestamp)
|
||||
void DecodedVideoProducer::ThreadData::resolve_seek(u32 seek_id, AK::Duration const& timestamp)
|
||||
{
|
||||
m_is_in_error_state = false;
|
||||
process_seek_on_main_thread(seek_id, [timestamp](auto& self) {
|
||||
|
|
@ -314,7 +314,7 @@ void VideoDataProvider::ThreadData::resolve_seek(u32 seek_id, AK::Duration const
|
|||
});
|
||||
}
|
||||
|
||||
bool VideoDataProvider::ThreadData::handle_seek()
|
||||
bool DecodedVideoProducer::ThreadData::handle_seek()
|
||||
{
|
||||
VERIFY(m_decoder);
|
||||
|
||||
|
|
@ -468,7 +468,7 @@ bool VideoDataProvider::ThreadData::handle_seek()
|
|||
}
|
||||
}
|
||||
|
||||
void VideoDataProvider::ThreadData::push_data_and_decode_some_frames()
|
||||
void DecodedVideoProducer::ThreadData::push_data_and_decode_some_frames()
|
||||
{
|
||||
VERIFY(m_decoder);
|
||||
|
||||
|
|
@ -485,7 +485,7 @@ void VideoDataProvider::ThreadData::push_data_and_decode_some_frames()
|
|||
});
|
||||
}
|
||||
|
||||
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Video Data Provider: Encountered an error, waiting for a seek to start decoding again...");
|
||||
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Decoded Video Producer: Encountered an error, waiting for a seek to start decoding again...");
|
||||
while (m_is_in_error_state) {
|
||||
if (handle_seek())
|
||||
break;
|
||||
|
|
@ -562,12 +562,12 @@ void VideoDataProvider::ThreadData::push_data_and_decode_some_frames()
|
|||
}
|
||||
}
|
||||
|
||||
bool VideoDataProvider::ThreadData::is_blocked() const
|
||||
bool DecodedVideoProducer::ThreadData::is_blocked() const
|
||||
{
|
||||
return m_demuxer->is_read_blocked_for_track(m_track);
|
||||
}
|
||||
|
||||
TimeRanges VideoDataProvider::ThreadData::buffered_time_ranges() const
|
||||
TimeRanges DecodedVideoProducer::ThreadData::buffered_time_ranges() const
|
||||
{
|
||||
return m_demuxer->buffered_time_ranges();
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
namespace Media {
|
||||
|
||||
// Retrieves coded data from a demuxer and decodes it asynchronously into video frames ready for display.
|
||||
class MEDIA_API VideoDataProvider final : public AtomicRefCounted<VideoDataProvider> {
|
||||
class MEDIA_API DecodedVideoProducer final : public AtomicRefCounted<DecodedVideoProducer> {
|
||||
class ThreadData;
|
||||
|
||||
public:
|
||||
|
|
@ -38,10 +38,10 @@ public:
|
|||
using SeekCompletionHandler = Function<void(AK::Duration)>;
|
||||
using FramesQueueIsFullHandler = Function<void()>;
|
||||
|
||||
static DecoderErrorOr<NonnullRefPtr<VideoDataProvider>> try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const&, Track const&, RefPtr<MediaTimeProvider> const& = nullptr);
|
||||
static DecoderErrorOr<NonnullRefPtr<DecodedVideoProducer>> try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const&, Track const&, RefPtr<MediaTimeProvider> const& = nullptr);
|
||||
|
||||
VideoDataProvider(NonnullRefPtr<ThreadData> const&);
|
||||
~VideoDataProvider();
|
||||
DecodedVideoProducer(NonnullRefPtr<ThreadData> const&);
|
||||
~DecodedVideoProducer();
|
||||
|
||||
void set_error_handler(ErrorHandler&&);
|
||||
void set_duration_change_handler(FrameEndTimeHandler&&);
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
#include <LibMedia/Audio/Forward.h>
|
||||
#include <LibMedia/Export.h>
|
||||
#include <LibMedia/Forward.h>
|
||||
#include <LibMedia/Providers/MediaTimeProvider.h>
|
||||
#include <LibMedia/MediaTimeProvider.h>
|
||||
|
||||
namespace Media {
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ class MEDIA_API AudioSink : public virtual MediaPipelineNode {
|
|||
public:
|
||||
virtual ~AudioSink() = default;
|
||||
|
||||
virtual void set_provider(Track const&, RefPtr<AudioDataProvider> const&) = 0;
|
||||
virtual RefPtr<AudioDataProvider> provider(Track const&) const = 0;
|
||||
virtual void set_producer(Track const&, RefPtr<DecodedAudioProducer> const&) = 0;
|
||||
virtual RefPtr<DecodedAudioProducer> producer(Track const&) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
*/
|
||||
|
||||
#include <LibMedia/Demuxer.h>
|
||||
#include <LibMedia/Providers/MediaTimeProvider.h>
|
||||
#include <LibMedia/Providers/VideoDataProvider.h>
|
||||
#include <LibMedia/MediaTimeProvider.h>
|
||||
#include <LibMedia/Producers/DecodedVideoProducer.h>
|
||||
#include <LibMedia/VideoFrame.h>
|
||||
|
||||
#include "DisplayingVideoSink.h"
|
||||
|
|
@ -32,30 +32,30 @@ void DisplayingVideoSink::set_time_provider(NonnullRefPtr<MediaTimeProvider> con
|
|||
|
||||
void DisplayingVideoSink::verify_track(Track const& track) const
|
||||
{
|
||||
if (m_provider == nullptr)
|
||||
if (m_producer == nullptr)
|
||||
return;
|
||||
VERIFY(m_track.has_value());
|
||||
VERIFY(m_track.value() == track);
|
||||
}
|
||||
|
||||
void DisplayingVideoSink::set_provider(Track const& track, RefPtr<VideoDataProvider> const& provider)
|
||||
void DisplayingVideoSink::set_producer(Track const& track, RefPtr<DecodedVideoProducer> const& producer)
|
||||
{
|
||||
verify_track(track);
|
||||
m_track = track;
|
||||
m_provider = provider;
|
||||
if (provider != nullptr)
|
||||
provider->start();
|
||||
m_producer = producer;
|
||||
if (producer != nullptr)
|
||||
producer->start();
|
||||
}
|
||||
|
||||
RefPtr<VideoDataProvider> DisplayingVideoSink::provider(Track const& track) const
|
||||
RefPtr<DecodedVideoProducer> DisplayingVideoSink::producer(Track const& track) const
|
||||
{
|
||||
verify_track(track);
|
||||
return m_provider;
|
||||
return m_producer;
|
||||
}
|
||||
|
||||
DisplayingVideoSinkUpdateResult DisplayingVideoSink::update()
|
||||
{
|
||||
if (m_provider == nullptr)
|
||||
if (m_producer == nullptr)
|
||||
return DisplayingVideoSinkUpdateResult::NoChange;
|
||||
if (m_pause_updates)
|
||||
return DisplayingVideoSinkUpdateResult::NoChange;
|
||||
|
|
@ -69,9 +69,9 @@ DisplayingVideoSinkUpdateResult DisplayingVideoSink::update()
|
|||
|
||||
while (true) {
|
||||
if (!m_next_frame) {
|
||||
m_next_frame = m_provider->retrieve_frame();
|
||||
m_next_frame = m_producer->retrieve_frame();
|
||||
if (!m_next_frame) {
|
||||
if (m_provider->is_blocked() && m_on_start_buffering)
|
||||
if (m_producer->is_blocked() && m_on_start_buffering)
|
||||
m_on_start_buffering();
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ public:
|
|||
|
||||
void set_time_provider(NonnullRefPtr<MediaTimeProvider> const&);
|
||||
|
||||
virtual void set_provider(Track const&, RefPtr<VideoDataProvider> const&) override;
|
||||
RefPtr<VideoDataProvider> provider(Track const&) const override;
|
||||
virtual void set_producer(Track const&, RefPtr<DecodedVideoProducer> const&) override;
|
||||
RefPtr<DecodedVideoProducer> producer(Track const&) const override;
|
||||
|
||||
[[nodiscard]] DisplayingVideoSinkUpdateResult update();
|
||||
void prepare_current_frame_for_next_update();
|
||||
|
|
@ -45,7 +45,7 @@ private:
|
|||
void verify_track(Track const&) const;
|
||||
|
||||
NonnullRefPtr<MediaTimeProvider> m_time_provider;
|
||||
RefPtr<VideoDataProvider> m_provider;
|
||||
RefPtr<DecodedVideoProducer> m_producer;
|
||||
Optional<Track> m_track;
|
||||
|
||||
RefPtr<VideoFrame> m_next_frame;
|
||||
|
|
|
|||
|
|
@ -12,13 +12,13 @@
|
|||
|
||||
namespace Media {
|
||||
|
||||
// A consumer to be attached to a VideoDataProvider in order to receive video frames from a decoding thread.
|
||||
// A consumer to be attached to a DecodedVideoProducer in order to receive video frames from a decoding thread.
|
||||
class VideoSink : public AtomicRefCounted<VideoSink> {
|
||||
public:
|
||||
virtual ~VideoSink() = default;
|
||||
|
||||
virtual void set_provider(Track const&, RefPtr<VideoDataProvider> const&) = 0;
|
||||
virtual RefPtr<VideoDataProvider> provider(Track const&) const = 0;
|
||||
virtual void set_producer(Track const&, RefPtr<DecodedVideoProducer> const&) = 0;
|
||||
virtual RefPtr<DecodedVideoProducer> producer(Track const&) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
include(audio)
|
||||
|
||||
set(TEST_SOURCES
|
||||
TestAudioDataProvider.cpp
|
||||
TestCICP.cpp
|
||||
TestDataProviders.cpp
|
||||
TestDataProducers.cpp
|
||||
TestDecodedAudioProducer.cpp
|
||||
TestFFmpegAudioNormalization.cpp
|
||||
TestFFmpegDemuxer.cpp
|
||||
TestH264Decode.cpp
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@
|
|||
#include <LibMedia/Containers/Matroska/MatroskaDemuxer.h>
|
||||
#include <LibMedia/FFmpeg/FFmpegDemuxer.h>
|
||||
#include <LibMedia/IncrementallyPopulatedStream.h>
|
||||
#include <LibMedia/Providers/AudioDataProvider.h>
|
||||
#include <LibMedia/Providers/MediaTimeProvider.h>
|
||||
#include <LibMedia/Providers/VideoDataProvider.h>
|
||||
#include <LibMedia/MediaTimeProvider.h>
|
||||
#include <LibMedia/Producers/DecodedAudioProducer.h>
|
||||
#include <LibMedia/Producers/DecodedVideoProducer.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
|
||||
// The following tests attempt to reproduce a race condition in AudioDataProvider and VideoDataProvider
|
||||
// The following tests attempt to reproduce a race condition in DecodedAudioProducer and DecodedVideoProducer
|
||||
// where rapidly transitioning through states None -> Suspended -> Exit can cause the decoder thread to
|
||||
// continue with a null decoder.
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ static NonnullRefPtr<Media::Demuxer> create_demuxer(NonnullRefPtr<Media::Increme
|
|||
|
||||
static constexpr size_t iterations = 100;
|
||||
|
||||
TEST_CASE(audio_provider_suspend_then_exit)
|
||||
TEST_CASE(audio_producer_suspend_then_exit)
|
||||
{
|
||||
Core::EventLoop loop;
|
||||
|
||||
|
|
@ -46,14 +46,14 @@ TEST_CASE(audio_provider_suspend_then_exit)
|
|||
auto track = TRY_OR_FAIL(demuxer->get_preferred_track_for_type(Media::TrackType::Audio));
|
||||
VERIFY(track.has_value());
|
||||
|
||||
auto provider = TRY_OR_FAIL(Media::AudioDataProvider::try_create(Core::EventLoop::current_weak(), demuxer, track.release_value()));
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedAudioProducer::try_create(Core::EventLoop::current_weak(), demuxer, track.release_value()));
|
||||
|
||||
provider->suspend();
|
||||
producer->suspend();
|
||||
MUST(Core::System::sleep_ms(1));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(video_provider_suspend_then_exit)
|
||||
TEST_CASE(video_producer_suspend_then_exit)
|
||||
{
|
||||
Core::EventLoop loop;
|
||||
|
||||
|
|
@ -63,14 +63,14 @@ TEST_CASE(video_provider_suspend_then_exit)
|
|||
auto track = TRY_OR_FAIL(demuxer->get_preferred_track_for_type(Media::TrackType::Video));
|
||||
VERIFY(track.has_value());
|
||||
|
||||
auto provider = TRY_OR_FAIL(Media::VideoDataProvider::try_create(Core::EventLoop::current_weak(), demuxer, track.release_value()));
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedVideoProducer::try_create(Core::EventLoop::current_weak(), demuxer, track.release_value()));
|
||||
|
||||
provider->suspend();
|
||||
producer->suspend();
|
||||
MUST(Core::System::sleep_ms(1));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(audio_provider_start_suspend_then_exit)
|
||||
TEST_CASE(audio_producer_start_suspend_then_exit)
|
||||
{
|
||||
Core::EventLoop loop;
|
||||
|
||||
|
|
@ -80,16 +80,16 @@ TEST_CASE(audio_provider_start_suspend_then_exit)
|
|||
auto track = TRY_OR_FAIL(demuxer->get_preferred_track_for_type(Media::TrackType::Audio));
|
||||
VERIFY(track.has_value());
|
||||
|
||||
auto provider = TRY_OR_FAIL(Media::AudioDataProvider::try_create(Core::EventLoop::current_weak(), demuxer, track.release_value()));
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedAudioProducer::try_create(Core::EventLoop::current_weak(), demuxer, track.release_value()));
|
||||
|
||||
provider->start();
|
||||
producer->start();
|
||||
MUST(Core::System::sleep_ms(1));
|
||||
provider->suspend();
|
||||
producer->suspend();
|
||||
MUST(Core::System::sleep_ms(1));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(video_provider_start_suspend_then_exit)
|
||||
TEST_CASE(video_producer_start_suspend_then_exit)
|
||||
{
|
||||
Core::EventLoop loop;
|
||||
|
||||
|
|
@ -99,16 +99,16 @@ TEST_CASE(video_provider_start_suspend_then_exit)
|
|||
auto track = TRY_OR_FAIL(demuxer->get_preferred_track_for_type(Media::TrackType::Video));
|
||||
VERIFY(track.has_value());
|
||||
|
||||
auto provider = TRY_OR_FAIL(Media::VideoDataProvider::try_create(Core::EventLoop::current_weak(), demuxer, track.release_value()));
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedVideoProducer::try_create(Core::EventLoop::current_weak(), demuxer, track.release_value()));
|
||||
|
||||
provider->start();
|
||||
producer->start();
|
||||
MUST(Core::System::sleep_ms(1));
|
||||
provider->suspend();
|
||||
producer->suspend();
|
||||
MUST(Core::System::sleep_ms(1));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(audio_provider_underspecified_5_1_channel_map)
|
||||
TEST_CASE(audio_producer_underspecified_5_1_channel_map)
|
||||
{
|
||||
Core::EventLoop loop;
|
||||
|
||||
|
|
@ -117,15 +117,15 @@ TEST_CASE(audio_provider_underspecified_5_1_channel_map)
|
|||
auto tracks = TRY_OR_FAIL(demuxer->get_tracks_for_type(Media::TrackType::Audio));
|
||||
VERIFY(!tracks.is_empty());
|
||||
|
||||
auto provider = TRY_OR_FAIL(Media::AudioDataProvider::try_create(Core::EventLoop::current_weak(), demuxer, tracks[0]));
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedAudioProducer::try_create(Core::EventLoop::current_weak(), demuxer, tracks[0]));
|
||||
|
||||
provider->start();
|
||||
producer->start();
|
||||
|
||||
auto time_limit = AK::Duration::from_seconds(1);
|
||||
auto start_time = MonotonicTime::now_coarse();
|
||||
|
||||
while (true) {
|
||||
auto block = provider->retrieve_block();
|
||||
auto block = producer->retrieve_block();
|
||||
if (!block.is_empty()) {
|
||||
EXPECT_EQ(block.channel_count(), 6);
|
||||
EXPECT_EQ(block.sample_specification().channel_map(), Audio::ChannelMap::surround_5_1());
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
#include <LibCore/EventLoop.h>
|
||||
#include <LibMedia/FFmpeg/FFmpegDemuxer.h>
|
||||
#include <LibMedia/IncrementallyPopulatedStream.h>
|
||||
#include <LibMedia/Providers/AudioDataProvider.h>
|
||||
#include <LibMedia/Producers/DecodedAudioProducer.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
|
||||
template<typename Integer>
|
||||
|
|
@ -78,17 +78,17 @@ static void decode_and_expect()
|
|||
|
||||
auto tracks = TRY_OR_FAIL(demuxer->get_tracks_for_type(Media::TrackType::Audio));
|
||||
VERIFY(!tracks.is_empty());
|
||||
auto provider = TRY_OR_FAIL(Media::AudioDataProvider::try_create(Core::EventLoop::current_weak(), demuxer, tracks[0]));
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedAudioProducer::try_create(Core::EventLoop::current_weak(), demuxer, tracks[0]));
|
||||
|
||||
bool reached_end_of_stream = false;
|
||||
provider->set_error_handler([&](Media::DecoderError&& error) {
|
||||
producer->set_error_handler([&](Media::DecoderError&& error) {
|
||||
if (error.category() == Media::DecoderErrorCategory::EndOfStream) {
|
||||
reached_end_of_stream = true;
|
||||
return;
|
||||
}
|
||||
FAIL("An error occurred while decoding generated WAV data.");
|
||||
});
|
||||
provider->start();
|
||||
producer->start();
|
||||
|
||||
bool saw_negative_full_scale_sample = false;
|
||||
bool saw_positive_peak_sample = false;
|
||||
|
|
@ -96,7 +96,7 @@ static void decode_and_expect()
|
|||
|
||||
MonotonicTime deadline = MonotonicTime::now_coarse() + AK::Duration::from_seconds(1);
|
||||
while (MonotonicTime::now_coarse() < deadline) {
|
||||
auto block = provider->retrieve_block();
|
||||
auto block = producer->retrieve_block();
|
||||
if (block.is_empty()) {
|
||||
if (reached_end_of_stream)
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#include <LibMedia/Containers/Matroska/Reader.h>
|
||||
#include <LibMedia/Demuxer.h>
|
||||
#include <LibMedia/FFmpeg/FFmpegDemuxer.h>
|
||||
#include <LibMedia/Providers/AudioDataProvider.h>
|
||||
#include <LibMedia/Producers/DecodedAudioProducer.h>
|
||||
#include <LibMedia/VideoDecoder.h>
|
||||
#include <LibMedia/VideoFrame.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
|
|
@ -82,17 +82,17 @@ static inline void decode_audio(StringView path, u32 sample_rate, u8 channel_cou
|
|||
}());
|
||||
auto tracks = TRY_OR_FAIL(demuxer->get_tracks_for_type(Media::TrackType::Audio));
|
||||
VERIFY(!tracks.is_empty());
|
||||
auto provider = TRY_OR_FAIL(Media::AudioDataProvider::try_create(Core::EventLoop::current_weak(), demuxer, tracks[0]));
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedAudioProducer::try_create(Core::EventLoop::current_weak(), demuxer, tracks[0]));
|
||||
|
||||
auto reached_end = false;
|
||||
provider->set_error_handler([&](Media::DecoderError&& error) {
|
||||
producer->set_error_handler([&](Media::DecoderError&& error) {
|
||||
if (error.category() == Media::DecoderErrorCategory::EndOfStream) {
|
||||
reached_end = true;
|
||||
return;
|
||||
}
|
||||
FAIL("An error occurred while decoding.");
|
||||
});
|
||||
provider->start();
|
||||
producer->start();
|
||||
|
||||
auto time_limit = AK::Duration::from_seconds(1);
|
||||
auto start_time = MonotonicTime::now_coarse();
|
||||
|
|
@ -101,7 +101,7 @@ static inline void decode_audio(StringView path, u32 sample_rate, u8 channel_cou
|
|||
size_t sample_count = 0;
|
||||
|
||||
while (true) {
|
||||
auto block = provider->retrieve_block();
|
||||
auto block = producer->retrieve_block();
|
||||
if (block.is_empty()) {
|
||||
if (reached_end)
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
TEST_CASE(44_1Khz_stereo)
|
||||
{
|
||||
// FIXME: 96 samples are marked to be discarded, but AudioDataProvider currently is not aware of this.
|
||||
// FIXME: 96 samples are marked to be discarded, but DecodedAudioProducer currently is not aware of this.
|
||||
decode_audio("vorbis/44_1Khz_stereo.ogg"sv, 44100, 2, 352800 + 96);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue