SoftOpus.cpp revision 08e8227514f5ab99822dfae8b4d39414646ff59d
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            if (mHeader->channels <= kMaxChannelsWithDefaultLayout) {
349                memcpy(&channel_mapping,
350                       kDefaultOpusChannelLayout,
351                       kMaxChannelsWithDefaultLayout);
352            } else {
353                memcpy(&channel_mapping,
354                       mHeader->stream_map,
355                       mHeader->channels);
356            }
357
358            int status = OPUS_INVALID_STATE;
359            mDecoder = opus_multistream_decoder_create(kRate,
360                                                       mHeader->channels,
361                                                       mHeader->num_streams,
362                                                       mHeader->num_coupled,
363                                                       channel_mapping,
364                                                       &status);
365            if (!mDecoder || status != OPUS_OK) {
366                ALOGV("opus_multistream_decoder_create failed status=%s",
367                      opus_strerror(status));
368                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
369                return;
370            }
371            status =
372                opus_multistream_decoder_ctl(mDecoder,
373                                             OPUS_SET_GAIN(mHeader->gain_db));
374            if (status != OPUS_OK) {
375                ALOGV("Failed to set OPUS header gain; status=%s",
376                      opus_strerror(status));
377                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
378                return;
379            }
380        } else if (mInputBufferCount == 1) {
381            mCodecDelay = ns_to_samples(
382                              *(reinterpret_cast<int64_t*>(header->pBuffer +
383                                                           header->nOffset)),
384                              kRate);
385            mSamplesToDiscard = mCodecDelay;
386        } else {
387            mSeekPreRoll = ns_to_samples(
388                               *(reinterpret_cast<int64_t*>(header->pBuffer +
389                                                            header->nOffset)),
390                               kRate);
391            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
392            mOutputPortSettingsChange = AWAITING_DISABLED;
393        }
394
395        inQueue.erase(inQueue.begin());
396        info->mOwnedByUs = false;
397        notifyEmptyBufferDone(header);
398        ++mInputBufferCount;
399        return;
400    }
401
402    while (!inQueue.empty() && !outQueue.empty()) {
403        BufferInfo *inInfo = *inQueue.begin();
404        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
405
406        // Ignore CSD re-submissions.
407        if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
408            inQueue.erase(inQueue.begin());
409            inInfo->mOwnedByUs = false;
410            notifyEmptyBufferDone(inHeader);
411            return;
412        }
413
414        BufferInfo *outInfo = *outQueue.begin();
415        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
416
417        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
418            inQueue.erase(inQueue.begin());
419            inInfo->mOwnedByUs = false;
420            notifyEmptyBufferDone(inHeader);
421
422            outHeader->nFilledLen = 0;
423            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
424
425            outQueue.erase(outQueue.begin());
426            outInfo->mOwnedByUs = false;
427            notifyFillBufferDone(outHeader);
428            return;
429        }
430
431        if (inHeader->nOffset == 0) {
432            mAnchorTimeUs = inHeader->nTimeStamp;
433            mNumFramesOutput = 0;
434        }
435
436        // When seeking to zero, |mCodecDelay| samples has to be discarded
437        // instead of |mSeekPreRoll| samples (as we would when seeking to any
438        // other timestamp).
439        if (inHeader->nTimeStamp == 0) {
440            mSamplesToDiscard = mCodecDelay;
441        }
442
443        const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
444        const uint32_t size = inHeader->nFilledLen;
445
446        int numFrames = opus_multistream_decode(mDecoder,
447                                                data,
448                                                size,
449                                                (int16_t *)outHeader->pBuffer,
450                                                kMaxOpusOutputPacketSizeSamples,
451                                                0);
452        if (numFrames < 0) {
453            ALOGE("opus_multistream_decode returned %d", numFrames);
454            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
455            return;
456        }
457
458        outHeader->nOffset = 0;
459        if (mSamplesToDiscard > 0) {
460            if (mSamplesToDiscard > numFrames) {
461                mSamplesToDiscard -= numFrames;
462                numFrames = 0;
463            } else {
464                numFrames -= mSamplesToDiscard;
465                outHeader->nOffset = mSamplesToDiscard * sizeof(int16_t) *
466                                     mHeader->channels;
467                mSamplesToDiscard = 0;
468            }
469        }
470
471        outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels;
472        outHeader->nFlags = 0;
473
474        outHeader->nTimeStamp = mAnchorTimeUs +
475                                (mNumFramesOutput * 1000000ll) /
476                                kRate;
477
478        mNumFramesOutput += numFrames;
479
480        inInfo->mOwnedByUs = false;
481        inQueue.erase(inQueue.begin());
482        inInfo = NULL;
483        notifyEmptyBufferDone(inHeader);
484        inHeader = NULL;
485
486        outInfo->mOwnedByUs = false;
487        outQueue.erase(outQueue.begin());
488        outInfo = NULL;
489        notifyFillBufferDone(outHeader);
490        outHeader = NULL;
491
492        ++mInputBufferCount;
493    }
494}
495
496void SoftOpus::onPortFlushCompleted(OMX_U32 portIndex) {
497    if (portIndex == 0 && mDecoder != NULL) {
498        // Make sure that the next buffer output does not still
499        // depend on fragments from the last one decoded.
500        mNumFramesOutput = 0;
501        opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE);
502        mAnchorTimeUs = 0;
503        mSamplesToDiscard = mSeekPreRoll;
504    }
505}
506
507void SoftOpus::onReset() {
508    mInputBufferCount = 0;
509    mNumFramesOutput = 0;
510    if (mDecoder != NULL) {
511        opus_multistream_decoder_destroy(mDecoder);
512        mDecoder = NULL;
513    }
514    if (mHeader != NULL) {
515        delete mHeader;
516        mHeader = NULL;
517    }
518
519    mOutputPortSettingsChange = NONE;
520}
521
522void SoftOpus::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
523    if (portIndex != 1) {
524        return;
525    }
526
527    switch (mOutputPortSettingsChange) {
528        case NONE:
529            break;
530
531        case AWAITING_DISABLED:
532        {
533            CHECK(!enabled);
534            mOutputPortSettingsChange = AWAITING_ENABLED;
535            break;
536        }
537
538        default:
539        {
540            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
541            CHECK(enabled);
542            mOutputPortSettingsChange = NONE;
543            break;
544        }
545    }
546}
547
548}  // namespace android
549
550android::SoftOMXComponent *createSoftOMXComponent(
551        const char *name, const OMX_CALLBACKTYPE *callbacks,
552        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
553    return new android::SoftOpus(name, callbacks, appData, component);
554}
555