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