chromium/media/mojo/mojom/video_encode_accelerator.mojom

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

module media.mojom;

import "media/mojo/mojom/media_log.mojom";
import "media/mojo/mojom/media_types.mojom";
import "mojo/public/mojom/base/shared_memory.mojom";
import "mojo/public/mojom/base/time.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
import "ui/gfx/mojom/color_space.mojom";
import "media/mojo/mojom/video_encoder_info.mojom";
import "sandbox/policy/mojom/sandbox.mojom";

// This file is the Mojo version of the media::VideoEncodeAccelerator interface
// and describes the communication between a Client and a remote "service"
// VideoEncodeAccelerator (VEA) with the purpose of encoding Video Frames by
// means of hardware accelerated features.
//
//   Client                                    VideoEncodeAccelerator
//      | ---> Initialize                                       |
//      |                     RequireBitstreamBuffers(N) <---   |
//      | ---> UseOutputBitstreamBuffer(0)                      |
//      | ---> UseOutputBitstreamBuffer(1)                      |
//      |  ...                                                  |
//      =                                                       =
// The Client requests a remote Encode() and eventually the VEA will leave the
// encoded results in a pre-shared BitstreamBuffer, that is then restored to the
// VEA when the Client is finished with it. Note that there might not be a 1:1
// relationship between Encode() and BitstreamBufferReady() calls.
//      | ---> Encode()                                         |
//      |                        BitstreamBufferReady(k) <---   |
//      | ---> UseOutputBitstreamBuffer(k)                      |
//      =                                                       =
// At any time the VEA can send a NotifyError() to the Client. Similarly at any
// time the Client can send a RequestEncodingParametersChange() to the VEA. None
// of these messages are acknowledged.


enum VideoEncodeAcceleratorSupportedRateControlMode {
  kNoMode,
  kConstantMode,
  kVariableMode,
  kExternalMode
};

struct VideoEncodeAcceleratorSupportedProfile {
  VideoCodecProfile profile;
  gfx.mojom.Size min_resolution;
  gfx.mojom.Size max_resolution;
  uint32 max_framerate_numerator;
  uint32 max_framerate_denominator;
  array<VideoEncodeAcceleratorSupportedRateControlMode> rate_control_modes;
  array<SVCScalabilityMode> scalability_modes;
  bool is_software_codec;
  array<VideoPixelFormat> gpu_supported_pixel_formats;
};

// A renderer process calls this interface's functions. GPU process implements
// this interface.
interface VideoEncodeAcceleratorProvider {
  // Creates a VideoEncodeAccelerator bound to |receiver|.
  CreateVideoEncodeAccelerator(
        pending_receiver<VideoEncodeAccelerator> receiver);

  // Get a VideoEncodeAccelerator supported profiles.
  GetVideoEncodeAcceleratorSupportedProfiles()
      => (array<VideoEncodeAcceleratorSupportedProfile> profiles);
};

// This interface allows the browser process to broker
// VideoEncodeAcceleratorProvider connection requests on behalf of a renderer.
// The browser creates the mojo pipe and gives the receiver to a utility
// process. The expected usage is as follows:
//
// 1) The browser process receives a request from a renderer process to bind a
//    pending_receiver<VideoEncodeAcceleratorProvider>.
//
// 2) To satisfy that request, the browser process first starts a utility
//    process that hosts a VideoEncodeAcceleratorProviderFactory if it hasn't
//    already done so -- note that each renderer process should get its own
//    corresponding utility process.
//
// 3) The browser process calls CreateVideoEncodeAcceleratorProvider() passing
//    the pending_receiver<VideoEncodeAcceleratorProvider> received from the
//    renderer process.
[EnableIf=is_linux_or_chromeos,
ServiceSandbox=sandbox.mojom.Sandbox.kHardwareVideoEncoding]
interface VideoEncodeAcceleratorProviderFactory {
  // Creates a VideoEncodeAcceleratorProvider and should be called by the
  // browser process.
  CreateVideoEncodeAcceleratorProvider(
        pending_receiver<VideoEncodeAcceleratorProvider> receiver);
};

// This defines a mojo transport format used in the
// mojo::VideoBitrateAllocation that corresponds to media::Bitrate::peak_bps_
struct VariableBitratePeak {
  uint32 bps;
};

// Class that describes how video bitrate, in bps, is allocated across temporal
// and spatial layers. See media::VideoBitrateAllocation for more details.
struct VideoBitrateAllocation {
  array<uint32> bitrates;
  VariableBitratePeak? variable_bitrate_peak;
};

// This defines a mojo transport format for
// media::VideoEncodeAccelerator::Config::SpatialLayer.
struct SpatialLayer {
  int32 width;
  int32 height;
  uint32 bitrate_bps;
  uint32 framerate;
  uint8 max_qp;
  uint8 num_of_temporal_layers;
};

// This defines a mojo transport format for a media::Bitrate of type kConstant.
// The default target here matches that in media::Bitrate.
struct ConstantBitrate {
  uint32 target_bps = 0;
};

// This defines a mojo transport format for a media::Bitrate of type kVariable.
// The default target here matches that in media::Bitrate.
struct VariableBitrate {
  uint32 target_bps = 0;
  uint32 peak_bps;
};

struct ExternalBitrate {
};

// This defines a mojo transport format for media::Bitrate.
union Bitrate {
  ConstantBitrate constant;
  VariableBitrate variable;
  ExternalBitrate external;
};

// This defines a mojo transport format for
// media::VideoEncodeAccelerator::Config.
struct VideoEncodeAcceleratorConfig {
  // See media::VideoEncodeAccelerator::Config::ContentType
  enum ContentType {
    kCamera,
    kDisplay
  };

  // See media::VideoEncodeAccelerator::Config::StorageType
  enum StorageType {
    kShmem,
    kGpuMemoryBuffer,
  };

  // See media::VideoEncodeAccelerator::Config::EncoderType
  enum EncoderType {
    kHardware,
    kSoftware,
    kNoPreference,
  };

  VideoPixelFormat input_format;
  gfx.mojom.Size input_visible_size;
  VideoCodecProfile output_profile;
  Bitrate bitrate;
  uint32 framerate;
  StorageType storage_type;
  ContentType content_type;
  uint32 gop_length;
  bool has_gop_length;  // Whether or not config has group of picture length
  uint8 h264_output_level;
  bool has_h264_output_level;  // Whether or not config has H264 output level
  bool is_constrained_h264;
  // See VideoEncodeAccelerator::Config for detail. Since this is a percentage
  // between 0 and 100, the type is uint8.
  uint8 drop_frame_thresh_percentage;
  array<SpatialLayer> spatial_layers;
  SVCInterLayerPredMode inter_layer_pred;
  bool require_low_delay;
  EncoderType required_encoder_type;
};

// Options for encoding a single frame by VideoEncodeAccelerator.
// This defines a mojo transport format for a
// media::VideoEncoder::EncodeOptions.
struct VideoEncodeOptions {
  // If True, next frame must be encoded as I-frame (random access point)
  bool force_keyframe;

  // Quantizer(QP) value for encoding of the given frame.
  // This value is only heeded if VEA configured with external rate control mode
  // TODO(crbug.com/40489779): All negative values mean "ignore this field",
  // we don't use proper optional field because Java bindgen doesn't support
  // optional primitive types.
  int32 quantizer;
};

// The interface to access the hardware video encoding accelerator.
interface VideoEncodeAccelerator {
  // Responded by VideoEncodeAcceleratorClient.RequireBitstreamBuffers().
  [Sync]
  Initialize(VideoEncodeAcceleratorConfig config,
             pending_associated_remote<VideoEncodeAcceleratorClient> client,
             pending_remote<MediaLog> media_log)
      => (bool result);

  // Encodes a |frame|, being completely done with it after its callback.
  Encode(VideoFrame frame, VideoEncodeOptions options) => ();

  UseOutputBitstreamBuffer(int32 bitstream_buffer_id,
                           mojo_base.mojom.UnsafeSharedMemoryRegion region);

  // Request a change to the encoding parameters.
  // This method is intended for use with spatial or temporal layers,
  // and is implicitly a constant bitrate encoding.
  // Parameters:
  //  |bitrate_allocation| is the requested new bitrate, per spatial and
  //                       temporal layer.
  //  |framerate| is the requested new framerate, in frames per second.
  //  |size| is the requested new input visible frame size. Clients can request
  //         frame size change only when there is no pending frame in the
  //         encoder.
  RequestEncodingParametersChangeWithLayers(
    VideoBitrateAllocation bitrate_allocation,
    uint32 framerate,
    gfx.mojom.Size? size);

  // Request a change to the encoding parameters. This method is for use
  // with non-layered bitrates, and may make requests for constant or
  // variable bitrates based on the initially-configured bitrate mode.
  // Parameters:
  //  |bitrate| is the requested new bitrate for non-layered encoding, which
  //            may be constant or variable bitrate. This should not change the
  //            encoding mode (constant -> variable or variable -> constant).
  //  |framerate| is the requested new framerate, in frames per second.
  //  |size| is the requested new input visible frame size. Clients can request
  //         frame size change only when there is no pending frame in the
  //         encoder.
  RequestEncodingParametersChangeWithBitrate(
    Bitrate bitrate,
    uint32 framerate,
    gfx.mojom.Size? size);

  [Sync]
  IsFlushSupported() => (bool result);

  Flush() => (bool result);
};

// DropFrameMetadata, H264Metadata, H265metadata, Vp8Metadata, Vp9Metadata and
// Av1Metadata define mojo transport formats for media::DropFrameMetadata,
// media::H264Metadata, media::H265Metadata, media::Vp8Metadata,
// media::Vp9Metadata and media::Av1Metadata, respectively. See the structures
// defined video_encode_accelerator.h for the descriptions of the variables.
// Either of them is filled in GPU process only in the case of temporal/spatial
// SVC encoding. That is, none of them is filled in the case of non
// temporal/spatial SVC encoding. Thus CodecMetadata is union and CodecMetadata
// exists as optional in BitstreamBufferMetadata.
// BitstreamBufferMetadata is metadata about a bitstream buffer produced by a
// hardware encoder. The structure is passed from GPU process to renderer
// process in BitstreamBufferReady() call.
struct DropFrameMetadata {
  uint8 spatial_idx;
  bool end_of_picture;
};

struct H264Metadata {
  uint8 temporal_idx;
  bool layer_sync;
};

struct H265Metadata {
  uint8 temporal_idx;
};

struct Vp8Metadata {
  bool non_reference;
  uint8 temporal_idx;
  bool layer_sync;
};

struct Vp9Metadata {
  bool inter_pic_predicted;
  bool temporal_up_switch;
  bool referenced_by_upper_spatial_layers;
  bool reference_lower_spatial_layers;
  bool end_of_picture;
  uint8 temporal_idx;
  uint8 spatial_idx;
  array<gfx.mojom.Size> spatial_layer_resolutions;
  uint8 begin_active_spatial_layer_index;
  uint8 end_active_spatial_layer_index;
  array<uint8> p_diffs;
};

struct Av1Metadata {
  uint8 temporal_idx;
};

// DropFrame or Codec specific metadata.
union OptionalMetadata {
  DropFrameMetadata drop;
  H264Metadata h264;
  H265Metadata h265;
  Vp8Metadata vp8;
  Vp9Metadata vp9;
  Av1Metadata av1;
};

struct BitstreamBufferMetadata {
  uint32 payload_size_bytes;
  bool key_frame;
  mojo_base.mojom.TimeDelta timestamp;
  int32 qp;
  OptionalMetadata? optional_metadata;
  gfx.mojom.Size? encoded_size;
  gfx.mojom.ColorSpace? encoded_color_space;
};

interface VideoEncodeAcceleratorClient {
  // Response to VideoEncodeAccelerator.Initialize().
  RequireBitstreamBuffers(uint32 input_count,
                          gfx.mojom.Size input_coded_size,
                          uint32 output_buffer_size);

  BitstreamBufferReady(int32 bitstream_buffer_id,
                       BitstreamBufferMetadata metadata);
  // VideoEncodeAccelerator calls this when the error occurs and it cannot
  // perform encoding any more. |status| represents the detail about the error.
  NotifyErrorStatus(EncoderStatus status);

  // VideoEncodeAccelerator calls this when its VideoEncoderInfo is changed.
  // |info| is the updated VideoEncoderInfo.
  NotifyEncoderInfoChange(VideoEncoderInfo info);
};