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