mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-01-02 13:02:13 +00:00
lavf/matroskadec: Add early support for some of the new colour elements.
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@gmail.com> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
parent
ac15d7a666
commit
bbda13a771
@ -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
|
||||
|
@ -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,38 @@ 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 } },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
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 } },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
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 +428,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 },
|
||||
@ -1708,6 +1773,69 @@ static void mkv_stereo_mode_display_mul(int stereo_mode, int *h_width, int *h_he
|
||||
}
|
||||
}
|
||||
|
||||
static int mkv_parse_video_color(AVStream *st, const MatroskaTrack *track) {
|
||||
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;
|
||||
|
||||
if (track->video.color.matrix_coefficients != AVCOL_SPC_RESERVED)
|
||||
st->codec->colorspace = track->video.color.matrix_coefficients;
|
||||
if (track->video.color.primaries != AVCOL_PRI_RESERVED)
|
||||
st->codec->color_primaries = track->video.color.primaries;
|
||||
if (track->video.color.transfer_characteristics != AVCOL_TRC_RESERVED)
|
||||
st->codec->color_trc = track->video.color.transfer_characteristics;
|
||||
if (track->video.color.range != AVCOL_RANGE_UNSPECIFIED &&
|
||||
track->video.color.range <= AVCOL_RANGE_JPEG)
|
||||
st->codec->color_range = track->video.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;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID *codec_id)
|
||||
{
|
||||
const AVCodecTag *codec_tags;
|
||||
@ -2177,6 +2305,12 @@ static int matroska_parse_tracks(AVFormatContext *s)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (s->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
|
||||
int ret = mkv_parse_video_color(st, track);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
|
||||
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
st->codec->codec_tag = fourcc;
|
||||
|
Loading…
Reference in New Issue
Block a user