[FFmpeg-devel] [PATCH 3/4] avformat/mov: add support for reading Mastering Display Metadata Box

James Almer jamrial at gmail.com
Sat May 27 17:58:05 EEST 2017


On 5/27/2017 11:05 AM, Michael Niedermayer wrote:
> On Sat, May 27, 2017 at 01:54:18AM -0300, James Almer wrote:
>> On 5/26/2017 8:05 PM, Michael Niedermayer wrote:
>>> On Wed, May 17, 2017 at 09:49:40PM -0300, James Almer wrote:
>>>> As defined in "VP Codec ISO Media File Format Binding v1.0"
>>>> https://github.com/webmproject/vp9-dash/blob/master/VPCodecISOMediaFileFormatBinding.md
>>>>
>>>> Partially based on Matroska decoder code.
>>>>
>>>> Signed-off-by: James Almer <jamrial at gmail.com>
>>>> ---
>>>>  libavformat/isom.h |  2 ++
>>>>  libavformat/mov.c  | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>>>  2 files changed, 67 insertions(+)
>>>>
>>>> diff --git a/libavformat/isom.h b/libavformat/isom.h
>>>> index d9956cf63a..426f732247 100644
>>>> --- a/libavformat/isom.h
>>>> +++ b/libavformat/isom.h
>>>> @@ -27,6 +27,7 @@
>>>>  #include <stddef.h>
>>>>  #include <stdint.h>
>>>>  
>>>> +#include "libavutil/mastering_display_metadata.h"
>>>>  #include "libavutil/spherical.h"
>>>>  #include "libavutil/stereo3d.h"
>>>>  
>>>> @@ -194,6 +195,7 @@ typedef struct MOVStreamContext {
>>>>      AVStereo3D *stereo3d;
>>>>      AVSphericalMapping *spherical;
>>>>      size_t spherical_size;
>>>> +    AVMasteringDisplayMetadata *mastering;
>>>>  
>>>>      uint32_t format;
>>>>  
>>>> diff --git a/libavformat/mov.c b/libavformat/mov.c
>>>> index afef53b79a..0b5fd849f3 100644
>>>> --- a/libavformat/mov.c
>>>> +++ b/libavformat/mov.c
>>>> @@ -4612,6 +4612,60 @@ static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
>>>>      return 0;
>>>>  }
>>>>  
>>>> +static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
>>>> +{
>>>> +    MOVStreamContext *sc;
>>>> +    const int chroma_den = 50000;
>>>> +    const int luma_den = 10000;
>>>> +    int version;
>>>> +
>>>> +    if (c->fc->nb_streams < 1)
>>>> +        return AVERROR_INVALIDDATA;
>>>> +
>>>> +    sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
>>>> +
>>>> +    if (atom.size < 5) {
>>>> +        av_log(c->fc, AV_LOG_ERROR, "Empty Mastering Display Metadata box\n");
>>>> +        return AVERROR_INVALIDDATA;
>>>> +    }
>>>> +
>>>> +    version = avio_r8(pb);
>>>> +    if (version) {
>>>> +        av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version);
>>>> +        return 0;
>>>> +    }
>>>> +    avio_skip(pb, 3); /* flags */
>>>> +
>>>> +    sc->mastering = av_mastering_display_metadata_alloc();
>>>> +    if (!sc->mastering)
>>>> +        return AVERROR(ENOMEM);
>>>> +
>>>
>>>> +    sc->mastering->display_primaries[0][0] =
>>>> +        av_make_q(lrint(((double)avio_rb16(pb) / (1 << 16)) * chroma_den), chroma_den);
>>>
>>> this is not optimal, precission wise
>>> av_d2q() should produce closer rationals
>>> alternativly av_reduce() can be used directly
>>>
>>> but iam not sure why a fixed chroma_den and luma_den is fixed
>>> maybe iam missing something
>>
>> Does
>>
>> for (i = 0; i < 3; i++)
>>   for (j = 0; j < 2; j++)
>>     av_reduce(&sc->mastering->display_primaries[i][j].num,
>>               &sc->mastering->display_primaries[i][j].den,
>>               lrint(((double)avio_rb16(pb) / (1 << 16)) * chroma_den),
>>               chroma_den, chroma_den);
> 
> Why do you use
> lrint(((double)avio_rb16(pb) / (1 << 16)) * chroma_den
> and
> chroma_den
> 
> instead of
> avio_rb16(pb)
> and
> 1 << 16
> 
> ?
> 

To follow the origin spec the vp9 in mp4 spec and the
AVMasteringDisplayMetadata API quote and are based on.

---------------
display_primaries_x[ c ] and display_primaries_y[ c ] specify the
normalized x and y chromaticity coordinates, respectively, of the colour
primary component c of the mastering display in increments of 0.00002,
according to the CIE 1931 definition of x and y as specified in ISO
11664-1 (see also ISO 11664-3 and CIE 15). For describing mastering
displays that use red, green and blue colour primaries, it is suggested
that index value c equal to 0 should correspond to the green primary, c
equal to 1 should correspond to the blue primary and c equal to 2 should
correspond to the red colour primary (see also Annex E and Table E.3).
The values of display_primaries_x[ c ] and display_primaries_y[ c ]
shall be in the range of 0 to 50 000, inclusive.

white_point_x and white_point_y specify the normalized x and y
chromaticity coordinates, respectively, of the white point of the
mastering display in normalized increments of 0.00002, according to the
CIE 1931 definition of x and y as specified in ISO 11664-1 (see also ISO
11664-3 and CIE 15). The values of white_point_x and white_point_y shall
be in the range of 0 to 50 000.

max_display_mastering_luminance and min_display_mastering_luminance
specify the nominal maximum and minimum display luminance, respectively,
of the mastering display in units of 0.0001 candelas per square metre.
------------

$ ./ffmpeg -i The\ World\ in\ HDR-tO01J-M3g0U.webm
    Side data:
      Mastering Display Metadata, has_primaries:1 has_luminance:1
r(0.6800,0.3200) g(0.2649,0.6900) b(0.1500 0.0600) wp(0.3127, 0.3290)
min_luminance=0.001000, max_luminance=1000.000000

$ mkvinfo The\ World\ in\ HDR-tO01J-M3g0U.webm
|    + Video colour mastering metadata
|     + Max luminance: 1000
|     + Min luminance: 0.001
|     + Red colour coordinate x: 0.68
|     + Red colour coordinate y: 0.31996
|     + Green colour coordinate x: 0.26494
|     + Green colour coordinate y: 0.68996
|     + Blue colour coordinate x: 0.15
|     + Blue colour coordinate y: 0.05998
|     + White colour coordinate x: 0.3127
|     + White colour coordinate y: 0.32896

$ ./ffmpeg -i The\ World\ in\ HDR-tO01J-M3g0U.webm -c:v copy mastering.mp4

------

Without chroma/luma_den rounding in demuxer

$ ./ffmpeg -i mastering.mp4
    Side data:
      Mastering Display Metadata, has_primaries:1 has_luminance:1
r(0.6800,0.3200) g(0.2649,0.6900) b(0.1500 0.0600) wp(0.3127, 0.3290)
min_luminance=0.000977, max_luminance=1000.000000

$ ./ffmpeg -i mastering.mp4 -c:v copy without_den.mkv

$ mkvinfo without_den.mkv
|    + Video colour mastering metadata
|     + Red colour coordinate x: 0.679993
|     + Red colour coordinate y: 0.319962
|     + Green colour coordinate x: 0.264938
|     + Green colour coordinate y: 0.689957
|     + Blue colour coordinate x: 0.149994
|     + Blue colour coordinate y: 0.0599823
|     + White colour coordinate x: 0.312698
|     + White colour coordinate y: 0.328964
|     + Max luminance: 1000
|     + Min luminance: 0.000976562

------

With chroma/luma_den rounding in demuxer

$ ./ffmpeg -i mastering.mp4
    Side data:
      Mastering Display Metadata, has_primaries:1 has_luminance:1
r(0.6800,0.3200) g(0.2649,0.6900) b(0.1500 0.0600) wp(0.3127, 0.3290)
min_luminance=0.001000, max_luminance=1000.000000

$ ./ffmpeg -i mastering.mp4 -c:v copy with_den.mkv

$ mkvinfo with_den.mkv
|     + Red colour coordinate x: 0.68
|     + Red colour coordinate y: 0.31996
|     + Green colour coordinate x: 0.26494
|     + Green colour coordinate y: 0.68996
|     + Blue colour coordinate x: 0.15
|     + Blue colour coordinate y: 0.05998
|     + White colour coordinate x: 0.3127
|     + White colour coordinate y: 0.32896
|     + Max luminance: 1000
|     + Min luminance: 0.001

------

Notice how all values break the increments of 0.00002 (50000
denominator) and 0.0001 (10000 denominator) constrains when i just take
the 0.16, 24.8 and 18.14 fixed point values stored in mp4 and dump them
into AVMasteringDisplayMetadata as is, like you suggest.


More information about the ffmpeg-devel mailing list