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

Commit 0a69bd28 authored by Marco Nelissen's avatar Marco Nelissen
Browse files

Add support for MPEG editlist gapless info

Change-Id: I862d89c805d738db9bdf81a8f1c5b317ff968dff
parent a02eae5e
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -817,6 +817,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
        case FOURCC('i', 'l', 's', 't'):
        case FOURCC('s', 'i', 'n', 'f'):
        case FOURCC('s', 'c', 'h', 'i'):
        case FOURCC('e', 'd', 't', 's'):
        {
            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
                ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
@@ -904,6 +905,66 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
            break;
        }

        case FOURCC('e', 'l', 's', 't'):
        {
            // See 14496-12 8.6.6
            uint8_t version;
            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
                return ERROR_IO;
            }

            uint32_t entry_count;
            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
                return ERROR_IO;
            }

            if (entry_count != 1) {
                // we only support a single entry at the moment, for gapless playback
                ALOGW("ignoring edit list with %d entries", entry_count);
            } else {
                off64_t entriesoffset = data_offset + 8;
                uint64_t segment_duration;
                int64_t media_time;

                if (version == 1) {
                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
                        return ERROR_IO;
                    }
                } else if (version == 0) {
                    uint32_t sd;
                    int32_t mt;
                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
                        return ERROR_IO;
                    }
                    segment_duration = sd;
                    media_time = mt;
                } else {
                    return ERROR_IO;
                }

                uint64_t halfscale = mLastTrack->timescale / 2;
                segment_duration = (segment_duration * 1000000 + halfscale)/ mLastTrack->timescale;
                media_time = (media_time * 1000000 + halfscale) / mLastTrack->timescale;

                int64_t duration;
                int32_t samplerate;
                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {

                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);

                    int64_t paddingus = duration - (segment_duration + media_time);
                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
                }
            }
            *offset += chunk_size;
            break;
        }

        case FOURCC('f', 'r', 'm', 'a'):
        {
            uint32_t original_fourcc;