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

Commit d637d296 authored by Lajos Molnar's avatar Lajos Molnar
Browse files

stagefright: fix hdr/color metadata handling for .mkv files

This is needed for proper VP9 profile detection

Bug: 28671284
Change-Id: Ief313c9635462db7157988d7446e40f54e4cada7
parent f489ff89
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -194,8 +194,7 @@ enum {
    kKeyNalLengthSize     = 'nals', // int32_t

    // HDR related
    kKeyMinLuminance     = 'minL', // int32_t, min luminance of the content in cd/m2.
    kKeyMaxLuminance     = 'maxL', // int32_t, max luminance of the content in cd/m2.
    kKeyHdrStaticInfo    = 'hdrS', // HDRStaticInfo

    // color aspects
    kKeyColorRange       = 'cRng', // int32_t, color range, value defined by ColorAspects.Range
+19 −4
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ static status_t copyNALUToABuffer(sp<ABuffer> *buffer, const uint8_t *ptr, size_
    return OK;
}

#if 0
static void convertMetaDataToMessageInt32(
        const sp<MetaData> &meta, sp<AMessage> &msg, uint32_t key, const char *name) {
    int32_t value;
@@ -103,6 +104,7 @@ static void convertMetaDataToMessageInt32(
        msg->setInt32(name, value);
    }
}
#endif

static void convertMetaDataToMessageColorAspects(const sp<MetaData> &meta, sp<AMessage> &msg) {
    // 0 values are unspecified
@@ -631,8 +633,14 @@ status_t convertMetaDataToMessage(
            msg->setInt32("rotation-degrees", rotationDegrees);
        }

        convertMetaDataToMessageInt32(meta, msg, kKeyMinLuminance, "min-luminance");
        convertMetaDataToMessageInt32(meta, msg, kKeyMaxLuminance, "max-luminance");
        uint32_t type;
        const void *data;
        size_t size;
        if (meta->findData(kKeyHdrStaticInfo, &type, &data, &size)
                && type == 'hdrS' && size == sizeof(HDRStaticInfo)) {
            ColorUtils::setHDRStaticInfoIntoFormat(*(HDRStaticInfo*)data, msg);
        }

        convertMetaDataToMessageColorAspects(meta, msg);
    } else if (!strncasecmp("audio/", mime, 6)) {
        int32_t numChannels, sampleRate;
@@ -1146,6 +1154,7 @@ static size_t reassembleHVCC(const sp<ABuffer> &csd0, uint8_t *hvcc, size_t hvcc
    return size;
}

#if 0
static void convertMessageToMetaDataInt32(
        const sp<AMessage> &msg, sp<MetaData> &meta, uint32_t key, const char *name) {
    int32_t value;
@@ -1153,6 +1162,7 @@ static void convertMessageToMetaDataInt32(
        meta->setInt32(key, value);
    }
}
#endif

static void convertMessageToMetaDataColorAspects(const sp<AMessage> &msg, sp<MetaData> &meta) {
    // 0 values are unspecified
@@ -1237,8 +1247,13 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
            meta->setInt32(kKeyRotation, rotationDegrees);
        }

        convertMessageToMetaDataInt32(msg, meta, kKeyMinLuminance, "min-luminance");
        convertMessageToMetaDataInt32(msg, meta, kKeyMaxLuminance, "max-luminance");
        if (msg->contains("hdr-static-info")) {
            HDRStaticInfo info;
            if (ColorUtils::getHDRStaticInfoFromFormat(msg, &info)) {
                meta->setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info));
            }
        }

        convertMessageToMetaDataColorAspects(msg, meta);
    } else if (mime.startsWith("audio/")) {
        int32_t numChannels;
+107 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaBuffer.h>
@@ -1058,6 +1059,109 @@ status_t MatroskaExtractor::synthesizeAVCC(TrackInfo *trackInfo, size_t index) {
    return OK;
}

static inline bool isValidInt32ColourValue(long long value) {
    return value != mkvparser::Colour::kValueNotPresent
            && value >= INT32_MIN
            && value <= INT32_MAX;
}

static inline bool isValidUint16ColourValue(long long value) {
    return value != mkvparser::Colour::kValueNotPresent
            && value >= 0
            && value <= UINT16_MAX;
}

static inline bool isValidPrimary(const mkvparser::PrimaryChromaticity *primary) {
    return primary != NULL && primary->x >= 0 && primary->x <= 1
             && primary->y >= 0 && primary->y <= 1;
}

void MatroskaExtractor::getColorInformation(
        const mkvparser::VideoTrack *vtrack, sp<MetaData> &meta) {
    const mkvparser::Colour *color = vtrack->GetColour();
    if (color == NULL) {
        return;
    }

    // Color Aspects
    {
        int32_t primaries = 2; // ISO unspecified
        int32_t transfer = 2; // ISO unspecified
        int32_t coeffs = 2; // ISO unspecified
        bool fullRange = false; // default
        bool rangeSpecified = false;

        if (isValidInt32ColourValue(color->primaries)) {
            primaries = color->primaries;
        }
        if (isValidInt32ColourValue(color->transfer_characteristics)) {
            transfer = color->transfer_characteristics;
        }
        if (isValidInt32ColourValue(color->matrix_coefficients)) {
            coeffs = color->matrix_coefficients;
        }
        if (color->range != mkvparser::Colour::kValueNotPresent
                && color->range != 0 /* MKV unspecified */) {
            // We only support MKV broadcast range (== limited) and full range.
            // We treat all other value as the default limited range.
            fullRange = color->range == 2 /* MKV fullRange */;
            rangeSpecified = true;
        }

        ColorAspects aspects;
        ColorUtils::convertIsoColorAspectsToCodecAspects(
                primaries, transfer, coeffs, fullRange, aspects);
        meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries);
        meta->setInt32(kKeyTransferFunction, aspects.mTransfer);
        meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
        meta->setInt32(
                kKeyColorRange, rangeSpecified ? aspects.mRange : ColorAspects::RangeUnspecified);
    }

    // HDR Static Info
    {
        HDRStaticInfo info, nullInfo; // nullInfo is a fully unspecified static info
        memset(&info, 0, sizeof(info));
        memset(&nullInfo, 0, sizeof(nullInfo));
        if (isValidUint16ColourValue(color->max_cll)) {
            info.sType1.mMaxContentLightLevel = color->max_cll;
        }
        if (isValidUint16ColourValue(color->max_fall)) {
            info.sType1.mMaxFrameAverageLightLevel = color->max_fall;
        }
        const mkvparser::MasteringMetadata *mastering = color->mastering_metadata;
        if (mastering != NULL) {
            // Convert matroska values to HDRStaticInfo equivalent values for each fully specified
            // group. See CTA-681.3 section 3.2.1 for more info.
            if (mastering->luminance_max >= 0.5 && mastering->luminance_max < 65535.5) {
                info.sType1.mMaxDisplayLuminance = (uint16_t)(mastering->luminance_max + 0.5);
            }
            if (mastering->luminance_min >= 0.00005 && mastering->luminance_min < 6.55355) {
                info.sType1.mMinDisplayLuminance =
                    (uint16_t)(10000 * mastering->luminance_min + 0.5);
            }
            if (isValidPrimary(mastering->white_point)) {
                info.sType1.mW.x = (uint16_t)(50000 * mastering->white_point->x + 0.5);
                info.sType1.mW.y = (uint16_t)(50000 * mastering->white_point->y + 0.5);
            }
            if (isValidPrimary(mastering->r) && isValidPrimary(mastering->g)
                    && isValidPrimary(mastering->b)) {
                info.sType1.mR.x = (uint16_t)(50000 * mastering->r->x + 0.5);
                info.sType1.mR.y = (uint16_t)(50000 * mastering->r->y + 0.5);
                info.sType1.mG.x = (uint16_t)(50000 * mastering->g->x + 0.5);
                info.sType1.mG.y = (uint16_t)(50000 * mastering->g->y + 0.5);
                info.sType1.mB.x = (uint16_t)(50000 * mastering->b->x + 0.5);
                info.sType1.mB.y = (uint16_t)(50000 * mastering->b->y + 0.5);
            }
        }
        // Only advertise static info if at least one of the groups have been specified.
        if (memcmp(&info, &nullInfo, sizeof(info)) != 0) {
            info.mID = HDRStaticInfo::kType1;
            meta->setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info));
        }
    }
}

void MatroskaExtractor::addTracks() {
    const mkvparser::Tracks *tracks = mSegment->GetTracks();

@@ -1127,6 +1231,9 @@ void MatroskaExtractor::addTracks() {

                meta->setInt32(kKeyWidth, vtrack->GetWidth());
                meta->setInt32(kKeyHeight, vtrack->GetHeight());

                getColorInformation(vtrack, meta);

                break;
            }

+2 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ namespace android {
struct AMessage;
class String8;

class MetaData;
struct DataSourceReader;
struct MatroskaSource;

@@ -80,7 +81,7 @@ private:
    status_t synthesizeAVCC(TrackInfo *trackInfo, size_t index);
    void addTracks();
    void findThumbnails();

    void getColorInformation(const mkvparser::VideoTrack *vtrack, sp<MetaData> &meta);
    bool isLiveStreaming() const;

    MatroskaExtractor(const MatroskaExtractor &);
+18 −0
Original line number Diff line number Diff line
@@ -98,6 +98,24 @@ enum Mkv {
    kMkvDisplayHeight = 0x54BA,
    kMkvDisplayUnit = 0x54B2,
    kMkvAspectRatioType = 0x54B3,
    kMkvColour = 0x55B0,
    kMkvColourMatrixCoefficients = 0x55B1,
    kMkvColourRange = 0x55B9,
    kMkvColourTransferCharacteristics = 0x55BA,
    kMkvColourPrimaries = 0x55BB,
    kMkvColourMaxCll = 0x55BC,
    kMkvColourMaxFall = 0x55BD,
    kMkvMasteringMetadata = 0x55D0,
    kMkvMasteringPrimaryRChromaticityX = 0x55D1,
    kMkvMasteringPrimaryRChromaticityY = 0x55D2,
    kMkvMasteringPrimaryGChromaticityX = 0x55D3,
    kMkvMasteringPrimaryGChromaticityY = 0x55D4,
    kMkvMasteringPrimaryBChromaticityX = 0x55D5,
    kMkvMasteringPrimaryBChromaticityY = 0x55D6,
    kMkvMasteringWhitePointChromaticityX = 0x55D7,
    kMkvMasteringWhitePointChromaticityY = 0x55D8,
    kMkvMasteringLuminanceMax = 0x55D9,
    kMkvMasteringLuminanceMin = 0x55DA,
    kMkvFrameRate = 0x2383E3,
    kMkvAudio = 0xE1,
    kMkvSamplingFrequency = 0xB5,
Loading