SurfaceMediaSource.cpp revision 404a123bed7f180724ead17f10e037b3eb347701
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#include <private/gui/ComposerService.h> 36 37namespace android { 38 39SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) : 40 mDefaultWidth(bufW), 41 mDefaultHeight(bufH), 42 mPixelFormat(0), 43 mBufferCount(MIN_ASYNC_BUFFER_SLOTS), 44 mClientBufferCount(0), 45 mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS), 46 mCurrentSlot(INVALID_BUFFER_SLOT), 47 mCurrentTimestamp(0), 48 mSynchronousMode(true), 49 mConnectedApi(NO_CONNECTED_API), 50 mFrameRate(30), 51 mStopped(false), 52 mNumFramesReceived(0), 53 mNumFramesEncoded(0), 54 mFirstFrameTimestamp(0) { 55 ALOGV("SurfaceMediaSource::SurfaceMediaSource"); 56 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 57 mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); 58} 59 60SurfaceMediaSource::~SurfaceMediaSource() { 61 ALOGV("SurfaceMediaSource::~SurfaceMediaSource"); 62 if (!mStopped) { 63 stop(); 64 } 65} 66 67size_t SurfaceMediaSource::getQueuedCount() const { 68 Mutex::Autolock lock(mMutex); 69 return mQueue.size(); 70} 71 72status_t SurfaceMediaSource::setBufferCountServerLocked(int bufferCount) { 73 if (bufferCount > NUM_BUFFER_SLOTS) 74 return BAD_VALUE; 75 76 // special-case, nothing to do 77 if (bufferCount == mBufferCount) 78 return OK; 79 80 if (!mClientBufferCount && 81 bufferCount >= mBufferCount) { 82 // easy, we just have more buffers 83 mBufferCount = bufferCount; 84 mServerBufferCount = bufferCount; 85 mDequeueCondition.signal(); 86 } else { 87 // we're here because we're either 88 // - reducing the number of available buffers 89 // - or there is a client-buffer-count in effect 90 91 // less than 2 buffers is never allowed 92 if (bufferCount < 2) 93 return BAD_VALUE; 94 95 // when there is non client-buffer-count in effect, the client is not 96 // allowed to dequeue more than one buffer at a time, 97 // so the next time they dequeue a buffer, we know that they don't 98 // own one. the actual resizing will happen during the next 99 // dequeueBuffer. 100 101 mServerBufferCount = bufferCount; 102 } 103 return OK; 104} 105 106// Called from the consumer side 107status_t SurfaceMediaSource::setBufferCountServer(int bufferCount) { 108 Mutex::Autolock lock(mMutex); 109 return setBufferCountServerLocked(bufferCount); 110} 111 112status_t SurfaceMediaSource::setBufferCount(int bufferCount) { 113 ALOGV("SurfaceMediaSource::setBufferCount"); 114 if (bufferCount > NUM_BUFFER_SLOTS) { 115 LOGE("setBufferCount: bufferCount is larger than the number of buffer slots"); 116 return BAD_VALUE; 117 } 118 119 Mutex::Autolock lock(mMutex); 120 // Error out if the user has dequeued buffers 121 for (int i = 0 ; i < mBufferCount ; i++) { 122 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { 123 LOGE("setBufferCount: client owns some buffers"); 124 return INVALID_OPERATION; 125 } 126 } 127 128 if (bufferCount == 0) { 129 const int minBufferSlots = mSynchronousMode ? 130 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; 131 mClientBufferCount = 0; 132 bufferCount = (mServerBufferCount >= minBufferSlots) ? 133 mServerBufferCount : minBufferSlots; 134 return setBufferCountServerLocked(bufferCount); 135 } 136 137 // We don't allow the client to set a buffer-count less than 138 // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it. 139 if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) { 140 return BAD_VALUE; 141 } 142 143 // here we're guaranteed that the client doesn't have dequeued buffers 144 // and will release all of its buffer references. 145 mBufferCount = bufferCount; 146 mClientBufferCount = bufferCount; 147 mCurrentSlot = INVALID_BUFFER_SLOT; 148 mQueue.clear(); 149 mDequeueCondition.signal(); 150 freeAllBuffersLocked(); 151 return OK; 152} 153 154status_t SurfaceMediaSource::requestBuffer(int slot, sp<GraphicBuffer>* buf) { 155 ALOGV("SurfaceMediaSource::requestBuffer"); 156 Mutex::Autolock lock(mMutex); 157 if (slot < 0 || mBufferCount <= slot) { 158 LOGE("requestBuffer: slot index out of range [0, %d]: %d", 159 mBufferCount, slot); 160 return BAD_VALUE; 161 } 162 mSlots[slot].mRequestBufferCalled = true; 163 *buf = mSlots[slot].mGraphicBuffer; 164 return NO_ERROR; 165} 166 167status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, 168 uint32_t format, uint32_t usage) { 169 ALOGV("dequeueBuffer"); 170 Mutex::Autolock lock(mMutex); 171 172 // Check for the buffer size- the client should just use the 173 // default width and height, and not try to set those. 174 // This is needed since 175 // the getFormat() returns mDefaultWidth/ Height for the OMX. It is 176 // queried by OMX in the beginning and not every time a frame comes. 177 // Not sure if there is a way to update the 178 // frame size while recording. So as of now, the client side 179 // sets the default values via the constructor, and the encoder is 180 // setup to encode frames of that size 181 // The design might need to change in the future. 182 // TODO: Currently just uses mDefaultWidth/Height. In the future 183 // we might declare mHeight and mWidth and check against those here. 184 if ((w != 0) || (h != 0)) { 185 if ((w != mDefaultWidth) || (h != mDefaultHeight)) { 186 LOGE("dequeuebuffer: invalid buffer size! Req: %dx%d, Found: %dx%d", 187 mDefaultWidth, mDefaultHeight, w, h); 188 return BAD_VALUE; 189 } 190 } 191 192 status_t returnFlags(OK); 193 int found, foundSync; 194 int dequeuedCount = 0; 195 bool tryAgain = true; 196 while (tryAgain) { 197 // We need to wait for the FIFO to drain if the number of buffer 198 // needs to change. 199 // 200 // The condition "number of buffer needs to change" is true if 201 // - the client doesn't care about how many buffers there are 202 // - AND the actual number of buffer is different from what was 203 // set in the last setBufferCountServer() 204 // - OR - 205 // setBufferCountServer() was set to a value incompatible with 206 // the synchronization mode (for instance because the sync mode 207 // changed since) 208 // 209 // As long as this condition is true AND the FIFO is not empty, we 210 // wait on mDequeueCondition. 211 212 int minBufferCountNeeded = mSynchronousMode ? 213 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; 214 215 if (!mClientBufferCount && 216 ((mServerBufferCount != mBufferCount) || 217 (mServerBufferCount < minBufferCountNeeded))) { 218 // wait for the FIFO to drain 219 while (!mQueue.isEmpty()) { 220 ALOGV("Waiting for the FIFO to drain"); 221 mDequeueCondition.wait(mMutex); 222 } 223 if (mStopped) { 224 return NO_INIT; 225 } 226 // need to check again since the mode could have changed 227 // while we were waiting 228 minBufferCountNeeded = mSynchronousMode ? 229 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; 230 } 231 232 if (!mClientBufferCount && 233 ((mServerBufferCount != mBufferCount) || 234 (mServerBufferCount < minBufferCountNeeded))) { 235 // here we're guaranteed that mQueue is empty 236 freeAllBuffersLocked(); 237 mBufferCount = mServerBufferCount; 238 if (mBufferCount < minBufferCountNeeded) 239 mBufferCount = minBufferCountNeeded; 240 mCurrentSlot = INVALID_BUFFER_SLOT; 241 returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS; 242 } 243 244 // look for a free buffer to give to the client 245 found = INVALID_BUFFER_SLOT; 246 foundSync = INVALID_BUFFER_SLOT; 247 dequeuedCount = 0; 248 for (int i = 0; i < mBufferCount; i++) { 249 const int state = mSlots[i].mBufferState; 250 if (state == BufferSlot::DEQUEUED) { 251 dequeuedCount++; 252 continue; // won't be continuing if could 253 // dequeue a non 'FREE' current slot like 254 // that in SurfaceTexture 255 } 256 // In case of Encoding, we do not deque the mCurrentSlot buffer 257 // since we follow synchronous mode (unlike possibly in 258 // SurfaceTexture that could be using the asynch mode 259 // or has some mechanism in GL to be able to wait till the 260 // currentslot is done using the data) 261 // Here, we have to wait for the MPEG4Writer(or equiv) 262 // to tell us when it's done using the current buffer 263 if (state == BufferSlot::FREE) { 264 foundSync = i; 265 // Unlike that in SurfaceTexture, 266 // We don't need to worry if it is the 267 // currentslot or not as it is in state FREE 268 found = i; 269 break; 270 } 271 } 272 273 // clients are not allowed to dequeue more than one buffer 274 // if they didn't set a buffer count. 275 if (!mClientBufferCount && dequeuedCount) { 276 return -EINVAL; 277 } 278 279 // See whether a buffer has been queued since the last setBufferCount so 280 // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below. 281 bool bufferHasBeenQueued = mCurrentSlot != INVALID_BUFFER_SLOT; 282 if (bufferHasBeenQueued) { 283 // make sure the client is not trying to dequeue more buffers 284 // than allowed. 285 const int avail = mBufferCount - (dequeuedCount+1); 286 if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { 287 LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)", 288 MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), 289 dequeuedCount); 290 return -EBUSY; 291 } 292 } 293 294 // we're in synchronous mode and didn't find a buffer, we need to wait 295 // for for some buffers to be consumed 296 tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT); 297 if (tryAgain) { 298 ALOGV("Waiting..In synchronous mode and no buffer to dequeue"); 299 mDequeueCondition.wait(mMutex); 300 } 301 if (mStopped) { 302 return NO_INIT; 303 } 304 } 305 306 if (mSynchronousMode && found == INVALID_BUFFER_SLOT) { 307 // foundSync guaranteed to be != INVALID_BUFFER_SLOT 308 found = foundSync; 309 } 310 311 if (found == INVALID_BUFFER_SLOT) { 312 return -EBUSY; 313 } 314 315 const int bufIndex = found; 316 *outBuf = found; 317 318 const bool useDefaultSize = !w && !h; 319 if (useDefaultSize) { 320 // use the default size 321 w = mDefaultWidth; 322 h = mDefaultHeight; 323 } 324 325 const bool updateFormat = (format != 0); 326 if (!updateFormat) { 327 // keep the current (or default) format 328 format = mPixelFormat; 329 } 330 331 // buffer is now in DEQUEUED (but can also be current at the same time, 332 // if we're in synchronous mode) 333 mSlots[bufIndex].mBufferState = BufferSlot::DEQUEUED; 334 335 const sp<GraphicBuffer>& buffer(mSlots[bufIndex].mGraphicBuffer); 336 if ((buffer == NULL) || 337 (uint32_t(buffer->width) != w) || 338 (uint32_t(buffer->height) != h) || 339 (uint32_t(buffer->format) != format) || 340 ((uint32_t(buffer->usage) & usage) != usage)) { 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 361status_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 385status_t SurfaceMediaSource::connect(int api, 386 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 387 ALOGV("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. 427status_t SurfaceMediaSource::disconnect(int api) { 428 ALOGV("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 458status_t SurfaceMediaSource::queueBuffer(int bufIndex, int64_t timestamp, 459 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 460 ALOGV("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 ALOGV("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 538status_t SurfaceMediaSource::onFrameReceivedLocked() { 539 ALOGV("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 558void SurfaceMediaSource::cancelBuffer(int bufIndex) { 559 ALOGV("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 574nsecs_t SurfaceMediaSource::getTimestamp() { 575 ALOGV("SurfaceMediaSource::getTimestamp"); 576 Mutex::Autolock lock(mMutex); 577 return mCurrentTimestamp; 578} 579 580 581void SurfaceMediaSource::setFrameAvailableListener( 582 const sp<FrameAvailableListener>& listener) { 583 ALOGV("SurfaceMediaSource::setFrameAvailableListener"); 584 Mutex::Autolock lock(mMutex); 585 mFrameAvailableListener = listener; 586} 587 588void SurfaceMediaSource::freeAllBuffersLocked() { 589 ALOGV("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 596sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const { 597 Mutex::Autolock lock(mMutex); 598 return mCurrentBuf; 599} 600 601int SurfaceMediaSource::query(int what, int* outValue) 602{ 603 ALOGV("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 631void SurfaceMediaSource::dump(String8& result) const 632{ 633 char buffer[1024]; 634 dump(result, "", buffer, 1024); 635} 636 637void 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 682status_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 693bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const { 694 ALOGV("isMetaDataStoredInVideoBuffers"); 695 return true; 696} 697 698int32_t SurfaceMediaSource::getFrameRate( ) const { 699 Mutex::Autolock lock(mMutex); 700 return mFrameRate; 701} 702 703status_t SurfaceMediaSource::start(MetaData *params) 704{ 705 ALOGV("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 717status_t SurfaceMediaSource::stop() 718{ 719 ALOGV("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 732sp<MetaData> SurfaceMediaSource::getFormat() 733{ 734 ALOGV("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 751status_t SurfaceMediaSource::read( MediaBuffer **buffer, 752 const ReadOptions *options) 753{ 754 Mutex::Autolock autoLock(mMutex) ; 755 756 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 808void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) { 809 ALOGV("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 ALOGV("handle = %p, , offset = %d, length = %d", 824 mCurrentBuf->handle, (*buffer)->range_length(), (*buffer)->range_offset()); 825} 826 827void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { 828 ALOGV("signalBufferReturned"); 829 830 bool foundBuffer = false; 831 Mutex::Autolock autoLock(mMutex); 832 833 if (mStopped) { 834 ALOGV("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 ALOGV("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 860bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) { 861 ALOGV("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