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
40 namespace android {
41
SurfaceMediaSource(uint32_t bufferWidth,uint32_t bufferHeight)42 SurfaceMediaSource::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
~SurfaceMediaSource()82 SurfaceMediaSource::~SurfaceMediaSource() {
83 ALOGV("~SurfaceMediaSource");
84 CHECK(!mStarted);
85 }
86
getTimestamp()87 nsecs_t SurfaceMediaSource::getTimestamp() {
88 ALOGV("getTimestamp");
89 Mutex::Autolock lock(mMutex);
90 return mCurrentTimestamp;
91 }
92
setFrameAvailableListener(const sp<FrameAvailableListener> & listener)93 void SurfaceMediaSource::setFrameAvailableListener(
94 const sp<FrameAvailableListener>& listener) {
95 ALOGV("setFrameAvailableListener");
96 Mutex::Autolock lock(mMutex);
97 mFrameAvailableListener = listener;
98 }
99
dump(String8 & result) const100 void SurfaceMediaSource::dump(String8& result) const
101 {
102 char buffer[1024];
103 dump(result, "", buffer, 1024);
104 }
105
dump(String8 & result,const char *,char * buffer,size_t) const106 void 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
setFrameRate(int32_t fps)118 status_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
metaDataStoredInVideoBuffers() const130 MetadataBufferType SurfaceMediaSource::metaDataStoredInVideoBuffers() const {
131 ALOGV("isMetaDataStoredInVideoBuffers");
132 return kMetadataBufferTypeANWBuffer;
133 }
134
getFrameRate() const135 int32_t SurfaceMediaSource::getFrameRate( ) const {
136 ALOGV("getFrameRate");
137 Mutex::Autolock lock(mMutex);
138 return mFrameRate;
139 }
140
start(MetaData * params)141 status_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
setMaxAcquiredBufferCount(size_t count)185 status_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
setUseAbsoluteTimestamps()195 status_t SurfaceMediaSource::setUseAbsoluteTimestamps() {
196 ALOGV("setUseAbsoluteTimestamps");
197 Mutex::Autolock lock(mMutex);
198 mUseAbsoluteTimestamps = true;
199
200 return OK;
201 }
202
stop()203 status_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
getFormat()233 sp<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
passMetadataBuffer_l(MediaBuffer ** buffer,ANativeWindowBuffer * bufferHandle) const255 void 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
read(MediaBuffer ** buffer,const ReadOptions *)270 status_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
getMediaBufferHandle(MediaBuffer * buffer)375 static 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
signalBufferReturned(MediaBuffer * buffer)383 void 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
onFrameAvailable(const BufferItem &)443 void 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
onBuffersReleased()462 void 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
onSidebandStreamChanged()474 void SurfaceMediaSource::onSidebandStreamChanged() {
475 ALOG_ASSERT(false, "SurfaceMediaSource can't consume sideband streams");
476 }
477
478 } // end of namespace android
479