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