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