CameraSource.cpp revision 0c89199745bc1bf05b997fc7c342017807676b6f
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#include <sys/time.h>
18
19#include <OMX_Component.h>
20
21#include <binder/IServiceManager.h>
22#include <media/stagefright/CameraSource.h>
23#include <media/stagefright/MediaDebug.h>
24#include <media/stagefright/MediaErrors.h>
25#include <media/stagefright/MetaData.h>
26#include <ui/ICameraClient.h>
27#include <ui/ICameraService.h>
28#include <ui/Overlay.h>
29#include <utils/String16.h>
30
31namespace android {
32
33class CameraBuffer : public MediaBuffer {
34public:
35    CameraBuffer(const sp<IMemory> &frame)
36        : MediaBuffer(frame->pointer(), frame->size()),
37          mFrame(frame) {
38    }
39
40    sp<IMemory> releaseFrame() {
41        sp<IMemory> frame = mFrame;
42        mFrame.clear();
43        return frame;
44    }
45
46private:
47    sp<IMemory> mFrame;
48};
49
50class CameraSourceClient : public BnCameraClient {
51public:
52    CameraSourceClient()
53        : mSource(NULL) {
54    }
55
56    virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) {
57        CHECK(mSource != NULL);
58        mSource->notifyCallback(msgType, ext1, ext2);
59    }
60
61    virtual void dataCallback(int32_t msgType, const sp<IMemory> &data) {
62        CHECK(mSource != NULL);
63        mSource->dataCallback(msgType, data);
64    }
65
66    void setCameraSource(CameraSource *source) {
67        mSource = source;
68    }
69
70private:
71    CameraSource *mSource;
72};
73
74class DummySurface : public BnSurface {
75public:
76    DummySurface() {}
77
78    virtual status_t registerBuffers(const BufferHeap &buffers) {
79        return OK;
80    }
81
82    virtual void postBuffer(ssize_t offset) {
83    }
84
85    virtual void unregisterBuffers() {
86    }
87
88    virtual sp<OverlayRef> createOverlay(
89            uint32_t w, uint32_t h, int32_t format) {
90        return NULL;
91    }
92};
93
94// static
95CameraSource *CameraSource::Create() {
96    sp<IServiceManager> sm = defaultServiceManager();
97
98    sp<ICameraService> service =
99        interface_cast<ICameraService>(
100                sm->getService(String16("media.camera")));
101
102    sp<CameraSourceClient> client = new CameraSourceClient;
103    sp<ICamera> camera = service->connect(client);
104
105    CameraSource *source = new CameraSource(camera, client);
106    client->setCameraSource(source);
107
108    return source;
109}
110
111CameraSource::CameraSource(
112        const sp<ICamera> &camera, const sp<ICameraClient> &client)
113    : mCamera(camera),
114      mCameraClient(client),
115      mNumFrames(0),
116      mStarted(false) {
117    printf("params: \"%s\"\n", mCamera->getParameters().string());
118}
119
120CameraSource::~CameraSource() {
121    if (mStarted) {
122        stop();
123    }
124
125    mCamera->disconnect();
126}
127
128status_t CameraSource::start(MetaData *) {
129    CHECK(!mStarted);
130
131    status_t err = mCamera->lock();
132    CHECK_EQ(err, OK);
133
134    err = mCamera->setPreviewDisplay(new DummySurface);
135    CHECK_EQ(err, OK);
136    mCamera->setPreviewCallbackFlag(1);
137    mCamera->startPreview();
138    CHECK_EQ(err, OK);
139
140    mStarted = true;
141
142    return OK;
143}
144
145status_t CameraSource::stop() {
146    CHECK(mStarted);
147
148    mCamera->stopPreview();
149    mCamera->unlock();
150
151    mStarted = false;
152
153    return OK;
154}
155
156sp<MetaData> CameraSource::getFormat() {
157    sp<MetaData> meta = new MetaData;
158    meta->setCString(kKeyMIMEType, "video/raw");
159    meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420SemiPlanar);
160    meta->setInt32(kKeyWidth, 480);
161    meta->setInt32(kKeyHeight, 320);
162
163    return meta;
164}
165
166status_t CameraSource::read(
167        MediaBuffer **buffer, const ReadOptions *options) {
168    CHECK(mStarted);
169
170    *buffer = NULL;
171
172    int64_t seekTimeUs;
173    if (options && options->getSeekTo(&seekTimeUs)) {
174        return ERROR_UNSUPPORTED;
175    }
176
177    sp<IMemory> frame;
178
179    {
180        Mutex::Autolock autoLock(mLock);
181        while (mFrames.empty()) {
182            mFrameAvailableCondition.wait(mLock);
183        }
184
185        frame = *mFrames.begin();
186        mFrames.erase(mFrames.begin());
187    }
188
189    int count = mNumFrames++;
190
191    *buffer = new CameraBuffer(frame);
192
193    (*buffer)->meta_data()->clear();
194    (*buffer)->meta_data()->setInt32(kKeyTimeScale, 15);
195    (*buffer)->meta_data()->setInt32(kKeyTimeUnits, count);
196
197    (*buffer)->add_ref();
198    (*buffer)->setObserver(this);
199
200    return OK;
201}
202
203void CameraSource::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) {
204    printf("notifyCallback %d, %d, %d\n", msgType, ext1, ext2);
205}
206
207void CameraSource::dataCallback(int32_t msgType, const sp<IMemory> &data) {
208    Mutex::Autolock autoLock(mLock);
209
210    mFrames.push_back(data);
211    mFrameAvailableCondition.signal();
212}
213
214void CameraSource::signalBufferReturned(MediaBuffer *_buffer) {
215    CameraBuffer *buffer = static_cast<CameraBuffer *>(_buffer);
216
217    mCamera->releaseRecordingFrame(buffer->releaseFrame());
218
219    buffer->setObserver(NULL);
220    buffer->release();
221    buffer = NULL;
222}
223
224}  // namespace android
225