120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
18a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
19c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong//#define LOG_NDEBUG 0
20c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#define LOG_TAG "CameraSource"
21c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <utils/Log.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <OMX_Component.h>
249d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong#include <binder/IPCThreadState.h>
25f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/CameraSource.h>
27be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <media/stagefright/MediaDefs.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaErrors.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
303cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/Camera.h>
313cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/CameraParameters.h>
32df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian#include <gui/Surface.h>
33be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <utils/String8.h>
34365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#if LOG_NDEBUG
3784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED_UNLESS_VERBOSE(x) (void)(x)
3884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#else
3984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED_UNLESS_VERBOSE(x)
4084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#endif
4184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dongstatic const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL;
45e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong
46be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberstruct CameraSourceListener : public CameraListener {
47be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const sp<CameraSource> &source);
48be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
49be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
5057c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li    virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr,
5157c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li                          camera_frame_metadata_t *metadata);
52be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
53be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void postDataTimestamp(
54be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber            nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
55be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
56be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberprotected:
57be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual ~CameraSourceListener();
58be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
60be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    wp<CameraSource> mSource;
61be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
62be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const CameraSourceListener &);
63be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener &operator=(const CameraSourceListener &);
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
67be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    : mSource(source) {
68be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::~CameraSourceListener() {
71be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
7484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    UNUSED_UNLESS_VERBOSE(msgType);
7584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    UNUSED_UNLESS_VERBOSE(ext1);
7684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    UNUSED_UNLESS_VERBOSE(ext2);
773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
78be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8057c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Livoid CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
8184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber                                    camera_frame_metadata_t * /* metadata */) {
82a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("postData(%d, ptr:%p, size:%zu)",
83be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber         msgType, dataPtr->pointer(), dataPtr->size());
8465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
8565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<CameraSource> source = mSource.promote();
8665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (source.get() != NULL) {
8765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        source->dataCallback(msgType, dataPtr);
8865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
89be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
90be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
91be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postDataTimestamp(
92be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
93c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
94c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    sp<CameraSource> source = mSource.promote();
95c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (source.get() != NULL) {
96c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
97c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
98be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
100653252be963c07c99109d20f942d1f30c52a9360James Dongstatic int32_t getColorFormat(const char* colorFormat) {
101e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
102e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong       return OMX_COLOR_FormatYUV420Planar;
103e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    }
104e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong
105653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
106653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_FormatYUV422SemiPlanar;
107653252be963c07c99109d20f942d1f30c52a9360James Dong    }
108653252be963c07c99109d20f942d1f30c52a9360James Dong
109653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
110653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYUV420SemiPlanar;
111653252be963c07c99109d20f942d1f30c52a9360James Dong    }
112653252be963c07c99109d20f942d1f30c52a9360James Dong
113653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
114653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYCbYCr;
115653252be963c07c99109d20f942d1f30c52a9360James Dong    }
116653252be963c07c99109d20f942d1f30c52a9360James Dong
117653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
118653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_Format16bitRGB565;
119653252be963c07c99109d20f942d1f30c52a9360James Dong    }
120653252be963c07c99109d20f942d1f30c52a9360James Dong
1211374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket    if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
1221374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket       return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
1231374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket    }
1241374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket
125bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE)) {
126bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala        return OMX_COLOR_FormatAndroidOpaque;
127bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala    }
128bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala
12929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    ALOGE("Uknown color format (%s), please add it to "
130a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong         "CameraSource::getColorFormat", colorFormat);
131a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong
132f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong    CHECK(!"Unknown color format");
133dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn    return -1;
134653252be963c07c99109d20f942d1f30c52a9360James Dong}
135653252be963c07c99109d20f942d1f30c52a9360James Dong
136ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville TalvalaCameraSource *CameraSource::Create(const String16 &clientName) {
13754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size size;
13854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.width = -1;
13954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.height = -1;
14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    sp<ICamera> camera;
142ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    return new CameraSource(camera, NULL, 0, clientName, -1,
143ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala            size, -1, NULL, false);
14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14630ab66297501757d745b9ae10da61adcd891f497Andreas Huber// static
14754ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource *CameraSource::CreateFromCamera(
14854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
1494ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
15054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
151ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    const String16& clientName,
152ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    uid_t clientUid,
15354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
15454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
15599617adda9bc46c43f511f0940bc735c73de61deMathias Agopian    const sp<IGraphicBufferProducer>& surface,
1565c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers) {
15754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1584ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    CameraSource *source = new CameraSource(camera, proxy, cameraId,
159ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala            clientName, clientUid, videoSize, frameRate, surface,
160ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala            storeMetaDataInVideoBuffers);
16154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return source;
16230ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
16330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
16454ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource::CameraSource(
16554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
1664ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
16754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
168ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    const String16& clientName,
169ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    uid_t clientUid,
17054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
17154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
17299617adda9bc46c43f511f0940bc735c73de61deMathias Agopian    const sp<IGraphicBufferProducer>& surface,
1735c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers)
17454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    : mCameraFlags(0),
175983cf231ab2d176a14595cdae46ff1b0c239af47James Dong      mNumInputBuffers(0),
17654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mVideoFrameRate(-1),
17754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mCamera(0),
17854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mSurface(surface),
17913aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesReceived(0),
18065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mLastFrameTimestampUs(0),
18165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mStarted(false),
18213aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesEncoded(0),
183e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong      mTimeBetweenFrameCaptureUs(0),
1847757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong      mFirstFrameTimeUs(0),
18513aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesDropped(0),
186f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mNumGlitches(0),
187f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mGlitchDurationThresholdUs(200000),
18865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mCollectStats(false) {
18954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width  = -1;
19054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = -1;
19154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1924ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mInitCheck = init(camera, proxy, cameraId,
193ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala                    clientName, clientUid,
1945c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate,
1955c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
19695068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mInitCheck != OK) releaseCamera();
19754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
19854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
19954ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::initCheck() const {
20054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return mInitCheck;
20154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
20254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
20354ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraAvailable(
2044ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
205ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    int32_t cameraId, const String16& clientName, uid_t clientUid) {
20654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
20754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (camera == 0) {
208ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        mCamera = Camera::connect(cameraId, clientName, clientUid);
2094ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
21054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags &= ~FLAGS_HOT_CAMERA;
21154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {
2124ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // We get the proxy from Camera, not ICamera. We need to get the proxy
2134ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // to the remote Camera owned by the application. Here mCamera is a
2144ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // local Camera object created by us. We cannot use the proxy from
2154ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // mCamera here.
21654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::create(camera);
2174ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
2184ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy = proxy;
21954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags |= FLAGS_HOT_CAMERA;
2203bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mDeathNotifier = new DeathNotifier();
2213bd3020c00ec8264ac1fe3870800f326487f9221James Dong        // isBinderAlive needs linkToDeath to work.
2223bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
22354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
22454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
2254ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCamera->lock();
2264ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
22754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
22854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
22954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
23054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
23154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
23254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check to see whether the requested video width and height is one
23354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * of the supported sizes.
23454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the video frame width in pixels
23554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the video frame height in pixels
23654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param suppportedSizes the vector of sizes that we check against
23754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return true if the dimension (width and height) is supported.
23854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
23954ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic bool isVideoSizeSupported(
24054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t width, int32_t height,
24154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const Vector<Size>& supportedSizes) {
24254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
2433856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("isVideoSizeSupported");
24454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    for (size_t i = 0; i < supportedSizes.size(); ++i) {
24554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (width  == supportedSizes[i].width &&
24654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            height == supportedSizes[i].height) {
24754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return true;
24854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
24954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
25054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return false;
25154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
25254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
25354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
25454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the preview and video output is separate, we only set the
25554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * the video size, and applications should set the preview size
25654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * to some proper value, and the recording framework will not
25754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * change the preview size; otherwise, if the video and preview
25854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * output is the same, we need to set the preview to be the same
25954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * as the requested video size.
26054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
26154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
26254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
26354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Query the camera to retrieve the supported video frame sizes
26454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * and also to see whether CameraParameters::setVideoSize()
26554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is supported or not.
26654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
26754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @@param isSetVideoSizeSupported retunrs whether method
26854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      CameraParameters::setVideoSize() is supported or not.
26954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param sizes returns the vector of Size objects for the
27054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      supported video frame sizes advertised by the camera.
27154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
27254ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic void getSupportedVideoSizes(
27354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const CameraParameters& params,
27454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool *isSetVideoSizeSupported,
27554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size>& sizes) {
27654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
27754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    *isSetVideoSizeSupported = true;
27854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    params.getSupportedVideoSizes(sizes);
27954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (sizes.size() == 0) {
280b8a805261bf0282e992d3608035e47d05a898710Steve Block        ALOGD("Camera does not support setVideoSize()");
28154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params.getSupportedPreviewSizes(sizes);
28254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        *isSetVideoSizeSupported = false;
28354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
28454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
28554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
28654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
28754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the camera has the supported color format
28854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
28954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
29054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
29154ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraColorFormatSupported(
29254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params) {
29354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mColorFormat = getColorFormat(params.get(
29454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            CameraParameters::KEY_VIDEO_FRAME_FORMAT));
29554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mColorFormat == -1) {
29654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
29754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
29854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
29954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
30054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
30154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
30254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Configure the camera to use the requested video size
30354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * (width and height) and/or frame rate. If both width and
30454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * height are -1, configuration on the video size is skipped.
30554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * if frameRate is -1, configuration on the frame rate
30654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is skipped. Skipping the configuration allows one to
30754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * use the current camera setting without the need to
30854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * actually know the specific values (see Create() method).
30954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
31054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params the CameraParameters to be configured
31154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the target video frame width in pixels
31254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the target video frame height in pixels
31354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
31454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
31554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
31654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::configureCamera(
31754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        CameraParameters* params,
31854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height,
31954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
3203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("configureCamera");
32154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size> sizes;
32254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isSetVideoSizeSupportedByCamera = true;
32354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
32454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isCameraParamChanged = false;
32554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
32654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (!isVideoSizeSupported(width, height, sizes)) {
32729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Video dimension (%dx%d) is unsupported", width, height);
32854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return BAD_VALUE;
32954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
33054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (isSetVideoSizeSupportedByCamera) {
33154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setVideoSize(width, height);
33254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        } else {
33354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setPreviewSize(width, height);
33454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
33554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
33654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else if ((width == -1 && height != -1) ||
33754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong               (width != -1 && height == -1)) {
33854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // If one and only one of the width and height is -1
33954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // we reject such a request.
34029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Requested video size (%dx%d) is not supported", width, height);
34154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
34254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // width == -1 && height == -1
34354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
34454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current width and height value setting from the camera.
34554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
34654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
34754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1) {
348635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(frameRate > 0 && frameRate <= 120);
349635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        const char* supportedFrameRates =
350635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
351635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(supportedFrameRates != NULL);
3523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Supported frame rates: %s", supportedFrameRates);
353635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        char buf[4];
354635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        snprintf(buf, 4, "%d", frameRate);
355635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        if (strstr(supportedFrameRates, buf) == NULL) {
35629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Requested frame rate (%d) is not supported: %s",
357635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                frameRate, supportedFrameRates);
358635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong            return BAD_VALUE;
359635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        }
360635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong
361635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        // The frame rate is supported, set the camera to the requested value.
36254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params->setPreviewFrameRate(frameRate);
36354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
36454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // frameRate == -1
36554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
36654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current frame rate value setting from the camera
36754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
36854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
36954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (isCameraParamChanged) {
37054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Either frame rate or frame size needs to be changed.
37154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        String8 s = params->flatten();
37254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (OK != mCamera->setParameters(s)) {
37329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Could not change settings."
37454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                 " Someone else is using camera %p?", mCamera.get());
37554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return -EBUSY;
37654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
37754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
37854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
37954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
38054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
38154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
38254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the requested video frame size
38354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * has been successfully configured or not. If both width and height
38454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * are -1, check on the current width and height value setting
38554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is performed.
38654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
38754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
38854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame width in pixels to check against
38954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame height in pixels to check against
39054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error
39154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
39254ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkVideoSize(
39354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
39454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height) {
39554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
3963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("checkVideoSize");
397f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // The actual video size is the same as the preview size
398f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // if the camera hal does not support separate video and
399f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // preview output. In this case, we retrieve the video
400f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // size from preview.
40154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameWidthActual = -1;
40254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameHeightActual = -1;
403f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    Vector<Size> sizes;
404f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    params.getSupportedVideoSizes(sizes);
405f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    if (sizes.size() == 0) {
406f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size is the same as preview size
407f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getPreviewSize(&frameWidthActual, &frameHeightActual);
408f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    } else {
409f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size may not be the same as preview
410f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getVideoSize(&frameWidthActual, &frameHeightActual);
411f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    }
41254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameWidthActual < 0 || frameHeightActual < 0) {
41329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Failed to retrieve video frame size (%dx%d)",
41454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                frameWidthActual, frameHeightActual);
41554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
41654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
41754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
41854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame size against the target/requested
41954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame size.
42054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
42154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (frameWidthActual != width || frameHeightActual != height) {
42229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Failed to set video frame size to %dx%d. "
42354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    "The actual video size is %dx%d ", width, height,
42454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameWidthActual, frameHeightActual);
42554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return UNKNOWN_ERROR;
42654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
42754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
42854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
42954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
43054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width = frameWidthActual;
43154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = frameHeightActual;
43254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
43354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
43454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
43554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
43654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check the requested frame rate has been successfully configured or not.
43754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the target frameRate is -1, check on the current frame rate value
43854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * setting is performed.
43954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
44054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
44154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame rate to check against
44254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
44354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
44454ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkFrameRate(
44554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
44654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
44754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
4483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("checkFrameRate");
44954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRateActual = params.getPreviewFrameRate();
45054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRateActual < 0) {
45129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
45254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
45354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
45454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
45554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame rate against the target/requested
45654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame rate.
45754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
45829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Failed to set preview frame rate to %d fps. The actual "
45954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                "frame rate is %d", frameRate, frameRateActual);
46054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
46154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
46254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
46354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
46454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoFrameRate = frameRateActual;
46554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
46654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
46754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
46854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
46954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Initialize the CameraSource to so that it becomes
47054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * ready for providing the video input streams as requested.
47154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param camera the camera object used for the video source
47254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param cameraId if camera == 0, use camera with this id
47354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      as the video source
47454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param videoSize the target video frame size. If both
47554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and height in videoSize is -1, use the current
47654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and heigth settings by the camera
47754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
47854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      if it is -1, use the current camera frame rate setting.
4795c9523154d106b555db6c41f85ab205a4f189b02James Dong * @param storeMetaDataInVideoBuffers request to store meta
4805c9523154d106b555db6c41f85ab205a4f189b02James Dong *      data or real YUV data in video buffers. Request to
4815c9523154d106b555db6c41f85ab205a4f189b02James Dong *      store meta data in video buffers may not be honored
4825c9523154d106b555db6c41f85ab205a4f189b02James Dong *      if the source does not support this feature.
4835c9523154d106b555db6c41f85ab205a4f189b02James Dong *
48454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
48554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
48654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::init(
48754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const sp<ICamera>& camera,
4884ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        const sp<ICameraRecordingProxy>& proxy,
48954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t cameraId,
490ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        const String16& clientName,
491ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        uid_t clientUid,
49254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        Size videoSize,
4935c9523154d106b555db6c41f85ab205a4f189b02James Dong        int32_t frameRate,
4945c9523154d106b555db6c41f85ab205a4f189b02James Dong        bool storeMetaDataInVideoBuffers) {
49554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
4963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("init");
49754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    status_t err = OK;
498ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
499ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    err = initWithCameraAccess(camera, proxy, cameraId, clientName, clientUid,
500ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               videoSize, frameRate,
501ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               storeMetaDataInVideoBuffers);
502ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
503ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    return err;
504ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong}
505ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong
506ae4c1ac6401185539c03ce0819e174fd1b04b136James Dongstatus_t CameraSource::initWithCameraAccess(
507ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        const sp<ICamera>& camera,
508ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        const sp<ICameraRecordingProxy>& proxy,
509ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t cameraId,
510ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        const String16& clientName,
511ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        uid_t clientUid,
512ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        Size videoSize,
513ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t frameRate,
514ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        bool storeMetaDataInVideoBuffers) {
5153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initWithCameraAccess");
516ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    status_t err = OK;
5179d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
518ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    if ((err = isCameraAvailable(camera, proxy, cameraId,
519ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala            clientName, clientUid)) != OK) {
52029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Camera connection could not be established.");
52154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
52254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
52354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters params(mCamera->getParameters());
52454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = isCameraColorFormatSupported(params)) != OK) {
52554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
52654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
527be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
52854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Set the camera to use the requested video frame size
52954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // and/or frame rate.
53054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = configureCamera(&params,
53154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    videoSize.width, videoSize.height,
53254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameRate))) {
53354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
53454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
535653252be963c07c99109d20f942d1f30c52a9360James Dong
53654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check on video frame size and frame rate.
53754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters newCameraParams(mCamera->getParameters());
53854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkVideoSize(newCameraParams,
53954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                videoSize.width, videoSize.height)) != OK) {
54054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
54154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
54254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
54354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
54454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
54554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
5468e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    // Set the preview display. Skip this if mSurface is null because
5478e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    // applications may already set a surface to the camera.
5488e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    if (mSurface != NULL) {
5498e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li        // This CHECK is good, since we just passed the lock/unlock
5508e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li        // check earlier by calling mCamera->setParameters().
5514b820b0e1fa069714b123fc35784541d0f94d267Eino-Ville Talvala        CHECK_EQ((status_t)OK, mCamera->setPreviewTarget(mSurface));
5528e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    }
5532b37ced30f89437c804c3945b901019b86d210aeJames Dong
554abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    // By default, do not store metadata in video buffers
5555c9523154d106b555db6c41f85ab205a4f189b02James Dong    mIsMetaDataStoredInVideoBuffers = false;
556abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    mCamera->storeMetaDataInBuffers(false);
557abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    if (storeMetaDataInVideoBuffers) {
558abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong        if (OK == mCamera->storeMetaDataInBuffers(true)) {
559abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong            mIsMetaDataStoredInVideoBuffers = true;
560abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong        }
5615c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
5625c9523154d106b555db6c41f85ab205a4f189b02James Dong
56354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
564f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (glitchDurationUs > mGlitchDurationThresholdUs) {
565f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mGlitchDurationThresholdUs = glitchDurationUs;
566f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
567f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
568ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // XXX: query camera for the stride and slice height
569ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // when the capability becomes available.
570653252be963c07c99109d20f942d1f30c52a9360James Dong    mMeta = new MetaData;
57154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setCString(kKeyMIMEType,  MEDIA_MIMETYPE_VIDEO_RAW);
57254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyColorFormat, mColorFormat);
57354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyWidth,       mVideoSize.width);
57454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyHeight,      mVideoSize.height);
57554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyStride,      mVideoSize.width);
57654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
577393410a441b6d06daf286ed496470e9d6b2b6ca8James Dong    mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
57854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource::~CameraSource() {
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
583b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong        reset();
584ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    } else if (mInitCheck == OK) {
585ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera is initialized but because start() is never called,
586ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // the lock on Camera is never released(). This makes sure
587ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera's lock is released in this case.
588ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        releaseCamera();
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59226cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunkstatus_t CameraSource::startCameraRecording() {
5933856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startCameraRecording");
5944ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // Reset the identity to the current thread because media server owns the
5954ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // camera and recording is started by the applications. The applications
5964ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // will connect to the camera in ICameraRecordingProxy::startRecording.
5974ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    int64_t token = IPCThreadState::self()->clearCallingIdentity();
59826cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    status_t err;
599983cf231ab2d176a14595cdae46ff1b0c239af47James Dong    if (mNumInputBuffers > 0) {
60026cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        err = mCamera->sendCommand(
601983cf231ab2d176a14595cdae46ff1b0c239af47James Dong            CAMERA_CMD_SET_VIDEO_BUFFER_COUNT, mNumInputBuffers, 0);
602983cf231ab2d176a14595cdae46ff1b0c239af47James Dong
603983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        // This could happen for CameraHAL1 clients; thus the failure is
604983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        // not a fatal error
605983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        if (err != OK) {
606983cf231ab2d176a14595cdae46ff1b0c239af47James Dong            ALOGW("Failed to set video buffer count to %d due to %d",
607983cf231ab2d176a14595cdae46ff1b0c239af47James Dong                mNumInputBuffers, err);
608983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        }
609983cf231ab2d176a14595cdae46ff1b0c239af47James Dong    }
610983cf231ab2d176a14595cdae46ff1b0c239af47James Dong
61126cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    err = OK;
6123bd3020c00ec8264ac1fe3870800f326487f9221James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
6133bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->unlock();
6143bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera.clear();
61526cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        if ((err = mCameraRecordingProxy->startRecording(
61626cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk                new ProxyListener(this))) != OK) {
61726cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk            ALOGE("Failed to start recording, received error: %s (%d)",
61826cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk                    strerror(-err), err);
61926cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        }
6203bd3020c00ec8264ac1fe3870800f326487f9221James Dong    } else {
6213bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->setListener(new CameraSourceListener(this));
6223bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->startRecording();
62326cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        if (!mCamera->recordingEnabled()) {
62426cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk            err = -EINVAL;
62526cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk            ALOGE("Failed to start recording");
62626cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        }
6273bd3020c00ec8264ac1fe3870800f326487f9221James Dong    }
6284ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    IPCThreadState::self()->restoreCallingIdentity(token);
62926cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    return err;
63065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
63165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
632f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongstatus_t CameraSource::start(MetaData *meta) {
6333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("start");
6340c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mStarted);
63554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mInitCheck != OK) {
63629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("CameraSource is not initialized yet");
63754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return mInitCheck;
63854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
640365a963142093a1cd8efdcea76b5f65096a5b115James Dong    char value[PROPERTY_VALUE_MAX];
641365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
642365a963142093a1cd8efdcea76b5f65096a5b115James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
643365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mCollectStats = true;
644365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
6459d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
646f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
647983cf231ab2d176a14595cdae46ff1b0c239af47James Dong    mNumInputBuffers = 0;
648983cf231ab2d176a14595cdae46ff1b0c239af47James Dong    if (meta) {
649983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        int64_t startTimeUs;
650983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        if (meta->findInt64(kKeyTime, &startTimeUs)) {
651983cf231ab2d176a14595cdae46ff1b0c239af47James Dong            mStartTimeUs = startTimeUs;
652983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        }
653983cf231ab2d176a14595cdae46ff1b0c239af47James Dong
654983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        int32_t nBuffers;
655983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        if (meta->findInt32(kKeyNumBuffers, &nBuffers)) {
656983cf231ab2d176a14595cdae46ff1b0c239af47James Dong            CHECK_GT(nBuffers, 0);
657983cf231ab2d176a14595cdae46ff1b0c239af47James Dong            mNumInputBuffers = nBuffers;
658983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        }
659f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
660f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
66126cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    status_t err;
66226cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    if ((err = startCameraRecording()) == OK) {
66326cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        mStarted = true;
66426cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    }
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66626cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    return err;
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::stopCameraRecording() {
6703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("stopCameraRecording");
6713bd3020c00ec8264ac1fe3870800f326487f9221James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
6723bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCameraRecordingProxy->stopRecording();
6733bd3020c00ec8264ac1fe3870800f326487f9221James Dong    } else {
6743bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->setListener(NULL);
6753bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->stopRecording();
6763bd3020c00ec8264ac1fe3870800f326487f9221James Dong    }
67765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
67865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
679ea7b485595f8cec6a66668b5c54c8f297d843f77James Dongvoid CameraSource::releaseCamera() {
6803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("releaseCamera");
681121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    sp<Camera> camera;
682121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    bool coldCamera = false;
683121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    {
684121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        Mutex::Autolock autoLock(mLock);
685121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        // get a local ref and clear ref to mCamera now
686121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        camera = mCamera;
687121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mCamera.clear();
688121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        coldCamera = (mCameraFlags & FLAGS_HOT_CAMERA) == 0;
689121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    }
690121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
691121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    if (camera != 0) {
692ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
693121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (coldCamera) {
6943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("Camera was cold when we started, stopping preview");
695121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            camera->stopPreview();
696121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            camera->disconnect();
69795068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        }
698121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        camera->unlock();
699ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
70095068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    }
701121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
702121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    {
703121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        Mutex::Autolock autoLock(mLock);
704121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mCameraRecordingProxy != 0) {
705121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
706121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            mCameraRecordingProxy.clear();
707121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
708121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mCameraFlags = 0;
709ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    }
710ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong}
711ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong
712b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dongstatus_t CameraSource::reset() {
713b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong    ALOGD("reset: E");
714121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
715121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    {
716121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        Mutex::Autolock autoLock(mLock);
717121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mStarted = false;
718121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mFrameAvailableCondition.signal();
719121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
720121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        int64_t token;
721121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        bool isTokenValid = false;
722121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mCamera != 0) {
723121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            token = IPCThreadState::self()->clearCallingIdentity();
724121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            isTokenValid = true;
725121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
726121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        releaseQueuedFrames();
727121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        while (!mFramesBeingEncoded.empty()) {
728121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            if (NO_ERROR !=
729121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                mFrameCompleteCondition.waitRelative(mLock,
730121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                        mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
731121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                ALOGW("Timed out waiting for outstanding frames being encoded: %zu",
732121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                    mFramesBeingEncoded.size());
733121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            }
734121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
735121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        stopCameraRecording();
736121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (isTokenValid) {
737121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            IPCThreadState::self()->restoreCallingIdentity(token);
73841152efd144ccf70c380d5c9a32105c02a039f43James Dong        }
7397278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
740121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mCollectStats) {
741121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            ALOGI("Frames received/encoded/dropped: %d/%d/%d in %" PRId64 " us",
742121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                    mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
743121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                    mLastFrameTimestampUs - mFirstFrameTimeUs);
744121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
745121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
746121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mNumGlitches > 0) {
747121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            ALOGW("%d long delays between neighboring video frames", mNumGlitches);
748121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
74913aec890216948b0c364f8f92792129d0335f506James Dong
750121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
751ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    }
752ba29002c7aee13c068049037cd14bba6a244da6bJames Dong
753121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    releaseCamera();
754121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
755b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong    ALOGD("reset: X");
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
7603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("releaseRecordingFrame");
7614ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    if (mCameraRecordingProxy != NULL) {
7624ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy->releaseRecordingFrame(frame);
763334d097870eefeb45137b6df026f7db861d47663James Dong    } else if (mCamera != NULL) {
7643bd3020c00ec8264ac1fe3870800f326487f9221James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
7653bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->releaseRecordingFrame(frame);
7663bd3020c00ec8264ac1fe3870800f326487f9221James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
767d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    }
76865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
76965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
770c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::releaseQueuedFrames() {
771c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    List<sp<IMemory> >::iterator it;
7727278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesReceived.empty()) {
7737278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        it = mFramesReceived.begin();
77465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseRecordingFrame(*it);
7757278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        mFramesReceived.erase(it);
77613aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesDropped;
777c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
778c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong}
779c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> CameraSource::getFormat() {
781653252be963c07c99109d20f942d1f30c52a9360James Dong    return mMeta;
78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
784f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
78565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    releaseRecordingFrame(frame);
786f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong}
787f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
7887278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) {
7893856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("signalBufferReturned: %p", buffer->data());
79056223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber    Mutex::Autolock autoLock(mLock);
7917278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
7927278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong         it != mFramesBeingEncoded.end(); ++it) {
7937278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        if ((*it)->pointer() ==  buffer->data()) {
794f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            releaseOneRecordingFrame((*it));
7957278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFramesBeingEncoded.erase(it);
7967278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            ++mNumFramesEncoded;
7977278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->setObserver(0);
7987278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->release();
7997278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFrameCompleteCondition.signal();
8007278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            return;
8017278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        }
8027278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
803f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong    CHECK(!"signalBufferReturned: bogus buffer");
8047278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong}
8057278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::read(
80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
8083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("read");
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *buffer = NULL;
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
813abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
814abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_UNSUPPORTED;
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<IMemory> frame;
819be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    int64_t frameTime;
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    {
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Mutex::Autolock autoLock(mLock);
82379e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        while (mStarted && mFramesReceived.empty()) {
82441152efd144ccf70c380d5c9a32105c02a039f43James Dong            if (NO_ERROR !=
825e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong                mFrameAvailableCondition.waitRelative(mLock,
826e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong                    mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
8273bd3020c00ec8264ac1fe3870800f326487f9221James Dong                if (mCameraRecordingProxy != 0 &&
8283bd3020c00ec8264ac1fe3870800f326487f9221James Dong                    !mCameraRecordingProxy->asBinder()->isBinderAlive()) {
8295ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                    ALOGW("camera recording proxy is gone");
8304ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                    return ERROR_END_OF_STREAM;
8314ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                }
832a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGW("Timed out waiting for incoming camera video frames: %" PRId64 " us",
83341152efd144ccf70c380d5c9a32105c02a039f43James Dong                    mLastFrameTimestampUs);
83441152efd144ccf70c380d5c9a32105c02a039f43James Dong            }
83520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
83679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        if (!mStarted) {
83779e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong            return OK;
83879e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        }
83979e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frame = *mFramesReceived.begin();
84079e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesReceived.erase(mFramesReceived.begin());
84179e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong
84279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frameTime = *mFrameTimes.begin();
84379e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFrameTimes.erase(mFrameTimes.begin());
84479e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesBeingEncoded.push_back(frame);
84579e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        *buffer = new MediaBuffer(frame->pointer(), frame->size());
84679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->setObserver(this);
84779e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->add_ref();
84879e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
8497278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
853c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs,
854c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        int32_t msgType, const sp<IMemory> &data) {
855a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("dataCallbackTimestamp: timestamp %" PRId64 " us", timestampUs);
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
857a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
858a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Drop frame at %" PRId64 "/%" PRId64 " us", timestampUs, mStartTimeUs);
859f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        releaseOneRecordingFrame(data);
860c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        return;
861c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
86398cfde007490a5903b729a4718c0dada755ae8f8James Dong    if (mNumFramesReceived > 0) {
86498cfde007490a5903b729a4718c0dada755ae8f8James Dong        CHECK(timestampUs > mLastFrameTimestampUs);
86598cfde007490a5903b729a4718c0dada755ae8f8James Dong        if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
86698cfde007490a5903b729a4718c0dada755ae8f8James Dong            ++mNumGlitches;
867f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
868f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
869f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
87065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // May need to skip frame or modify timestamp. Currently implemented
87165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // by the subclass CameraSourceTimeLapse.
87279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong    if (skipCurrentFrame(timestampUs)) {
87365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseOneRecordingFrame(data);
87465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return;
875fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra    }
876fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra
877365a963142093a1cd8efdcea76b5f65096a5b115James Dong    mLastFrameTimestampUs = timestampUs;
87813aec890216948b0c364f8f92792129d0335f506James Dong    if (mNumFramesReceived == 0) {
879c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        mFirstFrameTimeUs = timestampUs;
880f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        // Initial delay
881f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        if (mStartTimeUs > 0) {
882f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            if (timestampUs < mStartTimeUs) {
883f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Frame was captured before recording was started
884f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Drop it without updating the statistical data.
885f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                releaseOneRecordingFrame(data);
886f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                return;
887f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            }
888f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimeUs = timestampUs - mStartTimeUs;
889f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
890be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    }
89113aec890216948b0c364f8f92792129d0335f506James Dong    ++mNumFramesReceived;
892be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
89398cfde007490a5903b729a4718c0dada755ae8f8James Dong    CHECK(data != NULL && data->size() > 0);
8947278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    mFramesReceived.push_back(data);
895f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
896f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mFrameTimes.push_back(timeUs);
897a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("initial delay: %" PRId64 ", current time stamp: %" PRId64,
898f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs, timeUs);
89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFrameAvailableCondition.signal();
90020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
90120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9025c9523154d106b555db6c41f85ab205a4f189b02James Dongbool CameraSource::isMetaDataStoredInVideoBuffers() const {
9033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("isMetaDataStoredInVideoBuffers");
9045c9523154d106b555db6c41f85ab205a4f189b02James Dong    return mIsMetaDataStoredInVideoBuffers;
9055c9523154d106b555db6c41f85ab205a4f189b02James Dong}
9065c9523154d106b555db6c41f85ab205a4f189b02James Dong
9074ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng LiCameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
9084ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource = source;
9094ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
9104ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
9114ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::ProxyListener::dataCallbackTimestamp(
9124ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
9134ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
9144ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
9154ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
9164ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
917df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Camera recording proxy died");
9184ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
9194ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
921