• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <media/stagefright/ACodec.h>
21 
22 #include <binder/MemoryDealer.h>
23 
24 #include <media/stagefright/foundation/hexdump.h>
25 #include <media/stagefright/foundation/ABuffer.h>
26 #include <media/stagefright/foundation/ADebug.h>
27 #include <media/stagefright/foundation/AMessage.h>
28 
29 #include <media/stagefright/MediaCodecList.h>
30 #include <media/stagefright/MediaDefs.h>
31 #include <media/stagefright/NativeWindowWrapper.h>
32 #include <media/stagefright/OMXClient.h>
33 #include <media/stagefright/OMXCodec.h>
34 
35 #include <OMX_Component.h>
36 
37 namespace android {
38 
39 template<class T>
InitOMXParams(T * params)40 static void InitOMXParams(T *params) {
41     params->nSize = sizeof(T);
42     params->nVersion.s.nVersionMajor = 1;
43     params->nVersion.s.nVersionMinor = 0;
44     params->nVersion.s.nRevision = 0;
45     params->nVersion.s.nStep = 0;
46 }
47 
48 struct CodecObserver : public BnOMXObserver {
CodecObserverandroid::CodecObserver49     CodecObserver() {}
50 
setNotificationMessageandroid::CodecObserver51     void setNotificationMessage(const sp<AMessage> &msg) {
52         mNotify = msg;
53     }
54 
55     // from IOMXObserver
onMessageandroid::CodecObserver56     virtual void onMessage(const omx_message &omx_msg) {
57         sp<AMessage> msg = mNotify->dup();
58 
59         msg->setInt32("type", omx_msg.type);
60         msg->setPointer("node", omx_msg.node);
61 
62         switch (omx_msg.type) {
63             case omx_message::EVENT:
64             {
65                 msg->setInt32("event", omx_msg.u.event_data.event);
66                 msg->setInt32("data1", omx_msg.u.event_data.data1);
67                 msg->setInt32("data2", omx_msg.u.event_data.data2);
68                 break;
69             }
70 
71             case omx_message::EMPTY_BUFFER_DONE:
72             {
73                 msg->setPointer("buffer", omx_msg.u.buffer_data.buffer);
74                 break;
75             }
76 
77             case omx_message::FILL_BUFFER_DONE:
78             {
79                 msg->setPointer(
80                         "buffer", omx_msg.u.extended_buffer_data.buffer);
81                 msg->setInt32(
82                         "range_offset",
83                         omx_msg.u.extended_buffer_data.range_offset);
84                 msg->setInt32(
85                         "range_length",
86                         omx_msg.u.extended_buffer_data.range_length);
87                 msg->setInt32(
88                         "flags",
89                         omx_msg.u.extended_buffer_data.flags);
90                 msg->setInt64(
91                         "timestamp",
92                         omx_msg.u.extended_buffer_data.timestamp);
93                 msg->setPointer(
94                         "platform_private",
95                         omx_msg.u.extended_buffer_data.platform_private);
96                 msg->setPointer(
97                         "data_ptr",
98                         omx_msg.u.extended_buffer_data.data_ptr);
99                 break;
100             }
101 
102             default:
103                 TRESPASS();
104                 break;
105         }
106 
107         msg->post();
108     }
109 
110 protected:
~CodecObserverandroid::CodecObserver111     virtual ~CodecObserver() {}
112 
113 private:
114     sp<AMessage> mNotify;
115 
116     DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
117 };
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 
121 struct ACodec::BaseState : public AState {
122     BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
123 
124 protected:
125     enum PortMode {
126         KEEP_BUFFERS,
127         RESUBMIT_BUFFERS,
128         FREE_BUFFERS,
129     };
130 
131     ACodec *mCodec;
132 
133     virtual PortMode getPortMode(OMX_U32 portIndex);
134 
135     virtual bool onMessageReceived(const sp<AMessage> &msg);
136 
137     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
138 
139     virtual void onOutputBufferDrained(const sp<AMessage> &msg);
140     virtual void onInputBufferFilled(const sp<AMessage> &msg);
141 
142     void postFillThisBuffer(BufferInfo *info);
143 
144 private:
145     bool onOMXMessage(const sp<AMessage> &msg);
146 
147     bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
148 
149     bool onOMXFillBufferDone(
150             IOMX::buffer_id bufferID,
151             size_t rangeOffset, size_t rangeLength,
152             OMX_U32 flags,
153             int64_t timeUs,
154             void *platformPrivate,
155             void *dataPtr);
156 
157     void getMoreInputDataIfPossible();
158 
159     DISALLOW_EVIL_CONSTRUCTORS(BaseState);
160 };
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 
164 struct ACodec::UninitializedState : public ACodec::BaseState {
165     UninitializedState(ACodec *codec);
166 
167 protected:
168     virtual bool onMessageReceived(const sp<AMessage> &msg);
169     virtual void stateEntered();
170 
171 private:
172     void onSetup(const sp<AMessage> &msg);
173     bool onAllocateComponent(const sp<AMessage> &msg);
174 
175     DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
176 };
177 
178 ////////////////////////////////////////////////////////////////////////////////
179 
180 struct ACodec::LoadedState : public ACodec::BaseState {
181     LoadedState(ACodec *codec);
182 
183 protected:
184     virtual bool onMessageReceived(const sp<AMessage> &msg);
185     virtual void stateEntered();
186 
187 private:
188     friend struct ACodec::UninitializedState;
189 
190     bool onConfigureComponent(const sp<AMessage> &msg);
191     void onStart();
192     void onShutdown(bool keepComponentAllocated);
193 
194     DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
195 };
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 
199 struct ACodec::LoadedToIdleState : public ACodec::BaseState {
200     LoadedToIdleState(ACodec *codec);
201 
202 protected:
203     virtual bool onMessageReceived(const sp<AMessage> &msg);
204     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
205     virtual void stateEntered();
206 
207 private:
208     status_t allocateBuffers();
209 
210     DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
211 };
212 
213 ////////////////////////////////////////////////////////////////////////////////
214 
215 struct ACodec::IdleToExecutingState : public ACodec::BaseState {
216     IdleToExecutingState(ACodec *codec);
217 
218 protected:
219     virtual bool onMessageReceived(const sp<AMessage> &msg);
220     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
221     virtual void stateEntered();
222 
223 private:
224     DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
225 };
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 
229 struct ACodec::ExecutingState : public ACodec::BaseState {
230     ExecutingState(ACodec *codec);
231 
232     void submitOutputBuffers();
233 
234     // Submit output buffers to the decoder, submit input buffers to client
235     // to fill with data.
236     void resume();
237 
238     // Returns true iff input and output buffers are in play.
activeandroid::ACodec::ExecutingState239     bool active() const { return mActive; }
240 
241 protected:
242     virtual PortMode getPortMode(OMX_U32 portIndex);
243     virtual bool onMessageReceived(const sp<AMessage> &msg);
244     virtual void stateEntered();
245 
246     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
247 
248 private:
249     bool mActive;
250 
251     DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
252 };
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 
256 struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
257     OutputPortSettingsChangedState(ACodec *codec);
258 
259 protected:
260     virtual PortMode getPortMode(OMX_U32 portIndex);
261     virtual bool onMessageReceived(const sp<AMessage> &msg);
262     virtual void stateEntered();
263 
264     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
265 
266 private:
267     DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
268 };
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 
272 struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
273     ExecutingToIdleState(ACodec *codec);
274 
275 protected:
276     virtual bool onMessageReceived(const sp<AMessage> &msg);
277     virtual void stateEntered();
278 
279     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
280 
281     virtual void onOutputBufferDrained(const sp<AMessage> &msg);
282     virtual void onInputBufferFilled(const sp<AMessage> &msg);
283 
284 private:
285     void changeStateIfWeOwnAllBuffers();
286 
287     bool mComponentNowIdle;
288 
289     DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
290 };
291 
292 ////////////////////////////////////////////////////////////////////////////////
293 
294 struct ACodec::IdleToLoadedState : public ACodec::BaseState {
295     IdleToLoadedState(ACodec *codec);
296 
297 protected:
298     virtual bool onMessageReceived(const sp<AMessage> &msg);
299     virtual void stateEntered();
300 
301     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
302 
303 private:
304     DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
305 };
306 
307 ////////////////////////////////////////////////////////////////////////////////
308 
309 struct ACodec::FlushingState : public ACodec::BaseState {
310     FlushingState(ACodec *codec);
311 
312 protected:
313     virtual bool onMessageReceived(const sp<AMessage> &msg);
314     virtual void stateEntered();
315 
316     virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
317 
318     virtual void onOutputBufferDrained(const sp<AMessage> &msg);
319     virtual void onInputBufferFilled(const sp<AMessage> &msg);
320 
321 private:
322     bool mFlushComplete[2];
323 
324     void changeStateIfWeOwnAllBuffers();
325 
326     DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
327 };
328 
329 ////////////////////////////////////////////////////////////////////////////////
330 
ACodec()331 ACodec::ACodec()
332     : mQuirks(0),
333       mNode(NULL),
334       mSentFormat(false),
335       mIsEncoder(false),
336       mShutdownInProgress(false),
337       mEncoderDelay(0),
338       mEncoderPadding(0),
339       mChannelMaskPresent(false),
340       mChannelMask(0) {
341     mUninitializedState = new UninitializedState(this);
342     mLoadedState = new LoadedState(this);
343     mLoadedToIdleState = new LoadedToIdleState(this);
344     mIdleToExecutingState = new IdleToExecutingState(this);
345     mExecutingState = new ExecutingState(this);
346 
347     mOutputPortSettingsChangedState =
348         new OutputPortSettingsChangedState(this);
349 
350     mExecutingToIdleState = new ExecutingToIdleState(this);
351     mIdleToLoadedState = new IdleToLoadedState(this);
352     mFlushingState = new FlushingState(this);
353 
354     mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
355     mInputEOSResult = OK;
356 
357     changeState(mUninitializedState);
358 }
359 
~ACodec()360 ACodec::~ACodec() {
361 }
362 
setNotificationMessage(const sp<AMessage> & msg)363 void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
364     mNotify = msg;
365 }
366 
initiateSetup(const sp<AMessage> & msg)367 void ACodec::initiateSetup(const sp<AMessage> &msg) {
368     msg->setWhat(kWhatSetup);
369     msg->setTarget(id());
370     msg->post();
371 }
372 
initiateAllocateComponent(const sp<AMessage> & msg)373 void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
374     msg->setWhat(kWhatAllocateComponent);
375     msg->setTarget(id());
376     msg->post();
377 }
378 
initiateConfigureComponent(const sp<AMessage> & msg)379 void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
380     msg->setWhat(kWhatConfigureComponent);
381     msg->setTarget(id());
382     msg->post();
383 }
384 
initiateStart()385 void ACodec::initiateStart() {
386     (new AMessage(kWhatStart, id()))->post();
387 }
388 
signalFlush()389 void ACodec::signalFlush() {
390     ALOGV("[%s] signalFlush", mComponentName.c_str());
391     (new AMessage(kWhatFlush, id()))->post();
392 }
393 
signalResume()394 void ACodec::signalResume() {
395     (new AMessage(kWhatResume, id()))->post();
396 }
397 
initiateShutdown(bool keepComponentAllocated)398 void ACodec::initiateShutdown(bool keepComponentAllocated) {
399     sp<AMessage> msg = new AMessage(kWhatShutdown, id());
400     msg->setInt32("keepComponentAllocated", keepComponentAllocated);
401     msg->post();
402 }
403 
allocateBuffersOnPort(OMX_U32 portIndex)404 status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
405     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
406 
407     CHECK(mDealer[portIndex] == NULL);
408     CHECK(mBuffers[portIndex].isEmpty());
409 
410     status_t err;
411     if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
412         err = allocateOutputBuffersFromNativeWindow();
413     } else {
414         OMX_PARAM_PORTDEFINITIONTYPE def;
415         InitOMXParams(&def);
416         def.nPortIndex = portIndex;
417 
418         err = mOMX->getParameter(
419                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
420 
421         if (err == OK) {
422             ALOGV("[%s] Allocating %lu buffers of size %lu on %s port",
423                     mComponentName.c_str(),
424                     def.nBufferCountActual, def.nBufferSize,
425                     portIndex == kPortIndexInput ? "input" : "output");
426 
427             size_t totalSize = def.nBufferCountActual * def.nBufferSize;
428             mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
429 
430             for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
431                 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
432                 CHECK(mem.get() != NULL);
433 
434                 BufferInfo info;
435                 info.mStatus = BufferInfo::OWNED_BY_US;
436 
437                 uint32_t requiresAllocateBufferBit =
438                     (portIndex == kPortIndexInput)
439                         ? OMXCodec::kRequiresAllocateBufferOnInputPorts
440                         : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
441 
442                 if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) {
443                     mem.clear();
444 
445                     void *ptr;
446                     err = mOMX->allocateBuffer(
447                             mNode, portIndex, def.nBufferSize, &info.mBufferID,
448                             &ptr);
449 
450                     info.mData = new ABuffer(ptr, def.nBufferSize);
451                 } else if (mQuirks & requiresAllocateBufferBit) {
452                     err = mOMX->allocateBufferWithBackup(
453                             mNode, portIndex, mem, &info.mBufferID);
454                 } else {
455                     err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID);
456                 }
457 
458                 if (mem != NULL) {
459                     info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
460                 }
461 
462                 mBuffers[portIndex].push(info);
463             }
464         }
465     }
466 
467     if (err != OK) {
468         return err;
469     }
470 
471     sp<AMessage> notify = mNotify->dup();
472     notify->setInt32("what", ACodec::kWhatBuffersAllocated);
473 
474     notify->setInt32("portIndex", portIndex);
475 
476     sp<PortDescription> desc = new PortDescription;
477 
478     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
479         const BufferInfo &info = mBuffers[portIndex][i];
480 
481         desc->addBuffer(info.mBufferID, info.mData);
482     }
483 
484     notify->setObject("portDesc", desc);
485     notify->post();
486 
487     return OK;
488 }
489 
allocateOutputBuffersFromNativeWindow()490 status_t ACodec::allocateOutputBuffersFromNativeWindow() {
491     OMX_PARAM_PORTDEFINITIONTYPE def;
492     InitOMXParams(&def);
493     def.nPortIndex = kPortIndexOutput;
494 
495     status_t err = mOMX->getParameter(
496             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
497 
498     if (err != OK) {
499         return err;
500     }
501 
502     err = native_window_set_buffers_geometry(
503             mNativeWindow.get(),
504             def.format.video.nFrameWidth,
505             def.format.video.nFrameHeight,
506             def.format.video.eColorFormat);
507 
508     if (err != 0) {
509         ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
510                 strerror(-err), -err);
511         return err;
512     }
513 
514     // Set up the native window.
515     OMX_U32 usage = 0;
516     err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
517     if (err != 0) {
518         ALOGW("querying usage flags from OMX IL component failed: %d", err);
519         // XXX: Currently this error is logged, but not fatal.
520         usage = 0;
521     }
522 
523     if (mFlags & kFlagIsSecure) {
524         usage |= GRALLOC_USAGE_PROTECTED;
525     }
526 
527     // Make sure to check whether either Stagefright or the video decoder
528     // requested protected buffers.
529     if (usage & GRALLOC_USAGE_PROTECTED) {
530         // Verify that the ANativeWindow sends images directly to
531         // SurfaceFlinger.
532         int queuesToNativeWindow = 0;
533         err = mNativeWindow->query(
534                 mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
535                 &queuesToNativeWindow);
536         if (err != 0) {
537             ALOGE("error authenticating native window: %d", err);
538             return err;
539         }
540         if (queuesToNativeWindow != 1) {
541             ALOGE("native window could not be authenticated");
542             return PERMISSION_DENIED;
543         }
544     }
545 
546     err = native_window_set_usage(
547             mNativeWindow.get(),
548             usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
549 
550     if (err != 0) {
551         ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
552         return err;
553     }
554 
555     int minUndequeuedBufs = 0;
556     err = mNativeWindow->query(
557             mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
558             &minUndequeuedBufs);
559 
560     if (err != 0) {
561         ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
562                 strerror(-err), -err);
563         return err;
564     }
565 
566     // XXX: Is this the right logic to use?  It's not clear to me what the OMX
567     // buffer counts refer to - how do they account for the renderer holding on
568     // to buffers?
569     if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
570         OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
571         def.nBufferCountActual = newBufferCount;
572         err = mOMX->setParameter(
573                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
574 
575         if (err != OK) {
576             ALOGE("[%s] setting nBufferCountActual to %lu failed: %d",
577                     mComponentName.c_str(), newBufferCount, err);
578             return err;
579         }
580     }
581 
582     err = native_window_set_buffer_count(
583             mNativeWindow.get(), def.nBufferCountActual);
584 
585     if (err != 0) {
586         ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
587                 -err);
588         return err;
589     }
590 
591     ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
592          "output port",
593          mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize);
594 
595     // Dequeue buffers and send them to OMX
596     for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
597         ANativeWindowBuffer *buf;
598         err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
599         if (err != 0) {
600             ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
601             break;
602         }
603 
604         sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
605         BufferInfo info;
606         info.mStatus = BufferInfo::OWNED_BY_US;
607         info.mData = new ABuffer(0);
608         info.mGraphicBuffer = graphicBuffer;
609         mBuffers[kPortIndexOutput].push(info);
610 
611         IOMX::buffer_id bufferId;
612         err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
613                 &bufferId);
614         if (err != 0) {
615             ALOGE("registering GraphicBuffer %lu with OMX IL component failed: "
616                  "%d", i, err);
617             break;
618         }
619 
620         mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
621 
622         ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)",
623              mComponentName.c_str(),
624              bufferId, graphicBuffer.get());
625     }
626 
627     OMX_U32 cancelStart;
628     OMX_U32 cancelEnd;
629 
630     if (err != 0) {
631         // If an error occurred while dequeuing we need to cancel any buffers
632         // that were dequeued.
633         cancelStart = 0;
634         cancelEnd = mBuffers[kPortIndexOutput].size();
635     } else {
636         // Return the last two buffers to the native window.
637         cancelStart = def.nBufferCountActual - minUndequeuedBufs;
638         cancelEnd = def.nBufferCountActual;
639     }
640 
641     for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
642         BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
643         cancelBufferToNativeWindow(info);
644     }
645 
646     return err;
647 }
648 
cancelBufferToNativeWindow(BufferInfo * info)649 status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
650     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
651 
652     ALOGV("[%s] Calling cancelBuffer on buffer %p",
653          mComponentName.c_str(), info->mBufferID);
654 
655     int err = mNativeWindow->cancelBuffer(
656         mNativeWindow.get(), info->mGraphicBuffer.get());
657 
658     CHECK_EQ(err, 0);
659 
660     info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
661 
662     return OK;
663 }
664 
dequeueBufferFromNativeWindow()665 ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
666     ANativeWindowBuffer *buf;
667     if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) {
668         ALOGE("dequeueBuffer failed.");
669         return NULL;
670     }
671 
672     for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
673         BufferInfo *info =
674             &mBuffers[kPortIndexOutput].editItemAt(i);
675 
676         if (info->mGraphicBuffer->handle == buf->handle) {
677             CHECK_EQ((int)info->mStatus,
678                      (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
679 
680             info->mStatus = BufferInfo::OWNED_BY_US;
681 
682             return info;
683         }
684     }
685 
686     TRESPASS();
687 
688     return NULL;
689 }
690 
freeBuffersOnPort(OMX_U32 portIndex)691 status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
692     for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
693         CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
694     }
695 
696     mDealer[portIndex].clear();
697 
698     return OK;
699 }
700 
freeOutputBuffersNotOwnedByComponent()701 status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
702     for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
703         BufferInfo *info =
704             &mBuffers[kPortIndexOutput].editItemAt(i);
705 
706         if (info->mStatus !=
707                 BufferInfo::OWNED_BY_COMPONENT) {
708             // We shouldn't have sent out any buffers to the client at this
709             // point.
710             CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
711 
712             CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
713         }
714     }
715 
716     return OK;
717 }
718 
freeBuffer(OMX_U32 portIndex,size_t i)719 status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
720     BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
721 
722     CHECK(info->mStatus == BufferInfo::OWNED_BY_US
723             || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
724 
725     if (portIndex == kPortIndexOutput && mNativeWindow != NULL
726             && info->mStatus == BufferInfo::OWNED_BY_US) {
727         CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
728     }
729 
730     CHECK_EQ(mOMX->freeBuffer(
731                 mNode, portIndex, info->mBufferID),
732              (status_t)OK);
733 
734     mBuffers[portIndex].removeAt(i);
735 
736     return OK;
737 }
738 
findBufferByID(uint32_t portIndex,IOMX::buffer_id bufferID,ssize_t * index)739 ACodec::BufferInfo *ACodec::findBufferByID(
740         uint32_t portIndex, IOMX::buffer_id bufferID,
741         ssize_t *index) {
742     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
743         BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
744 
745         if (info->mBufferID == bufferID) {
746             if (index != NULL) {
747                 *index = i;
748             }
749             return info;
750         }
751     }
752 
753     TRESPASS();
754 
755     return NULL;
756 }
757 
setComponentRole(bool isEncoder,const char * mime)758 status_t ACodec::setComponentRole(
759         bool isEncoder, const char *mime) {
760     struct MimeToRole {
761         const char *mime;
762         const char *decoderRole;
763         const char *encoderRole;
764     };
765 
766     static const MimeToRole kMimeToRole[] = {
767         { MEDIA_MIMETYPE_AUDIO_MPEG,
768             "audio_decoder.mp3", "audio_encoder.mp3" },
769         { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
770             "audio_decoder.mp1", "audio_encoder.mp1" },
771         { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
772             "audio_decoder.mp2", "audio_encoder.mp2" },
773         { MEDIA_MIMETYPE_AUDIO_AMR_NB,
774             "audio_decoder.amrnb", "audio_encoder.amrnb" },
775         { MEDIA_MIMETYPE_AUDIO_AMR_WB,
776             "audio_decoder.amrwb", "audio_encoder.amrwb" },
777         { MEDIA_MIMETYPE_AUDIO_AAC,
778             "audio_decoder.aac", "audio_encoder.aac" },
779         { MEDIA_MIMETYPE_AUDIO_VORBIS,
780             "audio_decoder.vorbis", "audio_encoder.vorbis" },
781         { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
782             "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
783         { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
784             "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
785         { MEDIA_MIMETYPE_VIDEO_AVC,
786             "video_decoder.avc", "video_encoder.avc" },
787         { MEDIA_MIMETYPE_VIDEO_MPEG4,
788             "video_decoder.mpeg4", "video_encoder.mpeg4" },
789         { MEDIA_MIMETYPE_VIDEO_H263,
790             "video_decoder.h263", "video_encoder.h263" },
791         { MEDIA_MIMETYPE_VIDEO_VPX,
792             "video_decoder.vpx", "video_encoder.vpx" },
793         { MEDIA_MIMETYPE_AUDIO_RAW,
794             "audio_decoder.raw", "audio_encoder.raw" },
795         { MEDIA_MIMETYPE_AUDIO_FLAC,
796             "audio_decoder.flac", "audio_encoder.flac" },
797     };
798 
799     static const size_t kNumMimeToRole =
800         sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
801 
802     size_t i;
803     for (i = 0; i < kNumMimeToRole; ++i) {
804         if (!strcasecmp(mime, kMimeToRole[i].mime)) {
805             break;
806         }
807     }
808 
809     if (i == kNumMimeToRole) {
810         return ERROR_UNSUPPORTED;
811     }
812 
813     const char *role =
814         isEncoder ? kMimeToRole[i].encoderRole
815                   : kMimeToRole[i].decoderRole;
816 
817     if (role != NULL) {
818         OMX_PARAM_COMPONENTROLETYPE roleParams;
819         InitOMXParams(&roleParams);
820 
821         strncpy((char *)roleParams.cRole,
822                 role, OMX_MAX_STRINGNAME_SIZE - 1);
823 
824         roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
825 
826         status_t err = mOMX->setParameter(
827                 mNode, OMX_IndexParamStandardComponentRole,
828                 &roleParams, sizeof(roleParams));
829 
830         if (err != OK) {
831             ALOGW("[%s] Failed to set standard component role '%s'.",
832                  mComponentName.c_str(), role);
833 
834             return err;
835         }
836     }
837 
838     return OK;
839 }
840 
configureCodec(const char * mime,const sp<AMessage> & msg)841 status_t ACodec::configureCodec(
842         const char *mime, const sp<AMessage> &msg) {
843     int32_t encoder;
844     if (!msg->findInt32("encoder", &encoder)) {
845         encoder = false;
846     }
847 
848     mIsEncoder = encoder;
849 
850     status_t err = setComponentRole(encoder /* isEncoder */, mime);
851 
852     if (err != OK) {
853         return err;
854     }
855 
856     int32_t bitRate = 0;
857     // FLAC encoder doesn't need a bitrate, other encoders do
858     if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
859             && !msg->findInt32("bitrate", &bitRate)) {
860         return INVALID_OPERATION;
861     }
862 
863     if (!strncasecmp(mime, "video/", 6)) {
864         if (encoder) {
865             err = setupVideoEncoder(mime, msg);
866         } else {
867             int32_t width, height;
868             if (!msg->findInt32("width", &width)
869                     || !msg->findInt32("height", &height)) {
870                 err = INVALID_OPERATION;
871             } else {
872                 err = setupVideoDecoder(mime, width, height);
873             }
874         }
875     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
876         int32_t numChannels, sampleRate;
877         if (!msg->findInt32("channel-count", &numChannels)
878                 || !msg->findInt32("sample-rate", &sampleRate)) {
879             err = INVALID_OPERATION;
880         } else {
881             int32_t isADTS, aacProfile;
882             if (!msg->findInt32("is-adts", &isADTS)) {
883                 isADTS = 0;
884             }
885             if (!msg->findInt32("aac-profile", &aacProfile)) {
886                 aacProfile = OMX_AUDIO_AACObjectNull;
887             }
888 
889             err = setupAACCodec(
890                     encoder, numChannels, sampleRate, bitRate, aacProfile, isADTS != 0);
891         }
892     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
893         err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
894     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
895         err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
896     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
897             || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
898         // These are PCM-like formats with a fixed sample rate but
899         // a variable number of channels.
900 
901         int32_t numChannels;
902         if (!msg->findInt32("channel-count", &numChannels)) {
903             err = INVALID_OPERATION;
904         } else {
905             err = setupG711Codec(encoder, numChannels);
906         }
907     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
908         int32_t numChannels, sampleRate, compressionLevel = -1;
909         if (encoder &&
910                 (!msg->findInt32("channel-count", &numChannels)
911                         || !msg->findInt32("sample-rate", &sampleRate))) {
912             ALOGE("missing channel count or sample rate for FLAC encoder");
913             err = INVALID_OPERATION;
914         } else {
915             if (encoder) {
916                 if (!msg->findInt32("flac-compression-level", &compressionLevel)) {
917                     compressionLevel = 5;// default FLAC compression level
918                 } else if (compressionLevel < 0) {
919                     ALOGW("compression level %d outside [0..8] range, using 0", compressionLevel);
920                     compressionLevel = 0;
921                 } else if (compressionLevel > 8) {
922                     ALOGW("compression level %d outside [0..8] range, using 8", compressionLevel);
923                     compressionLevel = 8;
924                 }
925             }
926             err = setupFlacCodec(encoder, numChannels, sampleRate, compressionLevel);
927         }
928     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
929         int32_t numChannels, sampleRate;
930         if (encoder
931                 || !msg->findInt32("channel-count", &numChannels)
932                 || !msg->findInt32("sample-rate", &sampleRate)) {
933             err = INVALID_OPERATION;
934         } else {
935             err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
936         }
937     }
938 
939     if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
940         mEncoderDelay = 0;
941     }
942 
943     if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
944         mEncoderPadding = 0;
945     }
946 
947     if (msg->findInt32("channel-mask", &mChannelMask)) {
948         mChannelMaskPresent = true;
949     } else {
950         mChannelMaskPresent = false;
951     }
952 
953     int32_t maxInputSize;
954     if (msg->findInt32("max-input-size", &maxInputSize)) {
955         err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
956     } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
957         err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
958     }
959 
960     return err;
961 }
962 
setMinBufferSize(OMX_U32 portIndex,size_t size)963 status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
964     OMX_PARAM_PORTDEFINITIONTYPE def;
965     InitOMXParams(&def);
966     def.nPortIndex = portIndex;
967 
968     status_t err = mOMX->getParameter(
969             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
970 
971     if (err != OK) {
972         return err;
973     }
974 
975     if (def.nBufferSize >= size) {
976         return OK;
977     }
978 
979     def.nBufferSize = size;
980 
981     err = mOMX->setParameter(
982             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
983 
984     if (err != OK) {
985         return err;
986     }
987 
988     err = mOMX->getParameter(
989             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
990 
991     if (err != OK) {
992         return err;
993     }
994 
995     CHECK(def.nBufferSize >= size);
996 
997     return OK;
998 }
999 
selectAudioPortFormat(OMX_U32 portIndex,OMX_AUDIO_CODINGTYPE desiredFormat)1000 status_t ACodec::selectAudioPortFormat(
1001         OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
1002     OMX_AUDIO_PARAM_PORTFORMATTYPE format;
1003     InitOMXParams(&format);
1004 
1005     format.nPortIndex = portIndex;
1006     for (OMX_U32 index = 0;; ++index) {
1007         format.nIndex = index;
1008 
1009         status_t err = mOMX->getParameter(
1010                 mNode, OMX_IndexParamAudioPortFormat,
1011                 &format, sizeof(format));
1012 
1013         if (err != OK) {
1014             return err;
1015         }
1016 
1017         if (format.eEncoding == desiredFormat) {
1018             break;
1019         }
1020     }
1021 
1022     return mOMX->setParameter(
1023             mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
1024 }
1025 
setupAACCodec(bool encoder,int32_t numChannels,int32_t sampleRate,int32_t bitRate,int32_t aacProfile,bool isADTS)1026 status_t ACodec::setupAACCodec(
1027         bool encoder, int32_t numChannels, int32_t sampleRate,
1028         int32_t bitRate, int32_t aacProfile, bool isADTS) {
1029     if (encoder && isADTS) {
1030         return -EINVAL;
1031     }
1032 
1033     status_t err = setupRawAudioFormat(
1034             encoder ? kPortIndexInput : kPortIndexOutput,
1035             sampleRate,
1036             numChannels);
1037 
1038     if (err != OK) {
1039         return err;
1040     }
1041 
1042     if (encoder) {
1043         err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
1044 
1045         if (err != OK) {
1046             return err;
1047         }
1048 
1049         OMX_PARAM_PORTDEFINITIONTYPE def;
1050         InitOMXParams(&def);
1051         def.nPortIndex = kPortIndexOutput;
1052 
1053         err = mOMX->getParameter(
1054                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1055 
1056         if (err != OK) {
1057             return err;
1058         }
1059 
1060         def.format.audio.bFlagErrorConcealment = OMX_TRUE;
1061         def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1062 
1063         err = mOMX->setParameter(
1064                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1065 
1066         if (err != OK) {
1067             return err;
1068         }
1069 
1070         OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1071         InitOMXParams(&profile);
1072         profile.nPortIndex = kPortIndexOutput;
1073 
1074         err = mOMX->getParameter(
1075                 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1076 
1077         if (err != OK) {
1078             return err;
1079         }
1080 
1081         profile.nChannels = numChannels;
1082 
1083         profile.eChannelMode =
1084             (numChannels == 1)
1085                 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
1086 
1087         profile.nSampleRate = sampleRate;
1088         profile.nBitRate = bitRate;
1089         profile.nAudioBandWidth = 0;
1090         profile.nFrameLength = 0;
1091         profile.nAACtools = OMX_AUDIO_AACToolAll;
1092         profile.nAACERtools = OMX_AUDIO_AACERNone;
1093         profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
1094         profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1095 
1096         err = mOMX->setParameter(
1097                 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1098 
1099         if (err != OK) {
1100             return err;
1101         }
1102 
1103         return err;
1104     }
1105 
1106     OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1107     InitOMXParams(&profile);
1108     profile.nPortIndex = kPortIndexInput;
1109 
1110     err = mOMX->getParameter(
1111             mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1112 
1113     if (err != OK) {
1114         return err;
1115     }
1116 
1117     profile.nChannels = numChannels;
1118     profile.nSampleRate = sampleRate;
1119 
1120     profile.eAACStreamFormat =
1121         isADTS
1122             ? OMX_AUDIO_AACStreamFormatMP4ADTS
1123             : OMX_AUDIO_AACStreamFormatMP4FF;
1124 
1125     return mOMX->setParameter(
1126             mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1127 }
1128 
pickModeFromBitRate(bool isAMRWB,int32_t bps)1129 static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
1130         bool isAMRWB, int32_t bps) {
1131     if (isAMRWB) {
1132         if (bps <= 6600) {
1133             return OMX_AUDIO_AMRBandModeWB0;
1134         } else if (bps <= 8850) {
1135             return OMX_AUDIO_AMRBandModeWB1;
1136         } else if (bps <= 12650) {
1137             return OMX_AUDIO_AMRBandModeWB2;
1138         } else if (bps <= 14250) {
1139             return OMX_AUDIO_AMRBandModeWB3;
1140         } else if (bps <= 15850) {
1141             return OMX_AUDIO_AMRBandModeWB4;
1142         } else if (bps <= 18250) {
1143             return OMX_AUDIO_AMRBandModeWB5;
1144         } else if (bps <= 19850) {
1145             return OMX_AUDIO_AMRBandModeWB6;
1146         } else if (bps <= 23050) {
1147             return OMX_AUDIO_AMRBandModeWB7;
1148         }
1149 
1150         // 23850 bps
1151         return OMX_AUDIO_AMRBandModeWB8;
1152     } else {  // AMRNB
1153         if (bps <= 4750) {
1154             return OMX_AUDIO_AMRBandModeNB0;
1155         } else if (bps <= 5150) {
1156             return OMX_AUDIO_AMRBandModeNB1;
1157         } else if (bps <= 5900) {
1158             return OMX_AUDIO_AMRBandModeNB2;
1159         } else if (bps <= 6700) {
1160             return OMX_AUDIO_AMRBandModeNB3;
1161         } else if (bps <= 7400) {
1162             return OMX_AUDIO_AMRBandModeNB4;
1163         } else if (bps <= 7950) {
1164             return OMX_AUDIO_AMRBandModeNB5;
1165         } else if (bps <= 10200) {
1166             return OMX_AUDIO_AMRBandModeNB6;
1167         }
1168 
1169         // 12200 bps
1170         return OMX_AUDIO_AMRBandModeNB7;
1171     }
1172 }
1173 
setupAMRCodec(bool encoder,bool isWAMR,int32_t bitrate)1174 status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
1175     OMX_AUDIO_PARAM_AMRTYPE def;
1176     InitOMXParams(&def);
1177     def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
1178 
1179     status_t err =
1180         mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1181 
1182     if (err != OK) {
1183         return err;
1184     }
1185 
1186     def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1187     def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
1188 
1189     err = mOMX->setParameter(
1190             mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1191 
1192     if (err != OK) {
1193         return err;
1194     }
1195 
1196     return setupRawAudioFormat(
1197             encoder ? kPortIndexInput : kPortIndexOutput,
1198             isWAMR ? 16000 : 8000 /* sampleRate */,
1199             1 /* numChannels */);
1200 }
1201 
setupG711Codec(bool encoder,int32_t numChannels)1202 status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
1203     CHECK(!encoder);  // XXX TODO
1204 
1205     return setupRawAudioFormat(
1206             kPortIndexInput, 8000 /* sampleRate */, numChannels);
1207 }
1208 
setupFlacCodec(bool encoder,int32_t numChannels,int32_t sampleRate,int32_t compressionLevel)1209 status_t ACodec::setupFlacCodec(
1210         bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
1211 
1212     if (encoder) {
1213         OMX_AUDIO_PARAM_FLACTYPE def;
1214         InitOMXParams(&def);
1215         def.nPortIndex = kPortIndexOutput;
1216 
1217         // configure compression level
1218         status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1219         if (err != OK) {
1220             ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
1221             return err;
1222         }
1223         def.nCompressionLevel = compressionLevel;
1224         err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1225         if (err != OK) {
1226             ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
1227             return err;
1228         }
1229     }
1230 
1231     return setupRawAudioFormat(
1232             encoder ? kPortIndexInput : kPortIndexOutput,
1233             sampleRate,
1234             numChannels);
1235 }
1236 
setupRawAudioFormat(OMX_U32 portIndex,int32_t sampleRate,int32_t numChannels)1237 status_t ACodec::setupRawAudioFormat(
1238         OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1239     OMX_PARAM_PORTDEFINITIONTYPE def;
1240     InitOMXParams(&def);
1241     def.nPortIndex = portIndex;
1242 
1243     status_t err = mOMX->getParameter(
1244             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1245 
1246     if (err != OK) {
1247         return err;
1248     }
1249 
1250     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
1251 
1252     err = mOMX->setParameter(
1253             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1254 
1255     if (err != OK) {
1256         return err;
1257     }
1258 
1259     OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
1260     InitOMXParams(&pcmParams);
1261     pcmParams.nPortIndex = portIndex;
1262 
1263     err = mOMX->getParameter(
1264             mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1265 
1266     if (err != OK) {
1267         return err;
1268     }
1269 
1270     pcmParams.nChannels = numChannels;
1271     pcmParams.eNumData = OMX_NumericalDataSigned;
1272     pcmParams.bInterleaved = OMX_TRUE;
1273     pcmParams.nBitPerSample = 16;
1274     pcmParams.nSamplingRate = sampleRate;
1275     pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1276 
1277     if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
1278         return OMX_ErrorNone;
1279     }
1280 
1281     return mOMX->setParameter(
1282             mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1283 }
1284 
setVideoPortFormatType(OMX_U32 portIndex,OMX_VIDEO_CODINGTYPE compressionFormat,OMX_COLOR_FORMATTYPE colorFormat)1285 status_t ACodec::setVideoPortFormatType(
1286         OMX_U32 portIndex,
1287         OMX_VIDEO_CODINGTYPE compressionFormat,
1288         OMX_COLOR_FORMATTYPE colorFormat) {
1289     OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1290     InitOMXParams(&format);
1291     format.nPortIndex = portIndex;
1292     format.nIndex = 0;
1293     bool found = false;
1294 
1295     OMX_U32 index = 0;
1296     for (;;) {
1297         format.nIndex = index;
1298         status_t err = mOMX->getParameter(
1299                 mNode, OMX_IndexParamVideoPortFormat,
1300                 &format, sizeof(format));
1301 
1302         if (err != OK) {
1303             return err;
1304         }
1305 
1306         // The following assertion is violated by TI's video decoder.
1307         // CHECK_EQ(format.nIndex, index);
1308 
1309         if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
1310             if (portIndex == kPortIndexInput
1311                     && colorFormat == format.eColorFormat) {
1312                 // eCompressionFormat does not seem right.
1313                 found = true;
1314                 break;
1315             }
1316             if (portIndex == kPortIndexOutput
1317                     && compressionFormat == format.eCompressionFormat) {
1318                 // eColorFormat does not seem right.
1319                 found = true;
1320                 break;
1321             }
1322         }
1323 
1324         if (format.eCompressionFormat == compressionFormat
1325             && format.eColorFormat == colorFormat) {
1326             found = true;
1327             break;
1328         }
1329 
1330         ++index;
1331     }
1332 
1333     if (!found) {
1334         return UNKNOWN_ERROR;
1335     }
1336 
1337     status_t err = mOMX->setParameter(
1338             mNode, OMX_IndexParamVideoPortFormat,
1339             &format, sizeof(format));
1340 
1341     return err;
1342 }
1343 
setSupportedOutputFormat()1344 status_t ACodec::setSupportedOutputFormat() {
1345     OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1346     InitOMXParams(&format);
1347     format.nPortIndex = kPortIndexOutput;
1348     format.nIndex = 0;
1349 
1350     status_t err = mOMX->getParameter(
1351             mNode, OMX_IndexParamVideoPortFormat,
1352             &format, sizeof(format));
1353     CHECK_EQ(err, (status_t)OK);
1354     CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
1355 
1356     CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
1357            || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
1358            || format.eColorFormat == OMX_COLOR_FormatCbYCrY
1359            || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
1360            || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
1361 
1362     return mOMX->setParameter(
1363             mNode, OMX_IndexParamVideoPortFormat,
1364             &format, sizeof(format));
1365 }
1366 
GetVideoCodingTypeFromMime(const char * mime,OMX_VIDEO_CODINGTYPE * codingType)1367 static status_t GetVideoCodingTypeFromMime(
1368         const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
1369     if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
1370         *codingType = OMX_VIDEO_CodingAVC;
1371     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
1372         *codingType = OMX_VIDEO_CodingMPEG4;
1373     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
1374         *codingType = OMX_VIDEO_CodingH263;
1375     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
1376         *codingType = OMX_VIDEO_CodingMPEG2;
1377     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) {
1378         *codingType = OMX_VIDEO_CodingVPX;
1379     } else {
1380         *codingType = OMX_VIDEO_CodingUnused;
1381         return ERROR_UNSUPPORTED;
1382     }
1383 
1384     return OK;
1385 }
1386 
setupVideoDecoder(const char * mime,int32_t width,int32_t height)1387 status_t ACodec::setupVideoDecoder(
1388         const char *mime, int32_t width, int32_t height) {
1389     OMX_VIDEO_CODINGTYPE compressionFormat;
1390     status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1391 
1392     if (err != OK) {
1393         return err;
1394     }
1395 
1396     err = setVideoPortFormatType(
1397             kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1398 
1399     if (err != OK) {
1400         return err;
1401     }
1402 
1403     err = setSupportedOutputFormat();
1404 
1405     if (err != OK) {
1406         return err;
1407     }
1408 
1409     err = setVideoFormatOnPort(
1410             kPortIndexInput, width, height, compressionFormat);
1411 
1412     if (err != OK) {
1413         return err;
1414     }
1415 
1416     err = setVideoFormatOnPort(
1417             kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
1418 
1419     if (err != OK) {
1420         return err;
1421     }
1422 
1423     return OK;
1424 }
1425 
setupVideoEncoder(const char * mime,const sp<AMessage> & msg)1426 status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
1427     int32_t tmp;
1428     if (!msg->findInt32("color-format", &tmp)) {
1429         return INVALID_OPERATION;
1430     }
1431 
1432     OMX_COLOR_FORMATTYPE colorFormat =
1433         static_cast<OMX_COLOR_FORMATTYPE>(tmp);
1434 
1435     status_t err = setVideoPortFormatType(
1436             kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
1437 
1438     if (err != OK) {
1439         ALOGE("[%s] does not support color format %d",
1440               mComponentName.c_str(), colorFormat);
1441 
1442         return err;
1443     }
1444 
1445     /* Input port configuration */
1446 
1447     OMX_PARAM_PORTDEFINITIONTYPE def;
1448     InitOMXParams(&def);
1449 
1450     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1451 
1452     def.nPortIndex = kPortIndexInput;
1453 
1454     err = mOMX->getParameter(
1455             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1456 
1457     if (err != OK) {
1458         return err;
1459     }
1460 
1461     int32_t width, height, bitrate;
1462     if (!msg->findInt32("width", &width)
1463             || !msg->findInt32("height", &height)
1464             || !msg->findInt32("bitrate", &bitrate)) {
1465         return INVALID_OPERATION;
1466     }
1467 
1468     video_def->nFrameWidth = width;
1469     video_def->nFrameHeight = height;
1470 
1471     int32_t stride;
1472     if (!msg->findInt32("stride", &stride)) {
1473         stride = width;
1474     }
1475 
1476     video_def->nStride = stride;
1477 
1478     int32_t sliceHeight;
1479     if (!msg->findInt32("slice-height", &sliceHeight)) {
1480         sliceHeight = height;
1481     }
1482 
1483     video_def->nSliceHeight = sliceHeight;
1484 
1485     def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
1486 
1487     float frameRate;
1488     if (!msg->findFloat("frame-rate", &frameRate)) {
1489         int32_t tmp;
1490         if (!msg->findInt32("frame-rate", &tmp)) {
1491             return INVALID_OPERATION;
1492         }
1493         frameRate = (float)tmp;
1494     }
1495 
1496     video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
1497     video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
1498     video_def->eColorFormat = colorFormat;
1499 
1500     err = mOMX->setParameter(
1501             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1502 
1503     if (err != OK) {
1504         ALOGE("[%s] failed to set input port definition parameters.",
1505               mComponentName.c_str());
1506 
1507         return err;
1508     }
1509 
1510     /* Output port configuration */
1511 
1512     OMX_VIDEO_CODINGTYPE compressionFormat;
1513     err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1514 
1515     if (err != OK) {
1516         return err;
1517     }
1518 
1519     err = setVideoPortFormatType(
1520             kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
1521 
1522     if (err != OK) {
1523         ALOGE("[%s] does not support compression format %d",
1524              mComponentName.c_str(), compressionFormat);
1525 
1526         return err;
1527     }
1528 
1529     def.nPortIndex = kPortIndexOutput;
1530 
1531     err = mOMX->getParameter(
1532             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1533 
1534     if (err != OK) {
1535         return err;
1536     }
1537 
1538     video_def->nFrameWidth = width;
1539     video_def->nFrameHeight = height;
1540     video_def->xFramerate = 0;
1541     video_def->nBitrate = bitrate;
1542     video_def->eCompressionFormat = compressionFormat;
1543     video_def->eColorFormat = OMX_COLOR_FormatUnused;
1544 
1545     err = mOMX->setParameter(
1546             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1547 
1548     if (err != OK) {
1549         ALOGE("[%s] failed to set output port definition parameters.",
1550               mComponentName.c_str());
1551 
1552         return err;
1553     }
1554 
1555     switch (compressionFormat) {
1556         case OMX_VIDEO_CodingMPEG4:
1557             err = setupMPEG4EncoderParameters(msg);
1558             break;
1559 
1560         case OMX_VIDEO_CodingH263:
1561             err = setupH263EncoderParameters(msg);
1562             break;
1563 
1564         case OMX_VIDEO_CodingAVC:
1565             err = setupAVCEncoderParameters(msg);
1566             break;
1567 
1568         default:
1569             break;
1570     }
1571 
1572     ALOGI("setupVideoEncoder succeeded");
1573 
1574     return err;
1575 }
1576 
setPFramesSpacing(int32_t iFramesInterval,int32_t frameRate)1577 static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
1578     if (iFramesInterval < 0) {
1579         return 0xFFFFFFFF;
1580     } else if (iFramesInterval == 0) {
1581         return 0;
1582     }
1583     OMX_U32 ret = frameRate * iFramesInterval;
1584     CHECK(ret > 1);
1585     return ret;
1586 }
1587 
setupMPEG4EncoderParameters(const sp<AMessage> & msg)1588 status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
1589     int32_t bitrate, iFrameInterval;
1590     if (!msg->findInt32("bitrate", &bitrate)
1591             || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1592         return INVALID_OPERATION;
1593     }
1594 
1595     float frameRate;
1596     if (!msg->findFloat("frame-rate", &frameRate)) {
1597         int32_t tmp;
1598         if (!msg->findInt32("frame-rate", &tmp)) {
1599             return INVALID_OPERATION;
1600         }
1601         frameRate = (float)tmp;
1602     }
1603 
1604     OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
1605     InitOMXParams(&mpeg4type);
1606     mpeg4type.nPortIndex = kPortIndexOutput;
1607 
1608     status_t err = mOMX->getParameter(
1609             mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1610 
1611     if (err != OK) {
1612         return err;
1613     }
1614 
1615     mpeg4type.nSliceHeaderSpacing = 0;
1616     mpeg4type.bSVH = OMX_FALSE;
1617     mpeg4type.bGov = OMX_FALSE;
1618 
1619     mpeg4type.nAllowedPictureTypes =
1620         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1621 
1622     mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1623     if (mpeg4type.nPFrames == 0) {
1624         mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1625     }
1626     mpeg4type.nBFrames = 0;
1627     mpeg4type.nIDCVLCThreshold = 0;
1628     mpeg4type.bACPred = OMX_TRUE;
1629     mpeg4type.nMaxPacketSize = 256;
1630     mpeg4type.nTimeIncRes = 1000;
1631     mpeg4type.nHeaderExtension = 0;
1632     mpeg4type.bReversibleVLC = OMX_FALSE;
1633 
1634     int32_t profile;
1635     if (msg->findInt32("profile", &profile)) {
1636         int32_t level;
1637         if (!msg->findInt32("level", &level)) {
1638             return INVALID_OPERATION;
1639         }
1640 
1641         err = verifySupportForProfileAndLevel(profile, level);
1642 
1643         if (err != OK) {
1644             return err;
1645         }
1646 
1647         mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
1648         mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
1649     }
1650 
1651     err = mOMX->setParameter(
1652             mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1653 
1654     if (err != OK) {
1655         return err;
1656     }
1657 
1658     err = configureBitrate(bitrate);
1659 
1660     if (err != OK) {
1661         return err;
1662     }
1663 
1664     return setupErrorCorrectionParameters();
1665 }
1666 
setupH263EncoderParameters(const sp<AMessage> & msg)1667 status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
1668     int32_t bitrate, iFrameInterval;
1669     if (!msg->findInt32("bitrate", &bitrate)
1670             || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1671         return INVALID_OPERATION;
1672     }
1673 
1674     float frameRate;
1675     if (!msg->findFloat("frame-rate", &frameRate)) {
1676         int32_t tmp;
1677         if (!msg->findInt32("frame-rate", &tmp)) {
1678             return INVALID_OPERATION;
1679         }
1680         frameRate = (float)tmp;
1681     }
1682 
1683     OMX_VIDEO_PARAM_H263TYPE h263type;
1684     InitOMXParams(&h263type);
1685     h263type.nPortIndex = kPortIndexOutput;
1686 
1687     status_t err = mOMX->getParameter(
1688             mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1689 
1690     if (err != OK) {
1691         return err;
1692     }
1693 
1694     h263type.nAllowedPictureTypes =
1695         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1696 
1697     h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1698     if (h263type.nPFrames == 0) {
1699         h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1700     }
1701     h263type.nBFrames = 0;
1702 
1703     int32_t profile;
1704     if (msg->findInt32("profile", &profile)) {
1705         int32_t level;
1706         if (!msg->findInt32("level", &level)) {
1707             return INVALID_OPERATION;
1708         }
1709 
1710         err = verifySupportForProfileAndLevel(profile, level);
1711 
1712         if (err != OK) {
1713             return err;
1714         }
1715 
1716         h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
1717         h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
1718     }
1719 
1720     h263type.bPLUSPTYPEAllowed = OMX_FALSE;
1721     h263type.bForceRoundingTypeToZero = OMX_FALSE;
1722     h263type.nPictureHeaderRepetition = 0;
1723     h263type.nGOBHeaderInterval = 0;
1724 
1725     err = mOMX->setParameter(
1726             mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1727 
1728     if (err != OK) {
1729         return err;
1730     }
1731 
1732     err = configureBitrate(bitrate);
1733 
1734     if (err != OK) {
1735         return err;
1736     }
1737 
1738     return setupErrorCorrectionParameters();
1739 }
1740 
setupAVCEncoderParameters(const sp<AMessage> & msg)1741 status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
1742     int32_t bitrate, iFrameInterval;
1743     if (!msg->findInt32("bitrate", &bitrate)
1744             || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1745         return INVALID_OPERATION;
1746     }
1747 
1748     float frameRate;
1749     if (!msg->findFloat("frame-rate", &frameRate)) {
1750         int32_t tmp;
1751         if (!msg->findInt32("frame-rate", &tmp)) {
1752             return INVALID_OPERATION;
1753         }
1754         frameRate = (float)tmp;
1755     }
1756 
1757     OMX_VIDEO_PARAM_AVCTYPE h264type;
1758     InitOMXParams(&h264type);
1759     h264type.nPortIndex = kPortIndexOutput;
1760 
1761     status_t err = mOMX->getParameter(
1762             mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1763 
1764     if (err != OK) {
1765         return err;
1766     }
1767 
1768     h264type.nAllowedPictureTypes =
1769         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1770 
1771     int32_t profile;
1772     if (msg->findInt32("profile", &profile)) {
1773         int32_t level;
1774         if (!msg->findInt32("level", &level)) {
1775             return INVALID_OPERATION;
1776         }
1777 
1778         err = verifySupportForProfileAndLevel(profile, level);
1779 
1780         if (err != OK) {
1781             return err;
1782         }
1783 
1784         h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
1785         h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
1786     }
1787 
1788     // XXX
1789     if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
1790         ALOGW("Use baseline profile instead of %d for AVC recording",
1791             h264type.eProfile);
1792         h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
1793     }
1794 
1795     if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
1796         h264type.nSliceHeaderSpacing = 0;
1797         h264type.bUseHadamard = OMX_TRUE;
1798         h264type.nRefFrames = 1;
1799         h264type.nBFrames = 0;
1800         h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1801         if (h264type.nPFrames == 0) {
1802             h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1803         }
1804         h264type.nRefIdx10ActiveMinus1 = 0;
1805         h264type.nRefIdx11ActiveMinus1 = 0;
1806         h264type.bEntropyCodingCABAC = OMX_FALSE;
1807         h264type.bWeightedPPrediction = OMX_FALSE;
1808         h264type.bconstIpred = OMX_FALSE;
1809         h264type.bDirect8x8Inference = OMX_FALSE;
1810         h264type.bDirectSpatialTemporal = OMX_FALSE;
1811         h264type.nCabacInitIdc = 0;
1812     }
1813 
1814     if (h264type.nBFrames != 0) {
1815         h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
1816     }
1817 
1818     h264type.bEnableUEP = OMX_FALSE;
1819     h264type.bEnableFMO = OMX_FALSE;
1820     h264type.bEnableASO = OMX_FALSE;
1821     h264type.bEnableRS = OMX_FALSE;
1822     h264type.bFrameMBsOnly = OMX_TRUE;
1823     h264type.bMBAFF = OMX_FALSE;
1824     h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
1825 
1826     err = mOMX->setParameter(
1827             mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1828 
1829     if (err != OK) {
1830         return err;
1831     }
1832 
1833     return configureBitrate(bitrate);
1834 }
1835 
verifySupportForProfileAndLevel(int32_t profile,int32_t level)1836 status_t ACodec::verifySupportForProfileAndLevel(
1837         int32_t profile, int32_t level) {
1838     OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
1839     InitOMXParams(&params);
1840     params.nPortIndex = kPortIndexOutput;
1841 
1842     for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
1843         status_t err = mOMX->getParameter(
1844                 mNode,
1845                 OMX_IndexParamVideoProfileLevelQuerySupported,
1846                 &params,
1847                 sizeof(params));
1848 
1849         if (err != OK) {
1850             return err;
1851         }
1852 
1853         int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
1854         int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
1855 
1856         if (profile == supportedProfile && level <= supportedLevel) {
1857             return OK;
1858         }
1859     }
1860 }
1861 
configureBitrate(int32_t bitrate)1862 status_t ACodec::configureBitrate(int32_t bitrate) {
1863     OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
1864     InitOMXParams(&bitrateType);
1865     bitrateType.nPortIndex = kPortIndexOutput;
1866 
1867     status_t err = mOMX->getParameter(
1868             mNode, OMX_IndexParamVideoBitrate,
1869             &bitrateType, sizeof(bitrateType));
1870 
1871     if (err != OK) {
1872         return err;
1873     }
1874 
1875     bitrateType.eControlRate = OMX_Video_ControlRateVariable;
1876     bitrateType.nTargetBitrate = bitrate;
1877 
1878     return mOMX->setParameter(
1879             mNode, OMX_IndexParamVideoBitrate,
1880             &bitrateType, sizeof(bitrateType));
1881 }
1882 
setupErrorCorrectionParameters()1883 status_t ACodec::setupErrorCorrectionParameters() {
1884     OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
1885     InitOMXParams(&errorCorrectionType);
1886     errorCorrectionType.nPortIndex = kPortIndexOutput;
1887 
1888     status_t err = mOMX->getParameter(
1889             mNode, OMX_IndexParamVideoErrorCorrection,
1890             &errorCorrectionType, sizeof(errorCorrectionType));
1891 
1892     if (err != OK) {
1893         return OK;  // Optional feature. Ignore this failure
1894     }
1895 
1896     errorCorrectionType.bEnableHEC = OMX_FALSE;
1897     errorCorrectionType.bEnableResync = OMX_TRUE;
1898     errorCorrectionType.nResynchMarkerSpacing = 256;
1899     errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
1900     errorCorrectionType.bEnableRVLC = OMX_FALSE;
1901 
1902     return mOMX->setParameter(
1903             mNode, OMX_IndexParamVideoErrorCorrection,
1904             &errorCorrectionType, sizeof(errorCorrectionType));
1905 }
1906 
setVideoFormatOnPort(OMX_U32 portIndex,int32_t width,int32_t height,OMX_VIDEO_CODINGTYPE compressionFormat)1907 status_t ACodec::setVideoFormatOnPort(
1908         OMX_U32 portIndex,
1909         int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
1910     OMX_PARAM_PORTDEFINITIONTYPE def;
1911     InitOMXParams(&def);
1912     def.nPortIndex = portIndex;
1913 
1914     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1915 
1916     status_t err = mOMX->getParameter(
1917             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1918 
1919     CHECK_EQ(err, (status_t)OK);
1920 
1921     if (portIndex == kPortIndexInput) {
1922         // XXX Need a (much) better heuristic to compute input buffer sizes.
1923         const size_t X = 64 * 1024;
1924         if (def.nBufferSize < X) {
1925             def.nBufferSize = X;
1926         }
1927     }
1928 
1929     CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
1930 
1931     video_def->nFrameWidth = width;
1932     video_def->nFrameHeight = height;
1933 
1934     if (portIndex == kPortIndexInput) {
1935         video_def->eCompressionFormat = compressionFormat;
1936         video_def->eColorFormat = OMX_COLOR_FormatUnused;
1937     }
1938 
1939     err = mOMX->setParameter(
1940             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1941 
1942     return err;
1943 }
1944 
initNativeWindow()1945 status_t ACodec::initNativeWindow() {
1946     if (mNativeWindow != NULL) {
1947         return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
1948     }
1949 
1950     mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
1951     return OK;
1952 }
1953 
countBuffersOwnedByComponent(OMX_U32 portIndex) const1954 size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
1955     size_t n = 0;
1956 
1957     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1958         const BufferInfo &info = mBuffers[portIndex].itemAt(i);
1959 
1960         if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
1961             ++n;
1962         }
1963     }
1964 
1965     return n;
1966 }
1967 
allYourBuffersAreBelongToUs(OMX_U32 portIndex)1968 bool ACodec::allYourBuffersAreBelongToUs(
1969         OMX_U32 portIndex) {
1970     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1971         BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1972 
1973         if (info->mStatus != BufferInfo::OWNED_BY_US
1974                 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1975             ALOGV("[%s] Buffer %p on port %ld still has status %d",
1976                     mComponentName.c_str(),
1977                     info->mBufferID, portIndex, info->mStatus);
1978             return false;
1979         }
1980     }
1981 
1982     return true;
1983 }
1984 
allYourBuffersAreBelongToUs()1985 bool ACodec::allYourBuffersAreBelongToUs() {
1986     return allYourBuffersAreBelongToUs(kPortIndexInput)
1987         && allYourBuffersAreBelongToUs(kPortIndexOutput);
1988 }
1989 
deferMessage(const sp<AMessage> & msg)1990 void ACodec::deferMessage(const sp<AMessage> &msg) {
1991     bool wasEmptyBefore = mDeferredQueue.empty();
1992     mDeferredQueue.push_back(msg);
1993 }
1994 
processDeferredMessages()1995 void ACodec::processDeferredMessages() {
1996     List<sp<AMessage> > queue = mDeferredQueue;
1997     mDeferredQueue.clear();
1998 
1999     List<sp<AMessage> >::iterator it = queue.begin();
2000     while (it != queue.end()) {
2001         onMessageReceived(*it++);
2002     }
2003 }
2004 
sendFormatChange()2005 void ACodec::sendFormatChange() {
2006     sp<AMessage> notify = mNotify->dup();
2007     notify->setInt32("what", kWhatOutputFormatChanged);
2008 
2009     OMX_PARAM_PORTDEFINITIONTYPE def;
2010     InitOMXParams(&def);
2011     def.nPortIndex = kPortIndexOutput;
2012 
2013     CHECK_EQ(mOMX->getParameter(
2014                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
2015              (status_t)OK);
2016 
2017     CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
2018 
2019     switch (def.eDomain) {
2020         case OMX_PortDomainVideo:
2021         {
2022             OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2023 
2024             notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
2025             notify->setInt32("width", videoDef->nFrameWidth);
2026             notify->setInt32("height", videoDef->nFrameHeight);
2027             notify->setInt32("stride", videoDef->nStride);
2028             notify->setInt32("slice-height", videoDef->nSliceHeight);
2029             notify->setInt32("color-format", videoDef->eColorFormat);
2030 
2031             OMX_CONFIG_RECTTYPE rect;
2032             InitOMXParams(&rect);
2033             rect.nPortIndex = kPortIndexOutput;
2034 
2035             if (mOMX->getConfig(
2036                         mNode, OMX_IndexConfigCommonOutputCrop,
2037                         &rect, sizeof(rect)) != OK) {
2038                 rect.nLeft = 0;
2039                 rect.nTop = 0;
2040                 rect.nWidth = videoDef->nFrameWidth;
2041                 rect.nHeight = videoDef->nFrameHeight;
2042             }
2043 
2044             CHECK_GE(rect.nLeft, 0);
2045             CHECK_GE(rect.nTop, 0);
2046             CHECK_GE(rect.nWidth, 0u);
2047             CHECK_GE(rect.nHeight, 0u);
2048             CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
2049             CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
2050 
2051             notify->setRect(
2052                     "crop",
2053                     rect.nLeft,
2054                     rect.nTop,
2055                     rect.nLeft + rect.nWidth - 1,
2056                     rect.nTop + rect.nHeight - 1);
2057 
2058             if (mNativeWindow != NULL) {
2059                 android_native_rect_t crop;
2060                 crop.left = rect.nLeft;
2061                 crop.top = rect.nTop;
2062                 crop.right = rect.nLeft + rect.nWidth;
2063                 crop.bottom = rect.nTop + rect.nHeight;
2064 
2065                 CHECK_EQ(0, native_window_set_crop(
2066                             mNativeWindow.get(), &crop));
2067             }
2068             break;
2069         }
2070 
2071         case OMX_PortDomainAudio:
2072         {
2073             OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2074             CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
2075 
2076             OMX_AUDIO_PARAM_PCMMODETYPE params;
2077             InitOMXParams(&params);
2078             params.nPortIndex = kPortIndexOutput;
2079 
2080             CHECK_EQ(mOMX->getParameter(
2081                         mNode, OMX_IndexParamAudioPcm,
2082                         &params, sizeof(params)),
2083                      (status_t)OK);
2084 
2085             CHECK(params.nChannels == 1 || params.bInterleaved);
2086             CHECK_EQ(params.nBitPerSample, 16u);
2087             CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
2088             CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
2089 
2090             notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
2091             notify->setInt32("channel-count", params.nChannels);
2092             notify->setInt32("sample-rate", params.nSamplingRate);
2093             if (mEncoderDelay + mEncoderPadding) {
2094                 size_t frameSize = params.nChannels * sizeof(int16_t);
2095                 if (mSkipCutBuffer != NULL) {
2096                     size_t prevbufsize = mSkipCutBuffer->size();
2097                     if (prevbufsize != 0) {
2098                         ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbufsize);
2099                     }
2100                 }
2101                 mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay * frameSize,
2102                                                    mEncoderPadding * frameSize);
2103             }
2104 
2105             if (mChannelMaskPresent) {
2106                 notify->setInt32("channel-mask", mChannelMask);
2107             }
2108 
2109             break;
2110         }
2111 
2112         default:
2113             TRESPASS();
2114     }
2115 
2116     notify->post();
2117 
2118     mSentFormat = true;
2119 }
2120 
signalError(OMX_ERRORTYPE error,status_t internalError)2121 void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
2122     sp<AMessage> notify = mNotify->dup();
2123     notify->setInt32("what", ACodec::kWhatError);
2124     notify->setInt32("omx-error", error);
2125     notify->setInt32("err", internalError);
2126     notify->post();
2127 }
2128 
pushBlankBuffersToNativeWindow()2129 status_t ACodec::pushBlankBuffersToNativeWindow() {
2130     status_t err = NO_ERROR;
2131     ANativeWindowBuffer* anb = NULL;
2132     int numBufs = 0;
2133     int minUndequeuedBufs = 0;
2134 
2135     // We need to reconnect to the ANativeWindow as a CPU client to ensure that
2136     // no frames get dropped by SurfaceFlinger assuming that these are video
2137     // frames.
2138     err = native_window_api_disconnect(mNativeWindow.get(),
2139             NATIVE_WINDOW_API_MEDIA);
2140     if (err != NO_ERROR) {
2141         ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2142                 strerror(-err), -err);
2143         return err;
2144     }
2145 
2146     err = native_window_api_connect(mNativeWindow.get(),
2147             NATIVE_WINDOW_API_CPU);
2148     if (err != NO_ERROR) {
2149         ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
2150                 strerror(-err), -err);
2151         return err;
2152     }
2153 
2154     err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
2155             HAL_PIXEL_FORMAT_RGBX_8888);
2156     if (err != NO_ERROR) {
2157         ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
2158                 strerror(-err), -err);
2159         goto error;
2160     }
2161 
2162     err = native_window_set_usage(mNativeWindow.get(),
2163             GRALLOC_USAGE_SW_WRITE_OFTEN);
2164     if (err != NO_ERROR) {
2165         ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
2166                 strerror(-err), -err);
2167         goto error;
2168     }
2169 
2170     err = mNativeWindow->query(mNativeWindow.get(),
2171             NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
2172     if (err != NO_ERROR) {
2173         ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
2174                 "failed: %s (%d)", strerror(-err), -err);
2175         goto error;
2176     }
2177 
2178     numBufs = minUndequeuedBufs + 1;
2179     err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
2180     if (err != NO_ERROR) {
2181         ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
2182                 strerror(-err), -err);
2183         goto error;
2184     }
2185 
2186     // We  push numBufs + 1 buffers to ensure that we've drawn into the same
2187     // buffer twice.  This should guarantee that the buffer has been displayed
2188     // on the screen and then been replaced, so an previous video frames are
2189     // guaranteed NOT to be currently displayed.
2190     for (int i = 0; i < numBufs + 1; i++) {
2191         err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &anb);
2192         if (err != NO_ERROR) {
2193             ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
2194                     strerror(-err), -err);
2195             goto error;
2196         }
2197 
2198         sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
2199         err = mNativeWindow->lockBuffer(mNativeWindow.get(),
2200                 buf->getNativeBuffer());
2201         if (err != NO_ERROR) {
2202             ALOGE("error pushing blank frames: lockBuffer failed: %s (%d)",
2203                     strerror(-err), -err);
2204             goto error;
2205         }
2206 
2207         // Fill the buffer with the a 1x1 checkerboard pattern ;)
2208         uint32_t* img = NULL;
2209         err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
2210         if (err != NO_ERROR) {
2211             ALOGE("error pushing blank frames: lock failed: %s (%d)",
2212                     strerror(-err), -err);
2213             goto error;
2214         }
2215 
2216         *img = 0;
2217 
2218         err = buf->unlock();
2219         if (err != NO_ERROR) {
2220             ALOGE("error pushing blank frames: unlock failed: %s (%d)",
2221                     strerror(-err), -err);
2222             goto error;
2223         }
2224 
2225         err = mNativeWindow->queueBuffer(mNativeWindow.get(),
2226                 buf->getNativeBuffer());
2227         if (err != NO_ERROR) {
2228             ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
2229                     strerror(-err), -err);
2230             goto error;
2231         }
2232 
2233         anb = NULL;
2234     }
2235 
2236 error:
2237 
2238     if (err != NO_ERROR) {
2239         // Clean up after an error.
2240         if (anb != NULL) {
2241             mNativeWindow->cancelBuffer(mNativeWindow.get(), anb);
2242         }
2243 
2244         native_window_api_disconnect(mNativeWindow.get(),
2245                 NATIVE_WINDOW_API_CPU);
2246         native_window_api_connect(mNativeWindow.get(),
2247                 NATIVE_WINDOW_API_MEDIA);
2248 
2249         return err;
2250     } else {
2251         // Clean up after success.
2252         err = native_window_api_disconnect(mNativeWindow.get(),
2253                 NATIVE_WINDOW_API_CPU);
2254         if (err != NO_ERROR) {
2255             ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2256                     strerror(-err), -err);
2257             return err;
2258         }
2259 
2260         err = native_window_api_connect(mNativeWindow.get(),
2261                 NATIVE_WINDOW_API_MEDIA);
2262         if (err != NO_ERROR) {
2263             ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
2264                     strerror(-err), -err);
2265             return err;
2266         }
2267 
2268         return NO_ERROR;
2269     }
2270 }
2271 
2272 ////////////////////////////////////////////////////////////////////////////////
2273 
PortDescription()2274 ACodec::PortDescription::PortDescription() {
2275 }
2276 
addBuffer(IOMX::buffer_id id,const sp<ABuffer> & buffer)2277 void ACodec::PortDescription::addBuffer(
2278         IOMX::buffer_id id, const sp<ABuffer> &buffer) {
2279     mBufferIDs.push_back(id);
2280     mBuffers.push_back(buffer);
2281 }
2282 
countBuffers()2283 size_t ACodec::PortDescription::countBuffers() {
2284     return mBufferIDs.size();
2285 }
2286 
bufferIDAt(size_t index) const2287 IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
2288     return mBufferIDs.itemAt(index);
2289 }
2290 
bufferAt(size_t index) const2291 sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
2292     return mBuffers.itemAt(index);
2293 }
2294 
2295 ////////////////////////////////////////////////////////////////////////////////
2296 
BaseState(ACodec * codec,const sp<AState> & parentState)2297 ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
2298     : AState(parentState),
2299       mCodec(codec) {
2300 }
2301 
getPortMode(OMX_U32 portIndex)2302 ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
2303     return KEEP_BUFFERS;
2304 }
2305 
onMessageReceived(const sp<AMessage> & msg)2306 bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
2307     switch (msg->what()) {
2308         case kWhatInputBufferFilled:
2309         {
2310             onInputBufferFilled(msg);
2311             break;
2312         }
2313 
2314         case kWhatOutputBufferDrained:
2315         {
2316             onOutputBufferDrained(msg);
2317             break;
2318         }
2319 
2320         case ACodec::kWhatOMXMessage:
2321         {
2322             return onOMXMessage(msg);
2323         }
2324 
2325         default:
2326             return false;
2327     }
2328 
2329     return true;
2330 }
2331 
onOMXMessage(const sp<AMessage> & msg)2332 bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
2333     int32_t type;
2334     CHECK(msg->findInt32("type", &type));
2335 
2336     IOMX::node_id nodeID;
2337     CHECK(msg->findPointer("node", &nodeID));
2338     CHECK_EQ(nodeID, mCodec->mNode);
2339 
2340     switch (type) {
2341         case omx_message::EVENT:
2342         {
2343             int32_t event, data1, data2;
2344             CHECK(msg->findInt32("event", &event));
2345             CHECK(msg->findInt32("data1", &data1));
2346             CHECK(msg->findInt32("data2", &data2));
2347 
2348             if (event == OMX_EventCmdComplete
2349                     && data1 == OMX_CommandFlush
2350                     && data2 == (int32_t)OMX_ALL) {
2351                 // Use of this notification is not consistent across
2352                 // implementations. We'll drop this notification and rely
2353                 // on flush-complete notifications on the individual port
2354                 // indices instead.
2355 
2356                 return true;
2357             }
2358 
2359             return onOMXEvent(
2360                     static_cast<OMX_EVENTTYPE>(event),
2361                     static_cast<OMX_U32>(data1),
2362                     static_cast<OMX_U32>(data2));
2363         }
2364 
2365         case omx_message::EMPTY_BUFFER_DONE:
2366         {
2367             IOMX::buffer_id bufferID;
2368             CHECK(msg->findPointer("buffer", &bufferID));
2369 
2370             return onOMXEmptyBufferDone(bufferID);
2371         }
2372 
2373         case omx_message::FILL_BUFFER_DONE:
2374         {
2375             IOMX::buffer_id bufferID;
2376             CHECK(msg->findPointer("buffer", &bufferID));
2377 
2378             int32_t rangeOffset, rangeLength, flags;
2379             int64_t timeUs;
2380             void *platformPrivate;
2381             void *dataPtr;
2382 
2383             CHECK(msg->findInt32("range_offset", &rangeOffset));
2384             CHECK(msg->findInt32("range_length", &rangeLength));
2385             CHECK(msg->findInt32("flags", &flags));
2386             CHECK(msg->findInt64("timestamp", &timeUs));
2387             CHECK(msg->findPointer("platform_private", &platformPrivate));
2388             CHECK(msg->findPointer("data_ptr", &dataPtr));
2389 
2390             return onOMXFillBufferDone(
2391                     bufferID,
2392                     (size_t)rangeOffset, (size_t)rangeLength,
2393                     (OMX_U32)flags,
2394                     timeUs,
2395                     platformPrivate,
2396                     dataPtr);
2397         }
2398 
2399         default:
2400             TRESPASS();
2401             break;
2402     }
2403 }
2404 
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)2405 bool ACodec::BaseState::onOMXEvent(
2406         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2407     if (event != OMX_EventError) {
2408         ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
2409              mCodec->mComponentName.c_str(), event, data1, data2);
2410 
2411         return false;
2412     }
2413 
2414     ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
2415 
2416     mCodec->signalError((OMX_ERRORTYPE)data1);
2417 
2418     return true;
2419 }
2420 
onOMXEmptyBufferDone(IOMX::buffer_id bufferID)2421 bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
2422     ALOGV("[%s] onOMXEmptyBufferDone %p",
2423          mCodec->mComponentName.c_str(), bufferID);
2424 
2425     BufferInfo *info =
2426         mCodec->findBufferByID(kPortIndexInput, bufferID);
2427 
2428     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2429     info->mStatus = BufferInfo::OWNED_BY_US;
2430 
2431     PortMode mode = getPortMode(kPortIndexInput);
2432 
2433     switch (mode) {
2434         case KEEP_BUFFERS:
2435             break;
2436 
2437         case RESUBMIT_BUFFERS:
2438             postFillThisBuffer(info);
2439             break;
2440 
2441         default:
2442         {
2443             CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2444             TRESPASS();  // Not currently used
2445             break;
2446         }
2447     }
2448 
2449     return true;
2450 }
2451 
postFillThisBuffer(BufferInfo * info)2452 void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
2453     if (mCodec->mPortEOS[kPortIndexInput]) {
2454         return;
2455     }
2456 
2457     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
2458 
2459     sp<AMessage> notify = mCodec->mNotify->dup();
2460     notify->setInt32("what", ACodec::kWhatFillThisBuffer);
2461     notify->setPointer("buffer-id", info->mBufferID);
2462 
2463     info->mData->meta()->clear();
2464     notify->setBuffer("buffer", info->mData);
2465 
2466     sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
2467     reply->setPointer("buffer-id", info->mBufferID);
2468 
2469     notify->setMessage("reply", reply);
2470 
2471     notify->post();
2472 
2473     info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
2474 }
2475 
onInputBufferFilled(const sp<AMessage> & msg)2476 void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
2477     IOMX::buffer_id bufferID;
2478     CHECK(msg->findPointer("buffer-id", &bufferID));
2479 
2480     sp<ABuffer> buffer;
2481     int32_t err = OK;
2482     bool eos = false;
2483 
2484     if (!msg->findBuffer("buffer", &buffer)) {
2485         CHECK(msg->findInt32("err", &err));
2486 
2487         ALOGV("[%s] saw error %d instead of an input buffer",
2488              mCodec->mComponentName.c_str(), err);
2489 
2490         buffer.clear();
2491 
2492         eos = true;
2493     }
2494 
2495     int32_t tmp;
2496     if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
2497         eos = true;
2498         err = ERROR_END_OF_STREAM;
2499     }
2500 
2501     BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
2502     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
2503 
2504     info->mStatus = BufferInfo::OWNED_BY_US;
2505 
2506     PortMode mode = getPortMode(kPortIndexInput);
2507 
2508     switch (mode) {
2509         case KEEP_BUFFERS:
2510         {
2511             if (eos) {
2512                 if (!mCodec->mPortEOS[kPortIndexInput]) {
2513                     mCodec->mPortEOS[kPortIndexInput] = true;
2514                     mCodec->mInputEOSResult = err;
2515                 }
2516             }
2517             break;
2518         }
2519 
2520         case RESUBMIT_BUFFERS:
2521         {
2522             if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
2523                 int64_t timeUs;
2524                 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2525 
2526                 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
2527 
2528                 int32_t isCSD;
2529                 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
2530                     flags |= OMX_BUFFERFLAG_CODECCONFIG;
2531                 }
2532 
2533                 if (eos) {
2534                     flags |= OMX_BUFFERFLAG_EOS;
2535                 }
2536 
2537                 if (buffer != info->mData) {
2538                     if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
2539                         ALOGV("[%s] Needs to copy input data.",
2540                              mCodec->mComponentName.c_str());
2541                     }
2542 
2543                     CHECK_LE(buffer->size(), info->mData->capacity());
2544                     memcpy(info->mData->data(), buffer->data(), buffer->size());
2545                 }
2546 
2547                 if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
2548                     ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
2549                          mCodec->mComponentName.c_str(), bufferID);
2550                 } else if (flags & OMX_BUFFERFLAG_EOS) {
2551                     ALOGV("[%s] calling emptyBuffer %p w/ EOS",
2552                          mCodec->mComponentName.c_str(), bufferID);
2553                 } else {
2554                     ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
2555                          mCodec->mComponentName.c_str(), bufferID, timeUs);
2556                 }
2557 
2558                 CHECK_EQ(mCodec->mOMX->emptyBuffer(
2559                             mCodec->mNode,
2560                             bufferID,
2561                             0,
2562                             buffer->size(),
2563                             flags,
2564                             timeUs),
2565                          (status_t)OK);
2566 
2567                 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2568 
2569                 if (!eos) {
2570                     getMoreInputDataIfPossible();
2571                 } else {
2572                     ALOGV("[%s] Signalled EOS on the input port",
2573                          mCodec->mComponentName.c_str());
2574 
2575                     mCodec->mPortEOS[kPortIndexInput] = true;
2576                     mCodec->mInputEOSResult = err;
2577                 }
2578             } else if (!mCodec->mPortEOS[kPortIndexInput]) {
2579                 if (err != ERROR_END_OF_STREAM) {
2580                     ALOGV("[%s] Signalling EOS on the input port "
2581                          "due to error %d",
2582                          mCodec->mComponentName.c_str(), err);
2583                 } else {
2584                     ALOGV("[%s] Signalling EOS on the input port",
2585                          mCodec->mComponentName.c_str());
2586                 }
2587 
2588                 ALOGV("[%s] calling emptyBuffer %p signalling EOS",
2589                      mCodec->mComponentName.c_str(), bufferID);
2590 
2591                 CHECK_EQ(mCodec->mOMX->emptyBuffer(
2592                             mCodec->mNode,
2593                             bufferID,
2594                             0,
2595                             0,
2596                             OMX_BUFFERFLAG_EOS,
2597                             0),
2598                          (status_t)OK);
2599 
2600                 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2601 
2602                 mCodec->mPortEOS[kPortIndexInput] = true;
2603                 mCodec->mInputEOSResult = err;
2604             }
2605             break;
2606 
2607             default:
2608                 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2609                 break;
2610         }
2611     }
2612 }
2613 
getMoreInputDataIfPossible()2614 void ACodec::BaseState::getMoreInputDataIfPossible() {
2615     if (mCodec->mPortEOS[kPortIndexInput]) {
2616         return;
2617     }
2618 
2619     BufferInfo *eligible = NULL;
2620 
2621     for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
2622         BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
2623 
2624 #if 0
2625         if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
2626             // There's already a "read" pending.
2627             return;
2628         }
2629 #endif
2630 
2631         if (info->mStatus == BufferInfo::OWNED_BY_US) {
2632             eligible = info;
2633         }
2634     }
2635 
2636     if (eligible == NULL) {
2637         return;
2638     }
2639 
2640     postFillThisBuffer(eligible);
2641 }
2642 
onOMXFillBufferDone(IOMX::buffer_id bufferID,size_t rangeOffset,size_t rangeLength,OMX_U32 flags,int64_t timeUs,void * platformPrivate,void * dataPtr)2643 bool ACodec::BaseState::onOMXFillBufferDone(
2644         IOMX::buffer_id bufferID,
2645         size_t rangeOffset, size_t rangeLength,
2646         OMX_U32 flags,
2647         int64_t timeUs,
2648         void *platformPrivate,
2649         void *dataPtr) {
2650     ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx",
2651          mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
2652 
2653     ssize_t index;
2654     BufferInfo *info =
2655         mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2656 
2657     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2658 
2659     info->mStatus = BufferInfo::OWNED_BY_US;
2660 
2661     PortMode mode = getPortMode(kPortIndexOutput);
2662 
2663     switch (mode) {
2664         case KEEP_BUFFERS:
2665             break;
2666 
2667         case RESUBMIT_BUFFERS:
2668         {
2669             if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
2670                 ALOGV("[%s] calling fillBuffer %p",
2671                      mCodec->mComponentName.c_str(), info->mBufferID);
2672 
2673                 CHECK_EQ(mCodec->mOMX->fillBuffer(
2674                             mCodec->mNode, info->mBufferID),
2675                          (status_t)OK);
2676 
2677                 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2678                 break;
2679             }
2680 
2681             if (!mCodec->mIsEncoder && !mCodec->mSentFormat) {
2682                 mCodec->sendFormatChange();
2683             }
2684 
2685             if (mCodec->mNativeWindow == NULL) {
2686                 info->mData->setRange(rangeOffset, rangeLength);
2687             }
2688 
2689             if (mCodec->mSkipCutBuffer != NULL) {
2690                 mCodec->mSkipCutBuffer->submit(info->mData);
2691             }
2692             info->mData->meta()->setInt64("timeUs", timeUs);
2693 
2694             sp<AMessage> notify = mCodec->mNotify->dup();
2695             notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
2696             notify->setPointer("buffer-id", info->mBufferID);
2697             notify->setBuffer("buffer", info->mData);
2698             notify->setInt32("flags", flags);
2699 
2700             sp<AMessage> reply =
2701                 new AMessage(kWhatOutputBufferDrained, mCodec->id());
2702 
2703             reply->setPointer("buffer-id", info->mBufferID);
2704 
2705             notify->setMessage("reply", reply);
2706 
2707             notify->post();
2708 
2709             info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
2710 
2711             if (flags & OMX_BUFFERFLAG_EOS) {
2712                 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
2713 
2714                 sp<AMessage> notify = mCodec->mNotify->dup();
2715                 notify->setInt32("what", ACodec::kWhatEOS);
2716                 notify->setInt32("err", mCodec->mInputEOSResult);
2717                 notify->post();
2718 
2719                 mCodec->mPortEOS[kPortIndexOutput] = true;
2720             }
2721             break;
2722         }
2723 
2724         default:
2725         {
2726             CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2727 
2728             CHECK_EQ((status_t)OK,
2729                      mCodec->freeBuffer(kPortIndexOutput, index));
2730             break;
2731         }
2732     }
2733 
2734     return true;
2735 }
2736 
onOutputBufferDrained(const sp<AMessage> & msg)2737 void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
2738     IOMX::buffer_id bufferID;
2739     CHECK(msg->findPointer("buffer-id", &bufferID));
2740 
2741     ssize_t index;
2742     BufferInfo *info =
2743         mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2744     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
2745 
2746     int32_t render;
2747     if (mCodec->mNativeWindow != NULL
2748             && msg->findInt32("render", &render) && render != 0) {
2749         // The client wants this buffer to be rendered.
2750 
2751         status_t err;
2752         if ((err = mCodec->mNativeWindow->queueBuffer(
2753                     mCodec->mNativeWindow.get(),
2754                     info->mGraphicBuffer.get())) == OK) {
2755             info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
2756         } else {
2757             mCodec->signalError(OMX_ErrorUndefined, err);
2758             info->mStatus = BufferInfo::OWNED_BY_US;
2759         }
2760     } else {
2761         info->mStatus = BufferInfo::OWNED_BY_US;
2762     }
2763 
2764     PortMode mode = getPortMode(kPortIndexOutput);
2765 
2766     switch (mode) {
2767         case KEEP_BUFFERS:
2768         {
2769             // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
2770 
2771             if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2772                 // We cannot resubmit the buffer we just rendered, dequeue
2773                 // the spare instead.
2774 
2775                 info = mCodec->dequeueBufferFromNativeWindow();
2776             }
2777             break;
2778         }
2779 
2780         case RESUBMIT_BUFFERS:
2781         {
2782             if (!mCodec->mPortEOS[kPortIndexOutput]) {
2783                 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2784                     // We cannot resubmit the buffer we just rendered, dequeue
2785                     // the spare instead.
2786 
2787                     info = mCodec->dequeueBufferFromNativeWindow();
2788                 }
2789 
2790                 if (info != NULL) {
2791                     ALOGV("[%s] calling fillBuffer %p",
2792                          mCodec->mComponentName.c_str(), info->mBufferID);
2793 
2794                     CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
2795                              (status_t)OK);
2796 
2797                     info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2798                 }
2799             }
2800             break;
2801         }
2802 
2803         default:
2804         {
2805             CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2806 
2807             CHECK_EQ((status_t)OK,
2808                      mCodec->freeBuffer(kPortIndexOutput, index));
2809             break;
2810         }
2811     }
2812 }
2813 
2814 ////////////////////////////////////////////////////////////////////////////////
2815 
UninitializedState(ACodec * codec)2816 ACodec::UninitializedState::UninitializedState(ACodec *codec)
2817     : BaseState(codec) {
2818 }
2819 
stateEntered()2820 void ACodec::UninitializedState::stateEntered() {
2821     ALOGV("Now uninitialized");
2822 }
2823 
onMessageReceived(const sp<AMessage> & msg)2824 bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
2825     bool handled = false;
2826 
2827     switch (msg->what()) {
2828         case ACodec::kWhatSetup:
2829         {
2830             onSetup(msg);
2831 
2832             handled = true;
2833             break;
2834         }
2835 
2836         case ACodec::kWhatAllocateComponent:
2837         {
2838             onAllocateComponent(msg);
2839             handled = true;
2840             break;
2841         }
2842 
2843         case ACodec::kWhatShutdown:
2844         {
2845             int32_t keepComponentAllocated;
2846             CHECK(msg->findInt32(
2847                         "keepComponentAllocated", &keepComponentAllocated));
2848             CHECK(!keepComponentAllocated);
2849 
2850             sp<AMessage> notify = mCodec->mNotify->dup();
2851             notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2852             notify->post();
2853 
2854             handled = true;
2855             break;
2856         }
2857 
2858         case ACodec::kWhatFlush:
2859         {
2860             sp<AMessage> notify = mCodec->mNotify->dup();
2861             notify->setInt32("what", ACodec::kWhatFlushCompleted);
2862             notify->post();
2863 
2864             handled = true;
2865             break;
2866         }
2867 
2868         default:
2869             return BaseState::onMessageReceived(msg);
2870     }
2871 
2872     return handled;
2873 }
2874 
onSetup(const sp<AMessage> & msg)2875 void ACodec::UninitializedState::onSetup(
2876         const sp<AMessage> &msg) {
2877     if (onAllocateComponent(msg)
2878             && mCodec->mLoadedState->onConfigureComponent(msg)) {
2879         mCodec->mLoadedState->onStart();
2880     }
2881 }
2882 
onAllocateComponent(const sp<AMessage> & msg)2883 bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
2884     ALOGV("onAllocateComponent");
2885 
2886     CHECK(mCodec->mNode == NULL);
2887 
2888     OMXClient client;
2889     CHECK_EQ(client.connect(), (status_t)OK);
2890 
2891     sp<IOMX> omx = client.interface();
2892 
2893     Vector<String8> matchingCodecs;
2894     Vector<uint32_t> matchingCodecQuirks;
2895 
2896     AString mime;
2897 
2898     AString componentName;
2899     uint32_t quirks;
2900     if (msg->findString("componentName", &componentName)) {
2901         matchingCodecs.push_back(String8(componentName.c_str()));
2902 
2903         if (!OMXCodec::findCodecQuirks(componentName.c_str(), &quirks)) {
2904             quirks = 0;
2905         }
2906         matchingCodecQuirks.push_back(quirks);
2907     } else {
2908         CHECK(msg->findString("mime", &mime));
2909 
2910         int32_t encoder;
2911         if (!msg->findInt32("encoder", &encoder)) {
2912             encoder = false;
2913         }
2914 
2915         OMXCodec::findMatchingCodecs(
2916                 mime.c_str(),
2917                 encoder, // createEncoder
2918                 NULL,  // matchComponentName
2919                 0,     // flags
2920                 &matchingCodecs,
2921                 &matchingCodecQuirks);
2922     }
2923 
2924     sp<CodecObserver> observer = new CodecObserver;
2925     IOMX::node_id node = NULL;
2926 
2927     for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
2928             ++matchIndex) {
2929         componentName = matchingCodecs.itemAt(matchIndex).string();
2930         quirks = matchingCodecQuirks.itemAt(matchIndex);
2931 
2932         pid_t tid = androidGetTid();
2933         int prevPriority = androidGetThreadPriority(tid);
2934         androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
2935         status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
2936         androidSetThreadPriority(tid, prevPriority);
2937 
2938         if (err == OK) {
2939             break;
2940         }
2941 
2942         node = NULL;
2943     }
2944 
2945     if (node == NULL) {
2946         if (!mime.empty()) {
2947             ALOGE("Unable to instantiate a decoder for type '%s'.",
2948                  mime.c_str());
2949         } else {
2950             ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
2951         }
2952 
2953         mCodec->signalError(OMX_ErrorComponentNotFound);
2954         return false;
2955     }
2956 
2957     sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
2958     observer->setNotificationMessage(notify);
2959 
2960     mCodec->mComponentName = componentName;
2961     mCodec->mFlags = 0;
2962 
2963     if (componentName.endsWith(".secure")) {
2964         mCodec->mFlags |= kFlagIsSecure;
2965     }
2966 
2967     mCodec->mQuirks = quirks;
2968     mCodec->mOMX = omx;
2969     mCodec->mNode = node;
2970 
2971     mCodec->mPortEOS[kPortIndexInput] =
2972         mCodec->mPortEOS[kPortIndexOutput] = false;
2973 
2974     mCodec->mInputEOSResult = OK;
2975 
2976     {
2977         sp<AMessage> notify = mCodec->mNotify->dup();
2978         notify->setInt32("what", ACodec::kWhatComponentAllocated);
2979         notify->setString("componentName", mCodec->mComponentName.c_str());
2980         notify->post();
2981     }
2982 
2983     mCodec->changeState(mCodec->mLoadedState);
2984 
2985     return true;
2986 }
2987 
2988 ////////////////////////////////////////////////////////////////////////////////
2989 
LoadedState(ACodec * codec)2990 ACodec::LoadedState::LoadedState(ACodec *codec)
2991     : BaseState(codec) {
2992 }
2993 
stateEntered()2994 void ACodec::LoadedState::stateEntered() {
2995     ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2996 
2997     if (mCodec->mShutdownInProgress) {
2998         bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
2999 
3000         mCodec->mShutdownInProgress = false;
3001         mCodec->mKeepComponentAllocated = false;
3002 
3003         onShutdown(keepComponentAllocated);
3004     }
3005 }
3006 
onShutdown(bool keepComponentAllocated)3007 void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
3008     if (!keepComponentAllocated) {
3009         CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
3010 
3011         mCodec->mNativeWindow.clear();
3012         mCodec->mNode = NULL;
3013         mCodec->mOMX.clear();
3014         mCodec->mQuirks = 0;
3015         mCodec->mFlags = 0;
3016         mCodec->mComponentName.clear();
3017 
3018         mCodec->changeState(mCodec->mUninitializedState);
3019     }
3020 
3021     sp<AMessage> notify = mCodec->mNotify->dup();
3022     notify->setInt32("what", ACodec::kWhatShutdownCompleted);
3023     notify->post();
3024 }
3025 
onMessageReceived(const sp<AMessage> & msg)3026 bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
3027     bool handled = false;
3028 
3029     switch (msg->what()) {
3030         case ACodec::kWhatConfigureComponent:
3031         {
3032             onConfigureComponent(msg);
3033             handled = true;
3034             break;
3035         }
3036 
3037         case ACodec::kWhatStart:
3038         {
3039             onStart();
3040             handled = true;
3041             break;
3042         }
3043 
3044         case ACodec::kWhatShutdown:
3045         {
3046             int32_t keepComponentAllocated;
3047             CHECK(msg->findInt32(
3048                         "keepComponentAllocated", &keepComponentAllocated));
3049 
3050             onShutdown(keepComponentAllocated);
3051 
3052             handled = true;
3053             break;
3054         }
3055 
3056         case ACodec::kWhatFlush:
3057         {
3058             sp<AMessage> notify = mCodec->mNotify->dup();
3059             notify->setInt32("what", ACodec::kWhatFlushCompleted);
3060             notify->post();
3061 
3062             handled = true;
3063             break;
3064         }
3065 
3066         default:
3067             return BaseState::onMessageReceived(msg);
3068     }
3069 
3070     return handled;
3071 }
3072 
onConfigureComponent(const sp<AMessage> & msg)3073 bool ACodec::LoadedState::onConfigureComponent(
3074         const sp<AMessage> &msg) {
3075     ALOGV("onConfigureComponent");
3076 
3077     CHECK(mCodec->mNode != NULL);
3078 
3079     AString mime;
3080     CHECK(msg->findString("mime", &mime));
3081 
3082     status_t err = mCodec->configureCodec(mime.c_str(), msg);
3083 
3084     if (err != OK) {
3085         ALOGE("[%s] configureCodec returning error %d",
3086               mCodec->mComponentName.c_str(), err);
3087 
3088         mCodec->signalError(OMX_ErrorUndefined, err);
3089         return false;
3090     }
3091 
3092     sp<RefBase> obj;
3093     if (msg->findObject("native-window", &obj)
3094             && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
3095         sp<NativeWindowWrapper> nativeWindow(
3096                 static_cast<NativeWindowWrapper *>(obj.get()));
3097         CHECK(nativeWindow != NULL);
3098         mCodec->mNativeWindow = nativeWindow->getNativeWindow();
3099 
3100         native_window_set_scaling_mode(
3101                 mCodec->mNativeWindow.get(),
3102                 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3103     }
3104     CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
3105 
3106     {
3107         sp<AMessage> notify = mCodec->mNotify->dup();
3108         notify->setInt32("what", ACodec::kWhatComponentConfigured);
3109         notify->post();
3110     }
3111 
3112     return true;
3113 }
3114 
onStart()3115 void ACodec::LoadedState::onStart() {
3116     ALOGV("onStart");
3117 
3118     CHECK_EQ(mCodec->mOMX->sendCommand(
3119                 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
3120              (status_t)OK);
3121 
3122     mCodec->changeState(mCodec->mLoadedToIdleState);
3123 }
3124 
3125 ////////////////////////////////////////////////////////////////////////////////
3126 
LoadedToIdleState(ACodec * codec)3127 ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
3128     : BaseState(codec) {
3129 }
3130 
stateEntered()3131 void ACodec::LoadedToIdleState::stateEntered() {
3132     ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
3133 
3134     status_t err;
3135     if ((err = allocateBuffers()) != OK) {
3136         ALOGE("Failed to allocate buffers after transitioning to IDLE state "
3137              "(error 0x%08x)",
3138              err);
3139 
3140         mCodec->signalError(OMX_ErrorUndefined, err);
3141 
3142         mCodec->changeState(mCodec->mLoadedState);
3143     }
3144 }
3145 
allocateBuffers()3146 status_t ACodec::LoadedToIdleState::allocateBuffers() {
3147     status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
3148 
3149     if (err != OK) {
3150         return err;
3151     }
3152 
3153     return mCodec->allocateBuffersOnPort(kPortIndexOutput);
3154 }
3155 
onMessageReceived(const sp<AMessage> & msg)3156 bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3157     switch (msg->what()) {
3158         case kWhatShutdown:
3159         {
3160             mCodec->deferMessage(msg);
3161             return true;
3162         }
3163 
3164         default:
3165             return BaseState::onMessageReceived(msg);
3166     }
3167 }
3168 
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)3169 bool ACodec::LoadedToIdleState::onOMXEvent(
3170         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3171     switch (event) {
3172         case OMX_EventCmdComplete:
3173         {
3174             CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3175             CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
3176 
3177             CHECK_EQ(mCodec->mOMX->sendCommand(
3178                         mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
3179                      (status_t)OK);
3180 
3181             mCodec->changeState(mCodec->mIdleToExecutingState);
3182 
3183             return true;
3184         }
3185 
3186         default:
3187             return BaseState::onOMXEvent(event, data1, data2);
3188     }
3189 }
3190 
3191 ////////////////////////////////////////////////////////////////////////////////
3192 
IdleToExecutingState(ACodec * codec)3193 ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
3194     : BaseState(codec) {
3195 }
3196 
stateEntered()3197 void ACodec::IdleToExecutingState::stateEntered() {
3198     ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
3199 }
3200 
onMessageReceived(const sp<AMessage> & msg)3201 bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
3202     switch (msg->what()) {
3203         case kWhatShutdown:
3204         {
3205             mCodec->deferMessage(msg);
3206             return true;
3207         }
3208 
3209         default:
3210             return BaseState::onMessageReceived(msg);
3211     }
3212 }
3213 
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)3214 bool ACodec::IdleToExecutingState::onOMXEvent(
3215         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3216     switch (event) {
3217         case OMX_EventCmdComplete:
3218         {
3219             CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3220             CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
3221 
3222             mCodec->mExecutingState->resume();
3223             mCodec->changeState(mCodec->mExecutingState);
3224 
3225             return true;
3226         }
3227 
3228         default:
3229             return BaseState::onOMXEvent(event, data1, data2);
3230     }
3231 }
3232 
3233 ////////////////////////////////////////////////////////////////////////////////
3234 
ExecutingState(ACodec * codec)3235 ACodec::ExecutingState::ExecutingState(ACodec *codec)
3236     : BaseState(codec),
3237       mActive(false) {
3238 }
3239 
getPortMode(OMX_U32 portIndex)3240 ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
3241         OMX_U32 portIndex) {
3242     return RESUBMIT_BUFFERS;
3243 }
3244 
submitOutputBuffers()3245 void ACodec::ExecutingState::submitOutputBuffers() {
3246     for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
3247         BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
3248 
3249         if (mCodec->mNativeWindow != NULL) {
3250             CHECK(info->mStatus == BufferInfo::OWNED_BY_US
3251                     || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
3252 
3253             if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3254                 continue;
3255             }
3256 
3257             status_t err = mCodec->mNativeWindow->lockBuffer(
3258                     mCodec->mNativeWindow.get(),
3259                     info->mGraphicBuffer.get());
3260             CHECK_EQ(err, (status_t)OK);
3261         } else {
3262             CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
3263         }
3264 
3265         ALOGV("[%s] calling fillBuffer %p",
3266              mCodec->mComponentName.c_str(), info->mBufferID);
3267 
3268         CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
3269                  (status_t)OK);
3270 
3271         info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3272     }
3273 }
3274 
resume()3275 void ACodec::ExecutingState::resume() {
3276     if (mActive) {
3277         ALOGV("[%s] We're already active, no need to resume.",
3278              mCodec->mComponentName.c_str());
3279 
3280         return;
3281     }
3282 
3283     submitOutputBuffers();
3284 
3285     // Post the first input buffer.
3286     CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
3287     BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
3288 
3289     postFillThisBuffer(info);
3290 
3291     mActive = true;
3292 }
3293 
stateEntered()3294 void ACodec::ExecutingState::stateEntered() {
3295     ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
3296 
3297     mCodec->processDeferredMessages();
3298 }
3299 
onMessageReceived(const sp<AMessage> & msg)3300 bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
3301     bool handled = false;
3302 
3303     switch (msg->what()) {
3304         case kWhatShutdown:
3305         {
3306             int32_t keepComponentAllocated;
3307             CHECK(msg->findInt32(
3308                         "keepComponentAllocated", &keepComponentAllocated));
3309 
3310             mCodec->mShutdownInProgress = true;
3311             mCodec->mKeepComponentAllocated = keepComponentAllocated;
3312 
3313             mActive = false;
3314 
3315             CHECK_EQ(mCodec->mOMX->sendCommand(
3316                         mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
3317                      (status_t)OK);
3318 
3319             mCodec->changeState(mCodec->mExecutingToIdleState);
3320 
3321             handled = true;
3322             break;
3323         }
3324 
3325         case kWhatFlush:
3326         {
3327             ALOGV("[%s] ExecutingState flushing now "
3328                  "(codec owns %d/%d input, %d/%d output).",
3329                     mCodec->mComponentName.c_str(),
3330                     mCodec->countBuffersOwnedByComponent(kPortIndexInput),
3331                     mCodec->mBuffers[kPortIndexInput].size(),
3332                     mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
3333                     mCodec->mBuffers[kPortIndexOutput].size());
3334 
3335             mActive = false;
3336 
3337             CHECK_EQ(mCodec->mOMX->sendCommand(
3338                         mCodec->mNode, OMX_CommandFlush, OMX_ALL),
3339                      (status_t)OK);
3340 
3341             mCodec->changeState(mCodec->mFlushingState);
3342 
3343             handled = true;
3344             break;
3345         }
3346 
3347         case kWhatResume:
3348         {
3349             resume();
3350 
3351             handled = true;
3352             break;
3353         }
3354 
3355         default:
3356             handled = BaseState::onMessageReceived(msg);
3357             break;
3358     }
3359 
3360     return handled;
3361 }
3362 
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)3363 bool ACodec::ExecutingState::onOMXEvent(
3364         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3365     switch (event) {
3366         case OMX_EventPortSettingsChanged:
3367         {
3368             CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
3369 
3370             if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
3371                 CHECK_EQ(mCodec->mOMX->sendCommand(
3372                             mCodec->mNode,
3373                             OMX_CommandPortDisable, kPortIndexOutput),
3374                          (status_t)OK);
3375 
3376                 mCodec->freeOutputBuffersNotOwnedByComponent();
3377 
3378                 mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
3379             } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
3380                 mCodec->mSentFormat = false;
3381             } else {
3382                 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
3383                      mCodec->mComponentName.c_str(), data2);
3384             }
3385 
3386             return true;
3387         }
3388 
3389         case OMX_EventBufferFlag:
3390         {
3391             return true;
3392         }
3393 
3394         default:
3395             return BaseState::onOMXEvent(event, data1, data2);
3396     }
3397 }
3398 
3399 ////////////////////////////////////////////////////////////////////////////////
3400 
OutputPortSettingsChangedState(ACodec * codec)3401 ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
3402         ACodec *codec)
3403     : BaseState(codec) {
3404 }
3405 
getPortMode(OMX_U32 portIndex)3406 ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
3407         OMX_U32 portIndex) {
3408     if (portIndex == kPortIndexOutput) {
3409         return FREE_BUFFERS;
3410     }
3411 
3412     CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
3413 
3414     return RESUBMIT_BUFFERS;
3415 }
3416 
onMessageReceived(const sp<AMessage> & msg)3417 bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
3418         const sp<AMessage> &msg) {
3419     bool handled = false;
3420 
3421     switch (msg->what()) {
3422         case kWhatFlush:
3423         case kWhatShutdown:
3424         case kWhatResume:
3425         {
3426             if (msg->what() == kWhatResume) {
3427                 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
3428             }
3429 
3430             mCodec->deferMessage(msg);
3431             handled = true;
3432             break;
3433         }
3434 
3435         default:
3436             handled = BaseState::onMessageReceived(msg);
3437             break;
3438     }
3439 
3440     return handled;
3441 }
3442 
stateEntered()3443 void ACodec::OutputPortSettingsChangedState::stateEntered() {
3444     ALOGV("[%s] Now handling output port settings change",
3445          mCodec->mComponentName.c_str());
3446 }
3447 
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)3448 bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
3449         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3450     switch (event) {
3451         case OMX_EventCmdComplete:
3452         {
3453             if (data1 == (OMX_U32)OMX_CommandPortDisable) {
3454                 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3455 
3456                 ALOGV("[%s] Output port now disabled.",
3457                         mCodec->mComponentName.c_str());
3458 
3459                 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
3460                 mCodec->mDealer[kPortIndexOutput].clear();
3461 
3462                 CHECK_EQ(mCodec->mOMX->sendCommand(
3463                             mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
3464                          (status_t)OK);
3465 
3466                 status_t err;
3467                 if ((err = mCodec->allocateBuffersOnPort(
3468                                 kPortIndexOutput)) != OK) {
3469                     ALOGE("Failed to allocate output port buffers after "
3470                          "port reconfiguration (error 0x%08x)",
3471                          err);
3472 
3473                     mCodec->signalError(OMX_ErrorUndefined, err);
3474 
3475                     // This is technically not correct, but appears to be
3476                     // the only way to free the component instance.
3477                     // Controlled transitioning from excecuting->idle
3478                     // and idle->loaded seem impossible probably because
3479                     // the output port never finishes re-enabling.
3480                     mCodec->mShutdownInProgress = true;
3481                     mCodec->mKeepComponentAllocated = false;
3482                     mCodec->changeState(mCodec->mLoadedState);
3483                 }
3484 
3485                 return true;
3486             } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
3487                 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3488 
3489                 mCodec->mSentFormat = false;
3490 
3491                 ALOGV("[%s] Output port now reenabled.",
3492                         mCodec->mComponentName.c_str());
3493 
3494                 if (mCodec->mExecutingState->active()) {
3495                     mCodec->mExecutingState->submitOutputBuffers();
3496                 }
3497 
3498                 mCodec->changeState(mCodec->mExecutingState);
3499 
3500                 return true;
3501             }
3502 
3503             return false;
3504         }
3505 
3506         default:
3507             return false;
3508     }
3509 }
3510 
3511 ////////////////////////////////////////////////////////////////////////////////
3512 
ExecutingToIdleState(ACodec * codec)3513 ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
3514     : BaseState(codec),
3515       mComponentNowIdle(false) {
3516 }
3517 
onMessageReceived(const sp<AMessage> & msg)3518 bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3519     bool handled = false;
3520 
3521     switch (msg->what()) {
3522         case kWhatFlush:
3523         {
3524             // Don't send me a flush request if you previously wanted me
3525             // to shutdown.
3526             TRESPASS();
3527             break;
3528         }
3529 
3530         case kWhatShutdown:
3531         {
3532             // We're already doing that...
3533 
3534             handled = true;
3535             break;
3536         }
3537 
3538         default:
3539             handled = BaseState::onMessageReceived(msg);
3540             break;
3541     }
3542 
3543     return handled;
3544 }
3545 
stateEntered()3546 void ACodec::ExecutingToIdleState::stateEntered() {
3547     ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
3548 
3549     mComponentNowIdle = false;
3550     mCodec->mSentFormat = false;
3551 }
3552 
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)3553 bool ACodec::ExecutingToIdleState::onOMXEvent(
3554         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3555     switch (event) {
3556         case OMX_EventCmdComplete:
3557         {
3558             CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3559             CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
3560 
3561             mComponentNowIdle = true;
3562 
3563             changeStateIfWeOwnAllBuffers();
3564 
3565             return true;
3566         }
3567 
3568         case OMX_EventPortSettingsChanged:
3569         case OMX_EventBufferFlag:
3570         {
3571             // We're shutting down and don't care about this anymore.
3572             return true;
3573         }
3574 
3575         default:
3576             return BaseState::onOMXEvent(event, data1, data2);
3577     }
3578 }
3579 
changeStateIfWeOwnAllBuffers()3580 void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
3581     if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
3582         CHECK_EQ(mCodec->mOMX->sendCommand(
3583                     mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
3584                  (status_t)OK);
3585 
3586         CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
3587         CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
3588 
3589         if (mCodec->mFlags & kFlagIsSecure && mCodec->mNativeWindow != NULL) {
3590             // We push enough 1x1 blank buffers to ensure that one of
3591             // them has made it to the display.  This allows the OMX
3592             // component teardown to zero out any protected buffers
3593             // without the risk of scanning out one of those buffers.
3594             mCodec->pushBlankBuffersToNativeWindow();
3595         }
3596 
3597         mCodec->changeState(mCodec->mIdleToLoadedState);
3598     }
3599 }
3600 
onInputBufferFilled(const sp<AMessage> & msg)3601 void ACodec::ExecutingToIdleState::onInputBufferFilled(
3602         const sp<AMessage> &msg) {
3603     BaseState::onInputBufferFilled(msg);
3604 
3605     changeStateIfWeOwnAllBuffers();
3606 }
3607 
onOutputBufferDrained(const sp<AMessage> & msg)3608 void ACodec::ExecutingToIdleState::onOutputBufferDrained(
3609         const sp<AMessage> &msg) {
3610     BaseState::onOutputBufferDrained(msg);
3611 
3612     changeStateIfWeOwnAllBuffers();
3613 }
3614 
3615 ////////////////////////////////////////////////////////////////////////////////
3616 
IdleToLoadedState(ACodec * codec)3617 ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
3618     : BaseState(codec) {
3619 }
3620 
onMessageReceived(const sp<AMessage> & msg)3621 bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
3622     bool handled = false;
3623 
3624     switch (msg->what()) {
3625         case kWhatShutdown:
3626         {
3627             // We're already doing that...
3628 
3629             handled = true;
3630             break;
3631         }
3632 
3633         case kWhatFlush:
3634         {
3635             // Don't send me a flush request if you previously wanted me
3636             // to shutdown.
3637             TRESPASS();
3638             break;
3639         }
3640 
3641         default:
3642             handled = BaseState::onMessageReceived(msg);
3643             break;
3644     }
3645 
3646     return handled;
3647 }
3648 
stateEntered()3649 void ACodec::IdleToLoadedState::stateEntered() {
3650     ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
3651 }
3652 
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)3653 bool ACodec::IdleToLoadedState::onOMXEvent(
3654         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3655     switch (event) {
3656         case OMX_EventCmdComplete:
3657         {
3658             CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3659             CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
3660 
3661             mCodec->changeState(mCodec->mLoadedState);
3662 
3663             return true;
3664         }
3665 
3666         default:
3667             return BaseState::onOMXEvent(event, data1, data2);
3668     }
3669 }
3670 
3671 ////////////////////////////////////////////////////////////////////////////////
3672 
FlushingState(ACodec * codec)3673 ACodec::FlushingState::FlushingState(ACodec *codec)
3674     : BaseState(codec) {
3675 }
3676 
stateEntered()3677 void ACodec::FlushingState::stateEntered() {
3678     ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
3679 
3680     mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
3681 }
3682 
onMessageReceived(const sp<AMessage> & msg)3683 bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
3684     bool handled = false;
3685 
3686     switch (msg->what()) {
3687         case kWhatShutdown:
3688         {
3689             mCodec->deferMessage(msg);
3690             break;
3691         }
3692 
3693         case kWhatFlush:
3694         {
3695             // We're already doing this right now.
3696             handled = true;
3697             break;
3698         }
3699 
3700         default:
3701             handled = BaseState::onMessageReceived(msg);
3702             break;
3703     }
3704 
3705     return handled;
3706 }
3707 
onOMXEvent(OMX_EVENTTYPE event,OMX_U32 data1,OMX_U32 data2)3708 bool ACodec::FlushingState::onOMXEvent(
3709         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3710     ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
3711             mCodec->mComponentName.c_str(), event, data1);
3712 
3713     switch (event) {
3714         case OMX_EventCmdComplete:
3715         {
3716             CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
3717 
3718             if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
3719                 CHECK(!mFlushComplete[data2]);
3720                 mFlushComplete[data2] = true;
3721 
3722                 if (mFlushComplete[kPortIndexInput]
3723                         && mFlushComplete[kPortIndexOutput]) {
3724                     changeStateIfWeOwnAllBuffers();
3725                 }
3726             } else {
3727                 CHECK_EQ(data2, OMX_ALL);
3728                 CHECK(mFlushComplete[kPortIndexInput]);
3729                 CHECK(mFlushComplete[kPortIndexOutput]);
3730 
3731                 changeStateIfWeOwnAllBuffers();
3732             }
3733 
3734             return true;
3735         }
3736 
3737         case OMX_EventPortSettingsChanged:
3738         {
3739             sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
3740             msg->setInt32("type", omx_message::EVENT);
3741             msg->setPointer("node", mCodec->mNode);
3742             msg->setInt32("event", event);
3743             msg->setInt32("data1", data1);
3744             msg->setInt32("data2", data2);
3745 
3746             ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
3747                  mCodec->mComponentName.c_str());
3748 
3749             mCodec->deferMessage(msg);
3750 
3751             return true;
3752         }
3753 
3754         default:
3755             return BaseState::onOMXEvent(event, data1, data2);
3756     }
3757 
3758     return true;
3759 }
3760 
onOutputBufferDrained(const sp<AMessage> & msg)3761 void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
3762     BaseState::onOutputBufferDrained(msg);
3763 
3764     changeStateIfWeOwnAllBuffers();
3765 }
3766 
onInputBufferFilled(const sp<AMessage> & msg)3767 void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
3768     BaseState::onInputBufferFilled(msg);
3769 
3770     changeStateIfWeOwnAllBuffers();
3771 }
3772 
changeStateIfWeOwnAllBuffers()3773 void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
3774     if (mFlushComplete[kPortIndexInput]
3775             && mFlushComplete[kPortIndexOutput]
3776             && mCodec->allYourBuffersAreBelongToUs()) {
3777         sp<AMessage> notify = mCodec->mNotify->dup();
3778         notify->setInt32("what", ACodec::kWhatFlushCompleted);
3779         notify->post();
3780 
3781         mCodec->mPortEOS[kPortIndexInput] =
3782             mCodec->mPortEOS[kPortIndexOutput] = false;
3783 
3784         mCodec->mInputEOSResult = OK;
3785 
3786         mCodec->changeState(mCodec->mExecutingState);
3787     }
3788 }
3789 
3790 }  // namespace android
3791