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