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 <gui/Surface.h>
28
29 #include <media/stagefright/ACodec.h>
30
31 #include <binder/MemoryDealer.h>
32
33 #include <media/stagefright/foundation/hexdump.h>
34 #include <media/stagefright/foundation/ABuffer.h>
35 #include <media/stagefright/foundation/ADebug.h>
36 #include <media/stagefright/foundation/AMessage.h>
37 #include <media/stagefright/foundation/AUtils.h>
38
39 #include <media/stagefright/BufferProducerWrapper.h>
40 #include <media/stagefright/MediaCodec.h>
41 #include <media/stagefright/MediaCodecList.h>
42 #include <media/stagefright/MediaDefs.h>
43 #include <media/stagefright/OMXClient.h>
44 #include <media/stagefright/PersistentSurface.h>
45 #include <media/stagefright/SurfaceUtils.h>
46 #include <media/hardware/HardwareAPI.h>
47 #include <media/OMXBuffer.h>
48 #include <media/omx/1.0/WOmxNode.h>
49
50 #include <hidlmemory/mapping.h>
51
52 #include <media/openmax/OMX_AudioExt.h>
53 #include <media/openmax/OMX_VideoExt.h>
54 #include <media/openmax/OMX_Component.h>
55 #include <media/openmax/OMX_IndexExt.h>
56 #include <media/openmax/OMX_AsString.h>
57
58 #include "include/avc_utils.h"
59 #include "include/ACodecBufferChannel.h"
60 #include "include/DataConverter.h"
61 #include "include/SecureBuffer.h"
62 #include "include/SharedMemoryBuffer.h"
63 #include <media/stagefright/omx/OMXUtils.h>
64
65 namespace android {
66
67 using binder::Status;
68
69 enum {
70 kMaxIndicesToCheck = 32, // used when enumerating supported formats and profiles
71 };
72
73 // OMX errors are directly mapped into status_t range if
74 // there is no corresponding MediaError status code.
75 // Use the statusFromOMXError(int32_t omxError) function.
76 //
77 // Currently this is a direct map.
78 // See frameworks/native/include/media/openmax/OMX_Core.h
79 //
80 // Vendor OMX errors from 0x90000000 - 0x9000FFFF
81 // Extension OMX errors from 0x8F000000 - 0x90000000
82 // Standard OMX errors from 0x80001000 - 0x80001024 (0x80001024 current)
83 //
84
85 // returns true if err is a recognized OMX error code.
86 // as OMX error is OMX_S32, this is an int32_t type
isOMXError(int32_t err)87 static inline bool isOMXError(int32_t err) {
88 return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX);
89 }
90
91 // converts an OMX error to a status_t
statusFromOMXError(int32_t omxError)92 static inline status_t statusFromOMXError(int32_t omxError) {
93 switch (omxError) {
94 case OMX_ErrorInvalidComponentName:
95 case OMX_ErrorComponentNotFound:
96 return NAME_NOT_FOUND; // can trigger illegal argument error for provided names.
97 default:
98 return isOMXError(omxError) ? omxError : 0; // no translation required
99 }
100 }
101
statusFromBinderStatus(const Status & status)102 static inline status_t statusFromBinderStatus(const Status &status) {
103 if (status.isOk()) {
104 return OK;
105 }
106 status_t err;
107 if ((err = status.serviceSpecificErrorCode()) != OK) {
108 return err;
109 }
110 if ((err = status.transactionError()) != OK) {
111 return err;
112 }
113 // Other exception
114 return UNKNOWN_ERROR;
115 }
116
117 // checks and converts status_t to a non-side-effect status_t
makeNoSideEffectStatus(status_t err)118 static inline status_t makeNoSideEffectStatus(status_t err) {
119 switch (err) {
120 // the following errors have side effects and may come
121 // from other code modules. Remap for safety reasons.
122 case INVALID_OPERATION:
123 case DEAD_OBJECT:
124 return UNKNOWN_ERROR;
125 default:
126 return err;
127 }
128 }
129
130 struct MessageList : public RefBase {
MessageListandroid::MessageList131 MessageList() {
132 }
~MessageListandroid::MessageList133 virtual ~MessageList() {
134 }
getListandroid::MessageList135 std::list<sp<AMessage> > &getList() { return mList; }
136 private:
137 std::list<sp<AMessage> > mList;
138
139 DISALLOW_EVIL_CONSTRUCTORS(MessageList);
140 };
141
getCopyConverter()142 static sp<DataConverter> getCopyConverter() {
143 static pthread_once_t once = PTHREAD_ONCE_INIT; // const-inited
144 static sp<DataConverter> sCopyConverter; // zero-inited
145 pthread_once(&once, [](){ sCopyConverter = new DataConverter(); });
146 return sCopyConverter;
147 }
148
149 struct CodecObserver : public BnOMXObserver {
CodecObserverandroid::CodecObserver150 CodecObserver() {}
151
setNotificationMessageandroid::CodecObserver152 void setNotificationMessage(const sp<AMessage> &msg) {
153 mNotify = msg;
154 }
155
156 // from IOMXObserver
onMessagesandroid::CodecObserver157 virtual void onMessages(const std::list<omx_message> &messages) {
158 if (messages.empty()) {
159 return;
160 }
161
162 sp<AMessage> notify = mNotify->dup();
163 sp<MessageList> msgList = new MessageList();
164 for (std::list<omx_message>::const_iterator it = messages.cbegin();
165 it != messages.cend(); ++it) {
166 const omx_message &omx_msg = *it;
167
168 sp<AMessage> msg = new AMessage;
169 msg->setInt32("type", omx_msg.type);
170 switch (omx_msg.type) {
171 case omx_message::EVENT:
172 {
173 msg->setInt32("event", omx_msg.u.event_data.event);
174 msg->setInt32("data1", omx_msg.u.event_data.data1);
175 msg->setInt32("data2", omx_msg.u.event_data.data2);
176 break;
177 }
178
179 case omx_message::EMPTY_BUFFER_DONE:
180 {
181 msg->setInt32("buffer", omx_msg.u.buffer_data.buffer);
182 msg->setInt32("fence_fd", omx_msg.fenceFd);
183 break;
184 }
185
186 case omx_message::FILL_BUFFER_DONE:
187 {
188 msg->setInt32(
189 "buffer", omx_msg.u.extended_buffer_data.buffer);
190 msg->setInt32(
191 "range_offset",
192 omx_msg.u.extended_buffer_data.range_offset);
193 msg->setInt32(
194 "range_length",
195 omx_msg.u.extended_buffer_data.range_length);
196 msg->setInt32(
197 "flags",
198 omx_msg.u.extended_buffer_data.flags);
199 msg->setInt64(
200 "timestamp",
201 omx_msg.u.extended_buffer_data.timestamp);
202 msg->setInt32(
203 "fence_fd", omx_msg.fenceFd);
204 break;
205 }
206
207 case omx_message::FRAME_RENDERED:
208 {
209 msg->setInt64(
210 "media_time_us", omx_msg.u.render_data.timestamp);
211 msg->setInt64(
212 "system_nano", omx_msg.u.render_data.nanoTime);
213 break;
214 }
215
216 default:
217 ALOGE("Unrecognized message type: %d", omx_msg.type);
218 break;
219 }
220 msgList->getList().push_back(msg);
221 }
222 notify->setObject("messages", msgList);
223 notify->post();
224 }
225
226 protected:
~CodecObserverandroid::CodecObserver227 virtual ~CodecObserver() {}
228
229 private:
230 sp<AMessage> mNotify;
231
232 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
233 };
234
235 ////////////////////////////////////////////////////////////////////////////////
236
237 struct ACodec::BaseState : public AState {
238 explicit BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
239
240 protected:
241 enum PortMode {
242 KEEP_BUFFERS,
243 RESUBMIT_BUFFERS,
244 FREE_BUFFERS,
245 };
246
247 ACodec *mCodec;
248
249 virtual PortMode getPortMode(OMX_U32 portIndex);
250
251 virtual void stateExited();
252 virtual bool onMessageReceived(const sp<AMessage> &msg);
253
254 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
255
256 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
257 virtual void onInputBufferFilled(const sp<AMessage> &msg);
258
259 void postFillThisBuffer(BufferInfo *info);
260
261 private:
262 // Handles an OMX message. Returns true iff message was handled.
263 bool onOMXMessage(const sp<AMessage> &msg);
264
265 // Handles a list of messages. Returns true iff messages were handled.
266 bool onOMXMessageList(const sp<AMessage> &msg);
267
268 // returns true iff this message is for this component and the component is alive
269 bool checkOMXMessage(const sp<AMessage> &msg);
270
271 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd);
272
273 bool onOMXFillBufferDone(
274 IOMX::buffer_id bufferID,
275 size_t rangeOffset, size_t rangeLength,
276 OMX_U32 flags,
277 int64_t timeUs,
278 int fenceFd);
279
280 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
281
282 void getMoreInputDataIfPossible();
283
284 DISALLOW_EVIL_CONSTRUCTORS(BaseState);
285 };
286
287 ////////////////////////////////////////////////////////////////////////////////
288
289 struct ACodec::DeathNotifier :
290 public IBinder::DeathRecipient,
291 public ::android::hardware::hidl_death_recipient {
DeathNotifierandroid::ACodec::DeathNotifier292 explicit DeathNotifier(const sp<AMessage> ¬ify)
293 : mNotify(notify) {
294 }
295
binderDiedandroid::ACodec::DeathNotifier296 virtual void binderDied(const wp<IBinder> &) {
297 mNotify->post();
298 }
299
serviceDiedandroid::ACodec::DeathNotifier300 virtual void serviceDied(
301 uint64_t /* cookie */,
302 const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
303 mNotify->post();
304 }
305
306 protected:
~DeathNotifierandroid::ACodec::DeathNotifier307 virtual ~DeathNotifier() {}
308
309 private:
310 sp<AMessage> mNotify;
311
312 DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
313 };
314
315 struct ACodec::UninitializedState : public ACodec::BaseState {
316 explicit UninitializedState(ACodec *codec);
317
318 protected:
319 virtual bool onMessageReceived(const sp<AMessage> &msg);
320 virtual void stateEntered();
321
322 private:
323 void onSetup(const sp<AMessage> &msg);
324 bool onAllocateComponent(const sp<AMessage> &msg);
325
326 sp<DeathNotifier> mDeathNotifier;
327
328 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
329 };
330
331 ////////////////////////////////////////////////////////////////////////////////
332
333 struct ACodec::LoadedState : public ACodec::BaseState {
334 explicit LoadedState(ACodec *codec);
335
336 protected:
337 virtual bool onMessageReceived(const sp<AMessage> &msg);
338 virtual void stateEntered();
339
340 private:
341 friend struct ACodec::UninitializedState;
342
343 bool onConfigureComponent(const sp<AMessage> &msg);
344 void onCreateInputSurface(const sp<AMessage> &msg);
345 void onSetInputSurface(const sp<AMessage> &msg);
346 void onStart();
347 void onShutdown(bool keepComponentAllocated);
348
349 status_t setupInputSurface();
350
351 DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
352 };
353
354 ////////////////////////////////////////////////////////////////////////////////
355
356 struct ACodec::LoadedToIdleState : public ACodec::BaseState {
357 explicit LoadedToIdleState(ACodec *codec);
358
359 protected:
360 virtual bool onMessageReceived(const sp<AMessage> &msg);
361 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
362 virtual void stateEntered();
363
364 private:
365 status_t allocateBuffers();
366
367 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
368 };
369
370 ////////////////////////////////////////////////////////////////////////////////
371
372 struct ACodec::IdleToExecutingState : public ACodec::BaseState {
373 explicit IdleToExecutingState(ACodec *codec);
374
375 protected:
376 virtual bool onMessageReceived(const sp<AMessage> &msg);
377 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
378 virtual void stateEntered();
379
380 private:
381 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
382 };
383
384 ////////////////////////////////////////////////////////////////////////////////
385
386 struct ACodec::ExecutingState : public ACodec::BaseState {
387 explicit ExecutingState(ACodec *codec);
388
389 void submitRegularOutputBuffers();
390 void submitOutputMetaBuffers();
391 void submitOutputBuffers();
392
393 // Submit output buffers to the decoder, submit input buffers to client
394 // to fill with data.
395 void resume();
396
397 // Returns true iff input and output buffers are in play.
activeandroid::ACodec::ExecutingState398 bool active() const { return mActive; }
399
400 protected:
401 virtual PortMode getPortMode(OMX_U32 portIndex);
402 virtual bool onMessageReceived(const sp<AMessage> &msg);
403 virtual void stateEntered();
404
405 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
406 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
407
408 private:
409 bool mActive;
410
411 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
412 };
413
414 ////////////////////////////////////////////////////////////////////////////////
415
416 struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
417 explicit OutputPortSettingsChangedState(ACodec *codec);
418
419 protected:
420 virtual PortMode getPortMode(OMX_U32 portIndex);
421 virtual bool onMessageReceived(const sp<AMessage> &msg);
422 virtual void stateEntered();
423
424 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
425 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
426
427 private:
428 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
429 };
430
431 ////////////////////////////////////////////////////////////////////////////////
432
433 struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
434 explicit ExecutingToIdleState(ACodec *codec);
435
436 protected:
437 virtual bool onMessageReceived(const sp<AMessage> &msg);
438 virtual void stateEntered();
439
440 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
441
442 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
443 virtual void onInputBufferFilled(const sp<AMessage> &msg);
444
445 private:
446 void changeStateIfWeOwnAllBuffers();
447
448 bool mComponentNowIdle;
449
450 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
451 };
452
453 ////////////////////////////////////////////////////////////////////////////////
454
455 struct ACodec::IdleToLoadedState : public ACodec::BaseState {
456 explicit IdleToLoadedState(ACodec *codec);
457
458 protected:
459 virtual bool onMessageReceived(const sp<AMessage> &msg);
460 virtual void stateEntered();
461
462 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
463
464 private:
465 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
466 };
467
468 ////////////////////////////////////////////////////////////////////////////////
469
470 struct ACodec::FlushingState : public ACodec::BaseState {
471 explicit FlushingState(ACodec *codec);
472
473 protected:
474 virtual bool onMessageReceived(const sp<AMessage> &msg);
475 virtual void stateEntered();
476
477 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
478
479 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
480 virtual void onInputBufferFilled(const sp<AMessage> &msg);
481
482 private:
483 bool mFlushComplete[2];
484
485 void changeStateIfWeOwnAllBuffers();
486
487 DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
488 };
489
490 ////////////////////////////////////////////////////////////////////////////////
491
setWriteFence(int fenceFd,const char * dbg)492 void ACodec::BufferInfo::setWriteFence(int fenceFd, const char *dbg) {
493 if (mFenceFd >= 0) {
494 ALOGW("OVERWRITE OF %s fence %d by write fence %d in %s",
495 mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
496 }
497 mFenceFd = fenceFd;
498 mIsReadFence = false;
499 }
500
setReadFence(int fenceFd,const char * dbg)501 void ACodec::BufferInfo::setReadFence(int fenceFd, const char *dbg) {
502 if (mFenceFd >= 0) {
503 ALOGW("OVERWRITE OF %s fence %d by read fence %d in %s",
504 mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
505 }
506 mFenceFd = fenceFd;
507 mIsReadFence = true;
508 }
509
checkWriteFence(const char * dbg)510 void ACodec::BufferInfo::checkWriteFence(const char *dbg) {
511 if (mFenceFd >= 0 && mIsReadFence) {
512 ALOGD("REUSING read fence %d as write fence in %s", mFenceFd, dbg);
513 }
514 }
515
checkReadFence(const char * dbg)516 void ACodec::BufferInfo::checkReadFence(const char *dbg) {
517 if (mFenceFd >= 0 && !mIsReadFence) {
518 ALOGD("REUSING write fence %d as read fence in %s", mFenceFd, dbg);
519 }
520 }
521
522 ////////////////////////////////////////////////////////////////////////////////
523
ACodec()524 ACodec::ACodec()
525 : mSampleRate(0),
526 mNodeGeneration(0),
527 mUsingNativeWindow(false),
528 mNativeWindowUsageBits(0),
529 mLastNativeWindowDataSpace(HAL_DATASPACE_UNKNOWN),
530 mIsVideo(false),
531 mIsEncoder(false),
532 mFatalError(false),
533 mShutdownInProgress(false),
534 mExplicitShutdown(false),
535 mIsLegacyVP9Decoder(false),
536 mEncoderDelay(0),
537 mEncoderPadding(0),
538 mRotationDegrees(0),
539 mChannelMaskPresent(false),
540 mChannelMask(0),
541 mDequeueCounter(0),
542 mMetadataBuffersToSubmit(0),
543 mNumUndequeuedBuffers(0),
544 mRepeatFrameDelayUs(-1ll),
545 mMaxPtsGapUs(-1ll),
546 mMaxFps(-1),
547 mFps(-1.0),
548 mCaptureFps(-1.0),
549 mCreateInputBuffersSuspended(false),
550 mLatency(0),
551 mTunneled(false),
552 mDescribeColorAspectsIndex((OMX_INDEXTYPE)0),
553 mDescribeHDRStaticInfoIndex((OMX_INDEXTYPE)0),
554 mStateGeneration(0),
555 mVendorExtensionsStatus(kExtensionsUnchecked) {
556 mUninitializedState = new UninitializedState(this);
557 mLoadedState = new LoadedState(this);
558 mLoadedToIdleState = new LoadedToIdleState(this);
559 mIdleToExecutingState = new IdleToExecutingState(this);
560 mExecutingState = new ExecutingState(this);
561
562 mOutputPortSettingsChangedState =
563 new OutputPortSettingsChangedState(this);
564
565 mExecutingToIdleState = new ExecutingToIdleState(this);
566 mIdleToLoadedState = new IdleToLoadedState(this);
567 mFlushingState = new FlushingState(this);
568
569 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
570 mInputEOSResult = OK;
571
572 mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
573 mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
574
575 memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
576
577 changeState(mUninitializedState);
578
579 mTrebleFlag = false;
580 }
581
~ACodec()582 ACodec::~ACodec() {
583 }
584
initiateSetup(const sp<AMessage> & msg)585 void ACodec::initiateSetup(const sp<AMessage> &msg) {
586 msg->setWhat(kWhatSetup);
587 msg->setTarget(this);
588 msg->post();
589 }
590
getBufferChannel()591 std::shared_ptr<BufferChannelBase> ACodec::getBufferChannel() {
592 if (!mBufferChannel) {
593 mBufferChannel = std::make_shared<ACodecBufferChannel>(
594 new AMessage(kWhatInputBufferFilled, this),
595 new AMessage(kWhatOutputBufferDrained, this));
596 }
597 return mBufferChannel;
598 }
599
signalSetParameters(const sp<AMessage> & params)600 void ACodec::signalSetParameters(const sp<AMessage> ¶ms) {
601 sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
602 msg->setMessage("params", params);
603 msg->post();
604 }
605
initiateAllocateComponent(const sp<AMessage> & msg)606 void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
607 msg->setWhat(kWhatAllocateComponent);
608 msg->setTarget(this);
609 msg->post();
610 }
611
initiateConfigureComponent(const sp<AMessage> & msg)612 void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
613 msg->setWhat(kWhatConfigureComponent);
614 msg->setTarget(this);
615 msg->post();
616 }
617
setSurface(const sp<Surface> & surface)618 status_t ACodec::setSurface(const sp<Surface> &surface) {
619 sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
620 msg->setObject("surface", surface);
621
622 sp<AMessage> response;
623 status_t err = msg->postAndAwaitResponse(&response);
624
625 if (err == OK) {
626 (void)response->findInt32("err", &err);
627 }
628 return err;
629 }
630
initiateCreateInputSurface()631 void ACodec::initiateCreateInputSurface() {
632 (new AMessage(kWhatCreateInputSurface, this))->post();
633 }
634
initiateSetInputSurface(const sp<PersistentSurface> & surface)635 void ACodec::initiateSetInputSurface(
636 const sp<PersistentSurface> &surface) {
637 sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
638 msg->setObject("input-surface", surface);
639 msg->post();
640 }
641
signalEndOfInputStream()642 void ACodec::signalEndOfInputStream() {
643 (new AMessage(kWhatSignalEndOfInputStream, this))->post();
644 }
645
initiateStart()646 void ACodec::initiateStart() {
647 (new AMessage(kWhatStart, this))->post();
648 }
649
signalFlush()650 void ACodec::signalFlush() {
651 ALOGV("[%s] signalFlush", mComponentName.c_str());
652 (new AMessage(kWhatFlush, this))->post();
653 }
654
signalResume()655 void ACodec::signalResume() {
656 (new AMessage(kWhatResume, this))->post();
657 }
658
initiateShutdown(bool keepComponentAllocated)659 void ACodec::initiateShutdown(bool keepComponentAllocated) {
660 sp<AMessage> msg = new AMessage(kWhatShutdown, this);
661 msg->setInt32("keepComponentAllocated", keepComponentAllocated);
662 msg->post();
663 if (!keepComponentAllocated) {
664 // ensure shutdown completes in 3 seconds
665 (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000);
666 }
667 }
668
signalRequestIDRFrame()669 void ACodec::signalRequestIDRFrame() {
670 (new AMessage(kWhatRequestIDRFrame, this))->post();
671 }
672
673 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
674 // Some codecs may return input buffers before having them processed.
675 // This causes a halt if we already signaled an EOS on the input
676 // port. For now keep submitting an output buffer if there was an
677 // EOS on the input port, but not yet on the output port.
signalSubmitOutputMetadataBufferIfEOS_workaround()678 void ACodec::signalSubmitOutputMetadataBufferIfEOS_workaround() {
679 if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
680 mMetadataBuffersToSubmit > 0) {
681 (new AMessage(kWhatSubmitOutputMetadataBufferIfEOS, this))->post();
682 }
683 }
684
handleSetSurface(const sp<Surface> & surface)685 status_t ACodec::handleSetSurface(const sp<Surface> &surface) {
686 // allow keeping unset surface
687 if (surface == NULL) {
688 if (mNativeWindow != NULL) {
689 ALOGW("cannot unset a surface");
690 return INVALID_OPERATION;
691 }
692 return OK;
693 }
694
695 // cannot switch from bytebuffers to surface
696 if (mNativeWindow == NULL) {
697 ALOGW("component was not configured with a surface");
698 return INVALID_OPERATION;
699 }
700
701 ANativeWindow *nativeWindow = surface.get();
702 // if we have not yet started the codec, we can simply set the native window
703 if (mBuffers[kPortIndexInput].size() == 0) {
704 mNativeWindow = surface;
705 return OK;
706 }
707
708 // we do not support changing a tunneled surface after start
709 if (mTunneled) {
710 ALOGW("cannot change tunneled surface");
711 return INVALID_OPERATION;
712 }
713
714 int usageBits = 0;
715 // no need to reconnect as we will not dequeue all buffers
716 status_t err = setupNativeWindowSizeFormatAndUsage(
717 nativeWindow, &usageBits, !storingMetadataInDecodedBuffers());
718 if (err != OK) {
719 return err;
720 }
721
722 int ignoredFlags = kVideoGrallocUsage;
723 // New output surface is not allowed to add new usage flag except ignored ones.
724 if ((usageBits & ~(mNativeWindowUsageBits | ignoredFlags)) != 0) {
725 ALOGW("cannot change usage from %#x to %#x", mNativeWindowUsageBits, usageBits);
726 return BAD_VALUE;
727 }
728
729 // get min undequeued count. We cannot switch to a surface that has a higher
730 // undequeued count than we allocated.
731 int minUndequeuedBuffers = 0;
732 err = nativeWindow->query(
733 nativeWindow, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
734 &minUndequeuedBuffers);
735 if (err != 0) {
736 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
737 strerror(-err), -err);
738 return err;
739 }
740 if (minUndequeuedBuffers > (int)mNumUndequeuedBuffers) {
741 ALOGE("new surface holds onto more buffers (%d) than planned for (%zu)",
742 minUndequeuedBuffers, mNumUndequeuedBuffers);
743 return BAD_VALUE;
744 }
745
746 // we cannot change the number of output buffers while OMX is running
747 // set up surface to the same count
748 Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput];
749 ALOGV("setting up surface for %zu buffers", buffers.size());
750
751 err = native_window_set_buffer_count(nativeWindow, buffers.size());
752 if (err != 0) {
753 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
754 -err);
755 return err;
756 }
757
758 // need to enable allocation when attaching
759 surface->getIGraphicBufferProducer()->allowAllocation(true);
760
761 // for meta data mode, we move dequeud buffers to the new surface.
762 // for non-meta mode, we must move all registered buffers
763 for (size_t i = 0; i < buffers.size(); ++i) {
764 const BufferInfo &info = buffers[i];
765 // skip undequeued buffers for meta data mode
766 if (storingMetadataInDecodedBuffers()
767 && info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
768 ALOGV("skipping buffer");
769 continue;
770 }
771 ALOGV("attaching buffer %p", info.mGraphicBuffer->getNativeBuffer());
772
773 err = surface->attachBuffer(info.mGraphicBuffer->getNativeBuffer());
774 if (err != OK) {
775 ALOGE("failed to attach buffer %p to the new surface: %s (%d)",
776 info.mGraphicBuffer->getNativeBuffer(),
777 strerror(-err), -err);
778 return err;
779 }
780 }
781
782 // cancel undequeued buffers to new surface
783 if (!storingMetadataInDecodedBuffers()) {
784 for (size_t i = 0; i < buffers.size(); ++i) {
785 BufferInfo &info = buffers.editItemAt(i);
786 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
787 ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer());
788 err = nativeWindow->cancelBuffer(
789 nativeWindow, info.mGraphicBuffer->getNativeBuffer(), info.mFenceFd);
790 info.mFenceFd = -1;
791 if (err != OK) {
792 ALOGE("failed to cancel buffer %p to the new surface: %s (%d)",
793 info.mGraphicBuffer->getNativeBuffer(),
794 strerror(-err), -err);
795 return err;
796 }
797 }
798 }
799 // disallow further allocation
800 (void)surface->getIGraphicBufferProducer()->allowAllocation(false);
801 }
802
803 // push blank buffers to previous window if requested
804 if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) {
805 pushBlankBuffersToNativeWindow(mNativeWindow.get());
806 }
807
808 mNativeWindow = nativeWindow;
809 mNativeWindowUsageBits = usageBits;
810 return OK;
811 }
812
setPortMode(int32_t portIndex,IOMX::PortMode mode)813 status_t ACodec::setPortMode(int32_t portIndex, IOMX::PortMode mode) {
814 status_t err = mOMXNode->setPortMode(portIndex, mode);
815 if (err != OK) {
816 ALOGE("[%s] setPortMode on %s to %s failed w/ err %d",
817 mComponentName.c_str(),
818 portIndex == kPortIndexInput ? "input" : "output",
819 asString(mode),
820 err);
821 return err;
822 }
823
824 mPortMode[portIndex] = mode;
825 return OK;
826 }
827
allocateBuffersOnPort(OMX_U32 portIndex)828 status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
829 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
830
831 if (getTrebleFlag()) {
832 CHECK(mAllocator[portIndex] == NULL);
833 } else {
834 CHECK(mDealer[portIndex] == NULL);
835 }
836 CHECK(mBuffers[portIndex].isEmpty());
837
838 status_t err;
839 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
840 if (storingMetadataInDecodedBuffers()) {
841 err = allocateOutputMetadataBuffers();
842 } else {
843 err = allocateOutputBuffersFromNativeWindow();
844 }
845 } else {
846 OMX_PARAM_PORTDEFINITIONTYPE def;
847 InitOMXParams(&def);
848 def.nPortIndex = portIndex;
849
850 err = mOMXNode->getParameter(
851 OMX_IndexParamPortDefinition, &def, sizeof(def));
852
853 if (err == OK) {
854 const IOMX::PortMode &mode = mPortMode[portIndex];
855 size_t bufSize = def.nBufferSize;
856 // Always allocate VideoNativeMetadata if using ANWBuffer.
857 // OMX might use gralloc source internally, but we don't share
858 // metadata buffer with OMX, OMX has its own headers.
859 if (mode == IOMX::kPortModeDynamicANWBuffer) {
860 bufSize = sizeof(VideoNativeMetadata);
861 } else if (mode == IOMX::kPortModeDynamicNativeHandle) {
862 bufSize = sizeof(VideoNativeHandleMetadata);
863 }
864
865 size_t conversionBufferSize = 0;
866
867 sp<DataConverter> converter = mConverter[portIndex];
868 if (converter != NULL) {
869 // here we assume sane conversions of max 4:1, so result fits in int32
870 if (portIndex == kPortIndexInput) {
871 conversionBufferSize = converter->sourceSize(bufSize);
872 } else {
873 conversionBufferSize = converter->targetSize(bufSize);
874 }
875 }
876
877 size_t alignment = MemoryDealer::getAllocationAlignment();
878
879 ALOGV("[%s] Allocating %u buffers of size %zu (from %u using %s) on %s port",
880 mComponentName.c_str(),
881 def.nBufferCountActual, bufSize, def.nBufferSize, asString(mode),
882 portIndex == kPortIndexInput ? "input" : "output");
883
884 // verify buffer sizes to avoid overflow in align()
885 if (bufSize == 0 || max(bufSize, conversionBufferSize) > kMaxCodecBufferSize) {
886 ALOGE("b/22885421");
887 return NO_MEMORY;
888 }
889
890 // don't modify bufSize as OMX may not expect it to increase after negotiation
891 size_t alignedSize = align(bufSize, alignment);
892 size_t alignedConvSize = align(conversionBufferSize, alignment);
893 if (def.nBufferCountActual > SIZE_MAX / (alignedSize + alignedConvSize)) {
894 ALOGE("b/22885421");
895 return NO_MEMORY;
896 }
897
898 if (mode != IOMX::kPortModePresetSecureBuffer) {
899 if (getTrebleFlag()) {
900 mAllocator[portIndex] = TAllocator::getService("ashmem");
901 if (mAllocator[portIndex] == nullptr) {
902 ALOGE("hidl allocator on port %d is null",
903 (int)portIndex);
904 return NO_MEMORY;
905 }
906 } else {
907 size_t totalSize = def.nBufferCountActual *
908 (alignedSize + alignedConvSize);
909 mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
910 }
911 }
912
913 const sp<AMessage> &format =
914 portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
915 for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
916 hidl_memory hidlMemToken;
917 sp<TMemory> hidlMem;
918 sp<IMemory> mem;
919
920 BufferInfo info;
921 info.mStatus = BufferInfo::OWNED_BY_US;
922 info.mFenceFd = -1;
923 info.mRenderInfo = NULL;
924 info.mGraphicBuffer = NULL;
925 info.mNewGraphicBuffer = false;
926
927 if (mode == IOMX::kPortModePresetSecureBuffer) {
928 void *ptr = NULL;
929 sp<NativeHandle> native_handle;
930 err = mOMXNode->allocateSecureBuffer(
931 portIndex, bufSize, &info.mBufferID,
932 &ptr, &native_handle);
933
934 info.mData = (native_handle == NULL)
935 ? new SecureBuffer(format, ptr, bufSize)
936 : new SecureBuffer(format, native_handle, bufSize);
937 info.mCodecData = info.mData;
938 } else {
939 if (getTrebleFlag()) {
940 bool success;
941 auto transStatus = mAllocator[portIndex]->allocate(
942 bufSize,
943 [&success, &hidlMemToken](
944 bool s,
945 hidl_memory const& m) {
946 success = s;
947 hidlMemToken = m;
948 });
949
950 if (!transStatus.isOk()) {
951 ALOGE("hidl's AshmemAllocator failed at the "
952 "transport: %s",
953 transStatus.description().c_str());
954 return NO_MEMORY;
955 }
956 if (!success) {
957 return NO_MEMORY;
958 }
959 hidlMem = mapMemory(hidlMemToken);
960 if (hidlMem == nullptr) {
961 return NO_MEMORY;
962 }
963 err = mOMXNode->useBuffer(
964 portIndex, hidlMemToken, &info.mBufferID);
965 } else {
966 mem = mDealer[portIndex]->allocate(bufSize);
967 if (mem == NULL || mem->pointer() == NULL) {
968 return NO_MEMORY;
969 }
970
971 err = mOMXNode->useBuffer(
972 portIndex, mem, &info.mBufferID);
973 }
974
975 if (mode == IOMX::kPortModeDynamicANWBuffer) {
976 VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
977 getTrebleFlag() ?
978 (void*)hidlMem->getPointer() : mem->pointer());
979 metaData->nFenceFd = -1;
980 }
981
982 if (getTrebleFlag()) {
983 info.mCodecData = new SharedMemoryBuffer(
984 format, hidlMem);
985 info.mCodecRef = hidlMem;
986 } else {
987 info.mCodecData = new SharedMemoryBuffer(
988 format, mem);
989 info.mCodecRef = mem;
990 }
991
992 // if we require conversion, allocate conversion buffer for client use;
993 // otherwise, reuse codec buffer
994 if (mConverter[portIndex] != NULL) {
995 CHECK_GT(conversionBufferSize, (size_t)0);
996 if (getTrebleFlag()) {
997 bool success;
998 mAllocator[portIndex]->allocate(
999 conversionBufferSize,
1000 [&success, &hidlMemToken](
1001 bool s,
1002 hidl_memory const& m) {
1003 success = s;
1004 hidlMemToken = m;
1005 });
1006 if (!success) {
1007 return NO_MEMORY;
1008 }
1009 hidlMem = mapMemory(hidlMemToken);
1010 if (hidlMem == nullptr) {
1011 return NO_MEMORY;
1012 }
1013 info.mData = new SharedMemoryBuffer(format, hidlMem);
1014 info.mMemRef = hidlMem;
1015 } else {
1016 mem = mDealer[portIndex]->allocate(
1017 conversionBufferSize);
1018 if (mem == NULL|| mem->pointer() == NULL) {
1019 return NO_MEMORY;
1020 }
1021 info.mData = new SharedMemoryBuffer(format, mem);
1022 info.mMemRef = mem;
1023 }
1024 } else {
1025 info.mData = info.mCodecData;
1026 info.mMemRef = info.mCodecRef;
1027 }
1028 }
1029
1030 mBuffers[portIndex].push(info);
1031 }
1032 }
1033 }
1034
1035 if (err != OK) {
1036 return err;
1037 }
1038
1039 std::vector<ACodecBufferChannel::BufferAndId> array(mBuffers[portIndex].size());
1040 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1041 array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID};
1042 }
1043 if (portIndex == kPortIndexInput) {
1044 mBufferChannel->setInputBufferArray(array);
1045 } else if (portIndex == kPortIndexOutput) {
1046 mBufferChannel->setOutputBufferArray(array);
1047 } else {
1048 TRESPASS();
1049 }
1050
1051 return OK;
1052 }
1053
setupNativeWindowSizeFormatAndUsage(ANativeWindow * nativeWindow,int * finalUsage,bool reconnect)1054 status_t ACodec::setupNativeWindowSizeFormatAndUsage(
1055 ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */,
1056 bool reconnect) {
1057 OMX_PARAM_PORTDEFINITIONTYPE def;
1058 InitOMXParams(&def);
1059 def.nPortIndex = kPortIndexOutput;
1060
1061 status_t err = mOMXNode->getParameter(
1062 OMX_IndexParamPortDefinition, &def, sizeof(def));
1063
1064 if (err != OK) {
1065 return err;
1066 }
1067
1068 OMX_INDEXTYPE index;
1069 err = mOMXNode->getExtensionIndex(
1070 "OMX.google.android.index.AndroidNativeBufferConsumerUsage",
1071 &index);
1072
1073 if (err != OK) {
1074 // allow failure
1075 err = OK;
1076 } else {
1077 int usageBits = 0;
1078 if (nativeWindow->query(
1079 nativeWindow,
1080 NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1081 &usageBits) == OK) {
1082 OMX_PARAM_U32TYPE params;
1083 InitOMXParams(¶ms);
1084 params.nPortIndex = kPortIndexOutput;
1085 params.nU32 = (OMX_U32)usageBits;
1086
1087 err = mOMXNode->setParameter(index, ¶ms, sizeof(params));
1088
1089 if (err != OK) {
1090 ALOGE("Fail to set AndroidNativeBufferConsumerUsage: %d", err);
1091 return err;
1092 }
1093 }
1094 }
1095
1096 OMX_U32 usage = 0;
1097 err = mOMXNode->getGraphicBufferUsage(kPortIndexOutput, &usage);
1098 if (err != 0) {
1099 ALOGW("querying usage flags from OMX IL component failed: %d", err);
1100 // XXX: Currently this error is logged, but not fatal.
1101 usage = 0;
1102 }
1103 int omxUsage = usage;
1104
1105 if (mFlags & kFlagIsGrallocUsageProtected) {
1106 usage |= GRALLOC_USAGE_PROTECTED;
1107 }
1108
1109 usage |= kVideoGrallocUsage;
1110 *finalUsage = usage;
1111
1112 memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
1113 mLastNativeWindowDataSpace = HAL_DATASPACE_UNKNOWN;
1114
1115 ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage);
1116 return setNativeWindowSizeFormatAndUsage(
1117 nativeWindow,
1118 def.format.video.nFrameWidth,
1119 def.format.video.nFrameHeight,
1120 def.format.video.eColorFormat,
1121 mRotationDegrees,
1122 usage,
1123 reconnect);
1124 }
1125
configureOutputBuffersFromNativeWindow(OMX_U32 * bufferCount,OMX_U32 * bufferSize,OMX_U32 * minUndequeuedBuffers,bool preregister)1126 status_t ACodec::configureOutputBuffersFromNativeWindow(
1127 OMX_U32 *bufferCount, OMX_U32 *bufferSize,
1128 OMX_U32 *minUndequeuedBuffers, bool preregister) {
1129
1130 OMX_PARAM_PORTDEFINITIONTYPE def;
1131 InitOMXParams(&def);
1132 def.nPortIndex = kPortIndexOutput;
1133
1134 status_t err = mOMXNode->getParameter(
1135 OMX_IndexParamPortDefinition, &def, sizeof(def));
1136
1137 if (err == OK) {
1138 err = setupNativeWindowSizeFormatAndUsage(
1139 mNativeWindow.get(), &mNativeWindowUsageBits,
1140 preregister && !mTunneled /* reconnect */);
1141 }
1142 if (err != OK) {
1143 mNativeWindowUsageBits = 0;
1144 return err;
1145 }
1146
1147 // Exits here for tunneled video playback codecs -- i.e. skips native window
1148 // buffer allocation step as this is managed by the tunneled OMX omponent
1149 // itself and explicitly sets def.nBufferCountActual to 0.
1150 if (mTunneled) {
1151 ALOGV("Tunneled Playback: skipping native window buffer allocation.");
1152 def.nBufferCountActual = 0;
1153 err = mOMXNode->setParameter(
1154 OMX_IndexParamPortDefinition, &def, sizeof(def));
1155
1156 *minUndequeuedBuffers = 0;
1157 *bufferCount = 0;
1158 *bufferSize = 0;
1159 return err;
1160 }
1161
1162 *minUndequeuedBuffers = 0;
1163 err = mNativeWindow->query(
1164 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
1165 (int *)minUndequeuedBuffers);
1166
1167 if (err != 0) {
1168 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
1169 strerror(-err), -err);
1170 return err;
1171 }
1172
1173 // FIXME: assume that surface is controlled by app (native window
1174 // returns the number for the case when surface is not controlled by app)
1175 // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
1176 // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
1177
1178 // Use conservative allocation while also trying to reduce starvation
1179 //
1180 // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
1181 // minimum needed for the consumer to be able to work
1182 // 2. try to allocate two (2) additional buffers to reduce starvation from
1183 // the consumer
1184 // plus an extra buffer to account for incorrect minUndequeuedBufs
1185 for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
1186 OMX_U32 newBufferCount =
1187 def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
1188 def.nBufferCountActual = newBufferCount;
1189 err = mOMXNode->setParameter(
1190 OMX_IndexParamPortDefinition, &def, sizeof(def));
1191
1192 if (err == OK) {
1193 *minUndequeuedBuffers += extraBuffers;
1194 break;
1195 }
1196
1197 ALOGW("[%s] setting nBufferCountActual to %u failed: %d",
1198 mComponentName.c_str(), newBufferCount, err);
1199 /* exit condition */
1200 if (extraBuffers == 0) {
1201 return err;
1202 }
1203 }
1204
1205 err = native_window_set_buffer_count(
1206 mNativeWindow.get(), def.nBufferCountActual);
1207
1208 if (err != 0) {
1209 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
1210 -err);
1211 return err;
1212 }
1213
1214 *bufferCount = def.nBufferCountActual;
1215 *bufferSize = def.nBufferSize;
1216 return err;
1217 }
1218
allocateOutputBuffersFromNativeWindow()1219 status_t ACodec::allocateOutputBuffersFromNativeWindow() {
1220 // This method only handles the non-metadata mode (or simulating legacy
1221 // mode with metadata, which is transparent to ACodec).
1222 CHECK(!storingMetadataInDecodedBuffers());
1223
1224 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
1225 status_t err = configureOutputBuffersFromNativeWindow(
1226 &bufferCount, &bufferSize, &minUndequeuedBuffers, true /* preregister */);
1227 if (err != 0)
1228 return err;
1229 mNumUndequeuedBuffers = minUndequeuedBuffers;
1230
1231 static_cast<Surface*>(mNativeWindow.get())
1232 ->getIGraphicBufferProducer()->allowAllocation(true);
1233
1234 ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
1235 "output port",
1236 mComponentName.c_str(), bufferCount, bufferSize);
1237
1238 // Dequeue buffers and send them to OMX
1239 for (OMX_U32 i = 0; i < bufferCount; i++) {
1240 ANativeWindowBuffer *buf;
1241 int fenceFd;
1242 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1243 if (err != 0) {
1244 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1245 break;
1246 }
1247
1248 sp<GraphicBuffer> graphicBuffer(GraphicBuffer::from(buf));
1249 BufferInfo info;
1250 info.mStatus = BufferInfo::OWNED_BY_US;
1251 info.mFenceFd = fenceFd;
1252 info.mIsReadFence = false;
1253 info.mRenderInfo = NULL;
1254 info.mGraphicBuffer = graphicBuffer;
1255 info.mNewGraphicBuffer = false;
1256
1257 // TODO: We shouln't need to create MediaCodecBuffer. In metadata mode
1258 // OMX doesn't use the shared memory buffer, but some code still
1259 // access info.mData. Create an ABuffer as a placeholder.
1260 info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
1261 info.mCodecData = info.mData;
1262
1263 mBuffers[kPortIndexOutput].push(info);
1264
1265 IOMX::buffer_id bufferId;
1266 err = mOMXNode->useBuffer(kPortIndexOutput, graphicBuffer, &bufferId);
1267 if (err != 0) {
1268 ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
1269 "%d", i, err);
1270 break;
1271 }
1272
1273 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
1274
1275 ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
1276 mComponentName.c_str(),
1277 bufferId, graphicBuffer.get());
1278 }
1279
1280 OMX_U32 cancelStart;
1281 OMX_U32 cancelEnd;
1282
1283 if (err != OK) {
1284 // If an error occurred while dequeuing we need to cancel any buffers
1285 // that were dequeued. Also cancel all if we're in legacy metadata mode.
1286 cancelStart = 0;
1287 cancelEnd = mBuffers[kPortIndexOutput].size();
1288 } else {
1289 // Return the required minimum undequeued buffers to the native window.
1290 cancelStart = bufferCount - minUndequeuedBuffers;
1291 cancelEnd = bufferCount;
1292 }
1293
1294 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
1295 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1296 if (info->mStatus == BufferInfo::OWNED_BY_US) {
1297 status_t error = cancelBufferToNativeWindow(info);
1298 if (err == 0) {
1299 err = error;
1300 }
1301 }
1302 }
1303
1304 static_cast<Surface*>(mNativeWindow.get())
1305 ->getIGraphicBufferProducer()->allowAllocation(false);
1306
1307 return err;
1308 }
1309
allocateOutputMetadataBuffers()1310 status_t ACodec::allocateOutputMetadataBuffers() {
1311 CHECK(storingMetadataInDecodedBuffers());
1312
1313 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
1314 status_t err = configureOutputBuffersFromNativeWindow(
1315 &bufferCount, &bufferSize, &minUndequeuedBuffers,
1316 false /* preregister */);
1317 if (err != OK)
1318 return err;
1319 mNumUndequeuedBuffers = minUndequeuedBuffers;
1320
1321 ALOGV("[%s] Allocating %u meta buffers on output port",
1322 mComponentName.c_str(), bufferCount);
1323
1324 for (OMX_U32 i = 0; i < bufferCount; i++) {
1325 BufferInfo info;
1326 info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1327 info.mFenceFd = -1;
1328 info.mRenderInfo = NULL;
1329 info.mGraphicBuffer = NULL;
1330 info.mNewGraphicBuffer = false;
1331 info.mDequeuedAt = mDequeueCounter;
1332
1333 info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
1334
1335 // Initialize fence fd to -1 to avoid warning in freeBuffer().
1336 ((VideoNativeMetadata *)info.mData->base())->nFenceFd = -1;
1337
1338 info.mCodecData = info.mData;
1339
1340 err = mOMXNode->useBuffer(kPortIndexOutput, OMXBuffer::sPreset, &info.mBufferID);
1341 mBuffers[kPortIndexOutput].push(info);
1342
1343 ALOGV("[%s] allocated meta buffer with ID %u",
1344 mComponentName.c_str(), info.mBufferID);
1345 }
1346
1347 mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
1348 return err;
1349 }
1350
submitOutputMetadataBuffer()1351 status_t ACodec::submitOutputMetadataBuffer() {
1352 CHECK(storingMetadataInDecodedBuffers());
1353 if (mMetadataBuffersToSubmit == 0)
1354 return OK;
1355
1356 BufferInfo *info = dequeueBufferFromNativeWindow();
1357 if (info == NULL) {
1358 return ERROR_IO;
1359 }
1360
1361 ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
1362 mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer->handle);
1363
1364 --mMetadataBuffersToSubmit;
1365 info->checkWriteFence("submitOutputMetadataBuffer");
1366 return fillBuffer(info);
1367 }
1368
waitForFence(int fd,const char * dbg)1369 status_t ACodec::waitForFence(int fd, const char *dbg ) {
1370 status_t res = OK;
1371 if (fd >= 0) {
1372 sp<Fence> fence = new Fence(fd);
1373 res = fence->wait(IOMX::kFenceTimeoutMs);
1374 ALOGW_IF(res != OK, "FENCE TIMEOUT for %d in %s", fd, dbg);
1375 }
1376 return res;
1377 }
1378
1379 // static
_asString(BufferInfo::Status s)1380 const char *ACodec::_asString(BufferInfo::Status s) {
1381 switch (s) {
1382 case BufferInfo::OWNED_BY_US: return "OUR";
1383 case BufferInfo::OWNED_BY_COMPONENT: return "COMPONENT";
1384 case BufferInfo::OWNED_BY_UPSTREAM: return "UPSTREAM";
1385 case BufferInfo::OWNED_BY_DOWNSTREAM: return "DOWNSTREAM";
1386 case BufferInfo::OWNED_BY_NATIVE_WINDOW: return "SURFACE";
1387 case BufferInfo::UNRECOGNIZED: return "UNRECOGNIZED";
1388 default: return "?";
1389 }
1390 }
1391
dumpBuffers(OMX_U32 portIndex)1392 void ACodec::dumpBuffers(OMX_U32 portIndex) {
1393 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1394 ALOGI("[%s] %s port has %zu buffers:", mComponentName.c_str(),
1395 portIndex == kPortIndexInput ? "input" : "output", mBuffers[portIndex].size());
1396 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1397 const BufferInfo &info = mBuffers[portIndex][i];
1398 ALOGI(" slot %2zu: #%8u %p/%p %s(%d) dequeued:%u",
1399 i, info.mBufferID, info.mGraphicBuffer.get(),
1400 info.mGraphicBuffer == NULL ? NULL : info.mGraphicBuffer->getNativeBuffer(),
1401 _asString(info.mStatus), info.mStatus, info.mDequeuedAt);
1402 }
1403 }
1404
cancelBufferToNativeWindow(BufferInfo * info)1405 status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
1406 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1407
1408 ALOGV("[%s] Calling cancelBuffer on buffer %u",
1409 mComponentName.c_str(), info->mBufferID);
1410
1411 info->checkWriteFence("cancelBufferToNativeWindow");
1412 int err = mNativeWindow->cancelBuffer(
1413 mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
1414 info->mFenceFd = -1;
1415
1416 ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window",
1417 mComponentName.c_str(), info->mBufferID);
1418 // change ownership even if cancelBuffer fails
1419 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1420
1421 return err;
1422 }
1423
updateRenderInfoForDequeuedBuffer(ANativeWindowBuffer * buf,int fenceFd,BufferInfo * info)1424 void ACodec::updateRenderInfoForDequeuedBuffer(
1425 ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info) {
1426
1427 info->mRenderInfo =
1428 mRenderTracker.updateInfoForDequeuedBuffer(
1429 buf, fenceFd, info - &mBuffers[kPortIndexOutput][0]);
1430
1431 // check for any fences already signaled
1432 notifyOfRenderedFrames(false /* dropIncomplete */, info->mRenderInfo);
1433 }
1434
onFrameRendered(int64_t mediaTimeUs,nsecs_t systemNano)1435 void ACodec::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
1436 if (mRenderTracker.onFrameRendered(mediaTimeUs, systemNano) != OK) {
1437 mRenderTracker.dumpRenderQueue();
1438 }
1439 }
1440
notifyOfRenderedFrames(bool dropIncomplete,FrameRenderTracker::Info * until)1441 void ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Info *until) {
1442 std::list<FrameRenderTracker::Info> done =
1443 mRenderTracker.checkFencesAndGetRenderedFrames(until, dropIncomplete);
1444
1445 // unlink untracked frames
1446 for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
1447 it != done.cend(); ++it) {
1448 ssize_t index = it->getIndex();
1449 if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) {
1450 mBuffers[kPortIndexOutput].editItemAt(index).mRenderInfo = NULL;
1451 } else if (index >= 0) {
1452 // THIS SHOULD NEVER HAPPEN
1453 ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size());
1454 }
1455 }
1456
1457 mCallback->onOutputFramesRendered(done);
1458 }
1459
dequeueBufferFromNativeWindow()1460 ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
1461 ANativeWindowBuffer *buf;
1462 CHECK(mNativeWindow.get() != NULL);
1463
1464 if (mTunneled) {
1465 ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel"
1466 " video playback mode mode!");
1467 return NULL;
1468 }
1469
1470 if (mFatalError) {
1471 ALOGW("not dequeuing from native window due to fatal error");
1472 return NULL;
1473 }
1474
1475 int fenceFd = -1;
1476 do {
1477 status_t err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1478 if (err != 0) {
1479 ALOGE("dequeueBuffer failed: %s(%d).", asString(err), err);
1480 return NULL;
1481 }
1482
1483 bool stale = false;
1484 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1485 i--;
1486 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1487
1488 if (info->mGraphicBuffer != NULL &&
1489 info->mGraphicBuffer->handle == buf->handle) {
1490 // Since consumers can attach buffers to BufferQueues, it is possible
1491 // that a known yet stale buffer can return from a surface that we
1492 // once used. We can simply ignore this as we have already dequeued
1493 // this buffer properly. NOTE: this does not eliminate all cases,
1494 // e.g. it is possible that we have queued the valid buffer to the
1495 // NW, and a stale copy of the same buffer gets dequeued - which will
1496 // be treated as the valid buffer by ACodec.
1497 if (info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1498 ALOGI("dequeued stale buffer %p. discarding", buf);
1499 stale = true;
1500 break;
1501 }
1502
1503 ALOGV("dequeued buffer #%u with age %u, graphicBuffer %p",
1504 (unsigned)(info - &mBuffers[kPortIndexOutput][0]),
1505 mDequeueCounter - info->mDequeuedAt,
1506 info->mGraphicBuffer->handle);
1507
1508 info->mStatus = BufferInfo::OWNED_BY_US;
1509 info->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow");
1510 updateRenderInfoForDequeuedBuffer(buf, fenceFd, info);
1511 return info;
1512 }
1513 }
1514
1515 // It is also possible to receive a previously unregistered buffer
1516 // in non-meta mode. These should be treated as stale buffers. The
1517 // same is possible in meta mode, in which case, it will be treated
1518 // as a normal buffer, which is not desirable.
1519 // TODO: fix this.
1520 if (!stale && !storingMetadataInDecodedBuffers()) {
1521 ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf);
1522 stale = true;
1523 }
1524 if (stale) {
1525 // TODO: detach stale buffer, but there is no API yet to do it.
1526 buf = NULL;
1527 }
1528 } while (buf == NULL);
1529
1530 // get oldest undequeued buffer
1531 BufferInfo *oldest = NULL;
1532 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1533 i--;
1534 BufferInfo *info =
1535 &mBuffers[kPortIndexOutput].editItemAt(i);
1536 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
1537 (oldest == NULL ||
1538 // avoid potential issues from counter rolling over
1539 mDequeueCounter - info->mDequeuedAt >
1540 mDequeueCounter - oldest->mDequeuedAt)) {
1541 oldest = info;
1542 }
1543 }
1544
1545 // it is impossible dequeue a buffer when there are no buffers with ANW
1546 CHECK(oldest != NULL);
1547 // it is impossible to dequeue an unknown buffer in non-meta mode, as the
1548 // while loop above does not complete
1549 CHECK(storingMetadataInDecodedBuffers());
1550
1551 // discard buffer in LRU info and replace with new buffer
1552 oldest->mGraphicBuffer = GraphicBuffer::from(buf);
1553 oldest->mNewGraphicBuffer = true;
1554 oldest->mStatus = BufferInfo::OWNED_BY_US;
1555 oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest");
1556 mRenderTracker.untrackFrame(oldest->mRenderInfo);
1557 oldest->mRenderInfo = NULL;
1558
1559 ALOGV("replaced oldest buffer #%u with age %u, graphicBuffer %p",
1560 (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
1561 mDequeueCounter - oldest->mDequeuedAt,
1562 oldest->mGraphicBuffer->handle);
1563
1564 updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest);
1565 return oldest;
1566 }
1567
freeBuffersOnPort(OMX_U32 portIndex)1568 status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
1569 if (portIndex == kPortIndexInput) {
1570 mBufferChannel->setInputBufferArray({});
1571 } else {
1572 mBufferChannel->setOutputBufferArray({});
1573 }
1574
1575 status_t err = OK;
1576 for (size_t i = mBuffers[portIndex].size(); i > 0;) {
1577 i--;
1578 status_t err2 = freeBuffer(portIndex, i);
1579 if (err == OK) {
1580 err = err2;
1581 }
1582 }
1583
1584 if (getTrebleFlag()) {
1585 mAllocator[portIndex].clear();
1586 } else {
1587 mDealer[portIndex].clear();
1588 }
1589 return err;
1590 }
1591
freeOutputBuffersNotOwnedByComponent()1592 status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
1593 status_t err = OK;
1594 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1595 i--;
1596 BufferInfo *info =
1597 &mBuffers[kPortIndexOutput].editItemAt(i);
1598
1599 // At this time some buffers may still be with the component
1600 // or being drained.
1601 if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
1602 info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
1603 status_t err2 = freeBuffer(kPortIndexOutput, i);
1604 if (err == OK) {
1605 err = err2;
1606 }
1607 }
1608 }
1609
1610 return err;
1611 }
1612
freeBuffer(OMX_U32 portIndex,size_t i)1613 status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
1614 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1615 status_t err = OK;
1616
1617 // there should not be any fences in the metadata
1618 if (mPortMode[portIndex] == IOMX::kPortModeDynamicANWBuffer && info->mCodecData != NULL
1619 && info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
1620 int fenceFd = ((VideoNativeMetadata *)info->mCodecData->base())->nFenceFd;
1621 if (fenceFd >= 0) {
1622 ALOGW("unreleased fence (%d) in %s metadata buffer %zu",
1623 fenceFd, portIndex == kPortIndexInput ? "input" : "output", i);
1624 }
1625 }
1626
1627 switch (info->mStatus) {
1628 case BufferInfo::OWNED_BY_US:
1629 if (portIndex == kPortIndexOutput && mNativeWindow != NULL) {
1630 (void)cancelBufferToNativeWindow(info);
1631 }
1632 // fall through
1633
1634 case BufferInfo::OWNED_BY_NATIVE_WINDOW:
1635 err = mOMXNode->freeBuffer(portIndex, info->mBufferID);
1636 break;
1637
1638 default:
1639 ALOGE("trying to free buffer not owned by us or ANW (%d)", info->mStatus);
1640 err = FAILED_TRANSACTION;
1641 break;
1642 }
1643
1644 if (info->mFenceFd >= 0) {
1645 ::close(info->mFenceFd);
1646 }
1647
1648 if (portIndex == kPortIndexOutput) {
1649 mRenderTracker.untrackFrame(info->mRenderInfo, i);
1650 info->mRenderInfo = NULL;
1651 }
1652
1653 // remove buffer even if mOMXNode->freeBuffer fails
1654 mBuffers[portIndex].removeAt(i);
1655 return err;
1656 }
1657
findBufferByID(uint32_t portIndex,IOMX::buffer_id bufferID,ssize_t * index)1658 ACodec::BufferInfo *ACodec::findBufferByID(
1659 uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) {
1660 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1661 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1662
1663 if (info->mBufferID == bufferID) {
1664 if (index != NULL) {
1665 *index = i;
1666 }
1667 return info;
1668 }
1669 }
1670
1671 ALOGE("Could not find buffer with ID %u", bufferID);
1672 return NULL;
1673 }
1674
fillBuffer(BufferInfo * info)1675 status_t ACodec::fillBuffer(BufferInfo *info) {
1676 status_t err;
1677 // Even in dynamic ANW buffer mode, if the graphic buffer is not changing,
1678 // send sPreset instead of the same graphic buffer, so that OMX server
1679 // side doesn't update the meta. In theory it should make no difference,
1680 // however when the same buffer is parcelled again, a new handle could be
1681 // created on server side, and some decoder doesn't recognize the handle
1682 // even if it's the same buffer.
1683 if (!storingMetadataInDecodedBuffers() || !info->mNewGraphicBuffer) {
1684 err = mOMXNode->fillBuffer(
1685 info->mBufferID, OMXBuffer::sPreset, info->mFenceFd);
1686 } else {
1687 err = mOMXNode->fillBuffer(
1688 info->mBufferID, info->mGraphicBuffer, info->mFenceFd);
1689 }
1690
1691 info->mNewGraphicBuffer = false;
1692 info->mFenceFd = -1;
1693 if (err == OK) {
1694 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1695 }
1696 return err;
1697 }
1698
setComponentRole(bool isEncoder,const char * mime)1699 status_t ACodec::setComponentRole(
1700 bool isEncoder, const char *mime) {
1701 const char *role = GetComponentRole(isEncoder, mime);
1702 if (role == NULL) {
1703 return BAD_VALUE;
1704 }
1705 status_t err = SetComponentRole(mOMXNode, role);
1706 if (err != OK) {
1707 ALOGW("[%s] Failed to set standard component role '%s'.",
1708 mComponentName.c_str(), role);
1709 }
1710 return err;
1711 }
1712
configureCodec(const char * mime,const sp<AMessage> & msg)1713 status_t ACodec::configureCodec(
1714 const char *mime, const sp<AMessage> &msg) {
1715 int32_t encoder;
1716 if (!msg->findInt32("encoder", &encoder)) {
1717 encoder = false;
1718 }
1719
1720 sp<AMessage> inputFormat = new AMessage;
1721 sp<AMessage> outputFormat = new AMessage;
1722 mConfigFormat = msg;
1723
1724 mIsEncoder = encoder;
1725
1726 mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
1727 mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
1728
1729 status_t err = setComponentRole(encoder /* isEncoder */, mime);
1730
1731 if (err != OK) {
1732 return err;
1733 }
1734
1735 int32_t bitRate = 0;
1736 // FLAC encoder doesn't need a bitrate, other encoders do
1737 if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
1738 && !msg->findInt32("bitrate", &bitRate)) {
1739 return INVALID_OPERATION;
1740 }
1741
1742 // propagate bitrate to the output so that the muxer has it
1743 if (encoder && msg->findInt32("bitrate", &bitRate)) {
1744 // Technically ISO spec says that 'bitrate' should be 0 for VBR even though it is the
1745 // average bitrate. We've been setting both bitrate and max-bitrate to this same value.
1746 outputFormat->setInt32("bitrate", bitRate);
1747 outputFormat->setInt32("max-bitrate", bitRate);
1748 }
1749
1750 int32_t storeMeta;
1751 if (encoder
1752 && msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
1753 && storeMeta != kMetadataBufferTypeInvalid) {
1754 IOMX::PortMode mode;
1755 if (storeMeta == kMetadataBufferTypeNativeHandleSource) {
1756 mode = IOMX::kPortModeDynamicNativeHandle;
1757 } else if (storeMeta == kMetadataBufferTypeANWBuffer ||
1758 storeMeta == kMetadataBufferTypeGrallocSource) {
1759 mode = IOMX::kPortModeDynamicANWBuffer;
1760 } else {
1761 return BAD_VALUE;
1762 }
1763 err = setPortMode(kPortIndexInput, mode);
1764 if (err != OK) {
1765 return err;
1766 }
1767
1768 uint32_t usageBits;
1769 if (mOMXNode->getParameter(
1770 (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
1771 &usageBits, sizeof(usageBits)) == OK) {
1772 inputFormat->setInt32(
1773 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
1774 }
1775 }
1776
1777 int32_t prependSPSPPS = 0;
1778 if (encoder
1779 && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
1780 && prependSPSPPS != 0) {
1781 OMX_INDEXTYPE index;
1782 err = mOMXNode->getExtensionIndex(
1783 "OMX.google.android.index.prependSPSPPSToIDRFrames", &index);
1784
1785 if (err == OK) {
1786 PrependSPSPPSToIDRFramesParams params;
1787 InitOMXParams(¶ms);
1788 params.bEnable = OMX_TRUE;
1789
1790 err = mOMXNode->setParameter(index, ¶ms, sizeof(params));
1791 }
1792
1793 if (err != OK) {
1794 ALOGE("Encoder could not be configured to emit SPS/PPS before "
1795 "IDR frames. (err %d)", err);
1796
1797 return err;
1798 }
1799 }
1800
1801 // Only enable metadata mode on encoder output if encoder can prepend
1802 // sps/pps to idr frames, since in metadata mode the bitstream is in an
1803 // opaque handle, to which we don't have access.
1804 int32_t video = !strncasecmp(mime, "video/", 6);
1805 mIsVideo = video;
1806 if (encoder && video) {
1807 OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
1808 && msg->findInt32("android._store-metadata-in-buffers-output", &storeMeta)
1809 && storeMeta != 0);
1810 if (mFlags & kFlagIsSecure) {
1811 enable = OMX_TRUE;
1812 }
1813
1814 err = setPortMode(kPortIndexOutput, enable ?
1815 IOMX::kPortModePresetSecureBuffer : IOMX::kPortModePresetByteBuffer);
1816 if (err != OK) {
1817 return err;
1818 }
1819
1820 if (!msg->findInt64(
1821 "repeat-previous-frame-after",
1822 &mRepeatFrameDelayUs)) {
1823 mRepeatFrameDelayUs = -1ll;
1824 }
1825
1826 // only allow 32-bit value, since we pass it as U32 to OMX.
1827 if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
1828 mMaxPtsGapUs = -1ll;
1829 } else if (mMaxPtsGapUs > INT32_MAX || mMaxPtsGapUs < 0) {
1830 ALOGW("Unsupported value for max pts gap %lld", (long long) mMaxPtsGapUs);
1831 mMaxPtsGapUs = -1ll;
1832 }
1833
1834 if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
1835 mMaxFps = -1;
1836 }
1837
1838 if (!msg->findDouble("time-lapse-fps", &mCaptureFps)) {
1839 mCaptureFps = -1.0;
1840 }
1841
1842 if (!msg->findInt32(
1843 "create-input-buffers-suspended",
1844 (int32_t*)&mCreateInputBuffersSuspended)) {
1845 mCreateInputBuffersSuspended = false;
1846 }
1847 }
1848
1849 // NOTE: we only use native window for video decoders
1850 sp<RefBase> obj;
1851 bool haveNativeWindow = msg->findObject("native-window", &obj)
1852 && obj != NULL && video && !encoder;
1853 mUsingNativeWindow = haveNativeWindow;
1854 if (video && !encoder) {
1855 inputFormat->setInt32("adaptive-playback", false);
1856
1857 int32_t usageProtected;
1858 if (msg->findInt32("protected", &usageProtected) && usageProtected) {
1859 if (!haveNativeWindow) {
1860 ALOGE("protected output buffers must be sent to an ANativeWindow");
1861 return PERMISSION_DENIED;
1862 }
1863 mFlags |= kFlagIsGrallocUsageProtected;
1864 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1865 }
1866 }
1867 if (mFlags & kFlagIsSecure) {
1868 // use native_handles for secure input buffers
1869 err = setPortMode(kPortIndexInput, IOMX::kPortModePresetSecureBuffer);
1870
1871 if (err != OK) {
1872 ALOGI("falling back to non-native_handles");
1873 setPortMode(kPortIndexInput, IOMX::kPortModePresetByteBuffer);
1874 err = OK; // ignore error for now
1875 }
1876 }
1877 if (haveNativeWindow) {
1878 sp<ANativeWindow> nativeWindow =
1879 static_cast<ANativeWindow *>(static_cast<Surface *>(obj.get()));
1880
1881 // START of temporary support for automatic FRC - THIS WILL BE REMOVED
1882 int32_t autoFrc;
1883 if (msg->findInt32("auto-frc", &autoFrc)) {
1884 bool enabled = autoFrc;
1885 OMX_CONFIG_BOOLEANTYPE config;
1886 InitOMXParams(&config);
1887 config.bEnabled = (OMX_BOOL)enabled;
1888 status_t temp = mOMXNode->setConfig(
1889 (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
1890 &config, sizeof(config));
1891 if (temp == OK) {
1892 outputFormat->setInt32("auto-frc", enabled);
1893 } else if (enabled) {
1894 ALOGI("codec does not support requested auto-frc (err %d)", temp);
1895 }
1896 }
1897 // END of temporary support for automatic FRC
1898
1899 int32_t tunneled;
1900 if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
1901 tunneled != 0) {
1902 ALOGI("Configuring TUNNELED video playback.");
1903 mTunneled = true;
1904
1905 int32_t audioHwSync = 0;
1906 if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
1907 ALOGW("No Audio HW Sync provided for video tunnel");
1908 }
1909 err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
1910 if (err != OK) {
1911 ALOGE("configureTunneledVideoPlayback(%d,%p) failed!",
1912 audioHwSync, nativeWindow.get());
1913 return err;
1914 }
1915
1916 int32_t maxWidth = 0, maxHeight = 0;
1917 if (msg->findInt32("max-width", &maxWidth) &&
1918 msg->findInt32("max-height", &maxHeight)) {
1919
1920 err = mOMXNode->prepareForAdaptivePlayback(
1921 kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1922 if (err != OK) {
1923 ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
1924 mComponentName.c_str(), err);
1925 // allow failure
1926 err = OK;
1927 } else {
1928 inputFormat->setInt32("max-width", maxWidth);
1929 inputFormat->setInt32("max-height", maxHeight);
1930 inputFormat->setInt32("adaptive-playback", true);
1931 }
1932 }
1933 } else {
1934 ALOGV("Configuring CPU controlled video playback.");
1935 mTunneled = false;
1936
1937 // Explicity reset the sideband handle of the window for
1938 // non-tunneled video in case the window was previously used
1939 // for a tunneled video playback.
1940 err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
1941 if (err != OK) {
1942 ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
1943 return err;
1944 }
1945
1946 err = setPortMode(kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer);
1947 if (err != OK) {
1948 // if adaptive playback has been requested, try JB fallback
1949 // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
1950 // LARGE MEMORY REQUIREMENT
1951
1952 // we will not do adaptive playback on software accessed
1953 // surfaces as they never had to respond to changes in the
1954 // crop window, and we don't trust that they will be able to.
1955 int usageBits = 0;
1956 bool canDoAdaptivePlayback;
1957
1958 if (nativeWindow->query(
1959 nativeWindow.get(),
1960 NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1961 &usageBits) != OK) {
1962 canDoAdaptivePlayback = false;
1963 } else {
1964 canDoAdaptivePlayback =
1965 (usageBits &
1966 (GRALLOC_USAGE_SW_READ_MASK |
1967 GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
1968 }
1969
1970 int32_t maxWidth = 0, maxHeight = 0;
1971 if (canDoAdaptivePlayback &&
1972 msg->findInt32("max-width", &maxWidth) &&
1973 msg->findInt32("max-height", &maxHeight)) {
1974 ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
1975 mComponentName.c_str(), maxWidth, maxHeight);
1976
1977 err = mOMXNode->prepareForAdaptivePlayback(
1978 kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1979 ALOGW_IF(err != OK,
1980 "[%s] prepareForAdaptivePlayback failed w/ err %d",
1981 mComponentName.c_str(), err);
1982
1983 if (err == OK) {
1984 inputFormat->setInt32("max-width", maxWidth);
1985 inputFormat->setInt32("max-height", maxHeight);
1986 inputFormat->setInt32("adaptive-playback", true);
1987 }
1988 }
1989 // allow failure
1990 err = OK;
1991 } else {
1992 ALOGV("[%s] setPortMode on output to %s succeeded",
1993 mComponentName.c_str(), asString(IOMX::kPortModeDynamicANWBuffer));
1994 CHECK(storingMetadataInDecodedBuffers());
1995 inputFormat->setInt32("adaptive-playback", true);
1996 }
1997
1998 int32_t push;
1999 if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
2000 && push != 0) {
2001 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
2002 }
2003 }
2004
2005 int32_t rotationDegrees;
2006 if (msg->findInt32("rotation-degrees", &rotationDegrees)) {
2007 mRotationDegrees = rotationDegrees;
2008 } else {
2009 mRotationDegrees = 0;
2010 }
2011 }
2012
2013 AudioEncoding pcmEncoding = kAudioEncodingPcm16bit;
2014 (void)msg->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
2015 // invalid encodings will default to PCM-16bit in setupRawAudioFormat.
2016
2017 if (video) {
2018 // determine need for software renderer
2019 bool usingSwRenderer = false;
2020 if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
2021 usingSwRenderer = true;
2022 haveNativeWindow = false;
2023 (void)setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
2024 } else if (haveNativeWindow && !storingMetadataInDecodedBuffers()) {
2025 err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer);
2026 if (err != OK) {
2027 return err;
2028 }
2029 }
2030
2031 if (encoder) {
2032 err = setupVideoEncoder(mime, msg, outputFormat, inputFormat);
2033 } else {
2034 err = setupVideoDecoder(mime, msg, haveNativeWindow, usingSwRenderer, outputFormat);
2035 }
2036
2037 if (err != OK) {
2038 return err;
2039 }
2040
2041 if (haveNativeWindow) {
2042 mNativeWindow = static_cast<Surface *>(obj.get());
2043
2044 // fallback for devices that do not handle flex-YUV for native buffers
2045 int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
2046 if (msg->findInt32("color-format", &requestedColorFormat) &&
2047 requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
2048 status_t err = getPortFormat(kPortIndexOutput, outputFormat);
2049 if (err != OK) {
2050 return err;
2051 }
2052 int32_t colorFormat = OMX_COLOR_FormatUnused;
2053 OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
2054 if (!outputFormat->findInt32("color-format", &colorFormat)) {
2055 ALOGE("ouptut port did not have a color format (wrong domain?)");
2056 return BAD_VALUE;
2057 }
2058 ALOGD("[%s] Requested output format %#x and got %#x.",
2059 mComponentName.c_str(), requestedColorFormat, colorFormat);
2060 if (!IsFlexibleColorFormat(
2061 mOMXNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
2062 || flexibleEquivalent != (OMX_U32)requestedColorFormat) {
2063 // device did not handle flex-YUV request for native window, fall back
2064 // to SW renderer
2065 ALOGI("[%s] Falling back to software renderer", mComponentName.c_str());
2066 mNativeWindow.clear();
2067 mNativeWindowUsageBits = 0;
2068 haveNativeWindow = false;
2069 usingSwRenderer = true;
2070 // TODO: implement adaptive-playback support for bytebuffer mode.
2071 // This is done by SW codecs, but most HW codecs don't support it.
2072 err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
2073 inputFormat->setInt32("adaptive-playback", false);
2074 if (mFlags & kFlagIsGrallocUsageProtected) {
2075 // fallback is not supported for protected playback
2076 err = PERMISSION_DENIED;
2077 } else if (err == OK) {
2078 err = setupVideoDecoder(
2079 mime, msg, haveNativeWindow, usingSwRenderer, outputFormat);
2080 }
2081 }
2082 }
2083 }
2084
2085 if (usingSwRenderer) {
2086 outputFormat->setInt32("using-sw-renderer", 1);
2087 }
2088 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
2089 int32_t numChannels, sampleRate;
2090 if (!msg->findInt32("channel-count", &numChannels)
2091 || !msg->findInt32("sample-rate", &sampleRate)) {
2092 // Since we did not always check for these, leave them optional
2093 // and have the decoder figure it all out.
2094 err = OK;
2095 } else {
2096 err = setupRawAudioFormat(
2097 encoder ? kPortIndexInput : kPortIndexOutput,
2098 sampleRate,
2099 numChannels);
2100 }
2101 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2102 int32_t numChannels, sampleRate;
2103 if (!msg->findInt32("channel-count", &numChannels)
2104 || !msg->findInt32("sample-rate", &sampleRate)) {
2105 err = INVALID_OPERATION;
2106 } else {
2107 int32_t isADTS, aacProfile;
2108 int32_t sbrMode;
2109 int32_t maxOutputChannelCount;
2110 int32_t pcmLimiterEnable;
2111 drcParams_t drc;
2112 if (!msg->findInt32("is-adts", &isADTS)) {
2113 isADTS = 0;
2114 }
2115 if (!msg->findInt32("aac-profile", &aacProfile)) {
2116 aacProfile = OMX_AUDIO_AACObjectNull;
2117 }
2118 if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
2119 sbrMode = -1;
2120 }
2121
2122 if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
2123 maxOutputChannelCount = -1;
2124 }
2125 if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) {
2126 // value is unknown
2127 pcmLimiterEnable = -1;
2128 }
2129 if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
2130 // value is unknown
2131 drc.encodedTargetLevel = -1;
2132 }
2133 if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
2134 // value is unknown
2135 drc.drcCut = -1;
2136 }
2137 if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
2138 // value is unknown
2139 drc.drcBoost = -1;
2140 }
2141 if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
2142 // value is unknown
2143 drc.heavyCompression = -1;
2144 }
2145 if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
2146 // value is unknown
2147 drc.targetRefLevel = -1;
2148 }
2149
2150 err = setupAACCodec(
2151 encoder, numChannels, sampleRate, bitRate, aacProfile,
2152 isADTS != 0, sbrMode, maxOutputChannelCount, drc,
2153 pcmLimiterEnable);
2154 }
2155 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
2156 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
2157 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
2158 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
2159 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
2160 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
2161 // These are PCM-like formats with a fixed sample rate but
2162 // a variable number of channels.
2163
2164 int32_t numChannels;
2165 if (!msg->findInt32("channel-count", &numChannels)) {
2166 err = INVALID_OPERATION;
2167 } else {
2168 int32_t sampleRate;
2169 if (!msg->findInt32("sample-rate", &sampleRate)) {
2170 sampleRate = 8000;
2171 }
2172 err = setupG711Codec(encoder, sampleRate, numChannels);
2173 }
2174 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
2175 int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
2176 if (encoder &&
2177 (!msg->findInt32("channel-count", &numChannels)
2178 || !msg->findInt32("sample-rate", &sampleRate))) {
2179 ALOGE("missing channel count or sample rate for FLAC encoder");
2180 err = INVALID_OPERATION;
2181 } else {
2182 if (encoder) {
2183 if (!msg->findInt32(
2184 "complexity", &compressionLevel) &&
2185 !msg->findInt32(
2186 "flac-compression-level", &compressionLevel)) {
2187 compressionLevel = 5; // default FLAC compression level
2188 } else if (compressionLevel < 0) {
2189 ALOGW("compression level %d outside [0..8] range, "
2190 "using 0",
2191 compressionLevel);
2192 compressionLevel = 0;
2193 } else if (compressionLevel > 8) {
2194 ALOGW("compression level %d outside [0..8] range, "
2195 "using 8",
2196 compressionLevel);
2197 compressionLevel = 8;
2198 }
2199 }
2200 err = setupFlacCodec(
2201 encoder, numChannels, sampleRate, compressionLevel);
2202 }
2203 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
2204 int32_t numChannels, sampleRate;
2205 if (encoder
2206 || !msg->findInt32("channel-count", &numChannels)
2207 || !msg->findInt32("sample-rate", &sampleRate)) {
2208 err = INVALID_OPERATION;
2209 } else {
2210 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels, pcmEncoding);
2211 }
2212 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
2213 int32_t numChannels;
2214 int32_t sampleRate;
2215 if (!msg->findInt32("channel-count", &numChannels)
2216 || !msg->findInt32("sample-rate", &sampleRate)) {
2217 err = INVALID_OPERATION;
2218 } else {
2219 err = setupAC3Codec(encoder, numChannels, sampleRate);
2220 }
2221 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
2222 int32_t numChannels;
2223 int32_t sampleRate;
2224 if (!msg->findInt32("channel-count", &numChannels)
2225 || !msg->findInt32("sample-rate", &sampleRate)) {
2226 err = INVALID_OPERATION;
2227 } else {
2228 err = setupEAC3Codec(encoder, numChannels, sampleRate);
2229 }
2230 }
2231
2232 if (err != OK) {
2233 return err;
2234 }
2235
2236 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
2237 mEncoderDelay = 0;
2238 }
2239
2240 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
2241 mEncoderPadding = 0;
2242 }
2243
2244 if (msg->findInt32("channel-mask", &mChannelMask)) {
2245 mChannelMaskPresent = true;
2246 } else {
2247 mChannelMaskPresent = false;
2248 }
2249
2250 int32_t maxInputSize;
2251 if (msg->findInt32("max-input-size", &maxInputSize)) {
2252 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
2253 err = OK; // ignore error
2254 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
2255 err = setMinBufferSize(kPortIndexInput, 8192); // XXX
2256 err = OK; // ignore error
2257 }
2258
2259 int32_t priority;
2260 if (msg->findInt32("priority", &priority)) {
2261 err = setPriority(priority);
2262 err = OK; // ignore error
2263 }
2264
2265 int32_t rateInt = -1;
2266 float rateFloat = -1;
2267 if (!msg->findFloat("operating-rate", &rateFloat)) {
2268 msg->findInt32("operating-rate", &rateInt);
2269 rateFloat = (float)rateInt; // 16MHz (FLINTMAX) is OK for upper bound.
2270 }
2271 if (rateFloat > 0) {
2272 err = setOperatingRate(rateFloat, video);
2273 err = OK; // ignore errors
2274 }
2275
2276 if (err == OK) {
2277 err = setVendorParameters(msg);
2278 if (err != OK) {
2279 return err;
2280 }
2281 }
2282
2283 // NOTE: both mBaseOutputFormat and mOutputFormat are outputFormat to signal first frame.
2284 mBaseOutputFormat = outputFormat;
2285 mLastOutputFormat.clear();
2286
2287 err = getPortFormat(kPortIndexInput, inputFormat);
2288 if (err == OK) {
2289 err = getPortFormat(kPortIndexOutput, outputFormat);
2290 if (err == OK) {
2291 mInputFormat = inputFormat;
2292 mOutputFormat = outputFormat;
2293 }
2294 }
2295
2296 // create data converters if needed
2297 if (!video && err == OK) {
2298 AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit;
2299 if (encoder) {
2300 (void)mInputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
2301 mConverter[kPortIndexInput] = AudioConverter::Create(pcmEncoding, codecPcmEncoding);
2302 if (mConverter[kPortIndexInput] != NULL) {
2303 mInputFormat->setInt32("pcm-encoding", pcmEncoding);
2304 }
2305 } else {
2306 (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
2307 mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding);
2308 if (mConverter[kPortIndexOutput] != NULL) {
2309 mOutputFormat->setInt32("pcm-encoding", pcmEncoding);
2310 }
2311 }
2312 }
2313
2314 return err;
2315 }
2316
setLatency(uint32_t latency)2317 status_t ACodec::setLatency(uint32_t latency) {
2318 OMX_PARAM_U32TYPE config;
2319 InitOMXParams(&config);
2320 config.nPortIndex = kPortIndexInput;
2321 config.nU32 = (OMX_U32)latency;
2322 status_t err = mOMXNode->setConfig(
2323 (OMX_INDEXTYPE)OMX_IndexConfigLatency,
2324 &config, sizeof(config));
2325 return err;
2326 }
2327
getLatency(uint32_t * latency)2328 status_t ACodec::getLatency(uint32_t *latency) {
2329 OMX_PARAM_U32TYPE config;
2330 InitOMXParams(&config);
2331 config.nPortIndex = kPortIndexInput;
2332 status_t err = mOMXNode->getConfig(
2333 (OMX_INDEXTYPE)OMX_IndexConfigLatency,
2334 &config, sizeof(config));
2335 if (err == OK) {
2336 *latency = config.nU32;
2337 }
2338 return err;
2339 }
2340
setPriority(int32_t priority)2341 status_t ACodec::setPriority(int32_t priority) {
2342 if (priority < 0) {
2343 return BAD_VALUE;
2344 }
2345 OMX_PARAM_U32TYPE config;
2346 InitOMXParams(&config);
2347 config.nU32 = (OMX_U32)priority;
2348 status_t temp = mOMXNode->setConfig(
2349 (OMX_INDEXTYPE)OMX_IndexConfigPriority,
2350 &config, sizeof(config));
2351 if (temp != OK) {
2352 ALOGI("codec does not support config priority (err %d)", temp);
2353 }
2354 return OK;
2355 }
2356
setOperatingRate(float rateFloat,bool isVideo)2357 status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) {
2358 if (rateFloat < 0) {
2359 return BAD_VALUE;
2360 }
2361 OMX_U32 rate;
2362 if (isVideo) {
2363 if (rateFloat > 65535) {
2364 return BAD_VALUE;
2365 }
2366 rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f);
2367 } else {
2368 if (rateFloat > UINT_MAX) {
2369 return BAD_VALUE;
2370 }
2371 rate = (OMX_U32)(rateFloat);
2372 }
2373 OMX_PARAM_U32TYPE config;
2374 InitOMXParams(&config);
2375 config.nU32 = rate;
2376 status_t err = mOMXNode->setConfig(
2377 (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate,
2378 &config, sizeof(config));
2379 if (err != OK) {
2380 ALOGI("codec does not support config operating rate (err %d)", err);
2381 }
2382 return OK;
2383 }
2384
getIntraRefreshPeriod(uint32_t * intraRefreshPeriod)2385 status_t ACodec::getIntraRefreshPeriod(uint32_t *intraRefreshPeriod) {
2386 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
2387 InitOMXParams(¶ms);
2388 params.nPortIndex = kPortIndexOutput;
2389 status_t err = mOMXNode->getConfig(
2390 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params));
2391 if (err == OK) {
2392 *intraRefreshPeriod = params.nRefreshPeriod;
2393 return OK;
2394 }
2395
2396 // Fallback to query through standard OMX index.
2397 OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
2398 InitOMXParams(&refreshParams);
2399 refreshParams.nPortIndex = kPortIndexOutput;
2400 refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
2401 err = mOMXNode->getParameter(
2402 OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams));
2403 if (err != OK || refreshParams.nCirMBs == 0) {
2404 *intraRefreshPeriod = 0;
2405 return OK;
2406 }
2407
2408 // Calculate period based on width and height
2409 uint32_t width, height;
2410 OMX_PARAM_PORTDEFINITIONTYPE def;
2411 InitOMXParams(&def);
2412 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2413 def.nPortIndex = kPortIndexOutput;
2414 err = mOMXNode->getParameter(
2415 OMX_IndexParamPortDefinition, &def, sizeof(def));
2416 if (err != OK) {
2417 *intraRefreshPeriod = 0;
2418 return err;
2419 }
2420 width = video_def->nFrameWidth;
2421 height = video_def->nFrameHeight;
2422 // Use H.264/AVC MacroBlock size 16x16
2423 *intraRefreshPeriod = divUp((divUp(width, 16u) * divUp(height, 16u)), refreshParams.nCirMBs);
2424
2425 return OK;
2426 }
2427
setIntraRefreshPeriod(uint32_t intraRefreshPeriod,bool inConfigure)2428 status_t ACodec::setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure) {
2429 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
2430 InitOMXParams(¶ms);
2431 params.nPortIndex = kPortIndexOutput;
2432 params.nRefreshPeriod = intraRefreshPeriod;
2433 status_t err = mOMXNode->setConfig(
2434 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params));
2435 if (err == OK) {
2436 return OK;
2437 }
2438
2439 // Only in configure state, a component could invoke setParameter.
2440 if (!inConfigure) {
2441 return INVALID_OPERATION;
2442 } else {
2443 ALOGI("[%s] try falling back to Cyclic", mComponentName.c_str());
2444 }
2445
2446 OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
2447 InitOMXParams(&refreshParams);
2448 refreshParams.nPortIndex = kPortIndexOutput;
2449 refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
2450
2451 if (intraRefreshPeriod == 0) {
2452 // 0 means disable intra refresh.
2453 refreshParams.nCirMBs = 0;
2454 } else {
2455 // Calculate macroblocks that need to be intra coded base on width and height
2456 uint32_t width, height;
2457 OMX_PARAM_PORTDEFINITIONTYPE def;
2458 InitOMXParams(&def);
2459 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2460 def.nPortIndex = kPortIndexOutput;
2461 err = mOMXNode->getParameter(
2462 OMX_IndexParamPortDefinition, &def, sizeof(def));
2463 if (err != OK) {
2464 return err;
2465 }
2466 width = video_def->nFrameWidth;
2467 height = video_def->nFrameHeight;
2468 // Use H.264/AVC MacroBlock size 16x16
2469 refreshParams.nCirMBs = divUp((divUp(width, 16u) * divUp(height, 16u)), intraRefreshPeriod);
2470 }
2471
2472 err = mOMXNode->setParameter(
2473 OMX_IndexParamVideoIntraRefresh,
2474 &refreshParams, sizeof(refreshParams));
2475 if (err != OK) {
2476 return err;
2477 }
2478
2479 return OK;
2480 }
2481
configureTemporalLayers(const sp<AMessage> & msg,bool inConfigure,sp<AMessage> & outputFormat)2482 status_t ACodec::configureTemporalLayers(
2483 const sp<AMessage> &msg, bool inConfigure, sp<AMessage> &outputFormat) {
2484 if (!mIsVideo || !mIsEncoder) {
2485 return INVALID_OPERATION;
2486 }
2487
2488 AString tsSchema;
2489 if (!msg->findString("ts-schema", &tsSchema)) {
2490 return OK;
2491 }
2492
2493 unsigned int numLayers = 0;
2494 unsigned int numBLayers = 0;
2495 int tags;
2496 char dummy;
2497 OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE pattern =
2498 OMX_VIDEO_AndroidTemporalLayeringPatternNone;
2499 if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1
2500 && numLayers > 0) {
2501 pattern = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC;
2502 } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c",
2503 &numLayers, &dummy, &numBLayers, &dummy))
2504 && (tags == 1 || (tags == 3 && dummy == '+'))
2505 && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) {
2506 numLayers += numBLayers;
2507 pattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid;
2508 } else {
2509 ALOGI("Ignoring unsupported ts-schema [%s]", tsSchema.c_str());
2510 return BAD_VALUE;
2511 }
2512
2513 OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layerParams;
2514 InitOMXParams(&layerParams);
2515 layerParams.nPortIndex = kPortIndexOutput;
2516
2517 status_t err = mOMXNode->getParameter(
2518 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2519 &layerParams, sizeof(layerParams));
2520
2521 if (err != OK) {
2522 return err;
2523 } else if (!(layerParams.eSupportedPatterns & pattern)) {
2524 return BAD_VALUE;
2525 }
2526
2527 numLayers = min(numLayers, layerParams.nLayerCountMax);
2528 numBLayers = min(numBLayers, layerParams.nBLayerCountMax);
2529
2530 if (!inConfigure) {
2531 OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE layerConfig;
2532 InitOMXParams(&layerConfig);
2533 layerConfig.nPortIndex = kPortIndexOutput;
2534 layerConfig.ePattern = pattern;
2535 layerConfig.nPLayerCountActual = numLayers - numBLayers;
2536 layerConfig.nBLayerCountActual = numBLayers;
2537 layerConfig.bBitrateRatiosSpecified = OMX_FALSE;
2538
2539 err = mOMXNode->setConfig(
2540 (OMX_INDEXTYPE)OMX_IndexConfigAndroidVideoTemporalLayering,
2541 &layerConfig, sizeof(layerConfig));
2542 } else {
2543 layerParams.ePattern = pattern;
2544 layerParams.nPLayerCountActual = numLayers - numBLayers;
2545 layerParams.nBLayerCountActual = numBLayers;
2546 layerParams.bBitrateRatiosSpecified = OMX_FALSE;
2547
2548 err = mOMXNode->setParameter(
2549 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2550 &layerParams, sizeof(layerParams));
2551 }
2552
2553 AString configSchema;
2554 if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) {
2555 configSchema = AStringPrintf("android.generic.%u+%u", numLayers - numBLayers, numBLayers);
2556 } else if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) {
2557 configSchema = AStringPrintf("webrtc.vp8.%u", numLayers);
2558 }
2559
2560 if (err != OK) {
2561 ALOGW("Failed to set temporal layers to %s (requested %s)",
2562 configSchema.c_str(), tsSchema.c_str());
2563 return err;
2564 }
2565
2566 err = mOMXNode->getParameter(
2567 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
2568 &layerParams, sizeof(layerParams));
2569
2570 if (err == OK) {
2571 ALOGD("Temporal layers requested:%s configured:%s got:%s(%u: P=%u, B=%u)",
2572 tsSchema.c_str(), configSchema.c_str(),
2573 asString(layerParams.ePattern), layerParams.ePattern,
2574 layerParams.nPLayerCountActual, layerParams.nBLayerCountActual);
2575
2576 if (outputFormat.get() == mOutputFormat.get()) {
2577 mOutputFormat = mOutputFormat->dup(); // trigger an output format change event
2578 }
2579 // assume we got what we configured
2580 outputFormat->setString("ts-schema", configSchema);
2581 }
2582 return err;
2583 }
2584
setMinBufferSize(OMX_U32 portIndex,size_t size)2585 status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
2586 OMX_PARAM_PORTDEFINITIONTYPE def;
2587 InitOMXParams(&def);
2588 def.nPortIndex = portIndex;
2589
2590 status_t err = mOMXNode->getParameter(
2591 OMX_IndexParamPortDefinition, &def, sizeof(def));
2592
2593 if (err != OK) {
2594 return err;
2595 }
2596
2597 if (def.nBufferSize >= size) {
2598 return OK;
2599 }
2600
2601 def.nBufferSize = size;
2602
2603 err = mOMXNode->setParameter(
2604 OMX_IndexParamPortDefinition, &def, sizeof(def));
2605
2606 if (err != OK) {
2607 return err;
2608 }
2609
2610 err = mOMXNode->getParameter(
2611 OMX_IndexParamPortDefinition, &def, sizeof(def));
2612
2613 if (err != OK) {
2614 return err;
2615 }
2616
2617 if (def.nBufferSize < size) {
2618 ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize);
2619 return FAILED_TRANSACTION;
2620 }
2621
2622 return OK;
2623 }
2624
selectAudioPortFormat(OMX_U32 portIndex,OMX_AUDIO_CODINGTYPE desiredFormat)2625 status_t ACodec::selectAudioPortFormat(
2626 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
2627 OMX_AUDIO_PARAM_PORTFORMATTYPE format;
2628 InitOMXParams(&format);
2629
2630 format.nPortIndex = portIndex;
2631 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
2632 format.nIndex = index;
2633 status_t err = mOMXNode->getParameter(
2634 OMX_IndexParamAudioPortFormat, &format, sizeof(format));
2635
2636 if (err != OK) {
2637 return err;
2638 }
2639
2640 if (format.eEncoding == desiredFormat) {
2641 break;
2642 }
2643
2644 if (index == kMaxIndicesToCheck) {
2645 ALOGW("[%s] stopping checking formats after %u: %s(%x)",
2646 mComponentName.c_str(), index,
2647 asString(format.eEncoding), format.eEncoding);
2648 return ERROR_UNSUPPORTED;
2649 }
2650 }
2651
2652 return mOMXNode->setParameter(
2653 OMX_IndexParamAudioPortFormat, &format, sizeof(format));
2654 }
2655
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)2656 status_t ACodec::setupAACCodec(
2657 bool encoder, int32_t numChannels, int32_t sampleRate,
2658 int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
2659 int32_t maxOutputChannelCount, const drcParams_t& drc,
2660 int32_t pcmLimiterEnable) {
2661 if (encoder && isADTS) {
2662 return -EINVAL;
2663 }
2664
2665 status_t err = setupRawAudioFormat(
2666 encoder ? kPortIndexInput : kPortIndexOutput,
2667 sampleRate,
2668 numChannels);
2669
2670 if (err != OK) {
2671 return err;
2672 }
2673
2674 if (encoder) {
2675 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
2676
2677 if (err != OK) {
2678 return err;
2679 }
2680
2681 OMX_PARAM_PORTDEFINITIONTYPE def;
2682 InitOMXParams(&def);
2683 def.nPortIndex = kPortIndexOutput;
2684
2685 err = mOMXNode->getParameter(
2686 OMX_IndexParamPortDefinition, &def, sizeof(def));
2687
2688 if (err != OK) {
2689 return err;
2690 }
2691
2692 def.format.audio.bFlagErrorConcealment = OMX_TRUE;
2693 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
2694
2695 err = mOMXNode->setParameter(
2696 OMX_IndexParamPortDefinition, &def, sizeof(def));
2697
2698 if (err != OK) {
2699 return err;
2700 }
2701
2702 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2703 InitOMXParams(&profile);
2704 profile.nPortIndex = kPortIndexOutput;
2705
2706 err = mOMXNode->getParameter(
2707 OMX_IndexParamAudioAac, &profile, sizeof(profile));
2708
2709 if (err != OK) {
2710 return err;
2711 }
2712
2713 profile.nChannels = numChannels;
2714
2715 profile.eChannelMode =
2716 (numChannels == 1)
2717 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
2718
2719 profile.nSampleRate = sampleRate;
2720 profile.nBitRate = bitRate;
2721 profile.nAudioBandWidth = 0;
2722 profile.nFrameLength = 0;
2723 profile.nAACtools = OMX_AUDIO_AACToolAll;
2724 profile.nAACERtools = OMX_AUDIO_AACERNone;
2725 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
2726 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
2727 switch (sbrMode) {
2728 case 0:
2729 // disable sbr
2730 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2731 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2732 break;
2733 case 1:
2734 // enable single-rate sbr
2735 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2736 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2737 break;
2738 case 2:
2739 // enable dual-rate sbr
2740 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2741 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2742 break;
2743 case -1:
2744 // enable both modes -> the codec will decide which mode should be used
2745 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2746 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2747 break;
2748 default:
2749 // unsupported sbr mode
2750 return BAD_VALUE;
2751 }
2752
2753
2754 err = mOMXNode->setParameter(
2755 OMX_IndexParamAudioAac, &profile, sizeof(profile));
2756
2757 if (err != OK) {
2758 return err;
2759 }
2760
2761 return err;
2762 }
2763
2764 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2765 InitOMXParams(&profile);
2766 profile.nPortIndex = kPortIndexInput;
2767
2768 err = mOMXNode->getParameter(
2769 OMX_IndexParamAudioAac, &profile, sizeof(profile));
2770
2771 if (err != OK) {
2772 return err;
2773 }
2774
2775 profile.nChannels = numChannels;
2776 profile.nSampleRate = sampleRate;
2777
2778 profile.eAACStreamFormat =
2779 isADTS
2780 ? OMX_AUDIO_AACStreamFormatMP4ADTS
2781 : OMX_AUDIO_AACStreamFormatMP4FF;
2782
2783 OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
2784 InitOMXParams(&presentation);
2785 presentation.nMaxOutputChannels = maxOutputChannelCount;
2786 presentation.nDrcCut = drc.drcCut;
2787 presentation.nDrcBoost = drc.drcBoost;
2788 presentation.nHeavyCompression = drc.heavyCompression;
2789 presentation.nTargetReferenceLevel = drc.targetRefLevel;
2790 presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
2791 presentation.nPCMLimiterEnable = pcmLimiterEnable;
2792
2793 status_t res = mOMXNode->setParameter(
2794 OMX_IndexParamAudioAac, &profile, sizeof(profile));
2795 if (res == OK) {
2796 // optional parameters, will not cause configuration failure
2797 mOMXNode->setParameter(
2798 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
2799 &presentation, sizeof(presentation));
2800 } else {
2801 ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
2802 }
2803 mSampleRate = sampleRate;
2804 return res;
2805 }
2806
setupAC3Codec(bool encoder,int32_t numChannels,int32_t sampleRate)2807 status_t ACodec::setupAC3Codec(
2808 bool encoder, int32_t numChannels, int32_t sampleRate) {
2809 status_t err = setupRawAudioFormat(
2810 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2811
2812 if (err != OK) {
2813 return err;
2814 }
2815
2816 if (encoder) {
2817 ALOGW("AC3 encoding is not supported.");
2818 return INVALID_OPERATION;
2819 }
2820
2821 OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
2822 InitOMXParams(&def);
2823 def.nPortIndex = kPortIndexInput;
2824
2825 err = mOMXNode->getParameter(
2826 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
2827
2828 if (err != OK) {
2829 return err;
2830 }
2831
2832 def.nChannels = numChannels;
2833 def.nSampleRate = sampleRate;
2834
2835 return mOMXNode->setParameter(
2836 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
2837 }
2838
setupEAC3Codec(bool encoder,int32_t numChannels,int32_t sampleRate)2839 status_t ACodec::setupEAC3Codec(
2840 bool encoder, int32_t numChannels, int32_t sampleRate) {
2841 status_t err = setupRawAudioFormat(
2842 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2843
2844 if (err != OK) {
2845 return err;
2846 }
2847
2848 if (encoder) {
2849 ALOGW("EAC3 encoding is not supported.");
2850 return INVALID_OPERATION;
2851 }
2852
2853 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
2854 InitOMXParams(&def);
2855 def.nPortIndex = kPortIndexInput;
2856
2857 err = mOMXNode->getParameter(
2858 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
2859
2860 if (err != OK) {
2861 return err;
2862 }
2863
2864 def.nChannels = numChannels;
2865 def.nSampleRate = sampleRate;
2866
2867 return mOMXNode->setParameter(
2868 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
2869 }
2870
pickModeFromBitRate(bool isAMRWB,int32_t bps)2871 static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
2872 bool isAMRWB, int32_t bps) {
2873 if (isAMRWB) {
2874 if (bps <= 6600) {
2875 return OMX_AUDIO_AMRBandModeWB0;
2876 } else if (bps <= 8850) {
2877 return OMX_AUDIO_AMRBandModeWB1;
2878 } else if (bps <= 12650) {
2879 return OMX_AUDIO_AMRBandModeWB2;
2880 } else if (bps <= 14250) {
2881 return OMX_AUDIO_AMRBandModeWB3;
2882 } else if (bps <= 15850) {
2883 return OMX_AUDIO_AMRBandModeWB4;
2884 } else if (bps <= 18250) {
2885 return OMX_AUDIO_AMRBandModeWB5;
2886 } else if (bps <= 19850) {
2887 return OMX_AUDIO_AMRBandModeWB6;
2888 } else if (bps <= 23050) {
2889 return OMX_AUDIO_AMRBandModeWB7;
2890 }
2891
2892 // 23850 bps
2893 return OMX_AUDIO_AMRBandModeWB8;
2894 } else { // AMRNB
2895 if (bps <= 4750) {
2896 return OMX_AUDIO_AMRBandModeNB0;
2897 } else if (bps <= 5150) {
2898 return OMX_AUDIO_AMRBandModeNB1;
2899 } else if (bps <= 5900) {
2900 return OMX_AUDIO_AMRBandModeNB2;
2901 } else if (bps <= 6700) {
2902 return OMX_AUDIO_AMRBandModeNB3;
2903 } else if (bps <= 7400) {
2904 return OMX_AUDIO_AMRBandModeNB4;
2905 } else if (bps <= 7950) {
2906 return OMX_AUDIO_AMRBandModeNB5;
2907 } else if (bps <= 10200) {
2908 return OMX_AUDIO_AMRBandModeNB6;
2909 }
2910
2911 // 12200 bps
2912 return OMX_AUDIO_AMRBandModeNB7;
2913 }
2914 }
2915
setupAMRCodec(bool encoder,bool isWAMR,int32_t bitrate)2916 status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
2917 OMX_AUDIO_PARAM_AMRTYPE def;
2918 InitOMXParams(&def);
2919 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
2920
2921 status_t err = mOMXNode->getParameter(
2922 OMX_IndexParamAudioAmr, &def, sizeof(def));
2923
2924 if (err != OK) {
2925 return err;
2926 }
2927
2928 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
2929 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
2930
2931 err = mOMXNode->setParameter(
2932 OMX_IndexParamAudioAmr, &def, sizeof(def));
2933
2934 if (err != OK) {
2935 return err;
2936 }
2937
2938 return setupRawAudioFormat(
2939 encoder ? kPortIndexInput : kPortIndexOutput,
2940 isWAMR ? 16000 : 8000 /* sampleRate */,
2941 1 /* numChannels */);
2942 }
2943
setupG711Codec(bool encoder,int32_t sampleRate,int32_t numChannels)2944 status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) {
2945 if (encoder) {
2946 return INVALID_OPERATION;
2947 }
2948
2949 return setupRawAudioFormat(
2950 kPortIndexInput, sampleRate, numChannels);
2951 }
2952
setupFlacCodec(bool encoder,int32_t numChannels,int32_t sampleRate,int32_t compressionLevel)2953 status_t ACodec::setupFlacCodec(
2954 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
2955
2956 if (encoder) {
2957 OMX_AUDIO_PARAM_FLACTYPE def;
2958 InitOMXParams(&def);
2959 def.nPortIndex = kPortIndexOutput;
2960
2961 // configure compression level
2962 status_t err = mOMXNode->getParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
2963 if (err != OK) {
2964 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
2965 return err;
2966 }
2967 def.nCompressionLevel = compressionLevel;
2968 err = mOMXNode->setParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
2969 if (err != OK) {
2970 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
2971 return err;
2972 }
2973 }
2974
2975 return setupRawAudioFormat(
2976 encoder ? kPortIndexInput : kPortIndexOutput,
2977 sampleRate,
2978 numChannels);
2979 }
2980
setupRawAudioFormat(OMX_U32 portIndex,int32_t sampleRate,int32_t numChannels,AudioEncoding encoding)2981 status_t ACodec::setupRawAudioFormat(
2982 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels, AudioEncoding encoding) {
2983 OMX_PARAM_PORTDEFINITIONTYPE def;
2984 InitOMXParams(&def);
2985 def.nPortIndex = portIndex;
2986
2987 status_t err = mOMXNode->getParameter(
2988 OMX_IndexParamPortDefinition, &def, sizeof(def));
2989
2990 if (err != OK) {
2991 return err;
2992 }
2993
2994 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2995
2996 err = mOMXNode->setParameter(
2997 OMX_IndexParamPortDefinition, &def, sizeof(def));
2998
2999 if (err != OK) {
3000 return err;
3001 }
3002
3003 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
3004 InitOMXParams(&pcmParams);
3005 pcmParams.nPortIndex = portIndex;
3006
3007 err = mOMXNode->getParameter(
3008 OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3009
3010 if (err != OK) {
3011 return err;
3012 }
3013
3014 pcmParams.nChannels = numChannels;
3015 switch (encoding) {
3016 case kAudioEncodingPcm8bit:
3017 pcmParams.eNumData = OMX_NumericalDataUnsigned;
3018 pcmParams.nBitPerSample = 8;
3019 break;
3020 case kAudioEncodingPcmFloat:
3021 pcmParams.eNumData = OMX_NumericalDataFloat;
3022 pcmParams.nBitPerSample = 32;
3023 break;
3024 case kAudioEncodingPcm16bit:
3025 pcmParams.eNumData = OMX_NumericalDataSigned;
3026 pcmParams.nBitPerSample = 16;
3027 break;
3028 default:
3029 return BAD_VALUE;
3030 }
3031 pcmParams.bInterleaved = OMX_TRUE;
3032 pcmParams.nSamplingRate = sampleRate;
3033 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
3034
3035 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
3036 return OMX_ErrorNone;
3037 }
3038
3039 err = mOMXNode->setParameter(
3040 OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3041 // if we could not set up raw format to non-16-bit, try with 16-bit
3042 // NOTE: we will also verify this via readback, in case codec ignores these fields
3043 if (err != OK && encoding != kAudioEncodingPcm16bit) {
3044 pcmParams.eNumData = OMX_NumericalDataSigned;
3045 pcmParams.nBitPerSample = 16;
3046 err = mOMXNode->setParameter(
3047 OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
3048 }
3049 return err;
3050 }
3051
configureTunneledVideoPlayback(int32_t audioHwSync,const sp<ANativeWindow> & nativeWindow)3052 status_t ACodec::configureTunneledVideoPlayback(
3053 int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
3054 native_handle_t* sidebandHandle;
3055
3056 status_t err = mOMXNode->configureVideoTunnelMode(
3057 kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
3058 if (err != OK) {
3059 ALOGE("configureVideoTunnelMode failed! (err %d).", err);
3060 return err;
3061 }
3062
3063 err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
3064 if (err != OK) {
3065 ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
3066 sidebandHandle, err);
3067 return err;
3068 }
3069
3070 return OK;
3071 }
3072
setVideoPortFormatType(OMX_U32 portIndex,OMX_VIDEO_CODINGTYPE compressionFormat,OMX_COLOR_FORMATTYPE colorFormat,bool usingNativeBuffers)3073 status_t ACodec::setVideoPortFormatType(
3074 OMX_U32 portIndex,
3075 OMX_VIDEO_CODINGTYPE compressionFormat,
3076 OMX_COLOR_FORMATTYPE colorFormat,
3077 bool usingNativeBuffers) {
3078 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
3079 InitOMXParams(&format);
3080 format.nPortIndex = portIndex;
3081 format.nIndex = 0;
3082 bool found = false;
3083
3084 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
3085 format.nIndex = index;
3086 status_t err = mOMXNode->getParameter(
3087 OMX_IndexParamVideoPortFormat,
3088 &format, sizeof(format));
3089
3090 if (err != OK) {
3091 return err;
3092 }
3093
3094 // substitute back flexible color format to codec supported format
3095 OMX_U32 flexibleEquivalent;
3096 if (compressionFormat == OMX_VIDEO_CodingUnused
3097 && IsFlexibleColorFormat(
3098 mOMXNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
3099 && colorFormat == flexibleEquivalent) {
3100 ALOGI("[%s] using color format %#x in place of %#x",
3101 mComponentName.c_str(), format.eColorFormat, colorFormat);
3102 colorFormat = format.eColorFormat;
3103 }
3104
3105 // The following assertion is violated by TI's video decoder.
3106 // CHECK_EQ(format.nIndex, index);
3107
3108 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
3109 if (portIndex == kPortIndexInput
3110 && colorFormat == format.eColorFormat) {
3111 // eCompressionFormat does not seem right.
3112 found = true;
3113 break;
3114 }
3115 if (portIndex == kPortIndexOutput
3116 && compressionFormat == format.eCompressionFormat) {
3117 // eColorFormat does not seem right.
3118 found = true;
3119 break;
3120 }
3121 }
3122
3123 if (format.eCompressionFormat == compressionFormat
3124 && format.eColorFormat == colorFormat) {
3125 found = true;
3126 break;
3127 }
3128
3129 if (index == kMaxIndicesToCheck) {
3130 ALOGW("[%s] stopping checking formats after %u: %s(%x)/%s(%x)",
3131 mComponentName.c_str(), index,
3132 asString(format.eCompressionFormat), format.eCompressionFormat,
3133 asString(format.eColorFormat), format.eColorFormat);
3134 }
3135 }
3136
3137 if (!found) {
3138 return UNKNOWN_ERROR;
3139 }
3140
3141 status_t err = mOMXNode->setParameter(
3142 OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3143
3144 return err;
3145 }
3146
3147 // Set optimal output format. OMX component lists output formats in the order
3148 // of preference, but this got more complicated since the introduction of flexible
3149 // YUV formats. We support a legacy behavior for applications that do not use
3150 // surface output, do not specify an output format, but expect a "usable" standard
3151 // OMX format. SW readable and standard formats must be flex-YUV.
3152 //
3153 // Suggested preference order:
3154 // - optimal format for texture rendering (mediaplayer behavior)
3155 // - optimal SW readable & texture renderable format (flex-YUV support)
3156 // - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
3157 // - legacy "usable" standard formats
3158 //
3159 // For legacy support, we prefer a standard format, but will settle for a SW readable
3160 // flex-YUV format.
setSupportedOutputFormat(bool getLegacyFlexibleFormat)3161 status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
3162 OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
3163 InitOMXParams(&format);
3164 format.nPortIndex = kPortIndexOutput;
3165
3166 InitOMXParams(&legacyFormat);
3167 // this field will change when we find a suitable legacy format
3168 legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
3169
3170 for (OMX_U32 index = 0; ; ++index) {
3171 format.nIndex = index;
3172 status_t err = mOMXNode->getParameter(
3173 OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3174 if (err != OK) {
3175 // no more formats, pick legacy format if found
3176 if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
3177 memcpy(&format, &legacyFormat, sizeof(format));
3178 break;
3179 }
3180 return err;
3181 }
3182 if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
3183 return OMX_ErrorBadParameter;
3184 }
3185 if (!getLegacyFlexibleFormat) {
3186 break;
3187 }
3188 // standard formats that were exposed to users before
3189 if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
3190 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
3191 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
3192 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
3193 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
3194 break;
3195 }
3196 // find best legacy non-standard format
3197 OMX_U32 flexibleEquivalent;
3198 if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
3199 && IsFlexibleColorFormat(
3200 mOMXNode, format.eColorFormat, false /* usingNativeBuffers */,
3201 &flexibleEquivalent)
3202 && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
3203 memcpy(&legacyFormat, &format, sizeof(format));
3204 }
3205 }
3206 return mOMXNode->setParameter(
3207 OMX_IndexParamVideoPortFormat, &format, sizeof(format));
3208 }
3209
3210 static const struct VideoCodingMapEntry {
3211 const char *mMime;
3212 OMX_VIDEO_CODINGTYPE mVideoCodingType;
3213 } kVideoCodingMapEntry[] = {
3214 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
3215 { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
3216 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
3217 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
3218 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
3219 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
3220 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
3221 { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, OMX_VIDEO_CodingDolbyVision },
3222 };
3223
GetVideoCodingTypeFromMime(const char * mime,OMX_VIDEO_CODINGTYPE * codingType)3224 static status_t GetVideoCodingTypeFromMime(
3225 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
3226 for (size_t i = 0;
3227 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
3228 ++i) {
3229 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
3230 *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
3231 return OK;
3232 }
3233 }
3234
3235 *codingType = OMX_VIDEO_CodingUnused;
3236
3237 return ERROR_UNSUPPORTED;
3238 }
3239
GetMimeTypeForVideoCoding(OMX_VIDEO_CODINGTYPE codingType,AString * mime)3240 static status_t GetMimeTypeForVideoCoding(
3241 OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
3242 for (size_t i = 0;
3243 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
3244 ++i) {
3245 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
3246 *mime = kVideoCodingMapEntry[i].mMime;
3247 return OK;
3248 }
3249 }
3250
3251 mime->clear();
3252
3253 return ERROR_UNSUPPORTED;
3254 }
3255
setPortBufferNum(OMX_U32 portIndex,int bufferNum)3256 status_t ACodec::setPortBufferNum(OMX_U32 portIndex, int bufferNum) {
3257 OMX_PARAM_PORTDEFINITIONTYPE def;
3258 InitOMXParams(&def);
3259 def.nPortIndex = portIndex;
3260 status_t err;
3261 ALOGD("Setting [%s] %s port buffer number: %d", mComponentName.c_str(),
3262 portIndex == kPortIndexInput ? "input" : "output", bufferNum);
3263 err = mOMXNode->getParameter(
3264 OMX_IndexParamPortDefinition, &def, sizeof(def));
3265 if (err != OK) {
3266 return err;
3267 }
3268 def.nBufferCountActual = bufferNum;
3269 err = mOMXNode->setParameter(
3270 OMX_IndexParamPortDefinition, &def, sizeof(def));
3271 if (err != OK) {
3272 // Component could reject this request.
3273 ALOGW("Fail to set [%s] %s port buffer number: %d", mComponentName.c_str(),
3274 portIndex == kPortIndexInput ? "input" : "output", bufferNum);
3275 }
3276 return OK;
3277 }
3278
setupVideoDecoder(const char * mime,const sp<AMessage> & msg,bool haveNativeWindow,bool usingSwRenderer,sp<AMessage> & outputFormat)3279 status_t ACodec::setupVideoDecoder(
3280 const char *mime, const sp<AMessage> &msg, bool haveNativeWindow,
3281 bool usingSwRenderer, sp<AMessage> &outputFormat) {
3282 int32_t width, height;
3283 if (!msg->findInt32("width", &width)
3284 || !msg->findInt32("height", &height)) {
3285 return INVALID_OPERATION;
3286 }
3287
3288 OMX_VIDEO_CODINGTYPE compressionFormat;
3289 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3290
3291 if (err != OK) {
3292 return err;
3293 }
3294
3295 if (compressionFormat == OMX_VIDEO_CodingVP9) {
3296 OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
3297 InitOMXParams(¶ms);
3298 params.nPortIndex = kPortIndexInput;
3299 // Check if VP9 decoder advertises supported profiles.
3300 params.nProfileIndex = 0;
3301 status_t err = mOMXNode->getParameter(
3302 OMX_IndexParamVideoProfileLevelQuerySupported,
3303 ¶ms, sizeof(params));
3304 mIsLegacyVP9Decoder = err != OK;
3305 }
3306
3307 err = setVideoPortFormatType(
3308 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
3309
3310 if (err != OK) {
3311 return err;
3312 }
3313
3314 int32_t tmp;
3315 if (msg->findInt32("color-format", &tmp)) {
3316 OMX_COLOR_FORMATTYPE colorFormat =
3317 static_cast<OMX_COLOR_FORMATTYPE>(tmp);
3318 err = setVideoPortFormatType(
3319 kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
3320 if (err != OK) {
3321 ALOGW("[%s] does not support color format %d",
3322 mComponentName.c_str(), colorFormat);
3323 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
3324 }
3325 } else {
3326 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
3327 }
3328
3329 if (err != OK) {
3330 return err;
3331 }
3332
3333 // Set the component input buffer number to be |tmp|. If succeed,
3334 // component will set input port buffer number to be |tmp|. If fail,
3335 // component will keep the same buffer number as before.
3336 if (msg->findInt32("android._num-input-buffers", &tmp)) {
3337 err = setPortBufferNum(kPortIndexInput, tmp);
3338 if (err != OK)
3339 return err;
3340 }
3341
3342 // Set the component output buffer number to be |tmp|. If succeed,
3343 // component will set output port buffer number to be |tmp|. If fail,
3344 // component will keep the same buffer number as before.
3345 if (msg->findInt32("android._num-output-buffers", &tmp)) {
3346 err = setPortBufferNum(kPortIndexOutput, tmp);
3347 if (err != OK)
3348 return err;
3349 }
3350
3351 int32_t frameRateInt;
3352 float frameRateFloat;
3353 if (!msg->findFloat("frame-rate", &frameRateFloat)) {
3354 if (!msg->findInt32("frame-rate", &frameRateInt)) {
3355 frameRateInt = -1;
3356 }
3357 frameRateFloat = (float)frameRateInt;
3358 }
3359
3360 err = setVideoFormatOnPort(
3361 kPortIndexInput, width, height, compressionFormat, frameRateFloat);
3362
3363 if (err != OK) {
3364 return err;
3365 }
3366
3367 err = setVideoFormatOnPort(
3368 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
3369
3370 if (err != OK) {
3371 return err;
3372 }
3373
3374 err = setColorAspectsForVideoDecoder(
3375 width, height, haveNativeWindow | usingSwRenderer, msg, outputFormat);
3376 if (err == ERROR_UNSUPPORTED) { // support is optional
3377 err = OK;
3378 }
3379
3380 if (err != OK) {
3381 return err;
3382 }
3383
3384 err = setHDRStaticInfoForVideoCodec(kPortIndexOutput, msg, outputFormat);
3385 if (err == ERROR_UNSUPPORTED) { // support is optional
3386 err = OK;
3387 }
3388 return err;
3389 }
3390
initDescribeColorAspectsIndex()3391 status_t ACodec::initDescribeColorAspectsIndex() {
3392 status_t err = mOMXNode->getExtensionIndex(
3393 "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
3394 if (err != OK) {
3395 mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0;
3396 }
3397 return err;
3398 }
3399
setCodecColorAspects(DescribeColorAspectsParams & params,bool verify)3400 status_t ACodec::setCodecColorAspects(DescribeColorAspectsParams ¶ms, bool verify) {
3401 status_t err = ERROR_UNSUPPORTED;
3402 if (mDescribeColorAspectsIndex) {
3403 err = mOMXNode->setConfig(mDescribeColorAspectsIndex, ¶ms, sizeof(params));
3404 }
3405 ALOGV("[%s] setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
3406 mComponentName.c_str(),
3407 params.sAspects.mRange, asString(params.sAspects.mRange),
3408 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3409 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3410 params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3411 err, asString(err));
3412
3413 if (verify && err == OK) {
3414 err = getCodecColorAspects(params);
3415 }
3416
3417 ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex,
3418 "[%s] setting color aspects failed even though codec advertises support",
3419 mComponentName.c_str());
3420 return err;
3421 }
3422
setColorAspectsForVideoDecoder(int32_t width,int32_t height,bool usingNativeWindow,const sp<AMessage> & configFormat,sp<AMessage> & outputFormat)3423 status_t ACodec::setColorAspectsForVideoDecoder(
3424 int32_t width, int32_t height, bool usingNativeWindow,
3425 const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) {
3426 DescribeColorAspectsParams params;
3427 InitOMXParams(¶ms);
3428 params.nPortIndex = kPortIndexOutput;
3429
3430 getColorAspectsFromFormat(configFormat, params.sAspects);
3431 if (usingNativeWindow) {
3432 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3433 // The default aspects will be set back to the output format during the
3434 // getFormat phase of configure(). Set non-Unspecified values back into the
3435 // format, in case component does not support this enumeration.
3436 setColorAspectsIntoFormat(params.sAspects, outputFormat);
3437 }
3438
3439 (void)initDescribeColorAspectsIndex();
3440
3441 // communicate color aspects to codec
3442 return setCodecColorAspects(params);
3443 }
3444
getCodecColorAspects(DescribeColorAspectsParams & params)3445 status_t ACodec::getCodecColorAspects(DescribeColorAspectsParams ¶ms) {
3446 status_t err = ERROR_UNSUPPORTED;
3447 if (mDescribeColorAspectsIndex) {
3448 err = mOMXNode->getConfig(mDescribeColorAspectsIndex, ¶ms, sizeof(params));
3449 }
3450 ALOGV("[%s] got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
3451 mComponentName.c_str(),
3452 params.sAspects.mRange, asString(params.sAspects.mRange),
3453 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3454 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3455 params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3456 err, asString(err));
3457 if (params.bRequestingDataSpace) {
3458 ALOGV("for dataspace %#x", params.nDataSpace);
3459 }
3460 if (err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex
3461 && !params.bRequestingDataSpace && !params.bDataSpaceChanged) {
3462 ALOGW("[%s] getting color aspects failed even though codec advertises support",
3463 mComponentName.c_str());
3464 }
3465 return err;
3466 }
3467
getInputColorAspectsForVideoEncoder(sp<AMessage> & format)3468 status_t ACodec::getInputColorAspectsForVideoEncoder(sp<AMessage> &format) {
3469 DescribeColorAspectsParams params;
3470 InitOMXParams(¶ms);
3471 params.nPortIndex = kPortIndexInput;
3472 status_t err = getCodecColorAspects(params);
3473 if (err == OK) {
3474 // we only set encoder input aspects if codec supports them
3475 setColorAspectsIntoFormat(params.sAspects, format, true /* force */);
3476 }
3477 return err;
3478 }
3479
getDataSpace(DescribeColorAspectsParams & params,android_dataspace * dataSpace,bool tryCodec)3480 status_t ACodec::getDataSpace(
3481 DescribeColorAspectsParams ¶ms, android_dataspace *dataSpace /* nonnull */,
3482 bool tryCodec) {
3483 status_t err = OK;
3484 if (tryCodec) {
3485 // request dataspace guidance from codec.
3486 params.bRequestingDataSpace = OMX_TRUE;
3487 err = getCodecColorAspects(params);
3488 params.bRequestingDataSpace = OMX_FALSE;
3489 if (err == OK && params.nDataSpace != HAL_DATASPACE_UNKNOWN) {
3490 *dataSpace = (android_dataspace)params.nDataSpace;
3491 return err;
3492 } else if (err == ERROR_UNSUPPORTED) {
3493 // ignore not-implemented error for dataspace requests
3494 err = OK;
3495 }
3496 }
3497
3498 // this returns legacy versions if available
3499 *dataSpace = getDataSpaceForColorAspects(params.sAspects, true /* mayexpand */);
3500 ALOGV("[%s] using color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
3501 "and dataspace %#x",
3502 mComponentName.c_str(),
3503 params.sAspects.mRange, asString(params.sAspects.mRange),
3504 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
3505 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
3506 params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
3507 *dataSpace);
3508 return err;
3509 }
3510
3511
getColorAspectsAndDataSpaceForVideoDecoder(int32_t width,int32_t height,const sp<AMessage> & configFormat,sp<AMessage> & outputFormat,android_dataspace * dataSpace)3512 status_t ACodec::getColorAspectsAndDataSpaceForVideoDecoder(
3513 int32_t width, int32_t height, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat,
3514 android_dataspace *dataSpace) {
3515 DescribeColorAspectsParams params;
3516 InitOMXParams(¶ms);
3517 params.nPortIndex = kPortIndexOutput;
3518
3519 // reset default format and get resulting format
3520 getColorAspectsFromFormat(configFormat, params.sAspects);
3521 if (dataSpace != NULL) {
3522 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3523 }
3524 status_t err = setCodecColorAspects(params, true /* readBack */);
3525
3526 // we always set specified aspects for decoders
3527 setColorAspectsIntoFormat(params.sAspects, outputFormat);
3528
3529 if (dataSpace != NULL) {
3530 status_t res = getDataSpace(params, dataSpace, err == OK /* tryCodec */);
3531 if (err == OK) {
3532 err = res;
3533 }
3534 }
3535
3536 return err;
3537 }
3538
3539 // initial video encoder setup for bytebuffer mode
setColorAspectsForVideoEncoder(const sp<AMessage> & configFormat,sp<AMessage> & outputFormat,sp<AMessage> & inputFormat)3540 status_t ACodec::setColorAspectsForVideoEncoder(
3541 const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) {
3542 // copy config to output format as this is not exposed via getFormat
3543 copyColorConfig(configFormat, outputFormat);
3544
3545 DescribeColorAspectsParams params;
3546 InitOMXParams(¶ms);
3547 params.nPortIndex = kPortIndexInput;
3548 getColorAspectsFromFormat(configFormat, params.sAspects);
3549
3550 (void)initDescribeColorAspectsIndex();
3551
3552 int32_t usingRecorder;
3553 if (configFormat->findInt32("android._using-recorder", &usingRecorder) && usingRecorder) {
3554 android_dataspace dataSpace = HAL_DATASPACE_BT709;
3555 int32_t width, height;
3556 if (configFormat->findInt32("width", &width)
3557 && configFormat->findInt32("height", &height)) {
3558 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3559 status_t err = getDataSpace(
3560 params, &dataSpace, mDescribeColorAspectsIndex /* tryCodec */);
3561 if (err != OK) {
3562 return err;
3563 }
3564 setColorAspectsIntoFormat(params.sAspects, outputFormat);
3565 }
3566 inputFormat->setInt32("android._dataspace", (int32_t)dataSpace);
3567 }
3568
3569 // communicate color aspects to codec, but do not allow change of the platform aspects
3570 ColorAspects origAspects = params.sAspects;
3571 for (int triesLeft = 2; --triesLeft >= 0; ) {
3572 status_t err = setCodecColorAspects(params, true /* readBack */);
3573 if (err != OK
3574 || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
3575 params.sAspects, origAspects, true /* usePlatformAspects */)) {
3576 return err;
3577 }
3578 ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.",
3579 mComponentName.c_str());
3580 }
3581 return OK;
3582 }
3583
setHDRStaticInfoForVideoCodec(OMX_U32 portIndex,const sp<AMessage> & configFormat,sp<AMessage> & outputFormat)3584 status_t ACodec::setHDRStaticInfoForVideoCodec(
3585 OMX_U32 portIndex, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) {
3586 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
3587
3588 DescribeHDRStaticInfoParams params;
3589 InitOMXParams(¶ms);
3590 params.nPortIndex = portIndex;
3591
3592 HDRStaticInfo *info = ¶ms.sInfo;
3593 if (getHDRStaticInfoFromFormat(configFormat, info)) {
3594 setHDRStaticInfoIntoFormat(params.sInfo, outputFormat);
3595 }
3596
3597 (void)initDescribeHDRStaticInfoIndex();
3598
3599 // communicate HDR static Info to codec
3600 return setHDRStaticInfo(params);
3601 }
3602
3603 // subsequent initial video encoder setup for surface mode
setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(android_dataspace * dataSpace)3604 status_t ACodec::setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(
3605 android_dataspace *dataSpace /* nonnull */) {
3606 DescribeColorAspectsParams params;
3607 InitOMXParams(¶ms);
3608 params.nPortIndex = kPortIndexInput;
3609 ColorAspects &aspects = params.sAspects;
3610
3611 // reset default format and store resulting format into both input and output formats
3612 getColorAspectsFromFormat(mConfigFormat, aspects);
3613 int32_t width, height;
3614 if (mInputFormat->findInt32("width", &width) && mInputFormat->findInt32("height", &height)) {
3615 setDefaultCodecColorAspectsIfNeeded(aspects, width, height);
3616 }
3617 setColorAspectsIntoFormat(aspects, mInputFormat);
3618 setColorAspectsIntoFormat(aspects, mOutputFormat);
3619
3620 // communicate color aspects to codec, but do not allow any change
3621 ColorAspects origAspects = aspects;
3622 status_t err = OK;
3623 for (int triesLeft = 2; mDescribeColorAspectsIndex && --triesLeft >= 0; ) {
3624 status_t err = setCodecColorAspects(params, true /* readBack */);
3625 if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(aspects, origAspects)) {
3626 break;
3627 }
3628 ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.",
3629 mComponentName.c_str());
3630 }
3631
3632 *dataSpace = HAL_DATASPACE_BT709;
3633 aspects = origAspects; // restore desired color aspects
3634 status_t res = getDataSpace(
3635 params, dataSpace, err == OK && mDescribeColorAspectsIndex /* tryCodec */);
3636 if (err == OK) {
3637 err = res;
3638 }
3639 mInputFormat->setInt32("android._dataspace", (int32_t)*dataSpace);
3640 mInputFormat->setBuffer(
3641 "android._color-aspects", ABuffer::CreateAsCopy(&aspects, sizeof(aspects)));
3642
3643 // update input format with codec supported color aspects (basically set unsupported
3644 // aspects to Unspecified)
3645 if (err == OK) {
3646 (void)getInputColorAspectsForVideoEncoder(mInputFormat);
3647 }
3648
3649 ALOGV("set default color aspects, updated input format to %s, output format to %s",
3650 mInputFormat->debugString(4).c_str(), mOutputFormat->debugString(4).c_str());
3651
3652 return err;
3653 }
3654
getHDRStaticInfoForVideoCodec(OMX_U32 portIndex,sp<AMessage> & format)3655 status_t ACodec::getHDRStaticInfoForVideoCodec(OMX_U32 portIndex, sp<AMessage> &format) {
3656 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
3657 DescribeHDRStaticInfoParams params;
3658 InitOMXParams(¶ms);
3659 params.nPortIndex = portIndex;
3660
3661 status_t err = getHDRStaticInfo(params);
3662 if (err == OK) {
3663 // we only set decodec output HDRStaticInfo if codec supports them
3664 setHDRStaticInfoIntoFormat(params.sInfo, format);
3665 }
3666 return err;
3667 }
3668
initDescribeHDRStaticInfoIndex()3669 status_t ACodec::initDescribeHDRStaticInfoIndex() {
3670 status_t err = mOMXNode->getExtensionIndex(
3671 "OMX.google.android.index.describeHDRStaticInfo", &mDescribeHDRStaticInfoIndex);
3672 if (err != OK) {
3673 mDescribeHDRStaticInfoIndex = (OMX_INDEXTYPE)0;
3674 }
3675 return err;
3676 }
3677
setHDRStaticInfo(const DescribeHDRStaticInfoParams & params)3678 status_t ACodec::setHDRStaticInfo(const DescribeHDRStaticInfoParams ¶ms) {
3679 status_t err = ERROR_UNSUPPORTED;
3680 if (mDescribeHDRStaticInfoIndex) {
3681 err = mOMXNode->setConfig(mDescribeHDRStaticInfoIndex, ¶ms, sizeof(params));
3682 }
3683
3684 const HDRStaticInfo *info = ¶ms.sInfo;
3685 ALOGV("[%s] setting HDRStaticInfo (R: %u %u, G: %u %u, B: %u, %u, W: %u, %u, "
3686 "MaxDispL: %u, MinDispL: %u, MaxContentL: %u, MaxFrameAvgL: %u)",
3687 mComponentName.c_str(),
3688 info->sType1.mR.x, info->sType1.mR.y, info->sType1.mG.x, info->sType1.mG.y,
3689 info->sType1.mB.x, info->sType1.mB.y, info->sType1.mW.x, info->sType1.mW.y,
3690 info->sType1.mMaxDisplayLuminance, info->sType1.mMinDisplayLuminance,
3691 info->sType1.mMaxContentLightLevel, info->sType1.mMaxFrameAverageLightLevel);
3692
3693 ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex,
3694 "[%s] setting HDRStaticInfo failed even though codec advertises support",
3695 mComponentName.c_str());
3696 return err;
3697 }
3698
getHDRStaticInfo(DescribeHDRStaticInfoParams & params)3699 status_t ACodec::getHDRStaticInfo(DescribeHDRStaticInfoParams ¶ms) {
3700 status_t err = ERROR_UNSUPPORTED;
3701 if (mDescribeHDRStaticInfoIndex) {
3702 err = mOMXNode->getConfig(mDescribeHDRStaticInfoIndex, ¶ms, sizeof(params));
3703 }
3704
3705 ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex,
3706 "[%s] getting HDRStaticInfo failed even though codec advertises support",
3707 mComponentName.c_str());
3708 return err;
3709 }
3710
setupVideoEncoder(const char * mime,const sp<AMessage> & msg,sp<AMessage> & outputFormat,sp<AMessage> & inputFormat)3711 status_t ACodec::setupVideoEncoder(
3712 const char *mime, const sp<AMessage> &msg,
3713 sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) {
3714 int32_t tmp;
3715 if (!msg->findInt32("color-format", &tmp)) {
3716 return INVALID_OPERATION;
3717 }
3718
3719 OMX_COLOR_FORMATTYPE colorFormat =
3720 static_cast<OMX_COLOR_FORMATTYPE>(tmp);
3721
3722 status_t err = setVideoPortFormatType(
3723 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
3724
3725 if (err != OK) {
3726 ALOGE("[%s] does not support color format %d",
3727 mComponentName.c_str(), colorFormat);
3728
3729 return err;
3730 }
3731
3732 /* Input port configuration */
3733
3734 OMX_PARAM_PORTDEFINITIONTYPE def;
3735 InitOMXParams(&def);
3736
3737 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3738
3739 def.nPortIndex = kPortIndexInput;
3740
3741 err = mOMXNode->getParameter(
3742 OMX_IndexParamPortDefinition, &def, sizeof(def));
3743
3744 if (err != OK) {
3745 return err;
3746 }
3747
3748 int32_t width, height, bitrate;
3749 if (!msg->findInt32("width", &width)
3750 || !msg->findInt32("height", &height)
3751 || !msg->findInt32("bitrate", &bitrate)) {
3752 return INVALID_OPERATION;
3753 }
3754
3755 video_def->nFrameWidth = width;
3756 video_def->nFrameHeight = height;
3757
3758 int32_t stride;
3759 if (!msg->findInt32("stride", &stride)) {
3760 stride = width;
3761 }
3762
3763 video_def->nStride = stride;
3764
3765 int32_t sliceHeight;
3766 if (!msg->findInt32("slice-height", &sliceHeight)) {
3767 sliceHeight = height;
3768 }
3769
3770 video_def->nSliceHeight = sliceHeight;
3771
3772 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
3773
3774 float framerate;
3775 if (!msg->findFloat("frame-rate", &framerate)) {
3776 int32_t tmp;
3777 if (!msg->findInt32("frame-rate", &tmp)) {
3778 return INVALID_OPERATION;
3779 }
3780 mFps = (double)tmp;
3781 } else {
3782 mFps = (double)framerate;
3783 }
3784
3785 video_def->xFramerate = (OMX_U32)(mFps * 65536);
3786 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
3787 // this is redundant as it was already set up in setVideoPortFormatType
3788 // FIXME for now skip this only for flexible YUV formats
3789 if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
3790 video_def->eColorFormat = colorFormat;
3791 }
3792
3793 err = mOMXNode->setParameter(
3794 OMX_IndexParamPortDefinition, &def, sizeof(def));
3795
3796 if (err != OK) {
3797 ALOGE("[%s] failed to set input port definition parameters.",
3798 mComponentName.c_str());
3799
3800 return err;
3801 }
3802
3803 /* Output port configuration */
3804
3805 OMX_VIDEO_CODINGTYPE compressionFormat;
3806 err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3807
3808 if (err != OK) {
3809 return err;
3810 }
3811
3812 err = setVideoPortFormatType(
3813 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
3814
3815 if (err != OK) {
3816 ALOGE("[%s] does not support compression format %d",
3817 mComponentName.c_str(), compressionFormat);
3818
3819 return err;
3820 }
3821
3822 def.nPortIndex = kPortIndexOutput;
3823
3824 err = mOMXNode->getParameter(
3825 OMX_IndexParamPortDefinition, &def, sizeof(def));
3826
3827 if (err != OK) {
3828 return err;
3829 }
3830
3831 video_def->nFrameWidth = width;
3832 video_def->nFrameHeight = height;
3833 video_def->xFramerate = 0;
3834 video_def->nBitrate = bitrate;
3835 video_def->eCompressionFormat = compressionFormat;
3836 video_def->eColorFormat = OMX_COLOR_FormatUnused;
3837
3838 err = mOMXNode->setParameter(
3839 OMX_IndexParamPortDefinition, &def, sizeof(def));
3840
3841 if (err != OK) {
3842 ALOGE("[%s] failed to set output port definition parameters.",
3843 mComponentName.c_str());
3844
3845 return err;
3846 }
3847
3848 int32_t intraRefreshPeriod = 0;
3849 if (msg->findInt32("intra-refresh-period", &intraRefreshPeriod)
3850 && intraRefreshPeriod >= 0) {
3851 err = setIntraRefreshPeriod((uint32_t)intraRefreshPeriod, true);
3852 if (err != OK) {
3853 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
3854 mComponentName.c_str());
3855 err = OK;
3856 }
3857 }
3858
3859 configureEncoderLatency(msg);
3860
3861 switch (compressionFormat) {
3862 case OMX_VIDEO_CodingMPEG4:
3863 err = setupMPEG4EncoderParameters(msg);
3864 break;
3865
3866 case OMX_VIDEO_CodingH263:
3867 err = setupH263EncoderParameters(msg);
3868 break;
3869
3870 case OMX_VIDEO_CodingAVC:
3871 err = setupAVCEncoderParameters(msg);
3872 break;
3873
3874 case OMX_VIDEO_CodingHEVC:
3875 err = setupHEVCEncoderParameters(msg);
3876 break;
3877
3878 case OMX_VIDEO_CodingVP8:
3879 case OMX_VIDEO_CodingVP9:
3880 err = setupVPXEncoderParameters(msg, outputFormat);
3881 break;
3882
3883 default:
3884 break;
3885 }
3886
3887 if (err != OK) {
3888 return err;
3889 }
3890
3891 // Set up color aspects on input, but propagate them to the output format, as they will
3892 // not be read back from encoder.
3893 err = setColorAspectsForVideoEncoder(msg, outputFormat, inputFormat);
3894 if (err == ERROR_UNSUPPORTED) {
3895 ALOGI("[%s] cannot encode color aspects. Ignoring.", mComponentName.c_str());
3896 err = OK;
3897 }
3898
3899 if (err != OK) {
3900 return err;
3901 }
3902
3903 err = setHDRStaticInfoForVideoCodec(kPortIndexInput, msg, outputFormat);
3904 if (err == ERROR_UNSUPPORTED) { // support is optional
3905 ALOGI("[%s] cannot encode HDR static metadata. Ignoring.", mComponentName.c_str());
3906 err = OK;
3907 }
3908
3909 if (err != OK) {
3910 return err;
3911 }
3912
3913 switch (compressionFormat) {
3914 case OMX_VIDEO_CodingAVC:
3915 case OMX_VIDEO_CodingHEVC:
3916 err = configureTemporalLayers(msg, true /* inConfigure */, outputFormat);
3917 if (err != OK) {
3918 err = OK; // ignore failure
3919 }
3920 break;
3921
3922 case OMX_VIDEO_CodingVP8:
3923 case OMX_VIDEO_CodingVP9:
3924 // TODO: do we need to support android.generic layering? webrtc layering is
3925 // already set up in setupVPXEncoderParameters.
3926 break;
3927
3928 default:
3929 break;
3930 }
3931
3932 if (err == OK) {
3933 ALOGI("setupVideoEncoder succeeded");
3934 }
3935
3936 return err;
3937 }
3938
setCyclicIntraMacroblockRefresh(const sp<AMessage> & msg,int32_t mode)3939 status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
3940 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
3941 InitOMXParams(¶ms);
3942 params.nPortIndex = kPortIndexOutput;
3943
3944 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
3945
3946 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
3947 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3948 int32_t mbs;
3949 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
3950 return INVALID_OPERATION;
3951 }
3952 params.nCirMBs = mbs;
3953 }
3954
3955 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
3956 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3957 int32_t mbs;
3958 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
3959 return INVALID_OPERATION;
3960 }
3961 params.nAirMBs = mbs;
3962
3963 int32_t ref;
3964 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
3965 return INVALID_OPERATION;
3966 }
3967 params.nAirRef = ref;
3968 }
3969
3970 status_t err = mOMXNode->setParameter(
3971 OMX_IndexParamVideoIntraRefresh, ¶ms, sizeof(params));
3972 return err;
3973 }
3974
setPFramesSpacing(float iFramesInterval,int32_t frameRate,uint32_t BFramesSpacing=0)3975 static OMX_U32 setPFramesSpacing(
3976 float iFramesInterval /* seconds */, int32_t frameRate, uint32_t BFramesSpacing = 0) {
3977 // BFramesSpacing is the number of B frames between I/P frames
3978 // PFramesSpacing (the value to be returned) is the number of P frames between I frames
3979 //
3980 // keyFrameInterval = ((PFramesSpacing + 1) * BFramesSpacing) + PFramesSpacing + 1
3981 // ^^^ ^^^ ^^^
3982 // number of B frames number of P I frame
3983 //
3984 // = (PFramesSpacing + 1) * (BFramesSpacing + 1)
3985 //
3986 // E.g.
3987 // I P I : I-interval: 8, nPFrames 1, nBFrames 3
3988 // BBB BBB
3989
3990 if (iFramesInterval < 0) { // just 1 key frame
3991 return 0xFFFFFFFE; // don't use maxint as key-frame-interval calculation will add 1
3992 } else if (iFramesInterval == 0) { // just key frames
3993 return 0;
3994 }
3995
3996 // round down as key-frame-interval is an upper limit
3997 uint32_t keyFrameInterval = uint32_t(frameRate * iFramesInterval);
3998 OMX_U32 ret = keyFrameInterval / (BFramesSpacing + 1);
3999 return ret > 0 ? ret - 1 : 0;
4000 }
4001
getBitrateMode(const sp<AMessage> & msg)4002 static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
4003 int32_t tmp;
4004 if (!msg->findInt32("bitrate-mode", &tmp)) {
4005 return OMX_Video_ControlRateVariable;
4006 }
4007
4008 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
4009 }
4010
setupMPEG4EncoderParameters(const sp<AMessage> & msg)4011 status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
4012 int32_t bitrate;
4013 float iFrameInterval;
4014 if (!msg->findInt32("bitrate", &bitrate)
4015 || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4016 return INVALID_OPERATION;
4017 }
4018
4019 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
4020
4021 float frameRate;
4022 if (!msg->findFloat("frame-rate", &frameRate)) {
4023 int32_t tmp;
4024 if (!msg->findInt32("frame-rate", &tmp)) {
4025 return INVALID_OPERATION;
4026 }
4027 frameRate = (float)tmp;
4028 }
4029
4030 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
4031 InitOMXParams(&mpeg4type);
4032 mpeg4type.nPortIndex = kPortIndexOutput;
4033
4034 status_t err = mOMXNode->getParameter(
4035 OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
4036
4037 if (err != OK) {
4038 return err;
4039 }
4040
4041 mpeg4type.nSliceHeaderSpacing = 0;
4042 mpeg4type.bSVH = OMX_FALSE;
4043 mpeg4type.bGov = OMX_FALSE;
4044
4045 mpeg4type.nAllowedPictureTypes =
4046 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4047
4048 mpeg4type.nBFrames = 0;
4049 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, mpeg4type.nBFrames);
4050 if (mpeg4type.nPFrames == 0) {
4051 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4052 }
4053 mpeg4type.nIDCVLCThreshold = 0;
4054 mpeg4type.bACPred = OMX_TRUE;
4055 mpeg4type.nMaxPacketSize = 256;
4056 mpeg4type.nTimeIncRes = 1000;
4057 mpeg4type.nHeaderExtension = 0;
4058 mpeg4type.bReversibleVLC = OMX_FALSE;
4059
4060 int32_t profile;
4061 if (msg->findInt32("profile", &profile)) {
4062 int32_t level;
4063 if (!msg->findInt32("level", &level)) {
4064 return INVALID_OPERATION;
4065 }
4066
4067 err = verifySupportForProfileAndLevel(profile, level);
4068
4069 if (err != OK) {
4070 return err;
4071 }
4072
4073 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
4074 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
4075 }
4076
4077 err = mOMXNode->setParameter(
4078 OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
4079
4080 if (err != OK) {
4081 return err;
4082 }
4083
4084 err = configureBitrate(bitrate, bitrateMode);
4085
4086 if (err != OK) {
4087 return err;
4088 }
4089
4090 return setupErrorCorrectionParameters();
4091 }
4092
setupH263EncoderParameters(const sp<AMessage> & msg)4093 status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
4094 int32_t bitrate;
4095 float iFrameInterval;
4096 if (!msg->findInt32("bitrate", &bitrate)
4097 || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4098 return INVALID_OPERATION;
4099 }
4100
4101 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
4102
4103 float frameRate;
4104 if (!msg->findFloat("frame-rate", &frameRate)) {
4105 int32_t tmp;
4106 if (!msg->findInt32("frame-rate", &tmp)) {
4107 return INVALID_OPERATION;
4108 }
4109 frameRate = (float)tmp;
4110 }
4111
4112 OMX_VIDEO_PARAM_H263TYPE h263type;
4113 InitOMXParams(&h263type);
4114 h263type.nPortIndex = kPortIndexOutput;
4115
4116 status_t err = mOMXNode->getParameter(
4117 OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
4118
4119 if (err != OK) {
4120 return err;
4121 }
4122
4123 h263type.nAllowedPictureTypes =
4124 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4125
4126 h263type.nBFrames = 0;
4127 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h263type.nBFrames);
4128 if (h263type.nPFrames == 0) {
4129 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4130 }
4131
4132 int32_t profile;
4133 if (msg->findInt32("profile", &profile)) {
4134 int32_t level;
4135 if (!msg->findInt32("level", &level)) {
4136 return INVALID_OPERATION;
4137 }
4138
4139 err = verifySupportForProfileAndLevel(profile, level);
4140
4141 if (err != OK) {
4142 return err;
4143 }
4144
4145 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
4146 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
4147 }
4148
4149 h263type.bPLUSPTYPEAllowed = OMX_FALSE;
4150 h263type.bForceRoundingTypeToZero = OMX_FALSE;
4151 h263type.nPictureHeaderRepetition = 0;
4152 h263type.nGOBHeaderInterval = 0;
4153
4154 err = mOMXNode->setParameter(
4155 OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
4156
4157 if (err != OK) {
4158 return err;
4159 }
4160
4161 err = configureBitrate(bitrate, bitrateMode);
4162
4163 if (err != OK) {
4164 return err;
4165 }
4166
4167 return setupErrorCorrectionParameters();
4168 }
4169
4170 // static
getAVCLevelFor(int width,int height,int rate,int bitrate,OMX_VIDEO_AVCPROFILEEXTTYPE profile)4171 int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
4172 int width, int height, int rate, int bitrate,
4173 OMX_VIDEO_AVCPROFILEEXTTYPE profile) {
4174 // convert bitrate to main/baseline profile kbps equivalent
4175 switch ((uint32_t)profile) {
4176 case OMX_VIDEO_AVCProfileHigh10:
4177 bitrate = divUp(bitrate, 3000); break;
4178 case OMX_VIDEO_AVCProfileConstrainedHigh:
4179 case OMX_VIDEO_AVCProfileHigh:
4180 bitrate = divUp(bitrate, 1250); break;
4181 default:
4182 bitrate = divUp(bitrate, 1000); break;
4183 }
4184
4185 // convert size and rate to MBs
4186 width = divUp(width, 16);
4187 height = divUp(height, 16);
4188 int mbs = width * height;
4189 rate *= mbs;
4190 int maxDimension = max(width, height);
4191
4192 static const int limits[][5] = {
4193 /* MBps MB dim bitrate level */
4194 { 1485, 99, 28, 64, OMX_VIDEO_AVCLevel1 },
4195 { 1485, 99, 28, 128, OMX_VIDEO_AVCLevel1b },
4196 { 3000, 396, 56, 192, OMX_VIDEO_AVCLevel11 },
4197 { 6000, 396, 56, 384, OMX_VIDEO_AVCLevel12 },
4198 { 11880, 396, 56, 768, OMX_VIDEO_AVCLevel13 },
4199 { 11880, 396, 56, 2000, OMX_VIDEO_AVCLevel2 },
4200 { 19800, 792, 79, 4000, OMX_VIDEO_AVCLevel21 },
4201 { 20250, 1620, 113, 4000, OMX_VIDEO_AVCLevel22 },
4202 { 40500, 1620, 113, 10000, OMX_VIDEO_AVCLevel3 },
4203 { 108000, 3600, 169, 14000, OMX_VIDEO_AVCLevel31 },
4204 { 216000, 5120, 202, 20000, OMX_VIDEO_AVCLevel32 },
4205 { 245760, 8192, 256, 20000, OMX_VIDEO_AVCLevel4 },
4206 { 245760, 8192, 256, 50000, OMX_VIDEO_AVCLevel41 },
4207 { 522240, 8704, 263, 50000, OMX_VIDEO_AVCLevel42 },
4208 { 589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5 },
4209 { 983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
4210 { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
4211 };
4212
4213 for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
4214 const int (&limit)[5] = limits[i];
4215 if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
4216 && bitrate <= limit[3]) {
4217 return limit[4];
4218 }
4219 }
4220 return 0;
4221 }
4222
setupAVCEncoderParameters(const sp<AMessage> & msg)4223 status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
4224 int32_t bitrate;
4225 float iFrameInterval;
4226 if (!msg->findInt32("bitrate", &bitrate)
4227 || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4228 return INVALID_OPERATION;
4229 }
4230
4231 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
4232
4233 float frameRate;
4234 if (!msg->findFloat("frame-rate", &frameRate)) {
4235 int32_t tmp;
4236 if (!msg->findInt32("frame-rate", &tmp)) {
4237 return INVALID_OPERATION;
4238 }
4239 frameRate = (float)tmp;
4240 }
4241
4242 status_t err = OK;
4243 int32_t intraRefreshMode = 0;
4244 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
4245 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
4246 if (err != OK) {
4247 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
4248 err, intraRefreshMode);
4249 return err;
4250 }
4251 }
4252
4253 OMX_VIDEO_PARAM_AVCTYPE h264type;
4254 InitOMXParams(&h264type);
4255 h264type.nPortIndex = kPortIndexOutput;
4256
4257 err = mOMXNode->getParameter(
4258 OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4259
4260 if (err != OK) {
4261 return err;
4262 }
4263
4264 h264type.nAllowedPictureTypes =
4265 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4266
4267 int32_t profile;
4268 if (msg->findInt32("profile", &profile)) {
4269 int32_t level;
4270 if (!msg->findInt32("level", &level)) {
4271 return INVALID_OPERATION;
4272 }
4273
4274 err = verifySupportForProfileAndLevel(profile, level);
4275
4276 if (err != OK) {
4277 return err;
4278 }
4279
4280 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
4281 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
4282 } else {
4283 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
4284 #if 0 /* DON'T YET DEFAULT TO HIGHEST PROFILE */
4285 // Use largest supported profile for AVC recording if profile is not specified.
4286 for (OMX_VIDEO_AVCPROFILETYPE profile : {
4287 OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCProfileMain }) {
4288 if (verifySupportForProfileAndLevel(profile, 0) == OK) {
4289 h264type.eProfile = profile;
4290 break;
4291 }
4292 }
4293 #endif
4294 }
4295
4296 ALOGI("setupAVCEncoderParameters with [profile: %s] [level: %s]",
4297 asString(h264type.eProfile), asString(h264type.eLevel));
4298
4299 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
4300 h264type.nSliceHeaderSpacing = 0;
4301 h264type.bUseHadamard = OMX_TRUE;
4302 h264type.nRefFrames = 1;
4303 h264type.nBFrames = 0;
4304 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4305 if (h264type.nPFrames == 0) {
4306 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
4307 }
4308 h264type.nRefIdx10ActiveMinus1 = 0;
4309 h264type.nRefIdx11ActiveMinus1 = 0;
4310 h264type.bEntropyCodingCABAC = OMX_FALSE;
4311 h264type.bWeightedPPrediction = OMX_FALSE;
4312 h264type.bconstIpred = OMX_FALSE;
4313 h264type.bDirect8x8Inference = OMX_FALSE;
4314 h264type.bDirectSpatialTemporal = OMX_FALSE;
4315 h264type.nCabacInitIdc = 0;
4316 } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain ||
4317 h264type.eProfile == OMX_VIDEO_AVCProfileHigh) {
4318 h264type.nSliceHeaderSpacing = 0;
4319 h264type.bUseHadamard = OMX_TRUE;
4320 h264type.nRefFrames = 2;
4321 h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1);
4322
4323 // disable B-frames until MPEG4Writer can guarantee finalizing files with B-frames
4324 h264type.nRefFrames = 1;
4325 h264type.nBFrames = 0;
4326
4327 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4328 h264type.nAllowedPictureTypes =
4329 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
4330 h264type.nRefIdx10ActiveMinus1 = 0;
4331 h264type.nRefIdx11ActiveMinus1 = 0;
4332 h264type.bEntropyCodingCABAC = OMX_TRUE;
4333 h264type.bWeightedPPrediction = OMX_TRUE;
4334 h264type.bconstIpred = OMX_TRUE;
4335 h264type.bDirect8x8Inference = OMX_TRUE;
4336 h264type.bDirectSpatialTemporal = OMX_TRUE;
4337 h264type.nCabacInitIdc = 1;
4338 }
4339
4340 if (h264type.nBFrames != 0) {
4341 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
4342 }
4343
4344 h264type.bEnableUEP = OMX_FALSE;
4345 h264type.bEnableFMO = OMX_FALSE;
4346 h264type.bEnableASO = OMX_FALSE;
4347 h264type.bEnableRS = OMX_FALSE;
4348 h264type.bFrameMBsOnly = OMX_TRUE;
4349 h264type.bMBAFF = OMX_FALSE;
4350 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
4351
4352 err = mOMXNode->setParameter(
4353 OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4354
4355 if (err != OK) {
4356 return err;
4357 }
4358
4359 // TRICKY: if we are enabling temporal layering as well, some codecs may not support layering
4360 // when B-frames are enabled. Detect this now so we can disable B frames if temporal layering
4361 // is preferred.
4362 AString tsSchema;
4363 int32_t preferBFrames = (int32_t)false;
4364 if (msg->findString("ts-schema", &tsSchema)
4365 && (!msg->findInt32("android._prefer-b-frames", &preferBFrames) || !preferBFrames)) {
4366 OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layering;
4367 InitOMXParams(&layering);
4368 layering.nPortIndex = kPortIndexOutput;
4369 if (mOMXNode->getParameter(
4370 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
4371 &layering, sizeof(layering)) == OK
4372 && layering.eSupportedPatterns
4373 && layering.nBLayerCountMax == 0) {
4374 h264type.nBFrames = 0;
4375 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
4376 h264type.nAllowedPictureTypes &= ~OMX_VIDEO_PictureTypeB;
4377 ALOGI("disabling B-frames");
4378 err = mOMXNode->setParameter(
4379 OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
4380
4381 if (err != OK) {
4382 return err;
4383 }
4384 }
4385 }
4386
4387 return configureBitrate(bitrate, bitrateMode);
4388 }
4389
setupHEVCEncoderParameters(const sp<AMessage> & msg)4390 status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
4391 int32_t bitrate;
4392 float iFrameInterval;
4393 if (!msg->findInt32("bitrate", &bitrate)
4394 || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
4395 return INVALID_OPERATION;
4396 }
4397
4398 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
4399
4400 float frameRate;
4401 if (!msg->findFloat("frame-rate", &frameRate)) {
4402 int32_t tmp;
4403 if (!msg->findInt32("frame-rate", &tmp)) {
4404 return INVALID_OPERATION;
4405 }
4406 frameRate = (float)tmp;
4407 }
4408
4409 OMX_VIDEO_PARAM_HEVCTYPE hevcType;
4410 InitOMXParams(&hevcType);
4411 hevcType.nPortIndex = kPortIndexOutput;
4412
4413 status_t err = OK;
4414 err = mOMXNode->getParameter(
4415 (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
4416 if (err != OK) {
4417 return err;
4418 }
4419
4420 int32_t profile;
4421 if (msg->findInt32("profile", &profile)) {
4422 int32_t level;
4423 if (!msg->findInt32("level", &level)) {
4424 return INVALID_OPERATION;
4425 }
4426
4427 err = verifySupportForProfileAndLevel(profile, level);
4428 if (err != OK) {
4429 return err;
4430 }
4431
4432 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
4433 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
4434 }
4435 // TODO: finer control?
4436 hevcType.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate) + 1;
4437
4438 err = mOMXNode->setParameter(
4439 (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
4440 if (err != OK) {
4441 return err;
4442 }
4443
4444 return configureBitrate(bitrate, bitrateMode);
4445 }
4446
setupVPXEncoderParameters(const sp<AMessage> & msg,sp<AMessage> & outputFormat)4447 status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
4448 int32_t bitrate;
4449 float iFrameInterval = 0;
4450 size_t tsLayers = 0;
4451 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
4452 OMX_VIDEO_VPXTemporalLayerPatternNone;
4453 static const uint32_t kVp8LayerRateAlloction
4454 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
4455 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
4456 {100, 100, 100}, // 1 layer
4457 { 60, 100, 100}, // 2 layers {60%, 40%}
4458 { 40, 60, 100}, // 3 layers {40%, 20%, 40%}
4459 };
4460 if (!msg->findInt32("bitrate", &bitrate)) {
4461 return INVALID_OPERATION;
4462 }
4463 msg->findAsFloat("i-frame-interval", &iFrameInterval);
4464
4465 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
4466
4467 float frameRate;
4468 if (!msg->findFloat("frame-rate", &frameRate)) {
4469 int32_t tmp;
4470 if (!msg->findInt32("frame-rate", &tmp)) {
4471 return INVALID_OPERATION;
4472 }
4473 frameRate = (float)tmp;
4474 }
4475
4476 AString tsSchema;
4477 OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE tsType =
4478 OMX_VIDEO_AndroidTemporalLayeringPatternNone;
4479
4480 if (msg->findString("ts-schema", &tsSchema)) {
4481 unsigned int numLayers = 0;
4482 unsigned int numBLayers = 0;
4483 int tags;
4484 char dummy;
4485 if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1
4486 && numLayers > 0) {
4487 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
4488 tsType = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC;
4489 tsLayers = numLayers;
4490 } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c",
4491 &numLayers, &dummy, &numBLayers, &dummy))
4492 && (tags == 1 || (tags == 3 && dummy == '+'))
4493 && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) {
4494 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
4495 // VPX does not have a concept of B-frames, so just count all layers
4496 tsType = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid;
4497 tsLayers = numLayers + numBLayers;
4498 } else {
4499 ALOGW("Ignoring unsupported ts-schema [%s]", tsSchema.c_str());
4500 }
4501 tsLayers = min(tsLayers, (size_t)OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS);
4502 }
4503
4504 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4505 InitOMXParams(&vp8type);
4506 vp8type.nPortIndex = kPortIndexOutput;
4507 status_t err = mOMXNode->getParameter(
4508 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4509 &vp8type, sizeof(vp8type));
4510
4511 if (err == OK) {
4512 if (iFrameInterval > 0) {
4513 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate) + 1;
4514 }
4515 vp8type.eTemporalPattern = pattern;
4516 vp8type.nTemporalLayerCount = tsLayers;
4517 if (tsLayers > 0) {
4518 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
4519 vp8type.nTemporalLayerBitrateRatio[i] =
4520 kVp8LayerRateAlloction[tsLayers - 1][i];
4521 }
4522 }
4523 if (bitrateMode == OMX_Video_ControlRateConstant) {
4524 vp8type.nMinQuantizer = 2;
4525 vp8type.nMaxQuantizer = 63;
4526 }
4527
4528 err = mOMXNode->setParameter(
4529 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4530 &vp8type, sizeof(vp8type));
4531 if (err != OK) {
4532 ALOGW("Extended VP8 parameters set failed: %d", err);
4533 } else if (tsType == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) {
4534 // advertise even single layer WebRTC layering, as it is defined
4535 outputFormat->setString("ts-schema", AStringPrintf("webrtc.vp8.%u-layer", tsLayers));
4536 } else if (tsLayers > 0) {
4537 // tsType == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid
4538 outputFormat->setString("ts-schema", AStringPrintf("android.generic.%u", tsLayers));
4539 }
4540 }
4541
4542 return configureBitrate(bitrate, bitrateMode);
4543 }
4544
verifySupportForProfileAndLevel(int32_t profile,int32_t level)4545 status_t ACodec::verifySupportForProfileAndLevel(
4546 int32_t profile, int32_t level) {
4547 OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
4548 InitOMXParams(¶ms);
4549 params.nPortIndex = kPortIndexOutput;
4550
4551 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
4552 params.nProfileIndex = index;
4553 status_t err = mOMXNode->getParameter(
4554 OMX_IndexParamVideoProfileLevelQuerySupported,
4555 ¶ms, sizeof(params));
4556
4557 if (err != OK) {
4558 return err;
4559 }
4560
4561 int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
4562 int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
4563
4564 if (profile == supportedProfile && level <= supportedLevel) {
4565 return OK;
4566 }
4567
4568 if (index == kMaxIndicesToCheck) {
4569 ALOGW("[%s] stopping checking profiles after %u: %x/%x",
4570 mComponentName.c_str(), index,
4571 params.eProfile, params.eLevel);
4572 }
4573 }
4574 return ERROR_UNSUPPORTED;
4575 }
4576
configureBitrate(int32_t bitrate,OMX_VIDEO_CONTROLRATETYPE bitrateMode)4577 status_t ACodec::configureBitrate(
4578 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
4579 OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
4580 InitOMXParams(&bitrateType);
4581 bitrateType.nPortIndex = kPortIndexOutput;
4582
4583 status_t err = mOMXNode->getParameter(
4584 OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
4585
4586 if (err != OK) {
4587 return err;
4588 }
4589
4590 bitrateType.eControlRate = bitrateMode;
4591 bitrateType.nTargetBitrate = bitrate;
4592
4593 return mOMXNode->setParameter(
4594 OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
4595 }
4596
configureEncoderLatency(const sp<AMessage> & msg)4597 void ACodec::configureEncoderLatency(const sp<AMessage> &msg) {
4598 if (!mIsEncoder || !mIsVideo) {
4599 return;
4600 }
4601
4602 int32_t latency = 0, bitrateMode;
4603 if (msg->findInt32("latency", &latency) && latency > 0) {
4604 status_t err = setLatency(latency);
4605 if (err != OK) {
4606 ALOGW("[%s] failed setLatency. Failure is fine since this key is optional",
4607 mComponentName.c_str());
4608 err = OK;
4609 } else {
4610 mLatency = latency;
4611 }
4612 } else if ((!msg->findInt32("bitrate-mode", &bitrateMode) &&
4613 bitrateMode == OMX_Video_ControlRateConstant)) {
4614 // default the latency to be 1 if latency key is not specified or unsupported and bitrateMode
4615 // is CBR.
4616 mLatency = 1;
4617 }
4618 }
4619
setupErrorCorrectionParameters()4620 status_t ACodec::setupErrorCorrectionParameters() {
4621 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
4622 InitOMXParams(&errorCorrectionType);
4623 errorCorrectionType.nPortIndex = kPortIndexOutput;
4624
4625 status_t err = mOMXNode->getParameter(
4626 OMX_IndexParamVideoErrorCorrection,
4627 &errorCorrectionType, sizeof(errorCorrectionType));
4628
4629 if (err != OK) {
4630 return OK; // Optional feature. Ignore this failure
4631 }
4632
4633 errorCorrectionType.bEnableHEC = OMX_FALSE;
4634 errorCorrectionType.bEnableResync = OMX_TRUE;
4635 errorCorrectionType.nResynchMarkerSpacing = 256;
4636 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
4637 errorCorrectionType.bEnableRVLC = OMX_FALSE;
4638
4639 return mOMXNode->setParameter(
4640 OMX_IndexParamVideoErrorCorrection,
4641 &errorCorrectionType, sizeof(errorCorrectionType));
4642 }
4643
setVideoFormatOnPort(OMX_U32 portIndex,int32_t width,int32_t height,OMX_VIDEO_CODINGTYPE compressionFormat,float frameRate)4644 status_t ACodec::setVideoFormatOnPort(
4645 OMX_U32 portIndex,
4646 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
4647 float frameRate) {
4648 OMX_PARAM_PORTDEFINITIONTYPE def;
4649 InitOMXParams(&def);
4650 def.nPortIndex = portIndex;
4651
4652 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
4653
4654 status_t err = mOMXNode->getParameter(
4655 OMX_IndexParamPortDefinition, &def, sizeof(def));
4656 if (err != OK) {
4657 return err;
4658 }
4659
4660 if (portIndex == kPortIndexInput) {
4661 // XXX Need a (much) better heuristic to compute input buffer sizes.
4662 const size_t X = 64 * 1024;
4663 if (def.nBufferSize < X) {
4664 def.nBufferSize = X;
4665 }
4666 }
4667
4668 if (def.eDomain != OMX_PortDomainVideo) {
4669 ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain);
4670 return FAILED_TRANSACTION;
4671 }
4672
4673 video_def->nFrameWidth = width;
4674 video_def->nFrameHeight = height;
4675
4676 if (portIndex == kPortIndexInput) {
4677 video_def->eCompressionFormat = compressionFormat;
4678 video_def->eColorFormat = OMX_COLOR_FormatUnused;
4679 if (frameRate >= 0) {
4680 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
4681 }
4682 }
4683
4684 err = mOMXNode->setParameter(
4685 OMX_IndexParamPortDefinition, &def, sizeof(def));
4686
4687 return err;
4688 }
4689
countBuffersOwnedByComponent(OMX_U32 portIndex) const4690 size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
4691 size_t n = 0;
4692
4693 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4694 const BufferInfo &info = mBuffers[portIndex].itemAt(i);
4695
4696 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
4697 ++n;
4698 }
4699 }
4700
4701 return n;
4702 }
4703
countBuffersOwnedByNativeWindow() const4704 size_t ACodec::countBuffersOwnedByNativeWindow() const {
4705 size_t n = 0;
4706
4707 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
4708 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
4709
4710 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4711 ++n;
4712 }
4713 }
4714
4715 return n;
4716 }
4717
waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs()4718 void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
4719 if (mNativeWindow == NULL) {
4720 return;
4721 }
4722
4723 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
4724 && dequeueBufferFromNativeWindow() != NULL) {
4725 // these buffers will be submitted as regular buffers; account for this
4726 if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) {
4727 --mMetadataBuffersToSubmit;
4728 }
4729 }
4730 }
4731
allYourBuffersAreBelongToUs(OMX_U32 portIndex)4732 bool ACodec::allYourBuffersAreBelongToUs(
4733 OMX_U32 portIndex) {
4734 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4735 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
4736
4737 if (info->mStatus != BufferInfo::OWNED_BY_US
4738 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4739 ALOGV("[%s] Buffer %u on port %u still has status %d",
4740 mComponentName.c_str(),
4741 info->mBufferID, portIndex, info->mStatus);
4742 return false;
4743 }
4744 }
4745
4746 return true;
4747 }
4748
allYourBuffersAreBelongToUs()4749 bool ACodec::allYourBuffersAreBelongToUs() {
4750 return allYourBuffersAreBelongToUs(kPortIndexInput)
4751 && allYourBuffersAreBelongToUs(kPortIndexOutput);
4752 }
4753
deferMessage(const sp<AMessage> & msg)4754 void ACodec::deferMessage(const sp<AMessage> &msg) {
4755 mDeferredQueue.push_back(msg);
4756 }
4757
processDeferredMessages()4758 void ACodec::processDeferredMessages() {
4759 List<sp<AMessage> > queue = mDeferredQueue;
4760 mDeferredQueue.clear();
4761
4762 List<sp<AMessage> >::iterator it = queue.begin();
4763 while (it != queue.end()) {
4764 onMessageReceived(*it++);
4765 }
4766 }
4767
getPortFormat(OMX_U32 portIndex,sp<AMessage> & notify)4768 status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) {
4769 const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
4770 OMX_PARAM_PORTDEFINITIONTYPE def;
4771 InitOMXParams(&def);
4772 def.nPortIndex = portIndex;
4773
4774 status_t err = mOMXNode->getParameter(OMX_IndexParamPortDefinition, &def, sizeof(def));
4775 if (err != OK) {
4776 return err;
4777 }
4778
4779 if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) {
4780 ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex);
4781 return BAD_VALUE;
4782 }
4783
4784 switch (def.eDomain) {
4785 case OMX_PortDomainVideo:
4786 {
4787 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
4788 switch ((int)videoDef->eCompressionFormat) {
4789 case OMX_VIDEO_CodingUnused:
4790 {
4791 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
4792 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
4793
4794 notify->setInt32("stride", videoDef->nStride);
4795 notify->setInt32("slice-height", videoDef->nSliceHeight);
4796 notify->setInt32("color-format", videoDef->eColorFormat);
4797
4798 if (mNativeWindow == NULL) {
4799 DescribeColorFormat2Params describeParams;
4800 InitOMXParams(&describeParams);
4801 describeParams.eColorFormat = videoDef->eColorFormat;
4802 describeParams.nFrameWidth = videoDef->nFrameWidth;
4803 describeParams.nFrameHeight = videoDef->nFrameHeight;
4804 describeParams.nStride = videoDef->nStride;
4805 describeParams.nSliceHeight = videoDef->nSliceHeight;
4806 describeParams.bUsingNativeBuffers = OMX_FALSE;
4807
4808 if (DescribeColorFormat(mOMXNode, describeParams)) {
4809 notify->setBuffer(
4810 "image-data",
4811 ABuffer::CreateAsCopy(
4812 &describeParams.sMediaImage,
4813 sizeof(describeParams.sMediaImage)));
4814
4815 MediaImage2 &img = describeParams.sMediaImage;
4816 MediaImage2::PlaneInfo *plane = img.mPlane;
4817 ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }",
4818 mComponentName.c_str(), img.mWidth, img.mHeight,
4819 plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc,
4820 plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc,
4821 plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc);
4822 }
4823 }
4824
4825 int32_t width = (int32_t)videoDef->nFrameWidth;
4826 int32_t height = (int32_t)videoDef->nFrameHeight;
4827
4828 if (portIndex == kPortIndexOutput) {
4829 OMX_CONFIG_RECTTYPE rect;
4830 InitOMXParams(&rect);
4831 rect.nPortIndex = portIndex;
4832
4833 if (mOMXNode->getConfig(
4834 (portIndex == kPortIndexOutput ?
4835 OMX_IndexConfigCommonOutputCrop :
4836 OMX_IndexConfigCommonInputCrop),
4837 &rect, sizeof(rect)) != OK) {
4838 rect.nLeft = 0;
4839 rect.nTop = 0;
4840 rect.nWidth = videoDef->nFrameWidth;
4841 rect.nHeight = videoDef->nFrameHeight;
4842 }
4843
4844 if (rect.nLeft < 0 ||
4845 rect.nTop < 0 ||
4846 rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
4847 rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
4848 ALOGE("Wrong cropped rect (%d, %d, %u, %u) vs. frame (%u, %u)",
4849 rect.nLeft, rect.nTop,
4850 rect.nWidth, rect.nHeight,
4851 videoDef->nFrameWidth, videoDef->nFrameHeight);
4852 return BAD_VALUE;
4853 }
4854
4855 notify->setRect(
4856 "crop",
4857 rect.nLeft,
4858 rect.nTop,
4859 rect.nLeft + rect.nWidth - 1,
4860 rect.nTop + rect.nHeight - 1);
4861
4862 width = rect.nWidth;
4863 height = rect.nHeight;
4864
4865 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
4866 (void)getColorAspectsAndDataSpaceForVideoDecoder(
4867 width, height, mConfigFormat, notify,
4868 mUsingNativeWindow ? &dataSpace : NULL);
4869 if (mUsingNativeWindow) {
4870 notify->setInt32("android._dataspace", dataSpace);
4871 }
4872 (void)getHDRStaticInfoForVideoCodec(kPortIndexOutput, notify);
4873 } else {
4874 (void)getInputColorAspectsForVideoEncoder(notify);
4875 if (mConfigFormat->contains("hdr-static-info")) {
4876 (void)getHDRStaticInfoForVideoCodec(kPortIndexInput, notify);
4877 }
4878 uint32_t latency = 0;
4879 if (mIsEncoder && getLatency(&latency) == OK && latency > 0) {
4880 notify->setInt32("latency", latency);
4881 }
4882 }
4883
4884 break;
4885 }
4886
4887 case OMX_VIDEO_CodingVP8:
4888 case OMX_VIDEO_CodingVP9:
4889 {
4890 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4891 InitOMXParams(&vp8type);
4892 vp8type.nPortIndex = kPortIndexOutput;
4893 status_t err = mOMXNode->getParameter(
4894 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4895 &vp8type,
4896 sizeof(vp8type));
4897
4898 if (err == OK) {
4899 if (vp8type.eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC
4900 && vp8type.nTemporalLayerCount > 0
4901 && vp8type.nTemporalLayerCount
4902 <= OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) {
4903 // advertise as android.generic if we configured for android.generic
4904 AString origSchema;
4905 if (notify->findString("ts-schema", &origSchema)
4906 && origSchema.startsWith("android.generic")) {
4907 notify->setString("ts-schema", AStringPrintf(
4908 "android.generic.%u", vp8type.nTemporalLayerCount));
4909 } else {
4910 notify->setString("ts-schema", AStringPrintf(
4911 "webrtc.vp8.%u-layer", vp8type.nTemporalLayerCount));
4912 }
4913 }
4914 }
4915 // Fall through to set up mime.
4916 }
4917
4918 default:
4919 {
4920 if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
4921 // should be CodingUnused
4922 ALOGE("Raw port video compression format is %s(%d)",
4923 asString(videoDef->eCompressionFormat),
4924 videoDef->eCompressionFormat);
4925 return BAD_VALUE;
4926 }
4927 AString mime;
4928 if (GetMimeTypeForVideoCoding(
4929 videoDef->eCompressionFormat, &mime) != OK) {
4930 notify->setString("mime", "application/octet-stream");
4931 } else {
4932 notify->setString("mime", mime.c_str());
4933 }
4934 uint32_t intraRefreshPeriod = 0;
4935 if (mIsEncoder && getIntraRefreshPeriod(&intraRefreshPeriod) == OK
4936 && intraRefreshPeriod > 0) {
4937 notify->setInt32("intra-refresh-period", intraRefreshPeriod);
4938 }
4939 break;
4940 }
4941 }
4942 notify->setInt32("width", videoDef->nFrameWidth);
4943 notify->setInt32("height", videoDef->nFrameHeight);
4944 ALOGV("[%s] %s format is %s", mComponentName.c_str(),
4945 portIndex == kPortIndexInput ? "input" : "output",
4946 notify->debugString().c_str());
4947
4948 break;
4949 }
4950
4951 case OMX_PortDomainAudio:
4952 {
4953 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
4954
4955 switch ((int)audioDef->eEncoding) {
4956 case OMX_AUDIO_CodingPCM:
4957 {
4958 OMX_AUDIO_PARAM_PCMMODETYPE params;
4959 InitOMXParams(¶ms);
4960 params.nPortIndex = portIndex;
4961
4962 err = mOMXNode->getParameter(
4963 OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
4964 if (err != OK) {
4965 return err;
4966 }
4967
4968 if (params.nChannels <= 0
4969 || (params.nChannels != 1 && !params.bInterleaved)
4970 || params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
4971 ALOGE("unsupported PCM port: %u channels%s, %u-bit",
4972 params.nChannels,
4973 params.bInterleaved ? " interleaved" : "",
4974 params.nBitPerSample);
4975 return FAILED_TRANSACTION;
4976 }
4977
4978 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
4979 notify->setInt32("channel-count", params.nChannels);
4980 notify->setInt32("sample-rate", params.nSamplingRate);
4981
4982 AudioEncoding encoding = kAudioEncodingPcm16bit;
4983 if (params.eNumData == OMX_NumericalDataUnsigned
4984 && params.nBitPerSample == 8u) {
4985 encoding = kAudioEncodingPcm8bit;
4986 } else if (params.eNumData == OMX_NumericalDataFloat
4987 && params.nBitPerSample == 32u) {
4988 encoding = kAudioEncodingPcmFloat;
4989 } else if (params.nBitPerSample != 16u
4990 || params.eNumData != OMX_NumericalDataSigned) {
4991 ALOGE("unsupported PCM port: %s(%d), %s(%d) mode ",
4992 asString(params.eNumData), params.eNumData,
4993 asString(params.ePCMMode), params.ePCMMode);
4994 return FAILED_TRANSACTION;
4995 }
4996 notify->setInt32("pcm-encoding", encoding);
4997
4998 if (mChannelMaskPresent) {
4999 notify->setInt32("channel-mask", mChannelMask);
5000 }
5001 break;
5002 }
5003
5004 case OMX_AUDIO_CodingAAC:
5005 {
5006 OMX_AUDIO_PARAM_AACPROFILETYPE params;
5007 InitOMXParams(¶ms);
5008 params.nPortIndex = portIndex;
5009
5010 err = mOMXNode->getParameter(
5011 OMX_IndexParamAudioAac, ¶ms, sizeof(params));
5012 if (err != OK) {
5013 return err;
5014 }
5015
5016 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
5017 notify->setInt32("channel-count", params.nChannels);
5018 notify->setInt32("sample-rate", params.nSampleRate);
5019 break;
5020 }
5021
5022 case OMX_AUDIO_CodingAMR:
5023 {
5024 OMX_AUDIO_PARAM_AMRTYPE params;
5025 InitOMXParams(¶ms);
5026 params.nPortIndex = portIndex;
5027
5028 err = mOMXNode->getParameter(
5029 OMX_IndexParamAudioAmr, ¶ms, sizeof(params));
5030 if (err != OK) {
5031 return err;
5032 }
5033
5034 notify->setInt32("channel-count", 1);
5035 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
5036 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
5037 notify->setInt32("sample-rate", 16000);
5038 } else {
5039 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
5040 notify->setInt32("sample-rate", 8000);
5041 }
5042 break;
5043 }
5044
5045 case OMX_AUDIO_CodingFLAC:
5046 {
5047 OMX_AUDIO_PARAM_FLACTYPE params;
5048 InitOMXParams(¶ms);
5049 params.nPortIndex = portIndex;
5050
5051 err = mOMXNode->getParameter(
5052 OMX_IndexParamAudioFlac, ¶ms, sizeof(params));
5053 if (err != OK) {
5054 return err;
5055 }
5056
5057 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
5058 notify->setInt32("channel-count", params.nChannels);
5059 notify->setInt32("sample-rate", params.nSampleRate);
5060 break;
5061 }
5062
5063 case OMX_AUDIO_CodingMP3:
5064 {
5065 OMX_AUDIO_PARAM_MP3TYPE params;
5066 InitOMXParams(¶ms);
5067 params.nPortIndex = portIndex;
5068
5069 err = mOMXNode->getParameter(
5070 OMX_IndexParamAudioMp3, ¶ms, sizeof(params));
5071 if (err != OK) {
5072 return err;
5073 }
5074
5075 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
5076 notify->setInt32("channel-count", params.nChannels);
5077 notify->setInt32("sample-rate", params.nSampleRate);
5078 break;
5079 }
5080
5081 case OMX_AUDIO_CodingVORBIS:
5082 {
5083 OMX_AUDIO_PARAM_VORBISTYPE params;
5084 InitOMXParams(¶ms);
5085 params.nPortIndex = portIndex;
5086
5087 err = mOMXNode->getParameter(
5088 OMX_IndexParamAudioVorbis, ¶ms, sizeof(params));
5089 if (err != OK) {
5090 return err;
5091 }
5092
5093 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
5094 notify->setInt32("channel-count", params.nChannels);
5095 notify->setInt32("sample-rate", params.nSampleRate);
5096 break;
5097 }
5098
5099 case OMX_AUDIO_CodingAndroidAC3:
5100 {
5101 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
5102 InitOMXParams(¶ms);
5103 params.nPortIndex = portIndex;
5104
5105 err = mOMXNode->getParameter(
5106 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
5107 ¶ms, sizeof(params));
5108 if (err != OK) {
5109 return err;
5110 }
5111
5112 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
5113 notify->setInt32("channel-count", params.nChannels);
5114 notify->setInt32("sample-rate", params.nSampleRate);
5115 break;
5116 }
5117
5118 case OMX_AUDIO_CodingAndroidEAC3:
5119 {
5120 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
5121 InitOMXParams(¶ms);
5122 params.nPortIndex = portIndex;
5123
5124 err = mOMXNode->getParameter(
5125 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
5126 ¶ms, sizeof(params));
5127 if (err != OK) {
5128 return err;
5129 }
5130
5131 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
5132 notify->setInt32("channel-count", params.nChannels);
5133 notify->setInt32("sample-rate", params.nSampleRate);
5134 break;
5135 }
5136
5137 case OMX_AUDIO_CodingAndroidOPUS:
5138 {
5139 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
5140 InitOMXParams(¶ms);
5141 params.nPortIndex = portIndex;
5142
5143 err = mOMXNode->getParameter(
5144 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
5145 ¶ms, sizeof(params));
5146 if (err != OK) {
5147 return err;
5148 }
5149
5150 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
5151 notify->setInt32("channel-count", params.nChannels);
5152 notify->setInt32("sample-rate", params.nSampleRate);
5153 break;
5154 }
5155
5156 case OMX_AUDIO_CodingG711:
5157 {
5158 OMX_AUDIO_PARAM_PCMMODETYPE params;
5159 InitOMXParams(¶ms);
5160 params.nPortIndex = portIndex;
5161
5162 err = mOMXNode->getParameter(
5163 (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
5164 if (err != OK) {
5165 return err;
5166 }
5167
5168 const char *mime = NULL;
5169 if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
5170 mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
5171 } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
5172 mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
5173 } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
5174 mime = MEDIA_MIMETYPE_AUDIO_RAW;
5175 }
5176 notify->setString("mime", mime);
5177 notify->setInt32("channel-count", params.nChannels);
5178 notify->setInt32("sample-rate", params.nSamplingRate);
5179 notify->setInt32("pcm-encoding", kAudioEncodingPcm16bit);
5180 break;
5181 }
5182
5183 case OMX_AUDIO_CodingGSMFR:
5184 {
5185 OMX_AUDIO_PARAM_PCMMODETYPE params;
5186 InitOMXParams(¶ms);
5187 params.nPortIndex = portIndex;
5188
5189 err = mOMXNode->getParameter(
5190 OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
5191 if (err != OK) {
5192 return err;
5193 }
5194
5195 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
5196 notify->setInt32("channel-count", params.nChannels);
5197 notify->setInt32("sample-rate", params.nSamplingRate);
5198 break;
5199 }
5200
5201 default:
5202 ALOGE("Unsupported audio coding: %s(%d)\n",
5203 asString(audioDef->eEncoding), audioDef->eEncoding);
5204 return BAD_TYPE;
5205 }
5206 break;
5207 }
5208
5209 default:
5210 ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain);
5211 return BAD_TYPE;
5212 }
5213
5214 return getVendorParameters(portIndex, notify);
5215 }
5216
onDataSpaceChanged(android_dataspace dataSpace,const ColorAspects & aspects)5217 void ACodec::onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects &aspects) {
5218 // aspects are normally communicated in ColorAspects
5219 int32_t range, standard, transfer;
5220 convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer);
5221
5222 // if some aspects are unspecified, use dataspace fields
5223 if (range != 0) {
5224 range = (dataSpace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT;
5225 }
5226 if (standard != 0) {
5227 standard = (dataSpace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT;
5228 }
5229 if (transfer != 0) {
5230 transfer = (dataSpace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT;
5231 }
5232
5233 mOutputFormat = mOutputFormat->dup(); // trigger an output format changed event
5234 if (range != 0) {
5235 mOutputFormat->setInt32("color-range", range);
5236 }
5237 if (standard != 0) {
5238 mOutputFormat->setInt32("color-standard", standard);
5239 }
5240 if (transfer != 0) {
5241 mOutputFormat->setInt32("color-transfer", transfer);
5242 }
5243
5244 ALOGD("dataspace changed to %#x (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
5245 "(R:%d(%s), S:%d(%s), T:%d(%s))",
5246 dataSpace,
5247 aspects.mRange, asString(aspects.mRange),
5248 aspects.mPrimaries, asString(aspects.mPrimaries),
5249 aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
5250 aspects.mTransfer, asString(aspects.mTransfer),
5251 range, asString((ColorRange)range),
5252 standard, asString((ColorStandard)standard),
5253 transfer, asString((ColorTransfer)transfer));
5254 }
5255
onOutputFormatChanged(sp<const AMessage> expectedFormat)5256 void ACodec::onOutputFormatChanged(sp<const AMessage> expectedFormat) {
5257 // store new output format, at the same time mark that this is no longer the first frame
5258 mOutputFormat = mBaseOutputFormat->dup();
5259
5260 if (getPortFormat(kPortIndexOutput, mOutputFormat) != OK) {
5261 ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str());
5262 return;
5263 }
5264
5265 if (expectedFormat != NULL) {
5266 sp<const AMessage> changes = expectedFormat->changesFrom(mOutputFormat);
5267 sp<const AMessage> to = mOutputFormat->changesFrom(expectedFormat);
5268 if (changes->countEntries() != 0 || to->countEntries() != 0) {
5269 ALOGW("[%s] BAD CODEC: Output format changed unexpectedly from (diff) %s to (diff) %s",
5270 mComponentName.c_str(),
5271 changes->debugString(4).c_str(), to->debugString(4).c_str());
5272 }
5273 }
5274
5275 if (!mIsVideo && !mIsEncoder) {
5276 AudioEncoding pcmEncoding = kAudioEncodingPcm16bit;
5277 (void)mConfigFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
5278 AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit;
5279 (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
5280
5281 mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding);
5282 if (mConverter[kPortIndexOutput] != NULL) {
5283 mOutputFormat->setInt32("pcm-encoding", pcmEncoding);
5284 }
5285 }
5286
5287 if (mTunneled) {
5288 sendFormatChange();
5289 }
5290 }
5291
sendFormatChange()5292 void ACodec::sendFormatChange() {
5293 AString mime;
5294 CHECK(mOutputFormat->findString("mime", &mime));
5295
5296 if (mime == MEDIA_MIMETYPE_AUDIO_RAW && (mEncoderDelay || mEncoderPadding)) {
5297 int32_t channelCount, sampleRate;
5298 CHECK(mOutputFormat->findInt32("channel-count", &channelCount));
5299 CHECK(mOutputFormat->findInt32("sample-rate", &sampleRate));
5300 if (mSampleRate != 0 && sampleRate != 0) {
5301 // avoiding 32-bit overflows in intermediate values
5302 mEncoderDelay = (int32_t)((((int64_t)mEncoderDelay) * sampleRate) / mSampleRate);
5303 mEncoderPadding = (int32_t)((((int64_t)mEncoderPadding) * sampleRate) / mSampleRate);
5304 mSampleRate = sampleRate;
5305 }
5306 if (mSkipCutBuffer != NULL) {
5307 size_t prevbufsize = mSkipCutBuffer->size();
5308 if (prevbufsize != 0) {
5309 ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize);
5310 }
5311 }
5312 mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount);
5313 }
5314
5315 // mLastOutputFormat is not used when tunneled; doing this just to stay consistent
5316 mLastOutputFormat = mOutputFormat;
5317 }
5318
signalError(OMX_ERRORTYPE error,status_t internalError)5319 void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
5320 ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
5321
5322 if (internalError == UNKNOWN_ERROR) { // find better error code
5323 const status_t omxStatus = statusFromOMXError(error);
5324 if (omxStatus != 0) {
5325 internalError = omxStatus;
5326 } else {
5327 ALOGW("Invalid OMX error %#x", error);
5328 }
5329 }
5330
5331 mFatalError = true;
5332 mCallback->onError(internalError, ACTION_CODE_FATAL);
5333 }
5334
requestIDRFrame()5335 status_t ACodec::requestIDRFrame() {
5336 if (!mIsEncoder) {
5337 return ERROR_UNSUPPORTED;
5338 }
5339
5340 OMX_CONFIG_INTRAREFRESHVOPTYPE params;
5341 InitOMXParams(¶ms);
5342
5343 params.nPortIndex = kPortIndexOutput;
5344 params.IntraRefreshVOP = OMX_TRUE;
5345
5346 return mOMXNode->setConfig(
5347 OMX_IndexConfigVideoIntraVOPRefresh,
5348 ¶ms,
5349 sizeof(params));
5350 }
5351
5352 ////////////////////////////////////////////////////////////////////////////////
5353
BaseState(ACodec * codec,const sp<AState> & parentState)5354 ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
5355 : AState(parentState),
5356 mCodec(codec) {
5357 }
5358
getPortMode(OMX_U32)5359 ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
5360 OMX_U32 /* portIndex */) {
5361 return KEEP_BUFFERS;
5362 }
5363
stateExited()5364 void ACodec::BaseState::stateExited() {
5365 ++mCodec->mStateGeneration;
5366 }
5367
onMessageReceived(const sp<AMessage> & msg)5368 bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
5369 switch (msg->what()) {
5370 case kWhatInputBufferFilled:
5371 {
5372 onInputBufferFilled(msg);
5373 break;
5374 }
5375
5376 case kWhatOutputBufferDrained:
5377 {
5378 onOutputBufferDrained(msg);
5379 break;
5380 }
5381
5382 case ACodec::kWhatOMXMessageList:
5383 {
5384 return checkOMXMessage(msg) ? onOMXMessageList(msg) : true;
5385 }
5386
5387 case ACodec::kWhatOMXMessageItem:
5388 {
5389 // no need to check as we already did it for kWhatOMXMessageList
5390 return onOMXMessage(msg);
5391 }
5392
5393 case ACodec::kWhatOMXMessage:
5394 {
5395 return checkOMXMessage(msg) ? onOMXMessage(msg) : true;
5396 }
5397
5398 case ACodec::kWhatSetSurface:
5399 {
5400 sp<AReplyToken> replyID;
5401 CHECK(msg->senderAwaitsResponse(&replyID));
5402
5403 sp<RefBase> obj;
5404 CHECK(msg->findObject("surface", &obj));
5405
5406 status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
5407
5408 sp<AMessage> response = new AMessage;
5409 response->setInt32("err", err);
5410 response->postReply(replyID);
5411 break;
5412 }
5413
5414 case ACodec::kWhatCreateInputSurface:
5415 case ACodec::kWhatSetInputSurface:
5416 case ACodec::kWhatSignalEndOfInputStream:
5417 {
5418 // This may result in an app illegal state exception.
5419 ALOGE("Message 0x%x was not handled", msg->what());
5420 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
5421 return true;
5422 }
5423
5424 case ACodec::kWhatOMXDied:
5425 {
5426 // This will result in kFlagSawMediaServerDie handling in MediaCodec.
5427 ALOGE("OMX/mediaserver died, signalling error!");
5428 mCodec->mGraphicBufferSource.clear();
5429 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
5430 break;
5431 }
5432
5433 case ACodec::kWhatReleaseCodecInstance:
5434 {
5435 ALOGI("[%s] forcing the release of codec",
5436 mCodec->mComponentName.c_str());
5437 status_t err = mCodec->mOMXNode->freeNode();
5438 ALOGE_IF("[%s] failed to release codec instance: err=%d",
5439 mCodec->mComponentName.c_str(), err);
5440 mCodec->mCallback->onReleaseCompleted();
5441
5442 mCodec->changeState(mCodec->mUninitializedState);
5443 break;
5444 }
5445
5446 case ACodec::kWhatForceStateTransition:
5447 {
5448 ALOGV("Already transitioned --- ignore");
5449 break;
5450 }
5451
5452 default:
5453 return false;
5454 }
5455
5456 return true;
5457 }
5458
checkOMXMessage(const sp<AMessage> & msg)5459 bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) {
5460 // there is a possibility that this is an outstanding message for a
5461 // codec that we have already destroyed
5462 if (mCodec->mOMXNode == NULL) {
5463 ALOGI("ignoring message as already freed component: %s",
5464 msg->debugString().c_str());
5465 return false;
5466 }
5467
5468 int32_t generation;
5469 CHECK(msg->findInt32("generation", (int32_t*)&generation));
5470 if (generation != mCodec->mNodeGeneration) {
5471 ALOGW("Unexpected message for component: %s, gen %u, cur %u",
5472 msg->debugString().c_str(), generation, mCodec->mNodeGeneration);
5473 return false;
5474 }
5475 return true;
5476 }
5477
onOMXMessageList(const sp<AMessage> & msg)5478 bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) {
5479 sp<RefBase> obj;
5480 CHECK(msg->findObject("messages", &obj));
5481 sp<MessageList> msgList = static_cast<MessageList *>(obj.get());
5482
5483 bool receivedRenderedEvents = false;
5484 for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin();
5485 it != msgList->getList().cend(); ++it) {
5486 (*it)->setWhat(ACodec::kWhatOMXMessageItem);
5487 mCodec->handleMessage(*it);
5488 int32_t type;
5489 CHECK((*it)->findInt32("type", &type));
5490 if (type == omx_message::FRAME_RENDERED) {
5491 receivedRenderedEvents = true;
5492 }
5493 }
5494
5495 if (receivedRenderedEvents) {
5496 // NOTE: all buffers are rendered in this case
5497 mCodec->notifyOfRenderedFrames();
5498 }
5499 return true;
5500 }
5501
onOMXMessage(const sp<AMessage> & msg)5502 bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
5503 int32_t type;
5504 CHECK(msg->findInt32("type", &type));
5505
5506 switch (type) {
5507 case omx_message::EVENT:
5508 {
5509 int32_t event, data1, data2;
5510 CHECK(msg->findInt32("event", &event));
5511 CHECK(msg->findInt32("data1", &data1));
5512 CHECK(msg->findInt32("data2", &data2));
5513
5514 if (event == OMX_EventCmdComplete
5515 && data1 == OMX_CommandFlush
5516 && data2 == (int32_t)OMX_ALL) {
5517 // Use of this notification is not consistent across
5518 // implementations. We'll drop this notification and rely
5519 // on flush-complete notifications on the individual port
5520 // indices instead.
5521
5522 return true;
5523 }
5524
5525 return onOMXEvent(
5526 static_cast<OMX_EVENTTYPE>(event),
5527 static_cast<OMX_U32>(data1),
5528 static_cast<OMX_U32>(data2));
5529 }
5530
5531 case omx_message::EMPTY_BUFFER_DONE:
5532 {
5533 IOMX::buffer_id bufferID;
5534 int32_t fenceFd;
5535
5536 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
5537 CHECK(msg->findInt32("fence_fd", &fenceFd));
5538
5539 return onOMXEmptyBufferDone(bufferID, fenceFd);
5540 }
5541
5542 case omx_message::FILL_BUFFER_DONE:
5543 {
5544 IOMX::buffer_id bufferID;
5545 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
5546
5547 int32_t rangeOffset, rangeLength, flags, fenceFd;
5548 int64_t timeUs;
5549
5550 CHECK(msg->findInt32("range_offset", &rangeOffset));
5551 CHECK(msg->findInt32("range_length", &rangeLength));
5552 CHECK(msg->findInt32("flags", &flags));
5553 CHECK(msg->findInt64("timestamp", &timeUs));
5554 CHECK(msg->findInt32("fence_fd", &fenceFd));
5555
5556 return onOMXFillBufferDone(
5557 bufferID,
5558 (size_t)rangeOffset, (size_t)rangeLength,
5559 (OMX_U32)flags,
5560 timeUs,
5561 fenceFd);
5562 }
5563
5564 case omx_message::FRAME_RENDERED:
5565 {
5566 int64_t mediaTimeUs, systemNano;
5567
5568 CHECK(msg->findInt64("media_time_us", &mediaTimeUs));
5569 CHECK(msg->findInt64("system_nano", &systemNano));
5570
5571 return onOMXFrameRendered(
5572 mediaTimeUs, systemNano);
5573 }
5574
5575 default:
5576 ALOGE("Unexpected message type: %d", type);
5577 return false;
5578 }
5579 }
5580
onOMXFrameRendered(int64_t mediaTimeUs __unused,nsecs_t systemNano __unused)5581 bool ACodec::BaseState::onOMXFrameRendered(
5582 int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) {
5583 // ignore outside of Executing and PortSettingsChanged states
5584 return true;
5585 }
5586
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)5587 bool ACodec::BaseState::onOMXEvent(
5588 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5589 if (event == OMX_EventDataSpaceChanged) {
5590 ColorAspects aspects = ColorUtils::unpackToColorAspects(data2);
5591
5592 mCodec->onDataSpaceChanged((android_dataspace)data1, aspects);
5593 return true;
5594 }
5595
5596 if (event != OMX_EventError) {
5597 ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)",
5598 mCodec->mComponentName.c_str(), event, data1, data2);
5599
5600 return false;
5601 }
5602
5603 ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1);
5604
5605 // verify OMX component sends back an error we expect.
5606 OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
5607 if (!isOMXError(omxError)) {
5608 ALOGW("Invalid OMX error %#x", omxError);
5609 omxError = OMX_ErrorUndefined;
5610 }
5611 mCodec->signalError(omxError);
5612
5613 return true;
5614 }
5615
onOMXEmptyBufferDone(IOMX::buffer_id bufferID,int fenceFd)5616 bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) {
5617 ALOGV("[%s] onOMXEmptyBufferDone %u",
5618 mCodec->mComponentName.c_str(), bufferID);
5619
5620 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
5621 BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5622 if (status != BufferInfo::OWNED_BY_COMPONENT) {
5623 ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5624 mCodec->dumpBuffers(kPortIndexInput);
5625 if (fenceFd >= 0) {
5626 ::close(fenceFd);
5627 }
5628 return false;
5629 }
5630 info->mStatus = BufferInfo::OWNED_BY_US;
5631
5632 // input buffers cannot take fences, so wait for any fence now
5633 (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone");
5634 fenceFd = -1;
5635
5636 // still save fence for completeness
5637 info->setWriteFence(fenceFd, "onOMXEmptyBufferDone");
5638
5639 // We're in "store-metadata-in-buffers" mode, the underlying
5640 // OMX component had access to data that's implicitly refcounted
5641 // by this "MediaBuffer" object. Now that the OMX component has
5642 // told us that it's done with the input buffer, we can decrement
5643 // the mediaBuffer's reference count.
5644 info->mData->setMediaBufferBase(NULL);
5645
5646 PortMode mode = getPortMode(kPortIndexInput);
5647
5648 switch (mode) {
5649 case KEEP_BUFFERS:
5650 break;
5651
5652 case RESUBMIT_BUFFERS:
5653 postFillThisBuffer(info);
5654 break;
5655
5656 case FREE_BUFFERS:
5657 default:
5658 ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers");
5659 return false;
5660 }
5661
5662 return true;
5663 }
5664
postFillThisBuffer(BufferInfo * info)5665 void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
5666 if (mCodec->mPortEOS[kPortIndexInput]) {
5667 return;
5668 }
5669
5670 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5671
5672 info->mData->setFormat(mCodec->mInputFormat);
5673 mCodec->mBufferChannel->fillThisBuffer(info->mBufferID);
5674 info->mData.clear();
5675 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
5676 }
5677
onInputBufferFilled(const sp<AMessage> & msg)5678 void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
5679 IOMX::buffer_id bufferID;
5680 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
5681 sp<MediaCodecBuffer> buffer;
5682 int32_t err = OK;
5683 bool eos = false;
5684 PortMode mode = getPortMode(kPortIndexInput);
5685 int32_t discarded = 0;
5686 if (msg->findInt32("discarded", &discarded) && discarded) {
5687 // these are unfilled buffers returned by client
5688 // buffers are returned on MediaCodec.flush
5689 mode = KEEP_BUFFERS;
5690 }
5691 sp<RefBase> obj;
5692 CHECK(msg->findObject("buffer", &obj));
5693 buffer = static_cast<MediaCodecBuffer *>(obj.get());
5694
5695 int32_t tmp;
5696 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
5697 eos = true;
5698 err = ERROR_END_OF_STREAM;
5699 }
5700
5701 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
5702 BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5703 if (status != BufferInfo::OWNED_BY_UPSTREAM) {
5704 ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID);
5705 mCodec->dumpBuffers(kPortIndexInput);
5706 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5707 return;
5708 }
5709
5710 info->mStatus = BufferInfo::OWNED_BY_US;
5711 info->mData = buffer;
5712
5713 switch (mode) {
5714 case KEEP_BUFFERS:
5715 {
5716 if (eos) {
5717 if (!mCodec->mPortEOS[kPortIndexInput]) {
5718 mCodec->mPortEOS[kPortIndexInput] = true;
5719 mCodec->mInputEOSResult = err;
5720 }
5721 }
5722 break;
5723 }
5724
5725 case RESUBMIT_BUFFERS:
5726 {
5727 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
5728 // Do not send empty input buffer w/o EOS to the component.
5729 if (buffer->size() == 0 && !eos) {
5730 postFillThisBuffer(info);
5731 break;
5732 }
5733
5734 int64_t timeUs;
5735 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
5736
5737 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
5738
5739 int32_t isCSD = 0;
5740 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
5741 if (mCodec->mIsLegacyVP9Decoder) {
5742 ALOGV("[%s] is legacy VP9 decoder. Ignore %u codec specific data",
5743 mCodec->mComponentName.c_str(), bufferID);
5744 postFillThisBuffer(info);
5745 break;
5746 }
5747 flags |= OMX_BUFFERFLAG_CODECCONFIG;
5748 }
5749
5750 if (eos) {
5751 flags |= OMX_BUFFERFLAG_EOS;
5752 }
5753
5754 size_t size = buffer->size();
5755 size_t offset = buffer->offset();
5756 if (buffer->base() != info->mCodecData->base()) {
5757 ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)",
5758 mCodec->mComponentName.c_str(),
5759 bufferID,
5760 buffer->base(), info->mCodecData->base());
5761
5762 sp<DataConverter> converter = mCodec->mConverter[kPortIndexInput];
5763 if (converter == NULL || isCSD) {
5764 converter = getCopyConverter();
5765 }
5766 status_t err = converter->convert(buffer, info->mCodecData);
5767 if (err != OK) {
5768 mCodec->signalError(OMX_ErrorUndefined, err);
5769 return;
5770 }
5771 size = info->mCodecData->size();
5772 } else {
5773 info->mCodecData->setRange(offset, size);
5774 }
5775
5776 if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
5777 ALOGV("[%s] calling emptyBuffer %u w/ codec specific data",
5778 mCodec->mComponentName.c_str(), bufferID);
5779 } else if (flags & OMX_BUFFERFLAG_EOS) {
5780 ALOGV("[%s] calling emptyBuffer %u w/ EOS",
5781 mCodec->mComponentName.c_str(), bufferID);
5782 } else {
5783 #if TRACK_BUFFER_TIMING
5784 ALOGI("[%s] calling emptyBuffer %u w/ time %lld us",
5785 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
5786 #else
5787 ALOGV("[%s] calling emptyBuffer %u w/ time %lld us",
5788 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
5789 #endif
5790 }
5791
5792 #if TRACK_BUFFER_TIMING
5793 ACodec::BufferStats stats;
5794 stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
5795 stats.mFillBufferDoneTimeUs = -1ll;
5796 mCodec->mBufferStats.add(timeUs, stats);
5797 #endif
5798
5799 if (mCodec->storingMetadataInDecodedBuffers()) {
5800 // try to submit an output buffer for each input buffer
5801 PortMode outputMode = getPortMode(kPortIndexOutput);
5802
5803 ALOGV("MetadataBuffersToSubmit=%u portMode=%s",
5804 mCodec->mMetadataBuffersToSubmit,
5805 (outputMode == FREE_BUFFERS ? "FREE" :
5806 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
5807 if (outputMode == RESUBMIT_BUFFERS) {
5808 mCodec->submitOutputMetadataBuffer();
5809 }
5810 }
5811 info->checkReadFence("onInputBufferFilled");
5812
5813 status_t err2 = OK;
5814 switch (mCodec->mPortMode[kPortIndexInput]) {
5815 case IOMX::kPortModePresetByteBuffer:
5816 case IOMX::kPortModePresetANWBuffer:
5817 case IOMX::kPortModePresetSecureBuffer:
5818 {
5819 err2 = mCodec->mOMXNode->emptyBuffer(
5820 bufferID, info->mCodecData, flags, timeUs, info->mFenceFd);
5821 }
5822 break;
5823 #ifndef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
5824 case IOMX::kPortModeDynamicNativeHandle:
5825 if (info->mCodecData->size() >= sizeof(VideoNativeHandleMetadata)) {
5826 VideoNativeHandleMetadata *vnhmd =
5827 (VideoNativeHandleMetadata*)info->mCodecData->base();
5828 sp<NativeHandle> handle = NativeHandle::create(
5829 vnhmd->pHandle, false /* ownsHandle */);
5830 err2 = mCodec->mOMXNode->emptyBuffer(
5831 bufferID, handle, flags, timeUs, info->mFenceFd);
5832 }
5833 break;
5834 case IOMX::kPortModeDynamicANWBuffer:
5835 if (info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
5836 VideoNativeMetadata *vnmd = (VideoNativeMetadata*)info->mCodecData->base();
5837 sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(vnmd->pBuffer);
5838 err2 = mCodec->mOMXNode->emptyBuffer(
5839 bufferID, graphicBuffer, flags, timeUs, info->mFenceFd);
5840 }
5841 break;
5842 #endif
5843 default:
5844 ALOGW("Can't marshall %s data in %zu sized buffers in %zu-bit mode",
5845 asString(mCodec->mPortMode[kPortIndexInput]),
5846 info->mCodecData->size(),
5847 sizeof(buffer_handle_t) * 8);
5848 err2 = ERROR_UNSUPPORTED;
5849 break;
5850 }
5851
5852 info->mFenceFd = -1;
5853 if (err2 != OK) {
5854 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5855 return;
5856 }
5857 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5858 // Hold the reference while component is using the buffer.
5859 info->mData = buffer;
5860
5861 if (!eos && err == OK) {
5862 getMoreInputDataIfPossible();
5863 } else {
5864 ALOGV("[%s] Signalled EOS (%d) on the input port",
5865 mCodec->mComponentName.c_str(), err);
5866
5867 mCodec->mPortEOS[kPortIndexInput] = true;
5868 mCodec->mInputEOSResult = err;
5869 }
5870 } else if (!mCodec->mPortEOS[kPortIndexInput]) {
5871 if (err != OK && err != ERROR_END_OF_STREAM) {
5872 ALOGV("[%s] Signalling EOS on the input port due to error %d",
5873 mCodec->mComponentName.c_str(), err);
5874 } else {
5875 ALOGV("[%s] Signalling EOS on the input port",
5876 mCodec->mComponentName.c_str());
5877 }
5878
5879 ALOGV("[%s] calling emptyBuffer %u signalling EOS",
5880 mCodec->mComponentName.c_str(), bufferID);
5881
5882 info->checkReadFence("onInputBufferFilled");
5883 status_t err2 = mCodec->mOMXNode->emptyBuffer(
5884 bufferID, OMXBuffer::sPreset, OMX_BUFFERFLAG_EOS, 0, info->mFenceFd);
5885 info->mFenceFd = -1;
5886 if (err2 != OK) {
5887 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5888 return;
5889 }
5890 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5891
5892 mCodec->mPortEOS[kPortIndexInput] = true;
5893 mCodec->mInputEOSResult = err;
5894 }
5895 break;
5896 }
5897
5898 case FREE_BUFFERS:
5899 break;
5900
5901 default:
5902 ALOGE("invalid port mode: %d", mode);
5903 break;
5904 }
5905 }
5906
getMoreInputDataIfPossible()5907 void ACodec::BaseState::getMoreInputDataIfPossible() {
5908 if (mCodec->mPortEOS[kPortIndexInput]) {
5909 return;
5910 }
5911
5912 BufferInfo *eligible = NULL;
5913
5914 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5915 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5916
5917 #if 0
5918 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
5919 // There's already a "read" pending.
5920 return;
5921 }
5922 #endif
5923
5924 if (info->mStatus == BufferInfo::OWNED_BY_US) {
5925 eligible = info;
5926 }
5927 }
5928
5929 if (eligible == NULL) {
5930 return;
5931 }
5932
5933 postFillThisBuffer(eligible);
5934 }
5935
onOMXFillBufferDone(IOMX::buffer_id bufferID,size_t rangeOffset,size_t rangeLength,OMX_U32 flags,int64_t timeUs,int fenceFd)5936 bool ACodec::BaseState::onOMXFillBufferDone(
5937 IOMX::buffer_id bufferID,
5938 size_t rangeOffset, size_t rangeLength,
5939 OMX_U32 flags,
5940 int64_t timeUs,
5941 int fenceFd) {
5942 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
5943 mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
5944
5945 ssize_t index;
5946 status_t err= OK;
5947
5948 #if TRACK_BUFFER_TIMING
5949 index = mCodec->mBufferStats.indexOfKey(timeUs);
5950 if (index >= 0) {
5951 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
5952 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
5953
5954 ALOGI("frame PTS %lld: %lld",
5955 timeUs,
5956 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
5957
5958 mCodec->mBufferStats.removeItemsAt(index);
5959 stats = NULL;
5960 }
5961 #endif
5962
5963 BufferInfo *info =
5964 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
5965 BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5966 if (status != BufferInfo::OWNED_BY_COMPONENT) {
5967 ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5968 mCodec->dumpBuffers(kPortIndexOutput);
5969 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5970 if (fenceFd >= 0) {
5971 ::close(fenceFd);
5972 }
5973 return true;
5974 }
5975
5976 info->mDequeuedAt = ++mCodec->mDequeueCounter;
5977 info->mStatus = BufferInfo::OWNED_BY_US;
5978
5979 if (info->mRenderInfo != NULL) {
5980 // The fence for an emptied buffer must have signaled, but there still could be queued
5981 // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these,
5982 // as we will soon requeue this buffer to the surface. While in theory we could still keep
5983 // track of buffers that are requeued to the surface, it is better to add support to the
5984 // buffer-queue to notify us of released buffers and their fences (in the future).
5985 mCodec->notifyOfRenderedFrames(true /* dropIncomplete */);
5986 }
5987
5988 // byte buffers cannot take fences, so wait for any fence now
5989 if (mCodec->mNativeWindow == NULL) {
5990 (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone");
5991 fenceFd = -1;
5992 }
5993 info->setReadFence(fenceFd, "onOMXFillBufferDone");
5994
5995 PortMode mode = getPortMode(kPortIndexOutput);
5996
5997 switch (mode) {
5998 case KEEP_BUFFERS:
5999 break;
6000
6001 case RESUBMIT_BUFFERS:
6002 {
6003 if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
6004 || mCodec->mPortEOS[kPortIndexOutput])) {
6005 ALOGV("[%s] calling fillBuffer %u",
6006 mCodec->mComponentName.c_str(), info->mBufferID);
6007
6008 err = mCodec->fillBuffer(info);
6009 if (err != OK) {
6010 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6011 return true;
6012 }
6013 break;
6014 }
6015
6016 sp<MediaCodecBuffer> buffer = info->mData;
6017
6018 if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) {
6019 // pretend that output format has changed on the first frame (we used to do this)
6020 if (mCodec->mBaseOutputFormat == mCodec->mOutputFormat) {
6021 mCodec->onOutputFormatChanged(mCodec->mOutputFormat);
6022 }
6023 mCodec->sendFormatChange();
6024 }
6025 buffer->setFormat(mCodec->mOutputFormat);
6026
6027 if (mCodec->usingSecureBufferOnEncoderOutput()) {
6028 native_handle_t *handle = NULL;
6029 sp<SecureBuffer> secureBuffer = static_cast<SecureBuffer *>(buffer.get());
6030 if (secureBuffer != NULL) {
6031 #ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
6032 // handle is only valid on 32-bit/mediaserver process
6033 handle = NULL;
6034 #else
6035 handle = (native_handle_t *)secureBuffer->getDestinationPointer();
6036 #endif
6037 }
6038 buffer->meta()->setPointer("handle", handle);
6039 buffer->meta()->setInt32("rangeOffset", rangeOffset);
6040 buffer->meta()->setInt32("rangeLength", rangeLength);
6041 } else if (buffer->base() == info->mCodecData->base()) {
6042 buffer->setRange(rangeOffset, rangeLength);
6043 } else {
6044 info->mCodecData->setRange(rangeOffset, rangeLength);
6045 // in this case we know that mConverter is not null
6046 status_t err = mCodec->mConverter[kPortIndexOutput]->convert(
6047 info->mCodecData, buffer);
6048 if (err != OK) {
6049 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6050 return true;
6051 }
6052 }
6053 #if 0
6054 if (mCodec->mNativeWindow == NULL) {
6055 if (IsIDR(info->mData)) {
6056 ALOGI("IDR frame");
6057 }
6058 }
6059 #endif
6060
6061 if (mCodec->mSkipCutBuffer != NULL) {
6062 mCodec->mSkipCutBuffer->submit(buffer);
6063 }
6064 buffer->meta()->setInt64("timeUs", timeUs);
6065
6066 info->mData.clear();
6067
6068 mCodec->mBufferChannel->drainThisBuffer(info->mBufferID, flags);
6069
6070 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
6071
6072 if (flags & OMX_BUFFERFLAG_EOS) {
6073 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
6074
6075 mCodec->mCallback->onEos(mCodec->mInputEOSResult);
6076 mCodec->mPortEOS[kPortIndexOutput] = true;
6077 }
6078 break;
6079 }
6080
6081 case FREE_BUFFERS:
6082 err = mCodec->freeBuffer(kPortIndexOutput, index);
6083 if (err != OK) {
6084 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6085 return true;
6086 }
6087 break;
6088
6089 default:
6090 ALOGE("Invalid port mode: %d", mode);
6091 return false;
6092 }
6093
6094 return true;
6095 }
6096
onOutputBufferDrained(const sp<AMessage> & msg)6097 void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
6098 IOMX::buffer_id bufferID;
6099 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
6100 sp<RefBase> obj;
6101 CHECK(msg->findObject("buffer", &obj));
6102 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
6103 int32_t discarded = 0;
6104 msg->findInt32("discarded", &discarded);
6105
6106 ssize_t index;
6107 BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
6108 BufferInfo::Status status = BufferInfo::getSafeStatus(info);
6109 if (status != BufferInfo::OWNED_BY_DOWNSTREAM) {
6110 ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
6111 mCodec->dumpBuffers(kPortIndexOutput);
6112 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6113 return;
6114 }
6115 info->mData = buffer;
6116 int32_t render;
6117 if (mCodec->mNativeWindow != NULL
6118 && msg->findInt32("render", &render) && render != 0
6119 && !discarded && buffer->size() != 0) {
6120 ATRACE_NAME("render");
6121 // The client wants this buffer to be rendered.
6122
6123 android_native_rect_t crop;
6124 if (buffer->format()->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {
6125 // NOTE: native window uses extended right-bottom coordinate
6126 ++crop.right;
6127 ++crop.bottom;
6128 if (memcmp(&crop, &mCodec->mLastNativeWindowCrop, sizeof(crop)) != 0) {
6129 mCodec->mLastNativeWindowCrop = crop;
6130 status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
6131 ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
6132 }
6133 }
6134
6135 int32_t dataSpace;
6136 if (buffer->format()->findInt32("android._dataspace", &dataSpace)
6137 && dataSpace != mCodec->mLastNativeWindowDataSpace) {
6138 status_t err = native_window_set_buffers_data_space(
6139 mCodec->mNativeWindow.get(), (android_dataspace)dataSpace);
6140 mCodec->mLastNativeWindowDataSpace = dataSpace;
6141 ALOGW_IF(err != NO_ERROR, "failed to set dataspace: %d", err);
6142 }
6143
6144 // save buffers sent to the surface so we can get render time when they return
6145 int64_t mediaTimeUs = -1;
6146 buffer->meta()->findInt64("timeUs", &mediaTimeUs);
6147 if (mediaTimeUs >= 0) {
6148 mCodec->mRenderTracker.onFrameQueued(
6149 mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd)));
6150 }
6151
6152 int64_t timestampNs = 0;
6153 if (!msg->findInt64("timestampNs", ×tampNs)) {
6154 // use media timestamp if client did not request a specific render timestamp
6155 if (buffer->meta()->findInt64("timeUs", ×tampNs)) {
6156 ALOGV("using buffer PTS of %lld", (long long)timestampNs);
6157 timestampNs *= 1000;
6158 }
6159 }
6160
6161 status_t err;
6162 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
6163 ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);
6164
6165 info->checkReadFence("onOutputBufferDrained before queueBuffer");
6166 err = mCodec->mNativeWindow->queueBuffer(
6167 mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
6168 info->mFenceFd = -1;
6169 if (err == OK) {
6170 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
6171 } else {
6172 ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err);
6173 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6174 info->mStatus = BufferInfo::OWNED_BY_US;
6175 // keeping read fence as write fence to avoid clobbering
6176 info->mIsReadFence = false;
6177 }
6178 } else {
6179 if (mCodec->mNativeWindow != NULL && (discarded || buffer->size() != 0)) {
6180 // move read fence into write fence to avoid clobbering
6181 info->mIsReadFence = false;
6182 ATRACE_NAME("frame-drop");
6183 }
6184 info->mStatus = BufferInfo::OWNED_BY_US;
6185 }
6186
6187 PortMode mode = getPortMode(kPortIndexOutput);
6188
6189 switch (mode) {
6190 case KEEP_BUFFERS:
6191 {
6192 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
6193
6194 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6195 // We cannot resubmit the buffer we just rendered, dequeue
6196 // the spare instead.
6197
6198 info = mCodec->dequeueBufferFromNativeWindow();
6199 }
6200 break;
6201 }
6202
6203 case RESUBMIT_BUFFERS:
6204 {
6205 if (!mCodec->mPortEOS[kPortIndexOutput]) {
6206 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6207 // We cannot resubmit the buffer we just rendered, dequeue
6208 // the spare instead.
6209
6210 info = mCodec->dequeueBufferFromNativeWindow();
6211 }
6212
6213 if (info != NULL) {
6214 ALOGV("[%s] calling fillBuffer %u",
6215 mCodec->mComponentName.c_str(), info->mBufferID);
6216 info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS");
6217 status_t err = mCodec->fillBuffer(info);
6218 if (err != OK) {
6219 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6220 }
6221 }
6222 }
6223 break;
6224 }
6225
6226 case FREE_BUFFERS:
6227 {
6228 status_t err = mCodec->freeBuffer(kPortIndexOutput, index);
6229 if (err != OK) {
6230 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6231 }
6232 break;
6233 }
6234
6235 default:
6236 ALOGE("Invalid port mode: %d", mode);
6237 return;
6238 }
6239 }
6240
6241 ////////////////////////////////////////////////////////////////////////////////
6242
UninitializedState(ACodec * codec)6243 ACodec::UninitializedState::UninitializedState(ACodec *codec)
6244 : BaseState(codec) {
6245 }
6246
stateEntered()6247 void ACodec::UninitializedState::stateEntered() {
6248 ALOGV("Now uninitialized");
6249
6250 if (mDeathNotifier != NULL) {
6251 if (mCodec->mOMXNode != NULL) {
6252 if (mCodec->getTrebleFlag()) {
6253 auto tOmxNode = mCodec->mOMXNode->getHalInterface();
6254 tOmxNode->unlinkToDeath(mDeathNotifier);
6255 } else {
6256 sp<IBinder> binder = IInterface::asBinder(mCodec->mOMXNode);
6257 binder->unlinkToDeath(mDeathNotifier);
6258 }
6259 }
6260 mDeathNotifier.clear();
6261 }
6262
6263 mCodec->mUsingNativeWindow = false;
6264 mCodec->mNativeWindow.clear();
6265 mCodec->mNativeWindowUsageBits = 0;
6266 mCodec->mOMX.clear();
6267 mCodec->mOMXNode.clear();
6268 mCodec->mFlags = 0;
6269 mCodec->mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
6270 mCodec->mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
6271 mCodec->mConverter[0].clear();
6272 mCodec->mConverter[1].clear();
6273 mCodec->mComponentName.clear();
6274 }
6275
onMessageReceived(const sp<AMessage> & msg)6276 bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
6277 bool handled = false;
6278
6279 switch (msg->what()) {
6280 case ACodec::kWhatSetup:
6281 {
6282 onSetup(msg);
6283
6284 handled = true;
6285 break;
6286 }
6287
6288 case ACodec::kWhatAllocateComponent:
6289 {
6290 onAllocateComponent(msg);
6291 handled = true;
6292 break;
6293 }
6294
6295 case ACodec::kWhatShutdown:
6296 {
6297 int32_t keepComponentAllocated;
6298 CHECK(msg->findInt32(
6299 "keepComponentAllocated", &keepComponentAllocated));
6300 ALOGW_IF(keepComponentAllocated,
6301 "cannot keep component allocated on shutdown in Uninitialized state");
6302 if (keepComponentAllocated) {
6303 mCodec->mCallback->onStopCompleted();
6304 } else {
6305 mCodec->mCallback->onReleaseCompleted();
6306 }
6307 handled = true;
6308 break;
6309 }
6310
6311 case ACodec::kWhatFlush:
6312 {
6313 mCodec->mCallback->onFlushCompleted();
6314 handled = true;
6315 break;
6316 }
6317
6318 case ACodec::kWhatReleaseCodecInstance:
6319 {
6320 // nothing to do, as we have already signaled shutdown
6321 handled = true;
6322 break;
6323 }
6324
6325 default:
6326 return BaseState::onMessageReceived(msg);
6327 }
6328
6329 return handled;
6330 }
6331
onSetup(const sp<AMessage> & msg)6332 void ACodec::UninitializedState::onSetup(
6333 const sp<AMessage> &msg) {
6334 if (onAllocateComponent(msg)
6335 && mCodec->mLoadedState->onConfigureComponent(msg)) {
6336 mCodec->mLoadedState->onStart();
6337 }
6338 }
6339
onAllocateComponent(const sp<AMessage> & msg)6340 bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
6341 ALOGV("onAllocateComponent");
6342
6343 CHECK(mCodec->mOMXNode == NULL);
6344
6345 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
6346
6347 Vector<AString> matchingCodecs;
6348 Vector<AString> owners;
6349
6350 AString mime;
6351
6352 AString componentName;
6353 int32_t encoder = false;
6354 if (msg->findString("componentName", &componentName)) {
6355 sp<IMediaCodecList> list = MediaCodecList::getInstance();
6356 if (list == nullptr) {
6357 ALOGE("Unable to obtain MediaCodecList while "
6358 "attempting to create codec \"%s\"",
6359 componentName.c_str());
6360 mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
6361 return false;
6362 }
6363 ssize_t index = list->findCodecByName(componentName.c_str());
6364 if (index < 0) {
6365 ALOGE("Unable to find codec \"%s\"",
6366 componentName.c_str());
6367 mCodec->signalError(OMX_ErrorInvalidComponent, NAME_NOT_FOUND);
6368 return false;
6369 }
6370 sp<MediaCodecInfo> info = list->getCodecInfo(index);
6371 if (info == nullptr) {
6372 ALOGE("Unexpected error (index out-of-bound) while "
6373 "retrieving information for codec \"%s\"",
6374 componentName.c_str());
6375 mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR);
6376 return false;
6377 }
6378 matchingCodecs.add(info->getCodecName());
6379 owners.add(info->getOwnerName() == nullptr ?
6380 "default" : info->getOwnerName());
6381 } else {
6382 CHECK(msg->findString("mime", &mime));
6383
6384 if (!msg->findInt32("encoder", &encoder)) {
6385 encoder = false;
6386 }
6387
6388 MediaCodecList::findMatchingCodecs(
6389 mime.c_str(),
6390 encoder, // createEncoder
6391 0, // flags
6392 &matchingCodecs,
6393 &owners);
6394 }
6395
6396 sp<CodecObserver> observer = new CodecObserver;
6397 sp<IOMX> omx;
6398 sp<IOMXNode> omxNode;
6399
6400 status_t err = NAME_NOT_FOUND;
6401 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
6402 ++matchIndex) {
6403 componentName = matchingCodecs[matchIndex];
6404
6405 OMXClient client;
6406 bool trebleFlag;
6407 if (client.connect(owners[matchIndex].c_str(), &trebleFlag) != OK) {
6408 mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
6409 return false;
6410 }
6411 omx = client.interface();
6412
6413 pid_t tid = gettid();
6414 int prevPriority = androidGetThreadPriority(tid);
6415 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
6416 err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
6417 androidSetThreadPriority(tid, prevPriority);
6418
6419 if (err == OK) {
6420 mCodec->setTrebleFlag(trebleFlag);
6421 break;
6422 } else {
6423 ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
6424 }
6425
6426 omxNode = NULL;
6427 }
6428
6429 if (omxNode == NULL) {
6430 if (!mime.empty()) {
6431 ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
6432 encoder ? "en" : "de", mime.c_str(), err);
6433 } else {
6434 ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
6435 }
6436
6437 mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
6438 return false;
6439 }
6440
6441 mDeathNotifier = new DeathNotifier(notify);
6442 if (mCodec->getTrebleFlag()) {
6443 auto tOmxNode = omxNode->getHalInterface();
6444 if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
6445 mDeathNotifier.clear();
6446 }
6447 } else {
6448 if (IInterface::asBinder(omxNode)->linkToDeath(mDeathNotifier) != OK) {
6449 // This was a local binder, if it dies so do we, we won't care
6450 // about any notifications in the afterlife.
6451 mDeathNotifier.clear();
6452 }
6453 }
6454
6455 notify = new AMessage(kWhatOMXMessageList, mCodec);
6456 notify->setInt32("generation", ++mCodec->mNodeGeneration);
6457 observer->setNotificationMessage(notify);
6458
6459 mCodec->mComponentName = componentName;
6460 mCodec->mRenderTracker.setComponentName(componentName);
6461 mCodec->mFlags = 0;
6462
6463 if (componentName.endsWith(".secure")) {
6464 mCodec->mFlags |= kFlagIsSecure;
6465 mCodec->mFlags |= kFlagIsGrallocUsageProtected;
6466 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
6467 }
6468
6469 mCodec->mOMX = omx;
6470 mCodec->mOMXNode = omxNode;
6471 mCodec->mCallback->onComponentAllocated(mCodec->mComponentName.c_str());
6472 mCodec->changeState(mCodec->mLoadedState);
6473
6474 return true;
6475 }
6476
6477 ////////////////////////////////////////////////////////////////////////////////
6478
LoadedState(ACodec * codec)6479 ACodec::LoadedState::LoadedState(ACodec *codec)
6480 : BaseState(codec) {
6481 }
6482
stateEntered()6483 void ACodec::LoadedState::stateEntered() {
6484 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
6485
6486 mCodec->mPortEOS[kPortIndexInput] =
6487 mCodec->mPortEOS[kPortIndexOutput] = false;
6488
6489 mCodec->mInputEOSResult = OK;
6490
6491 mCodec->mDequeueCounter = 0;
6492 mCodec->mMetadataBuffersToSubmit = 0;
6493 mCodec->mRepeatFrameDelayUs = -1ll;
6494 mCodec->mInputFormat.clear();
6495 mCodec->mOutputFormat.clear();
6496 mCodec->mBaseOutputFormat.clear();
6497 mCodec->mGraphicBufferSource.clear();
6498
6499 if (mCodec->mShutdownInProgress) {
6500 bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
6501
6502 mCodec->mShutdownInProgress = false;
6503 mCodec->mKeepComponentAllocated = false;
6504
6505 onShutdown(keepComponentAllocated);
6506 }
6507 mCodec->mExplicitShutdown = false;
6508
6509 mCodec->processDeferredMessages();
6510 }
6511
onShutdown(bool keepComponentAllocated)6512 void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
6513 if (!keepComponentAllocated) {
6514 (void)mCodec->mOMXNode->freeNode();
6515
6516 mCodec->changeState(mCodec->mUninitializedState);
6517 }
6518
6519 if (mCodec->mExplicitShutdown) {
6520 if (keepComponentAllocated) {
6521 mCodec->mCallback->onStopCompleted();
6522 } else {
6523 mCodec->mCallback->onReleaseCompleted();
6524 }
6525 mCodec->mExplicitShutdown = false;
6526 }
6527 }
6528
onMessageReceived(const sp<AMessage> & msg)6529 bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
6530 bool handled = false;
6531
6532 switch (msg->what()) {
6533 case ACodec::kWhatConfigureComponent:
6534 {
6535 onConfigureComponent(msg);
6536 handled = true;
6537 break;
6538 }
6539
6540 case ACodec::kWhatCreateInputSurface:
6541 {
6542 onCreateInputSurface(msg);
6543 handled = true;
6544 break;
6545 }
6546
6547 case ACodec::kWhatSetInputSurface:
6548 {
6549 onSetInputSurface(msg);
6550 handled = true;
6551 break;
6552 }
6553
6554 case ACodec::kWhatStart:
6555 {
6556 onStart();
6557 handled = true;
6558 break;
6559 }
6560
6561 case ACodec::kWhatShutdown:
6562 {
6563 int32_t keepComponentAllocated;
6564 CHECK(msg->findInt32(
6565 "keepComponentAllocated", &keepComponentAllocated));
6566
6567 mCodec->mExplicitShutdown = true;
6568 onShutdown(keepComponentAllocated);
6569
6570 handled = true;
6571 break;
6572 }
6573
6574 case ACodec::kWhatFlush:
6575 {
6576 mCodec->mCallback->onFlushCompleted();
6577 handled = true;
6578 break;
6579 }
6580
6581 default:
6582 return BaseState::onMessageReceived(msg);
6583 }
6584
6585 return handled;
6586 }
6587
onConfigureComponent(const sp<AMessage> & msg)6588 bool ACodec::LoadedState::onConfigureComponent(
6589 const sp<AMessage> &msg) {
6590 ALOGV("onConfigureComponent");
6591
6592 CHECK(mCodec->mOMXNode != NULL);
6593
6594 status_t err = OK;
6595 AString mime;
6596 if (!msg->findString("mime", &mime)) {
6597 err = BAD_VALUE;
6598 } else {
6599 err = mCodec->configureCodec(mime.c_str(), msg);
6600 }
6601 if (err != OK) {
6602 ALOGE("[%s] configureCodec returning error %d",
6603 mCodec->mComponentName.c_str(), err);
6604
6605 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6606 return false;
6607 }
6608
6609 mCodec->mCallback->onComponentConfigured(mCodec->mInputFormat, mCodec->mOutputFormat);
6610
6611 return true;
6612 }
6613
setupInputSurface()6614 status_t ACodec::LoadedState::setupInputSurface() {
6615 if (mCodec->mGraphicBufferSource == NULL) {
6616 return BAD_VALUE;
6617 }
6618
6619 android_dataspace dataSpace;
6620 status_t err =
6621 mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
6622 if (err != OK) {
6623 ALOGE("Failed to get default data space");
6624 return err;
6625 }
6626
6627 err = statusFromBinderStatus(
6628 mCodec->mGraphicBufferSource->configure(mCodec->mOMXNode, dataSpace));
6629 if (err != OK) {
6630 ALOGE("[%s] Unable to configure for node (err %d)",
6631 mCodec->mComponentName.c_str(), err);
6632 return err;
6633 }
6634
6635 if (mCodec->mRepeatFrameDelayUs > 0ll) {
6636 err = statusFromBinderStatus(
6637 mCodec->mGraphicBufferSource->setRepeatPreviousFrameDelayUs(
6638 mCodec->mRepeatFrameDelayUs));
6639
6640 if (err != OK) {
6641 ALOGE("[%s] Unable to configure option to repeat previous "
6642 "frames (err %d)",
6643 mCodec->mComponentName.c_str(), err);
6644 return err;
6645 }
6646 }
6647
6648 if (mCodec->mMaxPtsGapUs > 0ll) {
6649 OMX_PARAM_U32TYPE maxPtsGapParams;
6650 InitOMXParams(&maxPtsGapParams);
6651 maxPtsGapParams.nPortIndex = kPortIndexInput;
6652 maxPtsGapParams.nU32 = (uint32_t) mCodec->mMaxPtsGapUs;
6653
6654 err = mCodec->mOMXNode->setParameter(
6655 (OMX_INDEXTYPE)OMX_IndexParamMaxFrameDurationForBitrateControl,
6656 &maxPtsGapParams, sizeof(maxPtsGapParams));
6657
6658 if (err != OK) {
6659 ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
6660 mCodec->mComponentName.c_str(), err);
6661 return err;
6662 }
6663 }
6664
6665 if (mCodec->mMaxFps > 0) {
6666 err = statusFromBinderStatus(
6667 mCodec->mGraphicBufferSource->setMaxFps(mCodec->mMaxFps));
6668
6669 if (err != OK) {
6670 ALOGE("[%s] Unable to configure max fps (err %d)",
6671 mCodec->mComponentName.c_str(), err);
6672 return err;
6673 }
6674 }
6675
6676 if (mCodec->mCaptureFps > 0. && mCodec->mFps > 0.) {
6677 err = statusFromBinderStatus(
6678 mCodec->mGraphicBufferSource->setTimeLapseConfig(
6679 mCodec->mFps, mCodec->mCaptureFps));
6680
6681 if (err != OK) {
6682 ALOGE("[%s] Unable to configure time lapse (err %d)",
6683 mCodec->mComponentName.c_str(), err);
6684 return err;
6685 }
6686 }
6687
6688 if (mCodec->mCreateInputBuffersSuspended) {
6689 err = statusFromBinderStatus(
6690 mCodec->mGraphicBufferSource->setSuspend(true, -1));
6691
6692 if (err != OK) {
6693 ALOGE("[%s] Unable to configure option to suspend (err %d)",
6694 mCodec->mComponentName.c_str(), err);
6695 return err;
6696 }
6697 }
6698
6699 uint32_t usageBits;
6700 if (mCodec->mOMXNode->getParameter(
6701 (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
6702 &usageBits, sizeof(usageBits)) == OK) {
6703 mCodec->mInputFormat->setInt32(
6704 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
6705 }
6706
6707 sp<ABuffer> colorAspectsBuffer;
6708 if (mCodec->mInputFormat->findBuffer("android._color-aspects", &colorAspectsBuffer)) {
6709 if (colorAspectsBuffer->size() != sizeof(ColorAspects)) {
6710 return INVALID_OPERATION;
6711 }
6712
6713 err = statusFromBinderStatus(
6714 mCodec->mGraphicBufferSource->setColorAspects(ColorUtils::packToU32(
6715 *(ColorAspects *)colorAspectsBuffer->base())));
6716
6717 if (err != OK) {
6718 ALOGE("[%s] Unable to configure color aspects (err %d)",
6719 mCodec->mComponentName.c_str(), err);
6720 return err;
6721 }
6722 }
6723 return OK;
6724 }
6725
onCreateInputSurface(const sp<AMessage> &)6726 void ACodec::LoadedState::onCreateInputSurface(
6727 const sp<AMessage> & /* msg */) {
6728 ALOGV("onCreateInputSurface");
6729
6730 sp<IGraphicBufferProducer> bufferProducer;
6731 status_t err = mCodec->mOMX->createInputSurface(
6732 &bufferProducer, &mCodec->mGraphicBufferSource);
6733
6734 if (err == OK) {
6735 err = setupInputSurface();
6736 }
6737
6738 if (err == OK) {
6739 mCodec->mCallback->onInputSurfaceCreated(
6740 mCodec->mInputFormat,
6741 mCodec->mOutputFormat,
6742 new BufferProducerWrapper(bufferProducer));
6743 } else {
6744 // Can't use mCodec->signalError() here -- MediaCodec won't forward
6745 // the error through because it's in the "configured" state. We
6746 // send a kWhatInputSurfaceCreated with an error value instead.
6747 ALOGE("[%s] onCreateInputSurface returning error %d",
6748 mCodec->mComponentName.c_str(), err);
6749 mCodec->mCallback->onInputSurfaceCreationFailed(err);
6750 }
6751 }
6752
onSetInputSurface(const sp<AMessage> & msg)6753 void ACodec::LoadedState::onSetInputSurface(const sp<AMessage> &msg) {
6754 ALOGV("onSetInputSurface");
6755
6756 sp<RefBase> obj;
6757 CHECK(msg->findObject("input-surface", &obj));
6758 sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
6759 mCodec->mGraphicBufferSource = surface->getBufferSource();
6760
6761 status_t err = setupInputSurface();
6762
6763 if (err == OK) {
6764 mCodec->mCallback->onInputSurfaceAccepted(
6765 mCodec->mInputFormat, mCodec->mOutputFormat);
6766 } else {
6767 // Can't use mCodec->signalError() here -- MediaCodec won't forward
6768 // the error through because it's in the "configured" state. We
6769 // send a kWhatInputSurfaceAccepted with an error value instead.
6770 ALOGE("[%s] onSetInputSurface returning error %d",
6771 mCodec->mComponentName.c_str(), err);
6772 mCodec->mCallback->onInputSurfaceDeclined(err);
6773 }
6774 }
6775
onStart()6776 void ACodec::LoadedState::onStart() {
6777 ALOGV("onStart");
6778
6779 status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
6780 if (err != OK) {
6781 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6782 } else {
6783 mCodec->changeState(mCodec->mLoadedToIdleState);
6784 }
6785 }
6786
6787 ////////////////////////////////////////////////////////////////////////////////
6788
LoadedToIdleState(ACodec * codec)6789 ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
6790 : BaseState(codec) {
6791 }
6792
stateEntered()6793 void ACodec::LoadedToIdleState::stateEntered() {
6794 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
6795
6796 status_t err;
6797 if ((err = allocateBuffers()) != OK) {
6798 ALOGE("Failed to allocate buffers after transitioning to IDLE state "
6799 "(error 0x%08x)",
6800 err);
6801
6802 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6803
6804 mCodec->mOMXNode->sendCommand(
6805 OMX_CommandStateSet, OMX_StateLoaded);
6806 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) {
6807 mCodec->freeBuffersOnPort(kPortIndexInput);
6808 }
6809 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexOutput)) {
6810 mCodec->freeBuffersOnPort(kPortIndexOutput);
6811 }
6812
6813 mCodec->changeState(mCodec->mLoadedState);
6814 }
6815 }
6816
allocateBuffers()6817 status_t ACodec::LoadedToIdleState::allocateBuffers() {
6818 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
6819 if (err != OK) {
6820 return err;
6821 }
6822
6823 err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
6824 if (err != OK) {
6825 return err;
6826 }
6827
6828 mCodec->mCallback->onStartCompleted();
6829
6830 return OK;
6831 }
6832
onMessageReceived(const sp<AMessage> & msg)6833 bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
6834 switch (msg->what()) {
6835 case kWhatSetParameters:
6836 case kWhatShutdown:
6837 {
6838 mCodec->deferMessage(msg);
6839 return true;
6840 }
6841
6842 case kWhatSignalEndOfInputStream:
6843 {
6844 mCodec->onSignalEndOfInputStream();
6845 return true;
6846 }
6847
6848 case kWhatResume:
6849 {
6850 // We'll be active soon enough.
6851 return true;
6852 }
6853
6854 case kWhatFlush:
6855 {
6856 // We haven't even started yet, so we're flushed alright...
6857 mCodec->mCallback->onFlushCompleted();
6858 return true;
6859 }
6860
6861 default:
6862 return BaseState::onMessageReceived(msg);
6863 }
6864 }
6865
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)6866 bool ACodec::LoadedToIdleState::onOMXEvent(
6867 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6868 switch (event) {
6869 case OMX_EventCmdComplete:
6870 {
6871 status_t err = OK;
6872 if (data1 != (OMX_U32)OMX_CommandStateSet
6873 || data2 != (OMX_U32)OMX_StateIdle) {
6874 ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)",
6875 asString((OMX_COMMANDTYPE)data1), data1,
6876 asString((OMX_STATETYPE)data2), data2);
6877 err = FAILED_TRANSACTION;
6878 }
6879
6880 if (err == OK) {
6881 err = mCodec->mOMXNode->sendCommand(
6882 OMX_CommandStateSet, OMX_StateExecuting);
6883 }
6884
6885 if (err != OK) {
6886 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6887 } else {
6888 mCodec->changeState(mCodec->mIdleToExecutingState);
6889 }
6890
6891 return true;
6892 }
6893
6894 default:
6895 return BaseState::onOMXEvent(event, data1, data2);
6896 }
6897 }
6898
6899 ////////////////////////////////////////////////////////////////////////////////
6900
IdleToExecutingState(ACodec * codec)6901 ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
6902 : BaseState(codec) {
6903 }
6904
stateEntered()6905 void ACodec::IdleToExecutingState::stateEntered() {
6906 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
6907 }
6908
onMessageReceived(const sp<AMessage> & msg)6909 bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
6910 switch (msg->what()) {
6911 case kWhatSetParameters:
6912 case kWhatShutdown:
6913 {
6914 mCodec->deferMessage(msg);
6915 return true;
6916 }
6917
6918 case kWhatResume:
6919 {
6920 // We'll be active soon enough.
6921 return true;
6922 }
6923
6924 case kWhatFlush:
6925 {
6926 // We haven't even started yet, so we're flushed alright...
6927 mCodec->mCallback->onFlushCompleted();
6928 return true;
6929 }
6930
6931 case kWhatSignalEndOfInputStream:
6932 {
6933 mCodec->onSignalEndOfInputStream();
6934 return true;
6935 }
6936
6937 default:
6938 return BaseState::onMessageReceived(msg);
6939 }
6940 }
6941
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)6942 bool ACodec::IdleToExecutingState::onOMXEvent(
6943 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6944 switch (event) {
6945 case OMX_EventCmdComplete:
6946 {
6947 if (data1 != (OMX_U32)OMX_CommandStateSet
6948 || data2 != (OMX_U32)OMX_StateExecuting) {
6949 ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)",
6950 asString((OMX_COMMANDTYPE)data1), data1,
6951 asString((OMX_STATETYPE)data2), data2);
6952 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6953 return true;
6954 }
6955
6956 mCodec->mExecutingState->resume();
6957 mCodec->changeState(mCodec->mExecutingState);
6958
6959 return true;
6960 }
6961
6962 default:
6963 return BaseState::onOMXEvent(event, data1, data2);
6964 }
6965 }
6966
6967 ////////////////////////////////////////////////////////////////////////////////
6968
ExecutingState(ACodec * codec)6969 ACodec::ExecutingState::ExecutingState(ACodec *codec)
6970 : BaseState(codec),
6971 mActive(false) {
6972 }
6973
getPortMode(OMX_U32)6974 ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
6975 OMX_U32 /* portIndex */) {
6976 return RESUBMIT_BUFFERS;
6977 }
6978
submitOutputMetaBuffers()6979 void ACodec::ExecutingState::submitOutputMetaBuffers() {
6980 // submit as many buffers as there are input buffers with the codec
6981 // in case we are in port reconfiguring
6982 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
6983 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
6984
6985 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
6986 if (mCodec->submitOutputMetadataBuffer() != OK)
6987 break;
6988 }
6989 }
6990
6991 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
6992 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
6993 }
6994
submitRegularOutputBuffers()6995 void ACodec::ExecutingState::submitRegularOutputBuffers() {
6996 bool failed = false;
6997 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
6998 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
6999
7000 if (mCodec->mNativeWindow != NULL) {
7001 if (info->mStatus != BufferInfo::OWNED_BY_US
7002 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
7003 ALOGE("buffers should be owned by us or the surface");
7004 failed = true;
7005 break;
7006 }
7007
7008 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
7009 continue;
7010 }
7011 } else {
7012 if (info->mStatus != BufferInfo::OWNED_BY_US) {
7013 ALOGE("buffers should be owned by us");
7014 failed = true;
7015 break;
7016 }
7017 }
7018
7019 ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
7020
7021 info->checkWriteFence("submitRegularOutputBuffers");
7022 status_t err = mCodec->fillBuffer(info);
7023 if (err != OK) {
7024 failed = true;
7025 break;
7026 }
7027 }
7028
7029 if (failed) {
7030 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7031 }
7032 }
7033
submitOutputBuffers()7034 void ACodec::ExecutingState::submitOutputBuffers() {
7035 submitRegularOutputBuffers();
7036 if (mCodec->storingMetadataInDecodedBuffers()) {
7037 submitOutputMetaBuffers();
7038 }
7039 }
7040
resume()7041 void ACodec::ExecutingState::resume() {
7042 if (mActive) {
7043 ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str());
7044 return;
7045 }
7046
7047 submitOutputBuffers();
7048
7049 // Post all available input buffers
7050 if (mCodec->mBuffers[kPortIndexInput].size() == 0u) {
7051 ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str());
7052 }
7053
7054 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
7055 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
7056 if (info->mStatus == BufferInfo::OWNED_BY_US) {
7057 postFillThisBuffer(info);
7058 }
7059 }
7060
7061 mActive = true;
7062 }
7063
stateEntered()7064 void ACodec::ExecutingState::stateEntered() {
7065 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
7066 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
7067 mCodec->processDeferredMessages();
7068 }
7069
onMessageReceived(const sp<AMessage> & msg)7070 bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
7071 bool handled = false;
7072
7073 switch (msg->what()) {
7074 case kWhatShutdown:
7075 {
7076 int32_t keepComponentAllocated;
7077 CHECK(msg->findInt32(
7078 "keepComponentAllocated", &keepComponentAllocated));
7079
7080 mCodec->mShutdownInProgress = true;
7081 mCodec->mExplicitShutdown = true;
7082 mCodec->mKeepComponentAllocated = keepComponentAllocated;
7083
7084 mActive = false;
7085
7086 status_t err = mCodec->mOMXNode->sendCommand(
7087 OMX_CommandStateSet, OMX_StateIdle);
7088 if (err != OK) {
7089 if (keepComponentAllocated) {
7090 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7091 }
7092 // TODO: do some recovery here.
7093 } else {
7094 mCodec->changeState(mCodec->mExecutingToIdleState);
7095 }
7096
7097 handled = true;
7098 break;
7099 }
7100
7101 case kWhatFlush:
7102 {
7103 ALOGV("[%s] ExecutingState flushing now "
7104 "(codec owns %zu/%zu input, %zu/%zu output).",
7105 mCodec->mComponentName.c_str(),
7106 mCodec->countBuffersOwnedByComponent(kPortIndexInput),
7107 mCodec->mBuffers[kPortIndexInput].size(),
7108 mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
7109 mCodec->mBuffers[kPortIndexOutput].size());
7110
7111 mActive = false;
7112
7113 status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandFlush, OMX_ALL);
7114 if (err != OK) {
7115 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7116 } else {
7117 mCodec->changeState(mCodec->mFlushingState);
7118 }
7119
7120 handled = true;
7121 break;
7122 }
7123
7124 case kWhatResume:
7125 {
7126 resume();
7127
7128 handled = true;
7129 break;
7130 }
7131
7132 case kWhatRequestIDRFrame:
7133 {
7134 status_t err = mCodec->requestIDRFrame();
7135 if (err != OK) {
7136 ALOGW("Requesting an IDR frame failed.");
7137 }
7138
7139 handled = true;
7140 break;
7141 }
7142
7143 case kWhatSetParameters:
7144 {
7145 sp<AMessage> params;
7146 CHECK(msg->findMessage("params", ¶ms));
7147
7148 status_t err = mCodec->setParameters(params);
7149
7150 sp<AMessage> reply;
7151 if (msg->findMessage("reply", &reply)) {
7152 reply->setInt32("err", err);
7153 reply->post();
7154 }
7155
7156 handled = true;
7157 break;
7158 }
7159
7160 case ACodec::kWhatSignalEndOfInputStream:
7161 {
7162 mCodec->onSignalEndOfInputStream();
7163 handled = true;
7164 break;
7165 }
7166
7167 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
7168 case kWhatSubmitOutputMetadataBufferIfEOS:
7169 {
7170 if (mCodec->mPortEOS[kPortIndexInput] &&
7171 !mCodec->mPortEOS[kPortIndexOutput]) {
7172 status_t err = mCodec->submitOutputMetadataBuffer();
7173 if (err == OK) {
7174 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
7175 }
7176 }
7177 return true;
7178 }
7179
7180 default:
7181 handled = BaseState::onMessageReceived(msg);
7182 break;
7183 }
7184
7185 return handled;
7186 }
7187
setParameters(const sp<AMessage> & params)7188 status_t ACodec::setParameters(const sp<AMessage> ¶ms) {
7189 int32_t videoBitrate;
7190 if (params->findInt32("video-bitrate", &videoBitrate)) {
7191 OMX_VIDEO_CONFIG_BITRATETYPE configParams;
7192 InitOMXParams(&configParams);
7193 configParams.nPortIndex = kPortIndexOutput;
7194 configParams.nEncodeBitrate = videoBitrate;
7195
7196 status_t err = mOMXNode->setConfig(
7197 OMX_IndexConfigVideoBitrate,
7198 &configParams,
7199 sizeof(configParams));
7200
7201 if (err != OK) {
7202 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
7203 videoBitrate, err);
7204
7205 return err;
7206 }
7207 }
7208
7209 int64_t timeOffsetUs;
7210 if (params->findInt64("time-offset-us", &timeOffsetUs)) {
7211 if (mGraphicBufferSource == NULL) {
7212 ALOGE("[%s] Invalid to set input buffer time offset without surface",
7213 mComponentName.c_str());
7214 return INVALID_OPERATION;
7215 }
7216
7217 status_t err = statusFromBinderStatus(
7218 mGraphicBufferSource->setTimeOffsetUs(timeOffsetUs));
7219
7220 if (err != OK) {
7221 ALOGE("[%s] Unable to set input buffer time offset (err %d)",
7222 mComponentName.c_str(),
7223 err);
7224 return err;
7225 }
7226 }
7227
7228 int64_t skipFramesBeforeUs;
7229 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
7230 if (mGraphicBufferSource == NULL) {
7231 ALOGE("[%s] Invalid to set start time without surface",
7232 mComponentName.c_str());
7233 return INVALID_OPERATION;
7234 }
7235
7236 status_t err = statusFromBinderStatus(
7237 mGraphicBufferSource->setStartTimeUs(skipFramesBeforeUs));
7238
7239 if (err != OK) {
7240 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
7241 return err;
7242 }
7243 }
7244
7245 int32_t dropInputFrames;
7246 if (params->findInt32("drop-input-frames", &dropInputFrames)) {
7247 if (mGraphicBufferSource == NULL) {
7248 ALOGE("[%s] Invalid to set suspend without surface",
7249 mComponentName.c_str());
7250 return INVALID_OPERATION;
7251 }
7252
7253 int64_t suspendStartTimeUs = -1;
7254 (void) params->findInt64("drop-start-time-us", &suspendStartTimeUs);
7255 status_t err = statusFromBinderStatus(
7256 mGraphicBufferSource->setSuspend(dropInputFrames != 0, suspendStartTimeUs));
7257
7258 if (err != OK) {
7259 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
7260 return err;
7261 }
7262 }
7263
7264 int64_t stopTimeUs;
7265 if (params->findInt64("stop-time-us", &stopTimeUs)) {
7266 if (mGraphicBufferSource == NULL) {
7267 ALOGE("[%s] Invalid to set stop time without surface",
7268 mComponentName.c_str());
7269 return INVALID_OPERATION;
7270 }
7271 status_t err = statusFromBinderStatus(
7272 mGraphicBufferSource->setStopTimeUs(stopTimeUs));
7273
7274 if (err != OK) {
7275 ALOGE("Failed to set parameter 'stop-time-us' (err %d)", err);
7276 return err;
7277 }
7278
7279 int64_t stopTimeOffsetUs;
7280 err = statusFromBinderStatus(
7281 mGraphicBufferSource->getStopTimeOffsetUs(&stopTimeOffsetUs));
7282
7283 if (err != OK) {
7284 ALOGE("Failed to get stop time offset (err %d)", err);
7285 return err;
7286 }
7287 mInputFormat->setInt64("android._stop-time-offset-us", stopTimeOffsetUs);
7288 }
7289
7290 int32_t dummy;
7291 if (params->findInt32("request-sync", &dummy)) {
7292 status_t err = requestIDRFrame();
7293
7294 if (err != OK) {
7295 ALOGE("Requesting a sync frame failed w/ err %d", err);
7296 return err;
7297 }
7298 }
7299
7300 float rate;
7301 if (params->findFloat("operating-rate", &rate) && rate > 0) {
7302 status_t err = setOperatingRate(rate, mIsVideo);
7303 if (err != OK) {
7304 ALOGE("Failed to set parameter 'operating-rate' (err %d)", err);
7305 return err;
7306 }
7307 }
7308
7309 int32_t intraRefreshPeriod = 0;
7310 if (params->findInt32("intra-refresh-period", &intraRefreshPeriod)
7311 && intraRefreshPeriod > 0) {
7312 status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false);
7313 if (err != OK) {
7314 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
7315 mComponentName.c_str());
7316 err = OK;
7317 }
7318 }
7319
7320 int32_t latency = 0;
7321 if (params->findInt32("latency", &latency) && latency > 0) {
7322 status_t err = setLatency(latency);
7323 if (err != OK) {
7324 ALOGI("[%s] failed setLatency. Failure is fine since this key is optional",
7325 mComponentName.c_str());
7326 err = OK;
7327 }
7328 }
7329
7330 status_t err = configureTemporalLayers(params, false /* inConfigure */, mOutputFormat);
7331 if (err != OK) {
7332 err = OK; // ignore failure
7333 }
7334
7335 return setVendorParameters(params);
7336 }
7337
7338 // Removes trailing tags matching |tag| from |key| (e.g. a settings name). |minLength| specifies
7339 // the minimum number of characters to keep in |key| (even if it has trailing tags).
7340 // (Used to remove trailing 'value' tags in settings names, e.g. to normalize
7341 // 'vendor.settingsX.value' to 'vendor.settingsX')
removeTrailingTags(char * key,size_t minLength,const char * tag)7342 static void removeTrailingTags(char *key, size_t minLength, const char *tag) {
7343 size_t length = strlen(key);
7344 size_t tagLength = strlen(tag);
7345 while (length > minLength + tagLength
7346 && !strcmp(key + length - tagLength, tag)
7347 && key[length - tagLength - 1] == '.') {
7348 length -= tagLength + 1;
7349 key[length] = '\0';
7350 }
7351 }
7352
7353 /**
7354 * Struct encompassing a vendor extension config structure and a potential error status (in case
7355 * the structure is null). Used to iterate through vendor extensions.
7356 */
7357 struct VendorExtension {
7358 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config; // structure does not own config
7359 status_t status;
7360
7361 // create based on an error status
VendorExtensionandroid::VendorExtension7362 VendorExtension(status_t s_ = NO_INIT) : config(nullptr), status(s_) { }
7363
7364 // create based on a successfully retrieved config structure
VendorExtensionandroid::VendorExtension7365 VendorExtension(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *c_) : config(c_), status(OK) { }
7366 };
7367
7368 // class VendorExtensions;
7369 /**
7370 * Forward iterator to enumerate vendor extensions supported by an OMX component.
7371 */
7372 class VendorExtensionIterator {
7373 //private:
7374 static constexpr size_t kLastIndex = ~(size_t)0; // last index marker
7375
7376 sp<IOMXNode> mNode; // component
7377 size_t mIndex; // current android extension index
7378 std::unique_ptr<uint8_t[]> mBacking; // current extension's backing
7379 VendorExtension mCurrent; // current extension
7380
VendorExtensionIterator(const sp<IOMXNode> & node,size_t index)7381 VendorExtensionIterator(const sp<IOMXNode> &node, size_t index)
7382 : mNode(node),
7383 mIndex(index) {
7384 mCurrent = retrieve();
7385 }
7386
7387 friend class VendorExtensions;
7388
7389 public:
7390 // copy constructor
VendorExtensionIterator(const VendorExtensionIterator & it)7391 VendorExtensionIterator(const VendorExtensionIterator &it)
7392 : VendorExtensionIterator(it.mNode, it.mIndex) { }
7393
7394 // retrieves the current extension pointed to by this iterator
retrieve()7395 VendorExtension retrieve() {
7396 if (mIndex == kLastIndex) {
7397 return NO_INIT;
7398 }
7399
7400 // try with one param first, then retry if extension needs more than 1 param
7401 for (size_t paramSizeUsed = 1;; ) {
7402 if (paramSizeUsed > OMX_MAX_ANDROID_VENDOR_PARAMCOUNT) {
7403 return BAD_VALUE; // this prevents overflow in the following formula
7404 }
7405
7406 size_t size = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) +
7407 (paramSizeUsed - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::param);
7408 mBacking.reset(new uint8_t[size]);
7409 if (!mBacking) {
7410 return NO_MEMORY;
7411 }
7412
7413 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config =
7414 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(mBacking.get());
7415
7416 InitOMXParams(config);
7417 config->nSize = size;
7418 config->nIndex = mIndex;
7419 config->nParamSizeUsed = paramSizeUsed;
7420 status_t err = mNode->getConfig(
7421 (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension, config, size);
7422 if (err == OK && config->nParamCount > paramSizeUsed && paramSizeUsed == 1) {
7423 // reallocate if we need a bigger config
7424 paramSizeUsed = config->nParamCount;
7425 continue;
7426 } else if (err == NOT_ENOUGH_DATA
7427 || (err != OK && mIndex == 0)) {
7428 // stop iterator on no-more signal, or if index is not at all supported
7429 mIndex = kLastIndex;
7430 return NO_INIT;
7431 } else if (err != OK) {
7432 return err;
7433 } else if (paramSizeUsed != config->nParamSizeUsed) {
7434 return BAD_VALUE; // component shall not modify size of nParam
7435 }
7436
7437 return config;
7438 }
7439 }
7440
7441 // returns extension pointed to by this iterator
operator *()7442 VendorExtension operator*() {
7443 return mCurrent;
7444 }
7445
7446 // prefix increment: move to next extension
operator ++()7447 VendorExtensionIterator &operator++() { // prefix
7448 if (mIndex != kLastIndex) {
7449 ++mIndex;
7450 mCurrent = retrieve();
7451 }
7452 return *this;
7453 }
7454
7455 // iterator equality operators
operator ==(const VendorExtensionIterator & o)7456 bool operator==(const VendorExtensionIterator &o) {
7457 return mNode == o.mNode && mIndex == o.mIndex;
7458 }
7459
operator !=(const VendorExtensionIterator & o)7460 bool operator!=(const VendorExtensionIterator &o) {
7461 return !(*this == o);
7462 }
7463 };
7464
7465 /**
7466 * Iterable container for vendor extensions provided by a component
7467 */
7468 class VendorExtensions {
7469 //private:
7470 sp<IOMXNode> mNode;
7471
7472 public:
VendorExtensions(const sp<IOMXNode> & node)7473 VendorExtensions(const sp<IOMXNode> &node)
7474 : mNode(node) {
7475 }
7476
begin()7477 VendorExtensionIterator begin() {
7478 return VendorExtensionIterator(mNode, 0);
7479 }
7480
end()7481 VendorExtensionIterator end() {
7482 return VendorExtensionIterator(mNode, VendorExtensionIterator::kLastIndex);
7483 }
7484 };
7485
setVendorParameters(const sp<AMessage> & params)7486 status_t ACodec::setVendorParameters(const sp<AMessage> ¶ms) {
7487 std::map<std::string, std::string> vendorKeys; // maps reduced name to actual name
7488 constexpr char prefix[] = "vendor.";
7489 constexpr size_t prefixLength = sizeof(prefix) - 1;
7490 // longest possible vendor param name
7491 char reducedKey[OMX_MAX_STRINGNAME_SIZE + OMX_MAX_STRINGVALUE_SIZE];
7492
7493 // identify all vendor keys to speed up search later and to detect vendor keys
7494 for (size_t i = params->countEntries(); i; --i) {
7495 AMessage::Type keyType;
7496 const char* key = params->getEntryNameAt(i - 1, &keyType);
7497 if (key != nullptr && !strncmp(key, prefix, prefixLength)
7498 // it is safe to limit format keys to the max vendor param size as we only
7499 // shorten parameter names by removing any trailing 'value' tags, and we
7500 // already remove the vendor prefix.
7501 && strlen(key + prefixLength) < sizeof(reducedKey)
7502 && (keyType == AMessage::kTypeInt32
7503 || keyType == AMessage::kTypeInt64
7504 || keyType == AMessage::kTypeString)) {
7505 strcpy(reducedKey, key + prefixLength);
7506 removeTrailingTags(reducedKey, 0, "value");
7507 auto existingKey = vendorKeys.find(reducedKey);
7508 if (existingKey != vendorKeys.end()) {
7509 ALOGW("[%s] vendor parameter '%s' aliases parameter '%s'",
7510 mComponentName.c_str(), key, existingKey->second.c_str());
7511 // ignore for now
7512 }
7513 vendorKeys.emplace(reducedKey, key);
7514 }
7515 }
7516
7517 // don't bother component if we don't have vendor extensions as they may not have implemented
7518 // the android vendor extension support, which will lead to unnecessary OMX failure logs.
7519 if (vendorKeys.empty()) {
7520 return OK;
7521 }
7522
7523 char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) +
7524 sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey)];
7525
7526 status_t finalError = OK;
7527
7528 // don't try again if component does not have vendor extensions
7529 if (mVendorExtensionsStatus == kExtensionsNone) {
7530 return OK;
7531 }
7532
7533 for (VendorExtension ext : VendorExtensions(mOMXNode)) {
7534 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config;
7535 if (config == nullptr) {
7536 return ext.status;
7537 }
7538
7539 mVendorExtensionsStatus = kExtensionsExist;
7540
7541 config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name
7542 strcpy(key, (const char *)config->cName);
7543 size_t nameLength = strlen(key);
7544 key[nameLength] = '.';
7545
7546 // don't set vendor extension if client has not provided any of its parameters
7547 // or if client simply unsets parameters that are already unset
7548 bool needToSet = false;
7549 for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) {
7550 // null-terminate param key
7551 config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0';
7552 strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey);
7553 removeTrailingTags(key, nameLength, "value");
7554 auto existingKey = vendorKeys.find(key);
7555
7556 // don't touch (e.g. change) parameters that are not specified by client
7557 if (existingKey == vendorKeys.end()) {
7558 continue;
7559 }
7560
7561 bool wasSet = config->param[paramIndex].bSet;
7562 switch (config->param[paramIndex].eValueType) {
7563 case OMX_AndroidVendorValueInt32:
7564 {
7565 int32_t value;
7566 config->param[paramIndex].bSet =
7567 (OMX_BOOL)params->findInt32(existingKey->second.c_str(), &value);
7568 if (config->param[paramIndex].bSet) {
7569 config->param[paramIndex].nInt32 = value;
7570 }
7571 break;
7572 }
7573 case OMX_AndroidVendorValueInt64:
7574 {
7575 int64_t value;
7576 config->param[paramIndex].bSet =
7577 (OMX_BOOL)params->findAsInt64(existingKey->second.c_str(), &value);
7578 if (config->param[paramIndex].bSet) {
7579 config->param[paramIndex].nInt64 = value;
7580 }
7581 break;
7582 }
7583 case OMX_AndroidVendorValueString:
7584 {
7585 AString value;
7586 config->param[paramIndex].bSet =
7587 (OMX_BOOL)params->findString(existingKey->second.c_str(), &value);
7588 if (config->param[paramIndex].bSet) {
7589 strncpy((char *)config->param[paramIndex].cString, value.c_str(),
7590 sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cString));
7591 }
7592 break;
7593 }
7594 default:
7595 ALOGW("[%s] vendor parameter '%s' is not a supported value",
7596 mComponentName.c_str(), key);
7597 continue;
7598 }
7599 if (config->param[paramIndex].bSet || wasSet) {
7600 needToSet = true;
7601 }
7602 }
7603
7604 if (needToSet) {
7605 status_t err = mOMXNode->setConfig(
7606 (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension,
7607 config, config->nSize);
7608 if (err != OK) {
7609 key[nameLength] = '\0';
7610 ALOGW("[%s] failed to set vendor extension '%s'", mComponentName.c_str(), key);
7611 // try to set each extension, and return first failure
7612 if (finalError == OK) {
7613 finalError = err;
7614 }
7615 }
7616 }
7617 }
7618
7619 if (mVendorExtensionsStatus == kExtensionsUnchecked) {
7620 mVendorExtensionsStatus = kExtensionsNone;
7621 }
7622
7623 return finalError;
7624 }
7625
getVendorParameters(OMX_U32 portIndex,sp<AMessage> & format)7626 status_t ACodec::getVendorParameters(OMX_U32 portIndex, sp<AMessage> &format) {
7627 constexpr char prefix[] = "vendor.";
7628 constexpr size_t prefixLength = sizeof(prefix) - 1;
7629 char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) +
7630 sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey) + prefixLength];
7631 strcpy(key, prefix);
7632
7633 // don't try again if component does not have vendor extensions
7634 if (mVendorExtensionsStatus == kExtensionsNone) {
7635 return OK;
7636 }
7637
7638 for (VendorExtension ext : VendorExtensions(mOMXNode)) {
7639 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config;
7640 if (config == nullptr) {
7641 return ext.status;
7642 }
7643
7644 mVendorExtensionsStatus = kExtensionsExist;
7645
7646 if (config->eDir != (portIndex == kPortIndexInput ? OMX_DirInput : OMX_DirOutput)) {
7647 continue;
7648 }
7649
7650 config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name
7651 strcpy(key + prefixLength, (const char *)config->cName);
7652 size_t nameLength = strlen(key);
7653 key[nameLength] = '.';
7654
7655 for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) {
7656 // null-terminate param key
7657 config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0';
7658 strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey);
7659 removeTrailingTags(key, nameLength, "value");
7660 if (config->param[paramIndex].bSet) {
7661 switch (config->param[paramIndex].eValueType) {
7662 case OMX_AndroidVendorValueInt32:
7663 {
7664 format->setInt32(key, config->param[paramIndex].nInt32);
7665 break;
7666 }
7667 case OMX_AndroidVendorValueInt64:
7668 {
7669 format->setInt64(key, config->param[paramIndex].nInt64);
7670 break;
7671 }
7672 case OMX_AndroidVendorValueString:
7673 {
7674 config->param[paramIndex].cString[OMX_MAX_STRINGVALUE_SIZE - 1] = '\0';
7675 format->setString(key, (const char *)config->param[paramIndex].cString);
7676 break;
7677 }
7678 default:
7679 ALOGW("vendor parameter %s is not a supported value", key);
7680 continue;
7681 }
7682 }
7683 }
7684 }
7685
7686 if (mVendorExtensionsStatus == kExtensionsUnchecked) {
7687 mVendorExtensionsStatus = kExtensionsNone;
7688 }
7689
7690 return OK;
7691 }
7692
onSignalEndOfInputStream()7693 void ACodec::onSignalEndOfInputStream() {
7694 status_t err = INVALID_OPERATION;
7695 if (mGraphicBufferSource != NULL) {
7696 err = statusFromBinderStatus(mGraphicBufferSource->signalEndOfInputStream());
7697 }
7698 mCallback->onSignaledInputEOS(err);
7699 }
7700
forceStateTransition(int generation)7701 void ACodec::forceStateTransition(int generation) {
7702 if (generation != mStateGeneration) {
7703 ALOGV("Ignoring stale force state transition message: #%d (now #%d)",
7704 generation, mStateGeneration);
7705 return;
7706 }
7707 ALOGE("State machine stuck");
7708 // Error must have already been signalled to the client.
7709
7710 // Deferred messages will be handled at LoadedState at the end of the
7711 // transition.
7712 mShutdownInProgress = true;
7713 // No shutdown complete callback at the end of the transition.
7714 mExplicitShutdown = false;
7715 mKeepComponentAllocated = true;
7716
7717 status_t err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
7718 if (err != OK) {
7719 // TODO: do some recovery here.
7720 } else {
7721 changeState(mExecutingToIdleState);
7722 }
7723 }
7724
onOMXFrameRendered(int64_t mediaTimeUs,nsecs_t systemNano)7725 bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
7726 mCodec->onFrameRendered(mediaTimeUs, systemNano);
7727 return true;
7728 }
7729
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)7730 bool ACodec::ExecutingState::onOMXEvent(
7731 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7732 switch (event) {
7733 case OMX_EventPortSettingsChanged:
7734 {
7735 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
7736
7737 mCodec->onOutputFormatChanged();
7738
7739 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
7740 mCodec->mMetadataBuffersToSubmit = 0;
7741 CHECK_EQ(mCodec->mOMXNode->sendCommand(
7742 OMX_CommandPortDisable, kPortIndexOutput),
7743 (status_t)OK);
7744
7745 mCodec->freeOutputBuffersNotOwnedByComponent();
7746
7747 mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
7748 } else if (data2 != OMX_IndexConfigCommonOutputCrop
7749 && data2 != OMX_IndexConfigAndroidIntraRefresh) {
7750 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x",
7751 mCodec->mComponentName.c_str(), data2);
7752 }
7753
7754 return true;
7755 }
7756
7757 case OMX_EventBufferFlag:
7758 {
7759 return true;
7760 }
7761
7762 default:
7763 return BaseState::onOMXEvent(event, data1, data2);
7764 }
7765 }
7766
7767 ////////////////////////////////////////////////////////////////////////////////
7768
OutputPortSettingsChangedState(ACodec * codec)7769 ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
7770 ACodec *codec)
7771 : BaseState(codec) {
7772 }
7773
getPortMode(OMX_U32 portIndex)7774 ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
7775 OMX_U32 portIndex) {
7776 if (portIndex == kPortIndexOutput) {
7777 return FREE_BUFFERS;
7778 }
7779
7780 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
7781
7782 return RESUBMIT_BUFFERS;
7783 }
7784
onMessageReceived(const sp<AMessage> & msg)7785 bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
7786 const sp<AMessage> &msg) {
7787 bool handled = false;
7788
7789 switch (msg->what()) {
7790 case kWhatFlush:
7791 case kWhatShutdown: {
7792 if (mCodec->mFatalError) {
7793 sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec);
7794 msg->setInt32("generation", mCodec->mStateGeneration);
7795 msg->post(3000000);
7796 }
7797 // fall-through
7798 }
7799 case kWhatResume:
7800 case kWhatSetParameters:
7801 {
7802 if (msg->what() == kWhatResume) {
7803 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
7804 }
7805
7806 mCodec->deferMessage(msg);
7807 handled = true;
7808 break;
7809 }
7810
7811 case kWhatForceStateTransition:
7812 {
7813 int32_t generation = 0;
7814 CHECK(msg->findInt32("generation", &generation));
7815 mCodec->forceStateTransition(generation);
7816
7817 handled = true;
7818 break;
7819 }
7820
7821 default:
7822 handled = BaseState::onMessageReceived(msg);
7823 break;
7824 }
7825
7826 return handled;
7827 }
7828
stateEntered()7829 void ACodec::OutputPortSettingsChangedState::stateEntered() {
7830 ALOGV("[%s] Now handling output port settings change",
7831 mCodec->mComponentName.c_str());
7832 }
7833
onOMXFrameRendered(int64_t mediaTimeUs,nsecs_t systemNano)7834 bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered(
7835 int64_t mediaTimeUs, nsecs_t systemNano) {
7836 mCodec->onFrameRendered(mediaTimeUs, systemNano);
7837 return true;
7838 }
7839
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)7840 bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
7841 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7842 switch (event) {
7843 case OMX_EventCmdComplete:
7844 {
7845 if (data1 == (OMX_U32)OMX_CommandPortDisable) {
7846 if (data2 != (OMX_U32)kPortIndexOutput) {
7847 ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2);
7848 return false;
7849 }
7850
7851 ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
7852
7853 status_t err = OK;
7854 if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
7855 ALOGE("disabled port should be empty, but has %zu buffers",
7856 mCodec->mBuffers[kPortIndexOutput].size());
7857 err = FAILED_TRANSACTION;
7858 } else {
7859 if (mCodec->getTrebleFlag()) {
7860 mCodec->mAllocator[kPortIndexOutput].clear();
7861 } else {
7862 mCodec->mDealer[kPortIndexOutput].clear();
7863 }
7864 }
7865
7866 if (err == OK) {
7867 err = mCodec->mOMXNode->sendCommand(
7868 OMX_CommandPortEnable, kPortIndexOutput);
7869 }
7870
7871 if (err == OK) {
7872 err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
7873 ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
7874 "reconfiguration: (%d)", err);
7875 mCodec->mCallback->onOutputBuffersChanged();
7876 }
7877
7878 if (err != OK) {
7879 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
7880 ALOGE("Error occurred while disabling the output port");
7881 }
7882
7883 return true;
7884 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
7885 if (data2 != (OMX_U32)kPortIndexOutput) {
7886 ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2);
7887 return false;
7888 }
7889
7890 ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str());
7891
7892 if (mCodec->mExecutingState->active()) {
7893 mCodec->mExecutingState->submitOutputBuffers();
7894 }
7895
7896 mCodec->changeState(mCodec->mExecutingState);
7897
7898 return true;
7899 }
7900
7901 return false;
7902 }
7903
7904 default:
7905 return BaseState::onOMXEvent(event, data1, data2);
7906 }
7907 }
7908
7909 ////////////////////////////////////////////////////////////////////////////////
7910
ExecutingToIdleState(ACodec * codec)7911 ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
7912 : BaseState(codec),
7913 mComponentNowIdle(false) {
7914 }
7915
onMessageReceived(const sp<AMessage> & msg)7916 bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
7917 bool handled = false;
7918
7919 switch (msg->what()) {
7920 case kWhatFlush:
7921 {
7922 // Don't send me a flush request if you previously wanted me
7923 // to shutdown.
7924 ALOGW("Ignoring flush request in ExecutingToIdleState");
7925 break;
7926 }
7927
7928 case kWhatShutdown:
7929 {
7930 mCodec->deferMessage(msg);
7931 handled = true;
7932 break;
7933 }
7934
7935 default:
7936 handled = BaseState::onMessageReceived(msg);
7937 break;
7938 }
7939
7940 return handled;
7941 }
7942
stateEntered()7943 void ACodec::ExecutingToIdleState::stateEntered() {
7944 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
7945
7946 mComponentNowIdle = false;
7947 mCodec->mLastOutputFormat.clear();
7948 }
7949
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)7950 bool ACodec::ExecutingToIdleState::onOMXEvent(
7951 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7952 switch (event) {
7953 case OMX_EventCmdComplete:
7954 {
7955 if (data1 != (OMX_U32)OMX_CommandStateSet
7956 || data2 != (OMX_U32)OMX_StateIdle) {
7957 ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)",
7958 asString((OMX_COMMANDTYPE)data1), data1,
7959 asString((OMX_STATETYPE)data2), data2);
7960 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7961 return true;
7962 }
7963
7964 mComponentNowIdle = true;
7965
7966 changeStateIfWeOwnAllBuffers();
7967
7968 return true;
7969 }
7970
7971 case OMX_EventPortSettingsChanged:
7972 case OMX_EventBufferFlag:
7973 {
7974 // We're shutting down and don't care about this anymore.
7975 return true;
7976 }
7977
7978 default:
7979 return BaseState::onOMXEvent(event, data1, data2);
7980 }
7981 }
7982
changeStateIfWeOwnAllBuffers()7983 void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
7984 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
7985 status_t err = mCodec->mOMXNode->sendCommand(
7986 OMX_CommandStateSet, OMX_StateLoaded);
7987 if (err == OK) {
7988 err = mCodec->freeBuffersOnPort(kPortIndexInput);
7989 status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
7990 if (err == OK) {
7991 err = err2;
7992 }
7993 }
7994
7995 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
7996 && mCodec->mNativeWindow != NULL) {
7997 // We push enough 1x1 blank buffers to ensure that one of
7998 // them has made it to the display. This allows the OMX
7999 // component teardown to zero out any protected buffers
8000 // without the risk of scanning out one of those buffers.
8001 pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get());
8002 }
8003
8004 if (err != OK) {
8005 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
8006 return;
8007 }
8008
8009 mCodec->changeState(mCodec->mIdleToLoadedState);
8010 }
8011 }
8012
onInputBufferFilled(const sp<AMessage> & msg)8013 void ACodec::ExecutingToIdleState::onInputBufferFilled(
8014 const sp<AMessage> &msg) {
8015 BaseState::onInputBufferFilled(msg);
8016
8017 changeStateIfWeOwnAllBuffers();
8018 }
8019
onOutputBufferDrained(const sp<AMessage> & msg)8020 void ACodec::ExecutingToIdleState::onOutputBufferDrained(
8021 const sp<AMessage> &msg) {
8022 BaseState::onOutputBufferDrained(msg);
8023
8024 changeStateIfWeOwnAllBuffers();
8025 }
8026
8027 ////////////////////////////////////////////////////////////////////////////////
8028
IdleToLoadedState(ACodec * codec)8029 ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
8030 : BaseState(codec) {
8031 }
8032
onMessageReceived(const sp<AMessage> & msg)8033 bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
8034 bool handled = false;
8035
8036 switch (msg->what()) {
8037 case kWhatShutdown:
8038 {
8039 mCodec->deferMessage(msg);
8040 handled = true;
8041 break;
8042 }
8043
8044 case kWhatFlush:
8045 {
8046 // Don't send me a flush request if you previously wanted me
8047 // to shutdown.
8048 ALOGE("Got flush request in IdleToLoadedState");
8049 break;
8050 }
8051
8052 default:
8053 handled = BaseState::onMessageReceived(msg);
8054 break;
8055 }
8056
8057 return handled;
8058 }
8059
stateEntered()8060 void ACodec::IdleToLoadedState::stateEntered() {
8061 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
8062 }
8063
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)8064 bool ACodec::IdleToLoadedState::onOMXEvent(
8065 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
8066 switch (event) {
8067 case OMX_EventCmdComplete:
8068 {
8069 if (data1 != (OMX_U32)OMX_CommandStateSet
8070 || data2 != (OMX_U32)OMX_StateLoaded) {
8071 ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)",
8072 asString((OMX_COMMANDTYPE)data1), data1,
8073 asString((OMX_STATETYPE)data2), data2);
8074 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
8075 return true;
8076 }
8077
8078 mCodec->changeState(mCodec->mLoadedState);
8079
8080 return true;
8081 }
8082
8083 default:
8084 return BaseState::onOMXEvent(event, data1, data2);
8085 }
8086 }
8087
8088 ////////////////////////////////////////////////////////////////////////////////
8089
FlushingState(ACodec * codec)8090 ACodec::FlushingState::FlushingState(ACodec *codec)
8091 : BaseState(codec) {
8092 }
8093
stateEntered()8094 void ACodec::FlushingState::stateEntered() {
8095 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
8096
8097 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
8098 }
8099
onMessageReceived(const sp<AMessage> & msg)8100 bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
8101 bool handled = false;
8102
8103 switch (msg->what()) {
8104 case kWhatShutdown:
8105 {
8106 mCodec->deferMessage(msg);
8107 if (mCodec->mFatalError) {
8108 sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec);
8109 msg->setInt32("generation", mCodec->mStateGeneration);
8110 msg->post(3000000);
8111 }
8112 break;
8113 }
8114
8115 case kWhatFlush:
8116 {
8117 // We're already doing this right now.
8118 handled = true;
8119 break;
8120 }
8121
8122 case kWhatForceStateTransition:
8123 {
8124 int32_t generation = 0;
8125 CHECK(msg->findInt32("generation", &generation));
8126 mCodec->forceStateTransition(generation);
8127
8128 handled = true;
8129 break;
8130 }
8131
8132 default:
8133 handled = BaseState::onMessageReceived(msg);
8134 break;
8135 }
8136
8137 return handled;
8138 }
8139
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)8140 bool ACodec::FlushingState::onOMXEvent(
8141 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
8142 ALOGV("[%s] FlushingState onOMXEvent(%u,%d)",
8143 mCodec->mComponentName.c_str(), event, (OMX_S32)data1);
8144
8145 switch (event) {
8146 case OMX_EventCmdComplete:
8147 {
8148 if (data1 != (OMX_U32)OMX_CommandFlush) {
8149 ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState",
8150 asString((OMX_COMMANDTYPE)data1), data1, data2);
8151 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
8152 return true;
8153 }
8154
8155 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
8156 if (mFlushComplete[data2]) {
8157 ALOGW("Flush already completed for %s port",
8158 data2 == kPortIndexInput ? "input" : "output");
8159 return true;
8160 }
8161 mFlushComplete[data2] = true;
8162
8163 if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) {
8164 changeStateIfWeOwnAllBuffers();
8165 }
8166 } else if (data2 == OMX_ALL) {
8167 if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) {
8168 ALOGW("received flush complete event for OMX_ALL before ports have been"
8169 "flushed (%d/%d)",
8170 mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]);
8171 return false;
8172 }
8173
8174 changeStateIfWeOwnAllBuffers();
8175 } else {
8176 ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2);
8177 }
8178
8179 return true;
8180 }
8181
8182 case OMX_EventPortSettingsChanged:
8183 {
8184 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
8185 msg->setInt32("type", omx_message::EVENT);
8186 msg->setInt32("generation", mCodec->mNodeGeneration);
8187 msg->setInt32("event", event);
8188 msg->setInt32("data1", data1);
8189 msg->setInt32("data2", data2);
8190
8191 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
8192 mCodec->mComponentName.c_str());
8193
8194 mCodec->deferMessage(msg);
8195
8196 return true;
8197 }
8198
8199 default:
8200 return BaseState::onOMXEvent(event, data1, data2);
8201 }
8202
8203 return true;
8204 }
8205
onOutputBufferDrained(const sp<AMessage> & msg)8206 void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
8207 BaseState::onOutputBufferDrained(msg);
8208
8209 changeStateIfWeOwnAllBuffers();
8210 }
8211
onInputBufferFilled(const sp<AMessage> & msg)8212 void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
8213 BaseState::onInputBufferFilled(msg);
8214
8215 changeStateIfWeOwnAllBuffers();
8216 }
8217
changeStateIfWeOwnAllBuffers()8218 void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
8219 if (mFlushComplete[kPortIndexInput]
8220 && mFlushComplete[kPortIndexOutput]
8221 && mCodec->allYourBuffersAreBelongToUs()) {
8222 // We now own all buffers except possibly those still queued with
8223 // the native window for rendering. Let's get those back as well.
8224 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
8225
8226 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
8227
8228 mCodec->mCallback->onFlushCompleted();
8229
8230 mCodec->mPortEOS[kPortIndexInput] =
8231 mCodec->mPortEOS[kPortIndexOutput] = false;
8232
8233 mCodec->mInputEOSResult = OK;
8234
8235 if (mCodec->mSkipCutBuffer != NULL) {
8236 mCodec->mSkipCutBuffer->clear();
8237 }
8238
8239 mCodec->changeState(mCodec->mExecutingState);
8240 }
8241 }
8242
queryCapabilities(const char * owner,const char * name,const char * mime,bool isEncoder,MediaCodecInfo::CapabilitiesWriter * caps)8243 status_t ACodec::queryCapabilities(
8244 const char* owner, const char* name, const char* mime, bool isEncoder,
8245 MediaCodecInfo::CapabilitiesWriter* caps) {
8246 const char *role = GetComponentRole(isEncoder, mime);
8247 if (role == NULL) {
8248 return BAD_VALUE;
8249 }
8250
8251 OMXClient client;
8252 status_t err = client.connect(owner);
8253 if (err != OK) {
8254 return err;
8255 }
8256
8257 sp<IOMX> omx = client.interface();
8258 sp<CodecObserver> observer = new CodecObserver;
8259 sp<IOMXNode> omxNode;
8260
8261 err = omx->allocateNode(name, observer, &omxNode);
8262 if (err != OK) {
8263 client.disconnect();
8264 return err;
8265 }
8266
8267 err = SetComponentRole(omxNode, role);
8268 if (err != OK) {
8269 omxNode->freeNode();
8270 client.disconnect();
8271 return err;
8272 }
8273
8274 bool isVideo = strncasecmp(mime, "video/", 6) == 0;
8275
8276 if (isVideo) {
8277 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
8278 InitOMXParams(¶m);
8279 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
8280
8281 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
8282 param.nProfileIndex = index;
8283 status_t err = omxNode->getParameter(
8284 OMX_IndexParamVideoProfileLevelQuerySupported,
8285 ¶m, sizeof(param));
8286 if (err != OK) {
8287 break;
8288 }
8289 caps->addProfileLevel(param.eProfile, param.eLevel);
8290
8291 // AVC components may not list the constrained profiles explicitly, but
8292 // decoders that support a profile also support its constrained version.
8293 // Encoders must explicitly support constrained profiles.
8294 if (!isEncoder && strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) == 0) {
8295 if (param.eProfile == OMX_VIDEO_AVCProfileHigh) {
8296 caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedHigh, param.eLevel);
8297 } else if (param.eProfile == OMX_VIDEO_AVCProfileBaseline) {
8298 caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedBaseline, param.eLevel);
8299 }
8300 }
8301
8302 if (index == kMaxIndicesToCheck) {
8303 ALOGW("[%s] stopping checking profiles after %u: %x/%x",
8304 name, index,
8305 param.eProfile, param.eLevel);
8306 }
8307 }
8308
8309 // Color format query
8310 // return colors in the order reported by the OMX component
8311 // prefix "flexible" standard ones with the flexible equivalent
8312 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
8313 InitOMXParams(&portFormat);
8314 portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput;
8315 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
8316 portFormat.nIndex = index;
8317 status_t err = omxNode->getParameter(
8318 OMX_IndexParamVideoPortFormat,
8319 &portFormat, sizeof(portFormat));
8320 if (err != OK) {
8321 break;
8322 }
8323
8324 OMX_U32 flexibleEquivalent;
8325 if (IsFlexibleColorFormat(
8326 omxNode, portFormat.eColorFormat, false /* usingNativeWindow */,
8327 &flexibleEquivalent)) {
8328 caps->addColorFormat(flexibleEquivalent);
8329 }
8330 caps->addColorFormat(portFormat.eColorFormat);
8331
8332 if (index == kMaxIndicesToCheck) {
8333 ALOGW("[%s] stopping checking formats after %u: %s(%x)",
8334 name, index,
8335 asString(portFormat.eColorFormat), portFormat.eColorFormat);
8336 }
8337 }
8338 } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC) == 0) {
8339 // More audio codecs if they have profiles.
8340 OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param;
8341 InitOMXParams(¶m);
8342 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
8343 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
8344 param.nProfileIndex = index;
8345 status_t err = omxNode->getParameter(
8346 (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported,
8347 ¶m, sizeof(param));
8348 if (err != OK) {
8349 break;
8350 }
8351 // For audio, level is ignored.
8352 caps->addProfileLevel(param.eProfile, 0 /* level */);
8353
8354 if (index == kMaxIndicesToCheck) {
8355 ALOGW("[%s] stopping checking profiles after %u: %x",
8356 name, index,
8357 param.eProfile);
8358 }
8359 }
8360
8361 // NOTE: Without Android extensions, OMX does not provide a way to query
8362 // AAC profile support
8363 if (param.nProfileIndex == 0) {
8364 ALOGW("component %s doesn't support profile query.", name);
8365 }
8366 }
8367
8368 if (isVideo && !isEncoder) {
8369 native_handle_t *sidebandHandle = NULL;
8370 if (omxNode->configureVideoTunnelMode(
8371 kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
8372 // tunneled playback includes adaptive playback
8373 caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
8374 | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
8375 } else if (omxNode->setPortMode(
8376 kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
8377 omxNode->prepareForAdaptivePlayback(
8378 kPortIndexOutput, OMX_TRUE,
8379 1280 /* width */, 720 /* height */) == OK) {
8380 caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
8381 }
8382 }
8383
8384 if (isVideo && isEncoder) {
8385 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
8386 InitOMXParams(¶ms);
8387 params.nPortIndex = kPortIndexOutput;
8388 // TODO: should we verify if fallback is supported?
8389 if (omxNode->getConfig(
8390 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
8391 ¶ms, sizeof(params)) == OK) {
8392 caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
8393 }
8394 }
8395
8396 omxNode->freeNode();
8397 client.disconnect();
8398 return OK;
8399 }
8400
8401 // These are supposed be equivalent to the logic in
8402 // "audio_channel_out_mask_from_count".
8403 //static
getOMXChannelMapping(size_t numChannels,OMX_AUDIO_CHANNELTYPE map[])8404 status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]) {
8405 switch (numChannels) {
8406 case 1:
8407 map[0] = OMX_AUDIO_ChannelCF;
8408 break;
8409 case 2:
8410 map[0] = OMX_AUDIO_ChannelLF;
8411 map[1] = OMX_AUDIO_ChannelRF;
8412 break;
8413 case 3:
8414 map[0] = OMX_AUDIO_ChannelLF;
8415 map[1] = OMX_AUDIO_ChannelRF;
8416 map[2] = OMX_AUDIO_ChannelCF;
8417 break;
8418 case 4:
8419 map[0] = OMX_AUDIO_ChannelLF;
8420 map[1] = OMX_AUDIO_ChannelRF;
8421 map[2] = OMX_AUDIO_ChannelLR;
8422 map[3] = OMX_AUDIO_ChannelRR;
8423 break;
8424 case 5:
8425 map[0] = OMX_AUDIO_ChannelLF;
8426 map[1] = OMX_AUDIO_ChannelRF;
8427 map[2] = OMX_AUDIO_ChannelCF;
8428 map[3] = OMX_AUDIO_ChannelLR;
8429 map[4] = OMX_AUDIO_ChannelRR;
8430 break;
8431 case 6:
8432 map[0] = OMX_AUDIO_ChannelLF;
8433 map[1] = OMX_AUDIO_ChannelRF;
8434 map[2] = OMX_AUDIO_ChannelCF;
8435 map[3] = OMX_AUDIO_ChannelLFE;
8436 map[4] = OMX_AUDIO_ChannelLR;
8437 map[5] = OMX_AUDIO_ChannelRR;
8438 break;
8439 case 7:
8440 map[0] = OMX_AUDIO_ChannelLF;
8441 map[1] = OMX_AUDIO_ChannelRF;
8442 map[2] = OMX_AUDIO_ChannelCF;
8443 map[3] = OMX_AUDIO_ChannelLFE;
8444 map[4] = OMX_AUDIO_ChannelLR;
8445 map[5] = OMX_AUDIO_ChannelRR;
8446 map[6] = OMX_AUDIO_ChannelCS;
8447 break;
8448 case 8:
8449 map[0] = OMX_AUDIO_ChannelLF;
8450 map[1] = OMX_AUDIO_ChannelRF;
8451 map[2] = OMX_AUDIO_ChannelCF;
8452 map[3] = OMX_AUDIO_ChannelLFE;
8453 map[4] = OMX_AUDIO_ChannelLR;
8454 map[5] = OMX_AUDIO_ChannelRR;
8455 map[6] = OMX_AUDIO_ChannelLS;
8456 map[7] = OMX_AUDIO_ChannelRS;
8457 break;
8458 default:
8459 return -EINVAL;
8460 }
8461
8462 return OK;
8463 }
8464
setTrebleFlag(bool trebleFlag)8465 void ACodec::setTrebleFlag(bool trebleFlag) {
8466 mTrebleFlag = trebleFlag;
8467 }
8468
getTrebleFlag() const8469 bool ACodec::getTrebleFlag() const {
8470 return mTrebleFlag;
8471 }
8472
8473 } // namespace android
8474