chromium/media/fuchsia/video/fuchsia_video_decoder.h

// Copyright 2018 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_FUCHSIA_VIDEO_FUCHSIA_VIDEO_DECODER_H_
#define MEDIA_FUCHSIA_VIDEO_FUCHSIA_VIDEO_DECODER_H_

#include <deque>
#include <memory>
#include <vector>

#include <fuchsia/media/cpp/fidl.h>
#include <lib/zx/eventpair.h>

#include "base/memory/scoped_refptr.h"
#include "media/base/media_export.h"
#include "media/base/video_decoder.h"
#include "media/base/video_decoder_config.h"
#include "media/fuchsia/common/sysmem_buffer_stream.h"
#include "media/fuchsia/common/sysmem_client.h"
#include "media/mojo/mojom/fuchsia_media.mojom.h"
#include "mojo/public/cpp/bindings/shared_remote.h"

namespace gfx {
class ClientNativePixmapFactory;
}  // namespace gfx

namespace viz {
class RasterContextProvider;
}  // namespace viz

namespace media {

namespace mojom {
class FuchsiaMediaCodecProvider;
}  // namespace mojom

class MEDIA_EXPORT FuchsiaVideoDecoder : public VideoDecoder,
                                         public SysmemBufferStream::Sink,
                                         public StreamProcessorHelper::Client {
 public:
  FuchsiaVideoDecoder(
      scoped_refptr<viz::RasterContextProvider> raster_context_provider,
      const mojo::SharedRemote<media::mojom::FuchsiaMediaCodecProvider>&
          media_codec_provider,
      bool allow_overlays);
  ~FuchsiaVideoDecoder() override;

  FuchsiaVideoDecoder(const FuchsiaVideoDecoder&) = delete;
  FuchsiaVideoDecoder& operator=(const FuchsiaVideoDecoder&) = delete;

  // Decoder implementation.
  bool IsPlatformDecoder() const override;
  bool SupportsDecryption() const override;
  VideoDecoderType GetDecoderType() const override;

  // VideoDecoder implementation.
  void Initialize(const VideoDecoderConfig& config,
                  bool low_delay,
                  CdmContext* cdm_context,
                  InitCB init_cb,
                  const OutputCB& output_cb,
                  const WaitingCB& waiting_cb) override;
  void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
  void Reset(base::OnceClosure closure) override;
  bool NeedsBitstreamConversion() const override;
  bool CanReadWithoutStalling() const override;
  int GetMaxDecodeRequests() const override;

  void SetClientNativePixmapFactoryForTests(
      std::unique_ptr<gfx::ClientNativePixmapFactory> factory);

 private:
  class OutputMailbox;

  DecoderStatus InitializeSysmemBufferStream(bool is_encrypted,
                                             CdmContext* cdm_context,
                                             bool* secure_mode);

  // SysmemBufferStream::Sink implementation.
  void OnSysmemBufferStreamBufferCollectionToken(
      fuchsia::sysmem2::BufferCollectionTokenPtr token) override;
  void OnSysmemBufferStreamOutputPacket(
      StreamProcessorHelper::IoPacket packet) override;
  void OnSysmemBufferStreamEndOfStream() override;
  void OnSysmemBufferStreamError() override;
  void OnSysmemBufferStreamNoKey() override;

  // StreamProcessorHelper::Client implementation.
  void OnStreamProcessorAllocateOutputBuffers(
      const fuchsia::media::StreamBufferConstraints& stream_constraints)
      override;
  void OnStreamProcessorEndOfStream() override;
  void OnStreamProcessorOutputFormat(
      fuchsia::media::StreamOutputFormat format) override;
  void OnStreamProcessorOutputPacket(
      StreamProcessorHelper::IoPacket packet) override;
  void OnStreamProcessorNoKey() override;
  void OnStreamProcessorError() override;

  // Calls next callback in the |decode_callbacks_| queue.
  void CallNextDecodeCallback();

  // Drops all pending input buffers and then calls all pending DecodeCB with
  // |status|. Returns true if the decoder still exists.
  bool DropInputQueue(DecoderStatus status);

  // Called on errors to shutdown the decoder and notify the client.
  void OnError();

  // Callback for SysmemBufferCollection::CreateSharedToken(), used to send the
  // sysmem buffer collection token to the GPU process.
  void SetBufferCollectionTokenForGpu(
      fuchsia::sysmem2::BufferCollectionTokenPtr token);

  // Called by OutputMailbox to signal that the output buffer can be reused.
  void ReleaseOutputPacket(StreamProcessorHelper::IoPacket packet);

  // Releases BufferCollection used for output buffers if any.
  void ReleaseOutputBuffers();

  const scoped_refptr<viz::RasterContextProvider> raster_context_provider_;
  const mojo::SharedRemote<media::mojom::FuchsiaMediaCodecProvider>
      media_codec_provider_;

  const bool use_overlays_for_video_;

  OutputCB output_cb_;
  WaitingCB waiting_cb_;

  std::unique_ptr<SysmemBufferStream> sysmem_buffer_stream_;

  // Initialized in InitializeSysmemBufferStream()
  size_t max_decoder_requests_ = 1;

  VideoDecoderConfig current_config_;

  std::unique_ptr<StreamProcessorHelper> decoder_;

  SysmemAllocatorClient sysmem_allocator_;
  std::unique_ptr<gfx::ClientNativePixmapFactory> client_native_pixmap_factory_;

  // Callbacks for pending Decode() request.
  std::deque<DecodeCB> decode_callbacks_;

  // Input buffers for |decoder_|.
  std::unique_ptr<SysmemCollectionClient> input_buffer_collection_;

  // Output buffers for |decoder_|.
  fuchsia::media::VideoUncompressedFormat output_format_;
  std::unique_ptr<SysmemCollectionClient> output_buffer_collection_;
  zx::eventpair output_buffer_collection_handle_;
  std::vector<OutputMailbox*> output_mailboxes_;

  // Set to true when the output buffers are protected.
  bool protected_output_ = false;

  size_t num_used_output_buffers_ = 0;

  SEQUENCE_CHECKER(sequence_checker_);

  // WeakPtrFactory used to schedule CallNextDecodeCallbacks(). These pointers
  // are discarded in DropInputQueue() in order to avoid calling
  // Decode() callback when the decoder queue is discarded.
  base::WeakPtrFactory<FuchsiaVideoDecoder> decode_callbacks_weak_factory_{
      this};
};

}  // namespace media

#endif  // MEDIA_FUCHSIA_VIDEO_FUCHSIA_VIDEO_DECODER_H_