blob: 4189354efc526eb7c7f04cc12dac7c99acdd1630 [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
29#include <media/stagefright/MediaDefs.h>
Glenn Kastencc562a32011-02-08 17:26:17 -080030#include <media/stagefright/NativeWindowWrapper.h>
Andreas Hubera1587462010-12-15 15:17:42 -080031#include <media/stagefright/OMXClient.h>
32
33#include <surfaceflinger/Surface.h>
Glenn Kastencc562a32011-02-08 17:26:17 -080034#include <gui/SurfaceTextureClient.h>
Andreas Hubera1587462010-12-15 15:17:42 -080035
36#include <OMX_Component.h>
37
38namespace android {
39
40template<class T>
41static void InitOMXParams(T *params) {
42 params->nSize = sizeof(T);
43 params->nVersion.s.nVersionMajor = 1;
44 params->nVersion.s.nVersionMinor = 0;
45 params->nVersion.s.nRevision = 0;
46 params->nVersion.s.nStep = 0;
47}
48
49struct CodecObserver : public BnOMXObserver {
50 CodecObserver() {}
51
52 void setNotificationMessage(const sp<AMessage> &msg) {
53 mNotify = msg;
54 }
55
56 // from IOMXObserver
57 virtual void onMessage(const omx_message &omx_msg) {
58 sp<AMessage> msg = mNotify->dup();
59
60 msg->setInt32("type", omx_msg.type);
61 msg->setPointer("node", omx_msg.node);
62
63 switch (omx_msg.type) {
64 case omx_message::EVENT:
65 {
66 msg->setInt32("event", omx_msg.u.event_data.event);
67 msg->setInt32("data1", omx_msg.u.event_data.data1);
68 msg->setInt32("data2", omx_msg.u.event_data.data2);
69 break;
70 }
71
72 case omx_message::EMPTY_BUFFER_DONE:
73 {
74 msg->setPointer("buffer", omx_msg.u.buffer_data.buffer);
75 break;
76 }
77
78 case omx_message::FILL_BUFFER_DONE:
79 {
80 msg->setPointer(
81 "buffer", omx_msg.u.extended_buffer_data.buffer);
82 msg->setInt32(
83 "range_offset",
84 omx_msg.u.extended_buffer_data.range_offset);
85 msg->setInt32(
86 "range_length",
87 omx_msg.u.extended_buffer_data.range_length);
88 msg->setInt32(
89 "flags",
90 omx_msg.u.extended_buffer_data.flags);
91 msg->setInt64(
92 "timestamp",
93 omx_msg.u.extended_buffer_data.timestamp);
94 msg->setPointer(
95 "platform_private",
96 omx_msg.u.extended_buffer_data.platform_private);
97 msg->setPointer(
98 "data_ptr",
99 omx_msg.u.extended_buffer_data.data_ptr);
100 break;
101 }
102
103 default:
104 TRESPASS();
105 break;
106 }
107
108 msg->post();
109 }
110
111protected:
112 virtual ~CodecObserver() {}
113
114private:
115 sp<AMessage> mNotify;
116
117 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
118};
119
120////////////////////////////////////////////////////////////////////////////////
121
122struct ACodec::BaseState : public AState {
123 BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
124
125protected:
126 enum PortMode {
127 KEEP_BUFFERS,
128 RESUBMIT_BUFFERS,
129 FREE_BUFFERS,
130 };
131
132 ACodec *mCodec;
133
134 virtual PortMode getPortMode(OMX_U32 portIndex);
135
136 virtual bool onMessageReceived(const sp<AMessage> &msg);
137
138 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
139
140 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
141 virtual void onInputBufferFilled(const sp<AMessage> &msg);
142
143 void postFillThisBuffer(BufferInfo *info);
144
145private:
146 bool onOMXMessage(const sp<AMessage> &msg);
147
148 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
149
150 bool onOMXFillBufferDone(
151 IOMX::buffer_id bufferID,
152 size_t rangeOffset, size_t rangeLength,
153 OMX_U32 flags,
154 int64_t timeUs,
155 void *platformPrivate,
156 void *dataPtr);
157
158 void getMoreInputDataIfPossible();
159
160 DISALLOW_EVIL_CONSTRUCTORS(BaseState);
161};
162
163////////////////////////////////////////////////////////////////////////////////
164
165struct ACodec::UninitializedState : public ACodec::BaseState {
166 UninitializedState(ACodec *codec);
167
168protected:
169 virtual bool onMessageReceived(const sp<AMessage> &msg);
170
171private:
172 void onSetup(const sp<AMessage> &msg);
173
174 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
175};
176
177////////////////////////////////////////////////////////////////////////////////
178
179struct ACodec::LoadedToIdleState : public ACodec::BaseState {
180 LoadedToIdleState(ACodec *codec);
181
182protected:
183 virtual bool onMessageReceived(const sp<AMessage> &msg);
184 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
185 virtual void stateEntered();
186
187private:
188 status_t allocateBuffers();
189
190 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
191};
192
193////////////////////////////////////////////////////////////////////////////////
194
195struct ACodec::IdleToExecutingState : public ACodec::BaseState {
196 IdleToExecutingState(ACodec *codec);
197
198protected:
199 virtual bool onMessageReceived(const sp<AMessage> &msg);
200 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
201 virtual void stateEntered();
202
203private:
204 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
205};
206
207////////////////////////////////////////////////////////////////////////////////
208
209struct ACodec::ExecutingState : public ACodec::BaseState {
210 ExecutingState(ACodec *codec);
211
212 void submitOutputBuffers();
213
214 // Submit output buffers to the decoder, submit input buffers to client
215 // to fill with data.
216 void resume();
217
Andreas Huber6760f982011-02-04 10:12:26 -0800218 // Returns true iff input and output buffers are in play.
219 bool active() const { return mActive; }
220
Andreas Hubera1587462010-12-15 15:17:42 -0800221protected:
222 virtual PortMode getPortMode(OMX_U32 portIndex);
223 virtual bool onMessageReceived(const sp<AMessage> &msg);
224 virtual void stateEntered();
225
226 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
227
228private:
Andreas Huber6760f982011-02-04 10:12:26 -0800229 bool mActive;
230
Andreas Hubera1587462010-12-15 15:17:42 -0800231 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
232};
233
234////////////////////////////////////////////////////////////////////////////////
235
236struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
237 OutputPortSettingsChangedState(ACodec *codec);
238
239protected:
240 virtual PortMode getPortMode(OMX_U32 portIndex);
241 virtual bool onMessageReceived(const sp<AMessage> &msg);
242 virtual void stateEntered();
243
244 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
245
246private:
247 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
248};
249
250////////////////////////////////////////////////////////////////////////////////
251
252struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
253 ExecutingToIdleState(ACodec *codec);
254
255protected:
256 virtual bool onMessageReceived(const sp<AMessage> &msg);
257 virtual void stateEntered();
258
259 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
260
261 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
262 virtual void onInputBufferFilled(const sp<AMessage> &msg);
263
264private:
265 void changeStateIfWeOwnAllBuffers();
266
267 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
268};
269
270////////////////////////////////////////////////////////////////////////////////
271
272struct ACodec::IdleToLoadedState : public ACodec::BaseState {
273 IdleToLoadedState(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
281private:
282 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
283};
284
285////////////////////////////////////////////////////////////////////////////////
286
287struct ACodec::ErrorState : public ACodec::BaseState {
288 ErrorState(ACodec *codec);
289
290protected:
291 virtual bool onMessageReceived(const sp<AMessage> &msg);
292 virtual void stateEntered();
293
294 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
295
296private:
297 DISALLOW_EVIL_CONSTRUCTORS(ErrorState);
298};
299
300////////////////////////////////////////////////////////////////////////////////
301
302struct ACodec::FlushingState : public ACodec::BaseState {
303 FlushingState(ACodec *codec);
304
305protected:
306 virtual bool onMessageReceived(const sp<AMessage> &msg);
307 virtual void stateEntered();
308
309 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
310
311 virtual void onOutputBufferDrained(const sp<AMessage> &msg);
312 virtual void onInputBufferFilled(const sp<AMessage> &msg);
313
314private:
315 bool mFlushComplete[2];
316
317 void changeStateIfWeOwnAllBuffers();
318
319 DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
320};
321
322////////////////////////////////////////////////////////////////////////////////
323
324ACodec::ACodec()
Andreas Huber7caa1302011-01-10 10:38:31 -0800325 : mNode(NULL),
326 mSentFormat(false) {
Andreas Hubera1587462010-12-15 15:17:42 -0800327 mUninitializedState = new UninitializedState(this);
328 mLoadedToIdleState = new LoadedToIdleState(this);
329 mIdleToExecutingState = new IdleToExecutingState(this);
330 mExecutingState = new ExecutingState(this);
331
332 mOutputPortSettingsChangedState =
333 new OutputPortSettingsChangedState(this);
334
335 mExecutingToIdleState = new ExecutingToIdleState(this);
336 mIdleToLoadedState = new IdleToLoadedState(this);
337 mErrorState = new ErrorState(this);
338 mFlushingState = new FlushingState(this);
339
340 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
341
342 changeState(mUninitializedState);
343}
344
345ACodec::~ACodec() {
346}
347
348void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
349 mNotify = msg;
350}
351
352void ACodec::initiateSetup(const sp<AMessage> &msg) {
353 msg->setWhat(kWhatSetup);
354 msg->setTarget(id());
355 msg->post();
356}
357
358void ACodec::signalFlush() {
359 (new AMessage(kWhatFlush, id()))->post();
360}
361
362void ACodec::signalResume() {
363 (new AMessage(kWhatResume, id()))->post();
364}
365
366void ACodec::initiateShutdown() {
367 (new AMessage(kWhatShutdown, id()))->post();
368}
369
370status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
371 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
372
373 CHECK(mDealer[portIndex] == NULL);
374 CHECK(mBuffers[portIndex].isEmpty());
375
376 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
377 return allocateOutputBuffersFromNativeWindow();
378 }
379
380 OMX_PARAM_PORTDEFINITIONTYPE def;
381 InitOMXParams(&def);
382 def.nPortIndex = portIndex;
383
384 status_t err = mOMX->getParameter(
385 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
386
387 if (err != OK) {
388 return err;
389 }
390
391 LOGV("[%s] Allocating %lu buffers of size %lu on %s port",
392 mComponentName.c_str(),
393 def.nBufferCountActual, def.nBufferSize,
394 portIndex == kPortIndexInput ? "input" : "output");
395
396 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
397 mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
398
399 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
400 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
401 CHECK(mem.get() != NULL);
402
403 IOMX::buffer_id buffer;
404#if 0
405 err = mOMX->allocateBufferWithBackup(mNode, portIndex, mem, &buffer);
406#else
407 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
408#endif
409
410 if (err != OK) {
411 return err;
412 }
413
414 BufferInfo info;
415 info.mBufferID = buffer;
416 info.mStatus = BufferInfo::OWNED_BY_US;
417 info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
418 mBuffers[portIndex].push(info);
419 }
420
421 return OK;
422}
423
424status_t ACodec::allocateOutputBuffersFromNativeWindow() {
425 OMX_PARAM_PORTDEFINITIONTYPE def;
426 InitOMXParams(&def);
427 def.nPortIndex = kPortIndexOutput;
428
429 status_t err = mOMX->getParameter(
430 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
431
432 if (err != OK) {
433 return err;
434 }
435
436 err = native_window_set_buffers_geometry(
437 mNativeWindow.get(),
438 def.format.video.nFrameWidth,
439 def.format.video.nFrameHeight,
440 def.format.video.eColorFormat);
441
442 if (err != 0) {
443 LOGE("native_window_set_buffers_geometry failed: %s (%d)",
444 strerror(-err), -err);
445 return err;
446 }
447
Andreas Hubera1587462010-12-15 15:17:42 -0800448 // Set up the native window.
Jamie Gennis94c59802011-02-24 12:48:17 -0800449 OMX_U32 usage = 0;
450 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
451 if (err != 0) {
452 LOGW("querying usage flags from OMX IL component failed: %d", err);
453 // XXX: Currently this error is logged, but not fatal.
454 usage = 0;
455 }
456
Andreas Hubera1587462010-12-15 15:17:42 -0800457 err = native_window_set_usage(
458 mNativeWindow.get(),
Jamie Gennis94c59802011-02-24 12:48:17 -0800459 usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
Andreas Hubera1587462010-12-15 15:17:42 -0800460
461 if (err != 0) {
462 LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
463 return err;
464 }
465
Jamie Gennis01951fd2011-02-27 15:10:34 -0800466 int minUndequeuedBufs = 0;
467 err = mNativeWindow->query(
468 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
469 &minUndequeuedBufs);
470
471 if (err != 0) {
472 LOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
473 strerror(-err), -err);
474 return err;
475 }
476
477 // XXX: Is this the right logic to use? It's not clear to me what the OMX
478 // buffer counts refer to - how do they account for the renderer holding on
479 // to buffers?
480 if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
481 OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
482 def.nBufferCountActual = newBufferCount;
483 err = mOMX->setParameter(
484 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
485
486 if (err != OK) {
487 LOGE("[%s] setting nBufferCountActual to %lu failed: %d",
488 mComponentName.c_str(), newBufferCount, err);
489 return err;
490 }
491 }
492
Andreas Hubera1587462010-12-15 15:17:42 -0800493 err = native_window_set_buffer_count(
494 mNativeWindow.get(), def.nBufferCountActual);
495
496 if (err != 0) {
497 LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
498 -err);
499 return err;
500 }
501
Andreas Hubera1587462010-12-15 15:17:42 -0800502 LOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
503 "output port",
504 mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize);
505
506 // Dequeue buffers and send them to OMX
Jamie Gennis42024642011-02-22 18:33:06 -0800507 for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
Iliyan Malchevb2a153a2011-05-01 11:33:26 -0700508 ANativeWindowBuffer *buf;
Andreas Hubera1587462010-12-15 15:17:42 -0800509 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
510 if (err != 0) {
511 LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
512 break;
513 }
514
515 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
Andreas Hubera1587462010-12-15 15:17:42 -0800516 BufferInfo info;
Andreas Hubera1587462010-12-15 15:17:42 -0800517 info.mStatus = BufferInfo::OWNED_BY_US;
518 info.mData = new ABuffer(0);
519 info.mGraphicBuffer = graphicBuffer;
520 mBuffers[kPortIndexOutput].push(info);
Jamie Gennis42024642011-02-22 18:33:06 -0800521
522 IOMX::buffer_id bufferId;
523 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
524 &bufferId);
525 if (err != 0) {
526 LOGE("registering GraphicBuffer %lu with OMX IL component failed: "
527 "%d", i, err);
528 break;
529 }
530
531 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
532
533 LOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)",
534 mComponentName.c_str(),
535 bufferId, graphicBuffer.get());
Andreas Hubera1587462010-12-15 15:17:42 -0800536 }
537
538 OMX_U32 cancelStart;
539 OMX_U32 cancelEnd;
540
541 if (err != 0) {
542 // If an error occurred while dequeuing we need to cancel any buffers
543 // that were dequeued.
544 cancelStart = 0;
Jamie Gennis42024642011-02-22 18:33:06 -0800545 cancelEnd = mBuffers[kPortIndexOutput].size();
Andreas Hubera1587462010-12-15 15:17:42 -0800546 } else {
547 // Return the last two buffers to the native window.
Jamie Gennis01951fd2011-02-27 15:10:34 -0800548 cancelStart = def.nBufferCountActual - minUndequeuedBufs;
Andreas Hubera1587462010-12-15 15:17:42 -0800549 cancelEnd = def.nBufferCountActual;
550 }
551
552 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
553 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
554 cancelBufferToNativeWindow(info);
555 }
556
557 return err;
558}
559
560status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
561 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
562
563 LOGV("[%s] Calling cancelBuffer on buffer %p",
564 mComponentName.c_str(), info->mBufferID);
565
566 int err = mNativeWindow->cancelBuffer(
567 mNativeWindow.get(), info->mGraphicBuffer.get());
568
569 CHECK_EQ(err, 0);
570
571 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
572
573 return OK;
574}
575
576ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
Iliyan Malchevb2a153a2011-05-01 11:33:26 -0700577 ANativeWindowBuffer *buf;
Andreas Hubera1587462010-12-15 15:17:42 -0800578 CHECK_EQ(mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf), 0);
579
580 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
581 BufferInfo *info =
582 &mBuffers[kPortIndexOutput].editItemAt(i);
583
584 if (info->mGraphicBuffer->handle == buf->handle) {
585 CHECK_EQ((int)info->mStatus,
586 (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
587
588 info->mStatus = BufferInfo::OWNED_BY_US;
589
590 return info;
591 }
592 }
593
594 TRESPASS();
595
596 return NULL;
597}
598
599status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
600 for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
601 CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
602 }
603
604 mDealer[portIndex].clear();
605
606 return OK;
607}
608
Andreas Huber6760f982011-02-04 10:12:26 -0800609status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
Andreas Hubera1587462010-12-15 15:17:42 -0800610 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
611 BufferInfo *info =
612 &mBuffers[kPortIndexOutput].editItemAt(i);
613
Andreas Huber6760f982011-02-04 10:12:26 -0800614 if (info->mStatus !=
615 BufferInfo::OWNED_BY_COMPONENT) {
616 // We shouldn't have sent out any buffers to the client at this
617 // point.
618 CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
619
Andreas Hubera1587462010-12-15 15:17:42 -0800620 CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
621 }
622 }
623
624 return OK;
625}
626
627status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
628 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
629
630 CHECK(info->mStatus == BufferInfo::OWNED_BY_US
631 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
632
633 if (portIndex == kPortIndexOutput && mNativeWindow != NULL
634 && info->mStatus == BufferInfo::OWNED_BY_US) {
635 CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
636 }
637
638 CHECK_EQ(mOMX->freeBuffer(
639 mNode, portIndex, info->mBufferID),
640 (status_t)OK);
641
642 mBuffers[portIndex].removeAt(i);
643
644 return OK;
645}
646
647ACodec::BufferInfo *ACodec::findBufferByID(
648 uint32_t portIndex, IOMX::buffer_id bufferID,
649 ssize_t *index) {
650 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
651 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
652
653 if (info->mBufferID == bufferID) {
654 if (index != NULL) {
655 *index = i;
656 }
657 return info;
658 }
659 }
660
661 TRESPASS();
662
663 return NULL;
664}
665
666void ACodec::setComponentRole(
667 bool isEncoder, const char *mime) {
668 struct MimeToRole {
669 const char *mime;
670 const char *decoderRole;
671 const char *encoderRole;
672 };
673
674 static const MimeToRole kMimeToRole[] = {
675 { MEDIA_MIMETYPE_AUDIO_MPEG,
676 "audio_decoder.mp3", "audio_encoder.mp3" },
677 { MEDIA_MIMETYPE_AUDIO_AMR_NB,
678 "audio_decoder.amrnb", "audio_encoder.amrnb" },
679 { MEDIA_MIMETYPE_AUDIO_AMR_WB,
680 "audio_decoder.amrwb", "audio_encoder.amrwb" },
681 { MEDIA_MIMETYPE_AUDIO_AAC,
682 "audio_decoder.aac", "audio_encoder.aac" },
683 { MEDIA_MIMETYPE_VIDEO_AVC,
684 "video_decoder.avc", "video_encoder.avc" },
685 { MEDIA_MIMETYPE_VIDEO_MPEG4,
686 "video_decoder.mpeg4", "video_encoder.mpeg4" },
687 { MEDIA_MIMETYPE_VIDEO_H263,
688 "video_decoder.h263", "video_encoder.h263" },
689 };
690
691 static const size_t kNumMimeToRole =
692 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
693
694 size_t i;
695 for (i = 0; i < kNumMimeToRole; ++i) {
696 if (!strcasecmp(mime, kMimeToRole[i].mime)) {
697 break;
698 }
699 }
700
701 if (i == kNumMimeToRole) {
702 return;
703 }
704
705 const char *role =
706 isEncoder ? kMimeToRole[i].encoderRole
707 : kMimeToRole[i].decoderRole;
708
709 if (role != NULL) {
710 OMX_PARAM_COMPONENTROLETYPE roleParams;
711 InitOMXParams(&roleParams);
712
713 strncpy((char *)roleParams.cRole,
714 role, OMX_MAX_STRINGNAME_SIZE - 1);
715
716 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
717
718 status_t err = mOMX->setParameter(
719 mNode, OMX_IndexParamStandardComponentRole,
720 &roleParams, sizeof(roleParams));
721
722 if (err != OK) {
723 LOGW("[%s] Failed to set standard component role '%s'.",
724 mComponentName.c_str(), role);
725 }
726 }
727}
728
729void ACodec::configureCodec(
730 const char *mime, const sp<AMessage> &msg) {
731 setComponentRole(false /* isEncoder */, mime);
732
733 if (!strncasecmp(mime, "video/", 6)) {
734 int32_t width, height;
735 CHECK(msg->findInt32("width", &width));
736 CHECK(msg->findInt32("height", &height));
737
738 CHECK_EQ(setupVideoDecoder(mime, width, height),
739 (status_t)OK);
740 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
741 int32_t numChannels, sampleRate;
742 CHECK(msg->findInt32("channel-count", &numChannels));
743 CHECK(msg->findInt32("sample-rate", &sampleRate));
744
745 CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK);
746 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
747 } else {
748 TRESPASS();
749 }
750
751 int32_t maxInputSize;
752 if (msg->findInt32("max-input-size", &maxInputSize)) {
753 CHECK_EQ(setMinBufferSize(kPortIndexInput, (size_t)maxInputSize),
754 (status_t)OK);
755 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
756 CHECK_EQ(setMinBufferSize(kPortIndexInput, 8192), // XXX
757 (status_t)OK);
758 }
759}
760
761status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
762 OMX_PARAM_PORTDEFINITIONTYPE def;
763 InitOMXParams(&def);
764 def.nPortIndex = portIndex;
765
766 status_t err = mOMX->getParameter(
767 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
768
769 if (err != OK) {
770 return err;
771 }
772
773 if (def.nBufferSize >= size) {
774 return OK;
775 }
776
777 def.nBufferSize = size;
778
779 err = mOMX->setParameter(
780 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
781
782 if (err != OK) {
783 return err;
784 }
785
786 err = mOMX->getParameter(
787 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
788
789 if (err != OK) {
790 return err;
791 }
792
793 CHECK(def.nBufferSize >= size);
794
795 return OK;
796}
797
798status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) {
799 OMX_AUDIO_PARAM_AACPROFILETYPE profile;
800 InitOMXParams(&profile);
801 profile.nPortIndex = kPortIndexInput;
802
803 status_t err = mOMX->getParameter(
804 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
805
806 if (err != OK) {
807 return err;
808 }
809
810 profile.nChannels = numChannels;
811 profile.nSampleRate = sampleRate;
812 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
813
814 err = mOMX->setParameter(
815 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
816
817 return err;
818}
819
820status_t ACodec::setVideoPortFormatType(
821 OMX_U32 portIndex,
822 OMX_VIDEO_CODINGTYPE compressionFormat,
823 OMX_COLOR_FORMATTYPE colorFormat) {
824 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
825 InitOMXParams(&format);
826 format.nPortIndex = portIndex;
827 format.nIndex = 0;
828 bool found = false;
829
830 OMX_U32 index = 0;
831 for (;;) {
832 format.nIndex = index;
833 status_t err = mOMX->getParameter(
834 mNode, OMX_IndexParamVideoPortFormat,
835 &format, sizeof(format));
836
837 if (err != OK) {
838 return err;
839 }
840
841 // The following assertion is violated by TI's video decoder.
842 // CHECK_EQ(format.nIndex, index);
843
844 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
845 if (portIndex == kPortIndexInput
846 && colorFormat == format.eColorFormat) {
847 // eCompressionFormat does not seem right.
848 found = true;
849 break;
850 }
851 if (portIndex == kPortIndexOutput
852 && compressionFormat == format.eCompressionFormat) {
853 // eColorFormat does not seem right.
854 found = true;
855 break;
856 }
857 }
858
859 if (format.eCompressionFormat == compressionFormat
860 && format.eColorFormat == colorFormat) {
861 found = true;
862 break;
863 }
864
865 ++index;
866 }
867
868 if (!found) {
869 return UNKNOWN_ERROR;
870 }
871
872 status_t err = mOMX->setParameter(
873 mNode, OMX_IndexParamVideoPortFormat,
874 &format, sizeof(format));
875
876 return err;
877}
878
879status_t ACodec::setSupportedOutputFormat() {
880 OMX_VIDEO_PARAM_PORTFORMATTYPE format;
881 InitOMXParams(&format);
882 format.nPortIndex = kPortIndexOutput;
883 format.nIndex = 0;
884
885 status_t err = mOMX->getParameter(
886 mNode, OMX_IndexParamVideoPortFormat,
887 &format, sizeof(format));
888 CHECK_EQ(err, (status_t)OK);
889 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
890
891 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
892
893 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
894 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
895 || format.eColorFormat == OMX_COLOR_FormatCbYCrY
896 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
897
898 return mOMX->setParameter(
899 mNode, OMX_IndexParamVideoPortFormat,
900 &format, sizeof(format));
901}
902
903status_t ACodec::setupVideoDecoder(
904 const char *mime, int32_t width, int32_t height) {
905 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
906 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
907 compressionFormat = OMX_VIDEO_CodingAVC;
908 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
909 compressionFormat = OMX_VIDEO_CodingMPEG4;
910 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
911 compressionFormat = OMX_VIDEO_CodingH263;
912 } else {
913 TRESPASS();
914 }
915
916 status_t err = setVideoPortFormatType(
917 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
918
919 if (err != OK) {
920 return err;
921 }
922
923 err = setSupportedOutputFormat();
924
925 if (err != OK) {
926 return err;
927 }
928
929 err = setVideoFormatOnPort(
930 kPortIndexInput, width, height, compressionFormat);
931
932 if (err != OK) {
933 return err;
934 }
935
936 err = setVideoFormatOnPort(
937 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
938
939 if (err != OK) {
940 return err;
941 }
942
943 return OK;
944}
945
946status_t ACodec::setVideoFormatOnPort(
947 OMX_U32 portIndex,
948 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
949 OMX_PARAM_PORTDEFINITIONTYPE def;
950 InitOMXParams(&def);
951 def.nPortIndex = portIndex;
952
953 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
954
955 status_t err = mOMX->getParameter(
956 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
957
958 CHECK_EQ(err, (status_t)OK);
959
960 if (portIndex == kPortIndexInput) {
961 // XXX Need a (much) better heuristic to compute input buffer sizes.
962 const size_t X = 64 * 1024;
963 if (def.nBufferSize < X) {
964 def.nBufferSize = X;
965 }
966 }
967
968 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
969
970 video_def->nFrameWidth = width;
971 video_def->nFrameHeight = height;
972
973 if (portIndex == kPortIndexInput) {
974 video_def->eCompressionFormat = compressionFormat;
975 video_def->eColorFormat = OMX_COLOR_FormatUnused;
976 }
977
978 err = mOMX->setParameter(
979 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
980
981 return err;
982}
983
984status_t ACodec::initNativeWindow() {
985 if (mNativeWindow != NULL) {
986 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
987 }
988
989 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
990 return OK;
991}
992
993bool ACodec::allYourBuffersAreBelongToUs(
994 OMX_U32 portIndex) {
995 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
996 BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
997
998 if (info->mStatus != BufferInfo::OWNED_BY_US
999 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1000 LOGV("[%s] Buffer %p on port %ld still has status %d",
1001 mComponentName.c_str(),
1002 info->mBufferID, portIndex, info->mStatus);
1003 return false;
1004 }
1005 }
1006
1007 return true;
1008}
1009
1010bool ACodec::allYourBuffersAreBelongToUs() {
1011 return allYourBuffersAreBelongToUs(kPortIndexInput)
1012 && allYourBuffersAreBelongToUs(kPortIndexOutput);
1013}
1014
1015void ACodec::deferMessage(const sp<AMessage> &msg) {
1016 bool wasEmptyBefore = mDeferredQueue.empty();
1017 mDeferredQueue.push_back(msg);
1018}
1019
1020void ACodec::processDeferredMessages() {
1021 List<sp<AMessage> > queue = mDeferredQueue;
1022 mDeferredQueue.clear();
1023
1024 List<sp<AMessage> >::iterator it = queue.begin();
1025 while (it != queue.end()) {
1026 onMessageReceived(*it++);
1027 }
1028}
1029
Andreas Huber7caa1302011-01-10 10:38:31 -08001030void ACodec::sendFormatChange() {
1031 sp<AMessage> notify = mNotify->dup();
1032 notify->setInt32("what", kWhatOutputFormatChanged);
1033
1034 OMX_PARAM_PORTDEFINITIONTYPE def;
1035 InitOMXParams(&def);
1036 def.nPortIndex = kPortIndexOutput;
1037
1038 CHECK_EQ(mOMX->getParameter(
1039 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
1040 (status_t)OK);
1041
1042 CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
1043
1044 switch (def.eDomain) {
1045 case OMX_PortDomainVideo:
1046 {
1047 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
1048
1049 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
1050 notify->setInt32("width", videoDef->nFrameWidth);
1051 notify->setInt32("height", videoDef->nFrameHeight);
1052
1053 OMX_CONFIG_RECTTYPE rect;
1054 InitOMXParams(&rect);
1055 rect.nPortIndex = kPortIndexOutput;
1056
1057 if (mOMX->getConfig(
1058 mNode, OMX_IndexConfigCommonOutputCrop,
1059 &rect, sizeof(rect)) != OK) {
1060 rect.nLeft = 0;
1061 rect.nTop = 0;
1062 rect.nWidth = videoDef->nFrameWidth;
1063 rect.nHeight = videoDef->nFrameHeight;
1064 }
1065
1066 CHECK_GE(rect.nLeft, 0);
1067 CHECK_GE(rect.nTop, 0);
1068 CHECK_GE(rect.nWidth, 0u);
1069 CHECK_GE(rect.nHeight, 0u);
1070 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
1071 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
1072
1073 notify->setRect(
1074 "crop",
1075 rect.nLeft,
1076 rect.nTop,
1077 rect.nLeft + rect.nWidth - 1,
1078 rect.nTop + rect.nHeight - 1);
1079
1080 if (mNativeWindow != NULL) {
1081 android_native_rect_t crop;
1082 crop.left = rect.nLeft;
1083 crop.top = rect.nTop;
Andreas Huberb13c4a92011-03-29 10:00:20 -07001084 crop.right = rect.nLeft + rect.nWidth;
1085 crop.bottom = rect.nTop + rect.nHeight;
Andreas Huber7caa1302011-01-10 10:38:31 -08001086
1087 CHECK_EQ(0, native_window_set_crop(
1088 mNativeWindow.get(), &crop));
1089 }
1090 break;
1091 }
1092
1093 case OMX_PortDomainAudio:
1094 {
1095 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
1096 CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
1097
1098 OMX_AUDIO_PARAM_PCMMODETYPE params;
1099 InitOMXParams(&params);
1100 params.nPortIndex = kPortIndexOutput;
1101
1102 CHECK_EQ(mOMX->getParameter(
1103 mNode, OMX_IndexParamAudioPcm,
1104 &params, sizeof(params)),
1105 (status_t)OK);
1106
1107 CHECK(params.nChannels == 1 || params.bInterleaved);
1108 CHECK_EQ(params.nBitPerSample, 16u);
1109 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
1110 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
1111
1112 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
1113 notify->setInt32("channel-count", params.nChannels);
1114 notify->setInt32("sample-rate", params.nSamplingRate);
1115 break;
1116 }
1117
1118 default:
1119 TRESPASS();
1120 }
1121
1122 notify->post();
1123
1124 mSentFormat = true;
1125}
1126
Andreas Hubera1587462010-12-15 15:17:42 -08001127////////////////////////////////////////////////////////////////////////////////
1128
1129ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
1130 : AState(parentState),
1131 mCodec(codec) {
1132}
1133
1134ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
1135 return KEEP_BUFFERS;
1136}
1137
1138bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
1139 switch (msg->what()) {
1140 case kWhatInputBufferFilled:
1141 {
1142 onInputBufferFilled(msg);
1143 break;
1144 }
1145
1146 case kWhatOutputBufferDrained:
1147 {
1148 onOutputBufferDrained(msg);
1149 break;
1150 }
1151
1152 case ACodec::kWhatOMXMessage:
1153 {
1154 return onOMXMessage(msg);
1155 }
1156
1157 default:
1158 return false;
1159 }
1160
1161 return true;
1162}
1163
1164bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
1165 int32_t type;
1166 CHECK(msg->findInt32("type", &type));
1167
1168 IOMX::node_id nodeID;
1169 CHECK(msg->findPointer("node", &nodeID));
1170 CHECK_EQ(nodeID, mCodec->mNode);
1171
1172 switch (type) {
1173 case omx_message::EVENT:
1174 {
1175 int32_t event, data1, data2;
1176 CHECK(msg->findInt32("event", &event));
1177 CHECK(msg->findInt32("data1", &data1));
1178 CHECK(msg->findInt32("data2", &data2));
1179
1180 return onOMXEvent(
1181 static_cast<OMX_EVENTTYPE>(event),
1182 static_cast<OMX_U32>(data1),
1183 static_cast<OMX_U32>(data2));
1184 }
1185
1186 case omx_message::EMPTY_BUFFER_DONE:
1187 {
1188 IOMX::buffer_id bufferID;
1189 CHECK(msg->findPointer("buffer", &bufferID));
1190
1191 return onOMXEmptyBufferDone(bufferID);
1192 }
1193
1194 case omx_message::FILL_BUFFER_DONE:
1195 {
1196 IOMX::buffer_id bufferID;
1197 CHECK(msg->findPointer("buffer", &bufferID));
1198
1199 int32_t rangeOffset, rangeLength, flags;
1200 int64_t timeUs;
1201 void *platformPrivate;
1202 void *dataPtr;
1203
1204 CHECK(msg->findInt32("range_offset", &rangeOffset));
1205 CHECK(msg->findInt32("range_length", &rangeLength));
1206 CHECK(msg->findInt32("flags", &flags));
1207 CHECK(msg->findInt64("timestamp", &timeUs));
1208 CHECK(msg->findPointer("platform_private", &platformPrivate));
1209 CHECK(msg->findPointer("data_ptr", &dataPtr));
1210
1211 return onOMXFillBufferDone(
1212 bufferID,
1213 (size_t)rangeOffset, (size_t)rangeLength,
1214 (OMX_U32)flags,
1215 timeUs,
1216 platformPrivate,
1217 dataPtr);
1218 }
1219
1220 default:
1221 TRESPASS();
1222 break;
1223 }
1224}
1225
1226bool ACodec::BaseState::onOMXEvent(
1227 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1228 if (event != OMX_EventError) {
Andreas Huber54e66492010-12-23 10:27:40 -08001229 LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
Andreas Hubera1587462010-12-15 15:17:42 -08001230 mCodec->mComponentName.c_str(), event, data1, data2);
1231
1232 return false;
1233 }
1234
1235 LOGE("[%s] ERROR(0x%08lx, 0x%08lx)",
1236 mCodec->mComponentName.c_str(), data1, data2);
1237
1238 mCodec->changeState(mCodec->mErrorState);
1239
1240 return true;
1241}
1242
1243bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
Andreas Huber6760f982011-02-04 10:12:26 -08001244 LOGV("[%s] onOMXEmptyBufferDone %p",
1245 mCodec->mComponentName.c_str(), bufferID);
1246
Andreas Hubera1587462010-12-15 15:17:42 -08001247 BufferInfo *info =
1248 mCodec->findBufferByID(kPortIndexInput, bufferID);
1249
1250 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1251 info->mStatus = BufferInfo::OWNED_BY_US;
1252
1253 PortMode mode = getPortMode(kPortIndexInput);
1254
1255 switch (mode) {
1256 case KEEP_BUFFERS:
1257 break;
1258
1259 case RESUBMIT_BUFFERS:
1260 postFillThisBuffer(info);
1261 break;
1262
1263 default:
1264 {
1265 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1266 TRESPASS(); // Not currently used
1267 break;
1268 }
1269 }
1270
1271 return true;
1272}
1273
1274void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
1275 if (mCodec->mPortEOS[kPortIndexInput]) {
1276 return;
1277 }
1278
1279 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1280
1281 sp<AMessage> notify = mCodec->mNotify->dup();
1282 notify->setInt32("what", ACodec::kWhatFillThisBuffer);
1283 notify->setPointer("buffer-id", info->mBufferID);
1284
1285 info->mData->meta()->clear();
1286 notify->setObject("buffer", info->mData);
1287
1288 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
1289 reply->setPointer("buffer-id", info->mBufferID);
1290
1291 notify->setMessage("reply", reply);
1292
1293 notify->post();
1294
1295 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
1296}
1297
1298void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
1299 IOMX::buffer_id bufferID;
1300 CHECK(msg->findPointer("buffer-id", &bufferID));
1301
1302 sp<RefBase> obj;
1303 int32_t err = OK;
1304 if (!msg->findObject("buffer", &obj)) {
1305 CHECK(msg->findInt32("err", &err));
1306
Andreas Huber41c3f742010-12-21 10:22:33 -08001307 LOGV("[%s] saw error %d instead of an input buffer",
1308 mCodec->mComponentName.c_str(), err);
1309
Andreas Hubera1587462010-12-15 15:17:42 -08001310 obj.clear();
1311 }
1312
1313 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
1314
1315 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
1316 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
1317
1318 info->mStatus = BufferInfo::OWNED_BY_US;
1319
1320 PortMode mode = getPortMode(kPortIndexInput);
1321
1322 switch (mode) {
1323 case KEEP_BUFFERS:
1324 {
1325 if (buffer == NULL) {
1326 mCodec->mPortEOS[kPortIndexInput] = true;
1327 }
1328 break;
1329 }
1330
1331 case RESUBMIT_BUFFERS:
1332 {
1333 if (buffer != NULL) {
1334 CHECK(!mCodec->mPortEOS[kPortIndexInput]);
1335
1336 int64_t timeUs;
1337 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1338
1339 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1340
1341 int32_t isCSD;
1342 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
1343 flags |= OMX_BUFFERFLAG_CODECCONFIG;
1344 }
1345
1346 if (buffer != info->mData) {
Andreas Huber6760f982011-02-04 10:12:26 -08001347 if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
Andreas Hubera1587462010-12-15 15:17:42 -08001348 LOGV("[%s] Needs to copy input data.",
1349 mCodec->mComponentName.c_str());
1350 }
1351
1352 CHECK_LE(buffer->size(), info->mData->capacity());
1353 memcpy(info->mData->data(), buffer->data(), buffer->size());
1354 }
1355
Andreas Huber6760f982011-02-04 10:12:26 -08001356 LOGV("[%s] calling emptyBuffer %p",
1357 mCodec->mComponentName.c_str(), bufferID);
1358
Andreas Hubera1587462010-12-15 15:17:42 -08001359 CHECK_EQ(mCodec->mOMX->emptyBuffer(
1360 mCodec->mNode,
1361 bufferID,
1362 0,
1363 buffer->size(),
1364 flags,
1365 timeUs),
1366 (status_t)OK);
1367
1368 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1369
1370 getMoreInputDataIfPossible();
1371 } else if (!mCodec->mPortEOS[kPortIndexInput]) {
1372 LOGV("[%s] Signalling EOS on the input port",
1373 mCodec->mComponentName.c_str());
1374
Andreas Huber6760f982011-02-04 10:12:26 -08001375 LOGV("[%s] calling emptyBuffer %p",
1376 mCodec->mComponentName.c_str(), bufferID);
1377
Andreas Hubera1587462010-12-15 15:17:42 -08001378 CHECK_EQ(mCodec->mOMX->emptyBuffer(
1379 mCodec->mNode,
1380 bufferID,
1381 0,
1382 0,
1383 OMX_BUFFERFLAG_EOS,
1384 0),
1385 (status_t)OK);
1386
1387 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1388
1389 mCodec->mPortEOS[kPortIndexInput] = true;
1390 }
1391 break;
1392
1393 default:
1394 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1395 break;
1396 }
1397 }
1398}
1399
1400void ACodec::BaseState::getMoreInputDataIfPossible() {
1401 if (mCodec->mPortEOS[kPortIndexInput]) {
1402 return;
1403 }
1404
1405 BufferInfo *eligible = NULL;
1406
1407 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
1408 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
1409
1410#if 0
1411 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
1412 // There's already a "read" pending.
1413 return;
1414 }
1415#endif
1416
1417 if (info->mStatus == BufferInfo::OWNED_BY_US) {
1418 eligible = info;
1419 }
1420 }
1421
1422 if (eligible == NULL) {
1423 return;
1424 }
1425
1426 postFillThisBuffer(eligible);
1427}
1428
1429bool ACodec::BaseState::onOMXFillBufferDone(
1430 IOMX::buffer_id bufferID,
1431 size_t rangeOffset, size_t rangeLength,
1432 OMX_U32 flags,
1433 int64_t timeUs,
1434 void *platformPrivate,
1435 void *dataPtr) {
Andreas Huber6760f982011-02-04 10:12:26 -08001436 LOGV("[%s] onOMXFillBufferDone %p",
1437 mCodec->mComponentName.c_str(), bufferID);
1438
Andreas Hubera1587462010-12-15 15:17:42 -08001439 ssize_t index;
1440 BufferInfo *info =
1441 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1442
1443 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1444
1445 info->mStatus = BufferInfo::OWNED_BY_US;
1446
1447 PortMode mode = getPortMode(kPortIndexOutput);
1448
1449 switch (mode) {
1450 case KEEP_BUFFERS:
1451 break;
1452
1453 case RESUBMIT_BUFFERS:
1454 {
1455 if (rangeLength == 0) {
1456 if (!(flags & OMX_BUFFERFLAG_EOS)) {
Andreas Huber6760f982011-02-04 10:12:26 -08001457 LOGV("[%s] calling fillBuffer %p",
1458 mCodec->mComponentName.c_str(), info->mBufferID);
1459
Andreas Hubera1587462010-12-15 15:17:42 -08001460 CHECK_EQ(mCodec->mOMX->fillBuffer(
1461 mCodec->mNode, info->mBufferID),
1462 (status_t)OK);
1463
1464 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1465 }
1466 } else {
Andreas Huber7caa1302011-01-10 10:38:31 -08001467 if (!mCodec->mSentFormat) {
1468 mCodec->sendFormatChange();
1469 }
1470
Andreas Hubera1587462010-12-15 15:17:42 -08001471 if (mCodec->mNativeWindow == NULL) {
1472 info->mData->setRange(rangeOffset, rangeLength);
1473 }
1474
1475 info->mData->meta()->setInt64("timeUs", timeUs);
1476
1477 sp<AMessage> notify = mCodec->mNotify->dup();
1478 notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
1479 notify->setPointer("buffer-id", info->mBufferID);
1480 notify->setObject("buffer", info->mData);
1481
1482 sp<AMessage> reply =
1483 new AMessage(kWhatOutputBufferDrained, mCodec->id());
1484
1485 reply->setPointer("buffer-id", info->mBufferID);
1486
1487 notify->setMessage("reply", reply);
1488
1489 notify->post();
1490
1491 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
1492 }
1493
1494 if (flags & OMX_BUFFERFLAG_EOS) {
1495 sp<AMessage> notify = mCodec->mNotify->dup();
1496 notify->setInt32("what", ACodec::kWhatEOS);
1497 notify->post();
1498
1499 mCodec->mPortEOS[kPortIndexOutput] = true;
1500 }
1501 break;
1502 }
1503
1504 default:
1505 {
1506 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1507
1508 CHECK_EQ((status_t)OK,
1509 mCodec->freeBuffer(kPortIndexOutput, index));
1510 break;
1511 }
1512 }
1513
1514 return true;
1515}
1516
1517void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
1518 IOMX::buffer_id bufferID;
1519 CHECK(msg->findPointer("buffer-id", &bufferID));
1520
1521 ssize_t index;
1522 BufferInfo *info =
1523 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1524 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
1525
1526 int32_t render;
1527 if (mCodec->mNativeWindow != NULL
1528 && msg->findInt32("render", &render) && render != 0) {
1529 // The client wants this buffer to be rendered.
1530
1531 CHECK_EQ(mCodec->mNativeWindow->queueBuffer(
1532 mCodec->mNativeWindow.get(),
1533 info->mGraphicBuffer.get()),
1534 0);
1535
1536 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1537 } else {
1538 info->mStatus = BufferInfo::OWNED_BY_US;
1539 }
1540
1541 PortMode mode = getPortMode(kPortIndexOutput);
1542
1543 switch (mode) {
1544 case KEEP_BUFFERS:
1545 {
1546 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
1547
1548 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1549 // We cannot resubmit the buffer we just rendered, dequeue
1550 // the spare instead.
1551
1552 info = mCodec->dequeueBufferFromNativeWindow();
1553 }
1554 break;
1555 }
1556
1557 case RESUBMIT_BUFFERS:
1558 {
1559 if (!mCodec->mPortEOS[kPortIndexOutput]) {
1560 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1561 // We cannot resubmit the buffer we just rendered, dequeue
1562 // the spare instead.
1563
1564 info = mCodec->dequeueBufferFromNativeWindow();
1565 }
1566
Andreas Huber6760f982011-02-04 10:12:26 -08001567 LOGV("[%s] calling fillBuffer %p",
1568 mCodec->mComponentName.c_str(), info->mBufferID);
1569
Andreas Hubera1587462010-12-15 15:17:42 -08001570 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1571 (status_t)OK);
1572
1573 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1574 }
1575 break;
1576 }
1577
1578 default:
1579 {
1580 CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1581
1582 CHECK_EQ((status_t)OK,
1583 mCodec->freeBuffer(kPortIndexOutput, index));
1584 break;
1585 }
1586 }
1587}
1588
1589////////////////////////////////////////////////////////////////////////////////
1590
1591ACodec::UninitializedState::UninitializedState(ACodec *codec)
1592 : BaseState(codec) {
1593}
1594
1595bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
1596 bool handled = false;
1597
1598 switch (msg->what()) {
1599 case ACodec::kWhatSetup:
1600 {
1601 onSetup(msg);
1602
1603 handled = true;
1604 break;
1605 }
1606
1607 case ACodec::kWhatShutdown:
1608 {
1609 sp<AMessage> notify = mCodec->mNotify->dup();
1610 notify->setInt32("what", ACodec::kWhatShutdownCompleted);
1611 notify->post();
1612
1613 handled = true;
1614 }
1615
1616 case ACodec::kWhatFlush:
1617 {
1618 sp<AMessage> notify = mCodec->mNotify->dup();
1619 notify->setInt32("what", ACodec::kWhatFlushCompleted);
1620 notify->post();
1621
1622 handled = true;
1623 }
1624
1625 default:
1626 return BaseState::onMessageReceived(msg);
1627 }
1628
1629 return handled;
1630}
1631
1632void ACodec::UninitializedState::onSetup(
1633 const sp<AMessage> &msg) {
1634 OMXClient client;
1635 CHECK_EQ(client.connect(), (status_t)OK);
1636
1637 sp<IOMX> omx = client.interface();
1638
1639 AString mime;
1640 CHECK(msg->findString("mime", &mime));
1641
1642 AString componentName;
1643
1644 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
1645 componentName = "OMX.Nvidia.h264.decode";
1646 } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
Andreas Huber4b3913a2011-05-11 14:13:42 -07001647 componentName = "OMX.google.aac.decoder";
Andreas Hubera1587462010-12-15 15:17:42 -08001648 } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_MPEG)) {
1649 componentName = "OMX.Nvidia.mp3.decoder";
1650 } else {
1651 TRESPASS();
1652 }
1653
1654 sp<CodecObserver> observer = new CodecObserver;
1655
1656 IOMX::node_id node;
1657 CHECK_EQ(omx->allocateNode(componentName.c_str(), observer, &node),
1658 (status_t)OK);
1659
1660 sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
1661 observer->setNotificationMessage(notify);
1662
1663 mCodec->mComponentName = componentName;
1664 mCodec->mOMX = omx;
1665 mCodec->mNode = node;
1666
Andreas Huber6760f982011-02-04 10:12:26 -08001667 mCodec->mPortEOS[kPortIndexInput] =
1668 mCodec->mPortEOS[kPortIndexOutput] = false;
1669
Andreas Hubera1587462010-12-15 15:17:42 -08001670 mCodec->configureCodec(mime.c_str(), msg);
1671
1672 sp<RefBase> obj;
Glenn Kastencc562a32011-02-08 17:26:17 -08001673 if (msg->findObject("native-window", &obj)) {
1674 sp<NativeWindowWrapper> nativeWindow(
1675 static_cast<NativeWindowWrapper *>(obj.get()));
1676 CHECK(nativeWindow != NULL);
1677 mCodec->mNativeWindow = nativeWindow->getNativeWindow();
Andreas Hubera1587462010-12-15 15:17:42 -08001678 }
1679
1680 CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
1681
1682 CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle),
1683 (status_t)OK);
1684
1685 mCodec->changeState(mCodec->mLoadedToIdleState);
1686}
1687
1688////////////////////////////////////////////////////////////////////////////////
1689
1690ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
1691 : BaseState(codec) {
1692}
1693
1694void ACodec::LoadedToIdleState::stateEntered() {
Andreas Huber54e66492010-12-23 10:27:40 -08001695 LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08001696
1697 CHECK_EQ(allocateBuffers(), (status_t)OK);
1698}
1699
1700status_t ACodec::LoadedToIdleState::allocateBuffers() {
1701 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
1702
1703 if (err != OK) {
1704 return err;
1705 }
1706
1707 return mCodec->allocateBuffersOnPort(kPortIndexOutput);
1708}
1709
1710bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
1711 switch (msg->what()) {
1712 case kWhatShutdown:
1713 {
1714 mCodec->deferMessage(msg);
1715 return true;
1716 }
1717
1718 default:
1719 return BaseState::onMessageReceived(msg);
1720 }
1721}
1722
1723bool ACodec::LoadedToIdleState::onOMXEvent(
1724 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1725 switch (event) {
1726 case OMX_EventCmdComplete:
1727 {
1728 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1729 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
1730
1731 CHECK_EQ(mCodec->mOMX->sendCommand(
1732 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
1733 (status_t)OK);
1734
1735 mCodec->changeState(mCodec->mIdleToExecutingState);
1736
1737 return true;
1738 }
1739
1740 default:
1741 return BaseState::onOMXEvent(event, data1, data2);
1742 }
1743}
1744
1745////////////////////////////////////////////////////////////////////////////////
1746
1747ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
1748 : BaseState(codec) {
1749}
1750
1751void ACodec::IdleToExecutingState::stateEntered() {
Andreas Huber54e66492010-12-23 10:27:40 -08001752 LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08001753}
1754
1755bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1756 switch (msg->what()) {
1757 case kWhatShutdown:
1758 {
1759 mCodec->deferMessage(msg);
1760 return true;
1761 }
1762
1763 default:
1764 return BaseState::onMessageReceived(msg);
1765 }
1766}
1767
1768bool ACodec::IdleToExecutingState::onOMXEvent(
1769 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1770 switch (event) {
1771 case OMX_EventCmdComplete:
1772 {
1773 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1774 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
1775
1776 mCodec->mExecutingState->resume();
1777 mCodec->changeState(mCodec->mExecutingState);
1778
1779 return true;
1780 }
1781
1782 default:
1783 return BaseState::onOMXEvent(event, data1, data2);
1784 }
1785}
1786
1787////////////////////////////////////////////////////////////////////////////////
1788
1789ACodec::ExecutingState::ExecutingState(ACodec *codec)
Andreas Huber6760f982011-02-04 10:12:26 -08001790 : BaseState(codec),
1791 mActive(false) {
Andreas Hubera1587462010-12-15 15:17:42 -08001792}
1793
1794ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
1795 OMX_U32 portIndex) {
1796 return RESUBMIT_BUFFERS;
1797}
1798
1799void ACodec::ExecutingState::submitOutputBuffers() {
1800 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
1801 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
1802
1803 if (mCodec->mNativeWindow != NULL) {
1804 CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1805 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1806
1807 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1808 continue;
1809 }
1810
1811 status_t err = mCodec->mNativeWindow->lockBuffer(
1812 mCodec->mNativeWindow.get(),
1813 info->mGraphicBuffer.get());
1814 CHECK_EQ(err, (status_t)OK);
1815 } else {
1816 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1817 }
1818
Andreas Huber6760f982011-02-04 10:12:26 -08001819 LOGV("[%s] calling fillBuffer %p",
1820 mCodec->mComponentName.c_str(), info->mBufferID);
1821
Andreas Hubera1587462010-12-15 15:17:42 -08001822 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1823 (status_t)OK);
1824
1825 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1826 }
1827}
1828
1829void ACodec::ExecutingState::resume() {
Andreas Huber6760f982011-02-04 10:12:26 -08001830 if (mActive) {
1831 LOGV("[%s] We're already active, no need to resume.",
1832 mCodec->mComponentName.c_str());
1833
1834 return;
1835 }
1836
Andreas Hubera1587462010-12-15 15:17:42 -08001837 submitOutputBuffers();
1838
1839 // Post the first input buffer.
1840 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
1841 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
1842
1843 postFillThisBuffer(info);
Andreas Huber6760f982011-02-04 10:12:26 -08001844
1845 mActive = true;
Andreas Hubera1587462010-12-15 15:17:42 -08001846}
1847
1848void ACodec::ExecutingState::stateEntered() {
Andreas Huber54e66492010-12-23 10:27:40 -08001849 LOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08001850
1851 mCodec->processDeferredMessages();
1852}
1853
1854bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1855 bool handled = false;
1856
1857 switch (msg->what()) {
1858 case kWhatShutdown:
1859 {
Andreas Huber6760f982011-02-04 10:12:26 -08001860 mActive = false;
1861
Andreas Hubera1587462010-12-15 15:17:42 -08001862 CHECK_EQ(mCodec->mOMX->sendCommand(
1863 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
1864 (status_t)OK);
1865
1866 mCodec->changeState(mCodec->mExecutingToIdleState);
1867
1868 handled = true;
1869 break;
1870 }
1871
1872 case kWhatFlush:
1873 {
Andreas Huber6760f982011-02-04 10:12:26 -08001874 mActive = false;
1875
Andreas Hubera1587462010-12-15 15:17:42 -08001876 CHECK_EQ(mCodec->mOMX->sendCommand(
1877 mCodec->mNode, OMX_CommandFlush, OMX_ALL),
1878 (status_t)OK);
1879
1880 mCodec->changeState(mCodec->mFlushingState);
1881
1882 handled = true;
1883 break;
1884 }
1885
1886 case kWhatResume:
1887 {
1888 resume();
1889
1890 handled = true;
1891 break;
1892 }
1893
1894 default:
1895 handled = BaseState::onMessageReceived(msg);
1896 break;
1897 }
1898
1899 return handled;
1900}
1901
1902bool ACodec::ExecutingState::onOMXEvent(
1903 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1904 switch (event) {
1905 case OMX_EventPortSettingsChanged:
1906 {
1907 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
1908
Andreas Huber7caa1302011-01-10 10:38:31 -08001909 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
Andreas Hubera1587462010-12-15 15:17:42 -08001910 CHECK_EQ(mCodec->mOMX->sendCommand(
1911 mCodec->mNode,
1912 OMX_CommandPortDisable, kPortIndexOutput),
1913 (status_t)OK);
1914
Andreas Huber6760f982011-02-04 10:12:26 -08001915 mCodec->freeOutputBuffersNotOwnedByComponent();
Andreas Hubera1587462010-12-15 15:17:42 -08001916
1917 mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
Andreas Huber7caa1302011-01-10 10:38:31 -08001918 } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
1919 mCodec->mSentFormat = false;
Andreas Hubera1587462010-12-15 15:17:42 -08001920 } else {
1921 LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
1922 mCodec->mComponentName.c_str(), data2);
1923 }
1924
1925 return true;
1926 }
1927
1928 case OMX_EventBufferFlag:
1929 {
1930 return true;
1931 }
1932
1933 default:
1934 return BaseState::onOMXEvent(event, data1, data2);
1935 }
1936}
1937
1938////////////////////////////////////////////////////////////////////////////////
1939
1940ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
1941 ACodec *codec)
1942 : BaseState(codec) {
1943}
1944
1945ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
1946 OMX_U32 portIndex) {
1947 if (portIndex == kPortIndexOutput) {
1948 return FREE_BUFFERS;
1949 }
1950
1951 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
1952
1953 return RESUBMIT_BUFFERS;
1954}
1955
1956bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
1957 const sp<AMessage> &msg) {
1958 bool handled = false;
1959
1960 switch (msg->what()) {
1961 case kWhatFlush:
1962 case kWhatShutdown:
Andreas Huber6760f982011-02-04 10:12:26 -08001963 case kWhatResume:
Andreas Hubera1587462010-12-15 15:17:42 -08001964 {
Andreas Huber6760f982011-02-04 10:12:26 -08001965 if (msg->what() == kWhatResume) {
1966 LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
1967 }
1968
Andreas Hubera1587462010-12-15 15:17:42 -08001969 mCodec->deferMessage(msg);
1970 handled = true;
1971 break;
1972 }
1973
1974 default:
1975 handled = BaseState::onMessageReceived(msg);
1976 break;
1977 }
1978
1979 return handled;
1980}
1981
1982void ACodec::OutputPortSettingsChangedState::stateEntered() {
Andreas Huber54e66492010-12-23 10:27:40 -08001983 LOGV("[%s] Now handling output port settings change",
Andreas Hubera1587462010-12-15 15:17:42 -08001984 mCodec->mComponentName.c_str());
1985}
1986
1987bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
1988 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1989 switch (event) {
1990 case OMX_EventCmdComplete:
1991 {
1992 if (data1 == (OMX_U32)OMX_CommandPortDisable) {
1993 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
1994
1995 LOGV("[%s] Output port now disabled.",
1996 mCodec->mComponentName.c_str());
1997
1998 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
1999 mCodec->mDealer[kPortIndexOutput].clear();
2000
2001 CHECK_EQ(mCodec->mOMX->sendCommand(
2002 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
2003 (status_t)OK);
2004
2005 CHECK_EQ(mCodec->allocateBuffersOnPort(kPortIndexOutput),
2006 (status_t)OK);
2007
2008 return true;
2009 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
2010 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
2011
Andreas Huber7caa1302011-01-10 10:38:31 -08002012 mCodec->mSentFormat = false;
2013
Andreas Hubera1587462010-12-15 15:17:42 -08002014 LOGV("[%s] Output port now reenabled.",
2015 mCodec->mComponentName.c_str());
2016
Andreas Huber6760f982011-02-04 10:12:26 -08002017 if (mCodec->mExecutingState->active()) {
2018 mCodec->mExecutingState->submitOutputBuffers();
2019 }
2020
Andreas Hubera1587462010-12-15 15:17:42 -08002021 mCodec->changeState(mCodec->mExecutingState);
2022
2023 return true;
2024 }
2025
2026 return false;
2027 }
2028
2029 default:
2030 return false;
2031 }
2032}
2033
2034////////////////////////////////////////////////////////////////////////////////
2035
2036ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
2037 : BaseState(codec) {
2038}
2039
2040bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2041 bool handled = false;
2042
2043 switch (msg->what()) {
2044 case kWhatFlush:
2045 {
2046 // Don't send me a flush request if you previously wanted me
2047 // to shutdown.
2048 TRESPASS();
2049 break;
2050 }
2051
2052 case kWhatShutdown:
2053 {
2054 // We're already doing that...
2055
2056 handled = true;
2057 break;
2058 }
2059
2060 default:
2061 handled = BaseState::onMessageReceived(msg);
2062 break;
2063 }
2064
2065 return handled;
2066}
2067
2068void ACodec::ExecutingToIdleState::stateEntered() {
Andreas Huber54e66492010-12-23 10:27:40 -08002069 LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
Andreas Huber7caa1302011-01-10 10:38:31 -08002070
2071 mCodec->mSentFormat = false;
Andreas Hubera1587462010-12-15 15:17:42 -08002072}
2073
2074bool ACodec::ExecutingToIdleState::onOMXEvent(
2075 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2076 switch (event) {
2077 case OMX_EventCmdComplete:
2078 {
2079 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2080 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2081
2082 changeStateIfWeOwnAllBuffers();
2083
2084 return true;
2085 }
2086
Andreas Huber6760f982011-02-04 10:12:26 -08002087 case OMX_EventPortSettingsChanged:
2088 case OMX_EventBufferFlag:
2089 {
2090 // We're shutting down and don't care about this anymore.
2091 return true;
2092 }
2093
Andreas Hubera1587462010-12-15 15:17:42 -08002094 default:
2095 return BaseState::onOMXEvent(event, data1, data2);
2096 }
2097}
2098void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
2099 if (mCodec->allYourBuffersAreBelongToUs()) {
2100 CHECK_EQ(mCodec->mOMX->sendCommand(
2101 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
2102 (status_t)OK);
2103
2104 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
2105 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
2106
2107 mCodec->changeState(mCodec->mIdleToLoadedState);
2108 }
2109}
2110
2111void ACodec::ExecutingToIdleState::onInputBufferFilled(
2112 const sp<AMessage> &msg) {
2113 BaseState::onInputBufferFilled(msg);
2114
2115 changeStateIfWeOwnAllBuffers();
2116}
2117
2118void ACodec::ExecutingToIdleState::onOutputBufferDrained(
2119 const sp<AMessage> &msg) {
2120 BaseState::onOutputBufferDrained(msg);
2121
2122 changeStateIfWeOwnAllBuffers();
2123}
2124
2125////////////////////////////////////////////////////////////////////////////////
2126
2127ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
2128 : BaseState(codec) {
2129}
2130
2131bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
2132 bool handled = false;
2133
2134 switch (msg->what()) {
2135 case kWhatShutdown:
2136 {
2137 // We're already doing that...
2138
2139 handled = true;
2140 break;
2141 }
2142
2143 case kWhatFlush:
2144 {
2145 // Don't send me a flush request if you previously wanted me
2146 // to shutdown.
2147 TRESPASS();
2148 break;
2149 }
2150
2151 default:
2152 handled = BaseState::onMessageReceived(msg);
2153 break;
2154 }
2155
2156 return handled;
2157}
2158
2159void ACodec::IdleToLoadedState::stateEntered() {
Andreas Huber54e66492010-12-23 10:27:40 -08002160 LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08002161}
2162
2163bool ACodec::IdleToLoadedState::onOMXEvent(
2164 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2165 switch (event) {
2166 case OMX_EventCmdComplete:
2167 {
2168 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2169 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
2170
Andreas Huber54e66492010-12-23 10:27:40 -08002171 LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08002172
2173 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2174
2175 mCodec->mNativeWindow.clear();
2176 mCodec->mNode = NULL;
2177 mCodec->mOMX.clear();
2178 mCodec->mComponentName.clear();
2179
2180 mCodec->changeState(mCodec->mUninitializedState);
2181
2182 sp<AMessage> notify = mCodec->mNotify->dup();
2183 notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2184 notify->post();
2185
2186 return true;
2187 }
2188
2189 default:
2190 return BaseState::onOMXEvent(event, data1, data2);
2191 }
2192}
2193
2194////////////////////////////////////////////////////////////////////////////////
2195
2196ACodec::ErrorState::ErrorState(ACodec *codec)
2197 : BaseState(codec) {
2198}
2199
2200bool ACodec::ErrorState::onMessageReceived(const sp<AMessage> &msg) {
2201 return BaseState::onMessageReceived(msg);
2202}
2203
2204void ACodec::ErrorState::stateEntered() {
Andreas Huber54e66492010-12-23 10:27:40 -08002205 LOGV("[%s] Now in ErrorState", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08002206}
2207
2208bool ACodec::ErrorState::onOMXEvent(
2209 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
Andreas Huber54e66492010-12-23 10:27:40 -08002210 LOGV("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2);
Andreas Hubera1587462010-12-15 15:17:42 -08002211 return true;
2212}
2213
2214////////////////////////////////////////////////////////////////////////////////
2215
2216ACodec::FlushingState::FlushingState(ACodec *codec)
2217 : BaseState(codec) {
2218}
2219
2220void ACodec::FlushingState::stateEntered() {
Andreas Huber54e66492010-12-23 10:27:40 -08002221 LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
Andreas Hubera1587462010-12-15 15:17:42 -08002222
2223 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
2224}
2225
2226bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
2227 bool handled = false;
2228
2229 switch (msg->what()) {
2230 case kWhatShutdown:
2231 {
2232 mCodec->deferMessage(msg);
2233 break;
2234 }
2235
2236 case kWhatFlush:
2237 {
2238 // We're already doing this right now.
2239 handled = true;
2240 break;
2241 }
2242
2243 default:
2244 handled = BaseState::onMessageReceived(msg);
2245 break;
2246 }
2247
2248 return handled;
2249}
2250
2251bool ACodec::FlushingState::onOMXEvent(
2252 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2253 switch (event) {
2254 case OMX_EventCmdComplete:
2255 {
2256 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
2257
2258 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
2259 CHECK(!mFlushComplete[data2]);
2260 mFlushComplete[data2] = true;
2261 } else {
2262 CHECK_EQ(data2, OMX_ALL);
2263 CHECK(mFlushComplete[kPortIndexInput]);
2264 CHECK(mFlushComplete[kPortIndexOutput]);
2265
2266 changeStateIfWeOwnAllBuffers();
2267 }
2268
2269 return true;
2270 }
2271
Andreas Huber6760f982011-02-04 10:12:26 -08002272 case OMX_EventPortSettingsChanged:
2273 {
2274 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
2275 msg->setInt32("type", omx_message::EVENT);
2276 msg->setPointer("node", mCodec->mNode);
2277 msg->setInt32("event", event);
2278 msg->setInt32("data1", data1);
2279 msg->setInt32("data2", data2);
2280
2281 LOGV("[%s] Deferring OMX_EventPortSettingsChanged",
2282 mCodec->mComponentName.c_str());
2283
2284 mCodec->deferMessage(msg);
2285
2286 return true;
2287 }
2288
Andreas Hubera1587462010-12-15 15:17:42 -08002289 default:
2290 return BaseState::onOMXEvent(event, data1, data2);
2291 }
2292
2293 return true;
2294}
2295
2296void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
2297 BaseState::onOutputBufferDrained(msg);
2298
2299 changeStateIfWeOwnAllBuffers();
2300}
2301
2302void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
2303 BaseState::onInputBufferFilled(msg);
2304
2305 changeStateIfWeOwnAllBuffers();
2306}
2307
2308void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
2309 if (mFlushComplete[kPortIndexInput]
2310 && mFlushComplete[kPortIndexOutput]
2311 && mCodec->allYourBuffersAreBelongToUs()) {
2312 sp<AMessage> notify = mCodec->mNotify->dup();
2313 notify->setInt32("what", ACodec::kWhatFlushCompleted);
2314 notify->post();
2315
2316 mCodec->mPortEOS[kPortIndexInput] =
2317 mCodec->mPortEOS[kPortIndexOutput] = false;
2318
2319 mCodec->changeState(mCodec->mExecutingState);
2320 }
2321}
2322
2323} // namespace android