Camera.java revision ab5b424db30b478570d83a30497319a72e91068c
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.util.StringTokenizer; 22import java.io.IOException; 23 24import android.util.Log; 25import android.view.Surface; 26import android.view.SurfaceHolder; 27import android.graphics.PixelFormat; 28import android.os.Handler; 29import android.os.Looper; 30import android.os.Message; 31 32/** 33 * The Camera class is used to connect/disconnect with the camera service, 34 * set capture settings, start/stop preview, snap a picture, and retrieve 35 * frames for encoding for video. 36 * <p>There is no default constructor for this class. Use {@link #open()} to 37 * get a Camera object.</p> 38 */ 39public class Camera { 40 private static final String TAG = "Camera"; 41 42 // These match the enum in libs/android_runtime/android_hardware_Camera.cpp 43 private static final int SHUTTER_CALLBACK = 0; 44 private static final int RAW_PICTURE_CALLBACK = 1; 45 private static final int JPEG_PICTURE_CALLBACK = 2; 46 private static final int PREVIEW_CALLBACK = 3; 47 private static final int AUTOFOCUS_CALLBACK = 4; 48 private static final int ERROR_CALLBACK = 5; 49 50 private int mNativeContext; // accessed by native methods 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 native_setParameters(params.flatten()); 409 } 410 411 /** 412 * Returns the picture Parameters for this Camera service. 413 */ 414 public Parameters getParameters() { 415 Parameters p = new Parameters(); 416 String s = native_getParameters(); 417 p.unflatten(s); 418 return p; 419 } 420 421 /** 422 * Handles the picture size (dimensions). 423 */ 424 public class Size { 425 /** 426 * Sets the dimensions for pictures. 427 * 428 * @param w the photo width (pixels) 429 * @param h the photo height (pixels) 430 */ 431 public Size(int w, int h) { 432 width = w; 433 height = h; 434 } 435 /** width of the picture */ 436 public int width; 437 /** height of the picture */ 438 public int height; 439 }; 440 441 /** 442 * Handles the parameters for pictures created by a Camera service. 443 */ 444 public class Parameters { 445 private HashMap<String, String> mMap; 446 447 private Parameters() { 448 mMap = new HashMap<String, String>(); 449 } 450 451 /** 452 * Writes the current Parameters to the log. 453 * @hide 454 * @deprecated 455 */ 456 public void dump() { 457 Log.e(TAG, "dump: size=" + mMap.size()); 458 for (String k : mMap.keySet()) { 459 Log.e(TAG, "dump: " + k + "=" + mMap.get(k)); 460 } 461 } 462 463 /** 464 * Creates a single string with all the parameters set in 465 * this Parameters object. 466 * <p>The {@link #unflatten(String)} method does the reverse.</p> 467 * 468 * @return a String with all values from this Parameters object, in 469 * semi-colon delimited key-value pairs 470 */ 471 public String flatten() { 472 StringBuilder flattened = new StringBuilder(); 473 for (String k : mMap.keySet()) { 474 flattened.append(k); 475 flattened.append("="); 476 flattened.append(mMap.get(k)); 477 flattened.append(";"); 478 } 479 // chop off the extra semicolon at the end 480 flattened.deleteCharAt(flattened.length()-1); 481 return flattened.toString(); 482 } 483 484 /** 485 * Takes a flattened string of parameters and adds each one to 486 * this Parameters object. 487 * <p>The {@link #flatten()} method does the reverse.</p> 488 * 489 * @param flattened a String of parameters (key-value paired) that 490 * are semi-colon delimited 491 */ 492 public void unflatten(String flattened) { 493 mMap.clear(); 494 495 StringTokenizer tokenizer = new StringTokenizer(flattened, ";"); 496 while (tokenizer.hasMoreElements()) { 497 String kv = tokenizer.nextToken(); 498 int pos = kv.indexOf('='); 499 if (pos == -1) { 500 continue; 501 } 502 String k = kv.substring(0, pos); 503 String v = kv.substring(pos + 1); 504 mMap.put(k, v); 505 } 506 } 507 508 public void remove(String key) { 509 mMap.remove(key); 510 } 511 512 /** 513 * Sets a String parameter. 514 * 515 * @param key the key name for the parameter 516 * @param value the String value of the parameter 517 */ 518 public void set(String key, String value) { 519 if (key.indexOf('=') != -1 || key.indexOf(';') != -1) { 520 Log.e(TAG, "Key \"" + key + "\" contains invalid character (= or ;)"); 521 return; 522 } 523 if (value.indexOf('=') != -1 || value.indexOf(';') != -1) { 524 Log.e(TAG, "Value \"" + value + "\" contains invalid character (= or ;)"); 525 return; 526 } 527 528 mMap.put(key, value); 529 } 530 531 /** 532 * Sets an integer parameter. 533 * 534 * @param key the key name for the parameter 535 * @param value the int value of the parameter 536 */ 537 public void set(String key, int value) { 538 mMap.put(key, Integer.toString(value)); 539 } 540 541 /** 542 * Returns the value of a String parameter. 543 * 544 * @param key the key name for the parameter 545 * @return the String value of the parameter 546 */ 547 public String get(String key) { 548 return mMap.get(key); 549 } 550 551 /** 552 * Returns the value of an integer parameter. 553 * 554 * @param key the key name for the parameter 555 * @return the int value of the parameter 556 */ 557 public int getInt(String key) { 558 return Integer.parseInt(mMap.get(key)); 559 } 560 561 /** 562 * Sets the dimensions for preview pictures. 563 * 564 * @param width the width of the pictures, in pixels 565 * @param height the height of the pictures, in pixels 566 */ 567 public void setPreviewSize(int width, int height) { 568 String v = Integer.toString(width) + "x" + Integer.toString(height); 569 set("preview-size", v); 570 } 571 572 /** 573 * Returns the dimensions setting for preview pictures. 574 * 575 * @return a Size object with the height and width setting 576 * for the preview picture 577 */ 578 public Size getPreviewSize() { 579 String pair = get("preview-size"); 580 if (pair == null) 581 return null; 582 String[] dims = pair.split("x"); 583 if (dims.length != 2) 584 return null; 585 586 return new Size(Integer.parseInt(dims[0]), 587 Integer.parseInt(dims[1])); 588 589 } 590 591 /** 592 * Sets the dimensions for EXIF thumbnails. 593 * 594 * @param width the width of the thumbnail, in pixels 595 * @param height the height of the thumbnail, in pixels 596 * 597 * FIXME: unhide before release 598 * @hide 599 */ 600 public void setThumbnailSize(int width, int height) { 601 set("jpeg-thumbnail-width", width); 602 set("jpeg-thumbnail-height", height); 603 } 604 605 /** 606 * Returns the dimensions for EXIF thumbnail 607 * 608 * @return a Size object with the height and width setting 609 * for the EXIF thumbnails 610 * 611 * FIXME: unhide before release 612 * @hide 613 */ 614 public Size getThumbnailSize() { 615 return new Size(getInt("jpeg-thumbnail-width"), 616 getInt("jpeg-thumbnail-height")); 617 } 618 619 /** 620 * Sets the quality of the EXIF thumbnail 621 * 622 * @param quality the JPEG quality of the EXIT thumbnail 623 * 624 * FIXME: unhide before release 625 * @hide 626 */ 627 public void setThumbnailQuality(int quality) { 628 set("jpeg-thumbnail-quality", quality); 629 } 630 631 /** 632 * Returns the quality setting for the EXIF thumbnail 633 * 634 * @return the JPEG quality setting of the EXIF thumbnail 635 * 636 * FIXME: unhide before release 637 * @hide 638 */ 639 public int getThumbnailQuality() { 640 return getInt("jpeg-thumbnail-quality"); 641 } 642 643 /** 644 * Sets the rate at which preview frames are received. 645 * 646 * @param fps the frame rate (frames per second) 647 */ 648 public void setPreviewFrameRate(int fps) { 649 set("preview-frame-rate", fps); 650 } 651 652 /** 653 * Returns the setting for the rate at which preview frames 654 * are received. 655 * 656 * @return the frame rate setting (frames per second) 657 */ 658 public int getPreviewFrameRate() { 659 return getInt("preview-frame-rate"); 660 } 661 662 /** 663 * Sets the image format for preview pictures. 664 * 665 * @param pixel_format the desired preview picture format 666 * (<var>PixelFormat.YCbCr_420_SP</var>, 667 * <var>PixelFormat.RGB_565</var>, or 668 * <var>PixelFormat.JPEG</var>) 669 * @see android.graphics.PixelFormat 670 */ 671 public void setPreviewFormat(int pixel_format) { 672 String s = cameraFormatForPixelFormat(pixel_format); 673 if (s == null) { 674 throw new IllegalArgumentException(); 675 } 676 677 set("preview-format", s); 678 } 679 680 /** 681 * Returns the image format for preview pictures. 682 * 683 * @return the PixelFormat int representing the preview picture format 684 */ 685 public int getPreviewFormat() { 686 return pixelFormatForCameraFormat(get("preview-format")); 687 } 688 689 /** 690 * Sets the dimensions for pictures. 691 * 692 * @param width the width for pictures, in pixels 693 * @param height the height for pictures, in pixels 694 */ 695 public void setPictureSize(int width, int height) { 696 String v = Integer.toString(width) + "x" + Integer.toString(height); 697 set("picture-size", v); 698 } 699 700 /** 701 * Returns the dimension setting for pictures. 702 * 703 * @return a Size object with the height and width setting 704 * for pictures 705 */ 706 public Size getPictureSize() { 707 String pair = get("picture-size"); 708 if (pair == null) 709 return null; 710 String[] dims = pair.split("x"); 711 if (dims.length != 2) 712 return null; 713 714 return new Size(Integer.parseInt(dims[0]), 715 Integer.parseInt(dims[1])); 716 717 } 718 719 /** 720 * Sets the image format for pictures. 721 * 722 * @param pixel_format the desired picture format 723 * (<var>PixelFormat.YCbCr_420_SP</var>, 724 * <var>PixelFormat.RGB_565</var>, or 725 * <var>PixelFormat.JPEG</var>) 726 * @see android.graphics.PixelFormat 727 */ 728 public void setPictureFormat(int pixel_format) { 729 String s = cameraFormatForPixelFormat(pixel_format); 730 if (s == null) { 731 throw new IllegalArgumentException(); 732 } 733 734 set("picture-format", s); 735 } 736 737 /** 738 * Returns the image format for pictures. 739 * 740 * @return the PixelFormat int representing the picture format 741 */ 742 public int getPictureFormat() { 743 return pixelFormatForCameraFormat(get("picture-format")); 744 } 745 746 private String cameraFormatForPixelFormat(int pixel_format) { 747 switch(pixel_format) { 748 case PixelFormat.YCbCr_422_SP: return "yuv422sp"; 749 case PixelFormat.YCbCr_420_SP: return "yuv420sp"; 750 case PixelFormat.RGB_565: return "rgb565"; 751 case PixelFormat.JPEG: return "jpeg"; 752 default: return null; 753 } 754 } 755 756 private int pixelFormatForCameraFormat(String format) { 757 if (format == null) 758 return PixelFormat.UNKNOWN; 759 760 if (format.equals("yuv422sp")) 761 return PixelFormat.YCbCr_422_SP; 762 763 if (format.equals("yuv420sp")) 764 return PixelFormat.YCbCr_420_SP; 765 766 if (format.equals("rgb565")) 767 return PixelFormat.RGB_565; 768 769 if (format.equals("jpeg")) 770 return PixelFormat.JPEG; 771 772 return PixelFormat.UNKNOWN; 773 } 774 775 }; 776} 777 778 779