SurfaceMediaSource.cpp revision 4c57986f963c81fc7c2455deb113c9b32b135468
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 35namespace android { 36 37SurfaceMediaSource::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 58SurfaceMediaSource::~SurfaceMediaSource() { 59 LOGV("SurfaceMediaSource::~SurfaceMediaSource"); 60 if (!mStopped) { 61 stop(); 62 } 63} 64 65size_t SurfaceMediaSource::getQueuedCount() const { 66 Mutex::Autolock lock(mMutex); 67 return mQueue.size(); 68} 69 70status_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 105status_t SurfaceMediaSource::setBufferCountServer(int bufferCount) { 106 Mutex::Autolock lock(mMutex); 107 return setBufferCountServerLocked(bufferCount); 108} 109 110status_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 152status_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 165status_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 usage |= GraphicBuffer::USAGE_HW_VIDEO_ENCODER; 340 status_t error; 341 sp<GraphicBuffer> graphicBuffer( 342 mGraphicBufferAlloc->createGraphicBuffer( 343 w, h, format, usage, &error)); 344 if (graphicBuffer == 0) { 345 LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); 346 return error; 347 } 348 if (updateFormat) { 349 mPixelFormat = format; 350 } 351 mSlots[bufIndex].mGraphicBuffer = graphicBuffer; 352 mSlots[bufIndex].mRequestBufferCalled = false; 353 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; 354 } 355 return returnFlags; 356} 357 358// TODO: clean this up 359status_t SurfaceMediaSource::setSynchronousMode(bool enabled) { 360 Mutex::Autolock lock(mMutex); 361 if (mStopped) { 362 LOGE("setSynchronousMode: SurfaceMediaSource has been stopped!"); 363 return NO_INIT; 364 } 365 366 if (!enabled) { 367 // Async mode is not allowed 368 LOGE("SurfaceMediaSource can be used only synchronous mode!"); 369 return INVALID_OPERATION; 370 } 371 372 if (mSynchronousMode != enabled) { 373 // - if we're going to asynchronous mode, the queue is guaranteed to be 374 // empty here 375 // - if the client set the number of buffers, we're guaranteed that 376 // we have at least 3 (because we don't allow less) 377 mSynchronousMode = enabled; 378 mDequeueCondition.signal(); 379 } 380 return OK; 381} 382 383status_t SurfaceMediaSource::connect(int api, 384 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 385 LOGV("SurfaceMediaSource::connect"); 386 Mutex::Autolock lock(mMutex); 387 388 if (mStopped) { 389 LOGE("Connect: SurfaceMediaSource has been stopped!"); 390 return NO_INIT; 391 } 392 393 status_t err = NO_ERROR; 394 switch (api) { 395 case NATIVE_WINDOW_API_EGL: 396 case NATIVE_WINDOW_API_CPU: 397 case NATIVE_WINDOW_API_MEDIA: 398 case NATIVE_WINDOW_API_CAMERA: 399 if (mConnectedApi != NO_CONNECTED_API) { 400 err = -EINVAL; 401 } else { 402 mConnectedApi = api; 403 *outWidth = mDefaultWidth; 404 *outHeight = mDefaultHeight; 405 *outTransform = 0; 406 } 407 break; 408 default: 409 err = -EINVAL; 410 break; 411 } 412 return err; 413} 414 415// This is called by the client side when it is done 416// TODO: Currently, this also sets mStopped to true which 417// is needed for unblocking the encoder which might be 418// waiting to read more frames. So if on the client side, 419// the same thread supplies the frames and also calls stop 420// on the encoder, the client has to call disconnect before 421// it calls stop. 422// In the case of the camera, 423// that need not be required since the thread supplying the 424// frames is separate than the one calling stop. 425status_t SurfaceMediaSource::disconnect(int api) { 426 LOGV("SurfaceMediaSource::disconnect"); 427 Mutex::Autolock lock(mMutex); 428 429 if (mStopped) { 430 LOGE("disconnect: SurfaceMediaSoource is already stopped!"); 431 return NO_INIT; 432 } 433 434 status_t err = NO_ERROR; 435 switch (api) { 436 case NATIVE_WINDOW_API_EGL: 437 case NATIVE_WINDOW_API_CPU: 438 case NATIVE_WINDOW_API_MEDIA: 439 case NATIVE_WINDOW_API_CAMERA: 440 if (mConnectedApi == api) { 441 mConnectedApi = NO_CONNECTED_API; 442 mStopped = true; 443 mDequeueCondition.signal(); 444 mFrameAvailableCondition.signal(); 445 } else { 446 err = -EINVAL; 447 } 448 break; 449 default: 450 err = -EINVAL; 451 break; 452 } 453 return err; 454} 455 456status_t SurfaceMediaSource::queueBuffer(int bufIndex, int64_t timestamp, 457 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 458 LOGV("queueBuffer"); 459 460 Mutex::Autolock lock(mMutex); 461 *outWidth = mDefaultWidth; 462 *outHeight = mDefaultHeight; 463 *outTransform = 0; 464 465 if (bufIndex < 0 || bufIndex >= mBufferCount) { 466 LOGE("queueBuffer: slot index out of range [0, %d]: %d", 467 mBufferCount, bufIndex); 468 return -EINVAL; 469 } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) { 470 LOGE("queueBuffer: slot %d is not owned by the client (state=%d)", 471 bufIndex, mSlots[bufIndex].mBufferState); 472 return -EINVAL; 473 } else if (!mSlots[bufIndex].mRequestBufferCalled) { 474 LOGE("queueBuffer: slot %d was enqueued without requesting a " 475 "buffer", bufIndex); 476 return -EINVAL; 477 } 478 479 if (mNumFramesReceived == 0) { 480 mFirstFrameTimestamp = timestamp; 481 // Initial delay 482 if (mStartTimeNs > 0) { 483 if (timestamp < mStartTimeNs) { 484 // This frame predates start of record, discard 485 mSlots[bufIndex].mBufferState = BufferSlot::FREE; 486 mDequeueCondition.signal(); 487 return OK; 488 } 489 mStartTimeNs = timestamp - mStartTimeNs; 490 } 491 } 492 timestamp = mStartTimeNs + (timestamp - mFirstFrameTimestamp); 493 494 mNumFramesReceived++; 495 if (mSynchronousMode) { 496 // in synchronous mode we queue all buffers in a FIFO 497 mQueue.push_back(bufIndex); 498 LOGV("Client queued buf# %d @slot: %d, Q size = %d, handle = %p, timestamp = %lld", 499 mNumFramesReceived, bufIndex, mQueue.size(), 500 mSlots[bufIndex].mGraphicBuffer->handle, timestamp); 501 } else { 502 // in asynchronous mode we only keep the most recent buffer 503 if (mQueue.empty()) { 504 mQueue.push_back(bufIndex); 505 } else { 506 Fifo::iterator front(mQueue.begin()); 507 // buffer currently queued is freed 508 mSlots[*front].mBufferState = BufferSlot::FREE; 509 // and we record the new buffer index in the queued list 510 *front = bufIndex; 511 } 512 } 513 514 mSlots[bufIndex].mBufferState = BufferSlot::QUEUED; 515 mSlots[bufIndex].mTimestamp = timestamp; 516 // TODO: (Confirm) Don't want to signal dequeue here. 517 // May be just in asynchronous mode? 518 // mDequeueCondition.signal(); 519 520 // Once the queuing is done, we need to let the listener 521 // and signal the buffer consumer (encoder) know that a 522 // buffer is available 523 onFrameReceivedLocked(); 524 525 526 return OK; 527} 528 529 530// onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder) 531// or listeners that a frame has been received 532// It is supposed to be called only from queuebuffer. 533// The buffer is NOT made available for dequeueing immediately. We need to 534// wait to hear from StageFrightRecorder to set the buffer FREE 535// Make sure this is called when the mutex is locked 536status_t SurfaceMediaSource::onFrameReceivedLocked() { 537 LOGV("On Frame Received locked"); 538 // Signal the encoder that a new frame has arrived 539 mFrameAvailableCondition.signal(); 540 541 // call back the listener 542 // TODO: The listener may not be needed in SurfaceMediaSource at all. 543 // This can be made a SurfaceTexture specific thing 544 sp<FrameAvailableListener> listener; 545 if (mSynchronousMode || mQueue.empty()) { 546 listener = mFrameAvailableListener; 547 } 548 549 if (listener != 0) { 550 listener->onFrameAvailable(); 551 } 552 return OK; 553} 554 555 556void SurfaceMediaSource::cancelBuffer(int bufIndex) { 557 LOGV("SurfaceMediaSource::cancelBuffer"); 558 Mutex::Autolock lock(mMutex); 559 if (bufIndex < 0 || bufIndex >= mBufferCount) { 560 LOGE("cancelBuffer: slot index out of range [0, %d]: %d", 561 mBufferCount, bufIndex); 562 return; 563 } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) { 564 LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", 565 bufIndex, mSlots[bufIndex].mBufferState); 566 return; 567 } 568 mSlots[bufIndex].mBufferState = BufferSlot::FREE; 569 mDequeueCondition.signal(); 570} 571 572nsecs_t SurfaceMediaSource::getTimestamp() { 573 LOGV("SurfaceMediaSource::getTimestamp"); 574 Mutex::Autolock lock(mMutex); 575 return mCurrentTimestamp; 576} 577 578 579void SurfaceMediaSource::setFrameAvailableListener( 580 const sp<FrameAvailableListener>& listener) { 581 LOGV("SurfaceMediaSource::setFrameAvailableListener"); 582 Mutex::Autolock lock(mMutex); 583 mFrameAvailableListener = listener; 584} 585 586void SurfaceMediaSource::freeAllBuffersLocked() { 587 LOGV("freeAllBuffersLocked"); 588 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 589 mSlots[i].mGraphicBuffer = 0; 590 mSlots[i].mBufferState = BufferSlot::FREE; 591 } 592} 593 594sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const { 595 Mutex::Autolock lock(mMutex); 596 return mCurrentBuf; 597} 598 599int SurfaceMediaSource::query(int what, int* outValue) 600{ 601 LOGV("query"); 602 Mutex::Autolock lock(mMutex); 603 int value; 604 switch (what) { 605 case NATIVE_WINDOW_WIDTH: 606 value = mDefaultWidth; 607 if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0) 608 value = mCurrentBuf->width; 609 break; 610 case NATIVE_WINDOW_HEIGHT: 611 value = mDefaultHeight; 612 if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0) 613 value = mCurrentBuf->height; 614 break; 615 case NATIVE_WINDOW_FORMAT: 616 value = mPixelFormat; 617 break; 618 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 619 value = mSynchronousMode ? 620 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS; 621 break; 622 default: 623 return BAD_VALUE; 624 } 625 outValue[0] = value; 626 return NO_ERROR; 627} 628 629void SurfaceMediaSource::dump(String8& result) const 630{ 631 char buffer[1024]; 632 dump(result, "", buffer, 1024); 633} 634 635void SurfaceMediaSource::dump(String8& result, const char* prefix, 636 char* buffer, size_t SIZE) const 637{ 638 Mutex::Autolock _l(mMutex); 639 snprintf(buffer, SIZE, 640 "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " 641 "mPixelFormat=%d, \n", 642 prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight, 643 mPixelFormat); 644 result.append(buffer); 645 646 String8 fifo; 647 int fifoSize = 0; 648 Fifo::const_iterator i(mQueue.begin()); 649 while (i != mQueue.end()) { 650 snprintf(buffer, SIZE, "%02d ", *i++); 651 fifoSize++; 652 fifo.append(buffer); 653 } 654 655 result.append(buffer); 656 657 struct { 658 const char * operator()(int state) const { 659 switch (state) { 660 case BufferSlot::DEQUEUED: return "DEQUEUED"; 661 case BufferSlot::QUEUED: return "QUEUED"; 662 case BufferSlot::FREE: return "FREE"; 663 default: return "Unknown"; 664 } 665 } 666 } stateName; 667 668 for (int i = 0; i < mBufferCount; i++) { 669 const BufferSlot& slot(mSlots[i]); 670 snprintf(buffer, SIZE, 671 "%s%s[%02d] state=%-8s, " 672 "timestamp=%lld\n", 673 prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState), 674 slot.mTimestamp 675 ); 676 result.append(buffer); 677 } 678} 679 680status_t SurfaceMediaSource::setFrameRate(int32_t fps) 681{ 682 Mutex::Autolock lock(mMutex); 683 const int MAX_FRAME_RATE = 60; 684 if (fps < 0 || fps > MAX_FRAME_RATE) { 685 return BAD_VALUE; 686 } 687 mFrameRate = fps; 688 return OK; 689} 690 691bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const { 692 LOGV("isMetaDataStoredInVideoBuffers"); 693 return true; 694} 695 696int32_t SurfaceMediaSource::getFrameRate( ) const { 697 Mutex::Autolock lock(mMutex); 698 return mFrameRate; 699} 700 701status_t SurfaceMediaSource::start(MetaData *params) 702{ 703 LOGV("started!"); 704 705 mStartTimeNs = 0; 706 int64_t startTimeUs; 707 if (params && params->findInt64(kKeyTime, &startTimeUs)) { 708 mStartTimeNs = startTimeUs * 1000; 709 } 710 711 return OK; 712} 713 714 715status_t SurfaceMediaSource::stop() 716{ 717 LOGV("Stop"); 718 719 Mutex::Autolock lock(mMutex); 720 // TODO: Add waiting on mFrameCompletedCondition here? 721 mStopped = true; 722 mFrameAvailableCondition.signal(); 723 mDequeueCondition.signal(); 724 mQueue.clear(); 725 freeAllBuffersLocked(); 726 727 return OK; 728} 729 730sp<MetaData> SurfaceMediaSource::getFormat() 731{ 732 LOGV("getFormat"); 733 Mutex::Autolock autoLock(mMutex); 734 sp<MetaData> meta = new MetaData; 735 736 meta->setInt32(kKeyWidth, mDefaultWidth); 737 meta->setInt32(kKeyHeight, mDefaultHeight); 738 // The encoder format is set as an opaque colorformat 739 // The encoder will later find out the actual colorformat 740 // from the GL Frames itself. 741 meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque); 742 meta->setInt32(kKeyStride, mDefaultWidth); 743 meta->setInt32(kKeySliceHeight, mDefaultHeight); 744 meta->setInt32(kKeyFrameRate, mFrameRate); 745 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 746 return meta; 747} 748 749status_t SurfaceMediaSource::read( MediaBuffer **buffer, 750 const ReadOptions *options) 751{ 752 Mutex::Autolock autoLock(mMutex) ; 753 754 LOGV("Read. Size of queued buffer: %d", mQueue.size()); 755 *buffer = NULL; 756 757 // If the recording has started and the queue is empty, then just 758 // wait here till the frames come in from the client side 759 while (!mStopped && mQueue.empty()) { 760 LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition"); 761 mFrameAvailableCondition.wait(mMutex); 762 } 763 764 // If the loop was exited as a result of stopping the recording, 765 // it is OK 766 if (mStopped) { 767 LOGV("Read: SurfaceMediaSource is stopped. Returning ERROR_END_OF_STREAM."); 768 return ERROR_END_OF_STREAM; 769 } 770 771 // Update the current buffer info 772 // TODO: mCurrentSlot can be made a bufferstate since there 773 // can be more than one "current" slots. 774 Fifo::iterator front(mQueue.begin()); 775 mCurrentSlot = *front; 776 mQueue.erase(front); 777 mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer; 778 int64_t prevTimeStamp = mCurrentTimestamp; 779 mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp; 780 781 mNumFramesEncoded++; 782 // Pass the data to the MediaBuffer. Pass in only the metadata 783 passMetadataBufferLocked(buffer); 784 785 (*buffer)->setObserver(this); 786 (*buffer)->add_ref(); 787 (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000); 788 LOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld", 789 mNumFramesEncoded, mCurrentTimestamp / 1000, 790 mCurrentTimestamp / 1000 - prevTimeStamp / 1000); 791 792 return OK; 793} 794 795// Pass the data to the MediaBuffer. Pass in only the metadata 796// The metadata passed consists of two parts: 797// 1. First, there is an integer indicating that it is a GRAlloc 798// source (kMetadataBufferTypeGrallocSource) 799// 2. This is followed by the buffer_handle_t that is a handle to the 800// GRalloc buffer. The encoder needs to interpret this GRalloc handle 801// and encode the frames. 802// -------------------------------------------------------------- 803// | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) | 804// -------------------------------------------------------------- 805// Note: Call only when you have the lock 806void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) { 807 LOGV("passMetadataBuffer"); 808 // MediaBuffer allocates and owns this data 809 MediaBuffer *tempBuffer = 810 new MediaBuffer(4 + sizeof(buffer_handle_t)); 811 char *data = (char *)tempBuffer->data(); 812 if (data == NULL) { 813 LOGE("Cannot allocate memory for metadata buffer!"); 814 return; 815 } 816 OMX_U32 type = kMetadataBufferTypeGrallocSource; 817 memcpy(data, &type, 4); 818 memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t)); 819 *buffer = tempBuffer; 820 821 LOGV("handle = %p, , offset = %d, length = %d", 822 mCurrentBuf->handle, (*buffer)->range_length(), (*buffer)->range_offset()); 823} 824 825void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { 826 LOGV("signalBufferReturned"); 827 828 bool foundBuffer = false; 829 Mutex::Autolock autoLock(mMutex); 830 831 if (mStopped) { 832 LOGV("signalBufferReturned: mStopped = true! Nothing to do!"); 833 return; 834 } 835 836 for (int id = 0; id < NUM_BUFFER_SLOTS; id++) { 837 if (mSlots[id].mGraphicBuffer == NULL) { 838 continue; 839 } 840 if (checkBufferMatchesSlot(id, buffer)) { 841 LOGV("Slot %d returned, matches handle = %p", id, 842 mSlots[id].mGraphicBuffer->handle); 843 mSlots[id].mBufferState = BufferSlot::FREE; 844 buffer->setObserver(0); 845 buffer->release(); 846 mDequeueCondition.signal(); 847 mFrameCompleteCondition.signal(); 848 foundBuffer = true; 849 break; 850 } 851 } 852 853 if (!foundBuffer) { 854 CHECK_EQ(0, "signalBufferReturned: bogus buffer"); 855 } 856} 857 858bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) { 859 LOGV("Check if Buffer matches slot"); 860 // need to convert to char* for pointer arithmetic and then 861 // copy the byte stream into our handle 862 buffer_handle_t bufferHandle ; 863 memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t)); 864 return mSlots[slot].mGraphicBuffer->handle == bufferHandle; 865} 866 867} // end of namespace android 868