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