diff options
Diffstat (limited to 'libmpdemux/demux_mkv.c')
-rw-r--r-- | libmpdemux/demux_mkv.c | 4734 |
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 = ebml_read_uint (s, &l); - if (num == EBML_UINT_INVALID) - return 0; - track->v_dheight = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Display height: %u\n", - track->v_dheight); - break; - |