CameraSource.cpp revision f8fb8b856427e9b1c406d516a114a9f37cfea4f2
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "CameraSource"
19#include <utils/Log.h>
20
21#include <OMX_Component.h>
22
23#include <media/stagefright/CameraSource.h>
24#include <media/stagefright/MediaDebug.h>
25#include <media/stagefright/MediaDefs.h>
26#include <media/stagefright/MediaErrors.h>
27#include <media/stagefright/MetaData.h>
28#include <camera/Camera.h>
29#include <camera/CameraParameters.h>
30#include <ui/GraphicBuffer.h>
31#include <ui/Overlay.h>
32#include <surfaceflinger/ISurface.h>
33#include <utils/String8.h>
34
35namespace android {
36
37struct DummySurface : public BnSurface {
38    DummySurface() {}
39
40    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage) {
41        return NULL;
42    }
43    virtual status_t setBufferCount(int bufferCount) {
44        return INVALID_OPERATION;
45    }
46
47    virtual status_t registerBuffers(const BufferHeap &buffers) {
48        return OK;
49    }
50
51    virtual void postBuffer(ssize_t offset) {}
52    virtual void unregisterBuffers() {}
53
54    virtual sp<OverlayRef> createOverlay(
55            uint32_t w, uint32_t h, int32_t format, int32_t orientation) {
56        return NULL;
57    }
58
59protected:
60    virtual ~DummySurface() {}
61
62    DummySurface(const DummySurface &);
63    DummySurface &operator=(const DummySurface &);
64};
65
66struct CameraSourceListener : public CameraListener {
67    CameraSourceListener(const sp<CameraSource> &source);
68
69    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
70    virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr);
71
72    virtual void postDataTimestamp(
73            nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
74
75protected:
76    virtual ~CameraSourceListener();
77
78private:
79    wp<CameraSource> mSource;
80
81    CameraSourceListener(const CameraSourceListener &);
82    CameraSourceListener &operator=(const CameraSourceListener &);
83};
84
85CameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
86    : mSource(source) {
87}
88
89CameraSourceListener::~CameraSourceListener() {
90}
91
92void CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
93    LOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
94}
95
96void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr) {
97    LOGV("postData(%d, ptr:%p, size:%d)",
98         msgType, dataPtr->pointer(), dataPtr->size());
99}
100
101void CameraSourceListener::postDataTimestamp(
102        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
103
104    sp<CameraSource> source = mSource.promote();
105    if (source.get() != NULL) {
106        source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
107    }
108}
109
110// static
111CameraSource *CameraSource::Create() {
112    sp<Camera> camera = Camera::connect(0);
113
114    if (camera.get() == NULL) {
115        return NULL;
116    }
117
118    return new CameraSource(camera);
119}
120
121// static
122CameraSource *CameraSource::CreateFromCamera(const sp<Camera> &camera) {
123    if (camera.get() == NULL) {
124        return NULL;
125    }
126
127    return new CameraSource(camera);
128}
129
130CameraSource::CameraSource(const sp<Camera> &camera)
131    : mCamera(camera),
132      mWidth(0),
133      mHeight(0),
134      mFirstFrameTimeUs(0),
135      mLastFrameTimestampUs(0),
136      mNumFramesReceived(0),
137      mNumFramesEncoded(0),
138      mNumFramesDropped(0),
139      mStarted(false) {
140    String8 s = mCamera->getParameters();
141    printf("params: \"%s\"\n", s.string());
142
143    CameraParameters params(s);
144    params.getPreviewSize(&mWidth, &mHeight);
145}
146
147CameraSource::~CameraSource() {
148    if (mStarted) {
149        stop();
150    }
151}
152
153void CameraSource::setPreviewSurface(const sp<ISurface> &surface) {
154    mPreviewSurface = surface;
155}
156
157status_t CameraSource::start(MetaData *) {
158    LOGV("start");
159    CHECK(!mStarted);
160
161    mCamera->setListener(new CameraSourceListener(this));
162
163    status_t err =
164        mCamera->setPreviewDisplay(
165                mPreviewSurface != NULL ? mPreviewSurface : new DummySurface);
166    CHECK_EQ(err, OK);
167
168    err = mCamera->startRecording();
169    CHECK_EQ(err, OK);
170
171    mStarted = true;
172
173    return OK;
174}
175
176status_t CameraSource::stop() {
177    LOGV("stop");
178    Mutex::Autolock autoLock(mLock);
179    mStarted = false;
180    mFrameAvailableCondition.signal();
181    mCamera->setListener(NULL);
182    mCamera->stopRecording();
183
184    releaseQueuedFrames();
185    LOGI("Frames received/encoded/dropped: %d/%d/%d, timestamp (us) last/first: %lld/%lld",
186            mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
187            mLastFrameTimestampUs, mFirstFrameTimeUs);
188
189    CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
190    return OK;
191}
192
193void CameraSource::releaseQueuedFrames() {
194    List<sp<IMemory> >::iterator it;
195    while (!mFrames.empty()) {
196        it = mFrames.begin();
197        mCamera->releaseRecordingFrame(*it);
198        mFrames.erase(it);
199        ++mNumFramesDropped;
200    }
201}
202
203sp<MetaData> CameraSource::getFormat() {
204    sp<MetaData> meta = new MetaData;
205    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
206    meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420SemiPlanar);
207    meta->setInt32(kKeyWidth, mWidth);
208    meta->setInt32(kKeyHeight, mHeight);
209
210    return meta;
211}
212
213status_t CameraSource::read(
214        MediaBuffer **buffer, const ReadOptions *options) {
215    LOGV("read");
216
217    *buffer = NULL;
218
219    int64_t seekTimeUs;
220    if (options && options->getSeekTo(&seekTimeUs)) {
221        return ERROR_UNSUPPORTED;
222    }
223
224    sp<IMemory> frame;
225    int64_t frameTime;
226
227    {
228        Mutex::Autolock autoLock(mLock);
229        while (mStarted && mFrames.empty()) {
230            mFrameAvailableCondition.wait(mLock);
231        }
232        if (!mStarted) {
233            return OK;
234        }
235        frame = *mFrames.begin();
236        mFrames.erase(mFrames.begin());
237
238        frameTime = *mFrameTimes.begin();
239        mFrameTimes.erase(mFrameTimes.begin());
240        ++mNumFramesEncoded;
241    }
242
243    *buffer = new MediaBuffer(frame->size());
244    memcpy((*buffer)->data(), frame->pointer(), frame->size());
245    (*buffer)->set_range(0, frame->size());
246    mCamera->releaseRecordingFrame(frame);
247
248    (*buffer)->meta_data()->clear();
249    (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
250
251    return OK;
252}
253
254void CameraSource::dataCallbackTimestamp(int64_t timestampUs,
255        int32_t msgType, const sp<IMemory> &data) {
256    LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
257    mLastFrameTimestampUs = timestampUs;
258    Mutex::Autolock autoLock(mLock);
259    if (!mStarted) {
260        mCamera->releaseRecordingFrame(data);
261        ++mNumFramesReceived;
262        ++mNumFramesDropped;
263        return;
264    }
265
266    if (mNumFramesReceived == 0) {
267        mFirstFrameTimeUs = timestampUs;
268    }
269    ++mNumFramesReceived;
270
271    mFrames.push_back(data);
272    mFrameTimes.push_back(timestampUs - mFirstFrameTimeUs);
273    mFrameAvailableCondition.signal();
274}
275
276}  // namespace android
277