mirror of
https://github.com/mpv-player/mpv
synced 2025-01-26 01:23:17 +00:00
demux_mkv: Parse ordered chapter information
Parse the ordered chapter structure if present and place the information in the public demuxer structure. Nothing uses the information yet.
This commit is contained in:
parent
4b33422c7b
commit
3279403611
@ -12,7 +12,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "talloc.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "stream/stream.h"
|
#include "stream/stream.h"
|
||||||
#include "demuxer.h"
|
#include "demuxer.h"
|
||||||
@ -405,6 +407,24 @@ static int demux_mkv_read_info(demuxer_t *demuxer)
|
|||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MATROSKA_ID_SEGMENTUID:;
|
||||||
|
l = ebml_read_length(s, &i);
|
||||||
|
length -= i;
|
||||||
|
if (l != sizeof(demuxer->matroska_data.segment_uid)) {
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_INFO,
|
||||||
|
"[mkv] segment uid invalid length %"PRIu64"\n", l);
|
||||||
|
stream_skip(s, l);
|
||||||
|
} else {
|
||||||
|
stream_read(s, demuxer->matroska_data.segment_uid, l);
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + segment uid");
|
||||||
|
for (int i = 0; i < l; i++)
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_V, " %02x",
|
||||||
|
demuxer->matroska_data.segment_uid[i]);
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_V, "\n");
|
||||||
|
}
|
||||||
|
length -= l;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ebml_read_skip(s, &l);
|
ebml_read_skip(s, &l);
|
||||||
length -= l;
|
length -= l;
|
||||||
@ -1074,10 +1094,11 @@ demux_mkv_read_cues (demuxer_t *demuxer)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t read_one_chapter(demuxer_t *demuxer, stream_t *s)
|
static uint64_t read_one_chapter(struct demuxer *demuxer, stream_t *s)
|
||||||
{
|
{
|
||||||
uint64_t len, l;
|
uint64_t len, l;
|
||||||
uint64_t start = 0, end = 0;
|
uint64_t start = 0, end = 0;
|
||||||
|
struct matroska_chapter chapter = {};
|
||||||
char *name = 0;
|
char *name = 0;
|
||||||
int i;
|
int i;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
@ -1117,6 +1138,24 @@ static uint64_t read_one_chapter(demuxer_t *demuxer, stream_t *s)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MATROSKA_ID_CHAPTERSEGMENTUID:
|
||||||
|
l = ebml_read_length(s, &i);
|
||||||
|
len -= l + i;
|
||||||
|
if (l != sizeof(chapter.segment_uid)) {
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_INFO,
|
||||||
|
"[mkv] chapter segment uid invalid length %"PRIu64"\n",
|
||||||
|
l);
|
||||||
|
stream_skip(s, l);
|
||||||
|
} else {
|
||||||
|
stream_read(s, chapter.segment_uid, l);
|
||||||
|
chapter.has_segment_uid = true;
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter segment uid ");
|
||||||
|
for (int i = 0; i < l; i++)
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_V, "%02x ", chapter.segment_uid[i]);
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_V, "\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ebml_read_skip(s, &l);
|
ebml_read_skip(s, &l);
|
||||||
len -= l;
|
len -= l;
|
||||||
@ -1128,6 +1167,15 @@ static uint64_t read_one_chapter(demuxer_t *demuxer, stream_t *s)
|
|||||||
name = strdup("(unnamed)");
|
name = strdup("(unnamed)");
|
||||||
|
|
||||||
int cid = demuxer_add_chapter(demuxer, name, start, end);
|
int cid = demuxer_add_chapter(demuxer, name, start, end);
|
||||||
|
struct matroska_data *m = &demuxer->matroska_data;
|
||||||
|
m->ordered_chapters = talloc_realloc(demuxer, m->ordered_chapters,
|
||||||
|
struct matroska_chapter,
|
||||||
|
m->num_ordered_chapters + 1);
|
||||||
|
chapter.start = start;
|
||||||
|
chapter.end = end;
|
||||||
|
// Will be undone later if this is a normal chapter rather than ordered
|
||||||
|
m->ordered_chapters[m->num_ordered_chapters] = chapter;
|
||||||
|
m->num_ordered_chapters++;
|
||||||
|
|
||||||
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter %u from %02d:%02d:%02d."
|
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter %u from %02d:%02d:%02d."
|
||||||
"%03d to %02d:%02d:%02d.%03d, %s\n",
|
"%03d to %02d:%02d:%02d.%03d, %s\n",
|
||||||
@ -1160,13 +1208,23 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer)
|
|||||||
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing chapters ] ---------\n");
|
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing chapters ] ---------\n");
|
||||||
length = ebml_read_length(s, NULL);
|
length = ebml_read_length(s, NULL);
|
||||||
|
|
||||||
|
bool have_edition = false;
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
id = ebml_read_id(s, &i);
|
id = ebml_read_id(s, &i);
|
||||||
length -= i;
|
length -= i;
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case MATROSKA_ID_EDITIONENTRY:;
|
case MATROSKA_ID_EDITIONENTRY:
|
||||||
|
if (have_edition) {
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Multiple edition entries"
|
||||||
|
" - ignoring all but first!\n");
|
||||||
|
ebml_read_skip(s, &l);
|
||||||
|
length -= l;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
have_edition = true;
|
||||||
uint64_t editionlen = ebml_read_length(s, &i);
|
uint64_t editionlen = ebml_read_length(s, &i);
|
||||||
length -= editionlen + i;
|
length -= editionlen + i;
|
||||||
|
bool ordered = false;
|
||||||
while (editionlen > 0) {
|
while (editionlen > 0) {
|
||||||
id = ebml_read_id(s, &i);
|
id = ebml_read_id(s, &i);
|
||||||
editionlen -= i;
|
editionlen -= i;
|
||||||
@ -1174,12 +1232,25 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer)
|
|||||||
case MATROSKA_ID_CHAPTERATOM:
|
case MATROSKA_ID_CHAPTERATOM:
|
||||||
l = read_one_chapter(demuxer, s);
|
l = read_one_chapter(demuxer, s);
|
||||||
break;
|
break;
|
||||||
|
case MATROSKA_ID_EDITIONFLAGORDERED:
|
||||||
|
ordered = ebml_read_uint(s, &l);
|
||||||
|
mp_msg(MSGT_DEMUX, MSGL_V,
|
||||||
|
"[mkv] Ordered chapter flag: %d\n", ordered);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ebml_read_skip(s, &l);
|
ebml_read_skip(s, &l);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
editionlen -= l;
|
editionlen -= l;
|
||||||
}
|
}
|
||||||
|
if (!ordered) {
|
||||||
|
// The chapters should be interpreted as normal ones,
|
||||||
|
// so undo the addition of this information.
|
||||||
|
talloc_free(demuxer->matroska_data.ordered_chapters);
|
||||||
|
demuxer->matroska_data.ordered_chapters = NULL;
|
||||||
|
demuxer->matroska_data.num_ordered_chapters = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "stream/stream.h"
|
#include "stream/stream.h"
|
||||||
|
|
||||||
@ -187,6 +188,18 @@ typedef struct demux_chapter
|
|||||||
char* name;
|
char* name;
|
||||||
} demux_chapter_t;
|
} demux_chapter_t;
|
||||||
|
|
||||||
|
struct matroska_data {
|
||||||
|
unsigned char segment_uid[16];
|
||||||
|
// Ordered chapter information if any
|
||||||
|
struct matroska_chapter {
|
||||||
|
uint64_t start;
|
||||||
|
uint64_t end;
|
||||||
|
bool has_segment_uid;
|
||||||
|
unsigned char segment_uid[16];
|
||||||
|
} *ordered_chapters;
|
||||||
|
int num_ordered_chapters;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct demux_attachment
|
typedef struct demux_attachment
|
||||||
{
|
{
|
||||||
char* name;
|
char* name;
|
||||||
@ -220,10 +233,12 @@ typedef struct demuxer {
|
|||||||
|
|
||||||
demux_chapter_t* chapters;
|
demux_chapter_t* chapters;
|
||||||
int num_chapters;
|
int num_chapters;
|
||||||
|
|
||||||
demux_attachment_t* attachments;
|
demux_attachment_t* attachments;
|
||||||
int num_attachments;
|
int num_attachments;
|
||||||
|
|
||||||
|
struct matroska_data matroska_data;
|
||||||
|
|
||||||
void* priv; // fileformat-dependent data
|
void* priv; // fileformat-dependent data
|
||||||
char** info;
|
char** info;
|
||||||
struct MPOpts *opts;
|
struct MPOpts *opts;
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
#define MATROSKA_ID_WRITINGAPP 0x5741
|
#define MATROSKA_ID_WRITINGAPP 0x5741
|
||||||
#define MATROSKA_ID_MUXINGAPP 0x4D80
|
#define MATROSKA_ID_MUXINGAPP 0x4D80
|
||||||
#define MATROSKA_ID_DATEUTC 0x4461
|
#define MATROSKA_ID_DATEUTC 0x4461
|
||||||
|
#define MATROSKA_ID_SEGMENTUID 0x73A4
|
||||||
|
|
||||||
/* ID in the tracks master */
|
/* ID in the tracks master */
|
||||||
#define MATROSKA_ID_TRACKENTRY 0xAE
|
#define MATROSKA_ID_TRACKENTRY 0xAE
|
||||||
@ -126,11 +127,13 @@
|
|||||||
|
|
||||||
/* IDs in the chapters master */
|
/* IDs in the chapters master */
|
||||||
#define MATROSKA_ID_EDITIONENTRY 0x45B9
|
#define MATROSKA_ID_EDITIONENTRY 0x45B9
|
||||||
|
#define MATROSKA_ID_EDITIONFLAGORDERED 0x45DD
|
||||||
#define MATROSKA_ID_CHAPTERATOM 0xB6
|
#define MATROSKA_ID_CHAPTERATOM 0xB6
|
||||||
#define MATROSKA_ID_CHAPTERTIMESTART 0x91
|
#define MATROSKA_ID_CHAPTERTIMESTART 0x91
|
||||||
#define MATROSKA_ID_CHAPTERTIMEEND 0x92
|
#define MATROSKA_ID_CHAPTERTIMEEND 0x92
|
||||||
#define MATROSKA_ID_CHAPTERDISPLAY 0x80
|
#define MATROSKA_ID_CHAPTERDISPLAY 0x80
|
||||||
#define MATROSKA_ID_CHAPSTRING 0x85
|
#define MATROSKA_ID_CHAPSTRING 0x85
|
||||||
|
#define MATROSKA_ID_CHAPTERSEGMENTUID 0x6E67
|
||||||
|
|
||||||
/* IDs in the cluster master */
|
/* IDs in the cluster master */
|
||||||
#define MATROSKA_ID_CLUSTERTIMECODE 0xE7
|
#define MATROSKA_ID_CLUSTERTIMECODE 0xE7
|
||||||
|
Loading…
Reference in New Issue
Block a user