SurfaceMediaSource.cpp revision f76e1672c674620cb056f338a25ee4826d55dfcb
10cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard/* 20cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * Copyright (C) 2011 The Android Open Source Project 30cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * 40cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * Licensed under the Apache License, Version 2.0 (the "License"); 50cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * you may not use this file except in compliance with the License. 60cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * You may obtain a copy of the License at 70cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * 80cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * http://www.apache.org/licenses/LICENSE-2.0 90cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * 100cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * Unless required by applicable law or agreed to in writing, software 110cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * distributed under the License is distributed on an "AS IS" BASIS, 120cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * See the License for the specific language governing permissions and 140cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * limitations under the License. 150cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard */ 160cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 170cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard// #define LOG_NDEBUG 0 180cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#define LOG_TAG "SurfaceMediaSource" 19256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani 200cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#include <media/stagefright/SurfaceMediaSource.h> 210cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#include <ui/GraphicBuffer.h> 229a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik#include <media/stagefright/MetaData.h> 230cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#include <media/stagefright/MediaDefs.h> 240cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#include <media/stagefright/MediaDebug.h> 250cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#include <media/stagefright/openmax/OMX_IVCommon.h> 260cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#include <media/stagefright/MetadataBufferType.h> 270cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 280cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#include <surfaceflinger/ISurfaceComposer.h> 290cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#include <surfaceflinger/SurfaceComposerClient.h> 300cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#include <surfaceflinger/IGraphicBufferAlloc.h> 310cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#include <OMX_Component.h> 320cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 330cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard#include <utils/Log.h> 349a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik#include <utils/String8.h> 359a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik 369a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheiknamespace android { 370cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 380cc0544a2995c7eb54a830ae54db60af89d4073dJean ChalardSurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) : 390cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mDefaultWidth(bufW), 409a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik mDefaultHeight(bufH), 410cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mPixelFormat(0), 420cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mBufferCount(MIN_ASYNC_BUFFER_SLOTS), 430cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mClientBufferCount(0), 440cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS), 450cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mCurrentSlot(INVALID_BUFFER_SLOT), 460cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mCurrentTimestamp(0), 470cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mSynchronousMode(true), 48a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka mConnectedApi(NO_CONNECTED_API), 49b8ff8ca9d9d17f61f3f0e019ed0b62fe13d1a33fJean Chalard mFrameRate(30), 500cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mStarted(false) { 510cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard LOGV("SurfaceMediaSource::SurfaceMediaSource"); 520cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 530cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); 540cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard} 550cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 560cc0544a2995c7eb54a830ae54db60af89d4073dJean ChalardSurfaceMediaSource::~SurfaceMediaSource() { 57e077c014616f7b4e28dbbfab622ba36c8e922268Jean Chalard LOGV("SurfaceMediaSource::~SurfaceMediaSource"); 58e077c014616f7b4e28dbbfab622ba36c8e922268Jean Chalard if (mStarted) { 590cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard stop(); 60256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani } 610cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard freeAllBuffers(); 620cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard} 630cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 640cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardsize_t SurfaceMediaSource::getQueuedCount() const { 650cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard Mutex::Autolock lock(mMutex); 660cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard return mQueue.size(); 670cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard} 680cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 690cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardstatus_t SurfaceMediaSource::setBufferCountServerLocked(int bufferCount) { 700cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard if (bufferCount > NUM_BUFFER_SLOTS) 710cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard return BAD_VALUE; 720cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 730cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // special-case, nothing to do 74e077c014616f7b4e28dbbfab622ba36c8e922268Jean Chalard if (bufferCount == mBufferCount) 750cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard return OK; 76256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani 770cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard if (!mClientBufferCount && 780cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard bufferCount >= mBufferCount) { 790cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // easy, we just have more buffers 800cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mBufferCount = bufferCount; 810cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mServerBufferCount = bufferCount; 820cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mDequeueCondition.signal(); 830cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } else { 840cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // we're here because we're either 850cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // - reducing the number of available buffers 860cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // - or there is a client-buffer-count in effect 870cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 880cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // less than 2 buffers is never allowed 890cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard if (bufferCount < 2) 900cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard return BAD_VALUE; 910cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 920cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // when there is non client-buffer-count in effect, the client is not 930cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // allowed to dequeue more than one buffer at a time, 940cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // so the next time they dequeue a buffer, we know that they don't 950cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // own one. the actual resizing will happen during the next 960cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // dequeueBuffer. 970cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 98b8ff8ca9d9d17f61f3f0e019ed0b62fe13d1a33fJean Chalard mServerBufferCount = bufferCount; 99b8ff8ca9d9d17f61f3f0e019ed0b62fe13d1a33fJean Chalard } 100b8ff8ca9d9d17f61f3f0e019ed0b62fe13d1a33fJean Chalard return OK; 101b8ff8ca9d9d17f61f3f0e019ed0b62fe13d1a33fJean Chalard} 102b8ff8ca9d9d17f61f3f0e019ed0b62fe13d1a33fJean Chalard 103b8ff8ca9d9d17f61f3f0e019ed0b62fe13d1a33fJean Chalard// Called from the consumer side 104b8ff8ca9d9d17f61f3f0e019ed0b62fe13d1a33fJean Chalardstatus_t SurfaceMediaSource::setBufferCountServer(int bufferCount) { 105b8ff8ca9d9d17f61f3f0e019ed0b62fe13d1a33fJean Chalard Mutex::Autolock lock(mMutex); 1060cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard return setBufferCountServerLocked(bufferCount); 1070cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard} 1080cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 109256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matanistatus_t SurfaceMediaSource::setBufferCount(int bufferCount) { 110256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani LOGV("SurfaceMediaSource::setBufferCount"); 111256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani if (bufferCount > NUM_BUFFER_SLOTS) { 112256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani LOGE("setBufferCount: bufferCount is larger than the number of buffer slots"); 113256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani return BAD_VALUE; 114256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani } 115256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani 116256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani Mutex::Autolock lock(mMutex); 117256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani // Error out if the user has dequeued buffers 118256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani for (int i = 0 ; i < mBufferCount ; i++) { 119256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { 120256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani LOGE("setBufferCount: client owns some buffers"); 1219a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik return INVALID_OPERATION; 1229a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik } 1239a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik } 1249a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik 1259a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik if (bufferCount == 0) { 1269a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik const int minBufferSlots = mSynchronousMode ? 1279a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; 1289a3598b0ee8ab5d8b90e35d65190ecea1aef7828Mohammadinamul Sheik mClientBufferCount = 0; 129256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani bufferCount = (mServerBufferCount >= minBufferSlots) ? 130256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani mServerBufferCount : minBufferSlots; 131256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani return setBufferCountServerLocked(bufferCount); 132256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani } 1330cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 1340cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // We don't allow the client to set a buffer-count less than 1350cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it. 1360cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) { 1370cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard return BAD_VALUE; 1380cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 1390cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 1400cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // here we're guaranteed that the client doesn't have dequeued buffers 1410cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // and will release all of its buffer references. 1420cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard freeAllBuffers(); 1430cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mBufferCount = bufferCount; 1440cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mClientBufferCount = bufferCount; 1450cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mCurrentSlot = INVALID_BUFFER_SLOT; 1460cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mQueue.clear(); 1470cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mDequeueCondition.signal(); 1480cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard return OK; 1490cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard} 1500cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 1510cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardstatus_t SurfaceMediaSource::requestBuffer(int slot, sp<GraphicBuffer>* buf) { 1520cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard LOGV("SurfaceMediaSource::requestBuffer"); 1530cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard Mutex::Autolock lock(mMutex); 1540cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard if (slot < 0 || mBufferCount <= slot) { 1550cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard LOGE("requestBuffer: slot index out of range [0, %d]: %d", 1560cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mBufferCount, slot); 1570cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard return BAD_VALUE; 1580cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 1590cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mSlots[slot].mRequestBufferCalled = true; 1600cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard *buf = mSlots[slot].mGraphicBuffer; 1610cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard return NO_ERROR; 1620cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard} 1630cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 1640cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardstatus_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, 1650cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard uint32_t format, uint32_t usage) { 1660cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard LOGV("dequeueBuffer"); 1670cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 1680cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 1690cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // Check for the buffer size- the client should just use the 1700cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // default width and height, and not try to set those. 1710cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // This is needed since 1720cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // the getFormat() returns mDefaultWidth/ Height for the OMX. It is 1730cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // 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 Mutex::Autolock lock(mMutex); 190 191 status_t returnFlags(OK); 192 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 LOGV("Waiting for the FIFO to drain"); 221 mDequeueCondition.wait(mMutex); 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 freeAllBuffers(); 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 LOGW("Waiting..In synchronous mode and no buffer to dQ"); 296 mDequeueCondition.wait(mMutex); 297 } 298 } 299 300 if (mSynchronousMode && found == INVALID_BUFFER_SLOT) { 301 // foundSync guaranteed to be != INVALID_BUFFER_SLOT 302 found = foundSync; 303 } 304 305 if (found == INVALID_BUFFER_SLOT) { 306 return -EBUSY; 307 } 308 309 const int buf = found; 310 *outBuf = found; 311 312 const bool useDefaultSize = !w && !h; 313 if (useDefaultSize) { 314 // use the default size 315 w = mDefaultWidth; 316 h = mDefaultHeight; 317 } 318 319 const bool updateFormat = (format != 0); 320 if (!updateFormat) { 321 // keep the current (or default) format 322 format = mPixelFormat; 323 } 324 325 // buffer is now in DEQUEUED (but can also be current at the same time, 326 // if we're in synchronous mode) 327 mSlots[buf].mBufferState = BufferSlot::DEQUEUED; 328 329 const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); 330 if ((buffer == NULL) || 331 (uint32_t(buffer->width) != w) || 332 (uint32_t(buffer->height) != h) || 333 (uint32_t(buffer->format) != format) || 334 ((uint32_t(buffer->usage) & usage) != usage)) { 335 usage |= GraphicBuffer::USAGE_HW_TEXTURE; 336 status_t error; 337 sp<GraphicBuffer> graphicBuffer( 338 mGraphicBufferAlloc->createGraphicBuffer( 339 w, h, format, usage, &error)); 340 if (graphicBuffer == 0) { 341 LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); 342 return error; 343 } 344 if (updateFormat) { 345 mPixelFormat = format; 346 } 347 mSlots[buf].mGraphicBuffer = graphicBuffer; 348 mSlots[buf].mRequestBufferCalled = false; 349 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; 350 } 351 return returnFlags; 352} 353 354status_t SurfaceMediaSource::setSynchronousMode(bool enabled) { 355 Mutex::Autolock lock(mMutex); 356 357 status_t err = OK; 358 if (!enabled) { 359 // going to asynchronous mode, drain the queue 360 while (mSynchronousMode != enabled && !mQueue.isEmpty()) { 361 mDequeueCondition.wait(mMutex); 362 } 363 } 364 365 if (mSynchronousMode != enabled) { 366 // - if we're going to asynchronous mode, the queue is guaranteed to be 367 // empty here 368 // - if the client set the number of buffers, we're guaranteed that 369 // we have at least 3 (because we don't allow less) 370 mSynchronousMode = enabled; 371 mDequeueCondition.signal(); 372 } 373 return err; 374} 375 376status_t SurfaceMediaSource::connect(int api, 377 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 378 LOGV("SurfaceMediaSource::connect"); 379 Mutex::Autolock lock(mMutex); 380 status_t err = NO_ERROR; 381 switch (api) { 382 case NATIVE_WINDOW_API_EGL: 383 case NATIVE_WINDOW_API_CPU: 384 case NATIVE_WINDOW_API_MEDIA: 385 case NATIVE_WINDOW_API_CAMERA: 386 if (mConnectedApi != NO_CONNECTED_API) { 387 err = -EINVAL; 388 } else { 389 mConnectedApi = api; 390 *outWidth = mDefaultWidth; 391 *outHeight = mDefaultHeight; 392 *outTransform = 0; 393 } 394 break; 395 default: 396 err = -EINVAL; 397 break; 398 } 399 return err; 400} 401 402status_t SurfaceMediaSource::disconnect(int api) { 403 LOGV("SurfaceMediaSource::disconnect"); 404 Mutex::Autolock lock(mMutex); 405 status_t err = NO_ERROR; 406 switch (api) { 407 case NATIVE_WINDOW_API_EGL: 408 case NATIVE_WINDOW_API_CPU: 409 case NATIVE_WINDOW_API_MEDIA: 410 case NATIVE_WINDOW_API_CAMERA: 411 if (mConnectedApi == api) { 412 mConnectedApi = NO_CONNECTED_API; 413 } else { 414 err = -EINVAL; 415 } 416 break; 417 default: 418 err = -EINVAL; 419 break; 420 } 421 return err; 422} 423 424status_t SurfaceMediaSource::queueBuffer(int buf, int64_t timestamp, 425 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { 426 LOGV("queueBuffer"); 427 428 Mutex::Autolock lock(mMutex); 429 if (buf < 0 || buf >= mBufferCount) { 430 LOGE("queueBuffer: slot index out of range [0, %d]: %d", 431 mBufferCount, buf); 432 return -EINVAL; 433 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 434 LOGE("queueBuffer: slot %d is not owned by the client (state=%d)", 435 buf, mSlots[buf].mBufferState); 436 return -EINVAL; 437 } else if (!mSlots[buf].mRequestBufferCalled) { 438 LOGE("queueBuffer: slot %d was enqueued without requesting a " 439 "buffer", buf); 440 return -EINVAL; 441 } 442 443 if (mSynchronousMode) { 444 // in synchronous mode we queue all buffers in a FIFO 445 mQueue.push_back(buf); 446 LOGV("Client queued buffer on slot: %d, Q size = %d", 447 buf, mQueue.size()); 448 } else { 449 // in asynchronous mode we only keep the most recent buffer 450 if (mQueue.empty()) { 451 mQueue.push_back(buf); 452 } else { 453 Fifo::iterator front(mQueue.begin()); 454 // buffer currently queued is freed 455 mSlots[*front].mBufferState = BufferSlot::FREE; 456 // and we record the new buffer index in the queued list 457 *front = buf; 458 } 459 } 460 461 mSlots[buf].mBufferState = BufferSlot::QUEUED; 462 mSlots[buf].mTimestamp = timestamp; 463 // TODO: (Confirm) Don't want to signal dequeue here. 464 // May be just in asynchronous mode? 465 // mDequeueCondition.signal(); 466 467 // Once the queuing is done, we need to let the listener 468 // and signal the buffer consumer (encoder) know that a 469 // buffer is available 470 onFrameReceivedLocked(); 471 472 *outWidth = mDefaultWidth; 473 *outHeight = mDefaultHeight; 474 *outTransform = 0; 475 476 return OK; 477} 478 479 480// onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder) 481// or listeners that a frame has been received 482// It is supposed to be called only from queuebuffer. 483// The buffer is NOT made available for dequeueing immediately. We need to 484// wait to hear from StageFrightRecorder to set the buffer FREE 485// Make sure this is called when the mutex is locked 486status_t SurfaceMediaSource::onFrameReceivedLocked() { 487 LOGV("On Frame Received"); 488 // Signal the encoder that a new frame has arrived 489 mFrameAvailableCondition.signal(); 490 491 // call back the listener 492 // TODO: The listener may not be needed in SurfaceMediaSource at all. 493 // This can be made a SurfaceTexture specific thing 494 sp<FrameAvailableListener> listener; 495 if (mSynchronousMode || mQueue.empty()) { 496 listener = mFrameAvailableListener; 497 } 498 499 if (listener != 0) { 500 listener->onFrameAvailable(); 501 } 502 return OK; 503} 504 505 506void SurfaceMediaSource::cancelBuffer(int buf) { 507 LOGV("SurfaceMediaSource::cancelBuffer"); 508 Mutex::Autolock lock(mMutex); 509 if (buf < 0 || buf >= mBufferCount) { 510 LOGE("cancelBuffer: slot index out of range [0, %d]: %d", 511 mBufferCount, buf); 512 return; 513 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { 514 LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", 515 buf, mSlots[buf].mBufferState); 516 return; 517 } 518 mSlots[buf].mBufferState = BufferSlot::FREE; 519 mDequeueCondition.signal(); 520} 521 522nsecs_t SurfaceMediaSource::getTimestamp() { 523 LOGV("SurfaceMediaSource::getTimestamp"); 524 Mutex::Autolock lock(mMutex); 525 return mCurrentTimestamp; 526} 527 528 529void SurfaceMediaSource::setFrameAvailableListener( 530 const sp<FrameAvailableListener>& listener) { 531 LOGV("SurfaceMediaSource::setFrameAvailableListener"); 532 Mutex::Autolock lock(mMutex); 533 mFrameAvailableListener = listener; 534} 535 536void SurfaceMediaSource::freeAllBuffers() { 537 LOGV("freeAllBuffers"); 538 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 539 mSlots[i].mGraphicBuffer = 0; 540 mSlots[i].mBufferState = BufferSlot::FREE; 541 } 542} 543 544sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const { 545 Mutex::Autolock lock(mMutex); 546 return mCurrentBuf; 547} 548 549int SurfaceMediaSource::query(int what, int* outValue) 550{ 551 LOGV("query"); 552 Mutex::Autolock lock(mMutex); 553 int value; 554 switch (what) { 555 case NATIVE_WINDOW_WIDTH: 556 value = mDefaultWidth; 557 if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0) 558 value = mCurrentBuf->width; 559 break; 560 case NATIVE_WINDOW_HEIGHT: 561 value = mDefaultHeight; 562 if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0) 563 value = mCurrentBuf->height; 564 break; 565 case NATIVE_WINDOW_FORMAT: 566 value = mPixelFormat; 567 break; 568 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 569 value = mSynchronousMode ? 570 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS; 571 break; 572 default: 573 return BAD_VALUE; 574 } 575 outValue[0] = value; 576 return NO_ERROR; 577} 578 579void SurfaceMediaSource::dump(String8& result) const 580{ 581 char buffer[1024]; 582 dump(result, "", buffer, 1024); 583} 584 585void SurfaceMediaSource::dump(String8& result, const char* prefix, 586 char* buffer, size_t SIZE) const 587{ 588 Mutex::Autolock _l(mMutex); 589 snprintf(buffer, SIZE, 590 "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " 591 "mPixelFormat=%d, \n", 592 prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight, 593 mPixelFormat); 594 result.append(buffer); 595 596 String8 fifo; 597 int fifoSize = 0; 598 Fifo::const_iterator i(mQueue.begin()); 599 while (i != mQueue.end()) { 600 snprintf(buffer, SIZE, "%02d ", *i++); 601 fifoSize++; 602 fifo.append(buffer); 603 } 604 605 result.append(buffer); 606 607 struct { 608 const char * operator()(int state) const { 609 switch (state) { 610 case BufferSlot::DEQUEUED: return "DEQUEUED"; 611 case BufferSlot::QUEUED: return "QUEUED"; 612 case BufferSlot::FREE: return "FREE"; 613 default: return "Unknown"; 614 } 615 } 616 } stateName; 617 618 for (int i = 0; i < mBufferCount; i++) { 619 const BufferSlot& slot(mSlots[i]); 620 snprintf(buffer, SIZE, 621 "%s%s[%02d] state=%-8s, " 622 "timestamp=%lld\n", 623 prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState), 624 slot.mTimestamp 625 ); 626 result.append(buffer); 627 } 628} 629 630status_t SurfaceMediaSource::setFrameRate(int32_t fps) 631{ 632 Mutex::Autolock lock(mMutex); 633 const int MAX_FRAME_RATE = 60; 634 if (fps < 0 || fps > MAX_FRAME_RATE) { 635 return BAD_VALUE; 636 } 637 mFrameRate = fps; 638 return OK; 639} 640 641bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const { 642 LOGV("isMetaDataStoredInVideoBuffers"); 643 return true; 644} 645 646int32_t SurfaceMediaSource::getFrameRate( ) const { 647 Mutex::Autolock lock(mMutex); 648 return mFrameRate; 649} 650 651status_t SurfaceMediaSource::start(MetaData *params) 652{ 653 LOGV("start"); 654 Mutex::Autolock lock(mMutex); 655 CHECK(!mStarted); 656 mStarted = true; 657 return OK; 658} 659 660 661status_t SurfaceMediaSource::stop() 662{ 663 LOGV("Stop"); 664 665 Mutex::Autolock lock(mMutex); 666 // TODO: Add waiting on mFrameCompletedCondition here? 667 mStarted = false; 668 mFrameAvailableCondition.signal(); 669 670 return OK; 671} 672 673sp<MetaData> SurfaceMediaSource::getFormat() 674{ 675 LOGV("getFormat"); 676 Mutex::Autolock autoLock(mMutex); 677 sp<MetaData> meta = new MetaData; 678 679 meta->setInt32(kKeyWidth, mDefaultWidth); 680 meta->setInt32(kKeyHeight, mDefaultHeight); 681 // The encoder format is set as an opaque colorformat 682 // The encoder will later find out the actual colorformat 683 // from the GL Frames itself. 684 meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque); 685 meta->setInt32(kKeyStride, mDefaultWidth); 686 meta->setInt32(kKeySliceHeight, mDefaultHeight); 687 meta->setInt32(kKeyFrameRate, mFrameRate); 688 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 689 return meta; 690} 691 692status_t SurfaceMediaSource::read( MediaBuffer **buffer, 693 const ReadOptions *options) 694{ 695 LOGV("Read. Size of queued buffer: %d", mQueue.size()); 696 *buffer = NULL; 697 698 Mutex::Autolock autoLock(mMutex) ; 699 // If the recording has started and the queue is empty, then just 700 // wait here till the frames come in from the client side 701 while (mStarted && mQueue.empty()) { 702 LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition"); 703 mFrameAvailableCondition.wait(mMutex); 704 } 705 706 // If the loop was exited as a result of stopping the recording, 707 // it is OK 708 if (!mStarted) { 709 return OK; 710 } 711 712 // Update the current buffer info 713 // TODO: mCurrentSlot can be made a bufferstate since there 714 // can be more than one "current" slots. 715 Fifo::iterator front(mQueue.begin()); 716 mCurrentSlot = *front; 717 mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer; 718 mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp; 719 720 // Pass the data to the MediaBuffer. Pass in only the metadata 721 passMetadataBufferLocked(buffer); 722 723 (*buffer)->setObserver(this); 724 (*buffer)->add_ref(); 725 (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp); 726 727 return OK; 728} 729 730// Pass the data to the MediaBuffer. Pass in only the metadata 731// The metadata passed consists of two parts: 732// 1. First, there is an integer indicating that it is a GRAlloc 733// source (kMetadataBufferTypeGrallocSource) 734// 2. This is followed by the buffer_handle_t that is a handle to the 735// GRalloc buffer. The encoder needs to interpret this GRalloc handle 736// and encode the frames. 737// -------------------------------------------------------------- 738// | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) | 739// -------------------------------------------------------------- 740// Note: Call only when you have the lock 741void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) { 742 LOGV("passMetadataBuffer"); 743 // MediaBuffer allocates and owns this data 744 MediaBuffer *tempBuffer = 745 new MediaBuffer(4 + sizeof(buffer_handle_t)); 746 char *data = (char *)tempBuffer->data(); 747 if (data == NULL) { 748 LOGE("Cannot allocate memory for passing buffer metadata!"); 749 return; 750 } 751 OMX_U32 type = kMetadataBufferTypeGrallocSource; 752 memcpy(data, &type, 4); 753 memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t)); 754 *buffer = tempBuffer; 755} 756 757 758void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { 759 LOGV("signalBufferReturned"); 760 761 bool foundBuffer = false; 762 Mutex::Autolock autoLock(mMutex); 763 764 if (!mStarted) { 765 LOGW("signalBufferReturned: mStarted = false! Nothing to do!"); 766 return; 767 } 768 769 for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) { 770 CHECK(mSlots[*it].mGraphicBuffer != NULL); 771 if (checkBufferMatchesSlot(*it, buffer)) { 772 mSlots[*it].mBufferState = BufferSlot::FREE; 773 mQueue.erase(it); 774 buffer->setObserver(0); 775 buffer->release(); 776 mDequeueCondition.signal(); 777 mFrameCompleteCondition.signal(); 778 foundBuffer = true; 779 break; 780 } 781 } 782 783 if (!foundBuffer) { 784 CHECK_EQ(0, "signalBufferReturned: bogus buffer"); 785 } 786} 787 788bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) { 789 LOGV("Check if Buffer matches slot"); 790 // need to convert to char* for pointer arithmetic and then 791 // copy the byte stream into our handle 792 buffer_handle_t bufferHandle ; 793 memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t)); 794 return mSlots[slot].mGraphicBuffer->handle == bufferHandle; 795} 796 797 798} // end of namespace android 799