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