Skip to content

Commit

Permalink
[android] Support KEY_MAX_INPUT_SIZE configurable from the webapp
Browse files Browse the repository at this point in the history
1. Add an h5vcc setting "Media.MaxInputSize" to allow the web app to explicitly set the MediaFormat.KEY_MAX_INPUT_SIZE.
2. This can also be set via MIME attribute "maxinputsize".
3. Use -1 for default value. It the setting value is smaller than default value, it will be ignored.

b/176923480
  • Loading branch information
borongc committed Nov 29, 2023
1 parent c905013 commit 769980f
Show file tree
Hide file tree
Showing 20 changed files with 174 additions and 12 deletions.
4 changes: 4 additions & 0 deletions cobalt/media/base/sbplayer_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ void DefaultSbPlayerInterface::SetVolume(SbPlayer player, double volume) {
SbPlayerSetVolume(player, volume);
}

bool DefaultSbPlayerInterface::SetMaxInputSize(int max_input_size) {
return SbPlayerSetMaxInputSize(max_input_size);
}

void DefaultSbPlayerInterface::GetInfo(SbPlayer player,
#if SB_API_VERSION >= 15
SbPlayerInfo* out_player_info) {
Expand Down
2 changes: 2 additions & 0 deletions cobalt/media/base/sbplayer_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class SbPlayerInterface {
int height) = 0;
virtual bool SetPlaybackRate(SbPlayer player, double playback_rate) = 0;
virtual void SetVolume(SbPlayer player, double volume) = 0;
virtual bool SetMaxInputSize(int max_input_size) = 0;

#if SB_API_VERSION >= 15
virtual void GetInfo(SbPlayer player, SbPlayerInfo* out_player_info) = 0;
Expand Down Expand Up @@ -124,6 +125,7 @@ class DefaultSbPlayerInterface final : public SbPlayerInterface {
int height) override;
bool SetPlaybackRate(SbPlayer player, double playback_rate) override;
void SetVolume(SbPlayer player, double volume) override;
bool SetMaxInputSize(int max_input_size) override;
#if SB_API_VERSION >= 15
void GetInfo(SbPlayer player, SbPlayerInfo* out_player_info) override;
#else // SB_API_VERSION >= 15
Expand Down
3 changes: 3 additions & 0 deletions cobalt/media/media_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ bool MediaModule::SetConfiguration(const std::string& name, int32 value) {
LOG(INFO) << (value ? "Enabling" : "Disabling")
<< " media metrics collection.";
return true;
} else if (name == "MaxInputSize") {
LOG(INFO) << "Video max_input_size is set to " << value << " via h5vcc.";
return sbplayer_interface_->SetMaxInputSize(value);

Check warning on line 203 in cobalt/media/media_module.cc

View check run for this annotation

Codecov / codecov/patch

cobalt/media/media_module.cc#L201-L203

Added lines #L201 - L203 were not covered by tests
#if SB_API_VERSION >= 15
} else if (name == "AudioWriteDurationLocal" && value > 0) {
audio_write_duration_local_ = value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@ public static void createVideoMediaCodecBridge(
MediaCrypto crypto,
ColorInfo colorInfo,
int tunnelModeAudioSessionId,
int maxInputSize,
CreateMediaCodecBridgeResult outCreateMediaCodecBridgeResult) {
MediaCodec mediaCodec = null;
outCreateMediaCodecBridgeResult.mMediaCodecBridge = null;
Expand Down Expand Up @@ -776,6 +777,20 @@ public static void createVideoMediaCodecBridge(
}
}

if (maxInputSize != -1) {
try {
mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, maxInputSize);
Log.i(
TAG,
"KEY_MAX_INPUT_SIZE is "
+ mediaFormat.getInteger(android.media.MediaFormat.KEY_MAX_INPUT_SIZE)
+ " after setting it to "
+ maxInputSize
+ '.');
} catch (Exception e) {
Log.w(TAG, "MediaFormat.getInteger(KEY_MAX_INPUT_SIZE) failed with exception: ", e);
}
}
if (!bridge.configureVideo(
mediaFormat, surface, crypto, 0, maxWidth, maxHeight, outCreateMediaCodecBridgeResult)) {
Log.e(TAG, "Failed to configure video codec.");
Expand Down Expand Up @@ -1177,9 +1192,9 @@ private void maybeSetMaxInputSize(MediaFormat format) {
return;
}
// Estimate the maximum input size assuming three channel 4:2:0 subsampled input frames.
int maxInputSize = (maxPixels * 3) / (2 * minCompressionRatio);
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, maxInputSize);
try {
int maxInputSize = (maxPixels * 3) / (2 * minCompressionRatio);
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, maxInputSize);
Log.i(
TAG,
"KEY_MAX_INPUT_SIZE is "
Expand Down
2 changes: 2 additions & 0 deletions starboard/android/shared/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ static_library("starboard_platform") {
"player_destroy.cc",
"player_get_preferred_output_mode.cc",
"player_set_bounds.cc",
"player_set_max_input_size.cc",
"player_set_playback_rate.cc",
"sanitizer_options.cc",
"socket_get_interface_address.cc",
Expand Down Expand Up @@ -420,6 +421,7 @@ static_library("starboard_platform") {
"//starboard/shared/starboard/player/player_destroy.cc",
"//starboard/shared/starboard/player/player_get_preferred_output_mode_prefer_punchout.cc",
"//starboard/shared/starboard/player/player_set_bounds.cc",
"//starboard/shared/starboard/player/player_set_max_input_size.cc",
"//starboard/shared/starboard/player/player_set_playback_rate.cc",
]

Expand Down
5 changes: 3 additions & 2 deletions starboard/android/shared/media_codec_bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ scoped_ptr<MediaCodecBridge> MediaCodecBridge::CreateVideoMediaCodecBridge(
bool require_secured_decoder,
bool require_software_codec,
int tunnel_mode_audio_session_id,
int max_input_size,
bool force_big_endian_hdr_metadata,
std::string* error_message) {
SB_DCHECK(error_message);
Expand Down Expand Up @@ -316,14 +317,14 @@ scoped_ptr<MediaCodecBridge> MediaCodecBridge::CreateVideoMediaCodecBridge(
"(JLjava/lang/String;Ljava/lang/String;IIIIILandroid/view/Surface;"
"Landroid/media/MediaCrypto;"
"Ldev/cobalt/media/MediaCodecBridge$ColorInfo;"
"I"
"II"
"Ldev/cobalt/media/MediaCodecBridge$CreateMediaCodecBridgeResult;)"
"V",
reinterpret_cast<jlong>(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());
max_input_size, j_create_media_codec_bridge_result.Get());

jobject j_media_codec_bridge = env->CallObjectMethodOrAbort(
j_create_media_codec_bridge_result.Get(), "mediaCodecBridge",
Expand Down
1 change: 1 addition & 0 deletions starboard/android/shared/media_codec_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ class MediaCodecBridge {
bool require_secured_decoder,
bool require_software_codec,
int tunnel_mode_audio_session_id,
int max_input_size,
bool force_big_endian_hdr_metadata,
std::string* error_message);

Expand Down
3 changes: 2 additions & 1 deletion starboard/android/shared/media_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ MediaDecoder::MediaDecoder(Host* host,
bool require_software_codec,
const FrameRenderedCB& frame_rendered_cb,
int tunnel_mode_audio_session_id,
int max_input_size,
bool force_big_endian_hdr_metadata,
std::string* error_message)
: media_type_(kSbMediaTypeVideo),
Expand All @@ -134,7 +135,7 @@ MediaDecoder::MediaDecoder(Host* host,
media_codec_bridge_ = MediaCodecBridge::CreateVideoMediaCodecBridge(
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,
require_software_codec, tunnel_mode_audio_session_id, max_input_size,
force_big_endian_hdr_metadata, error_message);
if (!media_codec_bridge_) {
SB_LOG(ERROR) << "Failed to create video media codec bridge with error: "
Expand Down
1 change: 1 addition & 0 deletions starboard/android/shared/media_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class MediaDecoder
bool require_software_codec,
const FrameRenderedCB& frame_rendered_cb,
int tunnel_mode_audio_session_id,
int max_input_size,
bool force_big_endian_hdr_metadata,
std::string* error_message);
~MediaDecoder();
Expand Down
6 changes: 6 additions & 0 deletions starboard/android/shared/media_is_video_supported.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
false)) {
MaxMediaCodecOutputBuffersLookupTable::GetInstance()->SetEnabled(false);
}

// Allow the web app to set the maximum size of input buffer
// (MediaFormat.KEY_MAX_INPUT_SIZE)
if (!mime_type->ValidateIntParameter("maxinputsize")) {
return false;
}
}

if (must_support_tunnel_mode && decode_to_texture_required) {
Expand Down
48 changes: 43 additions & 5 deletions starboard/android/shared/player_components_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
#include "starboard/shared/starboard/player/filter/video_renderer_internal_impl.h"
#include "starboard/shared/starboard/player/filter/video_renderer_sink.h"

// Specifies max_input_size to set MediaFormat.KEY_MAX_INPUT_SIZE on ATV.
// Use -1 as default value
inline int kSbMediaMaxInputSize = -1;

namespace starboard {
namespace android {
namespace shared {
Expand Down Expand Up @@ -231,6 +235,25 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player::
return scoped_ptr<PlayerComponents>();
}

// Set max_input_size with a non-zero value to overwrite
// MediaFormat.KEY_MAX_INPUT_SIZE. Use -1 as default value.
int max_input_size = kSbMediaMaxInputSize;
SB_LOG_IF(INFO, max_input_size != -1)
<< "max_input_size is " << max_input_size;
if (!creation_parameters.video_mime().empty()) {
MimeType video_mime_type(creation_parameters.video_mime());
if (!video_mime_type.is_valid() ||
!video_mime_type.ValidateIntParameter("maxinputsize")) {
return scoped_ptr<PlayerComponents>();
}

max_input_size = video_mime_type.GetParamIntValue("maxinputsize",
kSbMediaMaxInputSize);
SB_LOG_IF(INFO, max_input_size != -1)
<< "Mime attribute \"maxinputsize\" is set to: " << max_input_size
<< ".";
}

scoped_ptr<::starboard::shared::starboard::player::filter::VideoRenderer>
video_renderer;
if (creation_parameters.video_codec() != kSbMediaVideoCodecNone) {
Expand All @@ -239,7 +262,7 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player::

scoped_ptr<VideoDecoder> video_decoder = CreateVideoDecoder(
creation_parameters, kTunnelModeAudioSessionId,
kForceSecurePipelineUnderTunnelMode, error_message);
kForceSecurePipelineUnderTunnelMode, max_input_size, error_message);
if (video_decoder) {
using starboard::shared::starboard::player::filter::VideoRendererImpl;

Expand Down Expand Up @@ -294,6 +317,13 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player::
"Invalid video MIME: '" + std::string(video_mime) + "'";
return false;
}

if (!video_mime_type.is_valid() ||
!video_mime_type.ValidateIntParameter("maxinputsize")) {
*error_message =
"Invalid video MIME: '" + std::string(video_mime) + "'";
return false;
}
}

int tunnel_mode_audio_session_id = -1;
Expand Down Expand Up @@ -401,14 +431,21 @@ class PlayerComponentsFactory : public starboard::shared::starboard::player::
SB_DCHECK(video_render_algorithm);
SB_DCHECK(video_renderer_sink);
SB_DCHECK(error_message);
// Set max_input_size with a non-zero value to overwrite
// MediaFormat.KEY_MAX_INPUT_SIZE. Use -1 as default value.
int max_input_size = video_mime_type.GetParamIntValue(
"maxinputsize", kSbMediaMaxInputSize);
SB_LOG_IF(INFO, max_input_size != -1)
<< "max_input_size is " << max_input_size;

if (tunnel_mode_audio_session_id == -1) {
force_secure_pipeline_under_tunnel_mode = false;
}

scoped_ptr<VideoDecoder> video_decoder_impl = CreateVideoDecoder(
creation_parameters, tunnel_mode_audio_session_id,
force_secure_pipeline_under_tunnel_mode, error_message);
scoped_ptr<VideoDecoder> video_decoder_impl =
CreateVideoDecoder(creation_parameters, tunnel_mode_audio_session_id,
force_secure_pipeline_under_tunnel_mode,
max_input_size, error_message);
if (video_decoder_impl) {
*video_render_algorithm = video_decoder_impl->GetRenderAlgorithm();
*video_renderer_sink = video_decoder_impl->GetSink();
Expand Down Expand Up @@ -452,6 +489,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,
int max_input_size,
std::string* error_message) {
bool force_big_endian_hdr_metadata = false;
if (!creation_parameters.video_mime().empty()) {
Expand All @@ -473,7 +511,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));
max_input_size, error_message));
if (creation_parameters.video_codec() == kSbMediaVideoCodecAv1 ||
video_decoder->is_decoder_created()) {
return video_decoder.Pass();
Expand Down
31 changes: 31 additions & 0 deletions starboard/android/shared/player_set_max_input_size.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2023 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.

#include "starboard/player.h"

#include "starboard/android/shared/player_components_factory.h"
#include "starboard/common/log.h"
#include "starboard/shared/starboard/player/player_internal.h"

bool SbPlayerSetMaxInputSize(int max_input_size) {
// TODO(borongchen): replace 3110400 with the default value
if (max_input_size != -1 && max_input_size < 3110400) {
SB_DLOG(WARNING) << "Setting max_input_size " << max_input_size
<< " is small than default value ";
return false;
}
kSbMediaMaxInputSize = max_input_size;
SB_LOG(INFO) << "Set max_input_size to " << kSbMediaMaxInputSize;
return true;
}
6 changes: 4 additions & 2 deletions starboard/android/shared/video_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
int max_input_size,
std::string* error_message)
: video_codec_(video_stream_info.codec),
drm_system_(static_cast<DrmSystem*>(drm_system)),
Expand All @@ -364,6 +365,7 @@ VideoDecoder::VideoDecoder(const VideoStreamInfo& video_stream_info,
decode_target_graphics_context_provider),
max_video_capabilities_(max_video_capabilities),
tunnel_mode_audio_session_id_(tunnel_mode_audio_session_id),
max_input_size_(max_input_size),
force_reset_surface_under_tunnel_mode_(
force_reset_surface_under_tunnel_mode),
has_new_texture_available_(false),
Expand Down Expand Up @@ -710,8 +712,8 @@ bool VideoDecoder::InitializeCodec(const VideoStreamInfo& video_stream_info,
j_output_surface, drm_system_,
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));
tunnel_mode_audio_session_id_, max_input_size_,
force_big_endian_hdr_metadata_, error_message));
if (media_decoder_->is_valid()) {
if (error_cb_) {
media_decoder_->Initialize(
Expand Down
4 changes: 4 additions & 0 deletions starboard/android/shared/video_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
int max_input_size,
std::string* error_message);
~VideoDecoder() override;

Expand Down Expand Up @@ -146,6 +147,9 @@ class VideoDecoder

const int tunnel_mode_audio_session_id_ = -1;

// Allow to configure maximum input buffer size
const int max_input_size_;

// Force resetting the video surface after tunnel mode playback, which
// prevents video distortion on some devices.
const bool force_reset_surface_under_tunnel_mode_;
Expand Down
1 change: 1 addition & 0 deletions starboard/elf_loader/exported_symbols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ ExportedSymbols::ExportedSymbols() {
REGISTER_SYMBOL(SbPlayerSetBounds);
REGISTER_SYMBOL(SbPlayerSetPlaybackRate);
REGISTER_SYMBOL(SbPlayerSetVolume);
REGISTER_SYMBOL(SbPlayerSetMaxInputSize);
REGISTER_SYMBOL(SbPlayerWriteEndOfStream);
#if SB_API_VERSION >= 15
REGISTER_SYMBOL(SbPlayerWriteSamples);
Expand Down
6 changes: 6 additions & 0 deletions starboard/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,12 @@ SB_EXPORT bool SbPlayerSetPlaybackRate(SbPlayer player, double playback_rate);
// value of |1.0| means that it should be played at full volume.
SB_EXPORT void SbPlayerSetVolume(SbPlayer player, double volume);

// Sets maximum size of a buffer of input data.
//
// |max_input_size|: The maximum size of a buffer of input data.
// Use |-1| for default value.
SB_EXPORT bool SbPlayerSetMaxInputSize(int max_input_size);

// 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.
Expand Down
1 change: 1 addition & 0 deletions starboard/shared/starboard/player/buildfiles.gni
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ common_player_sources = [
"//starboard/shared/starboard/player/player_internal.h",
"//starboard/shared/starboard/player/player_seek.cc",
"//starboard/shared/starboard/player/player_set_bounds.cc",
"//starboard/shared/starboard/player/player_set_max_input_size.cc",
"//starboard/shared/starboard/player/player_set_playback_rate.cc",
"//starboard/shared/starboard/player/player_set_volume.cc",
"//starboard/shared/starboard/player/player_worker.cc",
Expand Down
23 changes: 23 additions & 0 deletions starboard/shared/starboard/player/player_set_max_input_size.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2023 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.

#include "starboard/player.h"

#include "starboard/common/log.h"
#include "starboard/shared/starboard/player/player_internal.h"

bool SbPlayerSetMaxInputSize(int max_input_size) {
SB_DLOG(WARNING) << "Set max_input_size only on ATV";
return false;

Check warning on line 22 in starboard/shared/starboard/player/player_set_max_input_size.cc

View check run for this annotation

Codecov / codecov/patch

starboard/shared/starboard/player/player_set_max_input_size.cc#L20-L22

Added lines #L20 - L22 were not covered by tests
}
Loading

0 comments on commit 769980f

Please sign in to comment.