Camera.java revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/* 2 * Copyright (C) 2008 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 17package android.hardware; 18 19import java.lang.ref.WeakReference; 20import java.util.HashMap; 21 22import android.util.Log; 23import android.view.Surface; 24import android.view.SurfaceHolder; 25import android.graphics.PixelFormat; 26import android.os.Handler; 27import android.os.Looper; 28import android.os.Message; 29 30/** 31 * The Camera class is used to connect/disconnect with the camera service, 32 * set capture settings, start/stop preview, snap a picture, and retrieve 33 * frames for encoding for video. 34 * <p>There is no default constructor for this class. Use {@link #open()} to 35 * get a Camera object.</p> 36 */ 37public class Camera { 38 private static final String TAG = "Camera"; 39 40 // These match the enum in libs/android_runtime/android_hardware_Camera.cpp 41 private static final int SHUTTER_CALLBACK = 0; 42 private static final int RAW_PICTURE_CALLBACK = 1; 43 private static final int JPEG_PICTURE_CALLBACK = 2; 44 private static final int PREVIEW_CALLBACK = 3; 45 private static final int AUTOFOCUS_CALLBACK = 4; 46 private static final int ERROR_CALLBACK = 5; 47 48 private int mNativeContext; // accessed by native methods 49 private int mListenerContext; 50 private EventHandler mEventHandler; 51 private ShutterCallback mShutterCallback; 52 private PictureCallback mRawImageCallback; 53 private PictureCallback mJpegCallback; 54 private PreviewCallback mPreviewCallback; 55 private AutoFocusCallback mAutoFocusCallback; 56 private ErrorCallback mErrorCallback; 57 58 /** 59 * Returns a new Camera object. 60 */ 61 public static Camera open() { 62 return new Camera(); 63 } 64 65 Camera() { 66 mShutterCallback = null; 67 mRawImageCallback = null; 68 mJpegCallback = null; 69 mPreviewCallback = null; 70 71 Looper looper; 72 if ((looper = Looper.myLooper()) != null) { 73 mEventHandler = new EventHandler(this, looper); 74 } else if ((looper = Looper.getMainLooper()) != null) { 75 mEventHandler = new EventHandler(this, looper); 76 } else { 77 mEventHandler = null; 78 } 79 80 native_setup(new WeakReference<Camera>(this)); 81 } 82 83 protected void finalize() { 84 native_release(); 85 } 86 87 private native final void native_setup(Object camera_this); 88 private native final void native_release(); 89 90 91 /** 92 * Disconnects and releases the Camera object resources. 93 * <p>It is recommended that you call this as soon as you're done with the 94 * Camera object.</p> 95 */ 96 public final void release() { 97 native_release(); 98 } 99 100 /** 101 * Sets the SurfaceHolder to be used for a picture preview. If the surface 102 * changed since the last call, the screen will blank. Nothing happens 103 * if the same surface is re-set. 104 * 105 * @param holder the SurfaceHolder upon which to place the picture preview 106 */ 107 public final void setPreviewDisplay(SurfaceHolder holder) { 108 setPreviewDisplay(holder.getSurface()); 109 } 110 111 private native final void setPreviewDisplay(Surface surface); 112 113 /** 114 * Used to get a copy of each preview frame. 115 */ 116 public interface PreviewCallback 117 { 118 /** 119 * The callback that delivers the preview frames. 120 * 121 * @param data The contents of the preview frame in getPreviewFormat() 122 * format. 123 * @param camera The Camera service object. 124 */ 125 void onPreviewFrame(byte[] data, Camera camera); 126 }; 127 128 /** 129 * Start drawing preview frames to the surface. 130 */ 131 public native final void startPreview(); 132 133 /** 134 * Stop drawing preview frames to the surface. 135 */ 136 public native final void stopPreview(); 137 138 /** 139 * Can be called at any time to instruct the camera to use a callback for 140 * each preview frame in addition to displaying it. 141 * 142 * @param cb A callback object that receives a copy of each preview frame. 143 * Pass null to stop receiving callbacks at any time. 144 */ 145 public final void setPreviewCallback(PreviewCallback cb) { 146 mPreviewCallback = cb; 147 setHasPreviewCallback(cb != null); 148 } 149 private native final void setHasPreviewCallback(boolean installed); 150 151 private class EventHandler extends Handler 152 { 153 private Camera mCamera; 154 155 public EventHandler(Camera c, Looper looper) { 156 super(looper); 157 mCamera = c; 158 } 159 160 @Override 161 public void handleMessage(Message msg) { 162 switch(msg.what) { 163 case SHUTTER_CALLBACK: 164 if (mShutterCallback != null) { 165 mShutterCallback.onShutter(); 166 } 167 return; 168 case RAW_PICTURE_CALLBACK: 169 if (mRawImageCallback != null) 170 mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera); 171 return; 172 173 case JPEG_PICTURE_CALLBACK: 174 if (mJpegCallback != null) 175 mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera); 176 return; 177 178 case PREVIEW_CALLBACK: 179 if (mPreviewCallback != null) 180 mPreviewCallback.onPreviewFrame((byte[])msg.obj, mCamera); 181 return; 182 183 case AUTOFOCUS_CALLBACK: 184 if (mAutoFocusCallback != null) 185 mAutoFocusCallback.onAutoFocus(msg.arg1 == 0 ? false : true, mCamera); 186 return; 187 188 case ERROR_CALLBACK: 189 Log.e(TAG, "Error " + msg.arg1); 190 if (mErrorCallback != null) 191 mErrorCallback.onError(msg.arg1, mCamera); 192 return; 193 194 default: 195 Log.e(TAG, "Unknown message type " + msg.what); 196 return; 197 } 198 } 199 } 200 201 private static void postEventFromNative(Object camera_ref, 202 int what, int arg1, int arg2, Object obj) 203 { 204 Camera c = (Camera)((WeakReference)camera_ref).get(); 205 if (c == null) 206 return; 207 208 if (c.mEventHandler != null) { 209 Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj); 210 c.mEventHandler.sendMessage(m); 211 } 212 } 213 214 /** 215 * Handles the callback for the camera auto focus. 216 */ 217 public interface AutoFocusCallback 218 { 219 /** 220 * Callback for the camera auto focus. 221 * 222 * @param success true if focus was successful, false if otherwise 223 * @param camera the Camera service object 224 */ 225 void onAutoFocus(boolean success, Camera camera); 226 }; 227 228 /** 229 * Registers a callback to be invoked when the auto focus responds. 230 * 231 * @param cb the callback to run 232 */ 233 public final void autoFocus(AutoFocusCallback cb) 234 { 235 mAutoFocusCallback = cb; 236 native_autoFocus(); 237 } 238 private native final void native_autoFocus(); 239 240 /** 241 * An interface which contains a callback for the shutter closing after taking a picture. 242 */ 243 public interface ShutterCallback 244 { 245 /** 246 * Can be used to play a shutter sound as soon as the image has been captured, but before 247 * the data is available. 248 */ 249 void onShutter(); 250 } 251 252 /** 253 * Handles the callback for when a picture is taken. 254 */ 255 public interface PictureCallback { 256 /** 257 * Callback for when a picture is taken. 258 * 259 * @param data a byte array of the picture data 260 * @param camera the Camera service object 261 */ 262 void onPictureTaken(byte[] data, Camera camera); 263 }; 264 265 /** 266 * Registers a callback to be invoked when a picture is taken. 267 * 268 * @param raw the callback to run for raw images, may be null 269 * @param jpeg the callback to run for jpeg images, may be null 270 */ 271 public final void takePicture(ShutterCallback shutter, PictureCallback raw, 272 PictureCallback jpeg) { 273 mShutterCallback = shutter; 274 mRawImageCallback = raw; 275 mJpegCallback = jpeg; 276 native_takePicture(); 277 } 278 private native final void native_takePicture(); 279 280 // These match the enum in libs/android_runtime/android_hardware_Camera.cpp 281 /** Unspecified camerar error. @see #ErrorCallback */ 282 public static final int CAMERA_ERROR_UNKNOWN = 1; 283 /** Media server died. In this case, the application must release the 284 * Camera object and instantiate a new one. @see #ErrorCallback */ 285 public static final int CAMERA_ERROR_SERVER_DIED = 100; 286 287 /** 288 * Handles the camera error callback. 289 */ 290 public interface ErrorCallback 291 { 292 /** 293 * Callback for camera errors. 294 * @param error error code: 295 * <ul> 296 * <li>{@link #CAMERA_ERROR_UNKNOWN} 297 * <li>{@link #CAMERA_ERROR_SERVER_DIED} 298 * </ul> 299 * @param camera the Camera service object 300 */ 301 void onError(int error, Camera camera); 302 }; 303 304 /** 305 * Registers a callback to be invoked when an error occurs. 306 * @param cb the callback to run 307 */ 308 public final void setErrorCallback(ErrorCallback cb) 309 { 310 mErrorCallback = cb; 311 } 312 313 private native final void native_setParameters(String params); 314 private native final String native_getParameters(); 315 316 /** 317 * Sets the Parameters for pictures from this Camera service. 318 * 319 * @param params the Parameters to use for this Camera service 320 */ 321 public void setParameters(Parameters params) { 322 Log.e(TAG, "setParameters()"); 323 //params.dump(); 324 native_setParameters(params.flatten()); 325 } 326 327 /** 328 * Returns the picture Parameters for this Camera service. 329 */ 330 public Parameters getParameters() { 331 Parameters p = new Parameters(); 332 String s = native_getParameters(); 333 Log.e(TAG, "_getParameters: " + s); 334 p.unflatten(s); 335 return p; 336 } 337 338 /** 339 * Handles the picture size (dimensions). 340 */ 341 public class Size { 342 /** 343 * Sets the dimensions for pictures. 344 * 345 * @param w the photo width (pixels) 346 * @param h the photo height (pixels) 347 */ 348 public Size(int w, int h) { 349 width = w; 350 height = h; 351 } 352 /** width of the picture */ 353 public int width; 354 /** height of the picture */ 355 public int height; 356 }; 357 358 /** 359 * Handles the parameters for pictures created by a Camera service. 360 */ 361 public class Parameters { 362 private HashMap<String, String> mMap; 363 364 private Parameters() { 365 mMap = new HashMap<String, String>(); 366 } 367 368 /** 369 * Writes the current Parameters to the log. 370 * @hide 371 * @deprecated 372 */ 373 public void dump() { 374 Log.e(TAG, "dump: size=" + mMap.size()); 375 for (String k : mMap.keySet()) { 376 Log.e(TAG, "dump: " + k + "=" + mMap.get(k)); 377 } 378 } 379 380 /** 381 * Creates a single string with all the parameters set in 382 * this Parameters object. 383 * <p>The {@link #unflatten(String)} method does the reverse.</p> 384 * 385 * @return a String with all values from this Parameters object, in 386 * semi-colon delimited key-value pairs 387 */ 388 public String flatten() { 389 StringBuilder flattened = new StringBuilder(); 390 for (String k : mMap.keySet()) { 391 flattened.append(k); 392 flattened.append("="); 393 flattened.append(mMap.get(k)); 394 flattened.append(";"); 395 } 396 // chop off the extra semicolon at the end 397 flattened.deleteCharAt(flattened.length()-1); 398 return flattened.toString(); 399 } 400 401 /** 402 * Takes a flattened string of parameters and adds each one to 403 * this Parameters object. 404 * <p>The {@link #flatten()} method does the reverse.</p> 405 * 406 * @param flattened a String of parameters (key-value paired) that 407 * are semi-colon delimited 408 */ 409 public void unflatten(String flattened) { 410 mMap.clear(); 411 String[] pairs = flattened.split(";"); 412 for (String p : pairs) { 413 String[] kv = p.split("="); 414 if (kv.length == 2) 415 mMap.put(kv[0], kv[1]); 416 } 417 } 418 419 public void remove(String key) { 420 mMap.remove(key); 421 } 422 423 /** 424 * Sets a String parameter. 425 * 426 * @param key the key name for the parameter 427 * @param value the String value of the parameter 428 */ 429 public void set(String key, String value) { 430 if (key.indexOf('=') != -1 || key.indexOf(';') != -1) { 431 Log.e(TAG, "Key \"" + key + "\" contains invalid character (= or ;)"); 432 return; 433 } 434 if (value.indexOf('=') != -1 || value.indexOf(';') != -1) { 435 Log.e(TAG, "Value \"" + value + "\" contains invalid character (= or ;)"); 436 return; 437 } 438 439 mMap.put(key, value); 440 } 441 442 /** 443 * Sets an integer parameter. 444 * 445 * @param key the key name for the parameter 446 * @param value the int value of the parameter 447 */ 448 public void set(String key, int value) { 449 mMap.put(key, Integer.toString(value)); 450 } 451 452 /** 453 * Returns the value of a String parameter. 454 * 455 * @param key the key name for the parameter 456 * @return the String value of the parameter 457 */ 458 public String get(String key) { 459 return mMap.get(key); 460 } 461 462 /** 463 * Returns the value of an integer parameter. 464 * 465 * @param key the key name for the parameter 466 * @return the int value of the parameter 467 */ 468 public int getInt(String key) { 469 return Integer.parseInt(mMap.get(key)); 470 } 471 472 /** 473 * Sets the dimensions for preview pictures. 474 * 475 * @param width the width of the pictures, in pixels 476 * @param height the height of the pictures, in pixels 477 */ 478 public void setPreviewSize(int width, int height) { 479 String v = Integer.toString(width) + "x" + Integer.toString(height); 480 set("preview-size", v); 481 } 482 483 /** 484 * Returns the dimensions setting for preview pictures. 485 * 486 * @return a Size object with the height and width setting 487 * for the preview picture 488 */ 489 public Size getPreviewSize() { 490 String pair = get("preview-size"); 491 if (pair == null) 492 return null; 493 String[] dims = pair.split("x"); 494 if (dims.length != 2) 495 return null; 496 497 return new Size(Integer.parseInt(dims[0]), 498 Integer.parseInt(dims[1])); 499 500 } 501 502 /** 503 * Sets the rate at which preview frames are received. 504 * 505 * @param fps the frame rate (frames per second) 506 */ 507 public void setPreviewFrameRate(int fps) { 508 set("preview-frame-rate", fps); 509 } 510 511 /** 512 * Returns the setting for the rate at which preview frames 513 * are received. 514 * 515 * @return the frame rate setting (frames per second) 516 */ 517 public int getPreviewFrameRate() { 518 return getInt("preview-frame-rate"); 519 } 520 521 /** 522 * Sets the image format for preview pictures. 523 * 524 * @param pixel_format the desired preview picture format 525 * (<var>PixelFormat.YCbCr_422_SP</var>, 526 * <var>PixelFormat.RGB_565</var>, or 527 * <var>PixelFormat.JPEG</var>) 528 * @see android.graphics.PixelFormat 529 */ 530 public void setPreviewFormat(int pixel_format) { 531 String s = cameraFormatForPixelFormat(pixel_format); 532 if (s == null) { 533 throw new IllegalArgumentException(); 534 } 535 536 set("preview-format", s); 537 } 538 539 /** 540 * Returns the image format for preview pictures. 541 * 542 * @return the PixelFormat int representing the preview picture format 543 */ 544 public int getPreviewFormat() { 545 return pixelFormatForCameraFormat(get("preview-format")); 546 } 547 548 /** 549 * Sets the dimensions for pictures. 550 * 551 * @param width the width for pictures, in pixels 552 * @param height the height for pictures, in pixels 553 */ 554 public void setPictureSize(int width, int height) { 555 String v = Integer.toString(width) + "x" + Integer.toString(height); 556 set("picture-size", v); 557 } 558 559 /** 560 * Returns the dimension setting for pictures. 561 * 562 * @return a Size object with the height and width setting 563 * for pictures 564 */ 565 public Size getPictureSize() { 566 String pair = get("picture-size"); 567 if (pair == null) 568 return null; 569 String[] dims = pair.split("x"); 570 if (dims.length != 2) 571 return null; 572 573 return new Size(Integer.parseInt(dims[0]), 574 Integer.parseInt(dims[1])); 575 576 } 577 578 /** 579 * Sets the image format for pictures. 580 * 581 * @param pixel_format the desired picture format 582 * (<var>PixelFormat.YCbCr_422_SP</var>, 583 * <var>PixelFormat.RGB_565</var>, or 584 * <var>PixelFormat.JPEG</var>) 585 * @see android.graphics.PixelFormat 586 */ 587 public void setPictureFormat(int pixel_format) { 588 String s = cameraFormatForPixelFormat(pixel_format); 589 if (s == null) { 590 throw new IllegalArgumentException(); 591 } 592 593 set("picture-format", s); 594 } 595 596 /** 597 * Returns the image format for pictures. 598 * 599 * @return the PixelFormat int representing the picture format 600 */ 601 public int getPictureFormat() { 602 return pixelFormatForCameraFormat(get("picture-format")); 603 } 604 605 private String cameraFormatForPixelFormat(int pixel_format) { 606 switch(pixel_format) { 607 case PixelFormat.YCbCr_422_SP: return "yuv422sp"; 608 case PixelFormat.RGB_565: return "rgb565"; 609 case PixelFormat.JPEG: return "jpeg"; 610 default: return null; 611 } 612 } 613 614 private int pixelFormatForCameraFormat(String format) { 615 if (format == null) 616 return PixelFormat.UNKNOWN; 617 618 if (format.equals("yuv422sp")) 619 return PixelFormat.YCbCr_422_SP; 620 621 if (format.equals("rgb565")) 622 return PixelFormat.RGB_565; 623 624 if (format.equals("jpeg")) 625 return PixelFormat.JPEG; 626 627 return PixelFormat.UNKNOWN; 628 } 629 630 }; 631} 632 633 634