Mercurial > mplayer.hg
changeset 31177:9175a9a22051
cosmetics: Reformat in K&R coding style.
author | diego |
---|---|
date | Thu, 27 May 2010 16:46:47 +0000 |
parents | 04c61b9e94c8 |
children | 986892228d92 |
files | libmpdemux/demux_mkv.c libmpdemux/ebml.c |
diffstat | 2 files changed, 2494 insertions(+), 2683 deletions(-) [+] |
line wrap: on
line diff
--- a/libmpdemux/demux_mkv.c Thu May 27 16:13:53 2010 +0000 +++ b/libmpdemux/demux_mkv.c Thu May 27 16:46:47 2010 +0000 @@ -58,138 +58,136 @@ #include "libavutil/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 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; +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; } mkv_content_encoding_t; -typedef struct mkv_track -{ - int tnum; - char *name; - - char *codec_id; - int ms_compat; - char *language; - - int type; - - uint32_t v_width, v_height, v_dwidth, v_dheight; - float v_frate; - - uint32_t a_formattag; - uint32_t a_channels, a_bps; - float a_sfreq; - - float default_duration; - - int default_track; - - void *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 */ - - /** 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; +typedef struct mkv_track { + int tnum; + char *name; + + char *codec_id; + int ms_compat; + char *language; + + int type; + + uint32_t v_width, v_height, v_dwidth, v_dheight; + float v_frate; + + uint32_t a_formattag; + uint32_t a_channels, a_bps; + float a_sfreq; + + float default_duration; + + int default_track; + + void *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 */ + + /** 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; } 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; - - float duration, last_pts; - uint64_t last_filepos; - - mkv_track_t **tracks; - int num_tracks; - - uint64_t tc_scale, cluster_tc, first_tc; - int has_first_tc; - - uint64_t cluster_size; - uint64_t blockgroup_size; - - mkv_index_t *indexes; - int num_indexes; - - off_t *parsed_cues; - int parsed_cues_num; - off_t *parsed_seekhead; - int parsed_seekhead_num; - - uint64_t *cluster_positions; - int num_cluster_pos; - - 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]; +typedef struct mkv_demuxer { + off_t segment_start; + + float duration, last_pts; + uint64_t last_filepos; + + mkv_track_t **tracks; + int num_tracks; + + uint64_t tc_scale, cluster_tc, first_tc; + int has_first_tc; + + uint64_t cluster_size; + uint64_t blockgroup_size; + + mkv_index_t *indexes; + int num_indexes; + + off_t *parsed_cues; + int parsed_cues_num; + off_t *parsed_seekhead; + int parsed_seekhead_num; + + uint64_t *cluster_positions; + int num_cluster_pos; + + 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]; } mkv_demuxer_t; #define REALHEADER_SIZE 16 @@ -208,59 +206,62 @@ * \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 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 mkv_track_t * -demux_mkv_find_track_by_num (mkv_demuxer_t *d, int n, int type) +static mkv_track_t *demux_mkv_find_track_by_num(mkv_demuxer_t *d, int n, + int type) { - int i, id; - - 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; + int i, id; + + 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 position) { - 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; + 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; } #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,166 +272,154 @@ * * \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 int 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; - - *dest = src; - if (track->num_encodings <= 0) - return 0; - - for (i=0; i<track->num_encodings; i++) - { - if (!(track->encodings[i].scope & type)) - continue; + int i, result; + int modified = 0; + + *dest = src; + if (track->num_encodings <= 0) + return 0; + + for (i = 0; i < track->num_encodings; i++) { + if (!(track->encodings[i].scope & type)) + continue; #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; + 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; } - 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; + + 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); } #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; + 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; } - 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; } } - return modified; + return modified; } -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)) + 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: { - case MATROSKA_ID_TIMECODESCALE: - { - uint64_t num = ebml_read_uint (s, &l); + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - return 1; + return 1; tc_scale = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + timecode scale: %"PRIu64"\n", - tc_scale); + 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); + { + long double num = ebml_read_float(s, &l); if (num == EBML_FLOAT_INVALID) - return 1; + return 1; duration = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3Lfs\n", - duration * tc_scale / 1000000000.0); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3Lfs\n", + duration * tc_scale / 1000000000.0); break; - } + } default: - ebml_read_skip (s, &l); - break; + ebml_read_skip(s, &l); + break; } - length -= l + il; + length -= l + il; } - mkv_d->tc_scale = tc_scale; - mkv_d->duration = duration * tc_scale / 1000000000.0; - return 0; + mkv_d->tc_scale = tc_scale; + mkv_d->duration = duration * tc_scale / 1000000000.0; + return 0; } /** @@ -438,2080 +427,1961 @@ * \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) +static void demux_mkv_free_encodings(mkv_content_encoding_t *encodings, + int numencodings) { - while (numencodings-- > 0) - free(encodings[numencodings].comp_settings); - free(encodings); + while (numencodings-- > 0) + free(encodings[numencodings].comp_settings); + free(encodings); } -static int -demux_mkv_read_trackencodings (demuxer_t *demuxer, mkv_track_t *track) +static int demux_mkv_read_trackencodings(demuxer_t *demuxer, + mkv_track_t *track) { - 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)) + 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: { - case MATROSKA_ID_CONTENTENCODING: - { uint64_t len; int i; - memset (&e, 0, sizeof (e)); + memset(&e, 0, sizeof(e)); e.scope = 1; - len = ebml_read_length (s, &i); + len = ebml_read_length(s, &i); l = len + i; - while (len > 0) - { + 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); + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_CONTENTENCODINGORDER: + num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - goto err_out; + goto err_out; e.order = num; break; - case MATROSKA_ID_CONTENTENCODINGSCOPE: - num = ebml_read_uint (s, &l); + case MATROSKA_ID_CONTENTENCODINGSCOPE: + num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - goto err_out; + goto err_out; e.scope = num; break; - case MATROSKA_ID_CONTENTENCODINGTYPE: - num = ebml_read_uint (s, &l); + case MATROSKA_ID_CONTENTENCODINGTYPE: + num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - goto err_out; + 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) + 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; + 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; } - - 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); - } + 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 !CONFIG_ZLIB - else if (e.comp_algo == 0) - { - mp_msg (MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_ZlibCompressionUnsupported, - track->tnum); - } -#endif - - break; + else if (e.comp_algo == 0) { + mp_msg(MSGT_DEMUX, MSGL_WARN, + MSGTR_MPDEMUX_MKV_ZlibCompressionUnsupported, + track->tnum); } - - default: - ebml_read_skip (s, &l); +#endif + break; - } + } + + default: + ebml_read_skip(s, &l); + break; + } len -= l + il; - } - for (i=0; i<n; 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)); + } + for (i = 0; i < n; 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; + ebml_read_skip(s, &l); + break; } - length -= l + il; + length -= l + il; } - track->encodings = ce; - track->num_encodings = n; - return len; + track->encodings = ce; + track->num_encodings = n; + return len; err_out: - demux_mkv_free_encodings(ce, n); - return 0; + demux_mkv_free_encodings(ce, n); + return 0; } -static int -demux_mkv_read_trackaudio (demuxer_t *demuxer, mkv_track_t *track) +static int demux_mkv_read_trackaudio(demuxer_t *demuxer, mkv_track_t *track) { - 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)) + 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: { - case MATROSKA_ID_AUDIOSAMPLINGFREQ: - { - long double num = ebml_read_float (s, &l); + long double num = ebml_read_float(s, &l); if (num == EBML_FLOAT_INVALID) - return 0; + return 0; track->a_sfreq = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Sampling frequency: %f\n", - track->a_sfreq); + 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); + { + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - return 0; + return 0; track->a_bps = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Bit depth: %u\n", - track->a_bps); + 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); + { + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - return 0; + return 0; track->a_channels = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Channels: %u\n", - track->a_channels); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Channels: %u\n", + track->a_channels); break; - } + } default: - ebml_read_skip (s, &l); + ebml_read_skip(s, &l); break; } - length -= l + il; + length -= l + il; } - return len; + return len; } -static int -demux_mkv_read_trackvideo (demuxer_t *demuxer, mkv_track_t *track) +static int demux_mkv_read_trackvideo(demuxer_t *demuxer, mkv_track_t *track) { - 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)) - { + 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); + { + long double num = ebml_read_float(s, &l); if (num == EBML_FLOAT_INVALID) - return 0; + return 0; track->v_frate = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Frame rate: %f\n", - track->v_frate); + 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; + track->default_duration = 1 / track->v_frate; break; - } + } case MATROSKA_ID_VIDEODISPLAYWIDTH: - { - uint64_t num = ebml_read_uint (s, &l); + { + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - return 0; + return 0; track->v_dwidth = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Display width: %u\n", - track->v_dwidth); + 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); + { + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - return 0; + return 0; track->v_dheight = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Display height: %u\n", - track->v_dheight); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Display height: %u\n", + track->v_dheight); break; - } + } case MATROSKA_ID_VIDEOPIXELWIDTH: - { - uint64_t num = ebml_read_uint (s, &l); + { + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - return 0; + return 0; track->v_width = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel width: %u\n", - track->v_width); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel width: %u\n", + track->v_width); break; - } + } case MATROSKA_ID_VIDEOPIXELHEIGHT: - { - uint64_t num = ebml_read_uint (s, &l); + { + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - return 0; + return 0; track->v_height = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel height: %u\n", - track->v_height); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel height: %u\n", + track->v_height); break; - } + } default: - ebml_read_skip (s, &l); + ebml_read_skip(s, &l); break; } - length -= l + il; + length -= l + il; } - return len; + return len; } /** * \brief free any data associated with given track * \param track track of which to free data */ -static void -demux_mkv_free_trackentry(mkv_track_t *track) { - free (track->name); - free (track->codec_id); - free (track->language); - free (track->private_data); - free (track->audio_buf); - free (track->audio_timestamp); - demux_mkv_free_encodings(track->encodings, track->num_encodings); - free(track); +static void demux_mkv_free_trackentry(mkv_track_t *track) +{ + free(track->name); + free(track->codec_id); + free(track->language); + free(track->private_data); + free(track->audio_buf); + free(track->audio_timestamp); + demux_mkv_free_encodings(track->encodings, track->num_encodings); + free(track); } -static int -demux_mkv_read_trackentry (demuxer_t *demuxer) +static int demux_mkv_read_trackentry(demuxer_t *demuxer) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - stream_t *s = demuxer->stream; - mkv_track_t *track; - uint64_t len, length, l; - int il; - - track = calloc (1, sizeof (*track)); - /* set default values */ - track->default_track = 1; - track->name = 0; - track->language = strdup("eng"); - - len = length = ebml_read_length (s, &il); - len += il; - while (length > 0) - { - switch (ebml_read_id (s, &il)) + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + stream_t *s = demuxer->stream; + mkv_track_t *track; + uint64_t len, length, l; + int il; + + track = calloc(1, sizeof(*track)); + /* set default values */ + track->default_track = 1; + track->name = 0; + track->language = strdup("eng"); + + len = length = ebml_read_length(s, &il); + len += il; + while (length > 0) { + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_TRACKNUMBER: { - case MATROSKA_ID_TRACKNUMBER: - { - uint64_t num = ebml_read_uint (s, &l); + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - goto err_out; + goto err_out; track->tnum = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Track number: %u\n", - track->tnum); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track number: %u\n", + track->tnum); break; - } + } case MATROSKA_ID_TRACKNAME: - { - track->name = ebml_read_utf8 (s, &l); + track->name = ebml_read_utf8(s, &l); if (track->name == NULL) - goto err_out; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Name: %s\n", - track->name); + goto err_out; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Name: %s\n", + track->name); break; - } case MATROSKA_ID_TRACKTYPE: - { - uint64_t num = ebml_read_uint (s, &l); + { + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - return 0; + return 0; track->type = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Track type: "); - switch (track->type) - { - case MATROSKA_TRACK_AUDIO: - mp_msg (MSGT_DEMUX, MSGL_V, "Audio\n"); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track type: "); + switch (track->type) { + case MATROSKA_TRACK_AUDIO: + mp_msg(MSGT_DEMUX, MSGL_V, "Audio\n"); break; - case MATROSKA_TRACK_VIDEO: - mp_msg (MSGT_DEMUX, MSGL_V, "Video\n"); + case MATROSKA_TRACK_VIDEO: + mp_msg(MSGT_DEMUX, MSGL_V, "Video\n"); break; - case MATROSKA_TRACK_SUBTITLE: - mp_msg (MSGT_DEMUX, MSGL_V, "Subtitle\n"); + case MATROSKA_TRACK_SUBTITLE: + mp_msg(MSGT_DEMUX, MSGL_V, "Subtitle\n"); break; - default: - mp_msg (MSGT_DEMUX, MSGL_V, "unknown\n"); + default: + mp_msg(MSGT_DEMUX, MSGL_V, "unknown\n"); break; } break; - } + } case MATROSKA_ID_TRACKAUDIO: - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Audio track\n"); - l = demux_mkv_read_trackaudio (demuxer, track); - if (l == 0) - goto err_out; - break; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Audio track\n"); + l = demux_mkv_read_trackaudio(demuxer, track); + if (l == 0) + goto err_out; + break; case MATROSKA_ID_TRACKVIDEO: - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Video track\n"); - l = demux_mkv_read_trackvideo (demuxer, track); - if (l == 0) - goto err_out; - break; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Video track\n"); + l = demux_mkv_read_trackvideo(demuxer, track); + if (l == 0) + goto err_out; + break; case MATROSKA_ID_CODECID: - track->codec_id = ebml_read_ascii (s, &l); - if (track->codec_id == NULL) - goto err_out; - if (!strcmp (track->codec_id, MKV_V_MSCOMP) || - !strcmp (track->codec_id, MKV_A_ACM)) - track->ms_compat = 1; - else if (!strcmp (track->codec_id, MKV_S_VOBSUB)) - track->subtitle_type = MATROSKA_SUBTYPE_VOBSUB; - else if (!strcmp (track->codec_id, MKV_S_TEXTSSA) - || !strcmp (track->codec_id, MKV_S_TEXTASS) - || !strcmp (track->codec_id, MKV_S_SSA) - || !strcmp (track->codec_id, MKV_S_ASS)) - { - track->subtitle_type = MATROSKA_SUBTYPE_SSA; + track->codec_id = ebml_read_ascii(s, &l); + if (track->codec_id == NULL) + goto err_out; + if (!strcmp(track->codec_id, MKV_V_MSCOMP) + || !strcmp(track->codec_id, MKV_A_ACM)) + track->ms_compat = 1; + else if (!strcmp(track->codec_id, MKV_S_VOBSUB)) + track->subtitle_type = MATROSKA_SUBTYPE_VOBSUB; + else if (!strcmp(track->codec_id, MKV_S_TEXTSSA) + || !strcmp(track->codec_id, MKV_S_TEXTASS) + || !strcmp(track->codec_id, MKV_S_SSA) + || !strcmp(track->codec_id, MKV_S_ASS)) { + track->subtitle_type = MATROSKA_SUBTYPE_SSA; + } else if (!strcmp(track->codec_id, MKV_S_TEXTASCII)) + track->subtitle_type = MATROSKA_SUBTYPE_TEXT; + if (!strcmp(track->codec_id, MKV_S_TEXTUTF8)) { + track->subtitle_type = MATROSKA_SUBTYPE_TEXT; } - else if (!strcmp (track->codec_id, MKV_S_TEXTASCII)) - track->subtitle_type = MATROSKA_SUBTYPE_TEXT; - if (!strcmp (track->codec_id, MKV_S_TEXTUTF8)) - { - track->subtitle_type = MATROSKA_SUBTYPE_TEXT; - } - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Codec ID: %s\n", - track->codec_id); - break; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Codec ID: %s\n", + track->codec_id); + break; case MATROSKA_ID_CODECPRIVATE: - { + { int x; - uint64_t num = ebml_read_length (s, &x); - // audit: cheap guard against overflows later.. - if (num > SIZE_MAX - 1000) return 0; + uint64_t num = ebml_read_length(s, &x); + // audit: cheap guard against overflows later.. + if (num > SIZE_MAX - 1000) + return 0; l = x + num; - track->private_data = malloc (num + AV_LZO_INPUT_PADDING); + track->private_data = malloc(num + AV_LZO_INPUT_PADDING); if (stream_read(s, track->private_data, num) != (int) num) - goto err_out; + goto err_out; track->private_size = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + CodecPrivate, length " - "%u\n", track->private_size); + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] | + CodecPrivate, length " "%u\n", + track->private_size); break; - } + } case MATROSKA_ID_TRACKLANGUAGE: - free(track->language); - track->language = ebml_read_utf8 (s, &l); - if (track->language == NULL) - goto err_out; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Language: %s\n", - track->language); - break; + free(track->language); + track->language = ebml_read_utf8(s, &l); + if (track->language == NULL) + goto err_out; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Language: %s\n", + track->language); + break; case MATROSKA_ID_TRACKFLAGDEFAULT: - { - uint64_t num = ebml_read_uint (s, &l); + { + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - goto err_out; + goto err_out; track->default_track = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Default flag: %u\n", - track->default_track); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Default flag: %u\n", + track->default_track); break; - } + } case MATROSKA_ID_TRACKDEFAULTDURATION: - { - uint64_t num = ebml_read_uint (s, &l); + { + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - goto err_out; + goto err_out; if (num == 0) - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Default duration: 0"); - else - { + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] | + Default duration: 0"); + else { track->v_frate = 1000000000.0 / num; track->default_duration = num / 1000000000.0; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + Default duration: " - "%.3fms ( = %.3f fps)\n",num/1000000.0,track->v_frate); - } + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] | + Default duration: " + "%.3fms ( = %.3f fps)\n", num / 1000000.0, + track->v_frate); + } break; - } + } case MATROSKA_ID_TRACKENCODINGS: - l = demux_mkv_read_trackencodings (demuxer, track); - if (l == 0) - goto err_out; - break; + l = demux_mkv_read_trackencodings(demuxer, track); + if (l == 0) + goto err_out; + break; default: - ebml_read_skip (s, &l); - break; + ebml_read_skip(s, &l); + break; } - length -= l + il; + length -= l + il; } - mkv_d->tracks[mkv_d->num_tracks++] = track; - return len; + mkv_d->tracks[mkv_d->num_tracks++] = track; + return len; err_out: - demux_mkv_free_trackentry(track); - return 0; + demux_mkv_free_trackentry(track); + return 0; } -static int -demux_mkv_read_tracks (demuxer_t *demuxer) +static int demux_mkv_read_tracks(demuxer_t *demuxer) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - stream_t *s = demuxer->stream; - uint64_t length, l; - int il; - - mkv_d->tracks = malloc (sizeof (*mkv_d->tracks)); - mkv_d->num_tracks = 0; - - length = ebml_read_length (s, NULL); - while (length > 0) - { - switch (ebml_read_id (s, &il)) - { + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + stream_t *s = demuxer->stream; + uint64_t length, l; + int il; + + mkv_d->tracks = malloc(sizeof(*mkv_d->tracks)); + mkv_d->num_tracks = 0; + + length = ebml_read_length(s, NULL); + while (length > 0) { + switch (ebml_read_id(s, &il)) { case MATROSKA_ID_TRACKENTRY: - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + a track...\n"); - mkv_d->tracks = realloc (mkv_d->tracks, - (mkv_d->num_tracks+1) - *sizeof (*mkv_d->tracks)); - l = demux_mkv_read_trackentry (demuxer); - if (l == 0) - return 1; - break; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + a track...\n"); + mkv_d->tracks = realloc(mkv_d->tracks, (mkv_d->num_tracks + 1) + * sizeof(*mkv_d->tracks)); + l = demux_mkv_read_trackentry(demuxer); + if (l == 0) + return 1; + break; default: - ebml_read_skip (s, &l); + ebml_read_skip(s, &l); break; } - length -= l + il; + length -= l + il; } - return 0; + return 0; } -static int -demux_mkv_read_cues (demuxer_t *demuxer) +static int demux_mkv_read_cues(demuxer_t *demuxer) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - stream_t *s = demuxer->stream; - uint64_t length, l, time, track, pos; - off_t off; - int i, il; - - if (index_mode == 0) { - ebml_read_skip (s, NULL); - return 0; - } - off = stream_tell (s); - for (i=0; i<mkv_d->parsed_cues_num; i++) - if (mkv_d->parsed_cues[i] == off) - { - ebml_read_skip (s, NULL); + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + stream_t *s = demuxer->stream; + uint64_t length, l, time, track, pos; + off_t off; + int i, il; + + if (index_mode == 0) { + ebml_read_skip(s, NULL); return 0; - } - mkv_d->parsed_cues = realloc (mkv_d->parsed_cues, - (mkv_d->parsed_cues_num+1) - * sizeof (off_t)); - mkv_d->parsed_cues[mkv_d->parsed_cues_num++] = off; - - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing cues ] -----------\n"); - length = ebml_read_length (s, NULL); - - while (length > 0) - { - time = track = pos = EBML_UINT_INVALID; - - switch (ebml_read_id (s, &il)) + } + off = stream_tell(s); + for (i = 0; i < mkv_d->parsed_cues_num; i++) + if (mkv_d->parsed_cues[i] == off) { + ebml_read_skip(s, NULL); + return 0; + } + mkv_d->parsed_cues = realloc(mkv_d->parsed_cues, + (mkv_d->parsed_cues_num + 1) * sizeof(off_t)); + mkv_d->parsed_cues[mkv_d->parsed_cues_num++] = off; + + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing cues ] -----------\n"); + length = ebml_read_length(s, NULL); + + while (length > 0) { + time = track = pos = EBML_UINT_INVALID; + + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_POINTENTRY: { - case MATROSKA_ID_POINTENTRY: - { uint64_t len; - len = ebml_read_length (s, &i); + len = ebml_read_length(s, &i); l = len + i; - while (len > 0) - { + while (len > 0) { uint64_t l; int il; - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_CUETIME: - time = ebml_read_uint (s, &l); + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_CUETIME: + time = ebml_read_uint(s, &l); break; - case MATROSKA_ID_CUETRACKPOSITION: - { - 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_CUETRACK: - track = ebml_read_uint (s, &l); - break; - - case MATROSKA_ID_CUECLUSTERPOSITION: - pos = ebml_read_uint (s, &l); - break; - - default: - ebml_read_skip (s, &l); - break; - } - le -= l + il; + case MATROSKA_ID_CUETRACKPOSITION: + { + 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_CUETRACK: + track = ebml_read_uint(s, &l); + break; + + case MATROSKA_ID_CUECLUSTERPOSITION: + pos = ebml_read_uint(s, &l); + break; + + default: + ebml_read_skip(s, &l); + break; } - break; + le -= l + il; } - - default: - ebml_read_skip (s, &l); break; - } + } + + default: + ebml_read_skip(s, &l); + break; + } len -= l + il; - } + } break; - } + } default: - ebml_read_skip (s, &l); - break; + ebml_read_skip(s, &l); + break; } - length -= l + il; - - if (time != EBML_UINT_INVALID && track != EBML_UINT_INVALID - && pos != EBML_UINT_INVALID) - { - grow_array(&mkv_d->indexes, mkv_d->num_indexes, sizeof(mkv_index_t)); - if (!mkv_d->indexes) { - mkv_d->num_indexes = 0; - break; - } - mkv_d->indexes[mkv_d->num_indexes].tnum = track; - mkv_d->indexes[mkv_d->num_indexes].timecode = time; - mkv_d->indexes[mkv_d->num_indexes].filepos =mkv_d->segment_start+pos; - mp_msg (MSGT_DEMUX, MSGL_DBG2, "[mkv] |+ found cue point " - "for track %"PRIu64": timecode %"PRIu64", filepos: %"PRIu64"\n", - track, time, mkv_d->segment_start + pos); - mkv_d->num_indexes++; + length -= l + il; + + if (time != EBML_UINT_INVALID && track != EBML_UINT_INVALID + && pos != EBML_UINT_INVALID) { + grow_array(&mkv_d->indexes, mkv_d->num_indexes, + sizeof(mkv_index_t)); + if (!mkv_d->indexes) { + mkv_d->num_indexes = 0; + break; + } + mkv_d->indexes[mkv_d->num_indexes].tnum = track; + mkv_d->indexes[mkv_d->num_indexes].timecode = time; + mkv_d->indexes[mkv_d->num_indexes].filepos = mkv_d->segment_start + + pos; + mp_msg(MSGT_DEMUX, MSGL_DBG2, + "[mkv] |+ found cue point " "for track %" PRIu64 + ": timecode %" PRIu64 ", filepos: %" PRIu64 "\n", track, + time, mkv_d->segment_start + pos); + mkv_d->num_indexes++; } } - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing cues ] -----------\n"); - return 0; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing cues ] -----------\n"); + return 0; } -static int -demux_mkv_read_chapters (demuxer_t *demuxer) +static int demux_mkv_read_chapters(demuxer_t *demuxer) { - stream_t *s = demuxer->stream; - uint64_t length, l; - int il; - - if (demuxer->chapters) - { - ebml_read_skip (s, NULL); - return 0; + stream_t *s = demuxer->stream; + uint64_t length, l; + int il; + + if (demuxer->chapters) { + ebml_read_skip(s, NULL); + return 0; } - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing chapters ] ---------\n"); - length = ebml_read_length (s, NULL); - - while (length > 0) - { - switch (ebml_read_id (s, &il)) + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing chapters ] ---------\n"); + length = ebml_read_length(s, NULL); + + while (length > 0) { + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_EDITIONENTRY: { - case MATROSKA_ID_EDITIONENTRY: - { uint64_t len; int i; - len = ebml_read_length (s, &i); + len = ebml_read_length(s, &i); l = len + i; - while (len > 0) - { + while (len > 0) { uint64_t l; int il; - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_CHAPTERATOM: - { - uint64_t len, start=0, end=0; - char* name = 0; - int i; - int cid; - - len = ebml_read_length (s, &i); - l = len + i; - - while (len > 0) + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_CHAPTERATOM: + { + uint64_t len, start = 0, end = 0; + char *name = 0; + int i; + int cid; + + len = ebml_read_length(s, &i); + l = len + i; + + while (len > 0) { + uint64_t l; + int il; + + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_CHAPTERTIMESTART: + start = ebml_read_uint(s, &l) / 1000000; + break; + + case MATROSKA_ID_CHAPTERTIMEEND: + end = ebml_read_uint(s, &l) / 1000000; + break; + + case MATROSKA_ID_CHAPTERDISPLAY: { - uint64_t l; - int il; - - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_CHAPTERTIMESTART: - start = ebml_read_uint (s, &l) / 1000000; - break; - - case MATROSKA_ID_CHAPTERTIMEEND: - end = ebml_read_uint (s, &l) / 1000000; - break; - - case MATROSKA_ID_CHAPTERDISPLAY: - { - uint64_t len; - int i; - - len = ebml_read_length (s, &i); - l = len + i; - while (len > 0) - { - uint64_t l; - int il; - - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_CHAPSTRING: - name = ebml_read_utf8 (s, &l); - break; - default: - ebml_read_skip (s, &l); - break; - } - len -= l + il; - } - } - break; - - default: - ebml_read_skip (s, &l); - break; + uint64_t len; + int i; + + len = ebml_read_length(s, &i); + l = len + i; + while (len > 0) { + uint64_t l; + int il; + + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_CHAPSTRING: + name = ebml_read_utf8(s, &l); + break; + default: + ebml_read_skip(s, &l); + break; + } + len -= l + il; } - len -= l + il; } - - if (!name) + break; + + default: + ebml_read_skip(s, &l); + break; + } + len -= l + il; + } + + if (!name) name = strdup("(unnamed)"); - cid = demuxer_add_chapter(demuxer, name, start, end); - - mp_msg(MSGT_DEMUX, MSGL_V, - "[mkv] Chapter %u from %02d:%02d:%02d." - "%03d to %02d:%02d:%02d.%03d, %s\n", - cid, - (int) (start / 60 / 60 / 1000), - (int) ((start / 60 / 1000) % 60), - (int) ((start / 1000) % 60), - (int) (start % 1000), - (int) (end / 60 / 60 / 1000), - (int) ((end / 60 / 1000) % 60), - (int) ((end / 1000) % 60), - (int) (end % 1000), name); - - free(name); - break; + cid = demuxer_add_chapter(demuxer, name, start, end); + + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] Chapter %u from %02d:%02d:%02d." + "%03d to %02d:%02d:%02d.%03d, %s\n", cid, + (int) (start / 60 / 60 / 1000), + (int) ((start / 60 / 1000) % 60), + (int) ((start / 1000) % 60), + (int) (start % 1000), + (int) (end / 60 / 60 / 1000), + (int) ((end / 60 / 1000) % 60), + (int) ((end / 1000) % 60), + (int) (end % 1000), name); + + free(name); + break; + } + + default: + ebml_read_skip(s, &l); + break; + } + len -= l + il; + } + break; + } + + default: + ebml_read_skip(s, &l); + break; + } + + length -= l + il; + } + + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] \\---- [ parsing chapters ] ---------\n"); + return 0; +} + +static int demux_mkv_read_tags(demuxer_t *demuxer) +{ + ebml_read_skip(demuxer->stream, NULL); + return 0; +} + +static int demux_mkv_read_attachments(demuxer_t *demuxer) +{ + stream_t *s = demuxer->stream; + uint64_t length, l; + int il; + + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] /---- [ parsing attachments ] ---------\n"); + length = ebml_read_length(s, NULL); + + while (length > 0) { + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_ATTACHEDFILE: + { + uint64_t len; + int i; + char *name = NULL; + char *mime = NULL; + char *data = NULL; + int data_size = 0; + + len = ebml_read_length(s, &i); + l = len + i; + + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + an attachment...\n"); + + while (len > 0) { + uint64_t l; + int il; + + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_FILENAME: + name = ebml_read_utf8(s, &l); + if (name == NULL) + return 0; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + FileName: %s\n", + name); + break; + + case MATROSKA_ID_FILEMIMETYPE: + mime = ebml_read_ascii(s, &l); + if (mime == NULL) + return 0; + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] | + FileMimeType: %s\n", mime); + break; + + case MATROSKA_ID_FILEDATA: + { + int x; + uint64_t num = ebml_read_length(s, &x); + l = x + num; + free(data); + data = malloc(num); + if (stream_read(s, data, num) != (int) num) { + free(data); + return 0; } - - default: - ebml_read_skip (s, &l); + data_size = num; + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] | + FileData, length " "%u\n", + data_size); + break; + } + + default: + ebml_read_skip(s, &l); break; - } + } len -= l + il; - } + } + + demuxer_add_attachment(demuxer, name, mime, data, data_size); + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] Attachment: %s, %s, %u bytes\n", name, mime, + data_size); break; - } + } default: - ebml_read_skip (s, &l); - break; + ebml_read_skip(s, &l); + break; } - - length -= l + il; + length -= l + il; } - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing chapters ] ---------\n"); - return 0; + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] \\---- [ parsing attachments ] ---------\n"); + return 0; } -static int -demux_mkv_read_tags (demuxer_t *demuxer) +static int demux_mkv_read_seekhead(demuxer_t *demuxer) { - ebml_read_skip (demuxer->stream, NULL); - return 0; -} - -static int -demux_mkv_read_attachments (demuxer_t *demuxer) -{ - stream_t *s = demuxer->stream; - uint64_t length, l; - int il; - - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing attachments ] ---------\n"); - length = ebml_read_length (s, NULL); - - while (length > 0) - { - switch (ebml_read_id (s, &il)) + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + stream_t *s = demuxer->stream; + uint64_t length, l, seek_pos, saved_pos, num; + uint32_t seek_id; + int i, il, res = 0; + off_t off; + + off = stream_tell(s); + for (i = 0; i < mkv_d->parsed_seekhead_num; i++) + if (mkv_d->parsed_seekhead[i] == off) { + ebml_read_skip(s, NULL); + return 0; + } + mkv_d->parsed_seekhead = realloc(mkv_d->parsed_seekhead, + (mkv_d->parsed_seekhead_num + 1) + * sizeof(off_t)); + mkv_d->parsed_seekhead[mkv_d->parsed_seekhead_num++] = off; + + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] /---- [ parsing seek head ] ---------\n"); + length = ebml_read_length(s, NULL); + /* off now holds the position of the next element after the seek head. */ + off = stream_tell(s) + length; + while (length > 0 && !res) { + + seek_id = 0; + seek_pos = EBML_UINT_INVALID; + + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_SEEKENTRY: { - case MATROSKA_ID_ATTACHEDFILE: - { - uint64_t len; - int i; - char* name = NULL; - char* mime = NULL; - char* data = NULL; - int data_size = 0; - - len = ebml_read_length (s, &i); - l = len + i; - - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + an attachment...\n"); - - while (len > 0) - { - uint64_t l; - int il; - - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_FILENAME: - name = ebml_read_utf8 (s, &l); - if (name == NULL) - return 0; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + FileName: %s\n", - name); - break; - - case MATROSKA_ID_FILEMIMETYPE: - mime = ebml_read_ascii (s, &l); - if (mime == NULL) - return 0; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + FileMimeType: %s\n", - mime); - break; - - case MATROSKA_ID_FILEDATA: - { - int x; - uint64_t num = ebml_read_length (s, &x); - l = x + num; - free(data); - data = malloc (num); - if (stream_read(s, data, num) != (int) num) - { - free(data); - return 0; - } - data_size = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + FileData, length " - "%u\n", data_size); - break; - } - - default: - ebml_read_skip (s, &l); - break; - } - len -= l + il; + uint64_t len; + + len = ebml_read_length(s, &i); + l = len + i; + + while (len > 0) { + uint64_t l; + int il; + + switch (ebml_read_id(s, &il)) { + case MATROSKA_ID_SEEKID: + num = ebml_read_uint(s, &l); + if (num != EBML_UINT_INVALID) + seek_id = num; + break; + + case MATROSKA_ID_SEEKPOSITION: + seek_pos = ebml_read_uint(s, &l); + break; + + default: + ebml_read_skip(s, &l); + break; } - - demuxer_add_attachment(demuxer, name, mime, data, data_size); - mp_msg(MSGT_DEMUX, MSGL_V, - "[mkv] Attachment: %s, %s, %u bytes\n", - name, mime, data_size); - break; + len -= l + il; } - default: - ebml_read_skip (s, &l); + break; + } + + default: + ebml_read_skip(s, &l); break; } - length -= l + il; + length -= l + il; + + if (seek_id == 0 || seek_id == MATROSKA_ID_CLUSTER + || seek_pos == EBML_UINT_INVALID + || ((mkv_d->segment_start + seek_pos) >= + (uint64_t) demuxer->movi_end)) + continue; + + saved_pos = stream_tell(s); + if (!stream_seek(s, mkv_d->segment_start + seek_pos)) + res = 1; + else { + if (ebml_read_id(s, &il) != seek_id) + res = 1; + else + switch (seek_id) { + case MATROSKA_ID_CUES: + if (demux_mkv_read_cues(demuxer)) + res = 1; + break; + + case MATROSKA_ID_TAGS: + if (demux_mkv_read_tags(demuxer)) + res = 1; + break; + + case MATROSKA_ID_SEEKHEAD: + if (demux_mkv_read_seekhead(demuxer)) + res = 1; + break; + + case MATROSKA_ID_CHAPTERS: + if (demux_mkv_read_chapters(demuxer)) + res = 1; + break; + } + } + + stream_seek(s, saved_pos); } - - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing attachments ] ---------\n"); - return 0; + if (res) { + /* If there was an error then try to skip this seek head. */ + if (stream_seek(s, off)) + res = 0; + } else if (length > 0) + stream_seek(s, stream_tell(s) + length); + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] \\---- [ parsing seek head ] ---------\n"); + return res; } -static int -demux_mkv_read_seekhead (demuxer_t *demuxer) +static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track, + int vid); +static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track, + int aid); +static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track, + int sid); + +static void display_create_tracks(demuxer_t *demuxer) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - stream_t *s = demuxer->stream; - uint64_t length, l, seek_pos, saved_pos, num; - uint32_t seek_id; - int i, il, res = 0; - off_t off; - - off = stream_tell (s); - for (i=0; i<mkv_d->parsed_seekhead_num; i++) - if (mkv_d->parsed_seekhead[i] == off) - { - ebml_read_skip (s, NULL); - return 0; - } - mkv_d->parsed_seekhead = realloc (mkv_d->parsed_seekhead, - (mkv_d->parsed_seekhead_num+1) - * sizeof (off_t)); - mkv_d->parsed_seekhead[mkv_d->parsed_seekhead_num++] = off; - - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing seek head ] ---------\n"); - length = ebml_read_length (s, NULL); - /* off now holds the position of the next element after the seek head. */ - off = stream_tell (s) + length; - while (length > 0 && !res) - { - - seek_id = 0; - seek_pos = EBML_UINT_INVALID; - - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_SEEKENTRY: - { - uint64_t len; - - len = ebml_read_length (s, &i); - l = len + i; - - while (len > 0) - { - uint64_t l; - int il; - - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_SEEKID: - num = ebml_read_uint (s, &l); - if (num != EBML_UINT_INVALID) - seek_id = num; - break; - - case MATROSKA_ID_SEEKPOSITION: - seek_pos = ebml_read_uint (s, &l); - break; - - default: - ebml_read_skip (s, &l); - break; - } - len -= l + il; - } - + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + int i, vid = 0, aid = 0, sid = 0; + + for (i = 0; i < mkv_d->num_tracks; i++) { + char *type = "unknown", str[32]; + *str = '\0'; + switch (mkv_d->tracks[i]->type) { + case MATROSKA_TRACK_VIDEO: + type = "video"; + demux_mkv_open_video(demuxer, mkv_d->tracks[i], vid); + if (mkv_d->tracks[i]->name) + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VID_%d_NAME=%s\n", vid, + mkv_d->tracks[i]->name); + sprintf(str, "-vid %u", vid++); break; - } - - default: - ebml_read_skip (s, &l); + case MATROSKA_TRACK_AUDIO: + type = "audio"; + demux_mkv_open_audio(demuxer, mkv_d->tracks[i], aid); + if (mkv_d->tracks[i]->name) + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_NAME=%s\n", aid, + mkv_d->tracks[i]->name); + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", aid, + mkv_d->tracks[i]->language); + sprintf(str, "-aid %u, -alang %.5s", aid++, + mkv_d->tracks[i]->language); + break; + case MATROSKA_TRACK_SUBTITLE: + type = "subtitles"; + demux_mkv_open_sub(demuxer, mkv_d->tracks[i], sid); + if (mkv_d->tracks[i]->name) + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_NAME=%s\n", sid, + mkv_d->tracks[i]->name); + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", sid, + mkv_d->tracks[i]->language); + sprintf(str, "-sid %u, -slang %.5s", sid++, + mkv_d->tracks[i]->language); break; } - length -= l + il; - - if (seek_id == 0 || seek_id == MATROSKA_ID_CLUSTER - || seek_pos == EBML_UINT_INVALID || - ((mkv_d->segment_start + seek_pos) >= (uint64_t)demuxer->movi_end)) - continue; - - saved_pos = stream_tell (s); - if (!stream_seek (s, mkv_d->segment_start + seek_pos)) - res = 1; - else - { - if (ebml_read_id (s, &il) != seek_id) - res = 1; - else - switch (seek_id) - { - case MATROSKA_ID_CUES: - if (demux_mkv_read_cues (demuxer)) - res = 1; - break; - - case MATROSKA_ID_TAGS: - if (demux_mkv_read_tags (demuxer)) - res = 1; - break; - - case MATROSKA_ID_SEEKHEAD: - if (demux_mkv_read_seekhead (demuxer)) - res = 1; - break; - - case MATROSKA_ID_CHAPTERS: - if (demux_mkv_read_chapters (demuxer)) - res = 1; - break; - } - } - - stream_seek (s, saved_pos); - } - if (res) - { - /* If there was an error then try to skip this seek head. */ - if (stream_seek (s, off)) - res = 0; - } - else - if (length > 0) - stream_seek (s, stream_tell (s) + length); - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing seek head ] ---------\n"); - return res; -} - -static int -demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track, int vid); -static int -demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid); -static int -demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track, int sid); - -static void -display_create_tracks (demuxer_t *demuxer) -{ - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *)demuxer->priv; - int i, vid=0, aid=0, sid=0; - - for (i=0; i<mkv_d->num_tracks; i++) - { - char *type = "unknown", str[32]; - *str = '\0'; - switch (mkv_d->tracks[i]->type) - { - case MATROSKA_TRACK_VIDEO: - type = "video"; - demux_mkv_open_video(demuxer, mkv_d->tracks[i], vid); - if (mkv_d->tracks[i]->name) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VID_%d_NAME=%s\n", vid, mkv_d->tracks[i]->name); - sprintf (str, "-vid %u", vid++); - break; - case MATROSKA_TRACK_AUDIO: - type = "audio"; - demux_mkv_open_audio(demuxer, mkv_d->tracks[i], aid); - if (mkv_d->tracks[i]->name) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_NAME=%s\n", aid, mkv_d->tracks[i]->name); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", aid, mkv_d->tracks[i]->language); - sprintf (str, "-aid %u, -alang %.5s",aid++,mkv_d->tracks[i]->language); - break; - case MATROSKA_TRACK_SUBTITLE: - type = "subtitles"; - demux_mkv_open_sub(demuxer, mkv_d->tracks[i], sid); - if (mkv_d->tracks[i]->name) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_NAME=%s\n", sid, mkv_d->tracks[i]->name); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", sid, mkv_d->tracks[i]->language); - sprintf (str, "-sid %u, -slang %.5s",sid++,mkv_d->tracks[i]->language); - break; - } - if (mkv_d->tracks[i]->name) - mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_TrackIDName, - mkv_d->tracks[i]->tnum, type, mkv_d->tracks[i]->codec_id, mkv_d->tracks[i]->name, str); - else - mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_TrackID, - mkv_d->tracks[i]->tnum, type, mkv_d->tracks[i]->codec_id, str); + if (mkv_d->tracks[i]->name) + mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_TrackIDName, + mkv_d->tracks[i]->tnum, type, mkv_d->tracks[i]->codec_id, + mkv_d->tracks[i]->name, str); + else + mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_TrackID, + mkv_d->tracks[i]->tnum, type, mkv_d->tracks[i]->codec_id, + str); } } typedef struct { - char *id; - int fourcc; - int extradata; + char *id; + int fourcc; + int extradata; } videocodec_info_t; static const videocodec_info_t vinfo[] = { - { MKV_V_MPEG1, mmioFOURCC('m', 'p', 'g', '1'), 0 }, - { MKV_V_MPEG2, mmioFOURCC('m', 'p', 'g', '2'), 0 }, - { MKV_V_MPEG4_SP, mmioFOURCC('m', 'p', '4', 'v'), 1 }, - { MKV_V_MPEG4_ASP, mmioFOURCC('m', 'p', '4', 'v'), 1 }, - { MKV_V_MPEG4_AP, mmioFOURCC('m', 'p', '4', 'v'), 1 }, - { MKV_V_MPEG4_AVC, mmioFOURCC('a', 'v', 'c', '1'), 1 }, - { MKV_V_THEORA, mmioFOURCC('t', 'h', 'e', 'o'), 1 }, - { NULL, 0, 0 } + {MKV_V_MPEG1, mmioFOURCC('m', 'p', 'g', '1'), 0}, + {MKV_V_MPEG2, mmioFOURCC('m', 'p', 'g', '2'), 0}, + {MKV_V_MPEG4_SP, mmioFOURCC('m', 'p', '4', 'v'), 1}, + {MKV_V_MPEG4_ASP, mmioFOURCC('m', 'p', '4', 'v'), 1}, + {MKV_V_MPEG4_AP, mmioFOURCC('m', 'p', '4', 'v'), 1}, + {MKV_V_MPEG4_AVC, mmioFOURCC('a', 'v', 'c', '1'), 1}, + {MKV_V_THEORA, mmioFOURCC('t', 'h', 'e', 'o'), 1}, + {NULL, 0, 0} }; -static int -demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track, int vid) +static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track, + int vid) { - BITMAPINFOHEADER *bih; - void *ImageDesc = NULL; - sh_video_t *sh_v; - - if (track->ms_compat) /* MS compatibility mode */ - { - BITMAPINFOHEADER *src; - - if (track->private_data == NULL - || track->private_size < sizeof (BITMAPINFOHEADER)) - return 1; - - src = (BITMAPINFOHEADER *) track->private_data; - bih = calloc (1, track->private_size); - bih->biSize = le2me_32 (src->biSize); - bih->biWidth = le2me_32 (src->biWidth); - bih->biHeight = le2me_32 (src->biHeight); - bih->biPlanes = le2me_16 (src->biPlanes); - bih->biBitCount = le2me_16 (src->biBitCount); - bih->biCompression = le2me_32 (src->biCompression); - bih->biSizeImage = le2me_32 (src->biSizeImage); - bih->biXPelsPerMeter = le2me_32 (src->biXPelsPerMeter); - bih->biYPelsPerMeter = le2me_32 (src->biYPelsPerMeter); - bih->biClrUsed = le2me_32 (src->biClrUsed); - bih->biClrImportant = le2me_32 (src->biClrImportant); - memcpy((char *) bih + sizeof (BITMAPINFOHEADER), - (char *) src + sizeof (BITMAPINFOHEADER), - track->private_size - sizeof (BITMAPINFOHEADER)); - - if (track->v_width == 0) - track->v_width = bih->biWidth; - if (track->v_height == 0) - track->v_height = bih->biHeight; - } - else - { - bih = calloc (1, sizeof (BITMAPINFOHEADER)); - bih->biSize = sizeof (BITMAPINFOHEADER); - bih->biWidth = track->v_width; - bih->biHeight = track->v_height; - bih->biBitCount = 24; - bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount/8; - - if (track->private_size >= RVPROPERTIES_SIZE - && (!strcmp (track->codec_id, MKV_V_REALV10) - || !strcmp (track->codec_id, MKV_V_REALV20) - || !strcmp (track->codec_id, MKV_V_REALV30) - || !strcmp (track->codec_id, MKV_V_REALV40))) - { - unsigned char *dst, *src; - uint32_t type2; - unsigned int cnt; - - src = (uint8_t *)track->private_data + RVPROPERTIES_SIZE; - - cnt = track->private_size - RVPROPERTIES_SIZE; - bih = realloc(bih, sizeof (BITMAPINFOHEADER)+8+cnt); - bih->biSize = 48+cnt; - bih->biPlanes = 1; - type2 = AV_RB32(src - 4); - if (type2 == 0x10003000 || type2 == 0x10003001) - bih->biCompression=mmioFOURCC('R','V','1','3'); - else - bih->biCompression=mmioFOURCC('R','V',track->codec_id[9],'0'); - dst = (unsigned char *) (bih + 1); - // copy type1 and type2 info from rv properties - memcpy(dst, src - 8, 8); - stream_read(demuxer->stream, dst+8, cnt); - track->realmedia = 1; + BITMAPINFOHEADER *bih; + void *ImageDesc = NULL; + sh_video_t *sh_v; + + if (track->ms_compat) { /* MS compatibility mode */ + BITMAPINFOHEADER *src; + + if (track->private_data == NULL + || track->private_size < sizeof(BITMAPINFOHEADER)) + return 1; + + src = (BITMAPINFOHEADER *) track->private_data; + bih = calloc(1, track->private_size); + bih->biSize = le2me_32(src->biSize); + bih->biWidth = le2me_32(src->biWidth); + bih->biHeight = le2me_32(src->biHeight); + bih->biPlanes = le2me_16(src->biPlanes); + bih->biBitCount = le2me_16(src->biBitCount); + bih->biCompression = le2me_32(src->biCompression); + bih->biSizeImage = le2me_32(src->biSizeImage); + bih->biXPelsPerMeter = le2me_32(src->biXPelsPerMeter); + bih->biYPelsPerMeter = le2me_32(src->biYPelsPerMeter); + bih->biClrUsed = le2me_32(src->biClrUsed); + bih->biClrImportant = le2me_32(src->biClrImportant); + memcpy((char *) bih + sizeof(BITMAPINFOHEADER), + (char *) src + sizeof(BITMAPINFOHEADER), + track->private_size - sizeof(BITMAPINFOHEADER)); + + if (track->v_width == 0) + track->v_width = bih->biWidth; + if (track->v_height == 0) + track->v_height = bih->biHeight; + } else { + bih = calloc(1, sizeof(BITMAPINFOHEADER)); + bih->biSize = sizeof(BITMAPINFOHEADER); + bih->biWidth = track->v_width; + bih->biHeight = track->v_height; + bih->biBitCount = 24; + bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount / 8; + + if (track->private_size >= RVPROPERTIES_SIZE + && (!strcmp(track->codec_id, MKV_V_REALV10) + || !strcmp(track->codec_id, MKV_V_REALV20) + || !strcmp(track->codec_id, MKV_V_REALV30) + || !strcmp(track->codec_id, MKV_V_REALV40))) { + unsigned char *dst, *src; + uint32_t type2; + unsigned int cnt; + + src = (uint8_t *) track->private_data + RVPROPERTIES_SIZE; + + cnt = track->private_size - RVPROPERTIES_SIZE; + bih = realloc(bih, sizeof(BITMAPINFOHEADER) + 8 + cnt); + bih->biSize = 48 + cnt; + bih->biPlanes = 1; + type2 = AV_RB32(src - 4); + if (type2 == 0x10003000 || type2 == 0x10003001) + bih->biCompression = mmioFOURCC('R', 'V', '1', '3'); + else + bih->biCompression = + mmioFOURCC('R', 'V', track->codec_id[9], '0'); + dst = (unsigned char *) (bih + 1); + // copy type1 and type2 info from rv properties + memcpy(dst, src - 8, 8); + stream_read(demuxer->stream, dst + 8, cnt); + track->realmedia = 1; #ifdef CONFIG_QTX_CODECS - } - else if (track->private_size >= sizeof (ImageDescription) - && !strcmp(track->codec_id, MKV_V_QUICKTIME)) - { - ImageDescriptionPtr idesc; - - idesc = (ImageDescriptionPtr) track->private_data; - idesc->idSize = be2me_32 (idesc->idSize); - idesc->cType = be2me_32 (idesc->cType); - idesc->version = be2me_16 (idesc->version); - idesc->revisionLevel = be2me_16 (idesc->revisionLevel); - idesc->vendor = be2me_32 (idesc->vendor); - idesc->temporalQuality = be2me_32 (idesc->temporalQuality); - idesc->spatialQuality = be2me_32 (idesc->spatialQuality); - idesc->width = be2me_16 (idesc->width); - idesc->height = be2me_16 (idesc->height); - idesc->hRes = be2me_32 (idesc->hRes); - idesc->vRes = be2me_32 (idesc->vRes); - idesc->dataSize = be2me_32 (idesc->dataSize); - idesc->frameCount = be2me_16 (idesc->frameCount); - idesc->depth = be2me_16 (idesc->depth); - idesc->clutID = be2me_16 (idesc->clutID); - bih->biPlanes = 1; - bih->biCompression = idesc->cType; - ImageDesc = idesc; -#endif /* CONFIG_QTX_CODECS */ - - } - else - { - const videocodec_info_t *vi = vinfo; - while (vi->id && strcmp(vi->id, track->codec_id)) vi++; - bih->biCompression = vi->fourcc; - if (vi->extradata && track->private_data && (track->private_size > 0)) - { - bih->biSize += track->private_size; - bih = realloc (bih, bih->biSize); - memcpy (bih + 1, track->private_data, track->private_size); + } else if (track->private_size >= sizeof(ImageDescription) + && !strcmp(track->codec_id, MKV_V_QUICKTIME)) { + ImageDescriptionPtr idesc; + + idesc = (ImageDescriptionPtr) track->private_data; + idesc->idSize = be2me_32(idesc->idSize); + idesc->cType = be2me_32(idesc->cType); + idesc->version = be2me_16(idesc->version); + idesc->revisionLevel = be2me_16(idesc->revisionLevel); + idesc->vendor = be2me_32(idesc->vendor); + idesc->temporalQuality = be2me_32(idesc->temporalQuality); + idesc->spatialQuality = be2me_32(idesc->spatialQuality); + idesc->width = be2me_16(idesc->width); + idesc->height = be2me_16(idesc->height); + idesc->hRes = be2me_32(idesc->hRes); + idesc->vRes = be2me_32(idesc->vRes); + idesc->dataSize = be2me_32(idesc->dataSize); + idesc->frameCount = be2me_16(idesc->frameCount); + idesc->depth = be2me_16(idesc->depth); + idesc->clutID = be2me_16(idesc->clutID); + bih->biPlanes = 1; + bih->biCompression = idesc->cType; + ImageDesc = idesc; +#endif /* CONFIG_QTX_CODECS */ + + } else { + const videocodec_info_t *vi = vinfo; + while (vi->id && strcmp(vi->id, track->codec_id)) + vi++; + bih->biCompression = vi->fourcc; + if (vi->extradata && track->private_data + && (track->private_size > 0)) { + bih->biSize += track->private_size; + bih = realloc(bih, bih->biSize); + memcpy(bih + 1, track->private_data, track->private_size); } - track->reorder_timecodes = user_correct_pts == 0; - if (!vi->id) { - mp_msg (MSGT_DEMUX,MSGL_WARN, MSGTR_MPDEMUX_MKV_UnknownCodecID, - track->codec_id, track->tnum); - free(bih); - return 1; - } + track->reorder_timecodes = user_correct_pts == 0; + if (!vi->id) { + mp_msg(MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_MKV_UnknownCodecID, + track->codec_id, track->tnum); + free(bih); + return 1; + } } } - sh_v = new_sh_video_vid (demuxer, track->tnum, vid); - sh_v->bih = bih; - sh_v->format = sh_v->bih->biCompression; - if (track->v_frate == 0.0) - track->v_frate = 25.0; - sh_v->fps = track->v_frate; - sh_v->frametime = 1 / track->v_frate; - sh_v->aspect = 0; - if (!track->realmedia) - { - sh_v->disp_w = track->v_width; - sh_v->disp_h = track->v_height; - if (track->v_dheight) - sh_v->aspect = (float)track->v_dwidth / (float)track->v_dheight; - } - else - { - // vd_realvid.c will set aspect to disp_w/disp_h and rederive - // disp_w and disp_h from the RealVideo stream contents returned - // by the Real DLLs. If DisplayWidth/DisplayHeight was not set in - // the Matroska file then it has already been set to PixelWidth/Height - // by check_track_information. - sh_v->disp_w = track->v_dwidth; - sh_v->disp_h = track->v_dheight; - } - sh_v->ImageDesc = ImageDesc; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] Aspect: %f\n", sh_v->aspect); - - sh_v->ds = demuxer->video; - return 0; -} - -static int -demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid) -{ - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - sh_audio_t *sh_a = new_sh_audio_aid(demuxer, track->tnum, aid); - demux_packet_t *dp; - if(!sh_a) return 1; - mkv_d->audio_tracks[mkv_d->last_aid] = track->tnum; - - if (track->language && (strcmp(track->language, "und") != 0)) - sh_a->lang = strdup(track->language); - sh_a->default_track = track->default_track; - sh_a->ds = demuxer->audio; - sh_a->wf = malloc (sizeof (WAVEFORMATEX)); - if (track->ms_compat && (track->private_size >= sizeof(WAVEFORMATEX))) - { - WAVEFORMATEX *wf = (WAVEFORMATEX *)track->private_data; - sh_a->wf = realloc(sh_a->wf, track->private_size); - sh_a->wf->wFormatTag = le2me_16 (wf->wFormatTag); - sh_a->wf->nChannels = le2me_16 (wf->nChannels); - sh_a->wf->nSamplesPerSec = le2me_32 (wf->nSamplesPerSec); - sh_a->wf->nAvgBytesPerSec = le2me_32 (wf->nAvgBytesPerSec); - sh_a->wf->nBlockAlign = le2me_16 (wf->nBlockAlign); - sh_a->wf->wBitsPerSample = le2me_16 (wf->wBitsPerSample); - sh_a->wf->cbSize = track->private_size - sizeof(WAVEFORMATEX); - memcpy(sh_a->wf + 1, wf + 1, track->private_size - sizeof(WAVEFORMATEX)); - if (track->a_sfreq == 0.0) - track->a_sfreq = sh_a->wf->nSamplesPerSec; - if (track->a_channels == 0) - track->a_channels = sh_a->wf->nChannels; - if (track->a_bps == 0) - track->a_bps = sh_a->wf->wBitsPerSample; - track->a_formattag = sh_a->wf->wFormatTag; + sh_v = new_sh_video_vid(demuxer, track->tnum, vid); + sh_v->bih = bih; + sh_v->format = sh_v->bih->biCompression; + if (track->v_frate == 0.0) + track->v_frate = 25.0; + sh_v->fps = track->v_frate; + sh_v->frametime = 1 / track->v_frate; + sh_v->aspect = 0; + if (!track->realmedia) { + sh_v->disp_w = track->v_width; + sh_v->disp_h = track->v_height; + if (track->v_dheight) + sh_v->aspect = (float) track->v_dwidth / (float) track->v_dheight; + } else { + // vd_realvid.c will set aspect to disp_w/disp_h and rederive + // disp_w and disp_h from the RealVideo stream contents returned + // by the Real DLLs. If DisplayWidth/DisplayHeight was not set in + // the Matroska file then it has already been set to PixelWidth/Height + // by check_track_information. + sh_v->disp_w = track->v_dwidth; + sh_v->disp_h = track->v_dheight; } - else - { - memset(sh_a->wf, 0, sizeof (WAVEFORMATEX)); - if (!strcmp(track->codec_id, MKV_A_MP3) || - !strcmp(track->codec_id, MKV_A_MP2)) - track->a_formattag = 0x0055; - else if (!strncmp(track->codec_id, MKV_A_AC3, strlen(MKV_A_AC3))) - track->a_formattag = 0x2000; - else if (!strcmp(track->codec_id, MKV_A_DTS)) - track->a_formattag = 0x2001; - else if (!strcmp(track->codec_id, MKV_A_PCM) || - !strcmp(track->codec_id, MKV_A_PCM_BE)) - track->a_formattag = 0x0001; - else if (!strcmp(track->codec_id, MKV_A_AAC_2MAIN) || - !strncmp(track->codec_id, MKV_A_AAC_2LC, - strlen(MKV_A_AAC_2LC)) || - !strcmp(track->codec_id, MKV_A_AAC_2SSR) || - !strcmp(track->codec_id, MKV_A_AAC_4MAIN) || - !strncmp(track->codec_id, MKV_A_AAC_4LC, - strlen(MKV_A_AAC_4LC)) || - !strcmp(track->codec_id, MKV_A_AAC_4SSR) || - !strcmp(track->codec_id, MKV_A_AAC_4LTP) || - !strcmp(track->codec_id, MKV_A_AAC)) - track->a_formattag = mmioFOURCC('M', 'P', '4', 'A'); - else if (!strcmp(track->codec_id, MKV_A_VORBIS)) - { - if (track->private_data == NULL) - return 1; - track->a_formattag = mmioFOURCC('v', 'r', 'b', 's'); - } - else if (!strcmp(track->codec_id, MKV_A_QDMC)) - track->a_formattag = mmioFOURCC('Q', 'D', 'M', 'C'); - else if (!strcmp(track->codec_id, MKV_A_QDMC2)) - track->a_formattag = mmioFOURCC('Q', 'D', 'M', '2'); - else if (!strcmp(track->codec_id, MKV_A_WAVPACK)) - track->a_formattag = mmioFOURCC('W', 'V', 'P', 'K'); - else if (!strcmp(track->codec_id, MKV_A_TRUEHD)) - track->a_formattag = mmioFOURCC('T', 'R', 'H', 'D'); - else if (!strcmp(track->codec_id, MKV_A_FLAC)) - { - if (track->private_data == NULL || track->private_size == 0) - { - mp_msg (MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_FlacTrackDoesNotContainValidHeaders); - return 1; + sh_v->ImageDesc = ImageDesc; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Aspect: %f\n", sh_v->aspect); + + sh_v->ds = demuxer->video; + return 0; +} + +static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track, + int aid) +{ + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + sh_audio_t *sh_a = new_sh_audio_aid(demuxer, track->tnum, aid); + demux_packet_t *dp; + if (!sh_a) + return 1; + mkv_d->audio_tracks[mkv_d->last_aid] = track->tnum; + + if (track->language && (strcmp(track->language, "und") != 0)) + sh_a->lang = strdup(track->language); + sh_a->default_track = track->default_track; + sh_a->ds = demuxer->audio; + sh_a->wf = malloc(sizeof(WAVEFORMATEX)); + if (track->ms_compat && (track->private_size >= sizeof(WAVEFORMATEX))) { + WAVEFORMATEX *wf = (WAVEFORMATEX *) track->private_data; + sh_a->wf = realloc(sh_a->wf, track->private_size); + sh_a->wf->wFormatTag = le2me_16(wf->wFormatTag); + sh_a->wf->nChannels = le2me_16(wf->nChannels); + sh_a->wf->nSamplesPerSec = le2me_32(wf->nSamplesPerSec); + sh_a->wf->nAvgBytesPerSec = le2me_32(wf->nAvgBytesPerSec); + sh_a->wf->nBlockAlign = le2me_16(wf->nBlockAlign); + sh_a->wf->wBitsPerSample = le2me_16(wf->wBitsPerSample); + sh_a->wf->cbSize = track->private_size - sizeof(WAVEFORMATEX); + memcpy(sh_a->wf + 1, wf + 1, + track->private_size - sizeof(WAVEFORMATEX)); + if (track->a_sfreq == 0.0) + track->a_sfreq = sh_a->wf->nSamplesPerSec; + if (track->a_channels == 0) + track->a_channels = sh_a->wf->nChannels; + if (track->a_bps == 0) + track->a_bps = sh_a->wf->wBitsPerSample; + track->a_formattag = sh_a->wf->wFormatTag; + } else { + memset(sh_a->wf, 0, sizeof(WAVEFORMATEX)); + if (!strcmp(track->codec_id, MKV_A_MP3) + || !strcmp(track->codec_id, MKV_A_MP2)) + track->a_formattag = 0x0055; + else if (!strncmp(track->codec_id, MKV_A_AC3, strlen(MKV_A_AC3))) + track->a_formattag = 0x2000; + else if (!strcmp(track->codec_id, MKV_A_DTS)) + track->a_formattag = 0x2001; + else if (!strcmp(track->codec_id, MKV_A_PCM) + || !strcmp(track->codec_id, MKV_A_PCM_BE)) + track->a_formattag = 0x0001; + else if (!strcmp(track->codec_id, MKV_A_AAC_2MAIN) + || !strncmp(track->codec_id, MKV_A_AAC_2LC, + strlen(MKV_A_AAC_2LC)) + || !strcmp(track->codec_id, MKV_A_AAC_2SSR) + || !strcmp(track->codec_id, MKV_A_AAC_4MAIN) + || !strncmp(track->codec_id, MKV_A_AAC_4LC, + strlen(MKV_A_AAC_4LC)) + || !strcmp(track->codec_id, MKV_A_AAC_4SSR) + || !strcmp(track->codec_id, MKV_A_AAC_4LTP) + || !strcmp(track->codec_id, MKV_A_AAC)) + track->a_formattag = mmioFOURCC('M', 'P', '4', 'A'); + else if (!strcmp(track->codec_id, MKV_A_VORBIS)) { + if (track->private_data == NULL) + return 1; + track->a_formattag = mmioFOURCC('v', 'r', 'b', 's'); + } else if (!strcmp(track->codec_id, MKV_A_QDMC)) + track->a_formattag = mmioFOURCC('Q', 'D', 'M', 'C'); + else if (!strcmp(track->codec_id, MKV_A_QDMC2)) + track->a_formattag = mmioFOURCC('Q', 'D', 'M', '2'); + else if (!strcmp(track->codec_id, MKV_A_WAVPACK)) + track->a_formattag = mmioFOURCC('W', 'V', 'P', 'K'); + else if (!strcmp(track->codec_id, MKV_A_TRUEHD)) + track->a_formattag = mmioFOURCC('T', 'R', 'H', 'D'); + else if (!strcmp(track->codec_id, MKV_A_FLAC)) { + if (track->private_data == NULL || track->private_size == 0) { + mp_msg(MSGT_DEMUX, MSGL_WARN, + MSGTR_MPDEMUX_MKV_FlacTrackDoesNotContainValidHeaders); + return 1; } - track->a_formattag = mmioFOURCC ('f', 'L', 'a', 'C'); - } - else if (track->private_size >= RAPROPERTIES4_SIZE) - { - if (!strcmp(track->codec_id, MKV_A_REAL28)) - track->a_formattag = mmioFOURCC('2', '8', '_', '8'); - else if (!strcmp(track->codec_id, MKV_A_REALATRC)) - track->a_formattag = mmioFOURCC('a', 't', 'r', 'c'); - else if (!strcmp(track->codec_id, MKV_A_REALCOOK)) - track->a_formattag = mmioFOURCC('c', 'o', 'o', 'k'); - else if (!strcmp(track->codec_id, MKV_A_REALDNET)) - track->a_formattag = mmioFOURCC('d', 'n', 'e', 't'); - else if (!strcmp(track->codec_id, MKV_A_REALSIPR)) - track->a_formattag = mmioFOURCC('s', 'i', 'p', 'r'); - } - else - { - mp_msg (MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_MKV_UnknownAudioCodec, - track->codec_id, track->tnum); - free_sh_audio(demuxer, track->tnum); - return 1; - } - } - - sh_a->format = track->a_formattag; - sh_a->wf->wFormatTag = track->a_formattag; - sh_a->channels = track->a_channels; - sh_a->wf->nChannels = track->a_channels; - sh_a->samplerate = (uint32_t) track->a_sfreq; - sh_a->wf->nSamplesPerSec = (uint32_t) track->a_sfreq; - if (track->a_bps == 0) - { - sh_a->samplesize = 2; - sh_a->wf->wBitsPerSample = 16; - } - else - { - sh_a->samplesize = track->a_bps / 8; - sh_a->wf->wBitsPerSample = track->a_bps; - } - if (track->a_formattag == 0x0055) /* MP3 || MP2 */ - { - sh_a->wf->nAvgBytesPerSec = 16000; - sh_a->wf->nBlockAlign = 1152; - } - else if ((track->a_formattag == 0x2000) || /* AC3 */ - (track->a_formattag == 0x2001)) /* DTS */ - { - free(sh_a->wf); - sh_a->wf = NULL; - } - else if (track->a_formattag == 0x0001) /* PCM || PCM_BE */ - { - sh_a->wf->nAvgBytesPerSec = sh_a->channels * sh_a->samplerate*2; - sh_a->wf->nBlockAlign = sh_a->wf->nAvgBytesPerSec; - if (!strcmp(track->codec_id, MKV_A_PCM_BE)) - sh_a->format = mmioFOURCC('t', 'w', 'o', 's'); - } - else if (!strcmp(track->codec_id, MKV_A_QDMC) || - !strcmp(track->codec_id, MKV_A_QDMC2)) - { - sh_a->wf->nAvgBytesPerSec = 16000; - sh_a->wf->nBlockAlign = 1486; - track->fix_i_bps = 1; - track->qt_last_a_pts = 0.0; - if (track->private_data != NULL) - { - sh_a->codecdata=malloc(track->private_size); - memcpy (sh_a->codecdata, track->private_data, - track->private_size); - sh_a->codecdata_len = track->private_size; + track->a_formattag = mmioFOURCC('f', 'L', 'a', 'C'); + } else if (track->private_size >= RAPROPERTIES4_SIZE) { + if (!strcmp(track->codec_id, MKV_A_REAL28)) + track->a_formattag = mmioFOURCC('2', '8', '_', '8'); + else if (!strcmp(track->codec_id, MKV_A_REALATRC)) + track->a_formattag = mmioFOURCC('a', 't', 'r', 'c'); + else if (!strcmp(track->codec_id, MKV_A_REALCOOK)) + track->a_formattag = mmioFOURCC('c', 'o', 'o', 'k'); + else if (!strcmp(track->codec_id, MKV_A_REALDNET)) + track->a_formattag = mmioFOURCC('d', 'n', 'e', 't'); + else if (!strcmp(track->codec_id, MKV_A_REALSIPR)) + track->a_formattag = mmioFOURCC('s', 'i', 'p', 'r'); + } else { + mp_msg(MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_MKV_UnknownAudioCodec, + track->codec_id, track->tnum); + free_sh_audio(demuxer, track->tnum); + return 1; } } - else if (track->a_formattag == mmioFOURCC('M', 'P', '4', 'A')) - { - int profile, srate_idx; - - sh_a->wf->nAvgBytesPerSec = 16000; - sh_a->wf->nBlockAlign = 1024; - - if (!strcmp (track->codec_id, MKV_A_AAC) && - (NULL != track->private_data)) - { - sh_a->codecdata=malloc(track->private_size); - memcpy (sh_a->codecdata, track->private_data, - track->private_size); - sh_a->codecdata_len = track->private_size; - return 0; - } - - /* Recreate the 'private data' */ - /* which faad2 uses in its initialization */ - srate_idx = aac_get_sample_rate_index (sh_a->samplerate); - if (!strncmp (&track->codec_id[12], "MAIN", 4)) - profile = 0; - else if (!strncmp (&track->codec_id[12], "LC", 2)) - profile = 1; - else if (!strncmp (&track->codec_id[12], "SSR", 3)) - profile = 2; - else - profile = 3; - sh_a->codecdata = malloc (5); - sh_a->codecdata[0] = ((profile+1) << 3) | ((srate_idx&0xE) >> 1); - sh_a->codecdata[1] = ((srate_idx&0x1)<<7)|(track->a_channels<<3); - - if (strstr(track->codec_id, "SBR") != NULL) - { - /* HE-AAC (aka SBR AAC) */ - sh_a->codecdata_len = 5; - - sh_a->samplerate *= 2; - sh_a->wf->nSamplesPerSec *= 2; - srate_idx = aac_get_sample_rate_index(sh_a->samplerate); - sh_a->codecdata[2] = AAC_SYNC_EXTENSION_TYPE >> 3; - sh_a->codecdata[3] = ((AAC_SYNC_EXTENSION_TYPE&0x07)<<5) | 5; - sh_a->codecdata[4] = (1 << 7) | (srate_idx << 3); - track->default_duration = 1024.0 / (sh_a->samplerate / 2); - } - else - { - sh_a->codecdata_len = 2; - track->default_duration = 1024.0 / (float)sh_a->samplerate; - } - } - else if (track->a_formattag == mmioFOURCC('v', 'r', 'b', 's')) /* VORBIS */ - { - sh_a->wf->cbSize = track->private_size; - sh_a->wf = realloc(sh_a->wf, sizeof(WAVEFORMATEX) + sh_a->wf->cbSize); - memcpy((unsigned char *) (sh_a->wf+1), track->private_data, sh_a->wf->cbSize); - } - else if (track->private_size >= RAPROPERTIES4_SIZE - && !strncmp (track->codec_id, MKV_A_REALATRC, 7)) - { - /* Common initialization for all RealAudio codecs */ - unsigned char *src = track->private_data; - int codecdata_length, version; - int flavor; - - sh_a->wf->nAvgBytesPerSec = 0; /* FIXME !? */ - - version = AV_RB16(src + 4); - flavor = AV_RB16(src + 22); - track->coded_framesize = AV_RB32(src + 24); - track->sub_packet_h = AV_RB16(src + 40); - sh_a->wf->nBlockAlign = - track->audiopk_size = AV_RB16(src + 42); - track->sub_packet_size = AV_RB16(src + 44); - if (version == 4) - { - src += RAPROPERTIES4_SIZE; - src += src[0] + 1; - src += src[0] + 1; - } - else - src += RAPROPERTIES5_SIZE; - - src += 3; - if (version == 5) - src++; - codecdata_length = AV_RB32(src); - src += 4; - sh_a->wf->cbSize = codecdata_length; - sh_a->wf = realloc (sh_a->wf, - sizeof (WAVEFORMATEX) + - sh_a->wf->cbSize); - memcpy(((char *)(sh_a->wf + 1)), src, codecdata_length); - - switch (track->a_formattag) { - case mmioFOURCC('a', 't', 'r', 'c'): - sh_a->wf->nAvgBytesPerSec = atrc_fl2bps[flavor]; - sh_a->wf->nBlockAlign = track->sub_packet_size; - track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size); - track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float)); - break; - case mmioFOURCC('c', 'o', 'o', 'k'): - sh_a->wf->nAvgBytesPerSec = cook_fl2bps[flavor]; - sh_a->wf->nBlockAlign = track->sub_packet_size; - track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size); - track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float)); - break; - case mmioFOURCC('s', 'i', 'p', 'r'): - sh_a->wf->nAvgBytesPerSec = sipr_fl2bps[flavor]; - sh_a->wf->nBlockAlign = track->coded_framesize; - track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size); - track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float)); - break; - case mmioFOURCC('2', '8', '_', '8'): - sh_a->wf->nAvgBytesPerSec = 3600; - sh_a->wf->nBlockAlign = track->coded_framesize; - track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size); - track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float)); - break; - } - - track->realmedia = 1; + + sh_a->format = track->a_formattag; + sh_a->wf->wFormatTag = track->a_formattag; + sh_a->channels = track->a_channels; + sh_a->wf->nChannels = track->a_channels; + sh_a->samplerate = (uint32_t) track->a_sfreq; + sh_a->wf->nSamplesPerSec = (uint32_t) track->a_sfreq; + if (track->a_bps == 0) { + sh_a->samplesize = 2; + sh_a->wf->wBitsPerSample = 16; + } else { + sh_a->samplesize = track->a_bps / 8; + sh_a->wf->wBitsPerSample = track->a_bps; } - else if (!strcmp(track->codec_id, MKV_A_FLAC) || - (track->a_formattag == 0xf1ac)) - { - unsigned char *ptr; - int size; - free(sh_a->wf); - sh_a->wf = NULL; - - if (track->a_formattag == mmioFOURCC('f', 'L', 'a', 'C')) - { - ptr = track->private_data; - size = track->private_size; + if (track->a_formattag == 0x0055) { /* MP3 || MP2 */ + sh_a->wf->nAvgBytesPerSec = 16000; + sh_a->wf->nBlockAlign = 1152; + } else if ((track->a_formattag == 0x2000) || /* AC3 */ + (track->a_formattag == 0x2001)) { /* DTS */ + free(sh_a->wf); + sh_a->wf = NULL; + } else if (track->a_formattag == 0x0001) { /* PCM || PCM_BE */ + sh_a->wf->nAvgBytesPerSec = sh_a->channels * sh_a->samplerate * 2; + sh_a->wf->nBlockAlign = sh_a->wf->nAvgBytesPerSec; + if (!strcmp(track->codec_id, MKV_A_PCM_BE)) + sh_a->format = mmioFOURCC('t', 'w', 'o', 's'); + } else if (!strcmp(track->codec_id, MKV_A_QDMC) + || !strcmp(track->codec_id, MKV_A_QDMC2)) { + sh_a->wf->nAvgBytesPerSec = 16000; + sh_a->wf->nBlockAlign = 1486; + track->fix_i_bps = 1; + track->qt_last_a_pts = 0.0; + if (track->private_data != NULL) { + sh_a->codecdata = malloc(track->private_size); + memcpy(sh_a->codecdata, track->private_data, track->private_size); + sh_a->codecdata_len = track->private_size; } - else - { - sh_a->format = mmioFOURCC('f', 'L', 'a', 'C'); - ptr = track->private_data + sizeof (WAVEFORMATEX); - size = track->private_size - sizeof (WAVEFORMATEX); + } else if (track->a_formattag == mmioFOURCC('M', 'P', '4', 'A')) { + int profile, srate_idx; + + sh_a->wf->nAvgBytesPerSec = 16000; + sh_a->wf->nBlockAlign = 1024; + + if (!strcmp(track->codec_id, MKV_A_AAC) + && (NULL != track->private_data)) { + sh_a->codecdata = malloc(track->private_size); + memcpy(sh_a->codecdata, track->private_data, track->private_size); + sh_a->codecdata_len = track->private_size; + return 0; + } + + /* Recreate the 'private data' */ + /* which faad2 uses in its initialization */ + srate_idx = aac_get_sample_rate_index(sh_a->samplerate); + if (!strncmp(&track->codec_id[12], "MAIN", 4)) + profile = 0; + else if (!strncmp(&track->codec_id[12], "LC", 2)) + profile = 1; + else if (!strncmp(&track->codec_id[12], "SSR", 3)) + profile = 2; + else + profile = 3; + sh_a->codecdata = malloc(5); + sh_a->codecdata[0] = ((profile + 1) << 3) | ((srate_idx & 0xE) >> 1); + sh_a->codecdata[1] = + ((srate_idx & 0x1) << 7) | (track->a_channels << 3); + + if (strstr(track->codec_id, "SBR") != NULL) { + /* HE-AAC (aka SBR AAC) */ + sh_a->codecdata_len = 5; + + sh_a->samplerate *= 2; + sh_a->wf->nSamplesPerSec *= 2; + srate_idx = aac_get_sample_rate_index(sh_a->samplerate); + sh_a->codecdata[2] = AAC_SYNC_EXTENSION_TYPE >> 3; + sh_a->codecdata[3] = ((AAC_SYNC_EXTENSION_TYPE & 0x07) << 5) | 5; + sh_a->codecdata[4] = (1 << 7) | (srate_idx << 3); + track->default_duration = 1024.0 / (sh_a->samplerate / 2); + } else { + sh_a->codecdata_len = 2; + track->default_duration = 1024.0 / (float) sh_a->samplerate; } - if (size < 4 || ptr[0] != 'f' || ptr[1] != 'L' || - ptr[2] != 'a' || ptr[3] != 'C') - { - dp = new_demux_packet (4); - memcpy (dp->buffer, "fLaC", 4); + } else if (track->a_formattag == mmioFOURCC('v', 'r', 'b', 's')) { /* VORBIS */ + sh_a->wf->cbSize = track->private_size; + sh_a->wf = realloc(sh_a->wf, sizeof(WAVEFORMATEX) + sh_a->wf->cbSize); + memcpy((unsigned char *) (sh_a->wf + 1), track->private_data, + sh_a->wf->cbSize); + } else if (track->private_size >= RAPROPERTIES4_SIZE + && !strncmp(track->codec_id, MKV_A_REALATRC, 7)) { + /* Common initialization for all RealAudio codecs */ + unsigned char *src = track->private_data; + int codecdata_length, version; + int flavor; + + sh_a->wf->nAvgBytesPerSec = 0; /* FIXME !? */ + + version = AV_RB16(src + 4); + flavor = AV_RB16(src + 22); + track->coded_framesize = AV_RB32(src + 24); + track->sub_packet_h = AV_RB16(src + 40); + sh_a->wf->nBlockAlign = track->audiopk_size = AV_RB16(src + 42); + track->sub_packet_size = AV_RB16(src + 44); + if (version == 4) { + src += RAPROPERTIES4_SIZE; + src += src[0] + 1; + src += src[0] + 1; + } else + src += RAPROPERTIES5_SIZE; + + src += 3; + if (version == 5) + src++; + codecdata_length = AV_RB32(src); + src += 4; + sh_a->wf->cbSize = codecdata_length; + sh_a->wf = realloc(sh_a->wf, sizeof(WAVEFORMATEX) + sh_a->wf->cbSize); + memcpy(((char *) (sh_a->wf + 1)), src, codecdata_length); + + switch (track->a_formattag) { + case mmioFOURCC('a', 't', 'r', 'c'): + sh_a->wf->nAvgBytesPerSec = atrc_fl2bps[flavor]; + sh_a->wf->nBlockAlign = track->sub_packet_size; + track->audio_buf = + malloc(track->sub_packet_h * track->audiopk_size); + track->audio_timestamp = + malloc(track->sub_packet_h * sizeof(float)); + break; + case mmioFOURCC('c', 'o', 'o', 'k'): + sh_a->wf->nAvgBytesPerSec = cook_fl2bps[flavor]; + sh_a->wf->nBlockAlign = track->sub_packet_size; + track->audio_buf = + malloc(track->sub_packet_h * track->audiopk_size); + track->audio_timestamp = + malloc(track->sub_packet_h * sizeof(float)); + break; + case mmioFOURCC('s', 'i', 'p', 'r'): + sh_a->wf->nAvgBytesPerSec = sipr_fl2bps[flavor]; + sh_a->wf->nBlockAlign = track->coded_framesize; + track->audio_buf = + malloc(track->sub_packet_h * track->audiopk_size); + track->audio_timestamp = + malloc(track->sub_packet_h * sizeof(float)); + break; + case mmioFOURCC('2', '8', '_', '8'): + sh_a->wf->nAvgBytesPerSec = 3600; + sh_a->wf->nBlockAlign = track->coded_framesize; + track->audio_buf = + malloc(track->sub_packet_h * track->audiopk_size); + track->audio_timestamp = + malloc(track->sub_packet_h * sizeof(float)); + break; } - else - { - dp = new_demux_packet (size); - memcpy (dp->buffer, ptr, size); + + track->realmedia = 1; + } else if (!strcmp(track->codec_id, MKV_A_FLAC) + || (track->a_formattag == 0xf1ac)) { + unsigned char *ptr; + int size; + free(sh_a->wf); + sh_a->wf = NULL; + + if (track->a_formattag == mmioFOURCC('f', 'L', 'a', 'C')) { + ptr = track->private_data; + size = track->private_size; + } else { + sh_a->format = mmioFOURCC('f', 'L', 'a', 'C'); + ptr = track->private_data + sizeof(WAVEFORMATEX); + size = track->private_size - sizeof(WAVEFORMATEX); } - dp->pts = 0; - dp->flags = 0; - ds_add_packet (demuxer->audio, dp); + if (size < 4 || ptr[0] != 'f' || ptr[1] != 'L' || ptr[2] != 'a' + || ptr[3] != 'C') { + dp = new_demux_packet(4); + memcpy(dp->buffer, "fLaC", 4); + } else { + dp = new_demux_packet(size); + memcpy(dp->buffer, ptr, size); + } + dp->pts = 0; + dp->flags = 0; + ds_add_packet(demuxer->audio, dp); + } else if (track->a_formattag == mmioFOURCC('W', 'V', 'P', 'K') || + track->a_formattag == mmioFOURCC('T', 'R', 'H', 'D')) { + /* do nothing, still works */ + } else if (!track->ms_compat + || (track->private_size < sizeof(WAVEFORMATEX))) { + free_sh_audio(demuxer, track->tnum); + return 1; } - else if (track->a_formattag == mmioFOURCC('W', 'V', 'P', 'K') || - track->a_formattag == mmioFOURCC('T', 'R', 'H', 'D')) - { /* do nothing, still works */ } - else if (!track->ms_compat || (track->private_size < sizeof(WAVEFORMATEX))) - { - free_sh_audio(demuxer, track->tnum); - return 1; - } - - return 0; + + return 0; } -static int -demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track, int sid) +static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track, + int sid) { - if (track->subtitle_type != MATROSKA_SUBTYPE_UNKNOWN) - { - int size, m; - uint8_t *buffer; - sh_sub_t *sh = new_sh_sub_sid(demuxer, track->tnum, sid); - track->sh_sub = sh; - sh->type = 't'; - if (track->subtitle_type == MATROSKA_SUBTYPE_VOBSUB) - sh->type = 'v'; - if (track->subtitle_type == MATROSKA_SUBTYPE_SSA) - sh->type = 'a'; - size = track->private_size; - m = demux_mkv_decode (track,track->private_data,&buffer,&size,2); - if (buffer && m) - { - free (track->private_data); - track->private_data = buffer; - track->private_size = size; + if (track->subtitle_type != MATROSKA_SUBTYPE_UNKNOWN) { + int size, m; + uint8_t *buffer; + sh_sub_t *sh = new_sh_sub_sid(demuxer, track->tnum, sid); + track->sh_sub = sh; + sh->type = 't'; + if (track->subtitle_type == MATROSKA_SUBTYPE_VOBSUB) + sh->type = 'v'; + if (track->subtitle_type == MATROSKA_SUBTYPE_SSA) + sh->type = 'a'; + size = track->private_size; + m = demux_mkv_decode(track, track->private_data, &buffer, &size, 2); + if (buffer && m) { + free(track->private_data); + track->private_data = buffer; + track->private_size = size; } - sh->extradata=malloc(track->private_size); - memcpy (sh->extradata, track->private_data, - track->private_size); - sh->extradata_len = track->private_size; - if (track->language && (strcmp(track->language, "und") != 0)) - sh->lang = strdup(track->language); - sh->default_track = track->default_track; + sh->extradata = malloc(track->private_size); + memcpy(sh->extradata, track->private_data, track->private_size); + sh->extradata_len = track->private_size; + if (track->language && (strcmp(track->language, "und") != 0)) + sh->lang = strdup(track->language); + sh->default_track = track->default_track; + } else { + mp_msg(MSGT_DEMUX, MSGL_ERR, + MSGTR_MPDEMUX_MKV_SubtitleTypeNotSupported, track->codec_id); + return 1; } - else - { - mp_msg (MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_MKV_SubtitleTypeNotSupported, - track->codec_id); - return 1; - } - - return 0; + + return 0; } -static int -demux_mkv_open (demuxer_t *demuxer) +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; - - stream_seek(s, s->start_pos); - str = ebml_read_header (s, &version); - if (str == NULL || strcmp (str, "matroska") || version > 2) - { - mp_msg (MSGT_DEMUX, MSGL_DBG2, "[mkv] no head found\n"); - return 0; + stream_t *s = demuxer->stream; + mkv_demuxer_t *mkv_d; + mkv_track_t *track; + int i, version, cont = 0; + char *str; + + stream_seek(s, s->start_pos); + str = ebml_read_header(s, &version); + if (str == NULL || strcmp(str, "matroska") || version > 2) { + mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] no head found\n"); + return 0; } - free (str); - - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] Found the head...\n"); - - if (ebml_read_id (s, NULL) != MATROSKA_ID_SEGMENT) - { - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] but no segment :(\n"); - return 0; + free(str); + + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Found the head...\n"); + + if (ebml_read_id(s, NULL) != MATROSKA_ID_SEGMENT) { + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] but no segment :(\n"); + return 0; } - ebml_read_length (s, NULL); /* return bytes number until EOF */ - - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] + a segment...\n"); - - mkv_d = calloc (1, sizeof (mkv_demuxer_t)); - demuxer->priv = mkv_d; - mkv_d->tc_scale = 1000000; - mkv_d->segment_start = stream_tell (s); - mkv_d->parsed_cues = malloc (sizeof (off_t)); - mkv_d->parsed_seekhead = malloc (sizeof (off_t)); - - while (!cont) - { - switch (ebml_read_id (s, NULL)) - { + ebml_read_length(s, NULL); /* return bytes number until EOF */ + + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] + a segment...\n"); + + mkv_d = calloc(1, sizeof(mkv_demuxer_t)); + demuxer->priv = mkv_d; + mkv_d->tc_scale = 1000000; + mkv_d->segment_start = stream_tell(s); + mkv_d->parsed_cues = malloc(sizeof(off_t)); + mkv_d->parsed_seekhead = malloc(sizeof(off_t)); + + while (!cont) { + switch (ebml_read_id(s, NULL)) { case MATROSKA_ID_INFO: - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |+ segment information...\n"); - cont = demux_mkv_read_info (demuxer); - break; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] |+ segment information...\n"); + cont = demux_mkv_read_info(demuxer); + break; case MATROSKA_ID_TRACKS: - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |+ segment tracks...\n"); - cont = demux_mkv_read_tracks (demuxer); - break; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] |+ segment tracks...\n"); + cont = demux_mkv_read_tracks(demuxer); + break; case MATROSKA_ID_CUES: - cont = demux_mkv_read_cues (demuxer); - break; + cont = demux_mkv_read_cues(demuxer); + break; case MATROSKA_ID_TAGS: - cont = demux_mkv_read_tags (demuxer); - break; + cont = demux_mkv_read_tags(demuxer); + break; case MATROSKA_ID_SEEKHEAD: - cont = demux_mkv_read_seekhead (demuxer); - break; + cont = demux_mkv_read_seekhead(demuxer); + break; case MATROSKA_ID_CHAPTERS: - cont = demux_mkv_read_chapters (demuxer); - break; + cont = demux_mkv_read_chapters(demuxer); + break; case MATROSKA_ID_ATTACHMENTS: - cont = demux_mkv_read_attachments (demuxer); - break; + cont = demux_mkv_read_attachments(demuxer); + break; case MATROSKA_ID_CLUSTER: - { + { int p, l; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |+ found cluster, headers are " - "parsed completely :)\n"); + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] |+ found cluster, headers are " + "parsed completely :)\n"); /* get the first cluster timecode */ p = stream_tell(s); - l = ebml_read_length (s, NULL); - while (ebml_read_id (s, NULL) != MATROSKA_ID_CLUSTERTIMECODE) - { - ebml_read_skip (s, NULL); - if (stream_tell (s) >= p + l) - break; - } - if (stream_tell (s) < p + l) - { - uint64_t num = ebml_read_uint (s, NULL); + l = ebml_read_length(s, NULL); + while (ebml_read_id(s, NULL) != MATROSKA_ID_CLUSTERTIMECODE) { + ebml_read_skip(s, NULL); + if (stream_tell(s) >= p + l) + break; + } + if (stream_tell(s) < p + l) { + uint64_t num = ebml_read_uint(s, NULL); if (num == EBML_UINT_INVALID) - return 0; + return 0; mkv_d->first_tc = num * mkv_d->tc_scale / 1000000.0; mkv_d->has_first_tc = 1; - } - stream_seek (s, p - 4); + } + stream_seek(s, p - 4); cont = 1; break; - } + } default: - cont = 1; + cont = 1; case EBML_ID_VOID: - ebml_read_skip (s, NULL); - break; - } - } - - display_create_tracks (demuxer); - - /* select video track */ - track = NULL; - if (demuxer->video->id == -1) /* automatically select a video track */ - { - /* search for a video track that has the 'default' flag set */ - for (i=0; i<mkv_d->num_tracks; i++) - if (mkv_d->tracks[i]->type == MATROSKA_TRACK_VIDEO - && mkv_d->tracks[i]->default_track) - { - track = mkv_d->tracks[i]; - break; - } - - if (track == NULL) - /* no track has the 'default' flag set */ - /* let's take the first video track */ - for (i=0; i<mkv_d->num_tracks; i++) - if (mkv_d->tracks[i]->type == MATROSKA_TRACK_VIDEO) - { - track = mkv_d->tracks[i]; - break; - } - } - else if (demuxer->video->id != -2) /* -2 = no video at all */ - track = demux_mkv_find_track_by_num (mkv_d, demuxer->video->id, - MATROSKA_TRACK_VIDEO); - - if (track && demuxer->v_streams[track->tnum]) - { - mp_msg (MSGT_DEMUX, MSGL_INFO, - MSGTR_MPDEMUX_MKV_WillPlayVideoTrack, track->tnum); - demuxer->video->id = track->tnum; - demuxer->video->sh = demuxer->v_streams[track->tnum]; - } - else - { - mp_msg (MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_NoVideoTrackFound); - demuxer->video->id = -2; - } - - /* select audio track */ - track = NULL; - if (track == NULL) - /* search for an audio track that has the 'default' flag set */ - for (i=0; i < mkv_d->num_tracks; i++) - if (mkv_d->tracks[i]->type == MATROSKA_TRACK_AUDIO - && mkv_d->tracks[i]->default_track) - { - track = mkv_d->tracks[i]; - break; - } - - if (track == NULL) - /* no track has the 'default' flag set */ - /* let's take the first audio track */ - for (i=0; i < mkv_d->num_tracks; i++) - if (mkv_d->tracks[i]->type == MATROSKA_TRACK_AUDIO) - { - track = mkv_d->tracks[i]; - break; - } - - if (track && demuxer->a_streams[track->tnum]) - { - demuxer->audio->id = track->tnum; - demuxer->audio->sh = demuxer->a_streams[track->tnum]; - } - else - { - mp_msg (MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_NoAudioTrackFound); - demuxer->audio->id = -2; - } - - - if(demuxer->audio->id != -2) - for (i=0; i < mkv_d->num_tracks; i++) - { - if(mkv_d->tracks[i]->type != MATROSKA_TRACK_AUDIO) - continue; - if(demuxer->a_streams[track->tnum]) - { - mkv_d->last_aid++; - if(mkv_d->last_aid == MAX_A_STREAMS) + ebml_read_skip(s, NULL); break; } } - if (demuxer->chapters) - { - for (i=0; i < (int)demuxer->num_chapters; i++) - { - demuxer->chapters[i].start -= mkv_d->first_tc; - demuxer->chapters[i].end -= mkv_d->first_tc; + display_create_tracks(demuxer); + + /* select video track */ + track = NULL; + if (demuxer->video->id == -1) { /* automatically select a video track */ + /* search for a video track that has the 'default' flag set */ + for (i = 0; i < mkv_d->num_tracks; i++) + if (mkv_d->tracks[i]->type == MATROSKA_TRACK_VIDEO + && mkv_d->tracks[i]->default_track) { + track = mkv_d->tracks[i]; + break; + } + + if (track == NULL) + /* no track has the 'default' flag set */ + /* let's take the first video track */ + for (i = 0; i < mkv_d->num_tracks; i++) + if (mkv_d->tracks[i]->type == MATROSKA_TRACK_VIDEO) { + track = mkv_d->tracks[i]; + break; + } + } else if (demuxer->video->id != -2) /* -2 = no video at all */ + track = demux_mkv_find_track_by_num(mkv_d, demuxer->video->id, + MATROSKA_TRACK_VIDEO); + + if (track && demuxer->v_streams[track->tnum]) { + mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_WillPlayVideoTrack, + track->tnum); + demuxer->video->id = track->tnum; + demuxer->video->sh = demuxer->v_streams[track->tnum]; + } else { + mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_NoVideoTrackFound); + demuxer->video->id = -2; + } + + /* select audio track */ + track = NULL; + if (track == NULL) + /* search for an audio track that has the 'default' flag set */ + for (i = 0; i < mkv_d->num_tracks; i++) + if (mkv_d->tracks[i]->type == MATROSKA_TRACK_AUDIO + && mkv_d->tracks[i]->default_track) { + track = mkv_d->tracks[i]; + break; + } + + if (track == NULL) + /* no track has the 'default' flag set */ + /* let's take the first audio track */ + for (i = 0; i < mkv_d->num_tracks; i++) + if (mkv_d->tracks[i]->type == MATROSKA_TRACK_AUDIO) { + track = mkv_d->tracks[i]; + break; + } + + if (track && demuxer->a_streams[track->tnum]) { + demuxer->audio->id = track->tnum; + demuxer->audio->sh = demuxer->a_streams[track->tnum]; + } else { + mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_NoAudioTrackFound); + demuxer->audio->id = -2; + } + + + if (demuxer->audio->id != -2) + for (i = 0; i < mkv_d->num_tracks; i++) { + if (mkv_d->tracks[i]->type != MATROSKA_TRACK_AUDIO) + continue; + if (demuxer->a_streams[track->tnum]) { + mkv_d->last_aid++; + if (mkv_d->last_aid == MAX_A_STREAMS) + break; + } } - if (dvd_last_chapter > 0 && dvd_last_chapter <= demuxer->num_chapters) - { - if (demuxer->chapters[dvd_last_chapter-1].end != 0) - mkv_d->stop_timecode = demuxer->chapters[dvd_last_chapter-1].end; - else if (dvd_last_chapter + 1 <= demuxer->num_chapters) - mkv_d->stop_timecode = demuxer->chapters[dvd_last_chapter].start; + + if (demuxer->chapters) { + for (i = 0; i < (int) demuxer->num_chapters; i++) { + demuxer->chapters[i].start -= mkv_d->first_tc; + demuxer->chapters[i].end -= mkv_d->first_tc; + } + if (dvd_last_chapter > 0 && dvd_last_chapter <= demuxer->num_chapters) { + if (demuxer->chapters[dvd_last_chapter - 1].end != 0) + mkv_d->stop_timecode = + demuxer->chapters[dvd_last_chapter - 1].end; + else if (dvd_last_chapter + 1 <= demuxer->num_chapters) + mkv_d->stop_timecode = + demuxer->chapters[dvd_last_chapter].start; } } - if (s->end_pos == 0 || (mkv_d->indexes == NULL && index_mode < 0)) - demuxer->seekable = 0; - else - { - demuxer->movi_start = s->start_pos; - demuxer->movi_end = s->end_pos; - demuxer->seekable = 1; + if (s->end_pos == 0 || (mkv_d->indexes == NULL && index_mode < 0)) + demuxer->seekable = 0; + else { + demuxer->movi_start = s->start_pos; + demuxer->movi_end = s->end_pos; + demuxer->seekable = 1; } - return DEMUXER_TYPE_MATROSKA; + return DEMUXER_TYPE_MATROSKA; } -static void -demux_close_mkv (demuxer_t *demuxer) +static void demux_close_mkv(demuxer_t *demuxer) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - - if (mkv_d) - { - int i; - free_cached_dps (demuxer); - if (mkv_d->tracks) - { - for (i=0; i<mkv_d->num_tracks; i++) - demux_mkv_free_trackentry(mkv_d->tracks[i]); - free (mkv_d->tracks); + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + + if (mkv_d) { + int i; + free_cached_dps(demuxer); + if (mkv_d->tracks) { + for (i = 0; i < mkv_d->num_tracks; i++) + demux_mkv_free_trackentry(mkv_d->tracks[i]); + free(mkv_d->tracks); } - free (mkv_d->indexes); - free (mkv_d->cluster_positions); - free (mkv_d->parsed_cues); - free (mkv_d->parsed_seekhead); - free (mkv_d); + free(mkv_d->indexes); + free(mkv_d->cluster_positions); + free(mkv_d->parsed_cues); + free(mkv_d->parsed_seekhead); + free(mkv_d); } } -static int -demux_mkv_read_block_lacing (uint8_t *buffer, uint64_t *size, - uint8_t *laces, uint32_t **all_lace_sizes) +static int demux_mkv_read_block_lacing(uint8_t *buffer, uint64_t *size, + uint8_t *laces, + uint32_t **all_lace_sizes) { - uint32_t total = 0, *lace_size; - uint8_t flags; - int i; - - *all_lace_sizes = NULL; - lace_size = NULL; - /* lacing flags */ - flags = *buffer++; - (*size)--; - - switch ((flags & 0x06) >> 1) - { - case 0: /* no lacing */ - *laces = 1; - lace_size = calloc(*laces, sizeof(uint32_t)); - lace_size[0] = *size; - break; - - case 1: /* xiph lacing */ - case 2: /* fixed-size lacing */ - case 3: /* EBML lacing */ - *laces = *buffer++; - (*size)--; - (*laces)++; - lace_size = calloc(*laces, sizeof(uint32_t)); - - switch ((flags & 0x06) >> 1) + uint32_t total = 0, *lace_size; + uint8_t flags; + int i; + + *all_lace_sizes = NULL; + lace_size = NULL; + /* lacing flags */ + flags = *buffer++; + (*size)--; + + switch ((flags & 0x06) >> 1) { + case 0: /* no lacing */ + *laces = 1; + lace_size = calloc(*laces, sizeof(uint32_t)); + lace_size[0] = *size; + break; + + case 1: /* xiph lacing */ + case 2: /* fixed-size lacing */ + case 3: /* EBML lacing */ + *laces = *buffer++; + (*size)--; + (*laces)++; + lace_size = calloc(*laces, sizeof(uint32_t)); + + switch ((flags & 0x06) >> 1) { + case 1: /* xiph lacing */ + for (i = 0; i < *laces - 1; i++) { + lace_size[i] = 0; + do { + lace_size[i] += *buffer; + (*size)--; + } while (*buffer++ == 0xFF); + total += lace_size[i]; + } + lace_size[i] = *size - total; + break; + + case 2: /* fixed-size lacing */ + for (i = 0; i < *laces; i++) + lace_size[i] = *size / *laces; + break; + + case 3: /* EBML lacing */ { - case 1: /* xiph lacing */ - for (i=0; i < *laces-1; i++) - { - lace_size[i] = 0; - do - { - lace_size[i] += *buffer; - (*size)--; - } while (*buffer++ == 0xFF); - total += lace_size[i]; - } - lace_size[i] = *size - total; - break; - - case 2: /* fixed-size lacing */ - for (i=0; i < *laces; i++) - lace_size[i] = *size / *laces; - break; - - case 3: /* EBML lacing */ - { int l; - uint64_t num = ebml_read_vlen_uint (buffer, &l); + uint64_t num = ebml_read_vlen_uint(buffer, &l); if (num == EBML_UINT_INVALID) { - free(lace_size); - return 1; + free(lace_size); + return 1; } buffer += l; *size -= l; total = lace_size[0] = num; - for (i=1; i < *laces-1; i++) - { + for (i = 1; i < *laces - 1; i++) { int64_t snum; - snum = ebml_read_vlen_int (buffer, &l); + snum = ebml_read_vlen_int(buffer, &l); if (snum == EBML_INT_INVALID) { - free(lace_size); - return 1; + free(lace_size); + return 1; } buffer += l; *size -= l; - lace_size[i] = lace_size[i-1] + snum; + lace_size[i] = lace_size[i - 1] + snum; total += lace_size[i]; - } + } lace_size[i] = *size - total; break; - } + } } - break; + break; } - *all_lace_sizes = lace_size; - return 0; + *all_lace_sizes = lace_size; + return 0; } -static void -handle_subtitles(demuxer_t *demuxer, mkv_track_t *track, char *block, - int64_t size, uint64_t block_duration, uint64_t timecode) +static void handle_subtitles(demuxer_t *demuxer, mkv_track_t *track, + char *block, int64_t size, + uint64_t block_duration, uint64_t timecode) { - demux_packet_t *dp; - - if (block_duration == 0) - { - mp_msg (MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_NoBlockDurationForSubtitleTrackFound); - return; + demux_packet_t *dp; + + if (block_duration == 0) { + mp_msg(MSGT_DEMUX, MSGL_WARN, + MSGTR_MPDEMUX_MKV_NoBlockDurationForSubtitleTrackFound); + return; } - sub_utf8 = 1; - dp = new_demux_packet(size); - memcpy(dp->buffer, block, size); - dp->pts = timecode / 1000.0f; - dp->endpts = (timecode + block_duration) / 1000.0f; - ds_add_packet(demuxer->sub, dp); + sub_utf8 = 1; + dp = new_demux_packet(size); + memcpy(dp->buffer, block, size); + dp->pts = timecode / 1000.0f; + dp->endpts = (timecode + block_duration) / 1000.0f; + ds_add_packet(demuxer->sub, dp); } -static void -handle_realvideo (demuxer_t *demuxer, mkv_track_t *track, uint8_t *buffer, - uint32_t size, int block_bref) +static void handle_realvideo(demuxer_t *demuxer, mkv_track_t *track, + uint8_t *buffer, uint32_t size, int block_bref) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - demux_packet_t *dp; - uint32_t timestamp = mkv_d->last_pts * 1000; - - dp = new_demux_packet (size); - memcpy (dp->buffer, buffer, size); - - if (mkv_d->v_skip_to_keyframe) - { - dp->pts = mkv_d->last_pts; - track->rv_kf_base = 0; - track->rv_kf_pts = timestamp; - } - else - dp->pts = real_fix_timestamp (dp->buffer, timestamp, - ((sh_video_t*)demuxer->video->sh)->bih->biCompression, - &track->rv_kf_base, &track->rv_kf_pts, NULL); - dp->pos = demuxer->filepos; - dp->flags = block_bref ? 0 : 0x10; - - ds_add_packet(demuxer->video, dp); + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + demux_packet_t *dp; + uint32_t timestamp = mkv_d->last_pts * 1000; + + dp = new_demux_packet(size); + memcpy(dp->buffer, buffer, size); + + if (mkv_d->v_skip_to_keyframe) { + dp->pts = mkv_d->last_pts; + track->rv_kf_base = 0; + track->rv_kf_pts = timestamp; + } else + dp->pts = + real_fix_timestamp(dp->buffer, timestamp, + ((sh_video_t *) demuxer->video->sh)->bih-> + biCompression, &track->rv_kf_base, + &track->rv_kf_pts, NULL); + dp->pos = demuxer->filepos; + dp->flags = block_bref ? 0 : 0x10; + + ds_add_packet(demuxer->video, dp); } -static void -handle_realaudio (demuxer_t *demuxer, mkv_track_t *track, uint8_t *buffer, - uint32_t size, int block_bref) +static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track, + uint8_t *buffer, uint32_t size, int block_bref) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - int sps = track->sub_packet_size; - int sph = track->sub_packet_h; - int cfs = track->coded_framesize; - int w = track->audiopk_size; - int spc = track->sub_packet_cnt; - demux_packet_t *dp; - int x; - - if ((track->a_formattag == mmioFOURCC('2', '8', '_', '8')) || - (track->a_formattag == mmioFOURCC('c', 'o', 'o', 'k')) || - (track->a_formattag == mmioFOURCC('a', 't', 'r', 'c')) || - (track->a_formattag == mmioFOURCC('s', 'i', 'p', 'r'))) - { + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + int sps = track->sub_packet_size; + int sph = track->sub_packet_h; + int cfs = track->coded_framesize; + int w = track->audiopk_size; + int spc = track->sub_packet_cnt; + demux_packet_t *dp; + int x; + + if ((track->a_formattag == mmioFOURCC('2', '8', '_', '8')) + || (track->a_formattag == mmioFOURCC('c', 'o', 'o', 'k')) + || (track->a_formattag == mmioFOURCC('a', 't', 'r', 'c')) + || (track->a_formattag == mmioFOURCC('s', 'i', 'p', 'r'))) { // if(!block_bref) // spc = track->sub_packet_cnt = 0; - switch (track->a_formattag) { + switch (track->a_formattag) { case mmioFOURCC('2', '8', '_', '8'): - for (x = 0; x < sph / 2; x++) - memcpy(track->audio_buf + x * 2 * w + spc * cfs, buffer + cfs * x, cfs); - break; + for (x = 0; x < sph / 2; x++) + memcpy(track->audio_buf + x * 2 * w + spc * cfs, + buffer + cfs * x, cfs); + break; case mmioFOURCC('c', 'o', 'o', 'k'): case mmioFOURCC('a', 't', 'r', 'c'): - for (x = 0; x < w / sps; x++) - memcpy(track->audio_buf + sps * (sph * x + ((sph + 1) / 2) * (spc & 1) + (spc >> 1)), buffer + sps * x, sps); - break; + for (x = 0; x < w / sps; x++) + memcpy(track->audio_buf + + sps * (sph * x + ((sph + 1) / 2) * (spc & 1) + + (spc >> 1)), buffer + sps * x, sps); + break; case mmioFOURCC('s', 'i', 'p', 'r'): - memcpy(track->audio_buf + spc * w, buffer, w); - if (spc == sph - 1) - { - int n; - int bs = sph * w * 2 / 96; // nibbles per subpacket - // Perform reordering - for(n=0; n < 38; n++) - { - int j; - int i = bs * sipr_swaps[n][0]; - int o = bs * sipr_swaps[n][1]; - // swap nibbles of block 'i' with 'o' TODO: optimize - for(j = 0;j < bs; j++) - { - int x = (i & 1) ? (track->audio_buf[i >> 1] >> 4) : (track->audio_buf[i >> 1] & 0x0F); - int y = (o & 1) ? (track->audio_buf[o >> 1] >> 4) : (track->audio_buf[o >> 1] & 0x0F); - if(o & 1) - track->audio_buf[o >> 1] = (track->audio_buf[o >> 1] & 0x0F) | (x << 4); - else - track->audio_buf[o >> 1] = (track->audio_buf[o >> 1] & 0xF0) | x; - if(i & 1) - track->audio_buf[i >> 1] = (track->audio_buf[i >> 1] & 0x0F) | (y << 4); - else - track->audio_buf[i >> 1] = (track->audio_buf[i >> 1] & 0xF0) | y; - ++i; ++o; + memcpy(track->audio_buf + spc * w, buffer, w); + if (spc == sph - 1) { + int n; + int bs = sph * w * 2 / 96; // nibbles per subpacket + // Perform reordering + for (n = 0; n < 38; n++) { + int j; + int i = bs * sipr_swaps[n][0]; + int o = bs * sipr_swaps[n][1]; + // swap nibbles of block 'i' with 'o' TODO: optimize + for (j = 0; j < bs; j++) { + int x = (i & 1) ? + (track->audio_buf[i >> 1] >> 4) : + (track->audio_buf[i >> 1] & 0x0F); + int y = (o & 1) ? + (track->audio_buf[o >> 1] >> 4) : + (track->audio_buf[o >> 1] & 0x0F); + if (o & 1) + track->audio_buf[o >> 1] = + (track->audio_buf[o >> 1] & 0x0F) | (x << 4); + else + track->audio_buf[o >> 1] = + (track->audio_buf[o >> 1] & 0xF0) | x; + if (i & 1) + track->audio_buf[i >> 1] = + (track->audio_buf[i >> 1] & 0x0F) | (y << 4); + else + track->audio_buf[i >> 1] = + (track->audio_buf[i >> 1] & 0xF0) | y; + ++i; + ++o; } } } - break; - } - track->audio_timestamp[track->sub_packet_cnt] = (track->ra_pts == mkv_d->last_pts) ? 0 : (mkv_d->last_pts); - track->ra_pts = mkv_d->last_pts; - if (track->sub_packet_cnt == 0) - track->audio_filepos = demuxer->filepos; - if (++(track->sub_packet_cnt) == sph) - { - int apk_usize = ((WAVEFORMATEX*)((sh_audio_t*)demuxer->audio->sh)->wf)->nBlockAlign; - track->sub_packet_cnt = 0; - // Release all the audio packets - for (x = 0; x < sph*w/apk_usize; x++) - { - dp = new_demux_packet(apk_usize); - memcpy(dp->buffer, track->audio_buf + x * apk_usize, apk_usize); - /* Put timestamp only on packets that correspond to original audio packets in file */ - dp->pts = (x * apk_usize % w) ? 0 : track->audio_timestamp[x * apk_usize / w]; - dp->pos = track->audio_filepos; // all equal - dp->flags = x ? 0 : 0x10; // Mark first packet as keyframe - ds_add_packet(demuxer->audio, dp); - } + break; } - } else { // Not a codec that require reordering - dp = new_demux_packet (size); - memcpy(dp->buffer, buffer, size); - if (track->ra_pts == mkv_d->last_pts && !mkv_d->a_skip_to_keyframe) - dp->pts = 0; - else - dp->pts = mkv_d->last_pts; - track->ra_pts = mkv_d->last_pts; - - dp->pos = demuxer->filepos; - dp->flags = block_bref ? 0 : 0x10; - ds_add_packet (demuxer->audio, dp); - } + track->audio_timestamp[track->sub_packet_cnt] = + (track->ra_pts == mkv_d->last_pts) ? 0 : (mkv_d->last_pts); + track->ra_pts = mkv_d->last_pts; + if (track->sub_packet_cnt == 0) + track->audio_filepos = demuxer->filepos; + if (++(track->sub_packet_cnt) == sph) { + int apk_usize = + ((WAVEFORMATEX *) ((sh_audio_t *) demuxer->audio->sh)->wf)->nBlockAlign; + track->sub_packet_cnt = 0; + // Release all the audio packets + for (x = 0; x < sph * w / apk_usize; x++) { + dp = new_demux_packet(apk_usize); + memcpy(dp->buffer, track->audio_buf + x * apk_usize, + apk_usize); + /* Put timestamp only on packets that correspond to original + * audio packets in file */ + dp->pts = (x * apk_usize % w) ? 0 : + track->audio_timestamp[x * apk_usize / w]; + dp->pos = track->audio_filepos; // all equal + dp->flags = x ? 0 : 0x10; // Mark first packet as keyframe + ds_add_packet(demuxer->audio, dp); + } + } + } else { // Not a codec that require reordering + dp = new_demux_packet(size); + memcpy(dp->buffer, buffer, size); + if (track->ra_pts == mkv_d->last_pts && !mkv_d->a_skip_to_keyframe) + dp->pts = 0; + else + dp->pts = mkv_d->last_pts; + track->ra_pts = mkv_d->last_pts; + + dp->pos = demuxer->filepos; + dp->flags = block_bref ? 0 : 0x10; + ds_add_packet(demuxer->audio, dp); + } } /** Reorder timecodes and add cached demux packets to the queues. @@ -2532,28 +2402,27 @@ * \param demuxer The Matroska demuxer struct for this instance. * \param track The track structure whose cache should be handled. */ -static void -flush_cached_dps (demuxer_t *demuxer, mkv_track_t *track) +static void flush_cached_dps(demuxer_t *demuxer, mkv_track_t *track) { - int i, ok; - - if (track->num_cached_dps == 0) - return; - - do { - ok = 1; - for (i = 1; i < track->num_cached_dps; i++) - if (track->cached_dps[i - 1]->pts > track->cached_dps[i]->pts) { - float tmp_pts = track->cached_dps[i - 1]->pts; - track->cached_dps[i - 1]->pts = track->cached_dps[i]->pts; - track->cached_dps[i]->pts = tmp_pts; - ok = 0; - } - } while (!ok); - - for (i = 0; i < track->num_cached_dps; i++) - ds_add_packet (demuxer->video, track->cached_dps[i]); - track->num_cached_dps = 0; + int i, ok; + + if (track->num_cached_dps == 0) + return; + + do { + ok = 1; + for (i = 1; i < track->num_cached_dps; i++) + if (track->cached_dps[i - 1]->pts > track->cached_dps[i]->pts) { + float tmp_pts = track->cached_dps[i - 1]->pts; + track->cached_dps[i - 1]->pts = track->cached_dps[i]->pts; + track->cached_dps[i]->pts = tmp_pts; + ok = 0; + } + } while (!ok); + + for (i = 0; i < track->num_cached_dps; i++) + ds_add_packet(demuxer->video, track->cached_dps[i]); + track->num_cached_dps = 0; } /** Cache video frames if timecodes have to be reordered. @@ -2576,574 +2445,534 @@ * then the frame is either an I frame or a P frame depending on the value * of \a block_bref. Otherwise it's a B frame. */ -static void -handle_video_bframes (demuxer_t *demuxer, mkv_track_t *track, uint8_t *buffer, - uint32_t size, int block_bref, int block_fref) +static void handle_video_bframes(demuxer_t *demuxer, mkv_track_t *track, + uint8_t *buffer, uint32_t size, + int block_bref, int block_fref) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - demux_packet_t *dp; - - dp = new_demux_packet (size); - memcpy(dp->buffer, buffer, size); - dp->pos = demuxer->filepos; - dp->pts = mkv_d->last_pts; - if ((track->num_cached_dps > 0) && (dp->pts < track->max_pts)) - block_fref = 1; - if (block_fref == 0) /* I or P frame */ - flush_cached_dps (demuxer, track); - if (block_bref != 0) /* I frame, don't cache it */ - dp->flags = 0x10; - if ((track->num_cached_dps + 1) > track->num_allocated_dps) - { - track->cached_dps = (demux_packet_t **) - realloc(track->cached_dps, (track->num_cached_dps + 10) * - sizeof(demux_packet_t *)); - track->num_allocated_dps += 10; + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + demux_packet_t *dp; + + dp = new_demux_packet(size); + memcpy(dp->buffer, buffer, size); + dp->pos = demuxer->filepos; + dp->pts = mkv_d->last_pts; + if ((track->num_cached_dps > 0) && (dp->pts < track->max_pts)) + block_fref = 1; + if (block_fref == 0) /* I or P frame */ + flush_cached_dps(demuxer, track); + if (block_bref != 0) /* I frame, don't cache it */ + dp->flags = 0x10; + if ((track->num_cached_dps + 1) > track->num_allocated_dps) { + track->cached_dps = (demux_packet_t **) + realloc(track->cached_dps, + (track->num_cached_dps + 10) * sizeof(demux_packet_t *)); + track->num_allocated_dps += 10; } - track->cached_dps[track->num_cached_dps] = dp; - track->num_cached_dps++; - if (dp->pts > track->max_pts) - track->max_pts = dp->pts; + track->cached_dps[track->num_cached_dps] = dp; + track->num_cached_dps++; + if (dp->pts > track->max_pts) + track->max_pts = dp->pts; } -static int -handle_block (demuxer_t *demuxer, uint8_t *block, uint64_t length, - uint64_t block_duration, int64_t block_bref, int64_t block_fref, uint8_t simpleblock) +static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length, + uint64_t block_duration, int64_t block_bref, + int64_t block_fref, uint8_t simpleblock) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - mkv_track_t *track = NULL; - demux_stream_t *ds = NULL; - uint64_t old_length; - int64_t tc; - uint32_t *lace_size; - uint8_t laces, flags; - int i, num, tmp, use_this_block = 1; - float current_pts; - int16_t time; - - /* first byte(s): track num */ - num = ebml_read_vlen_uint (block, &tmp); - block += tmp; - /* time (relative to cluster time) */ - time = block[0] << 8 | block[1]; - block += 2; - length -= tmp + 2; - old_length = length; - flags = block[0]; - if (demux_mkv_read_block_lacing (block, &length, &laces, &lace_size)) - return 0; - block += old_length - length; - - tc = ((time*mkv_d->tc_scale+mkv_d->cluster_tc) /1000000.0 - mkv_d->first_tc); - if (tc < 0) - tc = 0; - if (mkv_d->stop_timecode > 0 && tc > mkv_d->stop_timecode) { - free(lace_size); - return -1; - } - current_pts = tc / 1000.0; - - for (i=0; i<mkv_d->num_tracks; i++) - if (mkv_d->tracks[i]->tnum == num) { - track = mkv_d->tracks[i]; - break; + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + mkv_track_t *track = NULL; + demux_stream_t *ds = NULL; + uint64_t old_length; + int64_t tc; + uint32_t *lace_size; + uint8_t laces, flags; + int i, num, tmp, use_this_block = 1; + float current_pts; + int16_t time; + + /* first byte(s): track num */ + num = ebml_read_vlen_uint(block, &tmp); + block += tmp; + /* time (relative to cluster time) */ + time = block[0] << 8 | block[1]; + block += 2; + length -= tmp + 2; + old_length = length; + flags = block[0]; + if (demux_mkv_read_block_lacing(block, &length, &laces, &lace_size)) + return 0; + block += old_length - length; + + tc = ((time * mkv_d->tc_scale + mkv_d->cluster_tc) / 1000000.0 - + mkv_d->first_tc); + if (tc < 0) + tc = 0; + if (mkv_d->stop_timecode > 0 && tc > mkv_d->stop_timecode) { + free(lace_size); + return -1; } - if (track == NULL) - { - free(lace_size); - return 1; - } - if (num == demuxer->audio->id) - { - ds = demuxer->audio; - - if (mkv_d->a_skip_to_keyframe) - { - if (simpleblock) - { - if (!(flags&0x80)) /*current frame isn't a keyframe*/ - use_this_block = 0; - } - else if (block_bref != 0) - use_this_block = 0; + current_pts = tc / 1000.0; + + for (i = 0; i < mkv_d->num_tracks; i++) + if (mkv_d->tracks[i]->tnum == num) { + track = mkv_d->tracks[i]; + break; } - else if (mkv_d->v_skip_to_keyframe) - use_this_block = 0; - - if (track->fix_i_bps && use_this_block) - { - sh_audio_t *sh = (sh_audio_t *) ds->sh; - - if (block_duration != 0) - { - sh->i_bps = length * 1000 / block_duration; - track->fix_i_bps = 0; - } - else if (track->qt_last_a_pts == 0.0) - track->qt_last_a_pts = current_pts; - else if(track->qt_last_a_pts != current_pts) - { - sh->i_bps = length / (current_pts - track->qt_last_a_pts); - track->fix_i_bps = 0; + if (track == NULL) { + free(lace_size); + return 1; + } + if (num == demuxer->audio->id) { + ds = demuxer->audio; + + if (mkv_d->a_skip_to_keyframe) { + if (simpleblock) { + if (!(flags & 0x80)) /*current frame isn't a keyframe */ + use_this_block = 0; + } else if (block_bref != 0) + use_this_block = 0; + } else if (mkv_d->v_skip_to_keyframe) + use_this_block = 0; + + if (track->fix_i_bps && use_this_block) { + sh_audio_t *sh = (sh_audio_t *) ds->sh; + + if (block_duration != 0) { + sh->i_bps = length * 1000 / block_duration; + track->fix_i_bps = 0; + } else if (track->qt_last_a_pts == 0.0) + track->qt_last_a_pts = current_pts; + else if (track->qt_last_a_pts != current_pts) { + sh->i_bps = length / (current_pts - track->qt_last_a_pts); + track->fix_i_bps = 0; } } - } - else if (tc < mkv_d->skip_to_timecode) - use_this_block = 0; - else if (num == demuxer->video->id) - { - ds = demuxer->video; - if (mkv_d->v_skip_to_keyframe) - { - if (simpleblock) - { - if (!(flags&0x80)) /*current frame isn't a keyframe*/ + } else if (tc < mkv_d->skip_to_timecode) + use_this_block = 0; + else if (num == demuxer->video->id) { + ds = demuxer->video; + if (mkv_d->v_skip_to_keyframe) { + if (simpleblock) { + if (!(flags & 0x80)) /*current frame isn't a keyframe */ + use_this_block = 0; + } else if (block_bref != 0 || block_fref != 0) use_this_block = 0; - } - else if (block_bref != 0 || block_fref != 0) + } + } else if (num == demuxer->sub->id) { + ds = demuxer->sub; + if (track->subtitle_type != MATROSKA_SUBTYPE_VOBSUB) { + if (!mkv_d->v_skip_to_keyframe) + handle_subtitles(demuxer, track, block, length, block_duration, + tc); use_this_block = 0; } - } - else if (num == demuxer->sub->id) - { - ds = demuxer->sub; - if (track->subtitle_type != MATROSKA_SUBTYPE_VOBSUB) - { - if (!mkv_d->v_skip_to_keyframe) - handle_subtitles (demuxer, track, block, length, - block_duration, tc); - use_this_block = 0; - } - } - else - use_this_block = 0; - - if (use_this_block) - { - mkv_d->last_pts = current_pts; - mkv_d->last_filepos = demuxer->filepos; - - for (i=0; i < laces; i++) - { - if (ds == demuxer->video && track->realmedia) - handle_realvideo (demuxer, track, block, lace_size[i], block_bref); - else if (ds == demuxer->audio && track->realmedia) - handle_realaudio (demuxer, track, block, lace_size[i], block_bref); - else if (ds == demuxer->video && track->reorder_timecodes) - handle_video_bframes (demuxer, track, block, lace_size[i], - block_bref, block_fref); - else - { - int modified, size = lace_size[i]; - demux_packet_t *dp; - uint8_t *buffer; - modified = demux_mkv_decode (track, block, &buffer, &size, 1); - if (buffer) - { - dp = new_demux_packet (size); - memcpy (dp->buffer, buffer, size); - if (modified) - free (buffer); - dp->flags = (block_bref == 0 && block_fref == 0) ? 0x10 : 0; - /* If default_duration is 0, assume no pts value is known - * for packets after the first one (rather than all pts - * values being the same) */ - if (i == 0 || track->default_duration) - dp->pts = mkv_d->last_pts + i * track->default_duration; - ds_add_packet (ds, dp); + } else + use_this_block = 0; + + if (use_this_block) { + mkv_d->last_pts = current_pts; + mkv_d->last_filepos = demuxer->filepos; + + for (i = 0; i < laces; i++) { + if (ds == demuxer->video && track->realmedia) + handle_realvideo(demuxer, track, block, lace_size[i], + block_bref); + else if (ds == demuxer->audio && track->realmedia) + handle_realaudio(demuxer, track, block, lace_size[i], + block_bref); + else if (ds == demuxer->video && track->reorder_timecodes) + handle_video_bframes(demuxer, track, block, lace_size[i], + block_bref, block_fref); + else { + int modified, size = lace_size[i]; + demux_packet_t *dp; + uint8_t *buffer; + modified = demux_mkv_decode(track, block, &buffer, &size, 1); + if (buffer) { + dp = new_demux_packet(size); + memcpy(dp->buffer, buffer, size); + if (modified) + free(buffer); + dp->flags = (block_bref == 0 + && block_fref == 0) ? 0x10 : 0; + /* If default_duration is 0, assume no pts value is known + * for packets after the first one (rather than all pts + * values being the same) */ + if (i == 0 || track->default_duration) + dp->pts = + mkv_d->last_pts + i * track->default_duration; + ds_add_packet(ds, dp); } } - block += lace_size[i]; - } - - if (ds == demuxer->video) - { - mkv_d->v_skip_to_keyframe = 0; - mkv_d->skip_to_timecode = 0; + block += lace_size[i]; } - else if (ds == demuxer->audio) - mkv_d->a_skip_to_keyframe = 0; - - free(lace_size); - return 1; + + if (ds == demuxer->video) { + mkv_d->v_skip_to_keyframe = 0; + mkv_d->skip_to_timecode = 0; + } else if (ds == demuxer->audio) + mkv_d->a_skip_to_keyframe = 0; + + free(lace_size); + return 1; } - free(lace_size); - return 0; + free(lace_size); + return 0; } -static int -demux_mkv_fill_buffer (demuxer_t *demuxer, demux_stream_t *ds) +static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - stream_t *s = demuxer->stream; - uint64_t l; - int il, tmp; - - while (1) - { - while (mkv_d->cluster_size > 0) - { - uint64_t block_duration = 0, block_length = 0; - int64_t block_bref = 0, block_fref = 0; - uint8_t *block = NULL; - - while (mkv_d->blockgroup_size > 0) - { - switch (ebml_read_id (s, &il)) - { + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + stream_t *s = demuxer->stream; + uint64_t l; + int il, tmp; + + while (1) { + while (mkv_d->cluster_size > 0) { + uint64_t block_duration = 0, block_length = 0; + int64_t block_bref = 0, block_fref = 0; + uint8_t *block = NULL; + + while (mkv_d->blockgroup_size > 0) { + switch (ebml_read_id(s, &il)) { case MATROSKA_ID_BLOCKDURATION: - { - block_duration = ebml_read_uint (s, &l); + block_duration = ebml_read_uint(s, &l); if (block_duration == EBML_UINT_INVALID) { - free(block); - return 0; + free(block); + return 0; } block_duration *= mkv_d->tc_scale / 1000000.0; break; - } case MATROSKA_ID_BLOCK: - block_length = ebml_read_length (s, &tmp); - free(block); - if (block_length > SIZE_MAX - AV_LZO_INPUT_PADDING) return 0; - block = malloc (block_length + AV_LZO_INPUT_PADDING); - demuxer->filepos = stream_tell (s); - if (stream_read (s,block,block_length) != (int) block_length) - { + block_length = ebml_read_length(s, &tmp); free(block); - return 0; - } - l = tmp + block_length; - break; + if (block_length > SIZE_MAX - AV_LZO_INPUT_PADDING) + return 0; + block = malloc(block_length + AV_LZO_INPUT_PADDING); + demuxer->filepos = stream_tell(s); + if (stream_read(s, block, block_length) != + (int) block_length) { + free(block); + return 0; + } + l = tmp + block_length; + break; case MATROSKA_ID_REFERENCEBLOCK: - { - int64_t num = ebml_read_int (s, &l); + { + int64_t num = ebml_read_int(s, &l); if (num == EBML_INT_INVALID) { - free(block); - return 0; + free(block); + return 0; } if (num <= 0) - block_bref = num; + block_bref = num; else - block_fref = num; + block_fref = num; break; - } + } case EBML_ID_INVALID: - free(block); - return 0; + free(block); + return 0; default: - ebml_read_skip (s, &l); - break; + ebml_read_skip(s, &l); + break; } - mkv_d->blockgroup_size -= l + il; - mkv_d->cluster_size -= l + il; + mkv_d->blockgroup_size -= l + il; + mkv_d->cluster_size -= l + il; } - if (block) - { - int res = handle_block (demuxer, block, block_length, - block_duration, block_bref, block_fref, 0); - free (block); - if (res < 0) - return 0; - if (res) - return 1; + if (block) { + int res = handle_block(demuxer, block, block_length, + block_duration, block_bref, block_fref, + 0); + free(block); + if (res < 0) + return 0; + if (res) + return 1; } - if (mkv_d->cluster_size > 0) - { - switch (ebml_read_id (s, &il)) - { + if (mkv_d->cluster_size > 0) { + switch (ebml_read_id(s, &il)) { case MATROSKA_ID_CLUSTERTIMECODE: - { - uint64_t num = ebml_read_uint (s, &l); + { + uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) - return 0; - if (!mkv_d->has_first_tc) - { + return 0; + if (!mkv_d->has_first_tc) { mkv_d->first_tc = num * mkv_d->tc_scale / 1000000.0; mkv_d->has_first_tc = 1; - } + } mkv_d->cluster_tc = num * mkv_d->tc_scale; break; - } + } case MATROSKA_ID_BLOCKGROUP: - mkv_d->blockgroup_size = ebml_read_length (s, &tmp); - l = tmp; - break; + mkv_d->blockgroup_size = ebml_read_length(s, &tmp); + l = tmp; + break; case MATROSKA_ID_SIMPLEBLOCK: - { + { int res; - block_length = ebml_read_length (s, &tmp); - block = malloc (block_length); - demuxer->filepos = stream_tell (s); - if (stream_read (s,block,block_length) != (int) block_length) - { - free(block); - return 0; + block_length = ebml_read_length(s, &tmp); + block = malloc(block_length); + demuxer->filepos = stream_tell(s); + if (stream_read(s, block, block_length) != + (int) block_length) { + free(block); + return 0; } l = tmp + block_length; - res = handle_block (demuxer, block, block_length, - block_duration, block_bref, block_fref, 1); - free (block); + res = handle_block(demuxer, block, block_length, + block_duration, block_bref, + block_fref, 1); + free(block); mkv_d->cluster_size -= l + il; if (res < 0) - return 0; + return 0; else if (res) - return 1; - else mkv_d->cluster_size += l + il; + return 1; + else + mkv_d->cluster_size += l + il; break; - } + } case EBML_ID_INVALID: - return 0; + return 0; default: - ebml_read_skip (s, &l); - break; + ebml_read_skip(s, &l); + break; } - mkv_d->cluster_size -= l + il; + mkv_d->cluster_size -= l + il; } } - if (ebml_read_id (s, &il) != MATROSKA_ID_CLUSTER) - return 0; - add_cluster_position(mkv_d, stream_tell(s)-il); - mkv_d->cluster_size = ebml_read_length (s, NULL); + if (ebml_read_id(s, &il) != MATROSKA_ID_CLUSTER) + return 0; + add_cluster_position(mkv_d, stream_tell(s) - il); + mkv_d->cluster_size = ebml_read_length(s, NULL); } - return 0; + return 0; } -static void -demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) +static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, + float audio_delay, int flags) { - free_cached_dps (demuxer); - if (!(flags & SEEK_FACTOR)) /* time in secs */ - { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - stream_t *s = demuxer->stream; - int64_t target_timecode = 0, diff, min_diff=0xFFFFFFFFFFFFFFFLL; - int i; - - if (!(flags & SEEK_ABSOLUTE)) /* relative seek */ - target_timecode = (int64_t) (mkv_d->last_pts * 1000.0); - target_timecode += (int64_t)(rel_seek_secs * 1000.0); - if (target_timecode < 0) - target_timecode = 0; - - if (mkv_d->indexes == NULL) /* no index was found */ - { - uint64_t target_filepos, cluster_pos, max_pos; - - target_filepos = (uint64_t) (target_timecode * mkv_d->last_filepos - / (mkv_d->last_pts * 1000.0)); - - max_pos = mkv_d->num_cluster_pos ? mkv_d->cluster_positions[mkv_d->num_cluster_pos-1] : 0; - if (target_filepos > max_pos) - { - if ((off_t) max_pos > stream_tell (s)) - stream_seek (s, max_pos); - else - stream_seek (s, stream_tell (s) + mkv_d->cluster_size); - /* parse all the clusters upto target_filepos */ - while (!s->eof && stream_tell(s) < (off_t) target_filepos) - { - switch (ebml_read_id (s, &i)) - { + free_cached_dps(demuxer); + if (!(flags & SEEK_FACTOR)) { /* time in secs */ + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + stream_t *s = demuxer->stream; + int64_t target_timecode = 0, diff, min_diff = 0xFFFFFFFFFFFFFFFLL; + int i; + + if (!(flags & SEEK_ABSOLUTE)) /* relative seek */ + target_timecode = (int64_t) (mkv_d->last_pts * 1000.0); + target_timecode += (int64_t) (rel_seek_secs * 1000.0); + if (target_timecode < 0) + target_timecode = 0; + + if (mkv_d->indexes == NULL) { /* no index was found */ + uint64_t target_filepos, cluster_pos, max_pos; + + target_filepos = + (uint64_t) (target_timecode * mkv_d->last_filepos / + (mkv_d->last_pts * 1000.0)); + + max_pos = mkv_d->num_cluster_pos ? + mkv_d->cluster_positions[mkv_d->num_cluster_pos - 1] : 0; + if (target_filepos > max_pos) { + if ((off_t) max_pos > stream_tell(s)) + stream_seek(s, max_pos); + else + stream_seek(s, stream_tell(s) + mkv_d->cluster_size); + /* parse all the clusters upto target_filepos */ + while (!s->eof && stream_tell(s) < (off_t) target_filepos) { + switch (ebml_read_id(s, &i)) { case MATROSKA_ID_CLUSTER: - add_cluster_position(mkv_d, (uint64_t) stream_tell(s)-i); - break; + add_cluster_position(mkv_d, + (uint64_t) stream_tell(s) - i); + break; case MATROSKA_ID_CUES: - demux_mkv_read_cues (demuxer); - break; + demux_mkv_read_cues(demuxer); + break; } - ebml_read_skip (s, NULL); + ebml_read_skip(s, NULL); } - if (s->eof) - stream_reset(s); + if (s->eof) + stream_reset(s); } - if (mkv_d->indexes == NULL) - { - cluster_pos = mkv_d->cluster_positions[0]; - /* Let's find the nearest cluster */ - for (i=0; i < mkv_d->num_cluster_pos; i++) - { - diff = mkv_d->cluster_positions[i] - target_filepos; - if (rel_seek_secs < 0 && diff < 0 && -diff < min_diff) - { - cluster_pos = mkv_d->cluster_positions[i]; - min_diff = -diff; - } - else if (rel_seek_secs > 0 - && (diff < 0 ? -1 * diff : diff) < min_diff) - { - cluster_pos = mkv_d->cluster_positions[i]; - min_diff = diff < 0 ? -1 * diff : diff; + if (mkv_d->indexes == NULL) { + cluster_pos = mkv_d->cluster_positions[0]; + /* Let's find the nearest cluster */ + for (i = 0; i < mkv_d->num_cluster_pos; i++) { + diff = mkv_d->cluster_positions[i] - target_filepos; + if (rel_seek_secs < 0 && diff < 0 && -diff < min_diff) { + cluster_pos = mkv_d->cluster_positions[i]; + min_diff = -diff; + } else if (rel_seek_secs > 0 + && (diff < 0 ? -1 * diff : diff) < min_diff) { + cluster_pos = mkv_d->cluster_positions[i]; + min_diff = diff < 0 ? -1 * diff : diff; } } - mkv_d->cluster_size = mkv_d->blockgroup_size = 0; - stream_seek (s, cluster_pos); + mkv_d->cluster_size = mkv_d->blockgroup_size = 0; + stream_seek(s, cluster_pos); } - } - else - { - mkv_index_t *index = NULL; - int seek_id = (demuxer->video->id < 0) ? demuxer->audio->id : demuxer->video->id; - - /* let's find the entry in the indexes with the smallest */ - /* difference to the wanted timecode. */ - for (i=0; i < mkv_d->num_indexes; i++) - if (mkv_d->indexes[i].tnum == seek_id) - { - diff = target_timecode + mkv_d->first_tc - - (int64_t) mkv_d->indexes[i].timecode * mkv_d->tc_scale / 1000000.0; - - if ((flags & SEEK_ABSOLUTE || target_timecode <= mkv_d->last_pts*1000)) { - // Absolute seek or seek backward: find the last index - // position before target time - if (diff < 0 || diff >= min_diff) - continue; - } - else { - // Relative seek forward: find the first index position - // after target time. If no such index exists, find last - // position between current position and target time. - if (diff <= 0) { - if (min_diff <= 0 && diff <= min_diff) + } else { + mkv_index_t *index = NULL; + int seek_id = (demuxer->video->id < 0) ? + demuxer->audio->id : demuxer->video->id; + + /* let's find the entry in the indexes with the smallest */ + /* difference to the wanted timecode. */ + for (i = 0; i < mkv_d->num_indexes; i++) + if (mkv_d->indexes[i].tnum == seek_id) { + diff = + target_timecode + mkv_d->first_tc - + (int64_t) mkv_d->indexes[i].timecode * + mkv_d->tc_scale / 1000000.0; + + if ((flags & SEEK_ABSOLUTE + || target_timecode <= mkv_d->last_pts * 1000)) { + // Absolute seek or seek backward: find the last index + // position before target time + if (diff < 0 || diff >= min_diff) + continue; + } else { + // Relative seek forward: find the first index position + // after target time. If no such index exists, find last + // position between current position and target time. + if (diff <= 0) { + if (min_diff <= 0 && diff <= min_diff) + continue; + } else if (diff >= + FFMIN(target_timecode - mkv_d->last_pts, + min_diff)) continue; } - else if (diff >= FFMIN(target_timecode - mkv_d->last_pts, - min_diff)) - continue; + min_diff = diff; + index = mkv_d->indexes + i; } - min_diff = diff; - index = mkv_d->indexes + i; - } - - if (index) /* We've found an entry. */ - { - mkv_d->cluster_size = mkv_d->blockgroup_size = 0; - stream_seek (s, index->filepos); + + if (index) { /* We've found an entry. */ + mkv_d->cluster_size = mkv_d->blockgroup_size = 0; + stream_seek(s, index->filepos); } } - if (demuxer->video->id >= 0) - mkv_d->v_skip_to_keyframe = 1; - if (rel_seek_secs > 0.0) - mkv_d->skip_to_timecode = target_timecode; - mkv_d->a_skip_to_keyframe = 1; - - demux_mkv_fill_buffer(demuxer, NULL); - } - else if ((demuxer->movi_end <= 0) || !(flags & SEEK_ABSOLUTE)) - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] seek unsupported flags\n"); - else - { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - stream_t *s = demuxer->stream; - uint64_t target_filepos; - mkv_index_t *index = NULL; - int i; - - if (mkv_d->indexes == NULL) /* no index was found */ - { /* I'm lazy... */ - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] seek unsupported flags\n"); - return; + if (demuxer->video->id >= 0) + mkv_d->v_skip_to_keyframe = 1; + if (rel_seek_secs > 0.0) + mkv_d->skip_to_timecode = target_timecode; + mkv_d->a_skip_to_keyframe = 1; + + demux_mkv_fill_buffer(demuxer, NULL); + } else if ((demuxer->movi_end <= 0) || !(flags & SEEK_ABSOLUTE)) + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] seek unsupported flags\n"); + else { + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + stream_t *s = demuxer->stream; + uint64_t target_filepos; + mkv_index_t *index = NULL; + int i; + + if (mkv_d->indexes == NULL) { /* no index was found *//* I'm lazy... */ + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] seek unsupported flags\n"); + return; } - target_filepos = (uint64_t)(demuxer->movi_end * rel_seek_secs); - for (i=0; i < mkv_d->num_indexes; i++) - if (mkv_d->indexes[i].tnum == demuxer->video->id) - if ((index == NULL) || - ((mkv_d->indexes[i].filepos >= target_filepos) && - ((index->filepos < target_filepos) || - (mkv_d->indexes[i].filepos < index->filepos)))) - index = &mkv_d->indexes[i]; - - if (!index) - return; - - mkv_d->cluster_size = mkv_d->blockgroup_size = 0; - stream_seek (s, index->filepos); - - if (demuxer->video->id >= 0) - mkv_d->v_skip_to_keyframe = 1; - mkv_d->skip_to_timecode = index->timecode; - mkv_d->a_skip_to_keyframe = 1; - - demux_mkv_fill_buffer(demuxer, NULL); + target_filepos = (uint64_t) (demuxer->movi_end * rel_seek_secs); + for (i = 0; i < mkv_d->num_indexes; i++) + if (mkv_d->indexes[i].tnum == demuxer->video->id) + if ((index == NULL) + || ((mkv_d->indexes[i].filepos >= target_filepos) + && ((index->filepos < target_filepos) + || (mkv_d->indexes[i].filepos < index->filepos)))) + index = &mkv_d->indexes[i]; + + if (!index) + return; + + mkv_d->cluster_size = mkv_d->blockgroup_size = 0; + stream_seek(s, index->filepos); + + if (demuxer->video->id >= 0) + mkv_d->v_skip_to_keyframe = 1; + mkv_d->skip_to_timecode = index->timecode; + mkv_d->a_skip_to_keyframe = 1; + + demux_mkv_fill_buffer(demuxer, NULL); } } -static int -demux_mkv_control (demuxer_t *demuxer, int cmd, void *arg) +static int demux_mkv_control(demuxer_t *demuxer, int cmd, void *arg) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - - switch (cmd) - { + mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; + + switch (cmd) { case DEMUXER_CTRL_CORRECT_PTS: - return DEMUXER_CTRL_OK; + return DEMUXER_CTRL_OK; case DEMUXER_CTRL_GET_TIME_LENGTH: - if (mkv_d->duration == 0) - return DEMUXER_CTRL_DONTKNOW; - - *((double *)arg) = (double)mkv_d->duration; - return DEMUXER_CTRL_OK; + if (mkv_d->duration == 0) + return DEMUXER_CTRL_DONTKNOW; + + *((double *) arg) = (double) mkv_d->duration; + return DEMUXER_CTRL_OK; case DEMUXER_CTRL_GET_PERCENT_POS: - if (mkv_d->duration == 0) - { + if (mkv_d->duration == 0) { return DEMUXER_CTRL_DONTKNOW; } - *((int *) arg) = (int) (100 * mkv_d->last_pts / mkv_d->duration); - return DEMUXER_CTRL_OK; + *((int *) arg) = (int) (100 * mkv_d->last_pts / mkv_d->duration); + return DEMUXER_CTRL_OK; case DEMUXER_CTRL_SWITCH_AUDIO: - if (demuxer->audio && demuxer->audio->sh) { - sh_audio_t *sh = demuxer->a_streams[demuxer->audio->id]; - int aid = *(int*)arg; - if (aid < 0) - aid = (sh->aid + 1) % mkv_d->last_aid; - if (aid != sh->aid) { - mkv_track_t *track = demux_mkv_find_track_by_num (mkv_d, aid, MATROSKA_TRACK_AUDIO); - if (track) { - demuxer->audio->id = track->tnum; - sh = demuxer->a_streams[demuxer->audio->id]; - ds_free_packs(demuxer->audio); - } - } - *(int*)arg = sh->aid; - } else - *(int*)arg = -2; - return DEMUXER_CTRL_OK; + if (demuxer->audio && demuxer->audio->sh) { + sh_audio_t *sh = demuxer->a_streams[demuxer->audio->id]; + int aid = *(int *) arg; + if (aid < 0) + aid = (sh->aid + 1) % mkv_d->last_aid; + if (aid != sh->aid) { + mkv_track_t *track = + demux_mkv_find_track_by_num(mkv_d, aid, + MATROSKA_TRACK_AUDIO); + if (track) { + demuxer->audio->id = track->tnum; + sh = demuxer->a_streams[demuxer->audio->id]; + ds_free_packs(demuxer->audio); + } + } + *(int *) arg = sh->aid; + } else + *(int *) arg = -2; + return DEMUXER_CTRL_OK; default: - return DEMUXER_CTRL_NOTIMPL; + return DEMUXER_CTRL_NOTIMPL; } } const demuxer_desc_t demuxer_desc_matroska = { - "Matroska demuxer", - "mkv", - "Matroska", - "Aurelien Jacobs", - "", - DEMUXER_TYPE_MATROSKA, - 1, // safe autodetect - demux_mkv_open, - demux_mkv_fill_buffer, - NULL, - demux_close_mkv, - demux_mkv_seek, - demux_mkv_control + "Matroska demuxer", + "mkv", + "Matroska", + "Aurelien Jacobs", + "", + DEMUXER_TYPE_MATROSKA, + 1, // safe autodetect + demux_mkv_open, + demux_mkv_fill_buffer, + NULL, + demux_close_mkv, + demux_mkv_seek, + demux_mkv_control };
--- a/libmpdemux/ebml.c Thu May 27 16:13:53 2010 +0000 +++ b/libmpdemux/ebml.c Thu May 27 16:46:47 2010 +0000 @@ -39,161 +39,151 @@ * Read: the element content data ID. * Return: the ID. */ -uint32_t -ebml_read_id (stream_t *s, int *length) +uint32_t ebml_read_id(stream_t *s, int *length) { - int i, len_mask = 0x80; - uint32_t id; + int i, len_mask = 0x80; + uint32_t id; - for (i=0, id=stream_read_char (s); i<4 && !(id & len_mask); i++) - len_mask >>= 1; - if (i >= 4) - return EBML_ID_INVALID; - if (length) - *length = i + 1; - while (i--) - id = (id << 8) | stream_read_char (s); - return id; + for (i = 0, id = stream_read_char(s); i < 4 && !(id & len_mask); i++) + len_mask >>= 1; + if (i >= 4) + return EBML_ID_INVALID; + if (length) + *length = i + 1; + while (i--) + id = (id << 8) | stream_read_char(s); + return id; } /* * Read a variable length unsigned int. */ -uint64_t -ebml_read_vlen_uint (uint8_t *buffer, int *length) +uint64_t ebml_read_vlen_uint(uint8_t *buffer, int *length) { - int i, j, num_ffs = 0, len_mask = 0x80; - uint64_t num; + int i, j, num_ffs = 0, len_mask = 0x80; + uint64_t num; - for (i=0, num=*buffer++; i<8 && !(num & len_mask); i++) - len_mask >>= 1; - if (i >= 8) - return EBML_UINT_INVALID; - j = i+1; - if (length) - *length = j; - if ((int)(num &= (len_mask - 1)) == len_mask - 1) - num_ffs++; - while (i--) - { - num = (num << 8) | *buffer++; - if ((num & 0xFF) == 0xFF) + for (i = 0, num = *buffer++; i < 8 && !(num & len_mask); i++) + len_mask >>= 1; + if (i >= 8) + return EBML_UINT_INVALID; + j = i + 1; + if (length) + *length = j; + if ((int) (num &= (len_mask - 1)) == len_mask - 1) num_ffs++; + while (i--) { + num = (num << 8) | *buffer++; + if ((num & 0xFF) == 0xFF) + num_ffs++; } - if (j == num_ffs) - return EBML_UINT_INVALID; - return num; + if (j == num_ffs) + return EBML_UINT_INVALID; + return num; } /* * Read a variable length signed int. */ -int64_t -ebml_read_vlen_int (uint8_t *buffer, int *length) +int64_t ebml_read_vlen_int(uint8_t *buffer, int *length) { - uint64_t unum; - int l; + uint64_t unum; + int l; - /* read as unsigned number first */ - unum = ebml_read_vlen_uint (buffer, &l); - if (unum == EBML_UINT_INVALID) - return EBML_INT_INVALID; - if (length) - *length = l; + /* read as unsigned number first */ + unum = ebml_read_vlen_uint(buffer, &l); + if (unum == EBML_UINT_INVALID) + return EBML_INT_INVALID; + if (length) + *length = l; - return unum - ((1 << ((7 * l) - 1)) - 1); + return unum - ((1 << ((7 * l) - 1)) - 1); } /* * Read: element content length. */ -uint64_t -ebml_read_length (stream_t *s, int *length) +uint64_t ebml_read_length(stream_t *s, int *length) { - int i, j, num_ffs = 0, len_mask = 0x80; - uint64_t len; + int i, j, num_ffs = 0, len_mask = 0x80; + uint64_t len; - for (i=0, len=stream_read_char (s); i<8 && !(len & len_mask); i++) - len_mask >>= 1; - if (i >= 8) - return EBML_UINT_INVALID; - j = i+1; - if (length) - *length = j; - if ((int)(len &= (len_mask - 1)) == len_mask - 1) - num_ffs++; - while (i--) - { - len = (len << 8) | stream_read_char (s); - if ((len & 0xFF) == 0xFF) + for (i = 0, len = stream_read_char(s); i < 8 && !(len & len_mask); i++) + len_mask >>= 1; + if (i >= 8) + return EBML_UINT_INVALID; + j = i + 1; + if (length) + *length = j; + if ((int) (len &= (len_mask - 1)) == len_mask - 1) num_ffs++; + while (i--) { + len = (len << 8) | stream_read_char(s); + if ((len & 0xFF) == 0xFF) + num_ffs++; } - if (j == num_ffs) - return EBML_UINT_INVALID; - return len; + if (j == num_ffs) + return EBML_UINT_INVALID; + return len; } /* * Read the next element as an unsigned int. */ -uint64_t -ebml_read_uint (stream_t *s, uint64_t *length) +uint64_t ebml_read_uint(stream_t *s, uint64_t *length) { - uint64_t len, value = 0; - int l; + uint64_t len, value = 0; + int l; - len = ebml_read_length (s, &l); - if (len == EBML_UINT_INVALID || len < 1 || len > 8) - return EBML_UINT_INVALID; - if (length) - *length = len + l; + len = ebml_read_length(s, &l); + if (len == EBML_UINT_INVALID || len < 1 || len > 8) + return EBML_UINT_INVALID; + if (length) + *length = len + l; - while (len--) - value = (value << 8) | stream_read_char (s); + while (len--) + value = (value << 8) | stream_read_char(s); - return value; + return value; } /* * Read the next element as a signed int. */ -int64_t -ebml_read_int (stream_t *s, uint64_t *length) +int64_t ebml_read_int(stream_t *s, uint64_t *length) { - int64_t value = 0; - uint64_t len; - int l; + int64_t value = 0; + uint64_t len; + int l; - len = ebml_read_length (s, &l); - if (len == EBML_UINT_INVALID || len < 1 || len > 8) - return EBML_INT_INVALID; - if (length) - *length = len + l; + len = ebml_read_length(s, &l); + if (len == EBML_UINT_INVALID || len < 1 || len > 8) + return EBML_INT_INVALID; + if (length) + *length = len + l; - len--; - l = stream_read_char (s); - if (l & 0x80) - value = -1; - value = (value << 8) | l; - while (len--) - value = (value << 8) | stream_read_char (s); + len--; + l = stream_read_char(s); + if (l & 0x80) + value = -1; + value = (value << 8) | l; + while (len--) + value = (value << 8) | stream_read_char(s); - return value; + return value; } /* * Read the next element as a float. */ -long double -ebml_read_float (stream_t *s, uint64_t *length) +long double ebml_read_float(stream_t *s, uint64_t *length) { - long double value; - uint64_t len; - int l; + long double value; + uint64_t len; + int l; - len = ebml_read_length (s, &l); - switch (len) - { + len = ebml_read_length(s, &l); + switch (len) { case 4: value = av_int2flt(stream_read_dword(s)); break; @@ -203,168 +193,160 @@ break; default: - return EBML_FLOAT_INVALID; + return EBML_FLOAT_INVALID; } - if (length) - *length = len + l; + if (length) + *length = len + l; - return value; + return value; } /* * Read the next element as an ASCII string. */ -char * -ebml_read_ascii (stream_t *s, uint64_t *length) +char *ebml_read_ascii(stream_t *s, uint64_t *length) { - uint64_t len; - char *str; - int l; + uint64_t len; + char *str; + int l; - len = ebml_read_length (s, &l); - if (len == EBML_UINT_INVALID) - return NULL; - if (len > SIZE_MAX - 1) - return NULL; - if (length) - *length = len + l; + len = ebml_read_length(s, &l); + if (len == EBML_UINT_INVALID) + return NULL; + if (len > SIZE_MAX - 1) + return NULL; + if (length) + *length = len + l; - str = malloc (len + 1); - if (stream_read(s, str, len) != (int) len) - { - free (str); - return NULL; + str = malloc(len + 1); + if (stream_read(s, str, len) != (int) len) { + free(str); + return NULL; } - str[len] = '\0'; + str[len] = '\0'; - return str; + return str; } /* * Read the next element as a UTF-8 string. */ -char * -ebml_read_utf8 (stream_t *s, uint64_t *length) +char *ebml_read_utf8(stream_t *s, uint64_t *length) { - return ebml_read_ascii (s, length); + return ebml_read_ascii(s, length); } /* * Skip the next element. */ -int -ebml_read_skip (stream_t *s, uint64_t *length) +int ebml_read_skip(stream_t *s, uint64_t *length) { - uint64_t len; - int l; + uint64_t len; + int l; - len = ebml_read_length (s, &l); - if (len == EBML_UINT_INVALID) - return 1; - if (length) - *length = len + l; + len = ebml_read_length(s, &l); + if (len == EBML_UINT_INVALID) + return 1; + if (length) + *length = len + l; - stream_skip(s, len); + stream_skip(s, len); - return 0; + return 0; } /* * Read the next element, but only the header. The contents * are supposed to be sub-elements which can be read separately. */ -uint32_t -ebml_read_master (stream_t *s, uint64_t *length) +uint32_t ebml_read_master(stream_t *s, uint64_t *length) { - uint64_t len; - uint32_t id; + uint64_t len; + uint32_t id; + + id = ebml_read_id(s, NULL); + if (id == EBML_ID_INVALID) + return id; - id = ebml_read_id (s, NULL); - if (id == EBML_ID_INVALID) + len = ebml_read_length(s, NULL); + if (len == EBML_UINT_INVALID) + return EBML_ID_INVALID; + if (length) + *length = len; + return id; - - len = ebml_read_length (s, NULL); - if (len == EBML_UINT_INVALID) - return EBML_ID_INVALID; - if (length) - *length = len; - - return id; } /* * Read an EBML header. */ -char * -ebml_read_header (stream_t *s, int *version) +char *ebml_read_header(stream_t *s, int *version) { - uint64_t length, l, num; - uint32_t id; - char *str = NULL; + uint64_t length, l, num; + uint32_t id; + char *str = NULL; - if (ebml_read_master (s, &length) != EBML_ID_HEADER) - return 0; + if (ebml_read_master(s, &length) != EBML_ID_HEADER) + return 0; - if (version) - *version = 1; + if (version) + *version = 1; - while (length > 0) - { - id = ebml_read_id (s, NULL); - if (id == EBML_ID_INVALID) - return NULL; - length -= 2; + 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? */ + switch (id) { + /* is our read version uptodate? */ case EBML_ID_EBMLREADVERSION: - num = ebml_read_uint (s, &l); - if (num != EBML_VERSION) - return NULL; - break; + num = ebml_read_uint(s, &l); + if (num != EBML_VERSION) + return NULL; + break; - /* we only handle 8 byte lengths at max */ + /* 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; + num = ebml_read_uint(s, &l); + if (num != sizeof(uint64_t)) + return NULL; + break; - /* we handle 4 byte IDs at max */ + /* 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; + 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; + 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; + 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 */ + /* 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; + if (ebml_read_skip(s, &l)) + return NULL; + break; } - length -= l; + length -= l; } - return str; + return str; }