Skip to content

Commit f086c38

Browse files
kjyounandrewsavage1
authored andcommitted
android: Migrate Video/Audio capabilities logic to JNI generator (#7504)
Migrate the JNI bindings for 'MediaCapabilitiesCache' to utilize the Chromium JNI generator. This change replaces the manual JNI calls with generated C++ wrappers and getter methods. The Java code in 'MediaCodecUtil' now has new public static methods annotated with '@CalledByNative'. The corresponding C++ code in 'media_capabilities_cache.cc' leverages the generated JNI functions to access the media capabilities. This standardizes the JNI interaction, reduces manual error-prone code, and improves the maintainability of the Android JNI layer. It also removes the need for manual caching of JNI method IDs using constructs like 'std::call_once', as the JNI generator handles this automatically. Bug: 450024477 original-hexsha: 761a646
1 parent e9962cb commit f086c38

File tree

3 files changed

+104
-172
lines changed

3 files changed

+104
-172
lines changed

cobalt/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecUtil.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,58 @@ public static boolean isSoftwareDecoder(MediaCodecInfo codecInfo) {
549549
return false;
550550
}
551551

552+
@CalledByNative
553+
public static int getRangeUpper(Range<Integer> range) {
554+
return range.getUpper();
555+
}
556+
557+
@CalledByNative
558+
public static int getRangeLower(Range<Integer> range) {
559+
return range.getLower();
560+
}
561+
562+
@CalledByNative
563+
public static Range<Integer> getAudioBitrateRange(
564+
MediaCodecInfo.AudioCapabilities audioCapabilities) {
565+
return audioCapabilities.getBitrateRange();
566+
}
567+
568+
@CalledByNative
569+
public static Range<Integer> getVideoWidthRange(
570+
MediaCodecInfo.VideoCapabilities videoCapabilities) {
571+
return videoCapabilities.getSupportedWidths();
572+
}
573+
574+
@CalledByNative
575+
public static Range<Integer> getVideoHeightRange(
576+
MediaCodecInfo.VideoCapabilities videoCapabilities) {
577+
return videoCapabilities.getSupportedHeights();
578+
}
579+
580+
@CalledByNative
581+
public static Range<Integer> getVideoBitrateRange(
582+
MediaCodecInfo.VideoCapabilities videoCapabilities) {
583+
return videoCapabilities.getBitrateRange();
584+
}
585+
586+
@CalledByNative
587+
public static Range<Integer> getVideoFrameRateRange(
588+
MediaCodecInfo.VideoCapabilities videoCapabilities) {
589+
return videoCapabilities.getSupportedFrameRates();
590+
}
591+
592+
@CalledByNative
593+
public static boolean areSizeAndRateSupported(
594+
MediaCodecInfo.VideoCapabilities videoCapabilities, int width, int height, double frameRate) {
595+
return videoCapabilities.areSizeAndRateSupported(width, height, frameRate);
596+
}
597+
598+
@CalledByNative
599+
public static boolean isSizeSupported(
600+
MediaCodecInfo.VideoCapabilities videoCapabilities, int width, int height) {
601+
return videoCapabilities.isSizeSupported(width, height);
602+
}
603+
552604
/**
553605
* Returns the name of the video decoder if it is found, or "" otherwise.
554606
*

starboard/android/shared/media_capabilities_cache.cc

Lines changed: 46 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#include "base/android/jni_string.h"
2525
#include "base/android/scoped_java_ref.h"
2626
#include "starboard/android/shared/audio_output_manager.h"
27-
#include "starboard/android/shared/jni_utils.h"
2827
#include "starboard/android/shared/media_common.h"
2928
#include "starboard/android/shared/media_drm_bridge.h"
3029
#include "starboard/android/shared/starboard_bridge.h"
@@ -43,6 +42,8 @@ namespace {
4342
using base::android::AttachCurrentThread;
4443
using base::android::ConvertJavaStringToUTF8;
4544
using base::android::ConvertUTF8ToJavaString;
45+
using base::android::JavaParamRef;
46+
using base::android::ScopedJavaGlobalRef;
4647
using base::android::ScopedJavaLocalRef;
4748

4849
// https://developer.android.com/reference/android/view/Display.HdrCapabilities.html#HDR_TYPE_HDR10
@@ -62,47 +63,20 @@ bool EndsWith(const std::string& str, const std::string& suffix) {
6263
}
6364

6465
Range ConvertJavaRangeToRange(JNIEnv* env, jobject j_range) {
65-
struct RangeJniCache {
66-
jmethodID get_upper_method = nullptr;
67-
jmethodID get_lower_method = nullptr;
68-
jmethodID int_value_method = nullptr;
69-
};
70-
71-
static std::once_flag once_flag;
72-
static RangeJniCache cache;
73-
74-
std::call_once(once_flag, [env]() {
75-
jclass range_class = env->FindClass("android/util/Range");
76-
SB_CHECK(range_class);
77-
78-
cache.get_upper_method =
79-
env->GetMethodID(range_class, "getUpper", "()Ljava/lang/Comparable;");
80-
SB_CHECK(cache.get_upper_method);
81-
82-
cache.get_lower_method =
83-
env->GetMethodID(range_class, "getLower", "()Ljava/lang/Comparable;");
84-
SB_CHECK(cache.get_lower_method);
85-
env->DeleteLocalRef(range_class);
86-
87-
jclass integer_class = env->FindClass("java/lang/Integer");
88-
SB_CHECK(integer_class);
89-
90-
cache.int_value_method = env->GetMethodID(integer_class, "intValue", "()I");
91-
SB_CHECK(cache.int_value_method);
92-
env->DeleteLocalRef(integer_class);
93-
});
94-
95-
jobject j_upper_comparable =
96-
env->CallObjectMethod(j_range, cache.get_upper_method);
97-
jint j_upper_int =
98-
env->CallIntMethod(j_upper_comparable, cache.int_value_method);
99-
100-
jobject j_lower_comparable =
101-
env->CallObjectMethod(j_range, cache.get_lower_method);
102-
jint j_lower_int =
103-
env->CallIntMethod(j_lower_comparable, cache.int_value_method);
104-
105-
return Range(j_lower_int, j_upper_int);
66+
const auto j_range_ref = JavaParamRef<jobject>(env, j_range);
67+
return Range(Java_MediaCodecUtil_getRangeLower(env, j_range_ref),
68+
Java_MediaCodecUtil_getRangeUpper(env, j_range_ref));
69+
}
70+
71+
template <typename GetRangeFunc>
72+
Range GetRange(JNIEnv* env,
73+
const base::android::JavaRef<jobject>& j_capabilities,
74+
GetRangeFunc get_range_func) {
75+
SB_CHECK(env);
76+
SB_CHECK(j_capabilities);
77+
ScopedJavaLocalRef<jobject> j_range = get_range_func(env, j_capabilities);
78+
SB_CHECK(j_range);
79+
return ConvertJavaRangeToRange(env, j_range.obj());
10680
}
10781

10882
void ConvertStringToLowerCase(std::string* str) {
@@ -191,37 +165,16 @@ AudioCodecCapability::AudioCodecCapability(
191165
JNIEnv* env,
192166
ScopedJavaLocalRef<jobject>& j_codec_info,
193167
ScopedJavaLocalRef<jobject>& j_audio_capabilities)
194-
: CodecCapability(env, j_codec_info) {
195-
SB_CHECK(env);
168+
: CodecCapability(env, j_codec_info),
169+
supported_bitrates_([env, &j_audio_capabilities] {
170+
Range supported_bitrates =
171+
GetRange(env, j_audio_capabilities,
172+
&Java_MediaCodecUtil_getAudioBitrateRange);
173+
// Overwrite the lower bound to 0.
174+
supported_bitrates.minimum = 0;
175+
return supported_bitrates;
176+
}()) {
196177
SB_CHECK(j_codec_info);
197-
SB_CHECK(j_audio_capabilities);
198-
199-
struct AudioCapabilitiesJniCache {
200-
jmethodID get_bitrate_range_method;
201-
};
202-
203-
static std::once_flag once_flag;
204-
static AudioCapabilitiesJniCache cache;
205-
206-
std::call_once(once_flag, [env]() {
207-
jclass audio_capabilities_class =
208-
env->FindClass("android/media/MediaCodecInfo$AudioCapabilities");
209-
SB_CHECK(audio_capabilities_class);
210-
211-
cache.get_bitrate_range_method = env->GetMethodID(
212-
audio_capabilities_class, "getBitrateRange", "()Landroid/util/Range;");
213-
SB_CHECK(cache.get_bitrate_range_method);
214-
env->DeleteLocalRef(audio_capabilities_class);
215-
});
216-
217-
ScopedJavaLocalRef<jobject> j_bitrate_range(
218-
env, env->CallObjectMethod(j_audio_capabilities.obj(),
219-
cache.get_bitrate_range_method));
220-
SB_CHECK(j_bitrate_range);
221-
supported_bitrates_ = ConvertJavaRangeToRange(env, j_bitrate_range.obj());
222-
223-
// Overwrite the lower bound to 0.
224-
supported_bitrates_.minimum = 0;
225178
}
226179

227180
bool AudioCodecCapability::IsBitrateSupported(int bitrate) const {
@@ -236,110 +189,37 @@ VideoCodecCapability::VideoCodecCapability(
236189
is_software_decoder_(
237190
Java_CodecCapabilityInfo_isSoftware(env, j_codec_info)),
238191
is_hdr_capable_(Java_CodecCapabilityInfo_isHdrCapable(env, j_codec_info)),
239-
j_video_capabilities_(env, j_video_capabilities.obj()) {
240-
struct VideoCapabilitiesJniCache {
241-
jmethodID get_supported_widths_method;
242-
jmethodID get_supported_heights_method;
243-
jmethodID get_bitrate_range_method;
244-
jmethodID get_supported_frame_rates_method;
245-
};
246-
247-
static std::once_flag once_flag;
248-
static VideoCapabilitiesJniCache cache;
249-
250-
std::call_once(once_flag, [env]() {
251-
jclass video_capabilities_class =
252-
env->FindClass("android/media/MediaCodecInfo$VideoCapabilities");
253-
SB_CHECK(video_capabilities_class);
254-
255-
cache.get_supported_widths_method =
256-
env->GetMethodID(video_capabilities_class, "getSupportedWidths",
257-
"()Landroid/util/Range;");
258-
SB_CHECK(cache.get_supported_widths_method);
259-
260-
cache.get_supported_heights_method =
261-
env->GetMethodID(video_capabilities_class, "getSupportedHeights",
262-
"()Landroid/util/Range;");
263-
SB_CHECK(cache.get_supported_heights_method);
264-
265-
cache.get_bitrate_range_method = env->GetMethodID(
266-
video_capabilities_class, "getBitrateRange", "()Landroid/util/Range;");
267-
SB_CHECK(cache.get_bitrate_range_method);
268-
269-
cache.get_supported_frame_rates_method =
270-
env->GetMethodID(video_capabilities_class, "getSupportedFrameRates",
271-
"()Landroid/util/Range;");
272-
SB_CHECK(cache.get_supported_frame_rates_method);
273-
env->DeleteLocalRef(video_capabilities_class);
274-
});
275-
276-
ScopedJavaLocalRef<jobject> j_width_range(
277-
env, env->CallObjectMethod(j_video_capabilities_.obj(),
278-
cache.get_supported_widths_method));
279-
SB_CHECK(j_width_range);
280-
supported_widths_ = ConvertJavaRangeToRange(env, j_width_range.obj());
281-
282-
ScopedJavaLocalRef<jobject> j_height_range(
283-
env, env->CallObjectMethod(j_video_capabilities_.obj(),
284-
cache.get_supported_heights_method));
285-
SB_CHECK(j_height_range);
286-
supported_heights_ = ConvertJavaRangeToRange(env, j_height_range.obj());
287-
288-
ScopedJavaLocalRef<jobject> j_bitrate_range(
289-
env, env->CallObjectMethod(j_video_capabilities_.obj(),
290-
cache.get_bitrate_range_method));
291-
SB_CHECK(j_bitrate_range);
292-
supported_bitrates_ = ConvertJavaRangeToRange(env, j_bitrate_range.obj());
293-
294-
ScopedJavaLocalRef<jobject> j_frame_rate_range(
295-
env, env->CallObjectMethod(j_video_capabilities_.obj(),
296-
cache.get_supported_frame_rates_method));
297-
SB_CHECK(j_frame_rate_range);
298-
supported_frame_rates_ =
299-
ConvertJavaRangeToRange(env, j_frame_rate_range.obj());
300-
}
301-
302-
VideoCodecCapability::~VideoCodecCapability() {}
192+
j_video_capabilities_(env, j_video_capabilities.obj()),
193+
supported_widths_(GetRange(env,
194+
j_video_capabilities_,
195+
&Java_MediaCodecUtil_getVideoWidthRange)),
196+
supported_heights_(GetRange(env,
197+
j_video_capabilities_,
198+
&Java_MediaCodecUtil_getVideoHeightRange)),
199+
supported_bitrates_(GetRange(env,
200+
j_video_capabilities_,
201+
&Java_MediaCodecUtil_getVideoBitrateRange)),
202+
supported_frame_rates_(
203+
GetRange(env,
204+
j_video_capabilities_,
205+
&Java_MediaCodecUtil_getVideoFrameRateRange)) {}
206+
VideoCodecCapability::~VideoCodecCapability() = default;
303207

304208
bool VideoCodecCapability::IsBitrateSupported(int bitrate) const {
305209
return supported_bitrates_.Contains(bitrate);
306210
}
307211

308212
bool VideoCodecCapability::AreResolutionAndRateSupported(int frame_width,
309213
int frame_height,
310-
int fps) {
214+
int fps) const {
311215
JNIEnv* env = AttachCurrentThread();
312-
struct AreResolutionAndRateSupportedJniCache {
313-
jmethodID are_size_and_rate_supported_method;
314-
jmethodID is_size_supported_method;
315-
};
316-
317-
static std::once_flag once_flag;
318-
static AreResolutionAndRateSupportedJniCache cache;
319-
320-
std::call_once(once_flag, [env]() {
321-
jclass video_capabilities_class =
322-
env->FindClass("android/media/MediaCodecInfo$VideoCapabilities");
323-
SB_CHECK(video_capabilities_class);
324-
325-
cache.are_size_and_rate_supported_method = env->GetMethodID(
326-
video_capabilities_class, "areSizeAndRateSupported", "(IID)Z");
327-
SB_CHECK(cache.are_size_and_rate_supported_method);
328-
329-
cache.is_size_supported_method =
330-
env->GetMethodID(video_capabilities_class, "isSizeSupported", "(II)Z");
331-
SB_CHECK(cache.is_size_supported_method);
332-
env->DeleteLocalRef(video_capabilities_class);
333-
});
334-
335216
if (frame_width != 0 && frame_height != 0 && fps != 0) {
336-
return env->CallBooleanMethod(
337-
j_video_capabilities_.obj(), cache.are_size_and_rate_supported_method,
338-
frame_width, frame_height, static_cast<jdouble>(fps));
217+
return Java_MediaCodecUtil_areSizeAndRateSupported(
218+
env, j_video_capabilities_, frame_width, frame_height,
219+
static_cast<jdouble>(fps));
339220
} else if (frame_width != 0 && frame_height != 0) {
340-
return env->CallBooleanMethod(j_video_capabilities_.obj(),
341-
cache.is_size_supported_method, frame_width,
342-
frame_height);
221+
return Java_MediaCodecUtil_isSizeSupported(env, j_video_capabilities_,
222+
frame_width, frame_height);
343223
}
344224
if (frame_width != 0 && !supported_widths_.Contains(frame_width)) {
345225
return false;

starboard/android/shared/media_capabilities_cache.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class AudioCodecCapability : public CodecCapability {
7878
AudioCodecCapability(const AudioCodecCapability&) = delete;
7979
AudioCodecCapability& operator=(const AudioCodecCapability&) = delete;
8080

81-
Range supported_bitrates_;
81+
const Range supported_bitrates_;
8282
};
8383

8484
class VideoCodecCapability : public CodecCapability {
@@ -100,7 +100,7 @@ class VideoCodecCapability : public CodecCapability {
100100
// supportability.
101101
bool AreResolutionAndRateSupported(int frame_width,
102102
int frame_height,
103-
int fps);
103+
int fps) const;
104104

105105
private:
106106
VideoCodecCapability(const VideoCodecCapability&) = delete;
@@ -109,10 +109,10 @@ class VideoCodecCapability : public CodecCapability {
109109
const bool is_software_decoder_;
110110
const bool is_hdr_capable_;
111111
const base::android::ScopedJavaGlobalRef<jobject> j_video_capabilities_;
112-
Range supported_widths_;
113-
Range supported_heights_;
114-
Range supported_bitrates_;
115-
Range supported_frame_rates_;
112+
const Range supported_widths_;
113+
const Range supported_heights_;
114+
const Range supported_bitrates_;
115+
const Range supported_frame_rates_;
116116
};
117117

118118
class MediaCapabilitiesCache {

0 commit comments

Comments
 (0)