CameraSource.cpp revision 13aec890216948b0c364f8f92792129d0335f506
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 44 virtual status_t registerBuffers(const BufferHeap &buffers) { 45 return OK; 46 } 47 48 virtual void postBuffer(ssize_t offset) {} 49 virtual void unregisterBuffers() {} 50 51 virtual sp<OverlayRef> createOverlay( 52 uint32_t w, uint32_t h, int32_t format, int32_t orientation) { 53 return NULL; 54 } 55 56protected: 57 virtual ~DummySurface() {} 58 59 DummySurface(const DummySurface &); 60 DummySurface &operator=(const DummySurface &); 61}; 62 63struct CameraSourceListener : public CameraListener { 64 CameraSourceListener(const sp<CameraSource> &source); 65 66 virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); 67 virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr); 68 69 virtual void postDataTimestamp( 70 nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); 71 72protected: 73 virtual ~CameraSourceListener(); 74 75private: 76 wp<CameraSource> mSource; 77 78 CameraSourceListener(const CameraSourceListener &); 79 CameraSourceListener &operator=(const CameraSourceListener &); 80}; 81 82CameraSourceListener::CameraSourceListener(const sp<CameraSource> &source) 83 : mSource(source) { 84} 85 86CameraSourceListener::~CameraSourceListener() { 87} 88 89void CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) { 90 LOGV("notify(%d, %d, %d)", msgType, ext1, ext2); 91} 92 93void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr) { 94 LOGV("postData(%d, ptr:%p, size:%d)", 95 msgType, dataPtr->pointer(), dataPtr->size()); 96} 97 98void CameraSourceListener::postDataTimestamp( 99 nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { 100 101 sp<CameraSource> source = mSource.promote(); 102 if (source.get() != NULL) { 103 source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr); 104 } 105} 106 107// static 108CameraSource *CameraSource::Create() { 109 sp<Camera> camera = Camera::connect(); 110 111 if (camera.get() == NULL) { 112 return NULL; 113 } 114 115 return new CameraSource(camera); 116} 117 118// static 119CameraSource *CameraSource::CreateFromCamera(const sp<Camera> &camera) { 120 if (camera.get() == NULL) { 121 return NULL; 122 } 123 124 return new CameraSource(camera); 125} 126 127CameraSource::CameraSource(const sp<Camera> &camera) 128 : mCamera(camera), 129 mWidth(0), 130 mHeight(0), 131 mFirstFrameTimeUs(0), 132 mLastFrameTimestampUs(0), 133 mNumFramesReceived(0), 134 mNumFramesEncoded(0), 135 mNumFramesDropped(0), 136 mStarted(false) { 137 String8 s = mCamera->getParameters(); 138 printf("params: \"%s\"\n", s.string()); 139 140 CameraParameters params(s); 141 params.getPreviewSize(&mWidth, &mHeight); 142} 143 144CameraSource::~CameraSource() { 145 if (mStarted) { 146 stop(); 147 } 148} 149 150void CameraSource::setPreviewSurface(const sp<ISurface> &surface) { 151 mPreviewSurface = surface; 152} 153 154status_t CameraSource::start(MetaData *) { 155 LOGV("start"); 156 CHECK(!mStarted); 157 158 mCamera->setListener(new CameraSourceListener(this)); 159 160 status_t err = 161 mCamera->setPreviewDisplay( 162 mPreviewSurface != NULL ? mPreviewSurface : new DummySurface); 163 CHECK_EQ(err, OK); 164 165 err = mCamera->startRecording(); 166 CHECK_EQ(err, OK); 167 168 mStarted = true; 169 170 return OK; 171} 172 173status_t CameraSource::stop() { 174 LOGV("stop"); 175 Mutex::Autolock autoLock(mLock); 176 mStarted = false; 177 mFrameAvailableCondition.signal(); 178 mCamera->setListener(NULL); 179 mCamera->stopRecording(); 180 181 releaseQueuedFrames(); 182 LOGI("Frames received/encoded/dropped: %d/%d/%d, timestamp (us) last/first: %lld/%lld", 183 mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped, 184 mLastFrameTimestampUs, mFirstFrameTimeUs); 185 186 CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped); 187 return OK; 188} 189 190void CameraSource::releaseQueuedFrames() { 191 List<sp<IMemory> >::iterator it; 192 while (!mFrames.empty()) { 193 it = mFrames.begin(); 194 mCamera->releaseRecordingFrame(*it); 195 mFrames.erase(it); 196 ++mNumFramesDropped; 197 } 198} 199 200sp<MetaData> CameraSource::getFormat() { 201 sp<MetaData> meta = new MetaData; 202 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 203 meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420SemiPlanar); 204 meta->setInt32(kKeyWidth, mWidth); 205 meta->setInt32(kKeyHeight, mHeight); 206 207 return meta; 208} 209 210status_t CameraSource::read( 211 MediaBuffer **buffer, const ReadOptions *options) { 212 LOGV("read"); 213 214 *buffer = NULL; 215 216 int64_t seekTimeUs; 217 if (options && options->getSeekTo(&seekTimeUs)) { 218 return ERROR_UNSUPPORTED; 219 } 220 221 sp<IMemory> frame; 222 int64_t frameTime; 223 224 { 225 Mutex::Autolock autoLock(mLock); 226 while (mStarted && mFrames.empty()) { 227 mFrameAvailableCondition.wait(mLock); 228 } 229 if (!mStarted) { 230 return OK; 231 } 232 frame = *mFrames.begin(); 233 mFrames.erase(mFrames.begin()); 234 235 frameTime = *mFrameTimes.begin(); 236 mFrameTimes.erase(mFrameTimes.begin()); 237 ++mNumFramesEncoded; 238 } 239 240 *buffer = new MediaBuffer(frame->size()); 241 memcpy((*buffer)->data(), frame->pointer(), frame->size()); 242 (*buffer)->set_range(0, frame->size()); 243 mCamera->releaseRecordingFrame(frame); 244 245 (*buffer)->meta_data()->clear(); 246 (*buffer)->meta_data()->setInt64(kKeyTime, frameTime); 247 248 return OK; 249} 250 251void CameraSource::dataCallbackTimestamp(int64_t timestampUs, 252 int32_t msgType, const sp<IMemory> &data) { 253 LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs); 254 mLastFrameTimestampUs = timestampUs; 255 Mutex::Autolock autoLock(mLock); 256 if (!mStarted) { 257 mCamera->releaseRecordingFrame(data); 258 ++mNumFramesReceived; 259 ++mNumFramesDropped; 260 return; 261 } 262 263 if (mNumFramesReceived == 0) { 264 mFirstFrameTimeUs = timestampUs; 265 } 266 ++mNumFramesReceived; 267 268 mFrames.push_back(data); 269 mFrameTimes.push_back(timestampUs - mFirstFrameTimeUs); 270 mFrameAvailableCondition.signal(); 271} 272 273} // namespace android 274