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