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