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