chromium/content/renderer/pepper/pepper_video_decoder_host.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_PEPPER_VIDEO_DECODER_HOST_H_
#define CONTENT_RENDERER_PEPPER_PEPPER_VIDEO_DECODER_HOST_H_

#include <stdint.h>

#include <list>
#include <map>
#include <memory>
#include <set>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "content/renderer/pepper/video_decoder_shim.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "ppapi/c/pp_codecs.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/resource_message_params.h"

namespace gpu {
class ClientSharedImage;
}

namespace content {

class RendererPpapiHost;

class PepperVideoDecoderHost : public ppapi::host::ResourceHost {
 public:
  PepperVideoDecoderHost(RendererPpapiHost* host,
                         PP_Instance instance,
                         PP_Resource resource);

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

  ~PepperVideoDecoderHost() override;

 private:
  enum class PictureBufferState {
    ASSIGNED,
    IN_USE,
    DISMISSED,
  };

  struct PendingDecode {
    PendingDecode(int32_t decode_id,
                  uint32_t shm_id,
                  uint32_t size,
                  const ppapi::host::ReplyMessageContext& reply_context);
    ~PendingDecode();

    const int32_t decode_id;
    const uint32_t shm_id;
    const uint32_t size;
    const ppapi::host::ReplyMessageContext reply_context;
  };
  typedef std::list<PendingDecode> PendingDecodeList;

  struct MappedBuffer {
    MappedBuffer(base::UnsafeSharedMemoryRegion region,
                 base::WritableSharedMemoryMapping mapping);
    ~MappedBuffer();

    MappedBuffer(MappedBuffer&&);
    MappedBuffer& operator=(MappedBuffer&&);

    base::UnsafeSharedMemoryRegion region;
    base::WritableSharedMemoryMapping mapping;
    bool busy = false;
  };

  struct SharedImage {
    SharedImage(gfx::Size size,
                PictureBufferState state,
                scoped_refptr<gpu::ClientSharedImage> client_shared_image);
    SharedImage(const SharedImage& shared_image);
    ~SharedImage();

    gfx::Size size;
    PictureBufferState state;
    scoped_refptr<gpu::ClientSharedImage> client_shared_image;
  };

  friend class VideoDecoderShim;

  // ResourceHost implementation.
  int32_t OnResourceMessageReceived(
      const IPC::Message& msg,
      ppapi::host::HostMessageContext* context) override;

  gpu::Mailbox CreateSharedImage(gfx::Size size);
  void DestroySharedImage(const gpu::Mailbox& mailbox);
  void DestroySharedImageInternal(
      std::map<gpu::Mailbox, SharedImage>::iterator it);

  void SharedImageReady(int32_t decode_id,
                        const gpu::Mailbox& mailbox,
                        gfx::Size size,
                        const gfx::Rect& visible_rect);

  void NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id);
  void NotifyFlushDone();
  void NotifyResetDone();
  void NotifyError(media::VideoDecodeAccelerator::Error error);

  int32_t OnHostMsgInitialize(ppapi::host::HostMessageContext* context,
                              const ppapi::HostResource& graphics_context,
                              PP_VideoProfile profile,
                              PP_HardwareAcceleration acceleration,
                              uint32_t min_picture_count);
  int32_t OnHostMsgGetShm(ppapi::host::HostMessageContext* context,
                          uint32_t shm_id,
                          uint32_t shm_size);
  int32_t OnHostMsgDecode(ppapi::host::HostMessageContext* context,
                          uint32_t shm_id,
                          uint32_t size,
                          int32_t decode_id);
  int32_t OnHostMsgRecycleSharedImage(ppapi::host::HostMessageContext* context,
                                      const gpu::Mailbox& mailbox);
  int32_t OnHostMsgFlush(ppapi::host::HostMessageContext* context);
  int32_t OnHostMsgReset(ppapi::host::HostMessageContext* context);

  const uint8_t* DecodeIdToAddress(uint32_t decode_id);

  // Tries to initialize software decoder. Returns true on success.
  bool TryFallbackToSoftwareDecoder();

  PendingDecodeList::iterator GetPendingDecodeById(int32_t decode_id);

  // Non-owning pointer.
  raw_ptr<RendererPpapiHost> renderer_ppapi_host_;

  media::VideoCodecProfile profile_;

  // |decoder_| will call DestroySharedImage in its dtor, which accesses these
  // fields.
  std::map<gpu::Mailbox, SharedImage> shared_images_;

  std::unique_ptr<VideoDecoderShim> decoder_;

  bool software_fallback_allowed_ = false;
  bool software_fallback_used_ = false;

  // Used to record UMA values.
  bool mojo_video_decoder_path_initialized_ = false;

  // Used for UMA stats; not frame-accurate.
  gfx::Size coded_size_;

  // A vector holding our shm buffers, in sync with a similar vector in the
  // resource. We use a buffer's index in these vectors as its id on both sides
  // of the proxy. Only add buffers or update them in place so as not to
  // invalidate these ids.
  //
  // These regions are created here, in the host, and shared with the other side
  // of the proxy who will write into them. While they are only used in a
  // read-only way in the host, using a ReadOnlySharedMemoryRegion would involve
  // an extra round-trip to allow the other side of the proxy to map the region
  // writable before sending a read-only region back to the host.
  std::vector<MappedBuffer> shm_buffers_;

  uint32_t min_picture_count_;

  // Keeps list of pending decodes.
  PendingDecodeList pending_decodes_;

  ppapi::host::ReplyMessageContext flush_reply_context_;
  ppapi::host::ReplyMessageContext reset_reply_context_;

  bool initialized_ = false;
};

}  // namespace content

#endif  // CONTENT_RENDERER_PEPPER_PEPPER_VIDEO_DECODER_HOST_H_