ffmpeg | branch: master | Derek Buitenhuis <derek.buitenh...@gmail.com> | Sun May 8 22:58:18 2016 +0100| [f3972b3b7dfaea254187c1f26c22b9b8761a9bf0] | committer: Derek Buitenhuis
Merge commit '5f0226668124aa7ae4db501ba7f4ace4c770f3d1' * commit '5f0226668124aa7ae4db501ba7f4ace4c770f3d1': matroska: Support interlaced content correctly Merged-by: Derek Buitenhuis <derek.buitenh...@gmail.com> > http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=f3972b3b7dfaea254187c1f26c22b9b8761a9bf0 --- libavformat/matroska.h | 16 ++++++++++++++++ libavformat/matroskadec.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/libavformat/matroska.h b/libavformat/matroska.h index e97fe6b..e427c0e 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -119,6 +119,7 @@ #define MATROSKA_ID_VIDEOPIXELCROPR 0x54DD #define MATROSKA_ID_VIDEODISPLAYUNIT 0x54B2 #define MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A +#define MATROSKA_ID_VIDEOFIELDORDER 0x9D #define MATROSKA_ID_VIDEOSTEREOMODE 0x53B8 #define MATROSKA_ID_VIDEOALPHAMODE 0x53C0 #define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3 @@ -275,6 +276,21 @@ typedef enum { } MatroskaTrackEncodingCompAlgo; typedef enum { + MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED = 0, + MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED = 1, + MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE = 2 +} MatroskaVideoInterlaceFlag; + +typedef enum { + MATROSKA_VIDEO_FIELDORDER_PROGRESSIVE = 0, + MATROSKA_VIDEO_FIELDORDER_UNDETERMINED = 2, + MATROSKA_VIDEO_FIELDORDER_TT = 1, + MATROSKA_VIDEO_FIELDORDER_BB = 6, + MATROSKA_VIDEO_FIELDORDER_BT = 9, + MATROSKA_VIDEO_FIELDORDER_TB = 14, +} MatroskaVideoFieldOrder; + +typedef enum { MATROSKA_VIDEO_STEREOMODE_TYPE_MONO = 0, MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT = 1, MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP = 2, diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index fa301a7..1ef2001 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -168,6 +168,8 @@ typedef struct MatroskaTrackVideo { uint64_t pixel_width; uint64_t pixel_height; EbmlBin color_space; + uint64_t interlaced; + uint64_t field_order; uint64_t stereo_mode; uint64_t alpha_mode; MatroskaTrackVideoColor color; @@ -434,7 +436,8 @@ static const EbmlSyntax matroska_track_video[] = { { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE }, { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_NONE }, - { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_NONE }, + { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_UINT, 0, offsetof(MatroskaTrackVideo, interlaced), { .u = MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED } }, + { MATROSKA_ID_VIDEOFIELDORDER, EBML_UINT, 0, offsetof(MatroskaTrackVideo, field_order), { .u = MATROSKA_VIDEO_FIELDORDER_UNDETERMINED } }, { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo, stereo_mode), { .u = MATROSKA_VIDEO_STEREOMODE_TYPE_NB } }, { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE }, { 0 } @@ -1749,7 +1752,28 @@ static int matroska_parse_flac(AVFormatContext *s, return 0; } -static void mkv_stereo_mode_display_mul(int stereo_mode, int *h_width, int *h_height) +static int mkv_field_order(int64_t field_order) +{ + switch (field_order) { + case MATROSKA_VIDEO_FIELDORDER_PROGRESSIVE: + return AV_FIELD_PROGRESSIVE; + case MATROSKA_VIDEO_FIELDORDER_UNDETERMINED: + return AV_FIELD_UNKNOWN; + case MATROSKA_VIDEO_FIELDORDER_TT: + return AV_FIELD_TT; + case MATROSKA_VIDEO_FIELDORDER_BB: + return AV_FIELD_BB; + case MATROSKA_VIDEO_FIELDORDER_BT: + return AV_FIELD_BT; + case MATROSKA_VIDEO_FIELDORDER_TB: + return AV_FIELD_TB; + default: + return AV_FIELD_UNKNOWN; + } +} + +static void mkv_stereo_mode_display_mul(int stereo_mode, + int *h_width, int *h_height) { switch (stereo_mode) { case MATROSKA_VIDEO_STEREOMODE_TYPE_MONO: @@ -2255,6 +2279,9 @@ static int matroska_parse_tracks(AVFormatContext *s) st->codecpar->width = track->video.pixel_width; st->codecpar->height = track->video.pixel_height; + if (track->video.interlaced == MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED) + st->codecpar->field_order = mkv_field_order(track->video.field_order); + if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB) mkv_stereo_mode_display_mul(track->video.stereo_mode, &display_width_mul, &display_height_mul); ====================================================================== diff --cc libavformat/matroska.h index e97fe6b,40402bc..e427c0e --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@@ -119,38 -113,10 +119,39 @@@ #define MATROSKA_ID_VIDEOPIXELCROPR 0x54DD #define MATROSKA_ID_VIDEODISPLAYUNIT 0x54B2 #define MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A + #define MATROSKA_ID_VIDEOFIELDORDER 0x9D #define MATROSKA_ID_VIDEOSTEREOMODE 0x53B8 +#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 --cc libavformat/matroskadec.c index fa301a7,978d56d..1ef2001 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@@ -167,10 -122,10 +167,12 @@@ typedef struct MatroskaTrackVideo uint64_t display_height; uint64_t pixel_width; uint64_t pixel_height; - uint64_t fourcc; + EbmlBin color_space; + uint64_t interlaced; + uint64_t field_order; uint64_t stereo_mode; + uint64_t alpha_mode; + MatroskaTrackVideoColor color; } MatroskaTrackVideo; typedef struct MatroskaTrackAudio { @@@ -1749,118 -1528,49 +1752,139 @@@ static int matroska_parse_flac(AVFormat return 0; } - static void mkv_stereo_mode_display_mul(int stereo_mode, int *h_width, int *h_height) + static int mkv_field_order(int64_t field_order) + { + switch (field_order) { + case MATROSKA_VIDEO_FIELDORDER_PROGRESSIVE: + return AV_FIELD_PROGRESSIVE; + case MATROSKA_VIDEO_FIELDORDER_UNDETERMINED: + return AV_FIELD_UNKNOWN; + case MATROSKA_VIDEO_FIELDORDER_TT: + return AV_FIELD_TT; + case MATROSKA_VIDEO_FIELDORDER_BB: + return AV_FIELD_BB; + case MATROSKA_VIDEO_FIELDORDER_BT: + return AV_FIELD_BT; + case MATROSKA_VIDEO_FIELDORDER_TB: + return AV_FIELD_TB; + default: + return AV_FIELD_UNKNOWN; + } + } + + static void mkv_stereo_mode_display_mul(int stereo_mode, + int *h_width, int *h_height) { switch (stereo_mode) { - case MATROSKA_VIDEO_STEREOMODE_TYPE_MONO: - case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_RL: - case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR: - case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL: - case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR: - break; - case MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT: - case MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT: - case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_RL: - case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR: - *h_width = 2; - break; - case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP: - case MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM: - case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_RL: - case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR: - *h_height = 2; - break; + case MATROSKA_VIDEO_STEREOMODE_TYPE_MONO: + case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_RL: + case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR: + case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL: + case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR: + break; + case MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT: + case MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT: + case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_RL: + case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR: + *h_width = 2; + break; + case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP: + case MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM: + case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_RL: + case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR: + *h_height = 2; + break; + } +} + +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->codecpar->color_space = track->video.color.matrix_coefficients; + if (track->video.color.primaries != AVCOL_PRI_RESERVED) + st->codecpar->color_primaries = track->video.color.primaries; + if (track->video.color.transfer_characteristics != AVCOL_TRC_RESERVED) + st->codecpar->color_trc = track->video.color.transfer_characteristics; + if (track->video.color.range != AVCOL_RANGE_UNSPECIFIED && + track->video.color.range <= AVCOL_RANGE_JPEG) + st->codecpar->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; + + codec_tags = track->type == MATROSKA_TRACK_TYPE_VIDEO ? + ff_codec_movvideo_tags : ff_codec_movaudio_tags; + + /* Normalize noncompliant private data that starts with the fourcc + * by expanding/shifting the data by 4 bytes and storing the data + * size at the start. */ + if (ff_codec_get_id(codec_tags, AV_RL32(track->codec_priv.data))) { + uint8_t *p = av_realloc(track->codec_priv.data, + track->codec_priv.size + 4); + if (!p) + return AVERROR(ENOMEM); + memmove(p + 4, p, track->codec_priv.size); + track->codec_priv.data = p; + track->codec_priv.size += 4; + AV_WB32(track->codec_priv.data, track->codec_priv.size); + } + + *fourcc = AV_RL32(track->codec_priv.data + 4); + *codec_id = ff_codec_get_id(codec_tags, *fourcc); + + return 0; } static int matroska_parse_tracks(AVFormatContext *s) _______________________________________________ ffmpeg-cvslog mailing list ffmpeg-cvslog@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog