CameraSource.cpp revision 5c9523154d106b555db6c41f85ab205a4f189b02
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);
40be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr);
41be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
42be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void postDataTimestamp(
43be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber            nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
44be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
45be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberprotected:
46be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual ~CameraSourceListener();
47be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
49be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    wp<CameraSource> mSource;
50be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
51be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const CameraSourceListener &);
52be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener &operator=(const CameraSourceListener &);
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
56be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    : mSource(source) {
57be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::~CameraSourceListener() {
60be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
63be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    LOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
64be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr) {
67be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    LOGV("postData(%d, ptr:%p, size:%d)",
68be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber         msgType, dataPtr->pointer(), dataPtr->size());
6965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
7065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<CameraSource> source = mSource.promote();
7165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (source.get() != NULL) {
7265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        source->dataCallback(msgType, dataPtr);
7365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
74be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
75be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
76be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postDataTimestamp(
77be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
78c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
79c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    sp<CameraSource> source = mSource.promote();
80c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (source.get() != NULL) {
81c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
82c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
83be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85653252be963c07c99109d20f942d1f30c52a9360James Dongstatic int32_t getColorFormat(const char* colorFormat) {
86e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
87e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong       return OMX_COLOR_FormatYUV420Planar;
88e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    }
89e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong
90653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
91653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_FormatYUV422SemiPlanar;
92653252be963c07c99109d20f942d1f30c52a9360James Dong    }
93653252be963c07c99109d20f942d1f30c52a9360James Dong
94653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
95653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYUV420SemiPlanar;
96653252be963c07c99109d20f942d1f30c52a9360James Dong    }
97653252be963c07c99109d20f942d1f30c52a9360James Dong
98653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
99653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYCbYCr;
100653252be963c07c99109d20f942d1f30c52a9360James Dong    }
101653252be963c07c99109d20f942d1f30c52a9360James Dong
102653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
103653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_Format16bitRGB565;
104653252be963c07c99109d20f942d1f30c52a9360James Dong    }
105653252be963c07c99109d20f942d1f30c52a9360James Dong
106a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong    LOGE("Uknown color format (%s), please add it to "
107a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong         "CameraSource::getColorFormat", colorFormat);
108a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong
109653252be963c07c99109d20f942d1f30c52a9360James Dong    CHECK_EQ(0, "Unknown color format");
110653252be963c07c99109d20f942d1f30c52a9360James Dong}
111653252be963c07c99109d20f942d1f30c52a9360James Dong
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource *CameraSource::Create() {
11354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size size;
11454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.width = -1;
11554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.height = -1;
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    sp<ICamera> camera;
1185c9523154d106b555db6c41f85ab205a4f189b02James Dong    return new CameraSource(camera, 0, size, -1, NULL, false);
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12130ab66297501757d745b9ae10da61adcd891f497Andreas Huber// static
12254ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource *CameraSource::CreateFromCamera(
12354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
12454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
12554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
12654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
1275c9523154d106b555db6c41f85ab205a4f189b02James Dong    const sp<Surface>& surface,
1285c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers) {
12954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
13054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraSource *source = new CameraSource(camera, cameraId,
1315c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate, surface,
1325c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
13354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
13454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (source != NULL) {
13554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (source->initCheck() != OK) {
13654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            delete source;
13754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return NULL;
13854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
13930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
14054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return source;
14130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
14230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
14354ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource::CameraSource(
14454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
14554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
14654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
14754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
1485c9523154d106b555db6c41f85ab205a4f189b02James Dong    const sp<Surface>& surface,
1495c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers)
15054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    : mCameraFlags(0),
15154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mVideoFrameRate(-1),
15254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mCamera(0),
15354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mSurface(surface),
15413aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesReceived(0),
15565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mLastFrameTimestampUs(0),
15665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mStarted(false),
15765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mFirstFrameTimeUs(0),
15813aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesEncoded(0),
15913aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesDropped(0),
160f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mNumGlitches(0),
161f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mGlitchDurationThresholdUs(200000),
16265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mCollectStats(false) {
1639d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
16454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width  = -1;
16554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = -1;
16654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1675c9523154d106b555db6c41f85ab205a4f189b02James Dong    mInitCheck = init(camera, cameraId,
1685c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate,
1695c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
17054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
17154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
17254ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::initCheck() const {
17354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return mInitCheck;
17454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
17554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
17654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraAvailable(
17754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera, int32_t cameraId) {
17854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
17954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (camera == 0) {
18054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::connect(cameraId);
18154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags &= ~FLAGS_HOT_CAMERA;
18254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {
18354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::create(camera);
18454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags |= FLAGS_HOT_CAMERA;
18554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
18654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
18754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Is camera available?
18854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mCamera == 0) {
18954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Camera connection could not be established.");
19054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return -EBUSY;
19154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
19254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (!(mCameraFlags & FLAGS_HOT_CAMERA)) {
19354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera->lock();
19454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
19554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
19654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
19754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
19854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
19954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
20054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check to see whether the requested video width and height is one
20154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * of the supported sizes.
20254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the video frame width in pixels
20354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the video frame height in pixels
20454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param suppportedSizes the vector of sizes that we check against
20554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return true if the dimension (width and height) is supported.
20654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
20754ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic bool isVideoSizeSupported(
20854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t width, int32_t height,
20954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const Vector<Size>& supportedSizes) {
21054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
21154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    LOGV("isVideoSizeSupported");
21254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    for (size_t i = 0; i < supportedSizes.size(); ++i) {
21354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (width  == supportedSizes[i].width &&
21454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            height == supportedSizes[i].height) {
21554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return true;
21654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
21754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
21854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return false;
21954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
22054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
22154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
22254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the preview and video output is separate, we only set the
22354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * the video size, and applications should set the preview size
22454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * to some proper value, and the recording framework will not
22554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * change the preview size; otherwise, if the video and preview
22654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * output is the same, we need to set the preview to be the same
22754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * as the requested video size.
22854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
22954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
23054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
23154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Query the camera to retrieve the supported video frame sizes
23254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * and also to see whether CameraParameters::setVideoSize()
23354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is supported or not.
23454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
23554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @@param isSetVideoSizeSupported retunrs whether method
23654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      CameraParameters::setVideoSize() is supported or not.
23754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param sizes returns the vector of Size objects for the
23854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      supported video frame sizes advertised by the camera.
23954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
24054ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic void getSupportedVideoSizes(
24154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const CameraParameters& params,
24254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool *isSetVideoSizeSupported,
24354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size>& sizes) {
24454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
24554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    *isSetVideoSizeSupported = true;
24654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    params.getSupportedVideoSizes(sizes);
24754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (sizes.size() == 0) {
24854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGD("Camera does not support setVideoSize()");
24954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params.getSupportedPreviewSizes(sizes);
25054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        *isSetVideoSizeSupported = false;
25154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
25254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
25354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
25454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
25554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the camera has the supported color format
25654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
25754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
25854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
25954ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraColorFormatSupported(
26054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params) {
26154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mColorFormat = getColorFormat(params.get(
26254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            CameraParameters::KEY_VIDEO_FRAME_FORMAT));
26354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mColorFormat == -1) {
26454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
26554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
26654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
26754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
26854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
26954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
27054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Configure the camera to use the requested video size
27154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * (width and height) and/or frame rate. If both width and
27254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * height are -1, configuration on the video size is skipped.
27354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * if frameRate is -1, configuration on the frame rate
27454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is skipped. Skipping the configuration allows one to
27554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * use the current camera setting without the need to
27654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * actually know the specific values (see Create() method).
27754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
27854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params the CameraParameters to be configured
27954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the target video frame width in pixels
28054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the target video frame height in pixels
28154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
28254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
28354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
28454ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::configureCamera(
28554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        CameraParameters* params,
28654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height,
28754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
28854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
28954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size> sizes;
29054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isSetVideoSizeSupportedByCamera = true;
29154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
29254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isCameraParamChanged = false;
29354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
29454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (!isVideoSizeSupported(width, height, sizes)) {
29554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Video dimension (%dx%d) is unsupported", width, height);
29654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return BAD_VALUE;
29754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
29854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (isSetVideoSizeSupportedByCamera) {
29954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setVideoSize(width, height);
30054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        } else {
30154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setPreviewSize(width, height);
30254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
30354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
30454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else if ((width == -1 && height != -1) ||
30554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong               (width != -1 && height == -1)) {
30654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // If one and only one of the width and height is -1
30754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // we reject such a request.
30854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Requested video size (%dx%d) is not supported", width, height);
30954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
31054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // width == -1 && height == -1
31154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
31254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current width and height value setting from the camera.
31354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
31454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
31554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1) {
31654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params->setPreviewFrameRate(frameRate);
31754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
31854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // frameRate == -1
31954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
32054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current frame rate value setting from the camera
32154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
32254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
32354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (isCameraParamChanged) {
32454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Either frame rate or frame size needs to be changed.
32554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        String8 s = params->flatten();
32654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (OK != mCamera->setParameters(s)) {
32754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Could not change settings."
32854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                 " Someone else is using camera %p?", mCamera.get());
32954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return -EBUSY;
33054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
33154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
33254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
33354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
33454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
33554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
33654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the requested video frame size
33754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * has been successfully configured or not. If both width and height
33854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * are -1, check on the current width and height value setting
33954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is performed.
34054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
34154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
34254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame width in pixels to check against
34354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame height in pixels to check against
34454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error
34554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
34654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkVideoSize(
34754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
34854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height) {
34954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
35054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameWidthActual = -1;
35154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameHeightActual = -1;
35254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    params.getPreviewSize(&frameWidthActual, &frameHeightActual);
35354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameWidthActual < 0 || frameHeightActual < 0) {
35454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to retrieve video frame size (%dx%d)",
35554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                frameWidthActual, frameHeightActual);
35654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
35754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
35854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
35954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame size against the target/requested
36054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame size.
36154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
36254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (frameWidthActual != width || frameHeightActual != height) {
36354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Failed to set video frame size to %dx%d. "
36454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    "The actual video size is %dx%d ", width, height,
36554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameWidthActual, frameHeightActual);
36654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return UNKNOWN_ERROR;
36754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
36854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
36954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
37054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
37154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width = frameWidthActual;
37254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = frameHeightActual;
37354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
37454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
37554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
37654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
37754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check the requested frame rate has been successfully configured or not.
37854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the target frameRate is -1, check on the current frame rate value
37954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * setting is performed.
38054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
38154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
38254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame rate to check against
38354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
38454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
38554ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkFrameRate(
38654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
38754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
38854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
38954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRateActual = params.getPreviewFrameRate();
39054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRateActual < 0) {
39154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
39254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
39354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
39454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
39554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame rate against the target/requested
39654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame rate.
39754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
39854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to set preview frame rate to %d fps. The actual "
39954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                "frame rate is %d", frameRate, frameRateActual);
40054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
40154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
40254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
40354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
40454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoFrameRate = frameRateActual;
40554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
40654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
40754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
40854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
40954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Initialize the CameraSource to so that it becomes
41054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * ready for providing the video input streams as requested.
41154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param camera the camera object used for the video source
41254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param cameraId if camera == 0, use camera with this id
41354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      as the video source
41454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param videoSize the target video frame size. If both
41554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and height in videoSize is -1, use the current
41654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and heigth settings by the camera
41754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
41854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      if it is -1, use the current camera frame rate setting.
4195c9523154d106b555db6c41f85ab205a4f189b02James Dong * @param storeMetaDataInVideoBuffers request to store meta
4205c9523154d106b555db6c41f85ab205a4f189b02James Dong *      data or real YUV data in video buffers. Request to
4215c9523154d106b555db6c41f85ab205a4f189b02James Dong *      store meta data in video buffers may not be honored
4225c9523154d106b555db6c41f85ab205a4f189b02James Dong *      if the source does not support this feature.
4235c9523154d106b555db6c41f85ab205a4f189b02James Dong *
42454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
42554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
42654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::init(
42754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const sp<ICamera>& camera,
42854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t cameraId,
42954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        Size videoSize,
4305c9523154d106b555db6c41f85ab205a4f189b02James Dong        int32_t frameRate,
4315c9523154d106b555db6c41f85ab205a4f189b02James Dong        bool storeMetaDataInVideoBuffers) {
43254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
43354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    status_t err = OK;
4349d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
4359d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
43654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err  = isCameraAvailable(camera, cameraId)) != OK) {
43754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
43854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
43954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters params(mCamera->getParameters());
44054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = isCameraColorFormatSupported(params)) != OK) {
44154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
44254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
443be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
44454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Set the camera to use the requested video frame size
44554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // and/or frame rate.
44654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = configureCamera(&params,
44754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    videoSize.width, videoSize.height,
44854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameRate))) {
44954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
45054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
451653252be963c07c99109d20f942d1f30c52a9360James Dong
45254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check on video frame size and frame rate.
45354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters newCameraParams(mCamera->getParameters());
45454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkVideoSize(newCameraParams,
45554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                videoSize.width, videoSize.height)) != OK) {
45654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
45754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
45854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
45954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
46054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
46154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
46254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // This CHECK is good, since we just passed the lock/unlock
46354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // check earlier by calling mCamera->setParameters().
46454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CHECK_EQ(OK, mCamera->setPreviewDisplay(mSurface));
4652b37ced30f89437c804c3945b901019b86d210aeJames Dong
4665c9523154d106b555db6c41f85ab205a4f189b02James Dong    mIsMetaDataStoredInVideoBuffers = false;
4675c9523154d106b555db6c41f85ab205a4f189b02James Dong    if (storeMetaDataInVideoBuffers &&
4685c9523154d106b555db6c41f85ab205a4f189b02James Dong        OK == mCamera->storeMetaDataInBuffers(true)) {
4695c9523154d106b555db6c41f85ab205a4f189b02James Dong        mIsMetaDataStoredInVideoBuffers = true;
4705c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
4715c9523154d106b555db6c41f85ab205a4f189b02James Dong
4722b37ced30f89437c804c3945b901019b86d210aeJames Dong    /*
4732b37ced30f89437c804c3945b901019b86d210aeJames Dong     * mCamera->startRecording() signals camera hal to make
4742b37ced30f89437c804c3945b901019b86d210aeJames Dong     * available the video buffers (for instance, allocation
4752b37ced30f89437c804c3945b901019b86d210aeJames Dong     * of the video buffers may be triggered when camera hal's
4762b37ced30f89437c804c3945b901019b86d210aeJames Dong     * startRecording() method is called). Making available these
4772b37ced30f89437c804c3945b901019b86d210aeJames Dong     * video buffers earlier (before calling start()) is critical,
4782b37ced30f89437c804c3945b901019b86d210aeJames Dong     * if one wants to configure omx video encoders to use these
4792b37ced30f89437c804c3945b901019b86d210aeJames Dong     * buffers for passing video frame data during video recording
4802b37ced30f89437c804c3945b901019b86d210aeJames Dong     * without the need to memcpy the video frame data stored
4812b37ced30f89437c804c3945b901019b86d210aeJames Dong     * in these buffers. Eliminating memcpy for video frame data
4822b37ced30f89437c804c3945b901019b86d210aeJames Dong     * is crucial in performance for HD quality video recording
4832b37ced30f89437c804c3945b901019b86d210aeJames Dong     * applications.
4842b37ced30f89437c804c3945b901019b86d210aeJames Dong     *
4852b37ced30f89437c804c3945b901019b86d210aeJames Dong     * Based on OMX IL spec, configuring the omx video encoders
4862b37ced30f89437c804c3945b901019b86d210aeJames Dong     * must occur in loaded state. When start() is called, omx
4872b37ced30f89437c804c3945b901019b86d210aeJames Dong     * video encoders are already in idle state, which is too
4882b37ced30f89437c804c3945b901019b86d210aeJames Dong     * late. Thus, we must call mCamera->startRecording() earlier.
4892b37ced30f89437c804c3945b901019b86d210aeJames Dong     */
4902b37ced30f89437c804c3945b901019b86d210aeJames Dong    startCameraRecording();
4912b37ced30f89437c804c3945b901019b86d210aeJames Dong
49254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
49354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
49454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
495f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (glitchDurationUs > mGlitchDurationThresholdUs) {
496f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mGlitchDurationThresholdUs = glitchDurationUs;
497f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
498f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
499ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // XXX: query camera for the stride and slice height
500ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // when the capability becomes available.
501653252be963c07c99109d20f942d1f30c52a9360James Dong    mMeta = new MetaData;
50254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setCString(kKeyMIMEType,  MEDIA_MIMETYPE_VIDEO_RAW);
50354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyColorFormat, mColorFormat);
50454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyWidth,       mVideoSize.width);
50554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyHeight,      mVideoSize.height);
50654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyStride,      mVideoSize.width);
50754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
50854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource::~CameraSource() {
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::startCameraRecording() {
51865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    CHECK_EQ(OK, mCamera->startRecording());
5192b37ced30f89437c804c3945b901019b86d210aeJames Dong    CHECK(mCamera->recordingEnabled());
52065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
52165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
522f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongstatus_t CameraSource::start(MetaData *meta) {
5230c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mStarted);
52454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mInitCheck != OK) {
52554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("CameraSource is not initialized yet");
52654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return mInitCheck;
52754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
529365a963142093a1cd8efdcea76b5f65096a5b115James Dong    char value[PROPERTY_VALUE_MAX];
530365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
531365a963142093a1cd8efdcea76b5f65096a5b115James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
532365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mCollectStats = true;
533365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
5349d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
535f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
536f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t startTimeUs;
537f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (meta && meta->findInt64(kKeyTime, &startTimeUs)) {
538f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs = startTimeUs;
539f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
540f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
5419d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
542be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    mCamera->setListener(new CameraSourceListener(this));
5439d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::stopCameraRecording() {
55078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mCamera->setListener(NULL);
55165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    mCamera->stopRecording();
55265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
55365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::stop() {
555c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    LOGV("stop");
556c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    Mutex::Autolock autoLock(mLock);
55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
558c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    mFrameAvailableCondition.signal();
559365a963142093a1cd8efdcea76b5f65096a5b115James Dong
5609d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
56165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    stopCameraRecording();
562c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    releaseQueuedFrames();
5637278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesBeingEncoded.empty()) {
564365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("Waiting for outstanding frames being encoded: %d",
565365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mFramesBeingEncoded.size());
5667278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        mFrameCompleteCondition.wait(mLock);
5677278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
56854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
56954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    LOGV("Disconnect camera");
57054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
57154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGV("Camera was cold when we started, stopping preview");
57254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera->stopPreview();
57354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
57454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mCamera->unlock();
57554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mCamera.clear();
57654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mCamera = 0;
57754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mCameraFlags = 0;
5789d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
5797278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
580365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mCollectStats) {
581365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
582365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
583365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mLastFrameTimestampUs - mFirstFrameTimeUs);
584365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
58513aec890216948b0c364f8f92792129d0335f506James Dong
58613aec890216948b0c364f8f92792129d0335f506James Dong    CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
59165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    mCamera->releaseRecordingFrame(frame);
59265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
59365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
594c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::releaseQueuedFrames() {
595c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    List<sp<IMemory> >::iterator it;
5967278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesReceived.empty()) {
5977278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        it = mFramesReceived.begin();
59865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseRecordingFrame(*it);
5997278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        mFramesReceived.erase(it);
60013aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesDropped;
601c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
602c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong}
603c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> CameraSource::getFormat() {
605653252be963c07c99109d20f942d1f30c52a9360James Dong    return mMeta;
60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
608f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
609f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
61065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    releaseRecordingFrame(frame);
611f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
612f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong}
613f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
6147278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) {
6157278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    LOGV("signalBufferReturned: %p", buffer->data());
61656223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber    Mutex::Autolock autoLock(mLock);
6177278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
6187278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong         it != mFramesBeingEncoded.end(); ++it) {
6197278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        if ((*it)->pointer() ==  buffer->data()) {
620f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            releaseOneRecordingFrame((*it));
6217278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFramesBeingEncoded.erase(it);
6227278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            ++mNumFramesEncoded;
6237278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->setObserver(0);
6247278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->release();
6257278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFrameCompleteCondition.signal();
6267278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            return;
6277278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        }
6287278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
6297278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    CHECK_EQ(0, "signalBufferReturned: bogus buffer");
6307278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong}
6317278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::read(
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
634c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    LOGV("read");
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *buffer = NULL;
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
639abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
640abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_UNSUPPORTED;
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<IMemory> frame;
645be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    int64_t frameTime;
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    {
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Mutex::Autolock autoLock(mLock);
649542db5d438988360d491a5add1040a2df9aa90c9James Dong        while (mStarted) {
650542db5d438988360d491a5add1040a2df9aa90c9James Dong            while(mFramesReceived.empty()) {
651542db5d438988360d491a5add1040a2df9aa90c9James Dong                mFrameAvailableCondition.wait(mLock);
652542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
653542db5d438988360d491a5add1040a2df9aa90c9James Dong
654542db5d438988360d491a5add1040a2df9aa90c9James Dong            if (!mStarted) {
655542db5d438988360d491a5add1040a2df9aa90c9James Dong                return OK;
656542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
657542db5d438988360d491a5add1040a2df9aa90c9James Dong
658542db5d438988360d491a5add1040a2df9aa90c9James Dong            frame = *mFramesReceived.begin();
659542db5d438988360d491a5add1040a2df9aa90c9James Dong            mFramesReceived.erase(mFramesReceived.begin());
660542db5d438988360d491a5add1040a2df9aa90c9James Dong
661542db5d438988360d491a5add1040a2df9aa90c9James Dong            frameTime = *mFrameTimes.begin();
662542db5d438988360d491a5add1040a2df9aa90c9James Dong            mFrameTimes.erase(mFrameTimes.begin());
663542db5d438988360d491a5add1040a2df9aa90c9James Dong            int64_t skipTimeUs;
664542db5d438988360d491a5add1040a2df9aa90c9James Dong            if (!options || !options->getSkipFrame(&skipTimeUs)) {
665542db5d438988360d491a5add1040a2df9aa90c9James Dong                skipTimeUs = frameTime;
666542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
667542db5d438988360d491a5add1040a2df9aa90c9James Dong            if (skipTimeUs > frameTime) {
668542db5d438988360d491a5add1040a2df9aa90c9James Dong                LOGV("skipTimeUs: %lld us > frameTime: %lld us",
669542db5d438988360d491a5add1040a2df9aa90c9James Dong                    skipTimeUs, frameTime);
670542db5d438988360d491a5add1040a2df9aa90c9James Dong                releaseOneRecordingFrame(frame);
671542db5d438988360d491a5add1040a2df9aa90c9James Dong                ++mNumFramesDropped;
672542db5d438988360d491a5add1040a2df9aa90c9James Dong                // Safeguard against the abuse of the kSkipFrame_Option.
673542db5d438988360d491a5add1040a2df9aa90c9James Dong                if (skipTimeUs - frameTime >= 1E6) {
674542db5d438988360d491a5add1040a2df9aa90c9James Dong                    LOGE("Frame skipping requested is way too long: %lld us",
675542db5d438988360d491a5add1040a2df9aa90c9James Dong                        skipTimeUs - frameTime);
676542db5d438988360d491a5add1040a2df9aa90c9James Dong                    return UNKNOWN_ERROR;
677542db5d438988360d491a5add1040a2df9aa90c9James Dong                }
678542db5d438988360d491a5add1040a2df9aa90c9James Dong            } else {
679542db5d438988360d491a5add1040a2df9aa90c9James Dong                mFramesBeingEncoded.push_back(frame);
680542db5d438988360d491a5add1040a2df9aa90c9James Dong                *buffer = new MediaBuffer(frame->pointer(), frame->size());
681542db5d438988360d491a5add1040a2df9aa90c9James Dong                (*buffer)->setObserver(this);
682542db5d438988360d491a5add1040a2df9aa90c9James Dong                (*buffer)->add_ref();
683542db5d438988360d491a5add1040a2df9aa90c9James Dong                (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
68456223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber
685542db5d438988360d491a5add1040a2df9aa90c9James Dong                return OK;
686542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
6887278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
692c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs,
693c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        int32_t msgType, const sp<IMemory> &data) {
694c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
696c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (!mStarted) {
697f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        releaseOneRecordingFrame(data);
69813aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesReceived;
69913aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesDropped;
700c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        return;
701c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
703f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (mNumFramesReceived > 0 &&
704f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
705f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        if (mNumGlitches % 10 == 0) {  // Don't spam the log
706f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            LOGW("Long delay detected in video recording");
707f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
708f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        ++mNumGlitches;
709f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
710f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
71165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // May need to skip frame or modify timestamp. Currently implemented
71265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // by the subclass CameraSourceTimeLapse.
71365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if(skipCurrentFrame(timestampUs)) {
71465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseOneRecordingFrame(data);
71565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return;
716fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra    }
717fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra
718365a963142093a1cd8efdcea76b5f65096a5b115James Dong    mLastFrameTimestampUs = timestampUs;
71913aec890216948b0c364f8f92792129d0335f506James Dong    if (mNumFramesReceived == 0) {
720c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        mFirstFrameTimeUs = timestampUs;
721f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        // Initial delay
722f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        if (mStartTimeUs > 0) {
723f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            if (timestampUs < mStartTimeUs) {
724f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Frame was captured before recording was started
725f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Drop it without updating the statistical data.
726f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                releaseOneRecordingFrame(data);
727f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                return;
728f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            }
729f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimeUs = timestampUs - mStartTimeUs;
730f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
731be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    }
73213aec890216948b0c364f8f92792129d0335f506James Dong    ++mNumFramesReceived;
733be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
7347278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    mFramesReceived.push_back(data);
735f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
736f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mFrameTimes.push_back(timeUs);
737f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGV("initial delay: %lld, current time stamp: %lld",
738f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs, timeUs);
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFrameAvailableCondition.signal();
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7425c9523154d106b555db6c41f85ab205a4f189b02James Dongsize_t CameraSource::getNumberOfVideoBuffers() const {
7435c9523154d106b555db6c41f85ab205a4f189b02James Dong    LOGV("getNumberOfVideoBuffers");
7445c9523154d106b555db6c41f85ab205a4f189b02James Dong    size_t nBuffers = 0;
7455c9523154d106b555db6c41f85ab205a4f189b02James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
7465c9523154d106b555db6c41f85ab205a4f189b02James Dong    if (mInitCheck == OK && mCamera != 0) {
7475c9523154d106b555db6c41f85ab205a4f189b02James Dong        nBuffers = mCamera->getNumberOfVideoBuffers();
7485c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
7495c9523154d106b555db6c41f85ab205a4f189b02James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
7505c9523154d106b555db6c41f85ab205a4f189b02James Dong    return nBuffers;
7515c9523154d106b555db6c41f85ab205a4f189b02James Dong}
7525c9523154d106b555db6c41f85ab205a4f189b02James Dong
7535c9523154d106b555db6c41f85ab205a4f189b02James Dongsp<IMemory> CameraSource::getVideoBuffer(size_t index) const {
7545c9523154d106b555db6c41f85ab205a4f189b02James Dong    LOGV("getVideoBuffer: %d", index);
7555c9523154d106b555db6c41f85ab205a4f189b02James Dong    sp<IMemory> buffer = 0;
7565c9523154d106b555db6c41f85ab205a4f189b02James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
7575c9523154d106b555db6c41f85ab205a4f189b02James Dong    if (mInitCheck == OK && mCamera != 0) {
7585c9523154d106b555db6c41f85ab205a4f189b02James Dong        buffer = mCamera->getVideoBuffer(index);
7595c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
7605c9523154d106b555db6c41f85ab205a4f189b02James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
7615c9523154d106b555db6c41f85ab205a4f189b02James Dong    return buffer;
7625c9523154d106b555db6c41f85ab205a4f189b02James Dong}
7635c9523154d106b555db6c41f85ab205a4f189b02James Dong
7645c9523154d106b555db6c41f85ab205a4f189b02James Dongbool CameraSource::isMetaDataStoredInVideoBuffers() const {
7655c9523154d106b555db6c41f85ab205a4f189b02James Dong    LOGV("isMetaDataStoredInVideoBuffers");
7665c9523154d106b555db6c41f85ab205a4f189b02James Dong    return mIsMetaDataStoredInVideoBuffers;
7675c9523154d106b555db6c41f85ab205a4f189b02James Dong}
7685c9523154d106b555db6c41f85ab205a4f189b02James Dong
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
770