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

Commit 80f78b77 authored by Praveen Chavan's avatar Praveen Chavan Committed by Wei Jia
Browse files

MPEG4Writer: Handle writing multiple NAL units in a video sample

Encoder may prepend extension NALs (eg: AVC SVC extension NAL
for temporal layer info) to the VCL NAL.
Look out for non-VCL NALUs preceeding the slice NALs and write
them out separately.
Search for a limited size since such NALs are of small size.

Bug: 27596987
Change-Id: I434c5252098faca99c0ee18e6bc5f43a67718eba
(cherry picked from commit 7941196cf2f21c1a59c5cb2e8b93bbb6f7ff463c)
parent bf6dc1af
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -187,6 +187,7 @@ private:
    // Acquire lock before calling these methods
    off64_t addSample_l(MediaBuffer *buffer);
    off64_t addLengthPrefixedSample_l(MediaBuffer *buffer);
    off64_t addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer);

    bool exceedsFileSizeLimit();
    bool use32BitFileOffset() const;
+34 −2
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@

#include "include/ESDS.h"
#include "include/HevcUtils.h"
#include "include/avc_utils.h"

#ifndef __predict_false
#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
@@ -1162,6 +1163,37 @@ static void StripStartcode(MediaBuffer *buffer) {
    }
}

off64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) {
    off64_t old_offset = mOffset;

    const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs

    const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset();
    const uint8_t *currentNalStart = dataStart;
    const uint8_t *nextNalStart;
    const uint8_t *data = dataStart;
    size_t nextNalSize;
    size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ?
                   kExtensionNALSearchRange : buffer->range_length();

    while (getNextNALUnit(&data, &searchSize, &nextNalStart,
            &nextNalSize, true) == OK) {
        size_t currentNalSize = nextNalStart - currentNalStart - 3 /* strip start-code */;
        MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize);
        addLengthPrefixedSample_l(nalBuf);
        nalBuf->release();

        currentNalStart = nextNalStart;
    }

    size_t currentNalOffset = currentNalStart - dataStart;
    buffer->set_range(buffer->range_offset() + currentNalOffset,
            buffer->range_length() - currentNalOffset);
    addLengthPrefixedSample_l(buffer);

    return old_offset;
}

off64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
    off64_t old_offset = mOffset;

@@ -1684,7 +1716,7 @@ void MPEG4Writer::writeChunkToFile(Chunk* chunk) {
        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();

        off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
                                ? addLengthPrefixedSample_l(*it)
                                ? addMultipleLengthPrefixedSamples_l(*it)
                                : addSample_l(*it);

        if (isFirstSample) {
@@ -2593,7 +2625,7 @@ status_t MPEG4Writer::Track::threadEntry() {
            trackProgressStatus(timestampUs);
        }
        if (!hasMultipleTracks) {
            off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addLengthPrefixedSample_l(copy)
            off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy)
                                 : mOwner->addSample_l(copy);

            uint32_t count = (mOwner->use32BitFileOffset()