1/*
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
23#include "MediaPuller.h"
24#include "include/avc_utils.h"
25
26#include <cutils/properties.h>
27#include <gui/Surface.h>
28#include <media/ICrypto.h>
29#include <media/MediaCodecBuffer.h>
30#include <media/stagefright/foundation/ABuffer.h>
31#include <media/stagefright/foundation/ADebug.h>
32#include <media/stagefright/foundation/AMessage.h>
33#include <media/stagefright/MediaBuffer.h>
34#include <media/stagefright/MediaCodec.h>
35#include <media/stagefright/MediaDefs.h>
36#include <media/stagefright/MediaErrors.h>
37
38#include <arpa/inet.h>
39
40#include <OMX_Video.h>
41
42namespace android {
43
44Converter::Converter(
45        const sp<AMessage> &notify,
46        const sp<ALooper> &codecLooper,
47        const sp<AMessage> &outputFormat,
48        uint32_t flags)
49    : mNotify(notify),
50      mCodecLooper(codecLooper),
51      mOutputFormat(outputFormat),
52      mFlags(flags),
53      mIsVideo(false),
54      mIsH264(false),
55      mIsPCMAudio(false),
56      mNeedToManuallyPrependSPSPPS(false),
57      mDoMoreWorkPending(false)
58#if ENABLE_SILENCE_DETECTION
59      ,mFirstSilentFrameUs(-1ll)
60      ,mInSilentMode(false)
61#endif
62      ,mPrevVideoBitrate(-1)
63      ,mNumFramesToDrop(0)
64      ,mEncodingSuspended(false)
65    {
66    AString mime;
67    CHECK(mOutputFormat->findString("mime", &mime));
68
69    if (!strncasecmp("video/", mime.c_str(), 6)) {
70        mIsVideo = true;
71
72        mIsH264 = !strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC);
73    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime.c_str())) {
74        mIsPCMAudio = true;
75    }
76}
77
78void Converter::releaseEncoder() {
79    if (mEncoder == NULL) {
80        return;
81    }
82
83    mEncoder->release();
84    mEncoder.clear();
85
86    mInputBufferQueue.clear();
87    mEncoderInputBuffers.clear();
88    mEncoderOutputBuffers.clear();
89}
90
91Converter::~Converter() {
92    CHECK(mEncoder == NULL);
93}
94
95void Converter::shutdownAsync() {
96    ALOGV("shutdown");
97    (new AMessage(kWhatShutdown, this))->post();
98}
99
100status_t Converter::init() {
101    status_t err = initEncoder();
102
103    if (err != OK) {
104        releaseEncoder();
105    }
106
107    return err;
108}
109
110sp<IGraphicBufferProducer> Converter::getGraphicBufferProducer() {
111    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
112    return mGraphicBufferProducer;
113}
114
115size_t Converter::getInputBufferCount() const {
116    return mEncoderInputBuffers.size();
117}
118
119sp<AMessage> Converter::getOutputFormat() const {
120    return mOutputFormat;
121}
122
123bool Converter::needToManuallyPrependSPSPPS() const {
124    return mNeedToManuallyPrependSPSPPS;
125}
126
127// static
128int32_t Converter::GetInt32Property(
129        const char *propName, int32_t defaultValue) {
130    char val[PROPERTY_VALUE_MAX];
131    if (property_get(propName, val, NULL)) {
132        char *end;
133        unsigned long x = strtoul(val, &end, 10);
134
135        if (*end == '\0' && end > val && x > 0) {
136            return x;
137        }
138    }
139
140    return defaultValue;
141}
142
143status_t Converter::initEncoder() {
144    AString outputMIME;
145    CHECK(mOutputFormat->findString("mime", &outputMIME));
146
147    bool isAudio = !strncasecmp(outputMIME.c_str(), "audio/", 6);
148
149    if (!mIsPCMAudio) {
150        mEncoder = MediaCodec::CreateByType(
151                mCodecLooper, outputMIME.c_str(), true /* encoder */);
152
153        if (mEncoder == NULL) {
154            return ERROR_UNSUPPORTED;
155        }
156    }
157
158    if (mIsPCMAudio) {
159        return OK;
160    }
161
162    int32_t audioBitrate = GetInt32Property("media.wfd.audio-bitrate", 128000);
163    int32_t videoBitrate = GetInt32Property("media.wfd.video-bitrate", 5000000);
164    mPrevVideoBitrate = videoBitrate;
165
166    ALOGI("using audio bitrate of %d bps, video bitrate of %d bps",
167          audioBitrate, videoBitrate);
168
169    if (isAudio) {
170        mOutputFormat->setInt32("bitrate", audioBitrate);
171    } else {
172        mOutputFormat->setInt32("bitrate", videoBitrate);
173        mOutputFormat->setInt32("bitrate-mode", OMX_Video_ControlRateConstant);
174        mOutputFormat->setInt32("frame-rate", 30);
175        mOutputFormat->setInt32("i-frame-interval", 15);  // Iframes every 15 secs
176
177        // Configure encoder to use intra macroblock refresh mode
178        mOutputFormat->setInt32("intra-refresh-mode", OMX_VIDEO_IntraRefreshCyclic);
179
180        int width, height, mbs;
181        if (!mOutputFormat->findInt32("width", &width)
182                || !mOutputFormat->findInt32("height", &height)) {
183            return ERROR_UNSUPPORTED;
184        }
185
186        // Update macroblocks in a cyclic fashion with 10% of all MBs within
187        // frame gets updated at one time. It takes about 10 frames to
188        // completely update a whole video frame. If the frame rate is 30,
189        // it takes about 333 ms in the best case (if next frame is not an IDR)
190        // to recover from a lost/corrupted packet.
191        mbs = (((width + 15) / 16) * ((height + 15) / 16) * 10) / 100;
192        mOutputFormat->setInt32("intra-refresh-CIR-mbs", mbs);
193    }
194
195    ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
196
197    mNeedToManuallyPrependSPSPPS = false;
198
199    status_t err = NO_INIT;
200
201    if (!isAudio) {
202        sp<AMessage> tmp = mOutputFormat->dup();
203        tmp->setInt32("prepend-sps-pps-to-idr-frames", 1);
204
205        err = mEncoder->configure(
206                tmp,
207                NULL /* nativeWindow */,
208                NULL /* crypto */,
209                MediaCodec::CONFIGURE_FLAG_ENCODE);
210
211        if (err == OK) {
212            // Encoder supported prepending SPS/PPS, we don't need to emulate
213            // it.
214            mOutputFormat = tmp;
215        } else {
216            mNeedToManuallyPrependSPSPPS = true;
217
218            ALOGI("We going to manually prepend SPS and PPS to IDR frames.");
219        }
220    }
221
222    if (err != OK) {
223        // We'll get here for audio or if we failed to configure the encoder
224        // to automatically prepend SPS/PPS in the case of video.
225
226        err = mEncoder->configure(
227                    mOutputFormat,
228                    NULL /* nativeWindow */,
229                    NULL /* crypto */,
230                    MediaCodec::CONFIGURE_FLAG_ENCODE);
231    }
232
233    if (err != OK) {
234        return err;
235    }
236
237    if (mFlags & FLAG_USE_SURFACE_INPUT) {
238        CHECK(mIsVideo);
239
240        err = mEncoder->createInputSurface(&mGraphicBufferProducer);
241
242        if (err != OK) {
243            return err;
244        }
245    }
246
247    err = mEncoder->start();
248
249    if (err != OK) {
250        return err;
251    }
252
253    err = mEncoder->getInputBuffers(&mEncoderInputBuffers);
254
255    if (err != OK) {
256        return err;
257    }
258
259    err = mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
260
261    if (err != OK) {
262        return err;
263    }
264
265    if (mFlags & FLAG_USE_SURFACE_INPUT) {
266        scheduleDoMoreWork();
267    }
268
269    return OK;
270}
271
272void Converter::notifyError(status_t err) {
273    sp<AMessage> notify = mNotify->dup();
274    notify->setInt32("what", kWhatError);
275    notify->setInt32("err", err);
276    notify->post();
277}
278
279// static
280bool Converter::IsSilence(const sp<ABuffer> &accessUnit) {
281    const uint8_t *ptr = accessUnit->data();
282    const uint8_t *end = ptr + accessUnit->size();
283    while (ptr < end) {
284        if (*ptr != 0) {
285            return false;
286        }
287        ++ptr;
288    }
289
290    return true;
291}
292
293void Converter::onMessageReceived(const sp<AMessage> &msg) {
294    switch (msg->what()) {
295        case kWhatMediaPullerNotify:
296        {
297            int32_t what;
298            CHECK(msg->findInt32("what", &what));
299
300            if (!mIsPCMAudio && mEncoder == NULL) {
301                ALOGV("got msg '%s' after encoder shutdown.",
302                      msg->debugString().c_str());
303
304                if (what == MediaPuller::kWhatAccessUnit) {
305                    sp<ABuffer> accessUnit;
306                    CHECK(msg->findBuffer("accessUnit", &accessUnit));
307
308                    accessUnit->setMediaBufferBase(NULL);
309                }
310                break;
311            }
312
313            if (what == MediaPuller::kWhatEOS) {
314                mInputBufferQueue.push_back(NULL);
315
316                feedEncoderInputBuffers();
317
318                scheduleDoMoreWork();
319            } else {
320                CHECK_EQ(what, MediaPuller::kWhatAccessUnit);
321
322                sp<ABuffer> accessUnit;
323                CHECK(msg->findBuffer("accessUnit", &accessUnit));
324
325                if (mNumFramesToDrop > 0 || mEncodingSuspended) {
326                    if (mNumFramesToDrop > 0) {
327                        --mNumFramesToDrop;
328                        ALOGI("dropping frame.");
329                    }
330
331                    accessUnit->setMediaBufferBase(NULL);
332                    break;
333                }
334
335#if 0
336                MediaBuffer *mbuf =
337                    (MediaBuffer *)(accessUnit->getMediaBufferBase());
338                if (mbuf != NULL) {
339                    ALOGI("queueing mbuf %p", mbuf);
340                    mbuf->release();
341                }
342#endif
343
344#if ENABLE_SILENCE_DETECTION
345                if (!mIsVideo) {
346                    if (IsSilence(accessUnit)) {
347                        if (mInSilentMode) {
348                            break;
349                        }
350
351                        int64_t nowUs = ALooper::GetNowUs();
352
353                        if (mFirstSilentFrameUs < 0ll) {
354                            mFirstSilentFrameUs = nowUs;
355                        } else if (nowUs >= mFirstSilentFrameUs + 10000000ll) {
356                            mInSilentMode = true;
357                            ALOGI("audio in silent mode now.");
358                            break;
359                        }
360                    } else {
361                        if (mInSilentMode) {
362                            ALOGI("audio no longer in silent mode.");
363                        }
364                        mInSilentMode = false;
365                        mFirstSilentFrameUs = -1ll;
366                    }
367                }
368#endif
369
370                mInputBufferQueue.push_back(accessUnit);
371
372                feedEncoderInputBuffers();
373
374                scheduleDoMoreWork();
375            }
376            break;
377        }
378
379        case kWhatEncoderActivity:
380        {
381#if 0
382            int64_t whenUs;
383            if (msg->findInt64("whenUs", &whenUs)) {
384                int64_t nowUs = ALooper::GetNowUs();
385                ALOGI("[%s] kWhatEncoderActivity after %lld us",
386                      mIsVideo ? "video" : "audio", nowUs - whenUs);
387            }
388#endif
389
390            mDoMoreWorkPending = false;
391
392            if (mEncoder == NULL) {
393                break;
394            }
395
396            status_t err = doMoreWork();
397
398            if (err != OK) {
399                notifyError(err);
400            } else {
401                scheduleDoMoreWork();
402            }
403            break;
404        }
405
406        case kWhatRequestIDRFrame:
407        {
408            if (mEncoder == NULL) {
409                break;
410            }
411
412            if (mIsVideo) {
413                ALOGV("requesting IDR frame");
414                mEncoder->requestIDRFrame();
415            }
416            break;
417        }
418
419        case kWhatShutdown:
420        {
421            ALOGI("shutting down %s encoder", mIsVideo ? "video" : "audio");
422
423            releaseEncoder();
424
425            AString mime;
426            CHECK(mOutputFormat->findString("mime", &mime));
427            ALOGI("encoder (%s) shut down.", mime.c_str());
428
429            sp<AMessage> notify = mNotify->dup();
430            notify->setInt32("what", kWhatShutdownCompleted);
431            notify->post();
432            break;
433        }
434
435        case kWhatDropAFrame:
436        {
437            ++mNumFramesToDrop;
438            break;
439        }
440
441        case kWhatReleaseOutputBuffer:
442        {
443            if (mEncoder != NULL) {
444                size_t bufferIndex;
445                CHECK(msg->findInt32("bufferIndex", (int32_t*)&bufferIndex));
446                CHECK(bufferIndex < mEncoderOutputBuffers.size());
447                mEncoder->releaseOutputBuffer(bufferIndex);
448            }
449            break;
450        }
451
452        case kWhatSuspendEncoding:
453        {
454            int32_t suspend;
455            CHECK(msg->findInt32("suspend", &suspend));
456
457            mEncodingSuspended = suspend;
458
459            if (mFlags & FLAG_USE_SURFACE_INPUT) {
460                sp<AMessage> params = new AMessage;
461                params->setInt32("drop-input-frames",suspend);
462                mEncoder->setParameters(params);
463            }
464            break;
465        }
466
467        default:
468            TRESPASS();
469    }
470}
471
472void Converter::scheduleDoMoreWork() {
473    if (mIsPCMAudio) {
474        // There's no encoder involved in this case.
475        return;
476    }
477
478    if (mDoMoreWorkPending) {
479        return;
480    }
481
482    mDoMoreWorkPending = true;
483
484#if 1
485    if (mEncoderActivityNotify == NULL) {
486        mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, this);
487    }
488    mEncoder->requestActivityNotification(mEncoderActivityNotify->dup());
489#else
490    sp<AMessage> notify = new AMessage(kWhatEncoderActivity, this);
491    notify->setInt64("whenUs", ALooper::GetNowUs());
492    mEncoder->requestActivityNotification(notify);
493#endif
494}
495
496status_t Converter::feedRawAudioInputBuffers() {
497    // Split incoming PCM audio into buffers of 6 AUs of 80 audio frames each
498    // and add a 4 byte header according to the wifi display specs.
499
500    while (!mInputBufferQueue.empty()) {
501        sp<ABuffer> buffer = *mInputBufferQueue.begin();
502        mInputBufferQueue.erase(mInputBufferQueue.begin());
503
504        int16_t *ptr = (int16_t *)buffer->data();
505        int16_t *stop = (int16_t *)(buffer->data() + buffer->size());
506        while (ptr < stop) {
507            *ptr = htons(*ptr);
508            ++ptr;
509        }
510
511        static const size_t kFrameSize = 2 * sizeof(int16_t);  // stereo
512        static const size_t kFramesPerAU = 80;
513        static const size_t kNumAUsPerPESPacket = 6;
514
515        if (mPartialAudioAU != NULL) {
516            size_t bytesMissingForFullAU =
517                kNumAUsPerPESPacket * kFramesPerAU * kFrameSize
518                - mPartialAudioAU->size() + 4;
519
520            size_t copy = buffer->size();
521            if(copy > bytesMissingForFullAU) {
522                copy = bytesMissingForFullAU;
523            }
524
525            memcpy(mPartialAudioAU->data() + mPartialAudioAU->size(),
526                   buffer->data(),
527                   copy);
528
529            mPartialAudioAU->setRange(0, mPartialAudioAU->size() + copy);
530
531            buffer->setRange(buffer->offset() + copy, buffer->size() - copy);
532
533            int64_t timeUs;
534            CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
535
536            int64_t copyUs = (int64_t)((copy / kFrameSize) * 1E6 / 48000.0);
537            timeUs += copyUs;
538            buffer->meta()->setInt64("timeUs", timeUs);
539
540            if (bytesMissingForFullAU == copy) {
541                sp<AMessage> notify = mNotify->dup();
542                notify->setInt32("what", kWhatAccessUnit);
543                notify->setBuffer("accessUnit", mPartialAudioAU);
544                notify->post();
545
546                mPartialAudioAU.clear();
547            }
548        }
549
550        while (buffer->size() > 0) {
551            sp<ABuffer> partialAudioAU =
552                new ABuffer(
553                        4
554                        + kNumAUsPerPESPacket * kFrameSize * kFramesPerAU);
555
556            uint8_t *ptr = partialAudioAU->data();
557            ptr[0] = 0xa0;  // 10100000b
558            ptr[1] = kNumAUsPerPESPacket;
559            ptr[2] = 0;  // reserved, audio _emphasis_flag = 0
560
561            static const unsigned kQuantizationWordLength = 0;  // 16-bit
562            static const unsigned kAudioSamplingFrequency = 2;  // 48Khz
563            static const unsigned kNumberOfAudioChannels = 1;  // stereo
564
565            ptr[3] = (kQuantizationWordLength << 6)
566                    | (kAudioSamplingFrequency << 3)
567                    | kNumberOfAudioChannels;
568
569            size_t copy = buffer->size();
570            if (copy > partialAudioAU->size() - 4) {
571                copy = partialAudioAU->size() - 4;
572            }
573
574            memcpy(&ptr[4], buffer->data(), copy);
575
576            partialAudioAU->setRange(0, 4 + copy);
577            buffer->setRange(buffer->offset() + copy, buffer->size() - copy);
578
579            int64_t timeUs;
580            CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
581
582            partialAudioAU->meta()->setInt64("timeUs", timeUs);
583
584            int64_t copyUs = (int64_t)((copy / kFrameSize) * 1E6 / 48000.0);
585            timeUs += copyUs;
586            buffer->meta()->setInt64("timeUs", timeUs);
587
588            if (copy == partialAudioAU->capacity() - 4) {
589                sp<AMessage> notify = mNotify->dup();
590                notify->setInt32("what", kWhatAccessUnit);
591                notify->setBuffer("accessUnit", partialAudioAU);
592                notify->post();
593
594                partialAudioAU.clear();
595                continue;
596            }
597
598            mPartialAudioAU = partialAudioAU;
599        }
600    }
601
602    return OK;
603}
604
605status_t Converter::feedEncoderInputBuffers() {
606    if (mIsPCMAudio) {
607        return feedRawAudioInputBuffers();
608    }
609
610    while (!mInputBufferQueue.empty()
611            && !mAvailEncoderInputIndices.empty()) {
612        sp<ABuffer> buffer = *mInputBufferQueue.begin();
613        mInputBufferQueue.erase(mInputBufferQueue.begin());
614
615        size_t bufferIndex = *mAvailEncoderInputIndices.begin();
616        mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
617
618        int64_t timeUs = 0ll;
619        uint32_t flags = 0;
620
621        if (buffer != NULL) {
622            CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
623
624            memcpy(mEncoderInputBuffers.itemAt(bufferIndex)->data(),
625                   buffer->data(),
626                   buffer->size());
627
628            MediaBuffer *mediaBuffer =
629                (MediaBuffer *)(buffer->getMediaBufferBase());
630            if (mediaBuffer != NULL) {
631                mEncoderInputBuffers.itemAt(bufferIndex)->setMediaBufferBase(
632                        mediaBuffer);
633
634                buffer->setMediaBufferBase(NULL);
635            }
636        } else {
637            flags = MediaCodec::BUFFER_FLAG_EOS;
638        }
639
640        status_t err = mEncoder->queueInputBuffer(
641                bufferIndex, 0, (buffer == NULL) ? 0 : buffer->size(),
642                timeUs, flags);
643
644        if (err != OK) {
645            return err;
646        }
647    }
648
649    return OK;
650}
651
652sp<ABuffer> Converter::prependCSD(const sp<ABuffer> &accessUnit) const {
653    CHECK(mCSD0 != NULL);
654
655    sp<ABuffer> dup = new ABuffer(accessUnit->size() + mCSD0->size());
656    memcpy(dup->data(), mCSD0->data(), mCSD0->size());
657    memcpy(dup->data() + mCSD0->size(), accessUnit->data(), accessUnit->size());
658
659    int64_t timeUs;
660    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
661
662    dup->meta()->setInt64("timeUs", timeUs);
663
664    return dup;
665}
666
667status_t Converter::doMoreWork() {
668    status_t err;
669
670    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
671        for (;;) {
672            size_t bufferIndex;
673            err = mEncoder->dequeueInputBuffer(&bufferIndex);
674
675            if (err != OK) {
676                break;
677            }
678
679            mAvailEncoderInputIndices.push_back(bufferIndex);
680        }
681
682        feedEncoderInputBuffers();
683    }
684
685    for (;;) {
686        size_t bufferIndex;
687        size_t offset;
688        size_t size;
689        int64_t timeUs;
690        uint32_t flags;
691        native_handle_t* handle = NULL;
692        err = mEncoder->dequeueOutputBuffer(
693                &bufferIndex, &offset, &size, &timeUs, &flags);
694
695        if (err != OK) {
696            if (err == INFO_FORMAT_CHANGED) {
697                continue;
698            } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
699                mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
700                continue;
701            }
702
703            if (err == -EAGAIN) {
704                err = OK;
705            }
706            break;
707        }
708
709        if (flags & MediaCodec::BUFFER_FLAG_EOS) {
710            sp<AMessage> notify = mNotify->dup();
711            notify->setInt32("what", kWhatEOS);
712            notify->post();
713        } else {
714#if 0
715            if (mIsVideo) {
716                int32_t videoBitrate = GetInt32Property(
717                        "media.wfd.video-bitrate", 5000000);
718
719                setVideoBitrate(videoBitrate);
720            }
721#endif
722
723            sp<ABuffer> buffer;
724            sp<MediaCodecBuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex);
725
726            if (outbuf->meta()->findPointer("handle", (void**)&handle) &&
727                    handle != NULL) {
728                int32_t rangeLength, rangeOffset;
729                CHECK(outbuf->meta()->findInt32("rangeOffset", &rangeOffset));
730                CHECK(outbuf->meta()->findInt32("rangeLength", &rangeLength));
731                outbuf->meta()->setPointer("handle", NULL);
732
733                // MediaSender will post the following message when HDCP
734                // is done, to release the output buffer back to encoder.
735                sp<AMessage> notify(new AMessage(kWhatReleaseOutputBuffer, this));
736                notify->setInt32("bufferIndex", bufferIndex);
737
738                buffer = new ABuffer(
739                        rangeLength > (int32_t)size ? rangeLength : size);
740                buffer->meta()->setPointer("handle", handle);
741                buffer->meta()->setInt32("rangeOffset", rangeOffset);
742                buffer->meta()->setInt32("rangeLength", rangeLength);
743                buffer->meta()->setMessage("notify", notify);
744            } else {
745                buffer = new ABuffer(size);
746            }
747
748            buffer->meta()->setInt64("timeUs", timeUs);
749
750            ALOGV("[%s] time %lld us (%.2f secs)",
751                    mIsVideo ? "video" : "audio", (long long)timeUs, timeUs / 1E6);
752
753            memcpy(buffer->data(), outbuf->base() + offset, size);
754
755            if (flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) {
756                if (!handle) {
757                    if (mIsH264) {
758                        mCSD0 = buffer;
759                    }
760                    mOutputFormat->setBuffer("csd-0", buffer);
761                }
762            } else {
763                if (mNeedToManuallyPrependSPSPPS
764                        && mIsH264
765                        && (mFlags & FLAG_PREPEND_CSD_IF_NECESSARY)
766                        && IsIDR(buffer)) {
767                    buffer = prependCSD(buffer);
768                }
769
770                sp<AMessage> notify = mNotify->dup();
771                notify->setInt32("what", kWhatAccessUnit);
772                notify->setBuffer("accessUnit", buffer);
773                notify->post();
774            }
775        }
776
777        if (!handle) {
778            mEncoder->releaseOutputBuffer(bufferIndex);
779        }
780
781        if (flags & MediaCodec::BUFFER_FLAG_EOS) {
782            break;
783        }
784    }
785
786    return err;
787}
788
789void Converter::requestIDRFrame() {
790    (new AMessage(kWhatRequestIDRFrame, this))->post();
791}
792
793void Converter::dropAFrame() {
794    // Unsupported in surface input mode.
795    CHECK(!(mFlags & FLAG_USE_SURFACE_INPUT));
796
797    (new AMessage(kWhatDropAFrame, this))->post();
798}
799
800void Converter::suspendEncoding(bool suspend) {
801    sp<AMessage> msg = new AMessage(kWhatSuspendEncoding, this);
802    msg->setInt32("suspend", suspend);
803    msg->post();
804}
805
806int32_t Converter::getVideoBitrate() const {
807    return mPrevVideoBitrate;
808}
809
810void Converter::setVideoBitrate(int32_t bitRate) {
811    if (mIsVideo && mEncoder != NULL && bitRate != mPrevVideoBitrate) {
812        sp<AMessage> params = new AMessage;
813        params->setInt32("video-bitrate", bitRate);
814
815        mEncoder->setParameters(params);
816
817        mPrevVideoBitrate = bitRate;
818    }
819}
820
821}  // namespace android
822