1 /*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "ACodec"
19
20 #ifdef __LP64__
21 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
22 #endif
23
24 #include <inttypes.h>
25 #include <utils/Trace.h>
26
27 #include <gui/Surface.h>
28
29 #include <media/stagefright/ACodec.h>
30
31 #include <binder/MemoryDealer.h>
32
33 #include <media/stagefright/foundation/hexdump.h>
34 #include <media/stagefright/foundation/ABuffer.h>
35 #include <media/stagefright/foundation/ADebug.h>
36 #include <media/stagefright/foundation/AMessage.h>
37 #include <media/stagefright/foundation/AUtils.h>
38
39 #include <media/stagefright/BufferProducerWrapper.h>
40 #include <media/stagefright/MediaCodec.h>
41 #include <media/stagefright/MediaCodecList.h>
42 #include <media/stagefright/MediaDefs.h>
43 #include <media/stagefright/OMXClient.h>
44 #include <media/stagefright/OMXCodec.h>
45 #include <media/stagefright/PersistentSurface.h>
46 #include <media/stagefright/SurfaceUtils.h>
47 #include <media/hardware/HardwareAPI.h>
48
49 #include <OMX_AudioExt.h>
50 #include <OMX_VideoExt.h>
51 #include <OMX_Component.h>
52 #include <OMX_IndexExt.h>
53 #include <OMX_AsString.h>
54
55 #include "include/avc_utils.h"
56
57 namespace android {
58
59 // OMX errors are directly mapped into status_t range if
60 // there is no corresponding MediaError status code.
61 // Use the statusFromOMXError(int32_t omxError) function.
62 //
63 // Currently this is a direct map.
64 // See frameworks/native/include/media/openmax/OMX_Core.h
65 //
66 // Vendor OMX errors from 0x90000000 - 0x9000FFFF
67 // Extension OMX errors from 0x8F000000 - 0x90000000
68 // Standard OMX errors from 0x80001000 - 0x80001024 (0x80001024 current)
69 //
70
71 // returns true if err is a recognized OMX error code.
72 // as OMX error is OMX_S32, this is an int32_t type
isOMXError(int32_t err)73 static inline bool isOMXError(int32_t err) {
74 return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX);
75 }
76
77 // converts an OMX error to a status_t
statusFromOMXError(int32_t omxError)78 static inline status_t statusFromOMXError(int32_t omxError) {
79 switch (omxError) {
80 case OMX_ErrorInvalidComponentName:
81 case OMX_ErrorComponentNotFound:
82 return NAME_NOT_FOUND; // can trigger illegal argument error for provided names.
83 default:
84 return isOMXError(omxError) ? omxError : 0; // no translation required
85 }
86 }
87
88 // checks and converts status_t to a non-side-effect status_t
makeNoSideEffectStatus(status_t err)89 static inline status_t makeNoSideEffectStatus(status_t err) {
90 switch (err) {
91 // the following errors have side effects and may come
92 // from other code modules. Remap for safety reasons.
93 case INVALID_OPERATION:
94 case DEAD_OBJECT:
95 return UNKNOWN_ERROR;
96 default:
97 return err;
98 }
99 }
100
101 template<class T>
InitOMXParams(T * params)102 static void InitOMXParams(T *params) {
103 params->nSize = sizeof(T);
104 params->nVersion.s.nVersionMajor = 1;
105 params->nVersion.s.nVersionMinor = 0;
106 params->nVersion.s.nRevision = 0;
107 params->nVersion.s.nStep = 0;
108 }
109
110 struct MessageList : public RefBase {
MessageListandroid::MessageList111 MessageList() {
112 }
~MessageListandroid::MessageList113 virtual ~MessageList() {
114 }
getListandroid::MessageList115 std::list<sp<AMessage> > &getList() { return mList; }
116 private:
117 std::list<sp<AMessage> > mList;
118
119 DISALLOW_EVIL_CONSTRUCTORS(MessageList);
120 };
121
122 struct CodecObserver : public BnOMXObserver {
CodecObserverandroid::CodecObserver123 CodecObserver() {}
124
setNotificationMessageandroid::CodecObserver125 void setNotificationMessage(const sp<AMessage> &msg) {
126 mNotify = msg;
127 }
128
129 // from IOMXObserver
onMessagesandroid::CodecObserver130 virtual void onMessages(const std::list<omx_message> &messages) {
131 if (messages.empty()) {
132 return;
133 }
134
135 sp<AMessage> notify = mNotify->dup();
136 bool first = true;
137 sp<MessageList> msgList = new MessageList();
138 for (std::list<omx_message>::const_iterator it = messages.cbegin();
139 it != messages.cend(); ++it) {
140 const omx_message &omx_msg = *it;
141 if (first) {
142 notify->setInt32("node", omx_msg.node);
143 first = false;
144 }
145
146 sp<AMessage> msg = new AMessage;
147 msg->setInt32("type", omx_msg.type);
148 switch (omx_msg.type) {
149 case omx_message::EVENT:
150 {
151 msg->setInt32("event", omx_msg.u.event_data.event);
152 msg->setInt32("data1", omx_msg.u.event_data.data1);
153 msg->setInt32("data2", omx_msg.u.event_data.data2);
154 break;
155 }
156
157 case omx_message::EMPTY_BUFFER_DONE:
158 {
159 msg->setInt32("buffer", omx_msg.u.buffer_data.buffer);
160 msg->setInt32("fence_fd", omx_msg.fenceFd);
161 break;
162 }
163
164 case omx_message::FILL_BUFFER_DONE:
165 {
166 msg->setInt32(
167 "buffer", omx_msg.u.extended_buffer_data.buffer);
168 msg->setInt32(
169 "range_offset",
170 omx_msg.u.extended_buffer_data.range_offset);
171 msg->setInt32(
172 "range_length",
173 omx_msg.u.extended_buffer_data.range_length);
174 msg->setInt32(
175 "flags",
176 omx_msg.u.extended_buffer_data.flags);
177 msg->setInt64(
178 "timestamp",
179 omx_msg.u.extended_buffer_data.timestamp);
180 msg->setInt32(
181 "fence_fd", omx_msg.fenceFd);
182 break;
183 }
184
185 case omx_message::FRAME_RENDERED:
186 {
187 msg->setInt64(
188 "media_time_us", omx_msg.u.render_data.timestamp);
189 msg->setInt64(
190 "system_nano", omx_msg.u.render_data.nanoTime);
191 break;
192 }
193
194 default:
195 ALOGE("Unrecognized message type: %d", omx_msg.type);
196 break;
197 }
198 msgList->getList().push_back(msg);
199 }
200 notify->setObject("messages", msgList);
201 notify->post();
202 }
203
204 protected:
~CodecObserverandroid::CodecObserver205 virtual ~CodecObserver() {}
206
207 private:
208 sp<AMessage> mNotify;
209
210 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
211 };
212
213 ////////////////////////////////////////////////////////////////////////////////
214
215 struct ACodec::BaseState : public AState {
216 BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
217
218 protected:
219 enum PortMode {
220 KEEP_BUFFERS,
221 RESUBMIT_BUFFERS,
222 FREE_BUFFERS,
223 };
224
225 ACodec *mCodec;
226
227 virtual PortMode getPortMode(OMX_U32 portIndex);
228
229 virtual bool onMessageReceived(const sp<AMessage> &msg);
230
231 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
232
233 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
234 virtual void onInputBufferFilled(const sp<AMessage> &msg);
235
236 void postFillThisBuffer(BufferInfo *info);
237
238 private:
239 // Handles an OMX message. Returns true iff message was handled.
240 bool onOMXMessage(const sp<AMessage> &msg);
241
242 // Handles a list of messages. Returns true iff messages were handled.
243 bool onOMXMessageList(const sp<AMessage> &msg);
244
245 // returns true iff this message is for this component and the component is alive
246 bool checkOMXMessage(const sp<AMessage> &msg);
247
248 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd);
249
250 bool onOMXFillBufferDone(
251 IOMX::buffer_id bufferID,
252 size_t rangeOffset, size_t rangeLength,
253 OMX_U32 flags,
254 int64_t timeUs,
255 int fenceFd);
256
257 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
258
259 void getMoreInputDataIfPossible();
260
261 DISALLOW_EVIL_CONSTRUCTORS(BaseState);
262 };
263
264 ////////////////////////////////////////////////////////////////////////////////
265
266 struct ACodec::DeathNotifier : public IBinder::DeathRecipient {
DeathNotifierandroid::ACodec::DeathNotifier267 DeathNotifier(const sp<AMessage> ¬ify)
268 : mNotify(notify) {
269 }
270
binderDiedandroid::ACodec::DeathNotifier271 virtual void binderDied(const wp<IBinder> &) {
272 mNotify->post();
273 }
274
275 protected:
~DeathNotifierandroid::ACodec::DeathNotifier276 virtual ~DeathNotifier() {}
277
278 private:
279 sp<AMessage> mNotify;
280
281 DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
282 };
283
284 struct ACodec::UninitializedState : public ACodec::BaseState {
285 UninitializedState(ACodec *codec);
286
287 protected:
288 virtual bool onMessageReceived(const sp<AMessage> &msg);
289 virtual void stateEntered();
290
291 private:
292 void onSetup(const sp<AMessage> &msg);
293 bool onAllocateComponent(const sp<AMessage> &msg);
294
295 sp<DeathNotifier> mDeathNotifier;
296
297 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
298 };
299
300 ////////////////////////////////////////////////////////////////////////////////
301
302 struct ACodec::LoadedState : public ACodec::BaseState {
303 LoadedState(ACodec *codec);
304
305 protected:
306 virtual bool onMessageReceived(const sp<AMessage> &msg);
307 virtual void stateEntered();
308
309 private:
310 friend struct ACodec::UninitializedState;
311
312 bool onConfigureComponent(const sp<AMessage> &msg);
313 void onCreateInputSurface(const sp<AMessage> &msg);
314 void onSetInputSurface(const sp<AMessage> &msg);
315 void onStart();
316 void onShutdown(bool keepComponentAllocated);
317
318 status_t setupInputSurface();
319
320 DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
321 };
322
323 ////////////////////////////////////////////////////////////////////////////////
324
325 struct ACodec::LoadedToIdleState : public ACodec::BaseState {
326 LoadedToIdleState(ACodec *codec);
327
328 protected:
329 virtual bool onMessageReceived(const sp<AMessage> &msg);
330 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
331 virtual void stateEntered();
332
333 private:
334 status_t allocateBuffers();
335
336 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
337 };
338
339 ////////////////////////////////////////////////////////////////////////////////
340
341 struct ACodec::IdleToExecutingState : public ACodec::BaseState {
342 IdleToExecutingState(ACodec *codec);
343
344 protected:
345 virtual bool onMessageReceived(const sp<AMessage> &msg);
346 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
347 virtual void stateEntered();
348
349 private:
350 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
351 };
352
353 ////////////////////////////////////////////////////////////////////////////////
354
355 struct ACodec::ExecutingState : public ACodec::BaseState {
356 ExecutingState(ACodec *codec);
357
358 void submitRegularOutputBuffers();
359 void submitOutputMetaBuffers();
360 void submitOutputBuffers();
361
362 // Submit output buffers to the decoder, submit input buffers to client
363 // to fill with data.
364 void resume();
365
366 // Returns true iff input and output buffers are in play.
activeandroid::ACodec::ExecutingState367 bool active() const { return mActive; }
368
369 protected:
370 virtual PortMode getPortMode(OMX_U32 portIndex);
371 virtual bool onMessageReceived(const sp<AMessage> &msg);
372 virtual void stateEntered();
373
374 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
375 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
376
377 private:
378 bool mActive;
379
380 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
381 };
382
383 ////////////////////////////////////////////////////////////////////////////////
384
385 struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
386 OutputPortSettingsChangedState(ACodec *codec);
387
388 protected:
389 virtual PortMode getPortMode(OMX_U32 portIndex);
390 virtual bool onMessageReceived(const sp<AMessage> &msg);
391 virtual void stateEntered();
392
393 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
394 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
395
396 private:
397 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
398 };
399
400 ////////////////////////////////////////////////////////////////////////////////
401
402 struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
403 ExecutingToIdleState(ACodec *codec);
404
405 protected:
406 virtual bool onMessageReceived(const sp<AMessage> &msg);
407 virtual void stateEntered();
408
409 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
410
411 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
412 virtual void onInputBufferFilled(const sp<AMessage> &msg);
413
414 private:
415 void changeStateIfWeOwnAllBuffers();
416
417 bool mComponentNowIdle;
418
419 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
420 };
421
422 ////////////////////////////////////////////////////////////////////////////////
423
424 struct ACodec::IdleToLoadedState : public ACodec::BaseState {
425 IdleToLoadedState(ACodec *codec);
426
427 protected:
428 virtual bool onMessageReceived(const sp<AMessage> &msg);
429 virtual void stateEntered();
430
431 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
432
433 private:
434 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
435 };
436
437 ////////////////////////////////////////////////////////////////////////////////
438
439 struct ACodec::FlushingState : public ACodec::BaseState {
440 FlushingState(ACodec *codec);
441
442 protected:
443 virtual bool onMessageReceived(const sp<AMessage> &msg);
444 virtual void stateEntered();
445
446 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
447
448 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
449 virtual void onInputBufferFilled(const sp<AMessage> &msg);
450
451 private:
452 bool mFlushComplete[2];
453
454 void changeStateIfWeOwnAllBuffers();
455
456 DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
457 };
458
459 ////////////////////////////////////////////////////////////////////////////////
460
setWriteFence(int fenceFd,const char * dbg)461 void ACodec::BufferInfo::setWriteFence(int fenceFd, const char *dbg) {
462 if (mFenceFd >= 0) {
463 ALOGW("OVERWRITE OF %s fence %d by write fence %d in %s",
464 mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
465 }
466 mFenceFd = fenceFd;
467 mIsReadFence = false;
468 }
469
setReadFence(int fenceFd,const char * dbg)470 void ACodec::BufferInfo::setReadFence(int fenceFd, const char *dbg) {
471 if (mFenceFd >= 0) {
472 ALOGW("OVERWRITE OF %s fence %d by read fence %d in %s",
473 mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
474 }
475 mFenceFd = fenceFd;
476 mIsReadFence = true;
477 }
478
checkWriteFence(const char * dbg)479 void ACodec::BufferInfo::checkWriteFence(const char *dbg) {
480 if (mFenceFd >= 0 && mIsReadFence) {
481 ALOGD("REUSING read fence %d as write fence in %s", mFenceFd, dbg);
482 }
483 }
484
checkReadFence(const char * dbg)485 void ACodec::BufferInfo::checkReadFence(const char *dbg) {
486 if (mFenceFd >= 0 && !mIsReadFence) {
487 ALOGD("REUSING write fence %d as read fence in %s", mFenceFd, dbg);
488 }
489 }
490
491 ////////////////////////////////////////////////////////////////////////////////
492
ACodec()493 ACodec::ACodec()
494 : mQuirks(0),
495 mNode(0),
496 mNativeWindowUsageBits(0),
497 mSentFormat(false),
498 mIsVideo(false),
499 mIsEncoder(false),
500 mFatalError(false),
501 mShutdownInProgress(false),
502 mExplicitShutdown(false),
503 mEncoderDelay(0),
504 mEncoderPadding(0),
505 mRotationDegrees(0),
506 mChannelMaskPresent(false),
507 mChannelMask(0),
508 mDequeueCounter(0),
509 mInputMetadataType(kMetadataBufferTypeInvalid),
510 mOutputMetadataType(kMetadataBufferTypeInvalid),
511 mLegacyAdaptiveExperiment(false),
512 mMetadataBuffersToSubmit(0),
513 mRepeatFrameDelayUs(-1ll),
514 mMaxPtsGapUs(-1ll),
515 mMaxFps(-1),
516 mTimePerFrameUs(-1ll),
517 mTimePerCaptureUs(-1ll),
518 mCreateInputBuffersSuspended(false),
519 mTunneled(false) {
520 mUninitializedState = new UninitializedState(this);
521 mLoadedState = new LoadedState(this);
522 mLoadedToIdleState = new LoadedToIdleState(this);
523 mIdleToExecutingState = new IdleToExecutingState(this);
524 mExecutingState = new ExecutingState(this);
525
526 mOutputPortSettingsChangedState =
527 new OutputPortSettingsChangedState(this);
528
529 mExecutingToIdleState = new ExecutingToIdleState(this);
530 mIdleToLoadedState = new IdleToLoadedState(this);
531 mFlushingState = new FlushingState(this);
532
533 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
534 mInputEOSResult = OK;
535
536 changeState(mUninitializedState);
537 }
538
~ACodec()539 ACodec::~ACodec() {
540 }
541
setNotificationMessage(const sp<AMessage> & msg)542 void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
543 mNotify = msg;
544 }
545
initiateSetup(const sp<AMessage> & msg)546 void ACodec::initiateSetup(const sp<AMessage> &msg) {
547 msg->setWhat(kWhatSetup);
548 msg->setTarget(this);
549 msg->post();
550 }
551
signalSetParameters(const sp<AMessage> & params)552 void ACodec::signalSetParameters(const sp<AMessage> ¶ms) {
553 sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
554 msg->setMessage("params", params);
555 msg->post();
556 }
557
initiateAllocateComponent(const sp<AMessage> & msg)558 void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
559 msg->setWhat(kWhatAllocateComponent);
560 msg->setTarget(this);
561 msg->post();
562 }
563
initiateConfigureComponent(const sp<AMessage> & msg)564 void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
565 msg->setWhat(kWhatConfigureComponent);
566 msg->setTarget(this);
567 msg->post();
568 }
569
setSurface(const sp<Surface> & surface)570 status_t ACodec::setSurface(const sp<Surface> &surface) {
571 sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
572 msg->setObject("surface", surface);
573
574 sp<AMessage> response;
575 status_t err = msg->postAndAwaitResponse(&response);
576
577 if (err == OK) {
578 (void)response->findInt32("err", &err);
579 }
580 return err;
581 }
582
initiateCreateInputSurface()583 void ACodec::initiateCreateInputSurface() {
584 (new AMessage(kWhatCreateInputSurface, this))->post();
585 }
586
initiateSetInputSurface(const sp<PersistentSurface> & surface)587 void ACodec::initiateSetInputSurface(
588 const sp<PersistentSurface> &surface) {
589 sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
590 msg->setObject("input-surface", surface);
591 msg->post();
592 }
593
signalEndOfInputStream()594 void ACodec::signalEndOfInputStream() {
595 (new AMessage(kWhatSignalEndOfInputStream, this))->post();
596 }
597
initiateStart()598 void ACodec::initiateStart() {
599 (new AMessage(kWhatStart, this))->post();
600 }
601
signalFlush()602 void ACodec::signalFlush() {
603 ALOGV("[%s] signalFlush", mComponentName.c_str());
604 (new AMessage(kWhatFlush, this))->post();
605 }
606
signalResume()607 void ACodec::signalResume() {
608 (new AMessage(kWhatResume, this))->post();
609 }
610
initiateShutdown(bool keepComponentAllocated)611 void ACodec::initiateShutdown(bool keepComponentAllocated) {
612 sp<AMessage> msg = new AMessage(kWhatShutdown, this);
613 msg->setInt32("keepComponentAllocated", keepComponentAllocated);
614 msg->post();
615 if (!keepComponentAllocated) {
616 // ensure shutdown completes in 3 seconds
617 (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000);
618 }
619 }
620
signalRequestIDRFrame()621 void ACodec::signalRequestIDRFrame() {
622 (new AMessage(kWhatRequestIDRFrame, this))->post();
623 }
624
625 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
626 // Some codecs may return input buffers before having them processed.
627 // This causes a halt if we already signaled an EOS on the input
628 // port. For now keep submitting an output buffer if there was an
629 // EOS on the input port, but not yet on the output port.
signalSubmitOutputMetadataBufferIfEOS_workaround()630 void ACodec::signalSubmitOutputMetadataBufferIfEOS_workaround() {
631 if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
632 mMetadataBuffersToSubmit > 0) {
633 (new AMessage(kWhatSubmitOutputMetadataBufferIfEOS, this))->post();
634 }
635 }
636
handleSetSurface(const sp<Surface> & surface)637 status_t ACodec::handleSetSurface(const sp<Surface> &surface) {
638 // allow keeping unset surface
639 if (surface == NULL) {
640 if (mNativeWindow != NULL) {
641 ALOGW("cannot unset a surface");
642 return INVALID_OPERATION;
643 }
644 return OK;
645 }
646
647 // cannot switch from bytebuffers to surface
648 if (mNativeWindow == NULL) {
649 ALOGW("component was not configured with a surface");
650 return INVALID_OPERATION;
651 }
652
653 ANativeWindow *nativeWindow = surface.get();
654 // if we have not yet started the codec, we can simply set the native window
655 if (mBuffers[kPortIndexInput].size() == 0) {
656 mNativeWindow = surface;
657 return OK;
658 }
659
660 // we do not support changing a tunneled surface after start
661 if (mTunneled) {
662 ALOGW("cannot change tunneled surface");
663 return INVALID_OPERATION;
664 }
665
666 int usageBits = 0;
667 status_t err = setupNativeWindowSizeFormatAndUsage(nativeWindow, &usageBits);
668 if (err != OK) {
669 return err;
670 }
671
672 int ignoredFlags = kVideoGrallocUsage;
673 // New output surface is not allowed to add new usage flag except ignored ones.
674 if ((usageBits & ~(mNativeWindowUsageBits | ignoredFlags)) != 0) {
675 ALOGW("cannot change usage from %#x to %#x", mNativeWindowUsageBits, usageBits);
676 return BAD_VALUE;
677 }
678
679 // get min undequeued count. We cannot switch to a surface that has a higher
680 // undequeued count than we allocated.
681 int minUndequeuedBuffers = 0;
682 err = nativeWindow->query(
683 nativeWindow, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
684 &minUndequeuedBuffers);
685 if (err != 0) {
686 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
687 strerror(-err), -err);
688 return err;
689 }
690 if (minUndequeuedBuffers > (int)mNumUndequeuedBuffers) {
691 ALOGE("new surface holds onto more buffers (%d) than planned for (%zu)",
692 minUndequeuedBuffers, mNumUndequeuedBuffers);
693 return BAD_VALUE;
694 }
695
696 // we cannot change the number of output buffers while OMX is running
697 // set up surface to the same count
698 Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput];
699 ALOGV("setting up surface for %zu buffers", buffers.size());
700
701 err = native_window_set_buffer_count(nativeWindow, buffers.size());
702 if (err != 0) {
703 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
704 -err);
705 return err;
706 }
707
708 // need to enable allocation when attaching
709 surface->getIGraphicBufferProducer()->allowAllocation(true);
710
711 // for meta data mode, we move dequeud buffers to the new surface.
712 // for non-meta mode, we must move all registered buffers
713 for (size_t i = 0; i < buffers.size(); ++i) {
714 const BufferInfo &info = buffers[i];
715 // skip undequeued buffers for meta data mode
716 if (storingMetadataInDecodedBuffers()
717 && !mLegacyAdaptiveExperiment
718 && info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
719 ALOGV("skipping buffer %p", info.mGraphicBuffer->getNativeBuffer());
720 continue;
721 }
722 ALOGV("attaching buffer %p", info.mGraphicBuffer->getNativeBuffer());
723
724 err = surface->attachBuffer(info.mGraphicBuffer->getNativeBuffer());
725 if (err != OK) {
726 ALOGE("failed to attach buffer %p to the new surface: %s (%d)",
727 info.mGraphicBuffer->getNativeBuffer(),
728 strerror(-err), -err);
729 return err;
730 }
731 }
732
733 // cancel undequeued buffers to new surface
734 if (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment) {
735 for (size_t i = 0; i < buffers.size(); ++i) {
736 BufferInfo &info = buffers.editItemAt(i);
737 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
738 ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer());
739 err = nativeWindow->cancelBuffer(
740 nativeWindow, info.mGraphicBuffer->getNativeBuffer(), info.mFenceFd);
741 info.mFenceFd = -1;
742 if (err != OK) {
743 ALOGE("failed to cancel buffer %p to the new surface: %s (%d)",
744 info.mGraphicBuffer->getNativeBuffer(),
745 strerror(-err), -err);
746 return err;
747 }
748 }
749 }
750 // disallow further allocation
751 (void)surface->getIGraphicBufferProducer()->allowAllocation(false);
752 }
753
754 // push blank buffers to previous window if requested
755 if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) {
756 pushBlankBuffersToNativeWindow(mNativeWindow.get());
757 }
758
759 mNativeWindow = nativeWindow;
760 mNativeWindowUsageBits = usageBits;
761 return OK;
762 }
763
allocateBuffersOnPort(OMX_U32 portIndex)764 status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
765 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
766
767 CHECK(mDealer[portIndex] == NULL);
768 CHECK(mBuffers[portIndex].isEmpty());
769
770 status_t err;
771 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
772 if (storingMetadataInDecodedBuffers()) {
773 err = allocateOutputMetadataBuffers();
774 } else {
775 err = allocateOutputBuffersFromNativeWindow();
776 }
777 } else {
778 OMX_PARAM_PORTDEFINITIONTYPE def;
779 InitOMXParams(&def);
780 def.nPortIndex = portIndex;
781
782 err = mOMX->getParameter(
783 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
784
785 if (err == OK) {
786 MetadataBufferType type =
787 portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType;
788 int32_t bufSize = def.nBufferSize;
789 if (type == kMetadataBufferTypeGrallocSource) {
790 bufSize = sizeof(VideoGrallocMetadata);
791 } else if (type == kMetadataBufferTypeANWBuffer) {
792 bufSize = sizeof(VideoNativeMetadata);
793 }
794
795 // If using gralloc or native source input metadata buffers, allocate largest
796 // metadata size as we prefer to generate native source metadata, but component
797 // may require gralloc source. For camera source, allocate at least enough
798 // size for native metadata buffers.
799 int32_t allottedSize = bufSize;
800 if (portIndex == kPortIndexInput && type >= kMetadataBufferTypeGrallocSource) {
801 bufSize = max(sizeof(VideoGrallocMetadata), sizeof(VideoNativeMetadata));
802 } else if (portIndex == kPortIndexInput && type == kMetadataBufferTypeCameraSource) {
803 bufSize = max(bufSize, (int32_t)sizeof(VideoNativeMetadata));
804 }
805
806 ALOGV("[%s] Allocating %u buffers of size %d/%d (from %u using %s) on %s port",
807 mComponentName.c_str(),
808 def.nBufferCountActual, bufSize, allottedSize, def.nBufferSize, asString(type),
809 portIndex == kPortIndexInput ? "input" : "output");
810
811 size_t totalSize = def.nBufferCountActual * bufSize;
812 mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
813
814 for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
815 sp<IMemory> mem = mDealer[portIndex]->allocate(bufSize);
816 if (mem == NULL || mem->pointer() == NULL) {
817 return NO_MEMORY;
818 }
819
820 BufferInfo info;
821 info.mStatus = BufferInfo::OWNED_BY_US;
822 info.mFenceFd = -1;
823 info.mRenderInfo = NULL;
824
825 uint32_t requiresAllocateBufferBit =
826 (portIndex == kPortIndexInput)
827 ? OMXCodec::kRequiresAllocateBufferOnInputPorts
828 : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
829
830 if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
831 || (portIndex == kPortIndexOutput && usingMetadataOnEncoderOutput())) {
832 mem.clear();
833
834 void *ptr;
835 err = mOMX->allocateBuffer(
836 mNode, portIndex, bufSize, &info.mBufferID,
837 &ptr);
838
839 info.mData = new ABuffer(ptr, bufSize);
840 } else if (mQuirks & requiresAllocateBufferBit) {
841 err = mOMX->allocateBufferWithBackup(
842 mNode, portIndex, mem, &info.mBufferID, allottedSize);
843 } else {
844 err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID, allottedSize);
845 }
846
847 if (mem != NULL) {
848 info.mData = new ABuffer(mem->pointer(), bufSize);
849 if (type == kMetadataBufferTypeANWBuffer) {
850 ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
851 }
852 }
853
854 mBuffers[portIndex].push(info);
855 }
856 }
857 }
858
859 if (err != OK) {
860 return err;
861 }
862
863 sp<AMessage> notify = mNotify->dup();
864 notify->setInt32("what", CodecBase::kWhatBuffersAllocated);
865
866 notify->setInt32("portIndex", portIndex);
867
868 sp<PortDescription> desc = new PortDescription;
869
870 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
871 const BufferInfo &info = mBuffers[portIndex][i];
872
873 desc->addBuffer(info.mBufferID, info.mData);
874 }
875
876 notify->setObject("portDesc", desc);
877 notify->post();
878
879 return OK;
880 }
881
setupNativeWindowSizeFormatAndUsage(ANativeWindow * nativeWindow,int * finalUsage)882 status_t ACodec::setupNativeWindowSizeFormatAndUsage(
883 ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */) {
884 OMX_PARAM_PORTDEFINITIONTYPE def;
885 InitOMXParams(&def);
886 def.nPortIndex = kPortIndexOutput;
887
888 status_t err = mOMX->getParameter(
889 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
890
891 if (err != OK) {
892 return err;
893 }
894
895 OMX_U32 usage = 0;
896 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
897 if (err != 0) {
898 ALOGW("querying usage flags from OMX IL component failed: %d", err);
899 // XXX: Currently this error is logged, but not fatal.
900 usage = 0;
901 }
902 int omxUsage = usage;
903
904 if (mFlags & kFlagIsGrallocUsageProtected) {
905 usage |= GRALLOC_USAGE_PROTECTED;
906 }
907
908 usage |= kVideoGrallocUsage;
909 *finalUsage = usage;
910
911 ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage);
912 return setNativeWindowSizeFormatAndUsage(
913 nativeWindow,
914 def.format.video.nFrameWidth,
915 def.format.video.nFrameHeight,
916 def.format.video.eColorFormat,
917 mRotationDegrees,
918 usage);
919 }
920
configureOutputBuffersFromNativeWindow(OMX_U32 * bufferCount,OMX_U32 * bufferSize,OMX_U32 * minUndequeuedBuffers)921 status_t ACodec::configureOutputBuffersFromNativeWindow(
922 OMX_U32 *bufferCount, OMX_U32 *bufferSize,
923 OMX_U32 *minUndequeuedBuffers) {
924 OMX_PARAM_PORTDEFINITIONTYPE def;
925 InitOMXParams(&def);
926 def.nPortIndex = kPortIndexOutput;
927
928 status_t err = mOMX->getParameter(
929 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
930
931 if (err == OK) {
932 err = setupNativeWindowSizeFormatAndUsage(mNativeWindow.get(), &mNativeWindowUsageBits);
933 }
934 if (err != OK) {
935 mNativeWindowUsageBits = 0;
936 return err;
937 }
938
939 // Exits here for tunneled video playback codecs -- i.e. skips native window
940 // buffer allocation step as this is managed by the tunneled OMX omponent
941 // itself and explicitly sets def.nBufferCountActual to 0.
942 if (mTunneled) {
943 ALOGV("Tunneled Playback: skipping native window buffer allocation.");
944 def.nBufferCountActual = 0;
945 err = mOMX->setParameter(
946 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
947
948 *minUndequeuedBuffers = 0;
949 *bufferCount = 0;
950 *bufferSize = 0;
951 return err;
952 }
953
954 *minUndequeuedBuffers = 0;
955 err = mNativeWindow->query(
956 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
957 (int *)minUndequeuedBuffers);
958
959 if (err != 0) {
960 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
961 strerror(-err), -err);
962 return err;
963 }
964
965 // FIXME: assume that surface is controlled by app (native window
966 // returns the number for the case when surface is not controlled by app)
967 // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
968 // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
969
970 // Use conservative allocation while also trying to reduce starvation
971 //
972 // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
973 // minimum needed for the consumer to be able to work
974 // 2. try to allocate two (2) additional buffers to reduce starvation from
975 // the consumer
976 // plus an extra buffer to account for incorrect minUndequeuedBufs
977 for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
978 OMX_U32 newBufferCount =
979 def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
980 def.nBufferCountActual = newBufferCount;
981 err = mOMX->setParameter(
982 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
983
984 if (err == OK) {
985 *minUndequeuedBuffers += extraBuffers;
986 break;
987 }
988
989 ALOGW("[%s] setting nBufferCountActual to %u failed: %d",
990 mComponentName.c_str(), newBufferCount, err);
991 /* exit condition */
992 if (extraBuffers == 0) {
993 return err;
994 }
995 }
996
997 err = native_window_set_buffer_count(
998 mNativeWindow.get(), def.nBufferCountActual);
999
1000 if (err != 0) {
1001 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
1002 -err);
1003 return err;
1004 }
1005
1006 *bufferCount = def.nBufferCountActual;
1007 *bufferSize = def.nBufferSize;
1008 return err;
1009 }
1010
allocateOutputBuffersFromNativeWindow()1011 status_t ACodec::allocateOutputBuffersFromNativeWindow() {
1012 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
1013 status_t err = configureOutputBuffersFromNativeWindow(
1014 &bufferCount, &bufferSize, &minUndequeuedBuffers);
1015 if (err != 0)
1016 return err;
1017 mNumUndequeuedBuffers = minUndequeuedBuffers;
1018
1019 if (!storingMetadataInDecodedBuffers()) {
1020 static_cast<Surface*>(mNativeWindow.get())
1021 ->getIGraphicBufferProducer()->allowAllocation(true);
1022 }
1023
1024 ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
1025 "output port",
1026 mComponentName.c_str(), bufferCount, bufferSize);
1027
1028 // Dequeue buffers and send them to OMX
1029 for (OMX_U32 i = 0; i < bufferCount; i++) {
1030 ANativeWindowBuffer *buf;
1031 int fenceFd;
1032 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1033 if (err != 0) {
1034 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1035 break;
1036 }
1037
1038 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
1039 BufferInfo info;
1040 info.mStatus = BufferInfo::OWNED_BY_US;
1041 info.mFenceFd = fenceFd;
1042 info.mIsReadFence = false;
1043 info.mRenderInfo = NULL;
1044 info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */);
1045 info.mGraphicBuffer = graphicBuffer;
1046 mBuffers[kPortIndexOutput].push(info);
1047
1048 IOMX::buffer_id bufferId;
1049 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
1050 &bufferId);
1051 if (err != 0) {
1052 ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
1053 "%d", i, err);
1054 break;
1055 }
1056
1057 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
1058
1059 ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
1060 mComponentName.c_str(),
1061 bufferId, graphicBuffer.get());
1062 }
1063
1064 OMX_U32 cancelStart;
1065 OMX_U32 cancelEnd;
1066
1067 if (err != 0) {
1068 // If an error occurred while dequeuing we need to cancel any buffers
1069 // that were dequeued.
1070 cancelStart = 0;
1071 cancelEnd = mBuffers[kPortIndexOutput].size();
1072 } else {
1073 // Return the required minimum undequeued buffers to the native window.
1074 cancelStart = bufferCount - minUndequeuedBuffers;
1075 cancelEnd = bufferCount;
1076 }
1077
1078 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
1079 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1080 if (info->mStatus == BufferInfo::OWNED_BY_US) {
1081 status_t error = cancelBufferToNativeWindow(info);
1082 if (err == 0) {
1083 err = error;
1084 }
1085 }
1086 }
1087
1088 if (!storingMetadataInDecodedBuffers()) {
1089 static_cast<Surface*>(mNativeWindow.get())
1090 ->getIGraphicBufferProducer()->allowAllocation(false);
1091 }
1092
1093 return err;
1094 }
1095
allocateOutputMetadataBuffers()1096 status_t ACodec::allocateOutputMetadataBuffers() {
1097 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
1098 status_t err = configureOutputBuffersFromNativeWindow(
1099 &bufferCount, &bufferSize, &minUndequeuedBuffers);
1100 if (err != 0)
1101 return err;
1102 mNumUndequeuedBuffers = minUndequeuedBuffers;
1103
1104 ALOGV("[%s] Allocating %u meta buffers on output port",
1105 mComponentName.c_str(), bufferCount);
1106
1107 size_t bufSize = mOutputMetadataType == kMetadataBufferTypeANWBuffer ?
1108 sizeof(struct VideoNativeMetadata) : sizeof(struct VideoGrallocMetadata);
1109 size_t totalSize = bufferCount * bufSize;
1110 mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec");
1111
1112 // Dequeue buffers and send them to OMX
1113 for (OMX_U32 i = 0; i < bufferCount; i++) {
1114 BufferInfo info;
1115 info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1116 info.mFenceFd = -1;
1117 info.mRenderInfo = NULL;
1118 info.mGraphicBuffer = NULL;
1119 info.mDequeuedAt = mDequeueCounter;
1120
1121 sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(bufSize);
1122 if (mem == NULL || mem->pointer() == NULL) {
1123 return NO_MEMORY;
1124 }
1125 if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
1126 ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
1127 }
1128 info.mData = new ABuffer(mem->pointer(), mem->size());
1129
1130 // we use useBuffer for metadata regardless of quirks
1131 err = mOMX->useBuffer(
1132 mNode, kPortIndexOutput, mem, &info.mBufferID, mem->size());
1133
1134 mBuffers[kPortIndexOutput].push(info);
1135
1136 ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)",
1137 mComponentName.c_str(), info.mBufferID, mem->pointer());
1138 }
1139
1140 if (mLegacyAdaptiveExperiment) {
1141 // preallocate and preregister buffers
1142 static_cast<Surface *>(mNativeWindow.get())
1143 ->getIGraphicBufferProducer()->allowAllocation(true);
1144
1145 ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
1146 "output port",
1147 mComponentName.c_str(), bufferCount, bufferSize);
1148
1149 // Dequeue buffers then cancel them all
1150 for (OMX_U32 i = 0; i < bufferCount; i++) {
1151 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1152
1153 ANativeWindowBuffer *buf;
1154 int fenceFd;
1155 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1156 if (err != 0) {
1157 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1158 break;
1159 }
1160
1161 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
1162 mOMX->updateGraphicBufferInMeta(
1163 mNode, kPortIndexOutput, graphicBuffer, info->mBufferID);
1164 info->mStatus = BufferInfo::OWNED_BY_US;
1165 info->setWriteFence(fenceFd, "allocateOutputMetadataBuffers for legacy");
1166 info->mGraphicBuffer = graphicBuffer;
1167 }
1168
1169 for (OMX_U32 i = 0; i < mBuffers[kPortIndexOutput].size(); i++) {
1170 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1171 if (info->mStatus == BufferInfo::OWNED_BY_US) {
1172 status_t error = cancelBufferToNativeWindow(info);
1173 if (err == OK) {
1174 err = error;
1175 }
1176 }
1177 }
1178
1179 static_cast<Surface*>(mNativeWindow.get())
1180 ->getIGraphicBufferProducer()->allowAllocation(false);
1181 }
1182
1183 mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
1184 return err;
1185 }
1186
submitOutputMetadataBuffer()1187 status_t ACodec::submitOutputMetadataBuffer() {
1188 CHECK(storingMetadataInDecodedBuffers());
1189 if (mMetadataBuffersToSubmit == 0)
1190 return OK;
1191
1192 BufferInfo *info = dequeueBufferFromNativeWindow();
1193 if (info == NULL) {
1194 return ERROR_IO;
1195 }
1196
1197 ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
1198 mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get());
1199
1200 --mMetadataBuffersToSubmit;
1201 info->checkWriteFence("submitOutputMetadataBuffer");
1202 status_t err = mOMX->fillBuffer(mNode, info->mBufferID, info->mFenceFd);
1203 info->mFenceFd = -1;
1204 if (err == OK) {
1205 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1206 }
1207
1208 return err;
1209 }
1210
waitForFence(int fd,const char * dbg)1211 status_t ACodec::waitForFence(int fd, const char *dbg ) {
1212 status_t res = OK;
1213 if (fd >= 0) {
1214 sp<Fence> fence = new Fence(fd);
1215 res = fence->wait(IOMX::kFenceTimeoutMs);
1216 ALOGW_IF(res != OK, "FENCE TIMEOUT for %d in %s", fd, dbg);
1217 }
1218 return res;
1219 }
1220
1221 // static
_asString(BufferInfo::Status s)1222 const char *ACodec::_asString(BufferInfo::Status s) {
1223 switch (s) {
1224 case BufferInfo::OWNED_BY_US: return "OUR";
1225 case BufferInfo::OWNED_BY_COMPONENT: return "COMPONENT";
1226 case BufferInfo::OWNED_BY_UPSTREAM: return "UPSTREAM";
1227 case BufferInfo::OWNED_BY_DOWNSTREAM: return "DOWNSTREAM";
1228 case BufferInfo::OWNED_BY_NATIVE_WINDOW: return "SURFACE";
1229 case BufferInfo::UNRECOGNIZED: return "UNRECOGNIZED";
1230 default: return "?";
1231 }
1232 }
1233
dumpBuffers(OMX_U32 portIndex)1234 void ACodec::dumpBuffers(OMX_U32 portIndex) {
1235 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1236 ALOGI("[%s] %s port has %zu buffers:", mComponentName.c_str(),
1237 portIndex == kPortIndexInput ? "input" : "output", mBuffers[portIndex].size());
1238 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1239 const BufferInfo &info = mBuffers[portIndex][i];
1240 ALOGI(" slot %2zu: #%8u %p/%p %s(%d) dequeued:%u",
1241 i, info.mBufferID, info.mGraphicBuffer.get(),
1242 info.mGraphicBuffer == NULL ? NULL : info.mGraphicBuffer->getNativeBuffer(),
1243 _asString(info.mStatus), info.mStatus, info.mDequeuedAt);
1244 }
1245 }
1246
cancelBufferToNativeWindow(BufferInfo * info)1247 status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
1248 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1249
1250 ALOGV("[%s] Calling cancelBuffer on buffer %u",
1251 mComponentName.c_str(), info->mBufferID);
1252
1253 info->checkWriteFence("cancelBufferToNativeWindow");
1254 int err = mNativeWindow->cancelBuffer(
1255 mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
1256 info->mFenceFd = -1;
1257
1258 ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window",
1259 mComponentName.c_str(), info->mBufferID);
1260 // change ownership even if cancelBuffer fails
1261 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1262
1263 return err;
1264 }
1265
updateRenderInfoForDequeuedBuffer(ANativeWindowBuffer * buf,int fenceFd,BufferInfo * info)1266 void ACodec::updateRenderInfoForDequeuedBuffer(
1267 ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info) {
1268
1269 info->mRenderInfo =
1270 mRenderTracker.updateInfoForDequeuedBuffer(
1271 buf, fenceFd, info - &mBuffers[kPortIndexOutput][0]);
1272
1273 // check for any fences already signaled
1274 notifyOfRenderedFrames(false /* dropIncomplete */, info->mRenderInfo);
1275 }
1276
onFrameRendered(int64_t mediaTimeUs,nsecs_t systemNano)1277 void ACodec::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
1278 if (mRenderTracker.onFrameRendered(mediaTimeUs, systemNano) != OK) {
1279 mRenderTracker.dumpRenderQueue();
1280 }
1281 }
1282
notifyOfRenderedFrames(bool dropIncomplete,FrameRenderTracker::Info * until)1283 void ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Info *until) {
1284 sp<AMessage> msg = mNotify->dup();
1285 msg->setInt32("what", CodecBase::kWhatOutputFramesRendered);
1286 std::list<FrameRenderTracker::Info> done =
1287 mRenderTracker.checkFencesAndGetRenderedFrames(until, dropIncomplete);
1288
1289 // unlink untracked frames
1290 for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
1291 it != done.cend(); ++it) {
1292 ssize_t index = it->getIndex();
1293 if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) {
1294 mBuffers[kPortIndexOutput].editItemAt(index).mRenderInfo = NULL;
1295 } else if (index >= 0) {
1296 // THIS SHOULD NEVER HAPPEN
1297 ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size());
1298 }
1299 }
1300
1301 if (MediaCodec::CreateFramesRenderedMessage(done, msg)) {
1302 msg->post();
1303 }
1304 }
1305
dequeueBufferFromNativeWindow()1306 ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
1307 ANativeWindowBuffer *buf;
1308 CHECK(mNativeWindow.get() != NULL);
1309
1310 if (mTunneled) {
1311 ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel"
1312 " video playback mode mode!");
1313 return NULL;
1314 }
1315
1316 if (mFatalError) {
1317 ALOGW("not dequeuing from native window due to fatal error");
1318 return NULL;
1319 }
1320
1321 int fenceFd = -1;
1322 do {
1323 status_t err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1324 if (err != 0) {
1325 ALOGE("dequeueBuffer failed: %s(%d).", asString(err), err);
1326 return NULL;
1327 }
1328
1329 bool stale = false;
1330 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
1331 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1332
1333 if (info->mGraphicBuffer != NULL &&
1334 info->mGraphicBuffer->handle == buf->handle) {
1335 // Since consumers can attach buffers to BufferQueues, it is possible
1336 // that a known yet stale buffer can return from a surface that we
1337 // once used. We can simply ignore this as we have already dequeued
1338 // this buffer properly. NOTE: this does not eliminate all cases,
1339 // e.g. it is possible that we have queued the valid buffer to the
1340 // NW, and a stale copy of the same buffer gets dequeued - which will
1341 // be treated as the valid buffer by ACodec.
1342 if (info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1343 ALOGI("dequeued stale buffer %p. discarding", buf);
1344 stale = true;
1345 break;
1346 }
1347
1348 ALOGV("dequeued buffer %p", info->mGraphicBuffer->getNativeBuffer());
1349 info->mStatus = BufferInfo::OWNED_BY_US;
1350 info->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow");
1351 updateRenderInfoForDequeuedBuffer(buf, fenceFd, info);
1352 return info;
1353 }
1354 }
1355
1356 // It is also possible to receive a previously unregistered buffer
1357 // in non-meta mode. These should be treated as stale buffers. The
1358 // same is possible in meta mode, in which case, it will be treated
1359 // as a normal buffer, which is not desirable.
1360 // TODO: fix this.
1361 if (!stale && (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment)) {
1362 ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf);
1363 stale = true;
1364 }
1365 if (stale) {
1366 // TODO: detach stale buffer, but there is no API yet to do it.
1367 buf = NULL;
1368 }
1369 } while (buf == NULL);
1370
1371 // get oldest undequeued buffer
1372 BufferInfo *oldest = NULL;
1373 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
1374 BufferInfo *info =
1375 &mBuffers[kPortIndexOutput].editItemAt(i);
1376 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
1377 (oldest == NULL ||
1378 // avoid potential issues from counter rolling over
1379 mDequeueCounter - info->mDequeuedAt >
1380 mDequeueCounter - oldest->mDequeuedAt)) {
1381 oldest = info;
1382 }
1383 }
1384
1385 // it is impossible dequeue a buffer when there are no buffers with ANW
1386 CHECK(oldest != NULL);
1387 // it is impossible to dequeue an unknown buffer in non-meta mode, as the
1388 // while loop above does not complete
1389 CHECK(storingMetadataInDecodedBuffers());
1390
1391 // discard buffer in LRU info and replace with new buffer
1392 oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
1393 oldest->mStatus = BufferInfo::OWNED_BY_US;
1394 oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest");
1395 mRenderTracker.untrackFrame(oldest->mRenderInfo);
1396 oldest->mRenderInfo = NULL;
1397
1398 mOMX->updateGraphicBufferInMeta(
1399 mNode, kPortIndexOutput, oldest->mGraphicBuffer,
1400 oldest->mBufferID);
1401
1402 if (mOutputMetadataType == kMetadataBufferTypeGrallocSource) {
1403 VideoGrallocMetadata *grallocMeta =
1404 reinterpret_cast<VideoGrallocMetadata *>(oldest->mData->base());
1405 ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
1406 (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
1407 mDequeueCounter - oldest->mDequeuedAt,
1408 (void *)(uintptr_t)grallocMeta->pHandle,
1409 oldest->mGraphicBuffer->handle, oldest->mData->base());
1410 } else if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
1411 VideoNativeMetadata *nativeMeta =
1412 reinterpret_cast<VideoNativeMetadata *>(oldest->mData->base());
1413 ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
1414 (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
1415 mDequeueCounter - oldest->mDequeuedAt,
1416 (void *)(uintptr_t)nativeMeta->pBuffer,
1417 oldest->mGraphicBuffer->getNativeBuffer(), oldest->mData->base());
1418 }
1419
1420 updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest);
1421 return oldest;
1422 }
1423
freeBuffersOnPort(OMX_U32 portIndex)1424 status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
1425 status_t err = OK;
1426 for (size_t i = mBuffers[portIndex].size(); i > 0;) {
1427 i--;
1428 status_t err2 = freeBuffer(portIndex, i);
1429 if (err == OK) {
1430 err = err2;
1431 }
1432 }
1433
1434 // clear mDealer even on an error
1435 mDealer[portIndex].clear();
1436 return err;
1437 }
1438
freeOutputBuffersNotOwnedByComponent()1439 status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
1440 status_t err = OK;
1441 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1442 i--;
1443 BufferInfo *info =
1444 &mBuffers[kPortIndexOutput].editItemAt(i);
1445
1446 // At this time some buffers may still be with the component
1447 // or being drained.
1448 if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
1449 info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
1450 status_t err2 = freeBuffer(kPortIndexOutput, i);
1451 if (err == OK) {
1452 err = err2;
1453 }
1454 }
1455 }
1456
1457 return err;
1458 }
1459
freeBuffer(OMX_U32 portIndex,size_t i)1460 status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
1461 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1462 status_t err = OK;
1463
1464 // there should not be any fences in the metadata
1465 MetadataBufferType type =
1466 portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType;
1467 if (type == kMetadataBufferTypeANWBuffer && info->mData != NULL
1468 && info->mData->size() >= sizeof(VideoNativeMetadata)) {
1469 int fenceFd = ((VideoNativeMetadata *)info->mData->data())->nFenceFd;
1470 if (fenceFd >= 0) {
1471 ALOGW("unreleased fence (%d) in %s metadata buffer %zu",
1472 fenceFd, portIndex == kPortIndexInput ? "input" : "output", i);
1473 }
1474 }
1475
1476 switch (info->mStatus) {
1477 case BufferInfo::OWNED_BY_US:
1478 if (portIndex == kPortIndexOutput && mNativeWindow != NULL) {
1479 (void)cancelBufferToNativeWindow(info);
1480 }
1481 // fall through
1482
1483 case BufferInfo::OWNED_BY_NATIVE_WINDOW:
1484 err = mOMX->freeBuffer(mNode, portIndex, info->mBufferID);
1485 break;
1486
1487 default:
1488 ALOGE("trying to free buffer not owned by us or ANW (%d)", info->mStatus);
1489 err = FAILED_TRANSACTION;
1490 break;
1491 }
1492
1493 if (info->mFenceFd >= 0) {
1494 ::close(info->mFenceFd);
1495 }
1496
1497 if (portIndex == kPortIndexOutput) {
1498 mRenderTracker.untrackFrame(info->mRenderInfo, i);
1499 info->mRenderInfo = NULL;
1500 }
1501
1502 // remove buffer even if mOMX->freeBuffer fails
1503 mBuffers[portIndex].removeAt(i);
1504 return err;
1505 }
1506
findBufferByID(uint32_t portIndex,IOMX::buffer_id bufferID,ssize_t * index)1507 ACodec::BufferInfo *ACodec::findBufferByID(
1508 uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) {
1509 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1510 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1511
1512 if (info->mBufferID == bufferID) {
1513 if (index != NULL) {
1514 *index = i;
1515 }
1516 return info;
1517 }
1518 }
1519
1520 ALOGE("Could not find buffer with ID %u", bufferID);
1521 return NULL;
1522 }
1523
setComponentRole(bool isEncoder,const char * mime)1524 status_t ACodec::setComponentRole(
1525 bool isEncoder, const char *mime) {
1526 struct MimeToRole {
1527 const char *mime;
1528 const char *decoderRole;
1529 const char *encoderRole;
1530 };
1531
1532 static const MimeToRole kMimeToRole[] = {
1533 { MEDIA_MIMETYPE_AUDIO_MPEG,
1534 "audio_decoder.mp3", "audio_encoder.mp3" },
1535 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
1536 "audio_decoder.mp1", "audio_encoder.mp1" },
1537 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
1538 "audio_decoder.mp2", "audio_encoder.mp2" },
1539 { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1540 "audio_decoder.amrnb", "audio_encoder.amrnb" },
1541 { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1542 "audio_decoder.amrwb", "audio_encoder.amrwb" },
1543 { MEDIA_MIMETYPE_AUDIO_AAC,
1544 "audio_decoder.aac", "audio_encoder.aac" },
1545 { MEDIA_MIMETYPE_AUDIO_VORBIS,
1546 "audio_decoder.vorbis", "audio_encoder.vorbis" },
1547 { MEDIA_MIMETYPE_AUDIO_OPUS,
1548 "audio_decoder.opus", "audio_encoder.opus" },
1549 { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
1550 "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
1551 { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
1552 "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
1553 { MEDIA_MIMETYPE_VIDEO_AVC,
1554 "video_decoder.avc", "video_encoder.avc" },
1555 { MEDIA_MIMETYPE_VIDEO_HEVC,
1556 "video_decoder.hevc", "video_encoder.hevc" },
1557 { MEDIA_MIMETYPE_VIDEO_MPEG4,
1558 "video_decoder.mpeg4", "video_encoder.mpeg4" },
1559 { MEDIA_MIMETYPE_VIDEO_H263,
1560 "video_decoder.h263", "video_encoder.h263" },
1561 { MEDIA_MIMETYPE_VIDEO_VP8,
1562 "video_decoder.vp8", "video_encoder.vp8" },
1563 { MEDIA_MIMETYPE_VIDEO_VP9,
1564 "video_decoder.vp9", "video_encoder.vp9" },
1565 { MEDIA_MIMETYPE_AUDIO_RAW,
1566 "audio_decoder.raw", "audio_encoder.raw" },
1567 { MEDIA_MIMETYPE_AUDIO_FLAC,
1568 "audio_decoder.flac", "audio_encoder.flac" },
1569 { MEDIA_MIMETYPE_AUDIO_MSGSM,
1570 "audio_decoder.gsm", "audio_encoder.gsm" },
1571 { MEDIA_MIMETYPE_VIDEO_MPEG2,
1572 "video_decoder.mpeg2", "video_encoder.mpeg2" },
1573 { MEDIA_MIMETYPE_AUDIO_AC3,
1574 "audio_decoder.ac3", "audio_encoder.ac3" },
1575 { MEDIA_MIMETYPE_AUDIO_EAC3,
1576 "audio_decoder.eac3", "audio_encoder.eac3" },
1577 };
1578
1579 static const size_t kNumMimeToRole =
1580 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1581
1582 size_t i;
1583 for (i = 0; i < kNumMimeToRole; ++i) {
1584 if (!strcasecmp(mime, kMimeToRole[i].mime)) {
1585 break;
1586 }
1587 }
1588
1589 if (i == kNumMimeToRole) {
1590 return ERROR_UNSUPPORTED;
1591 }
1592
1593 const char *role =
1594 isEncoder ? kMimeToRole[i].encoderRole
1595 : kMimeToRole[i].decoderRole;
1596
1597 if (role != NULL) {
1598 OMX_PARAM_COMPONENTROLETYPE roleParams;
1599 InitOMXParams(&roleParams);
1600
1601 strncpy((char *)roleParams.cRole,
1602 role, OMX_MAX_STRINGNAME_SIZE - 1);
1603
1604 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1605
1606 status_t err = mOMX->setParameter(
1607 mNode, OMX_IndexParamStandardComponentRole,
1608 &roleParams, sizeof(roleParams));
1609
1610 if (err != OK) {
1611 ALOGW("[%s] Failed to set standard component role '%s'.",
1612 mComponentName.c_str(), role);
1613
1614 return err;
1615 }
1616 }
1617
1618 return OK;
1619 }
1620
configureCodec(const char * mime,const sp<AMessage> & msg)1621 status_t ACodec::configureCodec(
1622 const char *mime, const sp<AMessage> &msg) {
1623 int32_t encoder;
1624 if (!msg->findInt32("encoder", &encoder)) {
1625 encoder = false;
1626 }
1627
1628 sp<AMessage> inputFormat = new AMessage();
1629 sp<AMessage> outputFormat = mNotify->dup(); // will use this for kWhatOutputFormatChanged
1630
1631 mIsEncoder = encoder;
1632
1633 mInputMetadataType = kMetadataBufferTypeInvalid;
1634 mOutputMetadataType = kMetadataBufferTypeInvalid;
1635
1636 status_t err = setComponentRole(encoder /* isEncoder */, mime);
1637
1638 if (err != OK) {
1639 return err;
1640 }
1641
1642 int32_t bitRate = 0;
1643 // FLAC encoder doesn't need a bitrate, other encoders do
1644 if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
1645 && !msg->findInt32("bitrate", &bitRate)) {
1646 return INVALID_OPERATION;
1647 }
1648
1649 int32_t storeMeta;
1650 if (encoder
1651 && msg->findInt32("store-metadata-in-buffers", &storeMeta)
1652 && storeMeta != 0) {
1653 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE, &mInputMetadataType);
1654 if (err != OK) {
1655 ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
1656 mComponentName.c_str(), err);
1657
1658 return err;
1659 }
1660 // For this specific case we could be using camera source even if storeMetaDataInBuffers
1661 // returns Gralloc source. Pretend that we are; this will force us to use nBufferSize.
1662 if (mInputMetadataType == kMetadataBufferTypeGrallocSource) {
1663 mInputMetadataType = kMetadataBufferTypeCameraSource;
1664 }
1665
1666 uint32_t usageBits;
1667 if (mOMX->getParameter(
1668 mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
1669 &usageBits, sizeof(usageBits)) == OK) {
1670 inputFormat->setInt32(
1671 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
1672 }
1673 }
1674
1675 int32_t prependSPSPPS = 0;
1676 if (encoder
1677 && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
1678 && prependSPSPPS != 0) {
1679 OMX_INDEXTYPE index;
1680 err = mOMX->getExtensionIndex(
1681 mNode,
1682 "OMX.google.android.index.prependSPSPPSToIDRFrames",
1683 &index);
1684
1685 if (err == OK) {
1686 PrependSPSPPSToIDRFramesParams params;
1687 InitOMXParams(¶ms);
1688 params.bEnable = OMX_TRUE;
1689
1690 err = mOMX->setParameter(
1691 mNode, index, ¶ms, sizeof(params));
1692 }
1693
1694 if (err != OK) {
1695 ALOGE("Encoder could not be configured to emit SPS/PPS before "
1696 "IDR frames. (err %d)", err);
1697
1698 return err;
1699 }
1700 }
1701
1702 // Only enable metadata mode on encoder output if encoder can prepend
1703 // sps/pps to idr frames, since in metadata mode the bitstream is in an
1704 // opaque handle, to which we don't have access.
1705 int32_t video = !strncasecmp(mime, "video/", 6);
1706 mIsVideo = video;
1707 if (encoder && video) {
1708 OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
1709 && msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
1710 && storeMeta != 0);
1711
1712 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable, &mOutputMetadataType);
1713 if (err != OK) {
1714 ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
1715 mComponentName.c_str(), err);
1716 }
1717
1718 if (!msg->findInt64(
1719 "repeat-previous-frame-after",
1720 &mRepeatFrameDelayUs)) {
1721 mRepeatFrameDelayUs = -1ll;
1722 }
1723
1724 if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
1725 mMaxPtsGapUs = -1ll;
1726 }
1727
1728 if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
1729 mMaxFps = -1;
1730 }
1731
1732 if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) {
1733 mTimePerCaptureUs = -1ll;
1734 }
1735
1736 if (!msg->findInt32(
1737 "create-input-buffers-suspended",
1738 (int32_t*)&mCreateInputBuffersSuspended)) {
1739 mCreateInputBuffersSuspended = false;
1740 }
1741 }
1742
1743 // NOTE: we only use native window for video decoders
1744 sp<RefBase> obj;
1745 bool haveNativeWindow = msg->findObject("native-window", &obj)
1746 && obj != NULL && video && !encoder;
1747 mLegacyAdaptiveExperiment = false;
1748 if (video && !encoder) {
1749 inputFormat->setInt32("adaptive-playback", false);
1750
1751 int32_t usageProtected;
1752 if (msg->findInt32("protected", &usageProtected) && usageProtected) {
1753 if (!haveNativeWindow) {
1754 ALOGE("protected output buffers must be sent to an ANativeWindow");
1755 return PERMISSION_DENIED;
1756 }
1757 mFlags |= kFlagIsGrallocUsageProtected;
1758 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1759 }
1760 }
1761 if (haveNativeWindow) {
1762 sp<ANativeWindow> nativeWindow =
1763 static_cast<ANativeWindow *>(static_cast<Surface *>(obj.get()));
1764
1765 // START of temporary support for automatic FRC - THIS WILL BE REMOVED
1766 int32_t autoFrc;
1767 if (msg->findInt32("auto-frc", &autoFrc)) {
1768 bool enabled = autoFrc;
1769 OMX_CONFIG_BOOLEANTYPE config;
1770 InitOMXParams(&config);
1771 config.bEnabled = (OMX_BOOL)enabled;
1772 status_t temp = mOMX->setConfig(
1773 mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
1774 &config, sizeof(config));
1775 if (temp == OK) {
1776 outputFormat->setInt32("auto-frc", enabled);
1777 } else if (enabled) {
1778 ALOGI("codec does not support requested auto-frc (err %d)", temp);
1779 }
1780 }
1781 // END of temporary support for automatic FRC
1782
1783 int32_t tunneled;
1784 if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
1785 tunneled != 0) {
1786 ALOGI("Configuring TUNNELED video playback.");
1787 mTunneled = true;
1788
1789 int32_t audioHwSync = 0;
1790 if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
1791 ALOGW("No Audio HW Sync provided for video tunnel");
1792 }
1793 err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
1794 if (err != OK) {
1795 ALOGE("configureTunneledVideoPlayback(%d,%p) failed!",
1796 audioHwSync, nativeWindow.get());
1797 return err;
1798 }
1799
1800 int32_t maxWidth = 0, maxHeight = 0;
1801 if (msg->findInt32("max-width", &maxWidth) &&
1802 msg->findInt32("max-height", &maxHeight)) {
1803
1804 err = mOMX->prepareForAdaptivePlayback(
1805 mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1806 if (err != OK) {
1807 ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
1808 mComponentName.c_str(), err);
1809 // allow failure
1810 err = OK;
1811 } else {
1812 inputFormat->setInt32("max-width", maxWidth);
1813 inputFormat->setInt32("max-height", maxHeight);
1814 inputFormat->setInt32("adaptive-playback", true);
1815 }
1816 }
1817 } else {
1818 ALOGV("Configuring CPU controlled video playback.");
1819 mTunneled = false;
1820
1821 // Explicity reset the sideband handle of the window for
1822 // non-tunneled video in case the window was previously used
1823 // for a tunneled video playback.
1824 err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
1825 if (err != OK) {
1826 ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
1827 return err;
1828 }
1829
1830 // Always try to enable dynamic output buffers on native surface
1831 err = mOMX->storeMetaDataInBuffers(
1832 mNode, kPortIndexOutput, OMX_TRUE, &mOutputMetadataType);
1833 if (err != OK) {
1834 ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
1835 mComponentName.c_str(), err);
1836
1837 // if adaptive playback has been requested, try JB fallback
1838 // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
1839 // LARGE MEMORY REQUIREMENT
1840
1841 // we will not do adaptive playback on software accessed
1842 // surfaces as they never had to respond to changes in the
1843 // crop window, and we don't trust that they will be able to.
1844 int usageBits = 0;
1845 bool canDoAdaptivePlayback;
1846
1847 if (nativeWindow->query(
1848 nativeWindow.get(),
1849 NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1850 &usageBits) != OK) {
1851 canDoAdaptivePlayback = false;
1852 } else {
1853 canDoAdaptivePlayback =
1854 (usageBits &
1855 (GRALLOC_USAGE_SW_READ_MASK |
1856 GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
1857 }
1858
1859 int32_t maxWidth = 0, maxHeight = 0;
1860 if (canDoAdaptivePlayback &&
1861 msg->findInt32("max-width", &maxWidth) &&
1862 msg->findInt32("max-height", &maxHeight)) {
1863 ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
1864 mComponentName.c_str(), maxWidth, maxHeight);
1865
1866 err = mOMX->prepareForAdaptivePlayback(
1867 mNode, kPortIndexOutput, OMX_TRUE, maxWidth,
1868 maxHeight);
1869 ALOGW_IF(err != OK,
1870 "[%s] prepareForAdaptivePlayback failed w/ err %d",
1871 mComponentName.c_str(), err);
1872
1873 if (err == OK) {
1874 inputFormat->setInt32("max-width", maxWidth);
1875 inputFormat->setInt32("max-height", maxHeight);
1876 inputFormat->setInt32("adaptive-playback", true);
1877 }
1878 }
1879 // allow failure
1880 err = OK;
1881 } else {
1882 ALOGV("[%s] storeMetaDataInBuffers succeeded",
1883 mComponentName.c_str());
1884 CHECK(storingMetadataInDecodedBuffers());
1885 mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled(
1886 "legacy-adaptive", !msg->contains("no-experiments"));
1887
1888 inputFormat->setInt32("adaptive-playback", true);
1889 }
1890
1891 int32_t push;
1892 if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
1893 && push != 0) {
1894 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1895 }
1896 }
1897
1898 int32_t rotationDegrees;
1899 if (msg->findInt32("rotation-degrees", &rotationDegrees)) {
1900 mRotationDegrees = rotationDegrees;
1901 } else {
1902 mRotationDegrees = 0;
1903 }
1904 }
1905
1906 if (video) {
1907 // determine need for software renderer
1908 bool usingSwRenderer = false;
1909 if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
1910 usingSwRenderer = true;
1911 haveNativeWindow = false;
1912 }
1913
1914 if (encoder) {
1915 err = setupVideoEncoder(mime, msg);
1916 } else {
1917 err = setupVideoDecoder(mime, msg, haveNativeWindow);
1918 }
1919
1920 if (err != OK) {
1921 return err;
1922 }
1923
1924 if (haveNativeWindow) {
1925 mNativeWindow = static_cast<Surface *>(obj.get());
1926 }
1927
1928 // initialize native window now to get actual output format
1929 // TODO: this is needed for some encoders even though they don't use native window
1930 err = initNativeWindow();
1931 if (err != OK) {
1932 return err;
1933 }
1934
1935 // fallback for devices that do not handle flex-YUV for native buffers
1936 if (haveNativeWindow) {
1937 int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
1938 if (msg->findInt32("color-format", &requestedColorFormat) &&
1939 requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
1940 status_t err = getPortFormat(kPortIndexOutput, outputFormat);
1941 if (err != OK) {
1942 return err;
1943 }
1944 int32_t colorFormat = OMX_COLOR_FormatUnused;
1945 OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
1946 if (!outputFormat->findInt32("color-format", &colorFormat)) {
1947 ALOGE("ouptut port did not have a color format (wrong domain?)");
1948 return BAD_VALUE;
1949 }
1950 ALOGD("[%s] Requested output format %#x and got %#x.",
1951 mComponentName.c_str(), requestedColorFormat, colorFormat);
1952 if (!isFlexibleColorFormat(
1953 mOMX, mNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
1954 || flexibleEquivalent != (OMX_U32)requestedColorFormat) {
1955 // device did not handle flex-YUV request for native window, fall back
1956 // to SW renderer
1957 ALOGI("[%s] Falling back to software renderer", mComponentName.c_str());
1958 mNativeWindow.clear();
1959 mNativeWindowUsageBits = 0;
1960 haveNativeWindow = false;
1961 usingSwRenderer = true;
1962 if (storingMetadataInDecodedBuffers()) {
1963 err = mOMX->storeMetaDataInBuffers(
1964 mNode, kPortIndexOutput, OMX_FALSE, &mOutputMetadataType);
1965 mOutputMetadataType = kMetadataBufferTypeInvalid; // just in case
1966 // TODO: implement adaptive-playback support for bytebuffer mode.
1967 // This is done by SW codecs, but most HW codecs don't support it.
1968 inputFormat->setInt32("adaptive-playback", false);
1969 }
1970 if (err == OK) {
1971 err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
1972 }
1973 if (mFlags & kFlagIsGrallocUsageProtected) {
1974 // fallback is not supported for protected playback
1975 err = PERMISSION_DENIED;
1976 } else if (err == OK) {
1977 err = setupVideoDecoder(mime, msg, false);
1978 }
1979 }
1980 }
1981 }
1982
1983 if (usingSwRenderer) {
1984 outputFormat->setInt32("using-sw-renderer", 1);
1985 }
1986 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
1987 int32_t numChannels, sampleRate;
1988 if (!msg->findInt32("channel-count", &numChannels)
1989 || !msg->findInt32("sample-rate", &sampleRate)) {
1990 // Since we did not always check for these, leave them optional
1991 // and have the decoder figure it all out.
1992 err = OK;
1993 } else {
1994 err = setupRawAudioFormat(
1995 encoder ? kPortIndexInput : kPortIndexOutput,
1996 sampleRate,
1997 numChannels);
1998 }
1999 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2000 int32_t numChannels, sampleRate;
2001 if (!msg->findInt32("channel-count", &numChannels)
2002 || !msg->findInt32("sample-rate", &sampleRate)) {
2003 err = INVALID_OPERATION;
2004 } else {
2005 int32_t isADTS, aacProfile;
2006 int32_t sbrMode;
2007 int32_t maxOutputChannelCount;
2008 int32_t pcmLimiterEnable;
2009 drcParams_t drc;
2010 if (!msg->findInt32("is-adts", &isADTS)) {
2011 isADTS = 0;
2012 }
2013 if (!msg->findInt32("aac-profile", &aacProfile)) {
2014 aacProfile = OMX_AUDIO_AACObjectNull;
2015 }
2016 if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
2017 sbrMode = -1;
2018 }
2019
2020 if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
2021 maxOutputChannelCount = -1;
2022 }
2023 if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) {
2024 // value is unknown
2025 pcmLimiterEnable = -1;
2026 }
2027 if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
2028 // value is unknown
2029 drc.encodedTargetLevel = -1;
2030 }
2031 if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
2032 // value is unknown
2033 drc.drcCut = -1;
2034 }
2035 if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
2036 // value is unknown
2037 drc.drcBoost = -1;
2038 }
2039 if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
2040 // value is unknown
2041 drc.heavyCompression = -1;
2042 }
2043 if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
2044 // value is unknown
2045 drc.targetRefLevel = -1;
2046 }
2047
2048 err = setupAACCodec(
2049 encoder, numChannels, sampleRate, bitRate, aacProfile,
2050 isADTS != 0, sbrMode, maxOutputChannelCount, drc,
2051 pcmLimiterEnable);
2052 }
2053 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
2054 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
2055 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
2056 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
2057 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
2058 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
2059 // These are PCM-like formats with a fixed sample rate but
2060 // a variable number of channels.
2061
2062 int32_t numChannels;
2063 if (!msg->findInt32("channel-count", &numChannels)) {
2064 err = INVALID_OPERATION;
2065 } else {
2066 int32_t sampleRate;
2067 if (!msg->findInt32("sample-rate", &sampleRate)) {
2068 sampleRate = 8000;
2069 }
2070 err = setupG711Codec(encoder, sampleRate, numChannels);
2071 }
2072 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
2073 int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
2074 if (encoder &&
2075 (!msg->findInt32("channel-count", &numChannels)
2076 || !msg->findInt32("sample-rate", &sampleRate))) {
2077 ALOGE("missing channel count or sample rate for FLAC encoder");
2078 err = INVALID_OPERATION;
2079 } else {
2080 if (encoder) {
2081 if (!msg->findInt32(
2082 "complexity", &compressionLevel) &&
2083 !msg->findInt32(
2084 "flac-compression-level", &compressionLevel)) {
2085 compressionLevel = 5; // default FLAC compression level
2086 } else if (compressionLevel < 0) {
2087 ALOGW("compression level %d outside [0..8] range, "
2088 "using 0",
2089 compressionLevel);
2090 compressionLevel = 0;
2091 } else if (compressionLevel > 8) {
2092 ALOGW("compression level %d outside [0..8] range, "
2093 "using 8",
2094 compressionLevel);
2095 compressionLevel = 8;
2096 }
2097 }
2098 err = setupFlacCodec(
2099 encoder, numChannels, sampleRate, compressionLevel);
2100 }
2101 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
2102 int32_t numChannels, sampleRate;
2103 if (encoder
2104 || !msg->findInt32("channel-count", &numChannels)
2105 || !msg->findInt32("sample-rate", &sampleRate)) {
2106 err = INVALID_OPERATION;
2107 } else {
2108 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
2109 }
2110 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
2111 int32_t numChannels;
2112 int32_t sampleRate;
2113 if (!msg->findInt32("channel-count", &numChannels)
2114 || !msg->findInt32("sample-rate", &sampleRate)) {
2115 err = INVALID_OPERATION;
2116 } else {
2117 err = setupAC3Codec(encoder, numChannels, sampleRate);
2118 }
2119 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
2120 int32_t numChannels;
2121 int32_t sampleRate;
2122 if (!msg->findInt32("channel-count", &numChannels)
2123 || !msg->findInt32("sample-rate", &sampleRate)) {
2124 err = INVALID_OPERATION;
2125 } else {
2126 err = setupEAC3Codec(encoder, numChannels, sampleRate);
2127 }
2128 }
2129
2130 if (err != OK) {
2131 return err;
2132 }
2133
2134 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
2135 mEncoderDelay = 0;
2136 }
2137
2138 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
2139 mEncoderPadding = 0;
2140 }
2141
2142 if (msg->findInt32("channel-mask", &mChannelMask)) {
2143 mChannelMaskPresent = true;
2144 } else {
2145 mChannelMaskPresent = false;
2146 }
2147
2148 int32_t maxInputSize;
2149 if (msg->findInt32("max-input-size", &maxInputSize)) {
2150 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
2151 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
2152 err = setMinBufferSize(kPortIndexInput, 8192); // XXX
2153 }
2154
2155 int32_t priority;
2156 if (msg->findInt32("priority", &priority)) {
2157 err = setPriority(priority);
2158 }
2159
2160 int32_t rateInt = -1;
2161 float rateFloat = -1;
2162 if (!msg->findFloat("operating-rate", &rateFloat)) {
2163 msg->findInt32("operating-rate", &rateInt);
2164 rateFloat = (float)rateInt; // 16MHz (FLINTMAX) is OK for upper bound.
2165 }
2166 if (rateFloat > 0) {
2167 err = setOperatingRate(rateFloat, video);
2168 }
2169
2170 mBaseOutputFormat = outputFormat;
2171
2172 err = getPortFormat(kPortIndexInput, inputFormat);
2173 if (err == OK) {
2174 err = getPortFormat(kPortIndexOutput, outputFormat);
2175 if (err == OK) {
2176 mInputFormat = inputFormat;
2177 mOutputFormat = outputFormat;
2178 }
2179 }
2180 return err;
2181 }
2182
setPriority(int32_t priority)2183 status_t ACodec::setPriority(int32_t priority) {
2184 if (priority < 0) {
2185 return BAD_VALUE;
2186 }
2187 OMX_PARAM_U32TYPE config;
2188 InitOMXParams(&config);
2189 config.nU32 = (OMX_U32)priority;
2190 status_t temp = mOMX->setConfig(
2191 mNode, (OMX_INDEXTYPE)OMX_IndexConfigPriority,
2192 &config, sizeof(config));
2193 if (temp != OK) {
2194 ALOGI("codec does not support config priority (err %d)", temp);
2195 }
2196 return OK;
2197 }
2198
setOperatingRate(float rateFloat,bool isVideo)2199 status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) {
2200 if (rateFloat < 0) {
2201 return BAD_VALUE;
2202 }
2203 OMX_U32 rate;
2204 if (isVideo) {
2205 if (rateFloat > 65535) {
2206 return BAD_VALUE;
2207 }
2208 rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f);
2209 } else {
2210 if (rateFloat > UINT_MAX) {
2211 return BAD_VALUE;
2212 }
2213 rate = (OMX_U32)(rateFloat);
2214 }
2215 OMX_PARAM_U32TYPE config;
2216 InitOMXParams(&config);
2217 config.nU32 = rate;
2218 status_t err = mOMX->setConfig(
2219 mNode, (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate,
2220 &config, sizeof(config));
2221 if (err != OK) {
2222 ALOGI("codec does not support config operating rate (err %d)", err);
2223 }
2224 return OK;
2225 }
2226
setMinBufferSize(OMX_U32 portIndex,size_t size)2227 status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
2228 OMX_PARAM_PORTDEFINITIONTYPE def;
2229 InitOMXParams(&def);
2230 def.nPortIndex = portIndex;
2231
2232 status_t err = mOMX->getParameter(
2233 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2234
2235 if (err != OK) {
2236 return err;
2237 }
2238
2239 if (def.nBufferSize >= size) {
2240 return OK;
2241 }
2242
2243 def.nBufferSize = size;
2244
2245 err = mOMX->setParameter(
2246 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2247
2248 if (err != OK) {
2249 return err;
2250 }
2251
2252 err = mOMX->getParameter(
2253 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2254
2255 if (err != OK) {
2256 return err;
2257 }
2258
2259 if (def.nBufferSize < size) {
2260 ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize);
2261 return FAILED_TRANSACTION;
2262 }
2263
2264 return OK;
2265 }
2266
selectAudioPortFormat(OMX_U32 portIndex,OMX_AUDIO_CODINGTYPE desiredFormat)2267 status_t ACodec::selectAudioPortFormat(
2268 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
2269 OMX_AUDIO_PARAM_PORTFORMATTYPE format;
2270 InitOMXParams(&format);
2271
2272 format.nPortIndex = portIndex;
2273 for (OMX_U32 index = 0;; ++index) {
2274 format.nIndex = index;
2275
2276 status_t err = mOMX->getParameter(
2277 mNode, OMX_IndexParamAudioPortFormat,
2278 &format, sizeof(format));
2279
2280 if (err != OK) {
2281 return err;
2282 }
2283
2284 if (format.eEncoding == desiredFormat) {
2285 break;
2286 }
2287 }
2288
2289 return mOMX->setParameter(
2290 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
2291 }
2292
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)2293 status_t ACodec::setupAACCodec(
2294 bool encoder, int32_t numChannels, int32_t sampleRate,
2295 int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
2296 int32_t maxOutputChannelCount, const drcParams_t& drc,
2297 int32_t pcmLimiterEnable) {
2298 if (encoder && isADTS) {
2299 return -EINVAL;
2300 }
2301
2302 status_t err = setupRawAudioFormat(
2303 encoder ? kPortIndexInput : kPortIndexOutput,
2304 sampleRate,
2305 numChannels);
2306
2307 if (err != OK) {
2308 return err;
2309 }
2310
2311 if (encoder) {
2312 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
2313
2314 if (err != OK) {
2315 return err;
2316 }
2317
2318 OMX_PARAM_PORTDEFINITIONTYPE def;
2319 InitOMXParams(&def);
2320 def.nPortIndex = kPortIndexOutput;
2321
2322 err = mOMX->getParameter(
2323 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2324
2325 if (err != OK) {
2326 return err;
2327 }
2328
2329 def.format.audio.bFlagErrorConcealment = OMX_TRUE;
2330 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
2331
2332 err = mOMX->setParameter(
2333 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2334
2335 if (err != OK) {
2336 return err;
2337 }
2338
2339 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2340 InitOMXParams(&profile);
2341 profile.nPortIndex = kPortIndexOutput;
2342
2343 err = mOMX->getParameter(
2344 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2345
2346 if (err != OK) {
2347 return err;
2348 }
2349
2350 profile.nChannels = numChannels;
2351
2352 profile.eChannelMode =
2353 (numChannels == 1)
2354 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
2355
2356 profile.nSampleRate = sampleRate;
2357 profile.nBitRate = bitRate;
2358 profile.nAudioBandWidth = 0;
2359 profile.nFrameLength = 0;
2360 profile.nAACtools = OMX_AUDIO_AACToolAll;
2361 profile.nAACERtools = OMX_AUDIO_AACERNone;
2362 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
2363 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
2364 switch (sbrMode) {
2365 case 0:
2366 // disable sbr
2367 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2368 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2369 break;
2370 case 1:
2371 // enable single-rate sbr
2372 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2373 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2374 break;
2375 case 2:
2376 // enable dual-rate sbr
2377 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2378 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2379 break;
2380 case -1:
2381 // enable both modes -> the codec will decide which mode should be used
2382 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2383 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2384 break;
2385 default:
2386 // unsupported sbr mode
2387 return BAD_VALUE;
2388 }
2389
2390
2391 err = mOMX->setParameter(
2392 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2393
2394 if (err != OK) {
2395 return err;
2396 }
2397
2398 return err;
2399 }
2400
2401 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2402 InitOMXParams(&profile);
2403 profile.nPortIndex = kPortIndexInput;
2404
2405 err = mOMX->getParameter(
2406 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2407
2408 if (err != OK) {
2409 return err;
2410 }
2411
2412 profile.nChannels = numChannels;
2413 profile.nSampleRate = sampleRate;
2414
2415 profile.eAACStreamFormat =
2416 isADTS
2417 ? OMX_AUDIO_AACStreamFormatMP4ADTS
2418 : OMX_AUDIO_AACStreamFormatMP4FF;
2419
2420 OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
2421 InitOMXParams(&presentation);
2422 presentation.nMaxOutputChannels = maxOutputChannelCount;
2423 presentation.nDrcCut = drc.drcCut;
2424 presentation.nDrcBoost = drc.drcBoost;
2425 presentation.nHeavyCompression = drc.heavyCompression;
2426 presentation.nTargetReferenceLevel = drc.targetRefLevel;
2427 presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
2428 presentation.nPCMLimiterEnable = pcmLimiterEnable;
2429
2430 status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2431 if (res == OK) {
2432 // optional parameters, will not cause configuration failure
2433 mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
2434 &presentation, sizeof(presentation));
2435 } else {
2436 ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
2437 }
2438 return res;
2439 }
2440
setupAC3Codec(bool encoder,int32_t numChannels,int32_t sampleRate)2441 status_t ACodec::setupAC3Codec(
2442 bool encoder, int32_t numChannels, int32_t sampleRate) {
2443 status_t err = setupRawAudioFormat(
2444 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2445
2446 if (err != OK) {
2447 return err;
2448 }
2449
2450 if (encoder) {
2451 ALOGW("AC3 encoding is not supported.");
2452 return INVALID_OPERATION;
2453 }
2454
2455 OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
2456 InitOMXParams(&def);
2457 def.nPortIndex = kPortIndexInput;
2458
2459 err = mOMX->getParameter(
2460 mNode,
2461 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
2462 &def,
2463 sizeof(def));
2464
2465 if (err != OK) {
2466 return err;
2467 }
2468
2469 def.nChannels = numChannels;
2470 def.nSampleRate = sampleRate;
2471
2472 return mOMX->setParameter(
2473 mNode,
2474 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
2475 &def,
2476 sizeof(def));
2477 }
2478
setupEAC3Codec(bool encoder,int32_t numChannels,int32_t sampleRate)2479 status_t ACodec::setupEAC3Codec(
2480 bool encoder, int32_t numChannels, int32_t sampleRate) {
2481 status_t err = setupRawAudioFormat(
2482 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2483
2484 if (err != OK) {
2485 return err;
2486 }
2487
2488 if (encoder) {
2489 ALOGW("EAC3 encoding is not supported.");
2490 return INVALID_OPERATION;
2491 }
2492
2493 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
2494 InitOMXParams(&def);
2495 def.nPortIndex = kPortIndexInput;
2496
2497 err = mOMX->getParameter(
2498 mNode,
2499 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
2500 &def,
2501 sizeof(def));
2502
2503 if (err != OK) {
2504 return err;
2505 }
2506
2507 def.nChannels = numChannels;
2508 def.nSampleRate = sampleRate;
2509
2510 return mOMX->setParameter(
2511 mNode,
2512 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
2513 &def,
2514 sizeof(def));
2515 }
2516
pickModeFromBitRate(bool isAMRWB,int32_t bps)2517 static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
2518 bool isAMRWB, int32_t bps) {
2519 if (isAMRWB) {
2520 if (bps <= 6600) {
2521 return OMX_AUDIO_AMRBandModeWB0;
2522 } else if (bps <= 8850) {
2523 return OMX_AUDIO_AMRBandModeWB1;
2524 } else if (bps <= 12650) {
2525 return OMX_AUDIO_AMRBandModeWB2;
2526 } else if (bps <= 14250) {
2527 return OMX_AUDIO_AMRBandModeWB3;
2528 } else if (bps <= 15850) {
2529 return OMX_AUDIO_AMRBandModeWB4;
2530 } else if (bps <= 18250) {
2531 return OMX_AUDIO_AMRBandModeWB5;
2532 } else if (bps <= 19850) {
2533 return OMX_AUDIO_AMRBandModeWB6;
2534 } else if (bps <= 23050) {
2535 return OMX_AUDIO_AMRBandModeWB7;
2536 }
2537
2538 // 23850 bps
2539 return OMX_AUDIO_AMRBandModeWB8;
2540 } else { // AMRNB
2541 if (bps <= 4750) {
2542 return OMX_AUDIO_AMRBandModeNB0;
2543 } else if (bps <= 5150) {
2544 return OMX_AUDIO_AMRBandModeNB1;
2545 } else if (bps <= 5900) {
2546 return OMX_AUDIO_AMRBandModeNB2;
2547 } else if (bps <= 6700) {
2548 return OMX_AUDIO_AMRBandModeNB3;
2549 } else if (bps <= 7400) {
2550 return OMX_AUDIO_AMRBandModeNB4;
2551 } else if (bps <= 7950) {
2552 return OMX_AUDIO_AMRBandModeNB5;
2553 } else if (bps <= 10200) {
2554 return OMX_AUDIO_AMRBandModeNB6;
2555 }
2556
2557 // 12200 bps
2558 return OMX_AUDIO_AMRBandModeNB7;
2559 }
2560 }
2561
setupAMRCodec(bool encoder,bool isWAMR,int32_t bitrate)2562 status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
2563 OMX_AUDIO_PARAM_AMRTYPE def;
2564 InitOMXParams(&def);
2565 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
2566
2567 status_t err =
2568 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2569
2570 if (err != OK) {
2571 return err;
2572 }
2573
2574 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
2575 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
2576
2577 err = mOMX->setParameter(
2578 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2579
2580 if (err != OK) {
2581 return err;
2582 }
2583
2584 return setupRawAudioFormat(
2585 encoder ? kPortIndexInput : kPortIndexOutput,
2586 isWAMR ? 16000 : 8000 /* sampleRate */,
2587 1 /* numChannels */);
2588 }
2589
setupG711Codec(bool encoder,int32_t sampleRate,int32_t numChannels)2590 status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) {
2591 if (encoder) {
2592 return INVALID_OPERATION;
2593 }
2594
2595 return setupRawAudioFormat(
2596 kPortIndexInput, sampleRate, numChannels);
2597 }
2598
setupFlacCodec(bool encoder,int32_t numChannels,int32_t sampleRate,int32_t compressionLevel)2599 status_t ACodec::setupFlacCodec(
2600 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
2601
2602 if (encoder) {
2603 OMX_AUDIO_PARAM_FLACTYPE def;
2604 InitOMXParams(&def);
2605 def.nPortIndex = kPortIndexOutput;
2606
2607 // configure compression level
2608 status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
2609 if (err != OK) {
2610 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
2611 return err;
2612 }
2613 def.nCompressionLevel = compressionLevel;
2614 err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
2615 if (err != OK) {
2616 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
2617 return err;
2618 }
2619 }
2620
2621 return setupRawAudioFormat(
2622 encoder ? kPortIndexInput : kPortIndexOutput,
2623 sampleRate,
2624 numChannels);
2625 }
2626
setupRawAudioFormat(OMX_U32 portIndex,int32_t sampleRate,int32_t numChannels)2627 status_t ACodec::setupRawAudioFormat(
2628 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
2629 OMX_PARAM_PORTDEFINITIONTYPE def;
2630 InitOMXParams(&def);
2631 def.nPortIndex = portIndex;
2632
2633 status_t err = mOMX->getParameter(
2634 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2635
2636 if (err != OK) {
2637 return err;
2638 }
2639
2640 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2641
2642 err = mOMX->setParameter(
2643 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2644
2645 if (err != OK) {
2646 return err;
2647 }
2648
2649 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
2650 InitOMXParams(&pcmParams);
2651 pcmParams.nPortIndex = portIndex;
2652
2653 err = mOMX->getParameter(
2654 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2655
2656 if (err != OK) {
2657 return err;
2658 }
2659
2660 pcmParams.nChannels = numChannels;
2661 pcmParams.eNumData = OMX_NumericalDataSigned;
2662 pcmParams.bInterleaved = OMX_TRUE;
2663 pcmParams.nBitPerSample = 16;
2664 pcmParams.nSamplingRate = sampleRate;
2665 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
2666
2667 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
2668 return OMX_ErrorNone;
2669 }
2670
2671 return mOMX->setParameter(
2672 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2673 }
2674
configureTunneledVideoPlayback(int32_t audioHwSync,const sp<ANativeWindow> & nativeWindow)2675 status_t ACodec::configureTunneledVideoPlayback(
2676 int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
2677 native_handle_t* sidebandHandle;
2678
2679 status_t err = mOMX->configureVideoTunnelMode(
2680 mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
2681 if (err != OK) {
2682 ALOGE("configureVideoTunnelMode failed! (err %d).", err);
2683 return err;
2684 }
2685
2686 err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
2687 if (err != OK) {
2688 ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
2689 sidebandHandle, err);
2690 return err;
2691 }
2692
2693 return OK;
2694 }
2695
setVideoPortFormatType(OMX_U32 portIndex,OMX_VIDEO_CODINGTYPE compressionFormat,OMX_COLOR_FORMATTYPE colorFormat,bool usingNativeBuffers)2696 status_t ACodec::setVideoPortFormatType(
2697 OMX_U32 portIndex,
2698 OMX_VIDEO_CODINGTYPE compressionFormat,
2699 OMX_COLOR_FORMATTYPE colorFormat,
2700 bool usingNativeBuffers) {
2701 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
2702 InitOMXParams(&format);
2703 format.nPortIndex = portIndex;
2704 format.nIndex = 0;
2705 bool found = false;
2706
2707 OMX_U32 index = 0;
2708 for (;;) {
2709 format.nIndex = index;
2710 status_t err = mOMX->getParameter(
2711 mNode, OMX_IndexParamVideoPortFormat,
2712 &format, sizeof(format));
2713
2714 if (err != OK) {
2715 return err;
2716 }
2717
2718 // substitute back flexible color format to codec supported format
2719 OMX_U32 flexibleEquivalent;
2720 if (compressionFormat == OMX_VIDEO_CodingUnused
2721 && isFlexibleColorFormat(
2722 mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
2723 && colorFormat == flexibleEquivalent) {
2724 ALOGI("[%s] using color format %#x in place of %#x",
2725 mComponentName.c_str(), format.eColorFormat, colorFormat);
2726 colorFormat = format.eColorFormat;
2727 }
2728
2729 // The following assertion is violated by TI's video decoder.
2730 // CHECK_EQ(format.nIndex, index);
2731
2732 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
2733 if (portIndex == kPortIndexInput
2734 && colorFormat == format.eColorFormat) {
2735 // eCompressionFormat does not seem right.
2736 found = true;
2737 break;
2738 }
2739 if (portIndex == kPortIndexOutput
2740 && compressionFormat == format.eCompressionFormat) {
2741 // eColorFormat does not seem right.
2742 found = true;
2743 break;
2744 }
2745 }
2746
2747 if (format.eCompressionFormat == compressionFormat
2748 && format.eColorFormat == colorFormat) {
2749 found = true;
2750 break;
2751 }
2752
2753 ++index;
2754 }
2755
2756 if (!found) {
2757 return UNKNOWN_ERROR;
2758 }
2759
2760 status_t err = mOMX->setParameter(
2761 mNode, OMX_IndexParamVideoPortFormat,
2762 &format, sizeof(format));
2763
2764 return err;
2765 }
2766
2767 // Set optimal output format. OMX component lists output formats in the order
2768 // of preference, but this got more complicated since the introduction of flexible
2769 // YUV formats. We support a legacy behavior for applications that do not use
2770 // surface output, do not specify an output format, but expect a "usable" standard
2771 // OMX format. SW readable and standard formats must be flex-YUV.
2772 //
2773 // Suggested preference order:
2774 // - optimal format for texture rendering (mediaplayer behavior)
2775 // - optimal SW readable & texture renderable format (flex-YUV support)
2776 // - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
2777 // - legacy "usable" standard formats
2778 //
2779 // For legacy support, we prefer a standard format, but will settle for a SW readable
2780 // flex-YUV format.
setSupportedOutputFormat(bool getLegacyFlexibleFormat)2781 status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
2782 OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
2783 InitOMXParams(&format);
2784 format.nPortIndex = kPortIndexOutput;
2785
2786 InitOMXParams(&legacyFormat);
2787 // this field will change when we find a suitable legacy format
2788 legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
2789
2790 for (OMX_U32 index = 0; ; ++index) {
2791 format.nIndex = index;
2792 status_t err = mOMX->getParameter(
2793 mNode, OMX_IndexParamVideoPortFormat,
2794 &format, sizeof(format));
2795 if (err != OK) {
2796 // no more formats, pick legacy format if found
2797 if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
2798 memcpy(&format, &legacyFormat, sizeof(format));
2799 break;
2800 }
2801 return err;
2802 }
2803 if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
2804 return OMX_ErrorBadParameter;
2805 }
2806 if (!getLegacyFlexibleFormat) {
2807 break;
2808 }
2809 // standard formats that were exposed to users before
2810 if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
2811 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
2812 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
2813 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
2814 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
2815 break;
2816 }
2817 // find best legacy non-standard format
2818 OMX_U32 flexibleEquivalent;
2819 if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
2820 && isFlexibleColorFormat(
2821 mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */,
2822 &flexibleEquivalent)
2823 && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
2824 memcpy(&legacyFormat, &format, sizeof(format));
2825 }
2826 }
2827 return mOMX->setParameter(
2828 mNode, OMX_IndexParamVideoPortFormat,
2829 &format, sizeof(format));
2830 }
2831
2832 static const struct VideoCodingMapEntry {
2833 const char *mMime;
2834 OMX_VIDEO_CODINGTYPE mVideoCodingType;
2835 } kVideoCodingMapEntry[] = {
2836 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
2837 { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
2838 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
2839 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
2840 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
2841 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
2842 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
2843 };
2844
GetVideoCodingTypeFromMime(const char * mime,OMX_VIDEO_CODINGTYPE * codingType)2845 static status_t GetVideoCodingTypeFromMime(
2846 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
2847 for (size_t i = 0;
2848 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2849 ++i) {
2850 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
2851 *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
2852 return OK;
2853 }
2854 }
2855
2856 *codingType = OMX_VIDEO_CodingUnused;
2857
2858 return ERROR_UNSUPPORTED;
2859 }
2860
GetMimeTypeForVideoCoding(OMX_VIDEO_CODINGTYPE codingType,AString * mime)2861 static status_t GetMimeTypeForVideoCoding(
2862 OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
2863 for (size_t i = 0;
2864 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2865 ++i) {
2866 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
2867 *mime = kVideoCodingMapEntry[i].mMime;
2868 return OK;
2869 }
2870 }
2871
2872 mime->clear();
2873
2874 return ERROR_UNSUPPORTED;
2875 }
2876
setupVideoDecoder(const char * mime,const sp<AMessage> & msg,bool haveNativeWindow)2877 status_t ACodec::setupVideoDecoder(
2878 const char *mime, const sp<AMessage> &msg, bool haveNativeWindow) {
2879 int32_t width, height;
2880 if (!msg->findInt32("width", &width)
2881 || !msg->findInt32("height", &height)) {
2882 return INVALID_OPERATION;
2883 }
2884
2885 OMX_VIDEO_CODINGTYPE compressionFormat;
2886 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2887
2888 if (err != OK) {
2889 return err;
2890 }
2891
2892 err = setVideoPortFormatType(
2893 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
2894
2895 if (err != OK) {
2896 return err;
2897 }
2898
2899 int32_t tmp;
2900 if (msg->findInt32("color-format", &tmp)) {
2901 OMX_COLOR_FORMATTYPE colorFormat =
2902 static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2903 err = setVideoPortFormatType(
2904 kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
2905 if (err != OK) {
2906 ALOGW("[%s] does not support color format %d",
2907 mComponentName.c_str(), colorFormat);
2908 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
2909 }
2910 } else {
2911 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
2912 }
2913
2914 if (err != OK) {
2915 return err;
2916 }
2917
2918 int32_t frameRateInt;
2919 float frameRateFloat;
2920 if (!msg->findFloat("frame-rate", &frameRateFloat)) {
2921 if (!msg->findInt32("frame-rate", &frameRateInt)) {
2922 frameRateInt = -1;
2923 }
2924 frameRateFloat = (float)frameRateInt;
2925 }
2926
2927 err = setVideoFormatOnPort(
2928 kPortIndexInput, width, height, compressionFormat, frameRateFloat);
2929
2930 if (err != OK) {
2931 return err;
2932 }
2933
2934 err = setVideoFormatOnPort(
2935 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
2936
2937 if (err != OK) {
2938 return err;
2939 }
2940
2941 return OK;
2942 }
2943
setupVideoEncoder(const char * mime,const sp<AMessage> & msg)2944 status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
2945 int32_t tmp;
2946 if (!msg->findInt32("color-format", &tmp)) {
2947 return INVALID_OPERATION;
2948 }
2949
2950 OMX_COLOR_FORMATTYPE colorFormat =
2951 static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2952
2953 status_t err = setVideoPortFormatType(
2954 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
2955
2956 if (err != OK) {
2957 ALOGE("[%s] does not support color format %d",
2958 mComponentName.c_str(), colorFormat);
2959
2960 return err;
2961 }
2962
2963 /* Input port configuration */
2964
2965 OMX_PARAM_PORTDEFINITIONTYPE def;
2966 InitOMXParams(&def);
2967
2968 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2969
2970 def.nPortIndex = kPortIndexInput;
2971
2972 err = mOMX->getParameter(
2973 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2974
2975 if (err != OK) {
2976 return err;
2977 }
2978
2979 int32_t width, height, bitrate;
2980 if (!msg->findInt32("width", &width)
2981 || !msg->findInt32("height", &height)
2982 || !msg->findInt32("bitrate", &bitrate)) {
2983 return INVALID_OPERATION;
2984 }
2985
2986 video_def->nFrameWidth = width;
2987 video_def->nFrameHeight = height;
2988
2989 int32_t stride;
2990 if (!msg->findInt32("stride", &stride)) {
2991 stride = width;
2992 }
2993
2994 video_def->nStride = stride;
2995
2996 int32_t sliceHeight;
2997 if (!msg->findInt32("slice-height", &sliceHeight)) {
2998 sliceHeight = height;
2999 }
3000
3001 video_def->nSliceHeight = sliceHeight;
3002
3003 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
3004
3005 float frameRate;
3006 if (!msg->findFloat("frame-rate", &frameRate)) {
3007 int32_t tmp;
3008 if (!msg->findInt32("frame-rate", &tmp)) {
3009 return INVALID_OPERATION;
3010 }
3011 frameRate = (float)tmp;
3012 mTimePerFrameUs = (int64_t) (1000000.0f / frameRate);
3013 }
3014
3015 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3016 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
3017 // this is redundant as it was already set up in setVideoPortFormatType
3018 // FIXME for now skip this only for flexible YUV formats
3019 if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
3020 video_def->eColorFormat = colorFormat;
3021 }
3022
3023 err = mOMX->setParameter(
3024 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3025
3026 if (err != OK) {
3027 ALOGE("[%s] failed to set input port definition parameters.",
3028 mComponentName.c_str());
3029
3030 return err;
3031 }
3032
3033 /* Output port configuration */
3034
3035 OMX_VIDEO_CODINGTYPE compressionFormat;
3036 err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3037
3038 if (err != OK) {
3039 return err;
3040 }
3041
3042 err = setVideoPortFormatType(
3043 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
3044
3045 if (err != OK) {
3046 ALOGE("[%s] does not support compression format %d",
3047 mComponentName.c_str(), compressionFormat);
3048
3049 return err;
3050 }
3051
3052 def.nPortIndex = kPortIndexOutput;
3053
3054 err = mOMX->getParameter(
3055 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3056
3057 if (err != OK) {
3058 return err;
3059 }
3060
3061 video_def->nFrameWidth = width;
3062 video_def->nFrameHeight = height;
3063 video_def->xFramerate = 0;
3064 video_def->nBitrate = bitrate;
3065 video_def->eCompressionFormat = compressionFormat;
3066 video_def->eColorFormat = OMX_COLOR_FormatUnused;
3067
3068 err = mOMX->setParameter(
3069 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3070
3071 if (err != OK) {
3072 ALOGE("[%s] failed to set output port definition parameters.",
3073 mComponentName.c_str());
3074
3075 return err;
3076 }
3077
3078 switch (compressionFormat) {
3079 case OMX_VIDEO_CodingMPEG4:
3080 err = setupMPEG4EncoderParameters(msg);
3081 break;
3082
3083 case OMX_VIDEO_CodingH263:
3084 err = setupH263EncoderParameters(msg);
3085 break;
3086
3087 case OMX_VIDEO_CodingAVC:
3088 err = setupAVCEncoderParameters(msg);
3089 break;
3090
3091 case OMX_VIDEO_CodingHEVC:
3092 err = setupHEVCEncoderParameters(msg);
3093 break;
3094
3095 case OMX_VIDEO_CodingVP8:
3096 case OMX_VIDEO_CodingVP9:
3097 err = setupVPXEncoderParameters(msg);
3098 break;
3099
3100 default:
3101 break;
3102 }
3103
3104 if (err == OK) {
3105 ALOGI("setupVideoEncoder succeeded");
3106 }
3107
3108 return err;
3109 }
3110
setCyclicIntraMacroblockRefresh(const sp<AMessage> & msg,int32_t mode)3111 status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
3112 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
3113 InitOMXParams(¶ms);
3114 params.nPortIndex = kPortIndexOutput;
3115
3116 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
3117
3118 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
3119 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3120 int32_t mbs;
3121 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
3122 return INVALID_OPERATION;
3123 }
3124 params.nCirMBs = mbs;
3125 }
3126
3127 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
3128 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3129 int32_t mbs;
3130 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
3131 return INVALID_OPERATION;
3132 }
3133 params.nAirMBs = mbs;
3134
3135 int32_t ref;
3136 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
3137 return INVALID_OPERATION;
3138 }
3139 params.nAirRef = ref;
3140 }
3141
3142 status_t err = mOMX->setParameter(
3143 mNode, OMX_IndexParamVideoIntraRefresh,
3144 ¶ms, sizeof(params));
3145 return err;
3146 }
3147
setPFramesSpacing(int32_t iFramesInterval,int32_t frameRate)3148 static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
3149 if (iFramesInterval < 0) {
3150 return 0xFFFFFFFF;
3151 } else if (iFramesInterval == 0) {
3152 return 0;
3153 }
3154 OMX_U32 ret = frameRate * iFramesInterval;
3155 return ret;
3156 }
3157
getBitrateMode(const sp<AMessage> & msg)3158 static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
3159 int32_t tmp;
3160 if (!msg->findInt32("bitrate-mode", &tmp)) {
3161 return OMX_Video_ControlRateVariable;
3162 }
3163
3164 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
3165 }
3166
setupMPEG4EncoderParameters(const sp<AMessage> & msg)3167 status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
3168 int32_t bitrate, iFrameInterval;
3169 if (!msg->findInt32("bitrate", &bitrate)
3170 || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3171 return INVALID_OPERATION;
3172 }
3173
3174 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3175
3176 float frameRate;
3177 if (!msg->findFloat("frame-rate", &frameRate)) {
3178 int32_t tmp;
3179 if (!msg->findInt32("frame-rate", &tmp)) {
3180 return INVALID_OPERATION;
3181 }
3182 frameRate = (float)tmp;
3183 }
3184
3185 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
3186 InitOMXParams(&mpeg4type);
3187 mpeg4type.nPortIndex = kPortIndexOutput;
3188
3189 status_t err = mOMX->getParameter(
3190 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
3191
3192 if (err != OK) {
3193 return err;
3194 }
3195
3196 mpeg4type.nSliceHeaderSpacing = 0;
3197 mpeg4type.bSVH = OMX_FALSE;
3198 mpeg4type.bGov = OMX_FALSE;
3199
3200 mpeg4type.nAllowedPictureTypes =
3201 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
3202
3203 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3204 if (mpeg4type.nPFrames == 0) {
3205 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3206 }
3207 mpeg4type.nBFrames = 0;
3208 mpeg4type.nIDCVLCThreshold = 0;
3209 mpeg4type.bACPred = OMX_TRUE;
3210 mpeg4type.nMaxPacketSize = 256;
3211 mpeg4type.nTimeIncRes = 1000;
3212 mpeg4type.nHeaderExtension = 0;
3213 mpeg4type.bReversibleVLC = OMX_FALSE;
3214
3215 int32_t profile;
3216 if (msg->findInt32("profile", &profile)) {
3217 int32_t level;
3218 if (!msg->findInt32("level", &level)) {
3219 return INVALID_OPERATION;
3220 }
3221
3222 err = verifySupportForProfileAndLevel(profile, level);
3223
3224 if (err != OK) {
3225 return err;
3226 }
3227
3228 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
3229 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
3230 }
3231
3232 err = mOMX->setParameter(
3233 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
3234
3235 if (err != OK) {
3236 return err;
3237 }
3238
3239 err = configureBitrate(bitrate, bitrateMode);
3240
3241 if (err != OK) {
3242 return err;
3243 }
3244
3245 return setupErrorCorrectionParameters();
3246 }
3247
setupH263EncoderParameters(const sp<AMessage> & msg)3248 status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
3249 int32_t bitrate, iFrameInterval;
3250 if (!msg->findInt32("bitrate", &bitrate)
3251 || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3252 return INVALID_OPERATION;
3253 }
3254
3255 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3256
3257 float frameRate;
3258 if (!msg->findFloat("frame-rate", &frameRate)) {
3259 int32_t tmp;
3260 if (!msg->findInt32("frame-rate", &tmp)) {
3261 return INVALID_OPERATION;
3262 }
3263 frameRate = (float)tmp;
3264 }
3265
3266 OMX_VIDEO_PARAM_H263TYPE h263type;
3267 InitOMXParams(&h263type);
3268 h263type.nPortIndex = kPortIndexOutput;
3269
3270 status_t err = mOMX->getParameter(
3271 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
3272
3273 if (err != OK) {
3274 return err;
3275 }
3276
3277 h263type.nAllowedPictureTypes =
3278 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
3279
3280 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3281 if (h263type.nPFrames == 0) {
3282 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3283 }
3284 h263type.nBFrames = 0;
3285
3286 int32_t profile;
3287 if (msg->findInt32("profile", &profile)) {
3288 int32_t level;
3289 if (!msg->findInt32("level", &level)) {
3290 return INVALID_OPERATION;
3291 }
3292
3293 err = verifySupportForProfileAndLevel(profile, level);
3294
3295 if (err != OK) {
3296 return err;
3297 }
3298
3299 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
3300 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
3301 }
3302
3303 h263type.bPLUSPTYPEAllowed = OMX_FALSE;
3304 h263type.bForceRoundingTypeToZero = OMX_FALSE;
3305 h263type.nPictureHeaderRepetition = 0;
3306 h263type.nGOBHeaderInterval = 0;
3307
3308 err = mOMX->setParameter(
3309 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
3310
3311 if (err != OK) {
3312 return err;
3313 }
3314
3315 err = configureBitrate(bitrate, bitrateMode);
3316
3317 if (err != OK) {
3318 return err;
3319 }
3320
3321 return setupErrorCorrectionParameters();
3322 }
3323
3324 // static
getAVCLevelFor(int width,int height,int rate,int bitrate,OMX_VIDEO_AVCPROFILETYPE profile)3325 int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
3326 int width, int height, int rate, int bitrate,
3327 OMX_VIDEO_AVCPROFILETYPE profile) {
3328 // convert bitrate to main/baseline profile kbps equivalent
3329 switch (profile) {
3330 case OMX_VIDEO_AVCProfileHigh10:
3331 bitrate = divUp(bitrate, 3000); break;
3332 case OMX_VIDEO_AVCProfileHigh:
3333 bitrate = divUp(bitrate, 1250); break;
3334 default:
3335 bitrate = divUp(bitrate, 1000); break;
3336 }
3337
3338 // convert size and rate to MBs
3339 width = divUp(width, 16);
3340 height = divUp(height, 16);
3341 int mbs = width * height;
3342 rate *= mbs;
3343 int maxDimension = max(width, height);
3344
3345 static const int limits[][5] = {
3346 /* MBps MB dim bitrate level */
3347 { 1485, 99, 28, 64, OMX_VIDEO_AVCLevel1 },
3348 { 1485, 99, 28, 128, OMX_VIDEO_AVCLevel1b },
3349 { 3000, 396, 56, 192, OMX_VIDEO_AVCLevel11 },
3350 { 6000, 396, 56, 384, OMX_VIDEO_AVCLevel12 },
3351 { 11880, 396, 56, 768, OMX_VIDEO_AVCLevel13 },
3352 { 11880, 396, 56, 2000, OMX_VIDEO_AVCLevel2 },
3353 { 19800, 792, 79, 4000, OMX_VIDEO_AVCLevel21 },
3354 { 20250, 1620, 113, 4000, OMX_VIDEO_AVCLevel22 },
3355 { 40500, 1620, 113, 10000, OMX_VIDEO_AVCLevel3 },
3356 { 108000, 3600, 169, 14000, OMX_VIDEO_AVCLevel31 },
3357 { 216000, 5120, 202, 20000, OMX_VIDEO_AVCLevel32 },
3358 { 245760, 8192, 256, 20000, OMX_VIDEO_AVCLevel4 },
3359 { 245760, 8192, 256, 50000, OMX_VIDEO_AVCLevel41 },
3360 { 522240, 8704, 263, 50000, OMX_VIDEO_AVCLevel42 },
3361 { 589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5 },
3362 { 983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
3363 { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
3364 };
3365
3366 for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
3367 const int (&limit)[5] = limits[i];
3368 if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
3369 && bitrate <= limit[3]) {
3370 return limit[4];
3371 }
3372 }
3373 return 0;
3374 }
3375
setupAVCEncoderParameters(const sp<AMessage> & msg)3376 status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
3377 int32_t bitrate, iFrameInterval;
3378 if (!msg->findInt32("bitrate", &bitrate)
3379 || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3380 return INVALID_OPERATION;
3381 }
3382
3383 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3384
3385 float frameRate;
3386 if (!msg->findFloat("frame-rate", &frameRate)) {
3387 int32_t tmp;
3388 if (!msg->findInt32("frame-rate", &tmp)) {
3389 return INVALID_OPERATION;
3390 }
3391 frameRate = (float)tmp;
3392 }
3393
3394 status_t err = OK;
3395 int32_t intraRefreshMode = 0;
3396 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
3397 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
3398 if (err != OK) {
3399 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
3400 err, intraRefreshMode);
3401 return err;
3402 }
3403 }
3404
3405 OMX_VIDEO_PARAM_AVCTYPE h264type;
3406 InitOMXParams(&h264type);
3407 h264type.nPortIndex = kPortIndexOutput;
3408
3409 err = mOMX->getParameter(
3410 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
3411
3412 if (err != OK) {
3413 return err;
3414 }
3415
3416 h264type.nAllowedPictureTypes =
3417 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
3418
3419 int32_t profile;
3420 if (msg->findInt32("profile", &profile)) {
3421 int32_t level;
3422 if (!msg->findInt32("level", &level)) {
3423 return INVALID_OPERATION;
3424 }
3425
3426 err = verifySupportForProfileAndLevel(profile, level);
3427
3428 if (err != OK) {
3429 return err;
3430 }
3431
3432 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
3433 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
3434 }
3435
3436 // XXX
3437 if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
3438 ALOGW("Use baseline profile instead of %d for AVC recording",
3439 h264type.eProfile);
3440 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
3441 }
3442
3443 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
3444 h264type.nSliceHeaderSpacing = 0;
3445 h264type.bUseHadamard = OMX_TRUE;
3446 h264type.nRefFrames = 1;
3447 h264type.nBFrames = 0;
3448 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3449 if (h264type.nPFrames == 0) {
3450 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3451 }
3452 h264type.nRefIdx10ActiveMinus1 = 0;
3453 h264type.nRefIdx11ActiveMinus1 = 0;
3454 h264type.bEntropyCodingCABAC = OMX_FALSE;
3455 h264type.bWeightedPPrediction = OMX_FALSE;
3456 h264type.bconstIpred = OMX_FALSE;
3457 h264type.bDirect8x8Inference = OMX_FALSE;
3458 h264type.bDirectSpatialTemporal = OMX_FALSE;
3459 h264type.nCabacInitIdc = 0;
3460 }
3461
3462 if (h264type.nBFrames != 0) {
3463 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
3464 }
3465
3466 h264type.bEnableUEP = OMX_FALSE;
3467 h264type.bEnableFMO = OMX_FALSE;
3468 h264type.bEnableASO = OMX_FALSE;
3469 h264type.bEnableRS = OMX_FALSE;
3470 h264type.bFrameMBsOnly = OMX_TRUE;
3471 h264type.bMBAFF = OMX_FALSE;
3472 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
3473
3474 err = mOMX->setParameter(
3475 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
3476
3477 if (err != OK) {
3478 return err;
3479 }
3480
3481 return configureBitrate(bitrate, bitrateMode);
3482 }
3483
setupHEVCEncoderParameters(const sp<AMessage> & msg)3484 status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
3485 int32_t bitrate, iFrameInterval;
3486 if (!msg->findInt32("bitrate", &bitrate)
3487 || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3488 return INVALID_OPERATION;
3489 }
3490
3491 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3492
3493 float frameRate;
3494 if (!msg->findFloat("frame-rate", &frameRate)) {
3495 int32_t tmp;
3496 if (!msg->findInt32("frame-rate", &tmp)) {
3497 return INVALID_OPERATION;
3498 }
3499 frameRate = (float)tmp;
3500 }
3501
3502 OMX_VIDEO_PARAM_HEVCTYPE hevcType;
3503 InitOMXParams(&hevcType);
3504 hevcType.nPortIndex = kPortIndexOutput;
3505
3506 status_t err = OK;
3507 err = mOMX->getParameter(
3508 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
3509 if (err != OK) {
3510 return err;
3511 }
3512
3513 int32_t profile;
3514 if (msg->findInt32("profile", &profile)) {
3515 int32_t level;
3516 if (!msg->findInt32("level", &level)) {
3517 return INVALID_OPERATION;
3518 }
3519
3520 err = verifySupportForProfileAndLevel(profile, level);
3521 if (err != OK) {
3522 return err;
3523 }
3524
3525 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
3526 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
3527 }
3528
3529 // TODO: Need OMX structure definition for setting iFrameInterval
3530
3531 err = mOMX->setParameter(
3532 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
3533 if (err != OK) {
3534 return err;
3535 }
3536
3537 return configureBitrate(bitrate, bitrateMode);
3538 }
3539
setupVPXEncoderParameters(const sp<AMessage> & msg)3540 status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
3541 int32_t bitrate;
3542 int32_t iFrameInterval = 0;
3543 size_t tsLayers = 0;
3544 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
3545 OMX_VIDEO_VPXTemporalLayerPatternNone;
3546 static const uint32_t kVp8LayerRateAlloction
3547 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
3548 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
3549 {100, 100, 100}, // 1 layer
3550 { 60, 100, 100}, // 2 layers {60%, 40%}
3551 { 40, 60, 100}, // 3 layers {40%, 20%, 40%}
3552 };
3553 if (!msg->findInt32("bitrate", &bitrate)) {
3554 return INVALID_OPERATION;
3555 }
3556 msg->findInt32("i-frame-interval", &iFrameInterval);
3557
3558 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3559
3560 float frameRate;
3561 if (!msg->findFloat("frame-rate", &frameRate)) {
3562 int32_t tmp;
3563 if (!msg->findInt32("frame-rate", &tmp)) {
3564 return INVALID_OPERATION;
3565 }
3566 frameRate = (float)tmp;
3567 }
3568
3569 AString tsSchema;
3570 if (msg->findString("ts-schema", &tsSchema)) {
3571 if (tsSchema == "webrtc.vp8.1-layer") {
3572 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3573 tsLayers = 1;
3574 } else if (tsSchema == "webrtc.vp8.2-layer") {
3575 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3576 tsLayers = 2;
3577 } else if (tsSchema == "webrtc.vp8.3-layer") {
3578 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3579 tsLayers = 3;
3580 } else {
3581 ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
3582 }
3583 }
3584
3585 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3586 InitOMXParams(&vp8type);
3587 vp8type.nPortIndex = kPortIndexOutput;
3588 status_t err = mOMX->getParameter(
3589 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3590 &vp8type, sizeof(vp8type));
3591
3592 if (err == OK) {
3593 if (iFrameInterval > 0) {
3594 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
3595 }
3596 vp8type.eTemporalPattern = pattern;
3597 vp8type.nTemporalLayerCount = tsLayers;
3598 if (tsLayers > 0) {
3599 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
3600 vp8type.nTemporalLayerBitrateRatio[i] =
3601 kVp8LayerRateAlloction[tsLayers - 1][i];
3602 }
3603 }
3604 if (bitrateMode == OMX_Video_ControlRateConstant) {
3605 vp8type.nMinQuantizer = 2;
3606 vp8type.nMaxQuantizer = 63;
3607 }
3608
3609 err = mOMX->setParameter(
3610 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3611 &vp8type, sizeof(vp8type));
3612 if (err != OK) {
3613 ALOGW("Extended VP8 parameters set failed: %d", err);
3614 }
3615 }
3616
3617 return configureBitrate(bitrate, bitrateMode);
3618 }
3619
verifySupportForProfileAndLevel(int32_t profile,int32_t level)3620 status_t ACodec::verifySupportForProfileAndLevel(
3621 int32_t profile, int32_t level) {
3622 OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
3623 InitOMXParams(¶ms);
3624 params.nPortIndex = kPortIndexOutput;
3625
3626 for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
3627 status_t err = mOMX->getParameter(
3628 mNode,
3629 OMX_IndexParamVideoProfileLevelQuerySupported,
3630 ¶ms,
3631 sizeof(params));
3632
3633 if (err != OK) {
3634 return err;
3635 }
3636
3637 int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
3638 int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
3639
3640 if (profile == supportedProfile && level <= supportedLevel) {
3641 return OK;
3642 }
3643 }
3644 }
3645
configureBitrate(int32_t bitrate,OMX_VIDEO_CONTROLRATETYPE bitrateMode)3646 status_t ACodec::configureBitrate(
3647 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
3648 OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
3649 InitOMXParams(&bitrateType);
3650 bitrateType.nPortIndex = kPortIndexOutput;
3651
3652 status_t err = mOMX->getParameter(
3653 mNode, OMX_IndexParamVideoBitrate,
3654 &bitrateType, sizeof(bitrateType));
3655
3656 if (err != OK) {
3657 return err;
3658 }
3659
3660 bitrateType.eControlRate = bitrateMode;
3661 bitrateType.nTargetBitrate = bitrate;
3662
3663 return mOMX->setParameter(
3664 mNode, OMX_IndexParamVideoBitrate,
3665 &bitrateType, sizeof(bitrateType));
3666 }
3667
setupErrorCorrectionParameters()3668 status_t ACodec::setupErrorCorrectionParameters() {
3669 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
3670 InitOMXParams(&errorCorrectionType);
3671 errorCorrectionType.nPortIndex = kPortIndexOutput;
3672
3673 status_t err = mOMX->getParameter(
3674 mNode, OMX_IndexParamVideoErrorCorrection,
3675 &errorCorrectionType, sizeof(errorCorrectionType));
3676
3677 if (err != OK) {
3678 return OK; // Optional feature. Ignore this failure
3679 }
3680
3681 errorCorrectionType.bEnableHEC = OMX_FALSE;
3682 errorCorrectionType.bEnableResync = OMX_TRUE;
3683 errorCorrectionType.nResynchMarkerSpacing = 256;
3684 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
3685 errorCorrectionType.bEnableRVLC = OMX_FALSE;
3686
3687 return mOMX->setParameter(
3688 mNode, OMX_IndexParamVideoErrorCorrection,
3689 &errorCorrectionType, sizeof(errorCorrectionType));
3690 }
3691
setVideoFormatOnPort(OMX_U32 portIndex,int32_t width,int32_t height,OMX_VIDEO_CODINGTYPE compressionFormat,float frameRate)3692 status_t ACodec::setVideoFormatOnPort(
3693 OMX_U32 portIndex,
3694 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
3695 float frameRate) {
3696 OMX_PARAM_PORTDEFINITIONTYPE def;
3697 InitOMXParams(&def);
3698 def.nPortIndex = portIndex;
3699
3700 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3701
3702 status_t err = mOMX->getParameter(
3703 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3704 if (err != OK) {
3705 return err;
3706 }
3707
3708 if (portIndex == kPortIndexInput) {
3709 // XXX Need a (much) better heuristic to compute input buffer sizes.
3710 const size_t X = 64 * 1024;
3711 if (def.nBufferSize < X) {
3712 def.nBufferSize = X;
3713 }
3714 }
3715
3716 if (def.eDomain != OMX_PortDomainVideo) {
3717 ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain);
3718 return FAILED_TRANSACTION;
3719 }
3720
3721 video_def->nFrameWidth = width;
3722 video_def->nFrameHeight = height;
3723
3724 if (portIndex == kPortIndexInput) {
3725 video_def->eCompressionFormat = compressionFormat;
3726 video_def->eColorFormat = OMX_COLOR_FormatUnused;
3727 if (frameRate >= 0) {
3728 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3729 }
3730 }
3731
3732 err = mOMX->setParameter(
3733 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3734
3735 return err;
3736 }
3737
initNativeWindow()3738 status_t ACodec::initNativeWindow() {
3739 if (mNativeWindow != NULL) {
3740 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
3741 }
3742
3743 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
3744 return OK;
3745 }
3746
countBuffersOwnedByComponent(OMX_U32 portIndex) const3747 size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
3748 size_t n = 0;
3749
3750 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3751 const BufferInfo &info = mBuffers[portIndex].itemAt(i);
3752
3753 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
3754 ++n;
3755 }
3756 }
3757
3758 return n;
3759 }
3760
countBuffersOwnedByNativeWindow() const3761 size_t ACodec::countBuffersOwnedByNativeWindow() const {
3762 size_t n = 0;
3763
3764 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
3765 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
3766
3767 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3768 ++n;
3769 }
3770 }
3771
3772 return n;
3773 }
3774
waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs()3775 void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
3776 if (mNativeWindow == NULL) {
3777 return;
3778 }
3779
3780 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
3781 && dequeueBufferFromNativeWindow() != NULL) {
3782 // these buffers will be submitted as regular buffers; account for this
3783 if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) {
3784 --mMetadataBuffersToSubmit;
3785 }
3786 }
3787 }
3788
allYourBuffersAreBelongToUs(OMX_U32 portIndex)3789 bool ACodec::allYourBuffersAreBelongToUs(
3790 OMX_U32 portIndex) {
3791 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3792 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
3793
3794 if (info->mStatus != BufferInfo::OWNED_BY_US
3795 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3796 ALOGV("[%s] Buffer %u on port %u still has status %d",
3797 mComponentName.c_str(),
3798 info->mBufferID, portIndex, info->mStatus);
3799 return false;
3800 }
3801 }
3802
3803 return true;
3804 }
3805
allYourBuffersAreBelongToUs()3806 bool ACodec::allYourBuffersAreBelongToUs() {
3807 return allYourBuffersAreBelongToUs(kPortIndexInput)
3808 && allYourBuffersAreBelongToUs(kPortIndexOutput);
3809 }
3810
deferMessage(const sp<AMessage> & msg)3811 void ACodec::deferMessage(const sp<AMessage> &msg) {
3812 mDeferredQueue.push_back(msg);
3813 }
3814
processDeferredMessages()3815 void ACodec::processDeferredMessages() {
3816 List<sp<AMessage> > queue = mDeferredQueue;
3817 mDeferredQueue.clear();
3818
3819 List<sp<AMessage> >::iterator it = queue.begin();
3820 while (it != queue.end()) {
3821 onMessageReceived(*it++);
3822 }
3823 }
3824
3825 // static
describeDefaultColorFormat(DescribeColorFormatParams & params)3826 bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams ¶ms) {
3827 MediaImage &image = params.sMediaImage;
3828 memset(&image, 0, sizeof(image));
3829
3830 image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3831 image.mNumPlanes = 0;
3832
3833 const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
3834 image.mWidth = params.nFrameWidth;
3835 image.mHeight = params.nFrameHeight;
3836
3837 // only supporting YUV420
3838 if (fmt != OMX_COLOR_FormatYUV420Planar &&
3839 fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
3840 fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
3841 fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
3842 fmt != HAL_PIXEL_FORMAT_YV12) {
3843 ALOGW("do not know color format 0x%x = %d", fmt, fmt);
3844 return false;
3845 }
3846
3847 // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
3848 if (params.nStride != 0 && params.nSliceHeight == 0) {
3849 ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
3850 params.nFrameHeight);
3851 params.nSliceHeight = params.nFrameHeight;
3852 }
3853
3854 // we need stride and slice-height to be non-zero
3855 if (params.nStride == 0 || params.nSliceHeight == 0) {
3856 ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
3857 fmt, fmt, params.nStride, params.nSliceHeight);
3858 return false;
3859 }
3860
3861 // set-up YUV format
3862 image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
3863 image.mNumPlanes = 3;
3864 image.mBitDepth = 8;
3865 image.mPlane[image.Y].mOffset = 0;
3866 image.mPlane[image.Y].mColInc = 1;
3867 image.mPlane[image.Y].mRowInc = params.nStride;
3868 image.mPlane[image.Y].mHorizSubsampling = 1;
3869 image.mPlane[image.Y].mVertSubsampling = 1;
3870
3871 switch ((int)fmt) {
3872 case HAL_PIXEL_FORMAT_YV12:
3873 if (params.bUsingNativeBuffers) {
3874 size_t ystride = align(params.nStride, 16);
3875 size_t cstride = align(params.nStride / 2, 16);
3876 image.mPlane[image.Y].mRowInc = ystride;
3877
3878 image.mPlane[image.V].mOffset = ystride * params.nSliceHeight;
3879 image.mPlane[image.V].mColInc = 1;
3880 image.mPlane[image.V].mRowInc = cstride;
3881 image.mPlane[image.V].mHorizSubsampling = 2;
3882 image.mPlane[image.V].mVertSubsampling = 2;
3883
3884 image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset
3885 + (cstride * params.nSliceHeight / 2);
3886 image.mPlane[image.U].mColInc = 1;
3887 image.mPlane[image.U].mRowInc = cstride;
3888 image.mPlane[image.U].mHorizSubsampling = 2;
3889 image.mPlane[image.U].mVertSubsampling = 2;
3890 break;
3891 } else {
3892 // fall through as YV12 is used for YUV420Planar by some codecs
3893 }
3894
3895 case OMX_COLOR_FormatYUV420Planar:
3896 case OMX_COLOR_FormatYUV420PackedPlanar:
3897 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3898 image.mPlane[image.U].mColInc = 1;
3899 image.mPlane[image.U].mRowInc = params.nStride / 2;
3900 image.mPlane[image.U].mHorizSubsampling = 2;
3901 image.mPlane[image.U].mVertSubsampling = 2;
3902
3903 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
3904 + (params.nStride * params.nSliceHeight / 4);
3905 image.mPlane[image.V].mColInc = 1;
3906 image.mPlane[image.V].mRowInc = params.nStride / 2;
3907 image.mPlane[image.V].mHorizSubsampling = 2;
3908 image.mPlane[image.V].mVertSubsampling = 2;
3909 break;
3910
3911 case OMX_COLOR_FormatYUV420SemiPlanar:
3912 // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
3913 case OMX_COLOR_FormatYUV420PackedSemiPlanar:
3914 // NV12
3915 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3916 image.mPlane[image.U].mColInc = 2;
3917 image.mPlane[image.U].mRowInc = params.nStride;
3918 image.mPlane[image.U].mHorizSubsampling = 2;
3919 image.mPlane[image.U].mVertSubsampling = 2;
3920
3921 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
3922 image.mPlane[image.V].mColInc = 2;
3923 image.mPlane[image.V].mRowInc = params.nStride;
3924 image.mPlane[image.V].mHorizSubsampling = 2;
3925 image.mPlane[image.V].mVertSubsampling = 2;
3926 break;
3927
3928 default:
3929 TRESPASS();
3930 }
3931 return true;
3932 }
3933
3934 // static
describeColorFormat(const sp<IOMX> & omx,IOMX::node_id node,DescribeColorFormatParams & describeParams)3935 bool ACodec::describeColorFormat(
3936 const sp<IOMX> &omx, IOMX::node_id node,
3937 DescribeColorFormatParams &describeParams)
3938 {
3939 OMX_INDEXTYPE describeColorFormatIndex;
3940 if (omx->getExtensionIndex(
3941 node, "OMX.google.android.index.describeColorFormat",
3942 &describeColorFormatIndex) != OK ||
3943 omx->getParameter(
3944 node, describeColorFormatIndex,
3945 &describeParams, sizeof(describeParams)) != OK) {
3946 return describeDefaultColorFormat(describeParams);
3947 }
3948 return describeParams.sMediaImage.mType !=
3949 MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3950 }
3951
3952 // static
isFlexibleColorFormat(const sp<IOMX> & omx,IOMX::node_id node,uint32_t colorFormat,bool usingNativeBuffers,OMX_U32 * flexibleEquivalent)3953 bool ACodec::isFlexibleColorFormat(
3954 const sp<IOMX> &omx, IOMX::node_id node,
3955 uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
3956 DescribeColorFormatParams describeParams;
3957 InitOMXParams(&describeParams);
3958 describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
3959 // reasonable dummy values
3960 describeParams.nFrameWidth = 128;
3961 describeParams.nFrameHeight = 128;
3962 describeParams.nStride = 128;
3963 describeParams.nSliceHeight = 128;
3964 describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
3965
3966 CHECK(flexibleEquivalent != NULL);
3967
3968 if (!describeColorFormat(omx, node, describeParams)) {
3969 return false;
3970 }
3971
3972 const MediaImage &img = describeParams.sMediaImage;
3973 if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) {
3974 if (img.mNumPlanes != 3 ||
3975 img.mPlane[img.Y].mHorizSubsampling != 1 ||
3976 img.mPlane[img.Y].mVertSubsampling != 1) {
3977 return false;
3978 }
3979
3980 // YUV 420
3981 if (img.mPlane[img.U].mHorizSubsampling == 2
3982 && img.mPlane[img.U].mVertSubsampling == 2
3983 && img.mPlane[img.V].mHorizSubsampling == 2
3984 && img.mPlane[img.V].mVertSubsampling == 2) {
3985 // possible flexible YUV420 format
3986 if (img.mBitDepth <= 8) {
3987 *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
3988 return true;
3989 }
3990 }
3991 }
3992 return false;
3993 }
3994
getPortFormat(OMX_U32 portIndex,sp<AMessage> & notify)3995 status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) {
3996 const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
3997 OMX_PARAM_PORTDEFINITIONTYPE def;
3998 InitOMXParams(&def);
3999 def.nPortIndex = portIndex;
4000
4001 status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
4002 if (err != OK) {
4003 return err;
4004 }
4005
4006 if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) {
4007 ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex);
4008 return BAD_VALUE;
4009 }
4010
4011 switch (def.eDomain) {
4012 case OMX_PortDomainVideo:
4013 {
4014 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
4015 switch ((int)videoDef->eCompressionFormat) {
4016 case OMX_VIDEO_CodingUnused:
4017 {
4018 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
4019 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
4020
4021 notify->setInt32("stride", videoDef->nStride);
4022 notify->setInt32("slice-height", videoDef->nSliceHeight);
4023 notify->setInt32("color-format", videoDef->eColorFormat);
4024
4025 if (mNativeWindow == NULL) {
4026 DescribeColorFormatParams describeParams;
4027 InitOMXParams(&describeParams);
4028 describeParams.eColorFormat = videoDef->eColorFormat;
4029 describeParams.nFrameWidth = videoDef->nFrameWidth;
4030 describeParams.nFrameHeight = videoDef->nFrameHeight;
4031 describeParams.nStride = videoDef->nStride;
4032 describeParams.nSliceHeight = videoDef->nSliceHeight;
4033 describeParams.bUsingNativeBuffers = OMX_FALSE;
4034
4035 if (describeColorFormat(mOMX, mNode, describeParams)) {
4036 notify->setBuffer(
4037 "image-data",
4038 ABuffer::CreateAsCopy(
4039 &describeParams.sMediaImage,
4040 sizeof(describeParams.sMediaImage)));
4041
4042 MediaImage *img = &describeParams.sMediaImage;
4043 ALOGV("[%s] MediaImage { F(%ux%u) @%u+%u+%u @%u+%u+%u @%u+%u+%u }",
4044 mComponentName.c_str(), img->mWidth, img->mHeight,
4045 img->mPlane[0].mOffset, img->mPlane[0].mColInc, img->mPlane[0].mRowInc,
4046 img->mPlane[1].mOffset, img->mPlane[1].mColInc, img->mPlane[1].mRowInc,
4047 img->mPlane[2].mOffset, img->mPlane[2].mColInc, img->mPlane[2].mRowInc);
4048 }
4049 }
4050
4051 if (portIndex != kPortIndexOutput) {
4052 // TODO: also get input crop
4053 break;
4054 }
4055
4056 OMX_CONFIG_RECTTYPE rect;
4057 InitOMXParams(&rect);
4058 rect.nPortIndex = portIndex;
4059
4060 if (mOMX->getConfig(
4061 mNode,
4062 (portIndex == kPortIndexOutput ?
4063 OMX_IndexConfigCommonOutputCrop :
4064 OMX_IndexConfigCommonInputCrop),
4065 &rect, sizeof(rect)) != OK) {
4066 rect.nLeft = 0;
4067 rect.nTop = 0;
4068 rect.nWidth = videoDef->nFrameWidth;
4069 rect.nHeight = videoDef->nFrameHeight;
4070 }
4071
4072 if (rect.nLeft < 0 ||
4073 rect.nTop < 0 ||
4074 rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
4075 rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
4076 ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)",
4077 rect.nLeft, rect.nTop,
4078 rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight,
4079 videoDef->nFrameWidth, videoDef->nFrameHeight);
4080 return BAD_VALUE;
4081 }
4082
4083 notify->setRect(
4084 "crop",
4085 rect.nLeft,
4086 rect.nTop,
4087 rect.nLeft + rect.nWidth - 1,
4088 rect.nTop + rect.nHeight - 1);
4089
4090 break;
4091 }
4092
4093 case OMX_VIDEO_CodingVP8:
4094 case OMX_VIDEO_CodingVP9:
4095 {
4096 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4097 InitOMXParams(&vp8type);
4098 vp8type.nPortIndex = kPortIndexOutput;
4099 status_t err = mOMX->getParameter(
4100 mNode,
4101 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4102 &vp8type,
4103 sizeof(vp8type));
4104
4105 if (err == OK) {
4106 AString tsSchema = "none";
4107 if (vp8type.eTemporalPattern
4108 == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
4109 switch (vp8type.nTemporalLayerCount) {
4110 case 1:
4111 {
4112 tsSchema = "webrtc.vp8.1-layer";
4113 break;
4114 }
4115 case 2:
4116 {
4117 tsSchema = "webrtc.vp8.2-layer";
4118 break;
4119 }
4120 case 3:
4121 {
4122 tsSchema = "webrtc.vp8.3-layer";
4123 break;
4124 }
4125 default:
4126 {
4127 break;
4128 }
4129 }
4130 }
4131 notify->setString("ts-schema", tsSchema);
4132 }
4133 // Fall through to set up mime.
4134 }
4135
4136 default:
4137 {
4138 if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
4139 // should be CodingUnused
4140 ALOGE("Raw port video compression format is %s(%d)",
4141 asString(videoDef->eCompressionFormat),
4142 videoDef->eCompressionFormat);
4143 return BAD_VALUE;
4144 }
4145 AString mime;
4146 if (GetMimeTypeForVideoCoding(
4147 videoDef->eCompressionFormat, &mime) != OK) {
4148 notify->setString("mime", "application/octet-stream");
4149 } else {
4150 notify->setString("mime", mime.c_str());
4151 }
4152 break;
4153 }
4154 }
4155 notify->setInt32("width", videoDef->nFrameWidth);
4156 notify->setInt32("height", videoDef->nFrameHeight);
4157 ALOGV("[%s] %s format is %s", mComponentName.c_str(),
4158 portIndex == kPortIndexInput ? "input" : "output",
4159 notify->debugString().c_str());
4160
4161 break;
4162 }
4163
4164 case OMX_PortDomainAudio:
4165 {
4166 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
4167
4168 switch ((int)audioDef->eEncoding) {
4169 case OMX_AUDIO_CodingPCM:
4170 {
4171 OMX_AUDIO_PARAM_PCMMODETYPE params;
4172 InitOMXParams(¶ms);
4173 params.nPortIndex = portIndex;
4174
4175 err = mOMX->getParameter(
4176 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
4177 if (err != OK) {
4178 return err;
4179 }
4180
4181 if (params.nChannels <= 0
4182 || (params.nChannels != 1 && !params.bInterleaved)
4183 || params.nBitPerSample != 16u
4184 || params.eNumData != OMX_NumericalDataSigned
4185 || params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
4186 ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ",
4187 params.nChannels,
4188 params.bInterleaved ? " interleaved" : "",
4189 params.nBitPerSample,
4190 asString(params.eNumData), params.eNumData,
4191 asString(params.ePCMMode), params.ePCMMode);
4192 return FAILED_TRANSACTION;
4193 }
4194
4195 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
4196 notify->setInt32("channel-count", params.nChannels);
4197 notify->setInt32("sample-rate", params.nSamplingRate);
4198
4199 if (mChannelMaskPresent) {
4200 notify->setInt32("channel-mask", mChannelMask);
4201 }
4202 break;
4203 }
4204
4205 case OMX_AUDIO_CodingAAC:
4206 {
4207 OMX_AUDIO_PARAM_AACPROFILETYPE params;
4208 InitOMXParams(¶ms);
4209 params.nPortIndex = portIndex;
4210
4211 err = mOMX->getParameter(
4212 mNode, OMX_IndexParamAudioAac, ¶ms, sizeof(params));
4213 if (err != OK) {
4214 return err;
4215 }
4216
4217 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
4218 notify->setInt32("channel-count", params.nChannels);
4219 notify->setInt32("sample-rate", params.nSampleRate);
4220 break;
4221 }
4222
4223 case OMX_AUDIO_CodingAMR:
4224 {
4225 OMX_AUDIO_PARAM_AMRTYPE params;
4226 InitOMXParams(¶ms);
4227 params.nPortIndex = portIndex;
4228
4229 err = mOMX->getParameter(
4230 mNode, OMX_IndexParamAudioAmr, ¶ms, sizeof(params));
4231 if (err != OK) {
4232 return err;
4233 }
4234
4235 notify->setInt32("channel-count", 1);
4236 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
4237 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
4238 notify->setInt32("sample-rate", 16000);
4239 } else {
4240 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
4241 notify->setInt32("sample-rate", 8000);
4242 }
4243 break;
4244 }
4245
4246 case OMX_AUDIO_CodingFLAC:
4247 {
4248 OMX_AUDIO_PARAM_FLACTYPE params;
4249 InitOMXParams(¶ms);
4250 params.nPortIndex = portIndex;
4251
4252 err = mOMX->getParameter(
4253 mNode, OMX_IndexParamAudioFlac, ¶ms, sizeof(params));
4254 if (err != OK) {
4255 return err;
4256 }
4257
4258 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
4259 notify->setInt32("channel-count", params.nChannels);
4260 notify->setInt32("sample-rate", params.nSampleRate);
4261 break;
4262 }
4263
4264 case OMX_AUDIO_CodingMP3:
4265 {
4266 OMX_AUDIO_PARAM_MP3TYPE params;
4267 InitOMXParams(¶ms);
4268 params.nPortIndex = portIndex;
4269
4270 err = mOMX->getParameter(
4271 mNode, OMX_IndexParamAudioMp3, ¶ms, sizeof(params));
4272 if (err != OK) {
4273 return err;
4274 }
4275
4276 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
4277 notify->setInt32("channel-count", params.nChannels);
4278 notify->setInt32("sample-rate", params.nSampleRate);
4279 break;
4280 }
4281
4282 case OMX_AUDIO_CodingVORBIS:
4283 {
4284 OMX_AUDIO_PARAM_VORBISTYPE params;
4285 InitOMXParams(¶ms);
4286 params.nPortIndex = portIndex;
4287
4288 err = mOMX->getParameter(
4289 mNode, OMX_IndexParamAudioVorbis, ¶ms, sizeof(params));
4290 if (err != OK) {
4291 return err;
4292 }
4293
4294 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
4295 notify->setInt32("channel-count", params.nChannels);
4296 notify->setInt32("sample-rate", params.nSampleRate);
4297 break;
4298 }
4299
4300 case OMX_AUDIO_CodingAndroidAC3:
4301 {
4302 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
4303 InitOMXParams(¶ms);
4304 params.nPortIndex = portIndex;
4305
4306 err = mOMX->getParameter(
4307 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
4308 ¶ms, sizeof(params));
4309 if (err != OK) {
4310 return err;
4311 }
4312
4313 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
4314 notify->setInt32("channel-count", params.nChannels);
4315 notify->setInt32("sample-rate", params.nSampleRate);
4316 break;
4317 }
4318
4319 case OMX_AUDIO_CodingAndroidEAC3:
4320 {
4321 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
4322 InitOMXParams(¶ms);
4323 params.nPortIndex = portIndex;
4324
4325 err = mOMX->getParameter(
4326 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
4327 ¶ms, sizeof(params));
4328 if (err != OK) {
4329 return err;
4330 }
4331
4332 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
4333 notify->setInt32("channel-count", params.nChannels);
4334 notify->setInt32("sample-rate", params.nSampleRate);
4335 break;
4336 }
4337
4338 case OMX_AUDIO_CodingAndroidOPUS:
4339 {
4340 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
4341 InitOMXParams(¶ms);
4342 params.nPortIndex = portIndex;
4343
4344 err = mOMX->getParameter(
4345 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
4346 ¶ms, sizeof(params));
4347 if (err != OK) {
4348 return err;
4349 }
4350
4351 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
4352 notify->setInt32("channel-count", params.nChannels);
4353 notify->setInt32("sample-rate", params.nSampleRate);
4354 break;
4355 }
4356
4357 case OMX_AUDIO_CodingG711:
4358 {
4359 OMX_AUDIO_PARAM_PCMMODETYPE params;
4360 InitOMXParams(¶ms);
4361 params.nPortIndex = portIndex;
4362
4363 err = mOMX->getParameter(
4364 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
4365 if (err != OK) {
4366 return err;
4367 }
4368
4369 const char *mime = NULL;
4370 if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
4371 mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
4372 } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
4373 mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
4374 } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
4375 mime = MEDIA_MIMETYPE_AUDIO_RAW;
4376 }
4377 notify->setString("mime", mime);
4378 notify->setInt32("channel-count", params.nChannels);
4379 notify->setInt32("sample-rate", params.nSamplingRate);
4380 break;
4381 }
4382
4383 case OMX_AUDIO_CodingGSMFR:
4384 {
4385 OMX_AUDIO_PARAM_PCMMODETYPE params;
4386 InitOMXParams(¶ms);
4387 params.nPortIndex = portIndex;
4388
4389 err = mOMX->getParameter(
4390 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
4391 if (err != OK) {
4392 return err;
4393 }
4394
4395 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
4396 notify->setInt32("channel-count", params.nChannels);
4397 notify->setInt32("sample-rate", params.nSamplingRate);
4398 break;
4399 }
4400
4401 default:
4402 ALOGE("Unsupported audio coding: %s(%d)\n",
4403 asString(audioDef->eEncoding), audioDef->eEncoding);
4404 return BAD_TYPE;
4405 }
4406 break;
4407 }
4408
4409 default:
4410 ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain);
4411 return BAD_TYPE;
4412 }
4413
4414 return OK;
4415 }
4416
sendFormatChange(const sp<AMessage> & reply)4417 void ACodec::sendFormatChange(const sp<AMessage> &reply) {
4418 sp<AMessage> notify = mBaseOutputFormat->dup();
4419 notify->setInt32("what", kWhatOutputFormatChanged);
4420
4421 if (getPortFormat(kPortIndexOutput, notify) != OK) {
4422 ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str());
4423 return;
4424 }
4425
4426 AString mime;
4427 CHECK(notify->findString("mime", &mime));
4428
4429 int32_t left, top, right, bottom;
4430 if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
4431 mNativeWindow != NULL &&
4432 notify->findRect("crop", &left, &top, &right, &bottom)) {
4433 // notify renderer of the crop change
4434 // NOTE: native window uses extended right-bottom coordinate
4435 reply->setRect("crop", left, top, right + 1, bottom + 1);
4436 } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
4437 (mEncoderDelay || mEncoderPadding)) {
4438 int32_t channelCount;
4439 CHECK(notify->findInt32("channel-count", &channelCount));
4440 size_t frameSize = channelCount * sizeof(int16_t);
4441 if (mSkipCutBuffer != NULL) {
4442 size_t prevbufsize = mSkipCutBuffer->size();
4443 if (prevbufsize != 0) {
4444 ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize);
4445 }
4446 }
4447 mSkipCutBuffer = new SkipCutBuffer(
4448 mEncoderDelay * frameSize,
4449 mEncoderPadding * frameSize);
4450 }
4451
4452 notify->post();
4453
4454 mSentFormat = true;
4455 }
4456
signalError(OMX_ERRORTYPE error,status_t internalError)4457 void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
4458 sp<AMessage> notify = mNotify->dup();
4459 notify->setInt32("what", CodecBase::kWhatError);
4460 ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
4461
4462 if (internalError == UNKNOWN_ERROR) { // find better error code
4463 const status_t omxStatus = statusFromOMXError(error);
4464 if (omxStatus != 0) {
4465 internalError = omxStatus;
4466 } else {
4467 ALOGW("Invalid OMX error %#x", error);
4468 }
4469 }
4470
4471 mFatalError = true;
4472
4473 notify->setInt32("err", internalError);
4474 notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
4475 notify->post();
4476 }
4477
4478 ////////////////////////////////////////////////////////////////////////////////
4479
PortDescription()4480 ACodec::PortDescription::PortDescription() {
4481 }
4482
requestIDRFrame()4483 status_t ACodec::requestIDRFrame() {
4484 if (!mIsEncoder) {
4485 return ERROR_UNSUPPORTED;
4486 }
4487
4488 OMX_CONFIG_INTRAREFRESHVOPTYPE params;
4489 InitOMXParams(¶ms);
4490
4491 params.nPortIndex = kPortIndexOutput;
4492 params.IntraRefreshVOP = OMX_TRUE;
4493
4494 return mOMX->setConfig(
4495 mNode,
4496 OMX_IndexConfigVideoIntraVOPRefresh,
4497 ¶ms,
4498 sizeof(params));
4499 }
4500
addBuffer(IOMX::buffer_id id,const sp<ABuffer> & buffer)4501 void ACodec::PortDescription::addBuffer(
4502 IOMX::buffer_id id, const sp<ABuffer> &buffer) {
4503 mBufferIDs.push_back(id);
4504 mBuffers.push_back(buffer);
4505 }
4506
countBuffers()4507 size_t ACodec::PortDescription::countBuffers() {
4508 return mBufferIDs.size();
4509 }
4510
bufferIDAt(size_t index) const4511 IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
4512 return mBufferIDs.itemAt(index);
4513 }
4514
bufferAt(size_t index) const4515 sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
4516 return mBuffers.itemAt(index);
4517 }
4518
4519 ////////////////////////////////////////////////////////////////////////////////
4520
BaseState(ACodec * codec,const sp<AState> & parentState)4521 ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
4522 : AState(parentState),
4523 mCodec(codec) {
4524 }
4525
getPortMode(OMX_U32)4526 ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
4527 OMX_U32 /* portIndex */) {
4528 return KEEP_BUFFERS;
4529 }
4530
onMessageReceived(const sp<AMessage> & msg)4531 bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
4532 switch (msg->what()) {
4533 case kWhatInputBufferFilled:
4534 {
4535 onInputBufferFilled(msg);
4536 break;
4537 }
4538
4539 case kWhatOutputBufferDrained:
4540 {
4541 onOutputBufferDrained(msg);
4542 break;
4543 }
4544
4545 case ACodec::kWhatOMXMessageList:
4546 {
4547 return checkOMXMessage(msg) ? onOMXMessageList(msg) : true;
4548 }
4549
4550 case ACodec::kWhatOMXMessageItem:
4551 {
4552 // no need to check as we already did it for kWhatOMXMessageList
4553 return onOMXMessage(msg);
4554 }
4555
4556 case ACodec::kWhatOMXMessage:
4557 {
4558 return checkOMXMessage(msg) ? onOMXMessage(msg) : true;
4559 }
4560
4561 case ACodec::kWhatSetSurface:
4562 {
4563 sp<AReplyToken> replyID;
4564 CHECK(msg->senderAwaitsResponse(&replyID));
4565
4566 sp<RefBase> obj;
4567 CHECK(msg->findObject("surface", &obj));
4568
4569 status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
4570
4571 sp<AMessage> response = new AMessage;
4572 response->setInt32("err", err);
4573 response->postReply(replyID);
4574 break;
4575 }
4576
4577 case ACodec::kWhatCreateInputSurface:
4578 case ACodec::kWhatSetInputSurface:
4579 case ACodec::kWhatSignalEndOfInputStream:
4580 {
4581 // This may result in an app illegal state exception.
4582 ALOGE("Message 0x%x was not handled", msg->what());
4583 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
4584 return true;
4585 }
4586
4587 case ACodec::kWhatOMXDied:
4588 {
4589 // This will result in kFlagSawMediaServerDie handling in MediaCodec.
4590 ALOGE("OMX/mediaserver died, signalling error!");
4591 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
4592 break;
4593 }
4594
4595 case ACodec::kWhatReleaseCodecInstance:
4596 {
4597 ALOGI("[%s] forcing the release of codec",
4598 mCodec->mComponentName.c_str());
4599 status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
4600 ALOGE_IF("[%s] failed to release codec instance: err=%d",
4601 mCodec->mComponentName.c_str(), err);
4602 sp<AMessage> notify = mCodec->mNotify->dup();
4603 notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4604 notify->post();
4605 break;
4606 }
4607
4608 default:
4609 return false;
4610 }
4611
4612 return true;
4613 }
4614
checkOMXMessage(const sp<AMessage> & msg)4615 bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) {
4616 // there is a possibility that this is an outstanding message for a
4617 // codec that we have already destroyed
4618 if (mCodec->mNode == 0) {
4619 ALOGI("ignoring message as already freed component: %s",
4620 msg->debugString().c_str());
4621 return false;
4622 }
4623
4624 IOMX::node_id nodeID;
4625 CHECK(msg->findInt32("node", (int32_t*)&nodeID));
4626 if (nodeID != mCodec->mNode) {
4627 ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode);
4628 return false;
4629 }
4630 return true;
4631 }
4632
onOMXMessageList(const sp<AMessage> & msg)4633 bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) {
4634 sp<RefBase> obj;
4635 CHECK(msg->findObject("messages", &obj));
4636 sp<MessageList> msgList = static_cast<MessageList *>(obj.get());
4637
4638 bool receivedRenderedEvents = false;
4639 for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin();
4640 it != msgList->getList().cend(); ++it) {
4641 (*it)->setWhat(ACodec::kWhatOMXMessageItem);
4642 mCodec->handleMessage(*it);
4643 int32_t type;
4644 CHECK((*it)->findInt32("type", &type));
4645 if (type == omx_message::FRAME_RENDERED) {
4646 receivedRenderedEvents = true;
4647 }
4648 }
4649
4650 if (receivedRenderedEvents) {
4651 // NOTE: all buffers are rendered in this case
4652 mCodec->notifyOfRenderedFrames();
4653 }
4654 return true;
4655 }
4656
onOMXMessage(const sp<AMessage> & msg)4657 bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
4658 int32_t type;
4659 CHECK(msg->findInt32("type", &type));
4660
4661 switch (type) {
4662 case omx_message::EVENT:
4663 {
4664 int32_t event, data1, data2;
4665 CHECK(msg->findInt32("event", &event));
4666 CHECK(msg->findInt32("data1", &data1));
4667 CHECK(msg->findInt32("data2", &data2));
4668
4669 if (event == OMX_EventCmdComplete
4670 && data1 == OMX_CommandFlush
4671 && data2 == (int32_t)OMX_ALL) {
4672 // Use of this notification is not consistent across
4673 // implementations. We'll drop this notification and rely
4674 // on flush-complete notifications on the individual port
4675 // indices instead.
4676
4677 return true;
4678 }
4679
4680 return onOMXEvent(
4681 static_cast<OMX_EVENTTYPE>(event),
4682 static_cast<OMX_U32>(data1),
4683 static_cast<OMX_U32>(data2));
4684 }
4685
4686 case omx_message::EMPTY_BUFFER_DONE:
4687 {
4688 IOMX::buffer_id bufferID;
4689 int32_t fenceFd;
4690
4691 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4692 CHECK(msg->findInt32("fence_fd", &fenceFd));
4693
4694 return onOMXEmptyBufferDone(bufferID, fenceFd);
4695 }
4696
4697 case omx_message::FILL_BUFFER_DONE:
4698 {
4699 IOMX::buffer_id bufferID;
4700 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4701
4702 int32_t rangeOffset, rangeLength, flags, fenceFd;
4703 int64_t timeUs;
4704
4705 CHECK(msg->findInt32("range_offset", &rangeOffset));
4706 CHECK(msg->findInt32("range_length", &rangeLength));
4707 CHECK(msg->findInt32("flags", &flags));
4708 CHECK(msg->findInt64("timestamp", &timeUs));
4709 CHECK(msg->findInt32("fence_fd", &fenceFd));
4710
4711 return onOMXFillBufferDone(
4712 bufferID,
4713 (size_t)rangeOffset, (size_t)rangeLength,
4714 (OMX_U32)flags,
4715 timeUs,
4716 fenceFd);
4717 }
4718
4719 case omx_message::FRAME_RENDERED:
4720 {
4721 int64_t mediaTimeUs, systemNano;
4722
4723 CHECK(msg->findInt64("media_time_us", &mediaTimeUs));
4724 CHECK(msg->findInt64("system_nano", &systemNano));
4725
4726 return onOMXFrameRendered(
4727 mediaTimeUs, systemNano);
4728 }
4729
4730 default:
4731 ALOGE("Unexpected message type: %d", type);
4732 return false;
4733 }
4734 }
4735
onOMXFrameRendered(int64_t mediaTimeUs __unused,nsecs_t systemNano __unused)4736 bool ACodec::BaseState::onOMXFrameRendered(
4737 int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) {
4738 // ignore outside of Executing and PortSettingsChanged states
4739 return true;
4740 }
4741
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)4742 bool ACodec::BaseState::onOMXEvent(
4743 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4744 if (event != OMX_EventError) {
4745 ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)",
4746 mCodec->mComponentName.c_str(), event, data1, data2);
4747
4748 return false;
4749 }
4750
4751 ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1);
4752
4753 // verify OMX component sends back an error we expect.
4754 OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
4755 if (!isOMXError(omxError)) {
4756 ALOGW("Invalid OMX error %#x", omxError);
4757 omxError = OMX_ErrorUndefined;
4758 }
4759 mCodec->signalError(omxError);
4760
4761 return true;
4762 }
4763
onOMXEmptyBufferDone(IOMX::buffer_id bufferID,int fenceFd)4764 bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) {
4765 ALOGV("[%s] onOMXEmptyBufferDone %u",
4766 mCodec->mComponentName.c_str(), bufferID);
4767
4768 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4769 BufferInfo::Status status = BufferInfo::getSafeStatus(info);
4770 if (status != BufferInfo::OWNED_BY_COMPONENT) {
4771 ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
4772 mCodec->dumpBuffers(kPortIndexInput);
4773 if (fenceFd >= 0) {
4774 ::close(fenceFd);
4775 }
4776 return false;
4777 }
4778 info->mStatus = BufferInfo::OWNED_BY_US;
4779
4780 // input buffers cannot take fences, so wait for any fence now
4781 (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone");
4782 fenceFd = -1;
4783
4784 // still save fence for completeness
4785 info->setWriteFence(fenceFd, "onOMXEmptyBufferDone");
4786
4787 // We're in "store-metadata-in-buffers" mode, the underlying
4788 // OMX component had access to data that's implicitly refcounted
4789 // by this "MediaBuffer" object. Now that the OMX component has
4790 // told us that it's done with the input buffer, we can decrement
4791 // the mediaBuffer's reference count.
4792 info->mData->setMediaBufferBase(NULL);
4793
4794 PortMode mode = getPortMode(kPortIndexInput);
4795
4796 switch (mode) {
4797 case KEEP_BUFFERS:
4798 break;
4799
4800 case RESUBMIT_BUFFERS:
4801 postFillThisBuffer(info);
4802 break;
4803
4804 case FREE_BUFFERS:
4805 default:
4806 ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers");
4807 return false;
4808 }
4809
4810 return true;
4811 }
4812
postFillThisBuffer(BufferInfo * info)4813 void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
4814 if (mCodec->mPortEOS[kPortIndexInput]) {
4815 return;
4816 }
4817
4818 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4819
4820 sp<AMessage> notify = mCodec->mNotify->dup();
4821 notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
4822 notify->setInt32("buffer-id", info->mBufferID);
4823
4824 info->mData->meta()->clear();
4825 notify->setBuffer("buffer", info->mData);
4826
4827 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec);
4828 reply->setInt32("buffer-id", info->mBufferID);
4829
4830 notify->setMessage("reply", reply);
4831
4832 notify->post();
4833
4834 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
4835 }
4836
onInputBufferFilled(const sp<AMessage> & msg)4837 void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
4838 IOMX::buffer_id bufferID;
4839 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4840 sp<ABuffer> buffer;
4841 int32_t err = OK;
4842 bool eos = false;
4843 PortMode mode = getPortMode(kPortIndexInput);
4844
4845 if (!msg->findBuffer("buffer", &buffer)) {
4846 /* these are unfilled buffers returned by client */
4847 CHECK(msg->findInt32("err", &err));
4848
4849 if (err == OK) {
4850 /* buffers with no errors are returned on MediaCodec.flush */
4851 mode = KEEP_BUFFERS;
4852 } else {
4853 ALOGV("[%s] saw error %d instead of an input buffer",
4854 mCodec->mComponentName.c_str(), err);
4855 eos = true;
4856 }
4857
4858 buffer.clear();
4859 }
4860
4861 int32_t tmp;
4862 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
4863 eos = true;
4864 err = ERROR_END_OF_STREAM;
4865 }
4866
4867 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4868 BufferInfo::Status status = BufferInfo::getSafeStatus(info);
4869 if (status != BufferInfo::OWNED_BY_UPSTREAM) {
4870 ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID);
4871 mCodec->dumpBuffers(kPortIndexInput);
4872 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
4873 return;
4874 }
4875
4876 info->mStatus = BufferInfo::OWNED_BY_US;
4877
4878 switch (mode) {
4879 case KEEP_BUFFERS:
4880 {
4881 if (eos) {
4882 if (!mCodec->mPortEOS[kPortIndexInput]) {
4883 mCodec->mPortEOS[kPortIndexInput] = true;
4884 mCodec->mInputEOSResult = err;
4885 }
4886 }
4887 break;
4888 }
4889
4890 case RESUBMIT_BUFFERS:
4891 {
4892 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
4893 // Do not send empty input buffer w/o EOS to the component.
4894 if (buffer->size() == 0 && !eos) {
4895 postFillThisBuffer(info);
4896 break;
4897 }
4898
4899 int64_t timeUs;
4900 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
4901
4902 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
4903
4904 int32_t isCSD;
4905 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
4906 flags |= OMX_BUFFERFLAG_CODECCONFIG;
4907 }
4908
4909 if (eos) {
4910 flags |= OMX_BUFFERFLAG_EOS;
4911 }
4912
4913 if (buffer != info->mData) {
4914 ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)",
4915 mCodec->mComponentName.c_str(),
4916 bufferID,
4917 buffer.get(), info->mData.get());
4918
4919 if (buffer->size() > info->mData->capacity()) {
4920 ALOGE("data size (%zu) is greated than buffer capacity (%zu)",
4921 buffer->size(), // this is the data received
4922 info->mData->capacity()); // this is out buffer size
4923 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
4924 return;
4925 }
4926 memcpy(info->mData->data(), buffer->data(), buffer->size());
4927 }
4928
4929 if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
4930 ALOGV("[%s] calling emptyBuffer %u w/ codec specific data",
4931 mCodec->mComponentName.c_str(), bufferID);
4932 } else if (flags & OMX_BUFFERFLAG_EOS) {
4933 ALOGV("[%s] calling emptyBuffer %u w/ EOS",
4934 mCodec->mComponentName.c_str(), bufferID);
4935 } else {
4936 #if TRACK_BUFFER_TIMING
4937 ALOGI("[%s] calling emptyBuffer %u w/ time %lld us",
4938 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
4939 #else
4940 ALOGV("[%s] calling emptyBuffer %u w/ time %lld us",
4941 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
4942 #endif
4943 }
4944
4945 #if TRACK_BUFFER_TIMING
4946 ACodec::BufferStats stats;
4947 stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
4948 stats.mFillBufferDoneTimeUs = -1ll;
4949 mCodec->mBufferStats.add(timeUs, stats);
4950 #endif
4951
4952 if (mCodec->storingMetadataInDecodedBuffers()) {
4953 // try to submit an output buffer for each input buffer
4954 PortMode outputMode = getPortMode(kPortIndexOutput);
4955
4956 ALOGV("MetadataBuffersToSubmit=%u portMode=%s",
4957 mCodec->mMetadataBuffersToSubmit,
4958 (outputMode == FREE_BUFFERS ? "FREE" :
4959 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
4960 if (outputMode == RESUBMIT_BUFFERS) {
4961 mCodec->submitOutputMetadataBuffer();
4962 }
4963 }
4964 info->checkReadFence("onInputBufferFilled");
4965 status_t err2 = mCodec->mOMX->emptyBuffer(
4966 mCodec->mNode,
4967 bufferID,
4968 0,
4969 buffer->size(),
4970 flags,
4971 timeUs,
4972 info->mFenceFd);
4973 info->mFenceFd = -1;
4974 if (err2 != OK) {
4975 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
4976 return;
4977 }
4978 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4979
4980 if (!eos && err == OK) {
4981 getMoreInputDataIfPossible();
4982 } else {
4983 ALOGV("[%s] Signalled EOS (%d) on the input port",
4984 mCodec->mComponentName.c_str(), err);
4985
4986 mCodec->mPortEOS[kPortIndexInput] = true;
4987 mCodec->mInputEOSResult = err;
4988 }
4989 } else if (!mCodec->mPortEOS[kPortIndexInput]) {
4990 if (err != OK && err != ERROR_END_OF_STREAM) {
4991 ALOGV("[%s] Signalling EOS on the input port due to error %d",
4992 mCodec->mComponentName.c_str(), err);
4993 } else {
4994 ALOGV("[%s] Signalling EOS on the input port",
4995 mCodec->mComponentName.c_str());
4996 }
4997
4998 ALOGV("[%s] calling emptyBuffer %u signalling EOS",
4999 mCodec->mComponentName.c_str(), bufferID);
5000
5001 info->checkReadFence("onInputBufferFilled");
5002 status_t err2 = mCodec->mOMX->emptyBuffer(
5003 mCodec->mNode,
5004 bufferID,
5005 0,
5006 0,
5007 OMX_BUFFERFLAG_EOS,
5008 0,
5009 info->mFenceFd);
5010 info->mFenceFd = -1;
5011 if (err2 != OK) {
5012 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5013 return;
5014 }
5015 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5016
5017 mCodec->mPortEOS[kPortIndexInput] = true;
5018 mCodec->mInputEOSResult = err;
5019 }
5020 break;
5021 }
5022
5023 case FREE_BUFFERS:
5024 break;
5025
5026 default:
5027 ALOGE("invalid port mode: %d", mode);
5028 break;
5029 }
5030 }
5031
getMoreInputDataIfPossible()5032 void ACodec::BaseState::getMoreInputDataIfPossible() {
5033 if (mCodec->mPortEOS[kPortIndexInput]) {
5034 return;
5035 }
5036
5037 BufferInfo *eligible = NULL;
5038
5039 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5040 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5041
5042 #if 0
5043 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
5044 // There's already a "read" pending.
5045 return;
5046 }
5047 #endif
5048
5049 if (info->mStatus == BufferInfo::OWNED_BY_US) {
5050 eligible = info;
5051 }
5052 }
5053
5054 if (eligible == NULL) {
5055 return;
5056 }
5057
5058 postFillThisBuffer(eligible);
5059 }
5060
onOMXFillBufferDone(IOMX::buffer_id bufferID,size_t rangeOffset,size_t rangeLength,OMX_U32 flags,int64_t timeUs,int fenceFd)5061 bool ACodec::BaseState::onOMXFillBufferDone(
5062 IOMX::buffer_id bufferID,
5063 size_t rangeOffset, size_t rangeLength,
5064 OMX_U32 flags,
5065 int64_t timeUs,
5066 int fenceFd) {
5067 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
5068 mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
5069
5070 ssize_t index;
5071 status_t err= OK;
5072
5073 #if TRACK_BUFFER_TIMING
5074 index = mCodec->mBufferStats.indexOfKey(timeUs);
5075 if (index >= 0) {
5076 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
5077 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
5078
5079 ALOGI("frame PTS %lld: %lld",
5080 timeUs,
5081 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
5082
5083 mCodec->mBufferStats.removeItemsAt(index);
5084 stats = NULL;
5085 }
5086 #endif
5087
5088 BufferInfo *info =
5089 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
5090 BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5091 if (status != BufferInfo::OWNED_BY_COMPONENT) {
5092 ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5093 mCodec->dumpBuffers(kPortIndexOutput);
5094 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5095 if (fenceFd >= 0) {
5096 ::close(fenceFd);
5097 }
5098 return true;
5099 }
5100
5101 info->mDequeuedAt = ++mCodec->mDequeueCounter;
5102 info->mStatus = BufferInfo::OWNED_BY_US;
5103
5104 if (info->mRenderInfo != NULL) {
5105 // The fence for an emptied buffer must have signaled, but there still could be queued
5106 // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these,
5107 // as we will soon requeue this buffer to the surface. While in theory we could still keep
5108 // track of buffers that are requeued to the surface, it is better to add support to the
5109 // buffer-queue to notify us of released buffers and their fences (in the future).
5110 mCodec->notifyOfRenderedFrames(true /* dropIncomplete */);
5111 }
5112
5113 // byte buffers cannot take fences, so wait for any fence now
5114 if (mCodec->mNativeWindow == NULL) {
5115 (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone");
5116 fenceFd = -1;
5117 }
5118 info->setReadFence(fenceFd, "onOMXFillBufferDone");
5119
5120 PortMode mode = getPortMode(kPortIndexOutput);
5121
5122 switch (mode) {
5123 case KEEP_BUFFERS:
5124 break;
5125
5126 case RESUBMIT_BUFFERS:
5127 {
5128 if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
5129 || mCodec->mPortEOS[kPortIndexOutput])) {
5130 ALOGV("[%s] calling fillBuffer %u",
5131 mCodec->mComponentName.c_str(), info->mBufferID);
5132
5133 err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
5134 info->mFenceFd = -1;
5135 if (err != OK) {
5136 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5137 return true;
5138 }
5139
5140 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5141 break;
5142 }
5143
5144 sp<AMessage> reply =
5145 new AMessage(kWhatOutputBufferDrained, mCodec);
5146
5147 if (!mCodec->mSentFormat && rangeLength > 0) {
5148 mCodec->sendFormatChange(reply);
5149 }
5150 if (mCodec->usingMetadataOnEncoderOutput()) {
5151 native_handle_t *handle = NULL;
5152 VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)info->mData->data();
5153 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)info->mData->data();
5154 if (info->mData->size() >= sizeof(grallocMeta)
5155 && grallocMeta.eType == kMetadataBufferTypeGrallocSource) {
5156 handle = (native_handle_t *)(uintptr_t)grallocMeta.pHandle;
5157 } else if (info->mData->size() >= sizeof(nativeMeta)
5158 && nativeMeta.eType == kMetadataBufferTypeANWBuffer) {
5159 #ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
5160 // ANativeWindowBuffer is only valid on 32-bit/mediaserver process
5161 handle = NULL;
5162 #else
5163 handle = (native_handle_t *)nativeMeta.pBuffer->handle;
5164 #endif
5165 }
5166 info->mData->meta()->setPointer("handle", handle);
5167 info->mData->meta()->setInt32("rangeOffset", rangeOffset);
5168 info->mData->meta()->setInt32("rangeLength", rangeLength);
5169 } else {
5170 info->mData->setRange(rangeOffset, rangeLength);
5171 }
5172 #if 0
5173 if (mCodec->mNativeWindow == NULL) {
5174 if (IsIDR(info->mData)) {
5175 ALOGI("IDR frame");
5176 }
5177 }
5178 #endif
5179
5180 if (mCodec->mSkipCutBuffer != NULL) {
5181 mCodec->mSkipCutBuffer->submit(info->mData);
5182 }
5183 info->mData->meta()->setInt64("timeUs", timeUs);
5184
5185 sp<AMessage> notify = mCodec->mNotify->dup();
5186 notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
5187 notify->setInt32("buffer-id", info->mBufferID);
5188 notify->setBuffer("buffer", info->mData);
5189 notify->setInt32("flags", flags);
5190
5191 reply->setInt32("buffer-id", info->mBufferID);
5192
5193 notify->setMessage("reply", reply);
5194
5195 notify->post();
5196
5197 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
5198
5199 if (flags & OMX_BUFFERFLAG_EOS) {
5200 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
5201
5202 sp<AMessage> notify = mCodec->mNotify->dup();
5203 notify->setInt32("what", CodecBase::kWhatEOS);
5204 notify->setInt32("err", mCodec->mInputEOSResult);
5205 notify->post();
5206
5207 mCodec->mPortEOS[kPortIndexOutput] = true;
5208 }
5209 break;
5210 }
5211
5212 case FREE_BUFFERS:
5213 err = mCodec->freeBuffer(kPortIndexOutput, index);
5214 if (err != OK) {
5215 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5216 return true;
5217 }
5218 break;
5219
5220 default:
5221 ALOGE("Invalid port mode: %d", mode);
5222 return false;
5223 }
5224
5225 return true;
5226 }
5227
onOutputBufferDrained(const sp<AMessage> & msg)5228 void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
5229 IOMX::buffer_id bufferID;
5230 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
5231 ssize_t index;
5232 BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
5233 BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5234 if (status != BufferInfo::OWNED_BY_DOWNSTREAM) {
5235 ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5236 mCodec->dumpBuffers(kPortIndexOutput);
5237 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5238 return;
5239 }
5240
5241 android_native_rect_t crop;
5242 if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {
5243 status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
5244 ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
5245 }
5246
5247 int32_t render;
5248 if (mCodec->mNativeWindow != NULL
5249 && msg->findInt32("render", &render) && render != 0
5250 && info->mData != NULL && info->mData->size() != 0) {
5251 ATRACE_NAME("render");
5252 // The client wants this buffer to be rendered.
5253
5254 // save buffers sent to the surface so we can get render time when they return
5255 int64_t mediaTimeUs = -1;
5256 info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
5257 if (mediaTimeUs >= 0) {
5258 mCodec->mRenderTracker.onFrameQueued(
5259 mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd)));
5260 }
5261
5262 int64_t timestampNs = 0;
5263 if (!msg->findInt64("timestampNs", ×tampNs)) {
5264 // use media timestamp if client did not request a specific render timestamp
5265 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) {
5266 ALOGV("using buffer PTS of %lld", (long long)timestampNs);
5267 timestampNs *= 1000;
5268 }
5269 }
5270
5271 status_t err;
5272 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
5273 ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);
5274
5275 info->checkReadFence("onOutputBufferDrained before queueBuffer");
5276 err = mCodec->mNativeWindow->queueBuffer(
5277 mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
5278 info->mFenceFd = -1;
5279 if (err == OK) {
5280 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
5281 } else {
5282 ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err);
5283 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5284 info->mStatus = BufferInfo::OWNED_BY_US;
5285 // keeping read fence as write fence to avoid clobbering
5286 info->mIsReadFence = false;
5287 }
5288 } else {
5289 if (mCodec->mNativeWindow != NULL &&
5290 (info->mData == NULL || info->mData->size() != 0)) {
5291 // move read fence into write fence to avoid clobbering
5292 info->mIsReadFence = false;
5293 ATRACE_NAME("frame-drop");
5294 }
5295 info->mStatus = BufferInfo::OWNED_BY_US;
5296 }
5297
5298 PortMode mode = getPortMode(kPortIndexOutput);
5299
5300 switch (mode) {
5301 case KEEP_BUFFERS:
5302 {
5303 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
5304
5305 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5306 // We cannot resubmit the buffer we just rendered, dequeue
5307 // the spare instead.
5308
5309 info = mCodec->dequeueBufferFromNativeWindow();
5310 }
5311 break;
5312 }
5313
5314 case RESUBMIT_BUFFERS:
5315 {
5316 if (!mCodec->mPortEOS[kPortIndexOutput]) {
5317 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5318 // We cannot resubmit the buffer we just rendered, dequeue
5319 // the spare instead.
5320
5321 info = mCodec->dequeueBufferFromNativeWindow();
5322 }
5323
5324 if (info != NULL) {
5325 ALOGV("[%s] calling fillBuffer %u",
5326 mCodec->mComponentName.c_str(), info->mBufferID);
5327 info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS");
5328 status_t err = mCodec->mOMX->fillBuffer(
5329 mCodec->mNode, info->mBufferID, info->mFenceFd);
5330 info->mFenceFd = -1;
5331 if (err == OK) {
5332 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5333 } else {
5334 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5335 }
5336 }
5337 }
5338 break;
5339 }
5340
5341 case FREE_BUFFERS:
5342 {
5343 status_t err = mCodec->freeBuffer(kPortIndexOutput, index);
5344 if (err != OK) {
5345 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5346 }
5347 break;
5348 }
5349
5350 default:
5351 ALOGE("Invalid port mode: %d", mode);
5352 return;
5353 }
5354 }
5355
5356 ////////////////////////////////////////////////////////////////////////////////
5357
UninitializedState(ACodec * codec)5358 ACodec::UninitializedState::UninitializedState(ACodec *codec)
5359 : BaseState(codec) {
5360 }
5361
stateEntered()5362 void ACodec::UninitializedState::stateEntered() {
5363 ALOGV("Now uninitialized");
5364
5365 if (mDeathNotifier != NULL) {
5366 IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier);
5367 mDeathNotifier.clear();
5368 }
5369
5370 mCodec->mNativeWindow.clear();
5371 mCodec->mNativeWindowUsageBits = 0;
5372 mCodec->mNode = 0;
5373 mCodec->mOMX.clear();
5374 mCodec->mQuirks = 0;
5375 mCodec->mFlags = 0;
5376 mCodec->mInputMetadataType = kMetadataBufferTypeInvalid;
5377 mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid;
5378 mCodec->mComponentName.clear();
5379 }
5380
onMessageReceived(const sp<AMessage> & msg)5381 bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
5382 bool handled = false;
5383
5384 switch (msg->what()) {
5385 case ACodec::kWhatSetup:
5386 {
5387 onSetup(msg);
5388
5389 handled = true;
5390 break;
5391 }
5392
5393 case ACodec::kWhatAllocateComponent:
5394 {
5395 onAllocateComponent(msg);
5396 handled = true;
5397 break;
5398 }
5399
5400 case ACodec::kWhatShutdown:
5401 {
5402 int32_t keepComponentAllocated;
5403 CHECK(msg->findInt32(
5404 "keepComponentAllocated", &keepComponentAllocated));
5405 ALOGW_IF(keepComponentAllocated,
5406 "cannot keep component allocated on shutdown in Uninitialized state");
5407
5408 sp<AMessage> notify = mCodec->mNotify->dup();
5409 notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5410 notify->post();
5411
5412 handled = true;
5413 break;
5414 }
5415
5416 case ACodec::kWhatFlush:
5417 {
5418 sp<AMessage> notify = mCodec->mNotify->dup();
5419 notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5420 notify->post();
5421
5422 handled = true;
5423 break;
5424 }
5425
5426 case ACodec::kWhatReleaseCodecInstance:
5427 {
5428 // nothing to do, as we have already signaled shutdown
5429 handled = true;
5430 break;
5431 }
5432
5433 default:
5434 return BaseState::onMessageReceived(msg);
5435 }
5436
5437 return handled;
5438 }
5439
onSetup(const sp<AMessage> & msg)5440 void ACodec::UninitializedState::onSetup(
5441 const sp<AMessage> &msg) {
5442 if (onAllocateComponent(msg)
5443 && mCodec->mLoadedState->onConfigureComponent(msg)) {
5444 mCodec->mLoadedState->onStart();
5445 }
5446 }
5447
onAllocateComponent(const sp<AMessage> & msg)5448 bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
5449 ALOGV("onAllocateComponent");
5450
5451 CHECK(mCodec->mNode == 0);
5452
5453 OMXClient client;
5454 if (client.connect() != OK) {
5455 mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
5456 return false;
5457 }
5458
5459 sp<IOMX> omx = client.interface();
5460
5461 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
5462
5463 mDeathNotifier = new DeathNotifier(notify);
5464 if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) {
5465 // This was a local binder, if it dies so do we, we won't care
5466 // about any notifications in the afterlife.
5467 mDeathNotifier.clear();
5468 }
5469
5470 Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
5471
5472 AString mime;
5473
5474 AString componentName;
5475 uint32_t quirks = 0;
5476 int32_t encoder = false;
5477 if (msg->findString("componentName", &componentName)) {
5478 ssize_t index = matchingCodecs.add();
5479 OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
5480 entry->mName = String8(componentName.c_str());
5481
5482 if (!OMXCodec::findCodecQuirks(
5483 componentName.c_str(), &entry->mQuirks)) {
5484 entry->mQuirks = 0;
5485 }
5486 } else {
5487 CHECK(msg->findString("mime", &mime));
5488
5489 if (!msg->findInt32("encoder", &encoder)) {
5490 encoder = false;
5491 }
5492
5493 OMXCodec::findMatchingCodecs(
5494 mime.c_str(),
5495 encoder, // createEncoder
5496 NULL, // matchComponentName
5497 0, // flags
5498 &matchingCodecs);
5499 }
5500
5501 sp<CodecObserver> observer = new CodecObserver;
5502 IOMX::node_id node = 0;
5503
5504 status_t err = NAME_NOT_FOUND;
5505 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
5506 ++matchIndex) {
5507 componentName = matchingCodecs.itemAt(matchIndex).mName.string();
5508 quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
5509
5510 pid_t tid = gettid();
5511 int prevPriority = androidGetThreadPriority(tid);
5512 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
5513 err = omx->allocateNode(componentName.c_str(), observer, &node);
5514 androidSetThreadPriority(tid, prevPriority);
5515
5516 if (err == OK) {
5517 break;
5518 } else {
5519 ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
5520 }
5521
5522 node = 0;
5523 }
5524
5525 if (node == 0) {
5526 if (!mime.empty()) {
5527 ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
5528 encoder ? "en" : "de", mime.c_str(), err);
5529 } else {
5530 ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
5531 }
5532
5533 mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
5534 return false;
5535 }
5536
5537 notify = new AMessage(kWhatOMXMessageList, mCodec);
5538 observer->setNotificationMessage(notify);
5539
5540 mCodec->mComponentName = componentName;
5541 mCodec->mRenderTracker.setComponentName(componentName);
5542 mCodec->mFlags = 0;
5543
5544 if (componentName.endsWith(".secure")) {
5545 mCodec->mFlags |= kFlagIsSecure;
5546 mCodec->mFlags |= kFlagIsGrallocUsageProtected;
5547 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
5548 }
5549
5550 mCodec->mQuirks = quirks;
5551 mCodec->mOMX = omx;
5552 mCodec->mNode = node;
5553
5554 {
5555 sp<AMessage> notify = mCodec->mNotify->dup();
5556 notify->setInt32("what", CodecBase::kWhatComponentAllocated);
5557 notify->setString("componentName", mCodec->mComponentName.c_str());
5558 notify->post();
5559 }
5560
5561 mCodec->changeState(mCodec->mLoadedState);
5562
5563 return true;
5564 }
5565
5566 ////////////////////////////////////////////////////////////////////////////////
5567
LoadedState(ACodec * codec)5568 ACodec::LoadedState::LoadedState(ACodec *codec)
5569 : BaseState(codec) {
5570 }
5571
stateEntered()5572 void ACodec::LoadedState::stateEntered() {
5573 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
5574
5575 mCodec->mPortEOS[kPortIndexInput] =
5576 mCodec->mPortEOS[kPortIndexOutput] = false;
5577
5578 mCodec->mInputEOSResult = OK;
5579
5580 mCodec->mDequeueCounter = 0;
5581 mCodec->mMetadataBuffersToSubmit = 0;
5582 mCodec->mRepeatFrameDelayUs = -1ll;
5583 mCodec->mInputFormat.clear();
5584 mCodec->mOutputFormat.clear();
5585 mCodec->mBaseOutputFormat.clear();
5586
5587 if (mCodec->mShutdownInProgress) {
5588 bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
5589
5590 mCodec->mShutdownInProgress = false;
5591 mCodec->mKeepComponentAllocated = false;
5592
5593 onShutdown(keepComponentAllocated);
5594 }
5595 mCodec->mExplicitShutdown = false;
5596
5597 mCodec->processDeferredMessages();
5598 }
5599
onShutdown(bool keepComponentAllocated)5600 void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
5601 if (!keepComponentAllocated) {
5602 (void)mCodec->mOMX->freeNode(mCodec->mNode);
5603
5604 mCodec->changeState(mCodec->mUninitializedState);
5605 }
5606
5607 if (mCodec->mExplicitShutdown) {
5608 sp<AMessage> notify = mCodec->mNotify->dup();
5609 notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5610 notify->post();
5611 mCodec->mExplicitShutdown = false;
5612 }
5613 }
5614
onMessageReceived(const sp<AMessage> & msg)5615 bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
5616 bool handled = false;
5617
5618 switch (msg->what()) {
5619 case ACodec::kWhatConfigureComponent:
5620 {
5621 onConfigureComponent(msg);
5622 handled = true;
5623 break;
5624 }
5625
5626 case ACodec::kWhatCreateInputSurface:
5627 {
5628 onCreateInputSurface(msg);
5629 handled = true;
5630 break;
5631 }
5632
5633 case ACodec::kWhatSetInputSurface:
5634 {
5635 onSetInputSurface(msg);
5636 handled = true;
5637 break;
5638 }
5639
5640 case ACodec::kWhatStart:
5641 {
5642 onStart();
5643 handled = true;
5644 break;
5645 }
5646
5647 case ACodec::kWhatShutdown:
5648 {
5649 int32_t keepComponentAllocated;
5650 CHECK(msg->findInt32(
5651 "keepComponentAllocated", &keepComponentAllocated));
5652
5653 mCodec->mExplicitShutdown = true;
5654 onShutdown(keepComponentAllocated);
5655
5656 handled = true;
5657 break;
5658 }
5659
5660 case ACodec::kWhatFlush:
5661 {
5662 sp<AMessage> notify = mCodec->mNotify->dup();
5663 notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5664 notify->post();
5665
5666 handled = true;
5667 break;
5668 }
5669
5670 default:
5671 return BaseState::onMessageReceived(msg);
5672 }
5673
5674 return handled;
5675 }
5676
onConfigureComponent(const sp<AMessage> & msg)5677 bool ACodec::LoadedState::onConfigureComponent(
5678 const sp<AMessage> &msg) {
5679 ALOGV("onConfigureComponent");
5680
5681 CHECK(mCodec->mNode != 0);
5682
5683 status_t err = OK;
5684 AString mime;
5685 if (!msg->findString("mime", &mime)) {
5686 err = BAD_VALUE;
5687 } else {
5688 err = mCodec->configureCodec(mime.c_str(), msg);
5689 }
5690 if (err != OK) {
5691 ALOGE("[%s] configureCodec returning error %d",
5692 mCodec->mComponentName.c_str(), err);
5693
5694 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5695 return false;
5696 }
5697
5698 {
5699 sp<AMessage> notify = mCodec->mNotify->dup();
5700 notify->setInt32("what", CodecBase::kWhatComponentConfigured);
5701 notify->setMessage("input-format", mCodec->mInputFormat);
5702 notify->setMessage("output-format", mCodec->mOutputFormat);
5703 notify->post();
5704 }
5705
5706 return true;
5707 }
5708
setupInputSurface()5709 status_t ACodec::LoadedState::setupInputSurface() {
5710 status_t err = OK;
5711
5712 if (mCodec->mRepeatFrameDelayUs > 0ll) {
5713 err = mCodec->mOMX->setInternalOption(
5714 mCodec->mNode,
5715 kPortIndexInput,
5716 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
5717 &mCodec->mRepeatFrameDelayUs,
5718 sizeof(mCodec->mRepeatFrameDelayUs));
5719
5720 if (err != OK) {
5721 ALOGE("[%s] Unable to configure option to repeat previous "
5722 "frames (err %d)",
5723 mCodec->mComponentName.c_str(),
5724 err);
5725 return err;
5726 }
5727 }
5728
5729 if (mCodec->mMaxPtsGapUs > 0ll) {
5730 err = mCodec->mOMX->setInternalOption(
5731 mCodec->mNode,
5732 kPortIndexInput,
5733 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
5734 &mCodec->mMaxPtsGapUs,
5735 sizeof(mCodec->mMaxPtsGapUs));
5736
5737 if (err != OK) {
5738 ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
5739 mCodec->mComponentName.c_str(),
5740 err);
5741 return err;
5742 }
5743 }
5744
5745 if (mCodec->mMaxFps > 0) {
5746 err = mCodec->mOMX->setInternalOption(
5747 mCodec->mNode,
5748 kPortIndexInput,
5749 IOMX::INTERNAL_OPTION_MAX_FPS,
5750 &mCodec->mMaxFps,
5751 sizeof(mCodec->mMaxFps));
5752
5753 if (err != OK) {
5754 ALOGE("[%s] Unable to configure max fps (err %d)",
5755 mCodec->mComponentName.c_str(),
5756 err);
5757 return err;
5758 }
5759 }
5760
5761 if (mCodec->mTimePerCaptureUs > 0ll
5762 && mCodec->mTimePerFrameUs > 0ll) {
5763 int64_t timeLapse[2];
5764 timeLapse[0] = mCodec->mTimePerFrameUs;
5765 timeLapse[1] = mCodec->mTimePerCaptureUs;
5766 err = mCodec->mOMX->setInternalOption(
5767 mCodec->mNode,
5768 kPortIndexInput,
5769 IOMX::INTERNAL_OPTION_TIME_LAPSE,
5770 &timeLapse[0],
5771 sizeof(timeLapse));
5772
5773 if (err != OK) {
5774 ALOGE("[%s] Unable to configure time lapse (err %d)",
5775 mCodec->mComponentName.c_str(),
5776 err);
5777 return err;
5778 }
5779 }
5780
5781 if (mCodec->mCreateInputBuffersSuspended) {
5782 bool suspend = true;
5783 err = mCodec->mOMX->setInternalOption(
5784 mCodec->mNode,
5785 kPortIndexInput,
5786 IOMX::INTERNAL_OPTION_SUSPEND,
5787 &suspend,
5788 sizeof(suspend));
5789
5790 if (err != OK) {
5791 ALOGE("[%s] Unable to configure option to suspend (err %d)",
5792 mCodec->mComponentName.c_str(),
5793 err);
5794 return err;
5795 }
5796 }
5797
5798 uint32_t usageBits;
5799 if (mCodec->mOMX->getParameter(
5800 mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
5801 &usageBits, sizeof(usageBits)) == OK) {
5802 mCodec->mInputFormat->setInt32(
5803 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
5804 }
5805
5806 return OK;
5807 }
5808
onCreateInputSurface(const sp<AMessage> &)5809 void ACodec::LoadedState::onCreateInputSurface(
5810 const sp<AMessage> & /* msg */) {
5811 ALOGV("onCreateInputSurface");
5812
5813 sp<AMessage> notify = mCodec->mNotify->dup();
5814 notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
5815
5816 sp<IGraphicBufferProducer> bufferProducer;
5817 status_t err = mCodec->mOMX->createInputSurface(
5818 mCodec->mNode, kPortIndexInput, &bufferProducer, &mCodec->mInputMetadataType);
5819
5820 if (err == OK) {
5821 err = setupInputSurface();
5822 }
5823
5824 if (err == OK) {
5825 notify->setObject("input-surface",
5826 new BufferProducerWrapper(bufferProducer));
5827 } else {
5828 // Can't use mCodec->signalError() here -- MediaCodec won't forward
5829 // the error through because it's in the "configured" state. We
5830 // send a kWhatInputSurfaceCreated with an error value instead.
5831 ALOGE("[%s] onCreateInputSurface returning error %d",
5832 mCodec->mComponentName.c_str(), err);
5833 notify->setInt32("err", err);
5834 }
5835 notify->post();
5836 }
5837
onSetInputSurface(const sp<AMessage> & msg)5838 void ACodec::LoadedState::onSetInputSurface(
5839 const sp<AMessage> &msg) {
5840 ALOGV("onSetInputSurface");
5841
5842 sp<AMessage> notify = mCodec->mNotify->dup();
5843 notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted);
5844
5845 sp<RefBase> obj;
5846 CHECK(msg->findObject("input-surface", &obj));
5847 sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
5848
5849 status_t err = mCodec->mOMX->setInputSurface(
5850 mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(),
5851 &mCodec->mInputMetadataType);
5852
5853 if (err == OK) {
5854 err = setupInputSurface();
5855 }
5856
5857 if (err != OK) {
5858 // Can't use mCodec->signalError() here -- MediaCodec won't forward
5859 // the error through because it's in the "configured" state. We
5860 // send a kWhatInputSurfaceAccepted with an error value instead.
5861 ALOGE("[%s] onSetInputSurface returning error %d",
5862 mCodec->mComponentName.c_str(), err);
5863 notify->setInt32("err", err);
5864 }
5865 notify->post();
5866 }
5867
onStart()5868 void ACodec::LoadedState::onStart() {
5869 ALOGV("onStart");
5870
5871 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
5872 if (err != OK) {
5873 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5874 } else {
5875 mCodec->changeState(mCodec->mLoadedToIdleState);
5876 }
5877 }
5878
5879 ////////////////////////////////////////////////////////////////////////////////
5880
LoadedToIdleState(ACodec * codec)5881 ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
5882 : BaseState(codec) {
5883 }
5884
stateEntered()5885 void ACodec::LoadedToIdleState::stateEntered() {
5886 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
5887
5888 status_t err;
5889 if ((err = allocateBuffers()) != OK) {
5890 ALOGE("Failed to allocate buffers after transitioning to IDLE state "
5891 "(error 0x%08x)",
5892 err);
5893
5894 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5895
5896 mCodec->changeState(mCodec->mLoadedState);
5897 }
5898 }
5899
allocateBuffers()5900 status_t ACodec::LoadedToIdleState::allocateBuffers() {
5901 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
5902
5903 if (err != OK) {
5904 return err;
5905 }
5906
5907 return mCodec->allocateBuffersOnPort(kPortIndexOutput);
5908 }
5909
onMessageReceived(const sp<AMessage> & msg)5910 bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5911 switch (msg->what()) {
5912 case kWhatSetParameters:
5913 case kWhatShutdown:
5914 {
5915 mCodec->deferMessage(msg);
5916 return true;
5917 }
5918
5919 case kWhatSignalEndOfInputStream:
5920 {
5921 mCodec->onSignalEndOfInputStream();
5922 return true;
5923 }
5924
5925 case kWhatResume:
5926 {
5927 // We'll be active soon enough.
5928 return true;
5929 }
5930
5931 case kWhatFlush:
5932 {
5933 // We haven't even started yet, so we're flushed alright...
5934 sp<AMessage> notify = mCodec->mNotify->dup();
5935 notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5936 notify->post();
5937 return true;
5938 }
5939
5940 default:
5941 return BaseState::onMessageReceived(msg);
5942 }
5943 }
5944
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)5945 bool ACodec::LoadedToIdleState::onOMXEvent(
5946 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5947 switch (event) {
5948 case OMX_EventCmdComplete:
5949 {
5950 status_t err = OK;
5951 if (data1 != (OMX_U32)OMX_CommandStateSet
5952 || data2 != (OMX_U32)OMX_StateIdle) {
5953 ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)",
5954 asString((OMX_COMMANDTYPE)data1), data1,
5955 asString((OMX_STATETYPE)data2), data2);
5956 err = FAILED_TRANSACTION;
5957 }
5958
5959 if (err == OK) {
5960 err = mCodec->mOMX->sendCommand(
5961 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting);
5962 }
5963
5964 if (err != OK) {
5965 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5966 } else {
5967 mCodec->changeState(mCodec->mIdleToExecutingState);
5968 }
5969
5970 return true;
5971 }
5972
5973 default:
5974 return BaseState::onOMXEvent(event, data1, data2);
5975 }
5976 }
5977
5978 ////////////////////////////////////////////////////////////////////////////////
5979
IdleToExecutingState(ACodec * codec)5980 ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
5981 : BaseState(codec) {
5982 }
5983
stateEntered()5984 void ACodec::IdleToExecutingState::stateEntered() {
5985 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
5986 }
5987
onMessageReceived(const sp<AMessage> & msg)5988 bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5989 switch (msg->what()) {
5990 case kWhatSetParameters:
5991 case kWhatShutdown:
5992 {
5993 mCodec->deferMessage(msg);
5994 return true;
5995 }
5996
5997 case kWhatResume:
5998 {
5999 // We'll be active soon enough.
6000 return true;
6001 }
6002
6003 case kWhatFlush:
6004 {
6005 // We haven't even started yet, so we're flushed alright...
6006 sp<AMessage> notify = mCodec->mNotify->dup();
6007 notify->setInt32("what", CodecBase::kWhatFlushCompleted);
6008 notify->post();
6009
6010 return true;
6011 }
6012
6013 case kWhatSignalEndOfInputStream:
6014 {
6015 mCodec->onSignalEndOfInputStream();
6016 return true;
6017 }
6018
6019 default:
6020 return BaseState::onMessageReceived(msg);
6021 }
6022 }
6023
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)6024 bool ACodec::IdleToExecutingState::onOMXEvent(
6025 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6026 switch (event) {
6027 case OMX_EventCmdComplete:
6028 {
6029 if (data1 != (OMX_U32)OMX_CommandStateSet
6030 || data2 != (OMX_U32)OMX_StateExecuting) {
6031 ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)",
6032 asString((OMX_COMMANDTYPE)data1), data1,
6033 asString((OMX_STATETYPE)data2), data2);
6034 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6035 return true;
6036 }
6037
6038 mCodec->mExecutingState->resume();
6039 mCodec->changeState(mCodec->mExecutingState);
6040
6041 return true;
6042 }
6043
6044 default:
6045 return BaseState::onOMXEvent(event, data1, data2);
6046 }
6047 }
6048
6049 ////////////////////////////////////////////////////////////////////////////////
6050
ExecutingState(ACodec * codec)6051 ACodec::ExecutingState::ExecutingState(ACodec *codec)
6052 : BaseState(codec),
6053 mActive(false) {
6054 }
6055
getPortMode(OMX_U32)6056 ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
6057 OMX_U32 /* portIndex */) {
6058 return RESUBMIT_BUFFERS;
6059 }
6060
submitOutputMetaBuffers()6061 void ACodec::ExecutingState::submitOutputMetaBuffers() {
6062 // submit as many buffers as there are input buffers with the codec
6063 // in case we are in port reconfiguring
6064 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
6065 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
6066
6067 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
6068 if (mCodec->submitOutputMetadataBuffer() != OK)
6069 break;
6070 }
6071 }
6072
6073 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
6074 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
6075 }
6076
submitRegularOutputBuffers()6077 void ACodec::ExecutingState::submitRegularOutputBuffers() {
6078 bool failed = false;
6079 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
6080 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
6081
6082 if (mCodec->mNativeWindow != NULL) {
6083 if (info->mStatus != BufferInfo::OWNED_BY_US
6084 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6085 ALOGE("buffers should be owned by us or the surface");
6086 failed = true;
6087 break;
6088 }
6089
6090 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6091 continue;
6092 }
6093 } else {
6094 if (info->mStatus != BufferInfo::OWNED_BY_US) {
6095 ALOGE("buffers should be owned by us");
6096 failed = true;
6097 break;
6098 }
6099 }
6100
6101 ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
6102
6103 info->checkWriteFence("submitRegularOutputBuffers");
6104 status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
6105 info->mFenceFd = -1;
6106 if (err != OK) {
6107 failed = true;
6108 break;
6109 }
6110
6111 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
6112 }
6113
6114 if (failed) {
6115 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6116 }
6117 }
6118
submitOutputBuffers()6119 void ACodec::ExecutingState::submitOutputBuffers() {
6120 submitRegularOutputBuffers();
6121 if (mCodec->storingMetadataInDecodedBuffers()) {
6122 submitOutputMetaBuffers();
6123 }
6124 }
6125
resume()6126 void ACodec::ExecutingState::resume() {
6127 if (mActive) {
6128 ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str());
6129 return;
6130 }
6131
6132 submitOutputBuffers();
6133
6134 // Post all available input buffers
6135 if (mCodec->mBuffers[kPortIndexInput].size() == 0u) {
6136 ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str());
6137 }
6138
6139 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
6140 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
6141 if (info->mStatus == BufferInfo::OWNED_BY_US) {
6142 postFillThisBuffer(info);
6143 }
6144 }
6145
6146 mActive = true;
6147 }
6148
stateEntered()6149 void ACodec::ExecutingState::stateEntered() {
6150 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
6151
6152 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
6153 mCodec->processDeferredMessages();
6154 }
6155
onMessageReceived(const sp<AMessage> & msg)6156 bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
6157 bool handled = false;
6158
6159 switch (msg->what()) {
6160 case kWhatShutdown:
6161 {
6162 int32_t keepComponentAllocated;
6163 CHECK(msg->findInt32(
6164 "keepComponentAllocated", &keepComponentAllocated));
6165
6166 mCodec->mShutdownInProgress = true;
6167 mCodec->mExplicitShutdown = true;
6168 mCodec->mKeepComponentAllocated = keepComponentAllocated;
6169
6170 mActive = false;
6171
6172 status_t err = mCodec->mOMX->sendCommand(
6173 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
6174 if (err != OK) {
6175 if (keepComponentAllocated) {
6176 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6177 }
6178 // TODO: do some recovery here.
6179 } else {
6180 mCodec->changeState(mCodec->mExecutingToIdleState);
6181 }
6182
6183 handled = true;
6184 break;
6185 }
6186
6187 case kWhatFlush:
6188 {
6189 ALOGV("[%s] ExecutingState flushing now "
6190 "(codec owns %zu/%zu input, %zu/%zu output).",
6191 mCodec->mComponentName.c_str(),
6192 mCodec->countBuffersOwnedByComponent(kPortIndexInput),
6193 mCodec->mBuffers[kPortIndexInput].size(),
6194 mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
6195 mCodec->mBuffers[kPortIndexOutput].size());
6196
6197 mActive = false;
6198
6199 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL);
6200 if (err != OK) {
6201 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6202 } else {
6203 mCodec->changeState(mCodec->mFlushingState);
6204 }
6205
6206 handled = true;
6207 break;
6208 }
6209
6210 case kWhatResume:
6211 {
6212 resume();
6213
6214 handled = true;
6215 break;
6216 }
6217
6218 case kWhatRequestIDRFrame:
6219 {
6220 status_t err = mCodec->requestIDRFrame();
6221 if (err != OK) {
6222 ALOGW("Requesting an IDR frame failed.");
6223 }
6224
6225 handled = true;
6226 break;
6227 }
6228
6229 case kWhatSetParameters:
6230 {
6231 sp<AMessage> params;
6232 CHECK(msg->findMessage("params", ¶ms));
6233
6234 status_t err = mCodec->setParameters(params);
6235
6236 sp<AMessage> reply;
6237 if (msg->findMessage("reply", &reply)) {
6238 reply->setInt32("err", err);
6239 reply->post();
6240 }
6241
6242 handled = true;
6243 break;
6244 }
6245
6246 case ACodec::kWhatSignalEndOfInputStream:
6247 {
6248 mCodec->onSignalEndOfInputStream();
6249 handled = true;
6250 break;
6251 }
6252
6253 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
6254 case kWhatSubmitOutputMetadataBufferIfEOS:
6255 {
6256 if (mCodec->mPortEOS[kPortIndexInput] &&
6257 !mCodec->mPortEOS[kPortIndexOutput]) {
6258 status_t err = mCodec->submitOutputMetadataBuffer();
6259 if (err == OK) {
6260 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
6261 }
6262 }
6263 return true;
6264 }
6265
6266 default:
6267 handled = BaseState::onMessageReceived(msg);
6268 break;
6269 }
6270
6271 return handled;
6272 }
6273
setParameters(const sp<AMessage> & params)6274 status_t ACodec::setParameters(const sp<AMessage> ¶ms) {
6275 int32_t videoBitrate;
6276 if (params->findInt32("video-bitrate", &videoBitrate)) {
6277 OMX_VIDEO_CONFIG_BITRATETYPE configParams;
6278 InitOMXParams(&configParams);
6279 configParams.nPortIndex = kPortIndexOutput;
6280 configParams.nEncodeBitrate = videoBitrate;
6281
6282 status_t err = mOMX->setConfig(
6283 mNode,
6284 OMX_IndexConfigVideoBitrate,
6285 &configParams,
6286 sizeof(configParams));
6287
6288 if (err != OK) {
6289 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
6290 videoBitrate, err);
6291
6292 return err;
6293 }
6294 }
6295
6296 int64_t skipFramesBeforeUs;
6297 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
6298 status_t err =
6299 mOMX->setInternalOption(
6300 mNode,
6301 kPortIndexInput,
6302 IOMX::INTERNAL_OPTION_START_TIME,
6303 &skipFramesBeforeUs,
6304 sizeof(skipFramesBeforeUs));
6305
6306 if (err != OK) {
6307 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
6308 return err;
6309 }
6310 }
6311
6312 int32_t dropInputFrames;
6313 if (params->findInt32("drop-input-frames", &dropInputFrames)) {
6314 bool suspend = dropInputFrames != 0;
6315
6316 status_t err =
6317 mOMX->setInternalOption(
6318 mNode,
6319 kPortIndexInput,
6320 IOMX::INTERNAL_OPTION_SUSPEND,
6321 &suspend,
6322 sizeof(suspend));
6323
6324 if (err != OK) {
6325 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
6326 return err;
6327 }
6328 }
6329
6330 int32_t dummy;
6331 if (params->findInt32("request-sync", &dummy)) {
6332 status_t err = requestIDRFrame();
6333
6334 if (err != OK) {
6335 ALOGE("Requesting a sync frame failed w/ err %d", err);
6336 return err;
6337 }
6338 }
6339
6340 float rate;
6341 if (params->findFloat("operating-rate", &rate) && rate > 0) {
6342 status_t err = setOperatingRate(rate, mIsVideo);
6343 if (err != OK) {
6344 ALOGE("Failed to set parameter 'operating-rate' (err %d)", err);
6345 return err;
6346 }
6347 }
6348
6349 return OK;
6350 }
6351
onSignalEndOfInputStream()6352 void ACodec::onSignalEndOfInputStream() {
6353 sp<AMessage> notify = mNotify->dup();
6354 notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
6355
6356 status_t err = mOMX->signalEndOfInputStream(mNode);
6357 if (err != OK) {
6358 notify->setInt32("err", err);
6359 }
6360 notify->post();
6361 }
6362
onOMXFrameRendered(int64_t mediaTimeUs,nsecs_t systemNano)6363 bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
6364 mCodec->onFrameRendered(mediaTimeUs, systemNano);
6365 return true;
6366 }
6367
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)6368 bool ACodec::ExecutingState::onOMXEvent(
6369 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6370 switch (event) {
6371 case OMX_EventPortSettingsChanged:
6372 {
6373 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
6374
6375 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
6376 mCodec->mMetadataBuffersToSubmit = 0;
6377 CHECK_EQ(mCodec->mOMX->sendCommand(
6378 mCodec->mNode,
6379 OMX_CommandPortDisable, kPortIndexOutput),
6380 (status_t)OK);
6381
6382 mCodec->freeOutputBuffersNotOwnedByComponent();
6383
6384 mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
6385 } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
6386 mCodec->mSentFormat = false;
6387
6388 if (mCodec->mTunneled) {
6389 sp<AMessage> dummy = new AMessage(kWhatOutputBufferDrained, mCodec);
6390 mCodec->sendFormatChange(dummy);
6391 }
6392 } else {
6393 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x",
6394 mCodec->mComponentName.c_str(), data2);
6395 }
6396
6397 return true;
6398 }
6399
6400 case OMX_EventBufferFlag:
6401 {
6402 return true;
6403 }
6404
6405 default:
6406 return BaseState::onOMXEvent(event, data1, data2);
6407 }
6408 }
6409
6410 ////////////////////////////////////////////////////////////////////////////////
6411
OutputPortSettingsChangedState(ACodec * codec)6412 ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
6413 ACodec *codec)
6414 : BaseState(codec) {
6415 }
6416
getPortMode(OMX_U32 portIndex)6417 ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
6418 OMX_U32 portIndex) {
6419 if (portIndex == kPortIndexOutput) {
6420 return FREE_BUFFERS;
6421 }
6422
6423 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
6424
6425 return RESUBMIT_BUFFERS;
6426 }
6427
onMessageReceived(const sp<AMessage> & msg)6428 bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
6429 const sp<AMessage> &msg) {
6430 bool handled = false;
6431
6432 switch (msg->what()) {
6433 case kWhatFlush:
6434 case kWhatShutdown:
6435 case kWhatResume:
6436 case kWhatSetParameters:
6437 {
6438 if (msg->what() == kWhatResume) {
6439 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
6440 }
6441
6442 mCodec->deferMessage(msg);
6443 handled = true;
6444 break;
6445 }
6446
6447 default:
6448 handled = BaseState::onMessageReceived(msg);
6449 break;
6450 }
6451
6452 return handled;
6453 }
6454
stateEntered()6455 void ACodec::OutputPortSettingsChangedState::stateEntered() {
6456 ALOGV("[%s] Now handling output port settings change",
6457 mCodec->mComponentName.c_str());
6458 }
6459
onOMXFrameRendered(int64_t mediaTimeUs,nsecs_t systemNano)6460 bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered(
6461 int64_t mediaTimeUs, nsecs_t systemNano) {
6462 mCodec->onFrameRendered(mediaTimeUs, systemNano);
6463 return true;
6464 }
6465
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)6466 bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
6467 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6468 switch (event) {
6469 case OMX_EventCmdComplete:
6470 {
6471 if (data1 == (OMX_U32)OMX_CommandPortDisable) {
6472 if (data2 != (OMX_U32)kPortIndexOutput) {
6473 ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2);
6474 return false;
6475 }
6476
6477 ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
6478
6479 status_t err = OK;
6480 if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
6481 ALOGE("disabled port should be empty, but has %zu buffers",
6482 mCodec->mBuffers[kPortIndexOutput].size());
6483 err = FAILED_TRANSACTION;
6484 } else {
6485 mCodec->mDealer[kPortIndexOutput].clear();
6486 }
6487
6488 if (err == OK) {
6489 err = mCodec->mOMX->sendCommand(
6490 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput);
6491 }
6492
6493 if (err == OK) {
6494 err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
6495 ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
6496 "reconfiguration: (%d)", err);
6497 }
6498
6499 if (err != OK) {
6500 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6501
6502 // This is technically not correct, but appears to be
6503 // the only way to free the component instance.
6504 // Controlled transitioning from excecuting->idle
6505 // and idle->loaded seem impossible probably because
6506 // the output port never finishes re-enabling.
6507 mCodec->mShutdownInProgress = true;
6508 mCodec->mKeepComponentAllocated = false;
6509 mCodec->changeState(mCodec->mLoadedState);
6510 }
6511
6512 return true;
6513 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
6514 if (data2 != (OMX_U32)kPortIndexOutput) {
6515 ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2);
6516 return false;
6517 }
6518
6519 mCodec->mSentFormat = false;
6520
6521 if (mCodec->mTunneled) {
6522 sp<AMessage> dummy = new AMessage(kWhatOutputBufferDrained, mCodec);
6523 mCodec->sendFormatChange(dummy);
6524 }
6525
6526 ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str());
6527
6528 if (mCodec->mExecutingState->active()) {
6529 mCodec->mExecutingState->submitOutputBuffers();
6530 }
6531
6532 mCodec->changeState(mCodec->mExecutingState);
6533
6534 return true;
6535 }
6536
6537 return false;
6538 }
6539
6540 default:
6541 return false;
6542 }
6543 }
6544
6545 ////////////////////////////////////////////////////////////////////////////////
6546
ExecutingToIdleState(ACodec * codec)6547 ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
6548 : BaseState(codec),
6549 mComponentNowIdle(false) {
6550 }
6551
onMessageReceived(const sp<AMessage> & msg)6552 bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
6553 bool handled = false;
6554
6555 switch (msg->what()) {
6556 case kWhatFlush:
6557 {
6558 // Don't send me a flush request if you previously wanted me
6559 // to shutdown.
6560 ALOGW("Ignoring flush request in ExecutingToIdleState");
6561 break;
6562 }
6563
6564 case kWhatShutdown:
6565 {
6566 // We're already doing that...
6567
6568 handled = true;
6569 break;
6570 }
6571
6572 default:
6573 handled = BaseState::onMessageReceived(msg);
6574 break;
6575 }
6576
6577 return handled;
6578 }
6579
stateEntered()6580 void ACodec::ExecutingToIdleState::stateEntered() {
6581 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
6582
6583 mComponentNowIdle = false;
6584 mCodec->mSentFormat = false;
6585 }
6586
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)6587 bool ACodec::ExecutingToIdleState::onOMXEvent(
6588 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6589 switch (event) {
6590 case OMX_EventCmdComplete:
6591 {
6592 if (data1 != (OMX_U32)OMX_CommandStateSet
6593 || data2 != (OMX_U32)OMX_StateIdle) {
6594 ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)",
6595 asString((OMX_COMMANDTYPE)data1), data1,
6596 asString((OMX_STATETYPE)data2), data2);
6597 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6598 return true;
6599 }
6600
6601 mComponentNowIdle = true;
6602
6603 changeStateIfWeOwnAllBuffers();
6604
6605 return true;
6606 }
6607
6608 case OMX_EventPortSettingsChanged:
6609 case OMX_EventBufferFlag:
6610 {
6611 // We're shutting down and don't care about this anymore.
6612 return true;
6613 }
6614
6615 default:
6616 return BaseState::onOMXEvent(event, data1, data2);
6617 }
6618 }
6619
changeStateIfWeOwnAllBuffers()6620 void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
6621 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
6622 status_t err = mCodec->mOMX->sendCommand(
6623 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
6624 if (err == OK) {
6625 err = mCodec->freeBuffersOnPort(kPortIndexInput);
6626 status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
6627 if (err == OK) {
6628 err = err2;
6629 }
6630 }
6631
6632 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
6633 && mCodec->mNativeWindow != NULL) {
6634 // We push enough 1x1 blank buffers to ensure that one of
6635 // them has made it to the display. This allows the OMX
6636 // component teardown to zero out any protected buffers
6637 // without the risk of scanning out one of those buffers.
6638 pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get());
6639 }
6640
6641 if (err != OK) {
6642 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6643 return;
6644 }
6645
6646 mCodec->changeState(mCodec->mIdleToLoadedState);
6647 }
6648 }
6649
onInputBufferFilled(const sp<AMessage> & msg)6650 void ACodec::ExecutingToIdleState::onInputBufferFilled(
6651 const sp<AMessage> &msg) {
6652 BaseState::onInputBufferFilled(msg);
6653
6654 changeStateIfWeOwnAllBuffers();
6655 }
6656
onOutputBufferDrained(const sp<AMessage> & msg)6657 void ACodec::ExecutingToIdleState::onOutputBufferDrained(
6658 const sp<AMessage> &msg) {
6659 BaseState::onOutputBufferDrained(msg);
6660
6661 changeStateIfWeOwnAllBuffers();
6662 }
6663
6664 ////////////////////////////////////////////////////////////////////////////////
6665
IdleToLoadedState(ACodec * codec)6666 ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
6667 : BaseState(codec) {
6668 }
6669
onMessageReceived(const sp<AMessage> & msg)6670 bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
6671 bool handled = false;
6672
6673 switch (msg->what()) {
6674 case kWhatShutdown:
6675 {
6676 // We're already doing that...
6677
6678 handled = true;
6679 break;
6680 }
6681
6682 case kWhatFlush:
6683 {
6684 // Don't send me a flush request if you previously wanted me
6685 // to shutdown.
6686 ALOGE("Got flush request in IdleToLoadedState");
6687 break;
6688 }
6689
6690 default:
6691 handled = BaseState::onMessageReceived(msg);
6692 break;
6693 }
6694
6695 return handled;
6696 }
6697
stateEntered()6698 void ACodec::IdleToLoadedState::stateEntered() {
6699 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
6700 }
6701
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)6702 bool ACodec::IdleToLoadedState::onOMXEvent(
6703 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6704 switch (event) {
6705 case OMX_EventCmdComplete:
6706 {
6707 if (data1 != (OMX_U32)OMX_CommandStateSet
6708 || data2 != (OMX_U32)OMX_StateLoaded) {
6709 ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)",
6710 asString((OMX_COMMANDTYPE)data1), data1,
6711 asString((OMX_STATETYPE)data2), data2);
6712 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6713 return true;
6714 }
6715
6716 mCodec->changeState(mCodec->mLoadedState);
6717
6718 return true;
6719 }
6720
6721 default:
6722 return BaseState::onOMXEvent(event, data1, data2);
6723 }
6724 }
6725
6726 ////////////////////////////////////////////////////////////////////////////////
6727
FlushingState(ACodec * codec)6728 ACodec::FlushingState::FlushingState(ACodec *codec)
6729 : BaseState(codec) {
6730 }
6731
stateEntered()6732 void ACodec::FlushingState::stateEntered() {
6733 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
6734
6735 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
6736 }
6737
onMessageReceived(const sp<AMessage> & msg)6738 bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
6739 bool handled = false;
6740
6741 switch (msg->what()) {
6742 case kWhatShutdown:
6743 {
6744 mCodec->deferMessage(msg);
6745 break;
6746 }
6747
6748 case kWhatFlush:
6749 {
6750 // We're already doing this right now.
6751 handled = true;
6752 break;
6753 }
6754
6755 default:
6756 handled = BaseState::onMessageReceived(msg);
6757 break;
6758 }
6759
6760 return handled;
6761 }
6762
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)6763 bool ACodec::FlushingState::onOMXEvent(
6764 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6765 ALOGV("[%s] FlushingState onOMXEvent(%u,%d)",
6766 mCodec->mComponentName.c_str(), event, (OMX_S32)data1);
6767
6768 switch (event) {
6769 case OMX_EventCmdComplete:
6770 {
6771 if (data1 != (OMX_U32)OMX_CommandFlush) {
6772 ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState",
6773 asString((OMX_COMMANDTYPE)data1), data1, data2);
6774 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6775 return true;
6776 }
6777
6778 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
6779 if (mFlushComplete[data2]) {
6780 ALOGW("Flush already completed for %s port",
6781 data2 == kPortIndexInput ? "input" : "output");
6782 return true;
6783 }
6784 mFlushComplete[data2] = true;
6785
6786 if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) {
6787 changeStateIfWeOwnAllBuffers();
6788 }
6789 } else if (data2 == OMX_ALL) {
6790 if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) {
6791 ALOGW("received flush complete event for OMX_ALL before ports have been"
6792 "flushed (%d/%d)",
6793 mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]);
6794 return false;
6795 }
6796
6797 changeStateIfWeOwnAllBuffers();
6798 } else {
6799 ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2);
6800 }
6801
6802 return true;
6803 }
6804
6805 case OMX_EventPortSettingsChanged:
6806 {
6807 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
6808 msg->setInt32("type", omx_message::EVENT);
6809 msg->setInt32("node", mCodec->mNode);
6810 msg->setInt32("event", event);
6811 msg->setInt32("data1", data1);
6812 msg->setInt32("data2", data2);
6813
6814 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
6815 mCodec->mComponentName.c_str());
6816
6817 mCodec->deferMessage(msg);
6818
6819 return true;
6820 }
6821
6822 default:
6823 return BaseState::onOMXEvent(event, data1, data2);
6824 }
6825
6826 return true;
6827 }
6828
onOutputBufferDrained(const sp<AMessage> & msg)6829 void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
6830 BaseState::onOutputBufferDrained(msg);
6831
6832 changeStateIfWeOwnAllBuffers();
6833 }
6834
onInputBufferFilled(const sp<AMessage> & msg)6835 void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
6836 BaseState::onInputBufferFilled(msg);
6837
6838 changeStateIfWeOwnAllBuffers();
6839 }
6840
changeStateIfWeOwnAllBuffers()6841 void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
6842 if (mFlushComplete[kPortIndexInput]
6843 && mFlushComplete[kPortIndexOutput]
6844 && mCodec->allYourBuffersAreBelongToUs()) {
6845 // We now own all buffers except possibly those still queued with
6846 // the native window for rendering. Let's get those back as well.
6847 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
6848
6849 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
6850
6851 sp<AMessage> notify = mCodec->mNotify->dup();
6852 notify->setInt32("what", CodecBase::kWhatFlushCompleted);
6853 notify->post();
6854
6855 mCodec->mPortEOS[kPortIndexInput] =
6856 mCodec->mPortEOS[kPortIndexOutput] = false;
6857
6858 mCodec->mInputEOSResult = OK;
6859
6860 if (mCodec->mSkipCutBuffer != NULL) {
6861 mCodec->mSkipCutBuffer->clear();
6862 }
6863
6864 mCodec->changeState(mCodec->mExecutingState);
6865 }
6866 }
6867
6868 } // namespace android
6869