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