1 /*
2 * Copyright (C) 2010 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 "ACodec"
19
20 #ifdef __LP64__
21 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
22 #endif
23
24 #include <inttypes.h>
25 #include <utils/Trace.h>
26
27 #include <media/stagefright/ACodec.h>
28
29 #include <binder/MemoryDealer.h>
30
31 #include <media/stagefright/foundation/hexdump.h>
32 #include <media/stagefright/foundation/ABuffer.h>
33 #include <media/stagefright/foundation/ADebug.h>
34 #include <media/stagefright/foundation/AMessage.h>
35 #include <media/stagefright/foundation/AUtils.h>
36
37 #include <media/stagefright/BufferProducerWrapper.h>
38 #include <media/stagefright/MediaCodecList.h>
39 #include <media/stagefright/MediaDefs.h>
40 #include <media/stagefright/NativeWindowWrapper.h>
41 #include <media/stagefright/OMXClient.h>
42 #include <media/stagefright/OMXCodec.h>
43
44 #include <media/hardware/HardwareAPI.h>
45
46 #include <OMX_AudioExt.h>
47 #include <OMX_VideoExt.h>
48 #include <OMX_Component.h>
49 #include <OMX_IndexExt.h>
50
51 #include "include/avc_utils.h"
52
53 namespace android {
54
55 // OMX errors are directly mapped into status_t range if
56 // there is no corresponding MediaError status code.
57 // Use the statusFromOMXError(int32_t omxError) function.
58 //
59 // Currently this is a direct map.
60 // See frameworks/native/include/media/openmax/OMX_Core.h
61 //
62 // Vendor OMX errors from 0x90000000 - 0x9000FFFF
63 // Extension OMX errors from 0x8F000000 - 0x90000000
64 // Standard OMX errors from 0x80001000 - 0x80001024 (0x80001024 current)
65 //
66
67 // returns true if err is a recognized OMX error code.
68 // as OMX error is OMX_S32, this is an int32_t type
isOMXError(int32_t err)69 static inline bool isOMXError(int32_t err) {
70 return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX);
71 }
72
73 // converts an OMX error to a status_t
statusFromOMXError(int32_t omxError)74 static inline status_t statusFromOMXError(int32_t omxError) {
75 switch (omxError) {
76 case OMX_ErrorInvalidComponentName:
77 case OMX_ErrorComponentNotFound:
78 return NAME_NOT_FOUND; // can trigger illegal argument error for provided names.
79 default:
80 return isOMXError(omxError) ? omxError : 0; // no translation required
81 }
82 }
83
84 // checks and converts status_t to a non-side-effect status_t
makeNoSideEffectStatus(status_t err)85 static inline status_t makeNoSideEffectStatus(status_t err) {
86 switch (err) {
87 // the following errors have side effects and may come
88 // from other code modules. Remap for safety reasons.
89 case INVALID_OPERATION:
90 case DEAD_OBJECT:
91 return UNKNOWN_ERROR;
92 default:
93 return err;
94 }
95 }
96
97 template<class T>
InitOMXParams(T * params)98 static void InitOMXParams(T *params) {
99 params->nSize = sizeof(T);
100 params->nVersion.s.nVersionMajor = 1;
101 params->nVersion.s.nVersionMinor = 0;
102 params->nVersion.s.nRevision = 0;
103 params->nVersion.s.nStep = 0;
104 }
105
106 struct CodecObserver : public BnOMXObserver {
CodecObserverandroid::CodecObserver107 CodecObserver() {}
108
setNotificationMessageandroid::CodecObserver109 void setNotificationMessage(const sp<AMessage> &msg) {
110 mNotify = msg;
111 }
112
113 // from IOMXObserver
onMessageandroid::CodecObserver114 virtual void onMessage(const omx_message &omx_msg) {
115 sp<AMessage> msg = mNotify->dup();
116
117 msg->setInt32("type", omx_msg.type);
118 msg->setInt32("node", omx_msg.node);
119
120 switch (omx_msg.type) {
121 case omx_message::EVENT:
122 {
123 msg->setInt32("event", omx_msg.u.event_data.event);
124 msg->setInt32("data1", omx_msg.u.event_data.data1);
125 msg->setInt32("data2", omx_msg.u.event_data.data2);
126 break;
127 }
128
129 case omx_message::EMPTY_BUFFER_DONE:
130 {
131 msg->setInt32("buffer", omx_msg.u.buffer_data.buffer);
132 break;
133 }
134
135 case omx_message::FILL_BUFFER_DONE:
136 {
137 msg->setInt32(
138 "buffer", omx_msg.u.extended_buffer_data.buffer);
139 msg->setInt32(
140 "range_offset",
141 omx_msg.u.extended_buffer_data.range_offset);
142 msg->setInt32(
143 "range_length",
144 omx_msg.u.extended_buffer_data.range_length);
145 msg->setInt32(
146 "flags",
147 omx_msg.u.extended_buffer_data.flags);
148 msg->setInt64(
149 "timestamp",
150 omx_msg.u.extended_buffer_data.timestamp);
151 break;
152 }
153
154 default:
155 TRESPASS();
156 break;
157 }
158
159 msg->post();
160 }
161
162 protected:
~CodecObserverandroid::CodecObserver163 virtual ~CodecObserver() {}
164
165 private:
166 sp<AMessage> mNotify;
167
168 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
169 };
170
171 ////////////////////////////////////////////////////////////////////////////////
172
173 struct ACodec::BaseState : public AState {
174 BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
175
176 protected:
177 enum PortMode {
178 KEEP_BUFFERS,
179 RESUBMIT_BUFFERS,
180 FREE_BUFFERS,
181 };
182
183 ACodec *mCodec;
184
185 virtual PortMode getPortMode(OMX_U32 portIndex);
186
187 virtual bool onMessageReceived(const sp<AMessage> &msg);
188
189 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
190
191 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
192 virtual void onInputBufferFilled(const sp<AMessage> &msg);
193
194 void postFillThisBuffer(BufferInfo *info);
195
196 private:
197 bool onOMXMessage(const sp<AMessage> &msg);
198
199 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
200
201 bool onOMXFillBufferDone(
202 IOMX::buffer_id bufferID,
203 size_t rangeOffset, size_t rangeLength,
204 OMX_U32 flags,
205 int64_t timeUs);
206
207 void getMoreInputDataIfPossible();
208
209 DISALLOW_EVIL_CONSTRUCTORS(BaseState);
210 };
211
212 ////////////////////////////////////////////////////////////////////////////////
213
214 struct ACodec::DeathNotifier : public IBinder::DeathRecipient {
DeathNotifierandroid::ACodec::DeathNotifier215 DeathNotifier(const sp<AMessage> ¬ify)
216 : mNotify(notify) {
217 }
218
binderDiedandroid::ACodec::DeathNotifier219 virtual void binderDied(const wp<IBinder> &) {
220 mNotify->post();
221 }
222
223 protected:
~DeathNotifierandroid::ACodec::DeathNotifier224 virtual ~DeathNotifier() {}
225
226 private:
227 sp<AMessage> mNotify;
228
229 DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
230 };
231
232 struct ACodec::UninitializedState : public ACodec::BaseState {
233 UninitializedState(ACodec *codec);
234
235 protected:
236 virtual bool onMessageReceived(const sp<AMessage> &msg);
237 virtual void stateEntered();
238
239 private:
240 void onSetup(const sp<AMessage> &msg);
241 bool onAllocateComponent(const sp<AMessage> &msg);
242
243 sp<DeathNotifier> mDeathNotifier;
244
245 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
246 };
247
248 ////////////////////////////////////////////////////////////////////////////////
249
250 struct ACodec::LoadedState : public ACodec::BaseState {
251 LoadedState(ACodec *codec);
252
253 protected:
254 virtual bool onMessageReceived(const sp<AMessage> &msg);
255 virtual void stateEntered();
256
257 private:
258 friend struct ACodec::UninitializedState;
259
260 bool onConfigureComponent(const sp<AMessage> &msg);
261 void onCreateInputSurface(const sp<AMessage> &msg);
262 void onStart();
263 void onShutdown(bool keepComponentAllocated);
264
265 DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
266 };
267
268 ////////////////////////////////////////////////////////////////////////////////
269
270 struct ACodec::LoadedToIdleState : public ACodec::BaseState {
271 LoadedToIdleState(ACodec *codec);
272
273 protected:
274 virtual bool onMessageReceived(const sp<AMessage> &msg);
275 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
276 virtual void stateEntered();
277
278 private:
279 status_t allocateBuffers();
280
281 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
282 };
283
284 ////////////////////////////////////////////////////////////////////////////////
285
286 struct ACodec::IdleToExecutingState : public ACodec::BaseState {
287 IdleToExecutingState(ACodec *codec);
288
289 protected:
290 virtual bool onMessageReceived(const sp<AMessage> &msg);
291 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
292 virtual void stateEntered();
293
294 private:
295 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
296 };
297
298 ////////////////////////////////////////////////////////////////////////////////
299
300 struct ACodec::ExecutingState : public ACodec::BaseState {
301 ExecutingState(ACodec *codec);
302
303 void submitRegularOutputBuffers();
304 void submitOutputMetaBuffers();
305 void submitOutputBuffers();
306
307 // Submit output buffers to the decoder, submit input buffers to client
308 // to fill with data.
309 void resume();
310
311 // Returns true iff input and output buffers are in play.
activeandroid::ACodec::ExecutingState312 bool active() const { return mActive; }
313
314 protected:
315 virtual PortMode getPortMode(OMX_U32 portIndex);
316 virtual bool onMessageReceived(const sp<AMessage> &msg);
317 virtual void stateEntered();
318
319 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
320
321 private:
322 bool mActive;
323
324 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
325 };
326
327 ////////////////////////////////////////////////////////////////////////////////
328
329 struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
330 OutputPortSettingsChangedState(ACodec *codec);
331
332 protected:
333 virtual PortMode getPortMode(OMX_U32 portIndex);
334 virtual bool onMessageReceived(const sp<AMessage> &msg);
335 virtual void stateEntered();
336
337 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
338
339 private:
340 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
341 };
342
343 ////////////////////////////////////////////////////////////////////////////////
344
345 struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
346 ExecutingToIdleState(ACodec *codec);
347
348 protected:
349 virtual bool onMessageReceived(const sp<AMessage> &msg);
350 virtual void stateEntered();
351
352 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
353
354 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
355 virtual void onInputBufferFilled(const sp<AMessage> &msg);
356
357 private:
358 void changeStateIfWeOwnAllBuffers();
359
360 bool mComponentNowIdle;
361
362 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
363 };
364
365 ////////////////////////////////////////////////////////////////////////////////
366
367 struct ACodec::IdleToLoadedState : public ACodec::BaseState {
368 IdleToLoadedState(ACodec *codec);
369
370 protected:
371 virtual bool onMessageReceived(const sp<AMessage> &msg);
372 virtual void stateEntered();
373
374 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
375
376 private:
377 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
378 };
379
380 ////////////////////////////////////////////////////////////////////////////////
381
382 struct ACodec::FlushingState : public ACodec::BaseState {
383 FlushingState(ACodec *codec);
384
385 protected:
386 virtual bool onMessageReceived(const sp<AMessage> &msg);
387 virtual void stateEntered();
388
389 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
390
391 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
392 virtual void onInputBufferFilled(const sp<AMessage> &msg);
393
394 private:
395 bool mFlushComplete[2];
396
397 void changeStateIfWeOwnAllBuffers();
398
399 DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
400 };
401
402 ////////////////////////////////////////////////////////////////////////////////
403
ACodec()404 ACodec::ACodec()
405 : mQuirks(0),
406 mNode(0),
407 mSentFormat(false),
408 mIsEncoder(false),
409 mUseMetadataOnEncoderOutput(false),
410 mShutdownInProgress(false),
411 mExplicitShutdown(false),
412 mEncoderDelay(0),
413 mEncoderPadding(0),
414 mRotationDegrees(0),
415 mChannelMaskPresent(false),
416 mChannelMask(0),
417 mDequeueCounter(0),
418 mStoreMetaDataInOutputBuffers(false),
419 mMetaDataBuffersToSubmit(0),
420 mRepeatFrameDelayUs(-1ll),
421 mMaxPtsGapUs(-1ll),
422 mTimePerFrameUs(-1ll),
423 mTimePerCaptureUs(-1ll),
424 mCreateInputBuffersSuspended(false),
425 mTunneled(false) {
426 mUninitializedState = new UninitializedState(this);
427 mLoadedState = new LoadedState(this);
428 mLoadedToIdleState = new LoadedToIdleState(this);
429 mIdleToExecutingState = new IdleToExecutingState(this);
430 mExecutingState = new ExecutingState(this);
431
432 mOutputPortSettingsChangedState =
433 new OutputPortSettingsChangedState(this);
434
435 mExecutingToIdleState = new ExecutingToIdleState(this);
436 mIdleToLoadedState = new IdleToLoadedState(this);
437 mFlushingState = new FlushingState(this);
438
439 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
440 mInputEOSResult = OK;
441
442 changeState(mUninitializedState);
443 }
444
~ACodec()445 ACodec::~ACodec() {
446 }
447
setNotificationMessage(const sp<AMessage> & msg)448 void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
449 mNotify = msg;
450 }
451
initiateSetup(const sp<AMessage> & msg)452 void ACodec::initiateSetup(const sp<AMessage> &msg) {
453 msg->setWhat(kWhatSetup);
454 msg->setTarget(id());
455 msg->post();
456 }
457
signalSetParameters(const sp<AMessage> & params)458 void ACodec::signalSetParameters(const sp<AMessage> ¶ms) {
459 sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
460 msg->setMessage("params", params);
461 msg->post();
462 }
463
initiateAllocateComponent(const sp<AMessage> & msg)464 void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
465 msg->setWhat(kWhatAllocateComponent);
466 msg->setTarget(id());
467 msg->post();
468 }
469
initiateConfigureComponent(const sp<AMessage> & msg)470 void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
471 msg->setWhat(kWhatConfigureComponent);
472 msg->setTarget(id());
473 msg->post();
474 }
475
initiateCreateInputSurface()476 void ACodec::initiateCreateInputSurface() {
477 (new AMessage(kWhatCreateInputSurface, id()))->post();
478 }
479
signalEndOfInputStream()480 void ACodec::signalEndOfInputStream() {
481 (new AMessage(kWhatSignalEndOfInputStream, id()))->post();
482 }
483
initiateStart()484 void ACodec::initiateStart() {
485 (new AMessage(kWhatStart, id()))->post();
486 }
487
signalFlush()488 void ACodec::signalFlush() {
489 ALOGV("[%s] signalFlush", mComponentName.c_str());
490 (new AMessage(kWhatFlush, id()))->post();
491 }
492
signalResume()493 void ACodec::signalResume() {
494 (new AMessage(kWhatResume, id()))->post();
495 }
496
initiateShutdown(bool keepComponentAllocated)497 void ACodec::initiateShutdown(bool keepComponentAllocated) {
498 sp<AMessage> msg = new AMessage(kWhatShutdown, id());
499 msg->setInt32("keepComponentAllocated", keepComponentAllocated);
500 msg->post();
501 if (!keepComponentAllocated) {
502 // ensure shutdown completes in 3 seconds
503 (new AMessage(kWhatReleaseCodecInstance, id()))->post(3000000);
504 }
505 }
506
signalRequestIDRFrame()507 void ACodec::signalRequestIDRFrame() {
508 (new AMessage(kWhatRequestIDRFrame, id()))->post();
509 }
510
511 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
512 // Some codecs may return input buffers before having them processed.
513 // This causes a halt if we already signaled an EOS on the input
514 // port. For now keep submitting an output buffer if there was an
515 // EOS on the input port, but not yet on the output port.
signalSubmitOutputMetaDataBufferIfEOS_workaround()516 void ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() {
517 if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
518 mMetaDataBuffersToSubmit > 0) {
519 (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, id()))->post();
520 }
521 }
522
allocateBuffersOnPort(OMX_U32 portIndex)523 status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
524 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
525
526 CHECK(mDealer[portIndex] == NULL);
527 CHECK(mBuffers[portIndex].isEmpty());
528
529 status_t err;
530 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
531 if (mStoreMetaDataInOutputBuffers) {
532 err = allocateOutputMetaDataBuffers();
533 } else {
534 err = allocateOutputBuffersFromNativeWindow();
535 }
536 } else {
537 OMX_PARAM_PORTDEFINITIONTYPE def;
538 InitOMXParams(&def);
539 def.nPortIndex = portIndex;
540
541 err = mOMX->getParameter(
542 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
543
544 if (err == OK) {
545 ALOGV("[%s] Allocating %u buffers of size %u on %s port",
546 mComponentName.c_str(),
547 def.nBufferCountActual, def.nBufferSize,
548 portIndex == kPortIndexInput ? "input" : "output");
549
550 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
551 mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
552
553 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
554 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
555 CHECK(mem.get() != NULL);
556
557 BufferInfo info;
558 info.mStatus = BufferInfo::OWNED_BY_US;
559
560 uint32_t requiresAllocateBufferBit =
561 (portIndex == kPortIndexInput)
562 ? OMXCodec::kRequiresAllocateBufferOnInputPorts
563 : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
564
565 if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
566 || mUseMetadataOnEncoderOutput) {
567 mem.clear();
568
569 void *ptr;
570 err = mOMX->allocateBuffer(
571 mNode, portIndex, def.nBufferSize, &info.mBufferID,
572 &ptr);
573
574 int32_t bufSize = mUseMetadataOnEncoderOutput ?
575 (4 + sizeof(buffer_handle_t)) : def.nBufferSize;
576
577 info.mData = new ABuffer(ptr, bufSize);
578 } else if (mQuirks & requiresAllocateBufferBit) {
579 err = mOMX->allocateBufferWithBackup(
580 mNode, portIndex, mem, &info.mBufferID);
581 } else {
582 err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID);
583 }
584
585 if (mem != NULL) {
586 info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
587 }
588
589 mBuffers[portIndex].push(info);
590 }
591 }
592 }
593
594 if (err != OK) {
595 return err;
596 }
597
598 sp<AMessage> notify = mNotify->dup();
599 notify->setInt32("what", CodecBase::kWhatBuffersAllocated);
600
601 notify->setInt32("portIndex", portIndex);
602
603 sp<PortDescription> desc = new PortDescription;
604
605 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
606 const BufferInfo &info = mBuffers[portIndex][i];
607
608 desc->addBuffer(info.mBufferID, info.mData);
609 }
610
611 notify->setObject("portDesc", desc);
612 notify->post();
613
614 return OK;
615 }
616
configureOutputBuffersFromNativeWindow(OMX_U32 * bufferCount,OMX_U32 * bufferSize,OMX_U32 * minUndequeuedBuffers)617 status_t ACodec::configureOutputBuffersFromNativeWindow(
618 OMX_U32 *bufferCount, OMX_U32 *bufferSize,
619 OMX_U32 *minUndequeuedBuffers) {
620 OMX_PARAM_PORTDEFINITIONTYPE def;
621 InitOMXParams(&def);
622 def.nPortIndex = kPortIndexOutput;
623
624 status_t err = mOMX->getParameter(
625 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
626
627 if (err != OK) {
628 return err;
629 }
630
631 err = native_window_set_buffers_geometry(
632 mNativeWindow.get(),
633 def.format.video.nFrameWidth,
634 def.format.video.nFrameHeight,
635 def.format.video.eColorFormat);
636
637 if (err != 0) {
638 ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
639 strerror(-err), -err);
640 return err;
641 }
642
643 if (mRotationDegrees != 0) {
644 uint32_t transform = 0;
645 switch (mRotationDegrees) {
646 case 0: transform = 0; break;
647 case 90: transform = HAL_TRANSFORM_ROT_90; break;
648 case 180: transform = HAL_TRANSFORM_ROT_180; break;
649 case 270: transform = HAL_TRANSFORM_ROT_270; break;
650 default: transform = 0; break;
651 }
652
653 if (transform > 0) {
654 err = native_window_set_buffers_transform(
655 mNativeWindow.get(), transform);
656 if (err != 0) {
657 ALOGE("native_window_set_buffers_transform failed: %s (%d)",
658 strerror(-err), -err);
659 return err;
660 }
661 }
662 }
663
664 // Set up the native window.
665 OMX_U32 usage = 0;
666 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
667 if (err != 0) {
668 ALOGW("querying usage flags from OMX IL component failed: %d", err);
669 // XXX: Currently this error is logged, but not fatal.
670 usage = 0;
671 }
672 int omxUsage = usage;
673
674 if (mFlags & kFlagIsGrallocUsageProtected) {
675 usage |= GRALLOC_USAGE_PROTECTED;
676 }
677
678 // Make sure to check whether either Stagefright or the video decoder
679 // requested protected buffers.
680 if (usage & GRALLOC_USAGE_PROTECTED) {
681 // Verify that the ANativeWindow sends images directly to
682 // SurfaceFlinger.
683 int queuesToNativeWindow = 0;
684 err = mNativeWindow->query(
685 mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
686 &queuesToNativeWindow);
687 if (err != 0) {
688 ALOGE("error authenticating native window: %d", err);
689 return err;
690 }
691 if (queuesToNativeWindow != 1) {
692 ALOGE("native window could not be authenticated");
693 return PERMISSION_DENIED;
694 }
695 }
696
697 int consumerUsage = 0;
698 err = mNativeWindow->query(
699 mNativeWindow.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS,
700 &consumerUsage);
701 if (err != 0) {
702 ALOGW("failed to get consumer usage bits. ignoring");
703 err = 0;
704 }
705
706 ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec) + %#x(Consumer) = %#x",
707 omxUsage, usage, consumerUsage, usage | consumerUsage);
708 usage |= consumerUsage;
709 err = native_window_set_usage(
710 mNativeWindow.get(),
711 usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
712
713 if (err != 0) {
714 ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
715 return err;
716 }
717
718 // Exits here for tunneled video playback codecs -- i.e. skips native window
719 // buffer allocation step as this is managed by the tunneled OMX omponent
720 // itself and explicitly sets def.nBufferCountActual to 0.
721 if (mTunneled) {
722 ALOGV("Tunneled Playback: skipping native window buffer allocation.");
723 def.nBufferCountActual = 0;
724 err = mOMX->setParameter(
725 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
726
727 *minUndequeuedBuffers = 0;
728 *bufferCount = 0;
729 *bufferSize = 0;
730 return err;
731 }
732
733 *minUndequeuedBuffers = 0;
734 err = mNativeWindow->query(
735 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
736 (int *)minUndequeuedBuffers);
737
738 if (err != 0) {
739 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
740 strerror(-err), -err);
741 return err;
742 }
743
744 // FIXME: assume that surface is controlled by app (native window
745 // returns the number for the case when surface is not controlled by app)
746 // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
747 // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
748
749 // Use conservative allocation while also trying to reduce starvation
750 //
751 // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
752 // minimum needed for the consumer to be able to work
753 // 2. try to allocate two (2) additional buffers to reduce starvation from
754 // the consumer
755 // plus an extra buffer to account for incorrect minUndequeuedBufs
756 for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
757 OMX_U32 newBufferCount =
758 def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
759 def.nBufferCountActual = newBufferCount;
760 err = mOMX->setParameter(
761 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
762
763 if (err == OK) {
764 *minUndequeuedBuffers += extraBuffers;
765 break;
766 }
767
768 ALOGW("[%s] setting nBufferCountActual to %u failed: %d",
769 mComponentName.c_str(), newBufferCount, err);
770 /* exit condition */
771 if (extraBuffers == 0) {
772 return err;
773 }
774 }
775
776 err = native_window_set_buffer_count(
777 mNativeWindow.get(), def.nBufferCountActual);
778
779 if (err != 0) {
780 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
781 -err);
782 return err;
783 }
784
785 *bufferCount = def.nBufferCountActual;
786 *bufferSize = def.nBufferSize;
787 return err;
788 }
789
allocateOutputBuffersFromNativeWindow()790 status_t ACodec::allocateOutputBuffersFromNativeWindow() {
791 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
792 status_t err = configureOutputBuffersFromNativeWindow(
793 &bufferCount, &bufferSize, &minUndequeuedBuffers);
794 if (err != 0)
795 return err;
796 mNumUndequeuedBuffers = minUndequeuedBuffers;
797
798 ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
799 "output port",
800 mComponentName.c_str(), bufferCount, bufferSize);
801
802 // Dequeue buffers and send them to OMX
803 for (OMX_U32 i = 0; i < bufferCount; i++) {
804 ANativeWindowBuffer *buf;
805 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
806 if (err != 0) {
807 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
808 break;
809 }
810
811 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
812 BufferInfo info;
813 info.mStatus = BufferInfo::OWNED_BY_US;
814 info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */);
815 info.mGraphicBuffer = graphicBuffer;
816 mBuffers[kPortIndexOutput].push(info);
817
818 IOMX::buffer_id bufferId;
819 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
820 &bufferId);
821 if (err != 0) {
822 ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
823 "%d", i, err);
824 break;
825 }
826
827 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
828
829 ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
830 mComponentName.c_str(),
831 bufferId, graphicBuffer.get());
832 }
833
834 OMX_U32 cancelStart;
835 OMX_U32 cancelEnd;
836
837 if (err != 0) {
838 // If an error occurred while dequeuing we need to cancel any buffers
839 // that were dequeued.
840 cancelStart = 0;
841 cancelEnd = mBuffers[kPortIndexOutput].size();
842 } else {
843 // Return the required minimum undequeued buffers to the native window.
844 cancelStart = bufferCount - minUndequeuedBuffers;
845 cancelEnd = bufferCount;
846 }
847
848 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
849 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
850 status_t error = cancelBufferToNativeWindow(info);
851 if (err == 0) {
852 err = error;
853 }
854 }
855
856 return err;
857 }
858
allocateOutputMetaDataBuffers()859 status_t ACodec::allocateOutputMetaDataBuffers() {
860 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
861 status_t err = configureOutputBuffersFromNativeWindow(
862 &bufferCount, &bufferSize, &minUndequeuedBuffers);
863 if (err != 0)
864 return err;
865 mNumUndequeuedBuffers = minUndequeuedBuffers;
866
867 ALOGV("[%s] Allocating %u meta buffers on output port",
868 mComponentName.c_str(), bufferCount);
869
870 size_t totalSize = bufferCount * 8;
871 mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec");
872
873 // Dequeue buffers and send them to OMX
874 for (OMX_U32 i = 0; i < bufferCount; i++) {
875 BufferInfo info;
876 info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
877 info.mGraphicBuffer = NULL;
878 info.mDequeuedAt = mDequeueCounter;
879
880 sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(
881 sizeof(struct VideoDecoderOutputMetaData));
882 CHECK(mem.get() != NULL);
883 info.mData = new ABuffer(mem->pointer(), mem->size());
884
885 // we use useBuffer for metadata regardless of quirks
886 err = mOMX->useBuffer(
887 mNode, kPortIndexOutput, mem, &info.mBufferID);
888
889 mBuffers[kPortIndexOutput].push(info);
890
891 ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)",
892 mComponentName.c_str(), info.mBufferID, mem->pointer());
893 }
894
895 mMetaDataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
896 return err;
897 }
898
submitOutputMetaDataBuffer()899 status_t ACodec::submitOutputMetaDataBuffer() {
900 CHECK(mStoreMetaDataInOutputBuffers);
901 if (mMetaDataBuffersToSubmit == 0)
902 return OK;
903
904 BufferInfo *info = dequeueBufferFromNativeWindow();
905 if (info == NULL)
906 return ERROR_IO;
907
908 ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
909 mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get());
910
911 --mMetaDataBuffersToSubmit;
912 CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID),
913 (status_t)OK);
914
915 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
916 return OK;
917 }
918
cancelBufferToNativeWindow(BufferInfo * info)919 status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
920 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
921
922 ALOGV("[%s] Calling cancelBuffer on buffer %u",
923 mComponentName.c_str(), info->mBufferID);
924
925 int err = mNativeWindow->cancelBuffer(
926 mNativeWindow.get(), info->mGraphicBuffer.get(), -1);
927
928 ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window",
929 mComponentName.c_str(), info->mBufferID);
930
931 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
932
933 return err;
934 }
935
dequeueBufferFromNativeWindow()936 ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
937 ANativeWindowBuffer *buf;
938 int fenceFd = -1;
939 CHECK(mNativeWindow.get() != NULL);
940
941 if (mTunneled) {
942 ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel"
943 " video playback mode mode!");
944 return NULL;
945 }
946
947 if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) {
948 ALOGE("dequeueBuffer failed.");
949 return NULL;
950 }
951
952 BufferInfo *oldest = NULL;
953 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
954 BufferInfo *info =
955 &mBuffers[kPortIndexOutput].editItemAt(i);
956
957 if (info->mGraphicBuffer != NULL &&
958 info->mGraphicBuffer->handle == buf->handle) {
959 CHECK_EQ((int)info->mStatus,
960 (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
961
962 info->mStatus = BufferInfo::OWNED_BY_US;
963
964 return info;
965 }
966
967 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
968 (oldest == NULL ||
969 // avoid potential issues from counter rolling over
970 mDequeueCounter - info->mDequeuedAt >
971 mDequeueCounter - oldest->mDequeuedAt)) {
972 oldest = info;
973 }
974 }
975
976 if (oldest) {
977 CHECK(mStoreMetaDataInOutputBuffers);
978
979 // discard buffer in LRU info and replace with new buffer
980 oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
981 oldest->mStatus = BufferInfo::OWNED_BY_US;
982
983 mOMX->updateGraphicBufferInMeta(
984 mNode, kPortIndexOutput, oldest->mGraphicBuffer,
985 oldest->mBufferID);
986
987 VideoDecoderOutputMetaData *metaData =
988 reinterpret_cast<VideoDecoderOutputMetaData *>(
989 oldest->mData->base());
990 CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource);
991
992 ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
993 oldest - &mBuffers[kPortIndexOutput][0],
994 mDequeueCounter - oldest->mDequeuedAt,
995 metaData->pHandle,
996 oldest->mGraphicBuffer->handle, oldest->mData->base());
997
998 return oldest;
999 }
1000
1001 TRESPASS();
1002
1003 return NULL;
1004 }
1005
freeBuffersOnPort(OMX_U32 portIndex)1006 status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
1007 for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
1008 CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
1009 }
1010
1011 mDealer[portIndex].clear();
1012
1013 return OK;
1014 }
1015
freeOutputBuffersNotOwnedByComponent()1016 status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
1017 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
1018 BufferInfo *info =
1019 &mBuffers[kPortIndexOutput].editItemAt(i);
1020
1021 // At this time some buffers may still be with the component
1022 // or being drained.
1023 if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
1024 info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
1025 CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
1026 }
1027 }
1028
1029 return OK;
1030 }
1031
freeBuffer(OMX_U32 portIndex,size_t i)1032 status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
1033 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1034
1035 CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1036 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1037
1038 if (portIndex == kPortIndexOutput && mNativeWindow != NULL
1039 && info->mStatus == BufferInfo::OWNED_BY_US) {
1040 cancelBufferToNativeWindow(info);
1041 }
1042
1043 CHECK_EQ(mOMX->freeBuffer(
1044 mNode, portIndex, info->mBufferID),
1045 (status_t)OK);
1046
1047 mBuffers[portIndex].removeAt(i);
1048
1049 return OK;
1050 }
1051
findBufferByID(uint32_t portIndex,IOMX::buffer_id bufferID,ssize_t * index)1052 ACodec::BufferInfo *ACodec::findBufferByID(
1053 uint32_t portIndex, IOMX::buffer_id bufferID,
1054 ssize_t *index) {
1055 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1056 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1057
1058 if (info->mBufferID == bufferID) {
1059 if (index != NULL) {
1060 *index = i;
1061 }
1062 return info;
1063 }
1064 }
1065
1066 TRESPASS();
1067
1068 return NULL;
1069 }
1070
setComponentRole(bool isEncoder,const char * mime)1071 status_t ACodec::setComponentRole(
1072 bool isEncoder, const char *mime) {
1073 struct MimeToRole {
1074 const char *mime;
1075 const char *decoderRole;
1076 const char *encoderRole;
1077 };
1078
1079 static const MimeToRole kMimeToRole[] = {
1080 { MEDIA_MIMETYPE_AUDIO_MPEG,
1081 "audio_decoder.mp3", "audio_encoder.mp3" },
1082 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
1083 "audio_decoder.mp1", "audio_encoder.mp1" },
1084 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
1085 "audio_decoder.mp2", "audio_encoder.mp2" },
1086 { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1087 "audio_decoder.amrnb", "audio_encoder.amrnb" },
1088 { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1089 "audio_decoder.amrwb", "audio_encoder.amrwb" },
1090 { MEDIA_MIMETYPE_AUDIO_AAC,
1091 "audio_decoder.aac", "audio_encoder.aac" },
1092 { MEDIA_MIMETYPE_AUDIO_VORBIS,
1093 "audio_decoder.vorbis", "audio_encoder.vorbis" },
1094 { MEDIA_MIMETYPE_AUDIO_OPUS,
1095 "audio_decoder.opus", "audio_encoder.opus" },
1096 { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
1097 "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
1098 { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
1099 "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
1100 { MEDIA_MIMETYPE_VIDEO_AVC,
1101 "video_decoder.avc", "video_encoder.avc" },
1102 { MEDIA_MIMETYPE_VIDEO_HEVC,
1103 "video_decoder.hevc", "video_encoder.hevc" },
1104 { MEDIA_MIMETYPE_VIDEO_MPEG4,
1105 "video_decoder.mpeg4", "video_encoder.mpeg4" },
1106 { MEDIA_MIMETYPE_VIDEO_H263,
1107 "video_decoder.h263", "video_encoder.h263" },
1108 { MEDIA_MIMETYPE_VIDEO_VP8,
1109 "video_decoder.vp8", "video_encoder.vp8" },
1110 { MEDIA_MIMETYPE_VIDEO_VP9,
1111 "video_decoder.vp9", "video_encoder.vp9" },
1112 { MEDIA_MIMETYPE_AUDIO_RAW,
1113 "audio_decoder.raw", "audio_encoder.raw" },
1114 { MEDIA_MIMETYPE_AUDIO_FLAC,
1115 "audio_decoder.flac", "audio_encoder.flac" },
1116 { MEDIA_MIMETYPE_AUDIO_MSGSM,
1117 "audio_decoder.gsm", "audio_encoder.gsm" },
1118 { MEDIA_MIMETYPE_VIDEO_MPEG2,
1119 "video_decoder.mpeg2", "video_encoder.mpeg2" },
1120 { MEDIA_MIMETYPE_AUDIO_AC3,
1121 "audio_decoder.ac3", "audio_encoder.ac3" },
1122 { MEDIA_MIMETYPE_AUDIO_EAC3,
1123 "audio_decoder.eac3", "audio_encoder.eac3" },
1124 };
1125
1126 static const size_t kNumMimeToRole =
1127 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1128
1129 size_t i;
1130 for (i = 0; i < kNumMimeToRole; ++i) {
1131 if (!strcasecmp(mime, kMimeToRole[i].mime)) {
1132 break;
1133 }
1134 }
1135
1136 if (i == kNumMimeToRole) {
1137 return ERROR_UNSUPPORTED;
1138 }
1139
1140 const char *role =
1141 isEncoder ? kMimeToRole[i].encoderRole
1142 : kMimeToRole[i].decoderRole;
1143
1144 if (role != NULL) {
1145 OMX_PARAM_COMPONENTROLETYPE roleParams;
1146 InitOMXParams(&roleParams);
1147
1148 strncpy((char *)roleParams.cRole,
1149 role, OMX_MAX_STRINGNAME_SIZE - 1);
1150
1151 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1152
1153 status_t err = mOMX->setParameter(
1154 mNode, OMX_IndexParamStandardComponentRole,
1155 &roleParams, sizeof(roleParams));
1156
1157 if (err != OK) {
1158 ALOGW("[%s] Failed to set standard component role '%s'.",
1159 mComponentName.c_str(), role);
1160
1161 return err;
1162 }
1163 }
1164
1165 return OK;
1166 }
1167
configureCodec(const char * mime,const sp<AMessage> & msg)1168 status_t ACodec::configureCodec(
1169 const char *mime, const sp<AMessage> &msg) {
1170 int32_t encoder;
1171 if (!msg->findInt32("encoder", &encoder)) {
1172 encoder = false;
1173 }
1174
1175 sp<AMessage> inputFormat = new AMessage();
1176 sp<AMessage> outputFormat = mNotify->dup(); // will use this for kWhatOutputFormatChanged
1177
1178 mIsEncoder = encoder;
1179
1180 status_t err = setComponentRole(encoder /* isEncoder */, mime);
1181
1182 if (err != OK) {
1183 return err;
1184 }
1185
1186 int32_t bitRate = 0;
1187 // FLAC encoder doesn't need a bitrate, other encoders do
1188 if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
1189 && !msg->findInt32("bitrate", &bitRate)) {
1190 return INVALID_OPERATION;
1191 }
1192
1193 int32_t storeMeta;
1194 if (encoder
1195 && msg->findInt32("store-metadata-in-buffers", &storeMeta)
1196 && storeMeta != 0) {
1197 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
1198
1199 if (err != OK) {
1200 ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
1201 mComponentName.c_str(), err);
1202
1203 return err;
1204 }
1205 }
1206
1207 int32_t prependSPSPPS = 0;
1208 if (encoder
1209 && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
1210 && prependSPSPPS != 0) {
1211 OMX_INDEXTYPE index;
1212 err = mOMX->getExtensionIndex(
1213 mNode,
1214 "OMX.google.android.index.prependSPSPPSToIDRFrames",
1215 &index);
1216
1217 if (err == OK) {
1218 PrependSPSPPSToIDRFramesParams params;
1219 InitOMXParams(¶ms);
1220 params.bEnable = OMX_TRUE;
1221
1222 err = mOMX->setParameter(
1223 mNode, index, ¶ms, sizeof(params));
1224 }
1225
1226 if (err != OK) {
1227 ALOGE("Encoder could not be configured to emit SPS/PPS before "
1228 "IDR frames. (err %d)", err);
1229
1230 return err;
1231 }
1232 }
1233
1234 // Only enable metadata mode on encoder output if encoder can prepend
1235 // sps/pps to idr frames, since in metadata mode the bitstream is in an
1236 // opaque handle, to which we don't have access.
1237 int32_t video = !strncasecmp(mime, "video/", 6);
1238 if (encoder && video) {
1239 OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
1240 && msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
1241 && storeMeta != 0);
1242
1243 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable);
1244
1245 if (err != OK) {
1246 ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
1247 mComponentName.c_str(), err);
1248 mUseMetadataOnEncoderOutput = 0;
1249 } else {
1250 mUseMetadataOnEncoderOutput = enable;
1251 }
1252
1253 if (!msg->findInt64(
1254 "repeat-previous-frame-after",
1255 &mRepeatFrameDelayUs)) {
1256 mRepeatFrameDelayUs = -1ll;
1257 }
1258
1259 if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
1260 mMaxPtsGapUs = -1ll;
1261 }
1262
1263 if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) {
1264 mTimePerCaptureUs = -1ll;
1265 }
1266
1267 if (!msg->findInt32(
1268 "create-input-buffers-suspended",
1269 (int32_t*)&mCreateInputBuffersSuspended)) {
1270 mCreateInputBuffersSuspended = false;
1271 }
1272 }
1273
1274 // NOTE: we only use native window for video decoders
1275 sp<RefBase> obj;
1276 bool haveNativeWindow = msg->findObject("native-window", &obj)
1277 && obj != NULL && video && !encoder;
1278 mStoreMetaDataInOutputBuffers = false;
1279 if (video && !encoder) {
1280 inputFormat->setInt32("adaptive-playback", false);
1281
1282 int32_t usageProtected;
1283 if (msg->findInt32("protected", &usageProtected) && usageProtected) {
1284 if (!haveNativeWindow) {
1285 ALOGE("protected output buffers must be sent to an ANativeWindow");
1286 return PERMISSION_DENIED;
1287 }
1288 mFlags |= kFlagIsGrallocUsageProtected;
1289 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1290 }
1291 }
1292 if (haveNativeWindow) {
1293 sp<NativeWindowWrapper> windowWrapper(
1294 static_cast<NativeWindowWrapper *>(obj.get()));
1295 sp<ANativeWindow> nativeWindow = windowWrapper->getNativeWindow();
1296
1297 // START of temporary support for automatic FRC - THIS WILL BE REMOVED
1298 int32_t autoFrc;
1299 if (msg->findInt32("auto-frc", &autoFrc)) {
1300 bool enabled = autoFrc;
1301 OMX_CONFIG_BOOLEANTYPE config;
1302 InitOMXParams(&config);
1303 config.bEnabled = (OMX_BOOL)enabled;
1304 status_t temp = mOMX->setConfig(
1305 mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
1306 &config, sizeof(config));
1307 if (temp == OK) {
1308 outputFormat->setInt32("auto-frc", enabled);
1309 } else if (enabled) {
1310 ALOGI("codec does not support requested auto-frc (err %d)", temp);
1311 }
1312 }
1313 // END of temporary support for automatic FRC
1314
1315 int32_t tunneled;
1316 if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
1317 tunneled != 0) {
1318 ALOGI("Configuring TUNNELED video playback.");
1319 mTunneled = true;
1320
1321 int32_t audioHwSync = 0;
1322 if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
1323 ALOGW("No Audio HW Sync provided for video tunnel");
1324 }
1325 err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
1326 if (err != OK) {
1327 ALOGE("configureTunneledVideoPlayback(%d,%p) failed!",
1328 audioHwSync, nativeWindow.get());
1329 return err;
1330 }
1331
1332 int32_t maxWidth = 0, maxHeight = 0;
1333 if (msg->findInt32("max-width", &maxWidth) &&
1334 msg->findInt32("max-height", &maxHeight)) {
1335
1336 err = mOMX->prepareForAdaptivePlayback(
1337 mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1338 if (err != OK) {
1339 ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
1340 mComponentName.c_str(), err);
1341 // allow failure
1342 err = OK;
1343 } else {
1344 inputFormat->setInt32("max-width", maxWidth);
1345 inputFormat->setInt32("max-height", maxHeight);
1346 inputFormat->setInt32("adaptive-playback", true);
1347 }
1348 }
1349 } else {
1350 ALOGV("Configuring CPU controlled video playback.");
1351 mTunneled = false;
1352
1353 // Explicity reset the sideband handle of the window for
1354 // non-tunneled video in case the window was previously used
1355 // for a tunneled video playback.
1356 err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
1357 if (err != OK) {
1358 ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
1359 return err;
1360 }
1361
1362 // Always try to enable dynamic output buffers on native surface
1363 err = mOMX->storeMetaDataInBuffers(
1364 mNode, kPortIndexOutput, OMX_TRUE);
1365 if (err != OK) {
1366 ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
1367 mComponentName.c_str(), err);
1368
1369 // if adaptive playback has been requested, try JB fallback
1370 // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
1371 // LARGE MEMORY REQUIREMENT
1372
1373 // we will not do adaptive playback on software accessed
1374 // surfaces as they never had to respond to changes in the
1375 // crop window, and we don't trust that they will be able to.
1376 int usageBits = 0;
1377 bool canDoAdaptivePlayback;
1378
1379 if (nativeWindow->query(
1380 nativeWindow.get(),
1381 NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1382 &usageBits) != OK) {
1383 canDoAdaptivePlayback = false;
1384 } else {
1385 canDoAdaptivePlayback =
1386 (usageBits &
1387 (GRALLOC_USAGE_SW_READ_MASK |
1388 GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
1389 }
1390
1391 int32_t maxWidth = 0, maxHeight = 0;
1392 if (canDoAdaptivePlayback &&
1393 msg->findInt32("max-width", &maxWidth) &&
1394 msg->findInt32("max-height", &maxHeight)) {
1395 ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
1396 mComponentName.c_str(), maxWidth, maxHeight);
1397
1398 err = mOMX->prepareForAdaptivePlayback(
1399 mNode, kPortIndexOutput, OMX_TRUE, maxWidth,
1400 maxHeight);
1401 ALOGW_IF(err != OK,
1402 "[%s] prepareForAdaptivePlayback failed w/ err %d",
1403 mComponentName.c_str(), err);
1404
1405 if (err == OK) {
1406 inputFormat->setInt32("max-width", maxWidth);
1407 inputFormat->setInt32("max-height", maxHeight);
1408 inputFormat->setInt32("adaptive-playback", true);
1409 }
1410 }
1411 // allow failure
1412 err = OK;
1413 } else {
1414 ALOGV("[%s] storeMetaDataInBuffers succeeded",
1415 mComponentName.c_str());
1416 mStoreMetaDataInOutputBuffers = true;
1417 inputFormat->setInt32("adaptive-playback", true);
1418 }
1419
1420 int32_t push;
1421 if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
1422 && push != 0) {
1423 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1424 }
1425 }
1426
1427 int32_t rotationDegrees;
1428 if (msg->findInt32("rotation-degrees", &rotationDegrees)) {
1429 mRotationDegrees = rotationDegrees;
1430 } else {
1431 mRotationDegrees = 0;
1432 }
1433 }
1434
1435 if (video) {
1436 // determine need for software renderer
1437 bool usingSwRenderer = false;
1438 if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
1439 usingSwRenderer = true;
1440 haveNativeWindow = false;
1441 }
1442
1443 if (encoder) {
1444 err = setupVideoEncoder(mime, msg);
1445 } else {
1446 err = setupVideoDecoder(mime, msg, haveNativeWindow);
1447 }
1448
1449 if (err != OK) {
1450 return err;
1451 }
1452
1453 if (haveNativeWindow) {
1454 sp<NativeWindowWrapper> nativeWindow(
1455 static_cast<NativeWindowWrapper *>(obj.get()));
1456 CHECK(nativeWindow != NULL);
1457 mNativeWindow = nativeWindow->getNativeWindow();
1458
1459 native_window_set_scaling_mode(
1460 mNativeWindow.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
1461 }
1462
1463 // initialize native window now to get actual output format
1464 // TODO: this is needed for some encoders even though they don't use native window
1465 CHECK_EQ((status_t)OK, initNativeWindow());
1466
1467 // fallback for devices that do not handle flex-YUV for native buffers
1468 if (haveNativeWindow) {
1469 int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
1470 if (msg->findInt32("color-format", &requestedColorFormat) &&
1471 requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
1472 CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
1473 int32_t colorFormat = OMX_COLOR_FormatUnused;
1474 OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
1475 CHECK(outputFormat->findInt32("color-format", &colorFormat));
1476 ALOGD("[%s] Requested output format %#x and got %#x.",
1477 mComponentName.c_str(), requestedColorFormat, colorFormat);
1478 if (!isFlexibleColorFormat(
1479 mOMX, mNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
1480 || flexibleEquivalent != (OMX_U32)requestedColorFormat) {
1481 // device did not handle flex-YUV request for native window, fall back
1482 // to SW renderer
1483 ALOGI("[%s] Falling back to software renderer", mComponentName.c_str());
1484 mNativeWindow.clear();
1485 haveNativeWindow = false;
1486 usingSwRenderer = true;
1487 if (mStoreMetaDataInOutputBuffers) {
1488 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_FALSE);
1489 mStoreMetaDataInOutputBuffers = false;
1490 // TODO: implement adaptive-playback support for bytebuffer mode.
1491 // This is done by SW codecs, but most HW codecs don't support it.
1492 inputFormat->setInt32("adaptive-playback", false);
1493 }
1494 if (err == OK) {
1495 err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
1496 }
1497 if (mFlags & kFlagIsGrallocUsageProtected) {
1498 // fallback is not supported for protected playback
1499 err = PERMISSION_DENIED;
1500 } else if (err == OK) {
1501 err = setupVideoDecoder(mime, msg, false);
1502 }
1503 }
1504 }
1505 }
1506
1507 if (usingSwRenderer) {
1508 outputFormat->setInt32("using-sw-renderer", 1);
1509 }
1510 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
1511 int32_t numChannels, sampleRate;
1512 if (!msg->findInt32("channel-count", &numChannels)
1513 || !msg->findInt32("sample-rate", &sampleRate)) {
1514 // Since we did not always check for these, leave them optional
1515 // and have the decoder figure it all out.
1516 err = OK;
1517 } else {
1518 err = setupRawAudioFormat(
1519 encoder ? kPortIndexInput : kPortIndexOutput,
1520 sampleRate,
1521 numChannels);
1522 }
1523 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1524 int32_t numChannels, sampleRate;
1525 if (!msg->findInt32("channel-count", &numChannels)
1526 || !msg->findInt32("sample-rate", &sampleRate)) {
1527 err = INVALID_OPERATION;
1528 } else {
1529 int32_t isADTS, aacProfile;
1530 int32_t sbrMode;
1531 int32_t maxOutputChannelCount;
1532 int32_t pcmLimiterEnable;
1533 drcParams_t drc;
1534 if (!msg->findInt32("is-adts", &isADTS)) {
1535 isADTS = 0;
1536 }
1537 if (!msg->findInt32("aac-profile", &aacProfile)) {
1538 aacProfile = OMX_AUDIO_AACObjectNull;
1539 }
1540 if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
1541 sbrMode = -1;
1542 }
1543
1544 if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
1545 maxOutputChannelCount = -1;
1546 }
1547 if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) {
1548 // value is unknown
1549 pcmLimiterEnable = -1;
1550 }
1551 if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
1552 // value is unknown
1553 drc.encodedTargetLevel = -1;
1554 }
1555 if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
1556 // value is unknown
1557 drc.drcCut = -1;
1558 }
1559 if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
1560 // value is unknown
1561 drc.drcBoost = -1;
1562 }
1563 if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
1564 // value is unknown
1565 drc.heavyCompression = -1;
1566 }
1567 if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
1568 // value is unknown
1569 drc.targetRefLevel = -1;
1570 }
1571
1572 err = setupAACCodec(
1573 encoder, numChannels, sampleRate, bitRate, aacProfile,
1574 isADTS != 0, sbrMode, maxOutputChannelCount, drc,
1575 pcmLimiterEnable);
1576 }
1577 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
1578 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
1579 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
1580 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
1581 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
1582 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
1583 // These are PCM-like formats with a fixed sample rate but
1584 // a variable number of channels.
1585
1586 int32_t numChannels;
1587 if (!msg->findInt32("channel-count", &numChannels)) {
1588 err = INVALID_OPERATION;
1589 } else {
1590 err = setupG711Codec(encoder, numChannels);
1591 }
1592 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
1593 int32_t numChannels, sampleRate, compressionLevel = -1;
1594 if (encoder &&
1595 (!msg->findInt32("channel-count", &numChannels)
1596 || !msg->findInt32("sample-rate", &sampleRate))) {
1597 ALOGE("missing channel count or sample rate for FLAC encoder");
1598 err = INVALID_OPERATION;
1599 } else {
1600 if (encoder) {
1601 if (!msg->findInt32(
1602 "complexity", &compressionLevel) &&
1603 !msg->findInt32(
1604 "flac-compression-level", &compressionLevel)) {
1605 compressionLevel = 5; // default FLAC compression level
1606 } else if (compressionLevel < 0) {
1607 ALOGW("compression level %d outside [0..8] range, "
1608 "using 0",
1609 compressionLevel);
1610 compressionLevel = 0;
1611 } else if (compressionLevel > 8) {
1612 ALOGW("compression level %d outside [0..8] range, "
1613 "using 8",
1614 compressionLevel);
1615 compressionLevel = 8;
1616 }
1617 }
1618 err = setupFlacCodec(
1619 encoder, numChannels, sampleRate, compressionLevel);
1620 }
1621 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1622 int32_t numChannels, sampleRate;
1623 if (encoder
1624 || !msg->findInt32("channel-count", &numChannels)
1625 || !msg->findInt32("sample-rate", &sampleRate)) {
1626 err = INVALID_OPERATION;
1627 } else {
1628 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1629 }
1630 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
1631 int32_t numChannels;
1632 int32_t sampleRate;
1633 if (!msg->findInt32("channel-count", &numChannels)
1634 || !msg->findInt32("sample-rate", &sampleRate)) {
1635 err = INVALID_OPERATION;
1636 } else {
1637 err = setupAC3Codec(encoder, numChannels, sampleRate);
1638 }
1639 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
1640 int32_t numChannels;
1641 int32_t sampleRate;
1642 if (!msg->findInt32("channel-count", &numChannels)
1643 || !msg->findInt32("sample-rate", &sampleRate)) {
1644 err = INVALID_OPERATION;
1645 } else {
1646 err = setupEAC3Codec(encoder, numChannels, sampleRate);
1647 }
1648 }
1649
1650 if (err != OK) {
1651 return err;
1652 }
1653
1654 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
1655 mEncoderDelay = 0;
1656 }
1657
1658 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
1659 mEncoderPadding = 0;
1660 }
1661
1662 if (msg->findInt32("channel-mask", &mChannelMask)) {
1663 mChannelMaskPresent = true;
1664 } else {
1665 mChannelMaskPresent = false;
1666 }
1667
1668 int32_t maxInputSize;
1669 if (msg->findInt32("max-input-size", &maxInputSize)) {
1670 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
1671 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
1672 err = setMinBufferSize(kPortIndexInput, 8192); // XXX
1673 }
1674
1675 mBaseOutputFormat = outputFormat;
1676
1677 CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK);
1678 CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
1679 mInputFormat = inputFormat;
1680 mOutputFormat = outputFormat;
1681
1682 return err;
1683 }
1684
setMinBufferSize(OMX_U32 portIndex,size_t size)1685 status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
1686 OMX_PARAM_PORTDEFINITIONTYPE def;
1687 InitOMXParams(&def);
1688 def.nPortIndex = portIndex;
1689
1690 status_t err = mOMX->getParameter(
1691 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1692
1693 if (err != OK) {
1694 return err;
1695 }
1696
1697 if (def.nBufferSize >= size) {
1698 return OK;
1699 }
1700
1701 def.nBufferSize = size;
1702
1703 err = mOMX->setParameter(
1704 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1705
1706 if (err != OK) {
1707 return err;
1708 }
1709
1710 err = mOMX->getParameter(
1711 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1712
1713 if (err != OK) {
1714 return err;
1715 }
1716
1717 CHECK(def.nBufferSize >= size);
1718
1719 return OK;
1720 }
1721
selectAudioPortFormat(OMX_U32 portIndex,OMX_AUDIO_CODINGTYPE desiredFormat)1722 status_t ACodec::selectAudioPortFormat(
1723 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
1724 OMX_AUDIO_PARAM_PORTFORMATTYPE format;
1725 InitOMXParams(&format);
1726
1727 format.nPortIndex = portIndex;
1728 for (OMX_U32 index = 0;; ++index) {
1729 format.nIndex = index;
1730
1731 status_t err = mOMX->getParameter(
1732 mNode, OMX_IndexParamAudioPortFormat,
1733 &format, sizeof(format));
1734
1735 if (err != OK) {
1736 return err;
1737 }
1738
1739 if (format.eEncoding == desiredFormat) {
1740 break;
1741 }
1742 }
1743
1744 return mOMX->setParameter(
1745 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
1746 }
1747
setupAACCodec(bool encoder,int32_t numChannels,int32_t sampleRate,int32_t bitRate,int32_t aacProfile,bool isADTS,int32_t sbrMode,int32_t maxOutputChannelCount,const drcParams_t & drc,int32_t pcmLimiterEnable)1748 status_t ACodec::setupAACCodec(
1749 bool encoder, int32_t numChannels, int32_t sampleRate,
1750 int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
1751 int32_t maxOutputChannelCount, const drcParams_t& drc,
1752 int32_t pcmLimiterEnable) {
1753 if (encoder && isADTS) {
1754 return -EINVAL;
1755 }
1756
1757 status_t err = setupRawAudioFormat(
1758 encoder ? kPortIndexInput : kPortIndexOutput,
1759 sampleRate,
1760 numChannels);
1761
1762 if (err != OK) {
1763 return err;
1764 }
1765
1766 if (encoder) {
1767 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
1768
1769 if (err != OK) {
1770 return err;
1771 }
1772
1773 OMX_PARAM_PORTDEFINITIONTYPE def;
1774 InitOMXParams(&def);
1775 def.nPortIndex = kPortIndexOutput;
1776
1777 err = mOMX->getParameter(
1778 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1779
1780 if (err != OK) {
1781 return err;
1782 }
1783
1784 def.format.audio.bFlagErrorConcealment = OMX_TRUE;
1785 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1786
1787 err = mOMX->setParameter(
1788 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1789
1790 if (err != OK) {
1791 return err;
1792 }
1793
1794 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1795 InitOMXParams(&profile);
1796 profile.nPortIndex = kPortIndexOutput;
1797
1798 err = mOMX->getParameter(
1799 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1800
1801 if (err != OK) {
1802 return err;
1803 }
1804
1805 profile.nChannels = numChannels;
1806
1807 profile.eChannelMode =
1808 (numChannels == 1)
1809 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
1810
1811 profile.nSampleRate = sampleRate;
1812 profile.nBitRate = bitRate;
1813 profile.nAudioBandWidth = 0;
1814 profile.nFrameLength = 0;
1815 profile.nAACtools = OMX_AUDIO_AACToolAll;
1816 profile.nAACERtools = OMX_AUDIO_AACERNone;
1817 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
1818 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1819 switch (sbrMode) {
1820 case 0:
1821 // disable sbr
1822 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
1823 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
1824 break;
1825 case 1:
1826 // enable single-rate sbr
1827 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
1828 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
1829 break;
1830 case 2:
1831 // enable dual-rate sbr
1832 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
1833 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
1834 break;
1835 case -1:
1836 // enable both modes -> the codec will decide which mode should be used
1837 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
1838 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
1839 break;
1840 default:
1841 // unsupported sbr mode
1842 return BAD_VALUE;
1843 }
1844
1845
1846 err = mOMX->setParameter(
1847 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1848
1849 if (err != OK) {
1850 return err;
1851 }
1852
1853 return err;
1854 }
1855
1856 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1857 InitOMXParams(&profile);
1858 profile.nPortIndex = kPortIndexInput;
1859
1860 err = mOMX->getParameter(
1861 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1862
1863 if (err != OK) {
1864 return err;
1865 }
1866
1867 profile.nChannels = numChannels;
1868 profile.nSampleRate = sampleRate;
1869
1870 profile.eAACStreamFormat =
1871 isADTS
1872 ? OMX_AUDIO_AACStreamFormatMP4ADTS
1873 : OMX_AUDIO_AACStreamFormatMP4FF;
1874
1875 OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
1876 presentation.nMaxOutputChannels = maxOutputChannelCount;
1877 presentation.nDrcCut = drc.drcCut;
1878 presentation.nDrcBoost = drc.drcBoost;
1879 presentation.nHeavyCompression = drc.heavyCompression;
1880 presentation.nTargetReferenceLevel = drc.targetRefLevel;
1881 presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
1882 presentation.nPCMLimiterEnable = pcmLimiterEnable;
1883
1884 status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1885 if (res == OK) {
1886 // optional parameters, will not cause configuration failure
1887 mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
1888 &presentation, sizeof(presentation));
1889 } else {
1890 ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
1891 }
1892 return res;
1893 }
1894
setupAC3Codec(bool encoder,int32_t numChannels,int32_t sampleRate)1895 status_t ACodec::setupAC3Codec(
1896 bool encoder, int32_t numChannels, int32_t sampleRate) {
1897 status_t err = setupRawAudioFormat(
1898 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
1899
1900 if (err != OK) {
1901 return err;
1902 }
1903
1904 if (encoder) {
1905 ALOGW("AC3 encoding is not supported.");
1906 return INVALID_OPERATION;
1907 }
1908
1909 OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
1910 InitOMXParams(&def);
1911 def.nPortIndex = kPortIndexInput;
1912
1913 err = mOMX->getParameter(
1914 mNode,
1915 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1916 &def,
1917 sizeof(def));
1918
1919 if (err != OK) {
1920 return err;
1921 }
1922
1923 def.nChannels = numChannels;
1924 def.nSampleRate = sampleRate;
1925
1926 return mOMX->setParameter(
1927 mNode,
1928 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1929 &def,
1930 sizeof(def));
1931 }
1932
setupEAC3Codec(bool encoder,int32_t numChannels,int32_t sampleRate)1933 status_t ACodec::setupEAC3Codec(
1934 bool encoder, int32_t numChannels, int32_t sampleRate) {
1935 status_t err = setupRawAudioFormat(
1936 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
1937
1938 if (err != OK) {
1939 return err;
1940 }
1941
1942 if (encoder) {
1943 ALOGW("EAC3 encoding is not supported.");
1944 return INVALID_OPERATION;
1945 }
1946
1947 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
1948 InitOMXParams(&def);
1949 def.nPortIndex = kPortIndexInput;
1950
1951 err = mOMX->getParameter(
1952 mNode,
1953 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
1954 &def,
1955 sizeof(def));
1956
1957 if (err != OK) {
1958 return err;
1959 }
1960
1961 def.nChannels = numChannels;
1962 def.nSampleRate = sampleRate;
1963
1964 return mOMX->setParameter(
1965 mNode,
1966 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
1967 &def,
1968 sizeof(def));
1969 }
1970
pickModeFromBitRate(bool isAMRWB,int32_t bps)1971 static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
1972 bool isAMRWB, int32_t bps) {
1973 if (isAMRWB) {
1974 if (bps <= 6600) {
1975 return OMX_AUDIO_AMRBandModeWB0;
1976 } else if (bps <= 8850) {
1977 return OMX_AUDIO_AMRBandModeWB1;
1978 } else if (bps <= 12650) {
1979 return OMX_AUDIO_AMRBandModeWB2;
1980 } else if (bps <= 14250) {
1981 return OMX_AUDIO_AMRBandModeWB3;
1982 } else if (bps <= 15850) {
1983 return OMX_AUDIO_AMRBandModeWB4;
1984 } else if (bps <= 18250) {
1985 return OMX_AUDIO_AMRBandModeWB5;
1986 } else if (bps <= 19850) {
1987 return OMX_AUDIO_AMRBandModeWB6;
1988 } else if (bps <= 23050) {
1989 return OMX_AUDIO_AMRBandModeWB7;
1990 }
1991
1992 // 23850 bps
1993 return OMX_AUDIO_AMRBandModeWB8;
1994 } else { // AMRNB
1995 if (bps <= 4750) {
1996 return OMX_AUDIO_AMRBandModeNB0;
1997 } else if (bps <= 5150) {
1998 return OMX_AUDIO_AMRBandModeNB1;
1999 } else if (bps <= 5900) {
2000 return OMX_AUDIO_AMRBandModeNB2;
2001 } else if (bps <= 6700) {
2002 return OMX_AUDIO_AMRBandModeNB3;
2003 } else if (bps <= 7400) {
2004 return OMX_AUDIO_AMRBandModeNB4;
2005 } else if (bps <= 7950) {
2006 return OMX_AUDIO_AMRBandModeNB5;
2007 } else if (bps <= 10200) {
2008 return OMX_AUDIO_AMRBandModeNB6;
2009 }
2010
2011 // 12200 bps
2012 return OMX_AUDIO_AMRBandModeNB7;
2013 }
2014 }
2015
setupAMRCodec(bool encoder,bool isWAMR,int32_t bitrate)2016 status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
2017 OMX_AUDIO_PARAM_AMRTYPE def;
2018 InitOMXParams(&def);
2019 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
2020
2021 status_t err =
2022 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2023
2024 if (err != OK) {
2025 return err;
2026 }
2027
2028 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
2029 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
2030
2031 err = mOMX->setParameter(
2032 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2033
2034 if (err != OK) {
2035 return err;
2036 }
2037
2038 return setupRawAudioFormat(
2039 encoder ? kPortIndexInput : kPortIndexOutput,
2040 isWAMR ? 16000 : 8000 /* sampleRate */,
2041 1 /* numChannels */);
2042 }
2043
setupG711Codec(bool encoder,int32_t numChannels)2044 status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
2045 CHECK(!encoder); // XXX TODO
2046
2047 return setupRawAudioFormat(
2048 kPortIndexInput, 8000 /* sampleRate */, numChannels);
2049 }
2050
setupFlacCodec(bool encoder,int32_t numChannels,int32_t sampleRate,int32_t compressionLevel)2051 status_t ACodec::setupFlacCodec(
2052 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
2053
2054 if (encoder) {
2055 OMX_AUDIO_PARAM_FLACTYPE def;
2056 InitOMXParams(&def);
2057 def.nPortIndex = kPortIndexOutput;
2058
2059 // configure compression level
2060 status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
2061 if (err != OK) {
2062 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
2063 return err;
2064 }
2065 def.nCompressionLevel = compressionLevel;
2066 err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
2067 if (err != OK) {
2068 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
2069 return err;
2070 }
2071 }
2072
2073 return setupRawAudioFormat(
2074 encoder ? kPortIndexInput : kPortIndexOutput,
2075 sampleRate,
2076 numChannels);
2077 }
2078
setupRawAudioFormat(OMX_U32 portIndex,int32_t sampleRate,int32_t numChannels)2079 status_t ACodec::setupRawAudioFormat(
2080 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
2081 OMX_PARAM_PORTDEFINITIONTYPE def;
2082 InitOMXParams(&def);
2083 def.nPortIndex = portIndex;
2084
2085 status_t err = mOMX->getParameter(
2086 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2087
2088 if (err != OK) {
2089 return err;
2090 }
2091
2092 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2093
2094 err = mOMX->setParameter(
2095 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2096
2097 if (err != OK) {
2098 return err;
2099 }
2100
2101 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
2102 InitOMXParams(&pcmParams);
2103 pcmParams.nPortIndex = portIndex;
2104
2105 err = mOMX->getParameter(
2106 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2107
2108 if (err != OK) {
2109 return err;
2110 }
2111
2112 pcmParams.nChannels = numChannels;
2113 pcmParams.eNumData = OMX_NumericalDataSigned;
2114 pcmParams.bInterleaved = OMX_TRUE;
2115 pcmParams.nBitPerSample = 16;
2116 pcmParams.nSamplingRate = sampleRate;
2117 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
2118
2119 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
2120 return OMX_ErrorNone;
2121 }
2122
2123 return mOMX->setParameter(
2124 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2125 }
2126
configureTunneledVideoPlayback(int32_t audioHwSync,const sp<ANativeWindow> & nativeWindow)2127 status_t ACodec::configureTunneledVideoPlayback(
2128 int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
2129 native_handle_t* sidebandHandle;
2130
2131 status_t err = mOMX->configureVideoTunnelMode(
2132 mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
2133 if (err != OK) {
2134 ALOGE("configureVideoTunnelMode failed! (err %d).", err);
2135 return err;
2136 }
2137
2138 err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
2139 if (err != OK) {
2140 ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
2141 sidebandHandle, err);
2142 return err;
2143 }
2144
2145 return OK;
2146 }
2147
setVideoPortFormatType(OMX_U32 portIndex,OMX_VIDEO_CODINGTYPE compressionFormat,OMX_COLOR_FORMATTYPE colorFormat,bool usingNativeBuffers)2148 status_t ACodec::setVideoPortFormatType(
2149 OMX_U32 portIndex,
2150 OMX_VIDEO_CODINGTYPE compressionFormat,
2151 OMX_COLOR_FORMATTYPE colorFormat,
2152 bool usingNativeBuffers) {
2153 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
2154 InitOMXParams(&format);
2155 format.nPortIndex = portIndex;
2156 format.nIndex = 0;
2157 bool found = false;
2158
2159 OMX_U32 index = 0;
2160 for (;;) {
2161 format.nIndex = index;
2162 status_t err = mOMX->getParameter(
2163 mNode, OMX_IndexParamVideoPortFormat,
2164 &format, sizeof(format));
2165
2166 if (err != OK) {
2167 return err;
2168 }
2169
2170 // substitute back flexible color format to codec supported format
2171 OMX_U32 flexibleEquivalent;
2172 if (compressionFormat == OMX_VIDEO_CodingUnused
2173 && isFlexibleColorFormat(
2174 mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
2175 && colorFormat == flexibleEquivalent) {
2176 ALOGI("[%s] using color format %#x in place of %#x",
2177 mComponentName.c_str(), format.eColorFormat, colorFormat);
2178 colorFormat = format.eColorFormat;
2179 }
2180
2181 // The following assertion is violated by TI's video decoder.
2182 // CHECK_EQ(format.nIndex, index);
2183
2184 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
2185 if (portIndex == kPortIndexInput
2186 && colorFormat == format.eColorFormat) {
2187 // eCompressionFormat does not seem right.
2188 found = true;
2189 break;
2190 }
2191 if (portIndex == kPortIndexOutput
2192 && compressionFormat == format.eCompressionFormat) {
2193 // eColorFormat does not seem right.
2194 found = true;
2195 break;
2196 }
2197 }
2198
2199 if (format.eCompressionFormat == compressionFormat
2200 && format.eColorFormat == colorFormat) {
2201 found = true;
2202 break;
2203 }
2204
2205 ++index;
2206 }
2207
2208 if (!found) {
2209 return UNKNOWN_ERROR;
2210 }
2211
2212 status_t err = mOMX->setParameter(
2213 mNode, OMX_IndexParamVideoPortFormat,
2214 &format, sizeof(format));
2215
2216 return err;
2217 }
2218
2219 // Set optimal output format. OMX component lists output formats in the order
2220 // of preference, but this got more complicated since the introduction of flexible
2221 // YUV formats. We support a legacy behavior for applications that do not use
2222 // surface output, do not specify an output format, but expect a "usable" standard
2223 // OMX format. SW readable and standard formats must be flex-YUV.
2224 //
2225 // Suggested preference order:
2226 // - optimal format for texture rendering (mediaplayer behavior)
2227 // - optimal SW readable & texture renderable format (flex-YUV support)
2228 // - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
2229 // - legacy "usable" standard formats
2230 //
2231 // For legacy support, we prefer a standard format, but will settle for a SW readable
2232 // flex-YUV format.
setSupportedOutputFormat(bool getLegacyFlexibleFormat)2233 status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
2234 OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
2235 InitOMXParams(&format);
2236 format.nPortIndex = kPortIndexOutput;
2237
2238 InitOMXParams(&legacyFormat);
2239 // this field will change when we find a suitable legacy format
2240 legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
2241
2242 for (OMX_U32 index = 0; ; ++index) {
2243 format.nIndex = index;
2244 status_t err = mOMX->getParameter(
2245 mNode, OMX_IndexParamVideoPortFormat,
2246 &format, sizeof(format));
2247 if (err != OK) {
2248 // no more formats, pick legacy format if found
2249 if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
2250 memcpy(&format, &legacyFormat, sizeof(format));
2251 break;
2252 }
2253 return err;
2254 }
2255 if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
2256 return OMX_ErrorBadParameter;
2257 }
2258 if (!getLegacyFlexibleFormat) {
2259 break;
2260 }
2261 // standard formats that were exposed to users before
2262 if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
2263 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
2264 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
2265 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
2266 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
2267 break;
2268 }
2269 // find best legacy non-standard format
2270 OMX_U32 flexibleEquivalent;
2271 if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
2272 && isFlexibleColorFormat(
2273 mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */,
2274 &flexibleEquivalent)
2275 && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
2276 memcpy(&legacyFormat, &format, sizeof(format));
2277 }
2278 }
2279 return mOMX->setParameter(
2280 mNode, OMX_IndexParamVideoPortFormat,
2281 &format, sizeof(format));
2282 }
2283
2284 static const struct VideoCodingMapEntry {
2285 const char *mMime;
2286 OMX_VIDEO_CODINGTYPE mVideoCodingType;
2287 } kVideoCodingMapEntry[] = {
2288 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
2289 { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
2290 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
2291 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
2292 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
2293 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
2294 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
2295 };
2296
GetVideoCodingTypeFromMime(const char * mime,OMX_VIDEO_CODINGTYPE * codingType)2297 static status_t GetVideoCodingTypeFromMime(
2298 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
2299 for (size_t i = 0;
2300 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2301 ++i) {
2302 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
2303 *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
2304 return OK;
2305 }
2306 }
2307
2308 *codingType = OMX_VIDEO_CodingUnused;
2309
2310 return ERROR_UNSUPPORTED;
2311 }
2312
GetMimeTypeForVideoCoding(OMX_VIDEO_CODINGTYPE codingType,AString * mime)2313 static status_t GetMimeTypeForVideoCoding(
2314 OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
2315 for (size_t i = 0;
2316 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2317 ++i) {
2318 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
2319 *mime = kVideoCodingMapEntry[i].mMime;
2320 return OK;
2321 }
2322 }
2323
2324 mime->clear();
2325
2326 return ERROR_UNSUPPORTED;
2327 }
2328
setupVideoDecoder(const char * mime,const sp<AMessage> & msg,bool haveNativeWindow)2329 status_t ACodec::setupVideoDecoder(
2330 const char *mime, const sp<AMessage> &msg, bool haveNativeWindow) {
2331 int32_t width, height;
2332 if (!msg->findInt32("width", &width)
2333 || !msg->findInt32("height", &height)) {
2334 return INVALID_OPERATION;
2335 }
2336
2337 OMX_VIDEO_CODINGTYPE compressionFormat;
2338 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2339
2340 if (err != OK) {
2341 return err;
2342 }
2343
2344 err = setVideoPortFormatType(
2345 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
2346
2347 if (err != OK) {
2348 return err;
2349 }
2350
2351 int32_t tmp;
2352 if (msg->findInt32("color-format", &tmp)) {
2353 OMX_COLOR_FORMATTYPE colorFormat =
2354 static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2355 err = setVideoPortFormatType(
2356 kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
2357 if (err != OK) {
2358 ALOGW("[%s] does not support color format %d",
2359 mComponentName.c_str(), colorFormat);
2360 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
2361 }
2362 } else {
2363 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
2364 }
2365
2366 if (err != OK) {
2367 return err;
2368 }
2369
2370 int32_t frameRateInt;
2371 float frameRateFloat;
2372 if (!msg->findFloat("frame-rate", &frameRateFloat)) {
2373 if (!msg->findInt32("frame-rate", &frameRateInt)) {
2374 frameRateInt = -1;
2375 }
2376 frameRateFloat = (float)frameRateInt;
2377 }
2378
2379 err = setVideoFormatOnPort(
2380 kPortIndexInput, width, height, compressionFormat, frameRateFloat);
2381
2382 if (err != OK) {
2383 return err;
2384 }
2385
2386 err = setVideoFormatOnPort(
2387 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
2388
2389 if (err != OK) {
2390 return err;
2391 }
2392
2393 return OK;
2394 }
2395
setupVideoEncoder(const char * mime,const sp<AMessage> & msg)2396 status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
2397 int32_t tmp;
2398 if (!msg->findInt32("color-format", &tmp)) {
2399 return INVALID_OPERATION;
2400 }
2401
2402 OMX_COLOR_FORMATTYPE colorFormat =
2403 static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2404
2405 status_t err = setVideoPortFormatType(
2406 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
2407
2408 if (err != OK) {
2409 ALOGE("[%s] does not support color format %d",
2410 mComponentName.c_str(), colorFormat);
2411
2412 return err;
2413 }
2414
2415 /* Input port configuration */
2416
2417 OMX_PARAM_PORTDEFINITIONTYPE def;
2418 InitOMXParams(&def);
2419
2420 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2421
2422 def.nPortIndex = kPortIndexInput;
2423
2424 err = mOMX->getParameter(
2425 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2426
2427 if (err != OK) {
2428 return err;
2429 }
2430
2431 int32_t width, height, bitrate;
2432 if (!msg->findInt32("width", &width)
2433 || !msg->findInt32("height", &height)
2434 || !msg->findInt32("bitrate", &bitrate)) {
2435 return INVALID_OPERATION;
2436 }
2437
2438 video_def->nFrameWidth = width;
2439 video_def->nFrameHeight = height;
2440
2441 int32_t stride;
2442 if (!msg->findInt32("stride", &stride)) {
2443 stride = width;
2444 }
2445
2446 video_def->nStride = stride;
2447
2448 int32_t sliceHeight;
2449 if (!msg->findInt32("slice-height", &sliceHeight)) {
2450 sliceHeight = height;
2451 }
2452
2453 video_def->nSliceHeight = sliceHeight;
2454
2455 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
2456
2457 float frameRate;
2458 if (!msg->findFloat("frame-rate", &frameRate)) {
2459 int32_t tmp;
2460 if (!msg->findInt32("frame-rate", &tmp)) {
2461 return INVALID_OPERATION;
2462 }
2463 frameRate = (float)tmp;
2464 mTimePerFrameUs = (int64_t) (1000000.0f / frameRate);
2465 }
2466
2467 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
2468 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
2469 // this is redundant as it was already set up in setVideoPortFormatType
2470 // FIXME for now skip this only for flexible YUV formats
2471 if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
2472 video_def->eColorFormat = colorFormat;
2473 }
2474
2475 err = mOMX->setParameter(
2476 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2477
2478 if (err != OK) {
2479 ALOGE("[%s] failed to set input port definition parameters.",
2480 mComponentName.c_str());
2481
2482 return err;
2483 }
2484
2485 /* Output port configuration */
2486
2487 OMX_VIDEO_CODINGTYPE compressionFormat;
2488 err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2489
2490 if (err != OK) {
2491 return err;
2492 }
2493
2494 err = setVideoPortFormatType(
2495 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
2496
2497 if (err != OK) {
2498 ALOGE("[%s] does not support compression format %d",
2499 mComponentName.c_str(), compressionFormat);
2500
2501 return err;
2502 }
2503
2504 def.nPortIndex = kPortIndexOutput;
2505
2506 err = mOMX->getParameter(
2507 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2508
2509 if (err != OK) {
2510 return err;
2511 }
2512
2513 video_def->nFrameWidth = width;
2514 video_def->nFrameHeight = height;
2515 video_def->xFramerate = 0;
2516 video_def->nBitrate = bitrate;
2517 video_def->eCompressionFormat = compressionFormat;
2518 video_def->eColorFormat = OMX_COLOR_FormatUnused;
2519
2520 err = mOMX->setParameter(
2521 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2522
2523 if (err != OK) {
2524 ALOGE("[%s] failed to set output port definition parameters.",
2525 mComponentName.c_str());
2526
2527 return err;
2528 }
2529
2530 switch (compressionFormat) {
2531 case OMX_VIDEO_CodingMPEG4:
2532 err = setupMPEG4EncoderParameters(msg);
2533 break;
2534
2535 case OMX_VIDEO_CodingH263:
2536 err = setupH263EncoderParameters(msg);
2537 break;
2538
2539 case OMX_VIDEO_CodingAVC:
2540 err = setupAVCEncoderParameters(msg);
2541 break;
2542
2543 case OMX_VIDEO_CodingHEVC:
2544 err = setupHEVCEncoderParameters(msg);
2545 break;
2546
2547 case OMX_VIDEO_CodingVP8:
2548 case OMX_VIDEO_CodingVP9:
2549 err = setupVPXEncoderParameters(msg);
2550 break;
2551
2552 default:
2553 break;
2554 }
2555
2556 ALOGI("setupVideoEncoder succeeded");
2557
2558 return err;
2559 }
2560
setCyclicIntraMacroblockRefresh(const sp<AMessage> & msg,int32_t mode)2561 status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
2562 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
2563 InitOMXParams(¶ms);
2564 params.nPortIndex = kPortIndexOutput;
2565
2566 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
2567
2568 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
2569 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2570 int32_t mbs;
2571 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
2572 return INVALID_OPERATION;
2573 }
2574 params.nCirMBs = mbs;
2575 }
2576
2577 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
2578 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2579 int32_t mbs;
2580 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
2581 return INVALID_OPERATION;
2582 }
2583 params.nAirMBs = mbs;
2584
2585 int32_t ref;
2586 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
2587 return INVALID_OPERATION;
2588 }
2589 params.nAirRef = ref;
2590 }
2591
2592 status_t err = mOMX->setParameter(
2593 mNode, OMX_IndexParamVideoIntraRefresh,
2594 ¶ms, sizeof(params));
2595 return err;
2596 }
2597
setPFramesSpacing(int32_t iFramesInterval,int32_t frameRate)2598 static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
2599 if (iFramesInterval < 0) {
2600 return 0xFFFFFFFF;
2601 } else if (iFramesInterval == 0) {
2602 return 0;
2603 }
2604 OMX_U32 ret = frameRate * iFramesInterval;
2605 return ret;
2606 }
2607
getBitrateMode(const sp<AMessage> & msg)2608 static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
2609 int32_t tmp;
2610 if (!msg->findInt32("bitrate-mode", &tmp)) {
2611 return OMX_Video_ControlRateVariable;
2612 }
2613
2614 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
2615 }
2616
setupMPEG4EncoderParameters(const sp<AMessage> & msg)2617 status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
2618 int32_t bitrate, iFrameInterval;
2619 if (!msg->findInt32("bitrate", &bitrate)
2620 || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2621 return INVALID_OPERATION;
2622 }
2623
2624 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2625
2626 float frameRate;
2627 if (!msg->findFloat("frame-rate", &frameRate)) {
2628 int32_t tmp;
2629 if (!msg->findInt32("frame-rate", &tmp)) {
2630 return INVALID_OPERATION;
2631 }
2632 frameRate = (float)tmp;
2633 }
2634
2635 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
2636 InitOMXParams(&mpeg4type);
2637 mpeg4type.nPortIndex = kPortIndexOutput;
2638
2639 status_t err = mOMX->getParameter(
2640 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2641
2642 if (err != OK) {
2643 return err;
2644 }
2645
2646 mpeg4type.nSliceHeaderSpacing = 0;
2647 mpeg4type.bSVH = OMX_FALSE;
2648 mpeg4type.bGov = OMX_FALSE;
2649
2650 mpeg4type.nAllowedPictureTypes =
2651 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2652
2653 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2654 if (mpeg4type.nPFrames == 0) {
2655 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2656 }
2657 mpeg4type.nBFrames = 0;
2658 mpeg4type.nIDCVLCThreshold = 0;
2659 mpeg4type.bACPred = OMX_TRUE;
2660 mpeg4type.nMaxPacketSize = 256;
2661 mpeg4type.nTimeIncRes = 1000;
2662 mpeg4type.nHeaderExtension = 0;
2663 mpeg4type.bReversibleVLC = OMX_FALSE;
2664
2665 int32_t profile;
2666 if (msg->findInt32("profile", &profile)) {
2667 int32_t level;
2668 if (!msg->findInt32("level", &level)) {
2669 return INVALID_OPERATION;
2670 }
2671
2672 err = verifySupportForProfileAndLevel(profile, level);
2673
2674 if (err != OK) {
2675 return err;
2676 }
2677
2678 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
2679 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
2680 }
2681
2682 err = mOMX->setParameter(
2683 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2684
2685 if (err != OK) {
2686 return err;
2687 }
2688
2689 err = configureBitrate(bitrate, bitrateMode);
2690
2691 if (err != OK) {
2692 return err;
2693 }
2694
2695 return setupErrorCorrectionParameters();
2696 }
2697
setupH263EncoderParameters(const sp<AMessage> & msg)2698 status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
2699 int32_t bitrate, iFrameInterval;
2700 if (!msg->findInt32("bitrate", &bitrate)
2701 || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2702 return INVALID_OPERATION;
2703 }
2704
2705 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2706
2707 float frameRate;
2708 if (!msg->findFloat("frame-rate", &frameRate)) {
2709 int32_t tmp;
2710 if (!msg->findInt32("frame-rate", &tmp)) {
2711 return INVALID_OPERATION;
2712 }
2713 frameRate = (float)tmp;
2714 }
2715
2716 OMX_VIDEO_PARAM_H263TYPE h263type;
2717 InitOMXParams(&h263type);
2718 h263type.nPortIndex = kPortIndexOutput;
2719
2720 status_t err = mOMX->getParameter(
2721 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2722
2723 if (err != OK) {
2724 return err;
2725 }
2726
2727 h263type.nAllowedPictureTypes =
2728 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2729
2730 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2731 if (h263type.nPFrames == 0) {
2732 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2733 }
2734 h263type.nBFrames = 0;
2735
2736 int32_t profile;
2737 if (msg->findInt32("profile", &profile)) {
2738 int32_t level;
2739 if (!msg->findInt32("level", &level)) {
2740 return INVALID_OPERATION;
2741 }
2742
2743 err = verifySupportForProfileAndLevel(profile, level);
2744
2745 if (err != OK) {
2746 return err;
2747 }
2748
2749 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
2750 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
2751 }
2752
2753 h263type.bPLUSPTYPEAllowed = OMX_FALSE;
2754 h263type.bForceRoundingTypeToZero = OMX_FALSE;
2755 h263type.nPictureHeaderRepetition = 0;
2756 h263type.nGOBHeaderInterval = 0;
2757
2758 err = mOMX->setParameter(
2759 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2760
2761 if (err != OK) {
2762 return err;
2763 }
2764
2765 err = configureBitrate(bitrate, bitrateMode);
2766
2767 if (err != OK) {
2768 return err;
2769 }
2770
2771 return setupErrorCorrectionParameters();
2772 }
2773
2774 // static
getAVCLevelFor(int width,int height,int rate,int bitrate,OMX_VIDEO_AVCPROFILETYPE profile)2775 int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
2776 int width, int height, int rate, int bitrate,
2777 OMX_VIDEO_AVCPROFILETYPE profile) {
2778 // convert bitrate to main/baseline profile kbps equivalent
2779 switch (profile) {
2780 case OMX_VIDEO_AVCProfileHigh10:
2781 bitrate = divUp(bitrate, 3000); break;
2782 case OMX_VIDEO_AVCProfileHigh:
2783 bitrate = divUp(bitrate, 1250); break;
2784 default:
2785 bitrate = divUp(bitrate, 1000); break;
2786 }
2787
2788 // convert size and rate to MBs
2789 width = divUp(width, 16);
2790 height = divUp(height, 16);
2791 int mbs = width * height;
2792 rate *= mbs;
2793 int maxDimension = max(width, height);
2794
2795 static const int limits[][5] = {
2796 /* MBps MB dim bitrate level */
2797 { 1485, 99, 28, 64, OMX_VIDEO_AVCLevel1 },
2798 { 1485, 99, 28, 128, OMX_VIDEO_AVCLevel1b },
2799 { 3000, 396, 56, 192, OMX_VIDEO_AVCLevel11 },
2800 { 6000, 396, 56, 384, OMX_VIDEO_AVCLevel12 },
2801 { 11880, 396, 56, 768, OMX_VIDEO_AVCLevel13 },
2802 { 11880, 396, 56, 2000, OMX_VIDEO_AVCLevel2 },
2803 { 19800, 792, 79, 4000, OMX_VIDEO_AVCLevel21 },
2804 { 20250, 1620, 113, 4000, OMX_VIDEO_AVCLevel22 },
2805 { 40500, 1620, 113, 10000, OMX_VIDEO_AVCLevel3 },
2806 { 108000, 3600, 169, 14000, OMX_VIDEO_AVCLevel31 },
2807 { 216000, 5120, 202, 20000, OMX_VIDEO_AVCLevel32 },
2808 { 245760, 8192, 256, 20000, OMX_VIDEO_AVCLevel4 },
2809 { 245760, 8192, 256, 50000, OMX_VIDEO_AVCLevel41 },
2810 { 522240, 8704, 263, 50000, OMX_VIDEO_AVCLevel42 },
2811 { 589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5 },
2812 { 983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
2813 { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
2814 };
2815
2816 for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
2817 const int (&limit)[5] = limits[i];
2818 if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
2819 && bitrate <= limit[3]) {
2820 return limit[4];
2821 }
2822 }
2823 return 0;
2824 }
2825
setupAVCEncoderParameters(const sp<AMessage> & msg)2826 status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
2827 int32_t bitrate, iFrameInterval;
2828 if (!msg->findInt32("bitrate", &bitrate)
2829 || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2830 return INVALID_OPERATION;
2831 }
2832
2833 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2834
2835 float frameRate;
2836 if (!msg->findFloat("frame-rate", &frameRate)) {
2837 int32_t tmp;
2838 if (!msg->findInt32("frame-rate", &tmp)) {
2839 return INVALID_OPERATION;
2840 }
2841 frameRate = (float)tmp;
2842 }
2843
2844 status_t err = OK;
2845 int32_t intraRefreshMode = 0;
2846 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
2847 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
2848 if (err != OK) {
2849 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
2850 err, intraRefreshMode);
2851 return err;
2852 }
2853 }
2854
2855 OMX_VIDEO_PARAM_AVCTYPE h264type;
2856 InitOMXParams(&h264type);
2857 h264type.nPortIndex = kPortIndexOutput;
2858
2859 err = mOMX->getParameter(
2860 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2861
2862 if (err != OK) {
2863 return err;
2864 }
2865
2866 h264type.nAllowedPictureTypes =
2867 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2868
2869 int32_t profile;
2870 if (msg->findInt32("profile", &profile)) {
2871 int32_t level;
2872 if (!msg->findInt32("level", &level)) {
2873 return INVALID_OPERATION;
2874 }
2875
2876 err = verifySupportForProfileAndLevel(profile, level);
2877
2878 if (err != OK) {
2879 return err;
2880 }
2881
2882 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
2883 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
2884 }
2885
2886 // XXX
2887 if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
2888 ALOGW("Use baseline profile instead of %d for AVC recording",
2889 h264type.eProfile);
2890 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
2891 }
2892
2893 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
2894 h264type.nSliceHeaderSpacing = 0;
2895 h264type.bUseHadamard = OMX_TRUE;
2896 h264type.nRefFrames = 1;
2897 h264type.nBFrames = 0;
2898 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2899 if (h264type.nPFrames == 0) {
2900 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2901 }
2902 h264type.nRefIdx10ActiveMinus1 = 0;
2903 h264type.nRefIdx11ActiveMinus1 = 0;
2904 h264type.bEntropyCodingCABAC = OMX_FALSE;
2905 h264type.bWeightedPPrediction = OMX_FALSE;
2906 h264type.bconstIpred = OMX_FALSE;
2907 h264type.bDirect8x8Inference = OMX_FALSE;
2908 h264type.bDirectSpatialTemporal = OMX_FALSE;
2909 h264type.nCabacInitIdc = 0;
2910 }
2911
2912 if (h264type.nBFrames != 0) {
2913 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
2914 }
2915
2916 h264type.bEnableUEP = OMX_FALSE;
2917 h264type.bEnableFMO = OMX_FALSE;
2918 h264type.bEnableASO = OMX_FALSE;
2919 h264type.bEnableRS = OMX_FALSE;
2920 h264type.bFrameMBsOnly = OMX_TRUE;
2921 h264type.bMBAFF = OMX_FALSE;
2922 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
2923
2924 err = mOMX->setParameter(
2925 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2926
2927 if (err != OK) {
2928 return err;
2929 }
2930
2931 return configureBitrate(bitrate, bitrateMode);
2932 }
2933
setupHEVCEncoderParameters(const sp<AMessage> & msg)2934 status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
2935 int32_t bitrate, iFrameInterval;
2936 if (!msg->findInt32("bitrate", &bitrate)
2937 || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2938 return INVALID_OPERATION;
2939 }
2940
2941 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2942
2943 float frameRate;
2944 if (!msg->findFloat("frame-rate", &frameRate)) {
2945 int32_t tmp;
2946 if (!msg->findInt32("frame-rate", &tmp)) {
2947 return INVALID_OPERATION;
2948 }
2949 frameRate = (float)tmp;
2950 }
2951
2952 OMX_VIDEO_PARAM_HEVCTYPE hevcType;
2953 InitOMXParams(&hevcType);
2954 hevcType.nPortIndex = kPortIndexOutput;
2955
2956 status_t err = OK;
2957 err = mOMX->getParameter(
2958 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2959 if (err != OK) {
2960 return err;
2961 }
2962
2963 int32_t profile;
2964 if (msg->findInt32("profile", &profile)) {
2965 int32_t level;
2966 if (!msg->findInt32("level", &level)) {
2967 return INVALID_OPERATION;
2968 }
2969
2970 err = verifySupportForProfileAndLevel(profile, level);
2971 if (err != OK) {
2972 return err;
2973 }
2974
2975 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
2976 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
2977 }
2978
2979 // TODO: Need OMX structure definition for setting iFrameInterval
2980
2981 err = mOMX->setParameter(
2982 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2983 if (err != OK) {
2984 return err;
2985 }
2986
2987 return configureBitrate(bitrate, bitrateMode);
2988 }
2989
setupVPXEncoderParameters(const sp<AMessage> & msg)2990 status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
2991 int32_t bitrate;
2992 int32_t iFrameInterval = 0;
2993 size_t tsLayers = 0;
2994 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
2995 OMX_VIDEO_VPXTemporalLayerPatternNone;
2996 static const uint32_t kVp8LayerRateAlloction
2997 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
2998 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
2999 {100, 100, 100}, // 1 layer
3000 { 60, 100, 100}, // 2 layers {60%, 40%}
3001 { 40, 60, 100}, // 3 layers {40%, 20%, 40%}
3002 };
3003 if (!msg->findInt32("bitrate", &bitrate)) {
3004 return INVALID_OPERATION;
3005 }
3006 msg->findInt32("i-frame-interval", &iFrameInterval);
3007
3008 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3009
3010 float frameRate;
3011 if (!msg->findFloat("frame-rate", &frameRate)) {
3012 int32_t tmp;
3013 if (!msg->findInt32("frame-rate", &tmp)) {
3014 return INVALID_OPERATION;
3015 }
3016 frameRate = (float)tmp;
3017 }
3018
3019 AString tsSchema;
3020 if (msg->findString("ts-schema", &tsSchema)) {
3021 if (tsSchema == "webrtc.vp8.1-layer") {
3022 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3023 tsLayers = 1;
3024 } else if (tsSchema == "webrtc.vp8.2-layer") {
3025 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3026 tsLayers = 2;
3027 } else if (tsSchema == "webrtc.vp8.3-layer") {
3028 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3029 tsLayers = 3;
3030 } else {
3031 ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
3032 }
3033 }
3034
3035 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3036 InitOMXParams(&vp8type);
3037 vp8type.nPortIndex = kPortIndexOutput;
3038 status_t err = mOMX->getParameter(
3039 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3040 &vp8type, sizeof(vp8type));
3041
3042 if (err == OK) {
3043 if (iFrameInterval > 0) {
3044 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
3045 }
3046 vp8type.eTemporalPattern = pattern;
3047 vp8type.nTemporalLayerCount = tsLayers;
3048 if (tsLayers > 0) {
3049 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
3050 vp8type.nTemporalLayerBitrateRatio[i] =
3051 kVp8LayerRateAlloction[tsLayers - 1][i];
3052 }
3053 }
3054 if (bitrateMode == OMX_Video_ControlRateConstant) {
3055 vp8type.nMinQuantizer = 2;
3056 vp8type.nMaxQuantizer = 63;
3057 }
3058
3059 err = mOMX->setParameter(
3060 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3061 &vp8type, sizeof(vp8type));
3062 if (err != OK) {
3063 ALOGW("Extended VP8 parameters set failed: %d", err);
3064 }
3065 }
3066
3067 return configureBitrate(bitrate, bitrateMode);
3068 }
3069
verifySupportForProfileAndLevel(int32_t profile,int32_t level)3070 status_t ACodec::verifySupportForProfileAndLevel(
3071 int32_t profile, int32_t level) {
3072 OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
3073 InitOMXParams(¶ms);
3074 params.nPortIndex = kPortIndexOutput;
3075
3076 for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
3077 status_t err = mOMX->getParameter(
3078 mNode,
3079 OMX_IndexParamVideoProfileLevelQuerySupported,
3080 ¶ms,
3081 sizeof(params));
3082
3083 if (err != OK) {
3084 return err;
3085 }
3086
3087 int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
3088 int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
3089
3090 if (profile == supportedProfile && level <= supportedLevel) {
3091 return OK;
3092 }
3093 }
3094 }
3095
configureBitrate(int32_t bitrate,OMX_VIDEO_CONTROLRATETYPE bitrateMode)3096 status_t ACodec::configureBitrate(
3097 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
3098 OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
3099 InitOMXParams(&bitrateType);
3100 bitrateType.nPortIndex = kPortIndexOutput;
3101
3102 status_t err = mOMX->getParameter(
3103 mNode, OMX_IndexParamVideoBitrate,
3104 &bitrateType, sizeof(bitrateType));
3105
3106 if (err != OK) {
3107 return err;
3108 }
3109
3110 bitrateType.eControlRate = bitrateMode;
3111 bitrateType.nTargetBitrate = bitrate;
3112
3113 return mOMX->setParameter(
3114 mNode, OMX_IndexParamVideoBitrate,
3115 &bitrateType, sizeof(bitrateType));
3116 }
3117
setupErrorCorrectionParameters()3118 status_t ACodec::setupErrorCorrectionParameters() {
3119 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
3120 InitOMXParams(&errorCorrectionType);
3121 errorCorrectionType.nPortIndex = kPortIndexOutput;
3122
3123 status_t err = mOMX->getParameter(
3124 mNode, OMX_IndexParamVideoErrorCorrection,
3125 &errorCorrectionType, sizeof(errorCorrectionType));
3126
3127 if (err != OK) {
3128 return OK; // Optional feature. Ignore this failure
3129 }
3130
3131 errorCorrectionType.bEnableHEC = OMX_FALSE;
3132 errorCorrectionType.bEnableResync = OMX_TRUE;
3133 errorCorrectionType.nResynchMarkerSpacing = 256;
3134 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
3135 errorCorrectionType.bEnableRVLC = OMX_FALSE;
3136
3137 return mOMX->setParameter(
3138 mNode, OMX_IndexParamVideoErrorCorrection,
3139 &errorCorrectionType, sizeof(errorCorrectionType));
3140 }
3141
setVideoFormatOnPort(OMX_U32 portIndex,int32_t width,int32_t height,OMX_VIDEO_CODINGTYPE compressionFormat,float frameRate)3142 status_t ACodec::setVideoFormatOnPort(
3143 OMX_U32 portIndex,
3144 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
3145 float frameRate) {
3146 OMX_PARAM_PORTDEFINITIONTYPE def;
3147 InitOMXParams(&def);
3148 def.nPortIndex = portIndex;
3149
3150 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3151
3152 status_t err = mOMX->getParameter(
3153 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3154
3155 CHECK_EQ(err, (status_t)OK);
3156
3157 if (portIndex == kPortIndexInput) {
3158 // XXX Need a (much) better heuristic to compute input buffer sizes.
3159 const size_t X = 64 * 1024;
3160 if (def.nBufferSize < X) {
3161 def.nBufferSize = X;
3162 }
3163 }
3164
3165 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
3166
3167 video_def->nFrameWidth = width;
3168 video_def->nFrameHeight = height;
3169
3170 if (portIndex == kPortIndexInput) {
3171 video_def->eCompressionFormat = compressionFormat;
3172 video_def->eColorFormat = OMX_COLOR_FormatUnused;
3173 if (frameRate >= 0) {
3174 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3175 }
3176 }
3177
3178 err = mOMX->setParameter(
3179 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3180
3181 return err;
3182 }
3183
initNativeWindow()3184 status_t ACodec::initNativeWindow() {
3185 if (mNativeWindow != NULL) {
3186 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
3187 }
3188
3189 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
3190 return OK;
3191 }
3192
countBuffersOwnedByComponent(OMX_U32 portIndex) const3193 size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
3194 size_t n = 0;
3195
3196 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3197 const BufferInfo &info = mBuffers[portIndex].itemAt(i);
3198
3199 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
3200 ++n;
3201 }
3202 }
3203
3204 return n;
3205 }
3206
countBuffersOwnedByNativeWindow() const3207 size_t ACodec::countBuffersOwnedByNativeWindow() const {
3208 size_t n = 0;
3209
3210 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
3211 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
3212
3213 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3214 ++n;
3215 }
3216 }
3217
3218 return n;
3219 }
3220
waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs()3221 void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
3222 if (mNativeWindow == NULL) {
3223 return;
3224 }
3225
3226 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
3227 && dequeueBufferFromNativeWindow() != NULL) {
3228 // these buffers will be submitted as regular buffers; account for this
3229 if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
3230 --mMetaDataBuffersToSubmit;
3231 }
3232 }
3233 }
3234
allYourBuffersAreBelongToUs(OMX_U32 portIndex)3235 bool ACodec::allYourBuffersAreBelongToUs(
3236 OMX_U32 portIndex) {
3237 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3238 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
3239
3240 if (info->mStatus != BufferInfo::OWNED_BY_US
3241 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3242 ALOGV("[%s] Buffer %u on port %u still has status %d",
3243 mComponentName.c_str(),
3244 info->mBufferID, portIndex, info->mStatus);
3245 return false;
3246 }
3247 }
3248
3249 return true;
3250 }
3251
allYourBuffersAreBelongToUs()3252 bool ACodec::allYourBuffersAreBelongToUs() {
3253 return allYourBuffersAreBelongToUs(kPortIndexInput)
3254 && allYourBuffersAreBelongToUs(kPortIndexOutput);
3255 }
3256
deferMessage(const sp<AMessage> & msg)3257 void ACodec::deferMessage(const sp<AMessage> &msg) {
3258 bool wasEmptyBefore = mDeferredQueue.empty();
3259 mDeferredQueue.push_back(msg);
3260 }
3261
processDeferredMessages()3262 void ACodec::processDeferredMessages() {
3263 List<sp<AMessage> > queue = mDeferredQueue;
3264 mDeferredQueue.clear();
3265
3266 List<sp<AMessage> >::iterator it = queue.begin();
3267 while (it != queue.end()) {
3268 onMessageReceived(*it++);
3269 }
3270 }
3271
3272 // static
describeDefaultColorFormat(DescribeColorFormatParams & params)3273 bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams ¶ms) {
3274 MediaImage &image = params.sMediaImage;
3275 memset(&image, 0, sizeof(image));
3276
3277 image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3278 image.mNumPlanes = 0;
3279
3280 const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
3281 image.mWidth = params.nFrameWidth;
3282 image.mHeight = params.nFrameHeight;
3283
3284 // only supporting YUV420
3285 if (fmt != OMX_COLOR_FormatYUV420Planar &&
3286 fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
3287 fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
3288 fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
3289 fmt != HAL_PIXEL_FORMAT_YV12) {
3290 ALOGW("do not know color format 0x%x = %d", fmt, fmt);
3291 return false;
3292 }
3293
3294 // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
3295 if (params.nStride != 0 && params.nSliceHeight == 0) {
3296 ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
3297 params.nFrameHeight);
3298 params.nSliceHeight = params.nFrameHeight;
3299 }
3300
3301 // we need stride and slice-height to be non-zero
3302 if (params.nStride == 0 || params.nSliceHeight == 0) {
3303 ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
3304 fmt, fmt, params.nStride, params.nSliceHeight);
3305 return false;
3306 }
3307
3308 // set-up YUV format
3309 image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
3310 image.mNumPlanes = 3;
3311 image.mBitDepth = 8;
3312 image.mPlane[image.Y].mOffset = 0;
3313 image.mPlane[image.Y].mColInc = 1;
3314 image.mPlane[image.Y].mRowInc = params.nStride;
3315 image.mPlane[image.Y].mHorizSubsampling = 1;
3316 image.mPlane[image.Y].mVertSubsampling = 1;
3317
3318 switch ((int)fmt) {
3319 case HAL_PIXEL_FORMAT_YV12:
3320 if (params.bUsingNativeBuffers) {
3321 size_t ystride = align(params.nStride, 16);
3322 size_t cstride = align(params.nStride / 2, 16);
3323 image.mPlane[image.Y].mRowInc = ystride;
3324
3325 image.mPlane[image.V].mOffset = ystride * params.nSliceHeight;
3326 image.mPlane[image.V].mColInc = 1;
3327 image.mPlane[image.V].mRowInc = cstride;
3328 image.mPlane[image.V].mHorizSubsampling = 2;
3329 image.mPlane[image.V].mVertSubsampling = 2;
3330
3331 image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset
3332 + (cstride * params.nSliceHeight / 2);
3333 image.mPlane[image.U].mColInc = 1;
3334 image.mPlane[image.U].mRowInc = cstride;
3335 image.mPlane[image.U].mHorizSubsampling = 2;
3336 image.mPlane[image.U].mVertSubsampling = 2;
3337 break;
3338 } else {
3339 // fall through as YV12 is used for YUV420Planar by some codecs
3340 }
3341
3342 case OMX_COLOR_FormatYUV420Planar:
3343 case OMX_COLOR_FormatYUV420PackedPlanar:
3344 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3345 image.mPlane[image.U].mColInc = 1;
3346 image.mPlane[image.U].mRowInc = params.nStride / 2;
3347 image.mPlane[image.U].mHorizSubsampling = 2;
3348 image.mPlane[image.U].mVertSubsampling = 2;
3349
3350 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
3351 + (params.nStride * params.nSliceHeight / 4);
3352 image.mPlane[image.V].mColInc = 1;
3353 image.mPlane[image.V].mRowInc = params.nStride / 2;
3354 image.mPlane[image.V].mHorizSubsampling = 2;
3355 image.mPlane[image.V].mVertSubsampling = 2;
3356 break;
3357
3358 case OMX_COLOR_FormatYUV420SemiPlanar:
3359 // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
3360 case OMX_COLOR_FormatYUV420PackedSemiPlanar:
3361 // NV12
3362 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3363 image.mPlane[image.U].mColInc = 2;
3364 image.mPlane[image.U].mRowInc = params.nStride;
3365 image.mPlane[image.U].mHorizSubsampling = 2;
3366 image.mPlane[image.U].mVertSubsampling = 2;
3367
3368 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
3369 image.mPlane[image.V].mColInc = 2;
3370 image.mPlane[image.V].mRowInc = params.nStride;
3371 image.mPlane[image.V].mHorizSubsampling = 2;
3372 image.mPlane[image.V].mVertSubsampling = 2;
3373 break;
3374
3375 default:
3376 TRESPASS();
3377 }
3378 return true;
3379 }
3380
3381 // static
describeColorFormat(const sp<IOMX> & omx,IOMX::node_id node,DescribeColorFormatParams & describeParams)3382 bool ACodec::describeColorFormat(
3383 const sp<IOMX> &omx, IOMX::node_id node,
3384 DescribeColorFormatParams &describeParams)
3385 {
3386 OMX_INDEXTYPE describeColorFormatIndex;
3387 if (omx->getExtensionIndex(
3388 node, "OMX.google.android.index.describeColorFormat",
3389 &describeColorFormatIndex) != OK ||
3390 omx->getParameter(
3391 node, describeColorFormatIndex,
3392 &describeParams, sizeof(describeParams)) != OK) {
3393 return describeDefaultColorFormat(describeParams);
3394 }
3395 return describeParams.sMediaImage.mType !=
3396 MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3397 }
3398
3399 // static
isFlexibleColorFormat(const sp<IOMX> & omx,IOMX::node_id node,uint32_t colorFormat,bool usingNativeBuffers,OMX_U32 * flexibleEquivalent)3400 bool ACodec::isFlexibleColorFormat(
3401 const sp<IOMX> &omx, IOMX::node_id node,
3402 uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
3403 DescribeColorFormatParams describeParams;
3404 InitOMXParams(&describeParams);
3405 describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
3406 // reasonable dummy values
3407 describeParams.nFrameWidth = 128;
3408 describeParams.nFrameHeight = 128;
3409 describeParams.nStride = 128;
3410 describeParams.nSliceHeight = 128;
3411 describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
3412
3413 CHECK(flexibleEquivalent != NULL);
3414
3415 if (!describeColorFormat(omx, node, describeParams)) {
3416 return false;
3417 }
3418
3419 const MediaImage &img = describeParams.sMediaImage;
3420 if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) {
3421 if (img.mNumPlanes != 3 ||
3422 img.mPlane[img.Y].mHorizSubsampling != 1 ||
3423 img.mPlane[img.Y].mVertSubsampling != 1) {
3424 return false;
3425 }
3426
3427 // YUV 420
3428 if (img.mPlane[img.U].mHorizSubsampling == 2
3429 && img.mPlane[img.U].mVertSubsampling == 2
3430 && img.mPlane[img.V].mHorizSubsampling == 2
3431 && img.mPlane[img.V].mVertSubsampling == 2) {
3432 // possible flexible YUV420 format
3433 if (img.mBitDepth <= 8) {
3434 *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
3435 return true;
3436 }
3437 }
3438 }
3439 return false;
3440 }
3441
getPortFormat(OMX_U32 portIndex,sp<AMessage> & notify)3442 status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) {
3443 // TODO: catch errors an return them instead of using CHECK
3444 OMX_PARAM_PORTDEFINITIONTYPE def;
3445 InitOMXParams(&def);
3446 def.nPortIndex = portIndex;
3447
3448 CHECK_EQ(mOMX->getParameter(
3449 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
3450 (status_t)OK);
3451
3452 CHECK_EQ((int)def.eDir,
3453 (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput));
3454
3455 switch (def.eDomain) {
3456 case OMX_PortDomainVideo:
3457 {
3458 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
3459 switch ((int)videoDef->eCompressionFormat) {
3460 case OMX_VIDEO_CodingUnused:
3461 {
3462 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
3463 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
3464
3465 notify->setInt32("stride", videoDef->nStride);
3466 notify->setInt32("slice-height", videoDef->nSliceHeight);
3467 notify->setInt32("color-format", videoDef->eColorFormat);
3468
3469 if (mNativeWindow == NULL) {
3470 DescribeColorFormatParams describeParams;
3471 InitOMXParams(&describeParams);
3472 describeParams.eColorFormat = videoDef->eColorFormat;
3473 describeParams.nFrameWidth = videoDef->nFrameWidth;
3474 describeParams.nFrameHeight = videoDef->nFrameHeight;
3475 describeParams.nStride = videoDef->nStride;
3476 describeParams.nSliceHeight = videoDef->nSliceHeight;
3477 describeParams.bUsingNativeBuffers = OMX_FALSE;
3478
3479 if (describeColorFormat(mOMX, mNode, describeParams)) {
3480 notify->setBuffer(
3481 "image-data",
3482 ABuffer::CreateAsCopy(
3483 &describeParams.sMediaImage,
3484 sizeof(describeParams.sMediaImage)));
3485
3486 MediaImage *img = &describeParams.sMediaImage;
3487 ALOGV("[%s] MediaImage { F(%zux%zu) @%zu+%zu+%zu @%zu+%zu+%zu @%zu+%zu+%zu }",
3488 mComponentName.c_str(), img->mWidth, img->mHeight,
3489 img->mPlane[0].mOffset, img->mPlane[0].mColInc, img->mPlane[0].mRowInc,
3490 img->mPlane[1].mOffset, img->mPlane[1].mColInc, img->mPlane[1].mRowInc,
3491 img->mPlane[2].mOffset, img->mPlane[2].mColInc, img->mPlane[2].mRowInc);
3492 }
3493 }
3494
3495 if (portIndex != kPortIndexOutput) {
3496 // TODO: also get input crop
3497 break;
3498 }
3499
3500 OMX_CONFIG_RECTTYPE rect;
3501 InitOMXParams(&rect);
3502 rect.nPortIndex = portIndex;
3503
3504 if (mOMX->getConfig(
3505 mNode,
3506 (portIndex == kPortIndexOutput ?
3507 OMX_IndexConfigCommonOutputCrop :
3508 OMX_IndexConfigCommonInputCrop),
3509 &rect, sizeof(rect)) != OK) {
3510 rect.nLeft = 0;
3511 rect.nTop = 0;
3512 rect.nWidth = videoDef->nFrameWidth;
3513 rect.nHeight = videoDef->nFrameHeight;
3514 }
3515
3516 CHECK_GE(rect.nLeft, 0);
3517 CHECK_GE(rect.nTop, 0);
3518 CHECK_GE(rect.nWidth, 0u);
3519 CHECK_GE(rect.nHeight, 0u);
3520 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
3521 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
3522
3523 notify->setRect(
3524 "crop",
3525 rect.nLeft,
3526 rect.nTop,
3527 rect.nLeft + rect.nWidth - 1,
3528 rect.nTop + rect.nHeight - 1);
3529
3530 break;
3531 }
3532
3533 case OMX_VIDEO_CodingVP8:
3534 case OMX_VIDEO_CodingVP9:
3535 {
3536 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3537 InitOMXParams(&vp8type);
3538 vp8type.nPortIndex = kPortIndexOutput;
3539 status_t err = mOMX->getParameter(
3540 mNode,
3541 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3542 &vp8type,
3543 sizeof(vp8type));
3544
3545 if (err == OK) {
3546 AString tsSchema = "none";
3547 if (vp8type.eTemporalPattern
3548 == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
3549 switch (vp8type.nTemporalLayerCount) {
3550 case 1:
3551 {
3552 tsSchema = "webrtc.vp8.1-layer";
3553 break;
3554 }
3555 case 2:
3556 {
3557 tsSchema = "webrtc.vp8.2-layer";
3558 break;
3559 }
3560 case 3:
3561 {
3562 tsSchema = "webrtc.vp8.3-layer";
3563 break;
3564 }
3565 default:
3566 {
3567 break;
3568 }
3569 }
3570 }
3571 notify->setString("ts-schema", tsSchema);
3572 }
3573 // Fall through to set up mime.
3574 }
3575
3576 default:
3577 {
3578 CHECK(mIsEncoder ^ (portIndex == kPortIndexInput));
3579 AString mime;
3580 if (GetMimeTypeForVideoCoding(
3581 videoDef->eCompressionFormat, &mime) != OK) {
3582 notify->setString("mime", "application/octet-stream");
3583 } else {
3584 notify->setString("mime", mime.c_str());
3585 }
3586 break;
3587 }
3588 }
3589 notify->setInt32("width", videoDef->nFrameWidth);
3590 notify->setInt32("height", videoDef->nFrameHeight);
3591 ALOGV("[%s] %s format is %s", mComponentName.c_str(),
3592 portIndex == kPortIndexInput ? "input" : "output",
3593 notify->debugString().c_str());
3594
3595 break;
3596 }
3597
3598 case OMX_PortDomainAudio:
3599 {
3600 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
3601
3602 switch ((int)audioDef->eEncoding) {
3603 case OMX_AUDIO_CodingPCM:
3604 {
3605 OMX_AUDIO_PARAM_PCMMODETYPE params;
3606 InitOMXParams(¶ms);
3607 params.nPortIndex = portIndex;
3608
3609 CHECK_EQ(mOMX->getParameter(
3610 mNode, OMX_IndexParamAudioPcm,
3611 ¶ms, sizeof(params)),
3612 (status_t)OK);
3613
3614 CHECK_GT(params.nChannels, 0);
3615 CHECK(params.nChannels == 1 || params.bInterleaved);
3616 CHECK_EQ(params.nBitPerSample, 16u);
3617
3618 CHECK_EQ((int)params.eNumData,
3619 (int)OMX_NumericalDataSigned);
3620
3621 CHECK_EQ((int)params.ePCMMode,
3622 (int)OMX_AUDIO_PCMModeLinear);
3623
3624 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
3625 notify->setInt32("channel-count", params.nChannels);
3626 notify->setInt32("sample-rate", params.nSamplingRate);
3627
3628 if (mChannelMaskPresent) {
3629 notify->setInt32("channel-mask", mChannelMask);
3630 }
3631 break;
3632 }
3633
3634 case OMX_AUDIO_CodingAAC:
3635 {
3636 OMX_AUDIO_PARAM_AACPROFILETYPE params;
3637 InitOMXParams(¶ms);
3638 params.nPortIndex = portIndex;
3639
3640 CHECK_EQ(mOMX->getParameter(
3641 mNode, OMX_IndexParamAudioAac,
3642 ¶ms, sizeof(params)),
3643 (status_t)OK);
3644
3645 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
3646 notify->setInt32("channel-count", params.nChannels);
3647 notify->setInt32("sample-rate", params.nSampleRate);
3648 break;
3649 }
3650
3651 case OMX_AUDIO_CodingAMR:
3652 {
3653 OMX_AUDIO_PARAM_AMRTYPE params;
3654 InitOMXParams(¶ms);
3655 params.nPortIndex = portIndex;
3656
3657 CHECK_EQ(mOMX->getParameter(
3658 mNode, OMX_IndexParamAudioAmr,
3659 ¶ms, sizeof(params)),
3660 (status_t)OK);
3661
3662 notify->setInt32("channel-count", 1);
3663 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
3664 notify->setString(
3665 "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
3666
3667 notify->setInt32("sample-rate", 16000);
3668 } else {
3669 notify->setString(
3670 "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
3671
3672 notify->setInt32("sample-rate", 8000);
3673 }
3674 break;
3675 }
3676
3677 case OMX_AUDIO_CodingFLAC:
3678 {
3679 OMX_AUDIO_PARAM_FLACTYPE params;
3680 InitOMXParams(¶ms);
3681 params.nPortIndex = portIndex;
3682
3683 CHECK_EQ(mOMX->getParameter(
3684 mNode, OMX_IndexParamAudioFlac,
3685 ¶ms, sizeof(params)),
3686 (status_t)OK);
3687
3688 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
3689 notify->setInt32("channel-count", params.nChannels);
3690 notify->setInt32("sample-rate", params.nSampleRate);
3691 break;
3692 }
3693
3694 case OMX_AUDIO_CodingMP3:
3695 {
3696 OMX_AUDIO_PARAM_MP3TYPE params;
3697 InitOMXParams(¶ms);
3698 params.nPortIndex = portIndex;
3699
3700 CHECK_EQ(mOMX->getParameter(
3701 mNode, OMX_IndexParamAudioMp3,
3702 ¶ms, sizeof(params)),
3703 (status_t)OK);
3704
3705 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
3706 notify->setInt32("channel-count", params.nChannels);
3707 notify->setInt32("sample-rate", params.nSampleRate);
3708 break;
3709 }
3710
3711 case OMX_AUDIO_CodingVORBIS:
3712 {
3713 OMX_AUDIO_PARAM_VORBISTYPE params;
3714 InitOMXParams(¶ms);
3715 params.nPortIndex = portIndex;
3716
3717 CHECK_EQ(mOMX->getParameter(
3718 mNode, OMX_IndexParamAudioVorbis,
3719 ¶ms, sizeof(params)),
3720 (status_t)OK);
3721
3722 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
3723 notify->setInt32("channel-count", params.nChannels);
3724 notify->setInt32("sample-rate", params.nSampleRate);
3725 break;
3726 }
3727
3728 case OMX_AUDIO_CodingAndroidAC3:
3729 {
3730 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
3731 InitOMXParams(¶ms);
3732 params.nPortIndex = portIndex;
3733
3734 CHECK_EQ((status_t)OK, mOMX->getParameter(
3735 mNode,
3736 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
3737 ¶ms,
3738 sizeof(params)));
3739
3740 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
3741 notify->setInt32("channel-count", params.nChannels);
3742 notify->setInt32("sample-rate", params.nSampleRate);
3743 break;
3744 }
3745
3746 case OMX_AUDIO_CodingAndroidEAC3:
3747 {
3748 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
3749 InitOMXParams(¶ms);
3750 params.nPortIndex = portIndex;
3751
3752 CHECK_EQ((status_t)OK, mOMX->getParameter(
3753 mNode,
3754 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
3755 ¶ms,
3756 sizeof(params)));
3757
3758 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
3759 notify->setInt32("channel-count", params.nChannels);
3760 notify->setInt32("sample-rate", params.nSampleRate);
3761 break;
3762 }
3763
3764 case OMX_AUDIO_CodingAndroidOPUS:
3765 {
3766 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
3767 InitOMXParams(¶ms);
3768 params.nPortIndex = portIndex;
3769
3770 CHECK_EQ((status_t)OK, mOMX->getParameter(
3771 mNode,
3772 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
3773 ¶ms,
3774 sizeof(params)));
3775
3776 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
3777 notify->setInt32("channel-count", params.nChannels);
3778 notify->setInt32("sample-rate", params.nSampleRate);
3779 break;
3780 }
3781
3782 case OMX_AUDIO_CodingG711:
3783 {
3784 OMX_AUDIO_PARAM_PCMMODETYPE params;
3785 InitOMXParams(¶ms);
3786 params.nPortIndex = portIndex;
3787
3788 CHECK_EQ((status_t)OK, mOMX->getParameter(
3789 mNode,
3790 (OMX_INDEXTYPE)OMX_IndexParamAudioPcm,
3791 ¶ms,
3792 sizeof(params)));
3793
3794 const char *mime = NULL;
3795 if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
3796 mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
3797 } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
3798 mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
3799 } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
3800 mime = MEDIA_MIMETYPE_AUDIO_RAW;
3801 }
3802 notify->setString("mime", mime);
3803 notify->setInt32("channel-count", params.nChannels);
3804 notify->setInt32("sample-rate", params.nSamplingRate);
3805 break;
3806 }
3807
3808 case OMX_AUDIO_CodingGSMFR:
3809 {
3810 OMX_AUDIO_PARAM_MP3TYPE params;
3811 InitOMXParams(¶ms);
3812 params.nPortIndex = portIndex;
3813
3814 CHECK_EQ(mOMX->getParameter(
3815 mNode, OMX_IndexParamAudioPcm,
3816 ¶ms, sizeof(params)),
3817 (status_t)OK);
3818
3819 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
3820 notify->setInt32("channel-count", params.nChannels);
3821 notify->setInt32("sample-rate", params.nSampleRate);
3822 break;
3823 }
3824
3825 default:
3826 ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding);
3827 TRESPASS();
3828 }
3829 break;
3830 }
3831
3832 default:
3833 TRESPASS();
3834 }
3835
3836 return OK;
3837 }
3838
sendFormatChange(const sp<AMessage> & reply)3839 void ACodec::sendFormatChange(const sp<AMessage> &reply) {
3840 sp<AMessage> notify = mBaseOutputFormat->dup();
3841 notify->setInt32("what", kWhatOutputFormatChanged);
3842
3843 CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
3844
3845 AString mime;
3846 CHECK(notify->findString("mime", &mime));
3847
3848 int32_t left, top, right, bottom;
3849 if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
3850 mNativeWindow != NULL &&
3851 notify->findRect("crop", &left, &top, &right, &bottom)) {
3852 // notify renderer of the crop change
3853 // NOTE: native window uses extended right-bottom coordinate
3854 reply->setRect("crop", left, top, right + 1, bottom + 1);
3855 } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
3856 (mEncoderDelay || mEncoderPadding)) {
3857 int32_t channelCount;
3858 CHECK(notify->findInt32("channel-count", &channelCount));
3859 size_t frameSize = channelCount * sizeof(int16_t);
3860 if (mSkipCutBuffer != NULL) {
3861 size_t prevbufsize = mSkipCutBuffer->size();
3862 if (prevbufsize != 0) {
3863 ALOGW("Replacing SkipCutBuffer holding %d "
3864 "bytes",
3865 prevbufsize);
3866 }
3867 }
3868 mSkipCutBuffer = new SkipCutBuffer(
3869 mEncoderDelay * frameSize,
3870 mEncoderPadding * frameSize);
3871 }
3872
3873 notify->post();
3874
3875 mSentFormat = true;
3876 }
3877
signalError(OMX_ERRORTYPE error,status_t internalError)3878 void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
3879 sp<AMessage> notify = mNotify->dup();
3880 notify->setInt32("what", CodecBase::kWhatError);
3881 ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
3882
3883 if (internalError == UNKNOWN_ERROR) { // find better error code
3884 const status_t omxStatus = statusFromOMXError(error);
3885 if (omxStatus != 0) {
3886 internalError = omxStatus;
3887 } else {
3888 ALOGW("Invalid OMX error %#x", error);
3889 }
3890 }
3891 notify->setInt32("err", internalError);
3892 notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
3893 notify->post();
3894 }
3895
pushBlankBuffersToNativeWindow()3896 status_t ACodec::pushBlankBuffersToNativeWindow() {
3897 status_t err = NO_ERROR;
3898 ANativeWindowBuffer* anb = NULL;
3899 int numBufs = 0;
3900 int minUndequeuedBufs = 0;
3901
3902 // We need to reconnect to the ANativeWindow as a CPU client to ensure that
3903 // no frames get dropped by SurfaceFlinger assuming that these are video
3904 // frames.
3905 err = native_window_api_disconnect(mNativeWindow.get(),
3906 NATIVE_WINDOW_API_MEDIA);
3907 if (err != NO_ERROR) {
3908 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3909 strerror(-err), -err);
3910 return err;
3911 }
3912
3913 err = native_window_api_connect(mNativeWindow.get(),
3914 NATIVE_WINDOW_API_CPU);
3915 if (err != NO_ERROR) {
3916 ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3917 strerror(-err), -err);
3918 return err;
3919 }
3920
3921 err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
3922 HAL_PIXEL_FORMAT_RGBX_8888);
3923 if (err != NO_ERROR) {
3924 ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
3925 strerror(-err), -err);
3926 goto error;
3927 }
3928
3929 err = native_window_set_scaling_mode(mNativeWindow.get(),
3930 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3931 if (err != NO_ERROR) {
3932 ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)",
3933 strerror(-err), -err);
3934 goto error;
3935 }
3936
3937 err = native_window_set_usage(mNativeWindow.get(),
3938 GRALLOC_USAGE_SW_WRITE_OFTEN);
3939 if (err != NO_ERROR) {
3940 ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
3941 strerror(-err), -err);
3942 goto error;
3943 }
3944
3945 err = mNativeWindow->query(mNativeWindow.get(),
3946 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
3947 if (err != NO_ERROR) {
3948 ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
3949 "failed: %s (%d)", strerror(-err), -err);
3950 goto error;
3951 }
3952
3953 numBufs = minUndequeuedBufs + 1;
3954 err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
3955 if (err != NO_ERROR) {
3956 ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
3957 strerror(-err), -err);
3958 goto error;
3959 }
3960
3961 // We push numBufs + 1 buffers to ensure that we've drawn into the same
3962 // buffer twice. This should guarantee that the buffer has been displayed
3963 // on the screen and then been replaced, so an previous video frames are
3964 // guaranteed NOT to be currently displayed.
3965 for (int i = 0; i < numBufs + 1; i++) {
3966 int fenceFd = -1;
3967 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
3968 if (err != NO_ERROR) {
3969 ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
3970 strerror(-err), -err);
3971 goto error;
3972 }
3973
3974 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
3975
3976 // Fill the buffer with the a 1x1 checkerboard pattern ;)
3977 uint32_t* img = NULL;
3978 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
3979 if (err != NO_ERROR) {
3980 ALOGE("error pushing blank frames: lock failed: %s (%d)",
3981 strerror(-err), -err);
3982 goto error;
3983 }
3984
3985 *img = 0;
3986
3987 err = buf->unlock();
3988 if (err != NO_ERROR) {
3989 ALOGE("error pushing blank frames: unlock failed: %s (%d)",
3990 strerror(-err), -err);
3991 goto error;
3992 }
3993
3994 err = mNativeWindow->queueBuffer(mNativeWindow.get(),
3995 buf->getNativeBuffer(), -1);
3996 if (err != NO_ERROR) {
3997 ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
3998 strerror(-err), -err);
3999 goto error;
4000 }
4001
4002 anb = NULL;
4003 }
4004
4005 error:
4006
4007 if (err != NO_ERROR) {
4008 // Clean up after an error.
4009 if (anb != NULL) {
4010 mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
4011 }
4012
4013 native_window_api_disconnect(mNativeWindow.get(),
4014 NATIVE_WINDOW_API_CPU);
4015 native_window_api_connect(mNativeWindow.get(),
4016 NATIVE_WINDOW_API_MEDIA);
4017
4018 return err;
4019 } else {
4020 // Clean up after success.
4021 err = native_window_api_disconnect(mNativeWindow.get(),
4022 NATIVE_WINDOW_API_CPU);
4023 if (err != NO_ERROR) {
4024 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
4025 strerror(-err), -err);
4026 return err;
4027 }
4028
4029 err = native_window_api_connect(mNativeWindow.get(),
4030 NATIVE_WINDOW_API_MEDIA);
4031 if (err != NO_ERROR) {
4032 ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
4033 strerror(-err), -err);
4034 return err;
4035 }
4036
4037 return NO_ERROR;
4038 }
4039 }
4040
4041 ////////////////////////////////////////////////////////////////////////////////
4042
PortDescription()4043 ACodec::PortDescription::PortDescription() {
4044 }
4045
requestIDRFrame()4046 status_t ACodec::requestIDRFrame() {
4047 if (!mIsEncoder) {
4048 return ERROR_UNSUPPORTED;
4049 }
4050
4051 OMX_CONFIG_INTRAREFRESHVOPTYPE params;
4052 InitOMXParams(¶ms);
4053
4054 params.nPortIndex = kPortIndexOutput;
4055 params.IntraRefreshVOP = OMX_TRUE;
4056
4057 return mOMX->setConfig(
4058 mNode,
4059 OMX_IndexConfigVideoIntraVOPRefresh,
4060 ¶ms,
4061 sizeof(params));
4062 }
4063
addBuffer(IOMX::buffer_id id,const sp<ABuffer> & buffer)4064 void ACodec::PortDescription::addBuffer(
4065 IOMX::buffer_id id, const sp<ABuffer> &buffer) {
4066 mBufferIDs.push_back(id);
4067 mBuffers.push_back(buffer);
4068 }
4069
countBuffers()4070 size_t ACodec::PortDescription::countBuffers() {
4071 return mBufferIDs.size();
4072 }
4073
bufferIDAt(size_t index) const4074 IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
4075 return mBufferIDs.itemAt(index);
4076 }
4077
bufferAt(size_t index) const4078 sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
4079 return mBuffers.itemAt(index);
4080 }
4081
4082 ////////////////////////////////////////////////////////////////////////////////
4083
BaseState(ACodec * codec,const sp<AState> & parentState)4084 ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
4085 : AState(parentState),
4086 mCodec(codec) {
4087 }
4088
getPortMode(OMX_U32)4089 ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
4090 OMX_U32 /* portIndex */) {
4091 return KEEP_BUFFERS;
4092 }
4093
onMessageReceived(const sp<AMessage> & msg)4094 bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
4095 switch (msg->what()) {
4096 case kWhatInputBufferFilled:
4097 {
4098 onInputBufferFilled(msg);
4099 break;
4100 }
4101
4102 case kWhatOutputBufferDrained:
4103 {
4104 onOutputBufferDrained(msg);
4105 break;
4106 }
4107
4108 case ACodec::kWhatOMXMessage:
4109 {
4110 return onOMXMessage(msg);
4111 }
4112
4113 case ACodec::kWhatCreateInputSurface:
4114 case ACodec::kWhatSignalEndOfInputStream:
4115 {
4116 // This may result in an app illegal state exception.
4117 ALOGE("Message 0x%x was not handled", msg->what());
4118 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
4119 return true;
4120 }
4121
4122 case ACodec::kWhatOMXDied:
4123 {
4124 // This will result in kFlagSawMediaServerDie handling in MediaCodec.
4125 ALOGE("OMX/mediaserver died, signalling error!");
4126 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
4127 break;
4128 }
4129
4130 case ACodec::kWhatReleaseCodecInstance:
4131 {
4132 ALOGI("[%s] forcing the release of codec",
4133 mCodec->mComponentName.c_str());
4134 status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
4135 ALOGE_IF("[%s] failed to release codec instance: err=%d",
4136 mCodec->mComponentName.c_str(), err);
4137 sp<AMessage> notify = mCodec->mNotify->dup();
4138 notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4139 notify->post();
4140 break;
4141 }
4142
4143 default:
4144 return false;
4145 }
4146
4147 return true;
4148 }
4149
onOMXMessage(const sp<AMessage> & msg)4150 bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
4151 int32_t type;
4152 CHECK(msg->findInt32("type", &type));
4153
4154 // there is a possibility that this is an outstanding message for a
4155 // codec that we have already destroyed
4156 if (mCodec->mNode == NULL) {
4157 ALOGI("ignoring message as already freed component: %s",
4158 msg->debugString().c_str());
4159 return true;
4160 }
4161
4162 IOMX::node_id nodeID;
4163 CHECK(msg->findInt32("node", (int32_t*)&nodeID));
4164 CHECK_EQ(nodeID, mCodec->mNode);
4165
4166 switch (type) {
4167 case omx_message::EVENT:
4168 {
4169 int32_t event, data1, data2;
4170 CHECK(msg->findInt32("event", &event));
4171 CHECK(msg->findInt32("data1", &data1));
4172 CHECK(msg->findInt32("data2", &data2));
4173
4174 if (event == OMX_EventCmdComplete
4175 && data1 == OMX_CommandFlush
4176 && data2 == (int32_t)OMX_ALL) {
4177 // Use of this notification is not consistent across
4178 // implementations. We'll drop this notification and rely
4179 // on flush-complete notifications on the individual port
4180 // indices instead.
4181
4182 return true;
4183 }
4184
4185 return onOMXEvent(
4186 static_cast<OMX_EVENTTYPE>(event),
4187 static_cast<OMX_U32>(data1),
4188 static_cast<OMX_U32>(data2));
4189 }
4190
4191 case omx_message::EMPTY_BUFFER_DONE:
4192 {
4193 IOMX::buffer_id bufferID;
4194 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4195
4196 return onOMXEmptyBufferDone(bufferID);
4197 }
4198
4199 case omx_message::FILL_BUFFER_DONE:
4200 {
4201 IOMX::buffer_id bufferID;
4202 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4203
4204 int32_t rangeOffset, rangeLength, flags;
4205 int64_t timeUs;
4206
4207 CHECK(msg->findInt32("range_offset", &rangeOffset));
4208 CHECK(msg->findInt32("range_length", &rangeLength));
4209 CHECK(msg->findInt32("flags", &flags));
4210 CHECK(msg->findInt64("timestamp", &timeUs));
4211
4212 return onOMXFillBufferDone(
4213 bufferID,
4214 (size_t)rangeOffset, (size_t)rangeLength,
4215 (OMX_U32)flags,
4216 timeUs);
4217 }
4218
4219 default:
4220 TRESPASS();
4221 break;
4222 }
4223 }
4224
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)4225 bool ACodec::BaseState::onOMXEvent(
4226 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4227 if (event != OMX_EventError) {
4228 ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
4229 mCodec->mComponentName.c_str(), event, data1, data2);
4230
4231 return false;
4232 }
4233
4234 ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
4235
4236 // verify OMX component sends back an error we expect.
4237 OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
4238 if (!isOMXError(omxError)) {
4239 ALOGW("Invalid OMX error %#x", omxError);
4240 omxError = OMX_ErrorUndefined;
4241 }
4242 mCodec->signalError(omxError);
4243
4244 return true;
4245 }
4246
onOMXEmptyBufferDone(IOMX::buffer_id bufferID)4247 bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
4248 ALOGV("[%s] onOMXEmptyBufferDone %p",
4249 mCodec->mComponentName.c_str(), bufferID);
4250
4251 BufferInfo *info =
4252 mCodec->findBufferByID(kPortIndexInput, bufferID);
4253
4254 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4255 info->mStatus = BufferInfo::OWNED_BY_US;
4256
4257 // We're in "store-metadata-in-buffers" mode, the underlying
4258 // OMX component had access to data that's implicitly refcounted
4259 // by this "MediaBuffer" object. Now that the OMX component has
4260 // told us that it's done with the input buffer, we can decrement
4261 // the mediaBuffer's reference count.
4262 info->mData->setMediaBufferBase(NULL);
4263
4264 PortMode mode = getPortMode(kPortIndexInput);
4265
4266 switch (mode) {
4267 case KEEP_BUFFERS:
4268 break;
4269
4270 case RESUBMIT_BUFFERS:
4271 postFillThisBuffer(info);
4272 break;
4273
4274 default:
4275 {
4276 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4277 TRESPASS(); // Not currently used
4278 break;
4279 }
4280 }
4281
4282 return true;
4283 }
4284
postFillThisBuffer(BufferInfo * info)4285 void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
4286 if (mCodec->mPortEOS[kPortIndexInput]) {
4287 return;
4288 }
4289
4290 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4291
4292 sp<AMessage> notify = mCodec->mNotify->dup();
4293 notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
4294 notify->setInt32("buffer-id", info->mBufferID);
4295
4296 info->mData->meta()->clear();
4297 notify->setBuffer("buffer", info->mData);
4298
4299 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
4300 reply->setInt32("buffer-id", info->mBufferID);
4301
4302 notify->setMessage("reply", reply);
4303
4304 notify->post();
4305
4306 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
4307 }
4308
onInputBufferFilled(const sp<AMessage> & msg)4309 void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
4310 IOMX::buffer_id bufferID;
4311 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4312 sp<ABuffer> buffer;
4313 int32_t err = OK;
4314 bool eos = false;
4315 PortMode mode = getPortMode(kPortIndexInput);
4316
4317 if (!msg->findBuffer("buffer", &buffer)) {
4318 /* these are unfilled buffers returned by client */
4319 CHECK(msg->findInt32("err", &err));
4320
4321 if (err == OK) {
4322 /* buffers with no errors are returned on MediaCodec.flush */
4323 mode = KEEP_BUFFERS;
4324 } else {
4325 ALOGV("[%s] saw error %d instead of an input buffer",
4326 mCodec->mComponentName.c_str(), err);
4327 eos = true;
4328 }
4329
4330 buffer.clear();
4331 }
4332
4333 int32_t tmp;
4334 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
4335 eos = true;
4336 err = ERROR_END_OF_STREAM;
4337 }
4338
4339 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4340 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
4341
4342 info->mStatus = BufferInfo::OWNED_BY_US;
4343
4344 switch (mode) {
4345 case KEEP_BUFFERS:
4346 {
4347 if (eos) {
4348 if (!mCodec->mPortEOS[kPortIndexInput]) {
4349 mCodec->mPortEOS[kPortIndexInput] = true;
4350 mCodec->mInputEOSResult = err;
4351 }
4352 }
4353 break;
4354 }
4355
4356 case RESUBMIT_BUFFERS:
4357 {
4358 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
4359 int64_t timeUs;
4360 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
4361
4362 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
4363
4364 int32_t isCSD;
4365 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
4366 flags |= OMX_BUFFERFLAG_CODECCONFIG;
4367 }
4368
4369 if (eos) {
4370 flags |= OMX_BUFFERFLAG_EOS;
4371 }
4372
4373 if (buffer != info->mData) {
4374 ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
4375 mCodec->mComponentName.c_str(),
4376 bufferID,
4377 buffer.get(), info->mData.get());
4378
4379 CHECK_LE(buffer->size(), info->mData->capacity());
4380 memcpy(info->mData->data(), buffer->data(), buffer->size());
4381 }
4382
4383 if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
4384 ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
4385 mCodec->mComponentName.c_str(), bufferID);
4386 } else if (flags & OMX_BUFFERFLAG_EOS) {
4387 ALOGV("[%s] calling emptyBuffer %p w/ EOS",
4388 mCodec->mComponentName.c_str(), bufferID);
4389 } else {
4390 #if TRACK_BUFFER_TIMING
4391 ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
4392 mCodec->mComponentName.c_str(), bufferID, timeUs);
4393 #else
4394 ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
4395 mCodec->mComponentName.c_str(), bufferID, timeUs);
4396 #endif
4397 }
4398
4399 #if TRACK_BUFFER_TIMING
4400 ACodec::BufferStats stats;
4401 stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
4402 stats.mFillBufferDoneTimeUs = -1ll;
4403 mCodec->mBufferStats.add(timeUs, stats);
4404 #endif
4405
4406 if (mCodec->mStoreMetaDataInOutputBuffers) {
4407 // try to submit an output buffer for each input buffer
4408 PortMode outputMode = getPortMode(kPortIndexOutput);
4409
4410 ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
4411 mCodec->mMetaDataBuffersToSubmit,
4412 (outputMode == FREE_BUFFERS ? "FREE" :
4413 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
4414 if (outputMode == RESUBMIT_BUFFERS) {
4415 mCodec->submitOutputMetaDataBuffer();
4416 }
4417 }
4418
4419 CHECK_EQ(mCodec->mOMX->emptyBuffer(
4420 mCodec->mNode,
4421 bufferID,
4422 0,
4423 buffer->size(),
4424 flags,
4425 timeUs),
4426 (status_t)OK);
4427
4428 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4429
4430 if (!eos) {
4431 getMoreInputDataIfPossible();
4432 } else {
4433 ALOGV("[%s] Signalled EOS on the input port",
4434 mCodec->mComponentName.c_str());
4435
4436 mCodec->mPortEOS[kPortIndexInput] = true;
4437 mCodec->mInputEOSResult = err;
4438 }
4439 } else if (!mCodec->mPortEOS[kPortIndexInput]) {
4440 if (err != ERROR_END_OF_STREAM) {
4441 ALOGV("[%s] Signalling EOS on the input port "
4442 "due to error %d",
4443 mCodec->mComponentName.c_str(), err);
4444 } else {
4445 ALOGV("[%s] Signalling EOS on the input port",
4446 mCodec->mComponentName.c_str());
4447 }
4448
4449 ALOGV("[%s] calling emptyBuffer %p signalling EOS",
4450 mCodec->mComponentName.c_str(), bufferID);
4451
4452 CHECK_EQ(mCodec->mOMX->emptyBuffer(
4453 mCodec->mNode,
4454 bufferID,
4455 0,
4456 0,
4457 OMX_BUFFERFLAG_EOS,
4458 0),
4459 (status_t)OK);
4460
4461 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4462
4463 mCodec->mPortEOS[kPortIndexInput] = true;
4464 mCodec->mInputEOSResult = err;
4465 }
4466 break;
4467 }
4468
4469 default:
4470 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4471 break;
4472 }
4473 }
4474
getMoreInputDataIfPossible()4475 void ACodec::BaseState::getMoreInputDataIfPossible() {
4476 if (mCodec->mPortEOS[kPortIndexInput]) {
4477 return;
4478 }
4479
4480 BufferInfo *eligible = NULL;
4481
4482 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4483 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4484
4485 #if 0
4486 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
4487 // There's already a "read" pending.
4488 return;
4489 }
4490 #endif
4491
4492 if (info->mStatus == BufferInfo::OWNED_BY_US) {
4493 eligible = info;
4494 }
4495 }
4496
4497 if (eligible == NULL) {
4498 return;
4499 }
4500
4501 postFillThisBuffer(eligible);
4502 }
4503
onOMXFillBufferDone(IOMX::buffer_id bufferID,size_t rangeOffset,size_t rangeLength,OMX_U32 flags,int64_t timeUs)4504 bool ACodec::BaseState::onOMXFillBufferDone(
4505 IOMX::buffer_id bufferID,
4506 size_t rangeOffset, size_t rangeLength,
4507 OMX_U32 flags,
4508 int64_t timeUs) {
4509 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
4510 mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
4511
4512 ssize_t index;
4513
4514 #if TRACK_BUFFER_TIMING
4515 index = mCodec->mBufferStats.indexOfKey(timeUs);
4516 if (index >= 0) {
4517 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
4518 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
4519
4520 ALOGI("frame PTS %lld: %lld",
4521 timeUs,
4522 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
4523
4524 mCodec->mBufferStats.removeItemsAt(index);
4525 stats = NULL;
4526 }
4527 #endif
4528
4529 BufferInfo *info =
4530 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4531
4532 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4533
4534 info->mDequeuedAt = ++mCodec->mDequeueCounter;
4535 info->mStatus = BufferInfo::OWNED_BY_US;
4536
4537 PortMode mode = getPortMode(kPortIndexOutput);
4538
4539 switch (mode) {
4540 case KEEP_BUFFERS:
4541 break;
4542
4543 case RESUBMIT_BUFFERS:
4544 {
4545 if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
4546 || mCodec->mPortEOS[kPortIndexOutput])) {
4547 ALOGV("[%s] calling fillBuffer %u",
4548 mCodec->mComponentName.c_str(), info->mBufferID);
4549
4550 CHECK_EQ(mCodec->mOMX->fillBuffer(
4551 mCodec->mNode, info->mBufferID),
4552 (status_t)OK);
4553
4554 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4555 break;
4556 }
4557
4558 sp<AMessage> reply =
4559 new AMessage(kWhatOutputBufferDrained, mCodec->id());
4560
4561 if (!mCodec->mSentFormat && rangeLength > 0) {
4562 mCodec->sendFormatChange(reply);
4563 }
4564
4565 if (mCodec->mUseMetadataOnEncoderOutput) {
4566 native_handle_t* handle =
4567 *(native_handle_t**)(info->mData->data() + 4);
4568 info->mData->meta()->setPointer("handle", handle);
4569 info->mData->meta()->setInt32("rangeOffset", rangeOffset);
4570 info->mData->meta()->setInt32("rangeLength", rangeLength);
4571 } else {
4572 info->mData->setRange(rangeOffset, rangeLength);
4573 }
4574 #if 0
4575 if (mCodec->mNativeWindow == NULL) {
4576 if (IsIDR(info->mData)) {
4577 ALOGI("IDR frame");
4578 }
4579 }
4580 #endif
4581
4582 if (mCodec->mSkipCutBuffer != NULL) {
4583 mCodec->mSkipCutBuffer->submit(info->mData);
4584 }
4585 info->mData->meta()->setInt64("timeUs", timeUs);
4586
4587 sp<AMessage> notify = mCodec->mNotify->dup();
4588 notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
4589 notify->setInt32("buffer-id", info->mBufferID);
4590 notify->setBuffer("buffer", info->mData);
4591 notify->setInt32("flags", flags);
4592
4593 reply->setInt32("buffer-id", info->mBufferID);
4594
4595 notify->setMessage("reply", reply);
4596
4597 notify->post();
4598
4599 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
4600
4601 if (flags & OMX_BUFFERFLAG_EOS) {
4602 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
4603
4604 sp<AMessage> notify = mCodec->mNotify->dup();
4605 notify->setInt32("what", CodecBase::kWhatEOS);
4606 notify->setInt32("err", mCodec->mInputEOSResult);
4607 notify->post();
4608
4609 mCodec->mPortEOS[kPortIndexOutput] = true;
4610 }
4611 break;
4612 }
4613
4614 default:
4615 {
4616 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4617
4618 CHECK_EQ((status_t)OK,
4619 mCodec->freeBuffer(kPortIndexOutput, index));
4620 break;
4621 }
4622 }
4623
4624 return true;
4625 }
4626
onOutputBufferDrained(const sp<AMessage> & msg)4627 void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
4628 IOMX::buffer_id bufferID;
4629 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4630 ssize_t index;
4631 BufferInfo *info =
4632 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4633 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
4634
4635 android_native_rect_t crop;
4636 if (msg->findRect("crop",
4637 &crop.left, &crop.top, &crop.right, &crop.bottom)) {
4638 CHECK_EQ(0, native_window_set_crop(
4639 mCodec->mNativeWindow.get(), &crop));
4640 }
4641
4642 int32_t render;
4643 if (mCodec->mNativeWindow != NULL
4644 && msg->findInt32("render", &render) && render != 0
4645 && info->mData != NULL && info->mData->size() != 0) {
4646 ATRACE_NAME("render");
4647 // The client wants this buffer to be rendered.
4648
4649 int64_t timestampNs = 0;
4650 if (!msg->findInt64("timestampNs", ×tampNs)) {
4651 // TODO: it seems like we should use the timestamp
4652 // in the (media)buffer as it potentially came from
4653 // an input surface, but we did not propagate it prior to
4654 // API 20. Perhaps check for target SDK version.
4655 #if 0
4656 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) {
4657 ALOGV("using buffer PTS of %" PRId64, timestampNs);
4658 timestampNs *= 1000;
4659 }
4660 #endif
4661 }
4662
4663 status_t err;
4664 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
4665 if (err != OK) {
4666 ALOGW("failed to set buffer timestamp: %d", err);
4667 }
4668
4669 if ((err = mCodec->mNativeWindow->queueBuffer(
4670 mCodec->mNativeWindow.get(),
4671 info->mGraphicBuffer.get(), -1)) == OK) {
4672 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
4673 } else {
4674 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4675 info->mStatus = BufferInfo::OWNED_BY_US;
4676 }
4677 } else {
4678 if (mCodec->mNativeWindow != NULL &&
4679 (info->mData == NULL || info->mData->size() != 0)) {
4680 ATRACE_NAME("frame-drop");
4681 }
4682 info->mStatus = BufferInfo::OWNED_BY_US;
4683 }
4684
4685 PortMode mode = getPortMode(kPortIndexOutput);
4686
4687 switch (mode) {
4688 case KEEP_BUFFERS:
4689 {
4690 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
4691
4692 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4693 // We cannot resubmit the buffer we just rendered, dequeue
4694 // the spare instead.
4695
4696 info = mCodec->dequeueBufferFromNativeWindow();
4697 }
4698 break;
4699 }
4700
4701 case RESUBMIT_BUFFERS:
4702 {
4703 if (!mCodec->mPortEOS[kPortIndexOutput]) {
4704 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4705 // We cannot resubmit the buffer we just rendered, dequeue
4706 // the spare instead.
4707
4708 info = mCodec->dequeueBufferFromNativeWindow();
4709 }
4710
4711 if (info != NULL) {
4712 ALOGV("[%s] calling fillBuffer %u",
4713 mCodec->mComponentName.c_str(), info->mBufferID);
4714
4715 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4716 (status_t)OK);
4717
4718 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4719 }
4720 }
4721 break;
4722 }
4723
4724 default:
4725 {
4726 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4727
4728 CHECK_EQ((status_t)OK,
4729 mCodec->freeBuffer(kPortIndexOutput, index));
4730 break;
4731 }
4732 }
4733 }
4734
4735 ////////////////////////////////////////////////////////////////////////////////
4736
UninitializedState(ACodec * codec)4737 ACodec::UninitializedState::UninitializedState(ACodec *codec)
4738 : BaseState(codec) {
4739 }
4740
stateEntered()4741 void ACodec::UninitializedState::stateEntered() {
4742 ALOGV("Now uninitialized");
4743
4744 if (mDeathNotifier != NULL) {
4745 mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
4746 mDeathNotifier.clear();
4747 }
4748
4749 mCodec->mNativeWindow.clear();
4750 mCodec->mNode = NULL;
4751 mCodec->mOMX.clear();
4752 mCodec->mQuirks = 0;
4753 mCodec->mFlags = 0;
4754 mCodec->mUseMetadataOnEncoderOutput = 0;
4755 mCodec->mComponentName.clear();
4756 }
4757
onMessageReceived(const sp<AMessage> & msg)4758 bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
4759 bool handled = false;
4760
4761 switch (msg->what()) {
4762 case ACodec::kWhatSetup:
4763 {
4764 onSetup(msg);
4765
4766 handled = true;
4767 break;
4768 }
4769
4770 case ACodec::kWhatAllocateComponent:
4771 {
4772 onAllocateComponent(msg);
4773 handled = true;
4774 break;
4775 }
4776
4777 case ACodec::kWhatShutdown:
4778 {
4779 int32_t keepComponentAllocated;
4780 CHECK(msg->findInt32(
4781 "keepComponentAllocated", &keepComponentAllocated));
4782 ALOGW_IF(keepComponentAllocated,
4783 "cannot keep component allocated on shutdown in Uninitialized state");
4784
4785 sp<AMessage> notify = mCodec->mNotify->dup();
4786 notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4787 notify->post();
4788
4789 handled = true;
4790 break;
4791 }
4792
4793 case ACodec::kWhatFlush:
4794 {
4795 sp<AMessage> notify = mCodec->mNotify->dup();
4796 notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4797 notify->post();
4798
4799 handled = true;
4800 break;
4801 }
4802
4803 case ACodec::kWhatReleaseCodecInstance:
4804 {
4805 // nothing to do, as we have already signaled shutdown
4806 handled = true;
4807 break;
4808 }
4809
4810 default:
4811 return BaseState::onMessageReceived(msg);
4812 }
4813
4814 return handled;
4815 }
4816
onSetup(const sp<AMessage> & msg)4817 void ACodec::UninitializedState::onSetup(
4818 const sp<AMessage> &msg) {
4819 if (onAllocateComponent(msg)
4820 && mCodec->mLoadedState->onConfigureComponent(msg)) {
4821 mCodec->mLoadedState->onStart();
4822 }
4823 }
4824
onAllocateComponent(const sp<AMessage> & msg)4825 bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
4826 ALOGV("onAllocateComponent");
4827
4828 CHECK(mCodec->mNode == NULL);
4829
4830 OMXClient client;
4831 CHECK_EQ(client.connect(), (status_t)OK);
4832
4833 sp<IOMX> omx = client.interface();
4834
4835 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
4836
4837 mDeathNotifier = new DeathNotifier(notify);
4838 if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
4839 // This was a local binder, if it dies so do we, we won't care
4840 // about any notifications in the afterlife.
4841 mDeathNotifier.clear();
4842 }
4843
4844 Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
4845
4846 AString mime;
4847
4848 AString componentName;
4849 uint32_t quirks = 0;
4850 int32_t encoder = false;
4851 if (msg->findString("componentName", &componentName)) {
4852 ssize_t index = matchingCodecs.add();
4853 OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
4854 entry->mName = String8(componentName.c_str());
4855
4856 if (!OMXCodec::findCodecQuirks(
4857 componentName.c_str(), &entry->mQuirks)) {
4858 entry->mQuirks = 0;
4859 }
4860 } else {
4861 CHECK(msg->findString("mime", &mime));
4862
4863 if (!msg->findInt32("encoder", &encoder)) {
4864 encoder = false;
4865 }
4866
4867 OMXCodec::findMatchingCodecs(
4868 mime.c_str(),
4869 encoder, // createEncoder
4870 NULL, // matchComponentName
4871 0, // flags
4872 &matchingCodecs);
4873 }
4874
4875 sp<CodecObserver> observer = new CodecObserver;
4876 IOMX::node_id node = NULL;
4877
4878 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
4879 ++matchIndex) {
4880 componentName = matchingCodecs.itemAt(matchIndex).mName.string();
4881 quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
4882
4883 pid_t tid = androidGetTid();
4884 int prevPriority = androidGetThreadPriority(tid);
4885 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
4886 status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
4887 androidSetThreadPriority(tid, prevPriority);
4888
4889 if (err == OK) {
4890 break;
4891 } else {
4892 ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
4893 }
4894
4895 node = NULL;
4896 }
4897
4898 if (node == NULL) {
4899 if (!mime.empty()) {
4900 ALOGE("Unable to instantiate a %scoder for type '%s'.",
4901 encoder ? "en" : "de", mime.c_str());
4902 } else {
4903 ALOGE("Unable to instantiate codec '%s'.", componentName.c_str());
4904 }
4905
4906 mCodec->signalError(OMX_ErrorComponentNotFound);
4907 return false;
4908 }
4909
4910 notify = new AMessage(kWhatOMXMessage, mCodec->id());
4911 observer->setNotificationMessage(notify);
4912
4913 mCodec->mComponentName = componentName;
4914 mCodec->mFlags = 0;
4915
4916 if (componentName.endsWith(".secure")) {
4917 mCodec->mFlags |= kFlagIsSecure;
4918 mCodec->mFlags |= kFlagIsGrallocUsageProtected;
4919 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
4920 }
4921
4922 mCodec->mQuirks = quirks;
4923 mCodec->mOMX = omx;
4924 mCodec->mNode = node;
4925
4926 {
4927 sp<AMessage> notify = mCodec->mNotify->dup();
4928 notify->setInt32("what", CodecBase::kWhatComponentAllocated);
4929 notify->setString("componentName", mCodec->mComponentName.c_str());
4930 notify->post();
4931 }
4932
4933 mCodec->changeState(mCodec->mLoadedState);
4934
4935 return true;
4936 }
4937
4938 ////////////////////////////////////////////////////////////////////////////////
4939
LoadedState(ACodec * codec)4940 ACodec::LoadedState::LoadedState(ACodec *codec)
4941 : BaseState(codec) {
4942 }
4943
stateEntered()4944 void ACodec::LoadedState::stateEntered() {
4945 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
4946
4947 mCodec->mPortEOS[kPortIndexInput] =
4948 mCodec->mPortEOS[kPortIndexOutput] = false;
4949
4950 mCodec->mInputEOSResult = OK;
4951
4952 mCodec->mDequeueCounter = 0;
4953 mCodec->mMetaDataBuffersToSubmit = 0;
4954 mCodec->mRepeatFrameDelayUs = -1ll;
4955 mCodec->mInputFormat.clear();
4956 mCodec->mOutputFormat.clear();
4957 mCodec->mBaseOutputFormat.clear();
4958
4959 if (mCodec->mShutdownInProgress) {
4960 bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
4961
4962 mCodec->mShutdownInProgress = false;
4963 mCodec->mKeepComponentAllocated = false;
4964
4965 onShutdown(keepComponentAllocated);
4966 }
4967 mCodec->mExplicitShutdown = false;
4968
4969 mCodec->processDeferredMessages();
4970 }
4971
onShutdown(bool keepComponentAllocated)4972 void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
4973 if (!keepComponentAllocated) {
4974 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
4975
4976 mCodec->changeState(mCodec->mUninitializedState);
4977 }
4978
4979 if (mCodec->mExplicitShutdown) {
4980 sp<AMessage> notify = mCodec->mNotify->dup();
4981 notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4982 notify->post();
4983 mCodec->mExplicitShutdown = false;
4984 }
4985 }
4986
onMessageReceived(const sp<AMessage> & msg)4987 bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
4988 bool handled = false;
4989
4990 switch (msg->what()) {
4991 case ACodec::kWhatConfigureComponent:
4992 {
4993 onConfigureComponent(msg);
4994 handled = true;
4995 break;
4996 }
4997
4998 case ACodec::kWhatCreateInputSurface:
4999 {
5000 onCreateInputSurface(msg);
5001 handled = true;
5002 break;
5003 }
5004
5005 case ACodec::kWhatStart:
5006 {
5007 onStart();
5008 handled = true;
5009 break;
5010 }
5011
5012 case ACodec::kWhatShutdown:
5013 {
5014 int32_t keepComponentAllocated;
5015 CHECK(msg->findInt32(
5016 "keepComponentAllocated", &keepComponentAllocated));
5017
5018 mCodec->mExplicitShutdown = true;
5019 onShutdown(keepComponentAllocated);
5020
5021 handled = true;
5022 break;
5023 }
5024
5025 case ACodec::kWhatFlush:
5026 {
5027 sp<AMessage> notify = mCodec->mNotify->dup();
5028 notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5029 notify->post();
5030
5031 handled = true;
5032 break;
5033 }
5034
5035 default:
5036 return BaseState::onMessageReceived(msg);
5037 }
5038
5039 return handled;
5040 }
5041
onConfigureComponent(const sp<AMessage> & msg)5042 bool ACodec::LoadedState::onConfigureComponent(
5043 const sp<AMessage> &msg) {
5044 ALOGV("onConfigureComponent");
5045
5046 CHECK(mCodec->mNode != NULL);
5047
5048 AString mime;
5049 CHECK(msg->findString("mime", &mime));
5050
5051 status_t err = mCodec->configureCodec(mime.c_str(), msg);
5052
5053 if (err != OK) {
5054 ALOGE("[%s] configureCodec returning error %d",
5055 mCodec->mComponentName.c_str(), err);
5056
5057 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5058 return false;
5059 }
5060
5061 {
5062 sp<AMessage> notify = mCodec->mNotify->dup();
5063 notify->setInt32("what", CodecBase::kWhatComponentConfigured);
5064 notify->setMessage("input-format", mCodec->mInputFormat);
5065 notify->setMessage("output-format", mCodec->mOutputFormat);
5066 notify->post();
5067 }
5068
5069 return true;
5070 }
5071
onCreateInputSurface(const sp<AMessage> &)5072 void ACodec::LoadedState::onCreateInputSurface(
5073 const sp<AMessage> & /* msg */) {
5074 ALOGV("onCreateInputSurface");
5075
5076 sp<AMessage> notify = mCodec->mNotify->dup();
5077 notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
5078
5079 sp<IGraphicBufferProducer> bufferProducer;
5080 status_t err;
5081
5082 err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput,
5083 &bufferProducer);
5084
5085 if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) {
5086 err = mCodec->mOMX->setInternalOption(
5087 mCodec->mNode,
5088 kPortIndexInput,
5089 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
5090 &mCodec->mRepeatFrameDelayUs,
5091 sizeof(mCodec->mRepeatFrameDelayUs));
5092
5093 if (err != OK) {
5094 ALOGE("[%s] Unable to configure option to repeat previous "
5095 "frames (err %d)",
5096 mCodec->mComponentName.c_str(),
5097 err);
5098 }
5099 }
5100
5101 if (err == OK && mCodec->mMaxPtsGapUs > 0ll) {
5102 err = mCodec->mOMX->setInternalOption(
5103 mCodec->mNode,
5104 kPortIndexInput,
5105 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
5106 &mCodec->mMaxPtsGapUs,
5107 sizeof(mCodec->mMaxPtsGapUs));
5108
5109 if (err != OK) {
5110 ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
5111 mCodec->mComponentName.c_str(),
5112 err);
5113 }
5114 }
5115
5116 if (err == OK && mCodec->mTimePerCaptureUs > 0ll
5117 && mCodec->mTimePerFrameUs > 0ll) {
5118 int64_t timeLapse[2];
5119 timeLapse[0] = mCodec->mTimePerFrameUs;
5120 timeLapse[1] = mCodec->mTimePerCaptureUs;
5121 err = mCodec->mOMX->setInternalOption(
5122 mCodec->mNode,
5123 kPortIndexInput,
5124 IOMX::INTERNAL_OPTION_TIME_LAPSE,
5125 &timeLapse[0],
5126 sizeof(timeLapse));
5127
5128 if (err != OK) {
5129 ALOGE("[%s] Unable to configure time lapse (err %d)",
5130 mCodec->mComponentName.c_str(),
5131 err);
5132 }
5133 }
5134
5135 if (err == OK && mCodec->mCreateInputBuffersSuspended) {
5136 bool suspend = true;
5137 err = mCodec->mOMX->setInternalOption(
5138 mCodec->mNode,
5139 kPortIndexInput,
5140 IOMX::INTERNAL_OPTION_SUSPEND,
5141 &suspend,
5142 sizeof(suspend));
5143
5144 if (err != OK) {
5145 ALOGE("[%s] Unable to configure option to suspend (err %d)",
5146 mCodec->mComponentName.c_str(),
5147 err);
5148 }
5149 }
5150
5151 if (err == OK) {
5152 notify->setObject("input-surface",
5153 new BufferProducerWrapper(bufferProducer));
5154 } else {
5155 // Can't use mCodec->signalError() here -- MediaCodec won't forward
5156 // the error through because it's in the "configured" state. We
5157 // send a kWhatInputSurfaceCreated with an error value instead.
5158 ALOGE("[%s] onCreateInputSurface returning error %d",
5159 mCodec->mComponentName.c_str(), err);
5160 notify->setInt32("err", err);
5161 }
5162 notify->post();
5163 }
5164
onStart()5165 void ACodec::LoadedState::onStart() {
5166 ALOGV("onStart");
5167
5168 CHECK_EQ(mCodec->mOMX->sendCommand(
5169 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
5170 (status_t)OK);
5171
5172 mCodec->changeState(mCodec->mLoadedToIdleState);
5173 }
5174
5175 ////////////////////////////////////////////////////////////////////////////////
5176
LoadedToIdleState(ACodec * codec)5177 ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
5178 : BaseState(codec) {
5179 }
5180
stateEntered()5181 void ACodec::LoadedToIdleState::stateEntered() {
5182 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
5183
5184 status_t err;
5185 if ((err = allocateBuffers()) != OK) {
5186 ALOGE("Failed to allocate buffers after transitioning to IDLE state "
5187 "(error 0x%08x)",
5188 err);
5189
5190 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5191
5192 mCodec->changeState(mCodec->mLoadedState);
5193 }
5194 }
5195
allocateBuffers()5196 status_t ACodec::LoadedToIdleState::allocateBuffers() {
5197 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
5198
5199 if (err != OK) {
5200 return err;
5201 }
5202
5203 return mCodec->allocateBuffersOnPort(kPortIndexOutput);
5204 }
5205
onMessageReceived(const sp<AMessage> & msg)5206 bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5207 switch (msg->what()) {
5208 case kWhatSetParameters:
5209 case kWhatShutdown:
5210 {
5211 mCodec->deferMessage(msg);
5212 return true;
5213 }
5214
5215 case kWhatSignalEndOfInputStream:
5216 {
5217 mCodec->onSignalEndOfInputStream();
5218 return true;
5219 }
5220
5221 case kWhatResume:
5222 {
5223 // We'll be active soon enough.
5224 return true;
5225 }
5226
5227 case kWhatFlush:
5228 {
5229 // We haven't even started yet, so we're flushed alright...
5230 sp<AMessage> notify = mCodec->mNotify->dup();
5231 notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5232 notify->post();
5233 return true;
5234 }
5235
5236 default:
5237 return BaseState::onMessageReceived(msg);
5238 }
5239 }
5240
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)5241 bool ACodec::LoadedToIdleState::onOMXEvent(
5242 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5243 switch (event) {
5244 case OMX_EventCmdComplete:
5245 {
5246 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5247 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5248
5249 CHECK_EQ(mCodec->mOMX->sendCommand(
5250 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
5251 (status_t)OK);
5252
5253 mCodec->changeState(mCodec->mIdleToExecutingState);
5254
5255 return true;
5256 }
5257
5258 default:
5259 return BaseState::onOMXEvent(event, data1, data2);
5260 }
5261 }
5262
5263 ////////////////////////////////////////////////////////////////////////////////
5264
IdleToExecutingState(ACodec * codec)5265 ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
5266 : BaseState(codec) {
5267 }
5268
stateEntered()5269 void ACodec::IdleToExecutingState::stateEntered() {
5270 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
5271 }
5272
onMessageReceived(const sp<AMessage> & msg)5273 bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5274 switch (msg->what()) {
5275 case kWhatSetParameters:
5276 case kWhatShutdown:
5277 {
5278 mCodec->deferMessage(msg);
5279 return true;
5280 }
5281
5282 case kWhatResume:
5283 {
5284 // We'll be active soon enough.
5285 return true;
5286 }
5287
5288 case kWhatFlush:
5289 {
5290 // We haven't even started yet, so we're flushed alright...
5291 sp<AMessage> notify = mCodec->mNotify->dup();
5292 notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5293 notify->post();
5294
5295 return true;
5296 }
5297
5298 case kWhatSignalEndOfInputStream:
5299 {
5300 mCodec->onSignalEndOfInputStream();
5301 return true;
5302 }
5303
5304 default:
5305 return BaseState::onMessageReceived(msg);
5306 }
5307 }
5308
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)5309 bool ACodec::IdleToExecutingState::onOMXEvent(
5310 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5311 switch (event) {
5312 case OMX_EventCmdComplete:
5313 {
5314 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5315 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
5316
5317 mCodec->mExecutingState->resume();
5318 mCodec->changeState(mCodec->mExecutingState);
5319
5320 return true;
5321 }
5322
5323 default:
5324 return BaseState::onOMXEvent(event, data1, data2);
5325 }
5326 }
5327
5328 ////////////////////////////////////////////////////////////////////////////////
5329
ExecutingState(ACodec * codec)5330 ACodec::ExecutingState::ExecutingState(ACodec *codec)
5331 : BaseState(codec),
5332 mActive(false) {
5333 }
5334
getPortMode(OMX_U32)5335 ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
5336 OMX_U32 /* portIndex */) {
5337 return RESUBMIT_BUFFERS;
5338 }
5339
submitOutputMetaBuffers()5340 void ACodec::ExecutingState::submitOutputMetaBuffers() {
5341 // submit as many buffers as there are input buffers with the codec
5342 // in case we are in port reconfiguring
5343 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5344 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5345
5346 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
5347 if (mCodec->submitOutputMetaDataBuffer() != OK)
5348 break;
5349 }
5350 }
5351
5352 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5353 mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5354 }
5355
submitRegularOutputBuffers()5356 void ACodec::ExecutingState::submitRegularOutputBuffers() {
5357 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
5358 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
5359
5360 if (mCodec->mNativeWindow != NULL) {
5361 CHECK(info->mStatus == BufferInfo::OWNED_BY_US
5362 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
5363
5364 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5365 continue;
5366 }
5367 } else {
5368 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5369 }
5370
5371 ALOGV("[%s] calling fillBuffer %p",
5372 mCodec->mComponentName.c_str(), info->mBufferID);
5373
5374 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
5375 (status_t)OK);
5376
5377 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5378 }
5379 }
5380
submitOutputBuffers()5381 void ACodec::ExecutingState::submitOutputBuffers() {
5382 submitRegularOutputBuffers();
5383 if (mCodec->mStoreMetaDataInOutputBuffers) {
5384 submitOutputMetaBuffers();
5385 }
5386 }
5387
resume()5388 void ACodec::ExecutingState::resume() {
5389 if (mActive) {
5390 ALOGV("[%s] We're already active, no need to resume.",
5391 mCodec->mComponentName.c_str());
5392
5393 return;
5394 }
5395
5396 submitOutputBuffers();
5397
5398 // Post all available input buffers
5399 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
5400 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
5401 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5402 if (info->mStatus == BufferInfo::OWNED_BY_US) {
5403 postFillThisBuffer(info);
5404 }
5405 }
5406
5407 mActive = true;
5408 }
5409
stateEntered()5410 void ACodec::ExecutingState::stateEntered() {
5411 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
5412
5413 mCodec->processDeferredMessages();
5414 }
5415
onMessageReceived(const sp<AMessage> & msg)5416 bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5417 bool handled = false;
5418
5419 switch (msg->what()) {
5420 case kWhatShutdown:
5421 {
5422 int32_t keepComponentAllocated;
5423 CHECK(msg->findInt32(
5424 "keepComponentAllocated", &keepComponentAllocated));
5425
5426 mCodec->mShutdownInProgress = true;
5427 mCodec->mExplicitShutdown = true;
5428 mCodec->mKeepComponentAllocated = keepComponentAllocated;
5429
5430 mActive = false;
5431
5432 CHECK_EQ(mCodec->mOMX->sendCommand(
5433 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
5434 (status_t)OK);
5435
5436 mCodec->changeState(mCodec->mExecutingToIdleState);
5437
5438 handled = true;
5439 break;
5440 }
5441
5442 case kWhatFlush:
5443 {
5444 ALOGV("[%s] ExecutingState flushing now "
5445 "(codec owns %d/%d input, %d/%d output).",
5446 mCodec->mComponentName.c_str(),
5447 mCodec->countBuffersOwnedByComponent(kPortIndexInput),
5448 mCodec->mBuffers[kPortIndexInput].size(),
5449 mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
5450 mCodec->mBuffers[kPortIndexOutput].size());
5451
5452 mActive = false;
5453
5454 CHECK_EQ(mCodec->mOMX->sendCommand(
5455 mCodec->mNode, OMX_CommandFlush, OMX_ALL),
5456 (status_t)OK);
5457
5458 mCodec->changeState(mCodec->mFlushingState);
5459 handled = true;
5460 break;
5461 }
5462
5463 case kWhatResume:
5464 {
5465 resume();
5466
5467 handled = true;
5468 break;
5469 }
5470
5471 case kWhatRequestIDRFrame:
5472 {
5473 status_t err = mCodec->requestIDRFrame();
5474 if (err != OK) {
5475 ALOGW("Requesting an IDR frame failed.");
5476 }
5477
5478 handled = true;
5479 break;
5480 }
5481
5482 case kWhatSetParameters:
5483 {
5484 sp<AMessage> params;
5485 CHECK(msg->findMessage("params", ¶ms));
5486
5487 status_t err = mCodec->setParameters(params);
5488
5489 sp<AMessage> reply;
5490 if (msg->findMessage("reply", &reply)) {
5491 reply->setInt32("err", err);
5492 reply->post();
5493 }
5494
5495 handled = true;
5496 break;
5497 }
5498
5499 case ACodec::kWhatSignalEndOfInputStream:
5500 {
5501 mCodec->onSignalEndOfInputStream();
5502 handled = true;
5503 break;
5504 }
5505
5506 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5507 case kWhatSubmitOutputMetaDataBufferIfEOS:
5508 {
5509 if (mCodec->mPortEOS[kPortIndexInput] &&
5510 !mCodec->mPortEOS[kPortIndexOutput]) {
5511 status_t err = mCodec->submitOutputMetaDataBuffer();
5512 if (err == OK) {
5513 mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5514 }
5515 }
5516 return true;
5517 }
5518
5519 default:
5520 handled = BaseState::onMessageReceived(msg);
5521 break;
5522 }
5523
5524 return handled;
5525 }
5526
setParameters(const sp<AMessage> & params)5527 status_t ACodec::setParameters(const sp<AMessage> ¶ms) {
5528 int32_t videoBitrate;
5529 if (params->findInt32("video-bitrate", &videoBitrate)) {
5530 OMX_VIDEO_CONFIG_BITRATETYPE configParams;
5531 InitOMXParams(&configParams);
5532 configParams.nPortIndex = kPortIndexOutput;
5533 configParams.nEncodeBitrate = videoBitrate;
5534
5535 status_t err = mOMX->setConfig(
5536 mNode,
5537 OMX_IndexConfigVideoBitrate,
5538 &configParams,
5539 sizeof(configParams));
5540
5541 if (err != OK) {
5542 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
5543 videoBitrate, err);
5544
5545 return err;
5546 }
5547 }
5548
5549 int64_t skipFramesBeforeUs;
5550 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
5551 status_t err =
5552 mOMX->setInternalOption(
5553 mNode,
5554 kPortIndexInput,
5555 IOMX::INTERNAL_OPTION_START_TIME,
5556 &skipFramesBeforeUs,
5557 sizeof(skipFramesBeforeUs));
5558
5559 if (err != OK) {
5560 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
5561 return err;
5562 }
5563 }
5564
5565 int32_t dropInputFrames;
5566 if (params->findInt32("drop-input-frames", &dropInputFrames)) {
5567 bool suspend = dropInputFrames != 0;
5568
5569 status_t err =
5570 mOMX->setInternalOption(
5571 mNode,
5572 kPortIndexInput,
5573 IOMX::INTERNAL_OPTION_SUSPEND,
5574 &suspend,
5575 sizeof(suspend));
5576
5577 if (err != OK) {
5578 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
5579 return err;
5580 }
5581 }
5582
5583 int32_t dummy;
5584 if (params->findInt32("request-sync", &dummy)) {
5585 status_t err = requestIDRFrame();
5586
5587 if (err != OK) {
5588 ALOGE("Requesting a sync frame failed w/ err %d", err);
5589 return err;
5590 }
5591 }
5592
5593 return OK;
5594 }
5595
onSignalEndOfInputStream()5596 void ACodec::onSignalEndOfInputStream() {
5597 sp<AMessage> notify = mNotify->dup();
5598 notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
5599
5600 status_t err = mOMX->signalEndOfInputStream(mNode);
5601 if (err != OK) {
5602 notify->setInt32("err", err);
5603 }
5604 notify->post();
5605 }
5606
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)5607 bool ACodec::ExecutingState::onOMXEvent(
5608 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5609 switch (event) {
5610 case OMX_EventPortSettingsChanged:
5611 {
5612 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
5613
5614 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
5615 mCodec->mMetaDataBuffersToSubmit = 0;
5616 CHECK_EQ(mCodec->mOMX->sendCommand(
5617 mCodec->mNode,
5618 OMX_CommandPortDisable, kPortIndexOutput),
5619 (status_t)OK);
5620
5621 mCodec->freeOutputBuffersNotOwnedByComponent();
5622
5623 mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
5624 } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
5625 mCodec->mSentFormat = false;
5626 } else {
5627 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
5628 mCodec->mComponentName.c_str(), data2);
5629 }
5630
5631 return true;
5632 }
5633
5634 case OMX_EventBufferFlag:
5635 {
5636 return true;
5637 }
5638
5639 default:
5640 return BaseState::onOMXEvent(event, data1, data2);
5641 }
5642 }
5643
5644 ////////////////////////////////////////////////////////////////////////////////
5645
OutputPortSettingsChangedState(ACodec * codec)5646 ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
5647 ACodec *codec)
5648 : BaseState(codec) {
5649 }
5650
getPortMode(OMX_U32 portIndex)5651 ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
5652 OMX_U32 portIndex) {
5653 if (portIndex == kPortIndexOutput) {
5654 return FREE_BUFFERS;
5655 }
5656
5657 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
5658
5659 return RESUBMIT_BUFFERS;
5660 }
5661
onMessageReceived(const sp<AMessage> & msg)5662 bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
5663 const sp<AMessage> &msg) {
5664 bool handled = false;
5665
5666 switch (msg->what()) {
5667 case kWhatFlush:
5668 case kWhatShutdown:
5669 case kWhatResume:
5670 {
5671 if (msg->what() == kWhatResume) {
5672 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
5673 }
5674
5675 mCodec->deferMessage(msg);
5676 handled = true;
5677 break;
5678 }
5679
5680 default:
5681 handled = BaseState::onMessageReceived(msg);
5682 break;
5683 }
5684
5685 return handled;
5686 }
5687
stateEntered()5688 void ACodec::OutputPortSettingsChangedState::stateEntered() {
5689 ALOGV("[%s] Now handling output port settings change",
5690 mCodec->mComponentName.c_str());
5691 }
5692
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)5693 bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
5694 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5695 switch (event) {
5696 case OMX_EventCmdComplete:
5697 {
5698 if (data1 == (OMX_U32)OMX_CommandPortDisable) {
5699 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5700
5701 ALOGV("[%s] Output port now disabled.",
5702 mCodec->mComponentName.c_str());
5703
5704 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
5705 mCodec->mDealer[kPortIndexOutput].clear();
5706
5707 CHECK_EQ(mCodec->mOMX->sendCommand(
5708 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
5709 (status_t)OK);
5710
5711 status_t err;
5712 if ((err = mCodec->allocateBuffersOnPort(
5713 kPortIndexOutput)) != OK) {
5714 ALOGE("Failed to allocate output port buffers after "
5715 "port reconfiguration (error 0x%08x)",
5716 err);
5717
5718 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5719
5720 // This is technically not correct, but appears to be
5721 // the only way to free the component instance.
5722 // Controlled transitioning from excecuting->idle
5723 // and idle->loaded seem impossible probably because
5724 // the output port never finishes re-enabling.
5725 mCodec->mShutdownInProgress = true;
5726 mCodec->mKeepComponentAllocated = false;
5727 mCodec->changeState(mCodec->mLoadedState);
5728 }
5729
5730 return true;
5731 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
5732 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5733
5734 mCodec->mSentFormat = false;
5735
5736 ALOGV("[%s] Output port now reenabled.",
5737 mCodec->mComponentName.c_str());
5738
5739 if (mCodec->mExecutingState->active()) {
5740 mCodec->mExecutingState->submitOutputBuffers();
5741 }
5742
5743 mCodec->changeState(mCodec->mExecutingState);
5744
5745 return true;
5746 }
5747
5748 return false;
5749 }
5750
5751 default:
5752 return false;
5753 }
5754 }
5755
5756 ////////////////////////////////////////////////////////////////////////////////
5757
ExecutingToIdleState(ACodec * codec)5758 ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
5759 : BaseState(codec),
5760 mComponentNowIdle(false) {
5761 }
5762
onMessageReceived(const sp<AMessage> & msg)5763 bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5764 bool handled = false;
5765
5766 switch (msg->what()) {
5767 case kWhatFlush:
5768 {
5769 // Don't send me a flush request if you previously wanted me
5770 // to shutdown.
5771 TRESPASS();
5772 break;
5773 }
5774
5775 case kWhatShutdown:
5776 {
5777 // We're already doing that...
5778
5779 handled = true;
5780 break;
5781 }
5782
5783 default:
5784 handled = BaseState::onMessageReceived(msg);
5785 break;
5786 }
5787
5788 return handled;
5789 }
5790
stateEntered()5791 void ACodec::ExecutingToIdleState::stateEntered() {
5792 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
5793
5794 mComponentNowIdle = false;
5795 mCodec->mSentFormat = false;
5796 }
5797
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)5798 bool ACodec::ExecutingToIdleState::onOMXEvent(
5799 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5800 switch (event) {
5801 case OMX_EventCmdComplete:
5802 {
5803 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5804 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5805
5806 mComponentNowIdle = true;
5807
5808 changeStateIfWeOwnAllBuffers();
5809
5810 return true;
5811 }
5812
5813 case OMX_EventPortSettingsChanged:
5814 case OMX_EventBufferFlag:
5815 {
5816 // We're shutting down and don't care about this anymore.
5817 return true;
5818 }
5819
5820 default:
5821 return BaseState::onOMXEvent(event, data1, data2);
5822 }
5823 }
5824
changeStateIfWeOwnAllBuffers()5825 void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
5826 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
5827 CHECK_EQ(mCodec->mOMX->sendCommand(
5828 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
5829 (status_t)OK);
5830
5831 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
5832 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
5833
5834 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
5835 && mCodec->mNativeWindow != NULL) {
5836 // We push enough 1x1 blank buffers to ensure that one of
5837 // them has made it to the display. This allows the OMX
5838 // component teardown to zero out any protected buffers
5839 // without the risk of scanning out one of those buffers.
5840 mCodec->pushBlankBuffersToNativeWindow();
5841 }
5842
5843 mCodec->changeState(mCodec->mIdleToLoadedState);
5844 }
5845 }
5846
onInputBufferFilled(const sp<AMessage> & msg)5847 void ACodec::ExecutingToIdleState::onInputBufferFilled(
5848 const sp<AMessage> &msg) {
5849 BaseState::onInputBufferFilled(msg);
5850
5851 changeStateIfWeOwnAllBuffers();
5852 }
5853
onOutputBufferDrained(const sp<AMessage> & msg)5854 void ACodec::ExecutingToIdleState::onOutputBufferDrained(
5855 const sp<AMessage> &msg) {
5856 BaseState::onOutputBufferDrained(msg);
5857
5858 changeStateIfWeOwnAllBuffers();
5859 }
5860
5861 ////////////////////////////////////////////////////////////////////////////////
5862
IdleToLoadedState(ACodec * codec)5863 ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
5864 : BaseState(codec) {
5865 }
5866
onMessageReceived(const sp<AMessage> & msg)5867 bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
5868 bool handled = false;
5869
5870 switch (msg->what()) {
5871 case kWhatShutdown:
5872 {
5873 // We're already doing that...
5874
5875 handled = true;
5876 break;
5877 }
5878
5879 case kWhatFlush:
5880 {
5881 // Don't send me a flush request if you previously wanted me
5882 // to shutdown.
5883 TRESPASS();
5884 break;
5885 }
5886
5887 default:
5888 handled = BaseState::onMessageReceived(msg);
5889 break;
5890 }
5891
5892 return handled;
5893 }
5894
stateEntered()5895 void ACodec::IdleToLoadedState::stateEntered() {
5896 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
5897 }
5898
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)5899 bool ACodec::IdleToLoadedState::onOMXEvent(
5900 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5901 switch (event) {
5902 case OMX_EventCmdComplete:
5903 {
5904 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5905 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
5906
5907 mCodec->changeState(mCodec->mLoadedState);
5908
5909 return true;
5910 }
5911
5912 default:
5913 return BaseState::onOMXEvent(event, data1, data2);
5914 }
5915 }
5916
5917 ////////////////////////////////////////////////////////////////////////////////
5918
FlushingState(ACodec * codec)5919 ACodec::FlushingState::FlushingState(ACodec *codec)
5920 : BaseState(codec) {
5921 }
5922
stateEntered()5923 void ACodec::FlushingState::stateEntered() {
5924 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
5925
5926 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
5927 }
5928
onMessageReceived(const sp<AMessage> & msg)5929 bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
5930 bool handled = false;
5931
5932 switch (msg->what()) {
5933 case kWhatShutdown:
5934 {
5935 mCodec->deferMessage(msg);
5936 break;
5937 }
5938
5939 case kWhatFlush:
5940 {
5941 // We're already doing this right now.
5942 handled = true;
5943 break;
5944 }
5945
5946 default:
5947 handled = BaseState::onMessageReceived(msg);
5948 break;
5949 }
5950
5951 return handled;
5952 }
5953
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)5954 bool ACodec::FlushingState::onOMXEvent(
5955 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5956 ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
5957 mCodec->mComponentName.c_str(), event, data1);
5958
5959 switch (event) {
5960 case OMX_EventCmdComplete:
5961 {
5962 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
5963
5964 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
5965 CHECK(!mFlushComplete[data2]);
5966 mFlushComplete[data2] = true;
5967
5968 if (mFlushComplete[kPortIndexInput]
5969 && mFlushComplete[kPortIndexOutput]) {
5970 changeStateIfWeOwnAllBuffers();
5971 }
5972 } else {
5973 CHECK_EQ(data2, OMX_ALL);
5974 CHECK(mFlushComplete[kPortIndexInput]);
5975 CHECK(mFlushComplete[kPortIndexOutput]);
5976
5977 changeStateIfWeOwnAllBuffers();
5978 }
5979
5980 return true;
5981 }
5982
5983 case OMX_EventPortSettingsChanged:
5984 {
5985 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
5986 msg->setInt32("type", omx_message::EVENT);
5987 msg->setInt32("node", mCodec->mNode);
5988 msg->setInt32("event", event);
5989 msg->setInt32("data1", data1);
5990 msg->setInt32("data2", data2);
5991
5992 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
5993 mCodec->mComponentName.c_str());
5994
5995 mCodec->deferMessage(msg);
5996
5997 return true;
5998 }
5999
6000 default:
6001 return BaseState::onOMXEvent(event, data1, data2);
6002 }
6003
6004 return true;
6005 }
6006
onOutputBufferDrained(const sp<AMessage> & msg)6007 void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
6008 BaseState::onOutputBufferDrained(msg);
6009
6010 changeStateIfWeOwnAllBuffers();
6011 }
6012
onInputBufferFilled(const sp<AMessage> & msg)6013 void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
6014 BaseState::onInputBufferFilled(msg);
6015
6016 changeStateIfWeOwnAllBuffers();
6017 }
6018
changeStateIfWeOwnAllBuffers()6019 void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
6020 if (mFlushComplete[kPortIndexInput]
6021 && mFlushComplete[kPortIndexOutput]
6022 && mCodec->allYourBuffersAreBelongToUs()) {
6023 // We now own all buffers except possibly those still queued with
6024 // the native window for rendering. Let's get those back as well.
6025 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
6026
6027 sp<AMessage> notify = mCodec->mNotify->dup();
6028 notify->setInt32("what", CodecBase::kWhatFlushCompleted);
6029 notify->post();
6030
6031 mCodec->mPortEOS[kPortIndexInput] =
6032 mCodec->mPortEOS[kPortIndexOutput] = false;
6033
6034 mCodec->mInputEOSResult = OK;
6035
6036 if (mCodec->mSkipCutBuffer != NULL) {
6037 mCodec->mSkipCutBuffer->clear();
6038 }
6039
6040 mCodec->changeState(mCodec->mExecutingState);
6041 }
6042 }
6043
6044 } // namespace android
6045