1e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber/*
2e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Copyright (C) 2009 The Android Open Source Project
3e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
4e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * you may not use this file except in compliance with the License.
6e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * You may obtain a copy of the License at
7e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
8e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
10e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Unless required by applicable law or agreed to in writing, software
11e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * See the License for the specific language governing permissions and
14e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * limitations under the License.
15e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber */
16e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
17b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong//#define LOG_NDEBUG 0
18b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong#define LOG_TAG "CameraSource"
19b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong#include <utils/Log.h>
20e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
21e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <OMX_Component.h>
2271d714ccbf03948d67ab6cebad49703160e5895eJames Dong#include <binder/IPCThreadState.h>
23e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/CameraSource.h>
24b5ceb9ee21f37ae0817c16490c1fc148dd3eb5e2Andreas Huber#include <media/stagefright/MediaDebug.h>
25155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber#include <media/stagefright/MediaDefs.h>
26e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaErrors.h>
27e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MetaData.h>
28000479f9e325b4e426a67033abd92d47da412725Mathias Agopian#include <camera/Camera.h>
29000479f9e325b4e426a67033abd92d47da412725Mathias Agopian#include <camera/CameraParameters.h>
300c128b67f066b2e691348d5375c2da47b84f69acJames Dong#include <surfaceflinger/Surface.h>
31155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber#include <utils/String8.h>
32dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong#include <cutils/properties.h>
33e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
34e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubernamespace android {
35e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
3696af14d9b013496accf40a85a66fefcba3ac0111James Dongstatic const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL;
3796af14d9b013496accf40a85a66fefcba3ac0111James Dong
38155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huberstruct CameraSourceListener : public CameraListener {
39155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    CameraSourceListener(const sp<CameraSource> &source);
40155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber
41155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
42bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li    virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr,
43bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li                          camera_frame_metadata_t *metadata);
44155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber
45155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    virtual void postDataTimestamp(
46155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber            nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
47155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber
48155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huberprotected:
49155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    virtual ~CameraSourceListener();
50155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber
51e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberprivate:
52155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    wp<CameraSource> mSource;
53155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber
54155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    CameraSourceListener(const CameraSourceListener &);
55155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    CameraSourceListener &operator=(const CameraSourceListener &);
56e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber};
57e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
58155e2ad04c9e15562149772fbbaa39004d4778a7Andreas HuberCameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
59155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    : mSource(source) {
60155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber}
61e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
62155e2ad04c9e15562149772fbbaa39004d4778a7Andreas HuberCameraSourceListener::~CameraSourceListener() {
63155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber}
64e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
65155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Hubervoid CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
66155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    LOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
67155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber}
68e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
69bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Livoid CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
70bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li                                    camera_frame_metadata_t *metadata) {
71155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    LOGV("postData(%d, ptr:%p, size:%d)",
72155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber         msgType, dataPtr->pointer(), dataPtr->size());
73f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra
74f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra    sp<CameraSource> source = mSource.promote();
75f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra    if (source.get() != NULL) {
76f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra        source->dataCallback(msgType, dataPtr);
77f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra    }
78155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber}
79155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber
80155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Hubervoid CameraSourceListener::postDataTimestamp(
81155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
82b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong
83b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong    sp<CameraSource> source = mSource.promote();
84b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong    if (source.get() != NULL) {
85b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong        source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
86b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong    }
87155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber}
88e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
89c2f328d0d2821e402823d6e17589da2849b67d0dJames Dongstatic int32_t getColorFormat(const char* colorFormat) {
909b61dc564e673a116928838e42dae25bdf1e0796James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
919b61dc564e673a116928838e42dae25bdf1e0796James Dong       return OMX_COLOR_FormatYUV420Planar;
929b61dc564e673a116928838e42dae25bdf1e0796James Dong    }
939b61dc564e673a116928838e42dae25bdf1e0796James Dong
94c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
95c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong       return OMX_COLOR_FormatYUV422SemiPlanar;
96c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong    }
97c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong
98c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
99c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong        return OMX_COLOR_FormatYUV420SemiPlanar;
100c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong    }
101c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong
102c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
103c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong        return OMX_COLOR_FormatYCbYCr;
104c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong    }
105c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong
106c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
107c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong       return OMX_COLOR_Format16bitRGB565;
108c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong    }
109c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong
110e641dc502bb31d968856a022846414dd8e947e19Dandawate Saket    if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
111e641dc502bb31d968856a022846414dd8e947e19Dandawate Saket       return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
112e641dc502bb31d968856a022846414dd8e947e19Dandawate Saket    }
113e641dc502bb31d968856a022846414dd8e947e19Dandawate Saket
114b5024daa6c49daaf9839923e9665f3a8051cf5d1James Dong    LOGE("Uknown color format (%s), please add it to "
115b5024daa6c49daaf9839923e9665f3a8051cf5d1James Dong         "CameraSource::getColorFormat", colorFormat);
116b5024daa6c49daaf9839923e9665f3a8051cf5d1James Dong
117c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong    CHECK_EQ(0, "Unknown color format");
118c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong}
119c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong
120e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberCameraSource *CameraSource::Create() {
1210c128b67f066b2e691348d5375c2da47b84f69acJames Dong    Size size;
1220c128b67f066b2e691348d5375c2da47b84f69acJames Dong    size.width = -1;
1230c128b67f066b2e691348d5375c2da47b84f69acJames Dong    size.height = -1;
124e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
1250c128b67f066b2e691348d5375c2da47b84f69acJames Dong    sp<ICamera> camera;
12642419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    return new CameraSource(camera, NULL, 0, size, -1, NULL, false);
127e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
128e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
129ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber// static
1300c128b67f066b2e691348d5375c2da47b84f69acJames DongCameraSource *CameraSource::CreateFromCamera(
1310c128b67f066b2e691348d5375c2da47b84f69acJames Dong    const sp<ICamera>& camera,
13242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
1330c128b67f066b2e691348d5375c2da47b84f69acJames Dong    int32_t cameraId,
1340c128b67f066b2e691348d5375c2da47b84f69acJames Dong    Size videoSize,
1350c128b67f066b2e691348d5375c2da47b84f69acJames Dong    int32_t frameRate,
136ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong    const sp<Surface>& surface,
137ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong    bool storeMetaDataInVideoBuffers) {
1380c128b67f066b2e691348d5375c2da47b84f69acJames Dong
13942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    CameraSource *source = new CameraSource(camera, proxy, cameraId,
140ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong                    videoSize, frameRate, surface,
141ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong                    storeMetaDataInVideoBuffers);
1420c128b67f066b2e691348d5375c2da47b84f69acJames Dong    return source;
143ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
144ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
1450c128b67f066b2e691348d5375c2da47b84f69acJames DongCameraSource::CameraSource(
1460c128b67f066b2e691348d5375c2da47b84f69acJames Dong    const sp<ICamera>& camera,
14742419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
1480c128b67f066b2e691348d5375c2da47b84f69acJames Dong    int32_t cameraId,
1490c128b67f066b2e691348d5375c2da47b84f69acJames Dong    Size videoSize,
1500c128b67f066b2e691348d5375c2da47b84f69acJames Dong    int32_t frameRate,
151ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong    const sp<Surface>& surface,
152ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong    bool storeMetaDataInVideoBuffers)
1530c128b67f066b2e691348d5375c2da47b84f69acJames Dong    : mCameraFlags(0),
1540c128b67f066b2e691348d5375c2da47b84f69acJames Dong      mVideoFrameRate(-1),
1550c128b67f066b2e691348d5375c2da47b84f69acJames Dong      mCamera(0),
1560c128b67f066b2e691348d5375c2da47b84f69acJames Dong      mSurface(surface),
1573300e9667e3daa374659b4a8b97dd92c4d34e501James Dong      mNumFramesReceived(0),
158f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra      mLastFrameTimestampUs(0),
159f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra      mStarted(false),
1603300e9667e3daa374659b4a8b97dd92c4d34e501James Dong      mNumFramesEncoded(0),
16196af14d9b013496accf40a85a66fefcba3ac0111James Dong      mTimeBetweenFrameCaptureUs(0),
1625f3ab06e90365ad6c4865e2cab358a20e12ce0ebJames Dong      mFirstFrameTimeUs(0),
1633300e9667e3daa374659b4a8b97dd92c4d34e501James Dong      mNumFramesDropped(0),
16436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong      mNumGlitches(0),
16536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong      mGlitchDurationThresholdUs(200000),
166f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra      mCollectStats(false) {
1670c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mVideoSize.width  = -1;
1680c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mVideoSize.height = -1;
1690c128b67f066b2e691348d5375c2da47b84f69acJames Dong
17042419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    mInitCheck = init(camera, proxy, cameraId,
171ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong                    videoSize, frameRate,
172ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong                    storeMetaDataInVideoBuffers);
173528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li    if (mInitCheck != OK) releaseCamera();
1740c128b67f066b2e691348d5375c2da47b84f69acJames Dong}
1750c128b67f066b2e691348d5375c2da47b84f69acJames Dong
1760c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::initCheck() const {
1770c128b67f066b2e691348d5375c2da47b84f69acJames Dong    return mInitCheck;
1780c128b67f066b2e691348d5375c2da47b84f69acJames Dong}
1790c128b67f066b2e691348d5375c2da47b84f69acJames Dong
1800c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::isCameraAvailable(
18142419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
18242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    int32_t cameraId) {
1830c128b67f066b2e691348d5375c2da47b84f69acJames Dong
1840c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if (camera == 0) {
1850c128b67f066b2e691348d5375c2da47b84f69acJames Dong        mCamera = Camera::connect(cameraId);
18642419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li        if (mCamera == 0) return -EBUSY;
1870c128b67f066b2e691348d5375c2da47b84f69acJames Dong        mCameraFlags &= ~FLAGS_HOT_CAMERA;
1880c128b67f066b2e691348d5375c2da47b84f69acJames Dong    } else {
18942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li        // We get the proxy from Camera, not ICamera. We need to get the proxy
19042419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li        // to the remote Camera owned by the application. Here mCamera is a
19142419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li        // local Camera object created by us. We cannot use the proxy from
19242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li        // mCamera here.
1930c128b67f066b2e691348d5375c2da47b84f69acJames Dong        mCamera = Camera::create(camera);
19442419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li        if (mCamera == 0) return -EBUSY;
19542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li        mCameraRecordingProxy = proxy;
1960c128b67f066b2e691348d5375c2da47b84f69acJames Dong        mCameraFlags |= FLAGS_HOT_CAMERA;
197e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mDeathNotifier = new DeathNotifier();
198e02802306d63d5209afed11cc609ed6f65d5de89James Dong        // isBinderAlive needs linkToDeath to work.
199e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
2000c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
2010c128b67f066b2e691348d5375c2da47b84f69acJames Dong
20242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    mCamera->lock();
20342419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li
2040c128b67f066b2e691348d5375c2da47b84f69acJames Dong    return OK;
2050c128b67f066b2e691348d5375c2da47b84f69acJames Dong}
2060c128b67f066b2e691348d5375c2da47b84f69acJames Dong
2070c128b67f066b2e691348d5375c2da47b84f69acJames Dong
2080c128b67f066b2e691348d5375c2da47b84f69acJames Dong/*
2090c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Check to see whether the requested video width and height is one
2100c128b67f066b2e691348d5375c2da47b84f69acJames Dong * of the supported sizes.
2110c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param width the video frame width in pixels
2120c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param height the video frame height in pixels
2130c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param suppportedSizes the vector of sizes that we check against
2140c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return true if the dimension (width and height) is supported.
2150c128b67f066b2e691348d5375c2da47b84f69acJames Dong */
2160c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatic bool isVideoSizeSupported(
2170c128b67f066b2e691348d5375c2da47b84f69acJames Dong    int32_t width, int32_t height,
2180c128b67f066b2e691348d5375c2da47b84f69acJames Dong    const Vector<Size>& supportedSizes) {
2190c128b67f066b2e691348d5375c2da47b84f69acJames Dong
2200c128b67f066b2e691348d5375c2da47b84f69acJames Dong    LOGV("isVideoSizeSupported");
2210c128b67f066b2e691348d5375c2da47b84f69acJames Dong    for (size_t i = 0; i < supportedSizes.size(); ++i) {
2220c128b67f066b2e691348d5375c2da47b84f69acJames Dong        if (width  == supportedSizes[i].width &&
2230c128b67f066b2e691348d5375c2da47b84f69acJames Dong            height == supportedSizes[i].height) {
2240c128b67f066b2e691348d5375c2da47b84f69acJames Dong            return true;
2250c128b67f066b2e691348d5375c2da47b84f69acJames Dong        }
2260c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
2270c128b67f066b2e691348d5375c2da47b84f69acJames Dong    return false;
2280c128b67f066b2e691348d5375c2da47b84f69acJames Dong}
2290c128b67f066b2e691348d5375c2da47b84f69acJames Dong
2300c128b67f066b2e691348d5375c2da47b84f69acJames Dong/*
2310c128b67f066b2e691348d5375c2da47b84f69acJames Dong * If the preview and video output is separate, we only set the
2320c128b67f066b2e691348d5375c2da47b84f69acJames Dong * the video size, and applications should set the preview size
2330c128b67f066b2e691348d5375c2da47b84f69acJames Dong * to some proper value, and the recording framework will not
2340c128b67f066b2e691348d5375c2da47b84f69acJames Dong * change the preview size; otherwise, if the video and preview
2350c128b67f066b2e691348d5375c2da47b84f69acJames Dong * output is the same, we need to set the preview to be the same
2360c128b67f066b2e691348d5375c2da47b84f69acJames Dong * as the requested video size.
2370c128b67f066b2e691348d5375c2da47b84f69acJames Dong *
2380c128b67f066b2e691348d5375c2da47b84f69acJames Dong */
2390c128b67f066b2e691348d5375c2da47b84f69acJames Dong/*
2400c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Query the camera to retrieve the supported video frame sizes
2410c128b67f066b2e691348d5375c2da47b84f69acJames Dong * and also to see whether CameraParameters::setVideoSize()
2420c128b67f066b2e691348d5375c2da47b84f69acJames Dong * is supported or not.
2430c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param params CameraParameters to retrieve the information
2440c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @@param isSetVideoSizeSupported retunrs whether method
2450c128b67f066b2e691348d5375c2da47b84f69acJames Dong *      CameraParameters::setVideoSize() is supported or not.
2460c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param sizes returns the vector of Size objects for the
2470c128b67f066b2e691348d5375c2da47b84f69acJames Dong *      supported video frame sizes advertised by the camera.
2480c128b67f066b2e691348d5375c2da47b84f69acJames Dong */
2490c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatic void getSupportedVideoSizes(
2500c128b67f066b2e691348d5375c2da47b84f69acJames Dong    const CameraParameters& params,
2510c128b67f066b2e691348d5375c2da47b84f69acJames Dong    bool *isSetVideoSizeSupported,
2520c128b67f066b2e691348d5375c2da47b84f69acJames Dong    Vector<Size>& sizes) {
2530c128b67f066b2e691348d5375c2da47b84f69acJames Dong
2540c128b67f066b2e691348d5375c2da47b84f69acJames Dong    *isSetVideoSizeSupported = true;
2550c128b67f066b2e691348d5375c2da47b84f69acJames Dong    params.getSupportedVideoSizes(sizes);
2560c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if (sizes.size() == 0) {
2570c128b67f066b2e691348d5375c2da47b84f69acJames Dong        LOGD("Camera does not support setVideoSize()");
2580c128b67f066b2e691348d5375c2da47b84f69acJames Dong        params.getSupportedPreviewSizes(sizes);
2590c128b67f066b2e691348d5375c2da47b84f69acJames Dong        *isSetVideoSizeSupported = false;
2600c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
2610c128b67f066b2e691348d5375c2da47b84f69acJames Dong}
2620c128b67f066b2e691348d5375c2da47b84f69acJames Dong
2630c128b67f066b2e691348d5375c2da47b84f69acJames Dong/*
2640c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Check whether the camera has the supported color format
2650c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param params CameraParameters to retrieve the information
2660c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return OK if no error.
2670c128b67f066b2e691348d5375c2da47b84f69acJames Dong */
2680c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::isCameraColorFormatSupported(
2690c128b67f066b2e691348d5375c2da47b84f69acJames Dong        const CameraParameters& params) {
2700c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mColorFormat = getColorFormat(params.get(
2710c128b67f066b2e691348d5375c2da47b84f69acJames Dong            CameraParameters::KEY_VIDEO_FRAME_FORMAT));
2720c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if (mColorFormat == -1) {
2730c128b67f066b2e691348d5375c2da47b84f69acJames Dong        return BAD_VALUE;
2740c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
2750c128b67f066b2e691348d5375c2da47b84f69acJames Dong    return OK;
2760c128b67f066b2e691348d5375c2da47b84f69acJames Dong}
2770c128b67f066b2e691348d5375c2da47b84f69acJames Dong
2780c128b67f066b2e691348d5375c2da47b84f69acJames Dong/*
2790c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Configure the camera to use the requested video size
2800c128b67f066b2e691348d5375c2da47b84f69acJames Dong * (width and height) and/or frame rate. If both width and
2810c128b67f066b2e691348d5375c2da47b84f69acJames Dong * height are -1, configuration on the video size is skipped.
2820c128b67f066b2e691348d5375c2da47b84f69acJames Dong * if frameRate is -1, configuration on the frame rate
2830c128b67f066b2e691348d5375c2da47b84f69acJames Dong * is skipped. Skipping the configuration allows one to
2840c128b67f066b2e691348d5375c2da47b84f69acJames Dong * use the current camera setting without the need to
2850c128b67f066b2e691348d5375c2da47b84f69acJames Dong * actually know the specific values (see Create() method).
2860c128b67f066b2e691348d5375c2da47b84f69acJames Dong *
2870c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param params the CameraParameters to be configured
2880c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param width the target video frame width in pixels
2890c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param height the target video frame height in pixels
2900c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param frameRate the target frame rate in frames per second.
2910c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return OK if no error.
2920c128b67f066b2e691348d5375c2da47b84f69acJames Dong */
2930c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::configureCamera(
2940c128b67f066b2e691348d5375c2da47b84f69acJames Dong        CameraParameters* params,
2950c128b67f066b2e691348d5375c2da47b84f69acJames Dong        int32_t width, int32_t height,
2960c128b67f066b2e691348d5375c2da47b84f69acJames Dong        int32_t frameRate) {
297e02802306d63d5209afed11cc609ed6f65d5de89James Dong    LOGV("configureCamera");
2980c128b67f066b2e691348d5375c2da47b84f69acJames Dong    Vector<Size> sizes;
2990c128b67f066b2e691348d5375c2da47b84f69acJames Dong    bool isSetVideoSizeSupportedByCamera = true;
3000c128b67f066b2e691348d5375c2da47b84f69acJames Dong    getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
3010c128b67f066b2e691348d5375c2da47b84f69acJames Dong    bool isCameraParamChanged = false;
3020c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if (width != -1 && height != -1) {
3030c128b67f066b2e691348d5375c2da47b84f69acJames Dong        if (!isVideoSizeSupported(width, height, sizes)) {
3040c128b67f066b2e691348d5375c2da47b84f69acJames Dong            LOGE("Video dimension (%dx%d) is unsupported", width, height);
3050c128b67f066b2e691348d5375c2da47b84f69acJames Dong            return BAD_VALUE;
3060c128b67f066b2e691348d5375c2da47b84f69acJames Dong        }
3070c128b67f066b2e691348d5375c2da47b84f69acJames Dong        if (isSetVideoSizeSupportedByCamera) {
3080c128b67f066b2e691348d5375c2da47b84f69acJames Dong            params->setVideoSize(width, height);
3090c128b67f066b2e691348d5375c2da47b84f69acJames Dong        } else {
3100c128b67f066b2e691348d5375c2da47b84f69acJames Dong            params->setPreviewSize(width, height);
3110c128b67f066b2e691348d5375c2da47b84f69acJames Dong        }
3120c128b67f066b2e691348d5375c2da47b84f69acJames Dong        isCameraParamChanged = true;
3130c128b67f066b2e691348d5375c2da47b84f69acJames Dong    } else if ((width == -1 && height != -1) ||
3140c128b67f066b2e691348d5375c2da47b84f69acJames Dong               (width != -1 && height == -1)) {
3150c128b67f066b2e691348d5375c2da47b84f69acJames Dong        // If one and only one of the width and height is -1
3160c128b67f066b2e691348d5375c2da47b84f69acJames Dong        // we reject such a request.
3170c128b67f066b2e691348d5375c2da47b84f69acJames Dong        LOGE("Requested video size (%dx%d) is not supported", width, height);
3180c128b67f066b2e691348d5375c2da47b84f69acJames Dong        return BAD_VALUE;
3190c128b67f066b2e691348d5375c2da47b84f69acJames Dong    } else {  // width == -1 && height == -1
3200c128b67f066b2e691348d5375c2da47b84f69acJames Dong        // Do not configure the camera.
3210c128b67f066b2e691348d5375c2da47b84f69acJames Dong        // Use the current width and height value setting from the camera.
3220c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
3230c128b67f066b2e691348d5375c2da47b84f69acJames Dong
3240c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if (frameRate != -1) {
325b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong        CHECK(frameRate > 0 && frameRate <= 120);
326b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong        const char* supportedFrameRates =
327b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong                params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
328b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong        CHECK(supportedFrameRates != NULL);
329b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong        LOGV("Supported frame rates: %s", supportedFrameRates);
330b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong        char buf[4];
331b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong        snprintf(buf, 4, "%d", frameRate);
332b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong        if (strstr(supportedFrameRates, buf) == NULL) {
333b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong            LOGE("Requested frame rate (%d) is not supported: %s",
334b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong                frameRate, supportedFrameRates);
335b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong            return BAD_VALUE;
336b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong        }
337b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong
338b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong        // The frame rate is supported, set the camera to the requested value.
3390c128b67f066b2e691348d5375c2da47b84f69acJames Dong        params->setPreviewFrameRate(frameRate);
3400c128b67f066b2e691348d5375c2da47b84f69acJames Dong        isCameraParamChanged = true;
3410c128b67f066b2e691348d5375c2da47b84f69acJames Dong    } else {  // frameRate == -1
3420c128b67f066b2e691348d5375c2da47b84f69acJames Dong        // Do not configure the camera.
3430c128b67f066b2e691348d5375c2da47b84f69acJames Dong        // Use the current frame rate value setting from the camera
3440c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
3450c128b67f066b2e691348d5375c2da47b84f69acJames Dong
3460c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if (isCameraParamChanged) {
3470c128b67f066b2e691348d5375c2da47b84f69acJames Dong        // Either frame rate or frame size needs to be changed.
3480c128b67f066b2e691348d5375c2da47b84f69acJames Dong        String8 s = params->flatten();
3490c128b67f066b2e691348d5375c2da47b84f69acJames Dong        if (OK != mCamera->setParameters(s)) {
3500c128b67f066b2e691348d5375c2da47b84f69acJames Dong            LOGE("Could not change settings."
3510c128b67f066b2e691348d5375c2da47b84f69acJames Dong                 " Someone else is using camera %p?", mCamera.get());
3520c128b67f066b2e691348d5375c2da47b84f69acJames Dong            return -EBUSY;
3530c128b67f066b2e691348d5375c2da47b84f69acJames Dong        }
3540c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
3550c128b67f066b2e691348d5375c2da47b84f69acJames Dong    return OK;
3560c128b67f066b2e691348d5375c2da47b84f69acJames Dong}
3570c128b67f066b2e691348d5375c2da47b84f69acJames Dong
3580c128b67f066b2e691348d5375c2da47b84f69acJames Dong/*
3590c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Check whether the requested video frame size
3600c128b67f066b2e691348d5375c2da47b84f69acJames Dong * has been successfully configured or not. If both width and height
3610c128b67f066b2e691348d5375c2da47b84f69acJames Dong * are -1, check on the current width and height value setting
3620c128b67f066b2e691348d5375c2da47b84f69acJames Dong * is performed.
3630c128b67f066b2e691348d5375c2da47b84f69acJames Dong *
3640c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param params CameraParameters to retrieve the information
3650c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param the target video frame width in pixels to check against
3660c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param the target video frame height in pixels to check against
3670c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return OK if no error
3680c128b67f066b2e691348d5375c2da47b84f69acJames Dong */
3690c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::checkVideoSize(
3700c128b67f066b2e691348d5375c2da47b84f69acJames Dong        const CameraParameters& params,
3710c128b67f066b2e691348d5375c2da47b84f69acJames Dong        int32_t width, int32_t height) {
3720c128b67f066b2e691348d5375c2da47b84f69acJames Dong
373e02802306d63d5209afed11cc609ed6f65d5de89James Dong    LOGV("checkVideoSize");
37426e54e258f0331e09c045c7af9b6b8cf11d19257James Dong    // The actual video size is the same as the preview size
37526e54e258f0331e09c045c7af9b6b8cf11d19257James Dong    // if the camera hal does not support separate video and
37626e54e258f0331e09c045c7af9b6b8cf11d19257James Dong    // preview output. In this case, we retrieve the video
37726e54e258f0331e09c045c7af9b6b8cf11d19257James Dong    // size from preview.
3780c128b67f066b2e691348d5375c2da47b84f69acJames Dong    int32_t frameWidthActual = -1;
3790c128b67f066b2e691348d5375c2da47b84f69acJames Dong    int32_t frameHeightActual = -1;
38026e54e258f0331e09c045c7af9b6b8cf11d19257James Dong    Vector<Size> sizes;
38126e54e258f0331e09c045c7af9b6b8cf11d19257James Dong    params.getSupportedVideoSizes(sizes);
38226e54e258f0331e09c045c7af9b6b8cf11d19257James Dong    if (sizes.size() == 0) {
38326e54e258f0331e09c045c7af9b6b8cf11d19257James Dong        // video size is the same as preview size
38426e54e258f0331e09c045c7af9b6b8cf11d19257James Dong        params.getPreviewSize(&frameWidthActual, &frameHeightActual);
38526e54e258f0331e09c045c7af9b6b8cf11d19257James Dong    } else {
38626e54e258f0331e09c045c7af9b6b8cf11d19257James Dong        // video size may not be the same as preview
38726e54e258f0331e09c045c7af9b6b8cf11d19257James Dong        params.getVideoSize(&frameWidthActual, &frameHeightActual);
38826e54e258f0331e09c045c7af9b6b8cf11d19257James Dong    }
3890c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if (frameWidthActual < 0 || frameHeightActual < 0) {
3900c128b67f066b2e691348d5375c2da47b84f69acJames Dong        LOGE("Failed to retrieve video frame size (%dx%d)",
3910c128b67f066b2e691348d5375c2da47b84f69acJames Dong                frameWidthActual, frameHeightActual);
3920c128b67f066b2e691348d5375c2da47b84f69acJames Dong        return UNKNOWN_ERROR;
3930c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
3940c128b67f066b2e691348d5375c2da47b84f69acJames Dong
3950c128b67f066b2e691348d5375c2da47b84f69acJames Dong    // Check the actual video frame size against the target/requested
3960c128b67f066b2e691348d5375c2da47b84f69acJames Dong    // video frame size.
3970c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if (width != -1 && height != -1) {
3980c128b67f066b2e691348d5375c2da47b84f69acJames Dong        if (frameWidthActual != width || frameHeightActual != height) {
3990c128b67f066b2e691348d5375c2da47b84f69acJames Dong            LOGE("Failed to set video frame size to %dx%d. "
4000c128b67f066b2e691348d5375c2da47b84f69acJames Dong                    "The actual video size is %dx%d ", width, height,
4010c128b67f066b2e691348d5375c2da47b84f69acJames Dong                    frameWidthActual, frameHeightActual);
4020c128b67f066b2e691348d5375c2da47b84f69acJames Dong            return UNKNOWN_ERROR;
4030c128b67f066b2e691348d5375c2da47b84f69acJames Dong        }
4040c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
4050c128b67f066b2e691348d5375c2da47b84f69acJames Dong
4060c128b67f066b2e691348d5375c2da47b84f69acJames Dong    // Good now.
4070c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mVideoSize.width = frameWidthActual;
4080c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mVideoSize.height = frameHeightActual;
4090c128b67f066b2e691348d5375c2da47b84f69acJames Dong    return OK;
4100c128b67f066b2e691348d5375c2da47b84f69acJames Dong}
4110c128b67f066b2e691348d5375c2da47b84f69acJames Dong
4120c128b67f066b2e691348d5375c2da47b84f69acJames Dong/*
4130c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Check the requested frame rate has been successfully configured or not.
4140c128b67f066b2e691348d5375c2da47b84f69acJames Dong * If the target frameRate is -1, check on the current frame rate value
4150c128b67f066b2e691348d5375c2da47b84f69acJames Dong * setting is performed.
4160c128b67f066b2e691348d5375c2da47b84f69acJames Dong *
4170c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param params CameraParameters to retrieve the information
4180c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param the target video frame rate to check against
4190c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return OK if no error.
4200c128b67f066b2e691348d5375c2da47b84f69acJames Dong */
4210c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::checkFrameRate(
4220c128b67f066b2e691348d5375c2da47b84f69acJames Dong        const CameraParameters& params,
4230c128b67f066b2e691348d5375c2da47b84f69acJames Dong        int32_t frameRate) {
4240c128b67f066b2e691348d5375c2da47b84f69acJames Dong
425e02802306d63d5209afed11cc609ed6f65d5de89James Dong    LOGV("checkFrameRate");
4260c128b67f066b2e691348d5375c2da47b84f69acJames Dong    int32_t frameRateActual = params.getPreviewFrameRate();
4270c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if (frameRateActual < 0) {
4280c128b67f066b2e691348d5375c2da47b84f69acJames Dong        LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
4290c128b67f066b2e691348d5375c2da47b84f69acJames Dong        return UNKNOWN_ERROR;
4300c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
4310c128b67f066b2e691348d5375c2da47b84f69acJames Dong
4320c128b67f066b2e691348d5375c2da47b84f69acJames Dong    // Check the actual video frame rate against the target/requested
4330c128b67f066b2e691348d5375c2da47b84f69acJames Dong    // video frame rate.
4340c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
4350c128b67f066b2e691348d5375c2da47b84f69acJames Dong        LOGE("Failed to set preview frame rate to %d fps. The actual "
4360c128b67f066b2e691348d5375c2da47b84f69acJames Dong                "frame rate is %d", frameRate, frameRateActual);
4370c128b67f066b2e691348d5375c2da47b84f69acJames Dong        return UNKNOWN_ERROR;
4380c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
4390c128b67f066b2e691348d5375c2da47b84f69acJames Dong
4400c128b67f066b2e691348d5375c2da47b84f69acJames Dong    // Good now.
4410c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mVideoFrameRate = frameRateActual;
4420c128b67f066b2e691348d5375c2da47b84f69acJames Dong    return OK;
4430c128b67f066b2e691348d5375c2da47b84f69acJames Dong}
4440c128b67f066b2e691348d5375c2da47b84f69acJames Dong
4450c128b67f066b2e691348d5375c2da47b84f69acJames Dong/*
4460c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Initialize the CameraSource to so that it becomes
4470c128b67f066b2e691348d5375c2da47b84f69acJames Dong * ready for providing the video input streams as requested.
4480c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param camera the camera object used for the video source
4490c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param cameraId if camera == 0, use camera with this id
4500c128b67f066b2e691348d5375c2da47b84f69acJames Dong *      as the video source
4510c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param videoSize the target video frame size. If both
4520c128b67f066b2e691348d5375c2da47b84f69acJames Dong *      width and height in videoSize is -1, use the current
4530c128b67f066b2e691348d5375c2da47b84f69acJames Dong *      width and heigth settings by the camera
4540c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param frameRate the target frame rate in frames per second.
4550c128b67f066b2e691348d5375c2da47b84f69acJames Dong *      if it is -1, use the current camera frame rate setting.
456ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong * @param storeMetaDataInVideoBuffers request to store meta
457ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong *      data or real YUV data in video buffers. Request to
458ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong *      store meta data in video buffers may not be honored
459ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong *      if the source does not support this feature.
460ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong *
4610c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return OK if no error.
4620c128b67f066b2e691348d5375c2da47b84f69acJames Dong */
4630c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::init(
4640c128b67f066b2e691348d5375c2da47b84f69acJames Dong        const sp<ICamera>& camera,
46542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li        const sp<ICameraRecordingProxy>& proxy,
4660c128b67f066b2e691348d5375c2da47b84f69acJames Dong        int32_t cameraId,
4670c128b67f066b2e691348d5375c2da47b84f69acJames Dong        Size videoSize,
468ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong        int32_t frameRate,
469ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong        bool storeMetaDataInVideoBuffers) {
4700c128b67f066b2e691348d5375c2da47b84f69acJames Dong
471e02802306d63d5209afed11cc609ed6f65d5de89James Dong    LOGV("init");
4720c128b67f066b2e691348d5375c2da47b84f69acJames Dong    status_t err = OK;
4738d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
4748d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong    err = initWithCameraAccess(camera, proxy, cameraId,
4758d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong                               videoSize, frameRate,
4768d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong                               storeMetaDataInVideoBuffers);
4778d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong    IPCThreadState::self()->restoreCallingIdentity(token);
4788d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong    return err;
4798d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong}
4808d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong
4818d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dongstatus_t CameraSource::initWithCameraAccess(
4828d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        const sp<ICamera>& camera,
4838d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        const sp<ICameraRecordingProxy>& proxy,
4848d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        int32_t cameraId,
4858d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        Size videoSize,
4868d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        int32_t frameRate,
4878d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        bool storeMetaDataInVideoBuffers) {
488e02802306d63d5209afed11cc609ed6f65d5de89James Dong    LOGV("initWithCameraAccess");
4898d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong    status_t err = OK;
49071d714ccbf03948d67ab6cebad49703160e5895eJames Dong
49142419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
49242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li        LOGE("Camera connection could not be established.");
4930c128b67f066b2e691348d5375c2da47b84f69acJames Dong        return err;
4940c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
4950c128b67f066b2e691348d5375c2da47b84f69acJames Dong    CameraParameters params(mCamera->getParameters());
4960c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if ((err = isCameraColorFormatSupported(params)) != OK) {
4970c128b67f066b2e691348d5375c2da47b84f69acJames Dong        return err;
4980c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
499155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber
5000c128b67f066b2e691348d5375c2da47b84f69acJames Dong    // Set the camera to use the requested video frame size
5010c128b67f066b2e691348d5375c2da47b84f69acJames Dong    // and/or frame rate.
5020c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if ((err = configureCamera(&params,
5030c128b67f066b2e691348d5375c2da47b84f69acJames Dong                    videoSize.width, videoSize.height,
5040c128b67f066b2e691348d5375c2da47b84f69acJames Dong                    frameRate))) {
5050c128b67f066b2e691348d5375c2da47b84f69acJames Dong        return err;
5060c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
507c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong
5080c128b67f066b2e691348d5375c2da47b84f69acJames Dong    // Check on video frame size and frame rate.
5090c128b67f066b2e691348d5375c2da47b84f69acJames Dong    CameraParameters newCameraParams(mCamera->getParameters());
5100c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if ((err = checkVideoSize(newCameraParams,
5110c128b67f066b2e691348d5375c2da47b84f69acJames Dong                videoSize.width, videoSize.height)) != OK) {
5120c128b67f066b2e691348d5375c2da47b84f69acJames Dong        return err;
5130c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
5140c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
5150c128b67f066b2e691348d5375c2da47b84f69acJames Dong        return err;
5160c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
5170c128b67f066b2e691348d5375c2da47b84f69acJames Dong
5180c128b67f066b2e691348d5375c2da47b84f69acJames Dong    // This CHECK is good, since we just passed the lock/unlock
5190c128b67f066b2e691348d5375c2da47b84f69acJames Dong    // check earlier by calling mCamera->setParameters().
5200c128b67f066b2e691348d5375c2da47b84f69acJames Dong    CHECK_EQ(OK, mCamera->setPreviewDisplay(mSurface));
521997eaa2c7c6f7c59d145dab3e93431ea2e2a7dc7James Dong
522845584e7172406224071ebeb04838dc757761bcbJames Dong    // By default, do not store metadata in video buffers
523ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong    mIsMetaDataStoredInVideoBuffers = false;
524845584e7172406224071ebeb04838dc757761bcbJames Dong    mCamera->storeMetaDataInBuffers(false);
525845584e7172406224071ebeb04838dc757761bcbJames Dong    if (storeMetaDataInVideoBuffers) {
526845584e7172406224071ebeb04838dc757761bcbJames Dong        if (OK == mCamera->storeMetaDataInBuffers(true)) {
527845584e7172406224071ebeb04838dc757761bcbJames Dong            mIsMetaDataStoredInVideoBuffers = true;
528845584e7172406224071ebeb04838dc757761bcbJames Dong        }
529ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong    }
530ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong
5310c128b67f066b2e691348d5375c2da47b84f69acJames Dong    int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
53236e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    if (glitchDurationUs > mGlitchDurationThresholdUs) {
53336e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        mGlitchDurationThresholdUs = glitchDurationUs;
53436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    }
53536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong
5361244eab2cea41df1db4eeb930fddbb9e67ff7691James Dong    // XXX: query camera for the stride and slice height
5371244eab2cea41df1db4eeb930fddbb9e67ff7691James Dong    // when the capability becomes available.
538c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong    mMeta = new MetaData;
5390c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mMeta->setCString(kKeyMIMEType,  MEDIA_MIMETYPE_VIDEO_RAW);
5400c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mMeta->setInt32(kKeyColorFormat, mColorFormat);
5410c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mMeta->setInt32(kKeyWidth,       mVideoSize.width);
5420c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mMeta->setInt32(kKeyHeight,      mVideoSize.height);
5430c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mMeta->setInt32(kKeyStride,      mVideoSize.width);
5440c128b67f066b2e691348d5375c2da47b84f69acJames Dong    mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
545aac193cf38ac084eea0f6367b98f6304d1ec38f2James Dong    mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
5460c128b67f066b2e691348d5375c2da47b84f69acJames Dong    return OK;
547e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
548e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
549e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberCameraSource::~CameraSource() {
550e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    if (mStarted) {
551e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        stop();
5528d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong    } else if (mInitCheck == OK) {
5538d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        // Camera is initialized but because start() is never called,
5548d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        // the lock on Camera is never released(). This makes sure
5558d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        // Camera's lock is released in this case.
5568d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        releaseCamera();
557e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
558e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
559e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
560f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatravoid CameraSource::startCameraRecording() {
561e02802306d63d5209afed11cc609ed6f65d5de89James Dong    LOGV("startCameraRecording");
56242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    // Reset the identity to the current thread because media server owns the
56342419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    // camera and recording is started by the applications. The applications
56442419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    // will connect to the camera in ICameraRecordingProxy::startRecording.
56542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    int64_t token = IPCThreadState::self()->clearCallingIdentity();
566e02802306d63d5209afed11cc609ed6f65d5de89James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
567e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mCamera->unlock();
568e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mCamera.clear();
569e02802306d63d5209afed11cc609ed6f65d5de89James Dong        CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
570e02802306d63d5209afed11cc609ed6f65d5de89James Dong    } else {
571e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mCamera->setListener(new CameraSourceListener(this));
572e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mCamera->startRecording();
573e02802306d63d5209afed11cc609ed6f65d5de89James Dong        CHECK(mCamera->recordingEnabled());
574e02802306d63d5209afed11cc609ed6f65d5de89James Dong    }
57542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    IPCThreadState::self()->restoreCallingIdentity(token);
576f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra}
577f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra
57836e573bf7db5888f92c52eda26e0771aaa2406e4James Dongstatus_t CameraSource::start(MetaData *meta) {
579e02802306d63d5209afed11cc609ed6f65d5de89James Dong    LOGV("start");
580b5ceb9ee21f37ae0817c16490c1fc148dd3eb5e2Andreas Huber    CHECK(!mStarted);
5810c128b67f066b2e691348d5375c2da47b84f69acJames Dong    if (mInitCheck != OK) {
5820c128b67f066b2e691348d5375c2da47b84f69acJames Dong        LOGE("CameraSource is not initialized yet");
5830c128b67f066b2e691348d5375c2da47b84f69acJames Dong        return mInitCheck;
5840c128b67f066b2e691348d5375c2da47b84f69acJames Dong    }
585e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
586dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    char value[PROPERTY_VALUE_MAX];
587dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
588dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
589dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong        mCollectStats = true;
590dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    }
59171d714ccbf03948d67ab6cebad49703160e5895eJames Dong
59236e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    mStartTimeUs = 0;
59336e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    int64_t startTimeUs;
59436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    if (meta && meta->findInt64(kKeyTime, &startTimeUs)) {
59536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        mStartTimeUs = startTimeUs;
59636e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    }
59736e573bf7db5888f92c52eda26e0771aaa2406e4James Dong
598df7a856d3d7a62049e3d1091cf07e95019da4609James Dong    startCameraRecording();
599e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
600e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = true;
601e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
603e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
604f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatravoid CameraSource::stopCameraRecording() {
605e02802306d63d5209afed11cc609ed6f65d5de89James Dong    LOGV("stopCameraRecording");
606e02802306d63d5209afed11cc609ed6f65d5de89James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
607e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mCameraRecordingProxy->stopRecording();
608e02802306d63d5209afed11cc609ed6f65d5de89James Dong    } else {
609e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mCamera->setListener(NULL);
610e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mCamera->stopRecording();
611e02802306d63d5209afed11cc609ed6f65d5de89James Dong    }
612f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra}
613f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra
6145df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dongvoid CameraSource::releaseCamera() {
6155df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong    LOGV("releaseCamera");
616528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li    if (mCamera != 0) {
6178d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
618528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li        if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
619528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li            LOGV("Camera was cold when we started, stopping preview");
620528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li            mCamera->stopPreview();
621528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li            mCamera->disconnect();
622528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li        }
623e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mCamera->unlock();
624528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li        mCamera.clear();
625e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mCamera = 0;
6268d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong        IPCThreadState::self()->restoreCallingIdentity(token);
627528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li    }
628528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li    if (mCameraRecordingProxy != 0) {
629528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li        mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
630528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li        mCameraRecordingProxy.clear();
6315df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong    }
6325df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong    mCameraFlags = 0;
6335df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong}
6345df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong
635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t CameraSource::stop() {
6367455630fff59ac1b68d67077aba360056ca88eceJames Dong    LOGD("stop: E");
637b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong    Mutex::Autolock autoLock(mLock);
638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mStarted = false;
639b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong    mFrameAvailableCondition.signal();
640dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong
641831227816bdcb360148615393e3e93ac379bf3eaJames Dong    int64_t token;
642831227816bdcb360148615393e3e93ac379bf3eaJames Dong    bool isTokenValid = false;
643831227816bdcb360148615393e3e93ac379bf3eaJames Dong    if (mCamera != 0) {
644831227816bdcb360148615393e3e93ac379bf3eaJames Dong        token = IPCThreadState::self()->clearCallingIdentity();
645831227816bdcb360148615393e3e93ac379bf3eaJames Dong        isTokenValid = true;
646831227816bdcb360148615393e3e93ac379bf3eaJames Dong    }
647b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong    releaseQueuedFrames();
648dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong    while (!mFramesBeingEncoded.empty()) {
6497455630fff59ac1b68d67077aba360056ca88eceJames Dong        if (NO_ERROR !=
65096af14d9b013496accf40a85a66fefcba3ac0111James Dong            mFrameCompleteCondition.waitRelative(mLock,
65196af14d9b013496accf40a85a66fefcba3ac0111James Dong                    mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
6527455630fff59ac1b68d67077aba360056ca88eceJames Dong            LOGW("Timed out waiting for outstanding frames being encoded: %d",
653dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong                mFramesBeingEncoded.size());
6547455630fff59ac1b68d67077aba360056ca88eceJames Dong        }
655dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong    }
65663703876801b569caf3737ea6932ea3fc444c245James Dong    stopCameraRecording();
6575df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong    releaseCamera();
658831227816bdcb360148615393e3e93ac379bf3eaJames Dong    if (isTokenValid) {
659831227816bdcb360148615393e3e93ac379bf3eaJames Dong        IPCThreadState::self()->restoreCallingIdentity(token);
660831227816bdcb360148615393e3e93ac379bf3eaJames Dong    }
661dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong
662dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    if (mCollectStats) {
663dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong        LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
664dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong                mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
665dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong                mLastFrameTimestampUs - mFirstFrameTimeUs);
666dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    }
6673300e9667e3daa374659b4a8b97dd92c4d34e501James Dong
66808800f3fdc607e1e8f8d0554eff4a9dc9a6c53d3James Dong    if (mNumGlitches > 0) {
669cbeebb194b374a5eea2f1c6ed6298c09a937c4cbJames Dong        LOGW("%d long delays between neighboring video frames", mNumGlitches);
67008800f3fdc607e1e8f8d0554eff4a9dc9a6c53d3James Dong    }
67108800f3fdc607e1e8f8d0554eff4a9dc9a6c53d3James Dong
6723300e9667e3daa374659b4a8b97dd92c4d34e501James Dong    CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
6737455630fff59ac1b68d67077aba360056ca88eceJames Dong    LOGD("stop: X");
674e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
675e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
676e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
677f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
678e02802306d63d5209afed11cc609ed6f65d5de89James Dong    LOGV("releaseRecordingFrame");
67942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    if (mCameraRecordingProxy != NULL) {
68042419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li        mCameraRecordingProxy->releaseRecordingFrame(frame);
6810a5825edf5490588d730cae7d9bb7461ad0b29a5James Dong    } else if (mCamera != NULL) {
682e02802306d63d5209afed11cc609ed6f65d5de89James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
683e02802306d63d5209afed11cc609ed6f65d5de89James Dong        mCamera->releaseRecordingFrame(frame);
684e02802306d63d5209afed11cc609ed6f65d5de89James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
68563703876801b569caf3737ea6932ea3fc444c245James Dong    }
686f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra}
687f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra
688b00e246669a1da84b1dd7e3f014eedc21747562fJames Dongvoid CameraSource::releaseQueuedFrames() {
689b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong    List<sp<IMemory> >::iterator it;
690dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong    while (!mFramesReceived.empty()) {
691dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong        it = mFramesReceived.begin();
692f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra        releaseRecordingFrame(*it);
693dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong        mFramesReceived.erase(it);
6943300e9667e3daa374659b4a8b97dd92c4d34e501James Dong        ++mNumFramesDropped;
695b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong    }
696b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong}
697b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong
698e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> CameraSource::getFormat() {
699c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong    return mMeta;
700e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
701e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
70236e573bf7db5888f92c52eda26e0771aaa2406e4James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
703f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra    releaseRecordingFrame(frame);
70436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong}
70536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong
706dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) {
707dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong    LOGV("signalBufferReturned: %p", buffer->data());
70822bd242478fa9c9531cf0b750023db5a513eaa8cAndreas Huber    Mutex::Autolock autoLock(mLock);
709dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong    for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
710dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong         it != mFramesBeingEncoded.end(); ++it) {
711dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong        if ((*it)->pointer() ==  buffer->data()) {
71236e573bf7db5888f92c52eda26e0771aaa2406e4James Dong            releaseOneRecordingFrame((*it));
713dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong            mFramesBeingEncoded.erase(it);
714dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong            ++mNumFramesEncoded;
715dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong            buffer->setObserver(0);
716dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong            buffer->release();
717dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong            mFrameCompleteCondition.signal();
718dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong            return;
719dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong        }
720dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong    }
721dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong    CHECK_EQ(0, "signalBufferReturned: bogus buffer");
722dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong}
723dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong
724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t CameraSource::read(
725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
726b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong    LOGV("read");
727e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
728e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    *buffer = NULL;
729e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
730e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    int64_t seekTimeUs;
7316624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    ReadOptions::SeekMode mode;
7326624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
733e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        return ERROR_UNSUPPORTED;
734e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    }
735e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
736e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    sp<IMemory> frame;
737155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    int64_t frameTime;
738e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
739e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    {
740e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        Mutex::Autolock autoLock(mLock);
7412144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        while (mStarted && mFramesReceived.empty()) {
7427455630fff59ac1b68d67077aba360056ca88eceJames Dong            if (NO_ERROR !=
74396af14d9b013496accf40a85a66fefcba3ac0111James Dong                mFrameAvailableCondition.waitRelative(mLock,
74496af14d9b013496accf40a85a66fefcba3ac0111James Dong                    mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
745e02802306d63d5209afed11cc609ed6f65d5de89James Dong                if (mCameraRecordingProxy != 0 &&
746e02802306d63d5209afed11cc609ed6f65d5de89James Dong                    !mCameraRecordingProxy->asBinder()->isBinderAlive()) {
74742419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li                    LOGW("camera recording proxy is gone");
74842419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li                    return ERROR_END_OF_STREAM;
74942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li                }
7507455630fff59ac1b68d67077aba360056ca88eceJames Dong                LOGW("Timed out waiting for incoming camera video frames: %lld us",
7517455630fff59ac1b68d67077aba360056ca88eceJames Dong                    mLastFrameTimestampUs);
7527455630fff59ac1b68d67077aba360056ca88eceJames Dong            }
753e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber        }
7542144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        if (!mStarted) {
7552144f6316d9c993ba20c7de2a6cac35265291cc5James Dong            return OK;
7562144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        }
7572144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        frame = *mFramesReceived.begin();
7582144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        mFramesReceived.erase(mFramesReceived.begin());
7592144f6316d9c993ba20c7de2a6cac35265291cc5James Dong
7602144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        frameTime = *mFrameTimes.begin();
7612144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        mFrameTimes.erase(mFrameTimes.begin());
7622144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        mFramesBeingEncoded.push_back(frame);
7632144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        *buffer = new MediaBuffer(frame->pointer(), frame->size());
7642144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        (*buffer)->setObserver(this);
7652144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        (*buffer)->add_ref();
7662144f6316d9c993ba20c7de2a6cac35265291cc5James Dong        (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
767dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong    }
768e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    return OK;
769e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
770e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
771b00e246669a1da84b1dd7e3f014eedc21747562fJames Dongvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs,
772b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong        int32_t msgType, const sp<IMemory> &data) {
773b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong    LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
774e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Mutex::Autolock autoLock(mLock);
775cbeebb194b374a5eea2f1c6ed6298c09a937c4cbJames Dong    if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
776cbeebb194b374a5eea2f1c6ed6298c09a937c4cbJames Dong        LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
77736e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        releaseOneRecordingFrame(data);
778b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong        return;
779b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong    }
780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
78186f8b98e763b34e6a74e81bc9faa3a875c16e18cJames Dong    if (mNumFramesReceived > 0) {
78286f8b98e763b34e6a74e81bc9faa3a875c16e18cJames Dong        CHECK(timestampUs > mLastFrameTimestampUs);
78386f8b98e763b34e6a74e81bc9faa3a875c16e18cJames Dong        if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
78486f8b98e763b34e6a74e81bc9faa3a875c16e18cJames Dong            ++mNumGlitches;
78536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        }
78636e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    }
78736e573bf7db5888f92c52eda26e0771aaa2406e4James Dong
788f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra    // May need to skip frame or modify timestamp. Currently implemented
789f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra    // by the subclass CameraSourceTimeLapse.
7902144f6316d9c993ba20c7de2a6cac35265291cc5James Dong    if (skipCurrentFrame(timestampUs)) {
791f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra        releaseOneRecordingFrame(data);
792f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra        return;
793d26920ada05843e736d78709812e03797eedee55Nipun Kwatra    }
794d26920ada05843e736d78709812e03797eedee55Nipun Kwatra
795dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    mLastFrameTimestampUs = timestampUs;
7963300e9667e3daa374659b4a8b97dd92c4d34e501James Dong    if (mNumFramesReceived == 0) {
797b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong        mFirstFrameTimeUs = timestampUs;
79836e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        // Initial delay
79936e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        if (mStartTimeUs > 0) {
80036e573bf7db5888f92c52eda26e0771aaa2406e4James Dong            if (timestampUs < mStartTimeUs) {
80136e573bf7db5888f92c52eda26e0771aaa2406e4James Dong                // Frame was captured before recording was started
80236e573bf7db5888f92c52eda26e0771aaa2406e4James Dong                // Drop it without updating the statistical data.
80336e573bf7db5888f92c52eda26e0771aaa2406e4James Dong                releaseOneRecordingFrame(data);
80436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong                return;
80536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong            }
80636e573bf7db5888f92c52eda26e0771aaa2406e4James Dong            mStartTimeUs = timestampUs - mStartTimeUs;
80736e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        }
808155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber    }
8093300e9667e3daa374659b4a8b97dd92c4d34e501James Dong    ++mNumFramesReceived;
810155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber
81186f8b98e763b34e6a74e81bc9faa3a875c16e18cJames Dong    CHECK(data != NULL && data->size() > 0);
812dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong    mFramesReceived.push_back(data);
81336e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
81436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    mFrameTimes.push_back(timeUs);
81536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    LOGV("initial delay: %lld, current time stamp: %lld",
81636e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        mStartTimeUs, timeUs);
817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    mFrameAvailableCondition.signal();
818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}
819e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
820ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dongbool CameraSource::isMetaDataStoredInVideoBuffers() const {
821ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong    LOGV("isMetaDataStoredInVideoBuffers");
822ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong    return mIsMetaDataStoredInVideoBuffers;
823ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong}
824ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong
82542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng LiCameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
82642419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    mSource = source;
82742419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li}
82842419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li
82942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Livoid CameraSource::ProxyListener::dataCallbackTimestamp(
83042419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
83142419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
83242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li}
83342419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li
83442419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Livoid CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
83542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li    LOGI("Camera recording proxy died");
83642419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li}
83742419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li
838e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}  // namespace android
839