SoftOpus.cpp revision 67ef30185837950144d30e5a73d852eb9a7a0a89
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 (!isValidOMXParam(opusParams)) {
138                return OMX_ErrorBadParameter;
139            }
140
141            if (opusParams->nPortIndex != 0) {
142                return OMX_ErrorUndefined;
143            }
144
145            opusParams->nAudioBandWidth = 0;
146            opusParams->nSampleRate = kRate;
147            opusParams->nBitRate = 0;
148
149            if (!isConfigured()) {
150                opusParams->nChannels = 1;
151            } else {
152                opusParams->nChannels = mHeader->channels;
153            }
154
155            return OMX_ErrorNone;
156        }
157
158        case OMX_IndexParamAudioPcm:
159        {
160            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
161                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
162
163            if (!isValidOMXParam(pcmParams)) {
164                return OMX_ErrorBadParameter;
165            }
166
167            if (pcmParams->nPortIndex != 1) {
168                return OMX_ErrorUndefined;
169            }
170
171            pcmParams->eNumData = OMX_NumericalDataSigned;
172            pcmParams->eEndian = OMX_EndianBig;
173            pcmParams->bInterleaved = OMX_TRUE;
174            pcmParams->nBitPerSample = 16;
175            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
176            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
177            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
178            pcmParams->nSamplingRate = kRate;
179
180            if (!isConfigured()) {
181                pcmParams->nChannels = 1;
182            } else {
183                pcmParams->nChannels = mHeader->channels;
184            }
185
186            return OMX_ErrorNone;
187        }
188
189        default:
190            return SimpleSoftOMXComponent::internalGetParameter(index, params);
191    }
192}
193
194OMX_ERRORTYPE SoftOpus::internalSetParameter(
195        OMX_INDEXTYPE index, const OMX_PTR params) {
196    switch ((int)index) {
197        case OMX_IndexParamStandardComponentRole:
198        {
199            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
200                (const OMX_PARAM_COMPONENTROLETYPE *)params;
201
202            if (!isValidOMXParam(roleParams)) {
203                return OMX_ErrorBadParameter;
204            }
205
206            if (strncmp((const char *)roleParams->cRole,
207                        "audio_decoder.opus",
208                        OMX_MAX_STRINGNAME_SIZE - 1)) {
209                return OMX_ErrorUndefined;
210            }
211
212            return OMX_ErrorNone;
213        }
214
215        case OMX_IndexParamAudioAndroidOpus:
216        {
217            const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams =
218                (const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params;
219
220            if (!isValidOMXParam(opusParams)) {
221                return OMX_ErrorBadParameter;
222            }
223
224            if (opusParams->nPortIndex != 0) {
225                return OMX_ErrorUndefined;
226            }
227
228            return OMX_ErrorNone;
229        }
230
231        default:
232            return SimpleSoftOMXComponent::internalSetParameter(index, params);
233    }
234}
235
236bool SoftOpus::isConfigured() const {
237    return mInputBufferCount >= 1;
238}
239
240static uint16_t ReadLE16(const uint8_t *data, size_t data_size,
241                         uint32_t read_offset) {
242    if (read_offset + 1 > data_size)
243        return 0;
244    uint16_t val;
245    val = data[read_offset];
246    val |= data[read_offset + 1] << 8;
247    return val;
248}
249
250// Maximum packet size used in Xiph's opusdec.
251static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
252
253// Default audio output channel layout. Used to initialize |stream_map| in
254// OpusHeader, and passed to opus_multistream_decoder_create() when the header
255// does not contain mapping information. The values are valid only for mono and
256// stereo output: Opus streams with more than 2 channels require a stream map.
257static const int kMaxChannelsWithDefaultLayout = 2;
258static const uint8_t kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { 0, 1 };
259
260// Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header
261static bool ParseOpusHeader(const uint8_t *data, size_t data_size,
262                            OpusHeader* header) {
263    // Size of the Opus header excluding optional mapping information.
264    const size_t kOpusHeaderSize = 19;
265
266    // Offset to the channel count byte in the Opus header.
267    const size_t kOpusHeaderChannelsOffset = 9;
268
269    // Offset to the pre-skip value in the Opus header.
270    const size_t kOpusHeaderSkipSamplesOffset = 10;
271
272    // Offset to the gain value in the Opus header.
273    const size_t kOpusHeaderGainOffset = 16;
274
275    // Offset to the channel mapping byte in the Opus header.
276    const size_t kOpusHeaderChannelMappingOffset = 18;
277
278    // Opus Header contains a stream map. The mapping values are in the header
279    // beyond the always present |kOpusHeaderSize| bytes of data. The mapping
280    // data contains stream count, coupling information, and per channel mapping
281    // values:
282    //   - Byte 0: Number of streams.
283    //   - Byte 1: Number coupled.
284    //   - Byte 2: Starting at byte 2 are |header->channels| uint8 mapping
285    //             values.
286    const size_t kOpusHeaderNumStreamsOffset = kOpusHeaderSize;
287    const size_t kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1;
288    const size_t kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2;
289
290    if (data_size < kOpusHeaderSize) {
291        ALOGV("Header size is too small.");
292        return false;
293    }
294    header->channels = *(data + kOpusHeaderChannelsOffset);
295
296    if (header->channels <= 0 || header->channels > kMaxChannels) {
297        ALOGV("Invalid Header, wrong channel count: %d", header->channels);
298        return false;
299    }
300    header->skip_samples = ReadLE16(data, data_size,
301                                        kOpusHeaderSkipSamplesOffset);
302    header->gain_db = static_cast<int16_t>(
303                              ReadLE16(data, data_size,
304                                       kOpusHeaderGainOffset));
305    header->channel_mapping = *(data + kOpusHeaderChannelMappingOffset);
306    if (!header->channel_mapping) {
307        if (header->channels > kMaxChannelsWithDefaultLayout) {
308            ALOGV("Invalid Header, missing stream map.");
309            return false;
310        }
311        header->num_streams = 1;
312        header->num_coupled = header->channels > 1;
313        header->stream_map[0] = 0;
314        header->stream_map[1] = 1;
315        return true;
316    }
317    if (data_size < kOpusHeaderStreamMapOffset + header->channels) {
318        ALOGV("Invalid stream map; insufficient data for current channel "
319              "count: %d", header->channels);
320        return false;
321    }
322    header->num_streams = *(data + kOpusHeaderNumStreamsOffset);
323    header->num_coupled = *(data + kOpusHeaderNumCoupledOffset);
324    if (header->num_streams + header->num_coupled != header->channels) {
325        ALOGV("Inconsistent channel mapping.");
326        return false;
327    }
328    for (int i = 0; i < header->channels; ++i)
329      header->stream_map[i] = *(data + kOpusHeaderStreamMapOffset + i);
330    return true;
331}
332
333// Convert nanoseconds to number of samples.
334static uint64_t ns_to_samples(uint64_t ns, int kRate) {
335    return static_cast<double>(ns) * kRate / 1000000000;
336}
337
338void SoftOpus::onQueueFilled(OMX_U32 portIndex) {
339    List<BufferInfo *> &inQueue = getPortQueue(0);
340    List<BufferInfo *> &outQueue = getPortQueue(1);
341
342    if (mOutputPortSettingsChange != NONE) {
343        return;
344    }
345
346    if (portIndex == 0 && mInputBufferCount < 3) {
347        BufferInfo *info = *inQueue.begin();
348        OMX_BUFFERHEADERTYPE *header = info->mHeader;
349
350        const uint8_t *data = header->pBuffer + header->nOffset;
351        size_t size = header->nFilledLen;
352
353        if (mInputBufferCount == 0) {
354            CHECK(mHeader == NULL);
355            mHeader = new OpusHeader();
356            memset(mHeader, 0, sizeof(*mHeader));
357            if (!ParseOpusHeader(data, size, mHeader)) {
358                ALOGV("Parsing Opus Header failed.");
359                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
360                return;
361            }
362
363            uint8_t channel_mapping[kMaxChannels] = {0};
364            memcpy(&channel_mapping,
365                   kDefaultOpusChannelLayout,
366                   kMaxChannelsWithDefaultLayout);
367
368            int status = OPUS_INVALID_STATE;
369            mDecoder = opus_multistream_decoder_create(kRate,
370                                                       mHeader->channels,
371                                                       mHeader->num_streams,
372                                                       mHeader->num_coupled,
373                                                       channel_mapping,
374                                                       &status);
375            if (!mDecoder || status != OPUS_OK) {
376                ALOGV("opus_multistream_decoder_create failed status=%s",
377                      opus_strerror(status));
378                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
379                return;
380            }
381            status =
382                opus_multistream_decoder_ctl(mDecoder,
383                                             OPUS_SET_GAIN(mHeader->gain_db));
384            if (status != OPUS_OK) {
385                ALOGV("Failed to set OPUS header gain; status=%s",
386                      opus_strerror(status));
387                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
388                return;
389            }
390        } else if (mInputBufferCount == 1) {
391            mCodecDelay = ns_to_samples(
392                              *(reinterpret_cast<int64_t*>(header->pBuffer +
393                                                           header->nOffset)),
394                              kRate);
395            mSamplesToDiscard = mCodecDelay;
396        } else {
397            mSeekPreRoll = ns_to_samples(
398                               *(reinterpret_cast<int64_t*>(header->pBuffer +
399                                                            header->nOffset)),
400                               kRate);
401            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
402            mOutputPortSettingsChange = AWAITING_DISABLED;
403        }
404
405        inQueue.erase(inQueue.begin());
406        info->mOwnedByUs = false;
407        notifyEmptyBufferDone(header);
408        ++mInputBufferCount;
409        return;
410    }
411
412    while (!inQueue.empty() && !outQueue.empty()) {
413        BufferInfo *inInfo = *inQueue.begin();
414        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
415
416        BufferInfo *outInfo = *outQueue.begin();
417        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
418
419        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
420            inQueue.erase(inQueue.begin());
421            inInfo->mOwnedByUs = false;
422            notifyEmptyBufferDone(inHeader);
423
424            outHeader->nFilledLen = 0;
425            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
426
427            outQueue.erase(outQueue.begin());
428            outInfo->mOwnedByUs = false;
429            notifyFillBufferDone(outHeader);
430            return;
431        }
432
433        if (inHeader->nOffset == 0) {
434            mAnchorTimeUs = inHeader->nTimeStamp;
435            mNumFramesOutput = 0;
436        }
437
438        // When seeking to zero, |mCodecDelay| samples has to be discarded
439        // instead of |mSeekPreRoll| samples (as we would when seeking to any
440        // other timestamp).
441        if (inHeader->nTimeStamp == 0) {
442            mSamplesToDiscard = mCodecDelay;
443        }
444
445        const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
446        const uint32_t size = inHeader->nFilledLen;
447
448        int numFrames = opus_multistream_decode(mDecoder,
449                                                data,
450                                                size,
451                                                (int16_t *)outHeader->pBuffer,
452                                                kMaxOpusOutputPacketSizeSamples,
453                                                0);
454        if (numFrames < 0) {
455            ALOGE("opus_multistream_decode returned %d", numFrames);
456            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
457            return;
458        }
459
460        outHeader->nOffset = 0;
461        if (mSamplesToDiscard > 0) {
462            if (mSamplesToDiscard > numFrames) {
463                mSamplesToDiscard -= numFrames;
464                numFrames = 0;
465            } else {
466                numFrames -= mSamplesToDiscard;
467                outHeader->nOffset = mSamplesToDiscard * sizeof(int16_t) *
468                                     mHeader->channels;
469                mSamplesToDiscard = 0;
470            }
471        }
472
473        outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels;
474        outHeader->nFlags = 0;
475
476        outHeader->nTimeStamp = mAnchorTimeUs +
477                                (mNumFramesOutput * 1000000ll) /
478                                kRate;
479
480        mNumFramesOutput += numFrames;
481
482        inInfo->mOwnedByUs = false;
483        inQueue.erase(inQueue.begin());
484        inInfo = NULL;
485        notifyEmptyBufferDone(inHeader);
486        inHeader = NULL;
487
488        outInfo->mOwnedByUs = false;
489        outQueue.erase(outQueue.begin());
490        outInfo = NULL;
491        notifyFillBufferDone(outHeader);
492        outHeader = NULL;
493
494        ++mInputBufferCount;
495    }
496}
497
498void SoftOpus::onPortFlushCompleted(OMX_U32 portIndex) {
499    if (portIndex == 0 && mDecoder != NULL) {
500        // Make sure that the next buffer output does not still
501        // depend on fragments from the last one decoded.
502        mNumFramesOutput = 0;
503        opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE);
504        mAnchorTimeUs = 0;
505        mSamplesToDiscard = mSeekPreRoll;
506    }
507}
508
509void SoftOpus::onReset() {
510    mInputBufferCount = 0;
511    mNumFramesOutput = 0;
512    if (mDecoder != NULL) {
513        opus_multistream_decoder_destroy(mDecoder);
514        mDecoder = NULL;
515    }
516    if (mHeader != NULL) {
517        delete mHeader;
518        mHeader = NULL;
519    }
520
521    mOutputPortSettingsChange = NONE;
522}
523
524void SoftOpus::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
525    if (portIndex != 1) {
526        return;
527    }
528
529    switch (mOutputPortSettingsChange) {
530        case NONE:
531            break;
532
533        case AWAITING_DISABLED:
534        {
535            CHECK(!enabled);
536            mOutputPortSettingsChange = AWAITING_ENABLED;
537            break;
538        }
539
540        default:
541        {
542            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
543            CHECK(enabled);
544            mOutputPortSettingsChange = NONE;
545            break;
546        }
547    }
548}
549
550}  // namespace android
551
552android::SoftOMXComponent *createSoftOMXComponent(
553        const char *name, const OMX_CALLBACKTYPE *callbacks,
554        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
555    return new android::SoftOpus(name, callbacks, appData, component);
556}
557