SurfaceMediaSource.cpp revision a5750e0dad9e90f2195ce36f2c4457fa04b2b83e
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16//#define LOG_NDEBUG 0
17#define LOG_TAG "SurfaceMediaSource"
18
19#include <inttypes.h>
20
21#include <media/stagefright/foundation/ADebug.h>
22#include <media/stagefright/SurfaceMediaSource.h>
23#include <media/stagefright/MediaDefs.h>
24#include <media/stagefright/MetaData.h>
25#include <OMX_IVCommon.h>
26#include <media/hardware/MetadataBufferType.h>
27
28#include <ui/GraphicBuffer.h>
29#include <gui/ISurfaceComposer.h>
30#include <gui/IGraphicBufferAlloc.h>
31#include <OMX_Component.h>
32
33#include <utils/Log.h>
34#include <utils/String8.h>
35
36#include <private/gui/ComposerService.h>
37
38namespace android {
39
40SurfaceMediaSource::SurfaceMediaSource(uint32_t bufferWidth, uint32_t bufferHeight) :
41    mWidth(bufferWidth),
42    mHeight(bufferHeight),
43    mCurrentSlot(BufferQueue::INVALID_BUFFER_SLOT),
44    mNumPendingBuffers(0),
45    mCurrentTimestamp(0),
46    mFrameRate(30),
47    mStarted(false),
48    mNumFramesReceived(0),
49    mNumFramesEncoded(0),
50    mFirstFrameTimestamp(0),
51    mMaxAcquiredBufferCount(4),  // XXX double-check the default
52    mUseAbsoluteTimestamps(false) {
53    ALOGV("SurfaceMediaSource");
54
55    if (bufferWidth == 0 || bufferHeight == 0) {
56        ALOGE("Invalid dimensions %dx%d", bufferWidth, bufferHeight);
57    }
58
59    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
60    mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
61    mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER |
62            GRALLOC_USAGE_HW_TEXTURE);
63
64    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
65
66    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
67    // reference once the ctor ends, as that would cause the refcount of 'this'
68    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
69    // that's what we create.
70    wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
71    sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
72
73    status_t err = mConsumer->consumerConnect(proxy, false);
74    if (err != NO_ERROR) {
75        ALOGE("SurfaceMediaSource: error connecting to BufferQueue: %s (%d)",
76                strerror(-err), err);
77    }
78}
79
80SurfaceMediaSource::~SurfaceMediaSource() {
81    ALOGV("~SurfaceMediaSource");
82    CHECK(!mStarted);
83}
84
85nsecs_t SurfaceMediaSource::getTimestamp() {
86    ALOGV("getTimestamp");
87    Mutex::Autolock lock(mMutex);
88    return mCurrentTimestamp;
89}
90
91void SurfaceMediaSource::setFrameAvailableListener(
92        const sp<FrameAvailableListener>& listener) {
93    ALOGV("setFrameAvailableListener");
94    Mutex::Autolock lock(mMutex);
95    mFrameAvailableListener = listener;
96}
97
98void SurfaceMediaSource::dump(String8& result) const
99{
100    char buffer[1024];
101    dump(result, "", buffer, 1024);
102}
103
104void SurfaceMediaSource::dump(
105        String8& result,
106        const char* /* prefix */,
107        char* buffer,
108        size_t /* SIZE */) const
109{
110    Mutex::Autolock lock(mMutex);
111
112    result.append(buffer);
113    mConsumer->dump(result, "");
114}
115
116status_t SurfaceMediaSource::setFrameRate(int32_t fps)
117{
118    ALOGV("setFrameRate");
119    Mutex::Autolock lock(mMutex);
120    const int MAX_FRAME_RATE = 60;
121    if (fps < 0 || fps > MAX_FRAME_RATE) {
122        return BAD_VALUE;
123    }
124    mFrameRate = fps;
125    return OK;
126}
127
128bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const {
129    ALOGV("isMetaDataStoredInVideoBuffers");
130    return true;
131}
132
133int32_t SurfaceMediaSource::getFrameRate( ) const {
134    ALOGV("getFrameRate");
135    Mutex::Autolock lock(mMutex);
136    return mFrameRate;
137}
138
139status_t SurfaceMediaSource::start(MetaData *params)
140{
141    ALOGV("start");
142
143    Mutex::Autolock lock(mMutex);
144
145    CHECK(!mStarted);
146
147    mStartTimeNs = 0;
148    int64_t startTimeUs;
149    int32_t bufferCount = 0;
150    if (params) {
151        if (params->findInt64(kKeyTime, &startTimeUs)) {
152            mStartTimeNs = startTimeUs * 1000;
153        }
154
155        if (!params->findInt32(kKeyNumBuffers, &bufferCount)) {
156            ALOGE("Failed to find the advertised buffer count");
157            return UNKNOWN_ERROR;
158        }
159
160        if (bufferCount <= 1) {
161            ALOGE("bufferCount %d is too small", bufferCount);
162            return BAD_VALUE;
163        }
164
165        mMaxAcquiredBufferCount = bufferCount;
166    }
167
168    CHECK_GT(mMaxAcquiredBufferCount, 1);
169
170    status_t err =
171        mConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBufferCount);
172
173    if (err != OK) {
174        return err;
175    }
176
177    mNumPendingBuffers = 0;
178    mStarted = true;
179
180    return OK;
181}
182
183status_t SurfaceMediaSource::setMaxAcquiredBufferCount(size_t count) {
184    ALOGV("setMaxAcquiredBufferCount(%zu)", count);
185    Mutex::Autolock lock(mMutex);
186
187    CHECK_GT(count, 1);
188    mMaxAcquiredBufferCount = count;
189
190    return OK;
191}
192
193status_t SurfaceMediaSource::setUseAbsoluteTimestamps() {
194    ALOGV("setUseAbsoluteTimestamps");
195    Mutex::Autolock lock(mMutex);
196    mUseAbsoluteTimestamps = true;
197
198    return OK;
199}
200
201status_t SurfaceMediaSource::stop()
202{
203    ALOGV("stop");
204    Mutex::Autolock lock(mMutex);
205
206    if (!mStarted) {
207        return OK;
208    }
209
210    mStarted = false;
211    mFrameAvailableCondition.signal();
212
213    while (mNumPendingBuffers > 0) {
214        ALOGI("Still waiting for %zu buffers to be returned.",
215                mNumPendingBuffers);
216
217#if DEBUG_PENDING_BUFFERS
218        for (size_t i = 0; i < mPendingBuffers.size(); ++i) {
219            ALOGI("%d: %p", i, mPendingBuffers.itemAt(i));
220        }
221#endif
222
223        mMediaBuffersAvailableCondition.wait(mMutex);
224    }
225
226    mMediaBuffersAvailableCondition.signal();
227
228    return mConsumer->consumerDisconnect();
229}
230
231sp<MetaData> SurfaceMediaSource::getFormat()
232{
233    ALOGV("getFormat");
234
235    Mutex::Autolock lock(mMutex);
236    sp<MetaData> meta = new MetaData;
237
238    meta->setInt32(kKeyWidth, mWidth);
239    meta->setInt32(kKeyHeight, mHeight);
240    // The encoder format is set as an opaque colorformat
241    // The encoder will later find out the actual colorformat
242    // from the GL Frames itself.
243    meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque);
244    meta->setInt32(kKeyStride, mWidth);
245    meta->setInt32(kKeySliceHeight, mHeight);
246    meta->setInt32(kKeyFrameRate, mFrameRate);
247    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
248    return meta;
249}
250
251// Pass the data to the MediaBuffer. Pass in only the metadata
252// The metadata passed consists of two parts:
253// 1. First, there is an integer indicating that it is a GRAlloc
254// source (kMetadataBufferTypeGrallocSource)
255// 2. This is followed by the buffer_handle_t that is a handle to the
256// GRalloc buffer. The encoder needs to interpret this GRalloc handle
257// and encode the frames.
258// --------------------------------------------------------------
259// |  kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
260// --------------------------------------------------------------
261// Note: Call only when you have the lock
262static void passMetadataBuffer(MediaBuffer **buffer,
263        buffer_handle_t bufferHandle) {
264    *buffer = new MediaBuffer(4 + sizeof(buffer_handle_t));
265    char *data = (char *)(*buffer)->data();
266    if (data == NULL) {
267        ALOGE("Cannot allocate memory for metadata buffer!");
268        return;
269    }
270    OMX_U32 type = kMetadataBufferTypeGrallocSource;
271    memcpy(data, &type, 4);
272    memcpy(data + 4, &bufferHandle, sizeof(buffer_handle_t));
273
274    ALOGV("handle = %p, , offset = %zu, length = %zu",
275            bufferHandle, (*buffer)->range_length(), (*buffer)->range_offset());
276}
277
278status_t SurfaceMediaSource::read(
279        MediaBuffer **buffer, const ReadOptions * /* options */) {
280    ALOGV("read");
281    Mutex::Autolock lock(mMutex);
282
283    *buffer = NULL;
284
285    while (mStarted && mNumPendingBuffers == mMaxAcquiredBufferCount) {
286        mMediaBuffersAvailableCondition.wait(mMutex);
287    }
288
289    // Update the current buffer info
290    // TODO: mCurrentSlot can be made a bufferstate since there
291    // can be more than one "current" slots.
292
293    BufferQueue::BufferItem item;
294    // If the recording has started and the queue is empty, then just
295    // wait here till the frames come in from the client side
296    while (mStarted) {
297
298        status_t err = mConsumer->acquireBuffer(&item, 0);
299        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
300            // wait for a buffer to be queued
301            mFrameAvailableCondition.wait(mMutex);
302        } else if (err == OK) {
303            err = item.mFence->waitForever("SurfaceMediaSource::read");
304            if (err) {
305                ALOGW("read: failed to wait for buffer fence: %d", err);
306            }
307
308            // First time seeing the buffer?  Added it to the SMS slot
309            if (item.mGraphicBuffer != NULL) {
310                mSlots[item.mBuf].mGraphicBuffer = item.mGraphicBuffer;
311            }
312            mSlots[item.mBuf].mFrameNumber = item.mFrameNumber;
313
314            // check for the timing of this buffer
315            if (mNumFramesReceived == 0 && !mUseAbsoluteTimestamps) {
316                mFirstFrameTimestamp = item.mTimestamp;
317                // Initial delay
318                if (mStartTimeNs > 0) {
319                    if (item.mTimestamp < mStartTimeNs) {
320                        // This frame predates start of record, discard
321                        mConsumer->releaseBuffer(
322                                item.mBuf, item.mFrameNumber, EGL_NO_DISPLAY,
323                                EGL_NO_SYNC_KHR, Fence::NO_FENCE);
324                        continue;
325                    }
326                    mStartTimeNs = item.mTimestamp - mStartTimeNs;
327                }
328            }
329            item.mTimestamp = mStartTimeNs + (item.mTimestamp - mFirstFrameTimestamp);
330
331            mNumFramesReceived++;
332
333            break;
334        } else {
335            ALOGE("read: acquire failed with error code %d", err);
336            return ERROR_END_OF_STREAM;
337        }
338
339    }
340
341    // If the loop was exited as a result of stopping the recording,
342    // it is OK
343    if (!mStarted) {
344        ALOGV("Read: SurfaceMediaSource is stopped. Returning ERROR_END_OF_STREAM.");
345        return ERROR_END_OF_STREAM;
346    }
347
348    mCurrentSlot = item.mBuf;
349
350    // First time seeing the buffer?  Added it to the SMS slot
351    if (item.mGraphicBuffer != NULL) {
352        mSlots[item.mBuf].mGraphicBuffer = item.mGraphicBuffer;
353    }
354    mSlots[item.mBuf].mFrameNumber = item.mFrameNumber;
355
356    mCurrentBuffers.push_back(mSlots[mCurrentSlot].mGraphicBuffer);
357    int64_t prevTimeStamp = mCurrentTimestamp;
358    mCurrentTimestamp = item.mTimestamp;
359
360    mNumFramesEncoded++;
361    // Pass the data to the MediaBuffer. Pass in only the metadata
362
363    passMetadataBuffer(buffer, mSlots[mCurrentSlot].mGraphicBuffer->handle);
364
365    (*buffer)->setObserver(this);
366    (*buffer)->add_ref();
367    (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000);
368    ALOGV("Frames encoded = %d, timestamp = %" PRId64 ", time diff = %" PRId64,
369            mNumFramesEncoded, mCurrentTimestamp / 1000,
370            mCurrentTimestamp / 1000 - prevTimeStamp / 1000);
371
372    ++mNumPendingBuffers;
373
374#if DEBUG_PENDING_BUFFERS
375    mPendingBuffers.push_back(*buffer);
376#endif
377
378    ALOGV("returning mbuf %p", *buffer);
379
380    return OK;
381}
382
383static buffer_handle_t getMediaBufferHandle(MediaBuffer *buffer) {
384    // need to convert to char* for pointer arithmetic and then
385    // copy the byte stream into our handle
386    buffer_handle_t bufferHandle;
387    memcpy(&bufferHandle, (char*)(buffer->data()) + 4, sizeof(buffer_handle_t));
388    return bufferHandle;
389}
390
391void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
392    ALOGV("signalBufferReturned");
393
394    bool foundBuffer = false;
395
396    Mutex::Autolock lock(mMutex);
397
398    buffer_handle_t bufferHandle = getMediaBufferHandle(buffer);
399
400    for (size_t i = 0; i < mCurrentBuffers.size(); i++) {
401        if (mCurrentBuffers[i]->handle == bufferHandle) {
402            mCurrentBuffers.removeAt(i);
403            foundBuffer = true;
404            break;
405        }
406    }
407
408    if (!foundBuffer) {
409        ALOGW("returned buffer was not found in the current buffer list");
410    }
411
412    for (int id = 0; id < BufferQueue::NUM_BUFFER_SLOTS; id++) {
413        if (mSlots[id].mGraphicBuffer == NULL) {
414            continue;
415        }
416
417        if (bufferHandle == mSlots[id].mGraphicBuffer->handle) {
418            ALOGV("Slot %d returned, matches handle = %p", id,
419                    mSlots[id].mGraphicBuffer->handle);
420
421            mConsumer->releaseBuffer(id, mSlots[id].mFrameNumber,
422                                        EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
423                    Fence::NO_FENCE);
424
425            buffer->setObserver(0);
426            buffer->release();
427
428            foundBuffer = true;
429            break;
430        }
431    }
432
433    if (!foundBuffer) {
434        CHECK(!"signalBufferReturned: bogus buffer");
435    }
436
437#if DEBUG_PENDING_BUFFERS
438    for (size_t i = 0; i < mPendingBuffers.size(); ++i) {
439        if (mPendingBuffers.itemAt(i) == buffer) {
440            mPendingBuffers.removeAt(i);
441            break;
442        }
443    }
444#endif
445
446    --mNumPendingBuffers;
447    mMediaBuffersAvailableCondition.broadcast();
448}
449
450// Part of the BufferQueue::ConsumerListener
451void SurfaceMediaSource::onFrameAvailable() {
452    ALOGV("onFrameAvailable");
453
454    sp<FrameAvailableListener> listener;
455    { // scope for the lock
456        Mutex::Autolock lock(mMutex);
457        mFrameAvailableCondition.broadcast();
458        listener = mFrameAvailableListener;
459    }
460
461    if (listener != NULL) {
462        ALOGV("actually calling onFrameAvailable");
463        listener->onFrameAvailable();
464    }
465}
466
467// SurfaceMediaSource hijacks this event to assume
468// the prodcuer is disconnecting from the BufferQueue
469// and that it should stop the recording
470void SurfaceMediaSource::onBuffersReleased() {
471    ALOGV("onBuffersReleased");
472
473    Mutex::Autolock lock(mMutex);
474
475    mFrameAvailableCondition.signal();
476
477    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
478       mSlots[i].mGraphicBuffer = 0;
479    }
480}
481
482void SurfaceMediaSource::onSidebandStreamChanged() {
483    ALOG_ASSERT(false, "SurfaceMediaSource can't consume sideband streams");
484}
485
486} // end of namespace android
487