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

Commit 16f2fa2d authored by Harish Mahendrakar's avatar Harish Mahendrakar Committed by Ray Essick
Browse files

OggWriter: Support format without CSD for opus

If format doesn't contain CSD, then look for it when writing sample
data.
When CSD is present in both Format and sample data, the one in format
is used like MPEG4Writer.

Bug: 131747486
Bug: 134509194
Test: poc from bug

Change-Id: If2cab79d540688283afb4d74a6b043ea2e089ef0
parent 50f9a132
Loading
Loading
Loading
Loading
+41 −8
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ namespace android {

OggWriter::OggWriter(int fd)
      : mFd(dup(fd)),
        mHaveAllCodecSpecificData(false),
        mInitCheck(mFd < 0 ? NO_INIT : OK) {
    // empty
}
@@ -115,17 +116,26 @@ status_t OggWriter::addSource(const sp<MediaSource>& source) {

    mSampleRate = sampleRate;
    uint32_t type;
    const void *header_data;
    size_t packet_size;
    const void *header_data = NULL;
    size_t packet_size = 0;

    if (!source->getFormat()->findData(kKeyOpusHeader, &type, &header_data, &packet_size)) {
        ALOGE("opus header not found");
        return UNKNOWN_ERROR;
        ALOGV("opus header not found in format");
    } else if (header_data && packet_size) {
        writeOggHeaderPackets((unsigned char *)header_data, packet_size);
    } else {
        ALOGD("ignoring incomplete opus header data in format");
    }

    mSource = source;
    return OK;
}

status_t OggWriter::writeOggHeaderPackets(unsigned char *buf, size_t size) {
    ogg_packet op;
    ogg_page og;
    op.packet = (unsigned char *)header_data;
    op.bytes = packet_size;
    op.packet = buf;
    op.bytes = size;
    op.b_o_s = 1;
    op.e_o_s = 0;
    op.granulepos = 0;
@@ -169,8 +179,8 @@ status_t OggWriter::addSource(const sp<MediaSource>& source) {
        write(mFd, og.body, og.body_len);
    }

    mSource = source;
    free(comments);
    mHaveAllCodecSpecificData = true;
    return OK;
}

@@ -301,12 +311,35 @@ status_t OggWriter::threadFunc() {
             && isCodecSpecific)
            || IsOpusHeader((uint8_t*)buffer->data() + buffer->range_offset(),
                         buffer->range_length())) {
            ALOGV("Drop codec specific info buffer");
            if (mHaveAllCodecSpecificData == false) {
                size_t opusHeadSize = 0;
                size_t codecDelayBufSize = 0;
                size_t seekPreRollBufSize = 0;
                void *opusHeadBuf = NULL;
                void *codecDelayBuf = NULL;
                void *seekPreRollBuf = NULL;
                GetOpusHeaderBuffers((uint8_t*)buffer->data() + buffer->range_offset(),
                                    buffer->range_length(), &opusHeadBuf,
                                    &opusHeadSize, &codecDelayBuf,
                                    &codecDelayBufSize, &seekPreRollBuf,
                                    &seekPreRollBufSize);
                writeOggHeaderPackets((unsigned char *)opusHeadBuf, opusHeadSize);
            } else {
                ALOGV("ignoring later copy of CSD contained in info buffer");
            }
            buffer->release();
            buffer = nullptr;
            continue;
        }

        if (mHaveAllCodecSpecificData == false) {
            ALOGE("Did not get valid opus header before first sample data");
            buffer->release();
            buffer = nullptr;
            err = ERROR_MALFORMED;
            break;
        }

        int64_t timestampUs;
        CHECK(buffer->meta_data().findInt64(kKeyTime, &timestampUs));
        if (timestampUs > mEstimatedDurationUs) {
+3 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ protected:

private:
    int mFd;
    bool mHaveAllCodecSpecificData;
    status_t mInitCheck;
    sp<MediaSource> mSource;
    bool mStarted = false;
@@ -66,6 +67,8 @@ private:

    OggWriter(const OggWriter&);
    OggWriter& operator=(const OggWriter&);

    status_t writeOggHeaderPackets(unsigned char *buf, size_t size);
};

}  // namespace android