1 /*
2 * Copyright (C) 2009 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
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "OMXNodeInstance"
19 #include <utils/Log.h>
20
21 #include <inttypes.h>
22
23 #include "../include/OMXNodeInstance.h"
24 #include "OMXMaster.h"
25 #include "OMXUtils.h"
26 #include "GraphicBufferSource.h"
27
28 #include <OMX_Component.h>
29 #include <OMX_IndexExt.h>
30 #include <OMX_AsString.h>
31
32 #include <binder/IMemory.h>
33 #include <cutils/properties.h>
34 #include <gui/BufferQueue.h>
35 #include <HardwareAPI.h>
36 #include <media/stagefright/foundation/ADebug.h>
37 #include <media/stagefright/foundation/ABuffer.h>
38 #include <media/stagefright/MediaErrors.h>
39 #include <utils/misc.h>
40 #include <utils/NativeHandle.h>
41
42 static const OMX_U32 kPortIndexInput = 0;
43 static const OMX_U32 kPortIndexOutput = 1;
44
45 #define CLOGW(fmt, ...) ALOGW("[%x:%s] " fmt, mNodeID, mName, ##__VA_ARGS__)
46
47 #define CLOG_ERROR_IF(cond, fn, err, fmt, ...) \
48 ALOGE_IF(cond, #fn "(%x:%s, " fmt ") ERROR: %s(%#x)", \
49 mNodeID, mName, ##__VA_ARGS__, asString(err), err)
50 #define CLOG_ERROR(fn, err, fmt, ...) CLOG_ERROR_IF(true, fn, err, fmt, ##__VA_ARGS__)
51 #define CLOG_IF_ERROR(fn, err, fmt, ...) \
52 CLOG_ERROR_IF((err) != OMX_ErrorNone, fn, err, fmt, ##__VA_ARGS__)
53
54 #define CLOGI_(level, fn, fmt, ...) \
55 ALOGI_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__)
56 #define CLOGD_(level, fn, fmt, ...) \
57 ALOGD_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__)
58
59 #define CLOG_LIFE(fn, fmt, ...) CLOGI_(ADebug::kDebugLifeCycle, fn, fmt, ##__VA_ARGS__)
60 #define CLOG_STATE(fn, fmt, ...) CLOGI_(ADebug::kDebugState, fn, fmt, ##__VA_ARGS__)
61 #define CLOG_CONFIG(fn, fmt, ...) CLOGI_(ADebug::kDebugConfig, fn, fmt, ##__VA_ARGS__)
62 #define CLOG_INTERNAL(fn, fmt, ...) CLOGD_(ADebug::kDebugInternalState, fn, fmt, ##__VA_ARGS__)
63
64 #define CLOG_DEBUG_IF(cond, fn, fmt, ...) \
65 ALOGD_IF(cond, #fn "(%x, " fmt ")", mNodeID, ##__VA_ARGS__)
66
67 #define CLOG_BUFFER(fn, fmt, ...) \
68 CLOG_DEBUG_IF(DEBUG >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)
69 #define CLOG_BUMPED_BUFFER(fn, fmt, ...) \
70 CLOG_DEBUG_IF(DEBUG_BUMP >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)
71
72 /* buffer formatting */
73 #define BUFFER_FMT(port, fmt, ...) "%s:%u " fmt, portString(port), (port), ##__VA_ARGS__
74 #define NEW_BUFFER_FMT(buffer_id, port, fmt, ...) \
75 BUFFER_FMT(port, fmt ") (#%zu => %#x", ##__VA_ARGS__, mActiveBuffers.size(), (buffer_id))
76
77 #define SIMPLE_BUFFER(port, size, data) BUFFER_FMT(port, "%zu@%p", (size), (data))
78 #define SIMPLE_NEW_BUFFER(buffer_id, port, size, data) \
79 NEW_BUFFER_FMT(buffer_id, port, "%zu@%p", (size), (data))
80
81 #define EMPTY_BUFFER(addr, header, fenceFd) "%#x [%u@%p fc=%d]", \
82 (addr), (header)->nAllocLen, (header)->pBuffer, (fenceFd)
83 #define FULL_BUFFER(addr, header, fenceFd) "%#" PRIxPTR " [%u@%p (%u..+%u) f=%x ts=%lld fc=%d]", \
84 (intptr_t)(addr), (header)->nAllocLen, (header)->pBuffer, \
85 (header)->nOffset, (header)->nFilledLen, (header)->nFlags, (header)->nTimeStamp, (fenceFd)
86
87 #define WITH_STATS_WRAPPER(fmt, ...) fmt " { IN=%zu/%zu OUT=%zu/%zu }", ##__VA_ARGS__, \
88 mInputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexInput], \
89 mOutputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexOutput]
90 // TRICKY: this is needed so formatting macros expand before substitution
91 #define WITH_STATS(fmt, ...) WITH_STATS_WRAPPER(fmt, ##__VA_ARGS__)
92
93 namespace android {
94
95 struct BufferMeta {
BufferMetaandroid::BufferMeta96 BufferMeta(const sp<IMemory> &mem, OMX_U32 portIndex, bool is_backup = false)
97 : mMem(mem),
98 mIsBackup(is_backup),
99 mPortIndex(portIndex) {
100 }
101
BufferMetaandroid::BufferMeta102 BufferMeta(size_t size, OMX_U32 portIndex)
103 : mSize(size),
104 mIsBackup(false),
105 mPortIndex(portIndex) {
106 }
107
BufferMetaandroid::BufferMeta108 BufferMeta(const sp<GraphicBuffer> &graphicBuffer, OMX_U32 portIndex)
109 : mGraphicBuffer(graphicBuffer),
110 mIsBackup(false),
111 mPortIndex(portIndex) {
112 }
113
CopyFromOMXandroid::BufferMeta114 void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
115 if (!mIsBackup) {
116 return;
117 }
118
119 // check component returns proper range
120 sp<ABuffer> codec = getBuffer(header, false /* backup */, true /* limit */);
121
122 memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, codec->data(), codec->size());
123 }
124
CopyToOMXandroid::BufferMeta125 void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
126 if (!mIsBackup) {
127 return;
128 }
129
130 memcpy(header->pBuffer + header->nOffset,
131 (const OMX_U8 *)mMem->pointer() + header->nOffset,
132 header->nFilledLen);
133 }
134
135 // return either the codec or the backup buffer
getBufferandroid::BufferMeta136 sp<ABuffer> getBuffer(const OMX_BUFFERHEADERTYPE *header, bool backup, bool limit) {
137 sp<ABuffer> buf;
138 if (backup && mMem != NULL) {
139 buf = new ABuffer(mMem->pointer(), mMem->size());
140 } else {
141 buf = new ABuffer(header->pBuffer, header->nAllocLen);
142 }
143 if (limit) {
144 if (header->nOffset + header->nFilledLen > header->nOffset
145 && header->nOffset + header->nFilledLen <= header->nAllocLen) {
146 buf->setRange(header->nOffset, header->nFilledLen);
147 } else {
148 buf->setRange(0, 0);
149 }
150 }
151 return buf;
152 }
153
setGraphicBufferandroid::BufferMeta154 void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) {
155 mGraphicBuffer = graphicBuffer;
156 }
157
setNativeHandleandroid::BufferMeta158 void setNativeHandle(const sp<NativeHandle> &nativeHandle) {
159 mNativeHandle = nativeHandle;
160 }
161
getPortIndexandroid::BufferMeta162 OMX_U32 getPortIndex() {
163 return mPortIndex;
164 }
165
166 private:
167 sp<GraphicBuffer> mGraphicBuffer;
168 sp<NativeHandle> mNativeHandle;
169 sp<IMemory> mMem;
170 size_t mSize;
171 bool mIsBackup;
172 OMX_U32 mPortIndex;
173
174 BufferMeta(const BufferMeta &);
175 BufferMeta &operator=(const BufferMeta &);
176 };
177
178 // static
179 OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
180 &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
181 };
182
portString(OMX_U32 portIndex)183 static inline const char *portString(OMX_U32 portIndex) {
184 switch (portIndex) {
185 case kPortIndexInput: return "Input";
186 case kPortIndexOutput: return "Output";
187 case ~0U: return "All";
188 default: return "port";
189 }
190 }
191
OMXNodeInstance(OMX * owner,const sp<IOMXObserver> & observer,const char * name)192 OMXNodeInstance::OMXNodeInstance(
193 OMX *owner, const sp<IOMXObserver> &observer, const char *name)
194 : mOwner(owner),
195 mNodeID(0),
196 mHandle(NULL),
197 mObserver(observer),
198 mDying(false),
199 mBufferIDCount(0)
200 {
201 mName = ADebug::GetDebugName(name);
202 DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug");
203 ALOGV("debug level for %s is %d", name, DEBUG);
204 DEBUG_BUMP = DEBUG;
205 mNumPortBuffers[0] = 0;
206 mNumPortBuffers[1] = 0;
207 mDebugLevelBumpPendingBuffers[0] = 0;
208 mDebugLevelBumpPendingBuffers[1] = 0;
209 mMetadataType[0] = kMetadataBufferTypeInvalid;
210 mMetadataType[1] = kMetadataBufferTypeInvalid;
211 mSecureBufferType[0] = kSecureBufferTypeUnknown;
212 mSecureBufferType[1] = kSecureBufferTypeUnknown;
213 mIsSecure = AString(name).endsWith(".secure");
214 }
215
~OMXNodeInstance()216 OMXNodeInstance::~OMXNodeInstance() {
217 free(mName);
218 CHECK(mHandle == NULL);
219 }
220
setHandle(OMX::node_id node_id,OMX_HANDLETYPE handle)221 void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
222 mNodeID = node_id;
223 CLOG_LIFE(allocateNode, "handle=%p", handle);
224 CHECK(mHandle == NULL);
225 mHandle = handle;
226 }
227
getGraphicBufferSource()228 sp<GraphicBufferSource> OMXNodeInstance::getGraphicBufferSource() {
229 Mutex::Autolock autoLock(mGraphicBufferSourceLock);
230 return mGraphicBufferSource;
231 }
232
setGraphicBufferSource(const sp<GraphicBufferSource> & bufferSource)233 void OMXNodeInstance::setGraphicBufferSource(
234 const sp<GraphicBufferSource>& bufferSource) {
235 Mutex::Autolock autoLock(mGraphicBufferSourceLock);
236 CLOG_INTERNAL(setGraphicBufferSource, "%p", bufferSource.get());
237 mGraphicBufferSource = bufferSource;
238 }
239
owner()240 OMX *OMXNodeInstance::owner() {
241 return mOwner;
242 }
243
observer()244 sp<IOMXObserver> OMXNodeInstance::observer() {
245 return mObserver;
246 }
247
nodeID()248 OMX::node_id OMXNodeInstance::nodeID() {
249 return mNodeID;
250 }
251
freeNode(OMXMaster * master)252 status_t OMXNodeInstance::freeNode(OMXMaster *master) {
253 CLOG_LIFE(freeNode, "handle=%p", mHandle);
254 static int32_t kMaxNumIterations = 10;
255
256 // exit if we have already freed the node
257 if (mHandle == NULL) {
258 return OK;
259 }
260
261 // Transition the node from its current state all the way down
262 // to "Loaded".
263 // This ensures that all active buffers are properly freed even
264 // for components that don't do this themselves on a call to
265 // "FreeHandle".
266
267 // The code below may trigger some more events to be dispatched
268 // by the OMX component - we want to ignore them as our client
269 // does not expect them.
270 mDying = true;
271
272 OMX_STATETYPE state;
273 CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone);
274 switch (state) {
275 case OMX_StateExecuting:
276 {
277 ALOGV("forcing Executing->Idle");
278 sendCommand(OMX_CommandStateSet, OMX_StateIdle);
279 OMX_ERRORTYPE err;
280 int32_t iteration = 0;
281 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
282 && state != OMX_StateIdle
283 && state != OMX_StateInvalid) {
284 if (++iteration > kMaxNumIterations) {
285 CLOGW("failed to enter Idle state (now %s(%d), aborting.",
286 asString(state), state);
287 state = OMX_StateInvalid;
288 break;
289 }
290
291 usleep(100000);
292 }
293 CHECK_EQ(err, OMX_ErrorNone);
294
295 if (state == OMX_StateInvalid) {
296 break;
297 }
298
299 // fall through
300 }
301
302 case OMX_StateIdle:
303 {
304 ALOGV("forcing Idle->Loaded");
305 sendCommand(OMX_CommandStateSet, OMX_StateLoaded);
306
307 freeActiveBuffers();
308
309 OMX_ERRORTYPE err;
310 int32_t iteration = 0;
311 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
312 && state != OMX_StateLoaded
313 && state != OMX_StateInvalid) {
314 if (++iteration > kMaxNumIterations) {
315 CLOGW("failed to enter Loaded state (now %s(%d), aborting.",
316 asString(state), state);
317 state = OMX_StateInvalid;
318 break;
319 }
320
321 ALOGV("waiting for Loaded state...");
322 usleep(100000);
323 }
324 CHECK_EQ(err, OMX_ErrorNone);
325
326 // fall through
327 }
328
329 case OMX_StateLoaded:
330 case OMX_StateInvalid:
331 break;
332
333 default:
334 LOG_ALWAYS_FATAL("unknown state %s(%#x).", asString(state), state);
335 break;
336 }
337
338 ALOGV("[%x:%s] calling destroyComponentInstance", mNodeID, mName);
339 OMX_ERRORTYPE err = master->destroyComponentInstance(
340 static_cast<OMX_COMPONENTTYPE *>(mHandle));
341
342 mHandle = NULL;
343 CLOG_IF_ERROR(freeNode, err, "");
344 free(mName);
345 mName = NULL;
346
347 mOwner->invalidateNodeID(mNodeID);
348 mNodeID = 0;
349
350 ALOGV("OMXNodeInstance going away.");
351 delete this;
352
353 return StatusFromOMXError(err);
354 }
355
sendCommand(OMX_COMMANDTYPE cmd,OMX_S32 param)356 status_t OMXNodeInstance::sendCommand(
357 OMX_COMMANDTYPE cmd, OMX_S32 param) {
358 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
359 if (bufferSource != NULL && cmd == OMX_CommandStateSet) {
360 if (param == OMX_StateIdle) {
361 // Initiating transition from Executing -> Idle
362 // ACodec is waiting for all buffers to be returned, do NOT
363 // submit any more buffers to the codec.
364 bufferSource->omxIdle();
365 } else if (param == OMX_StateLoaded) {
366 // Initiating transition from Idle/Executing -> Loaded
367 // Buffers are about to be freed.
368 bufferSource->omxLoaded();
369 setGraphicBufferSource(NULL);
370 }
371
372 // fall through
373 }
374
375 Mutex::Autolock autoLock(mLock);
376
377 // bump internal-state debug level for 2 input and output frames past a command
378 {
379 Mutex::Autolock _l(mDebugLock);
380 bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */);
381 }
382
383 const char *paramString =
384 cmd == OMX_CommandStateSet ? asString((OMX_STATETYPE)param) : portString(param);
385 CLOG_STATE(sendCommand, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param);
386 OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
387 CLOG_IF_ERROR(sendCommand, err, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param);
388 return StatusFromOMXError(err);
389 }
390
getParameter(OMX_INDEXTYPE index,void * params,size_t)391 status_t OMXNodeInstance::getParameter(
392 OMX_INDEXTYPE index, void *params, size_t /* size */) {
393 Mutex::Autolock autoLock(mLock);
394
395 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
396 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
397 // some errors are expected for getParameter
398 if (err != OMX_ErrorNoMore) {
399 CLOG_IF_ERROR(getParameter, err, "%s(%#x)", asString(extIndex), index);
400 }
401 return StatusFromOMXError(err);
402 }
403
setParameter(OMX_INDEXTYPE index,const void * params,size_t size)404 status_t OMXNodeInstance::setParameter(
405 OMX_INDEXTYPE index, const void *params, size_t size) {
406 Mutex::Autolock autoLock(mLock);
407 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
408 CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
409
410 OMX_ERRORTYPE err = OMX_SetParameter(
411 mHandle, index, const_cast<void *>(params));
412 CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index);
413 return StatusFromOMXError(err);
414 }
415
getConfig(OMX_INDEXTYPE index,void * params,size_t)416 status_t OMXNodeInstance::getConfig(
417 OMX_INDEXTYPE index, void *params, size_t /* size */) {
418 Mutex::Autolock autoLock(mLock);
419
420 OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
421 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
422 // some errors are expected for getConfig
423 if (err != OMX_ErrorNoMore) {
424 CLOG_IF_ERROR(getConfig, err, "%s(%#x)", asString(extIndex), index);
425 }
426 return StatusFromOMXError(err);
427 }
428
setConfig(OMX_INDEXTYPE index,const void * params,size_t size)429 status_t OMXNodeInstance::setConfig(
430 OMX_INDEXTYPE index, const void *params, size_t size) {
431 Mutex::Autolock autoLock(mLock);
432 OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
433 CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
434
435 OMX_ERRORTYPE err = OMX_SetConfig(
436 mHandle, index, const_cast<void *>(params));
437 CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index);
438 return StatusFromOMXError(err);
439 }
440
getState(OMX_STATETYPE * state)441 status_t OMXNodeInstance::getState(OMX_STATETYPE* state) {
442 Mutex::Autolock autoLock(mLock);
443
444 OMX_ERRORTYPE err = OMX_GetState(mHandle, state);
445 CLOG_IF_ERROR(getState, err, "");
446 return StatusFromOMXError(err);
447 }
448
enableNativeBuffers(OMX_U32 portIndex,OMX_BOOL graphic,OMX_BOOL enable)449 status_t OMXNodeInstance::enableNativeBuffers(
450 OMX_U32 portIndex, OMX_BOOL graphic, OMX_BOOL enable) {
451 Mutex::Autolock autoLock(mLock);
452 CLOG_CONFIG(enableNativeBuffers, "%s:%u%s, %d", portString(portIndex), portIndex,
453 graphic ? ", graphic" : "", enable);
454 OMX_STRING name = const_cast<OMX_STRING>(
455 graphic ? "OMX.google.android.index.enableAndroidNativeBuffers"
456 : "OMX.google.android.index.allocateNativeHandle");
457
458 OMX_INDEXTYPE index;
459 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
460
461 if (err == OMX_ErrorNone) {
462 EnableAndroidNativeBuffersParams params;
463 InitOMXParams(¶ms);
464 params.nPortIndex = portIndex;
465 params.enable = enable;
466
467 err = OMX_SetParameter(mHandle, index, ¶ms);
468 CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index,
469 portString(portIndex), portIndex, enable);
470 if (!graphic) {
471 if (err == OMX_ErrorNone) {
472 mSecureBufferType[portIndex] =
473 enable ? kSecureBufferTypeNativeHandle : kSecureBufferTypeOpaque;
474 } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
475 mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
476 }
477 }
478 } else {
479 CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
480 if (!graphic) {
481 // Extension not supported, check for manual override with system property
482 // This is a temporary workaround until partners support the OMX extension
483 char value[PROPERTY_VALUE_MAX];
484 if (property_get("media.mediadrmservice.enable", value, NULL)
485 && (!strcmp("1", value) || !strcasecmp("true", value))) {
486 CLOG_CONFIG(enableNativeBuffers, "system property override: using native-handles");
487 mSecureBufferType[portIndex] = kSecureBufferTypeNativeHandle;
488 } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
489 mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
490 }
491 err = OMX_ErrorNone;
492 }
493 }
494
495 return StatusFromOMXError(err);
496 }
497
getGraphicBufferUsage(OMX_U32 portIndex,OMX_U32 * usage)498 status_t OMXNodeInstance::getGraphicBufferUsage(
499 OMX_U32 portIndex, OMX_U32* usage) {
500 Mutex::Autolock autoLock(mLock);
501
502 OMX_INDEXTYPE index;
503 OMX_STRING name = const_cast<OMX_STRING>(
504 "OMX.google.android.index.getAndroidNativeBufferUsage");
505 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
506
507 if (err != OMX_ErrorNone) {
508 CLOG_ERROR(getExtensionIndex, err, "%s", name);
509 return StatusFromOMXError(err);
510 }
511
512 GetAndroidNativeBufferUsageParams params;
513 InitOMXParams(¶ms);
514 params.nPortIndex = portIndex;
515
516 err = OMX_GetParameter(mHandle, index, ¶ms);
517 if (err != OMX_ErrorNone) {
518 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u", name, index,
519 portString(portIndex), portIndex);
520 return StatusFromOMXError(err);
521 }
522
523 *usage = params.nUsage;
524
525 return OK;
526 }
527
storeMetaDataInBuffers(OMX_U32 portIndex,OMX_BOOL enable,MetadataBufferType * type)528 status_t OMXNodeInstance::storeMetaDataInBuffers(
529 OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
530 Mutex::Autolock autolock(mLock);
531 CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u en:%d", portString(portIndex), portIndex, enable);
532 return storeMetaDataInBuffers_l(portIndex, enable, type);
533 }
534
storeMetaDataInBuffers_l(OMX_U32 portIndex,OMX_BOOL enable,MetadataBufferType * type)535 status_t OMXNodeInstance::storeMetaDataInBuffers_l(
536 OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
537 if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
538 android_errorWriteLog(0x534e4554, "26324358");
539 if (type != NULL) {
540 *type = kMetadataBufferTypeInvalid;
541 }
542 return BAD_VALUE;
543 }
544
545 OMX_INDEXTYPE index;
546 OMX_STRING name = const_cast<OMX_STRING>(
547 "OMX.google.android.index.storeMetaDataInBuffers");
548
549 OMX_STRING nativeBufferName = const_cast<OMX_STRING>(
550 "OMX.google.android.index.storeANWBufferInMetadata");
551 MetadataBufferType negotiatedType;
552 MetadataBufferType requestedType = type != NULL ? *type : kMetadataBufferTypeANWBuffer;
553
554 StoreMetaDataInBuffersParams params;
555 InitOMXParams(¶ms);
556 params.nPortIndex = portIndex;
557 params.bStoreMetaData = enable;
558
559 OMX_ERRORTYPE err =
560 requestedType == kMetadataBufferTypeANWBuffer
561 ? OMX_GetExtensionIndex(mHandle, nativeBufferName, &index)
562 : OMX_ErrorUnsupportedIndex;
563 OMX_ERRORTYPE xerr = err;
564 if (err == OMX_ErrorNone) {
565 err = OMX_SetParameter(mHandle, index, ¶ms);
566 if (err == OMX_ErrorNone) {
567 name = nativeBufferName; // set name for debugging
568 negotiatedType = requestedType;
569 }
570 }
571 if (err != OMX_ErrorNone) {
572 err = OMX_GetExtensionIndex(mHandle, name, &index);
573 xerr = err;
574 if (err == OMX_ErrorNone) {
575 negotiatedType =
576 requestedType == kMetadataBufferTypeANWBuffer
577 ? kMetadataBufferTypeGrallocSource : requestedType;
578 err = OMX_SetParameter(mHandle, index, ¶ms);
579 }
580 }
581
582 // don't log loud error if component does not support metadata mode on the output
583 if (err != OMX_ErrorNone) {
584 if (err == OMX_ErrorUnsupportedIndex && portIndex == kPortIndexOutput) {
585 CLOGW("component does not support metadata mode; using fallback");
586 } else if (xerr != OMX_ErrorNone) {
587 CLOG_ERROR(getExtensionIndex, xerr, "%s", name);
588 } else {
589 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d type=%d", name, index,
590 portString(portIndex), portIndex, enable, negotiatedType);
591 }
592 negotiatedType = mMetadataType[portIndex];
593 } else {
594 if (!enable) {
595 negotiatedType = kMetadataBufferTypeInvalid;
596 }
597 mMetadataType[portIndex] = negotiatedType;
598 }
599 CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u %srequested %s:%d negotiated %s:%d",
600 portString(portIndex), portIndex, enable ? "" : "UN",
601 asString(requestedType), requestedType, asString(negotiatedType), negotiatedType);
602
603 if (type != NULL) {
604 *type = negotiatedType;
605 }
606
607 return StatusFromOMXError(err);
608 }
609
prepareForAdaptivePlayback(OMX_U32 portIndex,OMX_BOOL enable,OMX_U32 maxFrameWidth,OMX_U32 maxFrameHeight)610 status_t OMXNodeInstance::prepareForAdaptivePlayback(
611 OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth,
612 OMX_U32 maxFrameHeight) {
613 Mutex::Autolock autolock(mLock);
614 CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u",
615 portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);
616
617 OMX_INDEXTYPE index;
618 OMX_STRING name = const_cast<OMX_STRING>(
619 "OMX.google.android.index.prepareForAdaptivePlayback");
620
621 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
622 if (err != OMX_ErrorNone) {
623 CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
624 return StatusFromOMXError(err);
625 }
626
627 PrepareForAdaptivePlaybackParams params;
628 InitOMXParams(¶ms);
629 params.nPortIndex = portIndex;
630 params.bEnable = enable;
631 params.nMaxFrameWidth = maxFrameWidth;
632 params.nMaxFrameHeight = maxFrameHeight;
633
634 err = OMX_SetParameter(mHandle, index, ¶ms);
635 CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d max=%ux%u", name, index,
636 portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);
637 return StatusFromOMXError(err);
638 }
639
configureVideoTunnelMode(OMX_U32 portIndex,OMX_BOOL tunneled,OMX_U32 audioHwSync,native_handle_t ** sidebandHandle)640 status_t OMXNodeInstance::configureVideoTunnelMode(
641 OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync,
642 native_handle_t **sidebandHandle) {
643 Mutex::Autolock autolock(mLock);
644 CLOG_CONFIG(configureVideoTunnelMode, "%s:%u tun=%d sync=%u",
645 portString(portIndex), portIndex, tunneled, audioHwSync);
646
647 OMX_INDEXTYPE index;
648 OMX_STRING name = const_cast<OMX_STRING>(
649 "OMX.google.android.index.configureVideoTunnelMode");
650
651 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
652 if (err != OMX_ErrorNone) {
653 CLOG_ERROR_IF(tunneled, getExtensionIndex, err, "%s", name);
654 return StatusFromOMXError(err);
655 }
656
657 ConfigureVideoTunnelModeParams tunnelParams;
658 InitOMXParams(&tunnelParams);
659 tunnelParams.nPortIndex = portIndex;
660 tunnelParams.bTunneled = tunneled;
661 tunnelParams.nAudioHwSync = audioHwSync;
662 err = OMX_SetParameter(mHandle, index, &tunnelParams);
663 if (err != OMX_ErrorNone) {
664 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index,
665 portString(portIndex), portIndex, tunneled, audioHwSync);
666 return StatusFromOMXError(err);
667 }
668
669 err = OMX_GetParameter(mHandle, index, &tunnelParams);
670 if (err != OMX_ErrorNone) {
671 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index,
672 portString(portIndex), portIndex, tunneled, audioHwSync);
673 return StatusFromOMXError(err);
674 }
675 if (sidebandHandle) {
676 *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;
677 }
678
679 return OK;
680 }
681
useBuffer(OMX_U32 portIndex,const sp<IMemory> & params,OMX::buffer_id * buffer,OMX_U32 allottedSize)682 status_t OMXNodeInstance::useBuffer(
683 OMX_U32 portIndex, const sp<IMemory> ¶ms,
684 OMX::buffer_id *buffer, OMX_U32 allottedSize) {
685 if (params == NULL || buffer == NULL) {
686 ALOGE("b/25884056");
687 return BAD_VALUE;
688 }
689
690 Mutex::Autolock autoLock(mLock);
691 if (allottedSize > params->size()) {
692 return BAD_VALUE;
693 }
694
695 BufferMeta *buffer_meta = new BufferMeta(params, portIndex);
696
697 OMX_BUFFERHEADERTYPE *header;
698
699 OMX_ERRORTYPE err = OMX_UseBuffer(
700 mHandle, &header, portIndex, buffer_meta,
701 allottedSize, static_cast<OMX_U8 *>(params->pointer()));
702
703 if (err != OMX_ErrorNone) {
704 CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(
705 portIndex, (size_t)allottedSize, params->pointer()));
706
707 delete buffer_meta;
708 buffer_meta = NULL;
709
710 *buffer = 0;
711
712 return StatusFromOMXError(err);
713 }
714
715 CHECK_EQ(header->pAppPrivate, buffer_meta);
716
717 *buffer = makeBufferID(header);
718
719 addActiveBuffer(portIndex, *buffer);
720
721 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
722 if (bufferSource != NULL && portIndex == kPortIndexInput) {
723 bufferSource->addCodecBuffer(header);
724 }
725
726 CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT(
727 *buffer, portIndex, "%u(%zu)@%p", allottedSize, params->size(), params->pointer()));
728 return OK;
729 }
730
useGraphicBuffer2_l(OMX_U32 portIndex,const sp<GraphicBuffer> & graphicBuffer,OMX::buffer_id * buffer)731 status_t OMXNodeInstance::useGraphicBuffer2_l(
732 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
733 OMX::buffer_id *buffer) {
734 if (graphicBuffer == NULL || buffer == NULL) {
735 ALOGE("b/25884056");
736 return BAD_VALUE;
737 }
738
739 // port definition
740 OMX_PARAM_PORTDEFINITIONTYPE def;
741 InitOMXParams(&def);
742 def.nPortIndex = portIndex;
743 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
744 if (err != OMX_ErrorNone) {
745 OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
746 CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u",
747 asString(index), index, portString(portIndex), portIndex);
748 return UNKNOWN_ERROR;
749 }
750
751 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex);
752
753 OMX_BUFFERHEADERTYPE *header = NULL;
754 OMX_U8* bufferHandle = const_cast<OMX_U8*>(
755 reinterpret_cast<const OMX_U8*>(graphicBuffer->handle));
756
757 err = OMX_UseBuffer(
758 mHandle,
759 &header,
760 portIndex,
761 bufferMeta,
762 def.nBufferSize,
763 bufferHandle);
764
765 if (err != OMX_ErrorNone) {
766 CLOG_ERROR(useBuffer, err, BUFFER_FMT(portIndex, "%u@%p", def.nBufferSize, bufferHandle));
767 delete bufferMeta;
768 bufferMeta = NULL;
769 *buffer = 0;
770 return StatusFromOMXError(err);
771 }
772
773 CHECK_EQ(header->pBuffer, bufferHandle);
774 CHECK_EQ(header->pAppPrivate, bufferMeta);
775
776 *buffer = makeBufferID(header);
777
778 addActiveBuffer(portIndex, *buffer);
779 CLOG_BUFFER(useGraphicBuffer2, NEW_BUFFER_FMT(
780 *buffer, portIndex, "%u@%p", def.nBufferSize, bufferHandle));
781 return OK;
782 }
783
784 // XXX: This function is here for backwards compatibility. Once the OMX
785 // implementations have been updated this can be removed and useGraphicBuffer2
786 // can be renamed to useGraphicBuffer.
useGraphicBuffer(OMX_U32 portIndex,const sp<GraphicBuffer> & graphicBuffer,OMX::buffer_id * buffer)787 status_t OMXNodeInstance::useGraphicBuffer(
788 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
789 OMX::buffer_id *buffer) {
790 if (graphicBuffer == NULL || buffer == NULL) {
791 ALOGE("b/25884056");
792 return BAD_VALUE;
793 }
794 Mutex::Autolock autoLock(mLock);
795
796 // See if the newer version of the extension is present.
797 OMX_INDEXTYPE index;
798 if (OMX_GetExtensionIndex(
799 mHandle,
800 const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"),
801 &index) == OMX_ErrorNone) {
802 return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
803 }
804
805 OMX_STRING name = const_cast<OMX_STRING>(
806 "OMX.google.android.index.useAndroidNativeBuffer");
807 OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
808 if (err != OMX_ErrorNone) {
809 CLOG_ERROR(getExtensionIndex, err, "%s", name);
810 return StatusFromOMXError(err);
811 }
812
813 BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex);
814
815 OMX_BUFFERHEADERTYPE *header;
816
817 OMX_VERSIONTYPE ver;
818 ver.s.nVersionMajor = 1;
819 ver.s.nVersionMinor = 0;
820 ver.s.nRevision = 0;
821 ver.s.nStep = 0;
822 UseAndroidNativeBufferParams params = {
823 sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta,
824 &header, graphicBuffer,
825 };
826
827 err = OMX_SetParameter(mHandle, index, ¶ms);
828
829 if (err != OMX_ErrorNone) {
830 CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u meta=%p GB=%p", name, index,
831 portString(portIndex), portIndex, bufferMeta, graphicBuffer->handle);
832
833 delete bufferMeta;
834 bufferMeta = NULL;
835
836 *buffer = 0;
837
838 return StatusFromOMXError(err);
839 }
840
841 CHECK_EQ(header->pAppPrivate, bufferMeta);
842
843 *buffer = makeBufferID(header);
844
845 addActiveBuffer(portIndex, *buffer);
846 CLOG_BUFFER(useGraphicBuffer, NEW_BUFFER_FMT(
847 *buffer, portIndex, "GB=%p", graphicBuffer->handle));
848 return OK;
849 }
850
updateGraphicBufferInMeta_l(OMX_U32 portIndex,const sp<GraphicBuffer> & graphicBuffer,OMX::buffer_id buffer,OMX_BUFFERHEADERTYPE * header,bool updateCodecBuffer)851 status_t OMXNodeInstance::updateGraphicBufferInMeta_l(
852 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
853 OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header, bool updateCodecBuffer) {
854 // No need to check |graphicBuffer| since NULL is valid for it as below.
855 if (header == NULL) {
856 ALOGE("b/25884056");
857 return BAD_VALUE;
858 }
859
860 if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
861 return BAD_VALUE;
862 }
863
864 BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
865 sp<ABuffer> data = bufferMeta->getBuffer(
866 header, !updateCodecBuffer /* backup */, false /* limit */);
867 bufferMeta->setGraphicBuffer(graphicBuffer);
868 MetadataBufferType metaType = mMetadataType[portIndex];
869 // we use gralloc source only in the codec buffers
870 if (metaType == kMetadataBufferTypeGrallocSource && !updateCodecBuffer) {
871 metaType = kMetadataBufferTypeANWBuffer;
872 }
873 if (metaType == kMetadataBufferTypeGrallocSource
874 && data->capacity() >= sizeof(VideoGrallocMetadata)) {
875 VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(data->data());
876 metadata.eType = kMetadataBufferTypeGrallocSource;
877 metadata.pHandle = graphicBuffer == NULL ? NULL : graphicBuffer->handle;
878 } else if (metaType == kMetadataBufferTypeANWBuffer
879 && data->capacity() >= sizeof(VideoNativeMetadata)) {
880 VideoNativeMetadata &metadata = *(VideoNativeMetadata *)(data->data());
881 metadata.eType = kMetadataBufferTypeANWBuffer;
882 metadata.pBuffer = graphicBuffer == NULL ? NULL : graphicBuffer->getNativeBuffer();
883 metadata.nFenceFd = -1;
884 } else {
885 CLOG_ERROR(updateGraphicBufferInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%u)",
886 portString(portIndex), portIndex, buffer, mMetadataType[portIndex], header->nAllocLen);
887 return BAD_VALUE;
888 }
889
890 CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p",
891 portString(portIndex), portIndex, buffer,
892 graphicBuffer == NULL ? NULL : graphicBuffer->handle);
893 return OK;
894 }
895
updateGraphicBufferInMeta(OMX_U32 portIndex,const sp<GraphicBuffer> & graphicBuffer,OMX::buffer_id buffer)896 status_t OMXNodeInstance::updateGraphicBufferInMeta(
897 OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
898 OMX::buffer_id buffer) {
899 Mutex::Autolock autoLock(mLock);
900 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
901 // update backup buffer for input, codec buffer for output
902 return updateGraphicBufferInMeta_l(
903 portIndex, graphicBuffer, buffer, header,
904 portIndex == kPortIndexOutput /* updateCodecBuffer */);
905 }
906
updateNativeHandleInMeta(OMX_U32 portIndex,const sp<NativeHandle> & nativeHandle,OMX::buffer_id buffer)907 status_t OMXNodeInstance::updateNativeHandleInMeta(
908 OMX_U32 portIndex, const sp<NativeHandle>& nativeHandle, OMX::buffer_id buffer) {
909 Mutex::Autolock autoLock(mLock);
910 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
911 // No need to check |nativeHandle| since NULL is valid for it as below.
912 if (header == NULL) {
913 ALOGE("b/25884056");
914 return BAD_VALUE;
915 }
916
917 if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
918 return BAD_VALUE;
919 }
920
921 BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
922 // update backup buffer for input, codec buffer for output
923 sp<ABuffer> data = bufferMeta->getBuffer(
924 header, portIndex == kPortIndexInput /* backup */, false /* limit */);
925 bufferMeta->setNativeHandle(nativeHandle);
926 if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource
927 && data->capacity() >= sizeof(VideoNativeHandleMetadata)) {
928 VideoNativeHandleMetadata &metadata = *(VideoNativeHandleMetadata *)(data->data());
929 metadata.eType = mMetadataType[portIndex];
930 metadata.pHandle =
931 nativeHandle == NULL ? NULL : const_cast<native_handle*>(nativeHandle->handle());
932 } else {
933 CLOG_ERROR(updateNativeHandleInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%zu)",
934 portString(portIndex), portIndex, buffer, mMetadataType[portIndex], data->capacity());
935 return BAD_VALUE;
936 }
937
938 CLOG_BUFFER(updateNativeHandleInMeta, "%s:%u, %#x := %p",
939 portString(portIndex), portIndex, buffer,
940 nativeHandle == NULL ? NULL : nativeHandle->handle());
941 return OK;
942 }
943
createGraphicBufferSource(OMX_U32 portIndex,sp<IGraphicBufferConsumer> bufferConsumer,MetadataBufferType * type)944 status_t OMXNodeInstance::createGraphicBufferSource(
945 OMX_U32 portIndex, sp<IGraphicBufferConsumer> bufferConsumer, MetadataBufferType *type) {
946 status_t err;
947
948 const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource();
949 if (surfaceCheck != NULL) {
950 if (portIndex < NELEM(mMetadataType) && type != NULL) {
951 *type = mMetadataType[portIndex];
952 }
953 return ALREADY_EXISTS;
954 }
955
956 // Input buffers will hold meta-data (ANativeWindowBuffer references).
957 if (type != NULL) {
958 *type = kMetadataBufferTypeANWBuffer;
959 }
960 err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, type);
961 if (err != OK) {
962 return err;
963 }
964
965 // Retrieve the width and height of the graphic buffer, set when the
966 // codec was configured.
967 OMX_PARAM_PORTDEFINITIONTYPE def;
968 InitOMXParams(&def);
969 def.nPortIndex = portIndex;
970 OMX_ERRORTYPE oerr = OMX_GetParameter(
971 mHandle, OMX_IndexParamPortDefinition, &def);
972 if (oerr != OMX_ErrorNone) {
973 OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
974 CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u",
975 asString(index), index, portString(portIndex), portIndex);
976 return UNKNOWN_ERROR;
977 }
978
979 if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) {
980 CLOGW("createInputSurface requires COLOR_FormatSurface "
981 "(AndroidOpaque) color format instead of %s(%#x)",
982 asString(def.format.video.eColorFormat), def.format.video.eColorFormat);
983 return INVALID_OPERATION;
984 }
985
986 uint32_t usageBits;
987 oerr = OMX_GetParameter(
988 mHandle, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits);
989 if (oerr != OMX_ErrorNone) {
990 usageBits = 0;
991 }
992
993 sp<GraphicBufferSource> bufferSource = new GraphicBufferSource(this,
994 def.format.video.nFrameWidth,
995 def.format.video.nFrameHeight,
996 def.nBufferCountActual,
997 usageBits,
998 bufferConsumer);
999
1000 if ((err = bufferSource->initCheck()) != OK) {
1001 return err;
1002 }
1003 setGraphicBufferSource(bufferSource);
1004
1005 return OK;
1006 }
1007
createInputSurface(OMX_U32 portIndex,android_dataspace dataSpace,sp<IGraphicBufferProducer> * bufferProducer,MetadataBufferType * type)1008 status_t OMXNodeInstance::createInputSurface(
1009 OMX_U32 portIndex, android_dataspace dataSpace,
1010 sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
1011 if (bufferProducer == NULL) {
1012 ALOGE("b/25884056");
1013 return BAD_VALUE;
1014 }
1015
1016 Mutex::Autolock autolock(mLock);
1017 status_t err = createGraphicBufferSource(portIndex, NULL /* bufferConsumer */, type);
1018
1019 if (err != OK) {
1020 return err;
1021 }
1022
1023 mGraphicBufferSource->setDefaultDataSpace(dataSpace);
1024
1025 *bufferProducer = mGraphicBufferSource->getIGraphicBufferProducer();
1026 return OK;
1027 }
1028
1029 //static
createPersistentInputSurface(sp<IGraphicBufferProducer> * bufferProducer,sp<IGraphicBufferConsumer> * bufferConsumer)1030 status_t OMXNodeInstance::createPersistentInputSurface(
1031 sp<IGraphicBufferProducer> *bufferProducer,
1032 sp<IGraphicBufferConsumer> *bufferConsumer) {
1033 if (bufferProducer == NULL || bufferConsumer == NULL) {
1034 ALOGE("b/25884056");
1035 return BAD_VALUE;
1036 }
1037 String8 name("GraphicBufferSource");
1038
1039 sp<IGraphicBufferProducer> producer;
1040 sp<IGraphicBufferConsumer> consumer;
1041 BufferQueue::createBufferQueue(&producer, &consumer);
1042 consumer->setConsumerName(name);
1043 consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
1044
1045 sp<BufferQueue::ProxyConsumerListener> proxy =
1046 new BufferQueue::ProxyConsumerListener(NULL);
1047 status_t err = consumer->consumerConnect(proxy, false);
1048 if (err != NO_ERROR) {
1049 ALOGE("Error connecting to BufferQueue: %s (%d)",
1050 strerror(-err), err);
1051 return err;
1052 }
1053
1054 *bufferProducer = producer;
1055 *bufferConsumer = consumer;
1056
1057 return OK;
1058 }
1059
setInputSurface(OMX_U32 portIndex,const sp<IGraphicBufferConsumer> & bufferConsumer,MetadataBufferType * type)1060 status_t OMXNodeInstance::setInputSurface(
1061 OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer,
1062 MetadataBufferType *type) {
1063 Mutex::Autolock autolock(mLock);
1064 return createGraphicBufferSource(portIndex, bufferConsumer, type);
1065 }
1066
signalEvent(OMX_EVENTTYPE event,OMX_U32 arg1,OMX_U32 arg2)1067 void OMXNodeInstance::signalEvent(OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
1068 mOwner->OnEvent(mNodeID, event, arg1, arg2, NULL);
1069 }
1070
signalEndOfInputStream()1071 status_t OMXNodeInstance::signalEndOfInputStream() {
1072 // For non-Surface input, the MediaCodec should convert the call to a
1073 // pair of requests (dequeue input buffer, queue input buffer with EOS
1074 // flag set). Seems easier than doing the equivalent from here.
1075 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
1076 if (bufferSource == NULL) {
1077 CLOGW("signalEndOfInputStream can only be used with Surface input");
1078 return INVALID_OPERATION;
1079 }
1080 return bufferSource->signalEndOfInputStream();
1081 }
1082
allocateSecureBuffer(OMX_U32 portIndex,size_t size,OMX::buffer_id * buffer,void ** buffer_data,sp<NativeHandle> * native_handle)1083 status_t OMXNodeInstance::allocateSecureBuffer(
1084 OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
1085 void **buffer_data, sp<NativeHandle> *native_handle) {
1086 if (buffer == NULL || buffer_data == NULL || native_handle == NULL) {
1087 ALOGE("b/25884056");
1088 return BAD_VALUE;
1089 }
1090
1091 Mutex::Autolock autoLock(mLock);
1092
1093 BufferMeta *buffer_meta = new BufferMeta(size, portIndex);
1094
1095 OMX_BUFFERHEADERTYPE *header;
1096
1097 OMX_ERRORTYPE err = OMX_AllocateBuffer(
1098 mHandle, &header, portIndex, buffer_meta, size);
1099
1100 if (err != OMX_ErrorNone) {
1101 CLOG_ERROR(allocateBuffer, err, BUFFER_FMT(portIndex, "%zu@", size));
1102 delete buffer_meta;
1103 buffer_meta = NULL;
1104
1105 *buffer = 0;
1106
1107 return StatusFromOMXError(err);
1108 }
1109
1110 CHECK_EQ(header->pAppPrivate, buffer_meta);
1111
1112 *buffer = makeBufferID(header);
1113 if (mSecureBufferType[portIndex] == kSecureBufferTypeNativeHandle) {
1114 *buffer_data = NULL;
1115 *native_handle = NativeHandle::create(
1116 (native_handle_t *)header->pBuffer, false /* ownsHandle */);
1117 } else {
1118 *buffer_data = header->pBuffer;
1119 *native_handle = NULL;
1120 }
1121
1122 addActiveBuffer(portIndex, *buffer);
1123
1124 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
1125 if (bufferSource != NULL && portIndex == kPortIndexInput) {
1126 bufferSource->addCodecBuffer(header);
1127 }
1128 CLOG_BUFFER(allocateSecureBuffer, NEW_BUFFER_FMT(
1129 *buffer, portIndex, "%zu@%p:%p", size, *buffer_data,
1130 *native_handle == NULL ? NULL : (*native_handle)->handle()));
1131
1132 return OK;
1133 }
1134
allocateBufferWithBackup(OMX_U32 portIndex,const sp<IMemory> & params,OMX::buffer_id * buffer,OMX_U32 allottedSize)1135 status_t OMXNodeInstance::allocateBufferWithBackup(
1136 OMX_U32 portIndex, const sp<IMemory> ¶ms,
1137 OMX::buffer_id *buffer, OMX_U32 allottedSize) {
1138 if (params == NULL || buffer == NULL) {
1139 ALOGE("b/25884056");
1140 return BAD_VALUE;
1141 }
1142
1143 Mutex::Autolock autoLock(mLock);
1144 if (allottedSize > params->size()) {
1145 return BAD_VALUE;
1146 }
1147
1148 BufferMeta *buffer_meta = new BufferMeta(params, portIndex, true);
1149
1150 OMX_BUFFERHEADERTYPE *header;
1151
1152 OMX_ERRORTYPE err = OMX_AllocateBuffer(
1153 mHandle, &header, portIndex, buffer_meta, allottedSize);
1154 if (err != OMX_ErrorNone) {
1155 CLOG_ERROR(allocateBufferWithBackup, err,
1156 SIMPLE_BUFFER(portIndex, (size_t)allottedSize, params->pointer()));
1157 delete buffer_meta;
1158 buffer_meta = NULL;
1159
1160 *buffer = 0;
1161
1162 return StatusFromOMXError(err);
1163 }
1164
1165 CHECK_EQ(header->pAppPrivate, buffer_meta);
1166
1167 *buffer = makeBufferID(header);
1168
1169 addActiveBuffer(portIndex, *buffer);
1170
1171 sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
1172 if (bufferSource != NULL && portIndex == kPortIndexInput) {
1173 bufferSource->addCodecBuffer(header);
1174 }
1175
1176 CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p :> %u@%p",
1177 params->size(), params->pointer(), allottedSize, header->pBuffer));
1178
1179 return OK;
1180 }
1181
freeBuffer(OMX_U32 portIndex,OMX::buffer_id buffer)1182 status_t OMXNodeInstance::freeBuffer(
1183 OMX_U32 portIndex, OMX::buffer_id buffer) {
1184 Mutex::Autolock autoLock(mLock);
1185 CLOG_BUFFER(freeBuffer, "%s:%u %#x", portString(portIndex), portIndex, buffer);
1186
1187 removeActiveBuffer(portIndex, buffer);
1188
1189 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
1190 if (header == NULL) {
1191 ALOGE("b/25884056");
1192 return BAD_VALUE;
1193 }
1194 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
1195
1196 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
1197 CLOG_IF_ERROR(freeBuffer, err, "%s:%u %#x", portString(portIndex), portIndex, buffer);
1198
1199 delete buffer_meta;
1200 buffer_meta = NULL;
1201 invalidateBufferID(buffer);
1202
1203 return StatusFromOMXError(err);
1204 }
1205
fillBuffer(OMX::buffer_id buffer,int fenceFd)1206 status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer, int fenceFd) {
1207 Mutex::Autolock autoLock(mLock);
1208
1209 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexOutput);
1210 if (header == NULL) {
1211 ALOGE("b/25884056");
1212 return BAD_VALUE;
1213 }
1214 header->nFilledLen = 0;
1215 header->nOffset = 0;
1216 header->nFlags = 0;
1217
1218 // meta now owns fenceFd
1219 status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexOutput);
1220 if (res != OK) {
1221 CLOG_ERROR(fillBuffer::storeFenceInMeta, res, EMPTY_BUFFER(buffer, header, fenceFd));
1222 return res;
1223 }
1224
1225 {
1226 Mutex::Autolock _l(mDebugLock);
1227 mOutputBuffersWithCodec.add(header);
1228 CLOG_BUMPED_BUFFER(fillBuffer, WITH_STATS(EMPTY_BUFFER(buffer, header, fenceFd)));
1229 }
1230
1231 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
1232 if (err != OMX_ErrorNone) {
1233 CLOG_ERROR(fillBuffer, err, EMPTY_BUFFER(buffer, header, fenceFd));
1234 Mutex::Autolock _l(mDebugLock);
1235 mOutputBuffersWithCodec.remove(header);
1236 }
1237 return StatusFromOMXError(err);
1238 }
1239
emptyBuffer(OMX::buffer_id buffer,OMX_U32 rangeOffset,OMX_U32 rangeLength,OMX_U32 flags,OMX_TICKS timestamp,int fenceFd)1240 status_t OMXNodeInstance::emptyBuffer(
1241 OMX::buffer_id buffer,
1242 OMX_U32 rangeOffset, OMX_U32 rangeLength,
1243 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
1244 Mutex::Autolock autoLock(mLock);
1245
1246 OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
1247 if (header == NULL) {
1248 ALOGE("b/25884056");
1249 return BAD_VALUE;
1250 }
1251 BufferMeta *buffer_meta =
1252 static_cast<BufferMeta *>(header->pAppPrivate);
1253 sp<ABuffer> backup = buffer_meta->getBuffer(header, true /* backup */, false /* limit */);
1254 sp<ABuffer> codec = buffer_meta->getBuffer(header, false /* backup */, false /* limit */);
1255
1256 // convert incoming ANW meta buffers if component is configured for gralloc metadata mode
1257 // ignore rangeOffset in this case
1258 if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource
1259 && backup->capacity() >= sizeof(VideoNativeMetadata)
1260 && codec->capacity() >= sizeof(VideoGrallocMetadata)
1261 && ((VideoNativeMetadata *)backup->base())->eType
1262 == kMetadataBufferTypeANWBuffer) {
1263 VideoNativeMetadata &backupMeta = *(VideoNativeMetadata *)backup->base();
1264 VideoGrallocMetadata &codecMeta = *(VideoGrallocMetadata *)codec->base();
1265 CLOG_BUFFER(emptyBuffer, "converting ANWB %p to handle %p",
1266 backupMeta.pBuffer, backupMeta.pBuffer->handle);
1267 codecMeta.pHandle = backupMeta.pBuffer != NULL ? backupMeta.pBuffer->handle : NULL;
1268 codecMeta.eType = kMetadataBufferTypeGrallocSource;
1269 header->nFilledLen = rangeLength ? sizeof(codecMeta) : 0;
1270 header->nOffset = 0;
1271 } else {
1272 // rangeLength and rangeOffset must be a subset of the allocated data in the buffer.
1273 // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0.
1274 if (rangeOffset > header->nAllocLen
1275 || rangeLength > header->nAllocLen - rangeOffset) {
1276 CLOG_ERROR(emptyBuffer, OMX_ErrorBadParameter, FULL_BUFFER(NULL, header, fenceFd));
1277 if (fenceFd >= 0) {
1278 ::close(fenceFd);
1279 }
1280 return BAD_VALUE;
1281 }
1282 header->nFilledLen = rangeLength;
1283 header->nOffset = rangeOffset;
1284
1285 buffer_meta->CopyToOMX(header);
1286 }
1287
1288 return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer, fenceFd);
1289 }
1290
1291 // log queued buffer activity for the next few input and/or output frames
1292 // if logging at internal state level
bumpDebugLevel_l(size_t numInputBuffers,size_t numOutputBuffers)1293 void OMXNodeInstance::bumpDebugLevel_l(size_t numInputBuffers, size_t numOutputBuffers) {
1294 if (DEBUG == ADebug::kDebugInternalState) {
1295 DEBUG_BUMP = ADebug::kDebugAll;
1296 if (numInputBuffers > 0) {
1297 mDebugLevelBumpPendingBuffers[kPortIndexInput] = numInputBuffers;
1298 }
1299 if (numOutputBuffers > 0) {
1300 mDebugLevelBumpPendingBuffers[kPortIndexOutput] = numOutputBuffers;
1301 }
1302 }
1303 }
1304
unbumpDebugLevel_l(size_t portIndex)1305 void OMXNodeInstance::unbumpDebugLevel_l(size_t portIndex) {
1306 if (mDebugLevelBumpPendingBuffers[portIndex]) {
1307 --mDebugLevelBumpPendingBuffers[portIndex];
1308 }
1309 if (!mDebugLevelBumpPendingBuffers[0]
1310 && !mDebugLevelBumpPendingBuffers[1]) {
1311 DEBUG_BUMP = DEBUG;
1312 }
1313 }
1314
storeFenceInMeta_l(OMX_BUFFERHEADERTYPE * header,int fenceFd,OMX_U32 portIndex)1315 status_t OMXNodeInstance::storeFenceInMeta_l(
1316 OMX_BUFFERHEADERTYPE *header, int fenceFd, OMX_U32 portIndex) {
1317 // propagate fence if component supports it; wait for it otherwise
1318 OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nFilledLen : header->nAllocLen;
1319 if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer
1320 && metaSize >= sizeof(VideoNativeMetadata)) {
1321 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer);
1322 if (nativeMeta.nFenceFd >= 0) {
1323 ALOGE("fence (%d) already exists in meta", nativeMeta.nFenceFd);
1324 if (fenceFd >= 0) {
1325 ::close(fenceFd);
1326 }
1327 return ALREADY_EXISTS;
1328 }
1329 nativeMeta.nFenceFd = fenceFd;
1330 } else if (fenceFd >= 0) {
1331 CLOG_BUFFER(storeFenceInMeta, "waiting for fence %d", fenceFd);
1332 sp<Fence> fence = new Fence(fenceFd);
1333 return fence->wait(IOMX::kFenceTimeoutMs);
1334 }
1335 return OK;
1336 }
1337
retrieveFenceFromMeta_l(OMX_BUFFERHEADERTYPE * header,OMX_U32 portIndex)1338 int OMXNodeInstance::retrieveFenceFromMeta_l(
1339 OMX_BUFFERHEADERTYPE *header, OMX_U32 portIndex) {
1340 OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nAllocLen : header->nFilledLen;
1341 int fenceFd = -1;
1342 if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer
1343 && header->nAllocLen >= sizeof(VideoNativeMetadata)) {
1344 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer);
1345 if (nativeMeta.eType == kMetadataBufferTypeANWBuffer) {
1346 fenceFd = nativeMeta.nFenceFd;
1347 nativeMeta.nFenceFd = -1;
1348 }
1349 if (metaSize < sizeof(nativeMeta) && fenceFd >= 0) {
1350 CLOG_ERROR(foundFenceInEmptyMeta, BAD_VALUE, FULL_BUFFER(
1351 NULL, header, nativeMeta.nFenceFd));
1352 fenceFd = -1;
1353 }
1354 }
1355 return fenceFd;
1356 }
1357
emptyBuffer_l(OMX_BUFFERHEADERTYPE * header,OMX_U32 flags,OMX_TICKS timestamp,intptr_t debugAddr,int fenceFd)1358 status_t OMXNodeInstance::emptyBuffer_l(
1359 OMX_BUFFERHEADERTYPE *header, OMX_U32 flags, OMX_TICKS timestamp,
1360 intptr_t debugAddr, int fenceFd) {
1361 header->nFlags = flags;
1362 header->nTimeStamp = timestamp;
1363
1364 status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexInput);
1365 if (res != OK) {
1366 CLOG_ERROR(emptyBuffer::storeFenceInMeta, res, WITH_STATS(
1367 FULL_BUFFER(debugAddr, header, fenceFd)));
1368 return res;
1369 }
1370
1371 {
1372 Mutex::Autolock _l(mDebugLock);
1373 mInputBuffersWithCodec.add(header);
1374
1375 // bump internal-state debug level for 2 input frames past a buffer with CSD
1376 if ((flags & OMX_BUFFERFLAG_CODECCONFIG) != 0) {
1377 bumpDebugLevel_l(2 /* numInputBuffers */, 0 /* numOutputBuffers */);
1378 }
1379
1380 CLOG_BUMPED_BUFFER(emptyBuffer, WITH_STATS(FULL_BUFFER(debugAddr, header, fenceFd)));
1381 }
1382
1383 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
1384 CLOG_IF_ERROR(emptyBuffer, err, FULL_BUFFER(debugAddr, header, fenceFd));
1385
1386 {
1387 Mutex::Autolock _l(mDebugLock);
1388 if (err != OMX_ErrorNone) {
1389 mInputBuffersWithCodec.remove(header);
1390 } else if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
1391 unbumpDebugLevel_l(kPortIndexInput);
1392 }
1393 }
1394
1395 return StatusFromOMXError(err);
1396 }
1397
1398 // like emptyBuffer, but the data is already in header->pBuffer
emptyGraphicBuffer(OMX_BUFFERHEADERTYPE * header,const sp<GraphicBuffer> & graphicBuffer,OMX_U32 flags,OMX_TICKS timestamp,int fenceFd)1399 status_t OMXNodeInstance::emptyGraphicBuffer(
1400 OMX_BUFFERHEADERTYPE *header, const sp<GraphicBuffer> &graphicBuffer,
1401 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
1402 if (header == NULL) {
1403 ALOGE("b/25884056");
1404 return BAD_VALUE;
1405 }
1406
1407 Mutex::Autolock autoLock(mLock);
1408 OMX::buffer_id buffer = findBufferID(header);
1409 status_t err = updateGraphicBufferInMeta_l(
1410 kPortIndexInput, graphicBuffer, buffer, header,
1411 true /* updateCodecBuffer */);
1412 if (err != OK) {
1413 CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER(
1414 (intptr_t)header->pBuffer, header, fenceFd));
1415 return err;
1416 }
1417
1418 header->nOffset = 0;
1419 if (graphicBuffer == NULL) {
1420 header->nFilledLen = 0;
1421 } else if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource) {
1422 header->nFilledLen = sizeof(VideoGrallocMetadata);
1423 } else {
1424 header->nFilledLen = sizeof(VideoNativeMetadata);
1425 }
1426 return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer, fenceFd);
1427 }
1428
getExtensionIndex(const char * parameterName,OMX_INDEXTYPE * index)1429 status_t OMXNodeInstance::getExtensionIndex(
1430 const char *parameterName, OMX_INDEXTYPE *index) {
1431 Mutex::Autolock autoLock(mLock);
1432
1433 OMX_ERRORTYPE err = OMX_GetExtensionIndex(
1434 mHandle, const_cast<char *>(parameterName), index);
1435
1436 return StatusFromOMXError(err);
1437 }
1438
asString(IOMX::InternalOptionType i,const char * def="??")1439 inline static const char *asString(IOMX::InternalOptionType i, const char *def = "??") {
1440 switch (i) {
1441 case IOMX::INTERNAL_OPTION_SUSPEND: return "SUSPEND";
1442 case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
1443 return "REPEAT_PREVIOUS_FRAME_DELAY";
1444 case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP: return "MAX_TIMESTAMP_GAP";
1445 case IOMX::INTERNAL_OPTION_MAX_FPS: return "MAX_FPS";
1446 case IOMX::INTERNAL_OPTION_START_TIME: return "START_TIME";
1447 case IOMX::INTERNAL_OPTION_TIME_LAPSE: return "TIME_LAPSE";
1448 default: return def;
1449 }
1450 }
1451
1452 template<typename T>
getInternalOption(const void * data,size_t size,T * out)1453 static bool getInternalOption(
1454 const void *data, size_t size, T *out) {
1455 if (size != sizeof(T)) {
1456 return false;
1457 }
1458 *out = *(T*)data;
1459 return true;
1460 }
1461
setInternalOption(OMX_U32 portIndex,IOMX::InternalOptionType type,const void * data,size_t size)1462 status_t OMXNodeInstance::setInternalOption(
1463 OMX_U32 portIndex,
1464 IOMX::InternalOptionType type,
1465 const void *data,
1466 size_t size) {
1467 CLOG_CONFIG(setInternalOption, "%s(%d): %s:%u %zu@%p",
1468 asString(type), type, portString(portIndex), portIndex, size, data);
1469 switch (type) {
1470 case IOMX::INTERNAL_OPTION_SUSPEND:
1471 case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
1472 case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP:
1473 case IOMX::INTERNAL_OPTION_MAX_FPS:
1474 case IOMX::INTERNAL_OPTION_START_TIME:
1475 case IOMX::INTERNAL_OPTION_TIME_LAPSE:
1476 case IOMX::INTERNAL_OPTION_COLOR_ASPECTS:
1477 {
1478 const sp<GraphicBufferSource> &bufferSource =
1479 getGraphicBufferSource();
1480
1481 if (bufferSource == NULL || portIndex != kPortIndexInput) {
1482 CLOGW("setInternalOption is only for Surface input");
1483 return ERROR_UNSUPPORTED;
1484 }
1485
1486 if (type == IOMX::INTERNAL_OPTION_SUSPEND) {
1487 bool suspend;
1488 if (!getInternalOption(data, size, &suspend)) {
1489 return INVALID_OPERATION;
1490 }
1491
1492 CLOG_CONFIG(setInternalOption, "suspend=%d", suspend);
1493 bufferSource->suspend(suspend);
1494 } else if (type == IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY) {
1495 int64_t delayUs;
1496 if (!getInternalOption(data, size, &delayUs)) {
1497 return INVALID_OPERATION;
1498 }
1499
1500 CLOG_CONFIG(setInternalOption, "delayUs=%lld", (long long)delayUs);
1501 return bufferSource->setRepeatPreviousFrameDelayUs(delayUs);
1502 } else if (type == IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP) {
1503 int64_t maxGapUs;
1504 if (!getInternalOption(data, size, &maxGapUs)) {
1505 return INVALID_OPERATION;
1506 }
1507
1508 CLOG_CONFIG(setInternalOption, "gapUs=%lld", (long long)maxGapUs);
1509 return bufferSource->setMaxTimestampGapUs(maxGapUs);
1510 } else if (type == IOMX::INTERNAL_OPTION_MAX_FPS) {
1511 float maxFps;
1512 if (!getInternalOption(data, size, &maxFps)) {
1513 return INVALID_OPERATION;
1514 }
1515
1516 CLOG_CONFIG(setInternalOption, "maxFps=%f", maxFps);
1517 return bufferSource->setMaxFps(maxFps);
1518 } else if (type == IOMX::INTERNAL_OPTION_START_TIME) {
1519 int64_t skipFramesBeforeUs;
1520 if (!getInternalOption(data, size, &skipFramesBeforeUs)) {
1521 return INVALID_OPERATION;
1522 }
1523
1524 CLOG_CONFIG(setInternalOption, "beforeUs=%lld", (long long)skipFramesBeforeUs);
1525 bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs);
1526 } else if (type == IOMX::INTERNAL_OPTION_TIME_LAPSE) {
1527 GraphicBufferSource::TimeLapseConfig config;
1528 if (!getInternalOption(data, size, &config)) {
1529 return INVALID_OPERATION;
1530 }
1531
1532 CLOG_CONFIG(setInternalOption, "perFrameUs=%lld perCaptureUs=%lld",
1533 (long long)config.mTimePerFrameUs, (long long)config.mTimePerCaptureUs);
1534
1535 return bufferSource->setTimeLapseConfig(config);
1536 } else if (type == IOMX::INTERNAL_OPTION_COLOR_ASPECTS) {
1537 ColorAspects aspects;
1538 if (!getInternalOption(data, size, &aspects)) {
1539 return INVALID_OPERATION;
1540 }
1541
1542 CLOG_CONFIG(setInternalOption, "setting color aspects");
1543 bufferSource->setColorAspects(aspects);
1544 }
1545
1546 return OK;
1547 }
1548
1549 default:
1550 return ERROR_UNSUPPORTED;
1551 }
1552 }
1553
handleMessage(omx_message & msg)1554 bool OMXNodeInstance::handleMessage(omx_message &msg) {
1555 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
1556
1557 if (msg.type == omx_message::FILL_BUFFER_DONE) {
1558 OMX_BUFFERHEADERTYPE *buffer =
1559 findBufferHeader(msg.u.extended_buffer_data.buffer, kPortIndexOutput);
1560 if (buffer == NULL) {
1561 ALOGE("b/25884056");
1562 return false;
1563 }
1564
1565 {
1566 Mutex::Autolock _l(mDebugLock);
1567 mOutputBuffersWithCodec.remove(buffer);
1568
1569 CLOG_BUMPED_BUFFER(
1570 FBD, WITH_STATS(FULL_BUFFER(
1571 msg.u.extended_buffer_data.buffer, buffer, msg.fenceFd)));
1572
1573 unbumpDebugLevel_l(kPortIndexOutput);
1574 }
1575
1576 BufferMeta *buffer_meta =
1577 static_cast<BufferMeta *>(buffer->pAppPrivate);
1578
1579 if (buffer->nOffset + buffer->nFilledLen < buffer->nOffset
1580 || buffer->nOffset + buffer->nFilledLen > buffer->nAllocLen) {
1581 CLOG_ERROR(onFillBufferDone, OMX_ErrorBadParameter,
1582 FULL_BUFFER(NULL, buffer, msg.fenceFd));
1583 }
1584 buffer_meta->CopyFromOMX(buffer);
1585
1586 if (bufferSource != NULL) {
1587 // fix up the buffer info (especially timestamp) if needed
1588 bufferSource->codecBufferFilled(buffer);
1589
1590 msg.u.extended_buffer_data.timestamp = buffer->nTimeStamp;
1591 }
1592 } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
1593 OMX_BUFFERHEADERTYPE *buffer =
1594 findBufferHeader(msg.u.buffer_data.buffer, kPortIndexInput);
1595 if (buffer == NULL) {
1596 return false;
1597 }
1598
1599 {
1600 Mutex::Autolock _l(mDebugLock);
1601 mInputBuffersWithCodec.remove(buffer);
1602
1603 CLOG_BUMPED_BUFFER(
1604 EBD, WITH_STATS(EMPTY_BUFFER(msg.u.buffer_data.buffer, buffer, msg.fenceFd)));
1605 }
1606
1607 if (bufferSource != NULL) {
1608 // This is one of the buffers used exclusively by
1609 // GraphicBufferSource.
1610 // Don't dispatch a message back to ACodec, since it doesn't
1611 // know that anyone asked to have the buffer emptied and will
1612 // be very confused.
1613 bufferSource->codecBufferEmptied(buffer, msg.fenceFd);
1614 return true;
1615 }
1616 }
1617
1618 return false;
1619 }
1620
onMessages(std::list<omx_message> & messages)1621 void OMXNodeInstance::onMessages(std::list<omx_message> &messages) {
1622 for (std::list<omx_message>::iterator it = messages.begin(); it != messages.end(); ) {
1623 if (handleMessage(*it)) {
1624 messages.erase(it++);
1625 } else {
1626 ++it;
1627 }
1628 }
1629
1630 if (!messages.empty()) {
1631 mObserver->onMessages(messages);
1632 }
1633 }
1634
onObserverDied(OMXMaster * master)1635 void OMXNodeInstance::onObserverDied(OMXMaster *master) {
1636 ALOGE("!!! Observer died. Quickly, do something, ... anything...");
1637
1638 // Try to force shutdown of the node and hope for the best.
1639 freeNode(master);
1640 }
1641
onGetHandleFailed()1642 void OMXNodeInstance::onGetHandleFailed() {
1643 delete this;
1644 }
1645
1646 // OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
1647 // Don't try to acquire mLock here -- in rare circumstances this will hang.
onEvent(OMX_EVENTTYPE event,OMX_U32 arg1,OMX_U32 arg2)1648 void OMXNodeInstance::onEvent(
1649 OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
1650 const char *arg1String = "??";
1651 const char *arg2String = "??";
1652 ADebug::Level level = ADebug::kDebugInternalState;
1653
1654 switch (event) {
1655 case OMX_EventCmdComplete:
1656 arg1String = asString((OMX_COMMANDTYPE)arg1);
1657 switch (arg1) {
1658 case OMX_CommandStateSet:
1659 arg2String = asString((OMX_STATETYPE)arg2);
1660 level = ADebug::kDebugState;
1661 break;
1662 case OMX_CommandFlush:
1663 case OMX_CommandPortEnable:
1664 {
1665 // bump internal-state debug level for 2 input and output frames
1666 Mutex::Autolock _l(mDebugLock);
1667 bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */);
1668 }
1669 // fall through
1670 default:
1671 arg2String = portString(arg2);
1672 }
1673 break;
1674 case OMX_EventError:
1675 arg1String = asString((OMX_ERRORTYPE)arg1);
1676 level = ADebug::kDebugLifeCycle;
1677 break;
1678 case OMX_EventPortSettingsChanged:
1679 arg2String = asString((OMX_INDEXEXTTYPE)arg2);
1680 // fall through
1681 default:
1682 arg1String = portString(arg1);
1683 }
1684
1685 CLOGI_(level, onEvent, "%s(%x), %s(%x), %s(%x)",
1686 asString(event), event, arg1String, arg1, arg2String, arg2);
1687 const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
1688
1689 if (bufferSource != NULL
1690 && event == OMX_EventCmdComplete
1691 && arg1 == OMX_CommandStateSet
1692 && arg2 == OMX_StateExecuting) {
1693 bufferSource->omxExecuting();
1694 }
1695 }
1696
1697 // static
OnEvent(OMX_IN OMX_HANDLETYPE,OMX_IN OMX_PTR pAppData,OMX_IN OMX_EVENTTYPE eEvent,OMX_IN OMX_U32 nData1,OMX_IN OMX_U32 nData2,OMX_IN OMX_PTR pEventData)1698 OMX_ERRORTYPE OMXNodeInstance::OnEvent(
1699 OMX_IN OMX_HANDLETYPE /* hComponent */,
1700 OMX_IN OMX_PTR pAppData,
1701 OMX_IN OMX_EVENTTYPE eEvent,
1702 OMX_IN OMX_U32 nData1,
1703 OMX_IN OMX_U32 nData2,
1704 OMX_IN OMX_PTR pEventData) {
1705 if (pAppData == NULL) {
1706 ALOGE("b/25884056");
1707 return OMX_ErrorBadParameter;
1708 }
1709 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1710 if (instance->mDying) {
1711 return OMX_ErrorNone;
1712 }
1713 return instance->owner()->OnEvent(
1714 instance->nodeID(), eEvent, nData1, nData2, pEventData);
1715 }
1716
1717 // static
OnEmptyBufferDone(OMX_IN OMX_HANDLETYPE,OMX_IN OMX_PTR pAppData,OMX_IN OMX_BUFFERHEADERTYPE * pBuffer)1718 OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
1719 OMX_IN OMX_HANDLETYPE /* hComponent */,
1720 OMX_IN OMX_PTR pAppData,
1721 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
1722 if (pAppData == NULL) {
1723 ALOGE("b/25884056");
1724 return OMX_ErrorBadParameter;
1725 }
1726 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1727 if (instance->mDying) {
1728 return OMX_ErrorNone;
1729 }
1730 int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);
1731 return instance->owner()->OnEmptyBufferDone(instance->nodeID(),
1732 instance->findBufferID(pBuffer), pBuffer, fenceFd);
1733 }
1734
1735 // static
OnFillBufferDone(OMX_IN OMX_HANDLETYPE,OMX_IN OMX_PTR pAppData,OMX_IN OMX_BUFFERHEADERTYPE * pBuffer)1736 OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
1737 OMX_IN OMX_HANDLETYPE /* hComponent */,
1738 OMX_IN OMX_PTR pAppData,
1739 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
1740 if (pAppData == NULL) {
1741 ALOGE("b/25884056");
1742 return OMX_ErrorBadParameter;
1743 }
1744 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
1745 if (instance->mDying) {
1746 return OMX_ErrorNone;
1747 }
1748 int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);
1749 return instance->owner()->OnFillBufferDone(instance->nodeID(),
1750 instance->findBufferID(pBuffer), pBuffer, fenceFd);
1751 }
1752
addActiveBuffer(OMX_U32 portIndex,OMX::buffer_id id)1753 void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
1754 ActiveBuffer active;
1755 active.mPortIndex = portIndex;
1756 active.mID = id;
1757 mActiveBuffers.push(active);
1758
1759 if (portIndex < NELEM(mNumPortBuffers)) {
1760 ++mNumPortBuffers[portIndex];
1761 }
1762 }
1763
removeActiveBuffer(OMX_U32 portIndex,OMX::buffer_id id)1764 void OMXNodeInstance::removeActiveBuffer(
1765 OMX_U32 portIndex, OMX::buffer_id id) {
1766 for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
1767 if (mActiveBuffers[i].mPortIndex == portIndex
1768 && mActiveBuffers[i].mID == id) {
1769 mActiveBuffers.removeItemsAt(i);
1770
1771 if (portIndex < NELEM(mNumPortBuffers)) {
1772 --mNumPortBuffers[portIndex];
1773 }
1774 return;
1775 }
1776 }
1777
1778 CLOGW("Attempt to remove an active buffer [%#x] we know nothing about...", id);
1779 }
1780
freeActiveBuffers()1781 void OMXNodeInstance::freeActiveBuffers() {
1782 // Make sure to count down here, as freeBuffer will in turn remove
1783 // the active buffer from the vector...
1784 for (size_t i = mActiveBuffers.size(); i > 0;) {
1785 i--;
1786 freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
1787 }
1788 }
1789
makeBufferID(OMX_BUFFERHEADERTYPE * bufferHeader)1790 OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1791 if (bufferHeader == NULL) {
1792 return 0;
1793 }
1794 Mutex::Autolock autoLock(mBufferIDLock);
1795 OMX::buffer_id buffer;
1796 do { // handle the very unlikely case of ID overflow
1797 if (++mBufferIDCount == 0) {
1798 ++mBufferIDCount;
1799 }
1800 buffer = (OMX::buffer_id)mBufferIDCount;
1801 } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0);
1802 mBufferIDToBufferHeader.add(buffer, bufferHeader);
1803 mBufferHeaderToBufferID.add(bufferHeader, buffer);
1804 return buffer;
1805 }
1806
findBufferHeader(OMX::buffer_id buffer,OMX_U32 portIndex)1807 OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(
1808 OMX::buffer_id buffer, OMX_U32 portIndex) {
1809 if (buffer == 0) {
1810 return NULL;
1811 }
1812 Mutex::Autolock autoLock(mBufferIDLock);
1813 ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
1814 if (index < 0) {
1815 CLOGW("findBufferHeader: buffer %u not found", buffer);
1816 return NULL;
1817 }
1818 OMX_BUFFERHEADERTYPE *header = mBufferIDToBufferHeader.valueAt(index);
1819 BufferMeta *buffer_meta =
1820 static_cast<BufferMeta *>(header->pAppPrivate);
1821 if (buffer_meta->getPortIndex() != portIndex) {
1822 CLOGW("findBufferHeader: buffer %u found but with incorrect port index.", buffer);
1823 android_errorWriteLog(0x534e4554, "28816827");
1824 return NULL;
1825 }
1826 return header;
1827 }
1828
findBufferID(OMX_BUFFERHEADERTYPE * bufferHeader)1829 OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
1830 if (bufferHeader == NULL) {
1831 return 0;
1832 }
1833 Mutex::Autolock autoLock(mBufferIDLock);
1834 ssize_t index = mBufferHeaderToBufferID.indexOfKey(bufferHeader);
1835 if (index < 0) {
1836 CLOGW("findBufferID: bufferHeader %p not found", bufferHeader);
1837 return 0;
1838 }
1839 return mBufferHeaderToBufferID.valueAt(index);
1840 }
1841
invalidateBufferID(OMX::buffer_id buffer)1842 void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) {
1843 if (buffer == 0) {
1844 return;
1845 }
1846 Mutex::Autolock autoLock(mBufferIDLock);
1847 ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
1848 if (index < 0) {
1849 CLOGW("invalidateBufferID: buffer %u not found", buffer);
1850 return;
1851 }
1852 mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueAt(index));
1853 mBufferIDToBufferHeader.removeItemsAt(index);
1854 }
1855
1856 } // namespace android
1857