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