#include "mojo/public/cpp/bindings/remote.h"
#include "platform/scheduler/public/thread.h"
#include "services/elementary_media_stream_source/public/cpp/logger.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/scheduler/public/main_thread.h"
namespace {
+template <typename T>
+class DeleteOnTaskRunner {
+ public:
+ explicit DeleteOnTaskRunner(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
+ : task_runner_(task_runner) {}
+
+ void operator()(T* obj) { task_runner_->DeleteSoon(FROM_HERE, obj); }
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
std::tuple<worker_thread::PendingDataStreamSrcInterfaces,
DemuxerDispatcher::PendingDataStreamSinkInterfaces>
CreateDataStream() {
} // anonymous namespace
+class DemuxerDispatcher::WorkerDemuxerImplHolder {
+ public:
+ template <typename T>
+ explicit WorkerDemuxerImplHolder(
+ std::unique_ptr<T>&& impl,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
+ : impl_(std::unique_ptr<T, DeleteOnTaskRunner<T>>{
+ impl.release(), DeleteOnTaskRunner<T>{task_runner}}) {}
+
+ private:
+ absl::variant<
+ std::unique_ptr<worker_thread::DataStreamDemuxerImpl,
+ DeleteOnTaskRunner<worker_thread::DataStreamDemuxerImpl>>,
+ std::unique_ptr<
+ worker_thread::MediaStreamDemuxerImpl,
+ DeleteOnTaskRunner<worker_thread::MediaStreamDemuxerImpl>>,
+ std::unique_ptr<worker_thread::MsDecodingStream,
+ DeleteOnTaskRunner<worker_thread::MsDecodingStream>>>
+ impl_;
+}; // class WorkerDemuxerImplHolder
+
// static
std::shared_ptr<DemuxerDispatcher> DemuxerDispatcher::Create(
PipelineMode pipeline_mode,
}
if (pipeline_mode.demuxer_mode == DemuxerMode::kDataStream) {
- SetWorkerClients<worker_thread::DataStreamDemuxerImpl>(
- pipeline_mode, demuxer_dispatcher,
- std::move(maybe_pending_data_stream_src),
- std::make_shared<worker_thread::DataStreamDemuxerImpl>(params));
+ demuxer_dispatcher->SetWorkerClients<worker_thread::DataStreamDemuxerImpl>(
+ pipeline_mode, std::move(maybe_pending_data_stream_src),
+ std::make_unique<worker_thread::DataStreamDemuxerImpl>(params));
} else if (pipeline_mode.latency_mode == LatencyMode::kNormal) {
- SetWorkerClients<worker_thread::MediaStreamDemuxerImpl>(
- pipeline_mode, demuxer_dispatcher,
- std::move(maybe_pending_data_stream_src),
- std::make_shared<worker_thread::MediaStreamDemuxerImpl>(params));
+ demuxer_dispatcher->SetWorkerClients<worker_thread::MediaStreamDemuxerImpl>(
+ pipeline_mode, std::move(maybe_pending_data_stream_src),
+ std::make_unique<worker_thread::MediaStreamDemuxerImpl>(params));
} else {
auto worker_demuxer_impl =
- std::make_shared<worker_thread::MsDecodingStream>(params);
- auto weak_ms_decoding_stream =
- std::weak_ptr<worker_thread::MsDecodingStream>{worker_demuxer_impl};
- SetWorkerClients<worker_thread::MsDecodingStream>(
- pipeline_mode, demuxer_dispatcher,
- std::move(maybe_pending_data_stream_src),
+ std::make_unique<worker_thread::MsDecodingStream>(params);
+ demuxer_dispatcher->SetWorkerClients<worker_thread::MsDecodingStream>(
+ pipeline_mode, std::move(maybe_pending_data_stream_src),
std::move(worker_demuxer_impl));
blink::Thread::MainThread()->GetDeprecatedTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
&GetGpuFactoriesOnBlinkMainThread,
- base::BindPostTask(
- demuxer_dispatcher->GetWorkerThreadTaskRunner(),
- base::BindOnce(
- [](std::weak_ptr<worker_thread::MsDecodingStream>
- weak_ms_decoding_stream,
- media::GpuVideoAcceleratorFactories* gpu_factories) {
- if (auto ms_decoding_stream =
- weak_ms_decoding_stream.lock()) {
- ms_decoding_stream->SetGpuFactories(gpu_factories);
- }
- },
- std::move(weak_ms_decoding_stream)))));
+ base::BindOnce(
+ [](std::weak_ptr<DemuxerDispatcher> maybe_dispatcher,
+ media::GpuVideoAcceleratorFactories* gpu_factories) {
+ auto dispatcher = maybe_dispatcher.lock();
+
+ if (!dispatcher)
+ return;
+
+ dispatcher->DispatchTask(&WorkerThreadClient::SetGpuFactories,
+ gpu_factories);
+ },
+ std::weak_ptr<DemuxerDispatcher>(demuxer_dispatcher))));
}
return demuxer_dispatcher;
DemuxerDispatcher::~DemuxerDispatcher() {
EMSS_DEBUG() << "Destructing object";
- if (!HasClient<WorkerLifecycleObserver>())
- return;
-
- DispatchTask(&WorkerLifecycleObserver::OnDispatcherDisconnected);
+ if (HasClient<WorkerLifecycleObserver>())
+ DispatchTask(&WorkerLifecycleObserver::OnDispatcherDisconnected);
}
DemuxerDispatcher::DemuxerDispatcher(
worker_thread_task_runner)
: Dispatcher(control_thread_task_runner),
pending_data_stream_sink_(std::move(pending_data_stream_sink)),
- worker_thread_task_runner_(worker_thread_task_runner) {
+ worker_thread_task_runner_(worker_thread_task_runner),
+ worker_demuxer_impl_holder_(nullptr) {
EMSS_DEBUG() << "Constructing object";
}
std::move(on_emss_initialized));
}
+std::unique_ptr<DemuxerDispatcher::WorkerDemuxerImplHolder>
+DemuxerDispatcher::WrapDemuxerWorkerImpl(
+ std::unique_ptr<worker_thread::DataStreamDemuxerImpl>&& impl) {
+ return std::make_unique<WorkerDemuxerImplHolder>(std::move(impl),
+ worker_thread_task_runner_);
+}
+
+std::unique_ptr<DemuxerDispatcher::WorkerDemuxerImplHolder>
+DemuxerDispatcher::WrapDemuxerWorkerImpl(
+ std::unique_ptr<worker_thread::MediaStreamDemuxerImpl>&& impl) {
+ return std::make_unique<WorkerDemuxerImplHolder>(std::move(impl),
+ worker_thread_task_runner_);
+}
+
+std::unique_ptr<DemuxerDispatcher::WorkerDemuxerImplHolder>
+DemuxerDispatcher::WrapDemuxerWorkerImpl(
+ std::unique_ptr<worker_thread::MsDecodingStream>&& impl) {
+ return std::make_unique<WorkerDemuxerImplHolder>(std::move(impl),
+ worker_thread_task_runner_);
+}
+
} // namespace any_thread
} // namespace elementary_media_stream_source
#include <atomic>
#include <memory>
+#include <optional>
#include <type_traits>
#include <utility>
} // namespace media_thread
namespace worker_thread {
+class DataStreamDemuxerImpl;
class DemuxerDispatcherClient;
+class MediaStreamDemuxerImpl;
+class MsDecodingStream;
class PlatformDemuxerAdapterClient;
class SourceImpl;
} // namespace worker_thread
} // namespace elementary_media_stream_source
} // namespace content
-namespace elementary_media_stream_source {
-template <>
-struct ClientTraits<::content::elementary_media_stream_source::media_thread::
- PlatformDemuxerAdapter> {
- public:
- using PointerType = ::content::elementary_media_stream_source::media_thread::
- PlatformDemuxerAdapter*;
-};
-} // namespace elementary_media_stream_source
-
namespace content {
namespace elementary_media_stream_source {
namespace any_thread {
}
private:
+ // Hides implementation of worker thread demuxer impl. Required, because it
+ // needs class implementation, not only forward declaration.
+ class WorkerDemuxerImplHolder;
+
template <typename DemuxerImplT>
static void SetAnyClients(
const std::shared_ptr<DemuxerDispatcher>& demuxer_dispatcher,
std::move(control_demuxer_impl));
}
+ std::unique_ptr<WorkerDemuxerImplHolder> WrapDemuxerWorkerImpl(
+ std::unique_ptr<worker_thread::DataStreamDemuxerImpl>&& impl);
+ std::unique_ptr<WorkerDemuxerImplHolder> WrapDemuxerWorkerImpl(
+ std::unique_ptr<worker_thread::MediaStreamDemuxerImpl>&& impl);
+ std::unique_ptr<WorkerDemuxerImplHolder> WrapDemuxerWorkerImpl(
+ std::unique_ptr<worker_thread::MsDecodingStream>&& impl);
+
template <typename DemuxerImplT>
- static void SetWorkerClients(
- PipelineMode pipeline_mode,
- const std::shared_ptr<DemuxerDispatcher>& demuxer_dispatcher,
- worker_thread::PendingDataStreamSrcInterfaces
- maybe_pending_data_stream_src,
- std::shared_ptr<DemuxerImplT>&& worker_demuxer_impl) {
- demuxer_dispatcher->SetClient<WorkerThreadClient>(worker_demuxer_impl);
- demuxer_dispatcher->SetClient<WorkerThreadDemuxerAdapterClient>(
- worker_demuxer_impl);
+ void SetWorkerClients(PipelineMode pipeline_mode,
+ worker_thread::PendingDataStreamSrcInterfaces
+ maybe_pending_data_stream_src,
+ std::unique_ptr<DemuxerImplT> worker_demuxer_impl) {
+ SetClient<WorkerThreadClient>(worker_demuxer_impl->GetWeakPtr());
+ SetClient<WorkerThreadDemuxerAdapterClient>(
+ worker_demuxer_impl->GetWeakPtr());
if constexpr (std::is_base_of_v<WorkerLifecycleObserver, DemuxerImplT>) {
- demuxer_dispatcher->SetClient<WorkerLifecycleObserver>(
- std::move(worker_demuxer_impl));
- demuxer_dispatcher->DispatchTask(
- &WorkerLifecycleObserver::OnDispatcherConnected,
- std::move(maybe_pending_data_stream_src));
+ SetClient<WorkerLifecycleObserver>(
+ std::move(worker_demuxer_impl->GetWeakPtr()));
+ DispatchTask(&WorkerLifecycleObserver::OnDispatcherConnected,
+ std::move(maybe_pending_data_stream_src));
}
+
+ worker_demuxer_impl_holder_ =
+ WrapDemuxerWorkerImpl(std::move(worker_demuxer_impl));
};
std::tuple<std::shared_ptr<AnyAudioMediaStream>,
std::shared_ptr<AnyVideoMediaStream>,
std::shared_ptr<ControlThreadClient>,
std::shared_ptr<ControlThreadDemuxerAdapterClient>,
- std::shared_ptr<WorkerLifecycleObserver>,
- std::shared_ptr<WorkerThreadClient>,
- std::shared_ptr<WorkerThreadDemuxerAdapterClient>,
+ base::WeakPtr<WorkerLifecycleObserver>,
+ base::WeakPtr<WorkerThreadClient>,
+ base::WeakPtr<WorkerThreadDemuxerAdapterClient>,
media_thread::PlatformDemuxerAdapter*>
clients_;
std::optional<PendingDataStreamSinkInterfaces> pending_data_stream_sink_;
scoped_refptr<base::SingleThreadTaskRunner> worker_thread_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> media_thread_task_runner_;
+
+ std::unique_ptr<WorkerDemuxerImplHolder> worker_demuxer_impl_holder_;
};
} // namespace any_thread
"demuxer.cc",
"demuxer.h",
"demuxer_client.h",
+ "demuxer_dispatcher_client.cc",
"demuxer_dispatcher_client.h",
"demuxer_dispatcher_lifecycle_observer.h",
"demuxer_stream_impl.h",
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
+#include "base/memory/weak_ptr.h"
#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_tools.h"
#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_types.h"
#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_dispatcher.h"
EMSS_DEBUG() << "Destructing object";
}
+base::WeakPtr<DataStreamDemuxerImpl> DataStreamDemuxerImpl::GetWeakPtr() {
+ EMSS_VERBOSE();
+
+ return weak_ptr_factory_.GetMutableWeakPtr();
+}
+
//////////////////// DemuxerDispatcherLifecycleObserver ////////////////////
void DataStreamDemuxerImpl::OnDispatcherConnected(
gfx::Size{tbm_buffer_handle.width, tbm_buffer_handle.height},
base::TimeDelta(), tbm_buffer_handle);
- auto weak_this = std::weak_ptr<DataStreamDemuxerImpl>(shared_from_this());
auto release_cb_runner =
base::ScopedClosureRunner{media::BindToCurrentLoop(base::BindOnce(
- [](const std::weak_ptr<DataStreamDemuxerImpl>& weak_demuxer_impl,
+ [](const base::WeakPtr<DataStreamDemuxerImpl>& maybe_demuxer_impl,
uint64_t packet_id) {
- auto demuxer_impl = weak_demuxer_impl.lock();
-
- if (!demuxer_impl) {
+ if (!maybe_demuxer_impl) {
EMSS_DEBUG_NO_INSTANCE();
return;
}
- demuxer_impl->ReleaseVideoTexture(packet_id);
+ maybe_demuxer_impl->ReleaseVideoTexture(packet_id);
},
- std::move(weak_this), packet_id))};
+ weak_ptr_factory_.GetWeakPtr(), packet_id))};
if (!video_frame) {
LOG(ERROR) << "Creating video frame failed";
//////////////////// Demuxer ///////////////////
-std::shared_ptr<AppendHost> DataStreamDemuxerImpl::GetAppendHost(TrackType) {
+base::WeakPtr<AppendHost> DataStreamDemuxerImpl::GetAppendHost(TrackType) {
EMSS_DEBUG();
- return shared_from_this();
+ return weak_ptr_factory_.GetWeakPtr();
}
void DataStreamDemuxerImpl::OnBufferedTimeRangesChanged(
base::OnceClosure on_source_registered) {
EMSS_DEBUG();
- client->RegisterDemuxer(shared_from_this());
+ client->RegisterDemuxer(weak_ptr_factory_.GetWeakPtr());
client_ = std::move(client);
std::move(on_source_registered).Run();
#include <vector>
#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_types.h"
#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_dispatcher.h"
class AppendClient;
// Demuxer implementation for MediaResource::Type::ELEMENTARY_STREAM.
-class DataStreamDemuxerImpl
- : public AppendHost,
- public DataStreamClient,
- public Demuxer,
- public DemuxerDispatcherClient,
- public PlatformDemuxerAdapterClient,
- public DemuxerDispatcherLifecycleObserver,
- public std::enable_shared_from_this<DataStreamDemuxerImpl> {
+class DataStreamDemuxerImpl : public AppendHost,
+ public DataStreamClient,
+ public Demuxer,
+ public DemuxerDispatcherClient,
+ public PlatformDemuxerAdapterClient,
+ public DemuxerDispatcherLifecycleObserver {
public:
using BackendError = ::elementary_media_stream_source::mojom::BackendError;
~DataStreamDemuxerImpl() override;
+ // Note: weak ptr is valid on worker_thread
+ base::WeakPtr<DataStreamDemuxerImpl> GetWeakPtr();
+
// DemuxerDispatcherLifecycleObserver
void OnDispatcherConnected(
PendingDataStreamSrcInterfaces pending_data_stream) override;
void OnClosedCaptions(const std::vector<uint8_t>& closed_captions) override;
// Demuxer
- std::shared_ptr<AppendHost> GetAppendHost(TrackType) override;
+ base::WeakPtr<AppendHost> GetAppendHost(TrackType) override;
void OnBufferedTimeRangesChanged(media::Ranges<base::TimeDelta>&&) override;
void OnInitialConfigReady(const MaybeAudioConfig&,
const MaybeVideoConfig&) override;
PipelineMode pipeline_mode_;
std::shared_ptr<any_thread::LockableDemuxerState> state_;
std::weak_ptr<VideoTextureClient> video_texture_client_;
+
+ base::WeakPtrFactory<DataStreamDemuxerImpl> weak_ptr_factory_{this};
};
} // namespace worker_thread
class Demuxer {
public:
virtual ~Demuxer() = default;
- virtual std::shared_ptr<AppendHost> GetAppendHost(TrackType) = 0;
+ virtual base::WeakPtr<AppendHost> GetAppendHost(TrackType) = 0;
virtual void OnBufferedTimeRangesChanged(
media::Ranges<base::TimeDelta>&&) = 0;
virtual void OnInitialConfigReady(const MaybeAudioConfig&,
class DemuxerClient {
public:
virtual ~DemuxerClient() = default;
- virtual void RegisterDemuxer(std::shared_ptr<Demuxer>) = 0;
+ virtual void RegisterDemuxer(base::WeakPtr<Demuxer>) = 0;
protected:
DemuxerClient() = default;
--- /dev/null
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/demuxer_dispatcher_client.h"
+
+#include "services/elementary_media_stream_source/public/cpp/logger.h"
+
+namespace content {
+namespace elementary_media_stream_source {
+namespace worker_thread {
+
+DemuxerDispatcherClient::DemuxerDispatcherClient() = default;
+
+DemuxerDispatcherClient::~DemuxerDispatcherClient() = default;
+
+void DemuxerDispatcherClient::SetGpuFactories(
+ media::GpuVideoAcceleratorFactories*) {
+ EMSS_LOG_ASSERT(false) << "Not implemented! Should never be called.";
+}
+
+} // namespace worker_thread
+} // namespace elementary_media_stream_source
+} // namespace content
#include "media/base/demuxer_stream.h"
#include "media/base/video_frame.h"
+namespace media {
+class GpuVideoAcceleratorFactories;
+} // namespace media
+
namespace content {
namespace elementary_media_stream_source {
// `DemuxerDispatcher` keeps `DemuxerImpl` alive through this interface.
class DemuxerDispatcherClient : public EnableDispatcher {
public:
- virtual ~DemuxerDispatcherClient() = default;
+ virtual ~DemuxerDispatcherClient();
virtual void OnPipelineClosed() = 0;
virtual void OnPipelineResuming() = 0;
virtual void OnReadRequested(TrackType) = 0;
virtual void OnSeekDone(base::TimeDelta new_time, uint32_t session_id) = 0;
virtual void OnSessionIdChange(uint32_t session_id) = 0;
+ virtual void SetGpuFactories(
+ media::GpuVideoAcceleratorFactories* gpu_factories);
protected:
- DemuxerDispatcherClient() = default;
+ DemuxerDispatcherClient();
};
} // namespace worker_thread
EMSS_DEBUG() << "Destructing object";
}
+base::WeakPtr<MediaStreamDemuxerImpl> MediaStreamDemuxerImpl::GetWeakPtr() {
+ EMSS_VERBOSE();
+
+ return weak_ptr_factory_.GetMutableWeakPtr();
+}
+
//////////////////// Demuxer ////////////////////
-std::shared_ptr<AppendHost> MediaStreamDemuxerImpl::GetAppendHost(TrackType) {
+base::WeakPtr<AppendHost> MediaStreamDemuxerImpl::GetAppendHost(TrackType) {
EMSS_DEBUG();
- return shared_from_this();
+ return weak_ptr_factory_.GetMutableWeakPtr();
}
void MediaStreamDemuxerImpl::OnBufferedTimeRangesChanged(
base::OnceClosure on_source_registered) {
EMSS_DEBUG();
- client->RegisterDemuxer(shared_from_this());
+ client->RegisterDemuxer(weak_ptr_factory_.GetMutableWeakPtr());
client_ = std::move(client);
std::move(on_source_registered).Run();
class AppendClient;
// Demuxer implementation for MediaResource::Type::STREAM.
-class MediaStreamDemuxerImpl
- : public Demuxer,
- public DemuxerDispatcherClient,
- public AppendHost,
- public PlatformDemuxerAdapterClient,
- public std::enable_shared_from_this<MediaStreamDemuxerImpl> {
+class MediaStreamDemuxerImpl : public Demuxer,
+ public DemuxerDispatcherClient,
+ public AppendHost,
+ public PlatformDemuxerAdapterClient {
public:
using BackendError = ::elementary_media_stream_source::mojom::BackendError;
~MediaStreamDemuxerImpl() override;
+ // Note: weak ptr is valid on worker_thread
+ base::WeakPtr<MediaStreamDemuxerImpl> GetWeakPtr();
+
// Demuxer
- std::shared_ptr<AppendHost> GetAppendHost(TrackType) override;
+ base::WeakPtr<AppendHost> GetAppendHost(TrackType) override;
void OnBufferedTimeRangesChanged(media::Ranges<base::TimeDelta>&&) override;
void OnInitialConfigReady(const MaybeAudioConfig&,
const MaybeVideoConfig&) override;
PipelineMode pipeline_mode_;
// std::shared_ptr<any_thread::LockableDemuxerState> state_;
// std::weak_ptr<VideoTextureClient> video_texture_client_;
+
+ base::WeakPtrFactory<MediaStreamDemuxerImpl> weak_ptr_factory_{this};
};
} // namespace worker_thread
}
}
+base::WeakPtr<MsDecodingStream> MsDecodingStream::GetWeakPtr() {
+ EMSS_VERBOSE();
+
+ return weak_ptr_factory_.GetMutableWeakPtr();
+}
+
void MsDecodingStream::SetGpuFactories(
media::GpuVideoAcceleratorFactories* gpu_factories) {
EMSS_DEBUG() << gpu_factories;
decoder_factory_, dispatcher_.lock()->GetControlThreadTaskRunner()));
}
-std::shared_ptr<AppendHost> MsDecodingStream::GetAppendHost(TrackType) {
+base::WeakPtr<AppendHost> MsDecodingStream::GetAppendHost(TrackType) {
EMSS_VERBOSE();
- return shared_from_this();
+ return weak_ptr_factory_.GetMutableWeakPtr();
}
void MsDecodingStream::OnBufferedTimeRangesChanged(
base::OnceClosure on_source_registered) {
EMSS_DEBUG();
- client->RegisterDemuxer(shared_from_this());
+ client->RegisterDemuxer(weak_ptr_factory_.GetMutableWeakPtr());
std::move(on_source_registered).Run();
}
class MsDecodingStream : public Demuxer,
public DemuxerDispatcherClient,
public AppendHost,
- public PlatformDemuxerAdapterClient,
- public std::enable_shared_from_this<MsDecodingStream> {
+ public PlatformDemuxerAdapterClient {
public:
using BackendError = ::elementary_media_stream_source::mojom::BackendError;
using CreateAudioDecodersCb =
~MsDecodingStream() override;
void EmitError(BackendError backend_error, const std::string& message);
- void SetGpuFactories(media::GpuVideoAcceleratorFactories* gpu_factories);
+
+ // Note: weak ptr is valid on worker_thread
+ base::WeakPtr<MsDecodingStream> GetWeakPtr();
// Demuxer:
void SetMediaStreamDecoderFactory(
base::WeakPtr<media::DecoderFactory>) override;
- std::shared_ptr<AppendHost> GetAppendHost(TrackType) override;
+ base::WeakPtr<AppendHost> GetAppendHost(TrackType) override;
void OnBufferedTimeRangesChanged(media::Ranges<base::TimeDelta>&&) override;
void OnInitialConfigReady(const MaybeAudioConfig&,
const MaybeVideoConfig&) override;
void OnReadRequested(TrackType) override;
void OnSeekDone(base::TimeDelta new_time, uint32_t session_id) override;
void OnSessionIdChange(uint32_t session_id) override;
+ void SetGpuFactories(
+ media::GpuVideoAcceleratorFactories* gpu_factories) override;
// AppendHost:
void NotifyFramerateSet(
std::weak_ptr<any_thread::DemuxerDispatcher> dispatcher_;
media::GpuVideoAcceleratorFactories* gpu_factories_{nullptr};
std::unique_ptr<media::MediaLog> media_log_;
+
+ base::WeakPtrFactory<MsDecodingStream> weak_ptr_factory_{this};
};
} // namespace worker_thread
virtual const media::Ranges<base::TimeDelta>& GetBufferedRanges() const = 0;
virtual std::shared_ptr<VideoTextureClient> GetVideoTextureClient() = 0;
virtual TrackType Type() const = 0;
- virtual void SetAppendHost(std::shared_ptr<AppendHost>) = 0;
+ virtual void SetAppendHost(base::WeakPtr<AppendHost>) = 0;
virtual void RegisterSource(std::shared_ptr<Source>) = 0;
protected:
//////////////////// Source ////////////////////
-void SourceImpl::RegisterDemuxer(std::shared_ptr<Demuxer> demuxer) {
+void SourceImpl::RegisterDemuxer(base::WeakPtr<Demuxer> demuxer) {
EMSS_DEBUG();
demuxer_ = demuxer;
shared_state->buffered_ranges = new_ranges;
}
- if (auto demuxer = demuxer_.lock())
- demuxer->OnBufferedTimeRangesChanged(std::move(new_ranges));
+ if (!demuxer_)
+ return;
+
+ demuxer_->OnBufferedTimeRangesChanged(std::move(new_ranges));
}
//////////////////// SourceDispatcherClient ////////////////////
<< "Should not be called in " << pipeline_mode_.demuxer_mode << " and "
<< pipeline_mode_.latency_mode;
- if (auto demuxer = demuxer_.lock()) {
- demuxer->OnInitialConfigReady(audio_config, video_config);
- }
+ if (!demuxer_)
+ return;
+
+ demuxer_->OnInitialConfigReady(audio_config, video_config);
}
void SourceImpl::RegisterClient(std::shared_ptr<SourceClient> client) {
clients_[+client->Type()] = client;
client->RegisterSource(std::static_pointer_cast<Source>(shared_from_this()));
- if (auto demuxer = demuxer_.lock()) {
- demuxer->SetAppendClient(client->Type(), client->GetAppendClient());
- client->SetAppendHost(demuxer->GetAppendHost(client->Type()));
+ if (!demuxer_)
+ return;
- if (pipeline_mode_.player_mode != PlayerMode::kDecodeToTexture ||
- client->Type() != TrackType::kVideo)
- return;
+ demuxer_->SetAppendClient(client->Type(), client->GetAppendClient());
+ client->SetAppendHost(demuxer_->GetAppendHost(client->Type()));
- demuxer->SetVideoTextureClient(client->GetVideoTextureClient());
- }
+ if (pipeline_mode_.player_mode != PlayerMode::kDecodeToTexture ||
+ client->Type() != TrackType::kVideo)
+ return;
+
+ demuxer_->SetVideoTextureClient(client->GetVideoTextureClient());
}
void SourceImpl::SetMediaStreamAudioTrackSink(
std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink> audio_sink) {
EMSS_DEBUG();
- if (auto demuxer = demuxer_.lock()) {
- demuxer->GetAppendHost(TrackType::kAudio)
- ->SetAudioSink(std::move(audio_sink));
- }
+ if (!demuxer_)
+ return;
+ auto append_host = demuxer_->GetAppendHost(TrackType::kAudio);
+ if (!append_host)
+ return;
+ append_host->SetAudioSink(std::move(audio_sink));
}
void SourceImpl::SetMediaStreamVideoTrackSink(
std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink> video_sink) {
EMSS_DEBUG();
- if (auto demuxer = demuxer_.lock()) {
- demuxer->GetAppendHost(TrackType::kVideo)
- ->SetVideoSink(std::move(video_sink));
- }
+ if (!demuxer_)
+ return;
+ auto append_host = demuxer_->GetAppendHost(TrackType::kVideo);
+ if (!append_host)
+ return;
+ append_host->SetVideoSink(std::move(video_sink));
}
void SourceImpl::SetMediaStreamDecoderFactory(
base::WeakPtr<media::DecoderFactory> decoder_factory) {
EMSS_DEBUG();
- if (auto demuxer = demuxer_.lock()) {
- demuxer->SetMediaStreamDecoderFactory(std::move(decoder_factory));
- }
+ if (!demuxer_)
+ return;
+ demuxer_->SetMediaStreamDecoderFactory(std::move(decoder_factory));
}
} // namespace worker_thread
~SourceImpl() override;
// DemuxerClient
- void RegisterDemuxer(std::shared_ptr<Demuxer>) override;
+ void RegisterDemuxer(base::WeakPtr<Demuxer>) override;
// Source + SourceDispatcherClient
void BufferedRangesChanged() const override;
const PipelineMode pipeline_mode_;
std::array<std::weak_ptr<SourceClient>, (+TrackType::kMaxValue + 1)> clients_;
- std::weak_ptr<Demuxer> demuxer_;
+ base::WeakPtr<Demuxer> demuxer_;
std::shared_ptr<any_thread::LockableSourceState> state_;
};
source_ = source;
}
-void TrackImpl::SetAppendHost(std::shared_ptr<AppendHost> append_host) {
+void TrackImpl::SetAppendHost(base::WeakPtr<AppendHost> append_host) {
EMSS_DEBUG_TYPED();
append_host_ = append_host;
track_mode_.demuxer_mode == DemuxerMode::kMediaStream) {
// Media Stream expects response to each read. Do not silently drop a read
// but fire an empty one if reseting read state was requested.
- if (auto append_host = append_host_.lock()) {
- append_host->OnReadMediaPackets(Type(), std::vector<Packet>{});
+ if (append_host_) {
+ append_host_->OnReadMediaPackets(Type(), std::vector<Packet>{});
}
}
EMSS_LOG_ASSERT(is_read_requested_) << "Read called when not requested";
EMSS_LOG_ASSERT(!packets_queue_.empty()) << "Read called on empty queue";
- auto append_host = append_host_.lock();
- if (!append_host) {
+ if (!append_host_) {
EMSS_VERBOSE_TYPED();
return;
}
const auto& first_packet = packets_queue_.front();
if (first_packet.packet) {
EMSS_VERBOSE_TYPED();
- ReadMediaPackets(shared_state, append_host.get());
+ ReadMediaPackets(shared_state, append_host_.get());
} else if (first_packet.status == ReadStatus::kConfigChanged) {
if (Type() == TrackType::kAudio) {
EMSS_VERBOSE_TYPED() << "Reading audio config";
EMSS_LOG_ASSERT(std::holds_alternative<media::AudioDecoderConfig>(
shared_state->config));
- append_host->OnReadConfig(ToAudioConfig(
+ append_host_->OnReadConfig(ToAudioConfig(
std::get<media::AudioDecoderConfig>(shared_state->config),
track_mode_.decoding_mode));
} else {
EMSS_VERBOSE_TYPED() << "Reading video config";
EMSS_LOG_ASSERT(std::holds_alternative<media::VideoDecoderConfig>(
shared_state->config));
- append_host->OnReadConfig(ToVideoConfig(
+ append_host_->OnReadConfig(ToVideoConfig(
std::get<media::VideoDecoderConfig>(shared_state->config),
track_mode_.decoding_mode));
}
std::shared_ptr<VideoTextureClient> GetVideoTextureClient() override;
TrackType Type() const override = 0;
void RegisterSource(std::shared_ptr<Source>) override;
- void SetAppendHost(std::shared_ptr<AppendHost>) override;
+ void SetAppendHost(base::WeakPtr<AppendHost>) override;
// TrackDispatcherClient
void AbortPendingReads() override;
const PacketHolder& GetNextPacket() const;
virtual void RunReadCb();
- std::weak_ptr<AppendHost> append_host_;
+ base::WeakPtr<AppendHost> append_host_;
std::weak_ptr<any_thread::TrackDispatcher> dispatcher_;
std::shared_ptr<any_thread::LockableTrackState> state_;
TrackMode track_mode_;
return std::static_pointer_cast<VideoTrackImpl>(shared_from_this());
}
-void VideoTrackImpl::SetAppendHost(std::shared_ptr<AppendHost> append_host) {
+void VideoTrackImpl::SetAppendHost(base::WeakPtr<AppendHost> append_host) {
EMSS_DEBUG();
{
void VideoTrackImpl::NotifyFramerateChange() const {
EMSS_VERBOSE();
- if (auto append_host = append_host_.lock())
- append_host->NotifyFramerateSet(current_framerate_);
+ if (append_host_)
+ append_host_->NotifyFramerateSet(current_framerate_);
}
void VideoTrackImpl::RunReadCb() {
// SourceClient
std::shared_ptr<VideoTextureClient> GetVideoTextureClient() override;
- void SetAppendHost(std::shared_ptr<AppendHost>) override;
+ void SetAppendHost(base::WeakPtr<AppendHost>) override;
TrackType Type() const override;
// VideoTextureClient
worker_thread_task_runner) {}
void SetClientsForTesting(
- std::shared_ptr<AnyThreadClient> any_thread_client_,
- std::shared_ptr<ControlThreadClient> control_thread_client_,
- std::shared_ptr<WorkerThreadClient> worker_thread_client_) {
- SetClient<AnyThreadClient>(std::move(any_thread_client_));
- SetClient<ControlThreadClient>(std::move(control_thread_client_));
- SetClient<WorkerThreadClient>(std::move(worker_thread_client_));
+ std::shared_ptr<AnyThreadClient> any_thread_client,
+ std::shared_ptr<ControlThreadClient> control_thread_client,
+ base::WeakPtr<WorkerThreadClient> worker_thread_client) {
+ SetClient<AnyThreadClient>(std::move(any_thread_client));
+ SetClient<ControlThreadClient>(std::move(control_thread_client));
+ SetClient<WorkerThreadClient>(std::move(worker_thread_client));
}
};
std::make_shared<testing::NiceMock<
control_thread::MockDemuxerDispatcherClient>>()),
mock_worker_thread_client_(
- std::make_shared<testing::NiceMock<
+ std::make_unique<testing::NiceMock<
worker_thread::MockDemuxerDispatcherClient>>()),
fake_media_thread_(CreateAndStartBaseThread("TestingMediaThread")),
mock_proxy_(std::make_unique<testing::NiceMock<
media_thread::MockPlatformDemuxerAdapter>>()) {
- demuxer_dispatcher_->SetClientsForTesting(mock_any_thread_client_,
- mock_control_thread_client_,
- mock_worker_thread_client_);
+ demuxer_dispatcher_->SetClientsForTesting(
+ mock_any_thread_client_, mock_control_thread_client_,
+ mock_worker_thread_client_->GetWeakPtr());
fake_media_thread_->task_runner()->PostTask(
FROM_HERE,
mock_any_thread_client_;
std::shared_ptr<control_thread::MockDemuxerDispatcherClient>
mock_control_thread_client_;
- std::shared_ptr<worker_thread::MockDemuxerDispatcherClient>
+ std::unique_ptr<worker_thread::MockDemuxerDispatcherClient>
mock_worker_thread_client_;
std::shared_ptr<base::Thread> fake_media_thread_;
class MockAppendHost : public AppendHost {
public:
+ base::WeakPtr<AppendHost> GetWeakPtr() {
+ return weak_ptr_factory_.GetMutableWeakPtr();
+ }
+
MOCK_METHOD(void,
NotifyFramerateSet,
(const media::StreamFramerate::Framerate&),
OnReadMediaPackets,
(TrackType, std::vector<Packet>),
(override));
+
+ private:
+ base::WeakPtrFactory<AppendHost> weak_ptr_factory_{this};
};
} // namespace worker_thread
class MockDemuxerClient : public DemuxerClient {
public:
- MOCK_METHOD1(RegisterDemuxer, void(std::shared_ptr<Demuxer>));
+ MOCK_METHOD1(RegisterDemuxer, void(base::WeakPtr<Demuxer>));
};
} // namespace worker_thread
#include <memory>
+#include "base/memory/weak_ptr.h"
#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/demuxer_dispatcher_client.h"
#include "testing/gmock/include/gmock/gmock.h"
class MockDemuxerDispatcherClient : public DemuxerDispatcherClient {
public:
+ base::WeakPtr<DemuxerDispatcherClient> GetWeakPtr() {
+ return weak_ptr_factory_.GetMutableWeakPtr();
+ }
+
MOCK_METHOD(void, OnPipelineClosed, (), (override));
MOCK_METHOD(void, OnPipelineResuming, (), (override));
MOCK_METHOD(void, OnPipelineSuspended, (), (override));
(base::TimeDelta new_time, uint32_t session_id),
(override));
MOCK_METHOD(void, OnSessionIdChange, (uint32_t session_id), (override));
+
+ private:
+ base::WeakPtrFactory<DemuxerDispatcherClient> weak_ptr_factory_{this};
};
} // namespace worker_thread
ResultCb cb_append = GetOnceCallback(cb_append_fn);
// append host needs to be set, or RunReadCb exits quickly
- auto append_host_mock = std::make_shared<NiceMock<MockAppendHost>>();
- track_->SetAppendHost(append_host_mock);
+ auto append_host_mock = std::make_unique<NiceMock<MockAppendHost>>();
+ track_->SetAppendHost(append_host_mock->GetWeakPtr());
auto source_mock = std::make_shared<MockSource>();
track_->RegisterSource(source_mock);
SetSessionId(session_id);
// append host needs to be set, or RunReadCb exits quickly
- auto append_host_mock = std::make_shared<NiceMock<MockAppendHost>>();
- track_->SetAppendHost(append_host_mock);
+ auto append_host_mock = std::make_unique<NiceMock<MockAppendHost>>();
+ track_->SetAppendHost(append_host_mock->GetWeakPtr());
auto source_mock = std::make_shared<MockSource>();
track_->RegisterSource(source_mock);
SetSessionId(session_id_state);
// append host needs to be set, or RunReadCb exits quickly
- auto append_host_mock = std::make_shared<NiceMock<MockAppendHost>>();
- track_->SetAppendHost(append_host_mock);
+ auto append_host_mock = std::make_unique<NiceMock<MockAppendHost>>();
+ track_->SetAppendHost(append_host_mock->GetWeakPtr());
auto source_mock = std::make_shared<MockSource>();
track_->RegisterSource(source_mock);
AddPacketToState();
// append host needs to be set, or RunReadCb exits quickly
- auto append_host_mock = std::make_shared<NiceMock<MockAppendHost>>();
- track_->SetAppendHost(append_host_mock);
+ auto append_host_mock = std::make_unique<NiceMock<MockAppendHost>>();
+ track_->SetAppendHost(append_host_mock->GetWeakPtr());
auto source_mock = std::make_shared<MockSource>();
track_->RegisterSource(source_mock);
ResultCb cb_append = GetOnceCallback(cb_append_fn);
ResultCb cb_append = GetOnceCallback(cb_append_fn);
// append host needs to be set, or RunReadCb exits quickly
- auto append_host_mock = std::make_shared<NiceMock<MockAppendHost>>();
- track_->SetAppendHost(append_host_mock);
+ auto append_host_mock = std::make_unique<NiceMock<MockAppendHost>>();
+ track_->SetAppendHost(append_host_mock->GetWeakPtr());
auto source_mock = std::make_shared<MockSource>();
track_->RegisterSource(source_mock);
ResultCb cb_append = GetOnceCallback(cb_append_fn);
// append host needs to be set, or RunReadCb exits quickly
- auto append_host_mock = std::make_shared<NiceMock<MockAppendHost>>();
- track_->SetAppendHost(append_host_mock);
+ auto append_host_mock = std::make_unique<NiceMock<MockAppendHost>>();
+ track_->SetAppendHost(append_host_mock->GetWeakPtr());
auto source_mock = std::make_shared<MockSource>();
track_->RegisterSource(source_mock);
uint32_t session_id_new = kDefaultSessionId + 1;
// append host needs to be set, or RunReadCb exits quickly
- auto append_host_mock = std::make_shared<NiceMock<MockAppendHost>>();
- track_->SetAppendHost(append_host_mock);
+ auto append_host_mock = std::make_unique<NiceMock<MockAppendHost>>();
+ track_->SetAppendHost(append_host_mock->GetWeakPtr());
auto source_mock = std::make_shared<MockSource>();
track_->RegisterSource(source_mock);
uint32_t session_id = kDefaultSessionId;
// append host needs to be set, or RunReadCb exits quickly
- auto append_host_mock = std::make_shared<NiceMock<MockAppendHost>>();
- track_->SetAppendHost(append_host_mock);
+ auto append_host_mock = std::make_unique<NiceMock<MockAppendHost>>();
+ track_->SetAppendHost(append_host_mock->GetWeakPtr());
auto source_mock = std::make_shared<MockSource>();
track_->RegisterSource(source_mock);
uint32_t session_id = kDefaultSessionId;
// append host needs to be set, or RunReadCb exits quickly
- auto append_host_mock = std::make_shared<NiceMock<MockAppendHost>>();
- track_->SetAppendHost(append_host_mock);
+ auto append_host_mock = std::make_unique<NiceMock<MockAppendHost>>();
+ track_->SetAppendHost(append_host_mock->GetWeakPtr());
auto source_mock = std::make_shared<MockSource>();
track_->RegisterSource(source_mock);
uint32_t session_id = kDefaultSessionId;
// append host needs to be set, or RunReadCb exits quickly
- auto append_host_mock = std::make_shared<NiceMock<MockAppendHost>>();
- track_->SetAppendHost(append_host_mock);
+ auto append_host_mock = std::make_unique<NiceMock<MockAppendHost>>();
+ track_->SetAppendHost(append_host_mock->GetWeakPtr());
auto source_mock = std::make_shared<MockSource>();
track_->RegisterSource(source_mock);
} // namespace player_thread
-template <>
-struct ClientTraits<control_thread::HostClientInterface> {
- public:
- using PointerType = control_thread::HostClientInterface*;
-};
-
namespace any_thread {
class HostDispatcher
namespace elementary_media_stream_source {
-// By default all clients execute on shared_ptr and make dispatcher owner of the
-// clients. Their pointer type can be changed by providing partial ClientTraits
-// specialization in dispatcher implementation (typically change pointer type to
-// raw ptr and make it a client dispatcher doesn't own).
-template <typename ClientType>
-struct ClientTraits {
- public:
- using PointerType = std::shared_ptr<ClientType>;
-};
-
namespace control_thread {
class EnableDispatcher;
} // namespace control_thread
template <class T>
using compatible_arg_dispatch_t = typename compatible_arg_dispatch<T>::type;
+template <class T, class Tuple>
+struct is_type_in_tuple : public std::false_type {};
+
+template <class T, class... TupleTypes>
+struct is_type_in_tuple<T, std::tuple<TupleTypes...>>
+ : public std::disjunction<std::is_same<T, TupleTypes>..., std::false_type> {
+};
+
+template <class T>
+struct is_shared_ptr : public std::false_type {};
+
+template <class HeldT>
+struct is_shared_ptr<std::shared_ptr<HeldT>> : public std::true_type {};
+
+template <class T>
+struct is_base_weak_ptr : public std::false_type {};
+
+template <class HeldT>
+struct is_base_weak_ptr<base::WeakPtr<HeldT>> : public std::true_type {};
+
// Base class for all dispatchers.
// Implements DispatchTask and RunTask public methods to be used in derived
// dispatchers classes.
template <typename ClientType>
bool HasClient() const {
- return !!GetClient<ClientType>();
+ return !!GetClient<ClientType>(static_cast<const Impl*>(this)->clients_);
}
template <typename ClientType, typename ReturnType, typename... Args>
DispatchResult DispatchTask(ReturnType (ClientType::*method)(Args...),
- compatible_arg_dispatch_t<Args>... args) const {
- auto client = GetClient<ClientType>();
+ compatible_arg_dispatch_t<Args>... args) {
+ auto client =
+ GetClient<ClientType>(static_cast<const Impl*>(this)->clients_);
if (!client)
return DispatchResult::kFailed;
LOG_ASSERT(client_task_runner)
<< "A task runner for ClientType* is not set.";
- if constexpr (!std::is_pointer<decltype(client)>::value) {
- // If it's not pointer, it's shared_ptr
+ if constexpr (is_shared_ptr<decltype(client)>::value) {
if (!client_task_runner->PostTask(
FROM_HERE,
base::BindOnce(
- ExecuteOnSharedPtr<ClientType, ReturnType, Args...>, method,
+ &ExecuteOnSharedPtr<ClientType, ReturnType, Args...>, method,
client, std::forward<decltype(args)>(args)...)))
return DispatchResult::kFailed;
+ } else if constexpr (is_base_weak_ptr<decltype(client)>::value) {
+ if (!client_task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ExecuteOnWeakPtr<ClientType, ReturnType, Args...>,
+ method, client,
+ std::forward<decltype(args)>(args)...)))
+ return DispatchResult::kFailed;
} else {
if (!client_task_runner->PostTask(
FROM_HERE,
- base::BindOnce(&ExecuteOnRawPtr<ClientType, ReturnType, Args...>,
- std::weak_ptr<const Dispatcher<Impl>>{
- this->shared_from_this()},
- method, std::forward<decltype(args)>(args)...)))
+ base::BindOnce(
+ &ExecuteOnRawPtr<ClientType, ReturnType, Args...>,
+ std::weak_ptr<Dispatcher<Impl>>{this->shared_from_this()},
+ method, std::forward<decltype(args)>(args)...)))
return DispatchResult::kFailed;
}
return DispatchResult::kOk;
template <typename ClientType, typename ReturnType, typename... Args>
DispatchResult DispatchTask(ReturnType (ClientType::*method)(Args...) const,
compatible_arg_dispatch_t<Args>... args) const {
- auto client = GetClient<ClientType>();
+ auto client =
+ GetClient<ClientType>(static_cast<const Impl*>(this)->clients_);
if (!client)
return DispatchResult::kFailed;
LOG_ASSERT(client_task_runner)
<< "A task runner for ClientType* is not set.";
- if constexpr (!std::is_pointer<decltype(client)>::value) {
- // If it's not pointer, it's shared_ptr
+ if constexpr (is_shared_ptr<decltype(client)>::value) {
if (!client_task_runner->PostTask(
FROM_HERE,
base::BindOnce(
ExecuteConstOnSharedPtr<ClientType, ReturnType, Args...>,
method, client, std::forward<decltype(args)>(args)...)))
return DispatchResult::kFailed;
+ } else if constexpr (is_base_weak_ptr<decltype(client)>::value) {
+ if (!client_task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ ExecuteConstOnWeakPtr<ClientType, ReturnType, Args...>,
+ method, client, std::forward<decltype(args)>(args)...)))
+ return DispatchResult::kFailed;
} else {
+ // It's a raw pointer.
if (!client_task_runner->PostTask(
FROM_HERE,
base::BindOnce(
LOG_ASSERT(client_task_runner->BelongsToCurrentThread())
<< "Running method from other thread without dispatching!";
- auto client = GetClient<ClientType>();
+ auto client =
+ GetClient<ClientType>(static_cast<const Impl*>(this)->clients_);
LOG_ASSERT(client) << "Client is empty. Should never happen...";
- return ExecuteOnSharedPtr<ClientType, ReturnType, Args...>(
- method, client, std::forward<decltype(args)>(args)...);
+ if constexpr (is_shared_ptr<decltype(client)>::value) {
+ return ExecuteOnSharedPtr<ClientType, ReturnType, Args...>(
+ method, client, std::forward<decltype(args)>(args)...);
+ } else {
+ return ExecuteOnWeakPtr<ClientType, ReturnType, Args...>(
+ method, client, std::forward<decltype(args)>(args)...);
+ }
}
template <typename ClientType, typename ReturnType, typename... Args>
LOG_ASSERT(client_task_runner->BelongsToCurrentThread())
<< "Running method from other thread without dispatching!";
- auto client = GetClient<ClientType>();
+ auto client =
+ GetClient<ClientType>(static_cast<const Impl*>(this)->clients_);
LOG_ASSERT(client) << "Client is empty. Should never happen...";
- return ExecuteConstOnSharedPtr<ClientType, ReturnType, Args...>(
- method, client, std::forward<decltype(args)>(args)...);
+ if constexpr (is_shared_ptr<decltype(client)>::value) {
+ return ExecuteConstOnSharedPtr<ClientType, ReturnType, Args...>(
+ method, client, std::forward<decltype(args)>(args)...);
+ } else {
+ return ExecuteConstOnWeakPtr<ClientType, ReturnType, Args...>(
+ method, client, std::forward<decltype(args)>(args)...);
+ }
}
scoped_refptr<base::SingleThreadTaskRunner> GetControlThreadTaskRunner()
client = std::move(ptr);
}
+ template <typename ClientType>
+ void SetClient(const base::WeakPtr<ClientType>& weak_ptr) {
+ auto& client =
+ std::get<base::WeakPtr<ClientType>>(static_cast<Impl*>(this)->clients_);
+ LOG_ASSERT(!client) << "Overriding existing client!";
+
+ client = std::move(weak_ptr);
+ }
+
// Client may not be owned by dispatcher and held by raw pointer. Following
// restrictions apply:
// * Client must outlive dispatcher, or dispatcher must be unset before client
return (client.get()->*method)(std::forward<Args>(args)...);
}
+ template <typename ClientType, typename ReturnType, typename... Args>
+ static ReturnType ExecuteOnWeakPtr(ReturnType (ClientType::*method)(Args...),
+ base::WeakPtr<ClientType> client,
+ Args... args) {
+ if (!client) {
+ if constexpr (std::is_void<ReturnType>::value) {
+ return;
+ } else {
+ return {};
+ }
+ }
+ return (client.get()->*method)(std::forward<Args>(args)...);
+ }
+
+ template <typename ClientType, typename ReturnType, typename... Args>
+ static ReturnType ExecuteConstOnWeakPtr(
+ ReturnType (ClientType::*method)(Args...) const,
+ base::WeakPtr<ClientType> client,
+ Args... args) {
+ if (!client) {
+ if constexpr (std::is_void<ReturnType>::value) {
+ return;
+ } else {
+ return {};
+ }
+ }
+ return (client.get()->*method)(std::forward<Args>(args)...);
+ }
+
template <typename ClientType, typename ReturnType, typename... Args>
static ReturnType ExecuteOnRawPtr(
- std::weak_ptr<const Dispatcher<Impl>> weak_dispatcher,
+ std::weak_ptr<Dispatcher<Impl>> weak_dispatcher,
ReturnType (ClientType::*method)(Args...),
Args... args) {
auto dispatcher = weak_dispatcher.lock();
}
}
- auto* client = dispatcher->template GetClient<ClientType>();
+ auto* client =
+ GetClient<ClientType>(static_cast<Impl*>(dispatcher.get())->clients_);
if (!client) {
if constexpr (std::is_void<ReturnType>::value) {
return;
template <typename ClientType, typename ReturnType, typename... Args>
static ReturnType ExecuteConstOnRawPtr(
- std::weak_ptr<Dispatcher> weak_dispatcher,
+ std::weak_ptr<const Dispatcher> weak_dispatcher,
ReturnType (ClientType::*method)(Args...) const,
Args... args) {
auto dispatcher = weak_dispatcher.lock();
if (!dispatcher)
return ReturnType{};
- auto* client = dispatcher->template GetClient<ClientType>();
+ auto* client = GetClient<ClientType>(
+ static_cast<const Impl*>(dispatcher.get())->clients_);
if (!client)
return ReturnType{};
return (client->*method)(std::forward<Args>(args)...);
}
- template <typename ClientType>
- typename ::elementary_media_stream_source::ClientTraits<
- ClientType>::PointerType
- GetClient() const {
- using PointerT = typename ::elementary_media_stream_source::ClientTraits<
- ClientType>::PointerType;
- return std::get<PointerT>(static_cast<const Impl*>(this)->clients_);
+ template <typename ClientType, typename ClientsTupleT>
+ typename std::enable_if_t<
+ is_type_in_tuple<std::shared_ptr<ClientType>, ClientsTupleT>::value,
+ std::shared_ptr<ClientType>&> static GetClient(ClientsTupleT& clients) {
+ return std::get<std::shared_ptr<ClientType>>(clients);
+ }
+
+ template <typename ClientType, typename ClientsTupleT>
+ typename std::enable_if_t<
+ is_type_in_tuple<std::shared_ptr<ClientType>, ClientsTupleT>::value,
+ const std::shared_ptr<ClientType>&> static GetClient(const ClientsTupleT&
+ clients) {
+ return std::get<std::shared_ptr<ClientType>>(clients);
+ }
+
+ template <typename ClientType, typename ClientsTupleT>
+ typename std::enable_if_t<
+ is_type_in_tuple<base::WeakPtr<ClientType>, ClientsTupleT>::value,
+ base::WeakPtr<ClientType>&> static GetClient(ClientsTupleT& clients) {
+ return std::get<base::WeakPtr<ClientType>>(clients);
+ }
+
+ template <typename ClientType, typename ClientsTupleT>
+ typename std::enable_if_t<
+ is_type_in_tuple<base::WeakPtr<ClientType>, ClientsTupleT>::value,
+ const base::WeakPtr<ClientType>&> static GetClient(const ClientsTupleT&
+ clients) {
+ return std::get<base::WeakPtr<ClientType>>(clients);
+ }
+
+ template <typename ClientType, typename ClientsTupleT>
+ typename std::enable_if_t<is_type_in_tuple<ClientType*, ClientsTupleT>::value,
+ ClientType*> static GetClient(ClientsTupleT&
+ clients) {
+ return std::get<ClientType*>(clients);
+ }
+
+ template <typename ClientType, typename ClientsTupleT>
+ typename std::enable_if_t<
+ is_type_in_tuple<ClientType*, ClientsTupleT>::value,
+ const ClientType*> static GetClient(const ClientsTupleT& clients) {
+ return std::get<ClientType*>(clients);
}
template <typename ClientType>