android_media_MediaRecorder.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/* //device/libs/media_jni/android_media_MediaRecorder.cpp 2** 3** Copyright 2007, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#define LOG_TAG "MediaRecorder" 19#include "utils/Log.h" 20 21#include <media/mediarecorder.h> 22#include <stdio.h> 23#include <assert.h> 24#include <limits.h> 25#include <unistd.h> 26#include <fcntl.h> 27#include <utils/threads.h> 28 29#include "jni.h" 30#include "JNIHelp.h" 31#include "android_runtime/AndroidRuntime.h" 32 33 34// ---------------------------------------------------------------------------- 35 36using namespace android; 37 38// ---------------------------------------------------------------------------- 39 40struct fields_t { 41 jfieldID context; 42 jfieldID surface; 43 /* actually in android.view.Surface XXX */ 44 jfieldID surface_native; 45}; 46static fields_t fields; 47 48// ---------------------------------------------------------------------------- 49 50static sp<Surface> get_surface(JNIEnv* env, jobject clazz) 51{ 52 Surface* const p = (Surface*)env->GetIntField(clazz, fields.surface_native); 53 return sp<Surface>(p); 54} 55 56static void process_media_recorder_call(JNIEnv *env, status_t opStatus, const char* exception, const char* message) 57{ 58 if (opStatus == (status_t)INVALID_OPERATION) { 59 jniThrowException(env, "java/lang/IllegalStateException", NULL); 60 } else if (opStatus != (status_t)OK) { 61 jniThrowException(env, exception, message); 62 } 63 return; 64} 65 66static void 67android_media_MediaRecorder_setVideoSource(JNIEnv *env, jobject thiz, jint vs) 68{ 69 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 70 process_media_recorder_call(env, mr->setVideoSource((video_source)vs), "java/lang/RuntimeException", "setVideoSource failed."); 71} 72 73static void 74android_media_MediaRecorder_setAudioSource(JNIEnv *env, jobject thiz, jint as) 75{ 76 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 77 process_media_recorder_call(env, mr->setAudioSource((audio_source)as), "java/lang/RuntimeException", "setAudioSource failed."); 78} 79 80static void 81android_media_MediaRecorder_setOutputFormat(JNIEnv *env, jobject thiz, jint of) 82{ 83 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 84 process_media_recorder_call(env, mr->setOutputFormat((output_format)of), "java/lang/RuntimeException", "setOutputFormat failed."); 85} 86 87static void 88android_media_MediaRecorder_setVideoEncoder(JNIEnv *env, jobject thiz, jint ve) 89{ 90 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 91 process_media_recorder_call(env, mr->setVideoEncoder((video_encoder)ve), "java/lang/RuntimeException", "setVideoEncoder failed."); 92} 93 94static void 95android_media_MediaRecorder_setAudioEncoder(JNIEnv *env, jobject thiz, jint ae) 96{ 97 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 98 process_media_recorder_call(env, mr->setAudioEncoder((audio_encoder)ae), "java/lang/RuntimeException", "setAudioEncoder failed."); 99} 100 101static void 102android_media_MediaRecorder_setOutputFile(JNIEnv *env, jobject thiz, jstring path) 103{ 104 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 105 106 if (path == NULL) { 107 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 108 return; 109 } 110 const char *pathStr = env->GetStringUTFChars(path, NULL); 111 if (pathStr == NULL) { // Out of memory 112 jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); 113 return; 114 } 115 status_t opStatus = mr->setOutputFile(pathStr); 116 117 // Make sure that local ref is released before a potential exception 118 env->ReleaseStringUTFChars(path, pathStr); 119 process_media_recorder_call(env, opStatus, "java/lang/RuntimeException", "setOutputFile failed."); 120} 121 122static void 123android_media_MediaRecorder_setVideoSize(JNIEnv *env, jobject thiz, jint width, jint height) 124{ 125 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 126 process_media_recorder_call(env, mr->setVideoSize(width, height), "java/lang/RuntimeException", "setVideoSize failed."); 127} 128 129static void 130android_media_MediaRecorder_setVideoFrameRate(JNIEnv *env, jobject thiz, jint rate) 131{ 132 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 133 process_media_recorder_call(env, mr->setVideoFrameRate(rate), "java/lang/RuntimeException", "setVideoFrameRate failed."); 134} 135 136static void 137android_media_MediaRecorder_prepare(JNIEnv *env, jobject thiz) 138{ 139 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 140 141 jobject surface = env->GetObjectField(thiz, fields.surface); 142 if (surface != NULL) { 143 const sp<Surface>& native_surface = get_surface(env, surface); 144 LOGI("prepare: surface=%p (id=%d)", 145 native_surface.get(), native_surface->ID()); 146 process_media_recorder_call(env, mr->setPreviewSurface(native_surface), "java/lang/RuntimeException", "setPreviewSurface failed."); 147 } 148 process_media_recorder_call(env, mr->prepare(), "java/io/IOException", "prepare failed."); 149} 150 151static int 152android_media_MediaRecorder_native_getMaxAmplitude(JNIEnv *env, jobject thiz) 153{ 154 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 155 int result = 0; 156 process_media_recorder_call(env, mr->getMaxAmplitude(&result), "java/lang/RuntimeException", "getMaxAmplitude failed."); 157 return result; 158} 159 160static void 161android_media_MediaRecorder_start(JNIEnv *env, jobject thiz) 162{ 163 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 164 process_media_recorder_call(env, mr->start(), "java/lang/RuntimeException", "start failed."); 165} 166 167static void 168android_media_MediaRecorder_stop(JNIEnv *env, jobject thiz) 169{ 170 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 171 process_media_recorder_call(env, mr->stop(), "java/lang/RuntimeException", "stop failed."); 172} 173 174static void 175android_media_MediaRecorder_reset(JNIEnv *env, jobject thiz) 176{ 177 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 178 process_media_recorder_call(env, mr->reset(), "java/lang/RuntimeException", "reset failed."); 179} 180 181static void 182android_media_MediaRecorder_release(JNIEnv *env, jobject thiz) 183{ 184 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 185 env->SetIntField(thiz, fields.context, 0); 186 delete mr; 187} 188 189static void 190android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz) 191{ 192 MediaRecorder *mr = new MediaRecorder(); 193 if (mr == NULL) { 194 jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); 195 return; 196 } 197 198 process_media_recorder_call(env, mr->init(), "java/lang/RuntimeException", "init failed."); 199 env->SetIntField(thiz, fields.context, (int)mr); 200} 201 202static void 203android_media_MediaRecorder_native_finalize(JNIEnv *env, jobject thiz) 204{ 205 MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context); 206 207 //printf("##### android_media_MediaRecorder_native_finalize: ctx=0x%p\n", ctx); 208 209 if (mr == 0) 210 return; 211 212 delete mr; 213} 214 215// ---------------------------------------------------------------------------- 216 217static JNINativeMethod gMethods[] = { 218 {"setVideoSource", "(I)V", (void *)android_media_MediaRecorder_setVideoSource}, 219 {"setAudioSource", "(I)V", (void *)android_media_MediaRecorder_setAudioSource}, 220 {"setOutputFormat", "(I)V", (void *)android_media_MediaRecorder_setOutputFormat}, 221 {"setVideoEncoder", "(I)V", (void *)android_media_MediaRecorder_setVideoEncoder}, 222 {"setAudioEncoder", "(I)V", (void *)android_media_MediaRecorder_setAudioEncoder}, 223 {"setOutputFile", "(Ljava/lang/String;)V", (void *)android_media_MediaRecorder_setOutputFile}, 224 {"setVideoSize", "(II)V", (void *)android_media_MediaRecorder_setVideoSize}, 225 {"setVideoFrameRate", "(I)V", (void *)android_media_MediaRecorder_setVideoFrameRate}, 226 {"prepare", "()V", (void *)android_media_MediaRecorder_prepare}, 227 {"getMaxAmplitude", "()I", (void *)android_media_MediaRecorder_native_getMaxAmplitude}, 228 {"start", "()V", (void *)android_media_MediaRecorder_start}, 229 {"stop", "()V", (void *)android_media_MediaRecorder_stop}, 230 {"reset", "()V", (void *)android_media_MediaRecorder_reset}, 231 {"release", "()V", (void *)android_media_MediaRecorder_release}, 232 {"native_setup", "()V", (void *)android_media_MediaRecorder_native_setup}, 233 {"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize}, 234}; 235 236static const char* const kClassPathName = "android/media/MediaRecorder"; 237 238int register_android_media_MediaRecorder(JNIEnv *env) 239{ 240 jclass clazz; 241 242 clazz = env->FindClass("android/media/MediaRecorder"); 243 if (clazz == NULL) { 244 LOGE("Can't find android/media/MediaRecorder"); 245 return -1; 246 } 247 248 fields.context = env->GetFieldID(clazz, "mNativeContext", "I"); 249 if (fields.context == NULL) { 250 LOGE("Can't find MediaRecorder.mNativeContext"); 251 return -1; 252 } 253 254 fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;"); 255 if (fields.surface == NULL) { 256 LOGE("Can't find MediaRecorder.mSurface"); 257 return -1; 258 } 259 260 jclass surface = env->FindClass("android/view/Surface"); 261 if (surface == NULL) { 262 LOGE("Can't find android/view/Surface"); 263 return -1; 264 } 265 266 fields.surface_native = env->GetFieldID(surface, "mSurface", "I"); 267 if (fields.surface_native == NULL) { 268 LOGE("Can't find Surface fields"); 269 return -1; 270 } 271 272 return AndroidRuntime::registerNativeMethods(env, 273 "android/media/MediaRecorder", gMethods, NELEM(gMethods)); 274} 275 276 277