Converter.cpp revision cf2604f8940093e249ed7e5382c12ba544a48545
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
25#include <cutils/properties.h>
26#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>
31#include <media/stagefright/MediaBuffer.h>
32#include <media/stagefright/MediaCodec.h>
33#include <media/stagefright/MediaDefs.h>
34#include <media/stagefright/MediaErrors.h>
35
36namespace android {
37
38Converter::Converter(
39        const sp<AMessage> &notify,
40        const sp<ALooper> &codecLooper,
41        const sp<AMessage> &format)
42    : mInitCheck(NO_INIT),
43      mNotify(notify),
44      mCodecLooper(codecLooper),
45      mInputFormat(format),
46      mIsVideo(false),
47      mDoMoreWorkPending(false)
48#if ENABLE_SILENCE_DETECTION
49      ,mFirstSilentFrameUs(-1ll)
50      ,mInSilentMode(false)
51#endif
52    {
53    AString mime;
54    CHECK(mInputFormat->findString("mime", &mime));
55
56    if (!strncasecmp("video/", mime.c_str(), 6)) {
57        mIsVideo = true;
58    }
59
60    mInitCheck = initEncoder();
61
62    if (mInitCheck != OK) {
63        if (mEncoder != NULL) {
64            mEncoder->release();
65            mEncoder.clear();
66        }
67    }
68}
69
70Converter::~Converter() {
71    CHECK(mEncoder == NULL);
72}
73
74void Converter::shutdownAsync() {
75    ALOGV("shutdown");
76    (new AMessage(kWhatShutdown, id()))->post();
77}
78
79status_t Converter::initCheck() const {
80    return mInitCheck;
81}
82
83size_t Converter::getInputBufferCount() const {
84    return mEncoderInputBuffers.size();
85}
86
87sp<AMessage> Converter::getOutputFormat() const {
88    return mOutputFormat;
89}
90
91static int32_t getBitrate(const char *propName, int32_t defaultValue) {
92    char val[PROPERTY_VALUE_MAX];
93    if (property_get(propName, val, NULL)) {
94        char *end;
95        unsigned long x = strtoul(val, &end, 10);
96
97        if (*end == '\0' && end > val && x > 0) {
98            return x;
99        }
100    }
101
102    return defaultValue;
103}
104
105status_t Converter::initEncoder() {
106    AString inputMIME;
107    CHECK(mInputFormat->findString("mime", &inputMIME));
108
109    AString outputMIME;
110    bool isAudio = false;
111    if (!strcasecmp(inputMIME.c_str(), MEDIA_MIMETYPE_AUDIO_RAW)) {
112        outputMIME = MEDIA_MIMETYPE_AUDIO_AAC;
113        isAudio = true;
114    } else if (!strcasecmp(inputMIME.c_str(), MEDIA_MIMETYPE_VIDEO_RAW)) {
115        outputMIME = MEDIA_MIMETYPE_VIDEO_AVC;
116    } else {
117        TRESPASS();
118    }
119
120    mEncoder = MediaCodec::CreateByType(
121            mCodecLooper, outputMIME.c_str(), true /* encoder */);
122
123    if (mEncoder == NULL) {
124        return ERROR_UNSUPPORTED;
125    }
126
127    mOutputFormat = mInputFormat->dup();
128    mOutputFormat->setString("mime", outputMIME.c_str());
129
130    int32_t audioBitrate = getBitrate("media.wfd.audio-bitrate", 128000);
131    int32_t videoBitrate = getBitrate("media.wfd.video-bitrate", 5000000);
132
133    ALOGI("using audio bitrate of %d bps, video bitrate of %d bps",
134          audioBitrate, videoBitrate);
135
136    if (isAudio) {
137        mOutputFormat->setInt32("bitrate", audioBitrate);
138    } else {
139        mOutputFormat->setInt32("bitrate", videoBitrate);
140        mOutputFormat->setInt32("frame-rate", 30);
141        mOutputFormat->setInt32("i-frame-interval", 1);  // Iframes every 1 secs
142        mOutputFormat->setInt32("prepend-sps-pps-to-idr-frames", 1);
143    }
144
145    ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
146
147    status_t err = mEncoder->configure(
148            mOutputFormat,
149            NULL /* nativeWindow */,
150            NULL /* crypto */,
151            MediaCodec::CONFIGURE_FLAG_ENCODE);
152
153    if (err != OK) {
154        return err;
155    }
156
157    err = mEncoder->start();
158
159    if (err != OK) {
160        return err;
161    }
162
163    err = mEncoder->getInputBuffers(&mEncoderInputBuffers);
164
165    if (err != OK) {
166        return err;
167    }
168
169    return mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
170}
171
172void Converter::notifyError(status_t err) {
173    sp<AMessage> notify = mNotify->dup();
174    notify->setInt32("what", kWhatError);
175    notify->setInt32("err", err);
176    notify->post();
177}
178
179// static
180bool Converter::IsSilence(const sp<ABuffer> &accessUnit) {
181    const uint8_t *ptr = accessUnit->data();
182    const uint8_t *end = ptr + accessUnit->size();
183    while (ptr < end) {
184        if (*ptr != 0) {
185            return false;
186        }
187        ++ptr;
188    }
189
190    return true;
191}
192
193void Converter::onMessageReceived(const sp<AMessage> &msg) {
194    switch (msg->what()) {
195        case kWhatMediaPullerNotify:
196        {
197            int32_t what;
198            CHECK(msg->findInt32("what", &what));
199
200            if (mEncoder == NULL) {
201                ALOGV("got msg '%s' after encoder shutdown.",
202                      msg->debugString().c_str());
203
204                if (what == MediaPuller::kWhatAccessUnit) {
205                    sp<ABuffer> accessUnit;
206                    CHECK(msg->findBuffer("accessUnit", &accessUnit));
207
208                    void *mbuf;
209                    if (accessUnit->meta()->findPointer("mediaBuffer", &mbuf)
210                            && mbuf != NULL) {
211                        ALOGV("releasing mbuf %p", mbuf);
212
213                        accessUnit->meta()->setPointer("mediaBuffer", NULL);
214
215                        static_cast<MediaBuffer *>(mbuf)->release();
216                        mbuf = NULL;
217                    }
218                }
219                break;
220            }
221
222            if (what == MediaPuller::kWhatEOS) {
223                mInputBufferQueue.push_back(NULL);
224
225                feedEncoderInputBuffers();
226
227                scheduleDoMoreWork();
228            } else {
229                CHECK_EQ(what, MediaPuller::kWhatAccessUnit);
230
231                sp<ABuffer> accessUnit;
232                CHECK(msg->findBuffer("accessUnit", &accessUnit));
233
234#if 0
235                void *mbuf;
236                if (accessUnit->meta()->findPointer("mediaBuffer", &mbuf)
237                        && mbuf != NULL) {
238                    ALOGI("queueing mbuf %p", mbuf);
239                }
240#endif
241
242#if ENABLE_SILENCE_DETECTION
243                if (!mIsVideo) {
244                    if (IsSilence(accessUnit)) {
245                        if (!mInSilentMode) {
246                            int64_t nowUs = ALooper::GetNowUs();
247
248                            if (mFirstSilentFrameUs < 0ll) {
249                                mFirstSilentFrameUs = nowUs;
250                            } else if (nowUs >= mFirstSilentFrameUs + 1000000ll) {
251                                mInSilentMode = true;
252                                ALOGI("audio in silent mode now.");
253                                break;
254                            }
255                        }
256                    } else {
257                        if (mInSilentMode) {
258                            ALOGI("audio no longer in silent mode.");
259                        }
260                        mInSilentMode = false;
261                        mFirstSilentFrameUs = -1ll;
262                    }
263                }
264#endif
265
266                mInputBufferQueue.push_back(accessUnit);
267
268                feedEncoderInputBuffers();
269
270                scheduleDoMoreWork();
271            }
272            break;
273        }
274
275        case kWhatDoMoreWork:
276        {
277            mDoMoreWorkPending = false;
278
279            if (mEncoder == NULL) {
280                break;
281            }
282
283            status_t err = doMoreWork();
284
285            if (err != OK) {
286                notifyError(err);
287            } else {
288                scheduleDoMoreWork();
289            }
290            break;
291        }
292
293        case kWhatRequestIDRFrame:
294        {
295            if (mEncoder == NULL) {
296                break;
297            }
298
299            if (mIsVideo) {
300                ALOGI("requesting IDR frame");
301                mEncoder->requestIDRFrame();
302            }
303            break;
304        }
305
306        case kWhatShutdown:
307        {
308            ALOGI("shutting down encoder");
309            mEncoder->release();
310            mEncoder.clear();
311
312            AString mime;
313            CHECK(mInputFormat->findString("mime", &mime));
314            ALOGI("encoder (%s) shut down.", mime.c_str());
315            break;
316        }
317
318        default:
319            TRESPASS();
320    }
321}
322
323void Converter::scheduleDoMoreWork() {
324    if (mDoMoreWorkPending) {
325        return;
326    }
327
328    mDoMoreWorkPending = true;
329    (new AMessage(kWhatDoMoreWork, id()))->post(mIsVideo ? 10000ll : 5000ll);
330}
331
332status_t Converter::feedEncoderInputBuffers() {
333    while (!mInputBufferQueue.empty()
334            && !mAvailEncoderInputIndices.empty()) {
335        sp<ABuffer> buffer = *mInputBufferQueue.begin();
336        mInputBufferQueue.erase(mInputBufferQueue.begin());
337
338        size_t bufferIndex = *mAvailEncoderInputIndices.begin();
339        mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
340
341        int64_t timeUs = 0ll;
342        uint32_t flags = 0;
343
344        if (buffer != NULL) {
345            CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
346
347            memcpy(mEncoderInputBuffers.itemAt(bufferIndex)->data(),
348                   buffer->data(),
349                   buffer->size());
350
351            void *mediaBuffer;
352            if (buffer->meta()->findPointer("mediaBuffer", &mediaBuffer)
353                    && mediaBuffer != NULL) {
354                mEncoderInputBuffers.itemAt(bufferIndex)->meta()
355                    ->setPointer("mediaBuffer", mediaBuffer);
356
357                buffer->meta()->setPointer("mediaBuffer", NULL);
358            }
359        } else {
360            flags = MediaCodec::BUFFER_FLAG_EOS;
361        }
362
363        status_t err = mEncoder->queueInputBuffer(
364                bufferIndex, 0, (buffer == NULL) ? 0 : buffer->size(),
365                timeUs, flags);
366
367        if (err != OK) {
368            return err;
369        }
370    }
371
372    return OK;
373}
374
375status_t Converter::doMoreWork() {
376    size_t bufferIndex;
377    status_t err = mEncoder->dequeueInputBuffer(&bufferIndex);
378
379    if (err == OK) {
380        mAvailEncoderInputIndices.push_back(bufferIndex);
381        feedEncoderInputBuffers();
382    }
383
384    for (;;) {
385        size_t offset;
386        size_t size;
387        int64_t timeUs;
388        uint32_t flags;
389        err = mEncoder->dequeueOutputBuffer(
390                &bufferIndex, &offset, &size, &timeUs, &flags);
391
392        if (err != OK) {
393            if (err == -EAGAIN) {
394                err = OK;
395            }
396            break;
397        }
398
399        if (flags & MediaCodec::BUFFER_FLAG_EOS) {
400            sp<AMessage> notify = mNotify->dup();
401            notify->setInt32("what", kWhatEOS);
402            notify->post();
403        } else {
404            sp<ABuffer> buffer = new ABuffer(size);
405            buffer->meta()->setInt64("timeUs", timeUs);
406
407            if (!mIsVideo) {
408                ALOGV("audio time %lld us (%.2f secs)", timeUs, timeUs / 1E6);
409            }
410
411            memcpy(buffer->data(),
412                   mEncoderOutputBuffers.itemAt(bufferIndex)->base() + offset,
413                   size);
414
415            if (flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) {
416                mOutputFormat->setBuffer("csd-0", buffer);
417            } else {
418                sp<AMessage> notify = mNotify->dup();
419                notify->setInt32("what", kWhatAccessUnit);
420                notify->setBuffer("accessUnit", buffer);
421                notify->post();
422            }
423        }
424
425        mEncoder->releaseOutputBuffer(bufferIndex);
426
427        if (flags & MediaCodec::BUFFER_FLAG_EOS) {
428            break;
429        }
430    }
431
432    return err;
433}
434
435void Converter::requestIDRFrame() {
436    (new AMessage(kWhatRequestIDRFrame, id()))->post();
437}
438
439}  // namespace android
440