media: pass full EncoderProfiles from XML

Get multiple audio/video codec profiles from MediaProfiles object
instead of just wrapping the old CamcorderProfiles objects.

Bug: 171673898
Test: atest CamcorderProfileTest
Change-Id: If56ac6c2a89992361f0491d8175af1f89dffd3d0
This commit is contained in:
Lajos Molnar
2021-04-30 16:31:24 -07:00
parent eee1089cb5
commit 973b2e89bd
3 changed files with 87 additions and 35 deletions

View File

@@ -602,39 +602,7 @@ public class CamcorderProfile
} catch (NumberFormatException e) {
return null;
}
CamcorderProfile cp = native_get_camcorder_profile(id, quality);
if (cp == null) {
return null;
};
EncoderProfiles.AudioProfile[] audioProfiles;
// timelapse profiles do not list audio profiles
if (cp.quality >= QUALITY_TIME_LAPSE_LIST_START
&& cp.quality <= QUALITY_TIME_LAPSE_LIST_END) {
audioProfiles = new EncoderProfiles.AudioProfile[] { };
} else {
audioProfiles = new EncoderProfiles.AudioProfile[] {
new EncoderProfiles.AudioProfile(
cp.audioCodec,
cp.audioChannels,
cp.audioSampleRate,
cp.audioBitRate)
};
}
return new EncoderProfiles(
cp.duration,
cp.fileFormat,
new EncoderProfiles.VideoProfile[] {
new EncoderProfiles.VideoProfile(
cp.videoCodec,
cp.videoFrameWidth,
cp.videoFrameHeight,
cp.videoFrameRate,
cp.videoBitRate,
0 /* TODO: get profile */)
},
audioProfiles);
return native_get_camcorder_profiles(id, quality);
}
/**
@@ -743,6 +711,8 @@ public class CamcorderProfile
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private static native final CamcorderProfile native_get_camcorder_profile(
int cameraId, int quality);
private static native final EncoderProfiles native_get_camcorder_profiles(
int cameraId, int quality);
private static native final boolean native_has_camcorder_profile(
int cameraId, int quality);
}

View File

@@ -181,7 +181,7 @@ public final class EncoderProfiles
/**
* The video encoder profile being used for the video track.
* <p>
* This value is 0 if there is no profile defined for the video codec.
* This value is negative if there is no profile defined for the video codec.
*
* @see MediaRecorder#setVideoEncodingProfileLevel
* @see MediaFormat#KEY_PROFILE
@@ -293,7 +293,7 @@ public final class EncoderProfiles
/**
* The audio encoder profile being used for the audio track
* <p>
* This value is 0 if there is no profile defined for the audio codec.
* This value is negative if there is no profile defined for the audio codec.
* @see MediaFormat#KEY_PROFILE
*/
public int getProfile() {

View File

@@ -223,6 +223,86 @@ android_media_MediaProfiles_native_get_camcorder_profile(JNIEnv *env, jobject /*
audioChannels);
}
static jobject
android_media_MediaProfiles_native_get_camcorder_profiles(JNIEnv *env, jobject /* thiz */, jint id,
jint quality)
{
ALOGV("native_get_camcorder_profiles: %d %d", id, quality);
if (!isCamcorderQualityKnown(quality)) {
jniThrowException(env, "java/lang/RuntimeException", "Unknown camcorder profile quality");
return NULL;
}
camcorder_quality q = static_cast<camcorder_quality>(quality);
const MediaProfiles::CamcorderProfile *cp = sProfiles->getCamcorderProfile(id, q);
if (!cp) {
jniThrowException(env, "java/lang/RuntimeException",
"Error retrieving camcorder profile params");
return NULL;
}
int duration = cp->getDuration();
int fileFormat = cp->getFileFormat();
jclass encoderProfilesClazz = env->FindClass("android/media/EncoderProfiles");
jmethodID encoderProfilesConstructorMethodID =
env->GetMethodID(encoderProfilesClazz, "<init>",
"(II[Landroid/media/EncoderProfiles$VideoProfile;[Landroid/media/EncoderProfiles$AudioProfile;)V");
jclass videoProfileClazz = env->FindClass("android/media/EncoderProfiles$VideoProfile");
jmethodID videoProfileConstructorMethodID =
env->GetMethodID(videoProfileClazz, "<init>", "(IIIIII)V");
jclass audioProfileClazz = env->FindClass("android/media/EncoderProfiles$AudioProfile");
jmethodID audioProfileConstructorMethodID =
env->GetMethodID(audioProfileClazz, "<init>", "(IIII)V");
jobjectArray videoCodecs = (jobjectArray)env->NewObjectArray(
cp->getVideoCodecs().size(), videoProfileClazz, nullptr);
{
int i = 0;
for (const MediaProfiles::VideoCodec *vc : cp->getVideoCodecs()) {
jobject videoCodec = env->NewObject(videoProfileClazz,
videoProfileConstructorMethodID,
vc->getCodec(),
vc->getFrameWidth(),
vc->getFrameHeight(),
vc->getFrameRate(),
vc->getBitrate(),
-1 /* profile */);
env->SetObjectArrayElement(videoCodecs, i++, videoCodec);
}
}
jobjectArray audioCodecs;
if (quality >= CAMCORDER_QUALITY_TIME_LAPSE_LIST_START
&& quality <= CAMCORDER_QUALITY_TIME_LAPSE_LIST_END) {
// timelapse profiles do not have audio codecs
audioCodecs = (jobjectArray)env->NewObjectArray(0, audioProfileClazz, nullptr);
} else {
audioCodecs = (jobjectArray)env->NewObjectArray(
cp->getAudioCodecs().size(), audioProfileClazz, nullptr);
int i = 0;
for (const MediaProfiles::AudioCodec *ac : cp->getAudioCodecs()) {
jobject audioCodec = env->NewObject(audioProfileClazz,
audioProfileConstructorMethodID,
ac->getCodec(),
ac->getChannels(),
ac->getSampleRate(),
ac->getBitrate());
env->SetObjectArrayElement(audioCodecs, i++, audioCodec);
}
}
return env->NewObject(encoderProfilesClazz,
encoderProfilesConstructorMethodID,
duration,
fileFormat,
videoCodecs,
audioCodecs);
}
static jboolean
android_media_MediaProfiles_native_has_camcorder_profile(JNIEnv* /* env */, jobject /* thiz */,
jint id, jint quality)
@@ -319,6 +399,8 @@ static const JNINativeMethod gMethodsForCamcorderProfileClass[] = {
{"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
{"native_get_camcorder_profile", "(II)Landroid/media/CamcorderProfile;",
(void *)android_media_MediaProfiles_native_get_camcorder_profile},
{"native_get_camcorder_profiles", "(II)Landroid/media/EncoderProfiles;",
(void *)android_media_MediaProfiles_native_get_camcorder_profiles},
{"native_has_camcorder_profile", "(II)Z",
(void *)android_media_MediaProfiles_native_has_camcorder_profile},
};