blob: 82c98b9ca6c9830459425ec1381027825e9feb00 [file] [log] [blame]
Andreas Huber35213f12012-08-29 11:41:50 -07001/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "Converter"
19#include <utils/Log.h>
20
21#include "Converter.h"
22
Andreas Hubera7f7e0a2012-09-28 10:23:51 -070023#include "MediaPuller.h"
24
Andreas Huber13da4ed2012-09-12 14:06:17 -070025#include <cutils/properties.h>
Andreas Huber35213f12012-08-29 11:41:50 -070026#include <gui/SurfaceTextureClient.h>
27#include <media/ICrypto.h>
28#include <media/stagefright/foundation/ABuffer.h>
29#include <media/stagefright/foundation/ADebug.h>
30#include <media/stagefright/foundation/AMessage.h>
Andreas Hubera7f7e0a2012-09-28 10:23:51 -070031#include <media/stagefright/MediaBuffer.h>
Andreas Huber35213f12012-08-29 11:41:50 -070032#include <media/stagefright/MediaCodec.h>
33#include <media/stagefright/MediaDefs.h>
34#include <media/stagefright/MediaErrors.h>
35
Andreas Huber7b426222012-11-01 15:48:44 -070036#include <OMX_Video.h>
37
Andreas Huber35213f12012-08-29 11:41:50 -070038namespace android {
39
40Converter::Converter(
41 const sp<AMessage> &notify,
42 const sp<ALooper> &codecLooper,
Andreas Huber20a5a982012-10-04 11:46:29 -070043 const sp<AMessage> &format,
44 bool usePCMAudio)
Andreas Huber35213f12012-08-29 11:41:50 -070045 : mInitCheck(NO_INIT),
46 mNotify(notify),
47 mCodecLooper(codecLooper),
48 mInputFormat(format),
Andreas Huber03e2ffa2012-09-13 16:43:51 -070049 mIsVideo(false),
Andreas Huber20a5a982012-10-04 11:46:29 -070050 mIsPCMAudio(usePCMAudio),
Andreas Huber83c9bd12012-11-12 13:08:44 -080051 mNeedToManuallyPrependSPSPPS(false),
Andreas Huber07fbf942012-10-02 14:17:38 -070052 mDoMoreWorkPending(false)
53#if ENABLE_SILENCE_DETECTION
54 ,mFirstSilentFrameUs(-1ll)
55 ,mInSilentMode(false)
56#endif
57 {
Andreas Huber03e2ffa2012-09-13 16:43:51 -070058 AString mime;
59 CHECK(mInputFormat->findString("mime", &mime));
60
61 if (!strncasecmp("video/", mime.c_str(), 6)) {
62 mIsVideo = true;
63 }
64
Andreas Huber20a5a982012-10-04 11:46:29 -070065 CHECK(!usePCMAudio || !mIsVideo);
66
Andreas Huber35213f12012-08-29 11:41:50 -070067 mInitCheck = initEncoder();
Andreas Huber13315ce2012-09-28 11:34:41 -070068
69 if (mInitCheck != OK) {
70 if (mEncoder != NULL) {
71 mEncoder->release();
72 mEncoder.clear();
73 }
74 }
Andreas Huber35213f12012-08-29 11:41:50 -070075}
76
77Converter::~Converter() {
Andreas Hubera7f7e0a2012-09-28 10:23:51 -070078 CHECK(mEncoder == NULL);
79}
Andreas Huber596b4cd2012-09-12 16:25:14 -070080
Andreas Hubera7f7e0a2012-09-28 10:23:51 -070081void Converter::shutdownAsync() {
82 ALOGV("shutdown");
83 (new AMessage(kWhatShutdown, id()))->post();
Andreas Huber35213f12012-08-29 11:41:50 -070084}
85
86status_t Converter::initCheck() const {
87 return mInitCheck;
88}
89
Andreas Huber7f066392012-09-04 16:30:49 -070090size_t Converter::getInputBufferCount() const {
91 return mEncoderInputBuffers.size();
92}
93
Andreas Huber35213f12012-08-29 11:41:50 -070094sp<AMessage> Converter::getOutputFormat() const {
95 return mOutputFormat;
96}
97
Andreas Huber83c9bd12012-11-12 13:08:44 -080098bool Converter::needToManuallyPrependSPSPPS() const {
99 return mNeedToManuallyPrependSPSPPS;
100}
101
Andreas Huber13da4ed2012-09-12 14:06:17 -0700102static int32_t getBitrate(const char *propName, int32_t defaultValue) {
103 char val[PROPERTY_VALUE_MAX];
104 if (property_get(propName, val, NULL)) {
105 char *end;
106 unsigned long x = strtoul(val, &end, 10);
107
108 if (*end == '\0' && end > val && x > 0) {
109 return x;
110 }
111 }
112
113 return defaultValue;
114}
115
Andreas Huber35213f12012-08-29 11:41:50 -0700116status_t Converter::initEncoder() {
117 AString inputMIME;
118 CHECK(mInputFormat->findString("mime", &inputMIME));
119
120 AString outputMIME;
121 bool isAudio = false;
122 if (!strcasecmp(inputMIME.c_str(), MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber20a5a982012-10-04 11:46:29 -0700123 if (mIsPCMAudio) {
124 outputMIME = MEDIA_MIMETYPE_AUDIO_RAW;
125 } else {
126 outputMIME = MEDIA_MIMETYPE_AUDIO_AAC;
127 }
Andreas Huber35213f12012-08-29 11:41:50 -0700128 isAudio = true;
129 } else if (!strcasecmp(inputMIME.c_str(), MEDIA_MIMETYPE_VIDEO_RAW)) {
130 outputMIME = MEDIA_MIMETYPE_VIDEO_AVC;
131 } else {
132 TRESPASS();
133 }
134
Andreas Huber20a5a982012-10-04 11:46:29 -0700135 if (!mIsPCMAudio) {
136 mEncoder = MediaCodec::CreateByType(
137 mCodecLooper, outputMIME.c_str(), true /* encoder */);
Andreas Huber35213f12012-08-29 11:41:50 -0700138
Andreas Huber20a5a982012-10-04 11:46:29 -0700139 if (mEncoder == NULL) {
140 return ERROR_UNSUPPORTED;
141 }
Andreas Huber35213f12012-08-29 11:41:50 -0700142 }
143
144 mOutputFormat = mInputFormat->dup();
Andreas Huber20a5a982012-10-04 11:46:29 -0700145
146 if (mIsPCMAudio) {
147 return OK;
148 }
149
Andreas Huber35213f12012-08-29 11:41:50 -0700150 mOutputFormat->setString("mime", outputMIME.c_str());
151
Dave Burkece51cb82012-09-27 12:54:57 -0700152 int32_t audioBitrate = getBitrate("media.wfd.audio-bitrate", 128000);
Dave Burkecc37e712012-10-26 23:49:43 -0700153 int32_t videoBitrate = getBitrate("media.wfd.video-bitrate", 5000000);
Andreas Huber13da4ed2012-09-12 14:06:17 -0700154
155 ALOGI("using audio bitrate of %d bps, video bitrate of %d bps",
156 audioBitrate, videoBitrate);
157
Andreas Huber35213f12012-08-29 11:41:50 -0700158 if (isAudio) {
Andreas Huber13da4ed2012-09-12 14:06:17 -0700159 mOutputFormat->setInt32("bitrate", audioBitrate);
Andreas Huber35213f12012-08-29 11:41:50 -0700160 } else {
Andreas Huber13da4ed2012-09-12 14:06:17 -0700161 mOutputFormat->setInt32("bitrate", videoBitrate);
Andreas Huber7b426222012-11-01 15:48:44 -0700162 mOutputFormat->setInt32("bitrate-mode", OMX_Video_ControlRateConstant);
Andreas Huber77c887a2012-10-02 12:49:33 -0700163 mOutputFormat->setInt32("frame-rate", 30);
Dave Burkebee01b82012-09-26 17:56:37 -0700164 mOutputFormat->setInt32("i-frame-interval", 1); // Iframes every 1 secs
Andreas Huber35213f12012-08-29 11:41:50 -0700165 }
166
167 ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
168
Andreas Huber83c9bd12012-11-12 13:08:44 -0800169 mNeedToManuallyPrependSPSPPS = false;
170
171 status_t err = NO_INIT;
172
173 if (!isAudio) {
174 sp<AMessage> tmp = mOutputFormat->dup();
175 tmp->setInt32("prepend-sps-pps-to-idr-frames", 1);
176
177 err = mEncoder->configure(
178 tmp,
179 NULL /* nativeWindow */,
180 NULL /* crypto */,
181 MediaCodec::CONFIGURE_FLAG_ENCODE);
182
183 if (err == OK) {
184 // Encoder supported prepending SPS/PPS, we don't need to emulate
185 // it.
186 mOutputFormat = tmp;
187 } else {
188 mNeedToManuallyPrependSPSPPS = true;
189
190 ALOGI("We going to manually prepend SPS and PPS to IDR frames.");
191 }
192 }
193
194 if (err != OK) {
195 // We'll get here for audio or if we failed to configure the encoder
196 // to automatically prepend SPS/PPS in the case of video.
197
198 err = mEncoder->configure(
199 mOutputFormat,
200 NULL /* nativeWindow */,
201 NULL /* crypto */,
202 MediaCodec::CONFIGURE_FLAG_ENCODE);
203 }
Andreas Huber35213f12012-08-29 11:41:50 -0700204
205 if (err != OK) {
206 return err;
207 }
208
209 err = mEncoder->start();
210
211 if (err != OK) {
212 return err;
213 }
214
215 err = mEncoder->getInputBuffers(&mEncoderInputBuffers);
216
217 if (err != OK) {
218 return err;
219 }
220
221 return mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
222}
223
Andreas Huber35213f12012-08-29 11:41:50 -0700224void Converter::notifyError(status_t err) {
225 sp<AMessage> notify = mNotify->dup();
226 notify->setInt32("what", kWhatError);
227 notify->setInt32("err", err);
228 notify->post();
229}
230
Andreas Huber07fbf942012-10-02 14:17:38 -0700231// static
232bool Converter::IsSilence(const sp<ABuffer> &accessUnit) {
233 const uint8_t *ptr = accessUnit->data();
234 const uint8_t *end = ptr + accessUnit->size();
235 while (ptr < end) {
236 if (*ptr != 0) {
237 return false;
238 }
239 ++ptr;
240 }
241
242 return true;
243}
244
Andreas Huber35213f12012-08-29 11:41:50 -0700245void Converter::onMessageReceived(const sp<AMessage> &msg) {
246 switch (msg->what()) {
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700247 case kWhatMediaPullerNotify:
Andreas Huber35213f12012-08-29 11:41:50 -0700248 {
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700249 int32_t what;
250 CHECK(msg->findInt32("what", &what));
Andreas Huber35213f12012-08-29 11:41:50 -0700251
Andreas Huber20a5a982012-10-04 11:46:29 -0700252 if (!mIsPCMAudio && mEncoder == NULL) {
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700253 ALOGV("got msg '%s' after encoder shutdown.",
254 msg->debugString().c_str());
Andreas Huber35213f12012-08-29 11:41:50 -0700255
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700256 if (what == MediaPuller::kWhatAccessUnit) {
257 sp<ABuffer> accessUnit;
258 CHECK(msg->findBuffer("accessUnit", &accessUnit));
Andreas Huber35213f12012-08-29 11:41:50 -0700259
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700260 void *mbuf;
261 if (accessUnit->meta()->findPointer("mediaBuffer", &mbuf)
262 && mbuf != NULL) {
263 ALOGV("releasing mbuf %p", mbuf);
Andreas Huber35213f12012-08-29 11:41:50 -0700264
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700265 accessUnit->meta()->setPointer("mediaBuffer", NULL);
Andreas Huber35213f12012-08-29 11:41:50 -0700266
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700267 static_cast<MediaBuffer *>(mbuf)->release();
268 mbuf = NULL;
269 }
270 }
271 break;
272 }
Andreas Huber35213f12012-08-29 11:41:50 -0700273
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700274 if (what == MediaPuller::kWhatEOS) {
275 mInputBufferQueue.push_back(NULL);
276
277 feedEncoderInputBuffers();
278
279 scheduleDoMoreWork();
280 } else {
281 CHECK_EQ(what, MediaPuller::kWhatAccessUnit);
282
283 sp<ABuffer> accessUnit;
284 CHECK(msg->findBuffer("accessUnit", &accessUnit));
285
286#if 0
287 void *mbuf;
288 if (accessUnit->meta()->findPointer("mediaBuffer", &mbuf)
289 && mbuf != NULL) {
290 ALOGI("queueing mbuf %p", mbuf);
291 }
292#endif
293
Andreas Huber07fbf942012-10-02 14:17:38 -0700294#if ENABLE_SILENCE_DETECTION
295 if (!mIsVideo) {
296 if (IsSilence(accessUnit)) {
Andreas Huber4a114f02012-10-03 09:01:11 -0700297 if (mInSilentMode) {
298 break;
299 }
Andreas Huber07fbf942012-10-02 14:17:38 -0700300
Andreas Huber4a114f02012-10-03 09:01:11 -0700301 int64_t nowUs = ALooper::GetNowUs();
302
303 if (mFirstSilentFrameUs < 0ll) {
304 mFirstSilentFrameUs = nowUs;
305 } else if (nowUs >= mFirstSilentFrameUs + 10000000ll) {
306 mInSilentMode = true;
307 ALOGI("audio in silent mode now.");
308 break;
Andreas Huber07fbf942012-10-02 14:17:38 -0700309 }
310 } else {
311 if (mInSilentMode) {
312 ALOGI("audio no longer in silent mode.");
313 }
314 mInSilentMode = false;
315 mFirstSilentFrameUs = -1ll;
316 }
317 }
318#endif
319
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700320 mInputBufferQueue.push_back(accessUnit);
321
322 feedEncoderInputBuffers();
323
324 scheduleDoMoreWork();
325 }
Andreas Huber35213f12012-08-29 11:41:50 -0700326 break;
327 }
328
Andreas Huber72c66862012-10-03 10:16:58 -0700329 case kWhatEncoderActivity:
Andreas Huber35213f12012-08-29 11:41:50 -0700330 {
Andreas Huber72c66862012-10-03 10:16:58 -0700331#if 0
332 int64_t whenUs;
333 if (msg->findInt64("whenUs", &whenUs)) {
334 int64_t nowUs = ALooper::GetNowUs();
335 ALOGI("[%s] kWhatEncoderActivity after %lld us",
336 mIsVideo ? "video" : "audio", nowUs - whenUs);
337 }
338#endif
339
Andreas Huber35213f12012-08-29 11:41:50 -0700340 mDoMoreWorkPending = false;
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700341
342 if (mEncoder == NULL) {
343 break;
344 }
345
Andreas Huber35213f12012-08-29 11:41:50 -0700346 status_t err = doMoreWork();
347
348 if (err != OK) {
349 notifyError(err);
350 } else {
351 scheduleDoMoreWork();
352 }
353 break;
354 }
355
Andreas Huber03e2ffa2012-09-13 16:43:51 -0700356 case kWhatRequestIDRFrame:
357 {
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700358 if (mEncoder == NULL) {
359 break;
360 }
361
Andreas Huber03e2ffa2012-09-13 16:43:51 -0700362 if (mIsVideo) {
363 ALOGI("requesting IDR frame");
364 mEncoder->requestIDRFrame();
365 }
366 break;
367 }
368
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700369 case kWhatShutdown:
370 {
371 ALOGI("shutting down encoder");
Andreas Huber20a5a982012-10-04 11:46:29 -0700372
373 if (mEncoder != NULL) {
374 mEncoder->release();
375 mEncoder.clear();
376 }
Andreas Hubera7f7e0a2012-09-28 10:23:51 -0700377
378 AString mime;
379 CHECK(mInputFormat->findString("mime", &mime));
380 ALOGI("encoder (%s) shut down.", mime.c_str());
381 break;
382 }
383
Andreas Huber35213f12012-08-29 11:41:50 -0700384 default:
385 TRESPASS();
386 }
387}
388
389void Converter::scheduleDoMoreWork() {
Andreas Huber20a5a982012-10-04 11:46:29 -0700390 if (mIsPCMAudio) {
391 // There's no encoder involved in this case.
392 return;
393 }
394
Andreas Huber35213f12012-08-29 11:41:50 -0700395 if (mDoMoreWorkPending) {
396 return;
397 }
398
399 mDoMoreWorkPending = true;
Andreas Huber72c66862012-10-03 10:16:58 -0700400
401#if 1
402 if (mEncoderActivityNotify == NULL) {
403 mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, id());
404 }
405 mEncoder->requestActivityNotification(mEncoderActivityNotify->dup());
406#else
407 sp<AMessage> notify = new AMessage(kWhatEncoderActivity, id());
408 notify->setInt64("whenUs", ALooper::GetNowUs());
409 mEncoder->requestActivityNotification(notify);
410#endif
Andreas Huber35213f12012-08-29 11:41:50 -0700411}
412
Andreas Huber20a5a982012-10-04 11:46:29 -0700413status_t Converter::feedRawAudioInputBuffers() {
414 // Split incoming PCM audio into buffers of 6 AUs of 80 audio frames each
415 // and add a 4 byte header according to the wifi display specs.
416
417 while (!mInputBufferQueue.empty()) {
418 sp<ABuffer> buffer = *mInputBufferQueue.begin();
419 mInputBufferQueue.erase(mInputBufferQueue.begin());
420
421 int16_t *ptr = (int16_t *)buffer->data();
422 int16_t *stop = (int16_t *)(buffer->data() + buffer->size());
423 while (ptr < stop) {
424 *ptr = htons(*ptr);
425 ++ptr;
426 }
427
428 static const size_t kFrameSize = 2 * sizeof(int16_t); // stereo
429 static const size_t kFramesPerAU = 80;
430 static const size_t kNumAUsPerPESPacket = 6;
431
432 if (mPartialAudioAU != NULL) {
433 size_t bytesMissingForFullAU =
434 kNumAUsPerPESPacket * kFramesPerAU * kFrameSize
435 - mPartialAudioAU->size() + 4;
436
437 size_t copy = buffer->size();
438 if(copy > bytesMissingForFullAU) {
439 copy = bytesMissingForFullAU;
440 }
441
442 memcpy(mPartialAudioAU->data() + mPartialAudioAU->size(),
443 buffer->data(),
444 copy);
445
446 mPartialAudioAU->setRange(0, mPartialAudioAU->size() + copy);
447
448 buffer->setRange(buffer->offset() + copy, buffer->size() - copy);
449
450 int64_t timeUs;
451 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
452
453 int64_t copyUs = (int64_t)((copy / kFrameSize) * 1E6 / 48000.0);
454 timeUs += copyUs;
455 buffer->meta()->setInt64("timeUs", timeUs);
456
457 if (bytesMissingForFullAU == copy) {
458 sp<AMessage> notify = mNotify->dup();
459 notify->setInt32("what", kWhatAccessUnit);
460 notify->setBuffer("accessUnit", mPartialAudioAU);
461 notify->post();
462
463 mPartialAudioAU.clear();
464 }
465 }
466
467 while (buffer->size() > 0) {
468 sp<ABuffer> partialAudioAU =
469 new ABuffer(
470 4
471 + kNumAUsPerPESPacket * kFrameSize * kFramesPerAU);
472
473 uint8_t *ptr = partialAudioAU->data();
474 ptr[0] = 0xa0; // 10100000b
475 ptr[1] = kNumAUsPerPESPacket;
476 ptr[2] = 0; // reserved, audio _emphasis_flag = 0
477
478 static const unsigned kQuantizationWordLength = 0; // 16-bit
479 static const unsigned kAudioSamplingFrequency = 2; // 48Khz
480 static const unsigned kNumberOfAudioChannels = 1; // stereo
481
482 ptr[3] = (kQuantizationWordLength << 6)
483 | (kAudioSamplingFrequency << 3)
484 | kNumberOfAudioChannels;
485
486 size_t copy = buffer->size();
487 if (copy > partialAudioAU->size() - 4) {
488 copy = partialAudioAU->size() - 4;
489 }
490
491 memcpy(&ptr[4], buffer->data(), copy);
492
493 partialAudioAU->setRange(0, 4 + copy);
494 buffer->setRange(buffer->offset() + copy, buffer->size() - copy);
495
496 int64_t timeUs;
497 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
498
499 partialAudioAU->meta()->setInt64("timeUs", timeUs);
500
501 int64_t copyUs = (int64_t)((copy / kFrameSize) * 1E6 / 48000.0);
502 timeUs += copyUs;
503 buffer->meta()->setInt64("timeUs", timeUs);
504
Andreas Huberbd4e99c2012-10-30 15:53:03 -0700505 if (copy == partialAudioAU->capacity() - 4) {
Andreas Huber20a5a982012-10-04 11:46:29 -0700506 sp<AMessage> notify = mNotify->dup();
507 notify->setInt32("what", kWhatAccessUnit);
508 notify->setBuffer("accessUnit", partialAudioAU);
509 notify->post();
510
511 partialAudioAU.clear();
512 continue;
513 }
514
515 mPartialAudioAU = partialAudioAU;
516 }
517 }
518
519 return OK;
520}
521
Andreas Huber35213f12012-08-29 11:41:50 -0700522status_t Converter::feedEncoderInputBuffers() {
Andreas Huber20a5a982012-10-04 11:46:29 -0700523 if (mIsPCMAudio) {
524 return feedRawAudioInputBuffers();
525 }
526
Andreas Huber35213f12012-08-29 11:41:50 -0700527 while (!mInputBufferQueue.empty()
528 && !mAvailEncoderInputIndices.empty()) {
529 sp<ABuffer> buffer = *mInputBufferQueue.begin();
530 mInputBufferQueue.erase(mInputBufferQueue.begin());
531
532 size_t bufferIndex = *mAvailEncoderInputIndices.begin();
533 mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
534
535 int64_t timeUs = 0ll;
536 uint32_t flags = 0;
537
538 if (buffer != NULL) {
539 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
540
541 memcpy(mEncoderInputBuffers.itemAt(bufferIndex)->data(),
542 buffer->data(),
543 buffer->size());
544
545 void *mediaBuffer;
546 if (buffer->meta()->findPointer("mediaBuffer", &mediaBuffer)
547 && mediaBuffer != NULL) {
548 mEncoderInputBuffers.itemAt(bufferIndex)->meta()
549 ->setPointer("mediaBuffer", mediaBuffer);
550
551 buffer->meta()->setPointer("mediaBuffer", NULL);
552 }
553 } else {
554 flags = MediaCodec::BUFFER_FLAG_EOS;
555 }
556
557 status_t err = mEncoder->queueInputBuffer(
558 bufferIndex, 0, (buffer == NULL) ? 0 : buffer->size(),
559 timeUs, flags);
560
561 if (err != OK) {
562 return err;
563 }
564 }
565
566 return OK;
567}
568
569status_t Converter::doMoreWork() {
Andreas Huber72c66862012-10-03 10:16:58 -0700570 status_t err;
Andreas Huber35213f12012-08-29 11:41:50 -0700571
Andreas Huber07fbf942012-10-02 14:17:38 -0700572 for (;;) {
Andreas Huber72c66862012-10-03 10:16:58 -0700573 size_t bufferIndex;
574 err = mEncoder->dequeueInputBuffer(&bufferIndex);
575
576 if (err != OK) {
577 break;
578 }
579
580 mAvailEncoderInputIndices.push_back(bufferIndex);
581 }
582
583 feedEncoderInputBuffers();
584
585 for (;;) {
586 size_t bufferIndex;
Andreas Huber07fbf942012-10-02 14:17:38 -0700587 size_t offset;
588 size_t size;
589 int64_t timeUs;
590 uint32_t flags;
591 err = mEncoder->dequeueOutputBuffer(
592 &bufferIndex, &offset, &size, &timeUs, &flags);
Andreas Huber35213f12012-08-29 11:41:50 -0700593
Andreas Huber07fbf942012-10-02 14:17:38 -0700594 if (err != OK) {
595 if (err == -EAGAIN) {
596 err = OK;
597 }
598 break;
599 }
600
Andreas Huber35213f12012-08-29 11:41:50 -0700601 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
602 sp<AMessage> notify = mNotify->dup();
603 notify->setInt32("what", kWhatEOS);
604 notify->post();
605 } else {
606 sp<ABuffer> buffer = new ABuffer(size);
607 buffer->meta()->setInt64("timeUs", timeUs);
608
Andreas Huber4a114f02012-10-03 09:01:11 -0700609 ALOGV("[%s] time %lld us (%.2f secs)",
610 mIsVideo ? "video" : "audio", timeUs, timeUs / 1E6);
Andreas Huber07fbf942012-10-02 14:17:38 -0700611
Andreas Huber35213f12012-08-29 11:41:50 -0700612 memcpy(buffer->data(),
613 mEncoderOutputBuffers.itemAt(bufferIndex)->base() + offset,
614 size);
615
616 if (flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) {
617 mOutputFormat->setBuffer("csd-0", buffer);
618 } else {
619 sp<AMessage> notify = mNotify->dup();
620 notify->setInt32("what", kWhatAccessUnit);
621 notify->setBuffer("accessUnit", buffer);
622 notify->post();
623 }
624 }
625
Andreas Huber07fbf942012-10-02 14:17:38 -0700626 mEncoder->releaseOutputBuffer(bufferIndex);
627
628 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
629 break;
630 }
Andreas Huber35213f12012-08-29 11:41:50 -0700631 }
632
633 return err;
634}
635
Andreas Huber03e2ffa2012-09-13 16:43:51 -0700636void Converter::requestIDRFrame() {
637 (new AMessage(kWhatRequestIDRFrame, id()))->post();
638}
639
Andreas Huber35213f12012-08-29 11:41:50 -0700640} // namespace android