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