Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc14a839 authored by Andreas Huber's avatar Andreas Huber
Browse files

Support a single format change at the beginning of audio playback. This way...

Support a single format change at the beginning of audio playback. This way the AAC+ decoder may change its output format from what is originally encoded in the audio stream and we'll still play it back correctly.

Change-Id: Icc790122744745e9a88099788d4818ca1e265a82
related-to-bug: 2826841
parent faf1d46a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -86,6 +86,10 @@ private:

    bool mStarted;

    bool mIsFirstBuffer;
    status_t mFirstBufferResult;
    MediaBuffer *mFirstBuffer;

    sp<MediaPlayerBase::AudioSink> mAudioSink;

    static void AudioCallback(int event, void *user, void *info);
+56 −1
Original line number Diff line number Diff line
@@ -41,6 +41,9 @@ AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink)
      mReachedEOS(false),
      mFinalStatus(OK),
      mStarted(false),
      mIsFirstBuffer(false),
      mFirstBufferResult(OK),
      mFirstBuffer(NULL),
      mAudioSink(audioSink) {
}

@@ -68,6 +71,24 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
        }
    }

    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
    // of playback, if there is one, getFormat below will retrieve the
    // updated format, if there isn't, we'll stash away the valid buffer
    // of data to be used on the first audio callback.

    CHECK(mFirstBuffer == NULL);

    mFirstBufferResult = mSource->read(&mFirstBuffer);
    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
        LOGV("INFO_FORMAT_CHANGED!!!");

        CHECK(mFirstBuffer == NULL);
        mFirstBufferResult = OK;
        mIsFirstBuffer = false;
    } else {
        mIsFirstBuffer = true;
    }

    sp<MetaData> format = mSource->getFormat();
    const char *mime;
    bool success = format->findCString(kKeyMIMEType, &mime);
@@ -87,6 +108,11 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
                DEFAULT_AUDIOSINK_BUFFERCOUNT,
                &AudioPlayer::AudioSinkCallback, this);
        if (err != OK) {
            if (mFirstBuffer != NULL) {
                mFirstBuffer->release();
                mFirstBuffer = NULL;
            }

            if (!sourceAlreadyStarted) {
                mSource->stop();
            }
@@ -110,6 +136,11 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
            delete mAudioTrack;
            mAudioTrack = NULL;

            if (mFirstBuffer != NULL) {
                mFirstBuffer->release();
                mFirstBuffer = NULL;
            }

            if (!sourceAlreadyStarted) {
                mSource->stop();
            }
@@ -163,6 +194,12 @@ void AudioPlayer::stop() {

    // Make sure to release any buffer we hold onto so that the
    // source is able to stop().

    if (mFirstBuffer != NULL) {
        mFirstBuffer->release();
        mFirstBuffer = NULL;
    }

    if (mInputBuffer != NULL) {
        LOGV("AudioPlayer releasing input buffer.");

@@ -247,6 +284,14 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) {
            Mutex::Autolock autoLock(mLock);

            if (mSeeking) {
                if (mIsFirstBuffer) {
                    if (mFirstBuffer != NULL) {
                        mFirstBuffer->release();
                        mFirstBuffer = NULL;
                    }
                    mIsFirstBuffer = false;
                }

                options.setSeekTo(mSeekTimeUs);

                if (mInputBuffer != NULL) {
@@ -259,7 +304,17 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) {
        }

        if (mInputBuffer == NULL) {
            status_t err = mSource->read(&mInputBuffer, &options);
            status_t err;

            if (mIsFirstBuffer) {
                mInputBuffer = mFirstBuffer;
                mFirstBuffer = NULL;
                err = mFirstBufferResult;

                mIsFirstBuffer = false;
            } else {
                err = mSource->read(&mInputBuffer, &options);
            }

            CHECK((err == OK && mInputBuffer != NULL)
                   || (err != OK && mInputBuffer == NULL));
+4 −66
Original line number Diff line number Diff line
@@ -1287,11 +1287,6 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
    uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
    int32_t sampleRate = 0;
    int32_t numChannels = 0;
    uint8_t offset = 0;
    static uint32_t kSamplingRate[] = {
        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
        16000, 12000, 11025, 8000, 7350
    };
    if (freqIndex == 15) {
        if (csd_size < 5) {
            return ERROR_MALFORMED;
@@ -1303,8 +1298,11 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
                        | (csd[4] >> 7);

        numChannels = (csd[4] >> 3) & 15;
        offset = 4;
    } else {
        static uint32_t kSamplingRate[] = {
            96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
            16000, 12000, 11025, 8000, 7350
        };

        if (freqIndex == 13 || freqIndex == 14) {
            return ERROR_MALFORMED;
@@ -1312,66 +1310,6 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(

        sampleRate = kSamplingRate[freqIndex];
        numChannels = (csd[1] >> 3) & 15;
        offset = 1;
    }

    uint8_t sbrPresentFlag = -1;
    uint8_t extensionAudioObjectType = 0;
    if (objectType == 5) {
        extensionAudioObjectType = objectType;
        sbrPresentFlag = 1;
        freqIndex = ((csd[offset] & 7) << 1) | (csd[offset + 1] >> 7);
        offset += 1;
        if (freqIndex == 15) {
            sampleRate = (((csd[offset] & 0x7f) << 17)
                            | (csd[offset + 1] << 9)
                            | (csd[offset + 2] << 1)
                            | (csd[offset + 3] >> 7));
            offset += 3;
        }
        objectType = csd[offset] >> 3;
    }

    if (((objectType >= 1 && objectType <= 4) ||
         (objectType >= 6 && objectType <= 7) ||
         (objectType == 17) ||
         (objectType >= 19 || objectType <= 23)) &&
        (0x00 == (csd[offset] & 7)) &&
        numChannels != 0) {

        // XXX: We are not handling coreCoderDelay,
        //      program_config_element(),
        //      extensionFlag, scalable profile, etc.
        if (objectType != 6 && objectType != 20) {
            if (objectType != 5 && csd_size - offset >= 2) {
                uint32_t syncExtensionType =
                    (csd[offset + 1] << 3) | (csd[offset + 2] >> 5);
                if (syncExtensionType == 0x2b7) {
                    extensionAudioObjectType =
                            csd[offset + 2] & 0x1F;
                    if (extensionAudioObjectType == 0x05) {
                        if (csd_size - offset < 3) {
                            return ERROR_MALFORMED;
                        }
                        uint8_t sbrPresentFlag = csd[offset + 3] & 0x80;
                        if (sbrPresentFlag) {
                            freqIndex = (csd[offset + 3] & 0x78) >> 3;
                            if (freqIndex == 15) {
                                if (csd_size - offset < 6) {
                                    return ERROR_MALFORMED;
                                }
                                sampleRate = (csd[offset + 3] & 0x07) << 21
                                        | csd[offset + 4] << 13
                                        | csd[offset + 5] << 5
                                        | csd[offset + 6] >> 3;
                            } else {
                                sampleRate = kSamplingRate[freqIndex];
                            }
                        }
                    }
                }
            }
        }
    }

    if (numChannels == 0) {