2004-01-19 20:16:10 +01:00
|
|
|
/*
|
2009-05-08 23:51:13 +02:00
|
|
|
* Matroska demuxer
|
|
|
|
* Copyright (C) 2004 Aurelien Jacobs <aurel@gnuage.org>
|
2004-01-19 20:16:10 +01:00
|
|
|
* Based on the one written by Ronald Bultje for gstreamer
|
2009-05-08 23:51:13 +02:00
|
|
|
* and on demux_mkv.cpp from Moritz Bunkus.
|
|
|
|
*
|
2015-04-13 09:36:54 +02:00
|
|
|
* This file is part of mpv.
|
2009-05-08 23:51:13 +02:00
|
|
|
*
|
demux_mkv: change license to LGPL
Most contributors have agreed. This claims it's based on gstreamer code,
but this was LGPL at the time (and still is). Contributors whose code
was removed were not accounted for. There are still some potentially
problematic cases:
06eee1b67 is potentially the most problematic case. Most of these
changes are gone due to mpv not using BITMAPINFOHEADER anymore. Some
of the other changes are rather trivial. If someone contests this and
claims that copyrightable changes are left, the original change can
simply be reverted.
62bfae140 has only 2 lines left: a "char *name;" struct field, and a
line that prints a message. All other code was removed. The parsing code
in particular was made declarative, which replaced reading this element
explicitly (and other elements, see 1b22101c77e). I'm putting the log
message under HAVE_GPL, but I don't think the declaration is
copyrightable, or the mere concept of reading this element. Redoing the
other 2 lines of code would result in the same program text.
d41e860ba was applied by someone who (potentially) disagreed. The patch
itself is from someone who did agree, though. It's unknown whether the
applier changed the patch. But it seems unlikely, and the change was
mostly rewritten.
50a86fcc3 all demux_mkv changes were reverted (old stdout slave mode)
3a406e94d same
2e40bfa13 the old MPlayer subtitle code was completely removed
316bb1d44 completely removed in 1cf4802c1d
87f93d9d7 same
11bfc6780 relative seeks were removed in 92ba630796
be54f4813 the corresponding demux_mkv code was removed in 5dabaaf093
efd53eed6 all internal vobsub handling is now in FFmpeg
d7f693a20 removed in f3db4b0b937
e8a1b3713 removed in 522ee6b7831
cfb890259 removed, see 6b1374b203 for analysis
c80808b5a same
2017-04-21 12:18:55 +02:00
|
|
|
* mpv is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
2009-05-08 23:51:13 +02:00
|
|
|
*
|
2015-04-13 09:36:54 +02:00
|
|
|
* mpv is distributed in the hope that it will be useful,
|
2009-05-08 23:51:13 +02:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
demux_mkv: change license to LGPL
Most contributors have agreed. This claims it's based on gstreamer code,
but this was LGPL at the time (and still is). Contributors whose code
was removed were not accounted for. There are still some potentially
problematic cases:
06eee1b67 is potentially the most problematic case. Most of these
changes are gone due to mpv not using BITMAPINFOHEADER anymore. Some
of the other changes are rather trivial. If someone contests this and
claims that copyrightable changes are left, the original change can
simply be reverted.
62bfae140 has only 2 lines left: a "char *name;" struct field, and a
line that prints a message. All other code was removed. The parsing code
in particular was made declarative, which replaced reading this element
explicitly (and other elements, see 1b22101c77e). I'm putting the log
message under HAVE_GPL, but I don't think the declaration is
copyrightable, or the mere concept of reading this element. Redoing the
other 2 lines of code would result in the same program text.
d41e860ba was applied by someone who (potentially) disagreed. The patch
itself is from someone who did agree, though. It's unknown whether the
applier changed the patch. But it seems unlikely, and the change was
mostly rewritten.
50a86fcc3 all demux_mkv changes were reverted (old stdout slave mode)
3a406e94d same
2e40bfa13 the old MPlayer subtitle code was completely removed
316bb1d44 completely removed in 1cf4802c1d
87f93d9d7 same
11bfc6780 relative seeks were removed in 92ba630796
be54f4813 the corresponding demux_mkv code was removed in 5dabaaf093
efd53eed6 all internal vobsub handling is now in FFmpeg
d7f693a20 removed in f3db4b0b937
e8a1b3713 removed in 522ee6b7831
cfb890259 removed, see 6b1374b203 for analysis
c80808b5a same
2017-04-21 12:18:55 +02:00
|
|
|
* GNU Lesser General Public License for more details.
|
2009-05-08 23:51:13 +02:00
|
|
|
*
|
demux_mkv: change license to LGPL
Most contributors have agreed. This claims it's based on gstreamer code,
but this was LGPL at the time (and still is). Contributors whose code
was removed were not accounted for. There are still some potentially
problematic cases:
06eee1b67 is potentially the most problematic case. Most of these
changes are gone due to mpv not using BITMAPINFOHEADER anymore. Some
of the other changes are rather trivial. If someone contests this and
claims that copyrightable changes are left, the original change can
simply be reverted.
62bfae140 has only 2 lines left: a "char *name;" struct field, and a
line that prints a message. All other code was removed. The parsing code
in particular was made declarative, which replaced reading this element
explicitly (and other elements, see 1b22101c77e). I'm putting the log
message under HAVE_GPL, but I don't think the declaration is
copyrightable, or the mere concept of reading this element. Redoing the
other 2 lines of code would result in the same program text.
d41e860ba was applied by someone who (potentially) disagreed. The patch
itself is from someone who did agree, though. It's unknown whether the
applier changed the patch. But it seems unlikely, and the change was
mostly rewritten.
50a86fcc3 all demux_mkv changes were reverted (old stdout slave mode)
3a406e94d same
2e40bfa13 the old MPlayer subtitle code was completely removed
316bb1d44 completely removed in 1cf4802c1d
87f93d9d7 same
11bfc6780 relative seeks were removed in 92ba630796
be54f4813 the corresponding demux_mkv code was removed in 5dabaaf093
efd53eed6 all internal vobsub handling is now in FFmpeg
d7f693a20 removed in f3db4b0b937
e8a1b3713 removed in 522ee6b7831
cfb890259 removed, see 6b1374b203 for analysis
c80808b5a same
2017-04-21 12:18:55 +02:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
2017-04-21 12:43:58 +02:00
|
|
|
*
|
|
|
|
* Parts under HAVE_GPL are licensed under GNU General Public License.
|
2004-01-19 20:16:10 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
2006-06-05 00:41:27 +02:00
|
|
|
#include <inttypes.h>
|
2009-03-16 22:30:48 +01:00
|
|
|
#include <stdbool.h>
|
2015-04-23 19:35:15 +02:00
|
|
|
#include <math.h>
|
demux_mkv: improve robustness against broken files
Fixes test7.mkv from the Matroska test file collection, as well as some
real broken files I've found in the wild. (Unfortunately, true recovery
requires resetting the decoders and playback state with a manual seek,
but it's still better than just exiting.)
If there are broken EBML elements, try harder to skip them correctly.
Do this by searching for the next cluster element. The cluster element
intentionally has a long ID, so it's a suitable element for
resynchronizing (mkvmerge does something similar).
We know that data is corrupt if the ID or length fields of an element
are malformed. Additionally, if skipping an unknown element goes past
the end of the file, we assume it's corrupt and undo the seek. Do this
because it often happens that corrupt data is interpreted as correct
EBML elements. Since these elements will have a ridiculous values in
their length fields due to the large value range that is possible
(0-2^56-2), they will go past the end of the file. So instead of
skipping them (which would result in playback termination), try to
find the next cluster instead. (We still skip unknown elements that
are within the file, as this is needed for correct operation. Also, we
first execute the seek, because we don't really know where the file
ends. Doing it this way is better for unseekable streams too, because
it will still work in the non-error case.)
This is done as special case in the packet reading function only. On
the other hand, that's the only part of the file that's read after
initialization is done.
2013-03-28 00:01:17 +01:00
|
|
|
#include <assert.h>
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2012-02-01 19:01:16 +01:00
|
|
|
#include <libavutil/common.h>
|
|
|
|
#include <libavutil/lzo.h>
|
|
|
|
#include <libavutil/intreadwrite.h>
|
|
|
|
#include <libavutil/avstring.h>
|
|
|
|
|
2013-12-27 20:00:24 +01:00
|
|
|
#include <libavcodec/avcodec.h>
|
2013-05-30 19:55:15 +02:00
|
|
|
#include <libavcodec/version.h>
|
|
|
|
|
2012-02-01 19:01:16 +01:00
|
|
|
#include "config.h"
|
|
|
|
|
2013-07-16 13:28:28 +02:00
|
|
|
#if HAVE_ZLIB
|
2012-02-01 19:01:16 +01:00
|
|
|
#include <zlib.h>
|
|
|
|
#endif
|
|
|
|
|
2016-01-11 19:03:40 +01:00
|
|
|
#include "mpv_talloc.h"
|
2013-12-27 20:00:24 +01:00
|
|
|
#include "common/av_common.h"
|
2016-09-06 20:09:56 +02:00
|
|
|
#include "options/m_config.h"
|
2015-04-23 19:21:17 +02:00
|
|
|
#include "options/m_option.h"
|
2014-08-29 12:09:04 +02:00
|
|
|
#include "misc/bstr.h"
|
2007-03-15 19:36:36 +01:00
|
|
|
#include "stream/stream.h"
|
2014-08-30 23:24:46 +02:00
|
|
|
#include "video/csputils.h"
|
2015-12-19 20:04:31 +01:00
|
|
|
#include "video/mp_image.h"
|
2012-11-09 01:06:43 +01:00
|
|
|
#include "demux.h"
|
2004-01-19 20:16:10 +01:00
|
|
|
#include "stheader.h"
|
|
|
|
#include "ebml.h"
|
|
|
|
#include "matroska.h"
|
2013-07-11 19:35:09 +02:00
|
|
|
#include "codec_tags.h"
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2013-12-17 02:39:45 +01:00
|
|
|
#include "common/msg.h"
|
2006-11-05 14:53:27 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
static const unsigned char sipr_swaps[38][2] = {
|
2006-04-03 21:41:17 +02:00
|
|
|
{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},
|
2009-12-29 20:06:21 +01:00
|
|
|
{77,80}
|
|
|
|
};
|
2006-04-03 21:41:17 +02:00
|
|
|
|
|
|
|
// Map flavour to bytes per second
|
|
|
|
#define SIPR_FLAVORS 4
|
|
|
|
#define ATRC_FLAVORS 8
|
|
|
|
#define COOK_FLAVORS 34
|
2009-12-29 20:06:21 +01:00
|
|
|
static const int sipr_fl2bps[SIPR_FLAVORS] = { 813, 1062, 625, 2000 };
|
2010-05-29 16:15:55 +02:00
|
|
|
static const int atrc_fl2bps[ATRC_FLAVORS] = {
|
|
|
|
8269, 11714, 13092, 16538, 18260, 22050, 33075, 44100 };
|
2008-04-12 17:51:11 +02:00
|
|
|
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,
|
2009-12-29 20:06:21 +01:00
|
|
|
12016, 16408, 22911, 33506
|
|
|
|
};
|
2006-04-03 21:41:17 +02:00
|
|
|
|
2013-04-12 16:07:45 +02:00
|
|
|
enum {
|
|
|
|
MAX_NUM_LACES = 256,
|
|
|
|
};
|
|
|
|
|
2010-01-26 15:05:49 +01:00
|
|
|
typedef struct mkv_content_encoding {
|
|
|
|
uint64_t order, type, scope;
|
|
|
|
uint64_t comp_algo;
|
2009-12-29 20:06:21 +01:00
|
|
|
uint8_t *comp_settings;
|
|
|
|
int comp_settings_len;
|
2004-01-19 20:16:10 +01:00
|
|
|
} mkv_content_encoding_t;
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
typedef struct mkv_track {
|
|
|
|
int tnum;
|
2016-08-12 21:39:32 +02:00
|
|
|
uint64_t uid;
|
2009-12-29 20:06:21 +01:00
|
|
|
char *name;
|
2013-04-14 19:23:18 +02:00
|
|
|
struct sh_stream *stream;
|
2009-07-07 01:26:13 +02:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
char *codec_id;
|
|
|
|
char *language;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
int type;
|
2009-07-07 01:26:13 +02:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
uint32_t v_width, v_height, v_dwidth, v_dheight;
|
2013-04-04 01:20:06 +02:00
|
|
|
bool v_dwidth_set, v_dheight_set;
|
2009-12-29 20:06:21 +01:00
|
|
|
double v_frate;
|
2013-01-24 16:57:21 +01:00
|
|
|
uint32_t colorspace;
|
2014-08-30 23:24:46 +02:00
|
|
|
int stereo_mode;
|
2016-11-08 02:24:49 +01:00
|
|
|
struct mp_colorspace color;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
uint32_t a_channels, a_bps;
|
|
|
|
float a_sfreq;
|
2010-11-21 13:52:08 +01:00
|
|
|
float a_osfreq;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
double default_duration;
|
2014-11-03 20:00:34 +01:00
|
|
|
double codec_delay;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
int default_track;
|
2015-06-27 22:02:24 +02:00
|
|
|
int forced_track;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
unsigned char *private_data;
|
|
|
|
unsigned int private_size;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2015-02-05 21:55:11 +01:00
|
|
|
bool parse;
|
|
|
|
int64_t parse_timebase;
|
2013-12-27 20:00:24 +01:00
|
|
|
void *parser_tmp;
|
|
|
|
AVCodecParserContext *av_parser;
|
|
|
|
AVCodecContext *av_parser_codec;
|
|
|
|
|
2016-12-19 21:29:46 +01:00
|
|
|
bool require_keyframes;
|
|
|
|
|
2015-02-05 21:55:11 +01:00
|
|
|
/* stuff for realaudio braincancer */
|
2009-12-29 20:06:21 +01:00
|
|
|
double ra_pts; /* previous audio timestamp */
|
2014-11-21 05:10:28 +01:00
|
|
|
uint32_t sub_packet_size; ///< sub packet size, per stream
|
|
|
|
uint32_t sub_packet_h; ///< number of coded frames per block
|
2014-06-29 23:22:07 +02:00
|
|
|
uint32_t coded_framesize; ///< coded frame size, per stream
|
2014-11-21 05:10:28 +01:00
|
|
|
uint32_t audiopk_size; ///< audio packet size
|
2009-12-29 20:06:21 +01:00
|
|
|
unsigned char *audio_buf; ///< place to store reordered audio data
|
|
|
|
double *audio_timestamp; ///< timestamp for each audio packet
|
2014-11-21 05:10:28 +01:00
|
|
|
uint32_t sub_packet_cnt; ///< number of subpacket already received
|
2009-12-29 20:06:21 +01:00
|
|
|
|
|
|
|
/* generic content encoding support */
|
|
|
|
mkv_content_encoding_t *encodings;
|
|
|
|
int num_encodings;
|
|
|
|
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
/* latest added index entry for this track */
|
2014-06-29 23:22:07 +02:00
|
|
|
size_t last_index_entry;
|
2004-01-19 20:16:10 +01:00
|
|
|
} mkv_track_t;
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
typedef struct mkv_index {
|
|
|
|
int tnum;
|
2016-01-27 21:08:53 +01:00
|
|
|
int64_t timecode, duration;
|
2014-11-05 20:44:21 +01:00
|
|
|
uint64_t filepos; // position of the cluster which contains the packet
|
2004-01-19 20:16:10 +01:00
|
|
|
} mkv_index_t;
|
|
|
|
|
2015-10-16 16:49:23 +02:00
|
|
|
struct block_info {
|
|
|
|
uint64_t duration, discardpadding;
|
2016-03-04 23:58:44 +01:00
|
|
|
bool simple, keyframe, duration_known;
|
2016-01-27 21:08:53 +01:00
|
|
|
int64_t timecode;
|
2015-10-16 16:49:23 +02:00
|
|
|
mkv_track_t *track;
|
|
|
|
bstr data;
|
|
|
|
void *alloc;
|
|
|
|
int64_t filepos;
|
2017-01-31 14:48:10 +01:00
|
|
|
struct ebml_block_additions *additions;
|
2015-10-16 16:49:23 +02:00
|
|
|
};
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
typedef struct mkv_demuxer {
|
2016-09-06 20:09:56 +02:00
|
|
|
struct demux_mkv_opts *opts;
|
|
|
|
|
2014-01-22 23:37:03 +01:00
|
|
|
int64_t segment_start, segment_end;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2016-02-28 19:14:23 +01:00
|
|
|
double duration;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_track_t **tracks;
|
|
|
|
int num_tracks;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2014-01-23 00:54:08 +01:00
|
|
|
struct ebml_tags *tags;
|
|
|
|
|
2016-01-27 21:08:53 +01:00
|
|
|
int64_t tc_scale, cluster_tc;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2010-01-01 17:42:52 +01:00
|
|
|
uint64_t cluster_start;
|
2013-04-11 20:31:58 +02:00
|
|
|
uint64_t cluster_end;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_index_t *indexes;
|
2014-06-29 23:22:07 +02:00
|
|
|
size_t num_indexes;
|
2013-04-11 17:40:23 +02:00
|
|
|
bool index_complete;
|
2016-09-06 20:09:56 +02:00
|
|
|
int index_mode;
|
|
|
|
|
|
|
|
int edition_id;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2014-01-22 22:12:14 +01:00
|
|
|
struct header_elem {
|
|
|
|
int32_t id;
|
|
|
|
int64_t pos;
|
2017-05-15 16:40:57 +02:00
|
|
|
bool needed;
|
2014-01-22 22:12:14 +01:00
|
|
|
bool parsed;
|
|
|
|
} *headers;
|
|
|
|
int num_headers;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2016-01-27 21:08:53 +01:00
|
|
|
int64_t skip_to_timecode;
|
2014-02-09 21:13:03 +01:00
|
|
|
int v_skip_to_keyframe, a_skip_to_keyframe;
|
2014-11-03 20:00:34 +01:00
|
|
|
int a_skip_preroll;
|
2013-09-08 05:09:16 +02:00
|
|
|
int subtitle_preroll;
|
2014-11-05 20:44:21 +01:00
|
|
|
|
|
|
|
bool index_has_durations;
|
2015-02-25 13:24:15 +01:00
|
|
|
|
2016-12-19 21:29:46 +01:00
|
|
|
bool eof_warning, keyframe_warning;
|
2015-10-16 16:49:23 +02:00
|
|
|
|
|
|
|
struct block_info tmp_block;
|
2004-01-19 20:16:10 +01:00
|
|
|
} mkv_demuxer_t;
|
|
|
|
|
2015-04-23 19:21:17 +02:00
|
|
|
#define OPT_BASE_STRUCT struct demux_mkv_opts
|
|
|
|
struct demux_mkv_opts {
|
|
|
|
int subtitle_preroll;
|
|
|
|
double subtitle_preroll_secs;
|
2015-12-27 01:01:25 +01:00
|
|
|
double subtitle_preroll_secs_index;
|
2015-04-23 19:21:17 +02:00
|
|
|
int probe_duration;
|
2015-10-16 16:49:23 +02:00
|
|
|
int probe_start_time;
|
2015-04-23 19:21:17 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
const struct m_sub_options demux_mkv_conf = {
|
|
|
|
.opts = (const m_option_t[]) {
|
2015-12-27 01:01:25 +01:00
|
|
|
OPT_CHOICE("subtitle-preroll", subtitle_preroll, 0,
|
|
|
|
({"no", 0}, {"yes", 1}, {"index", 2})),
|
2015-04-23 19:21:17 +02:00
|
|
|
OPT_DOUBLE("subtitle-preroll-secs", subtitle_preroll_secs,
|
|
|
|
M_OPT_MIN, .min = 0),
|
2015-12-27 01:01:25 +01:00
|
|
|
OPT_DOUBLE("subtitle-preroll-secs-index", subtitle_preroll_secs_index,
|
|
|
|
M_OPT_MIN, .min = 0),
|
2015-07-09 22:47:41 +02:00
|
|
|
OPT_CHOICE("probe-video-duration", probe_duration, 0,
|
|
|
|
({"no", 0}, {"yes", 1}, {"full", 2})),
|
2015-10-16 16:49:23 +02:00
|
|
|
OPT_FLAG("probe-start-time", probe_start_time, 0),
|
2015-04-23 19:21:17 +02:00
|
|
|
{0}
|
|
|
|
},
|
|
|
|
.size = sizeof(struct demux_mkv_opts),
|
|
|
|
.defaults = &(const struct demux_mkv_opts){
|
2015-12-27 01:01:25 +01:00
|
|
|
.subtitle_preroll = 2,
|
2015-04-23 19:21:17 +02:00
|
|
|
.subtitle_preroll_secs = 1.0,
|
2015-12-27 01:01:25 +01:00
|
|
|
.subtitle_preroll_secs_index = 10.0,
|
2015-10-16 16:49:23 +02:00
|
|
|
.probe_start_time = 1,
|
2015-04-23 19:21:17 +02:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2007-05-28 20:13:33 +02:00
|
|
|
#define REALHEADER_SIZE 16
|
|
|
|
#define RVPROPERTIES_SIZE 34
|
|
|
|
#define RAPROPERTIES4_SIZE 56
|
|
|
|
#define RAPROPERTIES5_SIZE 70
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2013-09-08 05:09:16 +02:00
|
|
|
// Maximum number of subtitle packets that are accepted for pre-roll.
|
2013-09-16 00:20:19 +02:00
|
|
|
// (Subtitle packets added before first A/V keyframe packet is found with seek.)
|
|
|
|
#define NUM_SUB_PREROLL_PACKETS 500
|
2013-09-08 05:09:16 +02:00
|
|
|
|
2015-10-27 20:57:11 +01:00
|
|
|
static void probe_last_timestamp(struct demuxer *demuxer, int64_t start_pos);
|
2015-10-16 16:49:23 +02:00
|
|
|
static void probe_first_timestamp(struct demuxer *demuxer);
|
|
|
|
static void free_block(struct block_info *block);
|
2014-11-18 23:07:20 +01:00
|
|
|
|
2004-01-19 20:16:10 +01:00
|
|
|
#define AAC_SYNC_EXTENSION_TYPE 0x02b7
|
2009-12-29 20:06:21 +01:00
|
|
|
static int aac_get_sample_rate_index(uint32_t sample_rate)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2009-12-29 20:06:21 +01:00
|
|
|
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;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2013-12-21 20:24:20 +01:00
|
|
|
static bstr demux_mkv_decode(struct mp_log *log, mkv_track_t *track,
|
|
|
|
bstr data, uint32_t type)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2013-04-12 17:25:51 +02:00
|
|
|
uint8_t *src = data.start;
|
2010-01-26 18:40:07 +01:00
|
|
|
uint8_t *orig_src = src;
|
2013-04-12 17:25:51 +02:00
|
|
|
uint8_t *dest = src;
|
|
|
|
uint32_t size = data.len;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2010-01-26 18:40:07 +01:00
|
|
|
for (int i = 0; i < track->num_encodings; i++) {
|
|
|
|
struct mkv_content_encoding *enc = track->encodings + i;
|
|
|
|
if (!(enc->scope & type))
|
2009-12-29 20:06:21 +01:00
|
|
|
continue;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2013-04-12 17:25:51 +02:00
|
|
|
if (src != dest && src != orig_src)
|
2010-03-21 17:36:47 +01:00
|
|
|
talloc_free(src);
|
2013-04-12 17:25:51 +02:00
|
|
|
src = dest; // output from last iteration is new source
|
2010-01-26 18:40:07 +01:00
|
|
|
|
|
|
|
if (enc->comp_algo == 0) {
|
2013-07-16 13:28:28 +02:00
|
|
|
#if HAVE_ZLIB
|
2009-12-29 20:06:21 +01:00
|
|
|
/* zlib encoded track */
|
2010-01-26 15:38:39 +01:00
|
|
|
|
2013-04-12 17:25:51 +02:00
|
|
|
if (size == 0)
|
2010-01-26 15:38:39 +01:00
|
|
|
continue;
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
z_stream zstream;
|
|
|
|
|
|
|
|
zstream.zalloc = (alloc_func) 0;
|
|
|
|
zstream.zfree = (free_func) 0;
|
|
|
|
zstream.opaque = (voidpf) 0;
|
|
|
|
if (inflateInit(&zstream) != Z_OK) {
|
2013-12-21 20:24:20 +01:00
|
|
|
mp_warn(log, "zlib initialization failed.\n");
|
2010-01-26 18:40:07 +01:00
|
|
|
goto error;
|
2009-12-29 20:06:21 +01:00
|
|
|
}
|
|
|
|
zstream.next_in = (Bytef *) src;
|
2013-04-12 17:25:51 +02:00
|
|
|
zstream.avail_in = size;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2013-04-12 17:25:51 +02:00
|
|
|
dest = NULL;
|
|
|
|
zstream.avail_out = size;
|
2010-01-26 18:40:07 +01:00
|
|
|
int result;
|
2009-12-29 20:06:21 +01:00
|
|
|
do {
|
2014-06-29 23:22:07 +02:00
|
|
|
if (size >= INT_MAX - 4000) {
|
|
|
|
talloc_free(dest);
|
|
|
|
dest = NULL;
|
|
|
|
inflateEnd(&zstream);
|
|
|
|
goto error;
|
|
|
|
}
|
2013-04-12 17:25:51 +02:00
|
|
|
size += 4000;
|
2013-12-27 20:00:24 +01:00
|
|
|
dest = talloc_realloc_size(track->parser_tmp, dest, size);
|
2013-04-12 17:25:51 +02:00
|
|
|
zstream.next_out = (Bytef *) (dest + zstream.total_out);
|
2009-12-29 20:06:21 +01:00
|
|
|
result = inflate(&zstream, Z_NO_FLUSH);
|
|
|
|
if (result != Z_OK && result != Z_STREAM_END) {
|
2013-12-21 20:24:20 +01:00
|
|
|
mp_warn(log, "zlib decompression failed.\n");
|
2013-04-12 17:25:51 +02:00
|
|
|
talloc_free(dest);
|
|
|
|
dest = NULL;
|
2009-12-29 20:06:21 +01:00
|
|
|
inflateEnd(&zstream);
|
2010-01-26 18:40:07 +01:00
|
|
|
goto error;
|
2009-12-29 20:06:21 +01:00
|
|
|
}
|
|
|
|
zstream.avail_out += 4000;
|
|
|
|
} while (zstream.avail_out == 4000 && zstream.avail_in != 0
|
|
|
|
&& result != Z_STREAM_END);
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2013-04-12 17:25:51 +02:00
|
|
|
size = zstream.total_out;
|
2009-12-29 20:06:21 +01:00
|
|
|
inflateEnd(&zstream);
|
2004-01-19 20:16:10 +01:00
|
|
|
#endif
|
2010-01-26 18:40:07 +01:00
|
|
|
} else if (enc->comp_algo == 2) {
|
2009-12-29 20:06:21 +01:00
|
|
|
/* lzo encoded track */
|
2010-09-18 19:24:39 +02:00
|
|
|
int out_avail;
|
2014-07-02 00:14:18 +02:00
|
|
|
int maxlen = INT_MAX - AV_LZO_OUTPUT_PADDING;
|
|
|
|
if (size >= maxlen / 3)
|
2014-06-29 23:22:07 +02:00
|
|
|
goto error;
|
2013-04-12 17:25:51 +02:00
|
|
|
int dstlen = size * 3;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2013-04-12 17:25:51 +02:00
|
|
|
dest = NULL;
|
2009-12-29 20:06:21 +01:00
|
|
|
while (1) {
|
2013-04-12 17:25:51 +02:00
|
|
|
int srclen = size;
|
2013-12-27 20:00:24 +01:00
|
|
|
dest = talloc_realloc_size(track->parser_tmp, dest,
|
2013-04-12 17:25:51 +02:00
|
|
|
dstlen + AV_LZO_OUTPUT_PADDING);
|
2010-09-18 19:24:39 +02:00
|
|
|
out_avail = dstlen;
|
2013-04-12 17:25:51 +02:00
|
|
|
int result = av_lzo1x_decode(dest, &out_avail, src, &srclen);
|
2009-12-29 20:06:21 +01:00
|
|
|
if (result == 0)
|
|
|
|
break;
|
|
|
|
if (!(result & AV_LZO_OUTPUT_FULL)) {
|
2013-12-21 20:24:20 +01:00
|
|
|
mp_warn(log, "lzo decompression failed.\n");
|
2013-04-12 17:25:51 +02:00
|
|
|
talloc_free(dest);
|
|
|
|
dest = NULL;
|
2010-01-26 18:40:07 +01:00
|
|
|
goto error;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2013-12-21 20:24:20 +01:00
|
|
|
mp_dbg(log, "lzo decompression buffer too small.\n");
|
2014-07-02 00:14:18 +02:00
|
|
|
if (dstlen >= maxlen / 2) {
|
2014-06-29 23:22:07 +02:00
|
|
|
talloc_free(dest);
|
|
|
|
dest = NULL;
|
|
|
|
goto error;
|
|
|
|
}
|
2015-01-12 01:33:35 +01:00
|
|
|
dstlen = MPMAX(1, 2 * dstlen);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2013-04-12 17:25:51 +02:00
|
|
|
size = dstlen - out_avail;
|
2010-01-26 18:40:07 +01:00
|
|
|
} else if (enc->comp_algo == 3) {
|
2013-12-27 20:00:24 +01:00
|
|
|
dest = talloc_size(track->parser_tmp, size + enc->comp_settings_len);
|
2013-04-12 17:25:51 +02:00
|
|
|
memcpy(dest, enc->comp_settings, enc->comp_settings_len);
|
|
|
|
memcpy(dest + enc->comp_settings_len, src, size);
|
|
|
|
size += enc->comp_settings_len;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-26 18:40:07 +01:00
|
|
|
error:
|
2013-04-12 17:25:51 +02:00
|
|
|
if (src != dest && src != orig_src)
|
2010-03-21 17:36:47 +01:00
|
|
|
talloc_free(src);
|
2014-06-29 23:22:07 +02:00
|
|
|
if (!size)
|
|
|
|
dest = NULL;
|
2013-04-12 17:25:51 +02:00
|
|
|
return (bstr){dest, size};
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-13 02:26:32 +01:00
|
|
|
static int demux_mkv_read_info(demuxer_t *demuxer)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2009-03-13 02:26:32 +01:00
|
|
|
mkv_demuxer_t *mkv_d = demuxer->priv;
|
|
|
|
stream_t *s = demuxer->stream;
|
2011-08-04 07:38:39 +02:00
|
|
|
int res = 0;
|
2009-03-16 22:30:48 +01:00
|
|
|
|
2014-01-22 22:12:14 +01:00
|
|
|
MP_VERBOSE(demuxer, "|+ segment information...\n");
|
|
|
|
|
2010-01-26 13:06:49 +01:00
|
|
|
mkv_d->tc_scale = 1000000;
|
|
|
|
mkv_d->duration = 0;
|
|
|
|
|
2013-11-04 23:49:22 +01:00
|
|
|
struct ebml_info info = {0};
|
2013-12-21 20:24:20 +01:00
|
|
|
struct ebml_parse_ctx parse_ctx = {demuxer->log};
|
2010-01-26 13:06:49 +01:00
|
|
|
if (ebml_read_element(s, &parse_ctx, &info, &ebml_info_desc) < 0)
|
2011-08-04 07:38:39 +02:00
|
|
|
return -1;
|
2015-11-06 12:48:24 +01:00
|
|
|
if (info.muxing_app)
|
|
|
|
MP_VERBOSE(demuxer, "| + muxing app: %s\n", info.muxing_app);
|
|
|
|
if (info.writing_app)
|
|
|
|
MP_VERBOSE(demuxer, "| + writing app: %s\n", info.writing_app);
|
2010-01-26 13:06:49 +01:00
|
|
|
if (info.n_timecode_scale) {
|
|
|
|
mkv_d->tc_scale = info.timecode_scale;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + timecode scale: %" PRIu64 "\n", mkv_d->tc_scale);
|
2014-12-06 13:47:03 +01:00
|
|
|
if (mkv_d->tc_scale < 1 || mkv_d->tc_scale > INT_MAX) {
|
|
|
|
res = -1;
|
|
|
|
goto out;
|
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2010-01-26 13:06:49 +01:00
|
|
|
if (info.n_duration) {
|
|
|
|
mkv_d->duration = info.duration * mkv_d->tc_scale / 1e9;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + duration: %.3fs\n",
|
2009-03-13 02:26:32 +01:00
|
|
|
mkv_d->duration);
|
2010-01-26 13:06:49 +01:00
|
|
|
}
|
2015-06-24 14:02:40 +02:00
|
|
|
if (info.title) {
|
|
|
|
mp_tags_set_str(demuxer->metadata, "TITLE", info.title);
|
2013-05-15 15:00:52 +02:00
|
|
|
}
|
2010-01-26 13:06:49 +01:00
|
|
|
if (info.n_segment_uid) {
|
|
|
|
int len = info.segment_uid.len;
|
2013-10-07 02:49:12 +02:00
|
|
|
if (len != sizeof(demuxer->matroska_data.uid.segment)) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_INFO(demuxer, "segment uid invalid length %d\n", len);
|
2010-01-26 13:06:49 +01:00
|
|
|
} else {
|
2013-10-07 02:49:12 +02:00
|
|
|
memcpy(demuxer->matroska_data.uid.segment, info.segment_uid.start,
|
2010-01-26 13:06:49 +01:00
|
|
|
len);
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + segment uid");
|
2010-01-26 13:06:49 +01:00
|
|
|
for (int i = 0; i < len; i++)
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, " %02x",
|
2013-10-07 02:49:12 +02:00
|
|
|
demuxer->matroska_data.uid.segment[i]);
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "\n");
|
2010-01-26 13:06:49 +01:00
|
|
|
}
|
|
|
|
}
|
2011-08-04 07:38:39 +02:00
|
|
|
if (demuxer->params && demuxer->params->matroska_wanted_uids) {
|
2013-09-27 02:42:09 +02:00
|
|
|
if (info.n_segment_uid) {
|
|
|
|
for (int i = 0; i < demuxer->params->matroska_num_wanted_uids; i++) {
|
2013-10-07 02:49:12 +02:00
|
|
|
struct matroska_segment_uid *uid = demuxer->params->matroska_wanted_uids + i;
|
2013-09-26 08:54:25 +02:00
|
|
|
if (!memcmp(info.segment_uid.start, uid->segment, 16)) {
|
|
|
|
demuxer->matroska_data.uid.edition = uid->edition;
|
2013-09-27 02:42:09 +02:00
|
|
|
goto out;
|
2013-09-26 08:54:25 +02:00
|
|
|
}
|
2013-09-27 02:42:09 +02:00
|
|
|
}
|
2011-08-04 07:38:39 +02:00
|
|
|
}
|
2015-01-28 03:41:01 +01:00
|
|
|
MP_VERBOSE(demuxer, "This is not one of the wanted files. "
|
2011-08-04 07:38:39 +02:00
|
|
|
"Stopping attempt to open.\n");
|
|
|
|
res = -2;
|
|
|
|
}
|
|
|
|
out:
|
2010-01-26 13:06:49 +01:00
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
2011-08-04 07:38:39 +02:00
|
|
|
return res;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
static void parse_trackencodings(struct demuxer *demuxer,
|
|
|
|
struct mkv_track *track,
|
|
|
|
struct ebml_content_encodings *encodings)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2010-01-26 15:05:49 +01:00
|
|
|
// initial allocation to be a non-NULL context before realloc
|
|
|
|
mkv_content_encoding_t *ce = talloc_size(track, 1);
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
for (int n_enc = 0; n_enc < encodings->n_content_encoding; n_enc++) {
|
|
|
|
struct ebml_content_encoding *enc = encodings->content_encoding + n_enc;
|
2013-10-19 23:15:06 +02:00
|
|
|
struct mkv_content_encoding e = {0};
|
2010-01-26 15:05:49 +01:00
|
|
|
e.order = enc->content_encoding_order;
|
|
|
|
if (enc->n_content_encoding_scope)
|
|
|
|
e.scope = enc->content_encoding_scope;
|
|
|
|
else
|
2004-01-19 20:16:10 +01:00
|
|
|
e.scope = 1;
|
2010-01-26 15:05:49 +01:00
|
|
|
e.type = enc->content_encoding_type;
|
|
|
|
|
|
|
|
if (enc->n_content_compression) {
|
|
|
|
struct ebml_content_compression *z = &enc->content_compression;
|
|
|
|
e.comp_algo = z->content_comp_algo;
|
|
|
|
if (z->n_content_comp_settings) {
|
|
|
|
int sz = z->content_comp_settings.len;
|
|
|
|
e.comp_settings = talloc_size(ce, sz);
|
|
|
|
memcpy(e.comp_settings, z->content_comp_settings.start, sz);
|
|
|
|
e.comp_settings_len = sz;
|
2009-12-29 20:06:21 +01:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2010-01-26 15:05:49 +01:00
|
|
|
if (e.type == 1) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "Track "
|
2010-01-26 15:05:49 +01:00
|
|
|
"number %u has been encrypted and "
|
|
|
|
"decryption has not yet been\n"
|
2013-12-21 20:24:20 +01:00
|
|
|
"implemented. Skipping track.\n",
|
2010-01-26 15:05:49 +01:00
|
|
|
track->tnum);
|
|
|
|
} else if (e.type != 0) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "Unknown content encoding type for "
|
2010-01-26 15:05:49 +01:00
|
|
|
"track %u. Skipping track.\n",
|
|
|
|
track->tnum);
|
2010-01-28 16:17:54 +01:00
|
|
|
} else if (e.comp_algo != 0 && e.comp_algo != 2 && e.comp_algo != 3) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "Track %u has been compressed with "
|
2010-01-26 15:05:49 +01:00
|
|
|
"an unknown/unsupported compression\n"
|
2013-12-21 20:24:20 +01:00
|
|
|
"algorithm (%" PRIu64 "). Skipping track.\n",
|
2010-01-26 15:05:49 +01:00
|
|
|
track->tnum, e.comp_algo);
|
|
|
|
}
|
2013-07-16 13:28:28 +02:00
|
|
|
#if !HAVE_ZLIB
|
2010-01-26 15:05:49 +01:00
|
|
|
else if (e.comp_algo == 0) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "Track %u was compressed with zlib "
|
2012-10-11 02:04:08 +02:00
|
|
|
"but mpv has not been compiled\n"
|
2013-12-21 20:24:20 +01:00
|
|
|
"with support for zlib compression. "
|
2010-01-26 15:05:49 +01:00
|
|
|
"Skipping track.\n",
|
|
|
|
track->tnum);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
int i;
|
2013-10-19 23:10:03 +02:00
|
|
|
for (i = 0; i < n_enc; i++) {
|
2010-01-26 18:40:07 +01:00
|
|
|
if (e.order >= ce[i].order)
|
2010-01-26 15:05:49 +01:00
|
|
|
break;
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2014-06-29 23:22:07 +02:00
|
|
|
ce = talloc_realloc(track, ce, mkv_content_encoding_t, n_enc + 1);
|
2010-01-26 15:05:49 +01:00
|
|
|
memmove(ce + i + 1, ce + i, (n_enc - i) * sizeof(*ce));
|
|
|
|
memcpy(ce + i, &e, sizeof(e));
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
track->encodings = ce;
|
2010-01-26 17:15:02 +01:00
|
|
|
track->num_encodings = encodings->n_content_encoding;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
static void parse_trackaudio(struct demuxer *demuxer, struct mkv_track *track,
|
|
|
|
struct ebml_audio *audio)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2010-01-26 17:15:02 +01:00
|
|
|
if (audio->n_sampling_frequency) {
|
|
|
|
track->a_sfreq = audio->sampling_frequency;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + Sampling frequency: %f\n", track->a_sfreq);
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
2010-01-26 13:41:07 +01:00
|
|
|
track->a_sfreq = 8000;
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2010-11-21 13:52:08 +01:00
|
|
|
if (audio->n_output_sampling_frequency) {
|
|
|
|
track->a_osfreq = audio->output_sampling_frequency;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + Output sampling frequency: %f\n", track->a_osfreq);
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
2010-11-21 13:52:08 +01:00
|
|
|
track->a_osfreq = track->a_sfreq;
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2010-01-26 17:15:02 +01:00
|
|
|
if (audio->n_bit_depth) {
|
|
|
|
track->a_bps = audio->bit_depth;
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Bit depth: %u\n", track->a_bps);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2010-01-26 17:15:02 +01:00
|
|
|
if (audio->n_channels) {
|
|
|
|
track->a_channels = audio->channels;
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Channels: %u\n", track->a_channels);
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
2010-01-26 13:41:07 +01:00
|
|
|
track->a_channels = 1;
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2016-11-08 02:24:49 +01:00
|
|
|
static void parse_trackcolour(struct demuxer *demuxer, struct mkv_track *track,
|
|
|
|
struct ebml_colour *colour)
|
|
|
|
{
|
|
|
|
// Note: As per matroska spec, the order is consistent with ISO/IEC
|
|
|
|
// 23001-8:2013/DCOR1, which is the same order used by libavutil/pixfmt.h,
|
|
|
|
// so we can just re-use our avcol_ conversion functions.
|
|
|
|
if (colour->n_matrix_coefficients) {
|
|
|
|
track->color.space = avcol_spc_to_mp_csp(colour->matrix_coefficients);
|
|
|
|
MP_VERBOSE(demuxer, "| + Matrix: %s\n",
|
|
|
|
m_opt_choice_str(mp_csp_names, track->color.space));
|
|
|
|
}
|
|
|
|
if (colour->n_primaries) {
|
|
|
|
track->color.primaries = avcol_pri_to_mp_csp_prim(colour->primaries);
|
|
|
|
MP_VERBOSE(demuxer, "| + Primaries: %s\n",
|
|
|
|
m_opt_choice_str(mp_csp_prim_names, track->color.primaries));
|
|
|
|
}
|
|
|
|
if (colour->n_transfer_characteristics) {
|
|
|
|
track->color.gamma = avcol_trc_to_mp_csp_trc(colour->transfer_characteristics);
|
|
|
|
MP_VERBOSE(demuxer, "| + Gamma: %s\n",
|
|
|
|
m_opt_choice_str(mp_csp_trc_names, track->color.gamma));
|
|
|
|
}
|
|
|
|
if (colour->n_range) {
|
|
|
|
track->color.levels = avcol_range_to_mp_csp_levels(colour->range);
|
|
|
|
MP_VERBOSE(demuxer, "| + Levels: %s\n",
|
|
|
|
m_opt_choice_str(mp_csp_levels_names, track->color.levels));
|
|
|
|
}
|
2017-06-10 14:02:55 +02:00
|
|
|
if (colour->n_max_cll) {
|
|
|
|
track->color.sig_peak = colour->max_cll / MP_REF_WHITE;
|
|
|
|
MP_VERBOSE(demuxer, "| + MaxCLL: %lu\n", colour->max_cll);
|
|
|
|
}
|
|
|
|
// if MaxCLL is unavailable, try falling back to the mastering metadata
|
|
|
|
if (!track->color.sig_peak && colour->n_mastering_metadata) {
|
2016-11-08 02:24:49 +01:00
|
|
|
struct ebml_mastering_metadata *mastering = &colour->mastering_metadata;
|
|
|
|
|
|
|
|
if (mastering->n_luminance_max) {
|
2017-06-10 14:01:25 +02:00
|
|
|
track->color.sig_peak = mastering->luminance_max / MP_REF_WHITE;
|
2016-11-08 02:24:49 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + HDR peak: %f\n", track->color.sig_peak);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
static void parse_trackvideo(struct demuxer *demuxer, struct mkv_track *track,
|
|
|
|
struct ebml_video *video)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2010-01-26 17:15:02 +01:00
|
|
|
if (video->n_frame_rate) {
|
2015-06-27 21:47:18 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Frame rate: %f (ignored)\n", video->frame_rate);
|
2010-01-26 13:55:06 +01:00
|
|
|
}
|
2010-01-26 17:15:02 +01:00
|
|
|
if (video->n_display_width) {
|
|
|
|
track->v_dwidth = video->display_width;
|
2013-04-04 01:20:06 +02:00
|
|
|
track->v_dwidth_set = true;
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Display width: %u\n", track->v_dwidth);
|
2010-01-26 13:55:06 +01:00
|
|
|
}
|
2010-01-26 17:15:02 +01:00
|
|
|
if (video->n_display_height) {
|
|
|
|
track->v_dheight = video->display_height;
|
2013-04-04 01:20:06 +02:00
|
|
|
track->v_dheight_set = true;
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Display height: %u\n", track->v_dheight);
|
2010-01-26 13:55:06 +01:00
|
|
|
}
|
2010-01-26 17:15:02 +01:00
|
|
|
if (video->n_pixel_width) {
|
|
|
|
track->v_width = video->pixel_width;
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Pixel width: %u\n", track->v_width);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2010-01-26 17:15:02 +01:00
|
|
|
if (video->n_pixel_height) {
|
|
|
|
track->v_height = video->pixel_height;
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Pixel height: %u\n", track->v_height);
|
2010-01-26 13:55:06 +01:00
|
|
|
}
|
2013-01-24 16:57:21 +01:00
|
|
|
if (video->n_colour_space && video->colour_space.len == 4) {
|
|
|
|
uint8_t *d = (uint8_t *)&video->colour_space.start[0];
|
|
|
|
track->colorspace = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + Colorspace: %#x\n",
|
2014-07-05 16:42:03 +02:00
|
|
|
(unsigned int)track->colorspace);
|
2013-01-24 16:57:21 +01:00
|
|
|
}
|
2014-08-30 23:24:46 +02:00
|
|
|
if (video->n_stereo_mode) {
|
|
|
|
const char *name = MP_STEREO3D_NAME(video->stereo_mode);
|
|
|
|
if (name) {
|
|
|
|
track->stereo_mode = video->stereo_mode;
|
|
|
|
MP_VERBOSE(demuxer, "| + StereoMode: %s\n", name);
|
|
|
|
} else {
|
|
|
|
MP_WARN(demuxer, "Unknown StereoMode: %d\n", (int)video->stereo_mode);
|
|
|
|
}
|
|
|
|
}
|
2016-11-08 02:24:49 +01:00
|
|
|
if (video->n_colour)
|
|
|
|
parse_trackcolour(demuxer, track, &video->colour);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2006-10-09 20:48:55 +02:00
|
|
|
/**
|
|
|
|
* \brief free any data associated with given track
|
|
|
|
* \param track track of which to free data
|
|
|
|
*/
|
2009-12-29 20:06:21 +01:00
|
|
|
static void demux_mkv_free_trackentry(mkv_track_t *track)
|
|
|
|
{
|
2013-12-27 20:00:24 +01:00
|
|
|
talloc_free(track->parser_tmp);
|
2010-01-26 15:05:49 +01:00
|
|
|
talloc_free(track);
|
2006-10-09 20:48:55 +02:00
|
|
|
}
|
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
static void parse_trackentry(struct demuxer *demuxer,
|
|
|
|
struct ebml_track_entry *entry)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
2014-06-29 23:22:07 +02:00
|
|
|
struct mkv_track *track = talloc_zero(NULL, struct mkv_track);
|
|
|
|
track->last_index_entry = (size_t)-1;
|
2013-12-27 20:00:24 +01:00
|
|
|
track->parser_tmp = talloc_new(track);
|
2010-01-26 17:15:02 +01:00
|
|
|
|
|
|
|
track->tnum = entry->track_number;
|
2013-10-19 23:10:03 +02:00
|
|
|
if (track->tnum) {
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Track number: %u\n", track->tnum);
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_ERR(demuxer, "Missing track number!\n");
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2016-08-12 21:39:32 +02:00
|
|
|
track->uid = entry->track_uid;
|
2010-01-26 17:15:02 +01:00
|
|
|
|
2015-06-24 14:02:40 +02:00
|
|
|
if (entry->name) {
|
|
|
|
track->name = talloc_strdup(track, entry->name);
|
demux_mkv: change license to LGPL
Most contributors have agreed. This claims it's based on gstreamer code,
but this was LGPL at the time (and still is). Contributors whose code
was removed were not accounted for. There are still some potentially
problematic cases:
06eee1b67 is potentially the most problematic case. Most of these
changes are gone due to mpv not using BITMAPINFOHEADER anymore. Some
of the other changes are rather trivial. If someone contests this and
claims that copyrightable changes are left, the original change can
simply be reverted.
62bfae140 has only 2 lines left: a "char *name;" struct field, and a
line that prints a message. All other code was removed. The parsing code
in particular was made declarative, which replaced reading this element
explicitly (and other elements, see 1b22101c77e). I'm putting the log
message under HAVE_GPL, but I don't think the declaration is
copyrightable, or the mere concept of reading this element. Redoing the
other 2 lines of code would result in the same program text.
d41e860ba was applied by someone who (potentially) disagreed. The patch
itself is from someone who did agree, though. It's unknown whether the
applier changed the patch. But it seems unlikely, and the change was
mostly rewritten.
50a86fcc3 all demux_mkv changes were reverted (old stdout slave mode)
3a406e94d same
2e40bfa13 the old MPlayer subtitle code was completely removed
316bb1d44 completely removed in 1cf4802c1d
87f93d9d7 same
11bfc6780 relative seeks were removed in 92ba630796
be54f4813 the corresponding demux_mkv code was removed in 5dabaaf093
efd53eed6 all internal vobsub handling is now in FFmpeg
d7f693a20 removed in f3db4b0b937
e8a1b3713 removed in 522ee6b7831
cfb890259 removed, see 6b1374b203 for analysis
c80808b5a same
2017-04-21 12:18:55 +02:00
|
|
|
#if HAVE_GPL
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Name: %s\n", track->name);
|
demux_mkv: change license to LGPL
Most contributors have agreed. This claims it's based on gstreamer code,
but this was LGPL at the time (and still is). Contributors whose code
was removed were not accounted for. There are still some potentially
problematic cases:
06eee1b67 is potentially the most problematic case. Most of these
changes are gone due to mpv not using BITMAPINFOHEADER anymore. Some
of the other changes are rather trivial. If someone contests this and
claims that copyrightable changes are left, the original change can
simply be reverted.
62bfae140 has only 2 lines left: a "char *name;" struct field, and a
line that prints a message. All other code was removed. The parsing code
in particular was made declarative, which replaced reading this element
explicitly (and other elements, see 1b22101c77e). I'm putting the log
message under HAVE_GPL, but I don't think the declaration is
copyrightable, or the mere concept of reading this element. Redoing the
other 2 lines of code would result in the same program text.
d41e860ba was applied by someone who (potentially) disagreed. The patch
itself is from someone who did agree, though. It's unknown whether the
applier changed the patch. But it seems unlikely, and the change was
mostly rewritten.
50a86fcc3 all demux_mkv changes were reverted (old stdout slave mode)
3a406e94d same
2e40bfa13 the old MPlayer subtitle code was completely removed
316bb1d44 completely removed in 1cf4802c1d
87f93d9d7 same
11bfc6780 relative seeks were removed in 92ba630796
be54f4813 the corresponding demux_mkv code was removed in 5dabaaf093
efd53eed6 all internal vobsub handling is now in FFmpeg
d7f693a20 removed in f3db4b0b937
e8a1b3713 removed in 522ee6b7831
cfb890259 removed, see 6b1374b203 for analysis
c80808b5a same
2017-04-21 12:18:55 +02:00
|
|
|
#endif
|
2010-01-26 17:15:02 +01:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
track->type = entry->track_type;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + Track type: ");
|
2010-01-26 17:15:02 +01:00
|
|
|
switch (track->type) {
|
|
|
|
case MATROSKA_TRACK_AUDIO:
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "Audio\n");
|
2010-01-26 17:15:02 +01:00
|
|
|
break;
|
|
|
|
case MATROSKA_TRACK_VIDEO:
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "Video\n");
|
2010-01-26 17:15:02 +01:00
|
|
|
break;
|
|
|
|
case MATROSKA_TRACK_SUBTITLE:
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "Subtitle\n");
|
2010-01-26 17:15:02 +01:00
|
|
|
break;
|
|
|
|
default:
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "unknown\n");
|
2010-01-26 17:15:02 +01:00
|
|
|
break;
|
|
|
|
}
|
2009-07-07 01:26:13 +02:00
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
if (entry->n_audio) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + Audio track\n");
|
2010-01-26 17:15:02 +01:00
|
|
|
parse_trackaudio(demuxer, track, &entry->audio);
|
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
if (entry->n_video) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + Video track\n");
|
2010-01-26 17:15:02 +01:00
|
|
|
parse_trackvideo(demuxer, track, &entry->video);
|
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2015-06-24 14:02:40 +02:00
|
|
|
if (entry->codec_id) {
|
|
|
|
track->codec_id = talloc_strdup(track, entry->codec_id);
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Codec ID: %s\n", track->codec_id);
|
2013-04-20 23:40:41 +02:00
|
|
|
} else {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_ERR(demuxer, "Missing codec ID!\n");
|
2013-04-20 23:40:41 +02:00
|
|
|
track->codec_id = "";
|
|
|
|
}
|
2010-01-26 17:15:02 +01:00
|
|
|
|
2014-09-04 19:19:28 +02:00
|
|
|
if (entry->n_codec_private && entry->codec_private.len <= 0x10000000) {
|
2010-01-26 17:15:02 +01:00
|
|
|
int len = entry->codec_private.len;
|
|
|
|
track->private_data = talloc_size(track, len + AV_LZO_INPUT_PADDING);
|
|
|
|
memcpy(track->private_data, entry->codec_private.start, len);
|
|
|
|
track->private_size = len;
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + CodecPrivate, length %u\n", track->private_size);
|
2010-01-26 17:15:02 +01:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2015-06-24 14:02:40 +02:00
|
|
|
if (entry->language) {
|
|
|
|
track->language = talloc_strdup(track, entry->language);
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Language: %s\n", track->language);
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
2010-01-26 17:15:02 +01:00
|
|
|
track->language = talloc_strdup(track, "eng");
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
if (entry->n_flag_default) {
|
|
|
|
track->default_track = entry->flag_default;
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "| + Default flag: %u\n", track->default_track);
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
2010-01-26 17:15:02 +01:00
|
|
|
track->default_track = 1;
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2010-01-26 17:15:02 +01:00
|
|
|
|
2015-06-27 22:02:24 +02:00
|
|
|
if (entry->n_flag_forced) {
|
|
|
|
track->forced_track = entry->flag_forced;
|
|
|
|
MP_VERBOSE(demuxer, "| + Forced flag: %u\n", track->forced_track);
|
|
|
|
}
|
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
if (entry->n_default_duration) {
|
|
|
|
track->default_duration = entry->default_duration / 1e9;
|
2013-10-19 23:10:03 +02:00
|
|
|
if (entry->default_duration == 0) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + Default duration: 0");
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
2015-06-27 21:47:18 +02:00
|
|
|
track->v_frate = 1e9 / entry->default_duration;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + Default duration: %.3fms ( = %.3f fps)\n",
|
2014-07-05 16:42:03 +02:00
|
|
|
entry->default_duration / 1000000.0, track->v_frate);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
if (entry->n_content_encodings)
|
|
|
|
parse_trackencodings(demuxer, track, &entry->content_encodings);
|
2006-10-09 20:48:55 +02:00
|
|
|
|
2014-11-03 20:00:34 +01:00
|
|
|
if (entry->n_codec_delay)
|
|
|
|
track->codec_delay = entry->codec_delay / 1e9;
|
|
|
|
|
2010-01-26 17:15:02 +01:00
|
|
|
mkv_d->tracks[mkv_d->num_tracks++] = track;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
static int demux_mkv_read_tracks(demuxer_t *demuxer)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
|
|
|
stream_t *s = demuxer->stream;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2014-01-22 22:12:14 +01:00
|
|
|
MP_VERBOSE(demuxer, "|+ segment tracks...\n");
|
|
|
|
|
2013-10-19 23:15:06 +02:00
|
|
|
struct ebml_tracks tracks = {0};
|
2013-12-21 20:24:20 +01:00
|
|
|
struct ebml_parse_ctx parse_ctx = {demuxer->log};
|
2010-01-26 17:15:02 +01:00
|
|
|
if (ebml_read_element(s, &parse_ctx, &tracks, &ebml_tracks_desc) < 0)
|
2011-08-20 20:45:42 +02:00
|
|
|
return -1;
|
2010-01-26 17:15:02 +01:00
|
|
|
|
2014-06-29 23:22:07 +02:00
|
|
|
mkv_d->tracks = talloc_zero_array(mkv_d, struct mkv_track*,
|
|
|
|
tracks.n_track_entry);
|
2010-01-26 17:15:02 +01:00
|
|
|
for (int i = 0; i < tracks.n_track_entry; i++) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "| + a track...\n");
|
2010-01-26 17:15:02 +01:00
|
|
|
parse_trackentry(demuxer, &tracks.track_entry[i]);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2010-01-26 17:15:02 +01:00
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
2009-12-29 20:06:21 +01:00
|
|
|
return 0;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2013-04-11 17:40:23 +02:00
|
|
|
static void cue_index_add(demuxer_t *demuxer, int track_id, uint64_t filepos,
|
2016-01-27 21:08:53 +01:00
|
|
|
int64_t timecode, int64_t duration)
|
2013-04-11 17:40:23 +02:00
|
|
|
{
|
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
|
|
|
|
2014-06-29 23:22:07 +02:00
|
|
|
MP_TARRAY_GROW(mkv_d, mkv_d->indexes, mkv_d->num_indexes);
|
|
|
|
|
2014-11-05 20:44:21 +01:00
|
|
|
mkv_d->indexes[mkv_d->num_indexes] = (mkv_index_t) {
|
|
|
|
.tnum = track_id,
|
|
|
|
.filepos = filepos,
|
|
|
|
.timecode = timecode,
|
|
|
|
.duration = duration,
|
|
|
|
};
|
|
|
|
|
2013-04-11 17:40:23 +02:00
|
|
|
mkv_d->num_indexes++;
|
|
|
|
}
|
|
|
|
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
static void add_block_position(demuxer_t *demuxer, struct mkv_track *track,
|
2014-11-05 20:44:21 +01:00
|
|
|
uint64_t filepos,
|
2016-01-27 21:08:53 +01:00
|
|
|
int64_t timecode, int64_t duration)
|
2013-04-11 17:40:23 +02:00
|
|
|
{
|
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
|
|
|
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
if (mkv_d->index_complete || !track)
|
2013-04-11 17:40:23 +02:00
|
|
|
return;
|
2014-11-05 20:44:21 +01:00
|
|
|
|
|
|
|
mkv_d->index_has_durations = true;
|
|
|
|
|
2014-06-29 23:22:07 +02:00
|
|
|
if (track->last_index_entry != (size_t)-1) {
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
mkv_index_t *index = &mkv_d->indexes[track->last_index_entry];
|
2014-11-05 20:42:20 +01:00
|
|
|
// Never add blocks which are already covered by the index.
|
|
|
|
if (index->timecode >= timecode)
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
return;
|
|
|
|
}
|
2014-11-05 20:44:21 +01:00
|
|
|
cue_index_add(demuxer, track->tnum, filepos, timecode, duration);
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
track->last_index_entry = mkv_d->num_indexes - 1;
|
2013-04-11 17:40:23 +02:00
|
|
|
}
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
static int demux_mkv_read_cues(demuxer_t *demuxer)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
|
|
|
stream_t *s = demuxer->stream;
|
|
|
|
|
2016-09-06 20:09:56 +02:00
|
|
|
if (mkv_d->index_mode != 1 || mkv_d->index_complete) {
|
2014-01-14 17:38:21 +01:00
|
|
|
ebml_read_skip(demuxer->log, -1, s);
|
2004-01-19 20:16:10 +01:00
|
|
|
return 0;
|
2009-12-29 20:06:21 +01:00
|
|
|
}
|
|
|
|
|
2015-06-27 21:42:19 +02:00
|
|
|
MP_VERBOSE(demuxer, "Parsing cues...\n");
|
2013-10-19 23:15:06 +02:00
|
|
|
struct ebml_cues cues = {0};
|
2013-12-21 20:24:20 +01:00
|
|
|
struct ebml_parse_ctx parse_ctx = {demuxer->log};
|
2010-01-25 12:19:09 +01:00
|
|
|
if (ebml_read_element(s, &parse_ctx, &cues, &ebml_cues_desc) < 0)
|
2011-08-20 20:45:42 +02:00
|
|
|
return -1;
|
2013-05-23 00:26:42 +02:00
|
|
|
|
2010-01-25 12:19:09 +01:00
|
|
|
for (int i = 0; i < cues.n_cue_point; i++) {
|
|
|
|
struct ebml_cue_point *cuepoint = &cues.cue_point[i];
|
|
|
|
if (cuepoint->n_cue_time != 1 || !cuepoint->n_cue_track_positions) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "Malformed CuePoint element\n");
|
2015-08-26 22:47:07 +02:00
|
|
|
goto done;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2015-08-26 22:47:07 +02:00
|
|
|
if (cuepoint->cue_time / 1e9 > mkv_d->duration / mkv_d->tc_scale * 10 &&
|
|
|
|
mkv_d->duration != 0)
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (cues.n_cue_point <= 3) // probably too sparse and will just break seeking
|
|
|
|
goto done;
|
|
|
|
|
2016-04-12 15:41:44 +02:00
|
|
|
// Discard incremental index. (Keep the first entry, which must be the
|
|
|
|
// start of the file - helps with files that miss the first index entry.)
|
|
|
|
mkv_d->num_indexes = MPMIN(1, mkv_d->num_indexes);
|
2015-08-26 22:47:07 +02:00
|
|
|
mkv_d->index_has_durations = false;
|
|
|
|
|
|
|
|
for (int i = 0; i < cues.n_cue_point; i++) {
|
|
|
|
struct ebml_cue_point *cuepoint = &cues.cue_point[i];
|
2010-01-25 12:19:09 +01:00
|
|
|
uint64_t time = cuepoint->cue_time;
|
2013-07-23 00:45:23 +02:00
|
|
|
for (int c = 0; c < cuepoint->n_cue_track_positions; c++) {
|
2010-01-25 12:19:09 +01:00
|
|
|
struct ebml_cue_track_positions *trackpos =
|
2013-07-23 00:45:23 +02:00
|
|
|
&cuepoint->cue_track_positions[c];
|
2013-04-11 17:40:23 +02:00
|
|
|
uint64_t pos = mkv_d->segment_start + trackpos->cue_cluster_position;
|
2014-11-05 20:44:21 +01:00
|
|
|
cue_index_add(demuxer, trackpos->cue_track, pos,
|
|
|
|
time, trackpos->cue_duration);
|
|
|
|
mkv_d->index_has_durations |= trackpos->n_cue_duration > 0;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_DBG(demuxer, "|+ found cue point for track %" PRIu64
|
2016-01-27 21:08:53 +01:00
|
|
|
": timecode %" PRId64 ", filepos: %" PRIu64
|
|
|
|
" offset %" PRIu64 ", duration %" PRId64 "\n",
|
2014-11-05 20:44:21 +01:00
|
|
|
trackpos->cue_track, time, pos,
|
|
|
|
trackpos->cue_relative_position, trackpos->cue_duration);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-11 17:40:23 +02:00
|
|
|
// Do not attempt to create index on the fly.
|
|
|
|
mkv_d->index_complete = true;
|
|
|
|
|
2015-08-26 22:47:07 +02:00
|
|
|
done:
|
|
|
|
if (!mkv_d->index_complete)
|
|
|
|
MP_WARN(demuxer, "Discarding potentially broken or useless index.\n");
|
2010-01-25 12:19:09 +01:00
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
2009-12-29 20:06:21 +01:00
|
|
|
return 0;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2009-03-13 02:26:32 +01:00
|
|
|
static int demux_mkv_read_chapters(struct demuxer *demuxer)
|
|
|
|
{
|
2016-09-06 20:09:56 +02:00
|
|
|
mkv_demuxer_t *mkv_d = demuxer->priv;
|
2009-03-13 02:26:32 +01:00
|
|
|
stream_t *s = demuxer->stream;
|
2016-09-06 20:09:56 +02:00
|
|
|
int wanted_edition = mkv_d->edition_id;
|
2013-09-26 08:53:54 +02:00
|
|
|
uint64_t wanted_edition_uid = demuxer->matroska_data.uid.edition;
|
|
|
|
|
|
|
|
/* A specific edition UID was requested; ignore the user option which is
|
|
|
|
* only applicable to the top-level file. */
|
|
|
|
if (wanted_edition_uid)
|
|
|
|
wanted_edition = -1;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2015-06-27 21:42:19 +02:00
|
|
|
MP_VERBOSE(demuxer, "Parsing chapters...\n");
|
2013-10-19 23:15:06 +02:00
|
|
|
struct ebml_chapters file_chapters = {0};
|
2013-12-21 20:24:20 +01:00
|
|
|
struct ebml_parse_ctx parse_ctx = {demuxer->log};
|
2010-01-26 12:39:33 +01:00
|
|
|
if (ebml_read_element(s, &parse_ctx, &file_chapters,
|
|
|
|
&ebml_chapters_desc) < 0)
|
2011-08-20 20:45:42 +02:00
|
|
|
return -1;
|
2009-03-13 02:26:32 +01:00
|
|
|
|
2013-09-26 08:53:54 +02:00
|
|
|
int selected_edition = -1;
|
2010-01-26 12:39:33 +01:00
|
|
|
int num_editions = file_chapters.n_edition_entry;
|
|
|
|
struct ebml_edition_entry *editions = file_chapters.edition_entry;
|
2014-01-23 00:54:08 +01:00
|
|
|
for (int i = 0; i < num_editions; i++) {
|
|
|
|
struct demux_edition new = {
|
|
|
|
.demuxer_id = editions[i].edition_uid,
|
|
|
|
.default_edition = editions[i].edition_flag_default,
|
|
|
|
.metadata = talloc_zero(demuxer, struct mp_tags),
|
|
|
|
};
|
|
|
|
MP_TARRAY_APPEND(demuxer, demuxer->editions, demuxer->num_editions, new);
|
|
|
|
}
|
2013-08-21 18:41:59 +02:00
|
|
|
if (wanted_edition >= 0 && wanted_edition < num_editions) {
|
|
|
|
selected_edition = wanted_edition;
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_VERBOSE(demuxer, "User-specified edition: %d\n", selected_edition);
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
|
|
|
for (int i = 0; i < num_editions; i++) {
|
2013-09-26 08:53:54 +02:00
|
|
|
if (wanted_edition_uid &&
|
|
|
|
editions[i].edition_uid == wanted_edition_uid) {
|
|
|
|
selected_edition = i;
|
|
|
|
break;
|
|
|
|
} else if (editions[i].edition_flag_default) {
|
2010-01-26 12:39:33 +01:00
|
|
|
selected_edition = i;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "Default edition: %d\n", i);
|
2010-01-26 12:39:33 +01:00
|
|
|
break;
|
|
|
|
}
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
|
|
|
}
|
2013-09-26 08:53:54 +02:00
|
|
|
if (selected_edition < 0) {
|
|
|
|
if (wanted_edition_uid) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_ERR(demuxer, "Unable to find expected edition uid: %"PRIu64"\n",
|
2013-09-26 08:53:54 +02:00
|
|
|
wanted_edition_uid);
|
2016-10-22 17:55:31 +02:00
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
2013-09-26 08:53:54 +02:00
|
|
|
return -1;
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
2013-09-26 08:53:54 +02:00
|
|
|
selected_edition = 0;
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2013-09-26 08:53:54 +02:00
|
|
|
}
|
2009-03-16 22:30:48 +01:00
|
|
|
|
2010-01-26 12:39:33 +01:00
|
|
|
for (int idx = 0; idx < num_editions; idx++) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "New edition %d\n", idx);
|
2010-01-26 12:39:33 +01:00
|
|
|
int warn_level = idx == selected_edition ? MSGL_WARN : MSGL_V;
|
|
|
|
if (editions[idx].n_edition_flag_default)
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "Default edition flag: %"PRIu64
|
2014-07-05 16:42:03 +02:00
|
|
|
"\n", editions[idx].edition_flag_default);
|
2010-01-26 12:39:33 +01:00
|
|
|
if (editions[idx].n_edition_flag_ordered)
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "Ordered chapter flag: %"PRIu64
|
2014-07-05 16:42:03 +02:00
|
|
|
"\n", editions[idx].edition_flag_ordered);
|
2013-10-19 23:02:53 +02:00
|
|
|
|
|
|
|
int chapter_count = editions[idx].n_chapter_atom;
|
|
|
|
|
|
|
|
struct matroska_chapter *m_chapters = NULL;
|
|
|
|
if (idx == selected_edition && editions[idx].edition_flag_ordered) {
|
|
|
|
m_chapters = talloc_array_ptrtype(demuxer, m_chapters, chapter_count);
|
|
|
|
demuxer->matroska_data.ordered_chapters = m_chapters;
|
|
|
|
demuxer->matroska_data.num_ordered_chapters = chapter_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < chapter_count; i++) {
|
2010-01-26 12:39:33 +01:00
|
|
|
struct ebml_chapter_atom *ca = editions[idx].chapter_atom + i;
|
2013-10-19 23:15:06 +02:00
|
|
|
struct matroska_chapter chapter = {0};
|
2015-06-24 14:02:40 +02:00
|
|
|
char *name = "(unnamed)";
|
2010-01-26 12:39:33 +01:00
|
|
|
|
2011-01-23 23:29:01 +01:00
|
|
|
chapter.start = ca->chapter_time_start;
|
|
|
|
chapter.end = ca->chapter_time_end;
|
2010-01-26 12:39:33 +01:00
|
|
|
|
2015-06-28 18:32:58 +02:00
|
|
|
if (!ca->n_chapter_time_start)
|
|
|
|
MP_MSG(demuxer, warn_level, "Chapter lacks start time\n");
|
|
|
|
if (!ca->n_chapter_time_start || !ca->n_chapter_time_end) {
|
|
|
|
if (demuxer->matroska_data.ordered_chapters) {
|
|
|
|
MP_MSG(demuxer, warn_level, "Chapter lacks start or end "
|
|
|
|
"time, disabling ordered chapters.\n");
|
|
|
|
demuxer->matroska_data.ordered_chapters = NULL;
|
|
|
|
demuxer->matroska_data.num_ordered_chapters = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-26 12:39:33 +01:00
|
|
|
if (ca->n_chapter_display) {
|
|
|
|
if (ca->n_chapter_display > 1)
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_MSG(demuxer, warn_level, "Multiple chapter "
|
2010-01-26 12:39:33 +01:00
|
|
|
"names not supported, picking first\n");
|
2015-06-24 14:02:40 +02:00
|
|
|
if (!ca->chapter_display[0].chap_string)
|
2014-07-05 16:42:03 +02:00
|
|
|
MP_MSG(demuxer, warn_level, "Malformed chapter name entry\n");
|
2010-01-26 12:39:33 +01:00
|
|
|
else
|
|
|
|
name = ca->chapter_display[0].chap_string;
|
2009-03-13 02:26:32 +01:00
|
|
|
}
|
2010-01-26 12:39:33 +01:00
|
|
|
|
|
|
|
if (ca->n_chapter_segment_uid) {
|
|
|
|
chapter.has_segment_uid = true;
|
|
|
|
int len = ca->chapter_segment_uid.len;
|
2013-10-07 02:49:12 +02:00
|
|
|
if (len != sizeof(chapter.uid.segment))
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_MSG(demuxer, warn_level,
|
|
|
|
"Chapter segment uid bad length %d\n", len);
|
2013-09-26 08:21:19 +02:00
|
|
|
else {
|
2013-10-07 02:49:12 +02:00
|
|
|
memcpy(chapter.uid.segment, ca->chapter_segment_uid.start,
|
2010-01-26 12:39:33 +01:00
|
|
|
len);
|
2013-09-26 08:21:19 +02:00
|
|
|
if (ca->n_chapter_segment_edition_uid)
|
|
|
|
chapter.uid.edition = ca->chapter_segment_edition_uid;
|
|
|
|
else
|
|
|
|
chapter.uid.edition = 0;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "Chapter segment uid ");
|
2013-07-23 00:45:23 +02:00
|
|
|
for (int n = 0; n < len; n++)
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "%02x ",
|
2013-10-07 02:49:12 +02:00
|
|
|
chapter.uid.segment[n]);
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "\n");
|
2010-01-26 12:39:33 +01:00
|
|
|
}
|
2009-03-16 22:30:48 +01:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "Chapter %u from %02d:%02d:%02d.%03d "
|
2015-06-24 14:02:40 +02:00
|
|
|
"to %02d:%02d:%02d.%03d, %s\n", i,
|
2011-01-23 23:29:01 +01:00
|
|
|
(int) (chapter.start / 60 / 60 / 1000000000),
|
|
|
|
(int) ((chapter.start / 60 / 1000000000) % 60),
|
|
|
|
(int) ((chapter.start / 1000000000) % 60),
|
|
|
|
(int) (chapter.start % 1000000000),
|
|
|
|
(int) (chapter.end / 60 / 60 / 1000000000),
|
|
|
|
(int) ((chapter.end / 60 / 1000000000) % 60),
|
|
|
|
(int) ((chapter.end / 1000000000) % 60),
|
|
|
|
(int) (chapter.end % 1000000000),
|
2015-06-24 14:02:40 +02:00
|
|
|
name);
|
2010-01-26 12:39:33 +01:00
|
|
|
|
2013-10-19 23:02:53 +02:00
|
|
|
if (idx == selected_edition) {
|
2015-06-24 14:18:51 +02:00
|
|
|
demuxer_add_chapter(demuxer, name, chapter.start / 1e9,
|
2013-09-08 07:42:05 +02:00
|
|
|
ca->chapter_uid);
|
2013-10-19 23:02:53 +02:00
|
|
|
}
|
|
|
|
if (m_chapters) {
|
2015-06-24 14:02:40 +02:00
|
|
|
chapter.name = talloc_strdup(m_chapters, name);
|
2013-10-19 23:02:53 +02:00
|
|
|
m_chapters[i] = chapter;
|
2010-01-26 12:39:33 +01:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-26 01:19:42 +02:00
|
|
|
demuxer->num_editions = num_editions;
|
|
|
|
demuxer->edition = selected_edition;
|
|
|
|
|
2010-01-26 12:39:33 +01:00
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
2009-03-13 02:26:32 +01:00
|
|
|
return 0;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
static int demux_mkv_read_tags(demuxer_t *demuxer)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2014-01-23 00:54:08 +01:00
|
|
|
struct mkv_demuxer *mkv_d = demuxer->priv;
|
2010-03-28 14:21:42 +02:00
|
|
|
stream_t *s = demuxer->stream;
|
|
|
|
|
2013-12-21 20:24:20 +01:00
|
|
|
struct ebml_parse_ctx parse_ctx = {demuxer->log};
|
2013-10-19 23:15:06 +02:00
|
|
|
struct ebml_tags tags = {0};
|
2010-03-28 14:21:42 +02:00
|
|
|
if (ebml_read_element(s, &parse_ctx, &tags, &ebml_tags_desc) < 0)
|
2011-08-20 20:45:42 +02:00
|
|
|
return -1;
|
2010-03-28 14:21:42 +02:00
|
|
|
|
2014-01-23 00:54:08 +01:00
|
|
|
mkv_d->tags = talloc_memdup(mkv_d, &tags, sizeof(tags));
|
|
|
|
talloc_steal(mkv_d->tags, parse_ctx.talloc_ctx);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void process_tags(demuxer_t *demuxer)
|
|
|
|
{
|
|
|
|
struct mkv_demuxer *mkv_d = demuxer->priv;
|
|
|
|
struct ebml_tags *tags = mkv_d->tags;
|
|
|
|
|
|
|
|
if (!tags)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (int i = 0; i < tags->n_tag; i++) {
|
|
|
|
struct ebml_tag tag = tags->tag[i];
|
2014-02-06 13:43:01 +01:00
|
|
|
struct mp_tags *dst = NULL;
|
|
|
|
|
2013-09-08 07:42:05 +02:00
|
|
|
if (tag.targets.target_chapter_uid) {
|
2014-02-06 13:43:01 +01:00
|
|
|
for (int n = 0; n < demuxer->num_chapters; n++) {
|
|
|
|
if (demuxer->chapters[n].demuxer_id ==
|
|
|
|
tag.targets.target_chapter_uid)
|
|
|
|
{
|
|
|
|
dst = demuxer->chapters[n].metadata;
|
|
|
|
break;
|
|
|
|
}
|
2013-09-08 07:42:05 +02:00
|
|
|
}
|
2014-01-23 00:54:08 +01:00
|
|
|
} else if (tag.targets.target_edition_uid) {
|
|
|
|
for (int n = 0; n < demuxer->num_editions; n++) {
|
|
|
|
if (demuxer->editions[n].demuxer_id ==
|
|
|
|
tag.targets.target_edition_uid)
|
|
|
|
{
|
2014-02-06 13:43:01 +01:00
|
|
|
dst = demuxer->editions[n].metadata;
|
2014-01-23 00:54:08 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-08-12 21:39:32 +02:00
|
|
|
} else if (tag.targets.target_track_uid) {
|
|
|
|
for (int n = 0; n < mkv_d->num_tracks; n++) {
|
|
|
|
if (mkv_d->tracks[n]->uid ==
|
|
|
|
tag.targets.target_track_uid)
|
|
|
|
{
|
|
|
|
struct sh_stream *sh = mkv_d->tracks[n]->stream;
|
|
|
|
if (sh)
|
|
|
|
dst = sh->tags;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (tag.targets.target_attachment_uid) {
|
|
|
|
/* ignore */
|
2013-09-08 07:42:05 +02:00
|
|
|
} else {
|
2014-02-06 13:43:01 +01:00
|
|
|
dst = demuxer->metadata;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dst) {
|
2013-09-08 07:42:05 +02:00
|
|
|
for (int j = 0; j < tag.n_simple_tag; j++) {
|
2015-06-24 14:02:40 +02:00
|
|
|
if (tag.simple_tag[j].tag_name && tag.simple_tag[j].tag_string) {
|
|
|
|
mp_tags_set_str(dst, tag.simple_tag[j].tag_name,
|
|
|
|
tag.simple_tag[j].tag_string);
|
|
|
|
}
|
2013-09-08 07:42:05 +02:00
|
|
|
}
|
|
|
|
}
|
2010-03-28 14:21:42 +02:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
static int demux_mkv_read_attachments(demuxer_t *demuxer)
|
2006-07-07 20:26:51 +02:00
|
|
|
{
|
2009-12-29 20:06:21 +01:00
|
|
|
stream_t *s = demuxer->stream;
|
|
|
|
|
2015-06-27 21:42:19 +02:00
|
|
|
MP_VERBOSE(demuxer, "Parsing attachments...\n");
|
2006-07-07 20:26:51 +02:00
|
|
|
|
2013-10-19 23:15:06 +02:00
|
|
|
struct ebml_attachments attachments = {0};
|
2013-12-21 20:24:20 +01:00
|
|
|
struct ebml_parse_ctx parse_ctx = {demuxer->log};
|
2010-01-25 18:42:37 +01:00
|
|
|
if (ebml_read_element(s, &parse_ctx, &attachments,
|
|
|
|
&ebml_attachments_desc) < 0)
|
2011-08-20 20:45:42 +02:00
|
|
|
return -1;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2010-01-25 18:42:37 +01:00
|
|
|
for (int i = 0; i < attachments.n_attached_file; i++) {
|
|
|
|
struct ebml_attached_file *attachment = &attachments.attached_file[i];
|
2015-06-24 14:02:40 +02:00
|
|
|
if (!attachment->file_name || !attachment->file_mime_type
|
2010-01-25 18:42:37 +01:00
|
|
|
|| !attachment->n_file_data) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "Malformed attachment\n");
|
2010-01-25 18:42:37 +01:00
|
|
|
continue;
|
2006-07-07 20:26:51 +02:00
|
|
|
}
|
2015-06-24 14:02:40 +02:00
|
|
|
char *name = attachment->file_name;
|
|
|
|
char *mime = attachment->file_mime_type;
|
2015-06-24 14:18:51 +02:00
|
|
|
demuxer_add_attachment(demuxer, name, mime, attachment->file_data.start,
|
|
|
|
attachment->file_data.len);
|
2015-06-24 14:02:40 +02:00
|
|
|
MP_VERBOSE(demuxer, "Attachment: %s, %s, %zu bytes\n",
|
|
|
|
name, mime, attachment->file_data.len);
|
2006-07-07 20:26:51 +02:00
|
|
|
}
|
|
|
|
|
2010-01-25 18:42:37 +01:00
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
2009-12-29 20:06:21 +01:00
|
|
|
return 0;
|
2006-07-07 20:26:51 +02:00
|
|
|
}
|
|
|
|
|
2014-01-22 22:12:14 +01:00
|
|
|
static struct header_elem *get_header_element(struct demuxer *demuxer,
|
|
|
|
uint32_t id,
|
|
|
|
int64_t element_filepos)
|
|
|
|
{
|
|
|
|
struct mkv_demuxer *mkv_d = demuxer->priv;
|
|
|
|
|
|
|
|
// Note that some files in fact contain a SEEKHEAD with a list of all
|
|
|
|
// clusters - we have no use for that.
|
|
|
|
if (!ebml_is_mkv_level1_id(id) || id == MATROSKA_ID_CLUSTER)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (int n = 0; n < mkv_d->num_headers; n++) {
|
|
|
|
struct header_elem *elem = &mkv_d->headers[n];
|
|
|
|
// SEEKHEAD is the only element that can happen multiple times.
|
|
|
|
// Other elements might be duplicated (or attempted to be read twice,
|
|
|
|
// even if it's only once in the file), but only the first is used.
|
|
|
|
if (elem->id == id && (id != MATROSKA_ID_SEEKHEAD ||
|
|
|
|
elem->pos == element_filepos))
|
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
struct header_elem elem = { .id = id, .pos = element_filepos };
|
|
|
|
MP_TARRAY_APPEND(mkv_d, mkv_d->headers, mkv_d->num_headers, elem);
|
|
|
|
return &mkv_d->headers[mkv_d->num_headers - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark the level 1 element with the given id as read. Return whether it
|
|
|
|
// was marked read before (e.g. for checking whether it was already read).
|
|
|
|
// element_filepos refers to the file position of the element ID.
|
|
|
|
static bool test_header_element(struct demuxer *demuxer, uint32_t id,
|
|
|
|
int64_t element_filepos)
|
|
|
|
{
|
|
|
|
struct header_elem *elem = get_header_element(demuxer, id, element_filepos);
|
|
|
|
if (!elem)
|
|
|
|
return false;
|
|
|
|
if (elem->parsed)
|
|
|
|
return true;
|
|
|
|
elem->parsed = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
static int demux_mkv_read_seekhead(demuxer_t *demuxer)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2010-01-25 11:37:42 +01:00
|
|
|
struct mkv_demuxer *mkv_d = demuxer->priv;
|
|
|
|
struct stream *s = demuxer->stream;
|
|
|
|
int res = 0;
|
2013-10-19 23:15:06 +02:00
|
|
|
struct ebml_seek_head seekhead = {0};
|
2013-12-21 20:24:20 +01:00
|
|
|
struct ebml_parse_ctx parse_ctx = {demuxer->log};
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2015-06-27 21:42:19 +02:00
|
|
|
MP_VERBOSE(demuxer, "Parsing seek head...\n");
|
2010-01-25 11:37:42 +01:00
|
|
|
if (ebml_read_element(s, &parse_ctx, &seekhead, &ebml_seek_head_desc) < 0) {
|
2011-08-04 07:38:39 +02:00
|
|
|
res = -1;
|
2010-01-25 11:37:42 +01:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < seekhead.n_seek; i++) {
|
|
|
|
struct ebml_seek *seek = &seekhead.seek[i];
|
|
|
|
if (seek->n_seek_id != 1 || seek->n_seek_position != 1) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "Invalid SeekHead entry\n");
|
2010-01-25 11:37:42 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
uint64_t pos = seek->seek_position + mkv_d->segment_start;
|
2014-12-29 23:14:19 +01:00
|
|
|
MP_DBG(demuxer, "Element 0x%x at %"PRIu64".\n",
|
|
|
|
(unsigned)seek->seek_id, pos);
|
2015-03-06 15:06:59 +01:00
|
|
|
get_header_element(demuxer, seek->seek_id, pos);
|
2010-01-25 11:37:42 +01:00
|
|
|
}
|
|
|
|
out:
|
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
|
|
|
return res;
|
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2010-01-25 11:37:42 +01:00
|
|
|
static int read_header_element(struct demuxer *demuxer, uint32_t id,
|
2014-01-22 22:12:14 +01:00
|
|
|
int64_t start_filepos)
|
2010-01-25 11:37:42 +01:00
|
|
|
{
|
2014-01-22 22:12:14 +01:00
|
|
|
if (id == EBML_ID_INVALID)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (test_header_element(demuxer, id, start_filepos))
|
|
|
|
goto skip;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2010-01-25 11:37:42 +01:00
|
|
|
switch(id) {
|
|
|
|
case MATROSKA_ID_INFO:
|
2011-08-04 07:38:39 +02:00
|
|
|
return demux_mkv_read_info(demuxer);
|
2010-01-25 11:37:42 +01:00
|
|
|
case MATROSKA_ID_TRACKS:
|
2011-08-20 20:45:42 +02:00
|
|
|
return demux_mkv_read_tracks(demuxer);
|
2010-01-25 11:37:42 +01:00
|
|
|
case MATROSKA_ID_CUES:
|
2011-08-20 20:45:42 +02:00
|
|
|
return demux_mkv_read_cues(demuxer);
|
2010-01-25 11:37:42 +01:00
|
|
|
case MATROSKA_ID_TAGS:
|
2011-08-20 20:45:42 +02:00
|
|
|
return demux_mkv_read_tags(demuxer);
|
2010-01-25 11:37:42 +01:00
|
|
|
case MATROSKA_ID_SEEKHEAD:
|
2011-08-04 07:38:39 +02:00
|
|
|
return demux_mkv_read_seekhead(demuxer);
|
2010-01-25 11:37:42 +01:00
|
|
|
case MATROSKA_ID_CHAPTERS:
|
2011-08-20 20:45:42 +02:00
|
|
|
return demux_mkv_read_chapters(demuxer);
|
2010-01-25 11:37:42 +01:00
|
|
|
case MATROSKA_ID_ATTACHMENTS:
|
2011-08-20 20:45:42 +02:00
|
|
|
return demux_mkv_read_attachments(demuxer);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2014-01-22 22:12:14 +01:00
|
|
|
skip:
|
|
|
|
ebml_read_skip(demuxer->log, -1, demuxer->stream);
|
|
|
|
return 0;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2015-02-25 13:26:03 +01:00
|
|
|
static int read_deferred_element(struct demuxer *demuxer,
|
|
|
|
struct header_elem *elem)
|
|
|
|
{
|
|
|
|
stream_t *s = demuxer->stream;
|
|
|
|
|
|
|
|
if (elem->parsed)
|
|
|
|
return 0;
|
|
|
|
elem->parsed = true;
|
|
|
|
MP_VERBOSE(demuxer, "Seeking to %"PRIu64" to read header element 0x%x.\n",
|
|
|
|
elem->pos, (unsigned)elem->id);
|
|
|
|
if (!stream_seek(s, elem->pos)) {
|
|
|
|
MP_WARN(demuxer, "Failed to seek when reading header element.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (ebml_read_id(s) != elem->id) {
|
|
|
|
MP_ERR(demuxer, "Expected element 0x%x not found\n",
|
|
|
|
(unsigned int)elem->id);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
elem->parsed = false; // don't make read_header_element skip it
|
|
|
|
return read_header_element(demuxer, elem->id, elem->pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void read_deferred_cues(demuxer_t *demuxer)
|
|
|
|
{
|
|
|
|
mkv_demuxer_t *mkv_d = demuxer->priv;
|
|
|
|
|
2016-09-06 20:09:56 +02:00
|
|
|
if (mkv_d->index_complete || mkv_d->index_mode != 1)
|
2015-02-25 13:26:03 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
for (int n = 0; n < mkv_d->num_headers; n++) {
|
|
|
|
struct header_elem *elem = &mkv_d->headers[n];
|
|
|
|
|
|
|
|
if (elem->id == MATROSKA_ID_CUES)
|
|
|
|
read_deferred_element(demuxer, elem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-22 12:53:51 +01:00
|
|
|
static void add_coverart(struct demuxer *demuxer)
|
|
|
|
{
|
|
|
|
for (int n = 0; n < demuxer->num_attachments; n++) {
|
|
|
|
struct demux_attachment *att = &demuxer->attachments[n];
|
|
|
|
const char *codec = mp_map_mimetype_to_video_codec(att->type);
|
|
|
|
if (!codec)
|
|
|
|
continue;
|
demux: remove weird tripple-buffering for the sh_stream list
The demuxer infrastructure was originally single-threaded. To make it
suitable for multithreading (specifically, demuxing and decoding on
separate threads), some sort of tripple-buffering was introduced. There
are separate "struct demuxer" allocations. The demuxer thread sets the
state on d_thread. If anything changes, the state is copied to d_buffer
(the copy is protected by a lock), and the decoder thread is notified.
Then the decoder thread copies the state from d_buffer to d_user (again
while holding a lock). This avoids the need for locking in the
demuxer/decoder code itself (only demux.c needs an internal, "invisible"
lock.)
Remove the streams/num_streams fields from this tripple-buffering
schema. Move them to the internal struct, and protect them with the
internal lock. Use accessors for read access outside of demux.c.
Other than replacing all field accesses with accessors, this separates
allocating and adding sh_streams. This is needed to avoid race
conditions. Before this change, this was awkwardly handled by first
initializing the sh_stream, and then sending a stream change event. Now
the stream is allocated, then initialized, and then declared as
immutable and added (at which point it becomes visible to the decoder
thread immediately).
This change is useful for PR #2626. And eventually, we should probably
get entirely of the tripple buffering, and this makes a nice first step.
2015-12-23 21:44:53 +01:00
|
|
|
struct sh_stream *sh = demux_alloc_sh_stream(STREAM_VIDEO);
|
2015-02-01 18:34:49 +01:00
|
|
|
sh->demuxer_id = -1 - sh->index; // don't clash with mkv IDs
|
2016-01-12 23:48:19 +01:00
|
|
|
sh->codec->codec = codec;
|
2014-12-22 12:53:51 +01:00
|
|
|
sh->attached_picture = new_demux_packet_from(att->data, att->data_size);
|
2015-01-05 06:16:50 +01:00
|
|
|
if (sh->attached_picture) {
|
|
|
|
sh->attached_picture->pts = 0;
|
|
|
|
talloc_steal(sh, sh->attached_picture);
|
|
|
|
sh->attached_picture->keyframe = true;
|
|
|
|
}
|
2014-12-23 02:50:53 +01:00
|
|
|
sh->title = att->name;
|
demux: remove weird tripple-buffering for the sh_stream list
The demuxer infrastructure was originally single-threaded. To make it
suitable for multithreading (specifically, demuxing and decoding on
separate threads), some sort of tripple-buffering was introduced. There
are separate "struct demuxer" allocations. The demuxer thread sets the
state on d_thread. If anything changes, the state is copied to d_buffer
(the copy is protected by a lock), and the decoder thread is notified.
Then the decoder thread copies the state from d_buffer to d_user (again
while holding a lock). This avoids the need for locking in the
demuxer/decoder code itself (only demux.c needs an internal, "invisible"
lock.)
Remove the streams/num_streams fields from this tripple-buffering
schema. Move them to the internal struct, and protect them with the
internal lock. Use accessors for read access outside of demux.c.
Other than replacing all field accesses with accessors, this separates
allocating and adding sh_streams. This is needed to avoid race
conditions. Before this change, this was awkwardly handled by first
initializing the sh_stream, and then sending a stream change event. Now
the stream is allocated, then initialized, and then declared as
immutable and added (at which point it becomes visible to the decoder
thread immediately).
This change is useful for PR #2626. And eventually, we should probably
get entirely of the tripple buffering, and this makes a nice first step.
2015-12-23 21:44:53 +01:00
|
|
|
demux_add_sh_stream(demuxer, sh);
|
2014-12-22 12:53:51 +01:00
|
|
|
}
|
|
|
|
}
|
2010-01-25 11:37:42 +01:00
|
|
|
|
2015-06-21 18:19:10 +02:00
|
|
|
static void init_track(demuxer_t *demuxer, mkv_track_t *track,
|
|
|
|
struct sh_stream *sh)
|
|
|
|
{
|
|
|
|
track->stream = sh;
|
|
|
|
|
|
|
|
if (track->language && (strcmp(track->language, "und") != 0))
|
|
|
|
sh->lang = track->language;
|
|
|
|
|
|
|
|
sh->demuxer_id = track->tnum;
|
|
|
|
sh->title = track->name;
|
|
|
|
sh->default_track = track->default_track;
|
2015-06-27 22:02:24 +02:00
|
|
|
sh->forced_track = track->forced_track;
|
2015-06-21 18:19:10 +02:00
|
|
|
}
|
|
|
|
|
2013-04-14 19:23:18 +02:00
|
|
|
static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track);
|
|
|
|
static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track);
|
|
|
|
static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track);
|
2006-08-26 21:17:04 +02:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
static void display_create_tracks(demuxer_t *demuxer)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
|
|
|
|
2013-04-14 19:23:18 +02:00
|
|
|
for (int i = 0; i < mkv_d->num_tracks; i++) {
|
2009-12-29 20:06:21 +01:00
|
|
|
switch (mkv_d->tracks[i]->type) {
|
2004-01-19 20:16:10 +01:00
|
|
|
case MATROSKA_TRACK_VIDEO:
|
2013-04-14 19:23:18 +02:00
|
|
|
demux_mkv_open_video(demuxer, mkv_d->tracks[i]);
|
2009-12-29 20:06:21 +01:00
|
|
|
break;
|
2004-01-19 20:16:10 +01:00
|
|
|
case MATROSKA_TRACK_AUDIO:
|
2013-04-14 19:23:18 +02:00
|
|
|
demux_mkv_open_audio(demuxer, mkv_d->tracks[i]);
|
2009-12-29 20:06:21 +01:00
|
|
|
break;
|
2004-01-19 20:16:10 +01:00
|
|
|
case MATROSKA_TRACK_SUBTITLE:
|
2013-04-14 19:23:18 +02:00
|
|
|
demux_mkv_open_sub(demuxer, mkv_d->tracks[i]);
|
2009-12-29 20:06:21 +01:00
|
|
|
break;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-26 23:16:25 +02:00
|
|
|
static const char *const mkv_video_tags[][2] = {
|
2015-06-19 21:41:57 +02:00
|
|
|
{"V_MJPEG", "mjpeg"},
|
|
|
|
{"V_MPEG1", "mpeg1video"},
|
|
|
|
{"V_MPEG2", "mpeg2video"},
|
|
|
|
{"V_MPEG4/ISO/SP", "mpeg4"},
|
|
|
|
{"V_MPEG4/ISO/ASP", "mpeg4"},
|
|
|
|
{"V_MPEG4/ISO/AP", "mpeg4"},
|
|
|
|
{"V_MPEG4/ISO/AVC", "h264"},
|
|
|
|
{"V_THEORA", "theora"},
|
|
|
|
{"V_VP8", "vp8"},
|
|
|
|
{"V_VP9", "vp9"},
|
|
|
|
{"V_DIRAC", "dirac"},
|
|
|
|
{"V_PRORES", "prores"},
|
|
|
|
{"V_MPEGH/ISO/HEVC", "hevc"},
|
2014-04-26 22:24:15 +02:00
|
|
|
{0}
|
2007-05-10 15:58:57 +02:00
|
|
|
};
|
|
|
|
|
2013-04-14 19:23:18 +02:00
|
|
|
static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2014-10-13 16:42:00 +02:00
|
|
|
unsigned char *extradata = NULL;
|
2013-04-14 06:04:58 +02:00
|
|
|
unsigned int extradata_size = 0;
|
demux: remove weird tripple-buffering for the sh_stream list
The demuxer infrastructure was originally single-threaded. To make it
suitable for multithreading (specifically, demuxing and decoding on
separate threads), some sort of tripple-buffering was introduced. There
are separate "struct demuxer" allocations. The demuxer thread sets the
state on d_thread. If anything changes, the state is copied to d_buffer
(the copy is protected by a lock), and the decoder thread is notified.
Then the decoder thread copies the state from d_buffer to d_user (again
while holding a lock). This avoids the need for locking in the
demuxer/decoder code itself (only demux.c needs an internal, "invisible"
lock.)
Remove the streams/num_streams fields from this tripple-buffering
schema. Move them to the internal struct, and protect them with the
internal lock. Use accessors for read access outside of demux.c.
Other than replacing all field accesses with accessors, this separates
allocating and adding sh_streams. This is needed to avoid race
conditions. Before this change, this was awkwardly handled by first
initializing the sh_stream, and then sending a stream change event. Now
the stream is allocated, then initialized, and then declared as
immutable and added (at which point it becomes visible to the decoder
thread immediately).
This change is useful for PR #2626. And eventually, we should probably
get entirely of the tripple buffering, and this makes a nice first step.
2015-12-23 21:44:53 +01:00
|
|
|
struct sh_stream *sh = demux_alloc_sh_stream(STREAM_VIDEO);
|
2015-06-21 18:19:10 +02:00
|
|
|
init_track(demuxer, track, sh);
|
2016-01-12 23:48:19 +01:00
|
|
|
struct mp_codec_params *sh_v = sh->codec;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2015-06-13 21:27:00 +02:00
|
|
|
sh_v->bits_per_coded_sample = 24;
|
|
|
|
|
2015-06-19 21:41:57 +02:00
|
|
|
if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC")) { /* AVI compatibility mode */
|
2014-09-25 02:22:44 +02:00
|
|
|
// The private_data contains a BITMAPINFOHEADER struct
|
|
|
|
if (track->private_data == NULL || track->private_size < 40)
|
demux: remove weird tripple-buffering for the sh_stream list
The demuxer infrastructure was originally single-threaded. To make it
suitable for multithreading (specifically, demuxing and decoding on
separate threads), some sort of tripple-buffering was introduced. There
are separate "struct demuxer" allocations. The demuxer thread sets the
state on d_thread. If anything changes, the state is copied to d_buffer
(the copy is protected by a lock), and the decoder thread is notified.
Then the decoder thread copies the state from d_buffer to d_user (again
while holding a lock). This avoids the need for locking in the
demuxer/decoder code itself (only demux.c needs an internal, "invisible"
lock.)
Remove the streams/num_streams fields from this tripple-buffering
schema. Move them to the internal struct, and protect them with the
internal lock. Use accessors for read access outside of demux.c.
Other than replacing all field accesses with accessors, this separates
allocating and adding sh_streams. This is needed to avoid race
conditions. Before this change, this was awkwardly handled by first
initializing the sh_stream, and then sending a stream change event. Now
the stream is allocated, then initialized, and then declared as
immutable and added (at which point it becomes visible to the decoder
thread immediately).
This change is useful for PR #2626. And eventually, we should probably
get entirely of the tripple buffering, and this makes a nice first step.
2015-12-23 21:44:53 +01:00
|
|
|
goto done;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2014-09-25 02:22:44 +02:00
|
|
|
unsigned char *h = track->private_data;
|
2009-12-29 20:06:21 +01:00
|
|
|
if (track->v_width == 0)
|
2014-09-25 02:22:44 +02:00
|
|
|
track->v_width = AV_RL32(h + 4); // biWidth
|
2009-12-29 20:06:21 +01:00
|
|
|
if (track->v_height == 0)
|
2014-09-25 02:22:44 +02:00
|
|
|
track->v_height = AV_RL32(h + 8); // biHeight
|
|
|
|
sh_v->bits_per_coded_sample = AV_RL16(h + 14); // biBitCount
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_v->codec_tag = AV_RL32(h + 16); // biCompression
|
2014-09-25 02:22:44 +02:00
|
|
|
|
|
|
|
extradata = track->private_data + 40;
|
|
|
|
extradata_size = track->private_size - 40;
|
2016-01-12 23:48:19 +01:00
|
|
|
mp_set_codec_from_tag(sh_v);
|
2015-06-13 21:17:48 +02:00
|
|
|
sh_v->avi_dts = true;
|
2015-06-13 21:27:00 +02:00
|
|
|
} else if (track->private_size >= RVPROPERTIES_SIZE
|
2015-06-19 21:41:57 +02:00
|
|
|
&& (!strcmp(track->codec_id, "V_REAL/RV10")
|
|
|
|
|| !strcmp(track->codec_id, "V_REAL/RV20")
|
|
|
|
|| !strcmp(track->codec_id, "V_REAL/RV30")
|
|
|
|
|| !strcmp(track->codec_id, "V_REAL/RV40")))
|
2015-06-13 21:27:00 +02:00
|
|
|
{
|
|
|
|
unsigned char *src;
|
|
|
|
unsigned int cnt;
|
|
|
|
|
|
|
|
src = (uint8_t *) track->private_data + RVPROPERTIES_SIZE;
|
|
|
|
|
|
|
|
cnt = track->private_size - RVPROPERTIES_SIZE;
|
2015-06-13 21:59:04 +02:00
|
|
|
uint32_t t2 = AV_RB32(src - 4);
|
|
|
|
switch (t2 == 0x10003000 || t2 == 0x10003001 ? '1' : track->codec_id[9]) {
|
2016-01-12 23:48:19 +01:00
|
|
|
case '1': sh_v->codec = "rv10"; break;
|
|
|
|
case '2': sh_v->codec = "rv20"; break;
|
|
|
|
case '3': sh_v->codec = "rv30"; break;
|
|
|
|
case '4': sh_v->codec = "rv40"; break;
|
2015-06-13 21:59:04 +02:00
|
|
|
}
|
2015-06-13 21:27:00 +02:00
|
|
|
// copy type1 and type2 info from rv properties
|
|
|
|
extradata_size = cnt + 8;
|
|
|
|
extradata = src - 8;
|
|
|
|
track->parse = true;
|
|
|
|
track->parse_timebase = 1e3;
|
2015-06-19 21:41:57 +02:00
|
|
|
} else if (strcmp(track->codec_id, "V_UNCOMPRESSED") == 0) {
|
2015-06-13 21:27:00 +02:00
|
|
|
// raw video, "like AVI" - this is a FourCC
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_v->codec_tag = track->colorspace;
|
|
|
|
sh_v->codec = "rawvideo";
|
2015-06-19 21:41:57 +02:00
|
|
|
} else if (strcmp(track->codec_id, "V_QUICKTIME") == 0) {
|
2015-06-13 21:27:00 +02:00
|
|
|
uint32_t fourcc1 = 0, fourcc2 = 0;
|
|
|
|
if (track->private_size >= 8) {
|
|
|
|
fourcc1 = AV_RL32(track->private_data + 0);
|
|
|
|
fourcc2 = AV_RL32(track->private_data + 4);
|
|
|
|
}
|
2017-06-18 15:00:36 +02:00
|
|
|
if (fourcc1 == MKTAG('S', 'V', 'Q', '3') ||
|
|
|
|
fourcc2 == MKTAG('S', 'V', 'Q', '3'))
|
2015-06-13 21:27:00 +02:00
|
|
|
{
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_v->codec = "svq3";
|
2015-06-13 21:27:00 +02:00
|
|
|
extradata = track->private_data;
|
|
|
|
extradata_size = track->private_size;
|
|
|
|
}
|
|
|
|
} else {
|
2015-06-26 23:16:25 +02:00
|
|
|
for (int i = 0; mkv_video_tags[i][0]; i++) {
|
|
|
|
if (!strcmp(mkv_video_tags[i][0], track->codec_id)) {
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_v->codec = mkv_video_tags[i][1];
|
2015-06-26 23:16:25 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-06-13 22:08:19 +02:00
|
|
|
if (track->private_data && track->private_size > 0) {
|
2015-06-13 21:27:00 +02:00
|
|
|
extradata = track->private_data;
|
|
|
|
extradata_size = track->private_size;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-12 23:48:19 +01:00
|
|
|
const char *codec = sh_v->codec ? sh_v->codec : "";
|
2015-06-13 21:59:04 +02:00
|
|
|
if (!strcmp(codec, "vp9")) {
|
2014-12-31 15:00:18 +01:00
|
|
|
track->parse = true;
|
2015-02-05 21:55:11 +01:00
|
|
|
track->parse_timebase = 1e9;
|
2015-06-13 21:59:04 +02:00
|
|
|
} else if (!strcmp(codec, "mjpeg")) {
|
2017-06-18 15:00:36 +02:00
|
|
|
sh_v->codec_tag = MKTAG('m', 'j', 'p', 'g');
|
2015-02-05 21:52:21 +01:00
|
|
|
}
|
2014-12-31 15:00:18 +01:00
|
|
|
|
2014-06-29 23:22:07 +02:00
|
|
|
if (extradata_size > 0x1000000) {
|
|
|
|
MP_WARN(demuxer, "Invalid CodecPrivate\n");
|
demux: remove weird tripple-buffering for the sh_stream list
The demuxer infrastructure was originally single-threaded. To make it
suitable for multithreading (specifically, demuxing and decoding on
separate threads), some sort of tripple-buffering was introduced. There
are separate "struct demuxer" allocations. The demuxer thread sets the
state on d_thread. If anything changes, the state is copied to d_buffer
(the copy is protected by a lock), and the decoder thread is notified.
Then the decoder thread copies the state from d_buffer to d_user (again
while holding a lock). This avoids the need for locking in the
demuxer/decoder code itself (only demux.c needs an internal, "invisible"
lock.)
Remove the streams/num_streams fields from this tripple-buffering
schema. Move them to the internal struct, and protect them with the
internal lock. Use accessors for read access outside of demux.c.
Other than replacing all field accesses with accessors, this separates
allocating and adding sh_streams. This is needed to avoid race
conditions. Before this change, this was awkwardly handled by first
initializing the sh_stream, and then sending a stream change event. Now
the stream is allocated, then initialized, and then declared as
immutable and added (at which point it becomes visible to the decoder
thread immediately).
This change is useful for PR #2626. And eventually, we should probably
get entirely of the tripple buffering, and this makes a nice first step.
2015-12-23 21:44:53 +01:00
|
|
|
goto done;
|
2014-06-29 23:22:07 +02:00
|
|
|
}
|
|
|
|
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_v->extradata = talloc_memdup(sh_v, extradata, extradata_size);
|
|
|
|
sh_v->extradata_size = extradata_size;
|
|
|
|
if (!sh_v->codec) {
|
2014-12-08 18:49:39 +01:00
|
|
|
MP_WARN(demuxer, "Unknown/unsupported CodecID (%s) or missing/bad "
|
|
|
|
"CodecPrivate data (track %u).\n",
|
|
|
|
track->codec_id, track->tnum);
|
2013-01-30 00:57:07 +01:00
|
|
|
}
|
2009-12-29 20:06:21 +01:00
|
|
|
sh_v->fps = track->v_frate;
|
2015-02-05 21:54:08 +01:00
|
|
|
sh_v->disp_w = track->v_width;
|
|
|
|
sh_v->disp_h = track->v_height;
|
2015-12-19 20:04:31 +01:00
|
|
|
|
|
|
|
int dw = track->v_dwidth_set ? track->v_dwidth : track->v_width;
|
|
|
|
int dh = track->v_dheight_set ? track->v_dheight : track->v_height;
|
|
|
|
struct mp_image_params p = {.w = track->v_width, .h = track->v_height};
|
|
|
|
mp_image_params_set_dsize(&p, dw, dh);
|
|
|
|
sh_v->par_w = p.p_w;
|
|
|
|
sh_v->par_h = p.p_h;
|
|
|
|
|
2014-08-30 23:24:46 +02:00
|
|
|
sh_v->stereo_mode = track->stereo_mode;
|
2016-11-08 17:53:55 +01:00
|
|
|
sh_v->color = track->color;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
demux: remove weird tripple-buffering for the sh_stream list
The demuxer infrastructure was originally single-threaded. To make it
suitable for multithreading (specifically, demuxing and decoding on
separate threads), some sort of tripple-buffering was introduced. There
are separate "struct demuxer" allocations. The demuxer thread sets the
state on d_thread. If anything changes, the state is copied to d_buffer
(the copy is protected by a lock), and the decoder thread is notified.
Then the decoder thread copies the state from d_buffer to d_user (again
while holding a lock). This avoids the need for locking in the
demuxer/decoder code itself (only demux.c needs an internal, "invisible"
lock.)
Remove the streams/num_streams fields from this tripple-buffering
schema. Move them to the internal struct, and protect them with the
internal lock. Use accessors for read access outside of demux.c.
Other than replacing all field accesses with accessors, this separates
allocating and adding sh_streams. This is needed to avoid race
conditions. Before this change, this was awkwardly handled by first
initializing the sh_stream, and then sending a stream change event. Now
the stream is allocated, then initialized, and then declared as
immutable and added (at which point it becomes visible to the decoder
thread immediately).
This change is useful for PR #2626. And eventually, we should probably
get entirely of the tripple buffering, and this makes a nice first step.
2015-12-23 21:44:53 +01:00
|
|
|
done:
|
|
|
|
demux_add_sh_stream(demuxer, sh);
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
return 0;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2015-07-20 12:48:41 +02:00
|
|
|
// Parse VorbisComment and look for WAVEFORMATEXTENSIBLE_CHANNEL_MASK.
|
|
|
|
// Do not change *channels if nothing found or an error happens.
|
|
|
|
static void parse_vorbis_chmap(struct mp_chmap *channels, unsigned char *data,
|
|
|
|
int size)
|
|
|
|
{
|
|
|
|
// Skip the useless vendor string.
|
|
|
|
if (size < 4)
|
|
|
|
return;
|
|
|
|
uint32_t vendor_length = AV_RL32(data);
|
|
|
|
if (vendor_length + 4 > size) // also check for the next AV_RB32 below
|
|
|
|
return;
|
|
|
|
size -= vendor_length + 4;
|
|
|
|
data += vendor_length + 4;
|
|
|
|
uint32_t num_headers = AV_RL32(data);
|
|
|
|
size -= 4;
|
|
|
|
data += 4;
|
|
|
|
for (int n = 0; n < num_headers; n++) {
|
|
|
|
if (size < 4)
|
|
|
|
return;
|
|
|
|
uint32_t len = AV_RL32(data);
|
|
|
|
size -= 4;
|
|
|
|
data += 4;
|
|
|
|
if (len > size)
|
|
|
|
return;
|
|
|
|
if (len > 34 && !memcmp(data, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK=", 34)) {
|
|
|
|
char smask[80];
|
|
|
|
snprintf(smask, sizeof(smask), "%.*s", (int)(len - 34), data + 34);
|
|
|
|
char *end = NULL;
|
|
|
|
uint32_t mask = strtol(smask, &end, 0);
|
|
|
|
if (!end || end[0])
|
|
|
|
mask = 0;
|
|
|
|
struct mp_chmap chmask = {0};
|
|
|
|
mp_chmap_from_waveext(&chmask, mask);
|
|
|
|
if (mp_chmap_is_valid(&chmask))
|
|
|
|
*channels = chmask;
|
|
|
|
}
|
|
|
|
size -= len;
|
|
|
|
data += len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse VorbisComment-in-FLAC and look for WAVEFORMATEXTENSIBLE_CHANNEL_MASK.
|
|
|
|
// Do not change *channels if nothing found or an error happens.
|
|
|
|
static void parse_flac_chmap(struct mp_chmap *channels, unsigned char *data,
|
|
|
|
int size)
|
|
|
|
{
|
|
|
|
// Skip FLAC header.
|
|
|
|
if (size < 4)
|
|
|
|
return;
|
|
|
|
data += 4;
|
|
|
|
size -= 4;
|
|
|
|
// Parse FLAC blocks...
|
|
|
|
while (size >= 4) {
|
|
|
|
unsigned btype = data[0] & 0x7F;
|
|
|
|
unsigned bsize = AV_RB24(data + 1);
|
|
|
|
data += 4;
|
|
|
|
size -= 4;
|
|
|
|
if (bsize > size)
|
|
|
|
return;
|
|
|
|
if (btype == 4) // VORBIS_COMMENT
|
|
|
|
parse_vorbis_chmap(channels, data, bsize);
|
|
|
|
data += bsize;
|
|
|
|
size -= bsize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-26 23:16:25 +02:00
|
|
|
static const char *const mkv_audio_tags[][2] = {
|
2016-11-23 15:55:22 +01:00
|
|
|
{ "A_MPEG/L2", "mp2" },
|
2015-06-19 21:41:57 +02:00
|
|
|
{ "A_MPEG/L3", "mp3" },
|
2015-06-19 21:42:55 +02:00
|
|
|
{ "A_AC3", "ac3" },
|
|
|
|
{ "A_EAC3", "eac3" },
|
2015-06-19 21:41:57 +02:00
|
|
|
{ "A_DTS", "dts" },
|
|
|
|
{ "A_AAC", "aac" },
|
|
|
|
{ "A_VORBIS", "vorbis" },
|
|
|
|
{ "A_OPUS", "opus" },
|
|
|
|
{ "A_OPUS/EXPERIMENTAL", "opus" },
|
|
|
|
{ "A_QUICKTIME/QDMC", "qdmc" },
|
|
|
|
{ "A_QUICKTIME/QDM2", "qdm2" },
|
|
|
|
{ "A_WAVPACK4", "wavpack" },
|
|
|
|
{ "A_TRUEHD", "truehd" },
|
|
|
|
{ "A_FLAC", "flac" },
|
|
|
|
{ "A_ALAC", "alac" },
|
|
|
|
{ "A_TTA1", "tta" },
|
2011-08-20 04:54:27 +02:00
|
|
|
{ NULL },
|
|
|
|
};
|
|
|
|
|
2013-04-14 19:23:18 +02:00
|
|
|
static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
demux: remove weird tripple-buffering for the sh_stream list
The demuxer infrastructure was originally single-threaded. To make it
suitable for multithreading (specifically, demuxing and decoding on
separate threads), some sort of tripple-buffering was introduced. There
are separate "struct demuxer" allocations. The demuxer thread sets the
state on d_thread. If anything changes, the state is copied to d_buffer
(the copy is protected by a lock), and the decoder thread is notified.
Then the decoder thread copies the state from d_buffer to d_user (again
while holding a lock). This avoids the need for locking in the
demuxer/decoder code itself (only demux.c needs an internal, "invisible"
lock.)
Remove the streams/num_streams fields from this tripple-buffering
schema. Move them to the internal struct, and protect them with the
internal lock. Use accessors for read access outside of demux.c.
Other than replacing all field accesses with accessors, this separates
allocating and adding sh_streams. This is needed to avoid race
conditions. Before this change, this was awkwardly handled by first
initializing the sh_stream, and then sending a stream change event. Now
the stream is allocated, then initialized, and then declared as
immutable and added (at which point it becomes visible to the decoder
thread immediately).
This change is useful for PR #2626. And eventually, we should probably
get entirely of the tripple buffering, and this makes a nice first step.
2015-12-23 21:44:53 +01:00
|
|
|
struct sh_stream *sh = demux_alloc_sh_stream(STREAM_AUDIO);
|
2015-06-21 18:19:10 +02:00
|
|
|
init_track(demuxer, track, sh);
|
2016-01-12 23:48:19 +01:00
|
|
|
struct mp_codec_params *sh_a = sh->codec;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2014-11-27 22:43:38 +01:00
|
|
|
if (track->private_size > 0x1000000)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
unsigned char *extradata = track->private_data;
|
|
|
|
unsigned int extradata_len = track->private_size;
|
2014-09-25 01:56:51 +02:00
|
|
|
|
2013-07-16 22:44:15 +02:00
|
|
|
if (!track->a_osfreq)
|
|
|
|
track->a_osfreq = track->a_sfreq;
|
2015-06-19 21:39:59 +02:00
|
|
|
sh_a->bits_per_coded_sample = track->a_bps ? track->a_bps : 16;
|
2015-06-19 21:42:55 +02:00
|
|
|
sh_a->samplerate = (uint32_t) track->a_osfreq;
|
demux_mkv: support FFmpeg A_MS/ACM extensions
Indeed, FFmpeg found a way to maximize the misery around VfW/AVI-style
muxing. It appears it can mux a number of random codecs by using random
format tags. To make this even more stranger, it has a probably custom
GUID for signaling them, although for unknown reasons this is done only
"sometimes" (judging from FFmpeg's riffenc.c).
Whatever, it's not too hard to support it. Also apparently fix the
incorrect interpretation of extended formats - there's absolutely no
reason to assume they're always PCM. Instead, check for the correct
GUIDs. Also while we're at it, move the channel mask handling also to
codec_tag.c, so all WAVEFORMATEXTENSIBLE handling is in one place. (With
the normal wav header handling strangely still in demux_mkv.c.)
The case I was looking at (aac_latm muxing) decodes now. While I'm not
entirely sure about its correctness (libavformat has a weird
special-case for SBR), it certainly doesn't try to play it as PCM,
which is much of an improvement.
The extradata mess in the demux_mkv.c A_MS/ACM code path is unfortunate
and ugly, but has less impact than refactoring all the code to make
this specific case nicer.
Did I mention yet that I hate VfW-style mkv muxing?
2017-06-03 22:41:45 +02:00
|
|
|
mp_chmap_set_unknown(&sh_a->channels, track->a_channels);
|
2015-06-19 21:42:55 +02:00
|
|
|
|
2015-06-26 23:16:25 +02:00
|
|
|
for (int i = 0; mkv_audio_tags[i][0]; i++) {
|
|
|
|
if (!strcmp(mkv_audio_tags[i][0], track->codec_id)) {
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->codec = mkv_audio_tags[i][1];
|
2015-06-19 21:42:55 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-09-25 02:22:44 +02:00
|
|
|
|
2015-06-19 21:41:57 +02:00
|
|
|
if (!strcmp(track->codec_id, "A_MS/ACM")) { /* AVI compatibility mode */
|
2014-09-25 02:22:44 +02:00
|
|
|
// The private_data contains a WAVEFORMATEX struct
|
|
|
|
if (track->private_size < 18)
|
2011-08-20 04:54:27 +02:00
|
|
|
goto error;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "track with MS compat audio.\n");
|
2014-09-25 02:22:44 +02:00
|
|
|
unsigned char *h = track->private_data;
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->codec_tag = AV_RL16(h + 0); // wFormatTag
|
2009-12-29 20:06:21 +01:00
|
|
|
if (track->a_channels == 0)
|
2014-09-25 02:22:44 +02:00
|
|
|
track->a_channels = AV_RL16(h + 2); // nChannels
|
2015-06-19 21:42:55 +02:00
|
|
|
if (sh_a->samplerate == 0)
|
|
|
|
sh_a->samplerate = AV_RL32(h + 4); // nSamplesPerSec
|
2014-09-25 02:22:44 +02:00
|
|
|
sh_a->bitrate = AV_RL32(h + 8) * 8; // nAvgBytesPerSec
|
|
|
|
sh_a->block_align = AV_RL16(h + 12); // nBlockAlign
|
2009-12-29 20:06:21 +01:00
|
|
|
if (track->a_bps == 0)
|
2014-09-25 02:22:44 +02:00
|
|
|
track->a_bps = AV_RL16(h + 14); // wBitsPerSample
|
|
|
|
extradata = track->private_data + 18;
|
|
|
|
extradata_len = track->private_size - 18;
|
2015-06-19 21:39:59 +02:00
|
|
|
sh_a->bits_per_coded_sample = track->a_bps;
|
demux_mkv: support FFmpeg A_MS/ACM extensions
Indeed, FFmpeg found a way to maximize the misery around VfW/AVI-style
muxing. It appears it can mux a number of random codecs by using random
format tags. To make this even more stranger, it has a probably custom
GUID for signaling them, although for unknown reasons this is done only
"sometimes" (judging from FFmpeg's riffenc.c).
Whatever, it's not too hard to support it. Also apparently fix the
incorrect interpretation of extended formats - there's absolutely no
reason to assume they're always PCM. Instead, check for the correct
GUIDs. Also while we're at it, move the channel mask handling also to
codec_tag.c, so all WAVEFORMATEXTENSIBLE handling is in one place. (With
the normal wav header handling strangely still in demux_mkv.c.)
The case I was looking at (aac_latm muxing) decodes now. While I'm not
entirely sure about its correctness (libavformat has a weird
special-case for SBR), it certainly doesn't try to play it as PCM,
which is much of an improvement.
The extradata mess in the demux_mkv.c A_MS/ACM code path is unfortunate
and ugly, but has less impact than refactoring all the code to make
this specific case nicer.
Did I mention yet that I hate VfW-style mkv muxing?
2017-06-03 22:41:45 +02:00
|
|
|
sh_a->extradata = extradata;
|
|
|
|
sh_a->extradata_size = extradata_len;
|
2016-01-12 23:48:19 +01:00
|
|
|
mp_set_codec_from_tag(sh_a);
|
demux_mkv: support FFmpeg A_MS/ACM extensions
Indeed, FFmpeg found a way to maximize the misery around VfW/AVI-style
muxing. It appears it can mux a number of random codecs by using random
format tags. To make this even more stranger, it has a probably custom
GUID for signaling them, although for unknown reasons this is done only
"sometimes" (judging from FFmpeg's riffenc.c).
Whatever, it's not too hard to support it. Also apparently fix the
incorrect interpretation of extended formats - there's absolutely no
reason to assume they're always PCM. Instead, check for the correct
GUIDs. Also while we're at it, move the channel mask handling also to
codec_tag.c, so all WAVEFORMATEXTENSIBLE handling is in one place. (With
the normal wav header handling strangely still in demux_mkv.c.)
The case I was looking at (aac_latm muxing) decodes now. While I'm not
entirely sure about its correctness (libavformat has a weird
special-case for SBR), it certainly doesn't try to play it as PCM,
which is much of an improvement.
The extradata mess in the demux_mkv.c A_MS/ACM code path is unfortunate
and ugly, but has less impact than refactoring all the code to make
this specific case nicer.
Did I mention yet that I hate VfW-style mkv muxing?
2017-06-03 22:41:45 +02:00
|
|
|
extradata = sh_a->extradata;
|
|
|
|
extradata_len = sh_a->extradata_size;
|
2015-06-19 21:42:55 +02:00
|
|
|
} else if (!strcmp(track->codec_id, "A_PCM/INT/LIT")) {
|
|
|
|
bool sign = sh_a->bits_per_coded_sample > 8;
|
2016-01-12 23:48:19 +01:00
|
|
|
mp_set_pcm_codec(sh_a, sign, false, sh_a->bits_per_coded_sample, false);
|
2015-06-19 21:42:55 +02:00
|
|
|
} else if (!strcmp(track->codec_id, "A_PCM/INT/BIG")) {
|
2015-06-19 21:39:59 +02:00
|
|
|
bool sign = sh_a->bits_per_coded_sample > 8;
|
2016-01-12 23:48:19 +01:00
|
|
|
mp_set_pcm_codec(sh_a, sign, false, sh_a->bits_per_coded_sample, true);
|
2015-06-19 21:42:55 +02:00
|
|
|
} else if (!strcmp(track->codec_id, "A_PCM/FLOAT/IEEE")) {
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->codec = sh_a->bits_per_coded_sample == 64 ? "pcm_f64le" : "pcm_f32le";
|
2015-06-19 21:39:59 +02:00
|
|
|
} else if (!strncmp(track->codec_id, "A_REAL/", 7)) {
|
2011-08-20 04:54:27 +02:00
|
|
|
if (track->private_size < RAPROPERTIES4_SIZE)
|
|
|
|
goto error;
|
2009-12-29 20:06:21 +01:00
|
|
|
/* Common initialization for all RealAudio codecs */
|
|
|
|
unsigned char *src = track->private_data;
|
|
|
|
|
2014-11-27 22:24:32 +01:00
|
|
|
int version = AV_RB16(src + 4);
|
|
|
|
unsigned int flavor = AV_RB16(src + 22);
|
2009-12-29 20:06:21 +01:00
|
|
|
track->coded_framesize = AV_RB32(src + 24);
|
|
|
|
track->sub_packet_h = AV_RB16(src + 40);
|
2014-09-25 01:56:51 +02:00
|
|
|
sh_a->block_align = track->audiopk_size = AV_RB16(src + 42);
|
2009-12-29 20:06:21 +01:00
|
|
|
track->sub_packet_size = AV_RB16(src + 44);
|
2015-06-19 21:43:55 +02:00
|
|
|
int offset = 0;
|
2009-12-29 20:06:21 +01:00
|
|
|
if (version == 4) {
|
2015-06-19 21:43:55 +02:00
|
|
|
offset += RAPROPERTIES4_SIZE;
|
|
|
|
if (offset + 1 > track->private_size)
|
|
|
|
goto error;
|
|
|
|
offset += (src[offset] + 1) * 2 + 3;
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
2015-06-19 21:43:55 +02:00
|
|
|
offset += RAPROPERTIES5_SIZE + 3 + (version == 5 ? 1 : 0);
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2014-06-29 23:22:07 +02:00
|
|
|
if (track->audiopk_size == 0 || track->sub_packet_size == 0 ||
|
|
|
|
track->sub_packet_h == 0 || track->coded_framesize == 0)
|
|
|
|
goto error;
|
|
|
|
if (track->coded_framesize > 0x40000000)
|
|
|
|
goto error;
|
|
|
|
|
2015-06-19 21:43:55 +02:00
|
|
|
if (offset + 4 > track->private_size)
|
|
|
|
goto error;
|
|
|
|
uint32_t codecdata_length = AV_RB32(src + offset);
|
|
|
|
offset += 4;
|
|
|
|
if (offset > track->private_size ||
|
|
|
|
codecdata_length > track->private_size - offset)
|
2014-06-29 23:22:07 +02:00
|
|
|
goto error;
|
2014-09-25 01:56:51 +02:00
|
|
|
extradata_len = codecdata_length;
|
2015-06-19 21:43:55 +02:00
|
|
|
extradata = src + offset;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2015-06-19 21:42:55 +02:00
|
|
|
if (!strcmp(track->codec_id, "A_REAL/ATRC")) {
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->codec = "atrac3";
|
2014-11-21 05:07:13 +01:00
|
|
|
if (flavor >= MP_ARRAY_SIZE(atrc_fl2bps))
|
|
|
|
goto error;
|
2014-09-25 01:56:51 +02:00
|
|
|
sh_a->bitrate = atrc_fl2bps[flavor] * 8;
|
|
|
|
sh_a->block_align = track->sub_packet_size;
|
2015-06-19 21:42:55 +02:00
|
|
|
} else if (!strcmp(track->codec_id, "A_REAL/COOK")) {
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->codec = "cook";
|
2014-11-21 05:07:13 +01:00
|
|
|
if (flavor >= MP_ARRAY_SIZE(cook_fl2bps))
|
|
|
|
goto error;
|
2014-09-25 01:56:51 +02:00
|
|
|
sh_a->bitrate = cook_fl2bps[flavor] * 8;
|
|
|
|
sh_a->block_align = track->sub_packet_size;
|
2015-06-19 21:42:55 +02:00
|
|
|
} else if (!strcmp(track->codec_id, "A_REAL/SIPR")) {
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->codec = "sipr";
|
2014-11-21 05:07:13 +01:00
|
|
|
if (flavor >= MP_ARRAY_SIZE(sipr_fl2bps))
|
|
|
|
goto error;
|
2014-09-25 01:56:51 +02:00
|
|
|
sh_a->bitrate = sipr_fl2bps[flavor] * 8;
|
|
|
|
sh_a->block_align = track->coded_framesize;
|
2015-06-19 21:42:55 +02:00
|
|
|
} else if (!strcmp(track->codec_id, "A_REAL/28_8")) {
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->codec = "ra_288";
|
2014-09-25 01:56:51 +02:00
|
|
|
sh_a->bitrate = 3600 * 8;
|
|
|
|
sh_a->block_align = track->coded_framesize;
|
2015-06-19 21:42:55 +02:00
|
|
|
} else if (!strcmp(track->codec_id, "A_REAL/DNET")) {
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->codec = "ac3";
|
2015-06-19 21:42:55 +02:00
|
|
|
} else {
|
|
|
|
goto error;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2015-02-05 21:55:11 +01:00
|
|
|
track->audio_buf =
|
|
|
|
talloc_array_size(track, track->sub_packet_h, track->audiopk_size);
|
|
|
|
track->audio_timestamp =
|
|
|
|
talloc_array(track, double, track->sub_packet_h);
|
2015-06-19 21:42:55 +02:00
|
|
|
} else if (!strncmp(track->codec_id, "A_AAC/", 6)) {
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->codec = "aac";
|
2015-06-19 21:42:55 +02:00
|
|
|
|
|
|
|
/* Recreate the 'private data' (not needed for plain A_AAC) */
|
|
|
|
int srate_idx = aac_get_sample_rate_index(track->a_sfreq);
|
|
|
|
const char *tail = "";
|
|
|
|
if (strlen(track->codec_id) >= 12)
|
|
|
|
tail = &track->codec_id[12];
|
|
|
|
int profile = 3;
|
|
|
|
if (!strncmp(tail, "MAIN", 4))
|
|
|
|
profile = 0;
|
|
|
|
else if (!strncmp(tail, "LC", 2))
|
|
|
|
profile = 1;
|
|
|
|
else if (!strncmp(tail, "SSR", 3))
|
|
|
|
profile = 2;
|
2015-06-21 17:49:43 +02:00
|
|
|
extradata = talloc_size(sh_a, 5);
|
|
|
|
extradata[0] = ((profile + 1) << 3) | ((srate_idx & 0xE) >> 1);
|
|
|
|
extradata[1] = ((srate_idx & 0x1) << 7) | (track->a_channels << 3);
|
2015-06-19 21:42:55 +02:00
|
|
|
|
|
|
|
if (strstr(track->codec_id, "SBR") != NULL) {
|
|
|
|
/* HE-AAC (aka SBR AAC) */
|
2015-06-21 17:49:43 +02:00
|
|
|
extradata_len = 5;
|
2015-06-19 21:42:55 +02:00
|
|
|
|
|
|
|
srate_idx = aac_get_sample_rate_index(sh_a->samplerate);
|
2015-06-21 17:49:43 +02:00
|
|
|
extradata[2] = AAC_SYNC_EXTENSION_TYPE >> 3;
|
|
|
|
extradata[3] = ((AAC_SYNC_EXTENSION_TYPE & 0x07) << 5) | 5;
|
|
|
|
extradata[4] = (1 << 7) | (srate_idx << 3);
|
2015-06-19 21:42:55 +02:00
|
|
|
track->default_duration = 1024.0 / (sh_a->samplerate / 2);
|
|
|
|
} else {
|
2015-06-21 17:49:43 +02:00
|
|
|
extradata_len = 2;
|
2015-06-19 21:42:55 +02:00
|
|
|
track->default_duration = 1024.0 / sh_a->samplerate;
|
|
|
|
}
|
|
|
|
} else if (!strncmp(track->codec_id, "A_AC3/", 6)) {
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->codec = "ac3";
|
2015-06-19 21:42:55 +02:00
|
|
|
} else if (!strncmp(track->codec_id, "A_EAC3/", 7)) {
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->codec = "eac3";
|
2015-06-19 21:42:55 +02:00
|
|
|
}
|
|
|
|
|
2016-01-12 23:48:19 +01:00
|
|
|
if (!sh_a->codec)
|
2015-06-19 21:42:55 +02:00
|
|
|
goto error;
|
2015-02-05 21:55:11 +01:00
|
|
|
|
2016-01-12 23:48:19 +01:00
|
|
|
const char *codec = sh_a->codec;
|
2016-11-23 15:55:22 +01:00
|
|
|
if (!strcmp(codec, "mp2") || !strcmp(codec, "mp3") ||
|
|
|
|
!strcmp(codec, "truehd"))
|
|
|
|
{
|
2015-06-19 21:42:55 +02:00
|
|
|
track->parse = true;
|
2015-06-19 21:39:59 +02:00
|
|
|
} else if (!strcmp(codec, "flac")) {
|
2014-11-27 22:43:38 +01:00
|
|
|
unsigned char *ptr = extradata;
|
|
|
|
unsigned int size = extradata_len;
|
2009-12-29 20:06:21 +01:00
|
|
|
if (size < 4 || ptr[0] != 'f' || ptr[1] != 'L' || ptr[2] != 'a'
|
|
|
|
|| ptr[3] != 'C') {
|
2015-06-21 17:49:43 +02:00
|
|
|
extradata = talloc_size(sh_a, 4);
|
|
|
|
extradata_len = 4;
|
|
|
|
memcpy(extradata, "fLaC", 4);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2015-07-20 12:48:41 +02:00
|
|
|
parse_flac_chmap(&sh_a->channels, extradata, extradata_len);
|
2015-06-19 21:39:59 +02:00
|
|
|
} else if (!strcmp(codec, "alac")) {
|
2014-11-27 22:43:38 +01:00
|
|
|
if (track->private_size) {
|
2015-06-21 17:49:43 +02:00
|
|
|
extradata_len = track->private_size + 12;
|
|
|
|
extradata = talloc_size(sh_a, extradata_len);
|
|
|
|
char *data = extradata;
|
|
|
|
AV_WB32(data + 0, extradata_len);
|
2013-03-15 07:49:47 +01:00
|
|
|
memcpy(data + 4, "alac", 4);
|
|
|
|
AV_WB32(data + 8, 0);
|
|
|
|
memcpy(data + 12, track->private_data, track->private_size);
|
|
|
|
}
|
2015-06-19 21:39:59 +02:00
|
|
|
} else if (!strcmp(codec, "tta")) {
|
2015-06-21 17:49:43 +02:00
|
|
|
extradata_len = 30;
|
|
|
|
extradata = talloc_zero_size(sh_a, extradata_len);
|
|
|
|
if (!extradata)
|
2010-04-02 15:00:42 +02:00
|
|
|
goto error;
|
2015-06-21 17:49:43 +02:00
|
|
|
char *data = extradata;
|
2010-04-02 15:00:42 +02:00
|
|
|
memcpy(data + 0, "TTA1", 4);
|
|
|
|
AV_WL16(data + 4, 1);
|
2013-04-06 22:43:12 +02:00
|
|
|
AV_WL16(data + 6, sh_a->channels.num);
|
2014-09-25 01:56:51 +02:00
|
|
|
AV_WL16(data + 8, sh_a->bits_per_coded_sample);
|
2013-07-16 22:44:15 +02:00
|
|
|
AV_WL32(data + 10, track->a_osfreq);
|
2010-04-02 15:00:42 +02:00
|
|
|
// Bogus: last frame won't be played.
|
|
|
|
AV_WL32(data + 14, 0);
|
2016-02-22 20:46:28 +01:00
|
|
|
} else if (!strcmp(codec, "opus")) {
|
2016-02-21 16:25:02 +01:00
|
|
|
// Hardcode the rate libavcodec's opus decoder outputs, so that
|
|
|
|
// AV_PKT_DATA_SKIP_SAMPLES actually works. The Matroska header only
|
|
|
|
// has an arbitrary "input" samplerate, while libavcodec is fixed to
|
|
|
|
// output 48000.
|
|
|
|
sh_a->samplerate = 48000;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2016-03-30 11:34:35 +02:00
|
|
|
// Some files have broken default DefaultDuration set, which will lead to
|
|
|
|
// audio packets with incorrect timestamps. This follows FFmpeg commit
|
|
|
|
// 6158a3b, sample see FFmpeg ticket 2508.
|
|
|
|
if (sh_a->samplerate == 8000 && strcmp(codec, "ac3") == 0)
|
|
|
|
track->default_duration = 0;
|
demux_mkv: ignore DefaultDuration in some cases
This fixes playback of the sample linked by FFmpeg ticket 2508. The fix
follows ffmpeg commit 6158a3b (although it's not exactly the same).
The problem here is that the file contains an apparently non-sense
DefaultDuration value. DefaultDuration for audio tracks is used to
derive PTS values for packets with no timestamps, like they can happen
with frames inside a laced block. So the first packet of a SimpleBlock
will have a correct PTS, while the PTS values of the following packets
are calculated using DefaultDuration, and thus are broken.
This leads to seemingly ok playback, but broken A/V sync. Not using the
DefaultDuration value will leave the PTS values of these packets unset,
and the audio decoder can derive them from the output instead.
The fix more or less uses a heuristic to detect the broken case: if the
sample rate is 8 KHz (Matroska default, can assume unset), and the codec
is AC3 (as the broken file did), don't use it. I'm not sure why this
should be done only for AC3, maybe the muxing application (mkvmerge
v4.9.1) has known issues with AC3. AC3 also doesn't support 8 KHz as
sample rate natively.
(By the way, I'm not sure why we should honor the DefaultDuration at all
for audio. It doesn't seem to be needed. You can't seek to these frames,
and decoders should always be able to produce perfect PTS values by
adding the duration of the decoded audio to the first PTS.)
2013-07-16 22:59:55 +02:00
|
|
|
|
2016-12-19 21:29:46 +01:00
|
|
|
// Deal with some FFmpeg-produced garbage, and assume all audio codecs can
|
|
|
|
// start decoding from anywhere.
|
2016-12-20 14:28:29 +01:00
|
|
|
if (strcmp(codec, "truehd") != 0)
|
|
|
|
track->require_keyframes = true;
|
2016-12-19 21:29:46 +01:00
|
|
|
|
2016-01-12 23:48:19 +01:00
|
|
|
sh_a->extradata = extradata;
|
|
|
|
sh_a->extradata_size = extradata_len;
|
2014-09-25 01:56:51 +02:00
|
|
|
|
demux: remove weird tripple-buffering for the sh_stream list
The demuxer infrastructure was originally single-threaded. To make it
suitable for multithreading (specifically, demuxing and decoding on
separate threads), some sort of tripple-buffering was introduced. There
are separate "struct demuxer" allocations. The demuxer thread sets the
state on d_thread. If anything changes, the state is copied to d_buffer
(the copy is protected by a lock), and the decoder thread is notified.
Then the decoder thread copies the state from d_buffer to d_user (again
while holding a lock). This avoids the need for locking in the
demuxer/decoder code itself (only demux.c needs an internal, "invisible"
lock.)
Remove the streams/num_streams fields from this tripple-buffering
schema. Move them to the internal struct, and protect them with the
internal lock. Use accessors for read access outside of demux.c.
Other than replacing all field accesses with accessors, this separates
allocating and adding sh_streams. This is needed to avoid race
conditions. Before this change, this was awkwardly handled by first
initializing the sh_stream, and then sending a stream change event. Now
the stream is allocated, then initialized, and then declared as
immutable and added (at which point it becomes visible to the decoder
thread immediately).
This change is useful for PR #2626. And eventually, we should probably
get entirely of the tripple buffering, and this makes a nice first step.
2015-12-23 21:44:53 +01:00
|
|
|
demux_add_sh_stream(demuxer, sh);
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
return 0;
|
2011-08-20 04:54:27 +02:00
|
|
|
|
|
|
|
error:
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "Unknown/unsupported audio "
|
|
|
|
"codec ID '%s' for track %u or missing/faulty\n"
|
2011-08-20 04:54:27 +02:00
|
|
|
"private codec data.\n", track->codec_id, track->tnum);
|
demux: remove weird tripple-buffering for the sh_stream list
The demuxer infrastructure was originally single-threaded. To make it
suitable for multithreading (specifically, demuxing and decoding on
separate threads), some sort of tripple-buffering was introduced. There
are separate "struct demuxer" allocations. The demuxer thread sets the
state on d_thread. If anything changes, the state is copied to d_buffer
(the copy is protected by a lock), and the decoder thread is notified.
Then the decoder thread copies the state from d_buffer to d_user (again
while holding a lock). This avoids the need for locking in the
demuxer/decoder code itself (only demux.c needs an internal, "invisible"
lock.)
Remove the streams/num_streams fields from this tripple-buffering
schema. Move them to the internal struct, and protect them with the
internal lock. Use accessors for read access outside of demux.c.
Other than replacing all field accesses with accessors, this separates
allocating and adding sh_streams. This is needed to avoid race
conditions. Before this change, this was awkwardly handled by first
initializing the sh_stream, and then sending a stream change event. Now
the stream is allocated, then initialized, and then declared as
immutable and added (at which point it becomes visible to the decoder
thread immediately).
This change is useful for PR #2626. And eventually, we should probably
get entirely of the tripple buffering, and this makes a nice first step.
2015-12-23 21:44:53 +01:00
|
|
|
demux_add_sh_stream(demuxer, sh); // add it anyway
|
2011-08-20 04:54:27 +02:00
|
|
|
return 1;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2014-06-10 23:56:05 +02:00
|
|
|
static const char *const mkv_sub_tag[][2] = {
|
2015-06-19 21:41:57 +02:00
|
|
|
{ "S_VOBSUB", "dvd_subtitle" },
|
|
|
|
{ "S_TEXT/SSA", "ass"},
|
|
|
|
{ "S_TEXT/ASS", "ass"},
|
|
|
|
{ "S_SSA", "ass"},
|
|
|
|
{ "S_ASS", "ass"},
|
|
|
|
{ "S_TEXT/ASCII", "subrip"},
|
|
|
|
{ "S_TEXT/UTF8", "subrip"},
|
|
|
|
{ "S_HDMV/PGS", "hdmv_pgs_subtitle"},
|
|
|
|
{ "D_WEBVTT/SUBTITLES", "webvtt-webm"},
|
|
|
|
{ "D_WEBVTT/CAPTIONS", "webvtt-webm"},
|
2016-06-14 16:43:07 +02:00
|
|
|
{ "S_TEXT/WEBVTT", "webvtt"},
|
2015-06-19 21:41:57 +02:00
|
|
|
{ "S_DVBSUB", "dvb_subtitle"},
|
2013-04-15 21:25:21 +02:00
|
|
|
{0}
|
|
|
|
};
|
|
|
|
|
2013-04-14 19:23:18 +02:00
|
|
|
static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2013-04-15 21:25:21 +02:00
|
|
|
const char *subtitle_type = NULL;
|
|
|
|
for (int n = 0; mkv_sub_tag[n][0]; n++) {
|
|
|
|
if (strcmp(track->codec_id, mkv_sub_tag[n][0]) == 0) {
|
|
|
|
subtitle_type = mkv_sub_tag[n][1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-04-16 10:22:54 +02:00
|
|
|
|
2014-06-29 23:22:07 +02:00
|
|
|
if (track->private_size > 0x10000000)
|
|
|
|
return 1;
|
|
|
|
|
demux: remove weird tripple-buffering for the sh_stream list
The demuxer infrastructure was originally single-threaded. To make it
suitable for multithreading (specifically, demuxing and decoding on
separate threads), some sort of tripple-buffering was introduced. There
are separate "struct demuxer" allocations. The demuxer thread sets the
state on d_thread. If anything changes, the state is copied to d_buffer
(the copy is protected by a lock), and the decoder thread is notified.
Then the decoder thread copies the state from d_buffer to d_user (again
while holding a lock). This avoids the need for locking in the
demuxer/decoder code itself (only demux.c needs an internal, "invisible"
lock.)
Remove the streams/num_streams fields from this tripple-buffering
schema. Move them to the internal struct, and protect them with the
internal lock. Use accessors for read access outside of demux.c.
Other than replacing all field accesses with accessors, this separates
allocating and adding sh_streams. This is needed to avoid race
conditions. Before this change, this was awkwardly handled by first
initializing the sh_stream, and then sending a stream change event. Now
the stream is allocated, then initialized, and then declared as
immutable and added (at which point it becomes visible to the decoder
thread immediately).
This change is useful for PR #2626. And eventually, we should probably
get entirely of the tripple buffering, and this makes a nice first step.
2015-12-23 21:44:53 +01:00
|
|
|
struct sh_stream *sh = demux_alloc_sh_stream(STREAM_SUB);
|
2015-06-21 18:19:10 +02:00
|
|
|
init_track(demuxer, track, sh);
|
|
|
|
|
2016-01-12 23:48:19 +01:00
|
|
|
sh->codec->codec = subtitle_type;
|
2014-11-27 22:24:32 +01:00
|
|
|
bstr in = (bstr){track->private_data, track->private_size};
|
2013-12-21 20:24:20 +01:00
|
|
|
bstr buffer = demux_mkv_decode(demuxer->log, track, in, 2);
|
2013-04-16 10:22:54 +02:00
|
|
|
if (buffer.start && buffer.start != track->private_data) {
|
|
|
|
talloc_free(track->private_data);
|
|
|
|
talloc_steal(track, buffer.start);
|
|
|
|
track->private_data = buffer.start;
|
|
|
|
track->private_size = buffer.len;
|
|
|
|
}
|
2016-01-12 23:48:19 +01:00
|
|
|
sh->codec->extradata = track->private_data;
|
|
|
|
sh->codec->extradata_size = track->private_size;
|
2013-04-16 10:22:54 +02:00
|
|
|
|
demux: remove weird tripple-buffering for the sh_stream list
The demuxer infrastructure was originally single-threaded. To make it
suitable for multithreading (specifically, demuxing and decoding on
separate threads), some sort of tripple-buffering was introduced. There
are separate "struct demuxer" allocations. The demuxer thread sets the
state on d_thread. If anything changes, the state is copied to d_buffer
(the copy is protected by a lock), and the decoder thread is notified.
Then the decoder thread copies the state from d_buffer to d_user (again
while holding a lock). This avoids the need for locking in the
demuxer/decoder code itself (only demux.c needs an internal, "invisible"
lock.)
Remove the streams/num_streams fields from this tripple-buffering
schema. Move them to the internal struct, and protect them with the
internal lock. Use accessors for read access outside of demux.c.
Other than replacing all field accesses with accessors, this separates
allocating and adding sh_streams. This is needed to avoid race
conditions. Before this change, this was awkwardly handled by first
initializing the sh_stream, and then sending a stream change event. Now
the stream is allocated, then initialized, and then declared as
immutable and added (at which point it becomes visible to the decoder
thread immediately).
This change is useful for PR #2626. And eventually, we should probably
get entirely of the tripple buffering, and this makes a nice first step.
2015-12-23 21:44:53 +01:00
|
|
|
demux_add_sh_stream(demuxer, sh);
|
|
|
|
|
2014-07-05 16:42:03 +02:00
|
|
|
if (!subtitle_type)
|
|
|
|
MP_ERR(demuxer, "Subtitle type '%s' is not supported.\n", track->codec_id);
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
return 0;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2013-04-14 02:49:07 +02:00
|
|
|
static int read_ebml_header(demuxer_t *demuxer)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2009-12-29 20:06:21 +01:00
|
|
|
stream_t *s = demuxer->stream;
|
|
|
|
|
2014-01-14 17:38:51 +01:00
|
|
|
if (ebml_read_id(s) != EBML_ID_EBML)
|
2010-01-25 01:43:27 +01:00
|
|
|
return 0;
|
2015-06-24 14:02:40 +02:00
|
|
|
struct ebml_ebml ebml_master = {0};
|
2013-12-21 20:24:20 +01:00
|
|
|
struct ebml_parse_ctx parse_ctx = { demuxer->log, .no_error_messages = true };
|
2010-01-25 01:43:27 +01:00
|
|
|
if (ebml_read_element(s, &parse_ctx, &ebml_master, &ebml_ebml_desc) < 0)
|
|
|
|
return 0;
|
2015-06-24 14:02:40 +02:00
|
|
|
if (!ebml_master.doc_type) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "File has EBML header but no doctype."
|
2014-07-05 16:42:03 +02:00
|
|
|
" Assuming \"matroska\".\n");
|
2015-06-24 14:02:40 +02:00
|
|
|
} else if (strcmp(ebml_master.doc_type, "matroska") != 0
|
|
|
|
&& strcmp(ebml_master.doc_type, "webm") != 0) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_DBG(demuxer, "no head found\n");
|
2010-01-25 01:43:27 +01:00
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (ebml_master.doc_type_read_version > 2) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "This looks like a Matroska file, "
|
2014-07-05 16:42:03 +02:00
|
|
|
"but we don't support format version %"PRIu64"\n",
|
|
|
|
ebml_master.doc_type_read_version);
|
2010-01-25 01:43:27 +01:00
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if ((ebml_master.n_ebml_read_version
|
|
|
|
&& ebml_master.ebml_read_version != EBML_VERSION)
|
|
|
|
|| (ebml_master.n_ebml_max_size_length
|
|
|
|
&& ebml_master.ebml_max_size_length > 8)
|
|
|
|
|| (ebml_master.n_ebml_max_id_length
|
2013-10-19 23:10:03 +02:00
|
|
|
&& ebml_master.ebml_max_id_length != 4))
|
|
|
|
{
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "This looks like a Matroska file, "
|
2014-07-05 16:42:03 +02:00
|
|
|
"but the header has bad parameters\n");
|
2010-01-25 01:43:27 +01:00
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
2009-12-29 20:06:21 +01:00
|
|
|
return 0;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2010-01-25 01:43:27 +01:00
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2013-04-14 02:49:07 +02:00
|
|
|
return 1;
|
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2014-01-22 23:37:03 +01:00
|
|
|
static int read_mkv_segment_header(demuxer_t *demuxer, int64_t *segment_end)
|
2013-04-14 02:49:07 +02:00
|
|
|
{
|
|
|
|
stream_t *s = demuxer->stream;
|
|
|
|
int num_skip = 0;
|
|
|
|
if (demuxer->params)
|
|
|
|
num_skip = demuxer->params->matroska_wanted_segment;
|
|
|
|
|
|
|
|
while (!s->eof) {
|
2014-01-14 17:38:51 +01:00
|
|
|
if (ebml_read_id(s) != MATROSKA_ID_SEGMENT) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "segment not found\n");
|
2013-04-14 02:49:07 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "+ a segment...\n");
|
2014-01-14 17:38:51 +01:00
|
|
|
uint64_t len = ebml_read_length(s);
|
2014-01-22 23:37:03 +01:00
|
|
|
*segment_end = (len == EBML_UINT_INVALID) ? 0 : stream_tell(s) + len;
|
2013-04-14 02:49:07 +02:00
|
|
|
if (num_skip <= 0)
|
|
|
|
return 1;
|
|
|
|
num_skip--;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, " (skipping)\n");
|
2014-01-22 23:37:03 +01:00
|
|
|
if (*segment_end <= 0)
|
2013-04-14 02:49:07 +02:00
|
|
|
break;
|
2015-08-18 00:10:54 +02:00
|
|
|
if (*segment_end >= stream_get_size(s))
|
2013-12-14 21:55:03 +01:00
|
|
|
return 0;
|
2014-01-22 23:37:03 +01:00
|
|
|
if (!stream_seek(s, *segment_end)) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "Failed to seek in file\n");
|
2013-04-14 02:49:07 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// Segments are like concatenated Matroska files
|
|
|
|
if (!read_ebml_header(demuxer))
|
|
|
|
return 0;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "End of file, no further segments.\n");
|
2013-04-14 02:49:07 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-07-12 21:58:11 +02:00
|
|
|
static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
|
2013-04-14 02:49:07 +02:00
|
|
|
{
|
|
|
|
stream_t *s = demuxer->stream;
|
|
|
|
mkv_demuxer_t *mkv_d;
|
2014-01-22 22:12:14 +01:00
|
|
|
int64_t start_pos;
|
2014-01-22 23:37:03 +01:00
|
|
|
int64_t end_pos;
|
2013-04-14 02:49:07 +02:00
|
|
|
|
2014-11-16 18:51:11 +01:00
|
|
|
bstr start = stream_peek(s, 4);
|
2014-11-21 03:50:40 +01:00
|
|
|
uint32_t start_id = 0;
|
2014-11-16 18:51:11 +01:00
|
|
|
for (int n = 0; n < start.len; n++)
|
|
|
|
start_id = (start_id << 8) | start.start[n];
|
|
|
|
if (start_id != EBML_ID_EBML)
|
|
|
|
return -1;
|
|
|
|
|
2013-04-14 02:49:07 +02:00
|
|
|
if (!read_ebml_header(demuxer))
|
2013-07-11 20:08:12 +02:00
|
|
|
return -1;
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_VERBOSE(demuxer, "Found the head...\n");
|
2013-04-14 02:49:07 +02:00
|
|
|
|
2014-01-22 23:37:03 +01:00
|
|
|
if (!read_mkv_segment_header(demuxer, &end_pos))
|
2013-07-11 20:08:12 +02:00
|
|
|
return -1;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2010-01-25 11:37:42 +01:00
|
|
|
mkv_d = talloc_zero(demuxer, struct mkv_demuxer);
|
2009-12-29 20:06:21 +01:00
|
|
|
demuxer->priv = mkv_d;
|
|
|
|
mkv_d->tc_scale = 1000000;
|
|
|
|
mkv_d->segment_start = stream_tell(s);
|
2014-01-22 23:37:03 +01:00
|
|
|
mkv_d->segment_end = end_pos;
|
2014-11-03 20:00:34 +01:00
|
|
|
mkv_d->a_skip_preroll = 1;
|
2016-01-27 21:08:53 +01:00
|
|
|
mkv_d->skip_to_timecode = INT64_MIN;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2016-09-06 20:09:56 +02:00
|
|
|
mp_read_option_raw(demuxer->global, "index", &m_option_type_choice,
|
|
|
|
&mkv_d->index_mode);
|
|
|
|
mp_read_option_raw(demuxer->global, "edition", &m_option_type_choice,
|
|
|
|
&mkv_d->edition_id);
|
|
|
|
mkv_d->opts = mp_get_config_group(mkv_d, demuxer->global, &demux_mkv_conf);
|
|
|
|
|
2013-04-14 02:49:07 +02:00
|
|
|
if (demuxer->params && demuxer->params->matroska_was_valid)
|
|
|
|
*demuxer->params->matroska_was_valid = true;
|
|
|
|
|
2011-08-04 07:38:39 +02:00
|
|
|
while (1) {
|
2014-01-22 22:12:14 +01:00
|
|
|
start_pos = stream_tell(s);
|
|
|
|
stream_peek(s, 4); // make sure we can always seek back
|
2014-01-14 17:38:51 +01:00
|
|
|
uint32_t id = ebml_read_id(s);
|
2011-09-25 17:35:09 +02:00
|
|
|
if (s->eof) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "Unexpected end of file (no clusters found)\n");
|
2013-04-14 02:39:11 +02:00
|
|
|
break;
|
2011-09-25 17:35:09 +02:00
|
|
|
}
|
2011-08-20 20:45:42 +02:00
|
|
|
if (id == MATROSKA_ID_CLUSTER) {
|
2014-01-22 22:12:14 +01:00
|
|
|
MP_VERBOSE(demuxer, "|+ found cluster\n");
|
2009-12-29 20:06:21 +01:00
|
|
|
break;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2014-01-22 22:12:14 +01:00
|
|
|
int res = read_header_element(demuxer, id, start_pos);
|
|
|
|
if (res < 0)
|
2014-01-22 22:33:55 +01:00
|
|
|
return -1;
|
2014-01-22 22:12:14 +01:00
|
|
|
}
|
|
|
|
|
2015-08-18 00:10:54 +02:00
|
|
|
int64_t end = stream_get_size(s);
|
2015-03-06 15:06:59 +01:00
|
|
|
|
2014-01-22 22:12:14 +01:00
|
|
|
// Read headers that come after the first cluster (i.e. require seeking).
|
|
|
|
// Note: reading might increase ->num_headers.
|
|
|
|
// Likewise, ->headers might be reallocated.
|
2017-05-15 16:40:57 +02:00
|
|
|
int only_cue = -1;
|
2014-01-22 22:12:14 +01:00
|
|
|
for (int n = 0; n < mkv_d->num_headers; n++) {
|
|
|
|
struct header_elem *elem = &mkv_d->headers[n];
|
2015-03-06 15:06:59 +01:00
|
|
|
if (elem->parsed)
|
|
|
|
continue;
|
2015-03-06 20:31:54 +01:00
|
|
|
// Warn against incomplete files and skip headers outside of range.
|
2015-03-06 15:06:59 +01:00
|
|
|
if (elem->pos >= end) {
|
|
|
|
elem->parsed = true; // don't bother if file is incomplete
|
|
|
|
if (!mkv_d->eof_warning) {
|
|
|
|
MP_WARN(demuxer, "SeekHead position beyond "
|
|
|
|
"end of file - incomplete file?\n");
|
|
|
|
mkv_d->eof_warning = true;
|
|
|
|
}
|
2015-03-06 20:31:54 +01:00
|
|
|
continue;
|
2015-03-06 15:06:59 +01:00
|
|
|
}
|
2017-05-15 16:40:57 +02:00
|
|
|
elem->needed = true;
|
|
|
|
only_cue = only_cue < 0 && elem->id == MATROSKA_ID_CUES;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there's only 1 needed element, and it's the cues, defer reading.
|
|
|
|
if (only_cue == 1) {
|
|
|
|
// Read cues when they are needed, to avoid seeking on opening.
|
|
|
|
MP_VERBOSE(demuxer, "Deferring reading cues.\n");
|
|
|
|
} else {
|
|
|
|
// Read them by ascending position to reduce unneeded seeks.
|
|
|
|
// O(n^2) because the number of elements is very low.
|
|
|
|
while (1) {
|
|
|
|
struct header_elem *lowest = NULL;
|
|
|
|
for (int n = 0; n < mkv_d->num_headers; n++) {
|
|
|
|
struct header_elem *elem = &mkv_d->headers[n];
|
|
|
|
if (!elem->needed)
|
|
|
|
continue;
|
|
|
|
if (!lowest || elem->pos < lowest->pos)
|
|
|
|
lowest = elem;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!lowest)
|
|
|
|
break;
|
|
|
|
|
|
|
|
lowest->needed = false;
|
|
|
|
if (read_deferred_element(demuxer, lowest) < 0)
|
|
|
|
return -1;
|
2014-01-22 22:12:14 +01:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2017-05-15 16:40:57 +02:00
|
|
|
|
2014-01-22 22:12:14 +01:00
|
|
|
if (!stream_seek(s, start_pos)) {
|
|
|
|
MP_ERR(demuxer, "Couldn't seek back after reading headers?\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
MP_VERBOSE(demuxer, "All headers are parsed!\n");
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
display_create_tracks(demuxer);
|
2014-12-22 12:53:51 +01:00
|
|
|
add_coverart(demuxer);
|
2016-08-12 21:39:32 +02:00
|
|
|
process_tags(demuxer);
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2015-10-16 16:49:23 +02:00
|
|
|
probe_first_timestamp(demuxer);
|
2016-09-06 20:09:56 +02:00
|
|
|
if (mkv_d->opts->probe_duration)
|
2015-10-27 20:57:11 +01:00
|
|
|
probe_last_timestamp(demuxer, start_pos);
|
2014-11-18 23:07:20 +01:00
|
|
|
|
2013-07-11 20:08:12 +02:00
|
|
|
return 0;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2013-04-12 17:25:51 +02:00
|
|
|
static bool bstr_read_u8(bstr *buffer, uint8_t *out_u8)
|
|
|
|
{
|
|
|
|
if (buffer->len > 0) {
|
|
|
|
*out_u8 = buffer->start[0];
|
|
|
|
buffer->len -= 1;
|
|
|
|
buffer->start += 1;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-13 18:16:50 +02:00
|
|
|
static int demux_mkv_read_block_lacing(bstr *buffer, int *laces,
|
2013-04-12 16:07:45 +02:00
|
|
|
uint32_t lace_size[MAX_NUM_LACES])
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2010-10-31 04:14:50 +01:00
|
|
|
uint32_t total = 0;
|
2013-04-13 18:16:50 +02:00
|
|
|
uint8_t flags, t;
|
2009-12-29 20:06:21 +01:00
|
|
|
int i;
|
|
|
|
|
|
|
|
/* lacing flags */
|
2013-04-12 17:25:51 +02:00
|
|
|
if (!bstr_read_u8(buffer, &flags))
|
2010-10-31 04:14:50 +01:00
|
|
|
goto error;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2013-04-13 18:44:11 +02:00
|
|
|
int type = (flags >> 1) & 0x03;
|
|
|
|
if (type == 0) { /* no lacing */
|
2009-12-29 20:06:21 +01:00
|
|
|
*laces = 1;
|
2013-04-12 17:25:51 +02:00
|
|
|
lace_size[0] = buffer->len;
|
2013-04-13 18:44:11 +02:00
|
|
|
} else {
|
2013-04-13 18:16:50 +02:00
|
|
|
if (!bstr_read_u8(buffer, &t))
|
2010-10-31 04:14:50 +01:00
|
|
|
goto error;
|
2013-04-13 18:16:50 +02:00
|
|
|
*laces = t + 1;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2013-04-13 18:44:11 +02:00
|
|
|
switch (type) {
|
2009-12-29 20:06:21 +01:00
|
|
|
case 1: /* xiph lacing */
|
|
|
|
for (i = 0; i < *laces - 1; i++) {
|
|
|
|
lace_size[i] = 0;
|
|
|
|
do {
|
2013-04-12 17:25:51 +02:00
|
|
|
if (!bstr_read_u8(buffer, &t))
|
2010-10-31 04:14:50 +01:00
|
|
|
goto error;
|
2013-04-12 17:25:51 +02:00
|
|
|
lace_size[i] += t;
|
|
|
|
} while (t == 0xFF);
|
2009-12-29 20:06:21 +01:00
|
|
|
total += lace_size[i];
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2013-04-12 17:25:51 +02:00
|
|
|
lace_size[i] = buffer->len - total;
|
2009-12-29 20:06:21 +01:00
|
|
|
break;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
case 2: /* fixed-size lacing */
|
|
|
|
for (i = 0; i < *laces; i++)
|
2013-04-12 17:25:51 +02:00
|
|
|
lace_size[i] = buffer->len / *laces;
|
2009-12-29 20:06:21 +01:00
|
|
|
break;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
case 3:; /* EBML lacing */
|
2013-04-12 17:25:51 +02:00
|
|
|
uint64_t num = ebml_read_vlen_uint(buffer);
|
2010-10-31 04:14:50 +01:00
|
|
|
if (num == EBML_UINT_INVALID)
|
|
|
|
goto error;
|
2013-04-12 17:25:51 +02:00
|
|
|
if (num > buffer->len)
|
2010-10-31 04:14:50 +01:00
|
|
|
goto error;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
|
|
|
total = lace_size[0] = num;
|
2009-12-29 20:06:21 +01:00
|
|
|
for (i = 1; i < *laces - 1; i++) {
|
2013-04-12 17:25:51 +02:00
|
|
|
int64_t snum = ebml_read_vlen_int(buffer);
|
2010-10-31 04:14:50 +01:00
|
|
|
if (snum == EBML_INT_INVALID)
|
|
|
|
goto error;
|
2009-12-29 20:06:21 +01:00
|
|
|
lace_size[i] = lace_size[i - 1] + snum;
|
2004-01-19 20:16:10 +01:00
|
|
|
total += lace_size[i];
|
2009-12-29 20:06:21 +01:00
|
|
|
}
|
2013-04-12 17:25:51 +02:00
|
|
|
lace_size[i] = buffer->len - total;
|
2004-01-19 20:16:10 +01:00
|
|
|
break;
|
2013-05-06 20:58:54 +02:00
|
|
|
|
|
|
|
default: abort();
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
2013-04-13 19:17:16 +02:00
|
|
|
|
|
|
|
total = buffer->len;
|
|
|
|
for (i = 0; i < *laces; i++) {
|
|
|
|
if (lace_size[i] > total)
|
|
|
|
goto error;
|
|
|
|
total -= lace_size[i];
|
|
|
|
}
|
|
|
|
if (total != 0)
|
|
|
|
goto error;
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
return 0;
|
2010-10-31 04:14:50 +01:00
|
|
|
|
|
|
|
error:
|
|
|
|
return 1;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2015-02-05 21:54:19 +01:00
|
|
|
// Return whether the packet was handled & freed.
|
|
|
|
static bool handle_realaudio(demuxer_t *demuxer, mkv_track_t *track,
|
|
|
|
struct demux_packet *orig)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2014-11-21 05:10:28 +01:00
|
|
|
uint32_t sps = track->sub_packet_size;
|
|
|
|
uint32_t sph = track->sub_packet_h;
|
2014-06-29 23:22:07 +02:00
|
|
|
uint32_t cfs = track->coded_framesize; // restricted to [1,0x40000000]
|
2014-11-21 05:10:28 +01:00
|
|
|
uint32_t w = track->audiopk_size;
|
|
|
|
uint32_t spc = track->sub_packet_cnt;
|
2015-02-05 21:54:19 +01:00
|
|
|
uint8_t *buffer = orig->buffer;
|
|
|
|
uint32_t size = orig->len;
|
2009-12-29 20:06:21 +01:00
|
|
|
demux_packet_t *dp;
|
2014-06-29 23:22:07 +02:00
|
|
|
// track->audio_buf allocation size
|
|
|
|
size_t audiobuf_size = sph * w;
|
|
|
|
|
2015-06-19 21:39:59 +02:00
|
|
|
if (!track->audio_buf || !track->audio_timestamp || !track->stream)
|
2015-02-05 21:55:11 +01:00
|
|
|
return false;
|
|
|
|
|
2016-01-12 23:48:19 +01:00
|
|
|
const char *codec = track->stream->codec->codec ? track->stream->codec->codec : "";
|
2015-06-19 21:39:59 +02:00
|
|
|
if (!strcmp(codec, "ra_288")) {
|
2015-02-05 21:54:32 +01:00
|
|
|
for (int x = 0; x < sph / 2; x++) {
|
|
|
|
uint64_t dst_offset = x * 2 * w + spc * (uint64_t)cfs;
|
|
|
|
if (dst_offset + cfs > audiobuf_size)
|
2014-06-29 23:22:07 +02:00
|
|
|
goto error;
|
2015-02-05 21:54:32 +01:00
|
|
|
uint64_t src_offset = x * (uint64_t)cfs;
|
|
|
|
if (src_offset + cfs > size)
|
|
|
|
goto error;
|
|
|
|
memcpy(track->audio_buf + dst_offset, buffer + src_offset, cfs);
|
2009-12-29 20:06:21 +01:00
|
|
|
}
|
2015-06-19 21:39:59 +02:00
|
|
|
} else if (!strcmp(codec, "cook") || !strcmp(codec, "atrac3")) {
|
2015-02-05 21:54:32 +01:00
|
|
|
for (int x = 0; x < w / sps; x++) {
|
|
|
|
uint32_t dst_offset =
|
|
|
|
sps * (sph * x + ((sph + 1) / 2) * (spc & 1) + (spc >> 1));
|
|
|
|
if (dst_offset + sps > audiobuf_size)
|
2014-06-29 23:22:07 +02:00
|
|
|
goto error;
|
2015-02-05 21:54:32 +01:00
|
|
|
uint32_t src_offset = sps * x;
|
|
|
|
if (src_offset + sps > size)
|
|
|
|
goto error;
|
|
|
|
memcpy(track->audio_buf + dst_offset, buffer + src_offset, sps);
|
|
|
|
}
|
2015-06-19 21:39:59 +02:00
|
|
|
} else if (!strcmp(codec, "sipr")) {
|
2015-02-05 21:54:32 +01:00
|
|
|
if (spc * w + w > audiobuf_size || w > size)
|
|
|
|
goto error;
|
|
|
|
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++) {
|
|
|
|
unsigned int i = bs * sipr_swaps[n][0]; // 77 max
|
|
|
|
unsigned int o = bs * sipr_swaps[n][1]; // 95 max
|
|
|
|
// swap nibbles of block 'i' with 'o'
|
|
|
|
for (int j = 0; j < bs; j++) {
|
|
|
|
if (i / 2 >= audiobuf_size || o / 2 >= audiobuf_size)
|
|
|
|
goto error;
|
|
|
|
uint8_t iv = track->audio_buf[i / 2];
|
|
|
|
uint8_t ov = track->audio_buf[o / 2];
|
|
|
|
int x = (i & 1) ? iv >> 4 : iv & 0x0F;
|
|
|
|
int y = (o & 1) ? ov >> 4 : ov & 0x0F;
|
2015-03-02 19:09:25 +01:00
|
|
|
track->audio_buf[o / 2] = (ov & 0x0F) | (o & 1 ? x << 4 : x);
|
|
|
|
track->audio_buf[i / 2] = (iv & 0x0F) | (i & 1 ? y << 4 : y);
|
2015-02-05 21:54:32 +01:00
|
|
|
i++;
|
|
|
|
o++;
|
|
|
|
}
|
2009-12-29 20:06:21 +01:00
|
|
|
}
|
2006-04-03 21:41:17 +02:00
|
|
|
}
|
2015-06-19 21:39:59 +02:00
|
|
|
} else {
|
2015-02-05 21:54:32 +01:00
|
|
|
// Not a codec that requires reordering
|
2015-02-05 21:54:19 +01:00
|
|
|
return false;
|
2009-12-29 20:06:21 +01:00
|
|
|
}
|
2015-02-05 21:54:32 +01:00
|
|
|
|
|
|
|
track->audio_timestamp[track->sub_packet_cnt] =
|
|
|
|
track->ra_pts == orig->pts ? 0 : orig->pts;
|
|
|
|
track->ra_pts = orig->pts;
|
|
|
|
|
|
|
|
if (++(track->sub_packet_cnt) == sph) {
|
|
|
|
track->sub_packet_cnt = 0;
|
|
|
|
// apk_usize has same range as coded_framesize in worst case
|
2016-01-12 23:48:19 +01:00
|
|
|
uint32_t apk_usize = track->stream->codec->block_align;
|
2015-02-05 21:54:32 +01:00
|
|
|
if (apk_usize > audiobuf_size)
|
|
|
|
goto error;
|
|
|
|
// Release all the audio packets
|
|
|
|
for (int x = 0; x < sph * w / apk_usize; x++) {
|
|
|
|
dp = new_demux_packet_from(track->audio_buf + x * apk_usize,
|
|
|
|
apk_usize);
|
|
|
|
if (!dp)
|
|
|
|
goto error;
|
|
|
|
/* Put timestamp only on packets that correspond to original
|
|
|
|
* audio packets in file */
|
|
|
|
dp->pts = (x * apk_usize % w) ? MP_NOPTS_VALUE :
|
|
|
|
track->audio_timestamp[x * apk_usize / w];
|
2015-02-13 21:17:07 +01:00
|
|
|
dp->pos = orig->pos + x;
|
2015-02-05 21:54:32 +01:00
|
|
|
dp->keyframe = !x; // Mark first packet as keyframe
|
|
|
|
demux_add_packet(track->stream, dp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
error:
|
|
|
|
talloc_free(orig);
|
|
|
|
return true;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2013-12-27 20:00:24 +01:00
|
|
|
static void mkv_seek_reset(demuxer_t *demuxer)
|
|
|
|
{
|
|
|
|
mkv_demuxer_t *mkv_d = demuxer->priv;
|
|
|
|
|
|
|
|
for (int i = 0; i < mkv_d->num_tracks; i++) {
|
|
|
|
mkv_track_t *track = mkv_d->tracks[i];
|
|
|
|
if (track->av_parser)
|
|
|
|
av_parser_close(track->av_parser);
|
|
|
|
track->av_parser = NULL;
|
|
|
|
if (track->av_parser_codec) {
|
|
|
|
avcodec_close(track->av_parser_codec);
|
|
|
|
av_free(track->av_parser_codec);
|
|
|
|
}
|
|
|
|
track->av_parser_codec = NULL;
|
|
|
|
}
|
2015-10-16 16:49:23 +02:00
|
|
|
|
|
|
|
free_block(&mkv_d->tmp_block);
|
2016-01-27 21:08:53 +01:00
|
|
|
|
|
|
|
mkv_d->skip_to_timecode = INT64_MIN;
|
2013-12-27 20:00:24 +01:00
|
|
|
}
|
|
|
|
|
2013-05-30 17:40:55 +02:00
|
|
|
// Copied from libavformat/matroskadec.c (FFmpeg 310f9dd / 2013-05-30)
|
|
|
|
// Originally added with Libav commit 9b6f47c
|
|
|
|
// License: LGPL v2.1 or later
|
|
|
|
// Author header: The FFmpeg Project (this function still came from Libav)
|
|
|
|
// Modified to use talloc, removed ffmpeg/libav specific error codes.
|
|
|
|
static int libav_parse_wavpack(mkv_track_t *track, uint8_t *src,
|
|
|
|
uint8_t **pdst, int *size)
|
|
|
|
{
|
|
|
|
uint8_t *dst = NULL;
|
|
|
|
int dstlen = 0;
|
|
|
|
int srclen = *size;
|
|
|
|
uint32_t samples;
|
|
|
|
uint16_t ver;
|
|
|
|
int offset = 0;
|
|
|
|
|
|
|
|
if (srclen < 12 || track->private_size < 2)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
ver = AV_RL16(track->private_data);
|
|
|
|
|
|
|
|
samples = AV_RL32(src);
|
|
|
|
src += 4;
|
|
|
|
srclen -= 4;
|
|
|
|
|
|
|
|
while (srclen >= 8) {
|
|
|
|
int multiblock;
|
|
|
|
uint32_t blocksize;
|
|
|
|
uint8_t *tmp;
|
|
|
|
|
|
|
|
uint32_t flags = AV_RL32(src);
|
|
|
|
uint32_t crc = AV_RL32(src + 4);
|
|
|
|
src += 8;
|
|
|
|
srclen -= 8;
|
|
|
|
|
|
|
|
multiblock = (flags & 0x1800) != 0x1800;
|
|
|
|
if (multiblock) {
|
|
|
|
if (srclen < 4)
|
|
|
|
goto fail;
|
|
|
|
blocksize = AV_RL32(src);
|
|
|
|
src += 4;
|
|
|
|
srclen -= 4;
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
2013-05-30 17:40:55 +02:00
|
|
|
blocksize = srclen;
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2013-05-30 17:40:55 +02:00
|
|
|
|
|
|
|
if (blocksize > srclen)
|
|
|
|
goto fail;
|
|
|
|
|
2014-06-29 23:22:07 +02:00
|
|
|
if (dstlen > 0x10000000 || blocksize > 0x10000000)
|
|
|
|
goto fail;
|
|
|
|
|
2013-12-27 20:00:24 +01:00
|
|
|
tmp = talloc_realloc(track->parser_tmp, dst, uint8_t,
|
|
|
|
dstlen + blocksize + 32);
|
2013-05-30 17:40:55 +02:00
|
|
|
if (!tmp)
|
|
|
|
goto fail;
|
|
|
|
dst = tmp;
|
|
|
|
dstlen += blocksize + 32;
|
|
|
|
|
|
|
|
AV_WL32(dst + offset, MKTAG('w', 'v', 'p', 'k')); // tag
|
|
|
|
AV_WL32(dst + offset + 4, blocksize + 24); // blocksize - 8
|
|
|
|
AV_WL16(dst + offset + 8, ver); // version
|
|
|
|
AV_WL16(dst + offset + 10, 0); // track/index_no
|
|
|
|
AV_WL32(dst + offset + 12, 0); // total samples
|
|
|
|
AV_WL32(dst + offset + 16, 0); // block index
|
|
|
|
AV_WL32(dst + offset + 20, samples); // number of samples
|
|
|
|
AV_WL32(dst + offset + 24, flags); // flags
|
|
|
|
AV_WL32(dst + offset + 28, crc); // crc
|
|
|
|
memcpy (dst + offset + 32, src, blocksize); // block data
|
|
|
|
|
|
|
|
src += blocksize;
|
|
|
|
srclen -= blocksize;
|
|
|
|
offset += blocksize + 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pdst = dst;
|
|
|
|
*size = dstlen;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
talloc_free(dst);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-02-05 21:52:07 +01:00
|
|
|
static void mkv_parse_and_add_packet(demuxer_t *demuxer, mkv_track_t *track,
|
|
|
|
struct demux_packet *dp)
|
2013-05-30 17:40:55 +02:00
|
|
|
{
|
2015-02-05 21:52:07 +01:00
|
|
|
struct sh_stream *stream = track->stream;
|
|
|
|
|
2015-02-05 21:55:11 +01:00
|
|
|
if (stream->type == STREAM_AUDIO && handle_realaudio(demuxer, track, dp))
|
|
|
|
return;
|
2015-02-05 21:52:07 +01:00
|
|
|
|
2016-01-12 23:48:19 +01:00
|
|
|
if (strcmp(stream->codec->codec, "wavpack") == 0) {
|
2015-02-05 21:52:07 +01:00
|
|
|
int size = dp->len;
|
2013-05-30 17:40:55 +02:00
|
|
|
uint8_t *parsed;
|
2015-02-05 21:52:07 +01:00
|
|
|
if (libav_parse_wavpack(track, dp->buffer, &parsed, &size) >= 0) {
|
|
|
|
struct demux_packet *new = new_demux_packet_from(parsed, size);
|
|
|
|
if (new) {
|
|
|
|
demux_packet_copy_attribs(new, dp);
|
|
|
|
talloc_free(dp);
|
|
|
|
demux_add_packet(stream, new);
|
|
|
|
return;
|
|
|
|
}
|
2013-05-30 17:40:55 +02:00
|
|
|
}
|
2015-02-05 21:52:07 +01:00
|
|
|
}
|
|
|
|
|
2016-01-12 23:48:19 +01:00
|
|
|
if (strcmp(stream->codec->codec, "prores") == 0) {
|
2015-02-05 21:52:07 +01:00
|
|
|
size_t newlen = dp->len + 8;
|
|
|
|
struct demux_packet *new = new_demux_packet(newlen);
|
|
|
|
if (new) {
|
|
|
|
AV_WB32(new->buffer + 0, newlen);
|
|
|
|
AV_WB32(new->buffer + 4, MKBETAG('i', 'c', 'p', 'f'));
|
|
|
|
memcpy(new->buffer + 8, dp->buffer, dp->len);
|
|
|
|
demux_packet_copy_attribs(new, dp);
|
|
|
|
talloc_free(dp);
|
|
|
|
demux_add_packet(stream, new);
|
|
|
|
return;
|
2013-12-27 20:00:24 +01:00
|
|
|
}
|
2015-02-05 21:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (track->parse && !track->av_parser) {
|
2016-01-12 23:48:19 +01:00
|
|
|
int id = mp_codec_to_av_codec_id(track->stream->codec->codec);
|
2015-02-05 21:52:07 +01:00
|
|
|
const AVCodec *codec = avcodec_find_decoder(id);
|
|
|
|
track->av_parser = av_parser_init(id);
|
|
|
|
if (codec)
|
|
|
|
track->av_parser_codec = avcodec_alloc_context3(codec);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!track->parse || !track->av_parser || !track->av_parser_codec) {
|
|
|
|
demux_add_packet(stream, dp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-02-05 21:55:11 +01:00
|
|
|
double tb = track->parse_timebase;
|
2015-02-05 21:52:21 +01:00
|
|
|
int64_t pts = dp->pts == MP_NOPTS_VALUE ? AV_NOPTS_VALUE : dp->pts * tb;
|
|
|
|
int64_t dts = dp->dts == MP_NOPTS_VALUE ? AV_NOPTS_VALUE : dp->dts * tb;
|
2017-05-30 22:50:05 +02:00
|
|
|
bool copy_sidedata = true;
|
2015-02-05 21:52:21 +01:00
|
|
|
|
2015-02-05 21:52:07 +01:00
|
|
|
while (dp->len) {
|
|
|
|
uint8_t *data = NULL;
|
|
|
|
int size = 0;
|
|
|
|
int len = av_parser_parse2(track->av_parser, track->av_parser_codec,
|
|
|
|
&data, &size, dp->buffer, dp->len,
|
2015-02-05 21:52:21 +01:00
|
|
|
pts, dts, 0);
|
2015-02-05 21:52:07 +01:00
|
|
|
if (len < 0 || len > dp->len)
|
|
|
|
break;
|
|
|
|
dp->buffer += len;
|
|
|
|
dp->len -= len;
|
2015-02-13 21:17:07 +01:00
|
|
|
dp->pos += len;
|
2015-02-05 21:52:07 +01:00
|
|
|
if (size) {
|
|
|
|
struct demux_packet *new = new_demux_packet_from(data, size);
|
|
|
|
if (!new)
|
|
|
|
break;
|
|
|
|
demux_packet_copy_attribs(new, dp);
|
2017-05-30 19:26:27 +02:00
|
|
|
#if LIBAVCODEC_VERSION_MICRO >= 100
|
2017-05-30 22:50:05 +02:00
|
|
|
if (copy_sidedata)
|
|
|
|
av_copy_packet_side_data(new->avpacket, dp->avpacket);
|
2017-05-30 19:26:27 +02:00
|
|
|
#endif
|
2017-05-30 22:50:05 +02:00
|
|
|
copy_sidedata = false;
|
2015-02-05 21:55:11 +01:00
|
|
|
if (track->parse_timebase) {
|
2015-02-05 21:52:21 +01:00
|
|
|
new->pts = track->av_parser->pts == AV_NOPTS_VALUE
|
|
|
|
? MP_NOPTS_VALUE : track->av_parser->pts / tb;
|
|
|
|
new->dts = track->av_parser->dts == AV_NOPTS_VALUE
|
|
|
|
? MP_NOPTS_VALUE : track->av_parser->dts / tb;
|
|
|
|
}
|
2015-02-05 21:52:07 +01:00
|
|
|
demux_add_packet(stream, new);
|
2013-12-27 20:00:24 +01:00
|
|
|
}
|
2015-02-05 21:52:21 +01:00
|
|
|
pts = dts = AV_NOPTS_VALUE;
|
2013-05-30 17:40:55 +02:00
|
|
|
}
|
2015-02-05 21:52:07 +01:00
|
|
|
|
|
|
|
if (dp->len) {
|
|
|
|
demux_add_packet(stream, dp);
|
|
|
|
} else {
|
|
|
|
talloc_free(dp);
|
|
|
|
}
|
2013-05-30 17:40:55 +02:00
|
|
|
}
|
|
|
|
|
2013-04-12 00:43:34 +02:00
|
|
|
static void free_block(struct block_info *block)
|
2013-04-11 21:42:46 +02:00
|
|
|
{
|
2013-04-12 01:26:02 +02:00
|
|
|
free(block->alloc);
|
2013-04-12 17:25:51 +02:00
|
|
|
block->alloc = NULL;
|
|
|
|
block->data = (bstr){0};
|
2017-01-31 14:48:10 +01:00
|
|
|
talloc_free(block->additions);
|
|
|
|
block->additions = NULL;
|
2013-04-11 21:42:46 +02:00
|
|
|
}
|
|
|
|
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
static void index_block(demuxer_t *demuxer, struct block_info *block)
|
|
|
|
{
|
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
|
|
|
if (block->keyframe) {
|
|
|
|
add_block_position(demuxer, block->track, mkv_d->cluster_start,
|
2014-11-05 20:44:21 +01:00
|
|
|
block->timecode / mkv_d->tc_scale,
|
|
|
|
block->duration / mkv_d->tc_scale);
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-14 17:38:08 +01:00
|
|
|
static int read_block(demuxer_t *demuxer, int64_t end, struct block_info *block)
|
2013-04-11 21:42:46 +02:00
|
|
|
{
|
2013-04-12 01:26:02 +02:00
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
2013-04-11 21:42:46 +02:00
|
|
|
stream_t *s = demuxer->stream;
|
2013-04-24 16:19:18 +02:00
|
|
|
uint64_t num;
|
2013-04-12 01:26:02 +02:00
|
|
|
int16_t time;
|
2013-04-12 17:25:51 +02:00
|
|
|
uint64_t length;
|
2013-04-12 01:26:02 +02:00
|
|
|
int res = -1;
|
2013-04-11 21:42:46 +02:00
|
|
|
|
2013-04-12 00:43:34 +02:00
|
|
|
free_block(block);
|
2014-01-14 17:38:51 +01:00
|
|
|
length = ebml_read_length(s);
|
2014-01-14 17:38:08 +01:00
|
|
|
if (length > 500000000 || stream_tell(s) + length > (uint64_t)end)
|
2013-04-12 01:26:02 +02:00
|
|
|
goto exit;
|
2013-04-12 17:25:51 +02:00
|
|
|
block->alloc = malloc(length + AV_LZO_INPUT_PADDING);
|
2013-04-12 17:40:45 +02:00
|
|
|
if (!block->alloc)
|
|
|
|
goto exit;
|
2013-04-12 17:25:51 +02:00
|
|
|
block->data = (bstr){block->alloc, length};
|
2013-11-16 21:04:28 +01:00
|
|
|
block->filepos = stream_tell(s);
|
2013-04-12 17:25:51 +02:00
|
|
|
if (stream_read(s, block->data.start, block->data.len) != block->data.len)
|
2013-04-12 01:26:02 +02:00
|
|
|
goto exit;
|
2013-04-12 00:43:34 +02:00
|
|
|
|
2013-04-12 01:26:02 +02:00
|
|
|
// Parse header of the Block element
|
|
|
|
/* first byte(s): track num */
|
2013-04-12 17:25:51 +02:00
|
|
|
num = ebml_read_vlen_uint(&block->data);
|
|
|
|
if (num == EBML_UINT_INVALID)
|
|
|
|
goto exit;
|
2013-04-12 01:26:02 +02:00
|
|
|
/* time (relative to cluster time) */
|
2013-04-12 17:25:51 +02:00
|
|
|
if (block->data.len < 3)
|
|
|
|
goto exit;
|
|
|
|
time = block->data.start[0] << 8 | block->data.start[1];
|
|
|
|
block->data.start += 2;
|
|
|
|
block->data.len -= 2;
|
2013-04-12 01:26:02 +02:00
|
|
|
if (block->simple)
|
2013-04-12 17:25:51 +02:00
|
|
|
block->keyframe = block->data.start[0] & 0x80;
|
2013-04-12 01:26:02 +02:00
|
|
|
block->timecode = time * mkv_d->tc_scale + mkv_d->cluster_tc;
|
|
|
|
for (int i = 0; i < mkv_d->num_tracks; i++) {
|
|
|
|
if (mkv_d->tracks[i]->tnum == num) {
|
|
|
|
block->track = mkv_d->tracks[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!block->track) {
|
|
|
|
res = 0;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
res = 1;
|
|
|
|
exit:
|
|
|
|
if (res <= 0)
|
|
|
|
free_block(block);
|
|
|
|
return res;
|
2013-04-11 21:42:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
2013-04-14 06:04:58 +02:00
|
|
|
int laces;
|
2009-12-29 20:06:21 +01:00
|
|
|
double current_pts;
|
2013-04-12 17:25:51 +02:00
|
|
|
bstr data = block_info->data;
|
2013-04-11 21:42:46 +02:00
|
|
|
bool keyframe = block_info->keyframe;
|
|
|
|
uint64_t block_duration = block_info->duration;
|
2016-01-27 21:08:53 +01:00
|
|
|
int64_t tc = block_info->timecode;
|
2013-04-12 01:26:02 +02:00
|
|
|
mkv_track_t *track = block_info->track;
|
2013-04-14 19:23:18 +02:00
|
|
|
struct sh_stream *stream = track->stream;
|
2013-04-12 16:07:45 +02:00
|
|
|
uint32_t lace_size[MAX_NUM_LACES];
|
2013-04-13 21:19:25 +02:00
|
|
|
bool use_this_block = tc >= mkv_d->skip_to_timecode;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2014-07-06 19:02:21 +02:00
|
|
|
if (!demux_stream_is_selected(stream))
|
2013-04-14 19:23:18 +02:00
|
|
|
return 0;
|
|
|
|
|
2013-12-21 20:24:20 +01:00
|
|
|
if (demux_mkv_read_block_lacing(&data, &laces, lace_size)) {
|
|
|
|
MP_ERR(demuxer, "Bad input [lacing]\n");
|
2009-12-29 20:06:21 +01:00
|
|
|
return 0;
|
2013-12-21 20:24:20 +01:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2015-11-07 17:37:32 +01:00
|
|
|
current_pts = tc / 1e9 - track->codec_delay;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2016-12-19 21:29:46 +01:00
|
|
|
if (track->require_keyframes && !keyframe) {
|
|
|
|
keyframe = true;
|
|
|
|
if (!mkv_d->keyframe_warning) {
|
|
|
|
MP_WARN(demuxer, "This is a broken file! Packets with incorrect "
|
|
|
|
"keyframe flag found. Enabling workaround.\n");
|
|
|
|
mkv_d->keyframe_warning = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-14 19:23:18 +02:00
|
|
|
if (track->type == MATROSKA_TRACK_AUDIO) {
|
2012-07-24 23:23:27 +02:00
|
|
|
if (mkv_d->a_skip_to_keyframe)
|
2014-02-09 19:00:06 +01:00
|
|
|
use_this_block &= keyframe;
|
2013-04-14 19:23:18 +02:00
|
|
|
} else if (track->type == MATROSKA_TRACK_SUBTITLE) {
|
2015-10-12 21:19:43 +02:00
|
|
|
if (!use_this_block && mkv_d->subtitle_preroll) {
|
|
|
|
int64_t end_time = block_info->timecode + block_info->duration;
|
|
|
|
if (!block_info->duration)
|
|
|
|
end_time = INT64_MAX;
|
|
|
|
use_this_block = end_time > mkv_d->skip_to_timecode;
|
|
|
|
}
|
2013-09-16 00:20:19 +02:00
|
|
|
if (use_this_block) {
|
|
|
|
if (mkv_d->subtitle_preroll) {
|
|
|
|
mkv_d->subtitle_preroll--;
|
|
|
|
} else {
|
|
|
|
// This could overflow the demuxer queue.
|
|
|
|
if (mkv_d->a_skip_to_keyframe || mkv_d->v_skip_to_keyframe)
|
|
|
|
use_this_block = 0;
|
|
|
|
}
|
2013-09-08 05:09:16 +02:00
|
|
|
}
|
2013-04-04 01:43:14 +02:00
|
|
|
if (use_this_block) {
|
|
|
|
if (laces > 1) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "Subtitles use Matroska "
|
2013-04-24 21:33:33 +02:00
|
|
|
"lacing. This is abnormal and not supported.\n");
|
2013-04-04 01:43:14 +02:00
|
|
|
use_this_block = 0;
|
|
|
|
}
|
|
|
|
}
|
2013-04-14 19:23:18 +02:00
|
|
|
} else if (track->type == MATROSKA_TRACK_VIDEO) {
|
2012-07-24 23:23:27 +02:00
|
|
|
if (mkv_d->v_skip_to_keyframe)
|
2013-04-13 21:19:25 +02:00
|
|
|
use_this_block &= keyframe;
|
|
|
|
}
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2013-04-14 19:23:18 +02:00
|
|
|
if (use_this_block) {
|
2015-02-13 21:17:07 +01:00
|
|
|
uint64_t filepos = block_info->filepos;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2013-04-14 06:04:58 +02:00
|
|
|
for (int i = 0; i < laces; i++) {
|
2013-04-12 17:25:51 +02:00
|
|
|
bstr block = bstr_splice(data, 0, lace_size[i]);
|
|
|
|
data = bstr_cut(data, lace_size[i]);
|
2015-02-05 21:52:07 +01:00
|
|
|
|
|
|
|
block = demux_mkv_decode(demuxer->log, track, block, 1);
|
|
|
|
|
|
|
|
demux_packet_t *dp = new_demux_packet_from(block.start, block.len);
|
|
|
|
if (!dp)
|
|
|
|
break;
|
|
|
|
dp->keyframe = keyframe;
|
2015-02-13 21:17:07 +01:00
|
|
|
dp->pos = filepos;
|
2015-02-05 21:52:07 +01:00
|
|
|
/* 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). Also, don't use it for extra
|
|
|
|
* packets resulting from parsing. */
|
|
|
|
if (i == 0 || track->default_duration)
|
2016-02-28 19:14:23 +01:00
|
|
|
dp->pts = current_pts + i * track->default_duration;
|
2016-01-12 23:48:19 +01:00
|
|
|
if (stream->codec->avi_dts)
|
2015-02-05 21:52:07 +01:00
|
|
|
MPSWAP(double, dp->pts, dp->dts);
|
2016-03-04 23:58:44 +01:00
|
|
|
if (i == 0 && block_info->duration_known)
|
2015-02-05 21:52:07 +01:00
|
|
|
dp->duration = block_duration / 1e9;
|
|
|
|
if (stream->type == STREAM_AUDIO) {
|
2016-02-22 20:46:28 +01:00
|
|
|
unsigned int srate = stream->codec->samplerate;
|
2015-02-05 21:52:07 +01:00
|
|
|
demux_packet_set_padding(dp,
|
|
|
|
mkv_d->a_skip_preroll ? track->codec_delay * srate : 0,
|
|
|
|
block_info->discardpadding / 1e9 * srate);
|
|
|
|
mkv_d->a_skip_preroll = 0;
|
|
|
|
}
|
2017-01-31 14:48:10 +01:00
|
|
|
if (block_info->additions) {
|
|
|
|
for (int n = 0; n < block_info->additions->n_block_more; n++) {
|
|
|
|
struct ebml_block_more *add =
|
|
|
|
&block_info->additions->block_more[n];
|
|
|
|
int64_t id = add->n_block_add_id ? add->block_add_id : 1;
|
|
|
|
demux_packet_add_blockadditional(dp, id,
|
|
|
|
add->block_additional.start, add->block_additional.len);
|
|
|
|
}
|
|
|
|
}
|
2015-02-05 21:52:07 +01:00
|
|
|
|
|
|
|
mkv_parse_and_add_packet(demuxer, track, dp);
|
|
|
|
talloc_free_children(track->parser_tmp);
|
2015-02-13 21:17:07 +01:00
|
|
|
filepos += block.len;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2013-04-14 19:23:18 +02:00
|
|
|
if (stream->type == STREAM_VIDEO) {
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_d->v_skip_to_keyframe = 0;
|
2016-01-27 21:08:53 +01:00
|
|
|
mkv_d->skip_to_timecode = INT64_MIN;
|
2013-09-08 05:09:16 +02:00
|
|
|
mkv_d->subtitle_preroll = 0;
|
2013-10-19 23:10:03 +02:00
|
|
|
} else if (stream->type == STREAM_AUDIO) {
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_d->a_skip_to_keyframe = 0;
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
return 1;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
return 0;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2013-04-11 23:33:42 +02:00
|
|
|
static int read_block_group(demuxer_t *demuxer, int64_t end,
|
|
|
|
struct block_info *block)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
|
|
|
stream_t *s = demuxer->stream;
|
2013-04-12 00:43:34 +02:00
|
|
|
*block = (struct block_info){ .keyframe = true };
|
2013-04-11 23:33:42 +02:00
|
|
|
|
|
|
|
while (stream_tell(s) < end) {
|
2014-01-14 17:38:51 +01:00
|
|
|
switch (ebml_read_id(s)) {
|
2013-04-11 23:33:42 +02:00
|
|
|
case MATROSKA_ID_BLOCKDURATION:
|
2014-01-14 17:38:51 +01:00
|
|
|
block->duration = ebml_read_uint(s);
|
2013-04-11 23:33:42 +02:00
|
|
|
if (block->duration == EBML_UINT_INVALID)
|
2013-04-12 00:43:34 +02:00
|
|
|
goto error;
|
2013-04-11 23:33:42 +02:00
|
|
|
block->duration *= mkv_d->tc_scale;
|
2016-03-04 23:58:44 +01:00
|
|
|
block->duration_known = true;
|
2013-04-11 23:33:42 +02:00
|
|
|
break;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2014-11-03 20:00:34 +01:00
|
|
|
case MATROSKA_ID_DISCARDPADDING:
|
|
|
|
block->discardpadding = ebml_read_uint(s);
|
|
|
|
if (block->discardpadding == EBML_UINT_INVALID)
|
|
|
|
goto error;
|
|
|
|
break;
|
|
|
|
|
2013-04-11 23:33:42 +02:00
|
|
|
case MATROSKA_ID_BLOCK:
|
2014-01-14 17:38:08 +01:00
|
|
|
if (read_block(demuxer, end, block) < 0)
|
2013-04-12 00:43:34 +02:00
|
|
|
goto error;
|
2013-04-11 23:33:42 +02:00
|
|
|
break;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2013-04-11 23:33:42 +02:00
|
|
|
case MATROSKA_ID_REFERENCEBLOCK:;
|
2014-01-14 17:38:51 +01:00
|
|
|
int64_t num = ebml_read_int(s);
|
2013-04-11 23:33:42 +02:00
|
|
|
if (num == EBML_INT_INVALID)
|
2013-04-12 00:43:34 +02:00
|
|
|
goto error;
|
2017-01-31 12:44:14 +01:00
|
|
|
block->keyframe = false;
|
2013-04-11 23:33:42 +02:00
|
|
|
break;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2017-01-31 14:48:10 +01:00
|
|
|
case MATROSKA_ID_BLOCKADDITIONS:;
|
|
|
|
struct ebml_block_additions additions = {0};
|
|
|
|
struct ebml_parse_ctx parse_ctx = {demuxer->log};
|
|
|
|
if (ebml_read_element(s, &parse_ctx, &additions,
|
|
|
|
&ebml_block_additions_desc) < 0)
|
|
|
|
return -1;
|
|
|
|
if (additions.n_block_more > 0) {
|
|
|
|
block->additions =
|
|
|
|
talloc_memdup(NULL, &additions, sizeof(additions));
|
|
|
|
talloc_steal(block->additions, parse_ctx.talloc_ctx);
|
|
|
|
parse_ctx.talloc_ctx = NULL;
|
|
|
|
}
|
|
|
|
talloc_free(parse_ctx.talloc_ctx);
|
|
|
|
break;
|
|
|
|
|
2014-01-14 17:38:21 +01:00
|
|
|
case MATROSKA_ID_CLUSTER:
|
2013-04-11 23:33:42 +02:00
|
|
|
case EBML_ID_INVALID:
|
2013-04-12 00:43:34 +02:00
|
|
|
goto error;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2013-04-11 23:33:42 +02:00
|
|
|
default:
|
2014-01-14 17:38:21 +01:00
|
|
|
if (ebml_read_skip(demuxer->log, end, s) != 0)
|
2013-04-12 00:43:34 +02:00
|
|
|
goto error;
|
2013-04-11 23:33:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2013-04-12 17:25:51 +02:00
|
|
|
return block->data.start ? 1 : 0;
|
2013-04-12 00:43:34 +02:00
|
|
|
|
|
|
|
error:
|
|
|
|
free_block(block);
|
|
|
|
return -1;
|
2013-04-11 23:33:42 +02:00
|
|
|
}
|
2004-02-09 20:21:08 +01:00
|
|
|
|
2013-04-12 00:43:34 +02:00
|
|
|
static int read_next_block(demuxer_t *demuxer, struct block_info *block)
|
2013-04-11 23:33:42 +02:00
|
|
|
{
|
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
|
|
|
stream_t *s = demuxer->stream;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2015-10-16 16:49:23 +02:00
|
|
|
if (mkv_d->tmp_block.alloc) {
|
|
|
|
*block = mkv_d->tmp_block;
|
|
|
|
mkv_d->tmp_block = (struct block_info){0};
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-04-11 23:33:42 +02:00
|
|
|
while (1) {
|
|
|
|
while (stream_tell(s) < mkv_d->cluster_end) {
|
2013-04-12 14:57:06 +02:00
|
|
|
int64_t start_filepos = stream_tell(s);
|
2014-01-14 17:38:51 +01:00
|
|
|
switch (ebml_read_id(s)) {
|
2013-04-12 14:57:06 +02:00
|
|
|
case MATROSKA_ID_TIMECODE: {
|
2014-01-14 17:38:51 +01:00
|
|
|
uint64_t num = ebml_read_uint(s);
|
2013-04-12 14:57:06 +02:00
|
|
|
if (num == EBML_UINT_INVALID)
|
|
|
|
goto find_next_cluster;
|
|
|
|
mkv_d->cluster_tc = num * mkv_d->tc_scale;
|
|
|
|
break;
|
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2013-04-12 14:57:06 +02:00
|
|
|
case MATROSKA_ID_BLOCKGROUP: {
|
2014-01-14 17:38:51 +01:00
|
|
|
int64_t end = ebml_read_length(s);
|
2013-04-12 14:57:06 +02:00
|
|
|
end += stream_tell(s);
|
2014-01-14 17:38:08 +01:00
|
|
|
if (end > mkv_d->cluster_end)
|
|
|
|
goto find_next_cluster;
|
2013-04-12 14:57:06 +02:00
|
|
|
int res = read_block_group(demuxer, end, block);
|
|
|
|
if (res < 0)
|
|
|
|
goto find_next_cluster;
|
|
|
|
if (res > 0)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2013-04-12 14:57:06 +02:00
|
|
|
case MATROSKA_ID_SIMPLEBLOCK: {
|
|
|
|
*block = (struct block_info){ .simple = true };
|
2014-01-14 17:38:08 +01:00
|
|
|
int res = read_block(demuxer, mkv_d->cluster_end, block);
|
2013-04-12 14:57:06 +02:00
|
|
|
if (res < 0)
|
|
|
|
goto find_next_cluster;
|
|
|
|
if (res > 0)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
}
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2013-04-12 14:57:06 +02:00
|
|
|
case MATROSKA_ID_CLUSTER:
|
|
|
|
mkv_d->cluster_start = start_filepos;
|
|
|
|
goto next_cluster;
|
2013-04-11 23:28:27 +02:00
|
|
|
|
2013-04-12 14:57:06 +02:00
|
|
|
case EBML_ID_INVALID:
|
|
|
|
goto find_next_cluster;
|
2004-02-09 20:21:08 +01:00
|
|
|
|
2013-04-12 14:57:06 +02:00
|
|
|
default: ;
|
2014-01-14 17:38:21 +01:00
|
|
|
if (ebml_read_skip(demuxer->log, mkv_d->cluster_end, s) != 0)
|
2013-04-12 14:57:06 +02:00
|
|
|
goto find_next_cluster;
|
|
|
|
break;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
demux_mkv: improve robustness against broken files
Fixes test7.mkv from the Matroska test file collection, as well as some
real broken files I've found in the wild. (Unfortunately, true recovery
requires resetting the decoders and playback state with a manual seek,
but it's still better than just exiting.)
If there are broken EBML elements, try harder to skip them correctly.
Do this by searching for the next cluster element. The cluster element
intentionally has a long ID, so it's a suitable element for
resynchronizing (mkvmerge does something similar).
We know that data is corrupt if the ID or length fields of an element
are malformed. Additionally, if skipping an unknown element goes past
the end of the file, we assume it's corrupt and undo the seek. Do this
because it often happens that corrupt data is interpreted as correct
EBML elements. Since these elements will have a ridiculous values in
their length fields due to the large value range that is possible
(0-2^56-2), they will go past the end of the file. So instead of
skipping them (which would result in playback termination), try to
find the next cluster instead. (We still skip unknown elements that
are within the file, as this is needed for correct operation. Also, we
first execute the seek, because we don't really know where the file
ends. Doing it this way is better for unseekable streams too, because
it will still work in the non-error case.)
This is done as special case in the packet reading function only. On
the other hand, that's the only part of the file that's read after
initialization is done.
2013-03-28 00:01:17 +01:00
|
|
|
find_next_cluster:
|
2013-04-11 23:33:42 +02:00
|
|
|
mkv_d->cluster_end = 0;
|
demux_mkv: improve robustness against broken files
Fixes test7.mkv from the Matroska test file collection, as well as some
real broken files I've found in the wild. (Unfortunately, true recovery
requires resetting the decoders and playback state with a manual seek,
but it's still better than just exiting.)
If there are broken EBML elements, try harder to skip them correctly.
Do this by searching for the next cluster element. The cluster element
intentionally has a long ID, so it's a suitable element for
resynchronizing (mkvmerge does something similar).
We know that data is corrupt if the ID or length fields of an element
are malformed. Additionally, if skipping an unknown element goes past
the end of the file, we assume it's corrupt and undo the seek. Do this
because it often happens that corrupt data is interpreted as correct
EBML elements. Since these elements will have a ridiculous values in
their length fields due to the large value range that is possible
(0-2^56-2), they will go past the end of the file. So instead of
skipping them (which would result in playback termination), try to
find the next cluster instead. (We still skip unknown elements that
are within the file, as this is needed for correct operation. Also, we
first execute the seek, because we don't really know where the file
ends. Doing it this way is better for unseekable streams too, because
it will still work in the non-error case.)
This is done as special case in the packet reading function only. On
the other hand, that's the only part of the file that's read after
initialization is done.
2013-03-28 00:01:17 +01:00
|
|
|
for (;;) {
|
2016-05-21 16:39:44 +02:00
|
|
|
stream_peek(s, 4); // guarantee we can undo ebml_read_id() below
|
2013-04-11 20:31:58 +02:00
|
|
|
mkv_d->cluster_start = stream_tell(s);
|
2014-01-14 17:38:51 +01:00
|
|
|
uint32_t id = ebml_read_id(s);
|
demux_mkv: improve robustness against broken files
Fixes test7.mkv from the Matroska test file collection, as well as some
real broken files I've found in the wild. (Unfortunately, true recovery
requires resetting the decoders and playback state with a manual seek,
but it's still better than just exiting.)
If there are broken EBML elements, try harder to skip them correctly.
Do this by searching for the next cluster element. The cluster element
intentionally has a long ID, so it's a suitable element for
resynchronizing (mkvmerge does something similar).
We know that data is corrupt if the ID or length fields of an element
are malformed. Additionally, if skipping an unknown element goes past
the end of the file, we assume it's corrupt and undo the seek. Do this
because it often happens that corrupt data is interpreted as correct
EBML elements. Since these elements will have a ridiculous values in
their length fields due to the large value range that is possible
(0-2^56-2), they will go past the end of the file. So instead of
skipping them (which would result in playback termination), try to
find the next cluster instead. (We still skip unknown elements that
are within the file, as this is needed for correct operation. Also, we
first execute the seek, because we don't really know where the file
ends. Doing it this way is better for unseekable streams too, because
it will still work in the non-error case.)
This is done as special case in the packet reading function only. On
the other hand, that's the only part of the file that's read after
initialization is done.
2013-03-28 00:01:17 +01:00
|
|
|
if (id == MATROSKA_ID_CLUSTER)
|
|
|
|
break;
|
2010-01-25 12:27:35 +01:00
|
|
|
if (s->eof)
|
2013-04-12 00:43:34 +02:00
|
|
|
return -1;
|
2015-03-09 22:32:04 +01:00
|
|
|
if (demux_cancel_test(demuxer))
|
|
|
|
return -1;
|
2014-01-22 23:37:03 +01:00
|
|
|
if (id == EBML_ID_EBML && stream_tell(s) >= mkv_d->segment_end) {
|
|
|
|
// Appended segment - don't use its clusters, consider this EOF.
|
|
|
|
stream_seek(s, stream_tell(s) - 4);
|
|
|
|
return -1;
|
|
|
|
}
|
2014-01-14 17:38:21 +01:00
|
|
|
// For the sake of robustness, consider even unknown level 1
|
|
|
|
// elements the same as unknown/broken IDs.
|
2015-12-29 20:12:46 +01:00
|
|
|
if ((!ebml_is_mkv_level1_id(id) && id != EBML_ID_VOID) ||
|
2014-01-14 17:38:21 +01:00
|
|
|
ebml_read_skip(demuxer->log, -1, s) != 0)
|
|
|
|
{
|
2016-05-21 16:39:44 +02:00
|
|
|
stream_seek(s, mkv_d->cluster_start);
|
2014-01-14 17:38:21 +01:00
|
|
|
ebml_resync_cluster(demuxer->log, s);
|
|
|
|
}
|
2010-01-25 12:27:35 +01:00
|
|
|
}
|
2013-04-11 23:28:27 +02:00
|
|
|
next_cluster:
|
2014-01-14 17:38:51 +01:00
|
|
|
mkv_d->cluster_end = ebml_read_length(s);
|
2013-04-11 23:28:27 +02:00
|
|
|
// mkv files for "streaming" can have this legally
|
|
|
|
if (mkv_d->cluster_end != EBML_UINT_INVALID)
|
|
|
|
mkv_d->cluster_end += stream_tell(s);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
2013-04-12 00:43:34 +02:00
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2013-07-11 19:17:51 +02:00
|
|
|
static int demux_mkv_fill_buffer(demuxer_t *demuxer)
|
2013-04-12 00:43:34 +02:00
|
|
|
{
|
|
|
|
for (;;) {
|
|
|
|
int res;
|
|
|
|
struct block_info block;
|
|
|
|
res = read_next_block(demuxer, &block);
|
|
|
|
if (res < 0)
|
|
|
|
return 0;
|
|
|
|
if (res > 0) {
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
index_block(demuxer, &block);
|
2013-04-12 00:43:34 +02:00
|
|
|
res = handle_block(demuxer, &block);
|
|
|
|
free_block(&block);
|
|
|
|
if (res > 0)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
static mkv_index_t *get_highest_index_entry(struct demuxer *demuxer)
|
|
|
|
{
|
|
|
|
struct mkv_demuxer *mkv_d = demuxer->priv;
|
|
|
|
assert(!mkv_d->index_complete); // would require separate code
|
|
|
|
|
|
|
|
mkv_index_t *index = NULL;
|
|
|
|
for (int n = 0; n < mkv_d->num_tracks; n++) {
|
|
|
|
int n_index = mkv_d->tracks[n]->last_index_entry;
|
|
|
|
if (n_index >= 0) {
|
|
|
|
mkv_index_t *index2 = &mkv_d->indexes[n_index];
|
|
|
|
if (!index || index2->filepos > index->filepos)
|
|
|
|
index = index2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
2016-01-27 21:08:53 +01:00
|
|
|
static int create_index_until(struct demuxer *demuxer, int64_t timecode)
|
2010-11-08 03:27:09 +01:00
|
|
|
{
|
|
|
|
struct mkv_demuxer *mkv_d = demuxer->priv;
|
|
|
|
struct stream *s = demuxer->stream;
|
|
|
|
|
2013-05-23 00:26:42 +02:00
|
|
|
read_deferred_cues(demuxer);
|
|
|
|
|
2013-04-11 17:40:23 +02:00
|
|
|
if (mkv_d->index_complete)
|
|
|
|
return 0;
|
|
|
|
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
mkv_index_t *index = get_highest_index_entry(demuxer);
|
|
|
|
|
|
|
|
if (!index || index->timecode * mkv_d->tc_scale < timecode) {
|
2015-11-17 21:43:35 +01:00
|
|
|
stream_seek(s, index ? index->filepos : mkv_d->cluster_start);
|
2016-01-27 21:08:53 +01:00
|
|
|
MP_VERBOSE(demuxer, "creating index until TC %" PRId64 "\n", timecode);
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
for (;;) {
|
|
|
|
int res;
|
|
|
|
struct block_info block;
|
|
|
|
res = read_next_block(demuxer, &block);
|
|
|
|
if (res < 0)
|
|
|
|
break;
|
|
|
|
if (res > 0) {
|
|
|
|
index_block(demuxer, &block);
|
|
|
|
free_block(&block);
|
2010-11-08 03:27:09 +01:00
|
|
|
}
|
demux_mkv: fix seeking with index generation
Relative seeks backwards didn't work too well with incomplete files, or
other files that are missing the seek index. The problem was that the
on-the-fly seek index generation simply added cluster positions as seek
entries. While this is perfectly fine, the seek code had no information
about the location of video key frames. For example, a 5 second long
cluster can have only 1 video key frame, which is located 4 seconds into
the cluster. Seeking backwards by one second while still located in the
same cluster would select this cluster as seek target again. Decoding
would resume with the key frame, giving the impression that seeking is
"stuck" at this frame.
Make the generated index aware of key frame and track information, so
that video can always be seeked in an idea way. This also uses the
normal block parsing code for indexing the clusters, instead of the
suspicious looking special code. (This code didn't parse the Matroska
elements correctly, but was fine for files with normal structure. Files
with corrupted clusters or clusters formatted for streaming were not
handled properly.)
Skipping is now quite a bit slower (takes about twice as long as
before), but it removes the special cased skipping code, and it's still
much faster (at least twice as fast) than libavformat. It needs to do
more I/O (no more skipping entire clusters, all data is read), and has
more CPU usage (more data needs to be parsed).
2013-04-12 02:22:23 +02:00
|
|
|
index = get_highest_index_entry(demuxer);
|
|
|
|
if (index && index->timecode * mkv_d->tc_scale >= timecode)
|
2010-11-08 03:43:48 +01:00
|
|
|
break;
|
2010-11-08 03:27:09 +01:00
|
|
|
}
|
|
|
|
}
|
2013-04-11 17:40:23 +02:00
|
|
|
if (!mkv_d->indexes) {
|
2013-12-21 20:24:20 +01:00
|
|
|
MP_WARN(demuxer, "no target for seek found\n");
|
2010-11-08 03:27:09 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-23 19:21:17 +02:00
|
|
|
#define FLAG_BACKWARD 1
|
|
|
|
#define FLAG_SUBPREROLL 2
|
2010-11-08 04:43:35 +01:00
|
|
|
static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
|
|
|
|
int64_t target_timecode, int flags)
|
|
|
|
{
|
|
|
|
struct mkv_demuxer *mkv_d = demuxer->priv;
|
|
|
|
struct mkv_index *index = NULL;
|
|
|
|
|
2015-04-23 15:27:04 +02:00
|
|
|
int64_t min_diff = INT64_MIN;
|
2014-06-29 23:22:07 +02:00
|
|
|
for (size_t i = 0; i < mkv_d->num_indexes; i++) {
|
2010-11-08 04:43:35 +01:00
|
|
|
if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) {
|
2010-11-15 16:48:22 +01:00
|
|
|
int64_t diff =
|
2016-01-27 21:08:53 +01:00
|
|
|
target_timecode - mkv_d->indexes[i].timecode * mkv_d->tc_scale;
|
2015-04-23 19:21:17 +02:00
|
|
|
if (flags & FLAG_BACKWARD)
|
2010-12-20 01:26:10 +01:00
|
|
|
diff = -diff;
|
2015-04-23 15:27:04 +02:00
|
|
|
if (min_diff != INT64_MIN) {
|
|
|
|
if (diff <= 0) {
|
|
|
|
if (min_diff <= 0 && diff <= min_diff)
|
|
|
|
continue;
|
|
|
|
} else if (diff >= min_diff)
|
2010-11-08 04:43:35 +01:00
|
|
|
continue;
|
2015-04-23 15:27:04 +02:00
|
|
|
}
|
2010-11-08 04:43:35 +01:00
|
|
|
min_diff = diff;
|
|
|
|
index = mkv_d->indexes + i;
|
|
|
|
}
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2010-11-08 04:43:35 +01:00
|
|
|
|
|
|
|
if (index) { /* We've found an entry. */
|
2013-04-04 01:43:14 +02:00
|
|
|
uint64_t seek_pos = index->filepos;
|
2015-04-23 19:21:17 +02:00
|
|
|
if (flags & FLAG_SUBPREROLL) {
|
2014-11-14 23:52:47 +01:00
|
|
|
// Find the cluster with the highest filepos, that has a timestamp
|
|
|
|
// still lower than min_tc.
|
2016-09-06 20:09:56 +02:00
|
|
|
double secs = mkv_d->opts->subtitle_preroll_secs;
|
2015-12-27 01:01:25 +01:00
|
|
|
if (mkv_d->index_has_durations)
|
2016-09-06 20:09:56 +02:00
|
|
|
secs = MPMAX(secs, mkv_d->opts->subtitle_preroll_secs_index);
|
2016-01-27 21:08:53 +01:00
|
|
|
int64_t pre = MPMIN(INT64_MAX, secs * 1e9 / mkv_d->tc_scale);
|
|
|
|
int64_t min_tc = pre < index->timecode ? index->timecode - pre : 0;
|
2013-04-04 01:43:14 +02:00
|
|
|
uint64_t prev_target = 0;
|
2016-01-27 21:08:53 +01:00
|
|
|
int64_t prev_tc = 0;
|
2014-06-29 23:22:07 +02:00
|
|
|
for (size_t i = 0; i < mkv_d->num_indexes; i++) {
|
2014-11-11 19:36:03 +01:00
|
|
|
if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) {
|
2014-11-14 23:52:47 +01:00
|
|
|
struct mkv_index *cur = &mkv_d->indexes[i];
|
|
|
|
if (cur->timecode <= min_tc && cur->timecode >= prev_tc) {
|
|
|
|
prev_tc = cur->timecode;
|
|
|
|
prev_target = cur->filepos;
|
|
|
|
}
|
2014-11-11 19:36:03 +01:00
|
|
|
}
|
2013-04-04 01:43:14 +02:00
|
|
|
}
|
2014-11-05 20:47:42 +01:00
|
|
|
if (mkv_d->index_has_durations) {
|
2014-11-11 19:36:03 +01:00
|
|
|
// Find the earliest cluster that is not before prev_target,
|
|
|
|
// but contains subtitle packets overlapping with the cluster
|
|
|
|
// at seek_pos.
|
|
|
|
uint64_t target = seek_pos;
|
2014-11-05 20:47:42 +01:00
|
|
|
for (size_t i = 0; i < mkv_d->num_indexes; i++) {
|
|
|
|
struct mkv_index *cur = &mkv_d->indexes[i];
|
2014-11-11 19:36:03 +01:00
|
|
|
if (cur->timecode <= index->timecode &&
|
|
|
|
cur->timecode + cur->duration > index->timecode &&
|
|
|
|
cur->filepos >= prev_target &&
|
|
|
|
cur->filepos < target)
|
|
|
|
{
|
|
|
|
target = cur->filepos;
|
|
|
|
}
|
2014-11-05 20:47:42 +01:00
|
|
|
}
|
2014-11-11 19:36:03 +01:00
|
|
|
prev_target = target;
|
2014-11-05 20:47:42 +01:00
|
|
|
}
|
2013-04-04 01:43:14 +02:00
|
|
|
if (prev_target)
|
|
|
|
seek_pos = prev_target;
|
|
|
|
}
|
|
|
|
|
2013-04-11 23:33:42 +02:00
|
|
|
mkv_d->cluster_end = 0;
|
2013-04-04 01:43:14 +02:00
|
|
|
stream_seek(demuxer->stream, seek_pos);
|
2010-11-08 04:43:35 +01:00
|
|
|
}
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
2016-02-28 19:14:23 +01:00
|
|
|
static void demux_mkv_seek(demuxer_t *demuxer, double seek_pts, int flags)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2010-05-22 09:14:41 +02:00
|
|
|
mkv_demuxer_t *mkv_d = demuxer->priv;
|
2013-05-23 00:26:42 +02:00
|
|
|
int64_t old_pos = stream_tell(demuxer->stream);
|
2010-05-22 09:14:41 +02:00
|
|
|
uint64_t v_tnum = -1;
|
|
|
|
uint64_t a_tnum = -1;
|
2013-04-14 19:23:18 +02:00
|
|
|
bool st_active[STREAM_TYPE_COUNT] = {0};
|
2013-12-27 20:00:24 +01:00
|
|
|
mkv_seek_reset(demuxer);
|
2013-04-14 19:23:18 +02:00
|
|
|
for (int i = 0; i < mkv_d->num_tracks; i++) {
|
|
|
|
mkv_track_t *track = mkv_d->tracks[i];
|
2014-07-06 19:02:21 +02:00
|
|
|
if (demux_stream_is_selected(track->stream)) {
|
2013-04-14 19:23:18 +02:00
|
|
|
st_active[track->stream->type] = true;
|
|
|
|
if (track->type == MATROSKA_TRACK_VIDEO)
|
|
|
|
v_tnum = track->tnum;
|
|
|
|
if (track->type == MATROSKA_TRACK_AUDIO)
|
|
|
|
a_tnum = track->tnum;
|
|
|
|
}
|
|
|
|
}
|
2015-04-23 19:21:17 +02:00
|
|
|
|
|
|
|
int cueflags = (flags & SEEK_BACKWARD) ? FLAG_BACKWARD : 0;
|
|
|
|
|
2013-09-16 00:20:19 +02:00
|
|
|
mkv_d->subtitle_preroll = NUM_SUB_PREROLL_PACKETS;
|
2016-09-06 20:09:56 +02:00
|
|
|
int preroll_opt = mkv_d->opts->subtitle_preroll;
|
2015-12-27 01:01:25 +01:00
|
|
|
if (((flags & SEEK_HR) || preroll_opt == 1 ||
|
|
|
|
(preroll_opt == 2 && mkv_d->index_has_durations))
|
|
|
|
&& st_active[STREAM_SUB] && st_active[STREAM_VIDEO])
|
2015-04-23 19:21:17 +02:00
|
|
|
cueflags |= FLAG_SUBPREROLL;
|
2014-10-29 22:45:21 +01:00
|
|
|
|
2009-03-31 18:30:14 +02:00
|
|
|
// Adjust the target a little bit to catch cases where the target position
|
|
|
|
// specifies a keyframe with high, but not perfect, precision.
|
2016-02-28 19:14:23 +01:00
|
|
|
seek_pts += flags & SEEK_FORWARD ? -0.005 : 0.005;
|
2009-03-31 18:30:14 +02:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
if (!(flags & SEEK_FACTOR)) { /* time in secs */
|
|
|
|
mkv_index_t *index = NULL;
|
|
|
|
|
2016-02-28 19:14:23 +01:00
|
|
|
seek_pts = FFMAX(seek_pts, 0);
|
|
|
|
int64_t target_timecode = seek_pts * 1e9 + 0.5;
|
2009-12-29 20:06:21 +01:00
|
|
|
|
2013-04-11 17:40:23 +02:00
|
|
|
if (create_index_until(demuxer, target_timecode) >= 0) {
|
2013-04-14 19:23:18 +02:00
|
|
|
int seek_id = st_active[STREAM_VIDEO] ? v_tnum : a_tnum;
|
2015-04-23 19:21:17 +02:00
|
|
|
index = seek_with_cues(demuxer, seek_id, target_timecode, cueflags);
|
2010-11-08 04:43:35 +01:00
|
|
|
if (!index)
|
2015-04-23 19:21:17 +02:00
|
|
|
index = seek_with_cues(demuxer, -1, target_timecode, cueflags);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2013-05-23 00:26:42 +02:00
|
|
|
if (!index)
|
|
|
|
stream_seek(demuxer->stream, old_pos);
|
|
|
|
|
2013-10-19 23:10:03 +02:00
|
|
|
if (flags & SEEK_FORWARD) {
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_d->skip_to_timecode = target_timecode;
|
2013-10-19 23:10:03 +02:00
|
|
|
} else {
|
2011-01-23 23:29:01 +01:00
|
|
|
mkv_d->skip_to_timecode = index ? index->timecode * mkv_d->tc_scale
|
2016-01-27 21:08:53 +01:00
|
|
|
: INT64_MIN;
|
2013-10-19 23:10:03 +02:00
|
|
|
}
|
2014-10-29 22:45:21 +01:00
|
|
|
} else {
|
2009-12-29 20:06:21 +01:00
|
|
|
stream_t *s = demuxer->stream;
|
|
|
|
|
2013-05-23 00:26:42 +02:00
|
|
|
read_deferred_cues(demuxer);
|
|
|
|
|
2015-08-18 00:10:54 +02:00
|
|
|
int64_t size = stream_get_size(s);
|
2016-02-28 19:14:23 +01:00
|
|
|
int64_t target_filepos = size * MPCLAMP(seek_pts, 0, 1);
|
2014-10-29 22:34:40 +01:00
|
|
|
|
|
|
|
mkv_index_t *index = NULL;
|
|
|
|
if (mkv_d->index_complete) {
|
|
|
|
for (size_t i = 0; i < mkv_d->num_indexes; i++) {
|
|
|
|
if (mkv_d->indexes[i].tnum == v_tnum) {
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
}
|
2013-05-23 00:26:42 +02:00
|
|
|
}
|
2004-03-26 20:45:06 +01:00
|
|
|
|
2013-04-11 23:33:42 +02:00
|
|
|
mkv_d->cluster_end = 0;
|
2004-03-26 20:45:06 +01:00
|
|
|
|
2014-10-29 22:34:40 +01:00
|
|
|
if (index) {
|
|
|
|
stream_seek(s, index->filepos);
|
|
|
|
mkv_d->skip_to_timecode = index->timecode * mkv_d->tc_scale;
|
|
|
|
} else {
|
2015-08-18 00:10:54 +02:00
|
|
|
stream_seek(s, MPMAX(target_filepos, 0));
|
2014-10-29 22:34:40 +01:00
|
|
|
if (ebml_resync_cluster(mp_null_log, s) < 0) {
|
|
|
|
// Assume EOF
|
|
|
|
mkv_d->cluster_end = size;
|
|
|
|
}
|
|
|
|
}
|
2004-03-26 20:45:06 +01:00
|
|
|
}
|
2014-11-03 20:25:21 +01:00
|
|
|
|
|
|
|
mkv_d->v_skip_to_keyframe = st_active[STREAM_VIDEO];
|
|
|
|
mkv_d->a_skip_to_keyframe = st_active[STREAM_AUDIO];
|
|
|
|
mkv_d->a_skip_preroll = mkv_d->a_skip_to_keyframe;
|
|
|
|
|
|
|
|
demux_mkv_fill_buffer(demuxer);
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
|
2015-10-27 20:57:11 +01:00
|
|
|
static void probe_last_timestamp(struct demuxer *demuxer, int64_t start_pos)
|
2014-11-18 23:07:20 +01:00
|
|
|
{
|
|
|
|
mkv_demuxer_t *mkv_d = demuxer->priv;
|
|
|
|
|
|
|
|
if (!demuxer->seekable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Pick some arbitrary video track
|
|
|
|
int v_tnum = -1;
|
|
|
|
for (int n = 0; n < mkv_d->num_tracks; n++) {
|
|
|
|
if (mkv_d->tracks[n]->type == MATROSKA_TRACK_VIDEO) {
|
|
|
|
v_tnum = mkv_d->tracks[n]->tnum;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (v_tnum < 0)
|
|
|
|
return;
|
|
|
|
|
2015-07-09 22:47:41 +02:00
|
|
|
// In full mode, we start reading data from the current file position,
|
|
|
|
// which works because this function is called after headers are parsed.
|
2016-09-06 20:09:56 +02:00
|
|
|
if (mkv_d->opts->probe_duration != 2) {
|
2015-07-09 22:47:41 +02:00
|
|
|
read_deferred_cues(demuxer);
|
|
|
|
if (mkv_d->index_complete) {
|
|
|
|
// Find last cluster that still has video packets
|
|
|
|
int64_t target = 0;
|
|
|
|
for (size_t i = 0; i < mkv_d->num_indexes; i++) {
|
|
|
|
struct mkv_index *cur = &mkv_d->indexes[i];
|
|
|
|
if (cur->tnum == v_tnum)
|
|
|
|
target = MPMAX(target, cur->filepos);
|
|
|
|
}
|
|
|
|
if (!target)
|
|
|
|
return;
|
2014-11-18 23:07:20 +01:00
|
|
|
|
2015-07-09 22:47:41 +02:00
|
|
|
if (!stream_seek(demuxer->stream, target))
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
// No index -> just try to find a random cluster towards file end.
|
2015-08-18 00:10:54 +02:00
|
|
|
int64_t size = stream_get_size(demuxer->stream);
|
2015-07-09 22:47:41 +02:00
|
|
|
stream_seek(demuxer->stream, MPMAX(size - 10 * 1024 * 1024, 0));
|
|
|
|
if (ebml_resync_cluster(mp_null_log, demuxer->stream) < 0)
|
2015-10-27 20:57:11 +01:00
|
|
|
stream_seek(demuxer->stream, start_pos); // full scan otherwise
|
2015-07-09 22:47:41 +02:00
|
|
|
}
|
2014-11-18 23:07:20 +01:00
|
|
|
}
|
|
|
|
|
2015-10-27 20:57:11 +01:00
|
|
|
free_block(&mkv_d->tmp_block);
|
|
|
|
|
2014-11-18 23:07:20 +01:00
|
|
|
int64_t last_ts[STREAM_TYPE_COUNT] = {0};
|
|
|
|
while (1) {
|
|
|
|
struct block_info block;
|
|
|
|
int res = read_next_block(demuxer, &block);
|
|
|
|
if (res < 0)
|
|
|
|
break;
|
|
|
|
if (res > 0) {
|
|
|
|
if (block.track && block.track->stream) {
|
|
|
|
enum stream_type type = block.track->stream->type;
|
2014-11-20 22:27:27 +01:00
|
|
|
uint64_t endtime = block.timecode + block.duration;
|
|
|
|
if (last_ts[type] < endtime)
|
|
|
|
last_ts[type] = endtime;
|
2014-11-18 23:07:20 +01:00
|
|
|
}
|
|
|
|
free_block(&block);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-09 22:47:41 +02:00
|
|
|
if (!last_ts[STREAM_VIDEO])
|
|
|
|
last_ts[STREAM_VIDEO] = mkv_d->cluster_tc;
|
|
|
|
|
2014-11-18 23:07:20 +01:00
|
|
|
if (last_ts[STREAM_VIDEO])
|
2015-10-26 18:21:31 +01:00
|
|
|
mkv_d->duration = last_ts[STREAM_VIDEO] / 1e9 - demuxer->start_time;
|
2014-11-18 23:07:20 +01:00
|
|
|
|
2015-10-27 20:57:11 +01:00
|
|
|
stream_seek(demuxer->stream, start_pos);
|
2014-11-18 23:07:20 +01:00
|
|
|
mkv_d->cluster_start = mkv_d->cluster_end = 0;
|
|
|
|
}
|
|
|
|
|
2015-10-16 16:49:23 +02:00
|
|
|
static void probe_first_timestamp(struct demuxer *demuxer)
|
|
|
|
{
|
|
|
|
mkv_demuxer_t *mkv_d = demuxer->priv;
|
|
|
|
|
2016-09-06 20:09:56 +02:00
|
|
|
if (!mkv_d->opts->probe_start_time)
|
2015-10-16 16:49:23 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
struct block_info block;
|
2016-04-12 15:41:44 +02:00
|
|
|
if (read_next_block(demuxer, &block) > 0) {
|
|
|
|
index_block(demuxer, &block);
|
2015-10-16 16:49:23 +02:00
|
|
|
mkv_d->tmp_block = block;
|
2016-04-12 15:41:44 +02:00
|
|
|
}
|
2015-10-16 16:49:23 +02:00
|
|
|
|
|
|
|
demuxer->start_time = mkv_d->cluster_tc / 1e9;
|
|
|
|
|
|
|
|
if (demuxer->start_time > 0)
|
|
|
|
MP_VERBOSE(demuxer, "Start PTS: %f\n", demuxer->start_time);
|
|
|
|
}
|
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
static int demux_mkv_control(demuxer_t *demuxer, int cmd, void *arg)
|
2004-01-19 20:16:10 +01:00
|
|
|
{
|
2009-12-29 20:06:21 +01:00
|
|
|
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
|
2009-07-07 01:26:13 +02:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
switch (cmd) {
|
2004-01-19 20:16:10 +01:00
|
|
|
case DEMUXER_CTRL_GET_TIME_LENGTH:
|
2009-12-29 20:06:21 +01:00
|
|
|
if (mkv_d->duration == 0)
|
2017-06-19 17:54:02 +02:00
|
|
|
return CONTROL_FALSE;
|
2004-01-19 20:16:10 +01:00
|
|
|
|
2009-12-29 20:06:21 +01:00
|
|
|
*((double *) arg) = (double) mkv_d->duration;
|
2017-06-19 17:54:02 +02:00
|
|
|
return CONTROL_OK;
|
2004-01-19 20:16:10 +01:00
|
|
|
default:
|
2017-06-19 17:54:02 +02:00
|
|
|
return CONTROL_UNKNOWN;
|
2004-01-19 20:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-27 20:00:24 +01:00
|
|
|
static void mkv_free(struct demuxer *demuxer)
|
|
|
|
{
|
|
|
|
struct mkv_demuxer *mkv_d = demuxer->priv;
|
|
|
|
if (!mkv_d)
|
|
|
|
return;
|
|
|
|
mkv_seek_reset(demuxer);
|
|
|
|
for (int i = 0; i < mkv_d->num_tracks; i++)
|
|
|
|
demux_mkv_free_trackentry(mkv_d->tracks[i]);
|
|
|
|
}
|
|
|
|
|
2008-01-13 17:00:39 +01:00
|
|
|
const demuxer_desc_t demuxer_desc_matroska = {
|
2013-07-11 20:08:12 +02:00
|
|
|
.name = "mkv",
|
2013-07-12 22:12:02 +02:00
|
|
|
.desc = "Matroska",
|
2013-07-12 21:58:11 +02:00
|
|
|
.open = demux_mkv_open,
|
2013-07-11 20:08:12 +02:00
|
|
|
.fill_buffer = demux_mkv_fill_buffer,
|
|
|
|
.close = mkv_free,
|
|
|
|
.seek = demux_mkv_seek,
|
2015-02-17 23:46:50 +01:00
|
|
|
.control = demux_mkv_control,
|
|
|
|
.load_timeline = build_ordered_chapter_timeline,
|
2005-08-05 21:57:47 +02:00
|
|
|
};
|
2013-10-07 02:49:12 +02:00
|
|
|
|
|
|
|
bool demux_matroska_uid_cmp(struct matroska_segment_uid *a,
|
|
|
|
struct matroska_segment_uid *b)
|
|
|
|
{
|
|
|
|
return (!memcmp(a->segment, b->segment, 16) &&
|
|
|
|
a->edition == b->edition);
|
|
|
|
}
|