chromium/content/renderer/pepper/video_decoder_shim.h

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_RENDERER_PEPPER_VIDEO_DECODER_SHIM_H_
#define CONTENT_RENDERER_PEPPER_VIDEO_DECODER_SHIM_H_

#include <stdint.h>

#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "base/containers/queue.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "media/base/video_decoder_config.h"
#include "media/renderers/paint_canvas_video_renderer.h"
#include "media/video/video_decode_accelerator.h"
#include "ppapi/c/pp_codecs.h"
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"

namespace content {

class PepperVideoDecoderHost;

// This class is a shim to wrap a media::VideoDecoder so that it can be used
// by PepperVideoDecoderHost. This class should be constructed, used, and
// destructed on the main (render) thread.
class VideoDecoderShim {
 public:
  static std::unique_ptr<VideoDecoderShim> Create(PepperVideoDecoderHost* host,
                                                  uint32_t texture_pool_size,
                                                  bool use_hw_decoder);

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

  ~VideoDecoderShim();

  bool Initialize(media::VideoCodecProfile profile);
  void Decode(media::BitstreamBuffer bitstream_buffer);
  void ReuseSharedImage(const gpu::Mailbox& mailbox, gfx::Size size);
  void Flush();
  void Reset();
  void Destroy();

  const scoped_refptr<viz::ContextProviderCommandBuffer>& context_provider()
      const {
    return shared_main_thread_context_provider_;
  }

 private:
  enum State {
    UNINITIALIZED,
    DECODING,
    FLUSHING,
    RESETTING,
  };

  struct PendingDecode;
  struct PendingFrame;
  class DecoderImpl;

  VideoDecoderShim(PepperVideoDecoderHost* host,
                   uint32_t texture_pool_size,
                   bool use_hw_decoder,
                   scoped_refptr<viz::ContextProviderCommandBuffer>
                       shared_main_thread_context_provider);

  void OnInitializeFailed();
  void OnDecodeComplete(int32_t result, std::optional<uint32_t> decode_id);
  void OnOutputComplete(std::unique_ptr<PendingFrame> frame);
  void SendSharedImages();
  void OnResetComplete();
  void NotifyCompletedDecodes();
  // Call this whenever we change GL state that the plugin relies on, such as
  // creating picture textures.
  void FlushCommandBuffer();

  std::unique_ptr<DecoderImpl> decoder_impl_;
  State state_;

  raw_ptr<PepperVideoDecoderHost> host_;
  scoped_refptr<base::SequencedTaskRunner> media_task_runner_;
  scoped_refptr<viz::ContextProviderCommandBuffer>
      shared_main_thread_context_provider_;

  // The current decoded frame size.
  gfx::Size texture_size_;

  std::vector<gpu::Mailbox> available_shared_images_;

  // Queue of completed decode ids, for notifying the host.
  using CompletedDecodeQueue = base::queue<uint32_t>;
  CompletedDecodeQueue completed_decodes_;

  // Queue of decoded frames that await rgb->yuv conversion.
  using PendingFrameQueue = base::queue<std::unique_ptr<PendingFrame>>;
  PendingFrameQueue pending_frames_;

  // The optimal number of textures to allocate for decoder_impl_.
  uint32_t texture_pool_size_;

  uint32_t num_pending_decodes_;

  const bool use_hw_decoder_;

  std::unique_ptr<media::PaintCanvasVideoRenderer> video_renderer_;

  base::WeakPtrFactory<VideoDecoderShim> weak_ptr_factory_{this};
};

}  // namespace content

#endif  // CONTENT_RENDERER_PEPPER_VIDEO_DECODER_SHIM_H_