#include "media/gpu/android/video_accelerator_util.h"
#include "base/android/build_info.h"
#include "base/android/jni_string.h"
#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h"
#include "media/base/android/media_jni_headers/VideoAcceleratorUtil_jni.h"
namespace media {
const std::vector<MediaCodecEncoderInfo>& GetEncoderInfoCache() {
static const base::NoDestructor<std::vector<MediaCodecEncoderInfo>> infos([] {
JNIEnv* env = base::android::AttachCurrentThread();
CHECK(env);
auto java_profiles =
Java_VideoAcceleratorUtil_getSupportedEncoderProfiles(env);
constexpr char kHasMediaCodecEncoderInfo[] =
"Media.Android.MediaCodecInfo.HasEncoderInfo";
std::vector<MediaCodecEncoderInfo> cpp_infos;
if (!java_profiles) {
base::UmaHistogramBoolean(kHasMediaCodecEncoderInfo, false);
return cpp_infos;
}
for (auto java_profile : java_profiles.ReadElements<jobject>()) {
MediaCodecEncoderInfo info;
info.profile.profile = static_cast<VideoCodecProfile>(
Java_SupportedProfileAdapter_getProfile(env, java_profile));
info.profile.min_resolution = gfx::Size(
Java_SupportedProfileAdapter_getMinWidth(env, java_profile),
Java_SupportedProfileAdapter_getMinHeight(env, java_profile));
info.profile.max_resolution = gfx::Size(
Java_SupportedProfileAdapter_getMaxWidth(env, java_profile),
Java_SupportedProfileAdapter_getMaxHeight(env, java_profile));
info.profile.max_framerate_numerator =
Java_SupportedProfileAdapter_getMaxFramerateNumerator(env,
java_profile);
info.profile.max_framerate_denominator =
Java_SupportedProfileAdapter_getMaxFramerateDenominator(env,
java_profile);
if (Java_SupportedProfileAdapter_supportsCbr(env, java_profile)) {
info.profile.rate_control_modes |=
VideoEncodeAccelerator::kConstantMode;
}
if (Java_SupportedProfileAdapter_supportsVbr(env, java_profile)) {
info.profile.rate_control_modes |=
VideoEncodeAccelerator::kVariableMode;
}
info.profile.is_software_codec =
Java_SupportedProfileAdapter_isSoftwareCodec(env, java_profile);
info.name = base::android::ConvertJavaStringToUTF8(
Java_SupportedProfileAdapter_getName(env, java_profile));
cpp_infos.push_back(info);
}
std::sort(
cpp_infos.begin(), cpp_infos.end(),
[](const MediaCodecEncoderInfo& a, const MediaCodecEncoderInfo& b) {
return a.profile.profile < b.profile.profile;
});
base::UmaHistogramBoolean(kHasMediaCodecEncoderInfo, !cpp_infos.empty());
return cpp_infos;
}());
return *infos;
}
const std::vector<MediaCodecDecoderInfo>& GetDecoderInfoCache() {
static const base::NoDestructor<std::vector<MediaCodecDecoderInfo>> infos([] {
JNIEnv* env = base::android::AttachCurrentThread();
CHECK(env);
auto java_profiles =
Java_VideoAcceleratorUtil_getSupportedDecoderProfiles(env);
constexpr char kHasMediaCodecDecoderInfo[] =
"Media.Android.MediaCodecInfo.HasDecoderInfo";
if (!java_profiles) {
base::UmaHistogramBoolean(kHasMediaCodecDecoderInfo, false);
LOG(ERROR)
<< "Unable to retreive MediaCodecInfo, assuming default support.";
constexpr auto kDefaultSize = gfx::Size(4096, 4096);
constexpr auto kSoftwareCodec = true;
constexpr auto kHardwareCodec = false;
constexpr char kUnknownDecoderName[] = "";
return std::vector<MediaCodecDecoderInfo>({
{H264PROFILE_BASELINE, kNoVideoCodecLevel, gfx::Size(), kDefaultSize,
kHardwareCodec, SecureCodecCapability::kClear, kUnknownDecoderName},
{H264PROFILE_MAIN, kNoVideoCodecLevel, gfx::Size(), kDefaultSize,
kHardwareCodec, SecureCodecCapability::kClear, kUnknownDecoderName},
{H264PROFILE_HIGH, kNoVideoCodecLevel, gfx::Size(), kDefaultSize,
kHardwareCodec, SecureCodecCapability::kClear, kUnknownDecoderName},
{HEVCPROFILE_MAIN, kNoVideoCodecLevel, gfx::Size(), kDefaultSize,
kHardwareCodec, SecureCodecCapability::kClear, kUnknownDecoderName},
{VP8PROFILE_ANY, kNoVideoCodecLevel, gfx::Size(), kDefaultSize,
kSoftwareCodec, SecureCodecCapability::kClear, kUnknownDecoderName},
{VP9PROFILE_PROFILE0, kNoVideoCodecLevel, gfx::Size(), kDefaultSize,
kSoftwareCodec, SecureCodecCapability::kClear, kUnknownDecoderName},
});
}
std::vector<MediaCodecDecoderInfo> cpp_infos;
for (auto java_profile : java_profiles.ReadElements<jobject>()) {
MediaCodecDecoderInfo info;
info.profile = static_cast<VideoCodecProfile>(
Java_SupportedProfileAdapter_getProfile(env, java_profile));
info.level = Java_SupportedProfileAdapter_getLevel(env, java_profile);
info.coded_size_min = gfx::Size(
Java_SupportedProfileAdapter_getMinWidth(env, java_profile),
Java_SupportedProfileAdapter_getMinHeight(env, java_profile));
info.coded_size_max = gfx::Size(
Java_SupportedProfileAdapter_getMaxWidth(env, java_profile),
Java_SupportedProfileAdapter_getMaxHeight(env, java_profile));
info.is_software_codec =
Java_SupportedProfileAdapter_isSoftwareCodec(env, java_profile);
bool supports_secure_playback =
Java_SupportedProfileAdapter_supportsSecurePlayback(env,
java_profile);
bool requires_secure_playback =
Java_SupportedProfileAdapter_requiresSecurePlayback(env,
java_profile);
DCHECK(!requires_secure_playback || supports_secure_playback);
info.secure_codec_capability =
requires_secure_playback
? SecureCodecCapability::kEncrypted
: (supports_secure_playback ? SecureCodecCapability::kAny
: SecureCodecCapability::kClear);
info.name = base::android::ConvertJavaStringToUTF8(
Java_SupportedProfileAdapter_getName(env, java_profile));
cpp_infos.push_back(info);
}
std::sort(
cpp_infos.begin(), cpp_infos.end(),
[](const MediaCodecDecoderInfo& a, const MediaCodecDecoderInfo& b) {
return a.profile < b.profile;
});
base::UmaHistogramBoolean(kHasMediaCodecDecoderInfo, !cpp_infos.empty());
return cpp_infos;
}());
return *infos;
}
}