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(¶ms);
1840 params.nPortIndex = kPortIndexOutput;
1841
1842 for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
1843 status_t err = mOMX->getParameter(
1844 mNode,
1845 OMX_IndexParamVideoProfileLevelQuerySupported,
1846 ¶ms,
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(¶ms);
2078 params.nPortIndex = kPortIndexOutput;
2079
2080 CHECK_EQ(mOMX->getParameter(
2081 mNode, OMX_IndexParamAudioPcm,
2082 ¶ms, 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