blob: 3017fe7249a0c759732f36dbc65d2c509b283136 [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
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800124CameraSource *CameraSource::Create(const String16 &clientName) {
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;
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800130 return new CameraSource(camera, NULL, 0, clientName, -1,
131 size, -1, NULL, false);
Andreas Huber20111aa2009-07-14 16:56:47 -0700132}
133
Andreas Huber30ab6622009-11-16 15:43:38 -0800134// static
James Dong54ff19a2010-10-08 11:59:32 -0700135CameraSource *CameraSource::CreateFromCamera(
136 const sp<ICamera>& camera,
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800137 const sp<ICameraRecordingProxy>& proxy,
James Dong54ff19a2010-10-08 11:59:32 -0700138 int32_t cameraId,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800139 const String16& clientName,
140 uid_t clientUid,
James Dong54ff19a2010-10-08 11:59:32 -0700141 Size videoSize,
142 int32_t frameRate,
Mathias Agopian99617ad2013-03-12 18:42:23 -0700143 const sp<IGraphicBufferProducer>& surface,
James Dong5c952312010-10-18 21:42:27 -0700144 bool storeMetaDataInVideoBuffers) {
Andreas Huber30ab6622009-11-16 15:43:38 -0800145
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800146 CameraSource *source = new CameraSource(camera, proxy, cameraId,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800147 clientName, clientUid, videoSize, frameRate, surface,
148 storeMetaDataInVideoBuffers);
James Dong54ff19a2010-10-08 11:59:32 -0700149 return source;
Andreas Huber30ab6622009-11-16 15:43:38 -0800150}
151
James Dong54ff19a2010-10-08 11:59:32 -0700152CameraSource::CameraSource(
153 const sp<ICamera>& camera,
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800154 const sp<ICameraRecordingProxy>& proxy,
James Dong54ff19a2010-10-08 11:59:32 -0700155 int32_t cameraId,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800156 const String16& clientName,
157 uid_t clientUid,
James Dong54ff19a2010-10-08 11:59:32 -0700158 Size videoSize,
159 int32_t frameRate,
Mathias Agopian99617ad2013-03-12 18:42:23 -0700160 const sp<IGraphicBufferProducer>& surface,
James Dong5c952312010-10-18 21:42:27 -0700161 bool storeMetaDataInVideoBuffers)
James Dong54ff19a2010-10-08 11:59:32 -0700162 : mCameraFlags(0),
James Dong983cf232012-08-01 16:39:55 -0700163 mNumInputBuffers(0),
James Dong54ff19a2010-10-08 11:59:32 -0700164 mVideoFrameRate(-1),
165 mCamera(0),
166 mSurface(surface),
James Dong13aec892010-04-21 16:14:15 -0700167 mNumFramesReceived(0),
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700168 mLastFrameTimestampUs(0),
169 mStarted(false),
James Dong13aec892010-04-21 16:14:15 -0700170 mNumFramesEncoded(0),
James Donge8e5f862011-11-20 09:45:44 -0800171 mTimeBetweenFrameCaptureUs(0),
James Dong7757f502011-01-25 16:31:28 -0800172 mFirstFrameTimeUs(0),
James Dong13aec892010-04-21 16:14:15 -0700173 mNumFramesDropped(0),
James Dongf60cafe2010-06-19 09:04:18 -0700174 mNumGlitches(0),
175 mGlitchDurationThresholdUs(200000),
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700176 mCollectStats(false) {
James Dong54ff19a2010-10-08 11:59:32 -0700177 mVideoSize.width = -1;
178 mVideoSize.height = -1;
179
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800180 mInitCheck = init(camera, proxy, cameraId,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800181 clientName, clientUid,
James Dong5c952312010-10-18 21:42:27 -0700182 videoSize, frameRate,
183 storeMetaDataInVideoBuffers);
Wu-cheng Li95068be2011-06-29 15:17:11 +0800184 if (mInitCheck != OK) releaseCamera();
James Dong54ff19a2010-10-08 11:59:32 -0700185}
186
187status_t CameraSource::initCheck() const {
188 return mInitCheck;
189}
190
191status_t CameraSource::isCameraAvailable(
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800192 const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800193 int32_t cameraId, const String16& clientName, uid_t clientUid) {
James Dong54ff19a2010-10-08 11:59:32 -0700194
195 if (camera == 0) {
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800196 mCamera = Camera::connect(cameraId, clientName, clientUid);
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800197 if (mCamera == 0) return -EBUSY;
James Dong54ff19a2010-10-08 11:59:32 -0700198 mCameraFlags &= ~FLAGS_HOT_CAMERA;
199 } else {
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800200 // We get the proxy from Camera, not ICamera. We need to get the proxy
201 // to the remote Camera owned by the application. Here mCamera is a
202 // local Camera object created by us. We cannot use the proxy from
203 // mCamera here.
James Dong54ff19a2010-10-08 11:59:32 -0700204 mCamera = Camera::create(camera);
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800205 if (mCamera == 0) return -EBUSY;
206 mCameraRecordingProxy = proxy;
James Dong54ff19a2010-10-08 11:59:32 -0700207 mCameraFlags |= FLAGS_HOT_CAMERA;
James Dong3bd30202011-07-19 20:24:22 -0700208 mDeathNotifier = new DeathNotifier();
209 // isBinderAlive needs linkToDeath to work.
210 mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
James Dong54ff19a2010-10-08 11:59:32 -0700211 }
212
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800213 mCamera->lock();
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800214
James Dong54ff19a2010-10-08 11:59:32 -0700215 return OK;
216}
217
218
219/*
220 * Check to see whether the requested video width and height is one
221 * of the supported sizes.
222 * @param width the video frame width in pixels
223 * @param height the video frame height in pixels
224 * @param suppportedSizes the vector of sizes that we check against
225 * @return true if the dimension (width and height) is supported.
226 */
227static bool isVideoSizeSupported(
228 int32_t width, int32_t height,
229 const Vector<Size>& supportedSizes) {
230
Steve Block3856b092011-10-20 11:56:00 +0100231 ALOGV("isVideoSizeSupported");
James Dong54ff19a2010-10-08 11:59:32 -0700232 for (size_t i = 0; i < supportedSizes.size(); ++i) {
233 if (width == supportedSizes[i].width &&
234 height == supportedSizes[i].height) {
235 return true;
236 }
237 }
238 return false;
239}
240
241/*
242 * If the preview and video output is separate, we only set the
243 * the video size, and applications should set the preview size
244 * to some proper value, and the recording framework will not
245 * change the preview size; otherwise, if the video and preview
246 * output is the same, we need to set the preview to be the same
247 * as the requested video size.
248 *
249 */
250/*
251 * Query the camera to retrieve the supported video frame sizes
252 * and also to see whether CameraParameters::setVideoSize()
253 * is supported or not.
254 * @param params CameraParameters to retrieve the information
255 * @@param isSetVideoSizeSupported retunrs whether method
256 * CameraParameters::setVideoSize() is supported or not.
257 * @param sizes returns the vector of Size objects for the
258 * supported video frame sizes advertised by the camera.
259 */
260static void getSupportedVideoSizes(
261 const CameraParameters& params,
262 bool *isSetVideoSizeSupported,
263 Vector<Size>& sizes) {
264
265 *isSetVideoSizeSupported = true;
266 params.getSupportedVideoSizes(sizes);
267 if (sizes.size() == 0) {
Steve Blockb8a80522011-12-20 16:23:08 +0000268 ALOGD("Camera does not support setVideoSize()");
James Dong54ff19a2010-10-08 11:59:32 -0700269 params.getSupportedPreviewSizes(sizes);
270 *isSetVideoSizeSupported = false;
271 }
272}
273
274/*
275 * Check whether the camera has the supported color format
276 * @param params CameraParameters to retrieve the information
277 * @return OK if no error.
278 */
279status_t CameraSource::isCameraColorFormatSupported(
280 const CameraParameters& params) {
281 mColorFormat = getColorFormat(params.get(
282 CameraParameters::KEY_VIDEO_FRAME_FORMAT));
283 if (mColorFormat == -1) {
284 return BAD_VALUE;
285 }
286 return OK;
287}
288
289/*
290 * Configure the camera to use the requested video size
291 * (width and height) and/or frame rate. If both width and
292 * height are -1, configuration on the video size is skipped.
293 * if frameRate is -1, configuration on the frame rate
294 * is skipped. Skipping the configuration allows one to
295 * use the current camera setting without the need to
296 * actually know the specific values (see Create() method).
297 *
298 * @param params the CameraParameters to be configured
299 * @param width the target video frame width in pixels
300 * @param height the target video frame height in pixels
301 * @param frameRate the target frame rate in frames per second.
302 * @return OK if no error.
303 */
304status_t CameraSource::configureCamera(
305 CameraParameters* params,
306 int32_t width, int32_t height,
307 int32_t frameRate) {
Steve Block3856b092011-10-20 11:56:00 +0100308 ALOGV("configureCamera");
James Dong54ff19a2010-10-08 11:59:32 -0700309 Vector<Size> sizes;
310 bool isSetVideoSizeSupportedByCamera = true;
311 getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
312 bool isCameraParamChanged = false;
313 if (width != -1 && height != -1) {
314 if (!isVideoSizeSupported(width, height, sizes)) {
Steve Block29357bc2012-01-06 19:20:56 +0000315 ALOGE("Video dimension (%dx%d) is unsupported", width, height);
James Dong54ff19a2010-10-08 11:59:32 -0700316 return BAD_VALUE;
317 }
318 if (isSetVideoSizeSupportedByCamera) {
319 params->setVideoSize(width, height);
320 } else {
321 params->setPreviewSize(width, height);
322 }
323 isCameraParamChanged = true;
324 } else if ((width == -1 && height != -1) ||
325 (width != -1 && height == -1)) {
326 // If one and only one of the width and height is -1
327 // we reject such a request.
Steve Block29357bc2012-01-06 19:20:56 +0000328 ALOGE("Requested video size (%dx%d) is not supported", width, height);
James Dong54ff19a2010-10-08 11:59:32 -0700329 return BAD_VALUE;
330 } else { // width == -1 && height == -1
331 // Do not configure the camera.
332 // Use the current width and height value setting from the camera.
333 }
334
335 if (frameRate != -1) {
James Dong63573082010-10-24 09:32:39 -0700336 CHECK(frameRate > 0 && frameRate <= 120);
337 const char* supportedFrameRates =
338 params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
339 CHECK(supportedFrameRates != NULL);
Steve Block3856b092011-10-20 11:56:00 +0100340 ALOGV("Supported frame rates: %s", supportedFrameRates);
James Dong63573082010-10-24 09:32:39 -0700341 char buf[4];
342 snprintf(buf, 4, "%d", frameRate);
343 if (strstr(supportedFrameRates, buf) == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +0000344 ALOGE("Requested frame rate (%d) is not supported: %s",
James Dong63573082010-10-24 09:32:39 -0700345 frameRate, supportedFrameRates);
346 return BAD_VALUE;
347 }
348
349 // The frame rate is supported, set the camera to the requested value.
James Dong54ff19a2010-10-08 11:59:32 -0700350 params->setPreviewFrameRate(frameRate);
351 isCameraParamChanged = true;
352 } else { // frameRate == -1
353 // Do not configure the camera.
354 // Use the current frame rate value setting from the camera
355 }
356
357 if (isCameraParamChanged) {
358 // Either frame rate or frame size needs to be changed.
359 String8 s = params->flatten();
360 if (OK != mCamera->setParameters(s)) {
Steve Block29357bc2012-01-06 19:20:56 +0000361 ALOGE("Could not change settings."
James Dong54ff19a2010-10-08 11:59:32 -0700362 " Someone else is using camera %p?", mCamera.get());
363 return -EBUSY;
364 }
365 }
366 return OK;
367}
368
369/*
370 * Check whether the requested video frame size
371 * has been successfully configured or not. If both width and height
372 * are -1, check on the current width and height value setting
373 * is performed.
374 *
375 * @param params CameraParameters to retrieve the information
376 * @param the target video frame width in pixels to check against
377 * @param the target video frame height in pixels to check against
378 * @return OK if no error
379 */
380status_t CameraSource::checkVideoSize(
381 const CameraParameters& params,
382 int32_t width, int32_t height) {
383
Steve Block3856b092011-10-20 11:56:00 +0100384 ALOGV("checkVideoSize");
James Dongf96c9d12010-10-20 11:41:33 -0700385 // The actual video size is the same as the preview size
386 // if the camera hal does not support separate video and
387 // preview output. In this case, we retrieve the video
388 // size from preview.
James Dong54ff19a2010-10-08 11:59:32 -0700389 int32_t frameWidthActual = -1;
390 int32_t frameHeightActual = -1;
James Dongf96c9d12010-10-20 11:41:33 -0700391 Vector<Size> sizes;
392 params.getSupportedVideoSizes(sizes);
393 if (sizes.size() == 0) {
394 // video size is the same as preview size
395 params.getPreviewSize(&frameWidthActual, &frameHeightActual);
396 } else {
397 // video size may not be the same as preview
398 params.getVideoSize(&frameWidthActual, &frameHeightActual);
399 }
James Dong54ff19a2010-10-08 11:59:32 -0700400 if (frameWidthActual < 0 || frameHeightActual < 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000401 ALOGE("Failed to retrieve video frame size (%dx%d)",
James Dong54ff19a2010-10-08 11:59:32 -0700402 frameWidthActual, frameHeightActual);
403 return UNKNOWN_ERROR;
404 }
405
406 // Check the actual video frame size against the target/requested
407 // video frame size.
408 if (width != -1 && height != -1) {
409 if (frameWidthActual != width || frameHeightActual != height) {
Steve Block29357bc2012-01-06 19:20:56 +0000410 ALOGE("Failed to set video frame size to %dx%d. "
James Dong54ff19a2010-10-08 11:59:32 -0700411 "The actual video size is %dx%d ", width, height,
412 frameWidthActual, frameHeightActual);
413 return UNKNOWN_ERROR;
414 }
415 }
416
417 // Good now.
418 mVideoSize.width = frameWidthActual;
419 mVideoSize.height = frameHeightActual;
420 return OK;
421}
422
423/*
424 * Check the requested frame rate has been successfully configured or not.
425 * If the target frameRate is -1, check on the current frame rate value
426 * setting is performed.
427 *
428 * @param params CameraParameters to retrieve the information
429 * @param the target video frame rate to check against
430 * @return OK if no error.
431 */
432status_t CameraSource::checkFrameRate(
433 const CameraParameters& params,
434 int32_t frameRate) {
435
Steve Block3856b092011-10-20 11:56:00 +0100436 ALOGV("checkFrameRate");
James Dong54ff19a2010-10-08 11:59:32 -0700437 int32_t frameRateActual = params.getPreviewFrameRate();
438 if (frameRateActual < 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000439 ALOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
James Dong54ff19a2010-10-08 11:59:32 -0700440 return UNKNOWN_ERROR;
441 }
442
443 // Check the actual video frame rate against the target/requested
444 // video frame rate.
445 if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000446 ALOGE("Failed to set preview frame rate to %d fps. The actual "
James Dong54ff19a2010-10-08 11:59:32 -0700447 "frame rate is %d", frameRate, frameRateActual);
448 return UNKNOWN_ERROR;
449 }
450
451 // Good now.
452 mVideoFrameRate = frameRateActual;
453 return OK;
454}
455
456/*
457 * Initialize the CameraSource to so that it becomes
458 * ready for providing the video input streams as requested.
459 * @param camera the camera object used for the video source
460 * @param cameraId if camera == 0, use camera with this id
461 * as the video source
462 * @param videoSize the target video frame size. If both
463 * width and height in videoSize is -1, use the current
464 * width and heigth settings by the camera
465 * @param frameRate the target frame rate in frames per second.
466 * if it is -1, use the current camera frame rate setting.
James Dong5c952312010-10-18 21:42:27 -0700467 * @param storeMetaDataInVideoBuffers request to store meta
468 * data or real YUV data in video buffers. Request to
469 * store meta data in video buffers may not be honored
470 * if the source does not support this feature.
471 *
James Dong54ff19a2010-10-08 11:59:32 -0700472 * @return OK if no error.
473 */
474status_t CameraSource::init(
475 const sp<ICamera>& camera,
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800476 const sp<ICameraRecordingProxy>& proxy,
James Dong54ff19a2010-10-08 11:59:32 -0700477 int32_t cameraId,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800478 const String16& clientName,
479 uid_t clientUid,
James Dong54ff19a2010-10-08 11:59:32 -0700480 Size videoSize,
James Dong5c952312010-10-18 21:42:27 -0700481 int32_t frameRate,
482 bool storeMetaDataInVideoBuffers) {
James Dong54ff19a2010-10-08 11:59:32 -0700483
Steve Block3856b092011-10-20 11:56:00 +0100484 ALOGV("init");
James Dong54ff19a2010-10-08 11:59:32 -0700485 status_t err = OK;
James Dongae4c1ac2011-07-08 17:59:29 -0700486 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800487 err = initWithCameraAccess(camera, proxy, cameraId, clientName, clientUid,
James Dongae4c1ac2011-07-08 17:59:29 -0700488 videoSize, frameRate,
489 storeMetaDataInVideoBuffers);
490 IPCThreadState::self()->restoreCallingIdentity(token);
491 return err;
492}
493
494status_t CameraSource::initWithCameraAccess(
495 const sp<ICamera>& camera,
496 const sp<ICameraRecordingProxy>& proxy,
497 int32_t cameraId,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800498 const String16& clientName,
499 uid_t clientUid,
James Dongae4c1ac2011-07-08 17:59:29 -0700500 Size videoSize,
501 int32_t frameRate,
502 bool storeMetaDataInVideoBuffers) {
Steve Block3856b092011-10-20 11:56:00 +0100503 ALOGV("initWithCameraAccess");
James Dongae4c1ac2011-07-08 17:59:29 -0700504 status_t err = OK;
James Dong54ff19a2010-10-08 11:59:32 -0700505
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800506 if ((err = isCameraAvailable(camera, proxy, cameraId,
507 clientName, clientUid)) != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000508 ALOGE("Camera connection could not be established.");
James Dong54ff19a2010-10-08 11:59:32 -0700509 return err;
510 }
511 CameraParameters params(mCamera->getParameters());
512 if ((err = isCameraColorFormatSupported(params)) != OK) {
513 return err;
514 }
515
516 // Set the camera to use the requested video frame size
517 // and/or frame rate.
518 if ((err = configureCamera(&params,
519 videoSize.width, videoSize.height,
520 frameRate))) {
521 return err;
522 }
523
524 // Check on video frame size and frame rate.
525 CameraParameters newCameraParams(mCamera->getParameters());
526 if ((err = checkVideoSize(newCameraParams,
527 videoSize.width, videoSize.height)) != OK) {
528 return err;
529 }
530 if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
531 return err;
532 }
533
Wu-cheng Li8e0792b2012-03-14 17:25:57 +0800534 // Set the preview display. Skip this if mSurface is null because
535 // applications may already set a surface to the camera.
536 if (mSurface != NULL) {
537 // This CHECK is good, since we just passed the lock/unlock
538 // check earlier by calling mCamera->setParameters().
Eino-Ville Talvala4b820b02013-08-21 14:39:05 -0700539 CHECK_EQ((status_t)OK, mCamera->setPreviewTarget(mSurface));
Wu-cheng Li8e0792b2012-03-14 17:25:57 +0800540 }
James Dong2b37ced2010-10-09 01:16:58 -0700541
James Dongabdd2ba2010-12-10 13:09:05 -0800542 // By default, do not store metadata in video buffers
James Dong5c952312010-10-18 21:42:27 -0700543 mIsMetaDataStoredInVideoBuffers = false;
James Dongabdd2ba2010-12-10 13:09:05 -0800544 mCamera->storeMetaDataInBuffers(false);
545 if (storeMetaDataInVideoBuffers) {
546 if (OK == mCamera->storeMetaDataInBuffers(true)) {
547 mIsMetaDataStoredInVideoBuffers = true;
548 }
James Dong5c952312010-10-18 21:42:27 -0700549 }
550
James Dong54ff19a2010-10-08 11:59:32 -0700551 int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
James Dongf60cafe2010-06-19 09:04:18 -0700552 if (glitchDurationUs > mGlitchDurationThresholdUs) {
553 mGlitchDurationThresholdUs = glitchDurationUs;
554 }
555
James Dongddcc4a62010-06-08 11:58:53 -0700556 // XXX: query camera for the stride and slice height
557 // when the capability becomes available.
James Dong653252b2010-06-03 11:48:31 -0700558 mMeta = new MetaData;
James Dong54ff19a2010-10-08 11:59:32 -0700559 mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
560 mMeta->setInt32(kKeyColorFormat, mColorFormat);
561 mMeta->setInt32(kKeyWidth, mVideoSize.width);
562 mMeta->setInt32(kKeyHeight, mVideoSize.height);
563 mMeta->setInt32(kKeyStride, mVideoSize.width);
564 mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
James Dong393410a2010-11-10 20:43:53 -0800565 mMeta->setInt32(kKeyFrameRate, mVideoFrameRate);
James Dong54ff19a2010-10-08 11:59:32 -0700566 return OK;
Andreas Huber20111aa2009-07-14 16:56:47 -0700567}
568
569CameraSource::~CameraSource() {
570 if (mStarted) {
James Dongb44c9d22012-02-02 18:04:02 -0800571 reset();
James Dongae4c1ac2011-07-08 17:59:29 -0700572 } else if (mInitCheck == OK) {
573 // Camera is initialized but because start() is never called,
574 // the lock on Camera is never released(). This makes sure
575 // Camera's lock is released in this case.
576 releaseCamera();
Andreas Huber20111aa2009-07-14 16:56:47 -0700577 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700578}
579
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700580void CameraSource::startCameraRecording() {
Steve Block3856b092011-10-20 11:56:00 +0100581 ALOGV("startCameraRecording");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800582 // Reset the identity to the current thread because media server owns the
583 // camera and recording is started by the applications. The applications
584 // will connect to the camera in ICameraRecordingProxy::startRecording.
585 int64_t token = IPCThreadState::self()->clearCallingIdentity();
James Dong983cf232012-08-01 16:39:55 -0700586 if (mNumInputBuffers > 0) {
587 status_t err = mCamera->sendCommand(
588 CAMERA_CMD_SET_VIDEO_BUFFER_COUNT, mNumInputBuffers, 0);
589
590 // This could happen for CameraHAL1 clients; thus the failure is
591 // not a fatal error
592 if (err != OK) {
593 ALOGW("Failed to set video buffer count to %d due to %d",
594 mNumInputBuffers, err);
595 }
596 }
597
James Dong3bd30202011-07-19 20:24:22 -0700598 if (mCameraFlags & FLAGS_HOT_CAMERA) {
599 mCamera->unlock();
600 mCamera.clear();
James Dongf1d5aa12012-02-06 23:46:37 -0800601 CHECK_EQ((status_t)OK,
602 mCameraRecordingProxy->startRecording(new ProxyListener(this)));
James Dong3bd30202011-07-19 20:24:22 -0700603 } else {
604 mCamera->setListener(new CameraSourceListener(this));
605 mCamera->startRecording();
606 CHECK(mCamera->recordingEnabled());
607 }
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800608 IPCThreadState::self()->restoreCallingIdentity(token);
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700609}
610
James Dongf60cafe2010-06-19 09:04:18 -0700611status_t CameraSource::start(MetaData *meta) {
Steve Block3856b092011-10-20 11:56:00 +0100612 ALOGV("start");
Andreas Huber0c891992009-08-26 14:48:20 -0700613 CHECK(!mStarted);
James Dong54ff19a2010-10-08 11:59:32 -0700614 if (mInitCheck != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000615 ALOGE("CameraSource is not initialized yet");
James Dong54ff19a2010-10-08 11:59:32 -0700616 return mInitCheck;
617 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700618
James Dong365a9632010-06-04 13:59:27 -0700619 char value[PROPERTY_VALUE_MAX];
620 if (property_get("media.stagefright.record-stats", value, NULL)
621 && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
622 mCollectStats = true;
623 }
James Dong9d7f58a2010-06-09 15:57:48 -0700624
James Dongf60cafe2010-06-19 09:04:18 -0700625 mStartTimeUs = 0;
James Dong983cf232012-08-01 16:39:55 -0700626 mNumInputBuffers = 0;
627 if (meta) {
628 int64_t startTimeUs;
629 if (meta->findInt64(kKeyTime, &startTimeUs)) {
630 mStartTimeUs = startTimeUs;
631 }
632
633 int32_t nBuffers;
634 if (meta->findInt32(kKeyNumBuffers, &nBuffers)) {
635 CHECK_GT(nBuffers, 0);
636 mNumInputBuffers = nBuffers;
637 }
James Dongf60cafe2010-06-19 09:04:18 -0700638 }
639
James Dongc42478e2010-11-15 10:38:37 -0800640 startCameraRecording();
Andreas Huber20111aa2009-07-14 16:56:47 -0700641
642 mStarted = true;
Andreas Huber20111aa2009-07-14 16:56:47 -0700643 return OK;
644}
645
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700646void CameraSource::stopCameraRecording() {
Steve Block3856b092011-10-20 11:56:00 +0100647 ALOGV("stopCameraRecording");
James Dong3bd30202011-07-19 20:24:22 -0700648 if (mCameraFlags & FLAGS_HOT_CAMERA) {
649 mCameraRecordingProxy->stopRecording();
650 } else {
651 mCamera->setListener(NULL);
652 mCamera->stopRecording();
653 }
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700654}
655
James Dongea7b4852010-12-05 14:25:34 -0800656void CameraSource::releaseCamera() {
Steve Block3856b092011-10-20 11:56:00 +0100657 ALOGV("releaseCamera");
Wu-cheng Li95068be2011-06-29 15:17:11 +0800658 if (mCamera != 0) {
James Dongae4c1ac2011-07-08 17:59:29 -0700659 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Wu-cheng Li95068be2011-06-29 15:17:11 +0800660 if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
Steve Block3856b092011-10-20 11:56:00 +0100661 ALOGV("Camera was cold when we started, stopping preview");
Wu-cheng Li95068be2011-06-29 15:17:11 +0800662 mCamera->stopPreview();
663 mCamera->disconnect();
Wu-cheng Li95068be2011-06-29 15:17:11 +0800664 }
James Dong3bd30202011-07-19 20:24:22 -0700665 mCamera->unlock();
Wu-cheng Li95068be2011-06-29 15:17:11 +0800666 mCamera.clear();
James Dong3bd30202011-07-19 20:24:22 -0700667 mCamera = 0;
James Dongae4c1ac2011-07-08 17:59:29 -0700668 IPCThreadState::self()->restoreCallingIdentity(token);
James Dongea7b4852010-12-05 14:25:34 -0800669 }
Wu-cheng Li95068be2011-06-29 15:17:11 +0800670 if (mCameraRecordingProxy != 0) {
671 mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
672 mCameraRecordingProxy.clear();
673 }
James Dongea7b4852010-12-05 14:25:34 -0800674 mCameraFlags = 0;
675}
676
James Dongb44c9d22012-02-02 18:04:02 -0800677status_t CameraSource::reset() {
678 ALOGD("reset: E");
James Dongc32cd792010-04-26 17:48:26 -0700679 Mutex::Autolock autoLock(mLock);
Andreas Huber20111aa2009-07-14 16:56:47 -0700680 mStarted = false;
James Dongc32cd792010-04-26 17:48:26 -0700681 mFrameAvailableCondition.signal();
James Dong365a9632010-06-04 13:59:27 -0700682
James Dong91974412011-08-24 19:50:36 -0700683 int64_t token;
684 bool isTokenValid = false;
685 if (mCamera != 0) {
686 token = IPCThreadState::self()->clearCallingIdentity();
687 isTokenValid = true;
688 }
James Dongc32cd792010-04-26 17:48:26 -0700689 releaseQueuedFrames();
James Dong7278cf32010-05-27 16:05:58 -0700690 while (!mFramesBeingEncoded.empty()) {
James Dong41152ef2010-12-20 21:29:12 -0800691 if (NO_ERROR !=
James Donge8e5f862011-11-20 09:45:44 -0800692 mFrameCompleteCondition.waitRelative(mLock,
693 mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000694 ALOGW("Timed out waiting for outstanding frames being encoded: %d",
James Dong365a9632010-06-04 13:59:27 -0700695 mFramesBeingEncoded.size());
James Dong41152ef2010-12-20 21:29:12 -0800696 }
James Dong7278cf32010-05-27 16:05:58 -0700697 }
James Dongd69c7f62010-12-09 11:24:22 -0800698 stopCameraRecording();
James Dongea7b4852010-12-05 14:25:34 -0800699 releaseCamera();
James Dong91974412011-08-24 19:50:36 -0700700 if (isTokenValid) {
701 IPCThreadState::self()->restoreCallingIdentity(token);
702 }
James Dong7278cf32010-05-27 16:05:58 -0700703
James Dong365a9632010-06-04 13:59:27 -0700704 if (mCollectStats) {
Steve Blockdf64d152012-01-04 20:05:49 +0000705 ALOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
James Dong365a9632010-06-04 13:59:27 -0700706 mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
707 mLastFrameTimestampUs - mFirstFrameTimeUs);
708 }
James Dong13aec892010-04-21 16:14:15 -0700709
James Dongba290022010-12-09 15:04:33 -0800710 if (mNumGlitches > 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000711 ALOGW("%d long delays between neighboring video frames", mNumGlitches);
James Dongba290022010-12-09 15:04:33 -0800712 }
713
James Dong13aec892010-04-21 16:14:15 -0700714 CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
James Dongb44c9d22012-02-02 18:04:02 -0800715 ALOGD("reset: X");
Andreas Huber20111aa2009-07-14 16:56:47 -0700716 return OK;
717}
718
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700719void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
Steve Block3856b092011-10-20 11:56:00 +0100720 ALOGV("releaseRecordingFrame");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800721 if (mCameraRecordingProxy != NULL) {
722 mCameraRecordingProxy->releaseRecordingFrame(frame);
James Dong334d0972011-08-05 17:19:29 -0700723 } else if (mCamera != NULL) {
James Dong3bd30202011-07-19 20:24:22 -0700724 int64_t token = IPCThreadState::self()->clearCallingIdentity();
725 mCamera->releaseRecordingFrame(frame);
726 IPCThreadState::self()->restoreCallingIdentity(token);
James Dongd69c7f62010-12-09 11:24:22 -0800727 }
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700728}
729
James Dongc32cd792010-04-26 17:48:26 -0700730void CameraSource::releaseQueuedFrames() {
731 List<sp<IMemory> >::iterator it;
James Dong7278cf32010-05-27 16:05:58 -0700732 while (!mFramesReceived.empty()) {
733 it = mFramesReceived.begin();
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700734 releaseRecordingFrame(*it);
James Dong7278cf32010-05-27 16:05:58 -0700735 mFramesReceived.erase(it);
James Dong13aec892010-04-21 16:14:15 -0700736 ++mNumFramesDropped;
James Dongc32cd792010-04-26 17:48:26 -0700737 }
738}
739
Andreas Huber20111aa2009-07-14 16:56:47 -0700740sp<MetaData> CameraSource::getFormat() {
James Dong653252b2010-06-03 11:48:31 -0700741 return mMeta;
Andreas Huber20111aa2009-07-14 16:56:47 -0700742}
743
James Dongf60cafe2010-06-19 09:04:18 -0700744void CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700745 releaseRecordingFrame(frame);
James Dongf60cafe2010-06-19 09:04:18 -0700746}
747
James Dong7278cf32010-05-27 16:05:58 -0700748void CameraSource::signalBufferReturned(MediaBuffer *buffer) {
Steve Block3856b092011-10-20 11:56:00 +0100749 ALOGV("signalBufferReturned: %p", buffer->data());
Andreas Huber56223b92010-08-11 12:34:32 -0700750 Mutex::Autolock autoLock(mLock);
James Dong7278cf32010-05-27 16:05:58 -0700751 for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
752 it != mFramesBeingEncoded.end(); ++it) {
753 if ((*it)->pointer() == buffer->data()) {
James Dongf60cafe2010-06-19 09:04:18 -0700754 releaseOneRecordingFrame((*it));
James Dong7278cf32010-05-27 16:05:58 -0700755 mFramesBeingEncoded.erase(it);
756 ++mNumFramesEncoded;
757 buffer->setObserver(0);
758 buffer->release();
759 mFrameCompleteCondition.signal();
760 return;
761 }
762 }
James Dongf1d5aa12012-02-06 23:46:37 -0800763 CHECK(!"signalBufferReturned: bogus buffer");
James Dong7278cf32010-05-27 16:05:58 -0700764}
765
Andreas Huber20111aa2009-07-14 16:56:47 -0700766status_t CameraSource::read(
767 MediaBuffer **buffer, const ReadOptions *options) {
Steve Block3856b092011-10-20 11:56:00 +0100768 ALOGV("read");
Andreas Huber20111aa2009-07-14 16:56:47 -0700769
770 *buffer = NULL;
771
772 int64_t seekTimeUs;
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700773 ReadOptions::SeekMode mode;
774 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700775 return ERROR_UNSUPPORTED;
776 }
777
778 sp<IMemory> frame;
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700779 int64_t frameTime;
Andreas Huber20111aa2009-07-14 16:56:47 -0700780
781 {
782 Mutex::Autolock autoLock(mLock);
James Dong79e23b42010-12-11 10:43:41 -0800783 while (mStarted && mFramesReceived.empty()) {
James Dong41152ef2010-12-20 21:29:12 -0800784 if (NO_ERROR !=
James Donge8e5f862011-11-20 09:45:44 -0800785 mFrameAvailableCondition.waitRelative(mLock,
786 mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
James Dong3bd30202011-07-19 20:24:22 -0700787 if (mCameraRecordingProxy != 0 &&
788 !mCameraRecordingProxy->asBinder()->isBinderAlive()) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000789 ALOGW("camera recording proxy is gone");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800790 return ERROR_END_OF_STREAM;
791 }
Steve Block5ff1dd52012-01-05 23:22:43 +0000792 ALOGW("Timed out waiting for incoming camera video frames: %lld us",
James Dong41152ef2010-12-20 21:29:12 -0800793 mLastFrameTimestampUs);
794 }
James Dong542db5d2010-07-21 14:51:35 -0700795 }
James Dong79e23b42010-12-11 10:43:41 -0800796 if (!mStarted) {
797 return OK;
798 }
799 frame = *mFramesReceived.begin();
800 mFramesReceived.erase(mFramesReceived.begin());
801
802 frameTime = *mFrameTimes.begin();
803 mFrameTimes.erase(mFrameTimes.begin());
804 mFramesBeingEncoded.push_back(frame);
805 *buffer = new MediaBuffer(frame->pointer(), frame->size());
806 (*buffer)->setObserver(this);
807 (*buffer)->add_ref();
808 (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
Andreas Huber20111aa2009-07-14 16:56:47 -0700809 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700810 return OK;
811}
812
James Dongc32cd792010-04-26 17:48:26 -0700813void CameraSource::dataCallbackTimestamp(int64_t timestampUs,
814 int32_t msgType, const sp<IMemory> &data) {
Steve Block3856b092011-10-20 11:56:00 +0100815 ALOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
Andreas Huber20111aa2009-07-14 16:56:47 -0700816 Mutex::Autolock autoLock(mLock);
James Donga4726132011-02-16 12:28:26 -0800817 if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
Steve Block3856b092011-10-20 11:56:00 +0100818 ALOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
James Dongf60cafe2010-06-19 09:04:18 -0700819 releaseOneRecordingFrame(data);
James Dongc32cd792010-04-26 17:48:26 -0700820 return;
821 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700822
James Dong98cfde02011-06-03 17:21:16 -0700823 if (mNumFramesReceived > 0) {
824 CHECK(timestampUs > mLastFrameTimestampUs);
825 if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
826 ++mNumGlitches;
James Dongf60cafe2010-06-19 09:04:18 -0700827 }
James Dongf60cafe2010-06-19 09:04:18 -0700828 }
829
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700830 // May need to skip frame or modify timestamp. Currently implemented
831 // by the subclass CameraSourceTimeLapse.
James Dong79e23b42010-12-11 10:43:41 -0800832 if (skipCurrentFrame(timestampUs)) {
Nipun Kwatra65e7e6f2010-07-12 09:17:14 -0700833 releaseOneRecordingFrame(data);
834 return;
Nipun Kwatrafc20aab2010-06-30 18:51:31 -0700835 }
836
James Dong365a9632010-06-04 13:59:27 -0700837 mLastFrameTimestampUs = timestampUs;
James Dong13aec892010-04-21 16:14:15 -0700838 if (mNumFramesReceived == 0) {
James Dongc32cd792010-04-26 17:48:26 -0700839 mFirstFrameTimeUs = timestampUs;
James Dongf60cafe2010-06-19 09:04:18 -0700840 // Initial delay
841 if (mStartTimeUs > 0) {
842 if (timestampUs < mStartTimeUs) {
843 // Frame was captured before recording was started
844 // Drop it without updating the statistical data.
845 releaseOneRecordingFrame(data);
846 return;
847 }
848 mStartTimeUs = timestampUs - mStartTimeUs;
849 }
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700850 }
James Dong13aec892010-04-21 16:14:15 -0700851 ++mNumFramesReceived;
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700852
James Dong98cfde02011-06-03 17:21:16 -0700853 CHECK(data != NULL && data->size() > 0);
James Dong7278cf32010-05-27 16:05:58 -0700854 mFramesReceived.push_back(data);
James Dongf60cafe2010-06-19 09:04:18 -0700855 int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
856 mFrameTimes.push_back(timeUs);
Steve Block3856b092011-10-20 11:56:00 +0100857 ALOGV("initial delay: %lld, current time stamp: %lld",
James Dongf60cafe2010-06-19 09:04:18 -0700858 mStartTimeUs, timeUs);
Andreas Huber20111aa2009-07-14 16:56:47 -0700859 mFrameAvailableCondition.signal();
860}
861
James Dong5c952312010-10-18 21:42:27 -0700862bool CameraSource::isMetaDataStoredInVideoBuffers() const {
Steve Block3856b092011-10-20 11:56:00 +0100863 ALOGV("isMetaDataStoredInVideoBuffers");
James Dong5c952312010-10-18 21:42:27 -0700864 return mIsMetaDataStoredInVideoBuffers;
865}
866
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800867CameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
868 mSource = source;
869}
870
871void CameraSource::ProxyListener::dataCallbackTimestamp(
872 nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
873 mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
874}
875
876void CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
Steve Blockdf64d152012-01-04 20:05:49 +0000877 ALOGI("Camera recording proxy died");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800878}
879
Andreas Huber20111aa2009-07-14 16:56:47 -0700880} // namespace android