SurfaceMediaSource.cpp revision ef7d3793fa9bbfb25253626ede9a020ee9280a17
13399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi/* 23399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * Copyright (C) 2011 The Android Open Source Project 33399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * 43399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * Licensed under the Apache License, Version 2.0 (the "License"); 53399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * you may not use this file except in compliance with the License. 63399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * You may obtain a copy of the License at 73399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * 83399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * http://www.apache.org/licenses/LICENSE-2.0 93399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * 103399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * Unless required by applicable law or agreed to in writing, software 113399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * distributed under the License is distributed on an "AS IS" BASIS, 123399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * See the License for the specific language governing permissions and 143399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * limitations under the License. 153399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi */ 167dc9b309f1ce01308bcfde9948ebfece32dc2870Pannag Sanketi//#define LOG_NDEBUG 0 171a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi#define LOG_TAG "SurfaceMediaSource" 183399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 19f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 201a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi#include <media/stagefright/SurfaceMediaSource.h> 213399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#include <media/stagefright/MediaDefs.h> 2200f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber#include <media/stagefright/MetaData.h> 236c6b4d0d2b98a7ceee8b697daaf611f8df3254fbJames Dong#include <OMX_IVCommon.h> 246c6b4d0d2b98a7ceee8b697daaf611f8df3254fbJames Dong#include <MetadataBufferType.h> 253399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 26f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <ui/GraphicBuffer.h> 27df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian#include <gui/ISurfaceComposer.h> 28df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian#include <gui/IGraphicBufferAlloc.h> 293399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#include <OMX_Component.h> 303399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 313399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#include <utils/Log.h> 323399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#include <utils/String8.h> 333399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 34404a123bed7f180724ead17f10e037b3eb347701Mathias Agopian#include <private/gui/ComposerService.h> 35404a123bed7f180724ead17f10e037b3eb347701Mathias Agopian 363399b7267185646c69b04352211fca4fad9d7547Pannag Sanketinamespace android { 373399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 38bdddc659a941afdb7f4958f582c6901c07246097Daniel LamSurfaceMediaSource::SurfaceMediaSource(uint32_t bufferWidth, uint32_t bufferHeight) : 39bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mWidth(bufferWidth), 40bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mHeight(bufferHeight), 41bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mCurrentSlot(BufferQueue::INVALID_BUFFER_SLOT), 4200f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber mNumPendingBuffers(0), 43bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mCurrentTimestamp(0), 44bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mFrameRate(30), 45bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mStopped(false), 46bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mNumFramesReceived(0), 47bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mNumFramesEncoded(0), 4800f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber mFirstFrameTimestamp(0), 4900f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber mMaxAcquiredBufferCount(4) // XXX double-check the default 50bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam{ 51a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennis ALOGV("SurfaceMediaSource"); 523399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 53bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam if (bufferWidth == 0 || bufferHeight == 0) { 54bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam ALOGE("Invalid dimensions %dx%d", bufferWidth, bufferHeight); 553399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi } 563399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 573d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong mBufferQueue = new BufferQueue(true); 58bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mBufferQueue->setDefaultBufferSize(bufferWidth, bufferHeight); 59bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mBufferQueue->setSynchronousMode(true); 608add6cf4976de9b7bca7b73b1473a1e5f7201087Eino-Ville Talvala mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER | 618add6cf4976de9b7bca7b73b1473a1e5f7201087Eino-Ville Talvala GRALLOC_USAGE_HW_TEXTURE); 623399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 63bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 643399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 65bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // Note that we can't create an sp<...>(this) in a ctor that will not keep a 66bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // reference once the ctor ends, as that would cause the refcount of 'this' 67bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // dropping to 0 at the end of the ctor. Since all we need is a wp<...> 68bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // that's what we create. 69bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam wp<BufferQueue::ConsumerListener> listener; 70bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam sp<BufferQueue::ConsumerListener> proxy; 71bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam listener = static_cast<BufferQueue::ConsumerListener*>(this); 72bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam proxy = new BufferQueue::ProxyConsumerListener(listener); 733399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 74bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam status_t err = mBufferQueue->consumerConnect(proxy); 75bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam if (err != NO_ERROR) { 76bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam ALOGE("SurfaceMediaSource: error connecting to BufferQueue: %s (%d)", 77bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam strerror(-err), err); 783399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi } 793399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 803399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 81bdddc659a941afdb7f4958f582c6901c07246097Daniel LamSurfaceMediaSource::~SurfaceMediaSource() { 82a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennis ALOGV("~SurfaceMediaSource"); 83a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennis CHECK(mStopped == true); 843399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 853399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 861a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketinsecs_t SurfaceMediaSource::getTimestamp() { 87a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennis ALOGV("getTimestamp"); 883399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi Mutex::Autolock lock(mMutex); 893399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi return mCurrentTimestamp; 903399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 913399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 921a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketivoid SurfaceMediaSource::setFrameAvailableListener( 933399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi const sp<FrameAvailableListener>& listener) { 94a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennis ALOGV("setFrameAvailableListener"); 953399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi Mutex::Autolock lock(mMutex); 963399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi mFrameAvailableListener = listener; 973399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 983399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 991a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketivoid SurfaceMediaSource::dump(String8& result) const 1003399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi{ 1013399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi char buffer[1024]; 1023399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi dump(result, "", buffer, 1024); 1033399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 1043399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 1051a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketivoid SurfaceMediaSource::dump(String8& result, const char* prefix, 1063399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi char* buffer, size_t SIZE) const 1073399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi{ 108bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam Mutex::Autolock lock(mMutex); 1093399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 1103399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi result.append(buffer); 111bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mBufferQueue->dump(result); 1123399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 1133399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 114b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketistatus_t SurfaceMediaSource::setFrameRate(int32_t fps) 1153399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi{ 116a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennis ALOGV("setFrameRate"); 1173399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi Mutex::Autolock lock(mMutex); 118b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi const int MAX_FRAME_RATE = 60; 119b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi if (fps < 0 || fps > MAX_FRAME_RATE) { 120b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi return BAD_VALUE; 121b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi } 1223399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi mFrameRate = fps; 123b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi return OK; 1243399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 1253399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 126b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketibool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const { 1273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("isMetaDataStoredInVideoBuffers"); 128b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi return true; 129b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi} 130b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi 131b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketiint32_t SurfaceMediaSource::getFrameRate( ) const { 132a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennis ALOGV("getFrameRate"); 1333399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi Mutex::Autolock lock(mMutex); 1343399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi return mFrameRate; 1353399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 1363399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 1371a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketistatus_t SurfaceMediaSource::start(MetaData *params) 1383399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi{ 139a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennis ALOGV("start"); 140df4a59c61103e7e0e9332e167a0be67da5d82ff3Eino-Ville Talvala 1413d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong Mutex::Autolock lock(mMutex); 1423d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong 143df4a59c61103e7e0e9332e167a0be67da5d82ff3Eino-Ville Talvala mStartTimeNs = 0; 144df4a59c61103e7e0e9332e167a0be67da5d82ff3Eino-Ville Talvala int64_t startTimeUs; 1453d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong int32_t bufferCount = 0; 1463d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong if (params) { 1473d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong if (params->findInt64(kKeyTime, &startTimeUs)) { 1483d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong mStartTimeNs = startTimeUs * 1000; 1493d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong } 1503d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong 1513d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong if (!params->findInt32(kKeyNumBuffers, &bufferCount)) { 1523d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong ALOGE("Failed to find the advertised buffer count"); 1533d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong return UNKNOWN_ERROR; 1543d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong } 1553d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong 1563d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong if (bufferCount <= 1) { 1573d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong ALOGE("bufferCount %d is too small", bufferCount); 1583d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong return BAD_VALUE; 1593d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong } 16000f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber 16100f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber mMaxAcquiredBufferCount = bufferCount; 1623d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong } 1633d26e897fc91cf6ad3576d25b4b240e9a2189970James Dong 16400f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber CHECK_GT(mMaxAcquiredBufferCount, 1); 16500f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber 16600f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber status_t err = 16700f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber mBufferQueue->setMaxAcquiredBufferCount(mMaxAcquiredBufferCount); 16800f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber 16900f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber if (err != OK) { 17000f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber return err; 171df4a59c61103e7e0e9332e167a0be67da5d82ff3Eino-Ville Talvala } 172df4a59c61103e7e0e9332e167a0be67da5d82ff3Eino-Ville Talvala 17300f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber mNumPendingBuffers = 0; 17400f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber 1753399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi return OK; 1763399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 1773399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 17866e72bc85fb762876baff60ef29de729da93cf26Andreas Huberstatus_t SurfaceMediaSource::setMaxAcquiredBufferCount(size_t count) { 17900f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber ALOGV("setMaxAcquiredBufferCount(%d)", count); 18000f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber Mutex::Autolock lock(mMutex); 18100f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber 18200f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber CHECK_GT(count, 1); 18300f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber mMaxAcquiredBufferCount = count; 18400f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber 18500f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber return OK; 18666e72bc85fb762876baff60ef29de729da93cf26Andreas Huber} 18766e72bc85fb762876baff60ef29de729da93cf26Andreas Huber 1883399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 189a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennisstatus_t SurfaceMediaSource::stop() 1903399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi{ 191a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennis ALOGV("stop"); 1923399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi Mutex::Autolock lock(mMutex); 193bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 194a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennis mStopped = true; 1953399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi mFrameAvailableCondition.signal(); 196ef7d3793fa9bbfb25253626ede9a020ee9280a17Andreas Huber mMediaBuffersAvailableCondition.signal(); 1973399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 198a0ead0a2d2ce1d114ad3a17d755dddce831abb40Jamie Gennis return mBufferQueue->consumerDisconnect(); 1993399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 2003399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 2011a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketisp<MetaData> SurfaceMediaSource::getFormat() 2023399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi{ 2033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getFormat"); 204bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 205bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam Mutex::Autolock lock(mMutex); 2063399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi sp<MetaData> meta = new MetaData; 207b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi 208bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam meta->setInt32(kKeyWidth, mWidth); 209bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam meta->setInt32(kKeyHeight, mHeight); 2103399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi // The encoder format is set as an opaque colorformat 2113399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi // The encoder will later find out the actual colorformat 2123399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi // from the GL Frames itself. 2133399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque); 214bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam meta->setInt32(kKeyStride, mWidth); 215bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam meta->setInt32(kKeySliceHeight, mHeight); 2163399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi meta->setInt32(kKeyFrameRate, mFrameRate); 2173399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 2183399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi return meta; 2193399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 2203399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 2212cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis// Pass the data to the MediaBuffer. Pass in only the metadata 2222cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis// The metadata passed consists of two parts: 2232cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis// 1. First, there is an integer indicating that it is a GRAlloc 2242cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis// source (kMetadataBufferTypeGrallocSource) 2252cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis// 2. This is followed by the buffer_handle_t that is a handle to the 2262cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis// GRalloc buffer. The encoder needs to interpret this GRalloc handle 2272cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis// and encode the frames. 2282cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis// -------------------------------------------------------------- 2292cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis// | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) | 2302cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis// -------------------------------------------------------------- 2312cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis// Note: Call only when you have the lock 2322cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennisstatic void passMetadataBuffer(MediaBuffer **buffer, 2332cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis buffer_handle_t bufferHandle) { 23400f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber *buffer = new MediaBuffer(4 + sizeof(buffer_handle_t)); 23500f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber char *data = (char *)(*buffer)->data(); 2362cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis if (data == NULL) { 2372cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis ALOGE("Cannot allocate memory for metadata buffer!"); 2382cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis return; 2392cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis } 2402cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis OMX_U32 type = kMetadataBufferTypeGrallocSource; 2412cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis memcpy(data, &type, 4); 2422cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis memcpy(data + 4, &bufferHandle, sizeof(buffer_handle_t)); 2432cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis 2442cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis ALOGV("handle = %p, , offset = %d, length = %d", 2452cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis bufferHandle, (*buffer)->range_length(), (*buffer)->range_offset()); 2462cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis} 2472cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis 2481a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketistatus_t SurfaceMediaSource::read( MediaBuffer **buffer, 2490c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi const ReadOptions *options) 2503399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi{ 251bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam ALOGV("read"); 252bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam Mutex::Autolock lock(mMutex); 2530c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi 2543399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi *buffer = NULL; 2553399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 25600f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber while (!mStopped && mNumPendingBuffers == mMaxAcquiredBufferCount) { 25700f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber mMediaBuffersAvailableCondition.wait(mMutex); 25800f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber } 25900f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber 260bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // Update the current buffer info 261bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // TODO: mCurrentSlot can be made a bufferstate since there 262bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // can be more than one "current" slots. 263bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 264bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam BufferQueue::BufferItem item; 2653399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi // If the recording has started and the queue is empty, then just 2663399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi // wait here till the frames come in from the client side 267bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam while (!mStopped) { 268bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 269bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam status_t err = mBufferQueue->acquireBuffer(&item); 270bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 271bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // wait for a buffer to be queued 272bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mFrameAvailableCondition.wait(mMutex); 273bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam } else if (err == OK) { 274bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 275bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // First time seeing the buffer? Added it to the SMS slot 276bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam if (item.mGraphicBuffer != NULL) { 277bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mBufferSlot[item.mBuf] = item.mGraphicBuffer; 278bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam } 279bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 280bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // check for the timing of this buffer 281bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam if (mNumFramesReceived == 0) { 282bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mFirstFrameTimestamp = item.mTimestamp; 283bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // Initial delay 284bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam if (mStartTimeNs > 0) { 285bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam if (item.mTimestamp < mStartTimeNs) { 286bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // This frame predates start of record, discard 287f15f6e2e7fc51d48ba95890e1f562908e6e957c0Jesse Hall mBufferQueue->releaseBuffer(item.mBuf, EGL_NO_DISPLAY, 288f15f6e2e7fc51d48ba95890e1f562908e6e957c0Jesse Hall EGL_NO_SYNC_KHR, Fence::NO_FENCE); 289bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam continue; 290bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam } 291bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mStartTimeNs = item.mTimestamp - mStartTimeNs; 292bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam } 293bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam } 294bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam item.mTimestamp = mStartTimeNs + (item.mTimestamp - mFirstFrameTimestamp); 295bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 296bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mNumFramesReceived++; 297bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 298bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam break; 299bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam } else { 300bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam ALOGE("read: acquire failed with error code %d", err); 301bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam return ERROR_END_OF_STREAM; 302bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam } 303bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 3043399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi } 3053399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 3063399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi // If the loop was exited as a result of stopping the recording, 3073399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi // it is OK 3080c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi if (mStopped) { 3093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Read: SurfaceMediaSource is stopped. Returning ERROR_END_OF_STREAM."); 3103e9bf4061475ae0d01c57e32c13e63808aa3e31fPannag Sanketi return ERROR_END_OF_STREAM; 3113399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi } 3123399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 313bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mCurrentSlot = item.mBuf; 314bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 315bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam // First time seeing the buffer? Added it to the SMS slot 316bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam if (item.mGraphicBuffer != NULL) { 317bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mBufferSlot[mCurrentSlot] = item.mGraphicBuffer; 318bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam } 3192cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis 3202cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis mCurrentBuffers.push_back(mBufferSlot[mCurrentSlot]); 3210c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi int64_t prevTimeStamp = mCurrentTimestamp; 322bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mCurrentTimestamp = item.mTimestamp; 323df4a59c61103e7e0e9332e167a0be67da5d82ff3Eino-Ville Talvala 3240c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi mNumFramesEncoded++; 325a361483bb5dbd3bbf132c5b99b2df7d197c3fc50Pannag Sanketi // Pass the data to the MediaBuffer. Pass in only the metadata 32600f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber 3272cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis passMetadataBuffer(buffer, mBufferSlot[mCurrentSlot]->handle); 328a361483bb5dbd3bbf132c5b99b2df7d197c3fc50Pannag Sanketi 3293399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi (*buffer)->setObserver(this); 3303399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi (*buffer)->add_ref(); 3310c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000); 3323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld", 3330c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi mNumFramesEncoded, mCurrentTimestamp / 1000, 3340c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi mCurrentTimestamp / 1000 - prevTimeStamp / 1000); 3353399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 33600f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber ++mNumPendingBuffers; 337bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 3383399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi return OK; 3393399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 3403399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 3412cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennisstatic buffer_handle_t getMediaBufferHandle(MediaBuffer *buffer) { 3422cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis // need to convert to char* for pointer arithmetic and then 3432cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis // copy the byte stream into our handle 3442cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis buffer_handle_t bufferHandle; 3452cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis memcpy(&bufferHandle, (char*)(buffer->data()) + 4, sizeof(buffer_handle_t)); 3462cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis return bufferHandle; 3470c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi} 348a361483bb5dbd3bbf132c5b99b2df7d197c3fc50Pannag Sanketi 3491a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketivoid SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { 3503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("signalBufferReturned"); 3513399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 3523399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi bool foundBuffer = false; 353bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 354bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam Mutex::Autolock lock(mMutex); 3553399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 3562cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis buffer_handle_t bufferHandle = getMediaBufferHandle(buffer); 3572cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis 3582cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis for (size_t i = 0; i < mCurrentBuffers.size(); i++) { 3592cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis if (mCurrentBuffers[i]->handle == bufferHandle) { 3602cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis mCurrentBuffers.removeAt(i); 3612cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis foundBuffer = true; 3622cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis break; 3632cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis } 3642cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis } 3652cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis 3662cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis if (!foundBuffer) { 3672cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis ALOGW("returned buffer was not found in the current buffer list"); 3683399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi } 3693399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 370bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam for (int id = 0; id < BufferQueue::NUM_BUFFER_SLOTS; id++) { 371bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam if (mBufferSlot[id] == NULL) { 3720c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi continue; 3730c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi } 3742cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis 3752cd25a9056cc150b9fd3ac9b0bca37a1334ffd47Jamie Gennis if (bufferHandle == mBufferSlot[id]->handle) { 3763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Slot %d returned, matches handle = %p", id, 377bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mBufferSlot[id]->handle); 378bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 379f15f6e2e7fc51d48ba95890e1f562908e6e957c0Jesse Hall mBufferQueue->releaseBuffer(id, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, 380f15f6e2e7fc51d48ba95890e1f562908e6e957c0Jesse Hall Fence::NO_FENCE); 381bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 3823399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi buffer->setObserver(0); 3833399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi buffer->release(); 384bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 3853399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi foundBuffer = true; 3863399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi break; 3873399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi } 3883399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi } 3893399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 3903399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi if (!foundBuffer) { 391f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong CHECK(!"signalBufferReturned: bogus buffer"); 3923399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi } 39300f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber 39400f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber --mNumPendingBuffers; 39500f41327264fa2e59cc05abaa5c554b2a32938e1Andreas Huber mMediaBuffersAvailableCondition.broadcast(); 3963399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} 3973399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 398bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam// Part of the BufferQueue::ConsumerListener 399bdddc659a941afdb7f4958f582c6901c07246097Daniel Lamvoid SurfaceMediaSource::onFrameAvailable() { 400bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam ALOGV("onFrameAvailable"); 401bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 402bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam sp<FrameAvailableListener> listener; 403bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam { // scope for the lock 404bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam Mutex::Autolock lock(mMutex); 405bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mFrameAvailableCondition.broadcast(); 406bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam listener = mFrameAvailableListener; 407bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam } 408bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 409bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam if (listener != NULL) { 410bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam ALOGV("actually calling onFrameAvailable"); 411bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam listener->onFrameAvailable(); 412bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam } 413bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam} 414bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 415bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam// SurfaceMediaSource hijacks this event to assume 416bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam// the prodcuer is disconnecting from the BufferQueue 417bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam// and that it should stop the recording 418bdddc659a941afdb7f4958f582c6901c07246097Daniel Lamvoid SurfaceMediaSource::onBuffersReleased() { 419bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam ALOGV("onBuffersReleased"); 420bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 421bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam Mutex::Autolock lock(mMutex); 422bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 423bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mFrameAvailableCondition.signal(); 424bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam 425bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { 426bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam mBufferSlot[i] = 0; 427bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam } 428a361483bb5dbd3bbf132c5b99b2df7d197c3fc50Pannag Sanketi} 4293399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi 4303399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi} // end of namespace android 431