CameraSource.cpp revision 57c86189bc07d9ccb0fd044e66df736d0bf19639
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
17c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong//#define LOG_NDEBUG 0
18c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#define LOG_TAG "CameraSource"
19c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <utils/Log.h>
2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <OMX_Component.h>
229d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong#include <binder/IPCThreadState.h>
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/CameraSource.h>
240c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h>
25be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <media/stagefright/MediaDefs.h>
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaErrors.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
283cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/Camera.h>
293cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/CameraParameters.h>
3054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong#include <surfaceflinger/Surface.h>
31be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <utils/String8.h>
32365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberstruct CameraSourceListener : public CameraListener {
37be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const sp<CameraSource> &source);
38be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
39be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
4057c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li    virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr,
4157c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li                          camera_frame_metadata_t *metadata);
42be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
43be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void postDataTimestamp(
44be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber            nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
45be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
46be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberprotected:
47be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual ~CameraSourceListener();
48be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
50be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    wp<CameraSource> mSource;
51be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
52be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const CameraSourceListener &);
53be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener &operator=(const CameraSourceListener &);
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
57be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    : mSource(source) {
58be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::~CameraSourceListener() {
61be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
64be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    LOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
65be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6757c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Livoid CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
6857c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li                                    camera_frame_metadata_t *metadata) {
69be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    LOGV("postData(%d, ptr:%p, size:%d)",
70be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber         msgType, dataPtr->pointer(), dataPtr->size());
7165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
7265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<CameraSource> source = mSource.promote();
7365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (source.get() != NULL) {
7465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        source->dataCallback(msgType, dataPtr);
7565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
76be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
77be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
78be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postDataTimestamp(
79be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
80c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
81c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    sp<CameraSource> source = mSource.promote();
82c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (source.get() != NULL) {
83c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
84c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
85be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
87653252be963c07c99109d20f942d1f30c52a9360James Dongstatic int32_t getColorFormat(const char* colorFormat) {
88e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
89e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong       return OMX_COLOR_FormatYUV420Planar;
90e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    }
91e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong
92653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
93653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_FormatYUV422SemiPlanar;
94653252be963c07c99109d20f942d1f30c52a9360James Dong    }
95653252be963c07c99109d20f942d1f30c52a9360James Dong
96653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
97653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYUV420SemiPlanar;
98653252be963c07c99109d20f942d1f30c52a9360James Dong    }
99653252be963c07c99109d20f942d1f30c52a9360James Dong
100653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
101653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYCbYCr;
102653252be963c07c99109d20f942d1f30c52a9360James Dong    }
103653252be963c07c99109d20f942d1f30c52a9360James Dong
104653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
105653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_Format16bitRGB565;
106653252be963c07c99109d20f942d1f30c52a9360James Dong    }
107653252be963c07c99109d20f942d1f30c52a9360James Dong
1081374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket    if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
1091374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket       return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
1101374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket    }
1111374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket
112a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong    LOGE("Uknown color format (%s), please add it to "
113a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong         "CameraSource::getColorFormat", colorFormat);
114a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong
115653252be963c07c99109d20f942d1f30c52a9360James Dong    CHECK_EQ(0, "Unknown color format");
116653252be963c07c99109d20f942d1f30c52a9360James Dong}
117653252be963c07c99109d20f942d1f30c52a9360James Dong
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource *CameraSource::Create() {
11954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size size;
12054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.width = -1;
12154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.height = -1;
12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    sp<ICamera> camera;
1244ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    return new CameraSource(camera, NULL, 0, size, -1, NULL, false);
12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12730ab66297501757d745b9ae10da61adcd891f497Andreas Huber// static
12854ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource *CameraSource::CreateFromCamera(
12954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
1304ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
13154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
13254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
13354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
1345c9523154d106b555db6c41f85ab205a4f189b02James Dong    const sp<Surface>& surface,
1355c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers) {
13654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1374ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    CameraSource *source = new CameraSource(camera, proxy, cameraId,
1385c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate, surface,
1395c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
14054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return source;
14130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
14230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
14354ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource::CameraSource(
14454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
1454ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
14654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
14754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
14854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
1495c9523154d106b555db6c41f85ab205a4f189b02James Dong    const sp<Surface>& surface,
1505c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers)
15154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    : mCameraFlags(0),
15254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mVideoFrameRate(-1),
15354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mCamera(0),
15454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mSurface(surface),
15513aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesReceived(0),
15665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mLastFrameTimestampUs(0),
15765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mStarted(false),
15813aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesEncoded(0),
1597757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong      mFirstFrameTimeUs(0),
16013aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesDropped(0),
161f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mNumGlitches(0),
162f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mGlitchDurationThresholdUs(200000),
16365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mCollectStats(false) {
16454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width  = -1;
16554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = -1;
16654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1674ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mInitCheck = init(camera, proxy, cameraId,
1685c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate,
1695c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
17095068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mInitCheck != OK) releaseCamera();
17154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
17254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
17354ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::initCheck() const {
17454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return mInitCheck;
17554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
17654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
17754ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraAvailable(
1784ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
1794ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    int32_t cameraId) {
18054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
18154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (camera == 0) {
18254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::connect(cameraId);
1834ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
18454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags &= ~FLAGS_HOT_CAMERA;
18554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {
1864ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // We get the proxy from Camera, not ICamera. We need to get the proxy
1874ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // to the remote Camera owned by the application. Here mCamera is a
1884ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // local Camera object created by us. We cannot use the proxy from
1894ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // mCamera here.
19054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::create(camera);
1914ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
1924ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy = proxy;
19354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags |= FLAGS_HOT_CAMERA;
1943bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mDeathNotifier = new DeathNotifier();
1953bd3020c00ec8264ac1fe3870800f326487f9221James Dong        // isBinderAlive needs linkToDeath to work.
1963bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
19754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
19854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1994ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCamera->lock();
2004ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
20154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
20254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
20354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
20454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
20554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
20654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check to see whether the requested video width and height is one
20754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * of the supported sizes.
20854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the video frame width in pixels
20954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the video frame height in pixels
21054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param suppportedSizes the vector of sizes that we check against
21154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return true if the dimension (width and height) is supported.
21254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
21354ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic bool isVideoSizeSupported(
21454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t width, int32_t height,
21554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const Vector<Size>& supportedSizes) {
21654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
21754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    LOGV("isVideoSizeSupported");
21854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    for (size_t i = 0; i < supportedSizes.size(); ++i) {
21954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (width  == supportedSizes[i].width &&
22054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            height == supportedSizes[i].height) {
22154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return true;
22254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
22354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
22454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return false;
22554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
22654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
22754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
22854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the preview and video output is separate, we only set the
22954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * the video size, and applications should set the preview size
23054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * to some proper value, and the recording framework will not
23154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * change the preview size; otherwise, if the video and preview
23254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * output is the same, we need to set the preview to be the same
23354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * as the requested video size.
23454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
23554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
23654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
23754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Query the camera to retrieve the supported video frame sizes
23854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * and also to see whether CameraParameters::setVideoSize()
23954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is supported or not.
24054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
24154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @@param isSetVideoSizeSupported retunrs whether method
24254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      CameraParameters::setVideoSize() is supported or not.
24354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param sizes returns the vector of Size objects for the
24454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      supported video frame sizes advertised by the camera.
24554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
24654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic void getSupportedVideoSizes(
24754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const CameraParameters& params,
24854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool *isSetVideoSizeSupported,
24954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size>& sizes) {
25054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
25154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    *isSetVideoSizeSupported = true;
25254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    params.getSupportedVideoSizes(sizes);
25354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (sizes.size() == 0) {
25454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGD("Camera does not support setVideoSize()");
25554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params.getSupportedPreviewSizes(sizes);
25654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        *isSetVideoSizeSupported = false;
25754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
25854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
25954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
26054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
26154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the camera has the supported color format
26254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
26354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
26454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
26554ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraColorFormatSupported(
26654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params) {
26754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mColorFormat = getColorFormat(params.get(
26854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            CameraParameters::KEY_VIDEO_FRAME_FORMAT));
26954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mColorFormat == -1) {
27054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
27154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
27254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
27354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
27454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
27554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
27654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Configure the camera to use the requested video size
27754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * (width and height) and/or frame rate. If both width and
27854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * height are -1, configuration on the video size is skipped.
27954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * if frameRate is -1, configuration on the frame rate
28054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is skipped. Skipping the configuration allows one to
28154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * use the current camera setting without the need to
28254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * actually know the specific values (see Create() method).
28354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
28454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params the CameraParameters to be configured
28554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the target video frame width in pixels
28654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the target video frame height in pixels
28754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
28854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
28954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
29054ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::configureCamera(
29154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        CameraParameters* params,
29254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height,
29354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
2943bd3020c00ec8264ac1fe3870800f326487f9221James Dong    LOGV("configureCamera");
29554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size> sizes;
29654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isSetVideoSizeSupportedByCamera = true;
29754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
29854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isCameraParamChanged = false;
29954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
30054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (!isVideoSizeSupported(width, height, sizes)) {
30154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Video dimension (%dx%d) is unsupported", width, height);
30254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return BAD_VALUE;
30354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
30454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (isSetVideoSizeSupportedByCamera) {
30554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setVideoSize(width, height);
30654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        } else {
30754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setPreviewSize(width, height);
30854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
30954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
31054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else if ((width == -1 && height != -1) ||
31154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong               (width != -1 && height == -1)) {
31254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // If one and only one of the width and height is -1
31354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // we reject such a request.
31454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Requested video size (%dx%d) is not supported", width, height);
31554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
31654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // width == -1 && height == -1
31754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
31854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current width and height value setting from the camera.
31954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
32054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
32154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1) {
322635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(frameRate > 0 && frameRate <= 120);
323635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        const char* supportedFrameRates =
324635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
325635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(supportedFrameRates != NULL);
326635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        LOGV("Supported frame rates: %s", supportedFrameRates);
327635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        char buf[4];
328635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        snprintf(buf, 4, "%d", frameRate);
329635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        if (strstr(supportedFrameRates, buf) == NULL) {
330635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong            LOGE("Requested frame rate (%d) is not supported: %s",
331635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                frameRate, supportedFrameRates);
332635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong            return BAD_VALUE;
333635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        }
334635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong
335635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        // The frame rate is supported, set the camera to the requested value.
33654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params->setPreviewFrameRate(frameRate);
33754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
33854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // frameRate == -1
33954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
34054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current frame rate value setting from the camera
34154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
34254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
34354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (isCameraParamChanged) {
34454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Either frame rate or frame size needs to be changed.
34554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        String8 s = params->flatten();
34654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (OK != mCamera->setParameters(s)) {
34754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Could not change settings."
34854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                 " Someone else is using camera %p?", mCamera.get());
34954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return -EBUSY;
35054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
35154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
35254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
35354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
35454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
35554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
35654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the requested video frame size
35754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * has been successfully configured or not. If both width and height
35854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * are -1, check on the current width and height value setting
35954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is performed.
36054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
36154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
36254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame width in pixels to check against
36354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame height in pixels to check against
36454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error
36554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
36654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkVideoSize(
36754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
36854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height) {
36954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
3703bd3020c00ec8264ac1fe3870800f326487f9221James Dong    LOGV("checkVideoSize");
371f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // The actual video size is the same as the preview size
372f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // if the camera hal does not support separate video and
373f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // preview output. In this case, we retrieve the video
374f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // size from preview.
37554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameWidthActual = -1;
37654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameHeightActual = -1;
377f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    Vector<Size> sizes;
378f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    params.getSupportedVideoSizes(sizes);
379f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    if (sizes.size() == 0) {
380f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size is the same as preview size
381f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getPreviewSize(&frameWidthActual, &frameHeightActual);
382f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    } else {
383f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size may not be the same as preview
384f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getVideoSize(&frameWidthActual, &frameHeightActual);
385f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    }
38654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameWidthActual < 0 || frameHeightActual < 0) {
38754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to retrieve video frame size (%dx%d)",
38854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                frameWidthActual, frameHeightActual);
38954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
39054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
39154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
39254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame size against the target/requested
39354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame size.
39454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
39554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (frameWidthActual != width || frameHeightActual != height) {
39654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Failed to set video frame size to %dx%d. "
39754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    "The actual video size is %dx%d ", width, height,
39854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameWidthActual, frameHeightActual);
39954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return UNKNOWN_ERROR;
40054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
40154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
40254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
40354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
40454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width = frameWidthActual;
40554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = frameHeightActual;
40654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
40754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
40854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
40954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
41054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check the requested frame rate has been successfully configured or not.
41154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the target frameRate is -1, check on the current frame rate value
41254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * setting is performed.
41354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
41454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
41554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame rate to check against
41654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
41754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
41854ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkFrameRate(
41954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
42054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
42154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
4223bd3020c00ec8264ac1fe3870800f326487f9221James Dong    LOGV("checkFrameRate");
42354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRateActual = params.getPreviewFrameRate();
42454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRateActual < 0) {
42554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
42654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
42754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
42854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
42954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame rate against the target/requested
43054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame rate.
43154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
43254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to set preview frame rate to %d fps. The actual "
43354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                "frame rate is %d", frameRate, frameRateActual);
43454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
43554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
43654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
43754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
43854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoFrameRate = frameRateActual;
43954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
44054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
44154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
44254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
44354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Initialize the CameraSource to so that it becomes
44454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * ready for providing the video input streams as requested.
44554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param camera the camera object used for the video source
44654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param cameraId if camera == 0, use camera with this id
44754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      as the video source
44854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param videoSize the target video frame size. If both
44954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and height in videoSize is -1, use the current
45054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and heigth settings by the camera
45154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
45254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      if it is -1, use the current camera frame rate setting.
4535c9523154d106b555db6c41f85ab205a4f189b02James Dong * @param storeMetaDataInVideoBuffers request to store meta
4545c9523154d106b555db6c41f85ab205a4f189b02James Dong *      data or real YUV data in video buffers. Request to
4555c9523154d106b555db6c41f85ab205a4f189b02James Dong *      store meta data in video buffers may not be honored
4565c9523154d106b555db6c41f85ab205a4f189b02James Dong *      if the source does not support this feature.
4575c9523154d106b555db6c41f85ab205a4f189b02James Dong *
45854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
45954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
46054ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::init(
46154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const sp<ICamera>& camera,
4624ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        const sp<ICameraRecordingProxy>& proxy,
46354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t cameraId,
46454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        Size videoSize,
4655c9523154d106b555db6c41f85ab205a4f189b02James Dong        int32_t frameRate,
4665c9523154d106b555db6c41f85ab205a4f189b02James Dong        bool storeMetaDataInVideoBuffers) {
46754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
4683bd3020c00ec8264ac1fe3870800f326487f9221James Dong    LOGV("init");
46954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    status_t err = OK;
470ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
471ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    err = initWithCameraAccess(camera, proxy, cameraId,
472ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               videoSize, frameRate,
473ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               storeMetaDataInVideoBuffers);
474ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
475ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    return err;
476ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong}
477ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong
478ae4c1ac6401185539c03ce0819e174fd1b04b136James Dongstatus_t CameraSource::initWithCameraAccess(
479ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        const sp<ICamera>& camera,
480ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        const sp<ICameraRecordingProxy>& proxy,
481ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t cameraId,
482ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        Size videoSize,
483ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t frameRate,
484ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        bool storeMetaDataInVideoBuffers) {
4853bd3020c00ec8264ac1fe3870800f326487f9221James Dong    LOGV("initWithCameraAccess");
486ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    status_t err = OK;
4879d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
4884ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
4894ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        LOGE("Camera connection could not be established.");
49054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
49154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
49254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters params(mCamera->getParameters());
49354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = isCameraColorFormatSupported(params)) != OK) {
49454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
49554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
496be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
49754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Set the camera to use the requested video frame size
49854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // and/or frame rate.
49954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = configureCamera(&params,
50054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    videoSize.width, videoSize.height,
50154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameRate))) {
50254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
50354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
504653252be963c07c99109d20f942d1f30c52a9360James Dong
50554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check on video frame size and frame rate.
50654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters newCameraParams(mCamera->getParameters());
50754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkVideoSize(newCameraParams,
50854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                videoSize.width, videoSize.height)) != OK) {
50954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
51054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
51154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
51254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
51354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
51454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
51554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // This CHECK is good, since we just passed the lock/unlock
51654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // check earlier by calling mCamera->setParameters().
51754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CHECK_EQ(OK, mCamera->setPreviewDisplay(mSurface));
5182b37ced30f89437c804c3945b901019b86d210aeJames Dong
519abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    // By default, do not store metadata in video buffers
5205c9523154d106b555db6c41f85ab205a4f189b02James Dong    mIsMetaDataStoredInVideoBuffers = false;
521abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    mCamera->storeMetaDataInBuffers(false);
522abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    if (storeMetaDataInVideoBuffers) {
523abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong        if (OK == mCamera->storeMetaDataInBuffers(true)) {
524abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong            mIsMetaDataStoredInVideoBuffers = true;
525abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong        }
5265c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
5275c9523154d106b555db6c41f85ab205a4f189b02James Dong
52854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
529f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (glitchDurationUs > mGlitchDurationThresholdUs) {
530f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mGlitchDurationThresholdUs = glitchDurationUs;
531f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
532f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
533ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // XXX: query camera for the stride and slice height
534ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // when the capability becomes available.
535653252be963c07c99109d20f942d1f30c52a9360James Dong    mMeta = new MetaData;
53654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setCString(kKeyMIMEType,  MEDIA_MIMETYPE_VIDEO_RAW);
53754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyColorFormat, mColorFormat);
53854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyWidth,       mVideoSize.width);
53954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyHeight,      mVideoSize.height);
54054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyStride,      mVideoSize.width);
54154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
542393410a441b6d06daf286ed496470e9d6b2b6ca8James Dong    mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
54354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource::~CameraSource() {
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
549ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    } else if (mInitCheck == OK) {
550ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera is initialized but because start() is never called,
551ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // the lock on Camera is never released(). This makes sure
552ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera's lock is released in this case.
553ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        releaseCamera();
55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::startCameraRecording() {
5583bd3020c00ec8264ac1fe3870800f326487f9221James Dong    LOGV("startCameraRecording");
5594ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // Reset the identity to the current thread because media server owns the
5604ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // camera and recording is started by the applications. The applications
5614ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // will connect to the camera in ICameraRecordingProxy::startRecording.
5624ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    int64_t token = IPCThreadState::self()->clearCallingIdentity();
5633bd3020c00ec8264ac1fe3870800f326487f9221James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
5643bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->unlock();
5653bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera.clear();
5663bd3020c00ec8264ac1fe3870800f326487f9221James Dong        CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
5673bd3020c00ec8264ac1fe3870800f326487f9221James Dong    } else {
5683bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->setListener(new CameraSourceListener(this));
5693bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->startRecording();
5703bd3020c00ec8264ac1fe3870800f326487f9221James Dong        CHECK(mCamera->recordingEnabled());
5713bd3020c00ec8264ac1fe3870800f326487f9221James Dong    }
5724ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    IPCThreadState::self()->restoreCallingIdentity(token);
57365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
57465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
575f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongstatus_t CameraSource::start(MetaData *meta) {
5763bd3020c00ec8264ac1fe3870800f326487f9221James Dong    LOGV("start");
5770c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mStarted);
57854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mInitCheck != OK) {
57954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("CameraSource is not initialized yet");
58054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return mInitCheck;
58154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
583365a963142093a1cd8efdcea76b5f65096a5b115James Dong    char value[PROPERTY_VALUE_MAX];
584365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
585365a963142093a1cd8efdcea76b5f65096a5b115James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
586365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mCollectStats = true;
587365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
5889d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
589f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
590f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t startTimeUs;
591f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (meta && meta->findInt64(kKeyTime, &startTimeUs)) {
592f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs = startTimeUs;
593f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
594f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
595c42478ed7b8a379d2f8a43d4d349680c8a37573fJames Dong    startCameraRecording();
59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::stopCameraRecording() {
6023bd3020c00ec8264ac1fe3870800f326487f9221James Dong    LOGV("stopCameraRecording");
6033bd3020c00ec8264ac1fe3870800f326487f9221James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
6043bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCameraRecordingProxy->stopRecording();
6053bd3020c00ec8264ac1fe3870800f326487f9221James Dong    } else {
6063bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->setListener(NULL);
6073bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->stopRecording();
6083bd3020c00ec8264ac1fe3870800f326487f9221James Dong    }
60965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
61065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
611ea7b485595f8cec6a66668b5c54c8f297d843f77James Dongvoid CameraSource::releaseCamera() {
612ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    LOGV("releaseCamera");
61395068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mCamera != 0) {
614ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
61595068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
61695068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li            LOGV("Camera was cold when we started, stopping preview");
61795068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li            mCamera->stopPreview();
61895068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li            mCamera->disconnect();
61995068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        }
6203bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->unlock();
62195068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        mCamera.clear();
6223bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera = 0;
623ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
62495068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    }
62595068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mCameraRecordingProxy != 0) {
62695068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
62795068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        mCameraRecordingProxy.clear();
628ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    }
629ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    mCameraFlags = 0;
630ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong}
631ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::stop() {
63341152efd144ccf70c380d5c9a32105c02a039f43James Dong    LOGD("stop: E");
634c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    Mutex::Autolock autoLock(mLock);
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
636c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    mFrameAvailableCondition.signal();
637365a963142093a1cd8efdcea76b5f65096a5b115James Dong
638c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    releaseQueuedFrames();
6397278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesBeingEncoded.empty()) {
64041152efd144ccf70c380d5c9a32105c02a039f43James Dong        if (NO_ERROR !=
64141152efd144ccf70c380d5c9a32105c02a039f43James Dong            mFrameCompleteCondition.waitRelative(mLock, 3000000000LL)) {
64241152efd144ccf70c380d5c9a32105c02a039f43James Dong            LOGW("Timed out waiting for outstanding frames being encoded: %d",
643365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mFramesBeingEncoded.size());
64441152efd144ccf70c380d5c9a32105c02a039f43James Dong        }
6457278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
646d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    stopCameraRecording();
647ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    releaseCamera();
6487278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
649365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mCollectStats) {
650365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
651365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
652365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mLastFrameTimestampUs - mFirstFrameTimeUs);
653365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
65413aec890216948b0c364f8f92792129d0335f506James Dong
655ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    if (mNumGlitches > 0) {
656a472613aec322e25891abf5c77bf3f7e3c244920James Dong        LOGW("%d long delays between neighboring video frames", mNumGlitches);
657ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    }
658ba29002c7aee13c068049037cd14bba6a244da6bJames Dong
65913aec890216948b0c364f8f92792129d0335f506James Dong    CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
66041152efd144ccf70c380d5c9a32105c02a039f43James Dong    LOGD("stop: X");
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
6653bd3020c00ec8264ac1fe3870800f326487f9221James Dong    LOGV("releaseRecordingFrame");
6664ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    if (mCameraRecordingProxy != NULL) {
6674ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy->releaseRecordingFrame(frame);
6683bd3020c00ec8264ac1fe3870800f326487f9221James Dong    } else {
6693bd3020c00ec8264ac1fe3870800f326487f9221James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
6703bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->releaseRecordingFrame(frame);
6713bd3020c00ec8264ac1fe3870800f326487f9221James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
672d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    }
67365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
67465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
675c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::releaseQueuedFrames() {
676c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    List<sp<IMemory> >::iterator it;
6777278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesReceived.empty()) {
6787278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        it = mFramesReceived.begin();
67965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseRecordingFrame(*it);
6807278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        mFramesReceived.erase(it);
68113aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesDropped;
682c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
683c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong}
684c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> CameraSource::getFormat() {
686653252be963c07c99109d20f942d1f30c52a9360James Dong    return mMeta;
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
689f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
69065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    releaseRecordingFrame(frame);
691f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong}
692f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
6937278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) {
6947278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    LOGV("signalBufferReturned: %p", buffer->data());
69556223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber    Mutex::Autolock autoLock(mLock);
6967278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
6977278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong         it != mFramesBeingEncoded.end(); ++it) {
6987278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        if ((*it)->pointer() ==  buffer->data()) {
699f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            releaseOneRecordingFrame((*it));
7007278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFramesBeingEncoded.erase(it);
7017278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            ++mNumFramesEncoded;
7027278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->setObserver(0);
7037278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->release();
7047278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFrameCompleteCondition.signal();
7057278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            return;
7067278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        }
7077278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
7087278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    CHECK_EQ(0, "signalBufferReturned: bogus buffer");
7097278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong}
7107278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::read(
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
713c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    LOGV("read");
71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *buffer = NULL;
71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
718abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
719abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
72020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_UNSUPPORTED;
72120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
72220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<IMemory> frame;
724be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    int64_t frameTime;
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    {
72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Mutex::Autolock autoLock(mLock);
72879e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        while (mStarted && mFramesReceived.empty()) {
72941152efd144ccf70c380d5c9a32105c02a039f43James Dong            if (NO_ERROR !=
7304ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                mFrameAvailableCondition.waitRelative(mLock, 1000000000LL)) {
7313bd3020c00ec8264ac1fe3870800f326487f9221James Dong                if (mCameraRecordingProxy != 0 &&
7323bd3020c00ec8264ac1fe3870800f326487f9221James Dong                    !mCameraRecordingProxy->asBinder()->isBinderAlive()) {
7334ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                    LOGW("camera recording proxy is gone");
7344ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                    return ERROR_END_OF_STREAM;
7354ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                }
73641152efd144ccf70c380d5c9a32105c02a039f43James Dong                LOGW("Timed out waiting for incoming camera video frames: %lld us",
73741152efd144ccf70c380d5c9a32105c02a039f43James Dong                    mLastFrameTimestampUs);
73841152efd144ccf70c380d5c9a32105c02a039f43James Dong            }
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
74079e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        if (!mStarted) {
74179e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong            return OK;
74279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        }
74379e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frame = *mFramesReceived.begin();
74479e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesReceived.erase(mFramesReceived.begin());
74579e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong
74679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frameTime = *mFrameTimes.begin();
74779e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFrameTimes.erase(mFrameTimes.begin());
74879e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesBeingEncoded.push_back(frame);
74979e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        *buffer = new MediaBuffer(frame->pointer(), frame->size());
75079e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->setObserver(this);
75179e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->add_ref();
75279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
7537278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
757c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs,
758c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        int32_t msgType, const sp<IMemory> &data) {
759c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
761a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
762a472613aec322e25891abf5c77bf3f7e3c244920James Dong        LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
763f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        releaseOneRecordingFrame(data);
764c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        return;
765c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76798cfde007490a5903b729a4718c0dada755ae8f8James Dong    if (mNumFramesReceived > 0) {
76898cfde007490a5903b729a4718c0dada755ae8f8James Dong        CHECK(timestampUs > mLastFrameTimestampUs);
76998cfde007490a5903b729a4718c0dada755ae8f8James Dong        if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
77098cfde007490a5903b729a4718c0dada755ae8f8James Dong            ++mNumGlitches;
771f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
772f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
773f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
77465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // May need to skip frame or modify timestamp. Currently implemented
77565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // by the subclass CameraSourceTimeLapse.
77679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong    if (skipCurrentFrame(timestampUs)) {
77765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseOneRecordingFrame(data);
77865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return;
779fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra    }
780fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra
781365a963142093a1cd8efdcea76b5f65096a5b115James Dong    mLastFrameTimestampUs = timestampUs;
78213aec890216948b0c364f8f92792129d0335f506James Dong    if (mNumFramesReceived == 0) {
783c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        mFirstFrameTimeUs = timestampUs;
784f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        // Initial delay
785f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        if (mStartTimeUs > 0) {
786f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            if (timestampUs < mStartTimeUs) {
787f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Frame was captured before recording was started
788f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Drop it without updating the statistical data.
789f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                releaseOneRecordingFrame(data);
790f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                return;
791f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            }
792f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimeUs = timestampUs - mStartTimeUs;
793f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
794be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    }
79513aec890216948b0c364f8f92792129d0335f506James Dong    ++mNumFramesReceived;
796be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
79798cfde007490a5903b729a4718c0dada755ae8f8James Dong    CHECK(data != NULL && data->size() > 0);
7987278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    mFramesReceived.push_back(data);
799f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
800f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mFrameTimes.push_back(timeUs);
801f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGV("initial delay: %lld, current time stamp: %lld",
802f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs, timeUs);
80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFrameAvailableCondition.signal();
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8065c9523154d106b555db6c41f85ab205a4f189b02James Dongbool CameraSource::isMetaDataStoredInVideoBuffers() const {
8075c9523154d106b555db6c41f85ab205a4f189b02James Dong    LOGV("isMetaDataStoredInVideoBuffers");
8085c9523154d106b555db6c41f85ab205a4f189b02James Dong    return mIsMetaDataStoredInVideoBuffers;
8095c9523154d106b555db6c41f85ab205a4f189b02James Dong}
8105c9523154d106b555db6c41f85ab205a4f189b02James Dong
8114ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng LiCameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
8124ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource = source;
8134ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
8144ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
8154ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::ProxyListener::dataCallbackTimestamp(
8164ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
8174ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
8184ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
8194ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
8204ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
8214ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    LOGI("Camera recording proxy died");
8224ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
8234ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
825