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