| // Copyright 2016 Google Inc. 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. |
| |
| // Module Overview: Starboard Player module |
| // |
| // Defines an interface for controlling playback of media elementary streams. |
| |
| #ifndef STARBOARD_PLAYER_H_ |
| #define STARBOARD_PLAYER_H_ |
| |
| #include "starboard/configuration.h" |
| |
| #if SB_HAS(PLAYER) |
| |
| #include "starboard/decode_target.h" |
| #include "starboard/drm.h" |
| #include "starboard/export.h" |
| #include "starboard/media.h" |
| #include "starboard/types.h" |
| #include "starboard/window.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| // --- Types ----------------------------------------------------------------- |
| |
| // An indicator of whether the decoder can accept more samples. |
| typedef enum SbPlayerDecoderState { |
| // The decoder is asking for one more sample. |
| kSbPlayerDecoderStateNeedsData, |
| |
| // The decoder is not ready for any more samples, so do not send them. |
| // Note that this enum value has been deprecated and the SbPlayer |
| // implementation should no longer use this value. |
| kSbPlayerDecoderStateBufferFull, |
| |
| // The player has been destroyed, and will send no more callbacks. |
| kSbPlayerDecoderStateDestroyed, |
| } SbPlayerDecoderState; |
| |
| // An indicator of the general playback state. |
| typedef enum SbPlayerState { |
| // The player has just been initialized. It is expecting an SbPlayerSeek() |
| // call to enter the prerolling state. |
| kSbPlayerStateInitialized, |
| |
| // The player is prerolling, collecting enough data to fill the pipeline |
| // before presentation starts. After the first preroll is completed, there |
| // should always be a video frame to render, even if the player goes back to |
| // Prerolling after a Seek. |
| kSbPlayerStatePrerolling, |
| |
| // The player is presenting media, and it is either paused or actively |
| // playing in real-time. Note that the implementation should use this |
| // state to signal that the preroll has been finished. |
| kSbPlayerStatePresenting, |
| |
| // The player is presenting media, but it is paused at the end of the stream. |
| kSbPlayerStateEndOfStream, |
| |
| // The player has been destroyed, and will send no more callbacks. |
| kSbPlayerStateDestroyed, |
| |
| // The player encountered an error. It expects an SbPlayerDestroy() call |
| // to tear down the player. Calls to other functions may be ignored and |
| // callbacks may not be triggered. |
| kSbPlayerStateError, |
| } SbPlayerState; |
| |
| // Information about the current media playback state. |
| typedef struct SbPlayerInfo { |
| // The position of the playback head, as precisely as possible, in 90KHz ticks |
| // (PTS). |
| SbMediaTime current_media_pts; |
| |
| // The known duration of the currently playing media stream, in 90KHz ticks |
| // (PTS). |
| SbMediaTime duration_pts; |
| |
| // The width of the currently displayed frame, in pixels, or 0 if not provided |
| // by this player. |
| int frame_width; |
| |
| // The height of the currently displayed frame, in pixels, or 0 if not |
| // provided by this player. |
| int frame_height; |
| |
| // Whether playback is currently paused. |
| bool is_paused; |
| |
| // The current player volume in [0, 1]. |
| double volume; |
| |
| // The number of video frames sent to the player since the creation of the |
| // player. |
| int total_video_frames; |
| |
| // The number of video frames decoded but not displayed since the creation of |
| // the player. |
| int dropped_video_frames; |
| |
| // The number of video frames that failed to be decoded since the creation of |
| // the player. |
| int corrupted_video_frames; |
| } SbPlayerInfo; |
| |
| // An opaque handle to an implementation-private structure representing a |
| // player. |
| typedef struct SbPlayerPrivate* SbPlayer; |
| |
| // Callback for decoder status updates, called in response to a call to |
| // SbPlayerSeek() or SbPlayerWriteSample(). This callback will never be called |
| // until at least one call to SbPlayerSeek has occurred. |ticket| will be set to |
| // the ticket passed into the last received call to SbPlayerSeek() at the time |
| // this callback was dispatched. This is to distinguish status callbacks for |
| // interrupting seeks. These callbacks will happen on a different thread than |
| // the calling thread, and it is not valid to call SbPlayer functions from |
| // within this callback. After an update with kSbPlayerDecoderStateNeedsData, |
| // the user of the player will make at most one call to SbPlayerWriteSample() or |
| // SbPlayerWriteEndOfStream(). The player implementation should update the |
| // decoder status again after such call to notify its user to continue writing |
| // more frames. |
| typedef void (*SbPlayerDecoderStatusFunc)(SbPlayer player, |
| void* context, |
| SbMediaType type, |
| SbPlayerDecoderState state, |
| int ticket); |
| |
| // Callback for player status updates. These callbacks will happen on a |
| // different thread than the calling thread, and it is not valid to call |
| // SbPlayer functions from within this callback. |
| typedef void (*SbPlayerStatusFunc)(SbPlayer player, |
| void* context, |
| SbPlayerState state, |
| int ticket); |
| |
| // Callback to free the given sample buffer data. |
| typedef void (*SbPlayerDeallocateSampleFunc)(SbPlayer player, |
| void* context, |
| const void* sample_buffer); |
| |
| #if SB_IS(PLAYER_COMPOSITED) |
| // A handle that can be used to compose a player's video output with other |
| // composition layers. |
| // TODO: Define a SbCompositor interface with a composition handle type. |
| typedef uint32_t SbPlayerCompositionHandle; |
| #endif |
| |
| // --- Constants ------------------------------------------------------------- |
| |
| // The value to pass into SbPlayerCreate's |duration_ptr| argument for cases |
| // where the duration is unknown, such as for live streams. |
| #define SB_PLAYER_NO_DURATION (-1) |
| |
| // The value of the initial ticket held by the player before the first seek. |
| // The player will use this ticket value to make the first call to |
| // SbPlayerStatusFunc with kSbPlayerStateInitialized. |
| #define SB_PLAYER_INITIAL_TICKET (0) |
| |
| // Well-defined value for an invalid player. |
| #define kSbPlayerInvalid ((SbPlayer)NULL) |
| |
| // Returns whether the given player handle is valid. |
| SB_C_INLINE bool SbPlayerIsValid(SbPlayer player) { |
| return player != kSbPlayerInvalid; |
| } |
| |
| // --- Functions ------------------------------------------------------------- |
| |
| // Creates a player that will be displayed on |window| for the specified |
| // |video_codec| and |audio_codec|, acquiring all resources needed to operate |
| // it, and returning an opaque handle to it. The expectation is that a new |
| // player will be created and destroyed for every playback. |
| // |
| // This function returns the created player. Note the following: |
| // - The associated decoder of the returned player should be assumed to not be |
| // in |kSbPlayerDecoderStateNeedsData| until SbPlayerSeek() has been called |
| // on it. |
| // - It is expected either that the thread that calls SbPlayerCreate is the same |
| // thread that calls the other |SbPlayer| functions for that player, or that |
| // there is a mutex guarding calls into each |SbPlayer| instance. |
| // - If there is a platform limitation on how many players can coexist |
| // simultaneously, then calls made to this function that attempt to exceed |
| // that limit will return |kSbPlayerInvalid|. |
| // |
| // |window|: The window that will display the player. |window| can be |
| // |kSbWindowInvalid| for platforms where video is only displayed on a |
| // particular window that the underlying implementation already has access to. |
| // |
| // |video_codec|: The video codec used for the player. If |video_codec| is |
| // |kSbMediaVideoCodecNone|, the player is an audio-only player. If |
| // |video_codec| is any other value, the player is an audio/video decoder. |
| // |
| // |audio_codec|: The audio codec used for the player. The value should never |
| // be |kSbMediaAudioCodecNone|. In addition, the caller must provide a |
| // populated |audio_header| if the audio codec is |kSbMediaAudioCodecAac|. |
| // |
| // |duration_pts|: The expected media duration in 90KHz ticks (PTS). It may be |
| // set to |SB_PLAYER_NO_DURATION| for live streams. |
| // |
| // |drm_system|: If the media stream has encrypted portions, then this |
| // parameter provides an appropriate DRM system, created with |
| // |SbDrmCreateSystem()|. If the stream does not have encrypted portions, |
| // then |drm_system| may be |kSbDrmSystemInvalid|. |
| // |
| // |audio_header|: Note that the caller must provide a populated |audio_header| |
| // if the audio codec is |kSbMediaAudioCodecAac|. Otherwise, |audio_header| |
| // can be NULL. See media.h for the format of the |SbMediaAudioHeader| struct. |
| // |
| // |sample_deallocator_func|: If not |NULL|, the player calls this function |
| // on an internal thread to free the sample buffers passed into |
| // SbPlayerWriteSample(). |
| // |
| // |decoder_status_func|: If not |NULL|, the decoder calls this function on an |
| // internal thread to provide an update on the decoder's status. No work |
| // should be done on this thread. Rather, it should just signal the client |
| // thread interacting with the decoder. |
| // |
| // |player_status_func|: If not |NULL|, the player calls this function on an |
| // internal thread to provide an update on the playback status. No work |
| // should be done on this thread. Rather, it should just signal the client |
| // thread interacting with the decoder. |
| // |
| // |context|: This is passed to all callbacks and is generally used to point |
| // at a class or struct that contains state associated with the player. |
| // |
| // |provider|: Only present in Starboard version 3 and up. If not |NULL|, |
| // then when SB_HAS(PLAYER_PRODUCING_TEXTURE) is true, the player MAY use the |
| // provider to create SbDecodeTargets. A provider could also potentially be |
| // required by the player, in which case, if the provider is not given, the |
| // player will fail by returning kSbPlayerInvalid. |
| SB_EXPORT SbPlayer SbPlayerCreate( |
| SbWindow window, |
| SbMediaVideoCodec video_codec, |
| SbMediaAudioCodec audio_codec, |
| SbMediaTime duration_pts, |
| SbDrmSystem drm_system, |
| const SbMediaAudioHeader* audio_header, |
| SbPlayerDeallocateSampleFunc sample_deallocate_func, |
| SbPlayerDecoderStatusFunc decoder_status_func, |
| SbPlayerStatusFunc player_status_func, |
| void* context |
| #if SB_VERSION(3) |
| , |
| SbDecodeTargetProvider* provider |
| #endif // SB_VERSION(3) |
| ); // NOLINT |
| |
| // Destroys |player|, freeing all associated resources. Each callback must |
| // receive one more callback to say that the player was destroyed. Callbacks |
| // may be in-flight when SbPlayerDestroy is called, and should be ignored once |
| // this function is called. |
| // |
| // It is not allowed to pass |player| into any other |SbPlayer| function once |
| // SbPlayerDestroy has been called on that player. |
| // |
| // |player|: The player to be destroyed. |
| SB_EXPORT void SbPlayerDestroy(SbPlayer player); |
| |
| // Tells the player to freeze playback (if playback has already started), |
| // reset or flush the decoder pipeline, and go back to the Prerolling state. |
| // The player should restart playback once it can display the frame at |
| // |seek_to_pts|, or the closest it can get. (Some players can only seek to |
| // I-Frames, for example.) |
| // |
| // - Seek must be called before samples are sent when starting playback for |
| // the first time, or the client never receives the |
| // |kSbPlayerDecoderStateNeedsData| signal. |
| // - A call to seek may interrupt another seek. |
| // - After this function is called, the client should not send any more audio |
| // or video samples until |SbPlayerDecoderStatusFunc| is called back with |
| // |kSbPlayerDecoderStateNeedsData| for each required media type. |
| // |SbPlayerDecoderStatusFunc| is the |decoder_status_func| callback function |
| // that was specified when the player was created (SbPlayerCreate). |
| // |
| // |player|: The SbPlayer in which the seek operation is being performed. |
| // |seek_to_pts|: The frame at which playback should begin. |
| // |ticket|: A user-supplied unique ID that is be passed to all subsequent |
| // |SbPlayerDecoderStatusFunc| calls. (That is the |decoder_status_func| |
| // callback function specified when calling SbPlayerCreate.) |
| // |
| // The |ticket| value is used to filter calls that may have been in flight |
| // when SbPlayerSeek was called. To be very specific, once SbPlayerSeek has |
| // been called with ticket X, a client should ignore all |
| // |SbPlayerDecoderStatusFunc| calls that do not pass in ticket X. |
| SB_EXPORT void SbPlayerSeek(SbPlayer player, |
| SbMediaTime seek_to_pts, |
| int ticket); |
| |
| // Writes a sample of the given media type to |player|'s input stream. The |
| // lifetime of |video_sample_info| and |sample_drm_info| (as well as member |
| // |subsample_mapping| contained inside it) are not guaranteed past the call |
| // to SbPlayerWriteSample. That means that before returning, the implementation |
| // must synchronously copy any information it wants to retain from those |
| // structures. |
| // |
| // |player|: The player to which the sample is written. |
| // |sample_type|: The type of sample being written. See the |SbMediaType| |
| // enum in media.h. |
| // |sample_buffer|: A pointer to a buffer with the data for this sample. The |
| // buffer is expected to be a portion of a bytestream of the codec type that |
| // the player was created with. The buffer should contain a sequence of whole |
| // NAL Units for video, or a complete audio frame. |
| // |sample_buffer_size|: The number of bytes in the given sample. |
| // |sample_pts|: The timestamp of the sample in 90KHz ticks (PTS). Note that |
| // samples MAY be written "slightly" out of order. |
| // |video_sample_info|: Information about a video sample. This value is |
| // required if |sample_type| is |kSbMediaTypeVideo|. Otherwise, it must be |
| // |NULL|. |
| // |sample_drm_info|: The DRM system for the media sample. This value is |
| // required for encrypted samples. Otherwise, it must be |NULL|. |
| SB_EXPORT void SbPlayerWriteSample( |
| SbPlayer player, |
| SbMediaType sample_type, |
| const void* sample_buffer, |
| int sample_buffer_size, |
| SbMediaTime sample_pts, |
| const SbMediaVideoSampleInfo* video_sample_info, |
| const SbDrmSampleInfo* sample_drm_info); |
| |
| // Writes a marker to |player|'s input stream of |stream_type| indicating that |
| // there are no more samples for that media type for the remainder of this |
| // media stream. This marker is invalidated, along with the rest of the stream's |
| // contents, after a call to SbPlayerSeek. |
| // |
| // |player|: The player to which the marker is written. |
| // |stream_type|: The type of stream for which the marker is written. |
| SB_EXPORT void SbPlayerWriteEndOfStream(SbPlayer player, |
| SbMediaType stream_type); |
| |
| #if SB_IS(PLAYER_PUNCHED_OUT) |
| // Sets the player bounds to the given graphics plane coordinates. The changes |
| // do not take effect until the next graphics frame buffer swap. The default |
| // bounds for a player is the full screen. |
| // |
| // This function is called on every graphics frame that changes the video |
| // bounds. For example, if the video bounds are being animated, then this will |
| // be called at up to 60 Hz. Since the function could be called up to once per |
| // frame, implementors should take care to avoid related performance concerns |
| // with such frequent calls. |
| // |
| // |player|: The player that is being resized. |
| // |x|: The x-coordinate of the upper-left corner of the player. |
| // |y|: The y-coordinate of the upper-left corner of the player. |
| // |width|: The width of the player, in pixels. |
| // |height|: The height of the player, in pixels. |
| SB_EXPORT void SbPlayerSetBounds(SbPlayer player, |
| int x, |
| int y, |
| int width, |
| int height); |
| #endif |
| |
| // Pauses or unpauses the |player|. If the |player|'s state is |
| // |kPlayerStatePrerolling|, this function sets the initial pause state for |
| // the current seek target. |
| SB_EXPORT void SbPlayerSetPause(SbPlayer player, bool pause); |
| |
| // Sets the player's volume. |
| // |
| // |player|: The player in which the volume is being adjusted. |
| // |volume|: The new player volume. The value must be between |0.0| and |1.0|, |
| // inclusive. A value of |0.0| means that the audio should be muted, and a |
| // value of |1.0| means that it should be played at full volume. |
| SB_EXPORT void SbPlayerSetVolume(SbPlayer player, double volume); |
| |
| // Gets a snapshot of the current player state and writes it to |
| // |out_player_info|. This function may be called very frequently and is |
| // expected to be inexpensive. |
| // |
| // |player|: The player about which information is being retrieved. |
| // |out_player_info|: The information retrieved for the player. |
| SB_EXPORT void SbPlayerGetInfo(SbPlayer player, SbPlayerInfo* out_player_info); |
| |
| #if SB_IS(PLAYER_COMPOSITED) |
| // Gets a handle that represents the player's video output, for the purpose of |
| // composing with |SbCompositor|, which is currently undefined. |
| // |
| // |player|: The player for which the video output handle is retrieved. |
| SB_EXPORT SbPlayerCompositionHandle |
| SbPlayerGetCompositionHandle(SbPlayer player); |
| #endif |
| |
| #if SB_IS(PLAYER_PRODUCING_TEXTURE) |
| // Gets an OpenGL texture ID that points to the player's video output frame at |
| // the time it was called. This function can be called once, and the texture ID |
| // will be appropriately remapped to the current video frame when it is drawn. |
| // |
| // |player|: The player for which the texture ID is retrieved. |
| SB_EXPORT uint32_t SbPlayerGetTextureId(SbPlayer player); |
| #endif |
| |
| #ifdef __cplusplus |
| } // extern "C" |
| #endif |
| |
| #endif // SB_HAS(PLAYER) |
| |
| #endif // STARBOARD_PLAYER_H_ |