blob: 09e4e451dced84ddc815575b328f914db4cb5c5b [file] [log] [blame]
James Dong2f1f2242011-03-17 11:02:04 -07001/*
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
Andreas Hubera1587462010-12-15 15:17:42 -080017//#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
Andreas Huber3d3864f2012-02-29 15:47:17 -080029#include <media/stagefright/MediaCodecList.h>
Andreas Hubera1587462010-12-15 15:17:42 -080030#include <media/stagefright/MediaDefs.h>
Glenn Kastencc562a32011-02-08 17:26:17 -080031#include <media/stagefright/NativeWindowWrapper.h>
Andreas Hubera1587462010-12-15 15:17:42 -080032#include <media/stagefright/OMXClient.h>
Andreas Hubere366f522011-06-28 10:51:41 -070033#include <media/stagefright/OMXCodec.h>
Andreas Hubera1587462010-12-15 15:17:42 -080034
Andreas Hubera1587462010-12-15 15:17:42 -080035#include <OMX_Component.h>
36
37namespace android {
38
39template<class T>
40static void InitOMXParams(T *params) {
41 params->nSize = sizeof(T);
42 params->nVersion.s.nVersionMajor = 1;
43 params->nVersion.s.nVersionMinor = 0;
44 params->nVersion.s.nRevision = 0;
45 params->nVersion.s.nStep = 0;
46}
47
48struct CodecObserver : public BnOMXObserver {
49 CodecObserver() {}
50
51 void setNotificationMessage(const sp<AMessage> &msg) {
52 mNotify = msg;
53 }
54
55 // from IOMXObserver
56 virtual void onMessage(const omx_message &omx_msg) {
57 sp<AMessage> msg = mNotify->dup();
58
59 msg->setInt32("type", omx_msg.type);
60 msg->setPointer("node", omx_msg.node);
61
62 switch (omx_msg.type) {
63 case omx_message::EVENT:
64 {
65 msg->setInt32("event", omx_msg.u.event_data.event);
66 msg->setInt32("data1", omx_msg.u.event_data.data1);
67 msg->setInt32("data2", omx_msg.u.event_data.data2);
68 break;
69 }
70
71 case omx_message::EMPTY_BUFFER_DONE:
72 {
73 msg->setPointer("buffer", omx_msg.u.buffer_data.buffer);
74 break;
75 }
76
77 case omx_message::FILL_BUFFER_DONE:
78 {
79 msg->setPointer(
80 "buffer", omx_msg.u.extended_buffer_data.buffer);
81 msg->setInt32(
82 "range_offset",
83 omx_msg.u.extended_buffer_data.range_offset);
84 msg->setInt32(
85 "range_length",
86 omx_msg.u.extended_buffer_data.range_length);
87 msg->setInt32(
88 "flags",
89 omx_msg.u.extended_buffer_data.flags);
90 msg->setInt64(
91 "timestamp",
92 omx_msg.u.extended_buffer_data.timestamp);
93 msg->setPointer(
94 "platform_private",
95 omx_msg.u.extended_buffer_data.platform_private);
96 msg->setPointer(
97 "data_ptr",
98 omx_msg.u.extended_buffer_data.data_ptr);
99 break;
100 }
101
102 default:
103 TRESPASS();
104 break;
105 }
106
107 msg->post();
108 }
109
110protected:
111 virtual ~CodecObserver() {}
112
113private:
114 sp<AMessage> mNotify;
115
116 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
117};
118
119////////////////////////////////////////////////////////////////////////////////
120
121struct ACodec::BaseState : public AState {
122 BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
123
124protected:
125 enum PortMode {
126 KEEP_BUFFERS,
127 RESUBMIT_BUFFERS,
128 FREE_BUFFERS,
129 };
130
131 ACodec *mCodec;
132
133 virtual PortMode getPortMode(OMX_U32 portIndex);
134
135 virtual bool onMessageReceived(const sp<AMessage> &msg);
136
137 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
138
139 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
140 virtual void onInputBufferFilled(const sp<AMessage> &msg);
141
142 void postFillThisBuffer(BufferInfo *info);
143
144private:
145 bool onOMXMessage(const sp<AMessage> &msg);
146
147 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
148
149 bool onOMXFillBufferDone(
150 IOMX::buffer_id bufferID,
151 size_t rangeOffset, size_t rangeLength,
152 OMX_U32 flags,
153 int64_t timeUs,
154 void *platformPrivate,
155 void *dataPtr);
156
157 void getMoreInputDataIfPossible();
158
159 DISALLOW_EVIL_CONSTRUCTORS(BaseState);
160};
161
162////////////////////////////////////////////////////////////////////////////////
163
164struct ACodec::UninitializedState : public ACodec::BaseState {
165 UninitializedState(ACodec *codec);
166
167protected:
168 virtual bool onMessageReceived(const sp<AMessage> &msg);
Andreas Huber4484bdd2012-02-28 15:54:51 -0800169 virtual void stateEntered();
Andreas Hubera1587462010-12-15 15:17:42 -0800170
171private:
172 void onSetup(const sp<AMessage> &msg);
Andreas Huber4484bdd2012-02-28 15:54:51 -0800173 bool onAllocateComponent(const sp<AMessage> &msg);
Andreas Hubera1587462010-12-15 15:17:42 -0800174
175 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
176};
177
178////////////////////////////////////////////////////////////////////////////////
179
Andreas Huber4484bdd2012-02-28 15:54:51 -0800180struct ACodec::LoadedState : public ACodec::BaseState {
181 LoadedState(ACodec *codec);
182
183protected:
184 virtual bool onMessageReceived(const sp<AMessage> &msg);
185 virtual void stateEntered();
186
187private:
188 friend struct ACodec::UninitializedState;
189
190 bool onConfigureComponent(const sp<AMessage> &msg);
191 void onStart();
192 void onShutdown(bool keepComponentAllocated);
193
194 DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
195};
196
197////////////////////////////////////////////////////////////////////////////////
198
Andreas Hubera1587462010-12-15 15:17:42 -0800199struct ACodec::LoadedToIdleState : public ACodec::BaseState {
200 LoadedToIdleState(ACodec *codec);
201
202protected:
203 virtual bool onMessageReceived(const sp<AMessage> &msg);
204 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
205 virtual void stateEntered();
206
207private:
208 status_t allocateBuffers();
209
210 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
211};
212
213////////////////////////////////////////////////////////////////////////////////
214
215struct ACodec::IdleToExecutingState : public ACodec::BaseState {
216 IdleToExecutingState(ACodec *codec);
217
218protected:
219 virtual bool onMessageReceived(const sp<AMessage> &msg);
220 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
221 virtual void stateEntered();
222
223private:
224 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
225};
226
227////////////////////////////////////////////////////////////////////////////////
228
229struct ACodec::ExecutingState : public ACodec::BaseState {
230 ExecutingState(ACodec *codec);
231
232 void submitOutputBuffers();
233
234 // Submit output buffers to the decoder, submit input buffers to client
235 // to fill with data.
236 void resume();
237
Andreas Huber6760f982011-02-04 10:12:26 -0800238 // Returns true iff input and output buffers are in play.
239 bool active() const { return mActive; }
240
Andreas Hubera1587462010-12-15 15:17:42 -0800241protected:
242 virtual PortMode getPortMode(OMX_U32 portIndex);
243 virtual bool onMessageReceived(const sp<AMessage> &msg);
244 virtual void stateEntered();
245
246 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
247
248private:
Andreas Huber6760f982011-02-04 10:12:26 -0800249 bool mActive;
250
Andreas Hubera1587462010-12-15 15:17:42 -0800251 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
252};
253
254////////////////////////////////////////////////////////////////////////////////
255
256struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
257 OutputPortSettingsChangedState(ACodec *codec);
258
259protected:
260 virtual PortMode getPortMode(OMX_U32 portIndex);
261 virtual bool onMessageReceived(const sp<AMessage> &msg);
262 virtual void stateEntered();
263
264 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
265
266private:
267 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
268};
269
270////////////////////////////////////////////////////////////////////////////////
271
272struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
273 ExecutingToIdleState(ACodec *codec);
274
275protected:
276 virtual bool onMessageReceived(const sp<AMessage> &msg);
277 virtual void stateEntered();
278
279 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
280
281 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
282 virtual void onInputBufferFilled(const sp<AMessage> &msg);
283
284private:
285 void changeStateIfWeOwnAllBuffers();
286
Andreas Huber88572f72012-02-21 11:47:18 -0800287 bool mComponentNowIdle;
288
Andreas Hubera1587462010-12-15 15:17:42 -0800289 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
290};
291
292////////////////////////////////////////////////////////////////////////////////
293
294struct ACodec::IdleToLoadedState : public ACodec::BaseState {
295 IdleToLoadedState(ACodec *codec);
296
297protected:
298 virtual bool onMessageReceived(const sp<AMessage> &msg);
299 virtual void stateEntered();
300
301 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
302
303private:
304 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
305};
306
307////////////////////////////////////////////////////////////////////////////////
308
Andreas Hubera1587462010-12-15 15:17:42 -0800309struct ACodec::FlushingState : public ACodec::BaseState {
310 FlushingState(ACodec *codec);
311
312protected:
313 virtual bool onMessageReceived(const sp<AMessage> &msg);
314 virtual void stateEntered();
315
316 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
317
318 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
319 virtual void onInputBufferFilled(const sp<AMessage> &msg);
320
321private:
322 bool mFlushComplete[2];
323
324 void changeStateIfWeOwnAllBuffers();
325
326 DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
327};
328
329////////////////////////////////////////////////////////////////////////////////
330
331ACodec::ACodec()
Andreas Huber3d3864f2012-02-29 15:47:17 -0800332 : mQuirks(0),
333 mNode(NULL),
Andreas Huber88572f72012-02-21 11:47:18 -0800334 mSentFormat(false),
Andreas Huber4484bdd2012-02-28 15:54:51 -0800335 mIsEncoder(false),
336 mShutdownInProgress(false) {
Andreas Hubera1587462010-12-15 15:17:42 -0800337 mUninitializedState = new UninitializedState(this);
Andreas Huber4484bdd2012-02-28 15:54:51 -0800338 mLoadedState = new LoadedState(this);
Andreas Hubera1587462010-12-15 15:17:42 -0800339 mLoadedToIdleState = new LoadedToIdleState(this);
340 mIdleToExecutingState = new IdleToExecutingState(this);
341 mExecutingState = new ExecutingState(this);
342
343 mOutputPortSettingsChangedState =
344 new OutputPortSettingsChangedState(this);
345
346 mExecutingToIdleState = new ExecutingToIdleState(this);
347 mIdleToLoadedState = new IdleToLoadedState(this);
Andreas Hubera1587462010-12-15 15:17:42 -0800348 mFlushingState = new FlushingState(this);
349
350 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
Andreas Huber928baf12011-09-26 10:53:29 -0700351 mInputEOSResult = OK;
Andreas Hubera1587462010-12-15 15:17:42 -0800352
353 changeState(mUninitializedState);
354}
355
356ACodec::~ACodec() {
357}
358
359void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
360 mNotify = msg;
361}
362
363void ACodec::initiateSetup(const sp<AMessage> &msg) {
364 msg->setWhat(kWhatSetup);
365 msg->setTarget(id());
366 msg->post();
367}
368
Andreas Huber88572f72012-02-21 11:47:18 -0800369void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
370 msg->setWhat(kWhatAllocateComponent);
371 msg->setTarget(id());
372 msg->post();
373}
374
375void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
376 msg->setWhat(kWhatConfigureComponent);
377 msg->setTarget(id());
378 msg->post();
379}
380
381void ACodec::initiateStart() {
382 (new AMessage(kWhatStart, id()))->post();
383}
384
Andreas Hubera1587462010-12-15 15:17:42 -0800385void ACodec::signalFlush() {
James Dong44ddd1f2011-11-29 17:59:29 -0800386 ALOGV("[%s] signalFlush", mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -0800387 (new AMessage(kWhatFlush, id()))->post();
388}
389
390void ACodec::signalResume() {
391 (new AMessage(kWhatResume, id()))->post();
392}
393
Andreas Huber4484bdd2012-02-28 15:54:51 -0800394void ACodec::initiateShutdown(bool keepComponentAllocated) {
395 sp<AMessage> msg = new AMessage(kWhatShutdown, id());
396 msg->setInt32("keepComponentAllocated", keepComponentAllocated);
397 msg->post();
Andreas Hubera1587462010-12-15 15:17:42 -0800398}
399
400status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
401 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
402
403 CHECK(mDealer[portIndex] == NULL);
404 CHECK(mBuffers[portIndex].isEmpty());
405
Andreas Huber88572f72012-02-21 11:47:18 -0800406 status_t err;
Andreas Hubera1587462010-12-15 15:17:42 -0800407 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
Andreas Huber88572f72012-02-21 11:47:18 -0800408 err = allocateOutputBuffersFromNativeWindow();
409 } else {
410 OMX_PARAM_PORTDEFINITIONTYPE def;
411 InitOMXParams(&def);
412 def.nPortIndex = portIndex;
413
414 err = mOMX->getParameter(
415 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
416
417 if (err == OK) {
418 ALOGV("[%s] Allocating %lu buffers of size %lu on %s port",
419 mComponentName.c_str(),
420 def.nBufferCountActual, def.nBufferSize,
421 portIndex == kPortIndexInput ? "input" : "output");
422
423 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
424 mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
425
426 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
427 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
428 CHECK(mem.get() != NULL);
429
430 IOMX::buffer_id buffer;
431
Andreas Huber3d3864f2012-02-29 15:47:17 -0800432 uint32_t requiresAllocateBufferBit =
433 (portIndex == kPortIndexInput)
434 ? OMXCodec::kRequiresAllocateBufferOnInputPorts
435 : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
Andreas Huber88572f72012-02-21 11:47:18 -0800436
Andreas Huber3d3864f2012-02-29 15:47:17 -0800437 if (mQuirks & requiresAllocateBufferBit) {
Andreas Huber88572f72012-02-21 11:47:18 -0800438 err = mOMX->allocateBufferWithBackup(
439 mNode, portIndex, mem, &buffer);
440 } else {
441 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
442 }
443
444 BufferInfo info;
445 info.mBufferID = buffer;
446 info.mStatus = BufferInfo::OWNED_BY_US;
447 info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
448 mBuffers[portIndex].push(info);
449 }
450 }
Andreas Hubera1587462010-12-15 15:17:42 -0800451 }
452
Andreas Hubera1587462010-12-15 15:17:42 -0800453 if (err != OK) {
454 return err;
455 }
456
Andreas Huber88572f72012-02-21 11:47:18 -0800457 sp<AMessage> notify = mNotify->dup();
458 notify->setInt32("what", ACodec::kWhatBuffersAllocated);
Andreas Hubera1587462010-12-15 15:17:42 -0800459
Andreas Huber88572f72012-02-21 11:47:18 -0800460 notify->setInt32("portIndex", portIndex);
461 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
462 AString name = StringPrintf("buffer-id_%d", i);
463 notify->setPointer(name.c_str(), mBuffers[portIndex][i].mBufferID);
Andreas Hubera1587462010-12-15 15:17:42 -0800464
Andreas Huber88572f72012-02-21 11:47:18 -0800465 name = StringPrintf("data_%d", i);
Andreas Huber5c850392012-02-21 14:38:23 -0800466 notify->setBuffer(name.c_str(), mBuffers[portIndex][i].mData);
Andreas Hubera1587462010-12-15 15:17:42 -0800467 }
468
Andreas Huber88572f72012-02-21 11:47:18 -0800469 notify->post();
470
Andreas Hubera1587462010-12-15 15:17:42 -0800471 return OK;
472}
473
474status_t ACodec::allocateOutputBuffersFromNativeWindow() {
475 OMX_PARAM_PORTDEFINITIONTYPE def;
476 InitOMXParams(&def);
477 def.nPortIndex = kPortIndexOutput;
478
479 status_t err = mOMX->getParameter(
480 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
481
482 if (err != OK) {
483 return err;
484 }
485
Mathias Agopianff86f372011-07-18 16:15:08 -0700486 err = native_window_set_scaling_mode(mNativeWindow.get(),
487 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
488
489 if (err != OK) {
490 return err;
491 }
492
Andreas Hubera1587462010-12-15 15:17:42 -0800493 err = native_window_set_buffers_geometry(
494 mNativeWindow.get(),
495 def.format.video.nFrameWidth,
496 def.format.video.nFrameHeight,
497 def.format.video.eColorFormat);
498
499 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +0000500 ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
Andreas Hubera1587462010-12-15 15:17:42 -0800501 strerror(-err), -err);
502 return err;
503 }
504
Andreas Hubera1587462010-12-15 15:17:42 -0800505 // Set up the native window.
Jamie Gennis94c59802011-02-24 12:48:17 -0800506 OMX_U32 usage = 0;
507 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
508 if (err != 0) {
Steve Block8564c8d2012-01-05 23:22:43 +0000509 ALOGW("querying usage flags from OMX IL component failed: %d", err);
Jamie Gennis94c59802011-02-24 12:48:17 -0800510 // XXX: Currently this error is logged, but not fatal.
511 usage = 0;
512 }
513
Andreas Hubera1587462010-12-15 15:17:42 -0800514 err = native_window_set_usage(
515 mNativeWindow.get(),
Jamie Gennis94c59802011-02-24 12:48:17 -0800516 usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
Andreas Hubera1587462010-12-15 15:17:42 -0800517
518 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +0000519 ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
Andreas Hubera1587462010-12-15 15:17:42 -0800520 return err;
521 }
522
Jamie Gennis01951fd2011-02-27 15:10:34 -0800523 int minUndequeuedBufs = 0;
524 err = mNativeWindow->query(
525 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
526 &minUndequeuedBufs);
527
528 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +0000529 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
Jamie Gennis01951fd2011-02-27 15:10:34 -0800530 strerror(-err), -err);
531 return err;
532 }
533
534 // XXX: Is this the right logic to use? It's not clear to me what the OMX
535 // buffer counts refer to - how do they account for the renderer holding on
536 // to buffers?
537 if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
538 OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
539 def.nBufferCountActual = newBufferCount;
540 err = mOMX->setParameter(
541 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
542
543 if (err != OK) {
Steve Block3762c312012-01-06 19:20:56 +0000544 ALOGE("[%s] setting nBufferCountActual to %lu failed: %d",
Jamie Gennis01951fd2011-02-27 15:10:34 -0800545 mComponentName.c_str(), newBufferCount, err);
546 return err;
547 }
548 }
549
Andreas Hubera1587462010-12-15 15:17:42 -0800550 err = native_window_set_buffer_count(
551 mNativeWindow.get(), def.nBufferCountActual);
552
553 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +0000554 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
Andreas Hubera1587462010-12-15 15:17:42 -0800555 -err);
556 return err;
557 }
558
Steve Block71f2cf12011-10-20 11:56:00 +0100559 ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
Andreas Hubera1587462010-12-15 15:17:42 -0800560 "output port",
561 mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize);
562
563 // Dequeue buffers and send them to OMX
Jamie Gennis42024642011-02-22 18:33:06 -0800564 for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
Iliyan Malchevb2a153a2011-05-01 11:33:26 -0700565 ANativeWindowBuffer *buf;
Andreas Hubera1587462010-12-15 15:17:42 -0800566 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
567 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +0000568 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
Andreas Hubera1587462010-12-15 15:17:42 -0800569 break;
570 }
571
572 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
Andreas Hubera1587462010-12-15 15:17:42 -0800573 BufferInfo info;
Andreas Hubera1587462010-12-15 15:17:42 -0800574 info.mStatus = BufferInfo::OWNED_BY_US;
575 info.mData = new ABuffer(0);
576 info.mGraphicBuffer = graphicBuffer;
577 mBuffers[kPortIndexOutput].push(info);
Jamie Gennis42024642011-02-22 18:33:06 -0800578
579 IOMX::buffer_id bufferId;
580 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
581 &bufferId);
582 if (err != 0) {
Steve Block3762c312012-01-06 19:20:56 +0000583 ALOGE("registering GraphicBuffer %lu with OMX IL component failed: "
Jamie Gennis42024642011-02-22 18:33:06 -0800584 "%d", i, err);
585 break;
586 }
587
588 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
589
Steve Block71f2cf12011-10-20 11:56:00 +0100590 ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)",
Jamie Gennis42024642011-02-22 18:33:06 -0800591 mComponentName.c_str(),
592 bufferId, graphicBuffer.get());
Andreas Hubera1587462010-12-15 15:17:42 -0800593 }
594
595 OMX_U32 cancelStart;
596 OMX_U32 cancelEnd;
597
598 if (err != 0) {
599 // If an error occurred while dequeuing we need to cancel any buffers
600 // that were dequeued.
601 cancelStart = 0;
Jamie Gennis42024642011-02-22 18:33:06 -0800602 cancelEnd = mBuffers[kPortIndexOutput].size();
Andreas Hubera1587462010-12-15 15:17:42 -0800603 } else {
604 // Return the last two buffers to the native window.
Jamie Gennis01951fd2011-02-27 15:10:34 -0800605 cancelStart = def.nBufferCountActual - minUndequeuedBufs;
Andreas Hubera1587462010-12-15 15:17:42 -0800606 cancelEnd = def.nBufferCountActual;
607 }
608
609 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
610 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
611 cancelBufferToNativeWindow(info);
612 }
613
614 return err;
615}
616
617status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
618 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
619
Steve Block71f2cf12011-10-20 11:56:00 +0100620 ALOGV("[%s] Calling cancelBuffer on buffer %p",
Andreas Hubera1587462010-12-15 15:17:42 -0800621 mComponentName.c_str(), info->mBufferID);
622
623 int err = mNativeWindow->cancelBuffer(
624 mNativeWindow.get(), info->mGraphicBuffer.get());
625
626 CHECK_EQ(err, 0);
627
628 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
629
630 return OK;
631}
632
633ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
Iliyan Malchevb2a153a2011-05-01 11:33:26 -0700634 ANativeWindowBuffer *buf;
Andreas Huberd84fd792011-08-16 13:48:44 -0700635 if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) {
Steve Block3762c312012-01-06 19:20:56 +0000636 ALOGE("dequeueBuffer failed.");
Andreas Huberd84fd792011-08-16 13:48:44 -0700637 return NULL;
638 }
Andreas Hubera1587462010-12-15 15:17:42 -0800639
640 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
641 BufferInfo *info =
642 &mBuffers[kPortIndexOutput].editItemAt(i);
643
644 if (info->mGraphicBuffer->handle == buf->handle) {
645 CHECK_EQ((int)info->mStatus,
646 (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
647
648 info->mStatus = BufferInfo::OWNED_BY_US;
649
650 return info;
651 }
652 }
653
654 TRESPASS();
655
656 return NULL;
657}
658
659status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
660 for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
661 CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
662 }
663
664 mDealer[portIndex].clear();
665
666 return OK;
667}
668
Andreas Huber6760f982011-02-04 10:12:26 -0800669status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
Andreas Hubera1587462010-12-15 15:17:42 -0800670 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
671 BufferInfo *info =
672 &mBuffers[kPortIndexOutput].editItemAt(i);
673
Andreas Huber6760f982011-02-04 10:12:26 -0800674 if (info->mStatus !=
675 BufferInfo::OWNED_BY_COMPONENT) {
676 // We shouldn't have sent out any buffers to the client at this
677 // point.
678 CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
679
Andreas Hubera1587462010-12-15 15:17:42 -0800680 CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
681 }
682 }
683
684 return OK;
685}
686
687status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
688 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
689
690 CHECK(info->mStatus == BufferInfo::OWNED_BY_US
691 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
692
693 if (portIndex == kPortIndexOutput && mNativeWindow != NULL
694 && info->mStatus == BufferInfo::OWNED_BY_US) {
695 CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
696 }
697
698 CHECK_EQ(mOMX->freeBuffer(
699 mNode, portIndex, info->mBufferID),
700 (status_t)OK);
701
702 mBuffers[portIndex].removeAt(i);
703
704 return OK;
705}
706
707ACodec::BufferInfo *ACodec::findBufferByID(
708 uint32_t portIndex, IOMX::buffer_id bufferID,
709 ssize_t *index) {
710 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
711 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
712
713 if (info->mBufferID == bufferID) {
714 if (index != NULL) {
715 *index = i;
716 }
717 return info;
718 }
719 }
720
721 TRESPASS();
722
723 return NULL;
724}
725
Andreas Huber88572f72012-02-21 11:47:18 -0800726status_t ACodec::setComponentRole(
Andreas Hubera1587462010-12-15 15:17:42 -0800727 bool isEncoder, const char *mime) {
728 struct MimeToRole {
729 const char *mime;
730 const char *decoderRole;
731 const char *encoderRole;
732 };
733
734 static const MimeToRole kMimeToRole[] = {
735 { MEDIA_MIMETYPE_AUDIO_MPEG,
736 "audio_decoder.mp3", "audio_encoder.mp3" },
Andreas Huberbc554952011-09-08 14:12:44 -0700737 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
738 "audio_decoder.mp1", "audio_encoder.mp1" },
739 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
740 "audio_decoder.mp2", "audio_encoder.mp2" },
Andreas Hubera1587462010-12-15 15:17:42 -0800741 { MEDIA_MIMETYPE_AUDIO_AMR_NB,
742 "audio_decoder.amrnb", "audio_encoder.amrnb" },
743 { MEDIA_MIMETYPE_AUDIO_AMR_WB,
744 "audio_decoder.amrwb", "audio_encoder.amrwb" },
745 { MEDIA_MIMETYPE_AUDIO_AAC,
746 "audio_decoder.aac", "audio_encoder.aac" },
Andreas Huber3e408f32011-09-28 12:37:36 -0700747 { MEDIA_MIMETYPE_AUDIO_VORBIS,
748 "audio_decoder.vorbis", "audio_encoder.vorbis" },
Andreas Hubera1587462010-12-15 15:17:42 -0800749 { MEDIA_MIMETYPE_VIDEO_AVC,
750 "video_decoder.avc", "video_encoder.avc" },
751 { MEDIA_MIMETYPE_VIDEO_MPEG4,
752 "video_decoder.mpeg4", "video_encoder.mpeg4" },
753 { MEDIA_MIMETYPE_VIDEO_H263,
754 "video_decoder.h263", "video_encoder.h263" },
Andreas Huber88572f72012-02-21 11:47:18 -0800755 { MEDIA_MIMETYPE_VIDEO_VPX,
756 "video_decoder.vpx", "video_encoder.vpx" },
Andreas Hubera1587462010-12-15 15:17:42 -0800757 };
758
759 static const size_t kNumMimeToRole =
760 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
761
762 size_t i;
763 for (i = 0; i < kNumMimeToRole; ++i) {
764 if (!strcasecmp(mime, kMimeToRole[i].mime)) {
765 break;
766 }
767 }
768
769 if (i == kNumMimeToRole) {
Andreas Huber88572f72012-02-21 11:47:18 -0800770 return ERROR_UNSUPPORTED;
Andreas Hubera1587462010-12-15 15:17:42 -0800771 }
772
773 const char *role =
774 isEncoder ? kMimeToRole[i].encoderRole
775 : kMimeToRole[i].decoderRole;
776
777 if (role != NULL) {
778 OMX_PARAM_COMPONENTROLETYPE roleParams;
779 InitOMXParams(&roleParams);
780
781 strncpy((char *)roleParams.cRole,
782 role, OMX_MAX_STRINGNAME_SIZE - 1);
783
784 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
785
786 status_t err = mOMX->setParameter(
787 mNode, OMX_IndexParamStandardComponentRole,
788 &roleParams, sizeof(roleParams));
789
790 if (err != OK) {
Steve Block8564c8d2012-01-05 23:22:43 +0000791 ALOGW("[%s] Failed to set standard component role '%s'.",
Andreas Hubera1587462010-12-15 15:17:42 -0800792 mComponentName.c_str(), role);
Andreas Huber88572f72012-02-21 11:47:18 -0800793
794 return err;
Andreas Hubera1587462010-12-15 15:17:42 -0800795 }
796 }
Andreas Huber88572f72012-02-21 11:47:18 -0800797
798 return OK;
Andreas Hubera1587462010-12-15 15:17:42 -0800799}
800
Andreas Huber88572f72012-02-21 11:47:18 -0800801status_t ACodec::configureCodec(
Andreas Hubera1587462010-12-15 15:17:42 -0800802 const char *mime, const sp<AMessage> &msg) {
Andreas Huber88572f72012-02-21 11:47:18 -0800803 int32_t encoder;
804 if (!msg->findInt32("encoder", &encoder)) {
805 encoder = false;
806 }
807
808 mIsEncoder = encoder;
809
810 status_t err = setComponentRole(encoder /* isEncoder */, mime);
811
812 if (err != OK) {
813 return err;
814 }
815
816 int32_t bitRate = 0;
817 if (encoder && !msg->findInt32("bitrate", &bitRate)) {
818 return INVALID_OPERATION;
819 }
Andreas Hubera1587462010-12-15 15:17:42 -0800820
821 if (!strncasecmp(mime, "video/", 6)) {
Andreas Huber88572f72012-02-21 11:47:18 -0800822 if (encoder) {
823 err = setupVideoEncoder(mime, msg);
824 } else {
825 int32_t width, height;
826 if (!msg->findInt32("width", &width)
827 || !msg->findInt32("height", &height)) {
828 err = INVALID_OPERATION;
829 } else {
830 err = setupVideoDecoder(mime, width, height);
831 }
832 }
Andreas Hubera1587462010-12-15 15:17:42 -0800833 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
834 int32_t numChannels, sampleRate;
Andreas Huber88572f72012-02-21 11:47:18 -0800835 if (!msg->findInt32("channel-count", &numChannels)
836 || !msg->findInt32("sample-rate", &sampleRate)) {
837 err = INVALID_OPERATION;
838 } else {
839 err = setupAACCodec(encoder, numChannels, sampleRate, bitRate);
840 }
Andreas Huber3e408f32011-09-28 12:37:36 -0700841 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
Andreas Huber88572f72012-02-21 11:47:18 -0800842 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
Andreas Huber3e408f32011-09-28 12:37:36 -0700843 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
Andreas Huber88572f72012-02-21 11:47:18 -0800844 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
Andreas Huber3e408f32011-09-28 12:37:36 -0700845 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
846 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
847 // These are PCM-like formats with a fixed sample rate but
848 // a variable number of channels.
849
850 int32_t numChannels;
Andreas Huber88572f72012-02-21 11:47:18 -0800851 if (!msg->findInt32("channel-count", &numChannels)) {
852 err = INVALID_OPERATION;
853 } else {
854 err = setupG711Codec(encoder, numChannels);
855 }
856 }
Andreas Huber3e408f32011-09-28 12:37:36 -0700857
Andreas Huber88572f72012-02-21 11:47:18 -0800858 if (err != OK) {
859 return err;
Andreas Hubera1587462010-12-15 15:17:42 -0800860 }
861
862 int32_t maxInputSize;
863 if (msg->findInt32("max-input-size", &maxInputSize)) {
Andreas Huber88572f72012-02-21 11:47:18 -0800864 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
Andreas Hubera1587462010-12-15 15:17:42 -0800865 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
Andreas Huber88572f72012-02-21 11:47:18 -0800866 err = setMinBufferSize(kPortIndexInput, 8192); // XXX
Andreas Hubera1587462010-12-15 15:17:42 -0800867 }
Andreas Huber88572f72012-02-21 11:47:18 -0800868
869 return err;
Andreas Hubera1587462010-12-15 15:17:42 -0800870}
871
872status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
873 OMX_PARAM_PORTDEFINITIONTYPE def;
874 InitOMXParams(&def);
875 def.nPortIndex = portIndex;
876
877 status_t err = mOMX->getParameter(
878 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
879
880 if (err != OK) {
881 return err;
882 }
883
884 if (def.nBufferSize >= size) {
885 return OK;
886 }
887
888 def.nBufferSize = size;
889
890 err = mOMX->setParameter(
891 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
892
893 if (err != OK) {
894 return err;
895 }
896
897 err = mOMX->getParameter(
898 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
899
900 if (err != OK) {
901 return err;
902 }
903
904 CHECK(def.nBufferSize >= size);
905
906 return OK;
907}
908
Andreas Huber88572f72012-02-21 11:47:18 -0800909status_t ACodec::selectAudioPortFormat(
910 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
911 OMX_AUDIO_PARAM_PORTFORMATTYPE format;
912 InitOMXParams(&format);
913
914 format.nPortIndex = portIndex;
915 for (OMX_U32 index = 0;; ++index) {
916 format.nIndex = index;
917
918 status_t err = mOMX->getParameter(
919 mNode, OMX_IndexParamAudioPortFormat,
920 &format, sizeof(format));
921
922 if (err != OK) {
923 return err;
924 }
925
926 if (format.eEncoding == desiredFormat) {
927 break;
928 }
929 }
930
931 return mOMX->setParameter(
932 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
933}
934
935status_t ACodec::setupAACCodec(
936 bool encoder,
937 int32_t numChannels, int32_t sampleRate, int32_t bitRate) {
938 status_t err = setupRawAudioFormat(
939 encoder ? kPortIndexInput : kPortIndexOutput,
940 sampleRate,
941 numChannels);
942
943 if (err != OK) {
944 return err;
945 }
946
947 if (encoder) {
948 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
949
950 if (err != OK) {
951 return err;
952 }
953
954 OMX_PARAM_PORTDEFINITIONTYPE def;
955 InitOMXParams(&def);
956 def.nPortIndex = kPortIndexOutput;
957
958 err = mOMX->getParameter(
959 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
960
961 if (err != OK) {
962 return err;
963 }
964
965 def.format.audio.bFlagErrorConcealment = OMX_TRUE;
966 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
967
968 err = mOMX->setParameter(
969 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
970
971 if (err != OK) {
972 return err;
973 }
974
975 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
976 InitOMXParams(&profile);
977 profile.nPortIndex = kPortIndexOutput;
978
979 err = mOMX->getParameter(
980 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
981
982 if (err != OK) {
983 return err;
984 }
985
986 profile.nChannels = numChannels;
987
988 profile.eChannelMode =
989 (numChannels == 1)
990 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
991
992 profile.nSampleRate = sampleRate;
993 profile.nBitRate = bitRate;
994 profile.nAudioBandWidth = 0;
995 profile.nFrameLength = 0;
996 profile.nAACtools = OMX_AUDIO_AACToolAll;
997 profile.nAACERtools = OMX_AUDIO_AACERNone;
998 profile.eAACProfile = OMX_AUDIO_AACObjectLC;
999 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1000
1001 err = mOMX->setParameter(
1002 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1003
1004 if (err != OK) {
1005 return err;
1006 }
1007
1008 return err;
1009 }
1010
Andreas Hubera1587462010-12-15 15:17:42 -08001011 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1012 InitOMXParams(&profile);
1013 profile.nPortIndex = kPortIndexInput;
1014
Andreas Huber88572f72012-02-21 11:47:18 -08001015 err = mOMX->getParameter(
Andreas Hubera1587462010-12-15 15:17:42 -08001016 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1017
1018 if (err != OK) {
1019 return err;
1020 }
1021
1022 profile.nChannels = numChannels;
1023 profile.nSampleRate = sampleRate;
1024 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
1025
Andreas Huber88572f72012-02-21 11:47:18 -08001026 return mOMX->setParameter(
Andreas Hubera1587462010-12-15 15:17:42 -08001027 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
Andreas Hubera1587462010-12-15 15:17:42 -08001028}
1029
Andreas Huber88572f72012-02-21 11:47:18 -08001030static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
1031 bool isAMRWB, int32_t bps) {
1032 if (isAMRWB) {
1033 if (bps <= 6600) {
1034 return OMX_AUDIO_AMRBandModeWB0;
1035 } else if (bps <= 8850) {
1036 return OMX_AUDIO_AMRBandModeWB1;
1037 } else if (bps <= 12650) {
1038 return OMX_AUDIO_AMRBandModeWB2;
1039 } else if (bps <= 14250) {
1040 return OMX_AUDIO_AMRBandModeWB3;
1041 } else if (bps <= 15850) {
1042 return OMX_AUDIO_AMRBandModeWB4;
1043 } else if (bps <= 18250) {
1044 return OMX_AUDIO_AMRBandModeWB5;
1045 } else if (bps <= 19850) {
1046 return OMX_AUDIO_AMRBandModeWB6;
1047 } else if (bps <= 23050) {
1048 return OMX_AUDIO_AMRBandModeWB7;
1049 }
1050
1051 // 23850 bps
1052 return OMX_AUDIO_AMRBandModeWB8;
1053 } else { // AMRNB
1054 if (bps <= 4750) {
1055 return OMX_AUDIO_AMRBandModeNB0;
1056 } else if (bps <= 5150) {
1057 return OMX_AUDIO_AMRBandModeNB1;
1058 } else if (bps <= 5900) {
1059 return OMX_AUDIO_AMRBandModeNB2;
1060 } else if (bps <= 6700) {
1061 return OMX_AUDIO_AMRBandModeNB3;
1062 } else if (bps <= 7400) {
1063 return OMX_AUDIO_AMRBandModeNB4;
1064 } else if (bps <= 7950) {
1065 return OMX_AUDIO_AMRBandModeNB5;
1066 } else if (bps <= 10200) {
1067 return OMX_AUDIO_AMRBandModeNB6;
1068 }
1069
1070 // 12200 bps
1071 return OMX_AUDIO_AMRBandModeNB7;
1072 }
1073}
1074
1075status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
Andreas Huber3e408f32011-09-28 12:37:36 -07001076 OMX_AUDIO_PARAM_AMRTYPE def;
1077 InitOMXParams(&def);
Andreas Huber88572f72012-02-21 11:47:18 -08001078 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
Andreas Huber3e408f32011-09-28 12:37:36 -07001079
1080 status_t err =
1081 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1082
1083 if (err != OK) {
1084 return err;
1085 }
1086
1087 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
Andreas Huber88572f72012-02-21 11:47:18 -08001088 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
Andreas Huber3e408f32011-09-28 12:37:36 -07001089
Andreas Huber88572f72012-02-21 11:47:18 -08001090 err = mOMX->setParameter(
1091 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
Andreas Huber3e408f32011-09-28 12:37:36 -07001092
Andreas Huber88572f72012-02-21 11:47:18 -08001093 if (err != OK) {
1094 return err;
1095 }
1096
1097 return setupRawAudioFormat(
1098 encoder ? kPortIndexInput : kPortIndexOutput,
1099 isWAMR ? 16000 : 8000 /* sampleRate */,
1100 1 /* numChannels */);
Andreas Huber3e408f32011-09-28 12:37:36 -07001101}
1102
Andreas Huber88572f72012-02-21 11:47:18 -08001103status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
1104 CHECK(!encoder); // XXX TODO
1105
Andreas Huber3e408f32011-09-28 12:37:36 -07001106 return setupRawAudioFormat(
1107 kPortIndexInput, 8000 /* sampleRate */, numChannels);
1108}
1109
1110status_t ACodec::setupRawAudioFormat(
1111 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1112 OMX_PARAM_PORTDEFINITIONTYPE def;
1113 InitOMXParams(&def);
1114 def.nPortIndex = portIndex;
1115
1116 status_t err = mOMX->getParameter(
1117 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1118
1119 if (err != OK) {
1120 return err;
1121 }
1122
1123 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
1124
1125 err = mOMX->setParameter(
1126 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1127
1128 if (err != OK) {
1129 return err;
1130 }
1131
1132 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
1133 InitOMXParams(&pcmParams);
1134 pcmParams.nPortIndex = portIndex;
1135
1136 err = mOMX->getParameter(
1137 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1138
1139 if (err != OK) {
1140 return err;
1141 }
1142
1143 pcmParams.nChannels = numChannels;
1144 pcmParams.eNumData = OMX_NumericalDataSigned;
1145 pcmParams.bInterleaved = OMX_TRUE;
1146 pcmParams.nBitPerSample = 16;
1147 pcmParams.nSamplingRate = sampleRate;
1148 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1149
1150 if (numChannels == 1) {
1151 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
1152 } else {
1153 CHECK_EQ(numChannels, 2);
1154
1155 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
1156 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
1157 }
1158
1159 return mOMX->setParameter(
1160 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1161}
1162
Andreas Hubera1587462010-12-15 15:17:42 -08001163status_t ACodec::setVideoPortFormatType(
1164 OMX_U32 portIndex,
1165 OMX_VIDEO_CODINGTYPE compressionFormat,
1166 OMX_COLOR_FORMATTYPE colorFormat) {
1167 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1168 InitOMXParams(&format);
1169 format.nPortIndex = portIndex;
1170 format.nIndex = 0;
1171 bool found = false;
1172
1173 OMX_U32 index = 0;
1174 for (;;) {
1175 format.nIndex = index;
1176 status_t err = mOMX->getParameter(
1177 mNode, OMX_IndexParamVideoPortFormat,
1178 &format, sizeof(format));
1179
1180 if (err != OK) {
1181 return err;
1182 }
1183
1184 // The following assertion is violated by TI's video decoder.
1185 // CHECK_EQ(format.nIndex, index);
1186
1187 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
1188 if (portIndex == kPortIndexInput
1189 && colorFormat == format.eColorFormat) {
1190 // eCompressionFormat does not seem right.
1191 found = true;
1192 break;
1193 }
1194 if (portIndex == kPortIndexOutput
1195 && compressionFormat == format.eCompressionFormat) {
1196 // eColorFormat does not seem right.
1197 found = true;
1198 break;
1199 }
1200 }
1201
1202 if (format.eCompressionFormat == compressionFormat
1203 && format.eColorFormat == colorFormat) {
1204 found = true;
1205 break;
1206 }
1207
1208 ++index;
1209 }
1210
1211 if (!found) {
1212 return UNKNOWN_ERROR;
1213 }
1214
1215 status_t err = mOMX->setParameter(
1216 mNode, OMX_IndexParamVideoPortFormat,
1217 &format, sizeof(format));
1218
1219 return err;
1220}
1221
1222status_t ACodec::setSupportedOutputFormat() {
1223 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1224 InitOMXParams(&format);
1225 format.nPortIndex = kPortIndexOutput;
1226 format.nIndex = 0;
1227
1228 status_t err = mOMX->getParameter(
1229 mNode, OMX_IndexParamVideoPortFormat,
1230 &format, sizeof(format));
1231 CHECK_EQ(err, (status_t)OK);
1232 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
1233
Andreas Hubera1587462010-12-15 15:17:42 -08001234 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
1235 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
1236 || format.eColorFormat == OMX_COLOR_FormatCbYCrY
Andreas Hubere366f522011-06-28 10:51:41 -07001237 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
Andreas Hubera1587462010-12-15 15:17:42 -08001238 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
1239
1240 return mOMX->setParameter(
1241 mNode, OMX_IndexParamVideoPortFormat,
1242 &format, sizeof(format));
1243}
1244
Andreas Huber88572f72012-02-21 11:47:18 -08001245static status_t GetVideoCodingTypeFromMime(
1246 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
Andreas Hubera1587462010-12-15 15:17:42 -08001247 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
Andreas Huber88572f72012-02-21 11:47:18 -08001248 *codingType = OMX_VIDEO_CodingAVC;
Andreas Hubera1587462010-12-15 15:17:42 -08001249 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
Andreas Huber88572f72012-02-21 11:47:18 -08001250 *codingType = OMX_VIDEO_CodingMPEG4;
Andreas Hubera1587462010-12-15 15:17:42 -08001251 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
Andreas Huber88572f72012-02-21 11:47:18 -08001252 *codingType = OMX_VIDEO_CodingH263;
Andreas Hubereb2f9c12011-05-19 08:37:39 -07001253 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
Andreas Huber88572f72012-02-21 11:47:18 -08001254 *codingType = OMX_VIDEO_CodingMPEG2;
1255 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) {
1256 *codingType = OMX_VIDEO_CodingVPX;
Andreas Hubera1587462010-12-15 15:17:42 -08001257 } else {
Andreas Huber88572f72012-02-21 11:47:18 -08001258 *codingType = OMX_VIDEO_CodingUnused;
1259 return ERROR_UNSUPPORTED;
Andreas Hubera1587462010-12-15 15:17:42 -08001260 }
1261
Andreas Huber88572f72012-02-21 11:47:18 -08001262 return OK;
1263}
1264
1265status_t ACodec::setupVideoDecoder(
1266 const char *mime, int32_t width, int32_t height) {
1267 OMX_VIDEO_CODINGTYPE compressionFormat;
1268 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1269
1270 if (err != OK) {
1271 return err;
1272 }
1273
1274 err = setVideoPortFormatType(
Andreas Hubera1587462010-12-15 15:17:42 -08001275 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1276
1277 if (err != OK) {
1278 return err;
1279 }
1280
1281 err = setSupportedOutputFormat();
1282
1283 if (err != OK) {
1284 return err;
1285 }
1286
1287 err = setVideoFormatOnPort(
1288 kPortIndexInput, width, height, compressionFormat);
1289
1290 if (err != OK) {
1291 return err;
1292 }
1293
1294 err = setVideoFormatOnPort(
1295 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
1296
1297 if (err != OK) {
1298 return err;
1299 }
1300
1301 return OK;
1302}
1303
Andreas Huber88572f72012-02-21 11:47:18 -08001304status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
1305 int32_t tmp;
1306 if (!msg->findInt32("color-format", &tmp)) {
1307 return INVALID_OPERATION;
1308 }
1309
1310 OMX_COLOR_FORMATTYPE colorFormat =
1311 static_cast<OMX_COLOR_FORMATTYPE>(tmp);
1312
1313 status_t err = setVideoPortFormatType(
1314 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
1315
1316 if (err != OK) {
1317 ALOGE("[%s] does not support color format %d",
1318 mComponentName.c_str(), colorFormat);
1319
1320 return err;
1321 }
1322
1323 /* Input port configuration */
1324
1325 OMX_PARAM_PORTDEFINITIONTYPE def;
1326 InitOMXParams(&def);
1327
1328 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1329
1330 def.nPortIndex = kPortIndexInput;
1331
1332 err = mOMX->getParameter(
1333 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1334
1335 if (err != OK) {
1336 return err;
1337 }
1338
1339 int32_t width, height, bitrate;
1340 if (!msg->findInt32("width", &width)
1341 || !msg->findInt32("height", &height)
1342 || !msg->findInt32("bitrate", &bitrate)) {
1343 return INVALID_OPERATION;
1344 }
1345
1346 video_def->nFrameWidth = width;
1347 video_def->nFrameHeight = height;
1348
1349 int32_t stride;
1350 if (!msg->findInt32("stride", &stride)) {
1351 stride = width;
1352 }
1353
1354 video_def->nStride = stride;
1355
1356 int32_t sliceHeight;
1357 if (!msg->findInt32("slice-height", &sliceHeight)) {
1358 sliceHeight = height;
1359 }
1360
1361 video_def->nSliceHeight = sliceHeight;
1362
1363 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
1364
1365 float frameRate;
1366 if (!msg->findFloat("frame-rate", &frameRate)) {
1367 int32_t tmp;
1368 if (!msg->findInt32("frame-rate", &tmp)) {
1369 return INVALID_OPERATION;
1370 }
1371 frameRate = (float)tmp;
1372 }
1373
1374 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
1375 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
1376 video_def->eColorFormat = colorFormat;
1377
1378 err = mOMX->setParameter(
1379 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1380
1381 if (err != OK) {
1382 ALOGE("[%s] failed to set input port definition parameters.",
1383 mComponentName.c_str());
1384
1385 return err;
1386 }
1387
1388 /* Output port configuration */
1389
1390 OMX_VIDEO_CODINGTYPE compressionFormat;
1391 err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1392
1393 if (err != OK) {
1394 return err;
1395 }
1396
1397 err = setVideoPortFormatType(
1398 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
1399
1400 if (err != OK) {
1401 ALOGE("[%s] does not support compression format %d",
1402 mComponentName.c_str(), compressionFormat);
1403
1404 return err;
1405 }
1406
1407 def.nPortIndex = kPortIndexOutput;
1408
1409 err = mOMX->getParameter(
1410 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1411
1412 if (err != OK) {
1413 return err;
1414 }
1415
1416 video_def->nFrameWidth = width;
1417 video_def->nFrameHeight = height;
1418 video_def->xFramerate = 0;
1419 video_def->nBitrate = bitrate;
1420 video_def->eCompressionFormat = compressionFormat;
1421 video_def->eColorFormat = OMX_COLOR_FormatUnused;
1422
1423 err = mOMX->setParameter(
1424 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1425
1426 if (err != OK) {
1427 ALOGE("[%s] failed to set output port definition parameters.",
1428 mComponentName.c_str());
1429
1430 return err;
1431 }
1432
1433 switch (compressionFormat) {
1434 case OMX_VIDEO_CodingMPEG4:
1435 err = setupMPEG4EncoderParameters(msg);
1436 break;
1437
1438 case OMX_VIDEO_CodingH263:
1439 err = setupH263EncoderParameters(msg);
1440 break;
1441
1442 case OMX_VIDEO_CodingAVC:
1443 err = setupAVCEncoderParameters(msg);
1444 break;
1445
1446 default:
1447 break;
1448 }
1449
1450 ALOGI("setupVideoEncoder succeeded");
1451
1452 return err;
1453}
1454
1455static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
1456 if (iFramesInterval < 0) {
1457 return 0xFFFFFFFF;
1458 } else if (iFramesInterval == 0) {
1459 return 0;
1460 }
1461 OMX_U32 ret = frameRate * iFramesInterval;
1462 CHECK(ret > 1);
1463 return ret;
1464}
1465
1466status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
1467 int32_t bitrate, iFrameInterval;
1468 if (!msg->findInt32("bitrate", &bitrate)
1469 || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1470 return INVALID_OPERATION;
1471 }
1472
1473 float frameRate;
1474 if (!msg->findFloat("frame-rate", &frameRate)) {
1475 int32_t tmp;
1476 if (!msg->findInt32("frame-rate", &tmp)) {
1477 return INVALID_OPERATION;
1478 }
1479 frameRate = (float)tmp;
1480 }
1481
1482 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
1483 InitOMXParams(&mpeg4type);
1484 mpeg4type.nPortIndex = kPortIndexOutput;
1485
1486 status_t err = mOMX->getParameter(
1487 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1488
1489 if (err != OK) {
1490 return err;
1491 }
1492
1493 mpeg4type.nSliceHeaderSpacing = 0;
1494 mpeg4type.bSVH = OMX_FALSE;
1495 mpeg4type.bGov = OMX_FALSE;
1496
1497 mpeg4type.nAllowedPictureTypes =
1498 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1499
1500 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1501 if (mpeg4type.nPFrames == 0) {
1502 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1503 }
1504 mpeg4type.nBFrames = 0;
1505 mpeg4type.nIDCVLCThreshold = 0;
1506 mpeg4type.bACPred = OMX_TRUE;
1507 mpeg4type.nMaxPacketSize = 256;
1508 mpeg4type.nTimeIncRes = 1000;
1509 mpeg4type.nHeaderExtension = 0;
1510 mpeg4type.bReversibleVLC = OMX_FALSE;
1511
1512 int32_t profile;
1513 if (msg->findInt32("profile", &profile)) {
1514 int32_t level;
1515 if (!msg->findInt32("level", &level)) {
1516 return INVALID_OPERATION;
1517 }
1518
1519 err = verifySupportForProfileAndLevel(profile, level);
1520
1521 if (err != OK) {
1522 return err;
1523 }
1524
1525 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
1526 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
1527 }
1528
1529 err = mOMX->setParameter(
1530 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1531
1532 if (err != OK) {
1533 return err;
1534 }
1535
1536 err = configureBitrate(bitrate);
1537
1538 if (err != OK) {
1539 return err;
1540 }
1541
1542 return setupErrorCorrectionParameters();
1543}
1544
1545status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
1546 int32_t bitrate, iFrameInterval;
1547 if (!msg->findInt32("bitrate", &bitrate)
1548 || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1549 return INVALID_OPERATION;
1550 }
1551
1552 float frameRate;
1553 if (!msg->findFloat("frame-rate", &frameRate)) {
1554 int32_t tmp;
1555 if (!msg->findInt32("frame-rate", &tmp)) {
1556 return INVALID_OPERATION;
1557 }
1558 frameRate = (float)tmp;
1559 }
1560
1561 OMX_VIDEO_PARAM_H263TYPE h263type;
1562 InitOMXParams(&h263type);
1563 h263type.nPortIndex = kPortIndexOutput;
1564
1565 status_t err = mOMX->getParameter(
1566 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1567
1568 if (err != OK) {
1569 return err;
1570 }
1571
1572 h263type.nAllowedPictureTypes =
1573 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1574
1575 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1576 if (h263type.nPFrames == 0) {
1577 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1578 }
1579 h263type.nBFrames = 0;
1580
1581 int32_t profile;
1582 if (msg->findInt32("profile", &profile)) {
1583 int32_t level;
1584 if (!msg->findInt32("level", &level)) {
1585 return INVALID_OPERATION;
1586 }
1587
1588 err = verifySupportForProfileAndLevel(profile, level);
1589
1590 if (err != OK) {
1591 return err;
1592 }
1593
1594 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
1595 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
1596 }
1597
1598 h263type.bPLUSPTYPEAllowed = OMX_FALSE;
1599 h263type.bForceRoundingTypeToZero = OMX_FALSE;
1600 h263type.nPictureHeaderRepetition = 0;
1601 h263type.nGOBHeaderInterval = 0;
1602
1603 err = mOMX->setParameter(
1604 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1605
1606 if (err != OK) {
1607 return err;
1608 }
1609
1610 err = configureBitrate(bitrate);
1611
1612 if (err != OK) {
1613 return err;
1614 }
1615
1616 return setupErrorCorrectionParameters();
1617}
1618
1619status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
1620 int32_t bitrate, iFrameInterval;
1621 if (!msg->findInt32("bitrate", &bitrate)
1622 || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1623 return INVALID_OPERATION;
1624 }
1625
1626 float frameRate;
1627 if (!msg->findFloat("frame-rate", &frameRate)) {
1628 int32_t tmp;
1629 if (!msg->findInt32("frame-rate", &tmp)) {
1630 return INVALID_OPERATION;
1631 }
1632 frameRate = (float)tmp;
1633 }
1634
1635 OMX_VIDEO_PARAM_AVCTYPE h264type;
1636 InitOMXParams(&h264type);
1637 h264type.nPortIndex = kPortIndexOutput;
1638
1639 status_t err = mOMX->getParameter(
1640 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1641
1642 if (err != OK) {
1643 return err;
1644 }
1645
1646 h264type.nAllowedPictureTypes =
1647 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1648
1649 int32_t profile;
1650 if (msg->findInt32("profile", &profile)) {
1651 int32_t level;
1652 if (!msg->findInt32("level", &level)) {
1653 return INVALID_OPERATION;
1654 }
1655
1656 err = verifySupportForProfileAndLevel(profile, level);
1657
1658 if (err != OK) {
1659 return err;
1660 }
1661
1662 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
1663 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
1664 }
1665
1666 // XXX
1667 if (!strncmp(mComponentName.c_str(), "OMX.TI.DUCATI1", 14)) {
1668 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
1669 }
1670
1671 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
1672 h264type.nSliceHeaderSpacing = 0;
1673 h264type.bUseHadamard = OMX_TRUE;
1674 h264type.nRefFrames = 1;
1675 h264type.nBFrames = 0;
1676 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1677 if (h264type.nPFrames == 0) {
1678 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1679 }
1680 h264type.nRefIdx10ActiveMinus1 = 0;
1681 h264type.nRefIdx11ActiveMinus1 = 0;
1682 h264type.bEntropyCodingCABAC = OMX_FALSE;
1683 h264type.bWeightedPPrediction = OMX_FALSE;
1684 h264type.bconstIpred = OMX_FALSE;
1685 h264type.bDirect8x8Inference = OMX_FALSE;
1686 h264type.bDirectSpatialTemporal = OMX_FALSE;
1687 h264type.nCabacInitIdc = 0;
1688 }
1689
1690 if (h264type.nBFrames != 0) {
1691 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
1692 }
1693
1694 h264type.bEnableUEP = OMX_FALSE;
1695 h264type.bEnableFMO = OMX_FALSE;
1696 h264type.bEnableASO = OMX_FALSE;
1697 h264type.bEnableRS = OMX_FALSE;
1698 h264type.bFrameMBsOnly = OMX_TRUE;
1699 h264type.bMBAFF = OMX_FALSE;
1700 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
1701
1702 if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName.c_str())) {
1703 h264type.eLevel = OMX_VIDEO_AVCLevelMax;
1704 }
1705
1706 err = mOMX->setParameter(
1707 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1708
1709 if (err != OK) {
1710 return err;
1711 }
1712
1713 return configureBitrate(bitrate);
1714}
1715
1716status_t ACodec::verifySupportForProfileAndLevel(
1717 int32_t profile, int32_t level) {
1718 OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
1719 InitOMXParams(&params);
1720 params.nPortIndex = kPortIndexOutput;
1721
1722 for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
1723 status_t err = mOMX->getParameter(
1724 mNode,
1725 OMX_IndexParamVideoProfileLevelQuerySupported,
1726 &params,
1727 sizeof(params));
1728
1729 if (err != OK) {
1730 return err;
1731 }
1732
1733 int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
1734 int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
1735
1736 if (profile == supportedProfile && level <= supportedLevel) {
1737 return OK;
1738 }
1739 }
1740}
1741
1742status_t ACodec::configureBitrate(int32_t bitrate) {
1743 OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
1744 InitOMXParams(&bitrateType);
1745 bitrateType.nPortIndex = kPortIndexOutput;
1746
1747 status_t err = mOMX->getParameter(
1748 mNode, OMX_IndexParamVideoBitrate,
1749 &bitrateType, sizeof(bitrateType));
1750
1751 if (err != OK) {
1752 return err;
1753 }
1754
1755 bitrateType.eControlRate = OMX_Video_ControlRateVariable;
1756 bitrateType.nTargetBitrate = bitrate;
1757
1758 return mOMX->setParameter(
1759 mNode, OMX_IndexParamVideoBitrate,
1760 &bitrateType, sizeof(bitrateType));
1761}
1762
1763status_t ACodec::setupErrorCorrectionParameters() {
1764 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
1765 InitOMXParams(&errorCorrectionType);
1766 errorCorrectionType.nPortIndex = kPortIndexOutput;
1767
1768 status_t err = mOMX->getParameter(
1769 mNode, OMX_IndexParamVideoErrorCorrection,
1770 &errorCorrectionType, sizeof(errorCorrectionType));
1771
1772 if (err != OK) {
1773 return OK; // Optional feature. Ignore this failure
1774 }
1775
1776 errorCorrectionType.bEnableHEC = OMX_FALSE;
1777 errorCorrectionType.bEnableResync = OMX_TRUE;
1778 errorCorrectionType.nResynchMarkerSpacing = 256;
1779 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
1780 errorCorrectionType.bEnableRVLC = OMX_FALSE;
1781
1782 return mOMX->setParameter(
1783 mNode, OMX_IndexParamVideoErrorCorrection,
1784 &errorCorrectionType, sizeof(errorCorrectionType));
1785}
1786
Andreas Hubera1587462010-12-15 15:17:42 -08001787status_t ACodec::setVideoFormatOnPort(
1788 OMX_U32 portIndex,
1789 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
1790 OMX_PARAM_PORTDEFINITIONTYPE def;
1791 InitOMXParams(&def);
1792 def.nPortIndex = portIndex;
1793
1794 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1795
1796 status_t err = mOMX->getParameter(
1797 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1798
1799 CHECK_EQ(err, (status_t)OK);
1800
1801 if (portIndex == kPortIndexInput) {
1802 // XXX Need a (much) better heuristic to compute input buffer sizes.
1803 const size_t X = 64 * 1024;
1804 if (def.nBufferSize < X) {
1805 def.nBufferSize = X;
1806 }
1807 }
1808
1809 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
1810
1811 video_def->nFrameWidth = width;
1812 video_def->nFrameHeight = height;
1813
1814 if (portIndex == kPortIndexInput) {
1815 video_def->eCompressionFormat = compressionFormat;
1816 video_def->eColorFormat = OMX_COLOR_FormatUnused;
1817 }
1818
1819 err = mOMX->setParameter(
1820 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1821
1822 return err;
1823}
1824
1825status_t ACodec::initNativeWindow() {
1826 if (mNativeWindow != NULL) {
1827 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
1828 }
1829
1830 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
1831 return OK;
1832}
1833
Andreas Huberd03e7d62011-11-28 10:54:12 -08001834size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
1835 size_t n = 0;
1836
1837 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1838 const BufferInfo &info = mBuffers[portIndex].itemAt(i);
1839
1840 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
1841 ++n;
1842 }
1843 }
1844
1845 return n;
1846}
1847
Andreas Hubera1587462010-12-15 15:17:42 -08001848bool ACodec::allYourBuffersAreBelongToUs(
1849 OMX_U32 portIndex) {
1850 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1851 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1852
1853 if (info->mStatus != BufferInfo::OWNED_BY_US
1854 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
Steve Block71f2cf12011-10-20 11:56:00 +01001855 ALOGV("[%s] Buffer %p on port %ld still has status %d",
Andreas Hubera1587462010-12-15 15:17:42 -08001856 mComponentName.c_str(),
1857 info->mBufferID, portIndex, info->mStatus);
1858 return false;
1859 }
1860 }
1861
1862 return true;
1863}
1864
1865bool ACodec::allYourBuffersAreBelongToUs() {
1866 return allYourBuffersAreBelongToUs(kPortIndexInput)
1867 && allYourBuffersAreBelongToUs(kPortIndexOutput);
1868}
1869
1870void ACodec::deferMessage(const sp<AMessage> &msg) {
1871 bool wasEmptyBefore = mDeferredQueue.empty();
1872 mDeferredQueue.push_back(msg);
1873}
1874
1875void ACodec::processDeferredMessages() {
1876 List<sp<AMessage> > queue = mDeferredQueue;
1877 mDeferredQueue.clear();
1878
1879 List<sp<AMessage> >::iterator it = queue.begin();
1880 while (it != queue.end()) {
1881 onMessageReceived(*it++);
1882 }
1883}
1884
Andreas Huber7caa1302011-01-10 10:38:31 -08001885void ACodec::sendFormatChange() {
1886 sp<AMessage> notify = mNotify->dup();
1887 notify->setInt32("what", kWhatOutputFormatChanged);
1888
1889 OMX_PARAM_PORTDEFINITIONTYPE def;
1890 InitOMXParams(&def);
1891 def.nPortIndex = kPortIndexOutput;
1892
1893 CHECK_EQ(mOMX->getParameter(
1894 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
1895 (status_t)OK);
1896
1897 CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
1898
1899 switch (def.eDomain) {
1900 case OMX_PortDomainVideo:
1901 {
1902 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
1903
1904 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
1905 notify->setInt32("width", videoDef->nFrameWidth);
1906 notify->setInt32("height", videoDef->nFrameHeight);
Andreas Huber88572f72012-02-21 11:47:18 -08001907 notify->setInt32("stride", videoDef->nStride);
1908 notify->setInt32("slice-height", videoDef->nSliceHeight);
1909 notify->setInt32("color-format", videoDef->eColorFormat);
Andreas Huber7caa1302011-01-10 10:38:31 -08001910
1911 OMX_CONFIG_RECTTYPE rect;
1912 InitOMXParams(&rect);
1913 rect.nPortIndex = kPortIndexOutput;
1914
1915 if (mOMX->getConfig(
1916 mNode, OMX_IndexConfigCommonOutputCrop,
1917 &rect, sizeof(rect)) != OK) {
1918 rect.nLeft = 0;
1919 rect.nTop = 0;
1920 rect.nWidth = videoDef->nFrameWidth;
1921 rect.nHeight = videoDef->nFrameHeight;
1922 }
1923
1924 CHECK_GE(rect.nLeft, 0);
1925 CHECK_GE(rect.nTop, 0);
1926 CHECK_GE(rect.nWidth, 0u);
1927 CHECK_GE(rect.nHeight, 0u);
1928 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
1929 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
1930
1931 notify->setRect(
1932 "crop",
1933 rect.nLeft,
1934 rect.nTop,
1935 rect.nLeft + rect.nWidth - 1,
1936 rect.nTop + rect.nHeight - 1);
1937
1938 if (mNativeWindow != NULL) {
1939 android_native_rect_t crop;
1940 crop.left = rect.nLeft;
1941 crop.top = rect.nTop;
Andreas Huberb13c4a92011-03-29 10:00:20 -07001942 crop.right = rect.nLeft + rect.nWidth;
1943 crop.bottom = rect.nTop + rect.nHeight;
Andreas Huber7caa1302011-01-10 10:38:31 -08001944
1945 CHECK_EQ(0, native_window_set_crop(
1946 mNativeWindow.get(), &crop));
1947 }
1948 break;
1949 }
1950
1951 case OMX_PortDomainAudio:
1952 {
1953 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
1954 CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
1955
1956 OMX_AUDIO_PARAM_PCMMODETYPE params;
1957 InitOMXParams(&params);
1958 params.nPortIndex = kPortIndexOutput;
1959
1960 CHECK_EQ(mOMX->getParameter(
1961 mNode, OMX_IndexParamAudioPcm,
1962 &params, sizeof(params)),
1963 (status_t)OK);
1964
1965 CHECK(params.nChannels == 1 || params.bInterleaved);
1966 CHECK_EQ(params.nBitPerSample, 16u);
1967 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
1968 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
1969
1970 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
1971 notify->setInt32("channel-count", params.nChannels);
1972 notify->setInt32("sample-rate", params.nSamplingRate);
1973 break;
1974 }
1975
1976 default:
1977 TRESPASS();
1978 }
1979
1980 notify->post();
1981
1982 mSentFormat = true;
1983}
1984
Andreas Huber88572f72012-02-21 11:47:18 -08001985void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
Andreas Huberd41108c2011-09-12 14:14:08 -07001986 sp<AMessage> notify = mNotify->dup();
1987 notify->setInt32("what", ACodec::kWhatError);
1988 notify->setInt32("omx-error", error);
Andreas Huber88572f72012-02-21 11:47:18 -08001989 notify->setInt32("err", internalError);
Andreas Huberd41108c2011-09-12 14:14:08 -07001990 notify->post();
1991}
1992
Andreas Hubera1587462010-12-15 15:17:42 -08001993////////////////////////////////////////////////////////////////////////////////
1994
1995ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
1996 : AState(parentState),
1997 mCodec(codec) {
1998}
1999
2000ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
2001 return KEEP_BUFFERS;
2002}
2003
2004bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
2005 switch (msg->what()) {
2006 case kWhatInputBufferFilled:
2007 {
2008 onInputBufferFilled(msg);
2009 break;
2010 }
2011
2012 case kWhatOutputBufferDrained:
2013 {
2014 onOutputBufferDrained(msg);
2015 break;
2016 }
2017
2018 case ACodec::kWhatOMXMessage:
2019 {
2020 return onOMXMessage(msg);
2021 }
2022
2023 default:
2024 return false;
2025 }
2026
2027 return true;
2028}
2029
2030bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
2031 int32_t type;
2032 CHECK(msg->findInt32("type", &type));
2033
2034 IOMX::node_id nodeID;
2035 CHECK(msg->findPointer("node", &nodeID));
2036 CHECK_EQ(nodeID, mCodec->mNode);
2037
2038 switch (type) {
2039 case omx_message::EVENT:
2040 {
2041 int32_t event, data1, data2;
2042 CHECK(msg->findInt32("event", &event));
2043 CHECK(msg->findInt32("data1", &data1));
2044 CHECK(msg->findInt32("data2", &data2));
2045
Andreas Huber919a7ae2011-07-01 13:13:02 -07002046 if (event == OMX_EventCmdComplete
2047 && data1 == OMX_CommandFlush
2048 && data2 == (int32_t)OMX_ALL) {
2049 // Use of this notification is not consistent across
2050 // implementations. We'll drop this notification and rely
2051 // on flush-complete notifications on the individual port
2052 // indices instead.
2053
2054 return true;
2055 }
2056
Andreas Hubera1587462010-12-15 15:17:42 -08002057 return onOMXEvent(
2058 static_cast<OMX_EVENTTYPE>(event),
2059 static_cast<OMX_U32>(data1),
2060 static_cast<OMX_U32>(data2));
2061 }
2062
2063 case omx_message::EMPTY_BUFFER_DONE:
2064 {
2065 IOMX::buffer_id bufferID;
2066 CHECK(msg->findPointer("buffer", &bufferID));
2067
2068 return onOMXEmptyBufferDone(bufferID);
2069 }
2070
2071 case omx_message::FILL_BUFFER_DONE:
2072 {
2073 IOMX::buffer_id bufferID;
2074 CHECK(msg->findPointer("buffer", &bufferID));
2075
2076 int32_t rangeOffset, rangeLength, flags;
2077 int64_t timeUs;
2078 void *platformPrivate;
2079 void *dataPtr;
2080
2081 CHECK(msg->findInt32("range_offset", &rangeOffset));
2082 CHECK(msg->findInt32("range_length", &rangeLength));
2083 CHECK(msg->findInt32("flags", &flags));
2084 CHECK(msg->findInt64("timestamp", &timeUs));
2085 CHECK(msg->findPointer("platform_private", &platformPrivate));
2086 CHECK(msg->findPointer("data_ptr", &dataPtr));
2087
2088 return onOMXFillBufferDone(
2089 bufferID,
2090 (size_t)rangeOffset, (size_t)rangeLength,
2091 (OMX_U32)flags,
2092 timeUs,
2093 platformPrivate,
2094 dataPtr);
2095 }
2096
2097 default:
2098 TRESPASS();
2099 break;
2100 }
2101}
2102
2103bool ACodec::BaseState::onOMXEvent(
2104 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2105 if (event != OMX_EventError) {
Steve Block71f2cf12011-10-20 11:56:00 +01002106 ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
Andreas Hubera1587462010-12-15 15:17:42 -08002107 mCodec->mComponentName.c_str(), event, data1, data2);
2108
2109 return false;
2110 }
2111
Steve Block3762c312012-01-06 19:20:56 +00002112 ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
Andreas Hubera1587462010-12-15 15:17:42 -08002113
Andreas Huberd41108c2011-09-12 14:14:08 -07002114 mCodec->signalError((OMX_ERRORTYPE)data1);
Andreas Hubera1587462010-12-15 15:17:42 -08002115
2116 return true;
2117}
2118
2119bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
Steve Block71f2cf12011-10-20 11:56:00 +01002120 ALOGV("[%s] onOMXEmptyBufferDone %p",
Andreas Huber6760f982011-02-04 10:12:26 -08002121 mCodec->mComponentName.c_str(), bufferID);
2122
Andreas Hubera1587462010-12-15 15:17:42 -08002123 BufferInfo *info =
2124 mCodec->findBufferByID(kPortIndexInput, bufferID);
2125
2126 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2127 info->mStatus = BufferInfo::OWNED_BY_US;
2128
2129 PortMode mode = getPortMode(kPortIndexInput);
2130
2131 switch (mode) {
2132 case KEEP_BUFFERS:
2133 break;
2134
2135 case RESUBMIT_BUFFERS:
2136 postFillThisBuffer(info);
2137 break;
2138
2139 default:
2140 {
2141 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2142 TRESPASS(); // Not currently used
2143 break;
2144 }
2145 }
2146
2147 return true;
2148}
2149
2150void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
2151 if (mCodec->mPortEOS[kPortIndexInput]) {
2152 return;
2153 }
2154
2155 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
2156
2157 sp<AMessage> notify = mCodec->mNotify->dup();
2158 notify->setInt32("what", ACodec::kWhatFillThisBuffer);
2159 notify->setPointer("buffer-id", info->mBufferID);
2160
2161 info->mData->meta()->clear();
Andreas Huber5c850392012-02-21 14:38:23 -08002162 notify->setBuffer("buffer", info->mData);
Andreas Hubera1587462010-12-15 15:17:42 -08002163
2164 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
2165 reply->setPointer("buffer-id", info->mBufferID);
2166
2167 notify->setMessage("reply", reply);
2168
2169 notify->post();
2170
2171 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
2172}
2173
2174void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
2175 IOMX::buffer_id bufferID;
2176 CHECK(msg->findPointer("buffer-id", &bufferID));
2177
Andreas Huber5c850392012-02-21 14:38:23 -08002178 sp<ABuffer> buffer;
Andreas Hubera1587462010-12-15 15:17:42 -08002179 int32_t err = OK;
Andreas Huber88572f72012-02-21 11:47:18 -08002180 bool eos = false;
2181
Andreas Huber5c850392012-02-21 14:38:23 -08002182 if (!msg->findBuffer("buffer", &buffer)) {
Andreas Hubera1587462010-12-15 15:17:42 -08002183 CHECK(msg->findInt32("err", &err));
2184
Steve Block71f2cf12011-10-20 11:56:00 +01002185 ALOGV("[%s] saw error %d instead of an input buffer",
Andreas Huber41c3f742010-12-21 10:22:33 -08002186 mCodec->mComponentName.c_str(), err);
2187
Andreas Huber5c850392012-02-21 14:38:23 -08002188 buffer.clear();
Andreas Huber88572f72012-02-21 11:47:18 -08002189
2190 eos = true;
Andreas Hubera1587462010-12-15 15:17:42 -08002191 }
2192
Andreas Huber88572f72012-02-21 11:47:18 -08002193 int32_t tmp;
2194 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
2195 eos = true;
2196 err = ERROR_END_OF_STREAM;
2197 }
2198
Andreas Hubera1587462010-12-15 15:17:42 -08002199 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
2200 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
2201
2202 info->mStatus = BufferInfo::OWNED_BY_US;
2203
2204 PortMode mode = getPortMode(kPortIndexInput);
2205
2206 switch (mode) {
2207 case KEEP_BUFFERS:
2208 {
Andreas Huber88572f72012-02-21 11:47:18 -08002209 if (eos) {
Andreas Huber928baf12011-09-26 10:53:29 -07002210 if (!mCodec->mPortEOS[kPortIndexInput]) {
2211 mCodec->mPortEOS[kPortIndexInput] = true;
2212 mCodec->mInputEOSResult = err;
2213 }
Andreas Hubera1587462010-12-15 15:17:42 -08002214 }
2215 break;
2216 }
2217
2218 case RESUBMIT_BUFFERS:
2219 {
Andreas Huber88572f72012-02-21 11:47:18 -08002220 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
Andreas Hubera1587462010-12-15 15:17:42 -08002221 int64_t timeUs;
2222 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2223
2224 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
2225
2226 int32_t isCSD;
2227 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
2228 flags |= OMX_BUFFERFLAG_CODECCONFIG;
2229 }
2230
Andreas Huber88572f72012-02-21 11:47:18 -08002231 if (eos) {
2232 flags |= OMX_BUFFERFLAG_EOS;
2233 }
2234
Andreas Hubera1587462010-12-15 15:17:42 -08002235 if (buffer != info->mData) {
Andreas Huber6760f982011-02-04 10:12:26 -08002236 if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
Steve Block71f2cf12011-10-20 11:56:00 +01002237 ALOGV("[%s] Needs to copy input data.",
Andreas Hubera1587462010-12-15 15:17:42 -08002238 mCodec->mComponentName.c_str());
2239 }
2240
2241 CHECK_LE(buffer->size(), info->mData->capacity());
2242 memcpy(info->mData->data(), buffer->data(), buffer->size());
2243 }
2244
Andreas Huber115cac82011-09-15 12:25:04 -07002245 if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
Steve Block71f2cf12011-10-20 11:56:00 +01002246 ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
Andreas Huber115cac82011-09-15 12:25:04 -07002247 mCodec->mComponentName.c_str(), bufferID);
Andreas Huber88572f72012-02-21 11:47:18 -08002248 } else if (flags & OMX_BUFFERFLAG_EOS) {
2249 ALOGV("[%s] calling emptyBuffer %p w/ EOS",
2250 mCodec->mComponentName.c_str(), bufferID);
Andreas Huber115cac82011-09-15 12:25:04 -07002251 } else {
Steve Block71f2cf12011-10-20 11:56:00 +01002252 ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
Andreas Huber115cac82011-09-15 12:25:04 -07002253 mCodec->mComponentName.c_str(), bufferID, timeUs);
2254 }
Andreas Huber6760f982011-02-04 10:12:26 -08002255
Andreas Hubera1587462010-12-15 15:17:42 -08002256 CHECK_EQ(mCodec->mOMX->emptyBuffer(
2257 mCodec->mNode,
2258 bufferID,
2259 0,
2260 buffer->size(),
2261 flags,
2262 timeUs),
2263 (status_t)OK);
2264
2265 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2266
Andreas Huber88572f72012-02-21 11:47:18 -08002267 if (!eos) {
2268 getMoreInputDataIfPossible();
2269 } else {
2270 ALOGV("[%s] Signalled EOS on the input port",
2271 mCodec->mComponentName.c_str());
2272
2273 mCodec->mPortEOS[kPortIndexInput] = true;
2274 mCodec->mInputEOSResult = err;
2275 }
Andreas Hubera1587462010-12-15 15:17:42 -08002276 } else if (!mCodec->mPortEOS[kPortIndexInput]) {
Andreas Huber928baf12011-09-26 10:53:29 -07002277 if (err != ERROR_END_OF_STREAM) {
Steve Block71f2cf12011-10-20 11:56:00 +01002278 ALOGV("[%s] Signalling EOS on the input port "
Andreas Huber928baf12011-09-26 10:53:29 -07002279 "due to error %d",
2280 mCodec->mComponentName.c_str(), err);
2281 } else {
Steve Block71f2cf12011-10-20 11:56:00 +01002282 ALOGV("[%s] Signalling EOS on the input port",
Andreas Huber928baf12011-09-26 10:53:29 -07002283 mCodec->mComponentName.c_str());
2284 }
Andreas Hubera1587462010-12-15 15:17:42 -08002285
Steve Block71f2cf12011-10-20 11:56:00 +01002286 ALOGV("[%s] calling emptyBuffer %p signalling EOS",
Andreas Huber6760f982011-02-04 10:12:26 -08002287 mCodec->mComponentName.c_str(), bufferID);
2288
Andreas Hubera1587462010-12-15 15:17:42 -08002289 CHECK_EQ(mCodec->mOMX->emptyBuffer(
2290 mCodec->mNode,
2291 bufferID,
2292 0,
2293 0,
2294 OMX_BUFFERFLAG_EOS,
2295 0),
2296 (status_t)OK);
2297
2298 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2299
2300 mCodec->mPortEOS[kPortIndexInput] = true;
Andreas Huber928baf12011-09-26 10:53:29 -07002301 mCodec->mInputEOSResult = err;
Andreas Hubera1587462010-12-15 15:17:42 -08002302 }
2303 break;
2304
2305 default:
2306 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2307 break;
2308 }
2309 }
2310}
2311
2312void ACodec::BaseState::getMoreInputDataIfPossible() {
2313 if (mCodec->mPortEOS[kPortIndexInput]) {
2314 return;
2315 }
2316
2317 BufferInfo *eligible = NULL;
2318
2319 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
2320 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
2321
2322#if 0
2323 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
2324 // There's already a "read" pending.
2325 return;
2326 }
2327#endif
2328
2329 if (info->mStatus == BufferInfo::OWNED_BY_US) {
2330 eligible = info;
2331 }
2332 }
2333
2334 if (eligible == NULL) {
2335 return;
2336 }
2337
2338 postFillThisBuffer(eligible);
2339}
2340
2341bool ACodec::BaseState::onOMXFillBufferDone(
2342 IOMX::buffer_id bufferID,
2343 size_t rangeOffset, size_t rangeLength,
2344 OMX_U32 flags,
2345 int64_t timeUs,
2346 void *platformPrivate,
2347 void *dataPtr) {
Andreas Huber88572f72012-02-21 11:47:18 -08002348 ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx",
2349 mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
Andreas Huber6760f982011-02-04 10:12:26 -08002350
Andreas Hubera1587462010-12-15 15:17:42 -08002351 ssize_t index;
2352 BufferInfo *info =
2353 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2354
2355 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2356
2357 info->mStatus = BufferInfo::OWNED_BY_US;
2358
2359 PortMode mode = getPortMode(kPortIndexOutput);
2360
2361 switch (mode) {
2362 case KEEP_BUFFERS:
2363 break;
2364
2365 case RESUBMIT_BUFFERS:
2366 {
Andreas Huber88572f72012-02-21 11:47:18 -08002367 if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
2368 ALOGV("[%s] calling fillBuffer %p",
2369 mCodec->mComponentName.c_str(), info->mBufferID);
Andreas Huber6760f982011-02-04 10:12:26 -08002370
Andreas Huber88572f72012-02-21 11:47:18 -08002371 CHECK_EQ(mCodec->mOMX->fillBuffer(
2372 mCodec->mNode, info->mBufferID),
2373 (status_t)OK);
Andreas Hubera1587462010-12-15 15:17:42 -08002374
Andreas Huber88572f72012-02-21 11:47:18 -08002375 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2376 break;
Andreas Hubera1587462010-12-15 15:17:42 -08002377 }
2378
Andreas Huber88572f72012-02-21 11:47:18 -08002379 if (!mCodec->mIsEncoder && !mCodec->mSentFormat) {
2380 mCodec->sendFormatChange();
2381 }
2382
2383 if (mCodec->mNativeWindow == NULL) {
2384 info->mData->setRange(rangeOffset, rangeLength);
2385 }
2386
2387 info->mData->meta()->setInt64("timeUs", timeUs);
2388
2389 sp<AMessage> notify = mCodec->mNotify->dup();
2390 notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
2391 notify->setPointer("buffer-id", info->mBufferID);
Andreas Huber5c850392012-02-21 14:38:23 -08002392 notify->setBuffer("buffer", info->mData);
Andreas Huber88572f72012-02-21 11:47:18 -08002393 notify->setInt32("flags", flags);
2394
2395 sp<AMessage> reply =
2396 new AMessage(kWhatOutputBufferDrained, mCodec->id());
2397
2398 reply->setPointer("buffer-id", info->mBufferID);
2399
2400 notify->setMessage("reply", reply);
2401
2402 notify->post();
2403
2404 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
2405
Andreas Hubera1587462010-12-15 15:17:42 -08002406 if (flags & OMX_BUFFERFLAG_EOS) {
Andreas Huber88572f72012-02-21 11:47:18 -08002407 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
2408
Andreas Hubera1587462010-12-15 15:17:42 -08002409 sp<AMessage> notify = mCodec->mNotify->dup();
2410 notify->setInt32("what", ACodec::kWhatEOS);
Andreas Huber928baf12011-09-26 10:53:29 -07002411 notify->setInt32("err", mCodec->mInputEOSResult);
Andreas Hubera1587462010-12-15 15:17:42 -08002412 notify->post();
2413
2414 mCodec->mPortEOS[kPortIndexOutput] = true;
2415 }
2416 break;
2417 }
2418
2419 default:
2420 {
2421 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2422
2423 CHECK_EQ((status_t)OK,
2424 mCodec->freeBuffer(kPortIndexOutput, index));
2425 break;
2426 }
2427 }
2428
2429 return true;
2430}
2431
2432void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
2433 IOMX::buffer_id bufferID;
2434 CHECK(msg->findPointer("buffer-id", &bufferID));
2435
2436 ssize_t index;
2437 BufferInfo *info =
2438 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
2439 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
2440
2441 int32_t render;
2442 if (mCodec->mNativeWindow != NULL
2443 && msg->findInt32("render", &render) && render != 0) {
2444 // The client wants this buffer to be rendered.
2445
Andreas Huber88572f72012-02-21 11:47:18 -08002446 status_t err;
2447 if ((err = mCodec->mNativeWindow->queueBuffer(
Andreas Hubera1587462010-12-15 15:17:42 -08002448 mCodec->mNativeWindow.get(),
Andreas Huber88572f72012-02-21 11:47:18 -08002449 info->mGraphicBuffer.get())) == OK) {
Andreas Huberd41108c2011-09-12 14:14:08 -07002450 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
2451 } else {
Andreas Huber88572f72012-02-21 11:47:18 -08002452 mCodec->signalError(OMX_ErrorUndefined, err);
Andreas Huberd41108c2011-09-12 14:14:08 -07002453 info->mStatus = BufferInfo::OWNED_BY_US;
2454 }
Andreas Hubera1587462010-12-15 15:17:42 -08002455 } else {
2456 info->mStatus = BufferInfo::OWNED_BY_US;
2457 }
2458
2459 PortMode mode = getPortMode(kPortIndexOutput);
2460
2461 switch (mode) {
2462 case KEEP_BUFFERS:
2463 {
2464 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
2465
2466 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2467 // We cannot resubmit the buffer we just rendered, dequeue
2468 // the spare instead.
2469
2470 info = mCodec->dequeueBufferFromNativeWindow();
2471 }
2472 break;
2473 }
2474
2475 case RESUBMIT_BUFFERS:
2476 {
2477 if (!mCodec->mPortEOS[kPortIndexOutput]) {
2478 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2479 // We cannot resubmit the buffer we just rendered, dequeue
2480 // the spare instead.
2481
2482 info = mCodec->dequeueBufferFromNativeWindow();
2483 }
2484
Andreas Huberd84fd792011-08-16 13:48:44 -07002485 if (info != NULL) {
Steve Block71f2cf12011-10-20 11:56:00 +01002486 ALOGV("[%s] calling fillBuffer %p",
Andreas Huberd84fd792011-08-16 13:48:44 -07002487 mCodec->mComponentName.c_str(), info->mBufferID);
Andreas Huber6760f982011-02-04 10:12:26 -08002488
Andreas Huberd84fd792011-08-16 13:48:44 -07002489 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
2490 (status_t)OK);
Andreas Hubera1587462010-12-15 15:17:42 -08002491
Andreas Huberd84fd792011-08-16 13:48:44 -07002492 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2493 }
Andreas Hubera1587462010-12-15 15:17:42 -08002494 }
2495 break;
2496 }
2497
2498 default:
2499 {
2500 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2501
2502 CHECK_EQ((status_t)OK,
2503 mCodec->freeBuffer(kPortIndexOutput, index));
2504 break;
2505 }
2506 }
2507}
2508
2509////////////////////////////////////////////////////////////////////////////////
2510
2511ACodec::UninitializedState::UninitializedState(ACodec *codec)
2512 : BaseState(codec) {
2513}
2514
Andreas Huber4484bdd2012-02-28 15:54:51 -08002515void ACodec::UninitializedState::stateEntered() {
2516 ALOGV("Now uninitialized");
2517}
2518
Andreas Hubera1587462010-12-15 15:17:42 -08002519bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
2520 bool handled = false;
2521
2522 switch (msg->what()) {
2523 case ACodec::kWhatSetup:
2524 {
2525 onSetup(msg);
2526
2527 handled = true;
2528 break;
2529 }
2530
Andreas Huber88572f72012-02-21 11:47:18 -08002531 case ACodec::kWhatAllocateComponent:
2532 {
2533 onAllocateComponent(msg);
2534 handled = true;
2535 break;
2536 }
2537
Andreas Hubera1587462010-12-15 15:17:42 -08002538 case ACodec::kWhatShutdown:
2539 {
Andreas Huber4484bdd2012-02-28 15:54:51 -08002540 int32_t keepComponentAllocated;
2541 CHECK(msg->findInt32(
2542 "keepComponentAllocated", &keepComponentAllocated));
2543 CHECK(!keepComponentAllocated);
2544
Andreas Hubera1587462010-12-15 15:17:42 -08002545 sp<AMessage> notify = mCodec->mNotify->dup();
2546 notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2547 notify->post();
2548
2549 handled = true;
Andreas Huberd84fd792011-08-16 13:48:44 -07002550 break;
Andreas Hubera1587462010-12-15 15:17:42 -08002551 }
2552
2553 case ACodec::kWhatFlush:
2554 {
2555 sp<AMessage> notify = mCodec->mNotify->dup();
2556 notify->setInt32("what", ACodec::kWhatFlushCompleted);
2557 notify->post();
2558
2559 handled = true;
Andreas Huberd84fd792011-08-16 13:48:44 -07002560 break;
Andreas Hubera1587462010-12-15 15:17:42 -08002561 }
2562
2563 default:
2564 return BaseState::onMessageReceived(msg);
2565 }
2566
2567 return handled;
2568}
2569
2570void ACodec::UninitializedState::onSetup(
2571 const sp<AMessage> &msg) {
Andreas Huber4484bdd2012-02-28 15:54:51 -08002572 if (onAllocateComponent(msg)
2573 && mCodec->mLoadedState->onConfigureComponent(msg)) {
2574 mCodec->mLoadedState->onStart();
2575 }
Andreas Huber88572f72012-02-21 11:47:18 -08002576}
2577
Andreas Huber4484bdd2012-02-28 15:54:51 -08002578bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
Andreas Huber88572f72012-02-21 11:47:18 -08002579 ALOGV("onAllocateComponent");
2580
Andreas Huber4484bdd2012-02-28 15:54:51 -08002581 CHECK(mCodec->mNode == NULL);
Andreas Huber88572f72012-02-21 11:47:18 -08002582
Andreas Hubera1587462010-12-15 15:17:42 -08002583 OMXClient client;
2584 CHECK_EQ(client.connect(), (status_t)OK);
2585
2586 sp<IOMX> omx = client.interface();
2587
Andreas Hubere366f522011-06-28 10:51:41 -07002588 Vector<String8> matchingCodecs;
Andreas Huber3d3864f2012-02-29 15:47:17 -08002589 Vector<uint32_t> matchingCodecQuirks;
Andreas Huber88572f72012-02-21 11:47:18 -08002590
2591 AString mime;
2592
2593 AString componentName;
Andreas Huber3d3864f2012-02-29 15:47:17 -08002594 uint32_t quirks;
Andreas Huber88572f72012-02-21 11:47:18 -08002595 if (msg->findString("componentName", &componentName)) {
2596 matchingCodecs.push_back(String8(componentName.c_str()));
Andreas Huber3d3864f2012-02-29 15:47:17 -08002597
2598 if (!OMXCodec::findCodecQuirks(componentName.c_str(), &quirks)) {
2599 quirks = 0;
2600 }
2601 matchingCodecQuirks.push_back(quirks);
Andreas Huber88572f72012-02-21 11:47:18 -08002602 } else {
2603 CHECK(msg->findString("mime", &mime));
2604
2605 int32_t encoder;
2606 if (!msg->findInt32("encoder", &encoder)) {
2607 encoder = false;
2608 }
2609
2610 OMXCodec::findMatchingCodecs(
2611 mime.c_str(),
2612 encoder, // createEncoder
2613 NULL, // matchComponentName
2614 0, // flags
Andreas Huber3d3864f2012-02-29 15:47:17 -08002615 &matchingCodecs,
2616 &matchingCodecQuirks);
Andreas Huber88572f72012-02-21 11:47:18 -08002617 }
Andreas Hubera1587462010-12-15 15:17:42 -08002618
2619 sp<CodecObserver> observer = new CodecObserver;
Andreas Hubere366f522011-06-28 10:51:41 -07002620 IOMX::node_id node = NULL;
Andreas Hubera1587462010-12-15 15:17:42 -08002621
Andreas Hubere366f522011-06-28 10:51:41 -07002622 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
2623 ++matchIndex) {
2624 componentName = matchingCodecs.itemAt(matchIndex).string();
Andreas Huber3d3864f2012-02-29 15:47:17 -08002625 quirks = matchingCodecQuirks.itemAt(matchIndex);
Andreas Hubere366f522011-06-28 10:51:41 -07002626
Andreas Huber115cac82011-09-15 12:25:04 -07002627 pid_t tid = androidGetTid();
2628 int prevPriority = androidGetThreadPriority(tid);
2629 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
Andreas Hubere366f522011-06-28 10:51:41 -07002630 status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
Andreas Huber115cac82011-09-15 12:25:04 -07002631 androidSetThreadPriority(tid, prevPriority);
Andreas Hubere366f522011-06-28 10:51:41 -07002632
2633 if (err == OK) {
2634 break;
2635 }
2636
2637 node = NULL;
2638 }
2639
Andreas Huberd84fd792011-08-16 13:48:44 -07002640 if (node == NULL) {
Andreas Huber88572f72012-02-21 11:47:18 -08002641 if (!mime.empty()) {
2642 ALOGE("Unable to instantiate a decoder for type '%s'.",
2643 mime.c_str());
2644 } else {
2645 ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
2646 }
Andreas Huberd84fd792011-08-16 13:48:44 -07002647
Andreas Huberd41108c2011-09-12 14:14:08 -07002648 mCodec->signalError(OMX_ErrorComponentNotFound);
Andreas Huber4484bdd2012-02-28 15:54:51 -08002649 return false;
Andreas Huberd84fd792011-08-16 13:48:44 -07002650 }
Andreas Hubera1587462010-12-15 15:17:42 -08002651
2652 sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
2653 observer->setNotificationMessage(notify);
2654
2655 mCodec->mComponentName = componentName;
Andreas Huber3d3864f2012-02-29 15:47:17 -08002656 mCodec->mQuirks = quirks;
Andreas Hubera1587462010-12-15 15:17:42 -08002657 mCodec->mOMX = omx;
2658 mCodec->mNode = node;
2659
Andreas Huber6760f982011-02-04 10:12:26 -08002660 mCodec->mPortEOS[kPortIndexInput] =
2661 mCodec->mPortEOS[kPortIndexOutput] = false;
2662
Andreas Huber928baf12011-09-26 10:53:29 -07002663 mCodec->mInputEOSResult = OK;
2664
Andreas Huber88572f72012-02-21 11:47:18 -08002665 {
2666 sp<AMessage> notify = mCodec->mNotify->dup();
2667 notify->setInt32("what", ACodec::kWhatComponentAllocated);
2668 notify->setString("componentName", mCodec->mComponentName.c_str());
2669 notify->post();
2670 }
Andreas Huber4484bdd2012-02-28 15:54:51 -08002671
2672 mCodec->changeState(mCodec->mLoadedState);
2673
2674 return true;
Andreas Huber88572f72012-02-21 11:47:18 -08002675}
2676
Andreas Huber4484bdd2012-02-28 15:54:51 -08002677////////////////////////////////////////////////////////////////////////////////
2678
2679ACodec::LoadedState::LoadedState(ACodec *codec)
2680 : BaseState(codec) {
2681}
2682
2683void ACodec::LoadedState::stateEntered() {
2684 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2685
2686 if (mCodec->mShutdownInProgress) {
2687 bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
2688
2689 mCodec->mShutdownInProgress = false;
2690 mCodec->mKeepComponentAllocated = false;
2691
2692 onShutdown(keepComponentAllocated);
2693 }
2694}
2695
2696void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
2697 if (!keepComponentAllocated) {
2698 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2699
2700 mCodec->mNativeWindow.clear();
2701 mCodec->mNode = NULL;
2702 mCodec->mOMX.clear();
Andreas Huber3d3864f2012-02-29 15:47:17 -08002703 mCodec->mQuirks = 0;
Andreas Huber4484bdd2012-02-28 15:54:51 -08002704 mCodec->mComponentName.clear();
2705
2706 mCodec->changeState(mCodec->mUninitializedState);
2707 }
2708
2709 sp<AMessage> notify = mCodec->mNotify->dup();
2710 notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2711 notify->post();
2712}
2713
2714bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
2715 bool handled = false;
2716
2717 switch (msg->what()) {
2718 case ACodec::kWhatConfigureComponent:
2719 {
2720 onConfigureComponent(msg);
2721 handled = true;
2722 break;
2723 }
2724
2725 case ACodec::kWhatStart:
2726 {
2727 onStart();
2728 handled = true;
2729 break;
2730 }
2731
2732 case ACodec::kWhatShutdown:
2733 {
2734 int32_t keepComponentAllocated;
2735 CHECK(msg->findInt32(
2736 "keepComponentAllocated", &keepComponentAllocated));
2737
2738 onShutdown(keepComponentAllocated);
2739
2740 handled = true;
2741 break;
2742 }
2743
2744 case ACodec::kWhatFlush:
2745 {
2746 sp<AMessage> notify = mCodec->mNotify->dup();
2747 notify->setInt32("what", ACodec::kWhatFlushCompleted);
2748 notify->post();
2749
2750 handled = true;
2751 break;
2752 }
2753
2754 default:
2755 return BaseState::onMessageReceived(msg);
2756 }
2757
2758 return handled;
2759}
2760
2761bool ACodec::LoadedState::onConfigureComponent(
Andreas Huber88572f72012-02-21 11:47:18 -08002762 const sp<AMessage> &msg) {
2763 ALOGV("onConfigureComponent");
2764
2765 CHECK(mCodec->mNode != NULL);
2766
2767 AString mime;
2768 CHECK(msg->findString("mime", &mime));
2769
2770 status_t err = mCodec->configureCodec(mime.c_str(), msg);
2771
2772 if (err != OK) {
2773 mCodec->signalError(OMX_ErrorUndefined, err);
Andreas Huber4484bdd2012-02-28 15:54:51 -08002774 return false;
Andreas Huber88572f72012-02-21 11:47:18 -08002775 }
Andreas Hubera1587462010-12-15 15:17:42 -08002776
2777 sp<RefBase> obj;
Andreas Hubereb2f9c12011-05-19 08:37:39 -07002778 if (msg->findObject("native-window", &obj)
Andreas Huber88572f72012-02-21 11:47:18 -08002779 && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
Glenn Kastencc562a32011-02-08 17:26:17 -08002780 sp<NativeWindowWrapper> nativeWindow(
2781 static_cast<NativeWindowWrapper *>(obj.get()));
2782 CHECK(nativeWindow != NULL);
2783 mCodec->mNativeWindow = nativeWindow->getNativeWindow();
Andreas Hubera1587462010-12-15 15:17:42 -08002784 }
Andreas Hubera1587462010-12-15 15:17:42 -08002785 CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
2786
Andreas Huber88572f72012-02-21 11:47:18 -08002787 {
2788 sp<AMessage> notify = mCodec->mNotify->dup();
2789 notify->setInt32("what", ACodec::kWhatComponentConfigured);
2790 notify->post();
2791 }
Andreas Huber4484bdd2012-02-28 15:54:51 -08002792
2793 return true;
Andreas Huber88572f72012-02-21 11:47:18 -08002794}
2795
Andreas Huber4484bdd2012-02-28 15:54:51 -08002796void ACodec::LoadedState::onStart() {
Andreas Huber88572f72012-02-21 11:47:18 -08002797 ALOGV("onStart");
2798
2799 CHECK_EQ(mCodec->mOMX->sendCommand(
2800 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
Andreas Hubera1587462010-12-15 15:17:42 -08002801 (status_t)OK);
2802
2803 mCodec->changeState(mCodec->mLoadedToIdleState);
2804}
2805
2806////////////////////////////////////////////////////////////////////////////////
2807
2808ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
2809 : BaseState(codec) {
2810}
2811
2812void ACodec::LoadedToIdleState::stateEntered() {
Steve Block71f2cf12011-10-20 11:56:00 +01002813 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08002814
Andreas Huber6032a602011-08-26 16:02:19 -07002815 status_t err;
2816 if ((err = allocateBuffers()) != OK) {
Steve Block3762c312012-01-06 19:20:56 +00002817 ALOGE("Failed to allocate buffers after transitioning to IDLE state "
Andreas Huber6032a602011-08-26 16:02:19 -07002818 "(error 0x%08x)",
2819 err);
2820
Andreas Huber88572f72012-02-21 11:47:18 -08002821 mCodec->signalError(OMX_ErrorUndefined, err);
Andreas Huber6032a602011-08-26 16:02:19 -07002822 }
Andreas Hubera1587462010-12-15 15:17:42 -08002823}
2824
2825status_t ACodec::LoadedToIdleState::allocateBuffers() {
2826 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
2827
2828 if (err != OK) {
2829 return err;
2830 }
2831
2832 return mCodec->allocateBuffersOnPort(kPortIndexOutput);
2833}
2834
2835bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2836 switch (msg->what()) {
2837 case kWhatShutdown:
2838 {
2839 mCodec->deferMessage(msg);
2840 return true;
2841 }
2842
2843 default:
2844 return BaseState::onMessageReceived(msg);
2845 }
2846}
2847
2848bool ACodec::LoadedToIdleState::onOMXEvent(
2849 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2850 switch (event) {
2851 case OMX_EventCmdComplete:
2852 {
2853 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2854 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2855
2856 CHECK_EQ(mCodec->mOMX->sendCommand(
2857 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
2858 (status_t)OK);
2859
2860 mCodec->changeState(mCodec->mIdleToExecutingState);
2861
2862 return true;
2863 }
2864
2865 default:
2866 return BaseState::onOMXEvent(event, data1, data2);
2867 }
2868}
2869
2870////////////////////////////////////////////////////////////////////////////////
2871
2872ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
2873 : BaseState(codec) {
2874}
2875
2876void ACodec::IdleToExecutingState::stateEntered() {
Steve Block71f2cf12011-10-20 11:56:00 +01002877 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08002878}
2879
2880bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
2881 switch (msg->what()) {
2882 case kWhatShutdown:
2883 {
2884 mCodec->deferMessage(msg);
2885 return true;
2886 }
2887
2888 default:
2889 return BaseState::onMessageReceived(msg);
2890 }
2891}
2892
2893bool ACodec::IdleToExecutingState::onOMXEvent(
2894 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2895 switch (event) {
2896 case OMX_EventCmdComplete:
2897 {
2898 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2899 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
2900
2901 mCodec->mExecutingState->resume();
2902 mCodec->changeState(mCodec->mExecutingState);
2903
2904 return true;
2905 }
2906
2907 default:
2908 return BaseState::onOMXEvent(event, data1, data2);
2909 }
2910}
2911
2912////////////////////////////////////////////////////////////////////////////////
2913
2914ACodec::ExecutingState::ExecutingState(ACodec *codec)
Andreas Huber6760f982011-02-04 10:12:26 -08002915 : BaseState(codec),
2916 mActive(false) {
Andreas Hubera1587462010-12-15 15:17:42 -08002917}
2918
2919ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
2920 OMX_U32 portIndex) {
2921 return RESUBMIT_BUFFERS;
2922}
2923
2924void ACodec::ExecutingState::submitOutputBuffers() {
2925 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
2926 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
2927
2928 if (mCodec->mNativeWindow != NULL) {
2929 CHECK(info->mStatus == BufferInfo::OWNED_BY_US
2930 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
2931
2932 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2933 continue;
2934 }
2935
2936 status_t err = mCodec->mNativeWindow->lockBuffer(
2937 mCodec->mNativeWindow.get(),
2938 info->mGraphicBuffer.get());
2939 CHECK_EQ(err, (status_t)OK);
2940 } else {
2941 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
2942 }
2943
Steve Block71f2cf12011-10-20 11:56:00 +01002944 ALOGV("[%s] calling fillBuffer %p",
Andreas Huber6760f982011-02-04 10:12:26 -08002945 mCodec->mComponentName.c_str(), info->mBufferID);
2946
Andreas Hubera1587462010-12-15 15:17:42 -08002947 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
2948 (status_t)OK);
2949
2950 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2951 }
2952}
2953
2954void ACodec::ExecutingState::resume() {
Andreas Huber6760f982011-02-04 10:12:26 -08002955 if (mActive) {
Steve Block71f2cf12011-10-20 11:56:00 +01002956 ALOGV("[%s] We're already active, no need to resume.",
Andreas Huber6760f982011-02-04 10:12:26 -08002957 mCodec->mComponentName.c_str());
2958
2959 return;
2960 }
2961
Andreas Hubera1587462010-12-15 15:17:42 -08002962 submitOutputBuffers();
2963
2964 // Post the first input buffer.
2965 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
2966 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
2967
2968 postFillThisBuffer(info);
Andreas Huber6760f982011-02-04 10:12:26 -08002969
2970 mActive = true;
Andreas Hubera1587462010-12-15 15:17:42 -08002971}
2972
2973void ACodec::ExecutingState::stateEntered() {
Steve Block71f2cf12011-10-20 11:56:00 +01002974 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08002975
2976 mCodec->processDeferredMessages();
2977}
2978
2979bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
2980 bool handled = false;
2981
2982 switch (msg->what()) {
2983 case kWhatShutdown:
2984 {
Andreas Huber4484bdd2012-02-28 15:54:51 -08002985 int32_t keepComponentAllocated;
2986 CHECK(msg->findInt32(
2987 "keepComponentAllocated", &keepComponentAllocated));
2988
2989 mCodec->mShutdownInProgress = true;
2990 mCodec->mKeepComponentAllocated = keepComponentAllocated;
2991
Andreas Huber6760f982011-02-04 10:12:26 -08002992 mActive = false;
2993
Andreas Hubera1587462010-12-15 15:17:42 -08002994 CHECK_EQ(mCodec->mOMX->sendCommand(
2995 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
2996 (status_t)OK);
2997
2998 mCodec->changeState(mCodec->mExecutingToIdleState);
2999
3000 handled = true;
3001 break;
3002 }
3003
3004 case kWhatFlush:
3005 {
James Dong44ddd1f2011-11-29 17:59:29 -08003006 ALOGV("[%s] ExecutingState flushing now "
Andreas Huberd03e7d62011-11-28 10:54:12 -08003007 "(codec owns %d/%d input, %d/%d output).",
3008 mCodec->mComponentName.c_str(),
3009 mCodec->countBuffersOwnedByComponent(kPortIndexInput),
3010 mCodec->mBuffers[kPortIndexInput].size(),
3011 mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
3012 mCodec->mBuffers[kPortIndexOutput].size());
3013
Andreas Huber6760f982011-02-04 10:12:26 -08003014 mActive = false;
3015
Andreas Hubera1587462010-12-15 15:17:42 -08003016 CHECK_EQ(mCodec->mOMX->sendCommand(
3017 mCodec->mNode, OMX_CommandFlush, OMX_ALL),
3018 (status_t)OK);
3019
3020 mCodec->changeState(mCodec->mFlushingState);
3021
3022 handled = true;
3023 break;
3024 }
3025
3026 case kWhatResume:
3027 {
3028 resume();
3029
3030 handled = true;
3031 break;
3032 }
3033
3034 default:
3035 handled = BaseState::onMessageReceived(msg);
3036 break;
3037 }
3038
3039 return handled;
3040}
3041
3042bool ACodec::ExecutingState::onOMXEvent(
3043 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3044 switch (event) {
3045 case OMX_EventPortSettingsChanged:
3046 {
3047 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
3048
Andreas Huber7caa1302011-01-10 10:38:31 -08003049 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
Andreas Hubera1587462010-12-15 15:17:42 -08003050 CHECK_EQ(mCodec->mOMX->sendCommand(
3051 mCodec->mNode,
3052 OMX_CommandPortDisable, kPortIndexOutput),
3053 (status_t)OK);
3054
Andreas Huber6760f982011-02-04 10:12:26 -08003055 mCodec->freeOutputBuffersNotOwnedByComponent();
Andreas Hubera1587462010-12-15 15:17:42 -08003056
3057 mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
Andreas Huber7caa1302011-01-10 10:38:31 -08003058 } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
3059 mCodec->mSentFormat = false;
Andreas Hubera1587462010-12-15 15:17:42 -08003060 } else {
Steve Block71f2cf12011-10-20 11:56:00 +01003061 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
Andreas Hubera1587462010-12-15 15:17:42 -08003062 mCodec->mComponentName.c_str(), data2);
3063 }
3064
3065 return true;
3066 }
3067
3068 case OMX_EventBufferFlag:
3069 {
3070 return true;
3071 }
3072
3073 default:
3074 return BaseState::onOMXEvent(event, data1, data2);
3075 }
3076}
3077
3078////////////////////////////////////////////////////////////////////////////////
3079
3080ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
3081 ACodec *codec)
3082 : BaseState(codec) {
3083}
3084
3085ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
3086 OMX_U32 portIndex) {
3087 if (portIndex == kPortIndexOutput) {
3088 return FREE_BUFFERS;
3089 }
3090
3091 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
3092
3093 return RESUBMIT_BUFFERS;
3094}
3095
3096bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
3097 const sp<AMessage> &msg) {
3098 bool handled = false;
3099
3100 switch (msg->what()) {
3101 case kWhatFlush:
3102 case kWhatShutdown:
Andreas Huber6760f982011-02-04 10:12:26 -08003103 case kWhatResume:
Andreas Hubera1587462010-12-15 15:17:42 -08003104 {
Andreas Huber6760f982011-02-04 10:12:26 -08003105 if (msg->what() == kWhatResume) {
Steve Block71f2cf12011-10-20 11:56:00 +01003106 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
Andreas Huber6760f982011-02-04 10:12:26 -08003107 }
3108
Andreas Hubera1587462010-12-15 15:17:42 -08003109 mCodec->deferMessage(msg);
3110 handled = true;
3111 break;
3112 }
3113
3114 default:
3115 handled = BaseState::onMessageReceived(msg);
3116 break;
3117 }
3118
3119 return handled;
3120}
3121
3122void ACodec::OutputPortSettingsChangedState::stateEntered() {
Steve Block71f2cf12011-10-20 11:56:00 +01003123 ALOGV("[%s] Now handling output port settings change",
Andreas Hubera1587462010-12-15 15:17:42 -08003124 mCodec->mComponentName.c_str());
3125}
3126
3127bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
3128 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3129 switch (event) {
3130 case OMX_EventCmdComplete:
3131 {
3132 if (data1 == (OMX_U32)OMX_CommandPortDisable) {
3133 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3134
Steve Block71f2cf12011-10-20 11:56:00 +01003135 ALOGV("[%s] Output port now disabled.",
Andreas Hubera1587462010-12-15 15:17:42 -08003136 mCodec->mComponentName.c_str());
3137
3138 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
3139 mCodec->mDealer[kPortIndexOutput].clear();
3140
3141 CHECK_EQ(mCodec->mOMX->sendCommand(
3142 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
3143 (status_t)OK);
3144
Andreas Huber6032a602011-08-26 16:02:19 -07003145 status_t err;
3146 if ((err = mCodec->allocateBuffersOnPort(
3147 kPortIndexOutput)) != OK) {
Steve Block3762c312012-01-06 19:20:56 +00003148 ALOGE("Failed to allocate output port buffers after "
Andreas Huber6032a602011-08-26 16:02:19 -07003149 "port reconfiguration (error 0x%08x)",
3150 err);
3151
Andreas Huber88572f72012-02-21 11:47:18 -08003152 mCodec->signalError(OMX_ErrorUndefined, err);
Andreas Huberd03e7d62011-11-28 10:54:12 -08003153
3154 // This is technically not correct, since we were unable
3155 // to allocate output buffers and therefore the output port
3156 // remains disabled. It is necessary however to allow us
3157 // to shutdown the codec properly.
3158 mCodec->changeState(mCodec->mExecutingState);
Andreas Huber6032a602011-08-26 16:02:19 -07003159 }
Andreas Hubera1587462010-12-15 15:17:42 -08003160
3161 return true;
3162 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
3163 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
3164
Andreas Huber7caa1302011-01-10 10:38:31 -08003165 mCodec->mSentFormat = false;
3166
Steve Block71f2cf12011-10-20 11:56:00 +01003167 ALOGV("[%s] Output port now reenabled.",
Andreas Hubera1587462010-12-15 15:17:42 -08003168 mCodec->mComponentName.c_str());
3169
Andreas Huber6760f982011-02-04 10:12:26 -08003170 if (mCodec->mExecutingState->active()) {
3171 mCodec->mExecutingState->submitOutputBuffers();
3172 }
3173
Andreas Hubera1587462010-12-15 15:17:42 -08003174 mCodec->changeState(mCodec->mExecutingState);
3175
3176 return true;
3177 }
3178
3179 return false;
3180 }
3181
3182 default:
3183 return false;
3184 }
3185}
3186
3187////////////////////////////////////////////////////////////////////////////////
3188
3189ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
Andreas Huber88572f72012-02-21 11:47:18 -08003190 : BaseState(codec),
3191 mComponentNowIdle(false) {
Andreas Hubera1587462010-12-15 15:17:42 -08003192}
3193
3194bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3195 bool handled = false;
3196
3197 switch (msg->what()) {
3198 case kWhatFlush:
3199 {
3200 // Don't send me a flush request if you previously wanted me
3201 // to shutdown.
3202 TRESPASS();
3203 break;
3204 }
3205
3206 case kWhatShutdown:
3207 {
3208 // We're already doing that...
3209
3210 handled = true;
3211 break;
3212 }
3213
3214 default:
3215 handled = BaseState::onMessageReceived(msg);
3216 break;
3217 }
3218
3219 return handled;
3220}
3221
3222void ACodec::ExecutingToIdleState::stateEntered() {
Steve Block71f2cf12011-10-20 11:56:00 +01003223 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
Andreas Huber7caa1302011-01-10 10:38:31 -08003224
Andreas Huber88572f72012-02-21 11:47:18 -08003225 mComponentNowIdle = false;
Andreas Huber7caa1302011-01-10 10:38:31 -08003226 mCodec->mSentFormat = false;
Andreas Hubera1587462010-12-15 15:17:42 -08003227}
3228
3229bool ACodec::ExecutingToIdleState::onOMXEvent(
3230 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3231 switch (event) {
3232 case OMX_EventCmdComplete:
3233 {
3234 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3235 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
3236
Andreas Huber88572f72012-02-21 11:47:18 -08003237 mComponentNowIdle = true;
3238
Andreas Hubera1587462010-12-15 15:17:42 -08003239 changeStateIfWeOwnAllBuffers();
3240
3241 return true;
3242 }
3243
Andreas Huber6760f982011-02-04 10:12:26 -08003244 case OMX_EventPortSettingsChanged:
3245 case OMX_EventBufferFlag:
3246 {
3247 // We're shutting down and don't care about this anymore.
3248 return true;
3249 }
3250
Andreas Hubera1587462010-12-15 15:17:42 -08003251 default:
3252 return BaseState::onOMXEvent(event, data1, data2);
3253 }
3254}
Andreas Huber919a7ae2011-07-01 13:13:02 -07003255
Andreas Hubera1587462010-12-15 15:17:42 -08003256void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
Andreas Huber88572f72012-02-21 11:47:18 -08003257 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
Andreas Hubera1587462010-12-15 15:17:42 -08003258 CHECK_EQ(mCodec->mOMX->sendCommand(
3259 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
3260 (status_t)OK);
3261
3262 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
3263 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
3264
3265 mCodec->changeState(mCodec->mIdleToLoadedState);
3266 }
3267}
3268
3269void ACodec::ExecutingToIdleState::onInputBufferFilled(
3270 const sp<AMessage> &msg) {
3271 BaseState::onInputBufferFilled(msg);
3272
3273 changeStateIfWeOwnAllBuffers();
3274}
3275
3276void ACodec::ExecutingToIdleState::onOutputBufferDrained(
3277 const sp<AMessage> &msg) {
3278 BaseState::onOutputBufferDrained(msg);
3279
3280 changeStateIfWeOwnAllBuffers();
3281}
3282
3283////////////////////////////////////////////////////////////////////////////////
3284
3285ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
3286 : BaseState(codec) {
3287}
3288
3289bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
3290 bool handled = false;
3291
3292 switch (msg->what()) {
3293 case kWhatShutdown:
3294 {
3295 // We're already doing that...
3296
3297 handled = true;
3298 break;
3299 }
3300
3301 case kWhatFlush:
3302 {
3303 // Don't send me a flush request if you previously wanted me
3304 // to shutdown.
3305 TRESPASS();
3306 break;
3307 }
3308
3309 default:
3310 handled = BaseState::onMessageReceived(msg);
3311 break;
3312 }
3313
3314 return handled;
3315}
3316
3317void ACodec::IdleToLoadedState::stateEntered() {
Steve Block71f2cf12011-10-20 11:56:00 +01003318 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08003319}
3320
3321bool ACodec::IdleToLoadedState::onOMXEvent(
3322 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3323 switch (event) {
3324 case OMX_EventCmdComplete:
3325 {
3326 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3327 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
3328
Andreas Huber4484bdd2012-02-28 15:54:51 -08003329 mCodec->changeState(mCodec->mLoadedState);
Andreas Hubera1587462010-12-15 15:17:42 -08003330
3331 return true;
3332 }
3333
3334 default:
3335 return BaseState::onOMXEvent(event, data1, data2);
3336 }
3337}
3338
3339////////////////////////////////////////////////////////////////////////////////
3340
Andreas Hubera1587462010-12-15 15:17:42 -08003341ACodec::FlushingState::FlushingState(ACodec *codec)
3342 : BaseState(codec) {
3343}
3344
3345void ACodec::FlushingState::stateEntered() {
Steve Block71f2cf12011-10-20 11:56:00 +01003346 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08003347
3348 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
3349}
3350
3351bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
3352 bool handled = false;
3353
3354 switch (msg->what()) {
3355 case kWhatShutdown:
3356 {
3357 mCodec->deferMessage(msg);
3358 break;
3359 }
3360
3361 case kWhatFlush:
3362 {
3363 // We're already doing this right now.
3364 handled = true;
3365 break;
3366 }
3367
3368 default:
3369 handled = BaseState::onMessageReceived(msg);
3370 break;
3371 }
3372
3373 return handled;
3374}
3375
3376bool ACodec::FlushingState::onOMXEvent(
3377 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
James Dong44ddd1f2011-11-29 17:59:29 -08003378 ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
Andreas Huberd03e7d62011-11-28 10:54:12 -08003379 mCodec->mComponentName.c_str(), event, data1);
3380
Andreas Hubera1587462010-12-15 15:17:42 -08003381 switch (event) {
3382 case OMX_EventCmdComplete:
3383 {
3384 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
3385
3386 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
3387 CHECK(!mFlushComplete[data2]);
3388 mFlushComplete[data2] = true;
Andreas Huber4f0205f2011-06-30 09:17:57 -07003389
3390 if (mFlushComplete[kPortIndexInput]
3391 && mFlushComplete[kPortIndexOutput]) {
3392 changeStateIfWeOwnAllBuffers();
3393 }
Andreas Hubera1587462010-12-15 15:17:42 -08003394 } else {
3395 CHECK_EQ(data2, OMX_ALL);
3396 CHECK(mFlushComplete[kPortIndexInput]);
3397 CHECK(mFlushComplete[kPortIndexOutput]);
3398
3399 changeStateIfWeOwnAllBuffers();
3400 }
3401
3402 return true;
3403 }
3404
Andreas Huber6760f982011-02-04 10:12:26 -08003405 case OMX_EventPortSettingsChanged:
3406 {
3407 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
3408 msg->setInt32("type", omx_message::EVENT);
3409 msg->setPointer("node", mCodec->mNode);
3410 msg->setInt32("event", event);
3411 msg->setInt32("data1", data1);
3412 msg->setInt32("data2", data2);
3413
Steve Block71f2cf12011-10-20 11:56:00 +01003414 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
Andreas Huber6760f982011-02-04 10:12:26 -08003415 mCodec->mComponentName.c_str());
3416
3417 mCodec->deferMessage(msg);
3418
3419 return true;
3420 }
3421
Andreas Hubera1587462010-12-15 15:17:42 -08003422 default:
3423 return BaseState::onOMXEvent(event, data1, data2);
3424 }
3425
3426 return true;
3427}
3428
3429void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
3430 BaseState::onOutputBufferDrained(msg);
3431
3432 changeStateIfWeOwnAllBuffers();
3433}
3434
3435void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
3436 BaseState::onInputBufferFilled(msg);
3437
3438 changeStateIfWeOwnAllBuffers();
3439}
3440
3441void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
3442 if (mFlushComplete[kPortIndexInput]
3443 && mFlushComplete[kPortIndexOutput]
3444 && mCodec->allYourBuffersAreBelongToUs()) {
3445 sp<AMessage> notify = mCodec->mNotify->dup();
3446 notify->setInt32("what", ACodec::kWhatFlushCompleted);
3447 notify->post();
3448
3449 mCodec->mPortEOS[kPortIndexInput] =
3450 mCodec->mPortEOS[kPortIndexOutput] = false;
3451
Andreas Huber928baf12011-09-26 10:53:29 -07003452 mCodec->mInputEOSResult = OK;
3453
Andreas Hubera1587462010-12-15 15:17:42 -08003454 mCodec->changeState(mCodec->mExecutingState);
3455 }
3456}
3457
3458} // namespace android