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