summaryrefslogtreecommitdiffstats
path: root/libmpdemux/demux_mkv.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmpdemux/demux_mkv.c')
-rw-r--r--libmpdemux/demux_mkv.c4734
1 files changed, 2107 insertions, 2627 deletions
diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c
index ecb171c551..24101d516e 100644
--- a/libmpdemux/demux_mkv.c
+++ b/libmpdemux/demux_mkv.c
@@ -27,7 +27,10 @@
#include <stdio.h>
#include <ctype.h>
#include <inttypes.h>
+#include <stdbool.h>
+#include "talloc.h"
+#include "options.h"
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
@@ -42,7 +45,7 @@
#include "subreader.h"
#include "libvo/sub.h"
-#include "libass/ass_mp.h"
+#include "ass_mp.h"
#include "libavutil/common.h"
@@ -55,141 +58,143 @@
#endif
#include "libavutil/lzo.h"
-#include "libavutil/intreadwrite.h"
+#include "ffmpeg_files/intreadwrite.h"
#include "libavutil/avstring.h"
-static const unsigned char sipr_swaps[38][2]={
+static const unsigned char sipr_swaps[38][2] = {
{0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68},
{13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46},
{25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56},
{42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83},
- {77,80} };
+ {77,80}
+};
// Map flavour to bytes per second
#define SIPR_FLAVORS 4
#define ATRC_FLAVORS 8
#define COOK_FLAVORS 34
-static const int sipr_fl2bps[SIPR_FLAVORS] = {813, 1062, 625, 2000};
+static const int sipr_fl2bps[SIPR_FLAVORS] = { 813, 1062, 625, 2000 };
static const int atrc_fl2bps[ATRC_FLAVORS] =
- {8269, 11714, 13092, 16538, 18260, 22050, 33075, 44100};
-static const int cook_fl2bps[COOK_FLAVORS] =
- { 1000, 1378, 2024, 2584, 4005, 5513, 8010, 4005, 750, 2498,
- 4048, 5513, 8010, 11973, 8010, 2584, 4005, 2067, 2584, 2584,
- 4005, 4005, 5513, 5513, 8010, 12059, 1550, 8010, 12059, 5513,
- 12016, 16408, 22911, 33506};
-
-typedef struct
-{
- uint32_t order, type, scope;
- uint32_t comp_algo;
- uint8_t *comp_settings;
- int comp_settings_len;
+ { 8269, 11714, 13092, 16538, 18260, 22050, 33075, 44100 };
+static const int cook_fl2bps[COOK_FLAVORS] = {
+ 1000, 1378, 2024, 2584, 4005, 5513, 8010, 4005, 750, 2498,
+ 4048, 5513, 8010, 11973, 8010, 2584, 4005, 2067, 2584, 2584,
+ 4005, 4005, 5513, 5513, 8010, 12059, 1550, 8010, 12059, 5513,
+ 12016, 16408, 22911, 33506
+};
+
+typedef struct mkv_content_encoding {
+ uint64_t order, type, scope;
+ uint64_t comp_algo;
+ uint8_t *comp_settings;
+ int comp_settings_len;
} mkv_content_encoding_t;
-typedef struct mkv_track
-{
- int tnum;
- char *name;
+typedef struct mkv_track {
+ int tnum;
+ char *name;
- char *codec_id;
- int ms_compat;
- char *language;
+ char *codec_id;
+ int ms_compat;
+ char *language;
- int type;
+ int type;
- uint32_t v_width, v_height, v_dwidth, v_dheight;
- float v_frate;
+ uint32_t v_width, v_height, v_dwidth, v_dheight;
+ double v_frate;
- uint32_t a_formattag;
- uint32_t a_channels, a_bps;
- float a_sfreq;
+ uint32_t a_formattag;
+ uint32_t a_channels, a_bps;
+ float a_sfreq;
- float default_duration;
+ double default_duration;
- int default_track;
+ int default_track;
- void *private_data;
- unsigned int private_size;
+ unsigned char *private_data;
+ unsigned int private_size;
- /* stuff for realmedia */
- int realmedia;
- int64_t rv_kf_base;
- int rv_kf_pts;
- float rv_pts; /* previous video timestamp */
- float ra_pts; /* previous audio timestamp */
+ /* stuff for realmedia */
+ int realmedia;
+ int64_t rv_kf_base;
+ int rv_kf_pts;
+ double rv_pts; /* previous video timestamp */
+ double ra_pts; /* previous audio timestamp */
/** realaudio descrambling */
- int sub_packet_size; ///< sub packet size, per stream
- int sub_packet_h; ///< number of coded frames per block
- int coded_framesize; ///< coded frame size, per stream
- int audiopk_size; ///< audio packet size
- unsigned char *audio_buf; ///< place to store reordered audio data
- float *audio_timestamp; ///< timestamp for each audio packet
- int sub_packet_cnt; ///< number of subpacket already received
- int audio_filepos; ///< file position of first audio packet in block
-
- /* stuff for quicktime */
- int fix_i_bps;
- float qt_last_a_pts;
-
- int subtitle_type;
-
- /* The timecodes of video frames might have to be reordered if they're
- in display order (the timecodes, not the frames themselves!). In this
- case demux packets have to be cached with the help of these variables. */
- int reorder_timecodes;
- demux_packet_t **cached_dps;
- int num_cached_dps, num_allocated_dps;
- float max_pts;
-
- /* generic content encoding support */
- mkv_content_encoding_t *encodings;
- int num_encodings;
-
- /* For VobSubs and SSA/ASS */
- sh_sub_t *sh_sub;
+ int sub_packet_size; ///< sub packet size, per stream
+ int sub_packet_h; ///< number of coded frames per block
+ int coded_framesize; ///< coded frame size, per stream
+ int audiopk_size; ///< audio packet size
+ unsigned char *audio_buf; ///< place to store reordered audio data
+ double *audio_timestamp; ///< timestamp for each audio packet
+ int sub_packet_cnt; ///< number of subpacket already received
+ int audio_filepos; ///< file position of first audio packet in block
+
+ /* stuff for quicktime */
+ int fix_i_bps;
+ double qt_last_a_pts;
+
+ int subtitle_type;
+
+ /* The timecodes of video frames might have to be reordered if they're
+ in display order (the timecodes, not the frames themselves!). In this
+ case demux packets have to be cached with the help of these variables. */
+ int reorder_timecodes;
+ demux_packet_t **cached_dps;
+ int num_cached_dps, num_allocated_dps;
+ double max_pts;
+
+ /* generic content encoding support */
+ mkv_content_encoding_t *encodings;
+ int num_encodings;
+
+ /* For VobSubs and SSA/ASS */
+ sh_sub_t *sh_sub;
} mkv_track_t;
-typedef struct mkv_index
-{
- int tnum;
- uint64_t timecode, filepos;
+typedef struct mkv_index {
+ int tnum;
+ uint64_t timecode, filepos;
} mkv_index_t;
-typedef struct mkv_demuxer
-{
- off_t segment_start;
+typedef struct mkv_demuxer {
+ off_t segment_start;
- float duration, last_pts;
- uint64_t last_filepos;
+ double duration, last_pts;
+ uint64_t last_filepos;
- mkv_track_t **tracks;
- int num_tracks;
+ mkv_track_t **tracks;
+ int num_tracks;
- uint64_t tc_scale, cluster_tc, first_tc;
- int has_first_tc;
+ uint64_t tc_scale, cluster_tc;
- uint64_t cluster_size;
- uint64_t blockgroup_size;
+ uint64_t cluster_start;
+ uint64_t cluster_size;
+ uint64_t blockgroup_size;
- mkv_index_t *indexes;
- int num_indexes;
+ mkv_index_t *indexes;
+ int num_indexes;
- off_t *parsed_cues;
- int parsed_cues_num;
- off_t *parsed_seekhead;
- int parsed_seekhead_num;
+ off_t *parsed_pos;
+ int num_parsed_pos;
+ bool parsed_info;
+ bool parsed_tracks;
+ bool parsed_tags;
+ bool parsed_chapters;
+ bool parsed_attachments;
- uint64_t *cluster_positions;
- int num_cluster_pos;
+ struct cluster_pos {
+ uint64_t filepos;
+ uint64_t timecode;
+ } *cluster_positions;
+ int num_cluster_pos;
- int64_t skip_to_timecode;
- int v_skip_to_keyframe, a_skip_to_keyframe;
+ int64_t skip_to_timecode;
+ int v_skip_to_keyframe, a_skip_to_keyframe;
- int64_t stop_timecode;
-
- int last_aid;
- int audio_tracks[MAX_A_STREAMS];
+ int last_aid;
+ int audio_tracks[MAX_A_STREAMS];
} mkv_demuxer_t;
#define REALHEADER_SIZE 16
@@ -197,70 +202,86 @@ typedef struct mkv_demuxer
#define RAPROPERTIES4_SIZE 56
#define RAPROPERTIES5_SIZE 70
-/* for e.g. "-slang ger" */
-extern char *dvdsub_lang;
-extern char *audio_lang;
-extern int dvdsub_id;
-
/**
* \brief ensures there is space for at least one additional element
- * \param arrayp array to grow
+ * \param array array to grow
* \param nelem current number of elements in array
* \param elsize size of one array element
*/
-static void av_noinline grow_array(void *arrayp, int nelem, size_t elsize) {
- void **array = arrayp;
- void *oldp = *array;
- if (nelem & 31)
- return;
- if (nelem > UINT_MAX / elsize - 32)
- *array = NULL;
- else
- *array = realloc(*array, (nelem + 32) * elsize);
- if (!*array)
- free(oldp);
+static void *grow_array(void *array, int nelem, size_t elsize)
+{
+ if (!(nelem & 31))
+ array = realloc(array, (nelem + 32) * elsize);
+ return array;
}
-static mkv_track_t *
-demux_mkv_find_track_by_num (mkv_demuxer_t *d, int n, int type)
+static bool is_parsed_header(struct mkv_demuxer *mkv_d, off_t pos)
{
- int i, id;
+ int low = 0;
+ int high = mkv_d->num_parsed_pos;
+ while (high > low + 1) {
+ int mid = high + low >> 1;
+ if (mkv_d->parsed_pos[mid] > pos)
+ high = mid;
+ else
+ low = mid;
+ }
+ if (mkv_d->num_parsed_pos && mkv_d->parsed_pos[low] == pos)
+ return true;
+ if (!(mkv_d->num_parsed_pos & 31))
+ mkv_d->parsed_pos = talloc_realloc(mkv_d, mkv_d->parsed_pos, off_t,
+ mkv_d->num_parsed_pos + 32);
+ mkv_d->num_parsed_pos++;
+ for (int i = mkv_d->num_parsed_pos - 1; i > low; i--)
+ mkv_d->parsed_pos[i] = mkv_d->parsed_pos[i - 1];
+ mkv_d->parsed_pos[low] = pos;
+ return false;
+}
- for (i=0, id=0; i < d->num_tracks; i++)
- if (d->tracks[i] != NULL && d->tracks[i]->type == type)
- if (id++ == n)
- return d->tracks[i];
+static mkv_track_t *demux_mkv_find_track_by_num(mkv_demuxer_t *d, int n,
+ int type)
+{
+ int i, id;
- return NULL;
+ for (i = 0, id = 0; i < d->num_tracks; i++)
+ if (d->tracks[i] != NULL && d->tracks[i]->type == type)
+ if (id++ == n)
+ return d->tracks[i];
+
+ return NULL;
}
-static void
-add_cluster_position (mkv_demuxer_t *mkv_d, uint64_t position)
+static void add_cluster_position(mkv_demuxer_t *mkv_d, uint64_t filepos,
+ uint64_t timecode)
{
- int i = mkv_d->num_cluster_pos;
-
- while (i--)
- if (mkv_d->cluster_positions[i] == position)
- return;
-
- grow_array(&mkv_d->cluster_positions, mkv_d->num_cluster_pos,
- sizeof(uint64_t));
- if (!mkv_d->cluster_positions) {
- mkv_d->num_cluster_pos = 0;
- return;
- }
- mkv_d->cluster_positions[mkv_d->num_cluster_pos++] = position;
+ if (mkv_d->indexes)
+ return;
+
+ int n = mkv_d->num_cluster_pos;
+ if (n > 0 && mkv_d->cluster_positions[n-1].filepos >= filepos)
+ return;
+
+ mkv_d->cluster_positions =
+ grow_array(mkv_d->cluster_positions, mkv_d->num_cluster_pos,
+ sizeof(*mkv_d->cluster_positions));
+ mkv_d->cluster_positions[mkv_d->num_cluster_pos++] = (struct cluster_pos){
+ .filepos = filepos,
+ .timecode = timecode,
+ };
}
#define AAC_SYNC_EXTENSION_TYPE 0x02b7
-static int
-aac_get_sample_rate_index (uint32_t sample_rate)
+static int aac_get_sample_rate_index(uint32_t sample_rate)
{
- static const int srates[] = {92017, 75132, 55426, 46009, 37566, 27713, 23004, 18783, 13856, 11502, 9391, 0};
- int i = 0;
- while (sample_rate < srates[i]) i++;
- return i;
+ static const int srates[] = {
+ 92017, 75132, 55426, 46009, 37566, 27713,
+ 23004, 18783, 13856, 11502, 9391, 0
+ };
+ int i = 0;
+ while (sample_rate < srates[i])
+ i++;
+ return i;
}
/** \brief Free cached demux packets
@@ -271,2250 +292,1732 @@ aac_get_sample_rate_index (uint32_t sample_rate)
*
* \param demuxer The demuxer for which the cache is to be freed.
*/
-static void
-free_cached_dps (demuxer_t *demuxer)
+static void free_cached_dps(demuxer_t *demuxer)
{
- mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
- mkv_track_t *track;
- int i, k;
-
- for (k = 0; k < mkv_d->num_tracks; k++)
- {
- track = mkv_d->tracks[k];
- for (i = 0; i < track->num_cached_dps; i++)
- free_demux_packet (track->cached_dps[i]);
- free(track->cached_dps);
- track->cached_dps = NULL;
- track->num_cached_dps = 0;
- track->num_allocated_dps = 0;
- track->max_pts = 0;
+ mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
+ mkv_track_t *track;
+ int i, k;
+
+ for (k = 0; k < mkv_d->num_tracks; k++) {
+ track = mkv_d->tracks[k];
+ for (i = 0; i < track->num_cached_dps; i++)
+ free_demux_packet(track->cached_dps[i]);
+ free(track->cached_dps);
+ track->cached_dps = NULL;
+ track->num_cached_dps = 0;
+ track->num_allocated_dps = 0;
+ track->max_pts = 0;
}
}
-static int
-demux_mkv_decode (mkv_track_t *track, uint8_t *src, uint8_t **dest,
- uint32_t *size, uint32_t type)
+static void demux_mkv_decode(mkv_track_t *track, uint8_t *src,
+ uint8_t **dest, uint32_t *size, uint32_t type)
{
- int i, result;
- int modified = 0;
+ uint8_t *orig_src = src;
- *dest = src;
- if (track->num_encodings <= 0)
- return 0;
+ *dest = src;
- for (i=0; i<track->num_encodings; i++)
- {
- if (!(track->encodings[i].scope & type))
- continue;
+ for (int i = 0; i < track->num_encodings; i++) {
+ struct mkv_content_encoding *enc = track->encodings + i;
+ if (!(enc->scope & type))
+ continue;
+ if (src != *dest && src != orig_src)
+ free(src);
+ src = *dest; // output from last iteration is new source
+
+ if (enc->comp_algo == 0) {
#if CONFIG_ZLIB
- if (track->encodings[i].comp_algo == 0)
- {
- /* zlib encoded track */
- z_stream zstream;
-
- zstream.zalloc = (alloc_func) 0;
- zstream.zfree = (free_func) 0;
- zstream.opaque = (voidpf) 0;
- if (inflateInit (&zstream) != Z_OK)
- {
- mp_msg (MSGT_DEMUX, MSGL_WARN,
- MSGTR_MPDEMUX_MKV_ZlibInitializationFailed);
- return modified;
+ /* zlib encoded track */
+
+ if (*size == 0)
+ continue;
+
+ z_stream zstream;
+
+ zstream.zalloc = (alloc_func) 0;
+ zstream.zfree = (free_func) 0;
+ zstream.opaque = (voidpf) 0;
+ if (inflateInit(&zstream) != Z_OK) {
+ mp_tmsg(MSGT_DEMUX, MSGL_WARN,
+ "[mkv] zlib initialization failed.\n");
+ goto error;
}
- zstream.next_in = (Bytef *) src;
- zstream.avail_in = *size;
-
- modified = 1;
- *dest = NULL;
- zstream.avail_out = *size;
- do {
- *size += 4000;
- *dest = realloc (*dest, *size);
- zstream.next_out = (Bytef *) (*dest + zstream.total_out);
- result = inflate (&zstream, Z_NO_FLUSH);
- if (result != Z_OK && result != Z_STREAM_END)
- {
- mp_msg (MSGT_DEMUX, MSGL_WARN,
- MSGTR_MPDEMUX_MKV_ZlibDecompressionFailed);
- free(*dest);
- *dest = NULL;
- inflateEnd (&zstream);
- return modified;
- }
- zstream.avail_out += 4000;
- } while (zstream.avail_out == 4000 &&
- zstream.avail_in != 0 && result != Z_STREAM_END);
-
- *size = zstream.total_out;
- inflateEnd (&zstream);
- }
+ zstream.next_in = (Bytef *) src;
+ zstream.avail_in = *size;
+
+ *dest = NULL;
+ zstream.avail_out = *size;
+ int result;
+ do {
+ *size += 4000;
+ *dest = realloc(*dest, *size);
+ zstream.next_out = (Bytef *) (*dest + zstream.total_out);
+ result = inflate(&zstream, Z_NO_FLUSH);
+ if (result != Z_OK && result != Z_STREAM_END) {
+ mp_tmsg(MSGT_DEMUX, MSGL_WARN,
+ "[mkv] zlib decompression failed.\n");
+ free(*dest);
+ *dest = NULL;
+ inflateEnd(&zstream);
+ goto error;
+ }
+ zstream.avail_out += 4000;
+ } while (zstream.avail_out == 4000 && zstream.avail_in != 0
+ && result != Z_STREAM_END);
+
+ *size = zstream.total_out;
+ inflateEnd(&zstream);
#endif
- if (track->encodings[i].comp_algo == 2)
- {
- /* lzo encoded track */
- int dstlen = *size * 3;
-
- *dest = NULL;
- while (1)
- {
- int srclen = *size;
- if (dstlen > SIZE_MAX - AV_LZO_OUTPUT_PADDING) goto lzo_fail;
- *dest = realloc (*dest, dstlen + AV_LZO_OUTPUT_PADDING);
- result = av_lzo1x_decode (*dest, &dstlen, src, &srclen);
- if (result == 0)
- break;
- if (!(result & AV_LZO_OUTPUT_FULL))
- {
-lzo_fail:
- mp_msg (MSGT_DEMUX, MSGL_WARN,
- MSGTR_MPDEMUX_MKV_LzoDecompressionFailed);
- free(*dest);
- *dest = NULL;
- return modified;
+ } else if (enc->comp_algo == 2) {
+ /* lzo encoded track */
+ int dstlen = *size * 3;
+
+ *dest = NULL;
+ while (1) {
+ int srclen = *size;
+ if (dstlen > SIZE_MAX - AV_LZO_OUTPUT_PADDING)
+ goto lzo_fail;
+ *dest = realloc(*dest, dstlen + AV_LZO_OUTPUT_PADDING);
+ int result = av_lzo1x_decode(*dest, &dstlen, src, &srclen);
+ if (result == 0)
+ break;
+ if (!(result & AV_LZO_OUTPUT_FULL)) {
+ lzo_fail:
+ mp_tmsg(MSGT_DEMUX, MSGL_WARN,
+ "[mkv] lzo decompression failed.\n");
+ free(*dest);
+ *dest = NULL;
+ goto error;
}
- mp_msg (MSGT_DEMUX, MSGL_DBG2,
- "[mkv] lzo decompression buffer too small.\n");
- dstlen *= 2;
+ mp_msg(MSGT_DEMUX, MSGL_DBG2,
+ "[mkv] lzo decompression buffer too small.\n");
+ dstlen *= 2;
}
- *size = dstlen;
+ *size = dstlen;
+ } else if (enc->comp_algo == 3) {
+ *dest = malloc(*size + enc->comp_settings_len);
+ memcpy(*dest, enc->comp_settings, enc->comp_settings_len);
+ memcpy(*dest + enc->comp_settings_len, src, *size);
+ *size += enc->comp_settings_len;
}
}
- return modified;
+ error:
+ if (src != *dest && src != orig_src)
+ free(src);
}
-static int
-demux_mkv_read_info (demuxer_t *demuxer)
+static int demux_mkv_read_info(demuxer_t *demuxer)
{
- mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
- stream_t *s = demuxer->stream;
- uint64_t length, l;
- int il;
- uint64_t tc_scale = 1000000;
- long double duration = 0.;
-
- length = ebml_read_length (s, NULL);
- while (length > 0)
- {
- switch (ebml_read_id (s, &il))
- {
- case MATROSKA_ID_TIMECODESCALE:
- {
- uint64_t num = ebml_read_uint (s, &l);
- if (num == EBML_UINT_INVALID)
- return 1;
- tc_scale = num;
- mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + timecode scale: %"PRIu64"\n",
- tc_scale);
- break;
- }
-
- case MATROSKA_ID_DURATION:
- {
- long double num = ebml_read_float (s, &l);
- if (num == EBML_FLOAT_INVALID)
- return 1;
- duration = num;
- mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3Lfs\n",
- duration * tc_scale / 1000000000.0);
- break;
- }
+ mkv_demuxer_t *mkv_d = demuxer->priv;
+ stream_t *s = demuxer->stream;
- default:
- ebml_read_skip (s, &l);
- break;
+ mkv_d->tc_scale = 1000000;
+ mkv_d->duration = 0;
+
+ struct ebml_info info = {};
+ struct ebml_parse_ctx parse_ctx = {};
+ if (ebml_read_element(s, &parse_ctx, &info, &ebml_info_desc) < 0)
+ return 1;
+ if (info.n_timecode_scale) {
+ mkv_d->tc_scale = info.timecode_scale;
+ mp_msg(MSGT_DEMUX, MSGL_V,
+ "[mkv] | + timecode scale: %" PRIu64 "\n", mkv_d->tc_scale);
+ }
+ if (info.n_duration) {
+ mkv_d->duration = info.duration * mkv_d->tc_scale / 1e9;
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3fs\n",
+ mkv_d->duration);
+ }
+ if (info.n_segment_uid) {
+ int len = info.segment_uid.len;
+ if (len != sizeof(demuxer->matroska_data.segment_uid)) {
+ mp_msg(MSGT_DEMUX, MSGL_INFO,
+ "[mkv] segment uid invalid length %d\n", len);
+ } else {
+ memcpy(demuxer->matroska_data.segment_uid, info.segment_uid.start,
+ len);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + segment uid");
+ for (int i = 0; i < len; i++)
+ mp_msg(MSGT_DEMUX, MSGL_V, " %02x",
+ demuxer->matroska_data.segment_uid[i]);
+ mp_msg(MSGT_DEMUX, MSGL_V, "\n");
}
- length -= l + il;
}
- mkv_d->tc_scale = tc_scale;
- mkv_d->duration = duration * tc_scale / 1000000000.0;
- return 0;
-}
-
-/**
- * \brief free array of kv_content_encoding_t
- * \param encodings pointer to array
- * \param numencodings number of encodings in array
- */
-static void
-demux_mkv_free_encodings(mkv_content_encoding_t *encodings, int numencodings)
-{
- while (numencodings-- > 0)
- free(encodings[numencodings].comp_settings);
- free(encodings);
+ talloc_free(parse_ctx.talloc_ctx);
+ return 0;
}
-static int
-demux_mkv_read_trackencodings (demuxer_t *demuxer, mkv_track_t *track)
+static void parse_trackencodings(struct demuxer *demuxer,
+ struct mkv_track *track,
+ struct ebml_content_encodings *encodings)
{
- stream_t *s = demuxer->stream;
- mkv_content_encoding_t *ce, e;
- uint64_t len, length, l;
- int il, n;
-
- ce = malloc (sizeof (*ce));
- n = 0;
-
- len = length = ebml_read_length (s, &il);
- len += il;
- while (length > 0)
- {
- switch (ebml_read_id (s, &il))
- {
- case MATROSKA_ID_CONTENTENCODING:
- {
- uint64_t len;
- int i;
-
- memset (&e, 0, sizeof (e));
+ // initial allocation to be a non-NULL context before realloc
+ mkv_content_encoding_t *ce = talloc_size(track, 1);
+
+ for (int n_enc = 0; n_enc < encodings->n_content_encoding; n_enc++) {
+ struct ebml_content_encoding *enc = encodings->content_encoding + n_enc;
+ struct mkv_content_encoding e = {};
+ e.order = enc->content_encoding_order;
+ if (enc->n_content_encoding_scope)
+ e.scope = enc->content_encoding_scope;
+ else
e.scope = 1;
+ e.type = enc->content_encoding_type;
+
+ if (enc->n_content_compression) {
+ struct ebml_content_compression *z = &enc->content_compression;
+ e.comp_algo = z->content_comp_algo;
+ if (z->n_content_comp_settings) {
+ int sz = z->content_comp_settings.len;
+ e.comp_settings = talloc_size(ce, sz);
+ memcpy(e.comp_settings, z->content_comp_settings.start, sz);
+ e.comp_settings_len = sz;
+ }
+ }
- len = ebml_read_length (s, &i);
- l = len + i;
-
- while (len > 0)
- {
- uint64_t num, l;
- int il;
-
- switch (ebml_read_id (s, &il))
- {
- case MATROSKA_ID_CONTENTENCODINGORDER:
- num = ebml_read_uint (s, &l);
- if (num == EBML_UINT_INVALID)
- goto err_out;
- e.order = num;
- break;
-
- case MATROSKA_ID_CONTENTENCODINGSCOPE:
- num = ebml_read_uint (s, &l);
- if (num == EBML_UINT_INVALID)
- goto err_out;
- e.scope = num;
- break;
-
- case MATROSKA_ID_CONTENTENCODINGTYPE:
- num = ebml_read_uint (s, &l);
- if (num == EBML_UINT_INVALID)
- goto err_out;
- e.type = num;
- break;
-
- case MATROSKA_ID_CONTENTCOMPRESSION:
- {
- uint64_t le;
-
- le = ebml_read_length (s, &i);
- l = le + i;
-
- while (le > 0)
- {
- uint64_t l;
- int il;
-
- switch (ebml_read_id (s, &il))
- {
- case MATROSKA_ID_CONTENTCOMPALGO:
- num = ebml_read_uint (s, &l);
- if (num == EBML_UINT_INVALID)
- goto err_out;
- e.comp_algo = num;
- break;
-
- case MATROSKA_ID_CONTENTCOMPSETTINGS:
- l = ebml_read_length (s, &i);
- e.comp_settings = malloc (l);
- stream_read (s, e.comp_settings, l);
- e.comp_settings_len = l;
- l += i;
- break;
-
- default:
- ebml_read_skip (s, &l);
- break;
- }
- le -= l + il;
- }
-
- if (e.type == 1)
- {
- mp_msg(MSGT_DEMUX, MSGL_WARN,
- MSGTR_MPDEMUX_MKV_TrackEncrypted, track->tnum);
- }
- else if (e.type != 0)
- {
- mp_msg(MSGT_DEMUX, MSGL_WARN,
- MSGTR_MPDEMUX_MKV_UnknownContentEncoding, track->tnum);
- }
-
- if (e.comp_algo != 0 && e.comp_algo != 2)
- {
- mp_msg (MSGT_DEMUX, MSGL_WARN,
- MSGTR_MPDEMUX_MKV_UnknownCompression,
- track->tnum, e.comp_algo);
- }
+ if (e.type == 1) {
+ mp_tmsg(MSGT_DEMUX, MSGL_WARN, "[mkv] Track "
+ "number %u has been encrypted and "
+ "decryption has not yet been\n"
+ "[mkv] implemented. Skipping track.\n",
+ track->tnum);
+ } else if (e.type != 0) {
+ mp_tmsg(MSGT_DEMUX, MSGL_WARN,
+ "[mkv] Unknown content encoding type for "
+ "track %u. Skipping track.\n",
+ track->tnum);
+ } else if (e.comp_algo != 0 && e.comp_algo != 2 && e.comp_algo != 3) {
+ mp_tmsg(MSGT_DEMUX, MSGL_WARN,
+ "[mkv] Track %u has been compressed with "
+ "an unknown/unsupported compression\n"
+ "[mkv] algorithm (%" PRIu64 "). Skipping track.\n",
+ track->tnum, e.comp_algo);
+ }
#if !CONFIG_ZLIB
- else if (e.comp_algo == 0)
- {
- mp_msg (MSGT_DEMUX, MSGL_WARN,
- MSGTR_MPDEMUX_MKV_ZlibCompressionUnsupported,
- track->tnum);
- }
+ else if (e.comp_algo == 0) {
+ mp_tmsg(MSGT_DEMUX, MSGL_WARN,
+ "[mkv] Track %u was compressed with zlib "
+ "but mplayer has not been compiled\n"
+ "[mkv] with support for zlib compression. "
+ "Skipping track.\n",
+ track->tnum);
+ }
#endif
-
- break;
- }
-
- default:
- ebml_read_skip (s, &l);
- break;
- }
- len -= l + il;
- }
- for (i=0; i<n; i++)
- if (e.order <= ce[i].order)
+ int i;
+ for (i = 0; i < n_enc; i++)
+ if (e.order >= ce[i].order)
break;
- ce = realloc (ce, (n+1) *sizeof (*ce));
- memmove (ce+i+1, ce+i, (n-i) * sizeof (*ce));
- memcpy (ce+i, &e, sizeof (e));
- n++;
- break;
- }
-
- default:
- ebml_read_skip (s, &l);
- break;
- }
-
- length -= l + il;
+ ce = talloc_realloc_size(track, ce, (n_enc + 1) * sizeof(*ce));
+ memmove(ce + i + 1, ce + i, (n_enc - i) * sizeof(*ce));
+ memcpy(ce + i, &e, sizeof(e));
}
- track->encodings = ce;
- track->num_encodings = n;
- return len;
-
-err_out:
- demux_mkv_free_encodings(ce, n);
- return 0;
+ track->encodings = ce;
+ track->num_encodings = encodings->n_content_encoding;
}
-static int
-demux_mkv_read_trackaudio (demuxer_t *demuxer, mkv_track_t *track)
+static void parse_trackaudio(struct demuxer *demuxer, struct mkv_track *track,
+ struct ebml_audio *audio)
{
- stream_t *s = demuxer->stream;
- uint64_t len, length, l;
- int il;
-
- track->a_sfreq = 8000.0;
- track->a_channels = 1;
-
- len = length = ebml_read_length (s, &il);
- len += il;
- while (length > 0)
- {
- switch (ebml_read_id (s, &il))
- {
- case MATROSKA_ID_AUDIOSAMPLINGFREQ:
- {
- long double num = ebml_read_float (s, &l);
- if (num == EBML_FLOAT_INVALID)
- return 0;
- track->a_sfreq = num;
- mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Sampling frequency: %f\n",
- track->a_sfreq);
- break;
- }
-
- case MATROSKA_ID_AUDIOBITDEPTH:
- {
- uint64_t num = ebml_read_uint (s, &l);
- if (num == EBML_UINT_INVALID)
- return 0;
- track->a_bps = num;
- mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Bit depth: %u\n",
- track->a_bps);
- break;
- }
-
- case MATROSKA_ID_AUDIOCHANNELS:
- {
- uint64_t num = ebml_read_uint (s, &l);
- if (num == EBML_UINT_INVALID)
- return 0;
- track->a_channels = num;
- mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Channels: %u\n",
- track->a_channels);
- break;
- }
-
- default:
- ebml_read_skip (s, &l);
- break;
- }
- length -= l + il;
+ if (audio->n_sampling_frequency) {
+ track->a_sfreq = audio->sampling_frequency;
+ mp_msg(MSGT_DEMUX, MSGL_V,
+ "[mkv] | + Sampling frequency: %f\n", track->a_sfreq);
+ } else
+ track->a_sfreq = 8000;
+ if (audio->n_bit_depth) {
+ track->a_bps = audio->bit_depth;
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Bit depth: %u\n",
+ track->a_bps);
}
- return len;
+ if (audio->n_channels) {
+ track->a_channels = audio->channels;
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Channels: %u\n",
+ track->a_channels);
+ } else
+ track->a_channels = 1;
}
-static int
-demux_mkv_read_trackvideo (demuxer_t *demuxer, mkv_track_t *track)
+static void parse_trackvideo(struct demuxer *demuxer, struct mkv_track *track,
+ struct ebml_video *video)
{
- stream_t *s = demuxer->stream;
- uint64_t len, length, l;
- int il;
-
- len = length = ebml_read_length (s, &il);
- len += il;
- while (length > 0)
- {
- switch (ebml_read_id (s, &il))
- {
- case MATROSKA_ID_VIDEOFRAMERATE:
- {
- long double num = ebml_read_float (s, &l);
- if (num == EBML_FLOAT_INVALID)
- return 0;
- track->v_frate = num;
- mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Frame rate: %f\n",
- track->v_frate);
- if (track->v_frate > 0)
- track->default_duration = 1 / track->v_frate;
- break;
- }
-
- case MATROSKA_ID_VIDEODISPLAYWIDTH:
- {
- uint64_t num = ebml_read_uint (s, &l);
- if (num == EBML_UINT_INVALID)
- return 0;
- track->v_dwidth = num;
- mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Display width: %u\n",
- track->v_dwidth);
- break;
- }
-
- case MATROSKA_ID_VIDEODISPLAYHEIGHT:
- {
- uint64_t num =