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

Commit fd085d12 authored by Apurupa Pattapu's avatar Apurupa Pattapu Committed by Steve Kondik
Browse files

mpeg2ts: Add support for parsing HEVC stream in MPEG2 TS container

- Add support for the HEVC codec in ATSParser via ExtendedUtils
- Extract width & height from the raw bitstream
- Add IDR detection support for seek
- Update the HLS stack to handle HEVC

CRs-Fixed: 797719
Change-Id: Iac32de93c7876ca69d47f5a24f01122560ac7be8
parent bd1850f2
Loading
Loading
Loading
Loading
+64 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@
#include <sys/socket.h>
#include <netdb.h>

#include "include/avc_utils.h"
#include "include/ExtendedUtils.h"

static const int64_t kDefaultAVSyncLateMargin =  40000;
@@ -63,6 +64,10 @@ static const unsigned kMinRtpPort = 1024;
static const unsigned kMaxRtpPort = 65535;

#define ARG_TOUCH(x) (void)x

static const uint8_t kHEVCNalUnitTypeIDR         = 0x13;
static const uint8_t kHEVCNalUnitTypeIDRNoLP     = 0x14;
static const uint8_t kHEVCNalUnitTypeCRA         = 0x15;
static const uint8_t kHEVCNalUnitTypeVidParamSet = 0x20;
static const uint8_t kHEVCNalUnitTypeSeqParamSet = 0x21;
static const uint8_t kHEVCNalUnitTypePicParamSet = 0x22;
@@ -713,6 +718,55 @@ status_t ExtendedUtils::HEVCMuxer::makeHEVCCodecSpecificData(
    return OK;
}

sp<MetaData> ExtendedUtils::MakeHEVCCodecSpecificData(const sp<ABuffer> &accessUnit) {
    const uint8_t *data = accessUnit->data();
    size_t size = accessUnit->size();

    if (data == NULL || size == 0) {
        ALOGE("Invalid HEVC CSD");
        return NULL;
    }

    sp<MetaData> meta = new MetaData;
    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
    meta->setData(kKeyHVCC, kTypeHVCC, data, size);

    // Set width & height to minimum (QCIF). This will trigger a port reconfig &
    // the decoder will find the correct dimensions.
    meta->setInt32(kKeyWidth, (int32_t)177);
    meta->setInt32(kKeyHeight, (int32_t)144);

    return meta;
}

bool ExtendedUtils::IsHevcIDR(const sp<ABuffer> &buffer) {
    const uint8_t *data = buffer->data();
    size_t size = buffer->size();

    bool foundRef = false;
    const uint8_t *nalStart;
    size_t nalSize;
    while (!foundRef && getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
        if (nalSize == 0) {
            ALOGW("Encountered zero-length HEVC NAL", nalSize);
            return false;
        }

        uint8_t nalType;
        getHEVCNalUnitType(nalStart[0], &nalType);

        switch(nalType) {
        case kHEVCNalUnitTypeIDR:
        case kHEVCNalUnitTypeIDRNoLP:
        case kHEVCNalUnitTypeCRA:
            foundRef = true;
            break;
        }
    }

    return foundRef;
}

bool ExtendedUtils::ShellProp::isAudioDisabled(bool isEncoder) {
    bool retVal = false;
    char disableAudio[PROPERTY_VALUE_MAX];
@@ -1995,6 +2049,16 @@ int32_t ExtendedUtils::HFR::getHFRCapabilities(
    return -1;
}

sp<MetaData> ExtendedUtils::MakeHEVCCodecSpecificData(const sp<ABuffer> &accessUnit) {
    ARG_TOUCH(accessUnit);
    return NULL;
}

bool ExtendedUtils::IsHevcIDR(const sp<ABuffer> &buffer) {
    ARG_TOUCH(buffer);
    return false;
}

bool ExtendedUtils::ShellProp::isAudioDisabled(bool isEncoder) {
    ARG_TOUCH(isEncoder);
    return false;
+0 −1
Original line number Diff line number Diff line
@@ -282,7 +282,6 @@ status_t convertMetaDataToMessage(
        const uint8_t *ptr = (const uint8_t *)data;

        CHECK(size >= 7);
        //CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
        uint8_t profile __unused = ptr[1] & 31;
        uint8_t level __unused = ptr[12];
        ptr += 22;
+11 −5
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "M3UParser.h"

#include "include/avc_utils.h"
#include "include/ExtendedUtils.h"
#include "include/HTTPBase.h"
#include "include/ID3.h"
#include "mpeg2ts/AnotherPacketSource.h"
@@ -1282,14 +1283,19 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
                    const char *mime;
                    sp<MetaData> format  = source->getFormat();
                    bool isAvc = false;
                    if (format != NULL && format->findCString(kKeyMIMEType, &mime)
                            && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
                    bool isHevc = false;
                    if (format != NULL && format->findCString(kKeyMIMEType, &mime)) {
                        if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
                            isAvc = true;
                        } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
                            isHevc = true;
                        }
                    if (isAvc && IsIDR(accessUnit)) {
                    }
                    if ((isAvc && IsIDR(accessUnit)) || (isHevc &&
                            ExtendedUtils::IsHevcIDR(accessUnit))) {
                        mVideoBuffer->clear();
                    }
                    if (isAvc) {
                    if (isAvc || isHevc) {
                        mVideoBuffer->queueAccessUnit(accessUnit);
                    }

+3 −0
Original line number Diff line number Diff line
@@ -267,6 +267,9 @@ struct ExtendedUtils {
	
    static bool is24bitPCMOffloaded(
                const sp<MetaData> &sMeta);

    static sp<MetaData> MakeHEVCCodecSpecificData(const sp<ABuffer> &accessUnit);
    static bool IsHevcIDR(const sp<ABuffer> &accessUnit);
};

}
+14 −2
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include "AnotherPacketSource.h"
#include "ESQueue.h"
#include "include/avc_utils.h"
#include "include/ExtendedUtils.h"

#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -521,6 +522,13 @@ ATSParser::Stream::Stream(
                    (mProgram->parserFlags() & ALIGNED_VIDEO_DATA)
                        ? ElementaryStreamQueue::kFlag_AlignedData : 0);
            break;
        case STREAMTYPE_H265:
            ALOGV("create ESQ for H265");
            mQueue = new ElementaryStreamQueue(
                    ElementaryStreamQueue::H265,
                    (mProgram->parserFlags() & ALIGNED_VIDEO_DATA)
                        ? ElementaryStreamQueue::kFlag_AlignedData : 0);
            break;
        case STREAMTYPE_MPEG2_AUDIO_ADTS:
            mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::AAC);
            break;
@@ -631,6 +639,7 @@ status_t ATSParser::Stream::parse(
bool ATSParser::Stream::isVideo() const {
    switch (mStreamType) {
        case STREAMTYPE_H264:
        case STREAMTYPE_H265:
        case STREAMTYPE_MPEG1_VIDEO:
        case STREAMTYPE_MPEG2_VIDEO:
        case STREAMTYPE_MPEG4_VIDEO:
@@ -928,9 +937,12 @@ void ATSParser::Stream::onPayloadData(
                     mElementaryPID, mStreamType);

                const char *mime;
                bool isAvcIDR = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
                        && !IsIDR(accessUnit);
                bool isHevcIDR = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)
                        && !ExtendedUtils::IsHevcIDR(accessUnit);
                if (meta->findCString(kKeyMIMEType, &mime)
                        && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
                        && !IsIDR(accessUnit)) {
                        && (isAvcIDR || isHevcIDR)) {
                    continue;
                }
                mSource = new AnotherPacketSource(meta);
Loading