android_media_MediaProfiles.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. * Copyright (C) 2010 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. //#define LOG_NDEBUG 0
  17. #define LOG_TAG "MediaProfilesJNI"
  18. #include <utils/Log.h>
  19. #include <stdio.h>
  20. #include <utils/threads.h>
  21. #include "jni.h"
  22. #include <nativehelper/JNIHelp.h>
  23. #include "android_runtime/AndroidRuntime.h"
  24. #include <media/MediaProfiles.h>
  25. using namespace android;
  26. static Mutex sLock;
  27. MediaProfiles *sProfiles = NULL;
  28. // This function is called from a static block in MediaProfiles.java class,
  29. // which won't run until the first time an instance of this class is used.
  30. static void
  31. android_media_MediaProfiles_native_init(JNIEnv* /* env */)
  32. {
  33. ALOGV("native_init");
  34. Mutex::Autolock lock(sLock);
  35. if (sProfiles == NULL) {
  36. sProfiles = MediaProfiles::getInstance();
  37. }
  38. }
  39. static jint
  40. android_media_MediaProfiles_native_get_num_file_formats(JNIEnv* /* env */, jobject /* thiz */)
  41. {
  42. ALOGV("native_get_num_file_formats");
  43. return (jint) sProfiles->getOutputFileFormats().size();
  44. }
  45. static jint
  46. android_media_MediaProfiles_native_get_file_format(JNIEnv *env, jobject /* thiz */, jint index)
  47. {
  48. ALOGV("native_get_file_format: %d", index);
  49. Vector<output_format> formats = sProfiles->getOutputFileFormats();
  50. int nSize = formats.size();
  51. if (index < 0 || index >= nSize) {
  52. jniThrowException(env, "java/lang/IllegalArgumentException", "out of array boundary");
  53. return -1;
  54. }
  55. return static_cast<jint>(formats[index]);
  56. }
  57. static jint
  58. android_media_MediaProfiles_native_get_num_video_encoders(JNIEnv* /* env */, jobject /* thiz */)
  59. {
  60. ALOGV("native_get_num_video_encoders");
  61. return sProfiles->getVideoEncoders().size();
  62. }
  63. static jobject
  64. android_media_MediaProfiles_native_get_video_encoder_cap(JNIEnv *env, jobject /* thiz */,
  65. jint index)
  66. {
  67. ALOGV("native_get_video_encoder_cap: %d", index);
  68. Vector<video_encoder> encoders = sProfiles->getVideoEncoders();
  69. int nSize = encoders.size();
  70. if (index < 0 || index >= nSize) {
  71. jniThrowException(env, "java/lang/IllegalArgumentException", "out of array boundary");
  72. return NULL;
  73. }
  74. video_encoder encoder = encoders[index];
  75. int minBitRate = sProfiles->getVideoEncoderParamByName("enc.vid.bps.min", encoder);
  76. int maxBitRate = sProfiles->getVideoEncoderParamByName("enc.vid.bps.max", encoder);
  77. int minFrameRate = sProfiles->getVideoEncoderParamByName("enc.vid.fps.min", encoder);
  78. int maxFrameRate = sProfiles->getVideoEncoderParamByName("enc.vid.fps.max", encoder);
  79. int minFrameWidth = sProfiles->getVideoEncoderParamByName("enc.vid.width.min", encoder);
  80. int maxFrameWidth = sProfiles->getVideoEncoderParamByName("enc.vid.width.max", encoder);
  81. int minFrameHeight = sProfiles->getVideoEncoderParamByName("enc.vid.height.min", encoder);
  82. int maxFrameHeight = sProfiles->getVideoEncoderParamByName("enc.vid.height.max", encoder);
  83. // Check on the values retrieved
  84. if ((minBitRate == -1 || maxBitRate == -1) ||
  85. (minFrameRate == -1 || maxFrameRate == -1) ||
  86. (minFrameWidth == -1 || maxFrameWidth == -1) ||
  87. (minFrameHeight == -1 || maxFrameHeight == -1)) {
  88. jniThrowException(env, "java/lang/RuntimeException", "Error retrieving video encoder capability params");
  89. return NULL;
  90. }
  91. // Construct an instance of the VideoEncoderCap and set its member variables
  92. jclass videoEncoderCapClazz = env->FindClass("android/media/EncoderCapabilities$VideoEncoderCap");
  93. jmethodID videoEncoderCapConstructorMethodID = env->GetMethodID(videoEncoderCapClazz, "<init>", "(IIIIIIIII)V");
  94. jobject cap = env->NewObject(videoEncoderCapClazz,
  95. videoEncoderCapConstructorMethodID,
  96. static_cast<int>(encoder),
  97. minBitRate, maxBitRate,
  98. minFrameRate, maxFrameRate,
  99. minFrameWidth, maxFrameWidth,
  100. minFrameHeight, maxFrameHeight);
  101. return cap;
  102. }
  103. static jint
  104. android_media_MediaProfiles_native_get_num_audio_encoders(JNIEnv* /* env */, jobject /* thiz */)
  105. {
  106. ALOGV("native_get_num_audio_encoders");
  107. return (jint) sProfiles->getAudioEncoders().size();
  108. }
  109. static jobject
  110. android_media_MediaProfiles_native_get_audio_encoder_cap(JNIEnv *env, jobject /* thiz */,
  111. jint index)
  112. {
  113. ALOGV("native_get_audio_encoder_cap: %d", index);
  114. Vector<audio_encoder> encoders = sProfiles->getAudioEncoders();
  115. int nSize = encoders.size();
  116. if (index < 0 || index >= nSize) {
  117. jniThrowException(env, "java/lang/IllegalArgumentException", "out of array boundary");
  118. return NULL;
  119. }
  120. audio_encoder encoder = encoders[index];
  121. int minBitRate = sProfiles->getAudioEncoderParamByName("enc.aud.bps.min", encoder);
  122. int maxBitRate = sProfiles->getAudioEncoderParamByName("enc.aud.bps.max", encoder);
  123. int minSampleRate = sProfiles->getAudioEncoderParamByName("enc.aud.hz.min", encoder);
  124. int maxSampleRate = sProfiles->getAudioEncoderParamByName("enc.aud.hz.max", encoder);
  125. int minChannels = sProfiles->getAudioEncoderParamByName("enc.aud.ch.min", encoder);
  126. int maxChannels = sProfiles->getAudioEncoderParamByName("enc.aud.ch.max", encoder);
  127. // Check on the values retrieved
  128. if ((minBitRate == -1 || maxBitRate == -1) ||
  129. (minSampleRate == -1 || maxSampleRate == -1) ||
  130. (minChannels == -1 || maxChannels == -1)) {
  131. jniThrowException(env, "java/lang/RuntimeException", "Error retrieving video encoder capability params");
  132. return NULL;
  133. }
  134. jclass audioEncoderCapClazz = env->FindClass("android/media/EncoderCapabilities$AudioEncoderCap");
  135. jmethodID audioEncoderCapConstructorMethodID = env->GetMethodID(audioEncoderCapClazz, "<init>", "(IIIIIII)V");
  136. jobject cap = env->NewObject(audioEncoderCapClazz,
  137. audioEncoderCapConstructorMethodID,
  138. static_cast<int>(encoder),
  139. minBitRate, maxBitRate,
  140. minSampleRate, maxSampleRate,
  141. minChannels, maxChannels);
  142. return cap;
  143. }
  144. static bool isCamcorderQualityKnown(int quality)
  145. {
  146. return ((quality >= CAMCORDER_QUALITY_LIST_START &&
  147. quality <= CAMCORDER_QUALITY_LIST_END) ||
  148. (quality >= CAMCORDER_QUALITY_TIME_LAPSE_LIST_START &&
  149. quality <= CAMCORDER_QUALITY_TIME_LAPSE_LIST_END) ||
  150. (quality >= CAMCORDER_QUALITY_HIGH_SPEED_LIST_START &&
  151. quality <= CAMCORDER_QUALITY_HIGH_SPEED_LIST_END));
  152. }
  153. static jobject
  154. android_media_MediaProfiles_native_get_camcorder_profile(JNIEnv *env, jobject /* thiz */, jint id,
  155. jint quality)
  156. {
  157. ALOGV("native_get_camcorder_profile: %d %d", id, quality);
  158. if (!isCamcorderQualityKnown(quality)) {
  159. jniThrowException(env, "java/lang/RuntimeException", "Unknown camcorder profile quality");
  160. return NULL;
  161. }
  162. camcorder_quality q = static_cast<camcorder_quality>(quality);
  163. int duration = sProfiles->getCamcorderProfileParamByName("duration", id, q);
  164. int fileFormat = sProfiles->getCamcorderProfileParamByName("file.format", id, q);
  165. int videoCodec = sProfiles->getCamcorderProfileParamByName("vid.codec", id, q);
  166. int videoBitRate = sProfiles->getCamcorderProfileParamByName("vid.bps", id, q);
  167. int videoFrameRate = sProfiles->getCamcorderProfileParamByName("vid.fps", id, q);
  168. int videoFrameWidth = sProfiles->getCamcorderProfileParamByName("vid.width", id, q);
  169. int videoFrameHeight = sProfiles->getCamcorderProfileParamByName("vid.height", id, q);
  170. int audioCodec = sProfiles->getCamcorderProfileParamByName("aud.codec", id, q);
  171. int audioBitRate = sProfiles->getCamcorderProfileParamByName("aud.bps", id, q);
  172. int audioSampleRate = sProfiles->getCamcorderProfileParamByName("aud.hz", id, q);
  173. int audioChannels = sProfiles->getCamcorderProfileParamByName("aud.ch", id, q);
  174. // Check on the values retrieved
  175. if (duration == -1 || fileFormat == -1 || videoCodec == -1 || audioCodec == -1 ||
  176. videoBitRate == -1 || videoFrameRate == -1 || videoFrameWidth == -1 || videoFrameHeight == -1 ||
  177. audioBitRate == -1 || audioSampleRate == -1 || audioChannels == -1) {
  178. jniThrowException(env, "java/lang/RuntimeException", "Error retrieving camcorder profile params");
  179. return NULL;
  180. }
  181. jclass camcorderProfileClazz = env->FindClass("android/media/CamcorderProfile");
  182. jmethodID camcorderProfileConstructorMethodID = env->GetMethodID(camcorderProfileClazz, "<init>", "(IIIIIIIIIIII)V");
  183. return env->NewObject(camcorderProfileClazz,
  184. camcorderProfileConstructorMethodID,
  185. duration,
  186. quality,
  187. fileFormat,
  188. videoCodec,
  189. videoBitRate,
  190. videoFrameRate,
  191. videoFrameWidth,
  192. videoFrameHeight,
  193. audioCodec,
  194. audioBitRate,
  195. audioSampleRate,
  196. audioChannels);
  197. }
  198. static jboolean
  199. android_media_MediaProfiles_native_has_camcorder_profile(JNIEnv* /* env */, jobject /* thiz */,
  200. jint id, jint quality)
  201. {
  202. ALOGV("native_has_camcorder_profile: %d %d", id, quality);
  203. if (!isCamcorderQualityKnown(quality)) {
  204. return JNI_FALSE;
  205. }
  206. camcorder_quality q = static_cast<camcorder_quality>(quality);
  207. return sProfiles->hasCamcorderProfile(id, q) ? JNI_TRUE : JNI_FALSE;
  208. }
  209. static jint
  210. android_media_MediaProfiles_native_get_num_video_decoders(JNIEnv* /* env */, jobject /* thiz */)
  211. {
  212. ALOGV("native_get_num_video_decoders");
  213. return (jint) sProfiles->getVideoDecoders().size();
  214. }
  215. static jint
  216. android_media_MediaProfiles_native_get_video_decoder_type(JNIEnv *env, jobject /* thiz */,
  217. jint index)
  218. {
  219. ALOGV("native_get_video_decoder_type: %d", index);
  220. Vector<video_decoder> decoders = sProfiles->getVideoDecoders();
  221. int nSize = decoders.size();
  222. if (index < 0 || index >= nSize) {
  223. jniThrowException(env, "java/lang/IllegalArgumentException", "out of array boundary");
  224. return -1;
  225. }
  226. return static_cast<jint>(decoders[index]);
  227. }
  228. static jint
  229. android_media_MediaProfiles_native_get_num_audio_decoders(JNIEnv* /* env */, jobject /* thiz */)
  230. {
  231. ALOGV("native_get_num_audio_decoders");
  232. return (jint) sProfiles->getAudioDecoders().size();
  233. }
  234. static jint
  235. android_media_MediaProfiles_native_get_audio_decoder_type(JNIEnv *env, jobject /* thiz */,
  236. jint index)
  237. {
  238. ALOGV("native_get_audio_decoder_type: %d", index);
  239. Vector<audio_decoder> decoders = sProfiles->getAudioDecoders();
  240. int nSize = decoders.size();
  241. if (index < 0 || index >= nSize) {
  242. jniThrowException(env, "java/lang/IllegalArgumentException", "out of array boundary");
  243. return -1;
  244. }
  245. return static_cast<jint>(decoders[index]);
  246. }
  247. static jint
  248. android_media_MediaProfiles_native_get_num_image_encoding_quality_levels(JNIEnv* /* env */,
  249. jobject /* thiz */,
  250. jint cameraId)
  251. {
  252. ALOGV("native_get_num_image_encoding_quality_levels");
  253. return (jint) sProfiles->getImageEncodingQualityLevels(cameraId).size();
  254. }
  255. static jint
  256. android_media_MediaProfiles_native_get_image_encoding_quality_level(JNIEnv *env, jobject /* thiz */,
  257. jint cameraId, jint index)
  258. {
  259. ALOGV("native_get_image_encoding_quality_level");
  260. Vector<int> levels = sProfiles->getImageEncodingQualityLevels(cameraId);
  261. if (index < 0 || index >= (jint) levels.size()) {
  262. jniThrowException(env, "java/lang/IllegalArgumentException", "out of array boundary");
  263. return -1;
  264. }
  265. return static_cast<jint>(levels[index]);
  266. }
  267. static const JNINativeMethod gMethodsForEncoderCapabilitiesClass[] = {
  268. {"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
  269. {"native_get_num_file_formats", "()I", (void *)android_media_MediaProfiles_native_get_num_file_formats},
  270. {"native_get_file_format", "(I)I", (void *)android_media_MediaProfiles_native_get_file_format},
  271. {"native_get_num_video_encoders", "()I", (void *)android_media_MediaProfiles_native_get_num_video_encoders},
  272. {"native_get_num_audio_encoders", "()I", (void *)android_media_MediaProfiles_native_get_num_audio_encoders},
  273. {"native_get_video_encoder_cap", "(I)Landroid/media/EncoderCapabilities$VideoEncoderCap;",
  274. (void *)android_media_MediaProfiles_native_get_video_encoder_cap},
  275. {"native_get_audio_encoder_cap", "(I)Landroid/media/EncoderCapabilities$AudioEncoderCap;",
  276. (void *)android_media_MediaProfiles_native_get_audio_encoder_cap},
  277. };
  278. static const JNINativeMethod gMethodsForCamcorderProfileClass[] = {
  279. {"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
  280. {"native_get_camcorder_profile", "(II)Landroid/media/CamcorderProfile;",
  281. (void *)android_media_MediaProfiles_native_get_camcorder_profile},
  282. {"native_has_camcorder_profile", "(II)Z",
  283. (void *)android_media_MediaProfiles_native_has_camcorder_profile},
  284. };
  285. static const JNINativeMethod gMethodsForDecoderCapabilitiesClass[] = {
  286. {"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
  287. {"native_get_num_video_decoders", "()I", (void *)android_media_MediaProfiles_native_get_num_video_decoders},
  288. {"native_get_num_audio_decoders", "()I", (void *)android_media_MediaProfiles_native_get_num_audio_decoders},
  289. {"native_get_video_decoder_type", "(I)I", (void *)android_media_MediaProfiles_native_get_video_decoder_type},
  290. {"native_get_audio_decoder_type", "(I)I", (void *)android_media_MediaProfiles_native_get_audio_decoder_type},
  291. };
  292. static const JNINativeMethod gMethodsForCameraProfileClass[] = {
  293. {"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
  294. {"native_get_num_image_encoding_quality_levels",
  295. "(I)I", (void *)android_media_MediaProfiles_native_get_num_image_encoding_quality_levels},
  296. {"native_get_image_encoding_quality_level","(II)I", (void *)android_media_MediaProfiles_native_get_image_encoding_quality_level},
  297. };
  298. static const char* const kEncoderCapabilitiesClassPathName = "android/media/EncoderCapabilities";
  299. static const char* const kDecoderCapabilitiesClassPathName = "android/media/DecoderCapabilities";
  300. static const char* const kCamcorderProfileClassPathName = "android/media/CamcorderProfile";
  301. static const char* const kCameraProfileClassPathName = "android/media/CameraProfile";
  302. // This function only registers the native methods, and is called from
  303. // JNI_OnLoad in android_media_MediaPlayer.cpp
  304. int register_android_media_MediaProfiles(JNIEnv *env)
  305. {
  306. int ret1 = AndroidRuntime::registerNativeMethods(env,
  307. kEncoderCapabilitiesClassPathName,
  308. gMethodsForEncoderCapabilitiesClass,
  309. NELEM(gMethodsForEncoderCapabilitiesClass));
  310. int ret2 = AndroidRuntime::registerNativeMethods(env,
  311. kCamcorderProfileClassPathName,
  312. gMethodsForCamcorderProfileClass,
  313. NELEM(gMethodsForCamcorderProfileClass));
  314. int ret3 = AndroidRuntime::registerNativeMethods(env,
  315. kDecoderCapabilitiesClassPathName,
  316. gMethodsForDecoderCapabilitiesClass,
  317. NELEM(gMethodsForDecoderCapabilitiesClass));
  318. int ret4 = AndroidRuntime::registerNativeMethods(env,
  319. kCameraProfileClassPathName,
  320. gMethodsForCameraProfileClass,
  321. NELEM(gMethodsForCameraProfileClass));
  322. // Success if all return values from above are 0
  323. return (ret1 || ret2 || ret3 || ret4);
  324. }