X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmatroskadec.c;h=fdb23ab05e8b2e4f4deba4a4daedd9c314fa6ffb;hb=33e997d992ccd4e93b57fa7dfb478fc6a67ce4ac;hp=7e74348b2a1b8833ed5fa67fce384b8c430d48d6;hpb=f84ece0a9831cbbdc53163eeb81a5d03cd840d70;p=ffmpeg diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 7e74348b2a1..fdb23ab05e8 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -89,6 +89,7 @@ typedef const struct EbmlSyntax { int list_elem_size; int data_offset; union { + int64_t i; uint64_t u; double f; const char *s; @@ -696,7 +697,7 @@ static const EbmlSyntax matroska_blockgroup[] = { { MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, offsetof(MatroskaBlock, bin) }, { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, offsetof(MatroskaBlock, duration) }, { MATROSKA_ID_DISCARDPADDING, EBML_SINT, 0, offsetof(MatroskaBlock, discard_padding) }, - { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 0, offsetof(MatroskaBlock, reference) }, + { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 0, offsetof(MatroskaBlock, reference), { .i = INT64_MIN } }, { MATROSKA_ID_CODECSTATE, EBML_NONE }, { 1, EBML_UINT, 0, offsetof(MatroskaBlock, non_simple), { .u = 1 } }, { 0 } @@ -1071,6 +1072,9 @@ static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, for (i = 0; syntax[i].id; i++) switch (syntax[i].type) { + case EBML_SINT: + *(int64_t *) ((char *) data + syntax[i].data_offset) = syntax[i].def.i; + break; case EBML_UINT: *(uint64_t *) ((char *) data + syntax[i].data_offset) = syntax[i].def.u; break; @@ -1909,18 +1913,64 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) AVSphericalMapping *spherical; enum AVSphericalProjection projection; size_t spherical_size; + size_t l = 0, t = 0, r = 0, b = 0; + size_t padding = 0; int ret; + GetByteContext gb; + + bytestream2_init(&gb, track->video.projection.private.data, + track->video.projection.private.size); + + if (bytestream2_get_byte(&gb) != 0) { + av_log(NULL, AV_LOG_WARNING, "Unknown spherical metadata\n"); + return 0; + } + + bytestream2_skip(&gb, 3); // flags switch (track->video.projection.type) { case MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR: - if (track->video.projection.private.size < 4) + if (track->video.projection.private.size == 20) { + t = bytestream2_get_be32(&gb); + b = bytestream2_get_be32(&gb); + l = bytestream2_get_be32(&gb); + r = bytestream2_get_be32(&gb); + + if (b >= UINT_MAX - t || r >= UINT_MAX - l) { + av_log(NULL, AV_LOG_ERROR, + "Invalid bounding rectangle coordinates " + "%"SIZE_SPECIFIER",%"SIZE_SPECIFIER"," + "%"SIZE_SPECIFIER",%"SIZE_SPECIFIER"\n", + l, t, r, b); + return AVERROR_INVALIDDATA; + } + } else if (track->video.projection.private.size != 0) { + av_log(NULL, AV_LOG_ERROR, "Unknown spherical metadata\n"); return AVERROR_INVALIDDATA; - projection = AV_SPHERICAL_EQUIRECTANGULAR; + } + + if (l || t || r || b) + projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE; + else + projection = AV_SPHERICAL_EQUIRECTANGULAR; break; case MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP: - if (track->video.projection.private.size < 4) + if (track->video.projection.private.size < 4) { + av_log(NULL, AV_LOG_ERROR, "Missing projection private properties\n"); return AVERROR_INVALIDDATA; - projection = AV_SPHERICAL_CUBEMAP; + } else if (track->video.projection.private.size == 12) { + uint32_t layout = bytestream2_get_be32(&gb); + if (layout) { + av_log(NULL, AV_LOG_WARNING, + "Unknown spherical cubemap layout %"PRIu32"\n", layout); + return 0; + } + projection = AV_SPHERICAL_CUBEMAP; + padding = bytestream2_get_be32(&gb); + } else { + av_log(NULL, AV_LOG_ERROR, "Unknown spherical metadata\n"); + return AVERROR_INVALIDDATA; + } break; default: return 0; @@ -1935,6 +1985,13 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) spherical->pitch = (int32_t)(track->video.projection.pitch * (1 << 16)); spherical->roll = (int32_t)(track->video.projection.roll * (1 << 16)); + spherical->padding = padding; + + spherical->bound_left = l; + spherical->bound_top = t; + spherical->bound_right = r; + spherical->bound_bottom = b; + ret = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL, (uint8_t *)spherical, spherical_size); if (ret < 0) { @@ -2287,7 +2344,7 @@ static int matroska_parse_tracks(AVFormatContext *s) track->audio.coded_framesize <= 0 || track->audio.sub_packet_h <= 0 || track->audio.frame_size <= 0 || - track->audio.sub_packet_size <= 0) + track->audio.sub_packet_size <= 0 && codec_id != AV_CODEC_ID_SIPR) return AVERROR_INVALIDDATA; track->audio.buf = av_malloc_array(track->audio.sub_packet_h, track->audio.frame_size); @@ -3363,7 +3420,7 @@ static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska) matroska->current_cluster_num_blocks = blocks_list->nb_elem; i = blocks_list->nb_elem - 1; if (blocks[i].bin.size > 0 && blocks[i].bin.data) { - int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1; + int is_keyframe = blocks[i].non_simple ? blocks[i].reference == INT64_MIN : -1; uint8_t* additional = blocks[i].additional.size > 0 ? blocks[i].additional.data : NULL; if (!blocks[i].non_simple) @@ -3401,7 +3458,7 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska) blocks = blocks_list->elem; for (i = 0; i < blocks_list->nb_elem; i++) if (blocks[i].bin.size > 0 && blocks[i].bin.data) { - int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1; + int is_keyframe = blocks[i].non_simple ? blocks[i].reference == INT64_MIN : -1; res = matroska_parse_block(matroska, blocks[i].bin.data, blocks[i].bin.size, blocks[i].bin.pos, cluster.timecode, blocks[i].duration,