[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