X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmatroskadec.c;h=f79511e4f1ee3b7668bdd77e98e11f43e4a070a3;hb=da97b244b04b48b827ece6d9635a1d1d1cf2021a;hp=a94398bd82039f039b6eccc2bd2c4629c7365f59;hpb=5114c62902d3726b898df5628b1eaf98b4a87027;p=ffmpeg diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index a94398bd820..f79511e4f1e 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -168,6 +168,7 @@ typedef struct MatroskaTrackVideo { uint64_t pixel_width; uint64_t pixel_height; EbmlBin color_space; + uint64_t display_unit; uint64_t interlaced; uint64_t field_order; uint64_t stereo_mode; @@ -406,17 +407,17 @@ static const EbmlSyntax matroska_mastering_meta[] = { }; 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_VIDEOCOLORMATRIXCOEFF, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, matrix_coefficients), { .u = AVCOL_SPC_UNSPECIFIED } }, + { MATROSKA_ID_VIDEOCOLORBITSPERCHANNEL, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, bits_per_channel), { .u=0 } }, { 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_VIDEOCOLORCHROMASITINGHORZ, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_horz), { .u = MATROSKA_COLOUR_CHROMASITINGHORZ_UNDETERMINED } }, + { MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_vert), { .u = MATROSKA_COLOUR_CHROMASITINGVERT_UNDETERMINED } }, + { MATROSKA_ID_VIDEOCOLORRANGE, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, range), { .u = AVCOL_RANGE_UNSPECIFIED } }, + { MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, transfer_characteristics), { .u = AVCOL_TRC_UNSPECIFIED } }, + { MATROSKA_ID_VIDEOCOLORPRIMARIES, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, primaries), { .u = AVCOL_PRI_UNSPECIFIED } }, { 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 } }, @@ -436,7 +437,7 @@ static const EbmlSyntax matroska_track_video[] = { { MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE }, - { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_NONE }, + { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_UINT, 0, offsetof(MatroskaTrackVideo, display_unit), { .u= MATROSKA_VIDEO_DISPLAYUNIT_PIXELS } }, { 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 } }, @@ -1752,8 +1753,15 @@ static int matroska_parse_flac(AVFormatContext *s, return 0; } -static int mkv_field_order(int64_t field_order) +static int mkv_field_order(MatroskaDemuxContext *matroska, int64_t field_order) { + int major, minor, micro, bttb = 0; + + /* workaround a bug in our Matroska muxer, introduced in version 57.36 alongside + * this function, and fixed in 57.52 */ + if (matroska->muxingapp && sscanf(matroska->muxingapp, "Lavf%d.%d.%d", &major, &minor, µ) == 3) + bttb = (major == 57 && minor >= 36 && minor <= 51 && micro >= 100); + switch (field_order) { case MATROSKA_VIDEO_FIELDORDER_PROGRESSIVE: return AV_FIELD_PROGRESSIVE; @@ -1764,9 +1772,9 @@ static int mkv_field_order(int64_t field_order) case MATROSKA_VIDEO_FIELDORDER_BB: return AV_FIELD_BB; case MATROSKA_VIDEO_FIELDORDER_BT: - return AV_FIELD_BT; + return bttb ? AV_FIELD_TB : AV_FIELD_BT; case MATROSKA_VIDEO_FIELDORDER_TB: - return AV_FIELD_TB; + return bttb ? AV_FIELD_BT : AV_FIELD_TB; default: return AV_FIELD_UNKNOWN; } @@ -1819,6 +1827,14 @@ static int mkv_parse_video_color(AVStream *st, const MatroskaTrack *track) { if (track->video.color.range != AVCOL_RANGE_UNSPECIFIED && track->video.color.range <= AVCOL_RANGE_JPEG) st->codecpar->color_range = track->video.color.range; + if (track->video.color.chroma_siting_horz != MATROSKA_COLOUR_CHROMASITINGHORZ_UNDETERMINED && + track->video.color.chroma_siting_vert != MATROSKA_COLOUR_CHROMASITINGVERT_UNDETERMINED && + track->video.color.chroma_siting_horz < MATROSKA_COLOUR_CHROMASITINGHORZ_NB && + track->video.color.chroma_siting_vert < MATROSKA_COLOUR_CHROMASITINGVERT_NB) { + st->codecpar->chroma_location = + avcodec_chroma_pos_to_enum((track->video.color.chroma_siting_horz - 1) << 7, + (track->video.color.chroma_siting_vert - 1) << 7); + } if (has_mastering_primaries || has_mastering_luminance) { // Use similar rationals as other standards. @@ -2282,18 +2298,20 @@ static int matroska_parse_tracks(AVFormatContext *s) 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); + st->codecpar->field_order = mkv_field_order(matroska, track->video.field_order); else if (track->video.interlaced == MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE) st->codecpar->field_order = AV_FIELD_PROGRESSIVE; 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); - av_reduce(&st->sample_aspect_ratio.num, - &st->sample_aspect_ratio.den, - st->codecpar->height * track->video.display_width * display_width_mul, - st->codecpar->width * track->video.display_height * display_height_mul, - 255); + if (track->video.display_unit < MATROSKA_VIDEO_DISPLAYUNIT_UNKNOWN) { + av_reduce(&st->sample_aspect_ratio.num, + &st->sample_aspect_ratio.den, + st->codecpar->height * track->video.display_width * display_width_mul, + st->codecpar->width * track->video.display_height * display_height_mul, + 255); + } if (st->codecpar->codec_id != AV_CODEC_ID_HEVC) st->need_parsing = AVSTREAM_PARSE_HEADERS; @@ -3064,10 +3082,14 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, av_free(pkt); return AVERROR(ENOMEM); } - AV_WL32(side_data, 0); - AV_WL32(side_data + 4, av_rescale_q(discard_padding, + discard_padding = av_rescale_q(discard_padding, (AVRational){1, 1000000000}, - (AVRational){1, st->codecpar->sample_rate})); + (AVRational){1, st->codecpar->sample_rate}); + if (discard_padding > 0) { + AV_WL32(side_data + 4, discard_padding); + } else { + AV_WL32(side_data, -discard_padding); + } } if (track->ms_compat) @@ -3754,6 +3776,11 @@ static int webm_dash_manifest_read_header(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "Failed to read file headers\n"); return -1; } + if (!s->nb_streams) { + matroska_read_close(s); + av_log(s, AV_LOG_ERROR, "No streams found\n"); + return AVERROR_INVALIDDATA; + } if (!matroska->is_live) { buf = av_asprintf("%g", matroska->duration);