blob: 59a30557e47296766ae1ed01f73ea4e4a7fe9727 [file] [log] [blame]
// Copyright 2022 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Contains extension code allowing partners to provide their own demuxer.
// CobaltExtensionDemuxerApi is the main API.
#ifndef COBALT_EXTENSION_DEMUXER_H_
#define COBALT_EXTENSION_DEMUXER_H_
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "starboard/time.h"
#ifdef __cplusplus
extern "C" {
#endif
#define kCobaltExtensionDemuxerApi "dev.cobalt.extension.Demuxer"
// This must stay in sync with ::media::PipelineStatus. Missing values are
// either irrelevant to the demuxer or are deprecated values of PipelineStatus.
typedef enum CobaltExtensionDemuxerStatus {
kCobaltExtensionDemuxerOk = 0,
kCobaltExtensionDemuxerErrorNetwork = 2,
kCobaltExtensionDemuxerErrorAbort = 5,
kCobaltExtensionDemuxerErrorInitializationFailed = 6,
kCobaltExtensionDemuxerErrorRead = 9,
kCobaltExtensionDemuxerErrorInvalidState = 11,
kCobaltExtensionDemuxerErrorCouldNotOpen = 12,
kCobaltExtensionDemuxerErrorCouldNotParse = 13,
kCobaltExtensionDemuxerErrorNoSupportedStreams = 14
} CobaltExtensionDemuxerStatus;
// Type of side data associated with a buffer.
typedef enum CobaltExtensionDemuxerSideDataType {
kCobaltExtensionDemuxerUnknownSideDataType = 0,
kCobaltExtensionDemuxerMatroskaBlockAdditional = 1,
} CobaltExtensionDemuxerSideDataType;
// This must stay in sync with ::media::AudioCodec.
typedef enum CobaltExtensionDemuxerAudioCodec {
kCobaltExtensionDemuxerCodecUnknownAudio = 0,
kCobaltExtensionDemuxerCodecAAC = 1,
kCobaltExtensionDemuxerCodecMP3 = 2,
kCobaltExtensionDemuxerCodecPCM = 3,
kCobaltExtensionDemuxerCodecVorbis = 4,
kCobaltExtensionDemuxerCodecFLAC = 5,
kCobaltExtensionDemuxerCodecAMR_NB = 6,
kCobaltExtensionDemuxerCodecAMR_WB = 7,
kCobaltExtensionDemuxerCodecPCM_MULAW = 8,
kCobaltExtensionDemuxerCodecGSM_MS = 9,
kCobaltExtensionDemuxerCodecPCM_S16BE = 10,
kCobaltExtensionDemuxerCodecPCM_S24BE = 11,
kCobaltExtensionDemuxerCodecOpus = 12,
kCobaltExtensionDemuxerCodecEAC3 = 13,
kCobaltExtensionDemuxerCodecPCM_ALAW = 14,
kCobaltExtensionDemuxerCodecALAC = 15,
kCobaltExtensionDemuxerCodecAC3 = 16
} CobaltExtensionDemuxerAudioCodec;
// This must stay in sync with ::media::VideoCodec.
typedef enum CobaltExtensionDemuxerVideoCodec {
kCobaltExtensionDemuxerCodecUnknownVideo = 0,
kCobaltExtensionDemuxerCodecH264,
kCobaltExtensionDemuxerCodecVC1,
kCobaltExtensionDemuxerCodecMPEG2,
kCobaltExtensionDemuxerCodecMPEG4,
kCobaltExtensionDemuxerCodecTheora,
kCobaltExtensionDemuxerCodecVP8,
kCobaltExtensionDemuxerCodecVP9,
kCobaltExtensionDemuxerCodecHEVC,
kCobaltExtensionDemuxerCodecDolbyVision,
kCobaltExtensionDemuxerCodecAV1,
} CobaltExtensionDemuxerVideoCodec;
// This must stay in sync with ::media::SampleFormat.
typedef enum CobaltExtensionDemuxerSampleFormat {
kCobaltExtensionDemuxerSampleFormatUnknown = 0,
kCobaltExtensionDemuxerSampleFormatU8, // Unsigned 8-bit w/ bias of 128.
kCobaltExtensionDemuxerSampleFormatS16, // Signed 16-bit.
kCobaltExtensionDemuxerSampleFormatS32, // Signed 32-bit.
kCobaltExtensionDemuxerSampleFormatF32, // Float 32-bit.
kCobaltExtensionDemuxerSampleFormatPlanarS16, // Signed 16-bit planar.
kCobaltExtensionDemuxerSampleFormatPlanarF32, // Float 32-bit planar.
kCobaltExtensionDemuxerSampleFormatPlanarS32, // Signed 32-bit planar.
kCobaltExtensionDemuxerSampleFormatS24, // Signed 24-bit.
} CobaltExtensionDemuxerSampleFormat;
// This must stay in sync with ::media::ChannelLayout.
typedef enum CobaltExtensionDemuxerChannelLayout {
kCobaltExtensionDemuxerChannelLayoutNone = 0,
kCobaltExtensionDemuxerChannelLayoutUnsupported = 1,
kCobaltExtensionDemuxerChannelLayoutMono = 2,
kCobaltExtensionDemuxerChannelLayoutStereo = 3,
kCobaltExtensionDemuxerChannelLayout2_1 = 4,
kCobaltExtensionDemuxerChannelLayoutSurround = 5,
kCobaltExtensionDemuxerChannelLayout4_0 = 6,
kCobaltExtensionDemuxerChannelLayout2_2 = 7,
kCobaltExtensionDemuxerChannelLayoutQuad = 8,
kCobaltExtensionDemuxerChannelLayout5_0 = 9,
kCobaltExtensionDemuxerChannelLayout5_1 = 10,
kCobaltExtensionDemuxerChannelLayout5_0Back = 11,
kCobaltExtensionDemuxerChannelLayout5_1Back = 12,
kCobaltExtensionDemuxerChannelLayout7_0 = 13,
kCobaltExtensionDemuxerChannelLayout7_1 = 14,
kCobaltExtensionDemuxerChannelLayout7_1Wide = 15,
kCobaltExtensionDemuxerChannelLayoutStereoDownmix = 16,
kCobaltExtensionDemuxerChannelLayout2point1 = 17,
kCobaltExtensionDemuxerChannelLayout3_1 = 18,
kCobaltExtensionDemuxerChannelLayout4_1 = 19,
kCobaltExtensionDemuxerChannelLayout6_0 = 20,
kCobaltExtensionDemuxerChannelLayout6_0Front = 21,
kCobaltExtensionDemuxerChannelLayoutHexagonal = 22,
kCobaltExtensionDemuxerChannelLayout6_1 = 23,
kCobaltExtensionDemuxerChannelLayout6_1Back = 24,
kCobaltExtensionDemuxerChannelLayout6_1Front = 25,
kCobaltExtensionDemuxerChannelLayout7_0Front = 26,
kCobaltExtensionDemuxerChannelLayout7_1WideBack = 27,
kCobaltExtensionDemuxerChannelLayoutOctagonal = 28,
kCobaltExtensionDemuxerChannelLayoutDiscrete = 29,
kCobaltExtensionDemuxerChannelLayoutStereoAndKeyboardMic = 30,
kCobaltExtensionDemuxerChannelLayout4_1QuadSide = 31,
kCobaltExtensionDemuxerChannelLayoutBitstream = 32
} CobaltExtensionDemuxerChannelLayout;
// This must stay in sync with ::media::VideoCodecProfile.
typedef enum CobaltExtensionDemuxerVideoCodecProfile {
kCobaltExtensionDemuxerVideoCodecProfileUnknown = -1,
kCobaltExtensionDemuxerH264ProfileMin = 0,
kCobaltExtensionDemuxerH264ProfileBaseline =
kCobaltExtensionDemuxerH264ProfileMin,
kCobaltExtensionDemuxerH264ProfileMain = 1,
kCobaltExtensionDemuxerH264ProfileExtended = 2,
kCobaltExtensionDemuxerH264ProfileHigh = 3,
kCobaltExtensionDemuxerH264ProfileHigh10Profile = 4,
kCobaltExtensionDemuxerH264ProfileHigh422Profile = 5,
kCobaltExtensionDemuxerH264ProfileHigh444PredictiveProfile = 6,
kCobaltExtensionDemuxerH264ProfileScalableBaseline = 7,
kCobaltExtensionDemuxerH264ProfileScalableHigh = 8,
kCobaltExtensionDemuxerH264ProfileStereoHigh = 9,
kCobaltExtensionDemuxerH264ProfileMultiviewHigh = 10,
kCobaltExtensionDemuxerH264ProfileMax =
kCobaltExtensionDemuxerH264ProfileMultiviewHigh,
kCobaltExtensionDemuxerVp8ProfileMin = 11,
kCobaltExtensionDemuxerVp8ProfileAny = kCobaltExtensionDemuxerVp8ProfileMin,
kCobaltExtensionDemuxerVp8ProfileMax = kCobaltExtensionDemuxerVp8ProfileAny,
kCobaltExtensionDemuxerVp9ProfileMin = 12,
kCobaltExtensionDemuxerVp9ProfileProfile0 =
kCobaltExtensionDemuxerVp9ProfileMin,
kCobaltExtensionDemuxerVp9ProfileProfile1 = 13,
kCobaltExtensionDemuxerVp9ProfileProfile2 = 14,
kCobaltExtensionDemuxerVp9ProfileProfile3 = 15,
kCobaltExtensionDemuxerVp9ProfileMax =
kCobaltExtensionDemuxerVp9ProfileProfile3,
kCobaltExtensionDemuxerHevcProfileMin = 16,
kCobaltExtensionDemuxerHevcProfileMain =
kCobaltExtensionDemuxerHevcProfileMin,
kCobaltExtensionDemuxerHevcProfileMain10 = 17,
kCobaltExtensionDemuxerHevcProfileMainStillPicture = 18,
kCobaltExtensionDemuxerHevcProfileMax =
kCobaltExtensionDemuxerHevcProfileMainStillPicture,
kCobaltExtensionDemuxerDolbyVisionProfile0 = 19,
kCobaltExtensionDemuxerDolbyVisionProfile4 = 20,
kCobaltExtensionDemuxerDolbyVisionProfile5 = 21,
kCobaltExtensionDemuxerDolbyVisionProfile7 = 22,
kCobaltExtensionDemuxerTheoraProfileMin = 23,
kCobaltExtensionDemuxerTheoraProfileAny =
kCobaltExtensionDemuxerTheoraProfileMin,
kCobaltExtensionDemuxerTheoraProfileMax =
kCobaltExtensionDemuxerTheoraProfileAny,
kCobaltExtensionDemuxerAv1ProfileMin = 24,
kCobaltExtensionDemuxerAv1ProfileProfileMain =
kCobaltExtensionDemuxerAv1ProfileMin,
kCobaltExtensionDemuxerAv1ProfileProfileHigh = 25,
kCobaltExtensionDemuxerAv1ProfileProfilePro = 26,
kCobaltExtensionDemuxerAv1ProfileMax =
kCobaltExtensionDemuxerAv1ProfileProfilePro,
kCobaltExtensionDemuxerDolbyVisionProfile8 = 27,
kCobaltExtensionDemuxerDolbyVisionProfile9 = 28,
} CobaltExtensionDemuxerVideoCodecProfile;
// This must be kept in sync with gfx::ColorSpace::RangeID.
typedef enum CobaltExtensionDemuxerColorSpaceRangeId {
kCobaltExtensionDemuxerColorSpaceRangeIdInvalid = 0,
kCobaltExtensionDemuxerColorSpaceRangeIdLimited = 1,
kCobaltExtensionDemuxerColorSpaceRangeIdFull = 2,
kCobaltExtensionDemuxerColorSpaceRangeIdDerived = 3
} CobaltExtensionDemuxerColorSpaceRangeId;
// This must be kept in sync with media::VideoDecoderConfig::AlphaMode.
typedef enum CobaltExtensionDemuxerAlphaMode {
kCobaltExtensionDemuxerHasAlpha,
kCobaltExtensionDemuxerIsOpaque
} CobaltExtensionDemuxerAlphaMode;
// This must be kept in sync with ::media::DemuxerStream::Type.
typedef enum CobaltExtensionDemuxerStreamType {
kCobaltExtensionDemuxerStreamTypeUnknown,
kCobaltExtensionDemuxerStreamTypeAudio,
kCobaltExtensionDemuxerStreamTypeVideo,
kCobaltExtensionDemuxerStreamTypeText
} CobaltExtensionDemuxerStreamType;
// This must be kept in sync with media::EncryptionScheme.
typedef enum CobaltExtensionDemuxerEncryptionScheme {
kCobaltExtensionDemuxerEncryptionSchemeUnencrypted,
kCobaltExtensionDemuxerEncryptionSchemeCenc,
kCobaltExtensionDemuxerEncryptionSchemeCbcs,
} CobaltExtensionDemuxerEncryptionScheme;
typedef struct CobaltExtensionDemuxerAudioDecoderConfig {
CobaltExtensionDemuxerAudioCodec codec;
CobaltExtensionDemuxerSampleFormat sample_format;
CobaltExtensionDemuxerChannelLayout channel_layout;
CobaltExtensionDemuxerEncryptionScheme encryption_scheme;
int samples_per_second;
uint8_t* extra_data; // Not owned by this struct.
int64_t extra_data_size;
} CobaltExtensionDemuxerAudioDecoderConfig;
typedef struct CobaltExtensionDemuxerVideoDecoderConfig {
CobaltExtensionDemuxerVideoCodec codec;
CobaltExtensionDemuxerVideoCodecProfile profile;
// These fields represent the color space.
int color_space_primaries;
int color_space_transfer;
int color_space_matrix;
CobaltExtensionDemuxerColorSpaceRangeId color_space_range_id;
CobaltExtensionDemuxerAlphaMode alpha_mode;
// These fields represent the coded size.
int coded_width;
int coded_height;
// These fields represent the visible rectangle.
int visible_rect_x;
int visible_rect_y;
int visible_rect_width;
int visible_rect_height;
// These fields represent the natural size.
int natural_width;
int natural_height;
CobaltExtensionDemuxerEncryptionScheme encryption_scheme;
uint8_t* extra_data; // Not owned by this struct.
int64_t extra_data_size;
} CobaltExtensionDemuxerVideoDecoderConfig;
typedef struct CobaltExtensionDemuxerSideData {
uint8_t* data; // Not owned by this struct.
// Number of bytes in |data|.
int64_t data_size;
// Specifies the format of |data|.
CobaltExtensionDemuxerSideDataType type;
} CobaltExtensionDemuxerSideData;
typedef struct CobaltExtensionDemuxerBuffer {
// The media data for this buffer. Ownership is not transferred via this
// struct.
uint8_t* data;
// Number of bytes in |data|.
int64_t data_size;
// An array of side data elements containing any side data for this buffer.
// Ownership is not transferred via this struct.
CobaltExtensionDemuxerSideData* side_data;
// Number of elements in |side_data|.
int64_t side_data_elements;
// Playback time in microseconds.
SbTime pts;
// Duration of this buffer in microseconds.
SbTime duration;
// True if this buffer contains a keyframe.
bool is_keyframe;
// Signifies the end of the stream. If this is true, the other fields will be
// ignored.
bool end_of_stream;
} CobaltExtensionDemuxerBuffer;
// Note: |buffer| is the input to this function, not the output. Cobalt
// implements this function to read media data provided by the implementer of
// CobaltExtensionDemuxer.
typedef void (*CobaltExtensionDemuxerReadCB)(
CobaltExtensionDemuxerBuffer* buffer, void* user_data);
// A fully synchronous demuxer API. Threading concerns are handled by the code
// that uses this API.
// When calling the defined functions, the |user_data| argument must be the
// void* user_data field stored in this struct.
typedef struct CobaltExtensionDemuxer {
// Initialize must only be called once for a demuxer; subsequent calls can
// fail.
CobaltExtensionDemuxerStatus (*Initialize)(void* user_data);
CobaltExtensionDemuxerStatus (*Seek)(SbTime seek_time, void* user_data);
// Returns the starting time for the media file; it is always positive.
SbTime (*GetStartTime)(void* user_data);
// Returns the time -- in microseconds since Windows epoch -- represented by
// presentation timestamp 0. If the timestamps are not associated with a time,
// returns 0.
SbTime (*GetTimelineOffset)(void* user_data);
// Calls |read_cb| with a buffer of type |type| and the user data provided by
// |read_cb_user_data|. |read_cb| is a synchronous function, so the data
// passed to it can safely be freed after |read_cb| returns. |read_cb| must be
// called exactly once, and it must be called before Read returns.
//
// An error can be handled in one of two ways:
// 1. Pass a null buffer to read_cb. This will cause the pipeline to handle
// the situation as an error. Alternatively,
// 2. Pass an "end of stream" buffer to read_cb. This will cause the relevant
// stream to end normally.
void (*Read)(CobaltExtensionDemuxerStreamType type,
CobaltExtensionDemuxerReadCB read_cb, void* read_cb_user_data,
void* user_data);
// Returns true and populates |audio_config| if an audio stream is present;
// returns false otherwise. |config| must not be null.
bool (*GetAudioConfig)(CobaltExtensionDemuxerAudioDecoderConfig* config,
void* user_data);
// Returns true and populates |video_config| if a video stream is present;
// returns false otherwise. |config| must not be null.
bool (*GetVideoConfig)(CobaltExtensionDemuxerVideoDecoderConfig* config,
void* user_data);
// Returns the duration, in microseconds.
SbTime (*GetDuration)(void* user_data);
// Will be passed to all functions.
void* user_data;
} CobaltExtensionDemuxer;
typedef struct CobaltExtensionDemuxerDataSource {
// Reads up to |bytes_requested|, writing the data into |data| and returning
// the number of bytes read. |data| must be able to store at least
// |bytes_requested| bytes. Calling BlockingRead advances the read position.
int (*BlockingRead)(uint8_t* data, int bytes_requested, void* user_data);
// Seeks to |position| (specified in bytes) in the data source.
void (*SeekTo)(int position, void* user_data);
// Returns the offset into the data source, in bytes.
int64_t (*GetPosition)(void* user_data);
// Returns the size of the data source, in bytes.
int64_t (*GetSize)(void* user_data);
// Whether this represents a streaming data source.
bool is_streaming;
// Will be passed to all functions.
void* user_data;
} CobaltExtensionDemuxerDataSource;
typedef struct CobaltExtensionDemuxerApi {
// Name should be the string |kCobaltExtensionDemuxerApi|.
// This helps to validate that the extension API is correct.
const char* name;
// This specifies the version of the API that is implemented.
uint32_t version;
// The fields below this point were added in version 1 or later.
// Creates a demuxer for the content provided by |data_source|. Ownership of
// |data_source| is not transferred to this function.
//
// Ownership of the returned demuxer is transferred to the caller, but it must
// be deleted via DestroyDemuxer (below). The caller must not manually delete
// the demuxer.
CobaltExtensionDemuxer* (*CreateDemuxer)(
CobaltExtensionDemuxerDataSource* data_source,
CobaltExtensionDemuxerAudioCodec* supported_audio_codecs,
int64_t supported_audio_codecs_size,
CobaltExtensionDemuxerVideoCodec* supported_video_codecs,
int64_t supported_video_codecs_size);
// Destroys |demuxer|. After calling this, |demuxer| must not be dereferenced
// or deleted by the caller.
void (*DestroyDemuxer)(CobaltExtensionDemuxer* demuxer);
} CobaltExtensionDemuxerApi;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // COBALT_EXTENSION_DEMUXER_H_