blob: 7bf601a004c9205621adc296acacba3bec5ca6fa [file]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_MOJO_SERVICES_STABLE_VIDEO_DECODER_SERVICE_H_
#define MEDIA_MOJO_SERVICES_STABLE_VIDEO_DECODER_SERVICE_H_
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "base/thread_annotations.h"
#include "base/unguessable_token.h"
#include "build/chromeos_buildflags.h"
#include "media/mojo/mojom/media_log.mojom.h"
#include "media/mojo/mojom/stable/stable_video_decoder.mojom.h"
#include "media/mojo/mojom/video_decoder.mojom.h"
#include "media/mojo/services/media_mojo_export.h"
#include "media/mojo/services/mojo_cdm_service_context.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chromeos/components/cdm_factory_daemon/remote_cdm_context.h"
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
namespace media {
// A StableVideoDecoderService serves as an adapter between the
// stable::mojom::StableVideoDecoder interface and the mojom::VideoDecoder
// interface. This allows us to provide hardware video decoding capabilities to
// clients that may be using a different version of the
// stable::mojom::StableVideoDecoder interface, e.g., LaCrOS. A
// StableVideoDecoderService is intended to live in a video decoder process.
// This process can host multiple StableVideoDecoderServices, but the assumption
// is that they don't distrust each other. For example, they should all be
// serving the same renderer process.
//
// TODO(b/195769334): a StableVideoDecoderService should probably be responsible
// for checking incoming data to address issues that may arise due to the stable
// nature of the stable::mojom::StableVideoDecoder interface. For example,
// suppose the StableVideoDecoderService implements an older version of the
// interface relative to the one used by the client. If the client Initialize()s
// the StableVideoDecoderService with a VideoCodecProfile that's unsupported by
// the older version of the interface, the StableVideoDecoderService should
// reject that initialization. Conversely, the client of the
// StableVideoDecoderService should also check incoming data due to similar
// concerns.
class MEDIA_MOJO_EXPORT StableVideoDecoderService
: public stable::mojom::StableVideoDecoder,
public stable::mojom::VideoFrameHandleReleaser,
public mojom::VideoDecoderClient,
public mojom::MediaLog {
public:
StableVideoDecoderService(
std::unique_ptr<mojom::VideoDecoder> dst_video_decoder,
MojoCdmServiceContext* cdm_service_context);
StableVideoDecoderService(const StableVideoDecoderService&) = delete;
StableVideoDecoderService& operator=(const StableVideoDecoderService&) =
delete;
~StableVideoDecoderService() override;
// stable::mojom::StableVideoDecoder implementation.
void GetSupportedConfigs(GetSupportedConfigsCallback callback) final;
void Construct(
mojo::PendingAssociatedRemote<stable::mojom::VideoDecoderClient>
stable_video_decoder_client_remote,
mojo::PendingRemote<stable::mojom::MediaLog> stable_media_log_remote,
mojo::PendingReceiver<stable::mojom::VideoFrameHandleReleaser>
stable_video_frame_handle_releaser_receiver,
mojo::ScopedDataPipeConsumerHandle decoder_buffer_pipe,
const gfx::ColorSpace& target_color_space) final;
void Initialize(
const VideoDecoderConfig& config,
bool low_delay,
mojo::PendingRemote<stable::mojom::StableCdmContext> cdm_context,
InitializeCallback callback) final;
void Decode(const scoped_refptr<DecoderBuffer>& buffer,
DecodeCallback callback) final;
void Reset(ResetCallback callback) final;
// mojom::stable::VideoFrameHandleReleaser implementation.
void ReleaseVideoFrame(const base::UnguessableToken& release_token) final;
// mojom::VideoDecoderClient implementation.
void OnVideoFrameDecoded(
const scoped_refptr<VideoFrame>& frame,
bool can_read_without_stalling,
const absl::optional<base::UnguessableToken>& release_token) final;
void OnWaiting(WaitingReason reason) final;
void RequestOverlayInfo(bool restart_for_transitions) final;
// mojom::MediaLog implementation.
void AddLogRecord(const MediaLogRecord& event) final;
private:
// Incoming calls from the |dst_video_decoder_| to
// |video_decoder_client_receiver_| are forwarded to
// |stable_video_decoder_client_remote_|.
mojo::AssociatedReceiver<mojom::VideoDecoderClient>
video_decoder_client_receiver_ GUARDED_BY_CONTEXT(sequence_checker_);
mojo::AssociatedRemote<stable::mojom::VideoDecoderClient>
stable_video_decoder_client_remote_ GUARDED_BY_CONTEXT(sequence_checker_);
// Incoming calls from the |dst_video_decoder_| to |media_log_receiver_| are
// forwarded to |stable_media_log_remote_|.
mojo::Receiver<mojom::MediaLog> media_log_receiver_
GUARDED_BY_CONTEXT(sequence_checker_);
mojo::Remote<stable::mojom::MediaLog> stable_media_log_remote_
GUARDED_BY_CONTEXT(sequence_checker_);
// Incoming requests from the client to
// |stable_video_frame_handle_releaser_receiver_| are forwarded to
// |video_frame_handle_releaser_remote_|.
mojo::Receiver<stable::mojom::VideoFrameHandleReleaser>
stable_video_frame_handle_releaser_receiver_
GUARDED_BY_CONTEXT(sequence_checker_);
mojo::Remote<mojom::VideoFrameHandleReleaser>
video_frame_handle_releaser_remote_ GUARDED_BY_CONTEXT(sequence_checker_);
// The incoming stable::mojom::StableVideoDecoder requests are forwarded to
// |dst_video_decoder_receiver_| through |dst_video_decoder_remote_|.
//
// Note: the implementation behind |dst_video_decoder_receiver_| (i.e.,
// |dst_video_decoder_|) lives in-process. The reason we don't just make calls
// directly to that implementation is that when we call Construct(), we need
// to pass a mojo::PendingAssociatedRemote which needs to be sent over an
// existing pipe before using it to make calls.
std::unique_ptr<mojom::VideoDecoder> dst_video_decoder_
GUARDED_BY_CONTEXT(sequence_checker_);
mojo::Receiver<mojom::VideoDecoder> dst_video_decoder_receiver_
GUARDED_BY_CONTEXT(sequence_checker_);
mojo::Remote<mojom::VideoDecoder> dst_video_decoder_remote_
GUARDED_BY_CONTEXT(sequence_checker_);
#if BUILDFLAG(IS_CHROMEOS_ASH)
// Used for registering the |remote_cdm_context_| so that it can be resolved
// from the |cdm_id_| later.
const raw_ptr<MojoCdmServiceContext> cdm_service_context_
GUARDED_BY_CONTEXT(sequence_checker_);
scoped_refptr<chromeos::RemoteCdmContext> remote_cdm_context_
GUARDED_BY_CONTEXT(sequence_checker_);
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
absl::optional<base::UnguessableToken> cdm_id_
GUARDED_BY_CONTEXT(sequence_checker_);
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace media
#endif // MEDIA_MOJO_SERVICES_STABLE_VIDEO_DECODER_SERVICE_H_