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 <media/stagefright/SurfaceMediaSource.h> 20 #include <ui/GraphicBuffer.h> 21 #include <media/stagefright/MetaData.h> 22 #include <media/stagefright/MediaDefs.h> 23 #include <media/stagefright/MediaDebug.h> 24 #include <media/stagefright/openmax/OMX_IVCommon.h> 25 #include <media/stagefright/MetadataBufferType.h> 26 27 #include <surfaceflinger/ISurfaceComposer.h> 28 #include <surfaceflinger/SurfaceComposerClient.h> 29 #include <surfaceflinger/IGraphicBufferAlloc.h> 30 #include <OMX_Component.h> 31 32 #include <utils/Log.h> 33 #include <utils/String8.h> 34 35 namespace android { 36 37 SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) : 38 mDefaultWidth(bufW), 39 mDefaultHeight(bufH), 40 mPixelFormat(0), 41 mBufferCount(MIN_ASYNC_BUFFER_SLOTS), 42 mClientBufferCount(0), 43 mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS), 44 mCurrentSlot(INVALID_BUFFER_SLOT), 45 mCurrentTimestamp(0), 46 mSynchronousMode(true), 47 mConnectedApi(NO_CONNECTED_API), 48 mFrameRate(30), 49 mStopped(false), 50 mNumFramesReceived(0), 51 mNumFramesEncoded(0), 52 mFirstFrameTimestamp(0) { 53 LOGV("SurfaceMediaSource::SurfaceMediaSource"); 54 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 55 mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); 56 } 57 58 SurfaceMediaSource::~SurfaceMediaSource() { 59 LOGV("SurfaceMediaSource::~SurfaceMediaSource"); 60 if (!mStopped) { 61 stop(); 62 } 63 } 64 65 size_t SurfaceMediaSource::getQueuedCount() const { 66 Mutex::Autolock lock(mMutex); 67 return mQueue.size(); 68 } 69 70 status_t SurfaceMediaSource::setBufferCountServerLocked(int bufferCount) { 71 if (bufferCount > NUM_BUFFER_SLOTS) 72 return BAD_VALUE; 73 74 // special-case, nothing to do 75 if (bufferCount == mBufferCount) 76 return OK; 77 78 if (!mClientBufferCount && 79 bufferCount >= mBufferCount) { 80 // easy, we just have more buffers 81 mBufferCount = bufferCount; 82 mServerBufferCount = bufferCount; 83 mDequeueCondition.signal(); 84 } else { 85 // we're here because we're either 86 // - reducing the number of available buffers 87 // - or there is a client-buffer-count in effect 88 89 // less than 2 buffers is never allowed 90 if (bufferCount < 2) 91 return BAD_VALUE; 92 93 // when there is non client-buffer-count in effect, the client is not 94 // allowed to dequeue more than one buffer at a time, 95 // so the next time they dequeue a buffer, we know that they don't 96 // own one. the actual resizing will happen during the next 97 // dequeueBuffer. 98 99 mServerBufferCount = bufferCount; 100 } 101 return OK; 102 } 103 104 // Called from the consumer side 105 status_t SurfaceMediaSource::setBufferCountServer(int bufferCount) { 106 Mutex::Autolock lock(mMutex); 107 return setBufferCountServerLocked(bufferCount); 108 } 109 110 status_t SurfaceMediaSource::setBufferCount(int bufferCount) { 111 LOGV("SurfaceMediaSource::setBufferCount"); 112 if (bufferCount > NUM_BUFFER_SLOTS) { 113 LOGE("setBufferCount: bufferCount is larger than the number of buffer slots"); 114 return BAD_VALUE; 115 } 116 117 Mutex::Autolock lock(mMutex); 118 // Error out if the user has dequeued buffers 119 for (int i = 0 ; i < mBufferCount ; i++) { 120 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { 121 LOGE("setBufferCount: client owns some buffers"); 122 return INVALID_OPERATION; 123 } 124 } 125 126 if (bufferCount == 0) { 127 const int minBufferSlots = mSynchronousMode ? 128 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; 129 mClientBufferCount = 0; 130 bufferCount = (mServerBufferCount >= minBufferSlots) ? 131 mServerBufferCount : minBufferSlots; 132 return setBufferCountServerLocked(bufferCount); 133 } 134 135 // We don't allow the client to set a buffer-count less than 136 // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it. 137 if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) { 138 return BAD_VALUE; 139 } 140 141 // here we're guaranteed that the client doesn't have dequeued buffers 142 // and will release all of its buffer references. 143 mBufferCount = bufferCount; 144 mClientBufferCount = bufferCount; 145 mCurrentSlot = INVALID_BUFFER_SLOT; 146 mQueue.clear(); 147 mDequeueCondition.signal(); 148 freeAllBuffersLocked(); 149 return OK; 150 } 151 152 status_t SurfaceMediaSource::requestBuffer(int slot, sp<GraphicBuffer>* buf) { 153 LOGV("SurfaceMediaSource::requestBuffer"); 154 Mutex::Autolock lock(mMutex); 155 if (slot < 0 || mBufferCount <= slot) { 156 LOGE("requestBuffer: slot index out of range [0, %d]: %d", 157 mBufferCount, slot); 158 return BAD_VALUE; 159 } 160 mSlots[slot].mRequestBufferCalled = true; 161 *buf = mSlots[slot].mGraphicBuffer; 162 return NO_ERROR; 163 } 164 165 status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, 166 uint32_t format, uint32_t usage) { 167 LOGV("dequeueBuffer"); 168 Mutex::Autolock lock(mMutex); 169 170 // Check for the buffer size- the client should just use the 171 // default width and height, and not try to set those. 172 // This is needed since 173 // the getFormat() returns mDefaultWidth/ Height for the OMX. It is 174 // queried by OMX in the beginning and not every time a frame comes. 175 // Not sure if there is a way to update the 176 // frame size while recording. So as of now, the client side 177 // sets the default values via the constructor, and the encoder is 178 // setup to encode frames of that size 179 // The design might need to change in the future. 180 // TODO: Currently just uses mDefaultWidth/Height. In the future 181 // we might declare mHeight and mWidth and check against those here. 182 if ((w != 0) || (h != 0)) { 183 if ((w != mDefaultWidth) || (h != mDefaultHeight)) { 184 LOGE("dequeuebuffer: invalid buffer size! Req: %dx%d, Found: %dx%d", 185 mDefaultWidth, mDefaultHeight, w, h); 186 return BAD_VALUE; 187 } 188 } 189 190 status_t returnFlags(OK); 191 int found, foundSync; 192 int dequeuedCount = 0; 193 bool tryAgain = true; 194 while (tryAgain) { 195 // We need to wait for the FIFO to drain if the number of buffer 196 // needs to change. 197 // 198 // The condition "number of buffer needs to change" is true if 199 // - the client doesn't care about how many buffers there are 200 // - AND the actual number of buffer is different from what was 201 // set in the last setBufferCountServer() 202 // - OR - 203 // setBufferCountServer() was set to a value incompatible with 204 // the synchronization mode (for instance because the sync mode 205 // changed since) 206 // 207 // As long as this condition is true AND the FIFO is not empty, we 208 // wait on mDequeueCondition. 209 210 int minBufferCountNeeded = mSynchronousMode ? 211 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; 212 213 if (!mClientBufferCount && 214 ((mServerBufferCount != mBufferCount) || 215 (mServerBufferCount < minBufferCountNeeded))) { 216 // wait for the FIFO to drain 217 while (!mQueue.isEmpty()) { 218 LOGV("Waiting for the FIFO to drain"); 219 mDequeueCondition.wait(mMutex); 220 } 221 if (mStopped) { 222 return NO_INIT; 223 } 224 // need to check again since the mode could have changed 225 // while we were waiting 226 minBufferCountNeeded = mSynchronousMode ? 227 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; 228 } 229 230 if (!mClientBufferCount && 231 ((mServerBufferCount != mBufferCount) || 232 (mServerBufferCount < minBufferCountNeeded))) { 233 // here we're guaranteed that mQueue is empty 234 freeAllBuffersLocked(); 235 mBufferCount = mServerBufferCount; 236 if (mBufferCount < minBufferCountNeeded) 237 mBufferCount = minBufferCountNeeded; 238 mCurrentSlot = INVALID_BUFFER_SLOT; 239 returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS; 240 } 241 242 // look for a free buffer to give to the client 243 found = INVALID_BUFFER_SLOT; 244 foundSync = INVALID_BUFFER_SLOT; 245 dequeuedCount = 0; 246 for (int i = 0; i < mBufferCount; i++) { 247 const int state = mSlots[i].mBufferState; 248 if (state == BufferSlot::DEQUEUED) { 249 dequeuedCount++; 250 continue; // won't be continuing if could 251 // dequeue a non 'FREE' current slot like 252 // that in SurfaceTexture 253 } 254 // In case of Encoding, we do not deque the mCurrentSlot buffer 255 // since we follow synchronous mode (unlike possibly in 256 // SurfaceTexture that could be using the asynch mode 257 // or has some mechanism in GL to be able to wait till the 258 // currentslot is done using the data) 259 // Here, we have to wait for the MPEG4Writer(or equiv) 260 // to tell us when it's done using the current buffer 261 if (state == BufferSlot::FREE) { 262 foundSync = i; 263 // Unlike that in SurfaceTexture, 264 // We don't need to worry if it is the 265 // currentslot or not as it is in state FREE 266 found = i; 267 break; 268 } 269 } 270 271 // clients are not allowed to dequeue more than one buffer 272 // if they didn't set a buffer count. 273 if (!mClientBufferCount && dequeuedCount) { 274 return -EINVAL; 275 } 276 277 // See whether a buffer has been queued since the last setBufferCount so 278 // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below. 279 bool bufferHasBeenQueued = mCurrentSlot != INVALID_BUFFER_SLOT; 280 if (bufferHasBeenQueued) { 281 // make sure the client is not trying to dequeue more buffers 282 // than allowed. 283 const int avail = mBufferCount - (dequeuedCount+1); 284 if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { 285 LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)", 286 MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), 287 dequeuedCount); 288 return -EBUSY; 289 } 290 } 291 292 // we're in synchronous mode and didn't find a buffer, we need to wait 293 // for for some buffers to be consumed 294 tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT); 295 if (tryAgain) { 296 LOGV("Waiting..In synchronous mode and no buffer to dequeue"); 297 mDequeueCondition.wait(mMutex); 298 } 299 if (mStopped) { 300 return NO_INIT; 301 } 302 } 303 304 if (mSynchronousMode && found == INVALID_BUFFER_SLOT) { 305 // foundSync guaranteed to be != INVALID_BUFFER_SLOT 306 found = foundSync; 307 } 308 309 if (found == INVALID_BUFFER_SLOT) { 310 return -EBUSY; 311 } 312 313 const int bufIndex = found; 314 *outBuf = found; 315 316 const bool useDefaultSize = !w && !h; 317 if (useDefaultSize) { 318 // use the default size 319 w = mDefaultWidth; 320 h = mDefaultHeight; 321 } 322 323 const bool updateFormat = (format != 0); 324 if (!updateFormat) { 325 // keep the current (or default) format 326 format = mPixelFormat; 327 } 328 329 // buffer is now in DEQUEUED (but can also be current at the same time, 330 // if we're in synchronous mode) 331 mSlots[bufIndex].mBufferState = BufferSlot::DEQUEUED; 332 333 const sp<GraphicBuffer>& buffer(mSlots[bufIndex].mGraphicBuffer); 334 if ((buffer == NULL) || 335 (uint32_t(buffer->width) != w) || 336 (uint32_t(buffer->height) != h) || 337 (uint32_t(buffer->format) != format) || 338 ((uint32_t(buffer->usage) & usage) != usage)) { 339 // XXX: This will be changed to USAGE_HW_VIDEO_ENCODER once driver 340 // issues with that flag get fixed. 341 usage |= GraphicBuffer::USAGE_HW_TEXTURE; 342 status_t error; 343 sp<GraphicBuffer> graphicBuffer( 344 mGraphicBufferAlloc->createGraphicBuffer( 345 w, h, format, usage, &error)); 346 if (graphicBuffer == 0) { 347 LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); 348 return error; 349 } 350 if (updateFormat) { 351 mPixelFormat = format; 352 } 353 mSlots[bufIndex].mGraphicBuffer = graphicBuffer; 354 mSlots[bufIndex].mRequestBufferCalled = false; 355 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; 356 } 357 return returnFlags; 358 } 359 360 // TODO: clean this up 361 status_t SurfaceMediaSource::setSynchronousMode(bool enabled) { 362 Mutex::Autolock lock(mMutex); 363 if (mStopped) { 364 LOGE("setSynchronousMode: SurfaceMediaSource has been stopped!"); 365 return NO_INIT; 366 } 367 368 if (!enabled) { 369 // Async mode is not allowed 370 LOGE("SurfaceMediaSource can be used only synchronous mode!"); 371 return INVALID_OPERATION; 372 } 373 374 if (mSynchronousMode != enabled) { 375 // - if we're going to asynchronous mode, the queue is guaranteed to be 376 // empty here 377 // - if the client set the number of buffers, we're guaranteed that 378 // we have at least 3 (because we don't allow less) 379 mSynchronousMode = enabled; 380 mDequeueCondition.signal(); 381 } 382 return OK; 383 } 384 385 status_t SurfaceMediaSource::connect(int api, 386 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 387 LOGV("SurfaceMediaSource::connect"); 388 Mutex::Autolock lock(mMutex); 389 390 if (mStopped) { 391 LOGE("Connect: SurfaceMediaSource has been stopped!"); 392 return NO_INIT; 393 } 394 395 status_t err = NO_ERROR; 396 switch (api) { 397 case NATIVE_WINDOW_API_EGL: 398 case NATIVE_WINDOW_API_CPU: 399 case NATIVE_WINDOW_API_MEDIA: 400 case NATIVE_WINDOW_API_CAMERA: 401 if (mConnectedApi != NO_CONNECTED_API) { 402 err = -EINVAL; 403 } else { 404 mConnectedApi = api; 405 *outWidth = mDefaultWidth; 406 *outHeight = mDefaultHeight; 407 *outTransform = 0; 408 } 409 break; 410 default: 411 err = -EINVAL; 412 break; 413 } 414 return err; 415 } 416 417 // This is called by the client side when it is done 418 // TODO: Currently, this also sets mStopped to true which 419 // is needed for unblocking the encoder which might be 420 // waiting to read more frames. So if on the client side, 421 // the same thread supplies the frames and also calls stop 422 // on the encoder, the client has to call disconnect before 423 // it calls stop. 424 // In the case of the camera, 425 // that need not be required since the thread supplying the 426 // frames is separate than the one calling stop. 427 status_t SurfaceMediaSource::disconnect(int api) { 428 LOGV("SurfaceMediaSource::disconnect"); 429 Mutex::Autolock lock(mMutex); 430 431 if (mStopped) { 432 LOGE("disconnect: SurfaceMediaSoource is already stopped!"); 433 return NO_INIT; 434 } 435 436 status_t err = NO_ERROR; 437 switch (api) { 438 case NATIVE_WINDOW_API_EGL: 439 case NATIVE_WINDOW_API_CPU: 440 case NATIVE_WINDOW_API_MEDIA: 441 case NATIVE_WINDOW_API_CAMERA: 442 if (mConnectedApi == api) { 443 mConnectedApi = NO_CONNECTED_API; 444 mStopped = true; 445 mDequeueCondition.signal(); 446 mFrameAvailableCondition.signal(); 447 } else { 448 err = -EINVAL; 449 } 450 break; 451 default: 452 err = -EINVAL; 453 break; 454 } 455 return err; 456 } 457 458 status_t SurfaceMediaSource::queueBuffer(int bufIndex, int64_t timestamp, 459 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 460 LOGV("queueBuffer"); 461 462 Mutex::Autolock lock(mMutex); 463 *outWidth = mDefaultWidth; 464 *outHeight = mDefaultHeight; 465 *outTransform = 0; 466 467 if (bufIndex < 0 || bufIndex >= mBufferCount) { 468 LOGE("queueBuffer: slot index out of range [0, %d]: %d", 469 mBufferCount, bufIndex); 470 return -EINVAL; 471 } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) { 472 LOGE("queueBuffer: slot %d is not owned by the client (state=%d)", 473 bufIndex, mSlots[bufIndex].mBufferState); 474 return -EINVAL; 475 } else if (!mSlots[bufIndex].mRequestBufferCalled) { 476 LOGE("queueBuffer: slot %d was enqueued without requesting a " 477 "buffer", bufIndex); 478 return -EINVAL; 479 } 480 481 if (mNumFramesReceived == 0) { 482 mFirstFrameTimestamp = timestamp; 483 // Initial delay 484 if (mStartTimeNs > 0) { 485 if (timestamp < mStartTimeNs) { 486 // This frame predates start of record, discard 487 mSlots[bufIndex].mBufferState = BufferSlot::FREE; 488 mDequeueCondition.signal(); 489 return OK; 490 } 491 mStartTimeNs = timestamp - mStartTimeNs; 492 } 493 } 494 timestamp = mStartTimeNs + (timestamp - mFirstFrameTimestamp); 495 496 mNumFramesReceived++; 497 if (mSynchronousMode) { 498 // in synchronous mode we queue all buffers in a FIFO 499 mQueue.push_back(bufIndex); 500 LOGV("Client queued buf# %d @slot: %d, Q size = %d, handle = %p, timestamp = %lld", 501 mNumFramesReceived, bufIndex, mQueue.size(), 502 mSlots[bufIndex].mGraphicBuffer->handle, timestamp); 503 } else { 504 // in asynchronous mode we only keep the most recent buffer 505 if (mQueue.empty()) { 506 mQueue.push_back(bufIndex); 507 } else { 508 Fifo::iterator front(mQueue.begin()); 509 // buffer currently queued is freed 510 mSlots[*front].mBufferState = BufferSlot::FREE; 511 // and we record the new buffer index in the queued list 512 *front = bufIndex; 513 } 514 } 515 516 mSlots[bufIndex].mBufferState = BufferSlot::QUEUED; 517 mSlots[bufIndex].mTimestamp = timestamp; 518 // TODO: (Confirm) Don't want to signal dequeue here. 519 // May be just in asynchronous mode? 520 // mDequeueCondition.signal(); 521 522 // Once the queuing is done, we need to let the listener 523 // and signal the buffer consumer (encoder) know that a 524 // buffer is available 525 onFrameReceivedLocked(); 526 527 528 return OK; 529 } 530 531 532 // onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder) 533 // or listeners that a frame has been received 534 // It is supposed to be called only from queuebuffer. 535 // The buffer is NOT made available for dequeueing immediately. We need to 536 // wait to hear from StageFrightRecorder to set the buffer FREE 537 // Make sure this is called when the mutex is locked 538 status_t SurfaceMediaSource::onFrameReceivedLocked() { 539 LOGV("On Frame Received locked"); 540 // Signal the encoder that a new frame has arrived 541 mFrameAvailableCondition.signal(); 542 543 // call back the listener 544 // TODO: The listener may not be needed in SurfaceMediaSource at all. 545 // This can be made a SurfaceTexture specific thing 546 sp<FrameAvailableListener> listener; 547 if (mSynchronousMode || mQueue.empty()) { 548 listener = mFrameAvailableListener; 549 } 550 551 if (listener != 0) { 552 listener->onFrameAvailable(); 553 } 554 return OK; 555 } 556 557 558 void SurfaceMediaSource::cancelBuffer(int bufIndex) { 559 LOGV("SurfaceMediaSource::cancelBuffer"); 560 Mutex::Autolock lock(mMutex); 561 if (bufIndex < 0 || bufIndex >= mBufferCount) { 562 LOGE("cancelBuffer: slot index out of range [0, %d]: %d", 563 mBufferCount, bufIndex); 564 return; 565 } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) { 566 LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", 567 bufIndex, mSlots[bufIndex].mBufferState); 568 return; 569 } 570 mSlots[bufIndex].mBufferState = BufferSlot::FREE; 571 mDequeueCondition.signal(); 572 } 573 574 nsecs_t SurfaceMediaSource::getTimestamp() { 575 LOGV("SurfaceMediaSource::getTimestamp"); 576 Mutex::Autolock lock(mMutex); 577 return mCurrentTimestamp; 578 } 579 580 581 void SurfaceMediaSource::setFrameAvailableListener( 582 const sp<FrameAvailableListener>& listener) { 583 LOGV("SurfaceMediaSource::setFrameAvailableListener"); 584 Mutex::Autolock lock(mMutex); 585 mFrameAvailableListener = listener; 586 } 587 588 void SurfaceMediaSource::freeAllBuffersLocked() { 589 LOGV("freeAllBuffersLocked"); 590 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 591 mSlots[i].mGraphicBuffer = 0; 592 mSlots[i].mBufferState = BufferSlot::FREE; 593 } 594 } 595 596 sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const { 597 Mutex::Autolock lock(mMutex); 598 return mCurrentBuf; 599 } 600 601 int SurfaceMediaSource::query(int what, int* outValue) 602 { 603 LOGV("query"); 604 Mutex::Autolock lock(mMutex); 605 int value; 606 switch (what) { 607 case NATIVE_WINDOW_WIDTH: 608 value = mDefaultWidth; 609 if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0) 610 value = mCurrentBuf->width; 611 break; 612 case NATIVE_WINDOW_HEIGHT: 613 value = mDefaultHeight; 614 if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0) 615 value = mCurrentBuf->height; 616 break; 617 case NATIVE_WINDOW_FORMAT: 618 value = mPixelFormat; 619 break; 620 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 621 value = mSynchronousMode ? 622 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS; 623 break; 624 default: 625 return BAD_VALUE; 626 } 627 outValue[0] = value; 628 return NO_ERROR; 629 } 630 631 void SurfaceMediaSource::dump(String8& result) const 632 { 633 char buffer[1024]; 634 dump(result, "", buffer, 1024); 635 } 636 637 void SurfaceMediaSource::dump(String8& result, const char* prefix, 638 char* buffer, size_t SIZE) const 639 { 640 Mutex::Autolock _l(mMutex); 641 snprintf(buffer, SIZE, 642 "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " 643 "mPixelFormat=%d, \n", 644 prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight, 645 mPixelFormat); 646 result.append(buffer); 647 648 String8 fifo; 649 int fifoSize = 0; 650 Fifo::const_iterator i(mQueue.begin()); 651 while (i != mQueue.end()) { 652 snprintf(buffer, SIZE, "%02d ", *i++); 653 fifoSize++; 654 fifo.append(buffer); 655 } 656 657 result.append(buffer); 658 659 struct { 660 const char * operator()(int state) const { 661 switch (state) { 662 case BufferSlot::DEQUEUED: return "DEQUEUED"; 663 case BufferSlot::QUEUED: return "QUEUED"; 664 case BufferSlot::FREE: return "FREE"; 665 default: return "Unknown"; 666 } 667 } 668 } stateName; 669 670 for (int i = 0; i < mBufferCount; i++) { 671 const BufferSlot& slot(mSlots[i]); 672 snprintf(buffer, SIZE, 673 "%s%s[%02d] state=%-8s, " 674 "timestamp=%lld\n", 675 prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState), 676 slot.mTimestamp 677 ); 678 result.append(buffer); 679 } 680 } 681 682 status_t SurfaceMediaSource::setFrameRate(int32_t fps) 683 { 684 Mutex::Autolock lock(mMutex); 685 const int MAX_FRAME_RATE = 60; 686 if (fps < 0 || fps > MAX_FRAME_RATE) { 687 return BAD_VALUE; 688 } 689 mFrameRate = fps; 690 return OK; 691 } 692 693 bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const { 694 LOGV("isMetaDataStoredInVideoBuffers"); 695 return true; 696 } 697 698 int32_t SurfaceMediaSource::getFrameRate( ) const { 699 Mutex::Autolock lock(mMutex); 700 return mFrameRate; 701 } 702 703 status_t SurfaceMediaSource::start(MetaData *params) 704 { 705 LOGV("started!"); 706 707 mStartTimeNs = 0; 708 int64_t startTimeUs; 709 if (params && params->findInt64(kKeyTime, &startTimeUs)) { 710 mStartTimeNs = startTimeUs * 1000; 711 } 712 713 return OK; 714 } 715 716 717 status_t SurfaceMediaSource::stop() 718 { 719 LOGV("Stop"); 720 721 Mutex::Autolock lock(mMutex); 722 // TODO: Add waiting on mFrameCompletedCondition here? 723 mStopped = true; 724 mFrameAvailableCondition.signal(); 725 mDequeueCondition.signal(); 726 mQueue.clear(); 727 freeAllBuffersLocked(); 728 729 return OK; 730 } 731 732 sp<MetaData> SurfaceMediaSource::getFormat() 733 { 734 LOGV("getFormat"); 735 Mutex::Autolock autoLock(mMutex); 736 sp<MetaData> meta = new MetaData; 737 738 meta->setInt32(kKeyWidth, mDefaultWidth); 739 meta->setInt32(kKeyHeight, mDefaultHeight); 740 // The encoder format is set as an opaque colorformat 741 // The encoder will later find out the actual colorformat 742 // from the GL Frames itself. 743 meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque); 744 meta->setInt32(kKeyStride, mDefaultWidth); 745 meta->setInt32(kKeySliceHeight, mDefaultHeight); 746 meta->setInt32(kKeyFrameRate, mFrameRate); 747 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 748 return meta; 749 } 750 751 status_t SurfaceMediaSource::read( MediaBuffer **buffer, 752 const ReadOptions *options) 753 { 754 Mutex::Autolock autoLock(mMutex) ; 755 756 LOGV("Read. Size of queued buffer: %d", mQueue.size()); 757 *buffer = NULL; 758 759 // If the recording has started and the queue is empty, then just 760 // wait here till the frames come in from the client side 761 while (!mStopped && mQueue.empty()) { 762 LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition"); 763 mFrameAvailableCondition.wait(mMutex); 764 } 765 766 // If the loop was exited as a result of stopping the recording, 767 // it is OK 768 if (mStopped) { 769 LOGV("Read: SurfaceMediaSource is stopped. Returning ERROR_END_OF_STREAM."); 770 return ERROR_END_OF_STREAM; 771 } 772 773 // Update the current buffer info 774 // TODO: mCurrentSlot can be made a bufferstate since there 775 // can be more than one "current" slots. 776 Fifo::iterator front(mQueue.begin()); 777 mCurrentSlot = *front; 778 mQueue.erase(front); 779 mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer; 780 int64_t prevTimeStamp = mCurrentTimestamp; 781 mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp; 782 783 mNumFramesEncoded++; 784 // Pass the data to the MediaBuffer. Pass in only the metadata 785 passMetadataBufferLocked(buffer); 786 787 (*buffer)->setObserver(this); 788 (*buffer)->add_ref(); 789 (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000); 790 LOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld", 791 mNumFramesEncoded, mCurrentTimestamp / 1000, 792 mCurrentTimestamp / 1000 - prevTimeStamp / 1000); 793 794 return OK; 795 } 796 797 // Pass the data to the MediaBuffer. Pass in only the metadata 798 // The metadata passed consists of two parts: 799 // 1. First, there is an integer indicating that it is a GRAlloc 800 // source (kMetadataBufferTypeGrallocSource) 801 // 2. This is followed by the buffer_handle_t that is a handle to the 802 // GRalloc buffer. The encoder needs to interpret this GRalloc handle 803 // and encode the frames. 804 // -------------------------------------------------------------- 805 // | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) | 806 // -------------------------------------------------------------- 807 // Note: Call only when you have the lock 808 void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) { 809 LOGV("passMetadataBuffer"); 810 // MediaBuffer allocates and owns this data 811 MediaBuffer *tempBuffer = 812 new MediaBuffer(4 + sizeof(buffer_handle_t)); 813 char *data = (char *)tempBuffer->data(); 814 if (data == NULL) { 815 LOGE("Cannot allocate memory for metadata buffer!"); 816 return; 817 } 818 OMX_U32 type = kMetadataBufferTypeGrallocSource; 819 memcpy(data, &type, 4); 820 memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t)); 821 *buffer = tempBuffer; 822 823 LOGV("handle = %p, , offset = %d, length = %d", 824 mCurrentBuf->handle, (*buffer)->range_length(), (*buffer)->range_offset()); 825 } 826 827 void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { 828 LOGV("signalBufferReturned"); 829 830 bool foundBuffer = false; 831 Mutex::Autolock autoLock(mMutex); 832 833 if (mStopped) { 834 LOGV("signalBufferReturned: mStopped = true! Nothing to do!"); 835 return; 836 } 837 838 for (int id = 0; id < NUM_BUFFER_SLOTS; id++) { 839 if (mSlots[id].mGraphicBuffer == NULL) { 840 continue; 841 } 842 if (checkBufferMatchesSlot(id, buffer)) { 843 LOGV("Slot %d returned, matches handle = %p", id, 844 mSlots[id].mGraphicBuffer->handle); 845 mSlots[id].mBufferState = BufferSlot::FREE; 846 buffer->setObserver(0); 847 buffer->release(); 848 mDequeueCondition.signal(); 849 mFrameCompleteCondition.signal(); 850 foundBuffer = true; 851 break; 852 } 853 } 854 855 if (!foundBuffer) { 856 CHECK_EQ(0, "signalBufferReturned: bogus buffer"); 857 } 858 } 859 860 bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) { 861 LOGV("Check if Buffer matches slot"); 862 // need to convert to char* for pointer arithmetic and then 863 // copy the byte stream into our handle 864 buffer_handle_t bufferHandle ; 865 memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t)); 866 return mSlots[slot].mGraphicBuffer->handle == bufferHandle; 867 } 868 869 } // end of namespace android 870