blob: bb8c38705370a298265333e394fb73d831d81174 [file] [log] [blame]
Andreas Huberd7bee3a2012-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 Huber96fc6cc2012-09-28 10:23:51 -070023#include "MediaPuller.h"
24
Andreas Huber44b59fd2012-09-12 14:06:17 -070025#include <cutils/properties.h>
Mathias Agopian1a2952a2013-02-14 17:11:27 -080026#include <gui/Surface.h>
Andreas Huberd7bee3a2012-08-29 11:41:50 -070027#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 Huber96fc6cc2012-09-28 10:23:51 -070031#include <media/stagefright/MediaBuffer.h>
Andreas Huberd7bee3a2012-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 Huber96076962012-11-01 15:48:44 -070036#include <OMX_Video.h>
37
Andreas Huberd7bee3a2012-08-29 11:41:50 -070038namespace android {
39
40Converter::Converter(
41 const sp<AMessage> &notify,
42 const sp<ALooper> &codecLooper,
Andreas Hubere7bd24a2012-10-04 11:46:29 -070043 const sp<AMessage> &format,
44 bool usePCMAudio)
Andreas Huberd7bee3a2012-08-29 11:41:50 -070045 : mInitCheck(NO_INIT),
46 mNotify(notify),
47 mCodecLooper(codecLooper),
48 mInputFormat(format),
Andreas Huber496238c2012-09-13 16:43:51 -070049 mIsVideo(false),
Andreas Hubere7bd24a2012-10-04 11:46:29 -070050 mIsPCMAudio(usePCMAudio),
Andreas Huber0224bf12012-11-12 13:08:44 -080051 mNeedToManuallyPrependSPSPPS(false),
Andreas Hubercf2604f2012-10-02 14:17:38 -070052 mDoMoreWorkPending(false)
53#if ENABLE_SILENCE_DETECTION
54 ,mFirstSilentFrameUs(-1ll)
55 ,mInSilentMode(false)
56#endif
Andreas Hubera2eb22c2013-02-07 10:56:14 -080057 ,mPrevVideoBitrate(-1)
Andreas Huber126568c2013-03-12 15:55:43 -070058 ,mNumFramesToDrop(0)
Andreas Hubercf2604f2012-10-02 14:17:38 -070059 {
Andreas Huber496238c2012-09-13 16:43:51 -070060 AString mime;
61 CHECK(mInputFormat->findString("mime", &mime));
62
63 if (!strncasecmp("video/", mime.c_str(), 6)) {
64 mIsVideo = true;
65 }
66
Andreas Hubere7bd24a2012-10-04 11:46:29 -070067 CHECK(!usePCMAudio || !mIsVideo);
68
Andreas Huberd7bee3a2012-08-29 11:41:50 -070069 mInitCheck = initEncoder();
Andreas Huber3a0ef0d2012-09-28 11:34:41 -070070
71 if (mInitCheck != OK) {
Andreas Huberc8e07e42012-12-20 13:49:34 -080072 releaseEncoder();
Andreas Huber3a0ef0d2012-09-28 11:34:41 -070073 }
Andreas Huberd7bee3a2012-08-29 11:41:50 -070074}
75
Andreas Huberc8e07e42012-12-20 13:49:34 -080076static void ReleaseMediaBufferReference(const sp<ABuffer> &accessUnit) {
77 void *mbuf;
78 if (accessUnit->meta()->findPointer("mediaBuffer", &mbuf)
79 && mbuf != NULL) {
80 ALOGV("releasing mbuf %p", mbuf);
81
82 accessUnit->meta()->setPointer("mediaBuffer", NULL);
83
84 static_cast<MediaBuffer *>(mbuf)->release();
85 mbuf = NULL;
86 }
87}
88
89void Converter::releaseEncoder() {
90 if (mEncoder == NULL) {
91 return;
92 }
93
94 mEncoder->release();
95 mEncoder.clear();
96
97 while (!mInputBufferQueue.empty()) {
98 sp<ABuffer> accessUnit = *mInputBufferQueue.begin();
99 mInputBufferQueue.erase(mInputBufferQueue.begin());
100
101 ReleaseMediaBufferReference(accessUnit);
102 }
103
104 for (size_t i = 0; i < mEncoderInputBuffers.size(); ++i) {
105 sp<ABuffer> accessUnit = mEncoderInputBuffers.itemAt(i);
106 ReleaseMediaBufferReference(accessUnit);
107 }
108
109 mEncoderInputBuffers.clear();
110 mEncoderOutputBuffers.clear();
111}
112
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700113Converter::~Converter() {
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700114 CHECK(mEncoder == NULL);
115}
Andreas Hubera4381232012-09-12 16:25:14 -0700116
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700117void Converter::shutdownAsync() {
118 ALOGV("shutdown");
119 (new AMessage(kWhatShutdown, id()))->post();
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700120}
121
122status_t Converter::initCheck() const {
123 return mInitCheck;
124}
125
Andreas Huber66e72bc2012-09-04 16:30:49 -0700126size_t Converter::getInputBufferCount() const {
127 return mEncoderInputBuffers.size();
128}
129
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700130sp<AMessage> Converter::getOutputFormat() const {
131 return mOutputFormat;
132}
133
Andreas Huber0224bf12012-11-12 13:08:44 -0800134bool Converter::needToManuallyPrependSPSPPS() const {
135 return mNeedToManuallyPrependSPSPPS;
136}
137
Andreas Huber44b59fd2012-09-12 14:06:17 -0700138static int32_t getBitrate(const char *propName, int32_t defaultValue) {
139 char val[PROPERTY_VALUE_MAX];
140 if (property_get(propName, val, NULL)) {
141 char *end;
142 unsigned long x = strtoul(val, &end, 10);
143
144 if (*end == '\0' && end > val && x > 0) {
145 return x;
146 }
147 }
148
149 return defaultValue;
150}
151
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700152status_t Converter::initEncoder() {
153 AString inputMIME;
154 CHECK(mInputFormat->findString("mime", &inputMIME));
155
156 AString outputMIME;
157 bool isAudio = false;
158 if (!strcasecmp(inputMIME.c_str(), MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Hubere7bd24a2012-10-04 11:46:29 -0700159 if (mIsPCMAudio) {
160 outputMIME = MEDIA_MIMETYPE_AUDIO_RAW;
161 } else {
162 outputMIME = MEDIA_MIMETYPE_AUDIO_AAC;
163 }
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700164 isAudio = true;
165 } else if (!strcasecmp(inputMIME.c_str(), MEDIA_MIMETYPE_VIDEO_RAW)) {
166 outputMIME = MEDIA_MIMETYPE_VIDEO_AVC;
167 } else {
168 TRESPASS();
169 }
170
Andreas Hubere7bd24a2012-10-04 11:46:29 -0700171 if (!mIsPCMAudio) {
172 mEncoder = MediaCodec::CreateByType(
173 mCodecLooper, outputMIME.c_str(), true /* encoder */);
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700174
Andreas Hubere7bd24a2012-10-04 11:46:29 -0700175 if (mEncoder == NULL) {
176 return ERROR_UNSUPPORTED;
177 }
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700178 }
179
180 mOutputFormat = mInputFormat->dup();
Andreas Hubere7bd24a2012-10-04 11:46:29 -0700181
182 if (mIsPCMAudio) {
183 return OK;
184 }
185
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700186 mOutputFormat->setString("mime", outputMIME.c_str());
187
Dave Burkef58cac42012-09-27 12:54:57 -0700188 int32_t audioBitrate = getBitrate("media.wfd.audio-bitrate", 128000);
Dave Burke2295ce22012-10-26 23:49:43 -0700189 int32_t videoBitrate = getBitrate("media.wfd.video-bitrate", 5000000);
Andreas Hubera2eb22c2013-02-07 10:56:14 -0800190 mPrevVideoBitrate = videoBitrate;
Andreas Huber44b59fd2012-09-12 14:06:17 -0700191
192 ALOGI("using audio bitrate of %d bps, video bitrate of %d bps",
193 audioBitrate, videoBitrate);
194
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700195 if (isAudio) {
Andreas Huber44b59fd2012-09-12 14:06:17 -0700196 mOutputFormat->setInt32("bitrate", audioBitrate);
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700197 } else {
Andreas Huber44b59fd2012-09-12 14:06:17 -0700198 mOutputFormat->setInt32("bitrate", videoBitrate);
Andreas Huber96076962012-11-01 15:48:44 -0700199 mOutputFormat->setInt32("bitrate-mode", OMX_Video_ControlRateConstant);
Andreas Huber4a8b9a22012-10-02 12:49:33 -0700200 mOutputFormat->setInt32("frame-rate", 30);
James Dong13e8a0e2012-11-15 18:31:50 -0800201 mOutputFormat->setInt32("i-frame-interval", 15); // Iframes every 15 secs
202
203 // Configure encoder to use intra macroblock refresh mode
204 mOutputFormat->setInt32("intra-refresh-mode", OMX_VIDEO_IntraRefreshCyclic);
205
206 int width, height, mbs;
207 if (!mOutputFormat->findInt32("width", &width)
208 || !mOutputFormat->findInt32("height", &height)) {
209 return ERROR_UNSUPPORTED;
210 }
211
212 // Update macroblocks in a cyclic fashion with 10% of all MBs within
213 // frame gets updated at one time. It takes about 10 frames to
214 // completely update a whole video frame. If the frame rate is 30,
215 // it takes about 333 ms in the best case (if next frame is not an IDR)
216 // to recover from a lost/corrupted packet.
217 mbs = (((width + 15) / 16) * ((height + 15) / 16) * 10) / 100;
218 mOutputFormat->setInt32("intra-refresh-CIR-mbs", mbs);
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700219 }
220
221 ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
222
Andreas Huber0224bf12012-11-12 13:08:44 -0800223 mNeedToManuallyPrependSPSPPS = false;
224
225 status_t err = NO_INIT;
226
227 if (!isAudio) {
228 sp<AMessage> tmp = mOutputFormat->dup();
229 tmp->setInt32("prepend-sps-pps-to-idr-frames", 1);
230
231 err = mEncoder->configure(
232 tmp,
233 NULL /* nativeWindow */,
234 NULL /* crypto */,
235 MediaCodec::CONFIGURE_FLAG_ENCODE);
236
237 if (err == OK) {
238 // Encoder supported prepending SPS/PPS, we don't need to emulate
239 // it.
240 mOutputFormat = tmp;
241 } else {
242 mNeedToManuallyPrependSPSPPS = true;
243
244 ALOGI("We going to manually prepend SPS and PPS to IDR frames.");
245 }
246 }
247
248 if (err != OK) {
249 // We'll get here for audio or if we failed to configure the encoder
250 // to automatically prepend SPS/PPS in the case of video.
251
252 err = mEncoder->configure(
253 mOutputFormat,
254 NULL /* nativeWindow */,
255 NULL /* crypto */,
256 MediaCodec::CONFIGURE_FLAG_ENCODE);
257 }
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700258
259 if (err != OK) {
260 return err;
261 }
262
263 err = mEncoder->start();
264
265 if (err != OK) {
266 return err;
267 }
268
269 err = mEncoder->getInputBuffers(&mEncoderInputBuffers);
270
271 if (err != OK) {
272 return err;
273 }
274
275 return mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
276}
277
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700278void Converter::notifyError(status_t err) {
279 sp<AMessage> notify = mNotify->dup();
280 notify->setInt32("what", kWhatError);
281 notify->setInt32("err", err);
282 notify->post();
283}
284
Andreas Hubercf2604f2012-10-02 14:17:38 -0700285// static
286bool Converter::IsSilence(const sp<ABuffer> &accessUnit) {
287 const uint8_t *ptr = accessUnit->data();
288 const uint8_t *end = ptr + accessUnit->size();
289 while (ptr < end) {
290 if (*ptr != 0) {
291 return false;
292 }
293 ++ptr;
294 }
295
296 return true;
297}
298
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700299void Converter::onMessageReceived(const sp<AMessage> &msg) {
300 switch (msg->what()) {
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700301 case kWhatMediaPullerNotify:
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700302 {
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700303 int32_t what;
304 CHECK(msg->findInt32("what", &what));
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700305
Andreas Hubere7bd24a2012-10-04 11:46:29 -0700306 if (!mIsPCMAudio && mEncoder == NULL) {
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700307 ALOGV("got msg '%s' after encoder shutdown.",
308 msg->debugString().c_str());
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700309
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700310 if (what == MediaPuller::kWhatAccessUnit) {
311 sp<ABuffer> accessUnit;
312 CHECK(msg->findBuffer("accessUnit", &accessUnit));
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700313
Andreas Huberc8e07e42012-12-20 13:49:34 -0800314 ReleaseMediaBufferReference(accessUnit);
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700315 }
316 break;
317 }
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700318
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700319 if (what == MediaPuller::kWhatEOS) {
320 mInputBufferQueue.push_back(NULL);
321
322 feedEncoderInputBuffers();
323
324 scheduleDoMoreWork();
325 } else {
326 CHECK_EQ(what, MediaPuller::kWhatAccessUnit);
327
328 sp<ABuffer> accessUnit;
329 CHECK(msg->findBuffer("accessUnit", &accessUnit));
330
Andreas Huber126568c2013-03-12 15:55:43 -0700331 if (mIsVideo && mNumFramesToDrop) {
332 --mNumFramesToDrop;
333 ALOGI("dropping frame.");
334 ReleaseMediaBufferReference(accessUnit);
335 break;
336 }
337
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700338#if 0
339 void *mbuf;
340 if (accessUnit->meta()->findPointer("mediaBuffer", &mbuf)
341 && mbuf != NULL) {
342 ALOGI("queueing mbuf %p", mbuf);
343 }
344#endif
345
Andreas Hubercf2604f2012-10-02 14:17:38 -0700346#if ENABLE_SILENCE_DETECTION
347 if (!mIsVideo) {
348 if (IsSilence(accessUnit)) {
Andreas Huber8d16bbc2012-10-03 09:01:11 -0700349 if (mInSilentMode) {
350 break;
351 }
Andreas Hubercf2604f2012-10-02 14:17:38 -0700352
Andreas Huber8d16bbc2012-10-03 09:01:11 -0700353 int64_t nowUs = ALooper::GetNowUs();
354
355 if (mFirstSilentFrameUs < 0ll) {
356 mFirstSilentFrameUs = nowUs;
357 } else if (nowUs >= mFirstSilentFrameUs + 10000000ll) {
358 mInSilentMode = true;
359 ALOGI("audio in silent mode now.");
360 break;
Andreas Hubercf2604f2012-10-02 14:17:38 -0700361 }
362 } else {
363 if (mInSilentMode) {
364 ALOGI("audio no longer in silent mode.");
365 }
366 mInSilentMode = false;
367 mFirstSilentFrameUs = -1ll;
368 }
369 }
370#endif
371
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700372 mInputBufferQueue.push_back(accessUnit);
373
374 feedEncoderInputBuffers();
375
376 scheduleDoMoreWork();
377 }
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700378 break;
379 }
380
Andreas Huber575a5362012-10-03 10:16:58 -0700381 case kWhatEncoderActivity:
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700382 {
Andreas Huber575a5362012-10-03 10:16:58 -0700383#if 0
384 int64_t whenUs;
385 if (msg->findInt64("whenUs", &whenUs)) {
386 int64_t nowUs = ALooper::GetNowUs();
387 ALOGI("[%s] kWhatEncoderActivity after %lld us",
388 mIsVideo ? "video" : "audio", nowUs - whenUs);
389 }
390#endif
391
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700392 mDoMoreWorkPending = false;
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700393
394 if (mEncoder == NULL) {
395 break;
396 }
397
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700398 status_t err = doMoreWork();
399
400 if (err != OK) {
401 notifyError(err);
402 } else {
403 scheduleDoMoreWork();
404 }
405 break;
406 }
407
Andreas Huber496238c2012-09-13 16:43:51 -0700408 case kWhatRequestIDRFrame:
409 {
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700410 if (mEncoder == NULL) {
411 break;
412 }
413
Andreas Huber496238c2012-09-13 16:43:51 -0700414 if (mIsVideo) {
415 ALOGI("requesting IDR frame");
416 mEncoder->requestIDRFrame();
417 }
418 break;
419 }
420
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700421 case kWhatShutdown:
422 {
Andreas Huberc8e07e42012-12-20 13:49:34 -0800423 ALOGI("shutting down %s encoder", mIsVideo ? "video" : "audio");
Andreas Hubere7bd24a2012-10-04 11:46:29 -0700424
Andreas Huberc8e07e42012-12-20 13:49:34 -0800425 releaseEncoder();
Andreas Huber96fc6cc2012-09-28 10:23:51 -0700426
427 AString mime;
428 CHECK(mInputFormat->findString("mime", &mime));
429 ALOGI("encoder (%s) shut down.", mime.c_str());
430 break;
431 }
432
Andreas Huber126568c2013-03-12 15:55:43 -0700433 case kWhatDropAFrame:
434 {
435 ++mNumFramesToDrop;
436 break;
437 }
438
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700439 default:
440 TRESPASS();
441 }
442}
443
444void Converter::scheduleDoMoreWork() {
Andreas Hubere7bd24a2012-10-04 11:46:29 -0700445 if (mIsPCMAudio) {
446 // There's no encoder involved in this case.
447 return;
448 }
449
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700450 if (mDoMoreWorkPending) {
451 return;
452 }
453
454 mDoMoreWorkPending = true;
Andreas Huber575a5362012-10-03 10:16:58 -0700455
456#if 1
457 if (mEncoderActivityNotify == NULL) {
458 mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, id());
459 }
460 mEncoder->requestActivityNotification(mEncoderActivityNotify->dup());
461#else
462 sp<AMessage> notify = new AMessage(kWhatEncoderActivity, id());
463 notify->setInt64("whenUs", ALooper::GetNowUs());
464 mEncoder->requestActivityNotification(notify);
465#endif
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700466}
467
Andreas Hubere7bd24a2012-10-04 11:46:29 -0700468status_t Converter::feedRawAudioInputBuffers() {
469 // Split incoming PCM audio into buffers of 6 AUs of 80 audio frames each
470 // and add a 4 byte header according to the wifi display specs.
471
472 while (!mInputBufferQueue.empty()) {
473 sp<ABuffer> buffer = *mInputBufferQueue.begin();
474 mInputBufferQueue.erase(mInputBufferQueue.begin());
475
476 int16_t *ptr = (int16_t *)buffer->data();
477 int16_t *stop = (int16_t *)(buffer->data() + buffer->size());
478 while (ptr < stop) {
479 *ptr = htons(*ptr);
480 ++ptr;
481 }
482
483 static const size_t kFrameSize = 2 * sizeof(int16_t); // stereo
484 static const size_t kFramesPerAU = 80;
485 static const size_t kNumAUsPerPESPacket = 6;
486
487 if (mPartialAudioAU != NULL) {
488 size_t bytesMissingForFullAU =
489 kNumAUsPerPESPacket * kFramesPerAU * kFrameSize
490 - mPartialAudioAU->size() + 4;
491
492 size_t copy = buffer->size();
493 if(copy > bytesMissingForFullAU) {
494 copy = bytesMissingForFullAU;
495 }
496
497 memcpy(mPartialAudioAU->data() + mPartialAudioAU->size(),
498 buffer->data(),
499 copy);
500
501 mPartialAudioAU->setRange(0, mPartialAudioAU->size() + copy);
502
503 buffer->setRange(buffer->offset() + copy, buffer->size() - copy);
504
505 int64_t timeUs;
506 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
507
508 int64_t copyUs = (int64_t)((copy / kFrameSize) * 1E6 / 48000.0);
509 timeUs += copyUs;
510 buffer->meta()->setInt64("timeUs", timeUs);
511
512 if (bytesMissingForFullAU == copy) {
513 sp<AMessage> notify = mNotify->dup();
514 notify->setInt32("what", kWhatAccessUnit);
515 notify->setBuffer("accessUnit", mPartialAudioAU);
516 notify->post();
517
518 mPartialAudioAU.clear();
519 }
520 }
521
522 while (buffer->size() > 0) {
523 sp<ABuffer> partialAudioAU =
524 new ABuffer(
525 4
526 + kNumAUsPerPESPacket * kFrameSize * kFramesPerAU);
527
528 uint8_t *ptr = partialAudioAU->data();
529 ptr[0] = 0xa0; // 10100000b
530 ptr[1] = kNumAUsPerPESPacket;
531 ptr[2] = 0; // reserved, audio _emphasis_flag = 0
532
533 static const unsigned kQuantizationWordLength = 0; // 16-bit
534 static const unsigned kAudioSamplingFrequency = 2; // 48Khz
535 static const unsigned kNumberOfAudioChannels = 1; // stereo
536
537 ptr[3] = (kQuantizationWordLength << 6)
538 | (kAudioSamplingFrequency << 3)
539 | kNumberOfAudioChannels;
540
541 size_t copy = buffer->size();
542 if (copy > partialAudioAU->size() - 4) {
543 copy = partialAudioAU->size() - 4;
544 }
545
546 memcpy(&ptr[4], buffer->data(), copy);
547
548 partialAudioAU->setRange(0, 4 + copy);
549 buffer->setRange(buffer->offset() + copy, buffer->size() - copy);
550
551 int64_t timeUs;
552 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
553
554 partialAudioAU->meta()->setInt64("timeUs", timeUs);
555
556 int64_t copyUs = (int64_t)((copy / kFrameSize) * 1E6 / 48000.0);
557 timeUs += copyUs;
558 buffer->meta()->setInt64("timeUs", timeUs);
559
Andreas Huber90a92052012-10-30 15:53:03 -0700560 if (copy == partialAudioAU->capacity() - 4) {
Andreas Hubere7bd24a2012-10-04 11:46:29 -0700561 sp<AMessage> notify = mNotify->dup();
562 notify->setInt32("what", kWhatAccessUnit);
563 notify->setBuffer("accessUnit", partialAudioAU);
564 notify->post();
565
566 partialAudioAU.clear();
567 continue;
568 }
569
570 mPartialAudioAU = partialAudioAU;
571 }
572 }
573
574 return OK;
575}
576
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700577status_t Converter::feedEncoderInputBuffers() {
Andreas Hubere7bd24a2012-10-04 11:46:29 -0700578 if (mIsPCMAudio) {
579 return feedRawAudioInputBuffers();
580 }
581
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700582 while (!mInputBufferQueue.empty()
583 && !mAvailEncoderInputIndices.empty()) {
584 sp<ABuffer> buffer = *mInputBufferQueue.begin();
585 mInputBufferQueue.erase(mInputBufferQueue.begin());
586
587 size_t bufferIndex = *mAvailEncoderInputIndices.begin();
588 mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
589
590 int64_t timeUs = 0ll;
591 uint32_t flags = 0;
592
593 if (buffer != NULL) {
594 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
595
596 memcpy(mEncoderInputBuffers.itemAt(bufferIndex)->data(),
597 buffer->data(),
598 buffer->size());
599
600 void *mediaBuffer;
601 if (buffer->meta()->findPointer("mediaBuffer", &mediaBuffer)
602 && mediaBuffer != NULL) {
603 mEncoderInputBuffers.itemAt(bufferIndex)->meta()
604 ->setPointer("mediaBuffer", mediaBuffer);
605
606 buffer->meta()->setPointer("mediaBuffer", NULL);
607 }
608 } else {
609 flags = MediaCodec::BUFFER_FLAG_EOS;
610 }
611
612 status_t err = mEncoder->queueInputBuffer(
613 bufferIndex, 0, (buffer == NULL) ? 0 : buffer->size(),
614 timeUs, flags);
615
616 if (err != OK) {
617 return err;
618 }
619 }
620
621 return OK;
622}
623
624status_t Converter::doMoreWork() {
Andreas Hubera2eb22c2013-02-07 10:56:14 -0800625 if (mIsVideo) {
626 int32_t videoBitrate = getBitrate("media.wfd.video-bitrate", 5000000);
627 if (videoBitrate != mPrevVideoBitrate) {
628 sp<AMessage> params = new AMessage;
629
630 params->setInt32("videoBitrate", videoBitrate);
631 mEncoder->setParameters(params);
632
633 mPrevVideoBitrate = videoBitrate;
634 }
635 }
636
Andreas Huber575a5362012-10-03 10:16:58 -0700637 status_t err;
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700638
Andreas Hubercf2604f2012-10-02 14:17:38 -0700639 for (;;) {
Andreas Huber575a5362012-10-03 10:16:58 -0700640 size_t bufferIndex;
641 err = mEncoder->dequeueInputBuffer(&bufferIndex);
642
643 if (err != OK) {
644 break;
645 }
646
647 mAvailEncoderInputIndices.push_back(bufferIndex);
648 }
649
650 feedEncoderInputBuffers();
651
652 for (;;) {
653 size_t bufferIndex;
Andreas Hubercf2604f2012-10-02 14:17:38 -0700654 size_t offset;
655 size_t size;
656 int64_t timeUs;
657 uint32_t flags;
658 err = mEncoder->dequeueOutputBuffer(
659 &bufferIndex, &offset, &size, &timeUs, &flags);
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700660
Andreas Hubercf2604f2012-10-02 14:17:38 -0700661 if (err != OK) {
662 if (err == -EAGAIN) {
663 err = OK;
664 }
665 break;
666 }
667
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700668 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
669 sp<AMessage> notify = mNotify->dup();
670 notify->setInt32("what", kWhatEOS);
671 notify->post();
672 } else {
673 sp<ABuffer> buffer = new ABuffer(size);
674 buffer->meta()->setInt64("timeUs", timeUs);
675
Andreas Huber8d16bbc2012-10-03 09:01:11 -0700676 ALOGV("[%s] time %lld us (%.2f secs)",
677 mIsVideo ? "video" : "audio", timeUs, timeUs / 1E6);
Andreas Hubercf2604f2012-10-02 14:17:38 -0700678
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700679 memcpy(buffer->data(),
680 mEncoderOutputBuffers.itemAt(bufferIndex)->base() + offset,
681 size);
682
683 if (flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) {
684 mOutputFormat->setBuffer("csd-0", buffer);
685 } else {
686 sp<AMessage> notify = mNotify->dup();
687 notify->setInt32("what", kWhatAccessUnit);
688 notify->setBuffer("accessUnit", buffer);
689 notify->post();
690 }
691 }
692
Andreas Hubercf2604f2012-10-02 14:17:38 -0700693 mEncoder->releaseOutputBuffer(bufferIndex);
694
695 if (flags & MediaCodec::BUFFER_FLAG_EOS) {
696 break;
697 }
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700698 }
699
700 return err;
701}
702
Andreas Huber496238c2012-09-13 16:43:51 -0700703void Converter::requestIDRFrame() {
704 (new AMessage(kWhatRequestIDRFrame, id()))->post();
705}
706
Andreas Huber126568c2013-03-12 15:55:43 -0700707void Converter::dropAFrame() {
708 (new AMessage(kWhatDropAFrame, id()))->post();
709}
710
Andreas Huberd7bee3a2012-08-29 11:41:50 -0700711} // namespace android