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