[FFmpeg-devel] [PATCH] lavf/matroskadec: Add early support for colour elements

Neil Birkbeck neil.birkbeck at gmail.com
Fri Mar 4 08:23:53 CET 2016


And yet another revision, where the syntax lists are actually terminated...

On Thu, Mar 3, 2016 at 12:09 PM, Neil Birkbeck <neil.birkbeck at gmail.com> wrote:
> I've attached a slightly cleaner (more isolated) patch that moves the
> parsing into a helper function.
>
> On Mon, Feb 29, 2016 at 5:15 PM, Neil Birkbeck <neil.birkbeck at gmail.com> wrote:
>> Adding early support for a subset of the proposed colour elements
>> according to the latest version of spec:
>> https://mailarchive.ietf.org/arch/search/?email_list=cellar&gbt=1&index=hIKLhMdgTMTEwUTeA4ct38h0tmE
>>
>> I've left out elements for pix_fmt related things as there still
>> seems to be some discussion around these, and the max_cll/max_fall
>> are currently not propagated as there is not yet side data for them.
>>
>> The new elements are exposed under strict experimental mode.
>>
>> Signed-off-by: Neil Birkbeck <neil.birkbeck at gmail.com>
>> ---
>>  libavformat/matroska.h    |  28 ++++++++++
>>  libavformat/matroskadec.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 164 insertions(+)
>>
>> diff --git a/libavformat/matroska.h b/libavformat/matroska.h
>> index a654e0c..e97fe6b 100644
>> --- a/libavformat/matroska.h
>> +++ b/libavformat/matroska.h
>> @@ -123,6 +123,34 @@
>>  #define MATROSKA_ID_VIDEOALPHAMODE 0x53C0
>>  #define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3
>>  #define MATROSKA_ID_VIDEOCOLORSPACE 0x2EB524
>> +#define MATROSKA_ID_VIDEOCOLOR 0x55B0
>> +
>> +#define MATROSKA_ID_VIDEOCOLORMATRIXCOEFF 0x55B1
>> +#define MATROSKA_ID_VIDEOCOLORBITSPERCHANNEL 0x55B2
>> +#define MATROSKA_ID_VIDEOCOLORCHROMASUBHORZ 0x55B3
>> +#define MATROSKA_ID_VIDEOCOLORCHROMASUBVERT 0x55B4
>> +#define MATROSKA_ID_VIDEOCOLORCBSUBHORZ 0x55B5
>> +#define MATROSKA_ID_VIDEOCOLORCBSUBVERT 0x55B6
>> +#define MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ 0x55B7
>> +#define MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT 0x55B8
>> +#define MATROSKA_ID_VIDEOCOLORRANGE 0x55B9
>> +#define MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS 0x55BA
>> +
>> +#define MATROSKA_ID_VIDEOCOLORPRIMARIES 0x55BB
>> +#define MATROSKA_ID_VIDEOCOLORMAXCLL 0x55BC
>> +#define MATROSKA_ID_VIDEOCOLORMAXFALL 0x55BD
>> +
>> +#define MATROSKA_ID_VIDEOCOLORMASTERINGMETA 0x55D0
>> +#define MATROSKA_ID_VIDEOCOLOR_RX 0x55D1
>> +#define MATROSKA_ID_VIDEOCOLOR_RY 0x55D2
>> +#define MATROSKA_ID_VIDEOCOLOR_GX 0x55D3
>> +#define MATROSKA_ID_VIDEOCOLOR_GY 0x55D4
>> +#define MATROSKA_ID_VIDEOCOLOR_BX 0x55D5
>> +#define MATROSKA_ID_VIDEOCOLOR_BY 0x55D6
>> +#define MATROSKA_ID_VIDEOCOLOR_WHITEX 0x55D7
>> +#define MATROSKA_ID_VIDEOCOLOR_WHITEY 0x55D8
>> +#define MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX 0x55D9
>> +#define MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN 0x55DA
>>
>>  /* IDs in the trackaudio master */
>>  #define MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5
>> diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
>> index d20568c..4510e8e 100644
>> --- a/libavformat/matroskadec.c
>> +++ b/libavformat/matroskadec.c
>> @@ -39,6 +39,7 @@
>>  #include "libavutil/intfloat.h"
>>  #include "libavutil/intreadwrite.h"
>>  #include "libavutil/lzo.h"
>> +#include "libavutil/mastering_display_metadata.h"
>>  #include "libavutil/mathematics.h"
>>  #include "libavutil/opt.h"
>>  #include "libavutil/time_internal.h"
>> @@ -130,6 +131,36 @@ typedef struct MatroskaTrackEncoding {
>>      MatroskaTrackEncryption encryption;
>>  } MatroskaTrackEncoding;
>>
>> +typedef struct MatroskaMasteringMeta {
>> +    double r_x;
>> +    double r_y;
>> +    double g_x;
>> +    double g_y;
>> +    double b_x;
>> +    double b_y;
>> +    double white_x;
>> +    double white_y;
>> +    double max_luminance;
>> +    double min_luminance;
>> +} MatroskaMasteringMeta;
>> +
>> +typedef struct MatroskaTrackVideoColor {
>> +    uint64_t matrix_coefficients;
>> +    uint64_t bits_per_channel;
>> +    uint64_t chroma_sub_horz;
>> +    uint64_t chroma_sub_vert;
>> +    uint64_t cb_sub_horz;
>> +    uint64_t cb_sub_vert;
>> +    uint64_t chroma_siting_horz;
>> +    uint64_t chroma_siting_vert;
>> +    uint64_t range;
>> +    uint64_t transfer_characteristics;
>> +    uint64_t primaries;
>> +    uint64_t max_cll;
>> +    uint64_t max_fall;
>> +    MatroskaMasteringMeta mastering_meta;
>> +} MatroskaTrackVideoColor;
>> +
>>  typedef struct MatroskaTrackVideo {
>>      double   frame_rate;
>>      uint64_t display_width;
>> @@ -139,6 +170,7 @@ typedef struct MatroskaTrackVideo {
>>      EbmlBin color_space;
>>      uint64_t stereo_mode;
>>      uint64_t alpha_mode;
>> +    MatroskaTrackVideoColor color;
>>  } MatroskaTrackVideo;
>>
>>  typedef struct MatroskaTrackAudio {
>> @@ -356,6 +388,36 @@ static const EbmlSyntax matroska_info[] = {
>>      { 0 }
>>  };
>>
>> +static const EbmlSyntax matroska_mastering_meta[] = {
>> +    { MATROSKA_ID_VIDEOCOLOR_RX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, r_x), { .f=-1 } },
>> +    { MATROSKA_ID_VIDEOCOLOR_RY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, r_y), { .f=-1 } },
>> +    { MATROSKA_ID_VIDEOCOLOR_GX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, g_x), { .f=-1 } },
>> +    { MATROSKA_ID_VIDEOCOLOR_GY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, g_y), { .f=-1 } },
>> +    { MATROSKA_ID_VIDEOCOLOR_BX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, b_x), { .f=-1 } },
>> +    { MATROSKA_ID_VIDEOCOLOR_BY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, b_y), { .f=-1 } },
>> +    { MATROSKA_ID_VIDEOCOLOR_WHITEX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, white_x), { .f=-1 } },
>> +    { MATROSKA_ID_VIDEOCOLOR_WHITEY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, white_y), { .f=-1 } },
>> +    { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, min_luminance), { .f=-1 } },
>> +    { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, max_luminance), { .f=-1 } },
>> +};
>> +
>> +static const EbmlSyntax matroska_track_video_color[] = {
>> +    { MATROSKA_ID_VIDEOCOLORMATRIXCOEFF,      EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, matrix_coefficients), { .u=2 } },
>> +    { MATROSKA_ID_VIDEOCOLORBITSPERCHANNEL,   EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, bits_per_channel), { .u=8 } },
>> +    { MATROSKA_ID_VIDEOCOLORCHROMASUBHORZ,    EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_horz), { .u=0 } },
>> +    { MATROSKA_ID_VIDEOCOLORCHROMASUBVERT,    EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_vert), { .u=0 } },
>> +    { MATROSKA_ID_VIDEOCOLORCBSUBHORZ,        EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, cb_sub_horz), { .u=0 } },
>> +    { MATROSKA_ID_VIDEOCOLORCBSUBVERT,        EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, cb_sub_vert), { .u=0 } },
>> +    { MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_horz), { .u=0 } },
>> +    { MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_vert), { .u=0 } },
>> +    { MATROSKA_ID_VIDEOCOLORRANGE,            EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, range), { .u=0 } },
>> +    { MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, transfer_characteristics), { .u=2 } },
>> +    { MATROSKA_ID_VIDEOCOLORPRIMARIES,        EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, primaries), { .u=2 } },
>> +    { MATROSKA_ID_VIDEOCOLORMAXCLL,           EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, max_cll), { .u=0 } },
>> +    { MATROSKA_ID_VIDEOCOLORMAXFALL,          EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, max_fall), { .u=0 } },
>> +    { MATROSKA_ID_VIDEOCOLORMASTERINGMETA,    EBML_NEST, 0, offsetof(MatroskaTrackVideoColor, mastering_meta), { .n = matroska_mastering_meta } }
>> +};
>> +
>>  static const EbmlSyntax matroska_track_video[] = {
>>      { MATROSKA_ID_VIDEOFRAMERATE,      EBML_FLOAT, 0, offsetof(MatroskaTrackVideo, frame_rate) },
>>      { MATROSKA_ID_VIDEODISPLAYWIDTH,   EBML_UINT,  0, offsetof(MatroskaTrackVideo, display_width), { .u=-1 } },
>> @@ -364,6 +426,7 @@ static const EbmlSyntax matroska_track_video[] = {
>>      { MATROSKA_ID_VIDEOPIXELHEIGHT,    EBML_UINT,  0, offsetof(MatroskaTrackVideo, pixel_height) },
>>      { MATROSKA_ID_VIDEOCOLORSPACE,     EBML_BIN,   0, offsetof(MatroskaTrackVideo, color_space) },
>>      { MATROSKA_ID_VIDEOALPHAMODE,      EBML_UINT,  0, offsetof(MatroskaTrackVideo, alpha_mode) },
>> +    { MATROSKA_ID_VIDEOCOLOR,          EBML_NEST,  0, offsetof(MatroskaTrackVideo, color), { .n = matroska_track_video_color } },
>>      { MATROSKA_ID_VIDEOPIXELCROPB,     EBML_NONE },
>>      { MATROSKA_ID_VIDEOPIXELCROPT,     EBML_NONE },
>>      { MATROSKA_ID_VIDEOPIXELCROPL,     EBML_NONE },
>> @@ -1753,6 +1816,10 @@ static int matroska_parse_tracks(AVFormatContext *s)
>>          int extradata_offset = 0;
>>          uint32_t fourcc = 0;
>>          AVIOContext b;
>> +        enum AVColorSpace color_space = AVCOL_SPC_UNSPECIFIED;
>> +        enum AVColorTransferCharacteristic color_trc = AVCOL_TRC_UNSPECIFIED;
>> +        enum AVColorPrimaries color_primaries = AVCOL_PRI_UNSPECIFIED;
>> +        enum AVColorRange color_range = AVCOL_RANGE_UNSPECIFIED;
>>          char* key_id_base64 = NULL;
>>          int bit_depth = -1;
>>
>> @@ -1786,6 +1853,16 @@ static int matroska_parse_tracks(AVFormatContext *s)
>>                  track->video.display_height = track->video.pixel_height;
>>              if (track->video.color_space.size == 4)
>>                  fourcc = AV_RL32(track->video.color_space.data);
>> +
>> +            if (track->video.color.matrix_coefficients != AVCOL_SPC_RESERVED)
>> +                color_space = track->video.color.matrix_coefficients;
>> +            if (track->video.color.primaries != AVCOL_PRI_RESERVED)
>> +                color_primaries = track->video.color.primaries;
>> +            if (track->video.color.transfer_characteristics != AVCOL_TRC_RESERVED)
>> +                color_trc = track->video.color.transfer_characteristics;
>> +            if (track->video.color.range != AVCOL_RANGE_UNSPECIFIED &&
>> +                track->video.color.range <= AVCOL_RANGE_JPEG)
>> +                color_range = track->video.color.range;
>>          } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
>>              if (!track->audio.out_samplerate)
>>                  track->audio.out_samplerate = track->audio.samplerate;
>> @@ -2177,6 +2254,65 @@ static int matroska_parse_tracks(AVFormatContext *s)
>>                  if (ret < 0)
>>                      return ret;
>>              }
>> +
>> +            if (s->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
>> +                const MatroskaMasteringMeta* mastering_meta =
>> +                    &track->video.color.mastering_meta;
>> +                // Mastering primaries are CIE 1931 coords, and must be >= 0.
>> +                const int has_mastering_primaries =
>> +                    mastering_meta->r_x >= 0 && mastering_meta->r_y >= 0 &&
>> +                    mastering_meta->g_x >= 0 && mastering_meta->g_y >= 0 &&
>> +                    mastering_meta->b_x >= 0 && mastering_meta->b_y >= 0 &&
>> +                    mastering_meta->white_x >= 0 && mastering_meta->white_y >= 0;
>> +                const int has_mastering_luminance =
>> +                    mastering_meta->max_luminance >= 0;
>> +
>> +                st->codec->colorspace = color_space;
>> +                st->codec->color_trc = color_trc;
>> +                st->codec->color_primaries = color_primaries;
>> +                st->codec->color_range = color_range;
>> +
>> +                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(mastering_meta->r_x * chroma_den), chroma_den);
>> +                        metadata->display_primaries[0][1] = av_make_q(
>> +                            round(mastering_meta->r_y * chroma_den), chroma_den);
>> +                        metadata->display_primaries[1][0] = av_make_q(
>> +                            round(mastering_meta->g_x * chroma_den), chroma_den);
>> +                        metadata->display_primaries[1][1] = av_make_q(
>> +                            round(mastering_meta->g_y * chroma_den), chroma_den);
>> +                        metadata->display_primaries[2][0] = av_make_q(
>> +                            round(mastering_meta->b_x * chroma_den), chroma_den);
>> +                        metadata->display_primaries[2][1] = av_make_q(
>> +                            round(mastering_meta->b_y * chroma_den), chroma_den);
>> +                        metadata->white_point[0] = av_make_q(
>> +                            round(mastering_meta->white_x * chroma_den), chroma_den);
>> +                        metadata->white_point[1] = av_make_q(
>> +                            round(mastering_meta->white_y * chroma_den), chroma_den);
>> +                        metadata->has_primaries = 1;
>> +                    }
>> +                    if (has_mastering_luminance) {
>> +                        metadata->max_luminance = av_make_q(
>> +                            round(mastering_meta->max_luminance * luma_den), luma_den);
>> +                        metadata->min_luminance = av_make_q(
>> +                            round(mastering_meta->min_luminance * luma_den), luma_den);
>> +                        metadata->has_luminance = 1;
>> +                    }
>> +                }
>> +            }
>> +
>>          } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
>>              st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
>>              st->codec->codec_tag   = fourcc;
>> --
>> 2.7.0.rc3.207.g0ac5344
>>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-lavf-matroskadec-Add-early-support-for-some-of-the-n.patch
Type: text/x-patch
Size: 12251 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20160303/b684bf52/attachment.bin>


More information about the ffmpeg-devel mailing list