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