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