mirror of
https://github.com/mpv-player/mpv
synced 2024-10-22 08:51:57 +02:00
demux_mkv: use new EBML parser for file header
This commit is contained in:
parent
5f631d1c08
commit
8b0726b28a
@ -2018,16 +2018,40 @@ static int demux_mkv_open(demuxer_t *demuxer)
|
||||
stream_t *s = demuxer->stream;
|
||||
mkv_demuxer_t *mkv_d;
|
||||
mkv_track_t *track;
|
||||
int i, version, cont = 0;
|
||||
char *str;
|
||||
int i, cont = 0;
|
||||
|
||||
stream_seek(s, s->start_pos);
|
||||
str = ebml_read_header(s, &version);
|
||||
if (str == NULL || strcmp(str, "matroska") || version > 2) {
|
||||
if (ebml_read_id(s, NULL) != EBML_ID_EBML)
|
||||
return 0;
|
||||
struct ebml_ebml ebml_master = {};
|
||||
struct ebml_parse_ctx parse_ctx = { .no_error_messages = true };
|
||||
if (ebml_read_element(s, &parse_ctx, &ebml_master, &ebml_ebml_desc) < 0)
|
||||
return 0;
|
||||
if (ebml_master.doc_type.len != 8 || strncmp(ebml_master.doc_type.start,
|
||||
"matroska", 8)) {
|
||||
mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] no head found\n");
|
||||
talloc_free(parse_ctx.talloc_ctx);
|
||||
return 0;
|
||||
}
|
||||
free(str);
|
||||
if (ebml_master.doc_type_read_version > 2) {
|
||||
mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] This looks like a Matroska file, "
|
||||
"but we don't support format version %"PRIu64"\n",
|
||||
ebml_master.doc_type_read_version);
|
||||
talloc_free(parse_ctx.talloc_ctx);
|
||||
return 0;
|
||||
}
|
||||
if ((ebml_master.n_ebml_read_version
|
||||
&& ebml_master.ebml_read_version != EBML_VERSION)
|
||||
|| (ebml_master.n_ebml_max_size_length
|
||||
&& ebml_master.ebml_max_size_length > 8)
|
||||
|| (ebml_master.n_ebml_max_id_length
|
||||
&& ebml_master.ebml_max_id_length != 4)) {
|
||||
mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] This looks like a Matroska file, "
|
||||
"but the header has bad parameters\n");
|
||||
talloc_free(parse_ctx.talloc_ctx);
|
||||
return 0;
|
||||
}
|
||||
talloc_free(parse_ctx.talloc_ctx);
|
||||
|
||||
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Found the head...\n");
|
||||
|
||||
|
@ -285,79 +285,6 @@ uint32_t ebml_read_master(stream_t *s, uint64_t *length)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read an EBML header.
|
||||
*/
|
||||
char *ebml_read_header(stream_t *s, int *version)
|
||||
{
|
||||
uint64_t length, l, num;
|
||||
uint32_t id;
|
||||
char *str = NULL;
|
||||
|
||||
if (ebml_read_master(s, &length) != EBML_ID_EBML)
|
||||
return 0;
|
||||
|
||||
if (version)
|
||||
*version = 1;
|
||||
|
||||
while (length > 0) {
|
||||
id = ebml_read_id(s, NULL);
|
||||
if (id == EBML_ID_INVALID)
|
||||
return NULL;
|
||||
length -= 2;
|
||||
|
||||
switch (id) {
|
||||
/* is our read version uptodate? */
|
||||
case EBML_ID_EBMLREADVERSION:
|
||||
num = ebml_read_uint(s, &l);
|
||||
if (num != EBML_VERSION)
|
||||
return NULL;
|
||||
break;
|
||||
|
||||
/* we only handle 8 byte lengths at max */
|
||||
case EBML_ID_EBMLMAXSIZELENGTH:
|
||||
num = ebml_read_uint(s, &l);
|
||||
if (num != sizeof(uint64_t))
|
||||
return NULL;
|
||||
break;
|
||||
|
||||
/* we handle 4 byte IDs at max */
|
||||
case EBML_ID_EBMLMAXIDLENGTH:
|
||||
num = ebml_read_uint(s, &l);
|
||||
if (num != sizeof(uint32_t))
|
||||
return NULL;
|
||||
break;
|
||||
|
||||
case EBML_ID_DOCTYPE:
|
||||
str = ebml_read_ascii(s, &l);
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
break;
|
||||
|
||||
case EBML_ID_DOCTYPEREADVERSION:
|
||||
num = ebml_read_uint(s, &l);
|
||||
if (num == EBML_UINT_INVALID)
|
||||
return NULL;
|
||||
if (version)
|
||||
*version = num;
|
||||
break;
|
||||
|
||||
/* we ignore these two, they don't tell us anything we care about */
|
||||
case EBML_ID_VOID:
|
||||
case EBML_ID_EBMLVERSION:
|
||||
case EBML_ID_DOCTYPEVERSION:
|
||||
default:
|
||||
if (ebml_read_skip(s, &l))
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
length -= l;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define EVALARGS(F, ...) F(__VA_ARGS__)
|
||||
#define E(str, N, type) const struct ebml_elem_desc ebml_ ## N ## _desc = { str, type };
|
||||
|
@ -109,7 +109,6 @@ char *ebml_read_ascii (stream_t *s, uint64_t *length);
|
||||
char *ebml_read_utf8 (stream_t *s, uint64_t *length);
|
||||
int ebml_read_skip (stream_t *s, uint64_t *length);
|
||||
uint32_t ebml_read_master (stream_t *s, uint64_t *length);
|
||||
char *ebml_read_header (stream_t *s, int *version);
|
||||
|
||||
int ebml_read_element(struct stream *s, struct ebml_parse_ctx *ctx,
|
||||
void *target, const struct ebml_elem_desc *desc);
|
||||
|
Loading…
Reference in New Issue
Block a user