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