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