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