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