SoftOpus.cpp revision 8d055459fe88267f445521673ac9771ba53f8638
1/*
2 * Copyright (C) 2014 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 "SoftOpus"
19#include <utils/Log.h>
20
21#include "SoftOpus.h"
22#include <OMX_AudioExt.h>
23#include <OMX_IndexExt.h>
24
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/MediaDefs.h>
27
28extern "C" {
29    #include <opus.h>
30    #include <opus_multistream.h>
31}
32
33namespace android {
34
35static const int kRate = 48000;
36
37// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies
38// mappings for up to 8 channels. This information is part of the Vorbis I
39// Specification:
40// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html
41static const int kMaxChannels = 8;
42
43template<class T>
44static void InitOMXParams(T *params) {
45    params->nSize = sizeof(T);
46    params->nVersion.s.nVersionMajor = 1;
47    params->nVersion.s.nVersionMinor = 0;
48    params->nVersion.s.nRevision = 0;
49    params->nVersion.s.nStep = 0;
50}
51
52SoftOpus::SoftOpus(
53        const char *name,
54        const OMX_CALLBACKTYPE *callbacks,
55        OMX_PTR appData,
56        OMX_COMPONENTTYPE **component)
57    : SimpleSoftOMXComponent(name, callbacks, appData, component),
58      mInputBufferCount(0),
59      mDecoder(NULL),
60      mHeader(NULL),
61      mCodecDelay(0),
62      mSeekPreRoll(0),
63      mAnchorTimeUs(0),
64      mNumFramesOutput(0),
65      mOutputPortSettingsChange(NONE) {
66    initPorts();
67    CHECK_EQ(initDecoder(), (status_t)OK);
68}
69
70SoftOpus::~SoftOpus() {
71    if (mDecoder != NULL) {
72        opus_multistream_decoder_destroy(mDecoder);
73        mDecoder = NULL;
74    }
75    if (mHeader != NULL) {
76        delete mHeader;
77        mHeader = NULL;
78    }
79}
80
81void SoftOpus::initPorts() {
82    OMX_PARAM_PORTDEFINITIONTYPE def;
83    InitOMXParams(&def);
84
85    def.nPortIndex = 0;
86    def.eDir = OMX_DirInput;
87    def.nBufferCountMin = kNumBuffers;
88    def.nBufferCountActual = def.nBufferCountMin;
89    def.nBufferSize = 960 * 6;
90    def.bEnabled = OMX_TRUE;
91    def.bPopulated = OMX_FALSE;
92    def.eDomain = OMX_PortDomainAudio;
93    def.bBuffersContiguous = OMX_FALSE;
94    def.nBufferAlignment = 1;
95
96    def.format.audio.cMIMEType =
97        const_cast<char *>(MEDIA_MIMETYPE_AUDIO_OPUS);
98
99    def.format.audio.pNativeRender = NULL;
100    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
101    def.format.audio.eEncoding =
102        (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS;
103
104    addPort(def);
105
106    def.nPortIndex = 1;
107    def.eDir = OMX_DirOutput;
108    def.nBufferCountMin = kNumBuffers;
109    def.nBufferCountActual = def.nBufferCountMin;
110    def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t) * kMaxChannels;
111    def.bEnabled = OMX_TRUE;
112    def.bPopulated = OMX_FALSE;
113    def.eDomain = OMX_PortDomainAudio;
114    def.bBuffersContiguous = OMX_FALSE;
115    def.nBufferAlignment = 2;
116
117    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
118    def.format.audio.pNativeRender = NULL;
119    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
120    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
121
122    addPort(def);
123}
124
125status_t SoftOpus::initDecoder() {
126    return OK;
127}
128
129OMX_ERRORTYPE SoftOpus::internalGetParameter(
130        OMX_INDEXTYPE index, OMX_PTR params) {
131    switch ((int)index) {
132        case OMX_IndexParamAudioAndroidOpus:
133        {
134            OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams =
135                (OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params;
136
137            if (opusParams->nPortIndex != 0) {
138                return OMX_ErrorUndefined;
139            }
140
141            opusParams->nAudioBandWidth = 0;
142            opusParams->nSampleRate = kRate;
143            opusParams->nBitRate = 0;
144
145            if (!isConfigured()) {
146                opusParams->nChannels = 1;
147            } else {
148                opusParams->nChannels = mHeader->channels;
149            }
150
151            return OMX_ErrorNone;
152        }
153
154        case OMX_IndexParamAudioPcm:
155        {
156            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
157                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
158
159            if (pcmParams->nPortIndex != 1) {
160                return OMX_ErrorUndefined;
161            }
162
163            pcmParams->eNumData = OMX_NumericalDataSigned;
164            pcmParams->eEndian = OMX_EndianBig;
165            pcmParams->bInterleaved = OMX_TRUE;
166            pcmParams->nBitPerSample = 16;
167            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
168            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
169            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
170            pcmParams->nSamplingRate = kRate;
171
172            if (!isConfigured()) {
173                pcmParams->nChannels = 1;
174            } else {
175                pcmParams->nChannels = mHeader->channels;
176            }
177
178            return OMX_ErrorNone;
179        }
180
181        default:
182            return SimpleSoftOMXComponent::internalGetParameter(index, params);
183    }
184}
185
186OMX_ERRORTYPE SoftOpus::internalSetParameter(
187        OMX_INDEXTYPE index, const OMX_PTR params) {
188    switch ((int)index) {
189        case OMX_IndexParamStandardComponentRole:
190        {
191            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
192                (const OMX_PARAM_COMPONENTROLETYPE *)params;
193
194            if (strncmp((const char *)roleParams->cRole,
195                        "audio_decoder.opus",
196                        OMX_MAX_STRINGNAME_SIZE - 1)) {
197                return OMX_ErrorUndefined;
198            }
199
200            return OMX_ErrorNone;
201        }
202
203        case OMX_IndexParamAudioAndroidOpus:
204        {
205            const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams =
206                (const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params;
207
208            if (opusParams->nPortIndex != 0) {
209                return OMX_ErrorUndefined;
210            }
211
212            return OMX_ErrorNone;
213        }
214
215        default:
216            return SimpleSoftOMXComponent::internalSetParameter(index, params);
217    }
218}
219
220bool SoftOpus::isConfigured() const {
221    return mInputBufferCount >= 1;
222}
223
224static uint16_t ReadLE16(const uint8_t *data, size_t data_size,
225                         uint32_t read_offset) {
226    if (read_offset + 1 > data_size)
227        return 0;
228    uint16_t val;
229    val = data[read_offset];
230    val |= data[read_offset + 1] << 8;
231    return val;
232}
233
234// Maximum packet size used in Xiph's opusdec.
235static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
236
237// Default audio output channel layout. Used to initialize |stream_map| in
238// OpusHeader, and passed to opus_multistream_decoder_create() when the header
239// does not contain mapping information. The values are valid only for mono and
240// stereo output: Opus streams with more than 2 channels require a stream map.
241static const int kMaxChannelsWithDefaultLayout = 2;
242static const uint8_t kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { 0, 1 };
243
244// Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header
245static bool ParseOpusHeader(const uint8_t *data, size_t data_size,
246                            OpusHeader* header) {
247    // Size of the Opus header excluding optional mapping information.
248    const size_t kOpusHeaderSize = 19;
249
250    // Offset to the channel count byte in the Opus header.
251    const size_t kOpusHeaderChannelsOffset = 9;
252
253    // Offset to the pre-skip value in the Opus header.
254    const size_t kOpusHeaderSkipSamplesOffset = 10;
255
256    // Offset to the gain value in the Opus header.
257    const size_t kOpusHeaderGainOffset = 16;
258
259    // Offset to the channel mapping byte in the Opus header.
260    const size_t kOpusHeaderChannelMappingOffset = 18;
261
262    // Opus Header contains a stream map. The mapping values are in the header
263    // beyond the always present |kOpusHeaderSize| bytes of data. The mapping
264    // data contains stream count, coupling information, and per channel mapping
265    // values:
266    //   - Byte 0: Number of streams.
267    //   - Byte 1: Number coupled.
268    //   - Byte 2: Starting at byte 2 are |header->channels| uint8 mapping
269    //             values.
270    const size_t kOpusHeaderNumStreamsOffset = kOpusHeaderSize;
271    const size_t kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1;
272    const size_t kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2;
273
274    if (data_size < kOpusHeaderSize) {
275        ALOGV("Header size is too small.");
276        return false;
277    }
278    header->channels = *(data + kOpusHeaderChannelsOffset);
279
280    if (header->channels <= 0 || header->channels > kMaxChannels) {
281        ALOGV("Invalid Header, wrong channel count: %d", header->channels);
282        return false;
283    }
284    header->skip_samples = ReadLE16(data, data_size,
285                                        kOpusHeaderSkipSamplesOffset);
286    header->gain_db = static_cast<int16_t>(
287                              ReadLE16(data, data_size,
288                                       kOpusHeaderGainOffset));
289    header->channel_mapping = *(data + kOpusHeaderChannelMappingOffset);
290    if (!header->channel_mapping) {
291        if (header->channels > kMaxChannelsWithDefaultLayout) {
292            ALOGV("Invalid Header, missing stream map.");
293            return false;
294        }
295        header->num_streams = 1;
296        header->num_coupled = header->channels > 1;
297        header->stream_map[0] = 0;
298        header->stream_map[1] = 1;
299        return true;
300    }
301    if (data_size < kOpusHeaderStreamMapOffset + header->channels) {
302        ALOGV("Invalid stream map; insufficient data for current channel "
303              "count: %d", header->channels);
304        return false;
305    }
306    header->num_streams = *(data + kOpusHeaderNumStreamsOffset);
307    header->num_coupled = *(data + kOpusHeaderNumCoupledOffset);
308    if (header->num_streams + header->num_coupled != header->channels) {
309        ALOGV("Inconsistent channel mapping.");
310        return false;
311    }
312    for (int i = 0; i < header->channels; ++i)
313      header->stream_map[i] = *(data + kOpusHeaderStreamMapOffset + i);
314    return true;
315}
316
317// Convert nanoseconds to number of samples.
318static uint64_t ns_to_samples(uint64_t ns, int kRate) {
319    return static_cast<double>(ns) * kRate / 1000000000;
320}
321
322void SoftOpus::onQueueFilled(OMX_U32 portIndex) {
323    List<BufferInfo *> &inQueue = getPortQueue(0);
324    List<BufferInfo *> &outQueue = getPortQueue(1);
325
326    if (mOutputPortSettingsChange != NONE) {
327        return;
328    }
329
330    if (portIndex == 0 && mInputBufferCount < 3) {
331        BufferInfo *info = *inQueue.begin();
332        OMX_BUFFERHEADERTYPE *header = info->mHeader;
333
334        const uint8_t *data = header->pBuffer + header->nOffset;
335        size_t size = header->nFilledLen;
336
337        if (mInputBufferCount == 0) {
338            CHECK(mHeader == NULL);
339            mHeader = new OpusHeader();
340            memset(mHeader, 0, sizeof(*mHeader));
341            if (!ParseOpusHeader(data, size, mHeader)) {
342                ALOGV("Parsing Opus Header failed.");
343                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
344                return;
345            }
346
347            uint8_t channel_mapping[kMaxChannels] = {0};
348            memcpy(&channel_mapping,
349                   kDefaultOpusChannelLayout,
350                   kMaxChannelsWithDefaultLayout);
351
352            int status = OPUS_INVALID_STATE;
353            mDecoder = opus_multistream_decoder_create(kRate,
354                                                       mHeader->channels,
355                                                       mHeader->num_streams,
356                                                       mHeader->num_coupled,
357                                                       channel_mapping,
358                                                       &status);
359            if (!mDecoder || status != OPUS_OK) {
360                ALOGV("opus_multistream_decoder_create failed status=%s",
361                      opus_strerror(status));
362                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
363                return;
364            }
365            status =
366                opus_multistream_decoder_ctl(mDecoder,
367                                             OPUS_SET_GAIN(mHeader->gain_db));
368            if (status != OPUS_OK) {
369                ALOGV("Failed to set OPUS header gain; status=%s",
370                      opus_strerror(status));
371                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
372                return;
373            }
374        } else if (mInputBufferCount == 1) {
375            mCodecDelay = ns_to_samples(
376                              *(reinterpret_cast<int64_t*>(header->pBuffer +
377                                                           header->nOffset)),
378                              kRate);
379            mSamplesToDiscard = mCodecDelay;
380        } else {
381            mSeekPreRoll = ns_to_samples(
382                               *(reinterpret_cast<int64_t*>(header->pBuffer +
383                                                            header->nOffset)),
384                               kRate);
385            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
386            mOutputPortSettingsChange = AWAITING_DISABLED;
387        }
388
389        inQueue.erase(inQueue.begin());
390        info->mOwnedByUs = false;
391        notifyEmptyBufferDone(header);
392        ++mInputBufferCount;
393        return;
394    }
395
396    while (!inQueue.empty() && !outQueue.empty()) {
397        BufferInfo *inInfo = *inQueue.begin();
398        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
399
400        BufferInfo *outInfo = *outQueue.begin();
401        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
402
403        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
404            inQueue.erase(inQueue.begin());
405            inInfo->mOwnedByUs = false;
406            notifyEmptyBufferDone(inHeader);
407
408            outHeader->nFilledLen = 0;
409            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
410
411            outQueue.erase(outQueue.begin());
412            outInfo->mOwnedByUs = false;
413            notifyFillBufferDone(outHeader);
414            return;
415        }
416
417        if (inHeader->nOffset == 0) {
418            mAnchorTimeUs = inHeader->nTimeStamp;
419            mNumFramesOutput = 0;
420        }
421
422        // When seeking to zero, |mCodecDelay| samples has to be discarded
423        // instead of |mSeekPreRoll| samples (as we would when seeking to any
424        // other timestamp).
425        if (inHeader->nTimeStamp == 0) {
426            mSamplesToDiscard = mCodecDelay;
427        }
428
429        const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
430        const uint32_t size = inHeader->nFilledLen;
431        size_t frameSize = kMaxOpusOutputPacketSizeSamples;
432        if (frameSize > outHeader->nAllocLen / sizeof(int16_t) / mHeader->channels) {
433            frameSize = outHeader->nAllocLen / sizeof(int16_t) / mHeader->channels;
434            android_errorWriteLog(0x534e4554, "27833616");
435        }
436
437        int numFrames = opus_multistream_decode(mDecoder,
438                                                data,
439                                                size,
440                                                (int16_t *)outHeader->pBuffer,
441                                                frameSize,
442                                                0);
443        if (numFrames < 0) {
444            ALOGE("opus_multistream_decode returned %d", numFrames);
445            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
446            return;
447        }
448
449        outHeader->nOffset = 0;
450        if (mSamplesToDiscard > 0) {
451            if (mSamplesToDiscard > numFrames) {
452                mSamplesToDiscard -= numFrames;
453                numFrames = 0;
454            } else {
455                numFrames -= mSamplesToDiscard;
456                outHeader->nOffset = mSamplesToDiscard * sizeof(int16_t) *
457                                     mHeader->channels;
458                mSamplesToDiscard = 0;
459            }
460        }
461
462        outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels;
463        outHeader->nFlags = 0;
464
465        outHeader->nTimeStamp = mAnchorTimeUs +
466                                (mNumFramesOutput * 1000000ll) /
467                                kRate;
468
469        mNumFramesOutput += numFrames;
470
471        inInfo->mOwnedByUs = false;
472        inQueue.erase(inQueue.begin());
473        inInfo = NULL;
474        notifyEmptyBufferDone(inHeader);
475        inHeader = NULL;
476
477        outInfo->mOwnedByUs = false;
478        outQueue.erase(outQueue.begin());
479        outInfo = NULL;
480        notifyFillBufferDone(outHeader);
481        outHeader = NULL;
482
483        ++mInputBufferCount;
484    }
485}
486
487void SoftOpus::onPortFlushCompleted(OMX_U32 portIndex) {
488    if (portIndex == 0 && mDecoder != NULL) {
489        // Make sure that the next buffer output does not still
490        // depend on fragments from the last one decoded.
491        mNumFramesOutput = 0;
492        opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE);
493        mAnchorTimeUs = 0;
494        mSamplesToDiscard = mSeekPreRoll;
495    }
496}
497
498void SoftOpus::onReset() {
499    mInputBufferCount = 0;
500    mNumFramesOutput = 0;
501    if (mDecoder != NULL) {
502        opus_multistream_decoder_destroy(mDecoder);
503        mDecoder = NULL;
504    }
505    if (mHeader != NULL) {
506        delete mHeader;
507        mHeader = NULL;
508    }
509
510    mOutputPortSettingsChange = NONE;
511}
512
513void SoftOpus::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
514    if (portIndex != 1) {
515        return;
516    }
517
518    switch (mOutputPortSettingsChange) {
519        case NONE:
520            break;
521
522        case AWAITING_DISABLED:
523        {
524            CHECK(!enabled);
525            mOutputPortSettingsChange = AWAITING_ENABLED;
526            break;
527        }
528
529        default:
530        {
531            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
532            CHECK(enabled);
533            mOutputPortSettingsChange = NONE;
534            break;
535        }
536    }
537}
538
539}  // namespace android
540
541android::SoftOMXComponent *createSoftOMXComponent(
542        const char *name, const OMX_CALLBACKTYPE *callbacks,
543        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
544    return new android::SoftOpus(name, callbacks, appData, component);
545}
546