diff options
-rw-r--r-- | api/current.xml | 30 | ||||
-rw-r--r-- | include/media/MediaProfiles.h | 35 | ||||
-rw-r--r-- | media/java/android/media/CamcorderProfile.java | 18 | ||||
-rw-r--r-- | media/java/android/media/CameraProfile.java | 38 | ||||
-rw-r--r-- | media/jni/android_media_MediaProfiles.cpp | 40 | ||||
-rw-r--r-- | media/libmedia/MediaProfiles.cpp | 81 |
6 files changed, 179 insertions, 63 deletions
diff --git a/api/current.xml b/api/current.xml index 9145462..5d71cad 100644 --- a/api/current.xml +++ b/api/current.xml @@ -87294,6 +87294,21 @@ <parameter name="quality" type="int"> </parameter> </method> +<method name="get" + return="android.media.CamcorderProfile" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="cameraId" type="int"> +</parameter> +<parameter name="quality" type="int"> +</parameter> +</method> <field name="QUALITY_HIGH" type="int" transient="false" @@ -87466,6 +87481,21 @@ <parameter name="quality" type="int"> </parameter> </method> +<method name="getJpegEncodingQualityParameter" + return="int" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="cameraId" type="int"> +</parameter> +<parameter name="quality" type="int"> +</parameter> +</method> <field name="QUALITY_HIGH" type="int" transient="false" diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h index a4eea2a..c3cd361 100644 --- a/include/media/MediaProfiles.h +++ b/include/media/MediaProfiles.h @@ -48,8 +48,8 @@ public: static MediaProfiles* getInstance(); /** - * Returns the value for the given param name at the given quality level, - * or -1 if error. + * Returns the value for the given param name for the given camera at + * the given quality level, or -1 if error. * * Supported param name are: * duration - the recording duration. @@ -64,7 +64,8 @@ public: * aud.hz - audio sample rate * aud.ch - number of audio channels */ - int getCamcorderProfileParamByName(const char *name, camcorder_quality quality) const; + int getCamcorderProfileParamByName(const char *name, int cameraId, + camcorder_quality quality) const; /** * Returns the output file formats supported. @@ -124,12 +125,7 @@ public: /** * Returns the number of image encoding quality levels supported. */ - Vector<int> getImageEncodingQualityLevels() const; - - /** - * Returns the maximum amount of memory in bytes we can use for decoding a JPEG file. - */ - int getImageDecodingMaxMemory() const; + Vector<int> getImageEncodingQualityLevels(int cameraId) const; private: MediaProfiles& operator=(const MediaProfiles&); // Don't call me @@ -171,7 +167,8 @@ private: struct CamcorderProfile { CamcorderProfile() - : mFileFormat(OUTPUT_FORMAT_THREE_GPP), + : mCameraId(0), + mFileFormat(OUTPUT_FORMAT_THREE_GPP), mQuality(CAMCORDER_QUALITY_HIGH), mDuration(0), mVideoCodec(0), @@ -182,6 +179,7 @@ private: delete mAudioCodec; } + int mCameraId; output_format mFileFormat; camcorder_quality mQuality; int mDuration; @@ -249,6 +247,11 @@ private: int tag; }; + struct ImageEncodingQualityLevels { + int mCameraId; + Vector<int> mLevels; + }; + // Debug static void logVideoCodec(const VideoCodec& codec); static void logAudioCodec(const AudioCodec& codec); @@ -267,9 +270,11 @@ private: static VideoDecoderCap* createVideoDecoderCap(const char **atts); static VideoEncoderCap* createVideoEncoderCap(const char **atts); static AudioEncoderCap* createAudioEncoderCap(const char **atts); - static CamcorderProfile* createCamcorderProfile(const char **atts); - static int getImageEncodingQualityLevel(const char **atts); - static int getImageDecodingMaxMemory(const char **atts); + static CamcorderProfile* createCamcorderProfile(int cameraId, const char **atts); + static int getCameraId(const char **atts); + + ImageEncodingQualityLevels* findImageEncodingQualityLevels(int cameraId) const; + void addImageEncodingQualityLevel(int cameraId, const char** atts); // Customized element tag handler for parsing the xml configuration file. static void startElementHandler(void *userData, const char *name, const char **atts); @@ -303,6 +308,7 @@ private: static bool sIsInitialized; static MediaProfiles *sInstance; static Mutex sLock; + int mCurrentCameraId; Vector<CamcorderProfile*> mCamcorderProfiles; Vector<AudioEncoderCap*> mAudioEncoders; @@ -310,8 +316,7 @@ private: Vector<AudioDecoderCap*> mAudioDecoders; Vector<VideoDecoderCap*> mVideoDecoders; Vector<output_format> mEncoderOutputFileFormats; - Vector<int> mImageEncodingQualityLevels; - int mImageDecodingMaxMemory; + Vector<ImageEncodingQualityLevels *> mImageEncodingQualityLevels; }; }; // namespace android diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java index 64d6460..a27df57 100644 --- a/media/java/android/media/CamcorderProfile.java +++ b/media/java/android/media/CamcorderProfile.java @@ -119,15 +119,26 @@ public class CamcorderProfile public int audioChannels; /** - * Returns the camcorder profile for the given quality level. + * Returns the camcorder profile for the default camera at the given + * quality level. * @param quality the target quality level for the camcorder profile */ public static CamcorderProfile get(int quality) { + return get(0, quality); + } + + /** + * Returns the camcorder profile for the given camera at the given + * quality level. + * @param cameraId the id for the camera + * @param quality the target quality level for the camcorder profile + */ + public static CamcorderProfile get(int cameraId, int quality) { if (quality < QUALITY_LOW || quality > QUALITY_HIGH) { String errMessage = "Unsupported quality level: " + quality; throw new IllegalArgumentException(errMessage); } - return native_get_camcorder_profile(quality); + return native_get_camcorder_profile(cameraId, quality); } static { @@ -165,5 +176,6 @@ public class CamcorderProfile // Methods implemented by JNI private static native final void native_init(); - private static native final CamcorderProfile native_get_camcorder_profile(int quality); + private static native final CamcorderProfile native_get_camcorder_profile( + int cameraId, int quality); } diff --git a/media/java/android/media/CameraProfile.java b/media/java/android/media/CameraProfile.java index f8d3935..6a0be08 100644 --- a/media/java/android/media/CameraProfile.java +++ b/media/java/android/media/CameraProfile.java @@ -17,6 +17,7 @@ package android.media; import java.util.Arrays; +import java.util.HashMap; /** * The CameraProfile class is used to retrieve the pre-defined still image @@ -40,36 +41,55 @@ public class CameraProfile /* * Cache the Jpeg encoding quality parameters */ - private static final int[] sJpegEncodingQualityParameters; + private static final HashMap<Integer, int[]> sCache = new HashMap<Integer, int[]>(); /** * Returns a pre-defined still image capture (jpeg) quality level - * used for the given quality level in the Camera application. + * used for the given quality level in the Camera application for + * the default camera. * * @param quality The target quality level */ public static int getJpegEncodingQualityParameter(int quality) { + return getJpegEncodingQualityParameter(0, quality); + } + + /** + * Returns a pre-defined still image capture (jpeg) quality level + * used for the given quality level in the Camera application for + * the specified camera. + * + * @param cameraId The id of the camera + * @param quality The target quality level + */ + public static int getJpegEncodingQualityParameter(int cameraId, int quality) { if (quality < QUALITY_LOW || quality > QUALITY_HIGH) { throw new IllegalArgumentException("Unsupported quality level: " + quality); } - return sJpegEncodingQualityParameters[quality]; + synchronized (sCache) { + int[] levels = sCache.get(cameraId); + if (levels == null) { + levels = getImageEncodingQualityLevels(cameraId); + sCache.put(cameraId, levels); + } + return levels[quality]; + } } static { System.loadLibrary("media_jni"); native_init(); - sJpegEncodingQualityParameters = getImageEncodingQualityLevels(); } - private static int[] getImageEncodingQualityLevels() { - int nLevels = native_get_num_image_encoding_quality_levels(); + private static int[] getImageEncodingQualityLevels(int cameraId) { + int nLevels = native_get_num_image_encoding_quality_levels(cameraId); if (nLevels != QUALITY_HIGH + 1) { throw new RuntimeException("Unexpected Jpeg encoding quality levels " + nLevels); } int[] levels = new int[nLevels]; for (int i = 0; i < nLevels; ++i) { - levels[i] = native_get_image_encoding_quality_level(i); + levels[i] = native_get_image_encoding_quality_level(cameraId, i); } Arrays.sort(levels); // Lower quality level ALWAYS comes before higher one return levels; @@ -77,6 +97,6 @@ public class CameraProfile // Methods implemented by JNI private static native final void native_init(); - private static native final int native_get_num_image_encoding_quality_levels(); - private static native final int native_get_image_encoding_quality_level(int index); + private static native final int native_get_num_image_encoding_quality_levels(int cameraId); + private static native final int native_get_image_encoding_quality_level(int cameraId, int index); } diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp index 7d7533a..cce9fd0 100644 --- a/media/jni/android_media_MediaProfiles.cpp +++ b/media/jni/android_media_MediaProfiles.cpp @@ -162,26 +162,26 @@ android_media_MediaProfiles_native_get_audio_encoder_cap(JNIEnv *env, jobject th } static jobject -android_media_MediaProfiles_native_get_camcorder_profile(JNIEnv *env, jobject thiz, jint quality) +android_media_MediaProfiles_native_get_camcorder_profile(JNIEnv *env, jobject thiz, jint id, jint quality) { - LOGV("native_get_camcorder_profile: %d", quality); + LOGV("native_get_camcorder_profile: %d %d", id, quality); if (quality != CAMCORDER_QUALITY_HIGH && quality != CAMCORDER_QUALITY_LOW) { jniThrowException(env, "java/lang/RuntimeException", "Unknown camcorder profile quality"); return NULL; } camcorder_quality q = static_cast<camcorder_quality>(quality); - int duration = sProfiles->getCamcorderProfileParamByName("duration", q); - int fileFormat = sProfiles->getCamcorderProfileParamByName("file.format", q); - int videoCodec = sProfiles->getCamcorderProfileParamByName("vid.codec", q); - int videoBitRate = sProfiles->getCamcorderProfileParamByName("vid.bps", q); - int videoFrameRate = sProfiles->getCamcorderProfileParamByName("vid.fps", q); - int videoFrameWidth = sProfiles->getCamcorderProfileParamByName("vid.width", q); - int videoFrameHeight = sProfiles->getCamcorderProfileParamByName("vid.height", q); - int audioCodec = sProfiles->getCamcorderProfileParamByName("aud.codec", q); - int audioBitRate = sProfiles->getCamcorderProfileParamByName("aud.bps", q); - int audioSampleRate = sProfiles->getCamcorderProfileParamByName("aud.hz", q); - int audioChannels = sProfiles->getCamcorderProfileParamByName("aud.ch", q); + int duration = sProfiles->getCamcorderProfileParamByName("duration", id, q); + int fileFormat = sProfiles->getCamcorderProfileParamByName("file.format", id, q); + int videoCodec = sProfiles->getCamcorderProfileParamByName("vid.codec", id, q); + int videoBitRate = sProfiles->getCamcorderProfileParamByName("vid.bps", id, q); + int videoFrameRate = sProfiles->getCamcorderProfileParamByName("vid.fps", id, q); + int videoFrameWidth = sProfiles->getCamcorderProfileParamByName("vid.width", id, q); + int videoFrameHeight = sProfiles->getCamcorderProfileParamByName("vid.height", id, q); + int audioCodec = sProfiles->getCamcorderProfileParamByName("aud.codec", id, q); + int audioBitRate = sProfiles->getCamcorderProfileParamByName("aud.bps", id, q); + int audioSampleRate = sProfiles->getCamcorderProfileParamByName("aud.hz", id, q); + int audioChannels = sProfiles->getCamcorderProfileParamByName("aud.ch", id, q); // Check on the values retrieved if (duration == -1 || fileFormat == -1 || videoCodec == -1 || audioCodec == -1 || @@ -253,17 +253,17 @@ android_media_MediaProfiles_native_get_audio_decoder_type(JNIEnv *env, jobject t } static jint -android_media_MediaProfiles_native_get_num_image_encoding_quality_levels(JNIEnv *env, jobject thiz) +android_media_MediaProfiles_native_get_num_image_encoding_quality_levels(JNIEnv *env, jobject thiz, jint cameraId) { LOGV("native_get_num_image_encoding_quality_levels"); - return sProfiles->getImageEncodingQualityLevels().size(); + return sProfiles->getImageEncodingQualityLevels(cameraId).size(); } static jint -android_media_MediaProfiles_native_get_image_encoding_quality_level(JNIEnv *env, jobject thiz, jint index) +android_media_MediaProfiles_native_get_image_encoding_quality_level(JNIEnv *env, jobject thiz, jint cameraId, jint index) { LOGV("native_get_image_encoding_quality_level"); - Vector<int> levels = sProfiles->getImageEncodingQualityLevels(); + Vector<int> levels = sProfiles->getImageEncodingQualityLevels(cameraId); if (index < 0 || index >= levels.size()) { jniThrowException(env, "java/lang/IllegalArgumentException", "out of array boundary"); return -1; @@ -287,7 +287,7 @@ static JNINativeMethod gMethodsForEncoderCapabilitiesClass[] = { static JNINativeMethod gMethodsForCamcorderProfileClass[] = { {"native_init", "()V", (void *)android_media_MediaProfiles_native_init}, - {"native_get_camcorder_profile", "(I)Landroid/media/CamcorderProfile;", + {"native_get_camcorder_profile", "(II)Landroid/media/CamcorderProfile;", (void *)android_media_MediaProfiles_native_get_camcorder_profile}, }; @@ -302,8 +302,8 @@ static JNINativeMethod gMethodsForDecoderCapabilitiesClass[] = { static JNINativeMethod gMethodsForCameraProfileClass[] = { {"native_init", "()V", (void *)android_media_MediaProfiles_native_init}, {"native_get_num_image_encoding_quality_levels", - "()I", (void *)android_media_MediaProfiles_native_get_num_image_encoding_quality_levels}, - {"native_get_image_encoding_quality_level","(I)I", (void *)android_media_MediaProfiles_native_get_image_encoding_quality_level}, + "(I)I", (void *)android_media_MediaProfiles_native_get_num_image_encoding_quality_levels}, + {"native_get_image_encoding_quality_level","(II)I", (void *)android_media_MediaProfiles_native_get_image_encoding_quality_level}, }; static const char* const kEncoderCapabilitiesClassPathName = "android/media/EncoderCapabilities"; diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index 1263373..3869389 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -272,7 +272,7 @@ MediaProfiles::createEncoderOutputFileFormat(const char **atts) } /*static*/ MediaProfiles::CamcorderProfile* -MediaProfiles::createCamcorderProfile(const char **atts) +MediaProfiles::createCamcorderProfile(int cameraId, const char **atts) { CHECK(!strcmp("quality", atts[0]) && !strcmp("fileFormat", atts[2]) && @@ -287,16 +287,47 @@ MediaProfiles::createCamcorderProfile(const char **atts) CHECK(fileFormat != -1); MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; + profile->mCameraId = cameraId; profile->mFileFormat = static_cast<output_format>(fileFormat); profile->mQuality = static_cast<camcorder_quality>(quality); profile->mDuration = atoi(atts[5]); return profile; } -/*static*/ int -MediaProfiles::getImageEncodingQualityLevel(const char** atts) +MediaProfiles::ImageEncodingQualityLevels* +MediaProfiles::findImageEncodingQualityLevels(int cameraId) const +{ + int n = mImageEncodingQualityLevels.size(); + for (int i = 0; i < n; i++) { + ImageEncodingQualityLevels *levels = mImageEncodingQualityLevels[i]; + if (levels->mCameraId == cameraId) { + return levels; + } + } + return NULL; +} + +void MediaProfiles::addImageEncodingQualityLevel(int cameraId, const char** atts) { CHECK(!strcmp("quality", atts[0])); + int quality = atoi(atts[1]); + LOGV("%s: cameraId=%d, quality=%d\n", __func__, cameraId, quality); + ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId); + + if (levels == NULL) { + levels = new ImageEncodingQualityLevels(); + levels->mCameraId = cameraId; + mImageEncodingQualityLevels.add(levels); + } + + levels->mLevels.add(quality); +} + +/*static*/ int +MediaProfiles::getCameraId(const char** atts) +{ + if (!atts[0]) return 0; // default cameraId = 0 + CHECK(!strcmp("cameraId", atts[0])); return atoi(atts[1]); } @@ -322,10 +353,13 @@ MediaProfiles::startElementHandler(void *userData, const char *name, const char profiles->mAudioDecoders.add(createAudioDecoderCap(atts)); } else if (strcmp("EncoderOutputFileFormat", name) == 0) { profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts)); + } else if (strcmp("CamcorderProfiles", name) == 0) { + profiles->mCurrentCameraId = getCameraId(atts); } else if (strcmp("EncoderProfile", name) == 0) { - profiles->mCamcorderProfiles.add(createCamcorderProfile(atts)); + profiles->mCamcorderProfiles.add( + createCamcorderProfile(profiles->mCurrentCameraId, atts)); } else if (strcmp("ImageEncoding", name) == 0) { - profiles->mImageEncodingQualityLevels.add(getImageEncodingQualityLevel(atts)); + profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts); } } @@ -383,7 +417,8 @@ MediaProfiles::createDefaultCamcorderHighProfile() new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20); AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); - CamcorderProfile *profile = new CamcorderProfile; + CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; + profile->mCameraId = 0; profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; profile->mQuality = CAMCORDER_QUALITY_HIGH; profile->mDuration = 60; @@ -402,6 +437,7 @@ MediaProfiles::createDefaultCamcorderLowProfile() new MediaProfiles::AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; + profile->mCameraId = 0; profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; profile->mQuality = CAMCORDER_QUALITY_LOW; profile->mDuration = 30; @@ -458,9 +494,12 @@ MediaProfiles::createDefaultAmrNBEncoderCap() /*static*/ void MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles) { - profiles->mImageEncodingQualityLevels.add(70); - profiles->mImageEncodingQualityLevels.add(80); - profiles->mImageEncodingQualityLevels.add(90); + ImageEncodingQualityLevels *levels = new ImageEncodingQualityLevels(); + levels->mCameraId = 0; + levels->mLevels.add(70); + levels->mLevels.add(80); + levels->mLevels.add(90); + profiles->mImageEncodingQualityLevels.add(levels); } /*static*/ MediaProfiles* @@ -629,19 +668,24 @@ Vector<audio_decoder> MediaProfiles::getAudioDecoders() const return decoders; // copy out } -int MediaProfiles::getCamcorderProfileParamByName(const char *name, camcorder_quality quality) const +int MediaProfiles::getCamcorderProfileParamByName(const char *name, + int cameraId, + camcorder_quality quality) const { - LOGV("getCamcorderProfileParamByName: %s for quality %d", name, quality); + LOGV("getCamcorderProfileParamByName: %s for camera %d, quality %d", + name, cameraId, quality); int index = -1; for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) { - if (mCamcorderProfiles[i]->mQuality == quality) { + if (mCamcorderProfiles[i]->mCameraId == cameraId && + mCamcorderProfiles[i]->mQuality == quality) { index = i; break; } } if (index == -1) { - LOGE("The given camcorder profile quality %d is not found", quality); + LOGE("The given camcorder profile camera %d quality %d is not found", + cameraId, quality); return -1; } @@ -657,13 +701,18 @@ int MediaProfiles::getCamcorderProfileParamByName(const char *name, camcorder_qu if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodec->mChannels; if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodec->mSampleRate; - LOGE("The given camcorder profile param name %s is not found", name); + LOGE("The given camcorder profile param id %d name %s is not found", cameraId, name); return -1; } -Vector<int> MediaProfiles::getImageEncodingQualityLevels() const +Vector<int> MediaProfiles::getImageEncodingQualityLevels(int cameraId) const { - return mImageEncodingQualityLevels; // copy out + Vector<int> result; + ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId); + if (levels != NULL) { + result = levels->mLevels; // copy out + } + return result; } MediaProfiles::~MediaProfiles() |