From afd3f68be282b1c979020f8156cc76ad38d43663 Mon Sep 17 00:00:00 2001 From: Joe Woodworth Date: Mon, 27 Aug 2018 11:34:05 -0700 Subject: [PATCH] Pass transfer id to SbMediaIsVideoSupported Pass transfer id to SbMediaIsVideoSupported to allow platforms to express support of eotf in combination with resolution, fps, etc. b/37353136 Change-Id: Id4533dd7b231d9dbc214126ac807cc79de96dc30 --- .../dev/cobalt/media/MediaCodecBridge.java | 9 +++- .../java/dev/cobalt/media/MediaCodecUtil.java | 40 ++++++++------ .../android/shared/configuration_public.h | 4 ++ .../shared/media_is_video_supported.cc | 52 +++++++++++++++++-- .../android/shared/starboard_platform.gypi | 1 - .../media_can_play_mime_and_key_system.cc | 15 +++++- ...a_is_transfer_characteristics_supported.cc | 25 +++++++++ .../starboard/media/media_support_internal.h | 6 +++ .../filter/testing/video_decoder_test.cc | 4 ++ .../shared/starboard/player/player_create.cc | 4 ++ 10 files changed, 138 insertions(+), 22 deletions(-) create mode 100644 starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc 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 b7b37754384a7..5fd0a8b2357e1 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 @@ -400,8 +400,15 @@ public static MediaCodecBridge createVideoMediaCodecBridge( MediaCrypto crypto, ColorInfo colorInfo) { MediaCodec mediaCodec = null; + + boolean findHDRDecoder = android.os.Build.VERSION.SDK_INT >= 24 && colorInfo != null; + // On first pass, try to find a decoder with HDR if the color info is non-null. MediaCodecUtil.FindVideoDecoderResult findVideoDecoderResult = - MediaCodecUtil.findVideoDecoder(mime, isSecure, 0, 0, 0, 0); + MediaCodecUtil.findVideoDecoder(mime, isSecure, 0, 0, 0, 0, findHDRDecoder); + if (findVideoDecoderResult.name.equals("") && findHDRDecoder) { + // On second pass, forget HDR. + findVideoDecoderResult = MediaCodecUtil.findVideoDecoder(mime, isSecure, 0, 0, 0, 0, false); + } try { String decoderName = findVideoDecoderResult.name; if (decoderName.equals("") || findVideoDecoderResult.videoCapabilities == null) { diff --git a/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecUtil.java b/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecUtil.java index 6f4d4929c8ae9..25a13c281572d 100644 --- a/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecUtil.java +++ b/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecUtil.java @@ -380,10 +380,17 @@ private MediaCodecUtil() {} @SuppressWarnings("unused") @UsedByNative public static boolean hasVideoDecoderFor( - String mimeType, boolean secure, int frameWidth, int frameHeight, int bitrate, int fps) { - return !findVideoDecoder(mimeType, secure, frameWidth, frameHeight, bitrate, fps) - .name - .equals(""); + String mimeType, + boolean secure, + int frameWidth, + int frameHeight, + int bitrate, + int fps, + boolean mustSupportHdr) { + FindVideoDecoderResult findVideoDecoderResult = + findVideoDecoder(mimeType, secure, frameWidth, frameHeight, bitrate, fps, mustSupportHdr); + return !findVideoDecoderResult.name.equals("") + && (!mustSupportHdr || isHdrCapableVp9Decoder(findVideoDecoderResult)); } /** @@ -406,16 +413,8 @@ public static boolean hasHdrCapableVp9Decoder() { return false; } - // Ideally we would just add this as a parameter to |findVideoDecoder|, - // however the shared starboard player implementation of - // |CanPlayMimeAndKeySystem| will call - // |SbMediaIsTransferCharacteristicsSupported| as a separate function. We - // make the reasonable assumption that no system will have two hardware - // VP9 decoders with one capable of playing HDR at lower - // resolutions/bitrates, and another not capable of playing HDR at higher - // resolutions/bitrates. FindVideoDecoderResult findVideoDecoderResult = - findVideoDecoder(VP9_MIME_TYPE, false, 0, 0, 0, 0); + findVideoDecoder(VP9_MIME_TYPE, false, 0, 0, 0, 0, true); return isHdrCapableVp9Decoder(findVideoDecoderResult); } @@ -444,7 +443,13 @@ public static boolean isHdrCapableVp9Decoder(FindVideoDecoderResult findVideoDec * "" otherwise. */ public static FindVideoDecoderResult findVideoDecoder( - String mimeType, boolean secure, int frameWidth, int frameHeight, int bitrate, int fps) { + String mimeType, + boolean secure, + int frameWidth, + int frameHeight, + int bitrate, + int fps, + boolean hdr) { Log.v( TAG, String.format( @@ -560,8 +565,13 @@ public static FindVideoDecoderResult findVideoDecoder( (secure && !name.endsWith(SECURE_DECODER_SUFFIX)) ? (name + SECURE_DECODER_SUFFIX) : name; + FindVideoDecoderResult findVideoDecoderResult = + new FindVideoDecoderResult(resultName, videoCapabilities, codecCapabilities); + if (hdr && !isHdrCapableVp9Decoder(findVideoDecoderResult)) { + continue; + } Log.v(TAG, String.format("Found suitable decoder, %s", name)); - return new FindVideoDecoderResult(resultName, videoCapabilities, codecCapabilities); + return findVideoDecoderResult; } } return new FindVideoDecoderResult("", null, null); diff --git a/starboard/android/shared/configuration_public.h b/starboard/android/shared/configuration_public.h index 5144b4bc3eb0b..79203a7b7a256 100644 --- a/starboard/android/shared/configuration_public.h +++ b/starboard/android/shared/configuration_public.h @@ -330,6 +330,10 @@ // stack size for media stack threads. #define SB_MEDIA_THREAD_STACK_SIZE 0U +// SbMediaTransferId argument |eotf| to SbMediaIsVideoSupported and remove the +// function SbMediaIsTransferCharacteristicsSupported. +#define SB_HAS_MEDIA_EOTF_CHECK_SUPPORT 1 + // --- Decoder-only Params --- // Specifies how media buffers must be aligned on this platform as some diff --git a/starboard/android/shared/media_is_video_supported.cc b/starboard/android/shared/media_is_video_supported.cc index ea0ee8b19f5c2..ed2941003e083 100644 --- a/starboard/android/shared/media_is_video_supported.cc +++ b/starboard/android/shared/media_is_video_supported.cc @@ -24,12 +24,55 @@ using starboard::android::shared::JniEnvExt; using starboard::android::shared::ScopedLocalJavaRef; using starboard::android::shared::SupportedVideoCodecToMimeType; +namespace { + +// https://developer.android.com/reference/android/view/Display.HdrCapabilities.html#HDR_TYPE_HDR10 +const jint HDR_TYPE_DOLBY_VISION = 1; +const jint HDR_TYPE_HDR10 = 2; +const jint HDR_TYPE_HLG = 3; + +bool IsTransferCharacteristicsSupported(SbMediaTransferId transfer_id) { + // Bt709 and unspecified are assumed to always be supported. + if (transfer_id == kSbMediaTransferIdBt709 || + transfer_id == kSbMediaTransferIdUnspecified) { + return true; + } + // An HDR capable VP9 decoder is needed to handle HDR at all. + bool has_hdr_capable_vp9_decoder = + JniEnvExt::Get()->CallStaticBooleanMethodOrAbort( + "dev/cobalt/media/MediaCodecUtil", "hasHdrCapableVp9Decoder", + "()Z") == JNI_TRUE; + if (!has_hdr_capable_vp9_decoder) { + return false; + } + + jint hdr_type; + if (transfer_id == kSbMediaTransferIdSmpteSt2084) { + hdr_type = HDR_TYPE_HDR10; + } else if (transfer_id == kSbMediaTransferIdAribStdB67) { + hdr_type = HDR_TYPE_HLG; + } else { + // No other transfer functions are supported, see + // https://source.android.com/devices/tech/display/hdr. + return false; + } + + return JniEnvExt::Get()->CallStarboardBooleanMethodOrAbort( + "isHdrTypeSupported", "(I)Z", hdr_type) == JNI_TRUE; +} + +} // namespace + SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, int frame_width, int frame_height, int64_t bitrate, int fps, - bool decode_to_texture_required) { + bool decode_to_texture_required, + SbMediaTransferId eotf) { + if (!IsTransferCharacteristicsSupported(eotf)) { + return false; + } // While not necessarily true, for now we assume that all Android devices // can play decode-to-texture video just as well as normal video. SB_UNREFERENCED_PARAMETER(decode_to_texture_required); @@ -40,8 +83,11 @@ SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, } JniEnvExt* env = JniEnvExt::Get(); ScopedLocalJavaRef j_mime(env->NewStringStandardUTFOrAbort(mime)); + bool must_support_hdr = (eotf != kSbMediaTransferIdBt709 && + eotf != kSbMediaTransferIdUnspecified); return env->CallStaticBooleanMethodOrAbort( "dev/cobalt/media/MediaCodecUtil", "hasVideoDecoderFor", - "(Ljava/lang/String;ZIIII)Z", j_mime.Get(), false, frame_width, - frame_height, static_cast(bitrate), fps) == JNI_TRUE; + "(Ljava/lang/String;ZIIIIZ)Z", j_mime.Get(), false, frame_width, + frame_height, static_cast(bitrate), fps, + must_support_hdr) == JNI_TRUE; } diff --git a/starboard/android/shared/starboard_platform.gypi b/starboard/android/shared/starboard_platform.gypi index 1a1cf7c4bb108..32528604a1dc6 100644 --- a/starboard/android/shared/starboard_platform.gypi +++ b/starboard/android/shared/starboard_platform.gypi @@ -116,7 +116,6 @@ 'media_is_audio_supported.cc', 'media_is_output_protected.cc', 'media_is_supported.cc', - 'media_is_transfer_characteristics_supported.cc', 'media_is_video_supported.cc', 'media_set_output_protection.cc', 'microphone_impl.cc', diff --git a/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc b/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc index a20ec3ea75411..e6dbcfaeeb307 100644 --- a/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc +++ b/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc @@ -84,6 +84,10 @@ SbMediaSupportType CanPlayProgressiveVideo(const MimeType& mime_type, , decode_to_texture_required #endif // SB_API_VERSION >= 10 +#if SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) + , + kSbMediaTransferIdUnspecified +#endif // SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) )) { return kSbMediaSupportTypeNotSupported; } @@ -203,9 +207,12 @@ SbMediaSupportType CanPlayMimeAndKeySystem(const MimeType& mime_type, } std::string eotf = mime_type.GetParamStringValue("eotf", ""); + SbMediaTransferId transfer_id = kSbMediaTransferIdUnspecified; if (!eotf.empty()) { - SbMediaTransferId transfer_id = GetTransferIdFromString(eotf); - if (!SbMediaIsTransferCharacteristicsSupported(transfer_id)) { + transfer_id = GetTransferIdFromString(eotf); + // If the eotf is not known, reject immediately - without checking with + // the platform. + if (transfer_id == kSbMediaTransferIdUnknown) { return kSbMediaSupportTypeNotSupported; } } @@ -239,6 +246,10 @@ SbMediaSupportType CanPlayMimeAndKeySystem(const MimeType& mime_type, , decode_to_texture_required #endif // SB_API_VERSION >= 10 +#if SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) + , + transfer_id +#endif // SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) )) { return kSbMediaSupportTypeProbably; } diff --git a/starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc b/starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc new file mode 100644 index 0000000000000..e3bbe0368dc97 --- /dev/null +++ b/starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc @@ -0,0 +1,25 @@ +// Copyright 2018 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/shared/starboard/media/media_support_internal.h" + +#include "starboard/media.h" + +#if !SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) +SB_EXPORT bool SbMediaIsTransferCharacteristicsSupported( + SbMediaTransferId transfer_id) { + return transfer_id == kSbMediaTransferIdBt709 || + transfer_id == kSbMediaTransferIdUnspecified; +} +#endif // !SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) diff --git a/starboard/shared/starboard/media/media_support_internal.h b/starboard/shared/starboard/media/media_support_internal.h index 0ecefdfbd28c2..f7e7dd4f8c3ca 100644 --- a/starboard/shared/starboard/media/media_support_internal.h +++ b/starboard/shared/starboard/media/media_support_internal.h @@ -46,6 +46,10 @@ SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, , bool decode_to_texture_required #endif // SB_API_VERSION >= 10 +#if SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) + , + SbMediaTransferId eotf +#endif // SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) ); // Indicates whether this platform supports |audio_codec| at |bitrate|. @@ -57,6 +61,7 @@ SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, SB_EXPORT bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, int64_t bitrate); +#if !SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) // Indicates whether this platform supports |transfer_id| as a transfer // characteristics. If |transfer_id| is not supported under any condition, this // function returns |false|. @@ -64,6 +69,7 @@ SB_EXPORT bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, // |transfer_id|: The id of transfer charateristics listed in SbMediaTransferId. SB_EXPORT bool SbMediaIsTransferCharacteristicsSupported( SbMediaTransferId transfer_id); +#endif // !SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) #ifdef __cplusplus } // extern "C" diff --git a/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc b/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc index 12622c561d9ef..a2d7f27c73579 100644 --- a/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc +++ b/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc @@ -651,6 +651,10 @@ std::vector GetSupportedTests() { , false #endif // SB_API_VERSION >= 10 +#if SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) + , + kSbMediaTransferIdUnspecified +#endif // SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) )) { test_params.push_back({output_mode, filename}); } diff --git a/starboard/shared/starboard/player/player_create.cc b/starboard/shared/starboard/player/player_create.cc index 725a0210cdfc6..1f9c81b2ff0b4 100644 --- a/starboard/shared/starboard/player/player_create.cc +++ b/starboard/shared/starboard/player/player_create.cc @@ -85,6 +85,10 @@ SbPlayer SbPlayerCreate(SbWindow window, , output_mode == kSbPlayerOutputModeDecodeToTexture #endif +#if SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) + , + kSbMediaTransferIdUnspecified +#endif // SB_HAS(MEDIA_EOTF_CHECK_SUPPORT) )) { SB_LOG(ERROR) << "Unsupported video codec " << video_codec; return kSbPlayerInvalid;