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