diff options
author | Hendrik Leppkes <h.leppkes@gmail.com> | 2016-11-18 17:07:31 +0300 |
---|---|---|
committer | Hendrik Leppkes <h.leppkes@gmail.com> | 2017-08-04 20:18:34 +0300 |
commit | 851687d17f7819ce2b8acd06e66c8e24d7da6924 (patch) | |
tree | 4d5ef8cdf671b631d6f5e0bc0944747f4de1dc3a | |
parent | 333a44b8bb0f9ba8befff76e49423e741c576468 (diff) |
matroskadec_haali: parse color and mastering info
-rw-r--r-- | libavformat/MatroskaParser.c | 88 | ||||
-rw-r--r-- | libavformat/MatroskaParser.h | 27 | ||||
-rw-r--r-- | libavformat/matroskadec_haali.c | 77 |
3 files changed, 192 insertions, 0 deletions
diff --git a/libavformat/MatroskaParser.c b/libavformat/MatroskaParser.c index 497581cc1c..173c2e1c20 100644 --- a/libavformat/MatroskaParser.c +++ b/libavformat/MatroskaParser.c @@ -1190,6 +1190,84 @@ out: ENDFOR(mf); } +static void parseVideoColourInfo(MatroskaFile *mf,ulonglong toplen,struct TrackInfo *ti) { + FOREACH(mf,toplen) + case 0x55b1: + ti->AV.Video.Colour.MatrixCoefficients = readUInt(mf,(unsigned)len); + break; + case 0x55b2: + ti->AV.Video.Colour.BitsPerChannel = readUInt(mf,(unsigned)len); + break; + case 0x55b3: + ti->AV.Video.Colour.ChromaSubsamplingHorz = readUInt(mf,(unsigned)len); + break; + case 0x55b4: + ti->AV.Video.Colour.ChromaSubsamplingVert = readUInt(mf,(unsigned)len); + break; + case 0x55b5: + ti->AV.Video.Colour.CbSubsamplingHorz = readUInt(mf,(unsigned)len); + break; + case 0x55b6: + ti->AV.Video.Colour.CbSubsamplingVert = readUInt(mf,(unsigned)len); + break; + case 0x55b7: + ti->AV.Video.Colour.ChromaSitingHorz = readUInt(mf,(unsigned)len); + break; + case 0x55b8: + ti->AV.Video.Colour.ChromaSitingVert = readUInt(mf,(unsigned)len); + break; + case 0x55b9: + ti->AV.Video.Colour.Range = readUInt(mf,(unsigned)len); + break; + case 0x55ba: + ti->AV.Video.Colour.TransferCharacteristics = readUInt(mf,(unsigned)len); + break; + case 0x55bb: + ti->AV.Video.Colour.Primaries = readUInt(mf,(unsigned)len); + break; + case 0x55bc: + ti->AV.Video.Colour.MaxCLL = readUInt(mf,(unsigned)len); + break; + case 0x55bd: + ti->AV.Video.Colour.MaxFALL = readUInt(mf,(unsigned)len); + break; + case 0x55d0: + FOREACH(mf,len) + case 0x55d1: + ti->AV.Video.Colour.MasteringMetadata.PrimaryRChromaticityX = readFloat(mf,(unsigned)len); + break; + case 0x55d2: + ti->AV.Video.Colour.MasteringMetadata.PrimaryRChromaticityY = readFloat(mf,(unsigned)len); + break; + case 0x55d3: + ti->AV.Video.Colour.MasteringMetadata.PrimaryGChromaticityX = readFloat(mf,(unsigned)len); + break; + case 0x55d4: + ti->AV.Video.Colour.MasteringMetadata.PrimaryGChromaticityY = readFloat(mf,(unsigned)len); + break; + case 0x55d5: + ti->AV.Video.Colour.MasteringMetadata.PrimaryBChromaticityX = readFloat(mf,(unsigned)len); + break; + case 0x55d6: + ti->AV.Video.Colour.MasteringMetadata.PrimaryBChromaticityY = readFloat(mf,(unsigned)len); + break; + case 0x55d7: + ti->AV.Video.Colour.MasteringMetadata.WhitePointChromaticityX = readFloat(mf,(unsigned)len); + break; + case 0x55d8: + ti->AV.Video.Colour.MasteringMetadata.WhitePointChromaticityY = readFloat(mf,(unsigned)len); + break; + case 0x55d9: + ti->AV.Video.Colour.MasteringMetadata.LuminanceMax = readFloat(mf,(unsigned)len); + break; + case 0x55da: + ti->AV.Video.Colour.MasteringMetadata.LuminanceMin = readFloat(mf,(unsigned)len); + break; + ENDFOR(mf); + break; + ENDFOR(mf); +} + static void parseVideoInfo(MatroskaFile *mf,ulonglong toplen,struct TrackInfo *ti) { ulonglong v; char dW = 0, dH = 0; @@ -1272,6 +1350,9 @@ static void parseVideoInfo(MatroskaFile *mf,ulonglong toplen,struct TrackInfo *t case 0x2fb523: // GammaValue ti->AV.Video.GammaValue = readFloat(mf,(unsigned)len); break; + case 0x55b0: // Colour + parseVideoColourInfo(mf,len,ti); + break; ENDFOR(mf); // DisplayWidth/Height defaults don't apply for DisplayUnit != 0 @@ -1368,6 +1449,13 @@ static void parseTrackEntry(MatroskaFile *mf,ulonglong toplen) { if (v<1 || v>254) errorjmp(mf,"Invalid track type: %d",(int)v); t.Type = (unsigned char)v; + + // Load type-dependent defaults + if (t.Type == TT_VIDEO) { + t.AV.Video.Colour.MatrixCoefficients = 2; + t.AV.Video.Colour.TransferCharacteristics = 2; + t.AV.Video.Colour.Primaries = 2; + } break; case 0xb9: // Enabled t.Enabled = readUInt(mf,(unsigned)len)!=0; diff --git a/libavformat/MatroskaParser.h b/libavformat/MatroskaParser.h index 7d04dd080f..fa7fbe6189 100644 --- a/libavformat/MatroskaParser.h +++ b/libavformat/MatroskaParser.h @@ -150,6 +150,33 @@ struct TrackInfo { unsigned int CropL, CropT, CropR, CropB; unsigned int ColourSpace; MKFLOAT GammaValue; + struct { + unsigned int MatrixCoefficients; + unsigned int BitsPerChannel; + unsigned int ChromaSubsamplingHorz; + unsigned int ChromaSubsamplingVert; + unsigned int CbSubsamplingHorz; + unsigned int CbSubsamplingVert; + unsigned int ChromaSitingHorz; + unsigned int ChromaSitingVert; + unsigned int Range; + unsigned int TransferCharacteristics; + unsigned int Primaries; + unsigned int MaxCLL; + unsigned int MaxFALL; + struct { + float PrimaryRChromaticityX; + float PrimaryRChromaticityY; + float PrimaryGChromaticityX; + float PrimaryGChromaticityY; + float PrimaryBChromaticityX; + float PrimaryBChromaticityY; + float WhitePointChromaticityX; + float WhitePointChromaticityY; + float LuminanceMax; + float LuminanceMin; + } MasteringMetadata; + } Colour; unsigned int Interlaced:1; } Video; diff --git a/libavformat/matroskadec_haali.c b/libavformat/matroskadec_haali.c index 377d402003..4a83348ef1 100644 --- a/libavformat/matroskadec_haali.c +++ b/libavformat/matroskadec_haali.c @@ -36,6 +36,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/avstring.h" #include "libavutil/dict.h" +#include "libavutil/mastering_display_metadata.h" #if CONFIG_ZLIB #include <zlib.h> #endif @@ -1055,6 +1056,79 @@ static int get_qt_codec(TrackInfo *track, uint32_t *fourcc, enum AVCodecID *code return 0; } +static int mkv_parse_video_color(AVStream *st, TrackInfo *info) +{ + // Mastering primaries are CIE 1931 coords, and must be > 0. + const int has_mastering_primaries = + info->AV.Video.Colour.MasteringMetadata.PrimaryRChromaticityX > 0 && info->AV.Video.Colour.MasteringMetadata.PrimaryRChromaticityY > 0 && + info->AV.Video.Colour.MasteringMetadata.PrimaryGChromaticityX > 0 && info->AV.Video.Colour.MasteringMetadata.PrimaryGChromaticityY > 0 && + info->AV.Video.Colour.MasteringMetadata.PrimaryBChromaticityX > 0 && info->AV.Video.Colour.MasteringMetadata.PrimaryBChromaticityY > 0 && + info->AV.Video.Colour.MasteringMetadata.WhitePointChromaticityX > 0 && info->AV.Video.Colour.MasteringMetadata.WhitePointChromaticityY > 0; + const int has_mastering_luminance = info->AV.Video.Colour.MasteringMetadata.LuminanceMax > 0; + + if (info->AV.Video.Colour.MatrixCoefficients != AVCOL_SPC_RESERVED) + st->codecpar->color_space = info->AV.Video.Colour.MatrixCoefficients; + if (info->AV.Video.Colour.Primaries != AVCOL_PRI_RESERVED && + info->AV.Video.Colour.Primaries != AVCOL_PRI_RESERVED0) + st->codecpar->color_primaries = info->AV.Video.Colour.Primaries; + if (info->AV.Video.Colour.TransferCharacteristics != AVCOL_TRC_RESERVED && + info->AV.Video.Colour.TransferCharacteristics != AVCOL_TRC_RESERVED0) + st->codecpar->color_trc = info->AV.Video.Colour.TransferCharacteristics; + if (info->AV.Video.Colour.Range != AVCOL_RANGE_UNSPECIFIED && + info->AV.Video.Colour.Range <= AVCOL_RANGE_JPEG) + st->codecpar->color_range = info->AV.Video.Colour.Range; + if (info->AV.Video.Colour.ChromaSitingHorz != MATROSKA_COLOUR_CHROMASITINGHORZ_UNDETERMINED && + info->AV.Video.Colour.ChromaSitingVert != MATROSKA_COLOUR_CHROMASITINGVERT_UNDETERMINED && + info->AV.Video.Colour.ChromaSitingHorz < MATROSKA_COLOUR_CHROMASITINGHORZ_NB && + info->AV.Video.Colour.ChromaSitingVert < MATROSKA_COLOUR_CHROMASITINGVERT_NB) { + st->codecpar->chroma_location = + avcodec_chroma_pos_to_enum((info->AV.Video.Colour.ChromaSitingHorz - 1) << 7, + (info->AV.Video.Colour.ChromaSitingVert - 1) << 7); + } + + if (has_mastering_primaries || has_mastering_luminance) { + // Use similar rationals as other standards. + const int chroma_den = 50000; + const int luma_den = 10000; + AVMasteringDisplayMetadata *metadata = + (AVMasteringDisplayMetadata*) av_stream_new_side_data( + st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, + sizeof(AVMasteringDisplayMetadata)); + if (!metadata) { + return AVERROR(ENOMEM); + } + memset(metadata, 0, sizeof(AVMasteringDisplayMetadata)); + if (has_mastering_primaries) { + metadata->display_primaries[0][0] = av_make_q( + round(info->AV.Video.Colour.MasteringMetadata.PrimaryRChromaticityX * chroma_den), chroma_den); + metadata->display_primaries[0][1] = av_make_q( + round(info->AV.Video.Colour.MasteringMetadata.PrimaryRChromaticityY * chroma_den), chroma_den); + metadata->display_primaries[1][0] = av_make_q( + round(info->AV.Video.Colour.MasteringMetadata.PrimaryGChromaticityX * chroma_den), chroma_den); + metadata->display_primaries[1][1] = av_make_q( + round(info->AV.Video.Colour.MasteringMetadata.PrimaryGChromaticityY * chroma_den), chroma_den); + metadata->display_primaries[2][0] = av_make_q( + round(info->AV.Video.Colour.MasteringMetadata.PrimaryBChromaticityX * chroma_den), chroma_den); + metadata->display_primaries[2][1] = av_make_q( + round(info->AV.Video.Colour.MasteringMetadata.PrimaryBChromaticityY * chroma_den), chroma_den); + metadata->white_point[0] = av_make_q( + round(info->AV.Video.Colour.MasteringMetadata.WhitePointChromaticityX * chroma_den), chroma_den); + metadata->white_point[1] = av_make_q( + round(info->AV.Video.Colour.MasteringMetadata.WhitePointChromaticityY * chroma_den), chroma_den); + metadata->has_primaries = 1; + } + if (has_mastering_luminance) { + metadata->max_luminance = av_make_q( + round(info->AV.Video.Colour.MasteringMetadata.LuminanceMax * luma_den), luma_den); + metadata->min_luminance = av_make_q( + round(info->AV.Video.Colour.MasteringMetadata.LuminanceMin * luma_den), luma_den); + metadata->has_luminance = 1; + } + } + + return 0; +} + static int mkv_read_header(AVFormatContext *s) { MatroskaDemuxContext *ctx = (MatroskaDemuxContext *)s->priv_data; @@ -1275,6 +1349,9 @@ static int mkv_read_header(AVFormatContext *s) return ret; } + ret = mkv_parse_video_color(st, info); + if (ret < 0) + return ret; // if we have virtual track, mark the real tracks /*for (j=0; j < track->operation.combine_planes.nb_elem; j++) { char buf[32]; |