blob: efd7af7e8a3873b9e773db03b8186a9773c3b251 [file] [log] [blame]
Andreas Huber20111aa2009-07-14 16:56:47 -07001/*
2 * Copyright (C) 2009 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
James Dongc32cd792010-04-26 17:48:26 -070017//#define LOG_NDEBUG 0
18#define LOG_TAG "CameraSource"
19#include <utils/Log.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070020
Andreas Huber20111aa2009-07-14 16:56:47 -070021#include <OMX_Component.h>
James Dong9d7f58a2010-06-09 15:57:48 -070022#include <binder/IPCThreadState.h>
James Dongf1d5aa12012-02-06 23:46:37 -080023#include <media/stagefright/foundation/ADebug.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070024#include <media/stagefright/CameraSource.h>
Andreas Huberbe5c74f2009-10-13 17:08:31 -070025#include <media/stagefright/MediaDefs.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070026#include <media/stagefright/MediaErrors.h>
27#include <media/stagefright/MetaData.h>
Mathias Agopian3cf61352010-02-09 17:46:37 -080028#include <camera/Camera.h>
29#include <camera/CameraParameters.h>
Mathias Agopiandf712ea2012-02-25 18:48:35 -080030#include <gui/Surface.h>
Andreas Huberbe5c74f2009-10-13 17:08:31 -070031#include <utils/String8.h>
James Dong365a9632010-06-04 13:59:27 -070032#include <cutils/properties.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070033
34namespace android {
35
James Donge8e5f862011-11-20 09:45:44 -080036static const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL;
37
Andreas Huberbe5c74f2009-10-13 17:08:31 -070038struct CameraSourceListener : public CameraListener {
39 CameraSourceListener(const sp<CameraSource> &source);
40
41 virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
Wu-cheng Li57c86182011-07-30 05:00:37 +080042 virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr,
43 camera_frame_metadata_t *metadata);
Andreas Huberbe5c74f2009-10-13 17:08:31 -070044
45 virtual void postDataTimestamp(
46 nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
47
48protected:
49 virtual ~CameraSourceListener();
50
51private:
52 wp<CameraSource> mSource;
53
54 CameraSourceListener(const CameraSourceListener &);
55 CameraSourceListener &operator=(const CameraSourceListener &);
56};
57
58CameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
59 : mSource(source) {
60}
61
62CameraSourceListener::~CameraSourceListener() {
63}
64
65void CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
Steve Block3856b092011-10-20 11:56:00 +010066 ALOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
Andreas Huberbe5c74f2009-10-13 17:08:31 -070067}
68
Wu-cheng Li57c86182011-07-30 05:00:37 +080069void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
70 camera_frame_metadata_t *metadata) {
Steve Block3856b092011-10-20 11:56:00 +010071 ALOGV("postData(%d, ptr:%p, size:%d)",
Andreas Huberbe5c74f2009-10-13 17:08:31 -070072 msgType, dataPtr->pointer(), dataPtr->size());
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -070073
74 sp<CameraSource> source = mSource.promote();
75 if (source.get() != NULL) {
76 source->dataCallback(msgType, dataPtr);
77 }
Andreas Huberbe5c74f2009-10-13 17:08:31 -070078}
79
80void CameraSourceListener::postDataTimestamp(
81 nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
James Dongc32cd792010-04-26 17:48:26 -070082
83 sp<CameraSource> source = mSource.promote();
84 if (source.get() != NULL) {
85 source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
86 }
Andreas Huberbe5c74f2009-10-13 17:08:31 -070087}
88
James Dong653252b2010-06-03 11:48:31 -070089static int32_t getColorFormat(const char* colorFormat) {
James Donge2d8ba82010-09-15 16:52:51 -070090 if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
91 return OMX_COLOR_FormatYUV420Planar;
92 }
93
James Dong653252b2010-06-03 11:48:31 -070094 if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
95 return OMX_COLOR_FormatYUV422SemiPlanar;
96 }
97
98 if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
99 return OMX_COLOR_FormatYUV420SemiPlanar;
100 }
101
102 if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
103 return OMX_COLOR_FormatYCbYCr;
104 }
105
106 if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
107 return OMX_COLOR_Format16bitRGB565;
108 }
109
Dandawate Saket1374edd2011-07-11 19:12:57 -0700110 if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
111 return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
112 }
113
Eino-Ville Talvalabf5bea92012-07-18 17:46:06 -0700114 if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE)) {
115 return OMX_COLOR_FormatAndroidOpaque;
116 }
117
Steve Block29357bc2012-01-06 19:20:56 +0000118 ALOGE("Uknown color format (%s), please add it to "
James Donga1abc1a2010-09-13 16:30:51 -0700119 "CameraSource::getColorFormat", colorFormat);
120
James Dongf1d5aa12012-02-06 23:46:37 -0800121 CHECK(!"Unknown color format");
James Dong653252b2010-06-03 11:48:31 -0700122}
123
Andreas Huber20111aa2009-07-14 16:56:47 -0700124CameraSource *CameraSource::Create() {
James Dong54ff19a2010-10-08 11:59:32 -0700125 Size size;
126 size.width = -1;
127 size.height = -1;
Andreas Huber20111aa2009-07-14 16:56:47 -0700128
James Dong54ff19a2010-10-08 11:59:32 -0700129 sp<ICamera> camera;
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800130 return new CameraSource(camera, NULL, 0, size, -1, NULL, false);
Andreas Huber20111aa2009-07-14 16:56:47 -0700131}
132
Andreas Huber30ab6622009-11-16 15:43:38 -0800133// static
James Dong54ff19a2010-10-08 11:59:32 -0700134CameraSource *CameraSource::CreateFromCamera(
135 const sp<ICamera>& camera,
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800136 const sp<ICameraRecordingProxy>& proxy,
James Dong54ff19a2010-10-08 11:59:32 -0700137 int32_t cameraId,
138 Size videoSize,
139 int32_t frameRate,
James Dong5c952312010-10-18 21:42:27 -0700140 const sp<Surface>& surface,
141 bool storeMetaDataInVideoBuffers) {
Andreas Huber30ab6622009-11-16 15:43:38 -0800142
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800143 CameraSource *source = new CameraSource(camera, proxy, cameraId,
James Dong5c952312010-10-18 21:42:27 -0700144 videoSize, frameRate, surface,
145 storeMetaDataInVideoBuffers);
James Dong54ff19a2010-10-08 11:59:32 -0700146 return source;
Andreas Huber30ab6622009-11-16 15:43:38 -0800147}
148
James Dong54ff19a2010-10-08 11:59:32 -0700149CameraSource::CameraSource(
150 const sp<ICamera>& camera,
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800151 const sp<ICameraRecordingProxy>& proxy,
James Dong54ff19a2010-10-08 11:59:32 -0700152 int32_t cameraId,
153 Size videoSize,
154 int32_t frameRate,
James Dong5c952312010-10-18 21:42:27 -0700155 const sp<Surface>& surface,
156 bool storeMetaDataInVideoBuffers)
James Dong54ff19a2010-10-08 11:59:32 -0700157 : mCameraFlags(0),
James Dong983cf232012-08-01 16:39:55 -0700158 mNumInputBuffers(0),
James Dong54ff19a2010-10-08 11:59:32 -0700159 mVideoFrameRate(-1),
160 mCamera(0),
161 mSurface(surface),
James Dong13aec892010-04-21 16:14:15 -0700162 mNumFramesReceived(0),
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700163 mLastFrameTimestampUs(0),
164 mStarted(false),
James Dong13aec892010-04-21 16:14:15 -0700165 mNumFramesEncoded(0),
James Donge8e5f862011-11-20 09:45:44 -0800166 mTimeBetweenFrameCaptureUs(0),
James Dong7757f502011-01-25 16:31:28 -0800167 mFirstFrameTimeUs(0),
James Dong13aec892010-04-21 16:14:15 -0700168 mNumFramesDropped(0),
James Dongf60cafe2010-06-19 09:04:18 -0700169 mNumGlitches(0),
170 mGlitchDurationThresholdUs(200000),
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700171 mCollectStats(false) {
James Dong54ff19a2010-10-08 11:59:32 -0700172 mVideoSize.width = -1;
173 mVideoSize.height = -1;
174
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800175 mInitCheck = init(camera, proxy, cameraId,
James Dong5c952312010-10-18 21:42:27 -0700176 videoSize, frameRate,
177 storeMetaDataInVideoBuffers);
Wu-cheng Li95068be2011-06-29 15:17:11 +0800178 if (mInitCheck != OK) releaseCamera();
James Dong54ff19a2010-10-08 11:59:32 -0700179}
180
181status_t CameraSource::initCheck() const {
182 return mInitCheck;
183}
184
185status_t CameraSource::isCameraAvailable(
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800186 const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
187 int32_t cameraId) {
James Dong54ff19a2010-10-08 11:59:32 -0700188
189 if (camera == 0) {
Wu-cheng Li08ad5ef2012-04-19 12:35:00 +0800190 mCamera = Camera::connect(cameraId);
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800191 if (mCamera == 0) return -EBUSY;
James Dong54ff19a2010-10-08 11:59:32 -0700192 mCameraFlags &= ~FLAGS_HOT_CAMERA;
193 } else {
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800194 // We get the proxy from Camera, not ICamera. We need to get the proxy
195 // to the remote Camera owned by the application. Here mCamera is a
196 // local Camera object created by us. We cannot use the proxy from
197 // mCamera here.
James Dong54ff19a2010-10-08 11:59:32 -0700198 mCamera = Camera::create(camera);
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800199 if (mCamera == 0) return -EBUSY;
200 mCameraRecordingProxy = proxy;
James Dong54ff19a2010-10-08 11:59:32 -0700201 mCameraFlags |= FLAGS_HOT_CAMERA;
James Dong3bd30202011-07-19 20:24:22 -0700202 mDeathNotifier = new DeathNotifier();
203 // isBinderAlive needs linkToDeath to work.
204 mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
James Dong54ff19a2010-10-08 11:59:32 -0700205 }
206
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800207 mCamera->lock();
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800208
James Dong54ff19a2010-10-08 11:59:32 -0700209 return OK;
210}
211
212
213/*
214 * Check to see whether the requested video width and height is one
215 * of the supported sizes.
216 * @param width the video frame width in pixels
217 * @param height the video frame height in pixels
218 * @param suppportedSizes the vector of sizes that we check against
219 * @return true if the dimension (width and height) is supported.
220 */
221static bool isVideoSizeSupported(
222 int32_t width, int32_t height,
223 const Vector<Size>& supportedSizes) {
224
Steve Block3856b092011-10-20 11:56:00 +0100225 ALOGV("isVideoSizeSupported");
James Dong54ff19a2010-10-08 11:59:32 -0700226 for (size_t i = 0; i < supportedSizes.size(); ++i) {
227 if (width == supportedSizes[i].width &&
228 height == supportedSizes[i].height) {
229 return true;
230 }
231 }
232 return false;
233}
234
235/*
236 * If the preview and video output is separate, we only set the
237 * the video size, and applications should set the preview size
238 * to some proper value, and the recording framework will not
239 * change the preview size; otherwise, if the video and preview
240 * output is the same, we need to set the preview to be the same
241 * as the requested video size.
242 *
243 */
244/*
245 * Query the camera to retrieve the supported video frame sizes
246 * and also to see whether CameraParameters::setVideoSize()
247 * is supported or not.
248 * @param params CameraParameters to retrieve the information
249 * @@param isSetVideoSizeSupported retunrs whether method
250 * CameraParameters::setVideoSize() is supported or not.
251 * @param sizes returns the vector of Size objects for the
252 * supported video frame sizes advertised by the camera.
253 */
254static void getSupportedVideoSizes(
255 const CameraParameters& params,
256 bool *isSetVideoSizeSupported,
257 Vector<Size>& sizes) {
258
259 *isSetVideoSizeSupported = true;
260 params.getSupportedVideoSizes(sizes);
261 if (sizes.size() == 0) {
Steve Blockb8a80522011-12-20 16:23:08 +0000262 ALOGD("Camera does not support setVideoSize()");
James Dong54ff19a2010-10-08 11:59:32 -0700263 params.getSupportedPreviewSizes(sizes);
264 *isSetVideoSizeSupported = false;
265 }
266}
267
268/*
269 * Check whether the camera has the supported color format
270 * @param params CameraParameters to retrieve the information
271 * @return OK if no error.
272 */
273status_t CameraSource::isCameraColorFormatSupported(
274 const CameraParameters& params) {
275 mColorFormat = getColorFormat(params.get(
276 CameraParameters::KEY_VIDEO_FRAME_FORMAT));
277 if (mColorFormat == -1) {
278 return BAD_VALUE;
279 }
280 return OK;
281}
282
283/*
284 * Configure the camera to use the requested video size
285 * (width and height) and/or frame rate. If both width and
286 * height are -1, configuration on the video size is skipped.
287 * if frameRate is -1, configuration on the frame rate
288 * is skipped. Skipping the configuration allows one to
289 * use the current camera setting without the need to
290 * actually know the specific values (see Create() method).
291 *
292 * @param params the CameraParameters to be configured
293 * @param width the target video frame width in pixels
294 * @param height the target video frame height in pixels
295 * @param frameRate the target frame rate in frames per second.
296 * @return OK if no error.
297 */
298status_t CameraSource::configureCamera(
299 CameraParameters* params,
300 int32_t width, int32_t height,
301 int32_t frameRate) {
Steve Block3856b092011-10-20 11:56:00 +0100302 ALOGV("configureCamera");
James Dong54ff19a2010-10-08 11:59:32 -0700303 Vector<Size> sizes;
304 bool isSetVideoSizeSupportedByCamera = true;
305 getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
306 bool isCameraParamChanged = false;
307 if (width != -1 && height != -1) {
308 if (!isVideoSizeSupported(width, height, sizes)) {
Steve Block29357bc2012-01-06 19:20:56 +0000309 ALOGE("Video dimension (%dx%d) is unsupported", width, height);
James Dong54ff19a2010-10-08 11:59:32 -0700310 return BAD_VALUE;
311 }
312 if (isSetVideoSizeSupportedByCamera) {
313 params->setVideoSize(width, height);
314 } else {
315 params->setPreviewSize(width, height);
316 }
317 isCameraParamChanged = true;
318 } else if ((width == -1 && height != -1) ||
319 (width != -1 && height == -1)) {
320 // If one and only one of the width and height is -1
321 // we reject such a request.
Steve Block29357bc2012-01-06 19:20:56 +0000322 ALOGE("Requested video size (%dx%d) is not supported", width, height);
James Dong54ff19a2010-10-08 11:59:32 -0700323 return BAD_VALUE;
324 } else { // width == -1 && height == -1
325 // Do not configure the camera.
326 // Use the current width and height value setting from the camera.
327 }
328
329 if (frameRate != -1) {
James Dong63573082010-10-24 09:32:39 -0700330 CHECK(frameRate > 0 && frameRate <= 120);
331 const char* supportedFrameRates =
332 params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
333 CHECK(supportedFrameRates != NULL);
Steve Block3856b092011-10-20 11:56:00 +0100334 ALOGV("Supported frame rates: %s", supportedFrameRates);
James Dong63573082010-10-24 09:32:39 -0700335 char buf[4];
336 snprintf(buf, 4, "%d", frameRate);
337 if (strstr(supportedFrameRates, buf) == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +0000338 ALOGE("Requested frame rate (%d) is not supported: %s",
James Dong63573082010-10-24 09:32:39 -0700339 frameRate, supportedFrameRates);
340 return BAD_VALUE;
341 }
342
343 // The frame rate is supported, set the camera to the requested value.
James Dong54ff19a2010-10-08 11:59:32 -0700344 params->setPreviewFrameRate(frameRate);
345 isCameraParamChanged = true;
346 } else { // frameRate == -1
347 // Do not configure the camera.
348 // Use the current frame rate value setting from the camera
349 }
350
351 if (isCameraParamChanged) {
352 // Either frame rate or frame size needs to be changed.
353 String8 s = params->flatten();
354 if (OK != mCamera->setParameters(s)) {
Steve Block29357bc2012-01-06 19:20:56 +0000355 ALOGE("Could not change settings."
James Dong54ff19a2010-10-08 11:59:32 -0700356 " Someone else is using camera %p?", mCamera.get());
357 return -EBUSY;
358 }
359 }
360 return OK;
361}
362
363/*
364 * Check whether the requested video frame size
365 * has been successfully configured or not. If both width and height
366 * are -1, check on the current width and height value setting
367 * is performed.
368 *
369 * @param params CameraParameters to retrieve the information
370 * @param the target video frame width in pixels to check against
371 * @param the target video frame height in pixels to check against
372 * @return OK if no error
373 */
374status_t CameraSource::checkVideoSize(
375 const CameraParameters& params,
376 int32_t width, int32_t height) {
377
Steve Block3856b092011-10-20 11:56:00 +0100378 ALOGV("checkVideoSize");
James Dongf96c9d12010-10-20 11:41:33 -0700379 // The actual video size is the same as the preview size
380 // if the camera hal does not support separate video and
381 // preview output. In this case, we retrieve the video
382 // size from preview.
James Dong54ff19a2010-10-08 11:59:32 -0700383 int32_t frameWidthActual = -1;
384 int32_t frameHeightActual = -1;
James Dongf96c9d12010-10-20 11:41:33 -0700385 Vector<Size> sizes;
386 params.getSupportedVideoSizes(sizes);
387 if (sizes.size() == 0) {
388 // video size is the same as preview size
389 params.getPreviewSize(&frameWidthActual, &frameHeightActual);
390 } else {
391 // video size may not be the same as preview
392 params.getVideoSize(&frameWidthActual, &frameHeightActual);
393 }
James Dong54ff19a2010-10-08 11:59:32 -0700394 if (frameWidthActual < 0 || frameHeightActual < 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000395 ALOGE("Failed to retrieve video frame size (%dx%d)",
James Dong54ff19a2010-10-08 11:59:32 -0700396 frameWidthActual, frameHeightActual);
397 return UNKNOWN_ERROR;
398 }
399
400 // Check the actual video frame size against the target/requested
401 // video frame size.
402 if (width != -1 && height != -1) {
403 if (frameWidthActual != width || frameHeightActual != height) {
Steve Block29357bc2012-01-06 19:20:56 +0000404 ALOGE("Failed to set video frame size to %dx%d. "
James Dong54ff19a2010-10-08 11:59:32 -0700405 "The actual video size is %dx%d ", width, height,
406 frameWidthActual, frameHeightActual);
407 return UNKNOWN_ERROR;
408 }
409 }
410
411 // Good now.
412 mVideoSize.width = frameWidthActual;
413 mVideoSize.height = frameHeightActual;
414 return OK;
415}
416
417/*
418 * Check the requested frame rate has been successfully configured or not.
419 * If the target frameRate is -1, check on the current frame rate value
420 * setting is performed.
421 *
422 * @param params CameraParameters to retrieve the information
423 * @param the target video frame rate to check against
424 * @return OK if no error.
425 */
426status_t CameraSource::checkFrameRate(
427 const CameraParameters& params,
428 int32_t frameRate) {
429
Steve Block3856b092011-10-20 11:56:00 +0100430 ALOGV("checkFrameRate");
James Dong54ff19a2010-10-08 11:59:32 -0700431 int32_t frameRateActual = params.getPreviewFrameRate();
432 if (frameRateActual < 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000433 ALOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
James Dong54ff19a2010-10-08 11:59:32 -0700434 return UNKNOWN_ERROR;
435 }
436
437 // Check the actual video frame rate against the target/requested
438 // video frame rate.
439 if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000440 ALOGE("Failed to set preview frame rate to %d fps. The actual "
James Dong54ff19a2010-10-08 11:59:32 -0700441 "frame rate is %d", frameRate, frameRateActual);
442 return UNKNOWN_ERROR;
443 }
444
445 // Good now.
446 mVideoFrameRate = frameRateActual;
447 return OK;
448}
449
450/*
451 * Initialize the CameraSource to so that it becomes
452 * ready for providing the video input streams as requested.
453 * @param camera the camera object used for the video source
454 * @param cameraId if camera == 0, use camera with this id
455 * as the video source
456 * @param videoSize the target video frame size. If both
457 * width and height in videoSize is -1, use the current
458 * width and heigth settings by the camera
459 * @param frameRate the target frame rate in frames per second.
460 * if it is -1, use the current camera frame rate setting.
James Dong5c952312010-10-18 21:42:27 -0700461 * @param storeMetaDataInVideoBuffers request to store meta
462 * data or real YUV data in video buffers. Request to
463 * store meta data in video buffers may not be honored
464 * if the source does not support this feature.
465 *
James Dong54ff19a2010-10-08 11:59:32 -0700466 * @return OK if no error.
467 */
468status_t CameraSource::init(
469 const sp<ICamera>& camera,
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800470 const sp<ICameraRecordingProxy>& proxy,
James Dong54ff19a2010-10-08 11:59:32 -0700471 int32_t cameraId,
472 Size videoSize,
James Dong5c952312010-10-18 21:42:27 -0700473 int32_t frameRate,
474 bool storeMetaDataInVideoBuffers) {
James Dong54ff19a2010-10-08 11:59:32 -0700475
Steve Block3856b092011-10-20 11:56:00 +0100476 ALOGV("init");
James Dong54ff19a2010-10-08 11:59:32 -0700477 status_t err = OK;
James Dongae4c1ac2011-07-08 17:59:29 -0700478 int64_t token = IPCThreadState::self()->clearCallingIdentity();
479 err = initWithCameraAccess(camera, proxy, cameraId,
480 videoSize, frameRate,
481 storeMetaDataInVideoBuffers);
482 IPCThreadState::self()->restoreCallingIdentity(token);
483 return err;
484}
485
486status_t CameraSource::initWithCameraAccess(
487 const sp<ICamera>& camera,
488 const sp<ICameraRecordingProxy>& proxy,
489 int32_t cameraId,
490 Size videoSize,
491 int32_t frameRate,
492 bool storeMetaDataInVideoBuffers) {
Steve Block3856b092011-10-20 11:56:00 +0100493 ALOGV("initWithCameraAccess");
James Dongae4c1ac2011-07-08 17:59:29 -0700494 status_t err = OK;
James Dong54ff19a2010-10-08 11:59:32 -0700495
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800496 if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000497 ALOGE("Camera connection could not be established.");
James Dong54ff19a2010-10-08 11:59:32 -0700498 return err;
499 }
500 CameraParameters params(mCamera->getParameters());
501 if ((err = isCameraColorFormatSupported(params)) != OK) {
502 return err;
503 }
504
505 // Set the camera to use the requested video frame size
506 // and/or frame rate.
507 if ((err = configureCamera(&params,
508 videoSize.width, videoSize.height,
509 frameRate))) {
510 return err;
511 }
512
513 // Check on video frame size and frame rate.
514 CameraParameters newCameraParams(mCamera->getParameters());
515 if ((err = checkVideoSize(newCameraParams,
516 videoSize.width, videoSize.height)) != OK) {
517 return err;
518 }
519 if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
520 return err;
521 }
522
Wu-cheng Li8e0792b2012-03-14 17:25:57 +0800523 // Set the preview display. Skip this if mSurface is null because
524 // applications may already set a surface to the camera.
525 if (mSurface != NULL) {
526 // This CHECK is good, since we just passed the lock/unlock
527 // check earlier by calling mCamera->setParameters().
528 CHECK_EQ((status_t)OK, mCamera->setPreviewDisplay(mSurface));
529 }
James Dong2b37ced2010-10-09 01:16:58 -0700530
James Dongabdd2ba2010-12-10 13:09:05 -0800531 // By default, do not store metadata in video buffers
James Dong5c952312010-10-18 21:42:27 -0700532 mIsMetaDataStoredInVideoBuffers = false;
James Dongabdd2ba2010-12-10 13:09:05 -0800533 mCamera->storeMetaDataInBuffers(false);
534 if (storeMetaDataInVideoBuffers) {
535 if (OK == mCamera->storeMetaDataInBuffers(true)) {
536 mIsMetaDataStoredInVideoBuffers = true;
537 }
James Dong5c952312010-10-18 21:42:27 -0700538 }
539
James Dong54ff19a2010-10-08 11:59:32 -0700540 int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
James Dongf60cafe2010-06-19 09:04:18 -0700541 if (glitchDurationUs > mGlitchDurationThresholdUs) {
542 mGlitchDurationThresholdUs = glitchDurationUs;
543 }
544
James Dongddcc4a62010-06-08 11:58:53 -0700545 // XXX: query camera for the stride and slice height
546 // when the capability becomes available.
James Dong653252b2010-06-03 11:48:31 -0700547 mMeta = new MetaData;
James Dong54ff19a2010-10-08 11:59:32 -0700548 mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
549 mMeta->setInt32(kKeyColorFormat, mColorFormat);
550 mMeta->setInt32(kKeyWidth, mVideoSize.width);
551 mMeta->setInt32(kKeyHeight, mVideoSize.height);
552 mMeta->setInt32(kKeyStride, mVideoSize.width);
553 mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
James Dong393410a2010-11-10 20:43:53 -0800554 mMeta->setInt32(kKeyFrameRate, mVideoFrameRate);
James Dong54ff19a2010-10-08 11:59:32 -0700555 return OK;
Andreas Huber20111aa2009-07-14 16:56:47 -0700556}
557
558CameraSource::~CameraSource() {
559 if (mStarted) {
James Dongb44c9d22012-02-02 18:04:02 -0800560 reset();
James Dongae4c1ac2011-07-08 17:59:29 -0700561 } else if (mInitCheck == OK) {
562 // Camera is initialized but because start() is never called,
563 // the lock on Camera is never released(). This makes sure
564 // Camera's lock is released in this case.
565 releaseCamera();
Andreas Huber20111aa2009-07-14 16:56:47 -0700566 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700567}
568
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700569void CameraSource::startCameraRecording() {
Steve Block3856b092011-10-20 11:56:00 +0100570 ALOGV("startCameraRecording");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800571 // Reset the identity to the current thread because media server owns the
572 // camera and recording is started by the applications. The applications
573 // will connect to the camera in ICameraRecordingProxy::startRecording.
574 int64_t token = IPCThreadState::self()->clearCallingIdentity();
James Dong983cf232012-08-01 16:39:55 -0700575 if (mNumInputBuffers > 0) {
576 status_t err = mCamera->sendCommand(
577 CAMERA_CMD_SET_VIDEO_BUFFER_COUNT, mNumInputBuffers, 0);
578
579 // This could happen for CameraHAL1 clients; thus the failure is
580 // not a fatal error
581 if (err != OK) {
582 ALOGW("Failed to set video buffer count to %d due to %d",
583 mNumInputBuffers, err);
584 }
585 }
586
James Dong3bd30202011-07-19 20:24:22 -0700587 if (mCameraFlags & FLAGS_HOT_CAMERA) {
588 mCamera->unlock();
589 mCamera.clear();
James Dongf1d5aa12012-02-06 23:46:37 -0800590 CHECK_EQ((status_t)OK,
591 mCameraRecordingProxy->startRecording(new ProxyListener(this)));
James Dong3bd30202011-07-19 20:24:22 -0700592 } else {
593 mCamera->setListener(new CameraSourceListener(this));
594 mCamera->startRecording();
595 CHECK(mCamera->recordingEnabled());
596 }
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800597 IPCThreadState::self()->restoreCallingIdentity(token);
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700598}
599
James Dongf60cafe2010-06-19 09:04:18 -0700600status_t CameraSource::start(MetaData *meta) {
Steve Block3856b092011-10-20 11:56:00 +0100601 ALOGV("start");
Andreas Huber0c891992009-08-26 14:48:20 -0700602 CHECK(!mStarted);
James Dong54ff19a2010-10-08 11:59:32 -0700603 if (mInitCheck != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000604 ALOGE("CameraSource is not initialized yet");
James Dong54ff19a2010-10-08 11:59:32 -0700605 return mInitCheck;
606 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700607
James Dong365a9632010-06-04 13:59:27 -0700608 char value[PROPERTY_VALUE_MAX];
609 if (property_get("media.stagefright.record-stats", value, NULL)
610 && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
611 mCollectStats = true;
612 }
James Dong9d7f58a2010-06-09 15:57:48 -0700613
James Dongf60cafe2010-06-19 09:04:18 -0700614 mStartTimeUs = 0;
James Dong983cf232012-08-01 16:39:55 -0700615 mNumInputBuffers = 0;
616 if (meta) {
617 int64_t startTimeUs;
618 if (meta->findInt64(kKeyTime, &startTimeUs)) {
619 mStartTimeUs = startTimeUs;
620 }
621
622 int32_t nBuffers;
623 if (meta->findInt32(kKeyNumBuffers, &nBuffers)) {
624 CHECK_GT(nBuffers, 0);
625 mNumInputBuffers = nBuffers;
626 }
James Dongf60cafe2010-06-19 09:04:18 -0700627 }
628
James Dongc42478e2010-11-15 10:38:37 -0800629 startCameraRecording();
Andreas Huber20111aa2009-07-14 16:56:47 -0700630
631 mStarted = true;
Andreas Huber20111aa2009-07-14 16:56:47 -0700632 return OK;
633}
634
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700635void CameraSource::stopCameraRecording() {
Steve Block3856b092011-10-20 11:56:00 +0100636 ALOGV("stopCameraRecording");
James Dong3bd30202011-07-19 20:24:22 -0700637 if (mCameraFlags & FLAGS_HOT_CAMERA) {
638 mCameraRecordingProxy->stopRecording();
639 } else {
640 mCamera->setListener(NULL);
641 mCamera->stopRecording();
642 }
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700643}
644
James Dongea7b4852010-12-05 14:25:34 -0800645void CameraSource::releaseCamera() {
Steve Block3856b092011-10-20 11:56:00 +0100646 ALOGV("releaseCamera");
Wu-cheng Li95068be2011-06-29 15:17:11 +0800647 if (mCamera != 0) {
James Dongae4c1ac2011-07-08 17:59:29 -0700648 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Wu-cheng Li95068be2011-06-29 15:17:11 +0800649 if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
Steve Block3856b092011-10-20 11:56:00 +0100650 ALOGV("Camera was cold when we started, stopping preview");
Wu-cheng Li95068be2011-06-29 15:17:11 +0800651 mCamera->stopPreview();
652 mCamera->disconnect();
Wu-cheng Li95068be2011-06-29 15:17:11 +0800653 }
James Dong3bd30202011-07-19 20:24:22 -0700654 mCamera->unlock();
Wu-cheng Li95068be2011-06-29 15:17:11 +0800655 mCamera.clear();
James Dong3bd30202011-07-19 20:24:22 -0700656 mCamera = 0;
James Dongae4c1ac2011-07-08 17:59:29 -0700657 IPCThreadState::self()->restoreCallingIdentity(token);
James Dongea7b4852010-12-05 14:25:34 -0800658 }
Wu-cheng Li95068be2011-06-29 15:17:11 +0800659 if (mCameraRecordingProxy != 0) {
660 mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
661 mCameraRecordingProxy.clear();
662 }
James Dongea7b4852010-12-05 14:25:34 -0800663 mCameraFlags = 0;
664}
665
James Dongb44c9d22012-02-02 18:04:02 -0800666status_t CameraSource::reset() {
667 ALOGD("reset: E");
James Dongc32cd792010-04-26 17:48:26 -0700668 Mutex::Autolock autoLock(mLock);
Andreas Huber20111aa2009-07-14 16:56:47 -0700669 mStarted = false;
James Dongc32cd792010-04-26 17:48:26 -0700670 mFrameAvailableCondition.signal();
James Dong365a9632010-06-04 13:59:27 -0700671
James Dong91974412011-08-24 19:50:36 -0700672 int64_t token;
673 bool isTokenValid = false;
674 if (mCamera != 0) {
675 token = IPCThreadState::self()->clearCallingIdentity();
676 isTokenValid = true;
677 }
James Dongc32cd792010-04-26 17:48:26 -0700678 releaseQueuedFrames();
James Dong7278cf32010-05-27 16:05:58 -0700679 while (!mFramesBeingEncoded.empty()) {
James Dong41152ef2010-12-20 21:29:12 -0800680 if (NO_ERROR !=
James Donge8e5f862011-11-20 09:45:44 -0800681 mFrameCompleteCondition.waitRelative(mLock,
682 mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000683 ALOGW("Timed out waiting for outstanding frames being encoded: %d",
James Dong365a9632010-06-04 13:59:27 -0700684 mFramesBeingEncoded.size());
James Dong41152ef2010-12-20 21:29:12 -0800685 }
James Dong7278cf32010-05-27 16:05:58 -0700686 }
James Dongd69c7f62010-12-09 11:24:22 -0800687 stopCameraRecording();
James Dongea7b4852010-12-05 14:25:34 -0800688 releaseCamera();
James Dong91974412011-08-24 19:50:36 -0700689 if (isTokenValid) {
690 IPCThreadState::self()->restoreCallingIdentity(token);
691 }
James Dong7278cf32010-05-27 16:05:58 -0700692
James Dong365a9632010-06-04 13:59:27 -0700693 if (mCollectStats) {
Steve Blockdf64d152012-01-04 20:05:49 +0000694 ALOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
James Dong365a9632010-06-04 13:59:27 -0700695 mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
696 mLastFrameTimestampUs - mFirstFrameTimeUs);
697 }
James Dong13aec892010-04-21 16:14:15 -0700698
James Dongba290022010-12-09 15:04:33 -0800699 if (mNumGlitches > 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000700 ALOGW("%d long delays between neighboring video frames", mNumGlitches);
James Dongba290022010-12-09 15:04:33 -0800701 }
702
James Dong13aec892010-04-21 16:14:15 -0700703 CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
James Dongb44c9d22012-02-02 18:04:02 -0800704 ALOGD("reset: X");
Andreas Huber20111aa2009-07-14 16:56:47 -0700705 return OK;
706}
707
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700708void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
Steve Block3856b092011-10-20 11:56:00 +0100709 ALOGV("releaseRecordingFrame");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800710 if (mCameraRecordingProxy != NULL) {
711 mCameraRecordingProxy->releaseRecordingFrame(frame);
James Dong334d0972011-08-05 17:19:29 -0700712 } else if (mCamera != NULL) {
James Dong3bd30202011-07-19 20:24:22 -0700713 int64_t token = IPCThreadState::self()->clearCallingIdentity();
714 mCamera->releaseRecordingFrame(frame);
715 IPCThreadState::self()->restoreCallingIdentity(token);
James Dongd69c7f62010-12-09 11:24:22 -0800716 }
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700717}
718
James Dongc32cd792010-04-26 17:48:26 -0700719void CameraSource::releaseQueuedFrames() {
720 List<sp<IMemory> >::iterator it;
James Dong7278cf32010-05-27 16:05:58 -0700721 while (!mFramesReceived.empty()) {
722 it = mFramesReceived.begin();
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700723 releaseRecordingFrame(*it);
James Dong7278cf32010-05-27 16:05:58 -0700724 mFramesReceived.erase(it);
James Dong13aec892010-04-21 16:14:15 -0700725 ++mNumFramesDropped;
James Dongc32cd792010-04-26 17:48:26 -0700726 }
727}
728
Andreas Huber20111aa2009-07-14 16:56:47 -0700729sp<MetaData> CameraSource::getFormat() {
James Dong653252b2010-06-03 11:48:31 -0700730 return mMeta;
Andreas Huber20111aa2009-07-14 16:56:47 -0700731}
732
James Dongf60cafe2010-06-19 09:04:18 -0700733void CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700734 releaseRecordingFrame(frame);
James Dongf60cafe2010-06-19 09:04:18 -0700735}
736
James Dong7278cf32010-05-27 16:05:58 -0700737void CameraSource::signalBufferReturned(MediaBuffer *buffer) {
Steve Block3856b092011-10-20 11:56:00 +0100738 ALOGV("signalBufferReturned: %p", buffer->data());
Andreas Huber56223b92010-08-11 12:34:32 -0700739 Mutex::Autolock autoLock(mLock);
James Dong7278cf32010-05-27 16:05:58 -0700740 for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
741 it != mFramesBeingEncoded.end(); ++it) {
742 if ((*it)->pointer() == buffer->data()) {
James Dongf60cafe2010-06-19 09:04:18 -0700743 releaseOneRecordingFrame((*it));
James Dong7278cf32010-05-27 16:05:58 -0700744 mFramesBeingEncoded.erase(it);
745 ++mNumFramesEncoded;
746 buffer->setObserver(0);
747 buffer->release();
748 mFrameCompleteCondition.signal();
749 return;
750 }
751 }
James Dongf1d5aa12012-02-06 23:46:37 -0800752 CHECK(!"signalBufferReturned: bogus buffer");
James Dong7278cf32010-05-27 16:05:58 -0700753}
754
Andreas Huber20111aa2009-07-14 16:56:47 -0700755status_t CameraSource::read(
756 MediaBuffer **buffer, const ReadOptions *options) {
Steve Block3856b092011-10-20 11:56:00 +0100757 ALOGV("read");
Andreas Huber20111aa2009-07-14 16:56:47 -0700758
759 *buffer = NULL;
760
761 int64_t seekTimeUs;
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700762 ReadOptions::SeekMode mode;
763 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700764 return ERROR_UNSUPPORTED;
765 }
766
767 sp<IMemory> frame;
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700768 int64_t frameTime;
Andreas Huber20111aa2009-07-14 16:56:47 -0700769
770 {
771 Mutex::Autolock autoLock(mLock);
James Dong79e23b42010-12-11 10:43:41 -0800772 while (mStarted && mFramesReceived.empty()) {
James Dong41152ef2010-12-20 21:29:12 -0800773 if (NO_ERROR !=
James Donge8e5f862011-11-20 09:45:44 -0800774 mFrameAvailableCondition.waitRelative(mLock,
775 mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
James Dong3bd30202011-07-19 20:24:22 -0700776 if (mCameraRecordingProxy != 0 &&
777 !mCameraRecordingProxy->asBinder()->isBinderAlive()) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000778 ALOGW("camera recording proxy is gone");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800779 return ERROR_END_OF_STREAM;
780 }
Steve Block5ff1dd52012-01-05 23:22:43 +0000781 ALOGW("Timed out waiting for incoming camera video frames: %lld us",
James Dong41152ef2010-12-20 21:29:12 -0800782 mLastFrameTimestampUs);
783 }
James Dong542db5d2010-07-21 14:51:35 -0700784 }
James Dong79e23b42010-12-11 10:43:41 -0800785 if (!mStarted) {
786 return OK;
787 }
788 frame = *mFramesReceived.begin();
789 mFramesReceived.erase(mFramesReceived.begin());
790
791 frameTime = *mFrameTimes.begin();
792 mFrameTimes.erase(mFrameTimes.begin());
793 mFramesBeingEncoded.push_back(frame);
794 *buffer = new MediaBuffer(frame->pointer(), frame->size());
795 (*buffer)->setObserver(this);
796 (*buffer)->add_ref();
797 (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
Andreas Huber20111aa2009-07-14 16:56:47 -0700798 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700799 return OK;
800}
801
James Dongc32cd792010-04-26 17:48:26 -0700802void CameraSource::dataCallbackTimestamp(int64_t timestampUs,
803 int32_t msgType, const sp<IMemory> &data) {
Steve Block3856b092011-10-20 11:56:00 +0100804 ALOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
Andreas Huber20111aa2009-07-14 16:56:47 -0700805 Mutex::Autolock autoLock(mLock);
James Donga4726132011-02-16 12:28:26 -0800806 if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
Steve Block3856b092011-10-20 11:56:00 +0100807 ALOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
James Dongf60cafe2010-06-19 09:04:18 -0700808 releaseOneRecordingFrame(data);
James Dongc32cd792010-04-26 17:48:26 -0700809 return;
810 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700811
James Dong98cfde02011-06-03 17:21:16 -0700812 if (mNumFramesReceived > 0) {
813 CHECK(timestampUs > mLastFrameTimestampUs);
814 if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
815 ++mNumGlitches;
James Dongf60cafe2010-06-19 09:04:18 -0700816 }
James Dongf60cafe2010-06-19 09:04:18 -0700817 }
818
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700819 // May need to skip frame or modify timestamp. Currently implemented
820 // by the subclass CameraSourceTimeLapse.
James Dong79e23b42010-12-11 10:43:41 -0800821 if (skipCurrentFrame(timestampUs)) {
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700822 releaseOneRecordingFrame(data);
823 return;
Nipun Kwatrafc20aab2010-06-30 18:51:31 -0700824 }
825
James Dong365a9632010-06-04 13:59:27 -0700826 mLastFrameTimestampUs = timestampUs;
James Dong13aec892010-04-21 16:14:15 -0700827 if (mNumFramesReceived == 0) {
James Dongc32cd792010-04-26 17:48:26 -0700828 mFirstFrameTimeUs = timestampUs;
James Dongf60cafe2010-06-19 09:04:18 -0700829 // Initial delay
830 if (mStartTimeUs > 0) {
831 if (timestampUs < mStartTimeUs) {
832 // Frame was captured before recording was started
833 // Drop it without updating the statistical data.
834 releaseOneRecordingFrame(data);
835 return;
836 }
837 mStartTimeUs = timestampUs - mStartTimeUs;
838 }
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700839 }
James Dong13aec892010-04-21 16:14:15 -0700840 ++mNumFramesReceived;
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700841
James Dong98cfde02011-06-03 17:21:16 -0700842 CHECK(data != NULL && data->size() > 0);
James Dong7278cf32010-05-27 16:05:58 -0700843 mFramesReceived.push_back(data);
James Dongf60cafe2010-06-19 09:04:18 -0700844 int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
845 mFrameTimes.push_back(timeUs);
Steve Block3856b092011-10-20 11:56:00 +0100846 ALOGV("initial delay: %lld, current time stamp: %lld",
James Dongf60cafe2010-06-19 09:04:18 -0700847 mStartTimeUs, timeUs);
Andreas Huber20111aa2009-07-14 16:56:47 -0700848 mFrameAvailableCondition.signal();
849}
850
James Dong5c952312010-10-18 21:42:27 -0700851bool CameraSource::isMetaDataStoredInVideoBuffers() const {
Steve Block3856b092011-10-20 11:56:00 +0100852 ALOGV("isMetaDataStoredInVideoBuffers");
James Dong5c952312010-10-18 21:42:27 -0700853 return mIsMetaDataStoredInVideoBuffers;
854}
855
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800856CameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
857 mSource = source;
858}
859
860void CameraSource::ProxyListener::dataCallbackTimestamp(
861 nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
862 mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
863}
864
865void CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
Steve Blockdf64d152012-01-04 20:05:49 +0000866 ALOGI("Camera recording proxy died");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800867}
868
Andreas Huber20111aa2009-07-14 16:56:47 -0700869} // namespace android