SurfaceMediaSource.cpp revision c7de3f6bbaa6c1b8b334574fad34d583e3a67f5d
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 mNumFramesReceived(0), 50 mNumFramesEncoded(0), 51 mStopped(false) { 52 LOGV("SurfaceMediaSource::SurfaceMediaSource"); 53 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 54 mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); 55} 56 57SurfaceMediaSource::~SurfaceMediaSource() { 58 LOGV("SurfaceMediaSource::~SurfaceMediaSource"); 59 if (!mStopped) { 60 stop(); 61 } 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 mBufferCount = bufferCount; 143 mClientBufferCount = bufferCount; 144 mCurrentSlot = INVALID_BUFFER_SLOT; 145 mQueue.clear(); 146 mDequeueCondition.signal(); 147 freeAllBuffersLocked(); 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 Mutex::Autolock lock(mMutex); 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 if ((w != mDefaultWidth) || (h != mDefaultHeight)) { 183 LOGE("dequeuebuffer: invalid buffer size! Req: %dx%d, Found: %dx%d", 184 mDefaultWidth, mDefaultHeight, w, h); 185 return BAD_VALUE; 186 } 187 } 188 189 status_t returnFlags(OK); 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 if (mStopped) { 221 return NO_INIT; 222 } 223 // need to check again since the mode could have changed 224 // while we were waiting 225 minBufferCountNeeded = mSynchronousMode ? 226 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; 227 } 228 229 if (!mClientBufferCount && 230 ((mServerBufferCount != mBufferCount) || 231 (mServerBufferCount < minBufferCountNeeded))) { 232 // here we're guaranteed that mQueue is empty 233 freeAllBuffersLocked(); 234 mBufferCount = mServerBufferCount; 235 if (mBufferCount < minBufferCountNeeded) 236 mBufferCount = minBufferCountNeeded; 237 mCurrentSlot = INVALID_BUFFER_SLOT; 238 returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS; 239 } 240 241 // look for a free buffer to give to the client 242 found = INVALID_BUFFER_SLOT; 243 foundSync = INVALID_BUFFER_SLOT; 244 dequeuedCount = 0; 245 for (int i = 0; i < mBufferCount; i++) { 246 const int state = mSlots[i].mBufferState; 247 if (state == BufferSlot::DEQUEUED) { 248 dequeuedCount++; 249 continue; // won't be continuing if could 250 // dequeue a non 'FREE' current slot like 251 // that in SurfaceTexture 252 } 253 // In case of Encoding, we do not deque the mCurrentSlot buffer 254 // since we follow synchronous mode (unlike possibly in 255 // SurfaceTexture that could be using the asynch mode 256 // or has some mechanism in GL to be able to wait till the 257 // currentslot is done using the data) 258 // Here, we have to wait for the MPEG4Writer(or equiv) 259 // to tell us when it's done using the current buffer 260 if (state == BufferSlot::FREE) { 261 foundSync = i; 262 // Unlike that in SurfaceTexture, 263 // We don't need to worry if it is the 264 // currentslot or not as it is in state FREE 265 found = i; 266 break; 267 } 268 } 269 270 // clients are not allowed to dequeue more than one buffer 271 // if they didn't set a buffer count. 272 if (!mClientBufferCount && dequeuedCount) { 273 return -EINVAL; 274 } 275 276 // See whether a buffer has been queued since the last setBufferCount so 277 // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below. 278 bool bufferHasBeenQueued = mCurrentSlot != INVALID_BUFFER_SLOT; 279 if (bufferHasBeenQueued) { 280 // make sure the client is not trying to dequeue more buffers 281 // than allowed. 282 const int avail = mBufferCount - (dequeuedCount+1); 283 if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { 284 LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)", 285 MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), 286 dequeuedCount); 287 return -EBUSY; 288 } 289 } 290 291 // we're in synchronous mode and didn't find a buffer, we need to wait 292 // for for some buffers to be consumed 293 tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT); 294 if (tryAgain) { 295 LOGV("Waiting..In synchronous mode and no buffer to dequeue"); 296 mDequeueCondition.wait(mMutex); 297 } 298 if (mStopped) { 299 return NO_INIT; 300 } 301 } 302 303 if (mSynchronousMode && found == INVALID_BUFFER_SLOT) { 304 // foundSync guaranteed to be != INVALID_BUFFER_SLOT 305 found = foundSync; 306 } 307 308 if (found == INVALID_BUFFER_SLOT) { 309 return -EBUSY; 310 } 311 312 const int bufIndex = found; 313 *outBuf = found; 314 315 const bool useDefaultSize = !w && !h; 316 if (useDefaultSize) { 317 // use the default size 318 w = mDefaultWidth; 319 h = mDefaultHeight; 320 } 321 322 const bool updateFormat = (format != 0); 323 if (!updateFormat) { 324 // keep the current (or default) format 325 format = mPixelFormat; 326 } 327 328 // buffer is now in DEQUEUED (but can also be current at the same time, 329 // if we're in synchronous mode) 330 mSlots[bufIndex].mBufferState = BufferSlot::DEQUEUED; 331 332 const sp<GraphicBuffer>& buffer(mSlots[bufIndex].mGraphicBuffer); 333 if ((buffer == NULL) || 334 (uint32_t(buffer->width) != w) || 335 (uint32_t(buffer->height) != h) || 336 (uint32_t(buffer->format) != format) || 337 ((uint32_t(buffer->usage) & usage) != usage)) { 338 usage |= GraphicBuffer::USAGE_HW_TEXTURE; 339 status_t error; 340 sp<GraphicBuffer> graphicBuffer( 341 mGraphicBufferAlloc->createGraphicBuffer( 342 w, h, format, usage, &error)); 343 if (graphicBuffer == 0) { 344 LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); 345 return error; 346 } 347 if (updateFormat) { 348 mPixelFormat = format; 349 } 350 mSlots[bufIndex].mGraphicBuffer = graphicBuffer; 351 mSlots[bufIndex].mRequestBufferCalled = false; 352 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; 353 } 354 return returnFlags; 355} 356 357// TODO: clean this up 358status_t SurfaceMediaSource::setSynchronousMode(bool enabled) { 359 Mutex::Autolock lock(mMutex); 360 if (mStopped) { 361 LOGE("setSynchronousMode: SurfaceMediaSource has been stopped!"); 362 return NO_INIT; 363 } 364 365 if (!enabled) { 366 // Async mode is not allowed 367 LOGE("SurfaceMediaSource can be used only synchronous mode!"); 368 return INVALID_OPERATION; 369 } 370 371 if (mSynchronousMode != enabled) { 372 // - if we're going to asynchronous mode, the queue is guaranteed to be 373 // empty here 374 // - if the client set the number of buffers, we're guaranteed that 375 // we have at least 3 (because we don't allow less) 376 mSynchronousMode = enabled; 377 mDequeueCondition.signal(); 378 } 379 return OK; 380} 381 382status_t SurfaceMediaSource::connect(int api, 383 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 384 LOGV("SurfaceMediaSource::connect"); 385 Mutex::Autolock lock(mMutex); 386 387 if (mStopped) { 388 LOGE("Connect: SurfaceMediaSource has been stopped!"); 389 return NO_INIT; 390 } 391 392 status_t err = NO_ERROR; 393 switch (api) { 394 case NATIVE_WINDOW_API_EGL: 395 case NATIVE_WINDOW_API_CPU: 396 case NATIVE_WINDOW_API_MEDIA: 397 case NATIVE_WINDOW_API_CAMERA: 398 if (mConnectedApi != NO_CONNECTED_API) { 399 err = -EINVAL; 400 } else { 401 mConnectedApi = api; 402 *outWidth = mDefaultWidth; 403 *outHeight = mDefaultHeight; 404 *outTransform = 0; 405 } 406 break; 407 default: 408 err = -EINVAL; 409 break; 410 } 411 return err; 412} 413 414// This is called by the client side when it is done 415// TODO: Currently, this also sets mStopped to true which 416// is needed for unblocking the encoder which might be 417// waiting to read more frames. So if on the client side, 418// the same thread supplies the frames and also calls stop 419// on the encoder, the client has to call disconnect before 420// it calls stop. 421// In the case of the camera, 422// that need not be required since the thread supplying the 423// frames is separate than the one calling stop. 424status_t SurfaceMediaSource::disconnect(int api) { 425 LOGV("SurfaceMediaSource::disconnect"); 426 Mutex::Autolock lock(mMutex); 427 428 if (mStopped) { 429 LOGE("disconnect: SurfaceMediaSoource is already stopped!"); 430 return NO_INIT; 431 } 432 433 status_t err = NO_ERROR; 434 switch (api) { 435 case NATIVE_WINDOW_API_EGL: 436 case NATIVE_WINDOW_API_CPU: 437 case NATIVE_WINDOW_API_MEDIA: 438 case NATIVE_WINDOW_API_CAMERA: 439 if (mConnectedApi == api) { 440 mConnectedApi = NO_CONNECTED_API; 441 mStopped = true; 442 mDequeueCondition.signal(); 443 mFrameAvailableCondition.signal(); 444 } else { 445 err = -EINVAL; 446 } 447 break; 448 default: 449 err = -EINVAL; 450 break; 451 } 452 return err; 453} 454 455status_t SurfaceMediaSource::queueBuffer(int bufIndex, int64_t timestamp, 456 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 457 LOGV("queueBuffer"); 458 459 Mutex::Autolock lock(mMutex); 460 if (bufIndex < 0 || bufIndex >= mBufferCount) { 461 LOGE("queueBuffer: slot index out of range [0, %d]: %d", 462 mBufferCount, bufIndex); 463 return -EINVAL; 464 } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) { 465 LOGE("queueBuffer: slot %d is not owned by the client (state=%d)", 466 bufIndex, mSlots[bufIndex].mBufferState); 467 return -EINVAL; 468 } else if (!mSlots[bufIndex].mRequestBufferCalled) { 469 LOGE("queueBuffer: slot %d was enqueued without requesting a " 470 "buffer", bufIndex); 471 return -EINVAL; 472 } 473 474 if (mSynchronousMode) { 475 // in synchronous mode we queue all buffers in a FIFO 476 mQueue.push_back(bufIndex); 477 mNumFramesReceived++; 478 LOGV("Client queued buf# %d @slot: %d, Q size = %d, handle = %p, timestamp = %lld", 479 mNumFramesReceived, bufIndex, mQueue.size(), 480 mSlots[bufIndex].mGraphicBuffer->handle, timestamp); 481 } else { 482 // in asynchronous mode we only keep the most recent buffer 483 if (mQueue.empty()) { 484 mQueue.push_back(bufIndex); 485 } else { 486 Fifo::iterator front(mQueue.begin()); 487 // buffer currently queued is freed 488 mSlots[*front].mBufferState = BufferSlot::FREE; 489 // and we record the new buffer index in the queued list 490 *front = bufIndex; 491 } 492 } 493 494 mSlots[bufIndex].mBufferState = BufferSlot::QUEUED; 495 mSlots[bufIndex].mTimestamp = timestamp; 496 // TODO: (Confirm) Don't want to signal dequeue here. 497 // May be just in asynchronous mode? 498 // mDequeueCondition.signal(); 499 500 // Once the queuing is done, we need to let the listener 501 // and signal the buffer consumer (encoder) know that a 502 // buffer is available 503 onFrameReceivedLocked(); 504 505 *outWidth = mDefaultWidth; 506 *outHeight = mDefaultHeight; 507 *outTransform = 0; 508 509 return OK; 510} 511 512 513// onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder) 514// or listeners that a frame has been received 515// It is supposed to be called only from queuebuffer. 516// The buffer is NOT made available for dequeueing immediately. We need to 517// wait to hear from StageFrightRecorder to set the buffer FREE 518// Make sure this is called when the mutex is locked 519status_t SurfaceMediaSource::onFrameReceivedLocked() { 520 LOGV("On Frame Received locked"); 521 // Signal the encoder that a new frame has arrived 522 mFrameAvailableCondition.signal(); 523 524 // call back the listener 525 // TODO: The listener may not be needed in SurfaceMediaSource at all. 526 // This can be made a SurfaceTexture specific thing 527 sp<FrameAvailableListener> listener; 528 if (mSynchronousMode || mQueue.empty()) { 529 listener = mFrameAvailableListener; 530 } 531 532 if (listener != 0) { 533 listener->onFrameAvailable(); 534 } 535 return OK; 536} 537 538 539void SurfaceMediaSource::cancelBuffer(int bufIndex) { 540 LOGV("SurfaceMediaSource::cancelBuffer"); 541 Mutex::Autolock lock(mMutex); 542 if (bufIndex < 0 || bufIndex >= mBufferCount) { 543 LOGE("cancelBuffer: slot index out of range [0, %d]: %d", 544 mBufferCount, bufIndex); 545 return; 546 } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) { 547 LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", 548 bufIndex, mSlots[bufIndex].mBufferState); 549 return; 550 } 551 mSlots[bufIndex].mBufferState = BufferSlot::FREE; 552 mDequeueCondition.signal(); 553} 554 555nsecs_t SurfaceMediaSource::getTimestamp() { 556 LOGV("SurfaceMediaSource::getTimestamp"); 557 Mutex::Autolock lock(mMutex); 558 return mCurrentTimestamp; 559} 560 561 562void SurfaceMediaSource::setFrameAvailableListener( 563 const sp<FrameAvailableListener>& listener) { 564 LOGV("SurfaceMediaSource::setFrameAvailableListener"); 565 Mutex::Autolock lock(mMutex); 566 mFrameAvailableListener = listener; 567} 568 569void SurfaceMediaSource::freeAllBuffersLocked() { 570 LOGV("freeAllBuffersLocked"); 571 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 572 mSlots[i].mGraphicBuffer = 0; 573 mSlots[i].mBufferState = BufferSlot::FREE; 574 } 575} 576 577sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const { 578 Mutex::Autolock lock(mMutex); 579 return mCurrentBuf; 580} 581 582int SurfaceMediaSource::query(int what, int* outValue) 583{ 584 LOGV("query"); 585 Mutex::Autolock lock(mMutex); 586 int value; 587 switch (what) { 588 case NATIVE_WINDOW_WIDTH: 589 value = mDefaultWidth; 590 if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0) 591 value = mCurrentBuf->width; 592 break; 593 case NATIVE_WINDOW_HEIGHT: 594 value = mDefaultHeight; 595 if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0) 596 value = mCurrentBuf->height; 597 break; 598 case NATIVE_WINDOW_FORMAT: 599 value = mPixelFormat; 600 break; 601 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 602 value = mSynchronousMode ? 603 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS; 604 break; 605 default: 606 return BAD_VALUE; 607 } 608 outValue[0] = value; 609 return NO_ERROR; 610} 611 612void SurfaceMediaSource::dump(String8& result) const 613{ 614 char buffer[1024]; 615 dump(result, "", buffer, 1024); 616} 617 618void SurfaceMediaSource::dump(String8& result, const char* prefix, 619 char* buffer, size_t SIZE) const 620{ 621 Mutex::Autolock _l(mMutex); 622 snprintf(buffer, SIZE, 623 "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " 624 "mPixelFormat=%d, \n", 625 prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight, 626 mPixelFormat); 627 result.append(buffer); 628 629 String8 fifo; 630 int fifoSize = 0; 631 Fifo::const_iterator i(mQueue.begin()); 632 while (i != mQueue.end()) { 633 snprintf(buffer, SIZE, "%02d ", *i++); 634 fifoSize++; 635 fifo.append(buffer); 636 } 637 638 result.append(buffer); 639 640 struct { 641 const char * operator()(int state) const { 642 switch (state) { 643 case BufferSlot::DEQUEUED: return "DEQUEUED"; 644 case BufferSlot::QUEUED: return "QUEUED"; 645 case BufferSlot::FREE: return "FREE"; 646 default: return "Unknown"; 647 } 648 } 649 } stateName; 650 651 for (int i = 0; i < mBufferCount; i++) { 652 const BufferSlot& slot(mSlots[i]); 653 snprintf(buffer, SIZE, 654 "%s%s[%02d] state=%-8s, " 655 "timestamp=%lld\n", 656 prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState), 657 slot.mTimestamp 658 ); 659 result.append(buffer); 660 } 661} 662 663status_t SurfaceMediaSource::setFrameRate(int32_t fps) 664{ 665 Mutex::Autolock lock(mMutex); 666 const int MAX_FRAME_RATE = 60; 667 if (fps < 0 || fps > MAX_FRAME_RATE) { 668 return BAD_VALUE; 669 } 670 mFrameRate = fps; 671 return OK; 672} 673 674bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const { 675 LOGV("isMetaDataStoredInVideoBuffers"); 676 return true; 677} 678 679int32_t SurfaceMediaSource::getFrameRate( ) const { 680 Mutex::Autolock lock(mMutex); 681 return mFrameRate; 682} 683 684status_t SurfaceMediaSource::start(MetaData *params) 685{ 686 LOGV("started!"); 687 return OK; 688} 689 690 691status_t SurfaceMediaSource::stop() 692{ 693 LOGV("Stop"); 694 695 Mutex::Autolock lock(mMutex); 696 // TODO: Add waiting on mFrameCompletedCondition here? 697 mStopped = true; 698 mFrameAvailableCondition.signal(); 699 mDequeueCondition.signal(); 700 mQueue.clear(); 701 freeAllBuffersLocked(); 702 703 return OK; 704} 705 706sp<MetaData> SurfaceMediaSource::getFormat() 707{ 708 LOGV("getFormat"); 709 Mutex::Autolock autoLock(mMutex); 710 sp<MetaData> meta = new MetaData; 711 712 meta->setInt32(kKeyWidth, mDefaultWidth); 713 meta->setInt32(kKeyHeight, mDefaultHeight); 714 // The encoder format is set as an opaque colorformat 715 // The encoder will later find out the actual colorformat 716 // from the GL Frames itself. 717 meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque); 718 meta->setInt32(kKeyStride, mDefaultWidth); 719 meta->setInt32(kKeySliceHeight, mDefaultHeight); 720 meta->setInt32(kKeyFrameRate, mFrameRate); 721 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 722 return meta; 723} 724 725status_t SurfaceMediaSource::read( MediaBuffer **buffer, 726 const ReadOptions *options) 727{ 728 Mutex::Autolock autoLock(mMutex) ; 729 730 LOGV("Read. Size of queued buffer: %d", mQueue.size()); 731 *buffer = NULL; 732 733 // If the recording has started and the queue is empty, then just 734 // wait here till the frames come in from the client side 735 while (!mStopped && mQueue.empty()) { 736 LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition"); 737 mFrameAvailableCondition.wait(mMutex); 738 } 739 740 // If the loop was exited as a result of stopping the recording, 741 // it is OK 742 if (mStopped) { 743 LOGV("Read: SurfaceMediaSource is stopped. Returning NO_INIT;"); 744 return NO_INIT; 745 } 746 747 // Update the current buffer info 748 // TODO: mCurrentSlot can be made a bufferstate since there 749 // can be more than one "current" slots. 750 Fifo::iterator front(mQueue.begin()); 751 mCurrentSlot = *front; 752 mQueue.erase(front); 753 mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer; 754 int64_t prevTimeStamp = mCurrentTimestamp; 755 mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp; 756 mNumFramesEncoded++; 757 // Pass the data to the MediaBuffer. Pass in only the metadata 758 passMetadataBufferLocked(buffer); 759 760 (*buffer)->setObserver(this); 761 (*buffer)->add_ref(); 762 (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000); 763 LOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld", 764 mNumFramesEncoded, mCurrentTimestamp / 1000, 765 mCurrentTimestamp / 1000 - prevTimeStamp / 1000); 766 767 return OK; 768} 769 770// Pass the data to the MediaBuffer. Pass in only the metadata 771// The metadata passed consists of two parts: 772// 1. First, there is an integer indicating that it is a GRAlloc 773// source (kMetadataBufferTypeGrallocSource) 774// 2. This is followed by the buffer_handle_t that is a handle to the 775// GRalloc buffer. The encoder needs to interpret this GRalloc handle 776// and encode the frames. 777// -------------------------------------------------------------- 778// | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) | 779// -------------------------------------------------------------- 780// Note: Call only when you have the lock 781void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) { 782 LOGV("passMetadataBuffer"); 783 // MediaBuffer allocates and owns this data 784 MediaBuffer *tempBuffer = 785 new MediaBuffer(4 + sizeof(buffer_handle_t)); 786 char *data = (char *)tempBuffer->data(); 787 if (data == NULL) { 788 LOGE("Cannot allocate memory for metadata buffer!"); 789 return; 790 } 791 OMX_U32 type = kMetadataBufferTypeGrallocSource; 792 memcpy(data, &type, 4); 793 memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t)); 794 *buffer = tempBuffer; 795 796 LOGV("handle = %p, , offset = %d, length = %d", 797 mCurrentBuf->handle, (*buffer)->range_length(), (*buffer)->range_offset()); 798} 799 800void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { 801 LOGV("signalBufferReturned"); 802 803 bool foundBuffer = false; 804 Mutex::Autolock autoLock(mMutex); 805 806 if (mStopped) { 807 LOGV("signalBufferReturned: mStopped = true! Nothing to do!"); 808 return; 809 } 810 811 for (int id = 0; id < NUM_BUFFER_SLOTS; id++) { 812 if (mSlots[id].mGraphicBuffer == NULL) { 813 continue; 814 } 815 if (checkBufferMatchesSlot(id, buffer)) { 816 LOGV("Slot %d returned, matches handle = %p", id, 817 mSlots[id].mGraphicBuffer->handle); 818 mSlots[id].mBufferState = BufferSlot::FREE; 819 buffer->setObserver(0); 820 buffer->release(); 821 mDequeueCondition.signal(); 822 mFrameCompleteCondition.signal(); 823 foundBuffer = true; 824 break; 825 } 826 } 827 828 if (!foundBuffer) { 829 CHECK_EQ(0, "signalBufferReturned: bogus buffer"); 830 } 831} 832 833bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) { 834 LOGV("Check if Buffer matches slot"); 835 // need to convert to char* for pointer arithmetic and then 836 // copy the byte stream into our handle 837 buffer_handle_t bufferHandle ; 838 memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t)); 839 return mSlots[slot].mGraphicBuffer->handle == bufferHandle; 840} 841 842} // end of namespace android 843