1/* 2 * Copyright (C) 2011 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//#define LOG_NDEBUG 0 17#define LOG_TAG "SurfaceMediaSource" 18 19#include <inttypes.h> 20 21#include <media/stagefright/foundation/ADebug.h> 22#include <media/stagefright/SurfaceMediaSource.h> 23#include <media/stagefright/MediaDefs.h> 24#include <media/stagefright/MetaData.h> 25#include <OMX_IVCommon.h> 26#include <media/hardware/HardwareAPI.h> 27#include <media/hardware/MetadataBufferType.h> 28 29#include <ui/GraphicBuffer.h> 30#include <gui/BufferItem.h> 31#include <gui/ISurfaceComposer.h> 32#include <gui/IGraphicBufferAlloc.h> 33#include <OMX_Component.h> 34 35#include <utils/Log.h> 36#include <utils/String8.h> 37 38#include <private/gui/ComposerService.h> 39 40namespace android { 41 42SurfaceMediaSource::SurfaceMediaSource(uint32_t bufferWidth, uint32_t bufferHeight) : 43 mWidth(bufferWidth), 44 mHeight(bufferHeight), 45 mCurrentSlot(BufferQueue::INVALID_BUFFER_SLOT), 46 mNumPendingBuffers(0), 47 mCurrentTimestamp(0), 48 mFrameRate(30), 49 mStarted(false), 50 mNumFramesReceived(0), 51 mNumFramesEncoded(0), 52 mFirstFrameTimestamp(0), 53 mMaxAcquiredBufferCount(4), // XXX double-check the default 54 mUseAbsoluteTimestamps(false) { 55 ALOGV("SurfaceMediaSource"); 56 57 if (bufferWidth == 0 || bufferHeight == 0) { 58 ALOGE("Invalid dimensions %dx%d", bufferWidth, bufferHeight); 59 } 60 61 BufferQueue::createBufferQueue(&mProducer, &mConsumer); 62 mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight); 63 mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER | 64 GRALLOC_USAGE_HW_TEXTURE); 65 66 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 67 68 // Note that we can't create an sp<...>(this) in a ctor that will not keep a 69 // reference once the ctor ends, as that would cause the refcount of 'this' 70 // dropping to 0 at the end of the ctor. Since all we need is a wp<...> 71 // that's what we create. 72 wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this); 73 sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener); 74 75 status_t err = mConsumer->consumerConnect(proxy, false); 76 if (err != NO_ERROR) { 77 ALOGE("SurfaceMediaSource: error connecting to BufferQueue: %s (%d)", 78 strerror(-err), err); 79 } 80} 81 82SurfaceMediaSource::~SurfaceMediaSource() { 83 ALOGV("~SurfaceMediaSource"); 84 CHECK(!mStarted); 85} 86 87nsecs_t SurfaceMediaSource::getTimestamp() { 88 ALOGV("getTimestamp"); 89 Mutex::Autolock lock(mMutex); 90 return mCurrentTimestamp; 91} 92 93void SurfaceMediaSource::setFrameAvailableListener( 94 const sp<FrameAvailableListener>& listener) { 95 ALOGV("setFrameAvailableListener"); 96 Mutex::Autolock lock(mMutex); 97 mFrameAvailableListener = listener; 98} 99 100void SurfaceMediaSource::dump(String8& result) const 101{ 102 char buffer[1024]; 103 dump(result, "", buffer, 1024); 104} 105 106void SurfaceMediaSource::dump( 107 String8& result, 108 const char* /* prefix */, 109 char* buffer, 110 size_t /* SIZE */) const 111{ 112 Mutex::Autolock lock(mMutex); 113 114 result.append(buffer); 115 mConsumer->dump(result, ""); 116} 117 118status_t SurfaceMediaSource::setFrameRate(int32_t fps) 119{ 120 ALOGV("setFrameRate"); 121 Mutex::Autolock lock(mMutex); 122 const int MAX_FRAME_RATE = 60; 123 if (fps < 0 || fps > MAX_FRAME_RATE) { 124 return BAD_VALUE; 125 } 126 mFrameRate = fps; 127 return OK; 128} 129 130MetadataBufferType SurfaceMediaSource::metaDataStoredInVideoBuffers() const { 131 ALOGV("isMetaDataStoredInVideoBuffers"); 132 return kMetadataBufferTypeANWBuffer; 133} 134 135int32_t SurfaceMediaSource::getFrameRate( ) const { 136 ALOGV("getFrameRate"); 137 Mutex::Autolock lock(mMutex); 138 return mFrameRate; 139} 140 141status_t SurfaceMediaSource::start(MetaData *params) 142{ 143 ALOGV("start"); 144 145 Mutex::Autolock lock(mMutex); 146 147 CHECK(!mStarted); 148 149 mStartTimeNs = 0; 150 int64_t startTimeUs; 151 int32_t bufferCount = 0; 152 if (params) { 153 if (params->findInt64(kKeyTime, &startTimeUs)) { 154 mStartTimeNs = startTimeUs * 1000; 155 } 156 157 if (!params->findInt32(kKeyNumBuffers, &bufferCount)) { 158 ALOGE("Failed to find the advertised buffer count"); 159 return UNKNOWN_ERROR; 160 } 161 162 if (bufferCount <= 1) { 163 ALOGE("bufferCount %d is too small", bufferCount); 164 return BAD_VALUE; 165 } 166 167 mMaxAcquiredBufferCount = bufferCount; 168 } 169 170 CHECK_GT(mMaxAcquiredBufferCount, 1); 171 172 status_t err = 173 mConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBufferCount); 174 175 if (err != OK) { 176 return err; 177 } 178 179 mNumPendingBuffers = 0; 180 mStarted = true; 181 182 return OK; 183} 184 185status_t SurfaceMediaSource::setMaxAcquiredBufferCount(size_t count) { 186 ALOGV("setMaxAcquiredBufferCount(%zu)", count); 187 Mutex::Autolock lock(mMutex); 188 189 CHECK_GT(count, 1); 190 mMaxAcquiredBufferCount = count; 191 192 return OK; 193} 194 195status_t SurfaceMediaSource::setUseAbsoluteTimestamps() { 196 ALOGV("setUseAbsoluteTimestamps"); 197 Mutex::Autolock lock(mMutex); 198 mUseAbsoluteTimestamps = true; 199 200 return OK; 201} 202 203status_t SurfaceMediaSource::stop() 204{ 205 ALOGV("stop"); 206 Mutex::Autolock lock(mMutex); 207 208 if (!mStarted) { 209 return OK; 210 } 211 212 mStarted = false; 213 mFrameAvailableCondition.signal(); 214 215 while (mNumPendingBuffers > 0) { 216 ALOGI("Still waiting for %zu buffers to be returned.", 217 mNumPendingBuffers); 218 219#if DEBUG_PENDING_BUFFERS 220 for (size_t i = 0; i < mPendingBuffers.size(); ++i) { 221 ALOGI("%d: %p", i, mPendingBuffers.itemAt(i)); 222 } 223#endif 224 225 mMediaBuffersAvailableCondition.wait(mMutex); 226 } 227 228 mMediaBuffersAvailableCondition.signal(); 229 230 return mConsumer->consumerDisconnect(); 231} 232 233sp<MetaData> SurfaceMediaSource::getFormat() 234{ 235 ALOGV("getFormat"); 236 237 Mutex::Autolock lock(mMutex); 238 sp<MetaData> meta = new MetaData; 239 240 meta->setInt32(kKeyWidth, mWidth); 241 meta->setInt32(kKeyHeight, mHeight); 242 // The encoder format is set as an opaque colorformat 243 // The encoder will later find out the actual colorformat 244 // from the GL Frames itself. 245 meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque); 246 meta->setInt32(kKeyStride, mWidth); 247 meta->setInt32(kKeySliceHeight, mHeight); 248 meta->setInt32(kKeyFrameRate, mFrameRate); 249 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 250 return meta; 251} 252 253// Pass the data to the MediaBuffer. Pass in only the metadata 254// Note: Call only when you have the lock 255void SurfaceMediaSource::passMetadataBuffer_l(MediaBuffer **buffer, 256 ANativeWindowBuffer *bufferHandle) const { 257 *buffer = new MediaBuffer(sizeof(VideoNativeMetadata)); 258 VideoNativeMetadata *data = (VideoNativeMetadata *)(*buffer)->data(); 259 if (data == NULL) { 260 ALOGE("Cannot allocate memory for metadata buffer!"); 261 return; 262 } 263 data->eType = metaDataStoredInVideoBuffers(); 264 data->pBuffer = bufferHandle; 265 data->nFenceFd = -1; 266 ALOGV("handle = %p, offset = %zu, length = %zu", 267 bufferHandle, (*buffer)->range_length(), (*buffer)->range_offset()); 268} 269 270status_t SurfaceMediaSource::read( 271 MediaBuffer **buffer, const ReadOptions * /* options */) { 272 ALOGV("read"); 273 Mutex::Autolock lock(mMutex); 274 275 *buffer = NULL; 276 277 while (mStarted && mNumPendingBuffers == mMaxAcquiredBufferCount) { 278 mMediaBuffersAvailableCondition.wait(mMutex); 279 } 280 281 // Update the current buffer info 282 // TODO: mCurrentSlot can be made a bufferstate since there 283 // can be more than one "current" slots. 284 285 BufferItem item; 286 // If the recording has started and the queue is empty, then just 287 // wait here till the frames come in from the client side 288 while (mStarted) { 289 290 status_t err = mConsumer->acquireBuffer(&item, 0); 291 if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 292 // wait for a buffer to be queued 293 mFrameAvailableCondition.wait(mMutex); 294 } else if (err == OK) { 295 err = item.mFence->waitForever("SurfaceMediaSource::read"); 296 if (err) { 297 ALOGW("read: failed to wait for buffer fence: %d", err); 298 } 299 300 // First time seeing the buffer? Added it to the SMS slot 301 if (item.mGraphicBuffer != NULL) { 302 mSlots[item.mSlot].mGraphicBuffer = item.mGraphicBuffer; 303 } 304 mSlots[item.mSlot].mFrameNumber = item.mFrameNumber; 305 306 // check for the timing of this buffer 307 if (mNumFramesReceived == 0 && !mUseAbsoluteTimestamps) { 308 mFirstFrameTimestamp = item.mTimestamp; 309 // Initial delay 310 if (mStartTimeNs > 0) { 311 if (item.mTimestamp < mStartTimeNs) { 312 // This frame predates start of record, discard 313 mConsumer->releaseBuffer( 314 item.mSlot, item.mFrameNumber, EGL_NO_DISPLAY, 315 EGL_NO_SYNC_KHR, Fence::NO_FENCE); 316 continue; 317 } 318 mStartTimeNs = item.mTimestamp - mStartTimeNs; 319 } 320 } 321 item.mTimestamp = mStartTimeNs + (item.mTimestamp - mFirstFrameTimestamp); 322 323 mNumFramesReceived++; 324 325 break; 326 } else { 327 ALOGE("read: acquire failed with error code %d", err); 328 return ERROR_END_OF_STREAM; 329 } 330 331 } 332 333 // If the loop was exited as a result of stopping the recording, 334 // it is OK 335 if (!mStarted) { 336 ALOGV("Read: SurfaceMediaSource is stopped. Returning ERROR_END_OF_STREAM."); 337 return ERROR_END_OF_STREAM; 338 } 339 340 mCurrentSlot = item.mSlot; 341 342 // First time seeing the buffer? Added it to the SMS slot 343 if (item.mGraphicBuffer != NULL) { 344 mSlots[item.mSlot].mGraphicBuffer = item.mGraphicBuffer; 345 } 346 mSlots[item.mSlot].mFrameNumber = item.mFrameNumber; 347 348 mCurrentBuffers.push_back(mSlots[mCurrentSlot].mGraphicBuffer); 349 int64_t prevTimeStamp = mCurrentTimestamp; 350 mCurrentTimestamp = item.mTimestamp; 351 352 mNumFramesEncoded++; 353 // Pass the data to the MediaBuffer. Pass in only the metadata 354 355 passMetadataBuffer_l(buffer, mSlots[mCurrentSlot].mGraphicBuffer->getNativeBuffer()); 356 357 (*buffer)->setObserver(this); 358 (*buffer)->add_ref(); 359 (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000); 360 ALOGV("Frames encoded = %d, timestamp = %" PRId64 ", time diff = %" PRId64, 361 mNumFramesEncoded, mCurrentTimestamp / 1000, 362 mCurrentTimestamp / 1000 - prevTimeStamp / 1000); 363 364 ++mNumPendingBuffers; 365 366#if DEBUG_PENDING_BUFFERS 367 mPendingBuffers.push_back(*buffer); 368#endif 369 370 ALOGV("returning mbuf %p", *buffer); 371 372 return OK; 373} 374 375static buffer_handle_t getMediaBufferHandle(MediaBuffer *buffer) { 376 // need to convert to char* for pointer arithmetic and then 377 // copy the byte stream into our handle 378 buffer_handle_t bufferHandle; 379 memcpy(&bufferHandle, (char*)(buffer->data()) + 4, sizeof(buffer_handle_t)); 380 return bufferHandle; 381} 382 383void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { 384 ALOGV("signalBufferReturned"); 385 386 bool foundBuffer = false; 387 388 Mutex::Autolock lock(mMutex); 389 390 buffer_handle_t bufferHandle = getMediaBufferHandle(buffer); 391 392 for (size_t i = 0; i < mCurrentBuffers.size(); i++) { 393 if (mCurrentBuffers[i]->handle == bufferHandle) { 394 mCurrentBuffers.removeAt(i); 395 foundBuffer = true; 396 break; 397 } 398 } 399 400 if (!foundBuffer) { 401 ALOGW("returned buffer was not found in the current buffer list"); 402 } 403 404 for (int id = 0; id < BufferQueue::NUM_BUFFER_SLOTS; id++) { 405 if (mSlots[id].mGraphicBuffer == NULL) { 406 continue; 407 } 408 409 if (bufferHandle == mSlots[id].mGraphicBuffer->handle) { 410 ALOGV("Slot %d returned, matches handle = %p", id, 411 mSlots[id].mGraphicBuffer->handle); 412 413 mConsumer->releaseBuffer(id, mSlots[id].mFrameNumber, 414 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, 415 Fence::NO_FENCE); 416 417 buffer->setObserver(0); 418 buffer->release(); 419 420 foundBuffer = true; 421 break; 422 } 423 } 424 425 if (!foundBuffer) { 426 CHECK(!"signalBufferReturned: bogus buffer"); 427 } 428 429#if DEBUG_PENDING_BUFFERS 430 for (size_t i = 0; i < mPendingBuffers.size(); ++i) { 431 if (mPendingBuffers.itemAt(i) == buffer) { 432 mPendingBuffers.removeAt(i); 433 break; 434 } 435 } 436#endif 437 438 --mNumPendingBuffers; 439 mMediaBuffersAvailableCondition.broadcast(); 440} 441 442// Part of the BufferQueue::ConsumerListener 443void SurfaceMediaSource::onFrameAvailable(const BufferItem& /* item */) { 444 ALOGV("onFrameAvailable"); 445 446 sp<FrameAvailableListener> listener; 447 { // scope for the lock 448 Mutex::Autolock lock(mMutex); 449 mFrameAvailableCondition.broadcast(); 450 listener = mFrameAvailableListener; 451 } 452 453 if (listener != NULL) { 454 ALOGV("actually calling onFrameAvailable"); 455 listener->onFrameAvailable(); 456 } 457} 458 459// SurfaceMediaSource hijacks this event to assume 460// the prodcuer is disconnecting from the BufferQueue 461// and that it should stop the recording 462void SurfaceMediaSource::onBuffersReleased() { 463 ALOGV("onBuffersReleased"); 464 465 Mutex::Autolock lock(mMutex); 466 467 mFrameAvailableCondition.signal(); 468 469 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { 470 mSlots[i].mGraphicBuffer = 0; 471 } 472} 473 474void SurfaceMediaSource::onSidebandStreamChanged() { 475 ALOG_ASSERT(false, "SurfaceMediaSource can't consume sideband streams"); 476} 477 478} // end of namespace android 479