CameraSource.cpp revision 8fc3c670fff26cb21d1e16dbfcbc4410d7758574
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>
258cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen#include <binder/MemoryBase.h>
268cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen#include <binder/MemoryHeapBase.h>
278cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen#include <media/hardware/HardwareAPI.h>
28f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/CameraSource.h>
30be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <media/stagefright/MediaDefs.h>
3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaErrors.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
333cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/Camera.h>
343cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/CameraParameters.h>
35df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian#include <gui/Surface.h>
36be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <utils/String8.h>
37365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#if LOG_NDEBUG
4084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED_UNLESS_VERBOSE(x) (void)(x)
4184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#else
4284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED_UNLESS_VERBOSE(x)
4384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#endif
4484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dongstatic const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL;
48e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong
49be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberstruct CameraSourceListener : public CameraListener {
50be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const sp<CameraSource> &source);
51be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
52be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
5357c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li    virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr,
5457c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li                          camera_frame_metadata_t *metadata);
55be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
56be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void postDataTimestamp(
57be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber            nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
58be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
59be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberprotected:
60be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual ~CameraSourceListener();
61be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
63be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    wp<CameraSource> mSource;
64be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
65be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const CameraSourceListener &);
66be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener &operator=(const CameraSourceListener &);
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
70be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    : mSource(source) {
71be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::~CameraSourceListener() {
74be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
7784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    UNUSED_UNLESS_VERBOSE(msgType);
7884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    UNUSED_UNLESS_VERBOSE(ext1);
7984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    UNUSED_UNLESS_VERBOSE(ext2);
803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
81be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8357c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Livoid CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
8484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber                                    camera_frame_metadata_t * /* metadata */) {
85a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("postData(%d, ptr:%p, size:%zu)",
86be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber         msgType, dataPtr->pointer(), dataPtr->size());
8765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
8865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<CameraSource> source = mSource.promote();
8965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (source.get() != NULL) {
9065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        source->dataCallback(msgType, dataPtr);
9165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
92be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
93be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
94be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postDataTimestamp(
95be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
96c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
97c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    sp<CameraSource> source = mSource.promote();
98c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (source.get() != NULL) {
99c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
100c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
101be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103653252be963c07c99109d20f942d1f30c52a9360James Dongstatic int32_t getColorFormat(const char* colorFormat) {
104e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
105e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong       return OMX_COLOR_FormatYUV420Planar;
106e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    }
107e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong
108653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
109653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_FormatYUV422SemiPlanar;
110653252be963c07c99109d20f942d1f30c52a9360James Dong    }
111653252be963c07c99109d20f942d1f30c52a9360James Dong
112653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
113653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYUV420SemiPlanar;
114653252be963c07c99109d20f942d1f30c52a9360James Dong    }
115653252be963c07c99109d20f942d1f30c52a9360James Dong
116653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
117653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYCbYCr;
118653252be963c07c99109d20f942d1f30c52a9360James Dong    }
119653252be963c07c99109d20f942d1f30c52a9360James Dong
120653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
121653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_Format16bitRGB565;
122653252be963c07c99109d20f942d1f30c52a9360James Dong    }
123653252be963c07c99109d20f942d1f30c52a9360James Dong
1241374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket    if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
1251374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket       return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
1261374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket    }
1271374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket
128bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE)) {
129bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala        return OMX_COLOR_FormatAndroidOpaque;
130bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala    }
131bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala
13229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    ALOGE("Uknown color format (%s), please add it to "
133a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong         "CameraSource::getColorFormat", colorFormat);
134a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong
135f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong    CHECK(!"Unknown color format");
136dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn    return -1;
137653252be963c07c99109d20f942d1f30c52a9360James Dong}
138653252be963c07c99109d20f942d1f30c52a9360James Dong
139ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville TalvalaCameraSource *CameraSource::Create(const String16 &clientName) {
14054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size size;
14154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.width = -1;
14254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.height = -1;
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    sp<ICamera> camera;
14598a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    return new CameraSource(camera, NULL, 0, clientName, Camera::USE_CALLING_UID,
14698a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen            Camera::USE_CALLING_PID, size, -1, NULL, false);
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14930ab66297501757d745b9ae10da61adcd891f497Andreas Huber// static
15054ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource *CameraSource::CreateFromCamera(
15154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
1524ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
15354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
154ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    const String16& clientName,
155ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    uid_t clientUid,
15698a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    pid_t clientPid,
15754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
15854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
15999617adda9bc46c43f511f0940bc735c73de61deMathias Agopian    const sp<IGraphicBufferProducer>& surface,
1605c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers) {
16154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1624ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    CameraSource *source = new CameraSource(camera, proxy, cameraId,
16398a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen            clientName, clientUid, clientPid, videoSize, frameRate, surface,
164ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala            storeMetaDataInVideoBuffers);
16554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return source;
16630ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
16730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
16854ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource::CameraSource(
16954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
1704ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
17154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
172ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    const String16& clientName,
173ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    uid_t clientUid,
17498a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    pid_t clientPid,
17554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
17654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
17799617adda9bc46c43f511f0940bc735c73de61deMathias Agopian    const sp<IGraphicBufferProducer>& surface,
1785c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers)
17954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    : mCameraFlags(0),
180983cf231ab2d176a14595cdae46ff1b0c239af47James Dong      mNumInputBuffers(0),
18154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mVideoFrameRate(-1),
18254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mCamera(0),
18354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mSurface(surface),
18413aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesReceived(0),
18565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mLastFrameTimestampUs(0),
18665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mStarted(false),
18713aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesEncoded(0),
188e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong      mTimeBetweenFrameCaptureUs(0),
1897757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong      mFirstFrameTimeUs(0),
19013aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesDropped(0),
191f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mNumGlitches(0),
192f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mGlitchDurationThresholdUs(200000),
19365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mCollectStats(false) {
19454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width  = -1;
19554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = -1;
19654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1974ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mInitCheck = init(camera, proxy, cameraId,
19898a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen                    clientName, clientUid, clientPid,
1995c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate,
2005c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
20195068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mInitCheck != OK) releaseCamera();
20254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
20354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
20454ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::initCheck() const {
20554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return mInitCheck;
20654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
20754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
20854ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraAvailable(
2094ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
21098a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    int32_t cameraId, const String16& clientName, uid_t clientUid, pid_t clientPid) {
21154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
21254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (camera == 0) {
21398a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen        mCamera = Camera::connect(cameraId, clientName, clientUid, clientPid);
2144ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
21554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags &= ~FLAGS_HOT_CAMERA;
21654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {
2174ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // We get the proxy from Camera, not ICamera. We need to get the proxy
2184ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // to the remote Camera owned by the application. Here mCamera is a
2194ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // local Camera object created by us. We cannot use the proxy from
2204ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // mCamera here.
22154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::create(camera);
2224ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
2234ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy = proxy;
22454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags |= FLAGS_HOT_CAMERA;
2253bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mDeathNotifier = new DeathNotifier();
2263bd3020c00ec8264ac1fe3870800f326487f9221James Dong        // isBinderAlive needs linkToDeath to work.
22706b46062d2f8bc82ca3061a23d197734ae51918bMarco Nelissen        IInterface::asBinder(mCameraRecordingProxy)->linkToDeath(mDeathNotifier);
22854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
22954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
2304ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCamera->lock();
2314ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
23254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
23354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
23454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
23554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
23654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
23754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check to see whether the requested video width and height is one
23854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * of the supported sizes.
23954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the video frame width in pixels
24054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the video frame height in pixels
24154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param suppportedSizes the vector of sizes that we check against
24254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return true if the dimension (width and height) is supported.
24354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
24454ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic bool isVideoSizeSupported(
24554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t width, int32_t height,
24654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const Vector<Size>& supportedSizes) {
24754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
2483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("isVideoSizeSupported");
24954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    for (size_t i = 0; i < supportedSizes.size(); ++i) {
25054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (width  == supportedSizes[i].width &&
25154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            height == supportedSizes[i].height) {
25254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return true;
25354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
25454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
25554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return false;
25654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
25754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
25854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
25954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the preview and video output is separate, we only set the
26054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * the video size, and applications should set the preview size
26154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * to some proper value, and the recording framework will not
26254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * change the preview size; otherwise, if the video and preview
26354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * output is the same, we need to set the preview to be the same
26454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * as the requested video size.
26554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
26654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
26754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
26854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Query the camera to retrieve the supported video frame sizes
26954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * and also to see whether CameraParameters::setVideoSize()
27054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is supported or not.
27154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
27254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @@param isSetVideoSizeSupported retunrs whether method
27354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      CameraParameters::setVideoSize() is supported or not.
27454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param sizes returns the vector of Size objects for the
27554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      supported video frame sizes advertised by the camera.
27654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
27754ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic void getSupportedVideoSizes(
27854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const CameraParameters& params,
27954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool *isSetVideoSizeSupported,
28054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size>& sizes) {
28154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
28254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    *isSetVideoSizeSupported = true;
28354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    params.getSupportedVideoSizes(sizes);
28454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (sizes.size() == 0) {
285b8a805261bf0282e992d3608035e47d05a898710Steve Block        ALOGD("Camera does not support setVideoSize()");
28654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params.getSupportedPreviewSizes(sizes);
28754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        *isSetVideoSizeSupported = false;
28854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
28954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
29054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
29154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
29254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the camera has the supported color format
29354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
29454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
29554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
29654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraColorFormatSupported(
29754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params) {
29854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mColorFormat = getColorFormat(params.get(
29954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            CameraParameters::KEY_VIDEO_FRAME_FORMAT));
30054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mColorFormat == -1) {
30154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
30254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
30354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
30454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
30554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
30654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
30754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Configure the camera to use the requested video size
30854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * (width and height) and/or frame rate. If both width and
30954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * height are -1, configuration on the video size is skipped.
31054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * if frameRate is -1, configuration on the frame rate
31154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is skipped. Skipping the configuration allows one to
31254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * use the current camera setting without the need to
31354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * actually know the specific values (see Create() method).
31454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
31554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params the CameraParameters to be configured
31654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the target video frame width in pixels
31754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the target video frame height in pixels
31854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
31954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
32054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
32154ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::configureCamera(
32254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        CameraParameters* params,
32354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height,
32454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
3253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("configureCamera");
32654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size> sizes;
32754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isSetVideoSizeSupportedByCamera = true;
32854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
32954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isCameraParamChanged = false;
33054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
33154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (!isVideoSizeSupported(width, height, sizes)) {
33229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Video dimension (%dx%d) is unsupported", width, height);
33354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return BAD_VALUE;
33454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
33554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (isSetVideoSizeSupportedByCamera) {
33654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setVideoSize(width, height);
33754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        } else {
33854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setPreviewSize(width, height);
33954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
34054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
34154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else if ((width == -1 && height != -1) ||
34254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong               (width != -1 && height == -1)) {
34354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // If one and only one of the width and height is -1
34454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // we reject such a request.
34529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Requested video size (%dx%d) is not supported", width, height);
34654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
34754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // width == -1 && height == -1
34854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
34954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current width and height value setting from the camera.
35054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
35154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
35254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1) {
353635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(frameRate > 0 && frameRate <= 120);
354635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        const char* supportedFrameRates =
355635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
356635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(supportedFrameRates != NULL);
3573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Supported frame rates: %s", supportedFrameRates);
358635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        char buf[4];
359635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        snprintf(buf, 4, "%d", frameRate);
360635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        if (strstr(supportedFrameRates, buf) == NULL) {
36129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Requested frame rate (%d) is not supported: %s",
362635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                frameRate, supportedFrameRates);
363635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong            return BAD_VALUE;
364635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        }
365635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong
366635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        // The frame rate is supported, set the camera to the requested value.
36754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params->setPreviewFrameRate(frameRate);
36854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
36954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // frameRate == -1
37054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
37154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current frame rate value setting from the camera
37254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
37354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
37454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (isCameraParamChanged) {
37554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Either frame rate or frame size needs to be changed.
37654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        String8 s = params->flatten();
37754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (OK != mCamera->setParameters(s)) {
37829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Could not change settings."
37954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                 " Someone else is using camera %p?", mCamera.get());
38054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return -EBUSY;
38154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
38254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
38354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
38454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
38554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
38654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
38754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the requested video frame size
38854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * has been successfully configured or not. If both width and height
38954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * are -1, check on the current width and height value setting
39054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is performed.
39154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
39254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
39354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame width in pixels to check against
39454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame height in pixels to check against
39554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error
39654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
39754ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkVideoSize(
39854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
39954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height) {
40054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
4013856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("checkVideoSize");
402f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // The actual video size is the same as the preview size
403f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // if the camera hal does not support separate video and
404f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // preview output. In this case, we retrieve the video
405f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // size from preview.
40654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameWidthActual = -1;
40754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameHeightActual = -1;
408f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    Vector<Size> sizes;
409f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    params.getSupportedVideoSizes(sizes);
410f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    if (sizes.size() == 0) {
411f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size is the same as preview size
412f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getPreviewSize(&frameWidthActual, &frameHeightActual);
413f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    } else {
414f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size may not be the same as preview
415f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getVideoSize(&frameWidthActual, &frameHeightActual);
416f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    }
41754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameWidthActual < 0 || frameHeightActual < 0) {
41829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Failed to retrieve video frame size (%dx%d)",
41954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                frameWidthActual, frameHeightActual);
42054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
42154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
42254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
42354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame size against the target/requested
42454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame size.
42554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
42654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (frameWidthActual != width || frameHeightActual != height) {
42729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Failed to set video frame size to %dx%d. "
42854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    "The actual video size is %dx%d ", width, height,
42954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameWidthActual, frameHeightActual);
43054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return UNKNOWN_ERROR;
43154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
43254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
43354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
43454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
43554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width = frameWidthActual;
43654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = frameHeightActual;
43754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
43854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
43954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
44054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
44154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check the requested frame rate has been successfully configured or not.
44254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the target frameRate is -1, check on the current frame rate value
44354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * setting is performed.
44454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
44554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
44654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame rate to check against
44754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
44854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
44954ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkFrameRate(
45054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
45154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
45254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
4533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("checkFrameRate");
45454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRateActual = params.getPreviewFrameRate();
45554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRateActual < 0) {
45629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
45754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
45854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
45954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
46054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame rate against the target/requested
46154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame rate.
46254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
46329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Failed to set preview frame rate to %d fps. The actual "
46454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                "frame rate is %d", frameRate, frameRateActual);
46554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
46654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
46754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
46854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
46954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoFrameRate = frameRateActual;
47054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
47154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
47254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
47354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
47454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Initialize the CameraSource to so that it becomes
47554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * ready for providing the video input streams as requested.
47654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param camera the camera object used for the video source
47754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param cameraId if camera == 0, use camera with this id
47854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      as the video source
47954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param videoSize the target video frame size. If both
48054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and height in videoSize is -1, use the current
48154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and heigth settings by the camera
48254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
48354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      if it is -1, use the current camera frame rate setting.
4845c9523154d106b555db6c41f85ab205a4f189b02James Dong * @param storeMetaDataInVideoBuffers request to store meta
4855c9523154d106b555db6c41f85ab205a4f189b02James Dong *      data or real YUV data in video buffers. Request to
4865c9523154d106b555db6c41f85ab205a4f189b02James Dong *      store meta data in video buffers may not be honored
4875c9523154d106b555db6c41f85ab205a4f189b02James Dong *      if the source does not support this feature.
4885c9523154d106b555db6c41f85ab205a4f189b02James Dong *
48954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
49054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
49154ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::init(
49254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const sp<ICamera>& camera,
4934ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        const sp<ICameraRecordingProxy>& proxy,
49454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t cameraId,
495ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        const String16& clientName,
496ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        uid_t clientUid,
49798a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen        pid_t clientPid,
49854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        Size videoSize,
4995c9523154d106b555db6c41f85ab205a4f189b02James Dong        int32_t frameRate,
5005c9523154d106b555db6c41f85ab205a4f189b02James Dong        bool storeMetaDataInVideoBuffers) {
50154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
5023856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("init");
50354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    status_t err = OK;
504ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
50598a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    err = initWithCameraAccess(camera, proxy, cameraId, clientName, clientUid, clientPid,
506ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               videoSize, frameRate,
507ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               storeMetaDataInVideoBuffers);
508ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
509ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    return err;
510ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong}
511ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong
5128cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chenstatus_t CameraSource::initBufferQueue(uint32_t width, uint32_t height,
5138cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        uint32_t format, android_dataspace dataSpace, uint32_t bufferCount) {
5148cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ALOGV("initBufferQueue");
5158cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5168cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (mVideoBufferConsumer != nullptr || mVideoBufferProducer != nullptr) {
5178cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Buffer queue already exists", __FUNCTION__);
5188cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return ALREADY_EXISTS;
5198cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5208cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5218cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // Create a buffer queue.
5228cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    sp<IGraphicBufferProducer> producer;
5238cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    sp<IGraphicBufferConsumer> consumer;
5248cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    BufferQueue::createBufferQueue(&producer, &consumer);
5258cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5268cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN;
5278cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
5288cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        usage = GRALLOC_USAGE_HW_VIDEO_ENCODER;
5298cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5308cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5318cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    bufferCount += kConsumerBufferCount;
5328cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5338cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mVideoBufferConsumer = new BufferItemConsumer(consumer, usage, bufferCount);
5348cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mVideoBufferConsumer->setName(String8::format("StageFright-CameraSource"));
5358cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mVideoBufferProducer = producer;
5368cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5378cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    status_t res = mVideoBufferConsumer->setDefaultBufferSize(width, height);
5388cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (res != OK) {
5398cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Could not set buffer dimensions %dx%d: %s (%d)", __FUNCTION__, width, height,
5408cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                strerror(-res), res);
5418cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return res;
5428cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5438cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5448cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    res = mVideoBufferConsumer->setDefaultBufferFormat(format);
5458cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (res != OK) {
5468cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Could not set buffer format %d: %s (%d)", __FUNCTION__, format,
5478cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                strerror(-res), res);
5488cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return res;
5498cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5508cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5518cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    res = mVideoBufferConsumer->setDefaultBufferDataSpace(dataSpace);
5528cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (res != OK) {
5538cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Could not set data space %d: %s (%d)", __FUNCTION__, dataSpace,
5548cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                strerror(-res), res);
5558cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return res;
5568cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5578cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5588cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    res = mCamera->setVideoTarget(mVideoBufferProducer);
5598cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (res != OK) {
5608cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Failed to set video target: %s (%d)", __FUNCTION__, strerror(-res), res);
5618cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return res;
5628cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5638cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5648cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // Create memory heap to store buffers as VideoNativeMetadata.
5658cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    size_t bufferSize = sizeof(VideoNativeMetadata);
5668cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mMemoryHeapBase = new MemoryHeapBase(bufferSize * bufferCount, 0,
5678cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            "StageFright-CameraSource-BufferHeap");
5688cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    for (uint32_t i = 0; i < bufferCount; i++) {
5698cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mMemoryBases.push_back(new MemoryBase(mMemoryHeapBase, i * bufferSize, bufferSize));
5708cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5718cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5728cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mBufferQueueListener = new BufferQueueListener(mVideoBufferConsumer, this);
5738cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    res = mBufferQueueListener->run("CameraSource-BufferQueueListener");
5748cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (res != OK) {
5758cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Could not run buffer queue listener thread: %s (%d)", __FUNCTION__,
5768cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                strerror(-res), res);
5778cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return res;
5788cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5798cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5808cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    return OK;
5818cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
5828cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
583ae4c1ac6401185539c03ce0819e174fd1b04b136James Dongstatus_t CameraSource::initWithCameraAccess(
584ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        const sp<ICamera>& camera,
585ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        const sp<ICameraRecordingProxy>& proxy,
586ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t cameraId,
587ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        const String16& clientName,
588ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        uid_t clientUid,
58998a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen        pid_t clientPid,
590ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        Size videoSize,
591ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t frameRate,
592ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        bool storeMetaDataInVideoBuffers) {
5933856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initWithCameraAccess");
594ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    status_t err = OK;
5959d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
596ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    if ((err = isCameraAvailable(camera, proxy, cameraId,
59798a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen            clientName, clientUid, clientPid)) != OK) {
59829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Camera connection could not be established.");
59954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
60054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
60154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters params(mCamera->getParameters());
60254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = isCameraColorFormatSupported(params)) != OK) {
60354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
60454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
605be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
60654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Set the camera to use the requested video frame size
60754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // and/or frame rate.
60854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = configureCamera(&params,
60954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    videoSize.width, videoSize.height,
61054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameRate))) {
61154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
61254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
613653252be963c07c99109d20f942d1f30c52a9360James Dong
61454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check on video frame size and frame rate.
61554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters newCameraParams(mCamera->getParameters());
61654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkVideoSize(newCameraParams,
61754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                videoSize.width, videoSize.height)) != OK) {
61854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
61954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
62054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
62154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
62254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
62354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
6248e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    // Set the preview display. Skip this if mSurface is null because
6258e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    // applications may already set a surface to the camera.
6268e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    if (mSurface != NULL) {
6278e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li        // This CHECK is good, since we just passed the lock/unlock
6288e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li        // check earlier by calling mCamera->setParameters().
6294b820b0e1fa069714b123fc35784541d0f94d267Eino-Ville Talvala        CHECK_EQ((status_t)OK, mCamera->setPreviewTarget(mSurface));
6308e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    }
6312b37ced30f89437c804c3945b901019b86d210aeJames Dong
6328cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // By default, store real data in video buffers.
6338cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mVideoBufferMode = ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV;
634abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    if (storeMetaDataInVideoBuffers) {
6358cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        if (OK == mCamera->setVideoBufferMode(ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE)) {
6368cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            mVideoBufferMode = ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE;
6378cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        } else if (OK == mCamera->setVideoBufferMode(
6388cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA)) {
6398cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            mVideoBufferMode = ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA;
6408cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
6418cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
6428cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
6438cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (mVideoBufferMode == ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV) {
6448cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        err = mCamera->setVideoBufferMode(ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV);
6458cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        if (err != OK) {
6468cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            ALOGE("%s: Setting video buffer mode to VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV failed: "
6478cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                    "%s (err=%d)", __FUNCTION__, strerror(-err), err);
6488cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            return err;
649abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong        }
6505c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
6515c9523154d106b555db6c41f85ab205a4f189b02James Dong
65254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
653f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (glitchDurationUs > mGlitchDurationThresholdUs) {
654f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mGlitchDurationThresholdUs = glitchDurationUs;
655f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
656f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
657ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // XXX: query camera for the stride and slice height
658ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // when the capability becomes available.
659653252be963c07c99109d20f942d1f30c52a9360James Dong    mMeta = new MetaData;
66054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setCString(kKeyMIMEType,  MEDIA_MIMETYPE_VIDEO_RAW);
66154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyColorFormat, mColorFormat);
66254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyWidth,       mVideoSize.width);
66354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyHeight,      mVideoSize.height);
66454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyStride,      mVideoSize.width);
66554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
666393410a441b6d06daf286ed496470e9d6b2b6ca8James Dong    mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
66754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource::~CameraSource() {
67120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
672b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong        reset();
673ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    } else if (mInitCheck == OK) {
674ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera is initialized but because start() is never called,
675ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // the lock on Camera is never released(). This makes sure
676ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera's lock is released in this case.
677ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        releaseCamera();
67820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
68020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68126cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunkstatus_t CameraSource::startCameraRecording() {
6823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startCameraRecording");
6834ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // Reset the identity to the current thread because media server owns the
6844ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // camera and recording is started by the applications. The applications
6854ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // will connect to the camera in ICameraRecordingProxy::startRecording.
6864ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    int64_t token = IPCThreadState::self()->clearCallingIdentity();
68726cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    status_t err;
6888cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
6898cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (mVideoBufferMode == ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE) {
6908cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        // Initialize buffer queue.
6918cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        err = initBufferQueue(mVideoSize.width, mVideoSize.height, mEncoderFormat,
6928cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                (android_dataspace_t)mEncoderDataSpace,
6938cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                mNumInputBuffers > 0 ? mNumInputBuffers : 1);
6948cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        if (err != OK) {
6958cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            ALOGE("%s: Failed to initialize buffer queue: %s (err=%d)", __FUNCTION__,
6968cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                    strerror(-err), err);
6978cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            return err;
6988cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
6998cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    } else {
7008cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        if (mNumInputBuffers > 0) {
7018cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            err = mCamera->sendCommand(
7028cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                CAMERA_CMD_SET_VIDEO_BUFFER_COUNT, mNumInputBuffers, 0);
7038cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
7048cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            // This could happen for CameraHAL1 clients; thus the failure is
7058cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            // not a fatal error
7068cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            if (err != OK) {
7078cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                ALOGW("Failed to set video buffer count to %d due to %d",
7088cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                    mNumInputBuffers, err);
7098cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            }
7108cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
7118cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
71226cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        err = mCamera->sendCommand(
7138cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            CAMERA_CMD_SET_VIDEO_FORMAT, mEncoderFormat, mEncoderDataSpace);
714983cf231ab2d176a14595cdae46ff1b0c239af47James Dong
715983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        // This could happen for CameraHAL1 clients; thus the failure is
716983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        // not a fatal error
717983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        if (err != OK) {
7188cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            ALOGW("Failed to set video encoder format/dataspace to %d, %d due to %d",
7198cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                    mEncoderFormat, mEncoderDataSpace, err);
720983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        }
721983cf231ab2d176a14595cdae46ff1b0c239af47James Dong    }
722983cf231ab2d176a14595cdae46ff1b0c239af47James Dong
72326cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    err = OK;
7243bd3020c00ec8264ac1fe3870800f326487f9221James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
7253bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->unlock();
7263bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera.clear();
72726cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        if ((err = mCameraRecordingProxy->startRecording(
72826cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk                new ProxyListener(this))) != OK) {
72926cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk            ALOGE("Failed to start recording, received error: %s (%d)",
73026cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk                    strerror(-err), err);
73126cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        }
7323bd3020c00ec8264ac1fe3870800f326487f9221James Dong    } else {
7333bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->setListener(new CameraSourceListener(this));
7343bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->startRecording();
73526cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        if (!mCamera->recordingEnabled()) {
73626cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk            err = -EINVAL;
73726cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk            ALOGE("Failed to start recording");
73826cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        }
7393bd3020c00ec8264ac1fe3870800f326487f9221James Dong    }
7404ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    IPCThreadState::self()->restoreCallingIdentity(token);
74126cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    return err;
74265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
74365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
744f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongstatus_t CameraSource::start(MetaData *meta) {
7453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("start");
7460c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mStarted);
74754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mInitCheck != OK) {
74829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("CameraSource is not initialized yet");
74954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return mInitCheck;
75054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
752365a963142093a1cd8efdcea76b5f65096a5b115James Dong    char value[PROPERTY_VALUE_MAX];
753365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
754365a963142093a1cd8efdcea76b5f65096a5b115James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
755365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mCollectStats = true;
756365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
7579d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
758f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
759983cf231ab2d176a14595cdae46ff1b0c239af47James Dong    mNumInputBuffers = 0;
760d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala    mEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
761d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala    mEncoderDataSpace = HAL_DATASPACE_BT709;
762d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala
763983cf231ab2d176a14595cdae46ff1b0c239af47James Dong    if (meta) {
764983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        int64_t startTimeUs;
765983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        if (meta->findInt64(kKeyTime, &startTimeUs)) {
766983cf231ab2d176a14595cdae46ff1b0c239af47James Dong            mStartTimeUs = startTimeUs;
767983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        }
768983cf231ab2d176a14595cdae46ff1b0c239af47James Dong
769983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        int32_t nBuffers;
770983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        if (meta->findInt32(kKeyNumBuffers, &nBuffers)) {
771983cf231ab2d176a14595cdae46ff1b0c239af47James Dong            CHECK_GT(nBuffers, 0);
772983cf231ab2d176a14595cdae46ff1b0c239af47James Dong            mNumInputBuffers = nBuffers;
773983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        }
774d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala
775c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        // apply encoder color format if specified
776c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        if (meta->findInt32(kKeyPixelFormat, &mEncoderFormat)) {
777c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            ALOGV("Using encoder format: %#x", mEncoderFormat);
778c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        }
779c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        if (meta->findInt32(kKeyColorSpace, &mEncoderDataSpace)) {
780c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            ALOGV("Using encoder data space: %#x", mEncoderDataSpace);
781c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        }
782f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
783f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
78426cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    status_t err;
78526cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    if ((err = startCameraRecording()) == OK) {
78626cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        mStarted = true;
78726cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    }
78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78926cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    return err;
79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::stopCameraRecording() {
7933856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("stopCameraRecording");
7943bd3020c00ec8264ac1fe3870800f326487f9221James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
7952da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim        if (mCameraRecordingProxy != 0) {
7962da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim            mCameraRecordingProxy->stopRecording();
7972da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim        }
7983bd3020c00ec8264ac1fe3870800f326487f9221James Dong    } else {
7992da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim        if (mCamera != 0) {
8002da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim            mCamera->setListener(NULL);
8012da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim            mCamera->stopRecording();
8022da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim        }
8033bd3020c00ec8264ac1fe3870800f326487f9221James Dong    }
80465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
80565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
806ea7b485595f8cec6a66668b5c54c8f297d843f77James Dongvoid CameraSource::releaseCamera() {
8073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("releaseCamera");
808121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    sp<Camera> camera;
809121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    bool coldCamera = false;
810121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    {
811121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        Mutex::Autolock autoLock(mLock);
812121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        // get a local ref and clear ref to mCamera now
813121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        camera = mCamera;
814121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mCamera.clear();
815121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        coldCamera = (mCameraFlags & FLAGS_HOT_CAMERA) == 0;
816121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    }
817121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
818121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    if (camera != 0) {
819ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
820121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (coldCamera) {
8213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("Camera was cold when we started, stopping preview");
822121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            camera->stopPreview();
823121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            camera->disconnect();
82495068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        }
825121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        camera->unlock();
826ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
82795068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    }
828121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
829121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    {
830121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        Mutex::Autolock autoLock(mLock);
831121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mCameraRecordingProxy != 0) {
83206b46062d2f8bc82ca3061a23d197734ae51918bMarco Nelissen            IInterface::asBinder(mCameraRecordingProxy)->unlinkToDeath(mDeathNotifier);
833121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            mCameraRecordingProxy.clear();
834121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
835121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mCameraFlags = 0;
836ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    }
837ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong}
838ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong
839b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dongstatus_t CameraSource::reset() {
840b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong    ALOGD("reset: E");
841121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
842121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    {
843121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        Mutex::Autolock autoLock(mLock);
844121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mStarted = false;
845121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mFrameAvailableCondition.signal();
846121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
847121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        int64_t token;
848121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        bool isTokenValid = false;
849121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mCamera != 0) {
850121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            token = IPCThreadState::self()->clearCallingIdentity();
851121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            isTokenValid = true;
852121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
853121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        releaseQueuedFrames();
854121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        while (!mFramesBeingEncoded.empty()) {
855121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            if (NO_ERROR !=
856121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                mFrameCompleteCondition.waitRelative(mLock,
857121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                        mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
858121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                ALOGW("Timed out waiting for outstanding frames being encoded: %zu",
859121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                    mFramesBeingEncoded.size());
860121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            }
861121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
862121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        stopCameraRecording();
863121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (isTokenValid) {
864121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            IPCThreadState::self()->restoreCallingIdentity(token);
86541152efd144ccf70c380d5c9a32105c02a039f43James Dong        }
8667278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
867121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mCollectStats) {
868121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            ALOGI("Frames received/encoded/dropped: %d/%d/%d in %" PRId64 " us",
869121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                    mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
870121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                    mLastFrameTimestampUs - mFirstFrameTimeUs);
871121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
872121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
873121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mNumGlitches > 0) {
874121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            ALOGW("%d long delays between neighboring video frames", mNumGlitches);
875121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
87613aec890216948b0c364f8f92792129d0335f506James Dong
877121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
878ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    }
879ba29002c7aee13c068049037cd14bba6a244da6bJames Dong
8808cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (mBufferQueueListener != nullptr) {
8818cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mBufferQueueListener->requestExit();
8828cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mBufferQueueListener->join();
8838cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mBufferQueueListener.clear();
8848cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
8858cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
8868cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mVideoBufferConsumer.clear();
8878cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mVideoBufferProducer.clear();
888121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    releaseCamera();
889121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
890b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong    ALOGD("reset: X");
89120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
89220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
89320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
89465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
8953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("releaseRecordingFrame");
8968cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
8978cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (mVideoBufferMode == ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE) {
8988cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        // Return the buffer to buffer queue in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
8998cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ssize_t offset;
9008cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        size_t size;
9018cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        sp<IMemoryHeap> heap = frame->getMemory(&offset, &size);
9028cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        if (heap->getHeapID() != mMemoryHeapBase->getHeapID()) {
9038cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            ALOGE("%s: Mismatched heap ID, ignoring release (got %x, expected %x)", __FUNCTION__,
9048cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                    heap->getHeapID(), mMemoryHeapBase->getHeapID());
9058cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            return;
9068cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
9078cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
9088cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        VideoNativeMetadata *payload = reinterpret_cast<VideoNativeMetadata*>(
9098cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                (uint8_t*)heap->getBase() + offset);
9108cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
9118cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        // Find the corresponding buffer item for the native window buffer.
9128cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ssize_t index = mReceivedBufferItemMap.indexOfKey(payload->pBuffer);
9138cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        if (index == NAME_NOT_FOUND) {
9148cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            ALOGE("%s: Couldn't find buffer item for %p", __FUNCTION__, payload->pBuffer);
9158cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            return;
9168cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
9178cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
9188cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        BufferItem buffer = mReceivedBufferItemMap.valueAt(index);
9198cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mReceivedBufferItemMap.removeItemsAt(index);
9208cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mVideoBufferConsumer->releaseBuffer(buffer);
9218cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mMemoryBases.push_back(frame);
9220419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen        mMemoryBaseAvailableCond.signal();
9238cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    } else if (mCameraRecordingProxy != NULL) {
9244ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy->releaseRecordingFrame(frame);
925334d097870eefeb45137b6df026f7db861d47663James Dong    } else if (mCamera != NULL) {
9263bd3020c00ec8264ac1fe3870800f326487f9221James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
9273bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->releaseRecordingFrame(frame);
9283bd3020c00ec8264ac1fe3870800f326487f9221James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
929d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    }
93065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
93165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
932c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::releaseQueuedFrames() {
933c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    List<sp<IMemory> >::iterator it;
9347278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesReceived.empty()) {
9357278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        it = mFramesReceived.begin();
93665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseRecordingFrame(*it);
9377278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        mFramesReceived.erase(it);
93813aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesDropped;
939c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
940c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong}
941c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> CameraSource::getFormat() {
943653252be963c07c99109d20f942d1f30c52a9360James Dong    return mMeta;
94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
94520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
946f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
94765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    releaseRecordingFrame(frame);
948f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong}
949f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
9507278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) {
9513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("signalBufferReturned: %p", buffer->data());
95256223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber    Mutex::Autolock autoLock(mLock);
9537278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
9547278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong         it != mFramesBeingEncoded.end(); ++it) {
9557278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        if ((*it)->pointer() ==  buffer->data()) {
956f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            releaseOneRecordingFrame((*it));
9577278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFramesBeingEncoded.erase(it);
9587278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            ++mNumFramesEncoded;
9597278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->setObserver(0);
9607278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->release();
9617278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFrameCompleteCondition.signal();
9627278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            return;
9637278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        }
9647278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
965f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong    CHECK(!"signalBufferReturned: bogus buffer");
9667278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong}
9677278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
96820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::read(
96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
9703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("read");
97120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *buffer = NULL;
97320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
975abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
976abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_UNSUPPORTED;
97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<IMemory> frame;
981be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    int64_t frameTime;
98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    {
98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Mutex::Autolock autoLock(mLock);
98579e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        while (mStarted && mFramesReceived.empty()) {
98641152efd144ccf70c380d5c9a32105c02a039f43James Dong            if (NO_ERROR !=
987e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong                mFrameAvailableCondition.waitRelative(mLock,
988e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong                    mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
9893bd3020c00ec8264ac1fe3870800f326487f9221James Dong                if (mCameraRecordingProxy != 0 &&
99006b46062d2f8bc82ca3061a23d197734ae51918bMarco Nelissen                    !IInterface::asBinder(mCameraRecordingProxy)->isBinderAlive()) {
9915ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                    ALOGW("camera recording proxy is gone");
9924ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                    return ERROR_END_OF_STREAM;
9934ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                }
994a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGW("Timed out waiting for incoming camera video frames: %" PRId64 " us",
99541152efd144ccf70c380d5c9a32105c02a039f43James Dong                    mLastFrameTimestampUs);
99641152efd144ccf70c380d5c9a32105c02a039f43James Dong            }
99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
99879e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        if (!mStarted) {
99979e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong            return OK;
100079e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        }
100179e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frame = *mFramesReceived.begin();
100279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesReceived.erase(mFramesReceived.begin());
100379e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong
100479e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frameTime = *mFrameTimes.begin();
100579e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFrameTimes.erase(mFrameTimes.begin());
100679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesBeingEncoded.push_back(frame);
100779e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        *buffer = new MediaBuffer(frame->pointer(), frame->size());
100879e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->setObserver(this);
100979e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->add_ref();
101079e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
10117278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
101220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10158cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chenbool CameraSource::shouldSkipFrameLocked(int64_t timestampUs) {
1016a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
1017ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("Drop frame at %lld/%lld us", (long long)timestampUs, (long long)mStartTimeUs);
10188cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return true;
1019c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
102165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // May need to skip frame or modify timestamp. Currently implemented
102265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // by the subclass CameraSourceTimeLapse.
102379e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong    if (skipCurrentFrame(timestampUs)) {
10248cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return true;
1025fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra    }
1026fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra
10270aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang    if (mNumFramesReceived > 0) {
10280aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang        if (timestampUs <= mLastFrameTimestampUs) {
10290aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang            ALOGW("Dropping frame with backward timestamp %lld (last %lld)",
10300aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang                    (long long)timestampUs, (long long)mLastFrameTimestampUs);
10318cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            return true;
10320aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang        }
10330aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang        if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
10340aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang            ++mNumGlitches;
10350aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang        }
10360aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang    }
10370aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang
1038365a963142093a1cd8efdcea76b5f65096a5b115James Dong    mLastFrameTimestampUs = timestampUs;
103913aec890216948b0c364f8f92792129d0335f506James Dong    if (mNumFramesReceived == 0) {
1040c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        mFirstFrameTimeUs = timestampUs;
1041f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        // Initial delay
1042f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        if (mStartTimeUs > 0) {
1043f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            if (timestampUs < mStartTimeUs) {
1044f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Frame was captured before recording was started
1045f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Drop it without updating the statistical data.
10468cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                return true;
1047f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            }
1048f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimeUs = timestampUs - mStartTimeUs;
1049f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
1050be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    }
10518cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
10528cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    return false;
10538cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
10548cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
10558cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chenvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs,
10568cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        int32_t msgType __unused, const sp<IMemory> &data) {
10578cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ALOGV("dataCallbackTimestamp: timestamp %lld us", (long long)timestampUs);
10588cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    Mutex::Autolock autoLock(mLock);
10598cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
10608cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (shouldSkipFrameLocked(timestampUs)) {
10618cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        releaseOneRecordingFrame(data);
10628cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return;
10638cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
10648cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
106513aec890216948b0c364f8f92792129d0335f506James Dong    ++mNumFramesReceived;
1066be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
106798cfde007490a5903b729a4718c0dada755ae8f8James Dong    CHECK(data != NULL && data->size() > 0);
10687278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    mFramesReceived.push_back(data);
1069f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
1070f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mFrameTimes.push_back(timeUs);
1071a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("initial delay: %" PRId64 ", current time stamp: %" PRId64,
1072f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs, timeUs);
107320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFrameAvailableCondition.signal();
107420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
107520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10768cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu ChenCameraSource::BufferQueueListener::BufferQueueListener(const sp<BufferItemConsumer>& consumer,
10778cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        const sp<CameraSource>& cameraSource) {
10788cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mConsumer = consumer;
10798cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mConsumer->setFrameAvailableListener(this);
10808cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mCameraSource = cameraSource;
10818cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
10828cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
10838cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chenvoid CameraSource::BufferQueueListener::onFrameAvailable(const BufferItem& /*item*/) {
10848cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ALOGV("%s: onFrameAvailable", __FUNCTION__);
10858cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
10868cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    Mutex::Autolock l(mLock);
10878cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
10888cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (!mFrameAvailable) {
10898cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mFrameAvailable = true;
10908cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mFrameAvailableSignal.signal();
10918cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
10928cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
10938cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
10948cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chenbool CameraSource::BufferQueueListener::threadLoop() {
10958cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (mConsumer == nullptr || mCameraSource == nullptr) {
10968cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return false;
10978cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
10988cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
10998cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    {
11008cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        Mutex::Autolock l(mLock);
11018cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        while (!mFrameAvailable) {
11028cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            if (mFrameAvailableSignal.waitRelative(mLock, kFrameAvailableTimeout) == TIMED_OUT) {
11038cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                return true;
11048cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            }
11058cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
11068cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mFrameAvailable = false;
11078cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
11088cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11098cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    BufferItem buffer;
11108cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    while (mConsumer->acquireBuffer(&buffer, 0) == OK) {
11118cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mCameraSource->processBufferQueueFrame(buffer);
11128cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
11138cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11148cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    return true;
11158cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
11168cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11178fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chenvoid CameraSource::processBufferQueueFrame(BufferItem& buffer) {
11188cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    Mutex::Autolock autoLock(mLock);
11198cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11208cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    int64_t timestampUs = buffer.mTimestamp / 1000;
11218cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (shouldSkipFrameLocked(timestampUs)) {
11228cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mVideoBufferConsumer->releaseBuffer(buffer);
11238cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return;
11248cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
11258cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11260419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen    while (mMemoryBases.empty()) {
11270419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen        if (mMemoryBaseAvailableCond.waitRelative(mLock, kMemoryBaseAvailableTimeoutNs) ==
11280419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen                TIMED_OUT) {
11290419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen            ALOGW("Waiting on an available memory base timed out. Dropping a recording frame.");
11300419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen            mVideoBufferConsumer->releaseBuffer(buffer);
11310419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen            return;
11320419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen        }
11338cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
11348cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11358cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ++mNumFramesReceived;
11368cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11378cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // Find a available memory slot to store the buffer as VideoNativeMetadata.
11388cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    sp<IMemory> data = *mMemoryBases.begin();
11398cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mMemoryBases.erase(mMemoryBases.begin());
11408cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11418cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ssize_t offset;
11428cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    size_t size;
11438cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    sp<IMemoryHeap> heap = data->getMemory(&offset, &size);
11448cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    VideoNativeMetadata *payload = reinterpret_cast<VideoNativeMetadata*>(
11458cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        (uint8_t*)heap->getBase() + offset);
11468cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    memset(payload, 0, sizeof(VideoNativeMetadata));
11478cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    payload->eType = kMetadataBufferTypeANWBuffer;
11488cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    payload->pBuffer = buffer.mGraphicBuffer->getNativeBuffer();
11498cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    payload->nFenceFd = -1;
11508cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11518cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // Add the mapping so we can find the corresponding buffer item to release to the buffer queue
11528cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // when the encoder returns the native window buffer.
11538cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mReceivedBufferItemMap.add(payload->pBuffer, buffer);
11548cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11558cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mFramesReceived.push_back(data);
11568cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
11578cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mFrameTimes.push_back(timeUs);
11588cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ALOGV("initial delay: %" PRId64 ", current time stamp: %" PRId64,
11598cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mStartTimeUs, timeUs);
11608cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mFrameAvailableCondition.signal();
11618cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
11628cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11635c9523154d106b555db6c41f85ab205a4f189b02James Dongbool CameraSource::isMetaDataStoredInVideoBuffers() const {
11643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("isMetaDataStoredInVideoBuffers");
11658cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11668cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // Output buffers will contain metadata if camera sends us buffer in metadata mode or via
11678cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // buffer queue.
11688cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    return (mVideoBufferMode == ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA ||
11698cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            mVideoBufferMode == ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE);
11705c9523154d106b555db6c41f85ab205a4f189b02James Dong}
11715c9523154d106b555db6c41f85ab205a4f189b02James Dong
11724ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng LiCameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
11734ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource = source;
11744ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
11754ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
11764ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::ProxyListener::dataCallbackTimestamp(
11774ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
11784ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
11794ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
11804ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
1181ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnarvoid CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who __unused) {
1182df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Camera recording proxy died");
11834ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
11844ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
1186