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