diff --git a/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java b/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java index 8164adda1569..3e176d4e6566 100644 --- a/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java +++ b/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java @@ -31,6 +31,8 @@ import android.media.MediaFormat; import android.os.Build; import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; import android.view.Surface; import androidx.annotation.Nullable; import dev.cobalt.util.Log; @@ -93,6 +95,9 @@ class MediaCodecBridge { // which would cause GC cycles long enough to impact playback. private final MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); + private Handler mHandler = null; + private HandlerThread mCallbackThread = null; + // Type of bitrate adjustment for video encoder. public enum BitrateAdjustmentTypes { // No adjustment - video encoder has no known bitrate problem. @@ -451,7 +456,8 @@ private MediaCodecBridge( MediaCodec mediaCodec, String mime, BitrateAdjustmentTypes bitrateAdjustmentType, - int tunnelModeAudioSessionId) { + int tunnelModeAudioSessionId, + boolean useCallbackThread) { if (mediaCodec == null) { throw new IllegalArgumentException(); } @@ -461,6 +467,11 @@ private MediaCodecBridge( mLastPresentationTimeUs = 0; mFlushed = true; mBitrateAdjustmentType = bitrateAdjustmentType; + if (useCallbackThread) { + mCallbackThread = new HandlerThread("MediaCodec:Callback:Handler"); + mCallbackThread.start(); + mHandler = new Handler(mCallbackThread.getLooper()); + } mCallback = new MediaCodec.Callback() { @Override @@ -525,7 +536,7 @@ public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) { } } }; - mMediaCodec.setCallback(mCallback); + mMediaCodec.setCallback(mCallback, mHandler); // TODO: support OnFrameRenderedListener for non tunnel mode if (tunnelModeAudioSessionId != -1) { @@ -555,6 +566,7 @@ public static MediaCodecBridge createAudioMediaCodecBridge( int sampleRate, int channelCount, MediaCrypto crypto, + boolean useCallbackThread, @Nullable byte[] configurationData) { if (decoderName.equals("")) { Log.e(TAG, "Invalid decoder name."); @@ -573,7 +585,12 @@ public static MediaCodecBridge createAudioMediaCodecBridge( } MediaCodecBridge bridge = new MediaCodecBridge( - nativeMediaCodecBridge, mediaCodec, mime, BitrateAdjustmentTypes.NO_ADJUSTMENT, -1); + nativeMediaCodecBridge, + mediaCodec, + mime, + BitrateAdjustmentTypes.NO_ADJUSTMENT, + -1, + useCallbackThread); MediaFormat mediaFormat = createAudioFormat(mime, sampleRate, channelCount); @@ -618,6 +635,7 @@ public static void createVideoMediaCodecBridge( MediaCrypto crypto, ColorInfo colorInfo, int tunnelModeAudioSessionId, + boolean useCallbackThread, CreateMediaCodecBridgeResult outCreateMediaCodecBridgeResult) { MediaCodec mediaCodec = null; outCreateMediaCodecBridgeResult.mMediaCodecBridge = null; @@ -671,7 +689,8 @@ public static void createVideoMediaCodecBridge( mediaCodec, mime, BitrateAdjustmentTypes.NO_ADJUSTMENT, - tunnelModeAudioSessionId); + tunnelModeAudioSessionId, + useCallbackThread); MediaFormat mediaFormat = createVideoDecoderFormat(mime, widthHint, heightHint, videoCapabilities); @@ -806,6 +825,11 @@ public void release() { Log.e(TAG, "Cannot release media codec", e); } mMediaCodec = null; + if (mCallbackThread != null) { + mCallbackThread.quitSafely(); + mCallbackThread = null; + mHandler = null; + } } @SuppressWarnings("unused") diff --git a/starboard/android/shared/audio_decoder.cc b/starboard/android/shared/audio_decoder.cc index 60e7a44a88e6..2708ee917a31 100644 --- a/starboard/android/shared/audio_decoder.cc +++ b/starboard/android/shared/audio_decoder.cc @@ -70,12 +70,14 @@ void* IncrementPointerByBytes(void* pointer, int offset) { } // namespace AudioDecoder::AudioDecoder(const AudioStreamInfo& audio_stream_info, - SbDrmSystem drm_system) + SbDrmSystem drm_system, + bool use_mediacodec_callback_thread) : audio_stream_info_(audio_stream_info), sample_type_(GetSupportedSampleType()), output_sample_rate_(audio_stream_info.samples_per_second), output_channel_count_(audio_stream_info.number_of_channels), - drm_system_(static_cast(drm_system)) { + drm_system_(static_cast(drm_system)), + use_mediacodec_callback_thread_(use_mediacodec_callback_thread) { if (!InitializeCodec()) { SB_LOG(ERROR) << "Failed to initialize audio decoder."; } @@ -186,7 +188,8 @@ void AudioDecoder::Reset() { bool AudioDecoder::InitializeCodec() { SB_DCHECK(!media_decoder_); - media_decoder_.reset(new MediaDecoder(this, audio_stream_info_, drm_system_)); + media_decoder_.reset(new MediaDecoder(this, audio_stream_info_, drm_system_, + use_mediacodec_callback_thread_)); if (media_decoder_->is_valid()) { if (error_cb_) { media_decoder_->Initialize( diff --git a/starboard/android/shared/audio_decoder.h b/starboard/android/shared/audio_decoder.h index a57f0ff22fb2..e135f07cba87 100644 --- a/starboard/android/shared/audio_decoder.h +++ b/starboard/android/shared/audio_decoder.h @@ -45,7 +45,8 @@ class AudioDecoder AudioStreamInfo; AudioDecoder(const AudioStreamInfo& audio_stream_info, - SbDrmSystem drm_system); + SbDrmSystem drm_system, + bool use_mediacodec_callback_thread); ~AudioDecoder() override; void Initialize(const OutputCB& output_cb, const ErrorCB& error_cb) override; @@ -83,6 +84,10 @@ class AudioDecoder DrmSystem* drm_system_; + // Set mediacodec callback with a handler on another thread to avoid running + // callbacks on the main thread and being blocked by other main thread tasks. + const bool use_mediacodec_callback_thread_; + OutputCB output_cb_; ErrorCB error_cb_; ConsumedCB consumed_cb_; diff --git a/starboard/android/shared/audio_renderer_passthrough.cc b/starboard/android/shared/audio_renderer_passthrough.cc index 0391ef7e3d18..3b1c97765eb5 100644 --- a/starboard/android/shared/audio_renderer_passthrough.cc +++ b/starboard/android/shared/audio_renderer_passthrough.cc @@ -75,14 +75,15 @@ int ParseAc3SyncframeAudioSampleCount(const uint8_t* buffer, int size) { AudioRendererPassthrough::AudioRendererPassthrough( const AudioStreamInfo& audio_stream_info, - SbDrmSystem drm_system) + SbDrmSystem drm_system, + bool use_mediacodec_callback_thread) : audio_stream_info_(audio_stream_info) { SB_DCHECK(audio_stream_info_.codec == kSbMediaAudioCodecAc3 || audio_stream_info_.codec == kSbMediaAudioCodecEac3); if (SbDrmSystemIsValid(drm_system)) { SB_LOG(INFO) << "Creating AudioDecoder as decryptor."; - scoped_ptr audio_decoder( - new AudioDecoder(audio_stream_info, drm_system)); + scoped_ptr audio_decoder(new AudioDecoder( + audio_stream_info, drm_system, use_mediacodec_callback_thread)); if (audio_decoder->is_valid()) { decoder_.reset(audio_decoder.release()); } diff --git a/starboard/android/shared/audio_renderer_passthrough.h b/starboard/android/shared/audio_renderer_passthrough.h index a17c116a592a..e317b9051b95 100644 --- a/starboard/android/shared/audio_renderer_passthrough.h +++ b/starboard/android/shared/audio_renderer_passthrough.h @@ -53,7 +53,8 @@ class AudioRendererPassthrough AudioStreamInfo; AudioRendererPassthrough(const AudioStreamInfo& audio_stream_info, - SbDrmSystem drm_system); + SbDrmSystem drm_system, + bool use_mediacodec_callback_thread); ~AudioRendererPassthrough() override; bool is_valid() const { return decoder_ != nullptr; } diff --git a/starboard/android/shared/media_codec_bridge.cc b/starboard/android/shared/media_codec_bridge.cc index a5b92e6ba977..22e795ded0b3 100644 --- a/starboard/android/shared/media_codec_bridge.cc +++ b/starboard/android/shared/media_codec_bridge.cc @@ -158,7 +158,8 @@ Java_dev_cobalt_media_MediaCodecBridge_nativeOnMediaCodecOutputFormatChanged( scoped_ptr MediaCodecBridge::CreateAudioMediaCodecBridge( const AudioStreamInfo& audio_stream_info, Handler* handler, - jobject j_media_crypto) { + jobject j_media_crypto, + bool use_callback_thread) { bool is_passthrough = false; const char* mime = SupportedAudioCodecToMimeType(audio_stream_info.codec, &is_passthrough); @@ -193,11 +194,11 @@ scoped_ptr MediaCodecBridge::CreateAudioMediaCodecBridge( new MediaCodecBridge(handler)); jobject j_media_codec_bridge = env->CallStaticObjectMethodOrAbort( "dev/cobalt/media/MediaCodecBridge", "createAudioMediaCodecBridge", - "(JLjava/lang/String;Ljava/lang/String;IILandroid/media/MediaCrypto;" + "(JLjava/lang/String;Ljava/lang/String;IILandroid/media/MediaCrypto;Z" "[B)Ldev/cobalt/media/MediaCodecBridge;", reinterpret_cast(native_media_codec_bridge.get()), j_mime.Get(), j_decoder_name.Get(), audio_stream_info.samples_per_second, - audio_stream_info.number_of_channels, j_media_crypto, + audio_stream_info.number_of_channels, j_media_crypto, use_callback_thread, configuration_data.Get()); if (!j_media_codec_bridge) { @@ -227,6 +228,7 @@ scoped_ptr MediaCodecBridge::CreateVideoMediaCodecBridge( bool require_software_codec, int tunnel_mode_audio_session_id, bool force_big_endian_hdr_metadata, + bool use_callback_thread, std::string* error_message) { SB_DCHECK(error_message); SB_DCHECK(max_width.has_engaged() == max_height.has_engaged()); @@ -316,14 +318,14 @@ scoped_ptr MediaCodecBridge::CreateVideoMediaCodecBridge( "(JLjava/lang/String;Ljava/lang/String;IIIIILandroid/view/Surface;" "Landroid/media/MediaCrypto;" "Ldev/cobalt/media/MediaCodecBridge$ColorInfo;" - "I" + "IZ" "Ldev/cobalt/media/MediaCodecBridge$CreateMediaCodecBridgeResult;)" "V", reinterpret_cast(native_media_codec_bridge.get()), j_mime.Get(), j_decoder_name.Get(), width_hint, height_hint, fps, max_width.value_or(-1), max_height.value_or(-1), j_surface, j_media_crypto, j_color_info.Get(), tunnel_mode_audio_session_id, - j_create_media_codec_bridge_result.Get()); + use_callback_thread, j_create_media_codec_bridge_result.Get()); jobject j_media_codec_bridge = env->CallObjectMethodOrAbort( j_create_media_codec_bridge_result.Get(), "mediaCodecBridge", diff --git a/starboard/android/shared/media_codec_bridge.h b/starboard/android/shared/media_codec_bridge.h index 5c1e4598d2a9..89e2c96a21f2 100644 --- a/starboard/android/shared/media_codec_bridge.h +++ b/starboard/android/shared/media_codec_bridge.h @@ -147,7 +147,8 @@ class MediaCodecBridge { static scoped_ptr CreateAudioMediaCodecBridge( const AudioStreamInfo& audio_stream_info, Handler* handler, - jobject j_media_crypto); + jobject j_media_crypto, + bool use_callback_thread); // `max_width` and `max_height` can be set to positive values to specify the // maximum resolutions the video can be adapted to. @@ -173,6 +174,7 @@ class MediaCodecBridge { bool require_software_codec, int tunnel_mode_audio_session_id, bool force_big_endian_hdr_metadata, + bool use_callback_thread, std::string* error_message); ~MediaCodecBridge(); diff --git a/starboard/android/shared/media_decoder.cc b/starboard/android/shared/media_decoder.cc index 26608686347b..7a39b912d9e2 100644 --- a/starboard/android/shared/media_decoder.cc +++ b/starboard/android/shared/media_decoder.cc @@ -76,7 +76,8 @@ const char* GetDecoderName(SbMediaType media_type) { MediaDecoder::MediaDecoder(Host* host, const AudioStreamInfo& audio_stream_info, - SbDrmSystem drm_system) + SbDrmSystem drm_system, + bool use_mediacodec_callback_thread) : media_type_(kSbMediaTypeAudio), host_(host), drm_system_(static_cast(drm_system)), @@ -87,7 +88,7 @@ MediaDecoder::MediaDecoder(Host* host, jobject j_media_crypto = drm_system_ ? drm_system_->GetMediaCrypto() : NULL; SB_DCHECK(!drm_system_ || j_media_crypto); media_codec_bridge_ = MediaCodecBridge::CreateAudioMediaCodecBridge( - audio_stream_info, this, j_media_crypto); + audio_stream_info, this, j_media_crypto, use_mediacodec_callback_thread); if (!media_codec_bridge_) { SB_LOG(ERROR) << "Failed to create audio media codec bridge."; return; @@ -118,6 +119,7 @@ MediaDecoder::MediaDecoder(Host* host, const FrameRenderedCB& frame_rendered_cb, int tunnel_mode_audio_session_id, bool force_big_endian_hdr_metadata, + bool use_mediacodec_callback_thread, std::string* error_message) : media_type_(kSbMediaTypeVideo), host_(host), @@ -135,7 +137,8 @@ MediaDecoder::MediaDecoder(Host* host, video_codec, width_hint, height_hint, fps, max_width, max_height, this, j_output_surface, j_media_crypto, color_metadata, require_secured_decoder, require_software_codec, tunnel_mode_audio_session_id, - force_big_endian_hdr_metadata, error_message); + force_big_endian_hdr_metadata, use_mediacodec_callback_thread, + error_message); if (!media_codec_bridge_) { SB_LOG(ERROR) << "Failed to create video media codec bridge with error: " << *error_message; diff --git a/starboard/android/shared/media_decoder.h b/starboard/android/shared/media_decoder.h index 3b62e1de0d86..548ee4b0ef72 100644 --- a/starboard/android/shared/media_decoder.h +++ b/starboard/android/shared/media_decoder.h @@ -79,7 +79,8 @@ class MediaDecoder MediaDecoder(Host* host, const AudioStreamInfo& audio_stream_info, - SbDrmSystem drm_system); + SbDrmSystem drm_system, + bool use_mediacodec_callback_thread); MediaDecoder(Host* host, SbMediaVideoCodec video_codec, // `width_hint` and `height_hint` are used to create the Android @@ -97,6 +98,7 @@ class MediaDecoder const FrameRenderedCB& frame_rendered_cb, int tunnel_mode_audio_session_id, bool force_big_endian_hdr_metadata, + bool use_mediacodec_callback_thread, std::string* error_message); ~MediaDecoder(); diff --git a/starboard/android/shared/media_is_video_supported.cc b/starboard/android/shared/media_is_video_supported.cc index c6e0462d750b..5ad383ef1009 100644 --- a/starboard/android/shared/media_is_video_supported.cc +++ b/starboard/android/shared/media_is_video_supported.cc @@ -92,6 +92,10 @@ bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, false)) { MaxMediaCodecOutputBuffersLookupTable::GetInstance()->SetEnabled(false); } + + if (!mime_type->ValidateBoolParameter("mediacodeccallbackthread")) { + return false; + } } if (must_support_tunnel_mode && decode_to_texture_required) { diff --git a/starboard/android/shared/player_components_factory.h b/starboard/android/shared/player_components_factory.h index ce38ebadcff0..cfef5c7aa0d8 100644 --- a/starboard/android/shared/player_components_factory.h +++ b/starboard/android/shared/player_components_factory.h @@ -207,10 +207,12 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player:: error_message); } + bool audio_use_mediacodec_callback_thread = true; if (!creation_parameters.audio_mime().empty()) { MimeType audio_mime_type(creation_parameters.audio_mime()); if (!audio_mime_type.is_valid() || - !audio_mime_type.ValidateBoolParameter("audiopassthrough")) { + !audio_mime_type.ValidateBoolParameter("audiopassthrough") || + !audio_mime_type.ValidateBoolParameter("mediacodeccallbackthread")) { return scoped_ptr(); } @@ -219,6 +221,8 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player:: "false. Passthrough is disabled."; return scoped_ptr(); } + audio_use_mediacodec_callback_thread = + audio_mime_type.GetParamBoolValue("mediacodeccallbackthread", true); } SB_LOG(INFO) << "Creating passthrough components."; @@ -226,7 +230,8 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player:: scoped_ptr audio_renderer; audio_renderer.reset( new AudioRendererPassthrough(creation_parameters.audio_stream_info(), - creation_parameters.drm_system())); + creation_parameters.drm_system(), + audio_use_mediacodec_callback_thread)); if (!audio_renderer->is_valid()) { return scoped_ptr(); } @@ -237,9 +242,21 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player:: constexpr int kTunnelModeAudioSessionId = -1; constexpr bool kForceSecurePipelineUnderTunnelMode = false; + bool video_use_mediacodec_callback_thread = true; + if (!creation_parameters.video_mime().empty()) { + MimeType video_mime_type(creation_parameters.video_mime()); + if (!video_mime_type.is_valid() || + !video_mime_type.ValidateBoolParameter( + "mediacodeccallbackthread")) { + return scoped_ptr(); + } + video_use_mediacodec_callback_thread = + video_mime_type.GetParamBoolValue("mediacodeccallbackthread", true); + } scoped_ptr video_decoder = CreateVideoDecoder( creation_parameters, kTunnelModeAudioSessionId, - kForceSecurePipelineUnderTunnelMode, error_message); + kForceSecurePipelineUnderTunnelMode, + video_use_mediacodec_callback_thread, error_message); if (video_decoder) { using starboard::shared::starboard::player::filter::VideoRendererImpl; @@ -275,7 +292,8 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player:: : ""; MimeType audio_mime_type(audio_mime); if (!audio_mime.empty()) { - if (!audio_mime_type.is_valid()) { + if (!audio_mime_type.is_valid() || + !audio_mime_type.ValidateBoolParameter("mediacodeccallbackthread")) { *error_message = "Invalid audio MIME: '" + std::string(audio_mime) + "'"; return false; @@ -289,7 +307,8 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player:: MimeType video_mime_type(video_mime); if (!video_mime.empty()) { if (!video_mime_type.is_valid() || - !video_mime_type.ValidateBoolParameter("tunnelmode")) { + !video_mime_type.ValidateBoolParameter("tunnelmode") || + !video_mime_type.ValidateBoolParameter("mediacodeccallbackthread")) { *error_message = "Invalid video MIME: '" + std::string(video_mime) + "'"; return false; @@ -355,8 +374,11 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player:: SB_DCHECK(audio_renderer_sink); using starboard::shared::starboard::media::AudioStreamInfo; - auto decoder_creator = [](const AudioStreamInfo& audio_stream_info, - SbDrmSystem drm_system) { + bool audio_use_mediacodec_callback_thread = + audio_mime_type.GetParamBoolValue("mediacodeccallbackthread", true); + auto decoder_creator = [audio_use_mediacodec_callback_thread]( + const AudioStreamInfo& audio_stream_info, + SbDrmSystem drm_system) { bool use_libopus_decoder = audio_stream_info.codec == kSbMediaAudioCodecOpus && !SbDrmSystemIsValid(drm_system) && !kForcePlatformOpusDecoder; @@ -369,7 +391,8 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player:: } else if (audio_stream_info.codec == kSbMediaAudioCodecAac || audio_stream_info.codec == kSbMediaAudioCodecOpus) { scoped_ptr audio_decoder_impl( - new AudioDecoder(audio_stream_info, drm_system)); + new AudioDecoder(audio_stream_info, drm_system, + audio_use_mediacodec_callback_thread)); if (audio_decoder_impl->is_valid()) { return audio_decoder_impl.PassAs(); } @@ -405,10 +428,12 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player:: if (tunnel_mode_audio_session_id == -1) { force_secure_pipeline_under_tunnel_mode = false; } - + bool video_use_mediacodec_callback_thread = + video_mime_type.GetParamBoolValue("mediacodeccallbackthread", true); scoped_ptr video_decoder_impl = CreateVideoDecoder( creation_parameters, tunnel_mode_audio_session_id, - force_secure_pipeline_under_tunnel_mode, error_message); + force_secure_pipeline_under_tunnel_mode, + video_use_mediacodec_callback_thread, error_message); if (video_decoder_impl) { *video_render_algorithm = video_decoder_impl->GetRenderAlgorithm(); *video_renderer_sink = video_decoder_impl->GetSink(); @@ -452,6 +477,7 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player:: const CreationParameters& creation_parameters, int tunnel_mode_audio_session_id, bool force_secure_pipeline_under_tunnel_mode, + bool use_mediacodec_callback_thread, std::string* error_message) { bool force_big_endian_hdr_metadata = false; if (!creation_parameters.video_mime().empty()) { @@ -473,7 +499,7 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player:: creation_parameters.max_video_capabilities(), tunnel_mode_audio_session_id, force_secure_pipeline_under_tunnel_mode, kForceResetSurfaceUnderTunnelMode, force_big_endian_hdr_metadata, - error_message)); + use_mediacodec_callback_thread, error_message)); if (creation_parameters.video_codec() == kSbMediaVideoCodecAv1 || video_decoder->is_decoder_created()) { return video_decoder.Pass(); diff --git a/starboard/android/shared/video_decoder.cc b/starboard/android/shared/video_decoder.cc index a6d9030b09fe..6f9db75f2039 100644 --- a/starboard/android/shared/video_decoder.cc +++ b/starboard/android/shared/video_decoder.cc @@ -356,6 +356,7 @@ VideoDecoder::VideoDecoder(const VideoStreamInfo& video_stream_info, bool force_secure_pipeline_under_tunnel_mode, bool force_reset_surface_under_tunnel_mode, bool force_big_endian_hdr_metadata, + bool use_mediacodec_callback_thread, std::string* error_message) : video_codec_(video_stream_info.codec), drm_system_(static_cast(drm_system)), @@ -370,7 +371,8 @@ VideoDecoder::VideoDecoder(const VideoStreamInfo& video_stream_info, surface_condition_variable_(surface_destroy_mutex_), require_software_codec_(IsSoftwareDecodeRequired(max_video_capabilities)), force_big_endian_hdr_metadata_(force_big_endian_hdr_metadata), - number_of_preroll_frames_(kInitialPrerollFrameCount) { + number_of_preroll_frames_(kInitialPrerollFrameCount), + use_mediacodec_callback_thread_(use_mediacodec_callback_thread) { SB_DCHECK(error_message); if (tunnel_mode_audio_session_id != -1) { @@ -711,7 +713,7 @@ bool VideoDecoder::InitializeCodec(const VideoStreamInfo& video_stream_info, color_metadata_ ? &*color_metadata_ : nullptr, require_software_codec_, std::bind(&VideoDecoder::OnTunnelModeFrameRendered, this, _1), tunnel_mode_audio_session_id_, force_big_endian_hdr_metadata_, - error_message)); + use_mediacodec_callback_thread_, error_message)); if (media_decoder_->is_valid()) { if (error_cb_) { media_decoder_->Initialize( diff --git a/starboard/android/shared/video_decoder.h b/starboard/android/shared/video_decoder.h index 606a7c38294a..85a211302118 100644 --- a/starboard/android/shared/video_decoder.h +++ b/starboard/android/shared/video_decoder.h @@ -70,6 +70,7 @@ class VideoDecoder bool force_secure_pipeline_under_tunnel_mode, bool force_reset_surface_under_tunnel_mode, bool force_big_endian_hdr_metadata, + bool use_mediacodec_callback_thread, std::string* error_message); ~VideoDecoder() override; @@ -209,6 +210,10 @@ class VideoDecoder bool first_output_format_changed_ = false; optional output_format_; size_t number_of_preroll_frames_; + + // Set mediacodec callback with a handler on another thread to avoid running + // callbacks on the main thread and being blocked by other main thread tasks. + const bool use_mediacodec_callback_thread_; }; } // namespace shared