2009-05-08 21:51:13 +00:00
|
|
|
/*
|
2015-04-13 07:36:54 +00:00
|
|
|
* This file is part of mpv.
|
2009-05-08 21:51:13 +00:00
|
|
|
*
|
2015-04-13 07:36:54 +00:00
|
|
|
* mpv is free software; you can redistribute it and/or modify
|
2009-05-08 21:51:13 +00:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
2015-04-13 07:36:54 +00:00
|
|
|
* mpv is distributed in the hope that it will be useful,
|
2009-05-08 21:51:13 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
2015-04-13 07:36:54 +00:00
|
|
|
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
2009-05-08 21:51:13 +00:00
|
|
|
*/
|
|
|
|
|
2008-02-22 09:09:46 +00:00
|
|
|
#ifndef MPLAYER_DEMUXER_H
|
|
|
|
#define MPLAYER_DEMUXER_H
|
2001-04-23 16:12:21 +00:00
|
|
|
|
2008-06-17 09:09:36 +00:00
|
|
|
#include <sys/types.h>
|
2008-03-05 23:32:01 +00:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2009-03-16 21:30:48 +00:00
|
|
|
#include <stdbool.h>
|
2008-03-05 23:32:01 +00:00
|
|
|
|
2014-08-29 10:09:04 +00:00
|
|
|
#include "misc/bstr.h"
|
2013-12-17 01:39:45 +00:00
|
|
|
#include "common/common.h"
|
2014-04-13 12:01:55 +00:00
|
|
|
#include "common/tags.h"
|
2013-11-18 17:46:44 +00:00
|
|
|
#include "packet.h"
|
2012-08-19 16:01:30 +00:00
|
|
|
#include "stheader.h"
|
2006-07-07 18:26:51 +00:00
|
|
|
|
2002-11-16 03:42:14 +00:00
|
|
|
// DEMUXER control commands/answers
|
|
|
|
#define DEMUXER_CTRL_NOTIMPL -1
|
|
|
|
#define DEMUXER_CTRL_DONTKNOW 0
|
|
|
|
#define DEMUXER_CTRL_OK 1
|
2013-04-14 04:20:31 +00:00
|
|
|
|
2013-10-02 19:19:16 +00:00
|
|
|
enum demux_ctrl {
|
2014-02-06 12:41:20 +00:00
|
|
|
DEMUXER_CTRL_SWITCHED_TRACKS = 1,
|
2013-10-02 19:19:16 +00:00
|
|
|
DEMUXER_CTRL_GET_TIME_LENGTH,
|
|
|
|
DEMUXER_CTRL_RESYNC,
|
|
|
|
DEMUXER_CTRL_IDENTIFY_PROGRAM,
|
2014-07-16 20:40:21 +00:00
|
|
|
DEMUXER_CTRL_STREAM_CTRL,
|
player: redo how stream caching and pausing on low cache works
Add the --cache-secs option, which literally overrides the value of
--demuxer-readahead-secs if the stream cache is active. The default
value is very high (10 seconds), which means it can act as network
cache.
Remove the old behavior of trying to pause once the byte cache runs
low. Instead, do something similar wit the demuxer cache. The nice
thing is that we can guess how many seconds of video it has cached,
and we can make better decisions. But for now, apply a relatively
naive heuristic: if the cache is below 0.5 secs, pause, and wait
until at least 2 secs are available.
Note that due to timestamp reordering, the estimated cached duration
of video might be inaccurate, depending on the file format. If the
file format has DTS, it's easy, otherwise the duration will seemingly
jump back and forth.
2014-08-26 23:13:20 +00:00
|
|
|
DEMUXER_CTRL_GET_READER_STATE,
|
2014-12-12 00:00:58 +00:00
|
|
|
DEMUXER_CTRL_GET_BITRATE_STATS, // double[STREAM_TYPE_COUNT]
|
2016-08-26 11:05:14 +00:00
|
|
|
DEMUXER_CTRL_REPLACE_STREAM,
|
player: redo how stream caching and pausing on low cache works
Add the --cache-secs option, which literally overrides the value of
--demuxer-readahead-secs if the stream cache is active. The default
value is very high (10 seconds), which means it can act as network
cache.
Remove the old behavior of trying to pause once the byte cache runs
low. Instead, do something similar wit the demuxer cache. The nice
thing is that we can guess how many seconds of video it has cached,
and we can make better decisions. But for now, apply a relatively
naive heuristic: if the cache is below 0.5 secs, pause, and wait
until at least 2 secs are available.
Note that due to timestamp reordering, the estimated cached duration
of video might be inaccurate, depending on the file format. If the
file format has DTS, it's easy, otherwise the duration will seemingly
jump back and forth.
2014-08-26 23:13:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct demux_ctrl_reader_state {
|
|
|
|
bool eof, underrun, idle;
|
|
|
|
double ts_range[2]; // start, end
|
2014-08-27 20:42:28 +00:00
|
|
|
double ts_duration;
|
command: redo ancient TV/DVB/PVR commands
Convert all these commands to properties. (Except tv_last_channel, not
sure what to do with this.) Also, internally, don't access stream
details directly, but dispatch commands with stream ctrls.
Many of the new properties are a bit strange, because they're write-
only. Also remove some OSD output these commands produced, because I
couldn't be bothered to port these.
In general, this makes everything much cleaner, and will also make it
easier to e.g. move the demuxer to its own thread.
Don't bother updating input.conf, but changes.rst documents how old
commands map to the new ones.
Mostly untested, due to lack of hardware.
2014-06-09 21:38:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct demux_ctrl_stream_ctrl {
|
|
|
|
int ctrl;
|
|
|
|
void *arg;
|
|
|
|
int res;
|
2013-10-02 19:19:16 +00:00
|
|
|
};
|
2002-11-16 03:42:14 +00:00
|
|
|
|
2015-01-19 19:45:31 +00:00
|
|
|
#define SEEK_FACTOR (1 << 1) // argument is in range [0,1]
|
|
|
|
#define SEEK_FORWARD (1 << 2) // prefer later time if not exact
|
|
|
|
#define SEEK_BACKWARD (1 << 3) // prefer earlier time if not exact
|
|
|
|
#define SEEK_HR (1 << 5) // hr-seek (this is a weak hint only)
|
2008-01-29 15:11:38 +00:00
|
|
|
|
2013-07-12 19:58:11 +00:00
|
|
|
// Strictness of the demuxer open format check.
|
|
|
|
// demux.c will try by default: NORMAL, UNSAFE (in this order)
|
|
|
|
// Using "-demuxer format" will try REQUEST
|
|
|
|
// Using "-demuxer +format" will try FORCE
|
|
|
|
// REQUEST can be used as special value for raw demuxers which have no file
|
|
|
|
// header check; then they should fail if check!=FORCE && check!=REQUEST.
|
|
|
|
//
|
|
|
|
// In general, the list is sorted from weakest check to normal check.
|
|
|
|
// You can use relation operators to compare the check level.
|
|
|
|
enum demux_check {
|
|
|
|
DEMUX_CHECK_FORCE, // force format if possible
|
|
|
|
DEMUX_CHECK_UNSAFE, // risky/fuzzy detection
|
|
|
|
DEMUX_CHECK_REQUEST,// requested by user or stream implementation
|
|
|
|
DEMUX_CHECK_NORMAL, // normal, safe detection
|
|
|
|
};
|
|
|
|
|
2014-07-05 14:45:56 +00:00
|
|
|
enum demux_event {
|
2014-07-16 20:40:21 +00:00
|
|
|
DEMUX_EVENT_INIT = 1 << 0, // complete (re-)initialization
|
|
|
|
DEMUX_EVENT_STREAMS = 1 << 1, // a stream was added
|
|
|
|
DEMUX_EVENT_METADATA = 1 << 2, // metadata or stream_metadata changed
|
|
|
|
DEMUX_EVENT_ALL = 0xFFFF,
|
2014-07-05 14:45:56 +00:00
|
|
|
};
|
|
|
|
|
2008-04-24 02:49:44 +00:00
|
|
|
struct demuxer;
|
2015-02-17 22:46:12 +00:00
|
|
|
struct timeline;
|
2005-08-05 19:57:47 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Demuxer description structure
|
|
|
|
*/
|
2008-04-24 02:49:44 +00:00
|
|
|
typedef struct demuxer_desc {
|
2011-02-10 10:05:26 +00:00
|
|
|
const char *name; // Demuxer name, used with -demuxer switch
|
2013-07-12 20:12:02 +00:00
|
|
|
const char *desc; // Displayed to user
|
2011-02-10 10:05:26 +00:00
|
|
|
|
2013-07-11 18:08:12 +00:00
|
|
|
// Return 0 on success, otherwise -1
|
2013-07-12 19:58:11 +00:00
|
|
|
int (*open)(struct demuxer *demuxer, enum demux_check check);
|
2013-07-11 18:08:12 +00:00
|
|
|
// The following functions are all optional
|
|
|
|
int (*fill_buffer)(struct demuxer *demuxer); // 0 on EOF, otherwise 1
|
|
|
|
void (*close)(struct demuxer *demuxer);
|
2014-07-21 17:28:18 +00:00
|
|
|
void (*seek)(struct demuxer *demuxer, double rel_seek_secs, int flags);
|
2011-02-10 10:05:26 +00:00
|
|
|
int (*control)(struct demuxer *demuxer, int cmd, void *arg);
|
2015-02-17 22:46:12 +00:00
|
|
|
// See timeline.c
|
|
|
|
void (*load_timeline)(struct timeline *tl);
|
2005-08-05 19:57:47 +00:00
|
|
|
} demuxer_desc_t;
|
|
|
|
|
2008-04-24 02:49:44 +00:00
|
|
|
typedef struct demux_chapter
|
2006-08-06 18:55:34 +00:00
|
|
|
{
|
2013-04-12 11:20:37 +00:00
|
|
|
int original_index;
|
2014-11-02 16:20:04 +00:00
|
|
|
double pts;
|
2013-09-08 05:42:05 +00:00
|
|
|
struct mp_tags *metadata;
|
|
|
|
uint64_t demuxer_id; // for mapping to internal demuxer data structures
|
2006-08-06 18:55:34 +00:00
|
|
|
} demux_chapter_t;
|
|
|
|
|
2014-01-22 23:54:08 +00:00
|
|
|
struct demux_edition {
|
|
|
|
uint64_t demuxer_id;
|
|
|
|
bool default_edition;
|
|
|
|
struct mp_tags *metadata;
|
|
|
|
};
|
|
|
|
|
2013-10-07 00:49:12 +00:00
|
|
|
struct matroska_segment_uid {
|
|
|
|
unsigned char segment[16];
|
|
|
|
uint64_t edition;
|
|
|
|
};
|
|
|
|
|
2009-03-16 21:30:48 +00:00
|
|
|
struct matroska_data {
|
2013-10-07 00:49:12 +00:00
|
|
|
struct matroska_segment_uid uid;
|
2009-03-16 21:30:48 +00:00
|
|
|
// Ordered chapter information if any
|
|
|
|
struct matroska_chapter {
|
|
|
|
uint64_t start;
|
|
|
|
uint64_t end;
|
|
|
|
bool has_segment_uid;
|
2013-10-07 00:49:12 +00:00
|
|
|
struct matroska_segment_uid uid;
|
2009-04-02 02:00:22 +00:00
|
|
|
char *name;
|
2009-03-16 21:30:48 +00:00
|
|
|
} *ordered_chapters;
|
|
|
|
int num_ordered_chapters;
|
|
|
|
};
|
|
|
|
|
2014-03-25 10:46:10 +00:00
|
|
|
struct replaygain_data {
|
|
|
|
float track_gain;
|
|
|
|
float track_peak;
|
|
|
|
float album_gain;
|
|
|
|
float album_peak;
|
|
|
|
};
|
|
|
|
|
2008-04-24 02:49:44 +00:00
|
|
|
typedef struct demux_attachment
|
2008-01-12 01:12:36 +00:00
|
|
|
{
|
2011-02-10 10:05:26 +00:00
|
|
|
char *name;
|
|
|
|
char *type;
|
|
|
|
void *data;
|
|
|
|
unsigned int data_size;
|
2008-01-12 01:12:36 +00:00
|
|
|
} demux_attachment_t;
|
|
|
|
|
2011-08-04 05:38:39 +00:00
|
|
|
struct demuxer_params {
|
2015-02-20 20:21:14 +00:00
|
|
|
char *force_format;
|
2013-09-26 06:22:06 +00:00
|
|
|
int matroska_num_wanted_uids;
|
2013-10-07 00:49:12 +00:00
|
|
|
struct matroska_segment_uid *matroska_wanted_uids;
|
2013-04-14 00:49:07 +00:00
|
|
|
int matroska_wanted_segment;
|
|
|
|
bool *matroska_was_valid;
|
Rewrite ordered chapters and timeline stuff
This uses a different method to piece segments together. The old
approach basically changes to a new file (with a new start offset) any
time a segment ends. This meant waiting for audio/video end on segment
end, and then changing to the new segment all at once. It had a very
weird impact on the playback core, and some things (like truly gapless
segment transitions, or frame backstepping) just didn't work.
The new approach adds the demux_timeline pseudo-demuxer, which presents
an uniform packet stream from the many segments. This is pretty similar
to how ordered chapters are implemented everywhere else. It also reminds
of the FFmpeg concat pseudo-demuxer.
The "pure" version of this approach doesn't work though. Segments can
actually have different codec configurations (different extradata), and
subtitles are most likely broken too. (Subtitles have multiple corner
cases which break the pure stream-concatenation approach completely.)
To counter this, we do two things:
- Reinit the decoder with each segment. We go as far as allowing
concatenating files with completely different codecs for the sake
of EDL (which also uses the timeline infrastructure). A "lighter"
approach would try to make use of decoder mechanism to update e.g.
the extradata, but that seems fragile.
- Clip decoded data to segment boundaries. This is equivalent to
normal playback core mechanisms like hr-seek, but now the playback
core doesn't need to care about these things.
These two mechanisms are equivalent to what happened in the old
implementation, except they don't happen in the playback core anymore.
In other words, the playback core is completely relieved from timeline
implementation details. (Which honestly is exactly what I'm trying to
do here. I don't think ordered chapter behavior deserves improvement,
even if it's bad - but I want to get it out from the playback core.)
There is code duplication between audio and video decoder common code.
This is awful and could be shareable - but this will happen later.
Note that the audio path has some code to clip audio frames for the
purpose of codec preroll/gapless handling, but it's not shared as
sharing it would cause more pain than it would help.
2016-02-15 20:04:07 +00:00
|
|
|
struct timeline *timeline;
|
2015-08-03 23:01:09 +00:00
|
|
|
// -- demux_open_url() only
|
|
|
|
int stream_flags;
|
|
|
|
bool allow_capture;
|
|
|
|
bool disable_cache;
|
|
|
|
// result
|
|
|
|
bool demuxer_failed;
|
2011-08-04 05:38:39 +00:00
|
|
|
};
|
|
|
|
|
2008-04-24 02:49:44 +00:00
|
|
|
typedef struct demuxer {
|
2011-02-10 10:05:26 +00:00
|
|
|
const demuxer_desc_t *desc; ///< Demuxer description structure
|
2011-05-04 20:12:55 +00:00
|
|
|
const char *filetype; // format name when not identified by demuxer (libavformat)
|
2012-11-18 19:46:12 +00:00
|
|
|
int64_t filepos; // input stream current pos.
|
2013-07-12 19:58:11 +00:00
|
|
|
char *filename; // same as stream->url
|
2015-01-26 12:46:33 +00:00
|
|
|
bool seekable;
|
2016-03-03 14:30:55 +00:00
|
|
|
bool partially_seekable; // true if _maybe_ seekable; implies seekable=true
|
2014-07-05 14:54:49 +00:00
|
|
|
double start_time;
|
2013-03-01 12:20:33 +00:00
|
|
|
// File format allows PTS resets (even if the current file is without)
|
|
|
|
bool ts_resets_possible;
|
2015-02-18 20:10:43 +00:00
|
|
|
// The file data was fully read, and there is no need to keep the stream
|
|
|
|
// open, keep the cache active, or to run the demuxer thread. Generating
|
|
|
|
// packets is not slow either (unlike e.g. libavdevice pseudo-demuxers).
|
|
|
|
// Typical examples: text subtitles, playlists
|
|
|
|
bool fully_read;
|
2016-08-26 10:31:09 +00:00
|
|
|
bool is_network; // opened directly from a network stream
|
2001-04-23 16:12:21 +00:00
|
|
|
|
2014-07-05 14:45:56 +00:00
|
|
|
// Bitmask of DEMUX_EVENT_*
|
|
|
|
int events;
|
|
|
|
|
2014-01-22 23:54:08 +00:00
|
|
|
struct demux_edition *editions;
|
2012-08-25 23:19:42 +00:00
|
|
|
int num_editions;
|
|
|
|
int edition;
|
2011-12-31 12:20:08 +00:00
|
|
|
|
2011-02-10 10:05:26 +00:00
|
|
|
struct demux_chapter *chapters;
|
|
|
|
int num_chapters;
|
|
|
|
|
|
|
|
struct demux_attachment *attachments;
|
|
|
|
int num_attachments;
|
2008-01-12 01:12:36 +00:00
|
|
|
|
2009-03-16 21:30:48 +00:00
|
|
|
struct matroska_data matroska_data;
|
|
|
|
|
2013-08-25 18:40:21 +00:00
|
|
|
// If the file is a playlist file
|
|
|
|
struct playlist *playlist;
|
|
|
|
|
2013-09-08 04:32:48 +00:00
|
|
|
struct mp_tags *metadata;
|
2014-07-05 14:45:56 +00:00
|
|
|
|
2011-02-10 10:05:26 +00:00
|
|
|
void *priv; // demuxer-specific internal data
|
2013-12-21 19:24:20 +00:00
|
|
|
struct mpv_global *global;
|
2013-12-21 20:55:41 +00:00
|
|
|
struct mp_log *log, *glog;
|
2011-08-04 05:38:39 +00:00
|
|
|
struct demuxer_params *params;
|
2014-07-16 20:40:21 +00:00
|
|
|
|
2016-08-12 19:39:32 +00:00
|
|
|
// internal to demux.c
|
|
|
|
struct demux_internal *in;
|
|
|
|
struct mp_tags **update_stream_tags;
|
|
|
|
int num_update_stream_tags;
|
2014-07-16 20:40:21 +00:00
|
|
|
|
|
|
|
// Since the demuxer can run in its own thread, and the stream is not
|
|
|
|
// thread-safe, only the demuxer is allowed to access the stream directly.
|
|
|
|
// You can freely use demux_stream_control() to send STREAM_CTRLs, or use
|
|
|
|
// demux_pause() to get exclusive access to the stream.
|
2016-08-26 11:05:14 +00:00
|
|
|
// Also note that the stream can get replaced if fully_read is set.
|
2014-07-16 20:40:21 +00:00
|
|
|
struct stream *stream;
|
2001-04-23 16:12:21 +00:00
|
|
|
} demuxer_t;
|
|
|
|
|
2006-11-18 14:31:31 +00:00
|
|
|
typedef struct {
|
2011-02-10 10:05:26 +00:00
|
|
|
int progid; //program id
|
|
|
|
int aid, vid, sid; //audio, video and subtitle id
|
2006-11-18 14:31:31 +00:00
|
|
|
} demux_program_t;
|
|
|
|
|
2011-02-10 10:05:26 +00:00
|
|
|
void free_demuxer(struct demuxer *demuxer);
|
2015-02-20 20:08:10 +00:00
|
|
|
void free_demuxer_and_stream(struct demuxer *demuxer);
|
2001-04-23 16:12:21 +00:00
|
|
|
|
2015-10-17 12:27:55 +00:00
|
|
|
void demux_add_packet(struct sh_stream *stream, demux_packet_t *dp);
|
2015-12-22 01:35:15 +00:00
|
|
|
void demuxer_feed_caption(struct sh_stream *stream, demux_packet_t *dp);
|
2013-07-11 17:10:33 +00:00
|
|
|
|
|
|
|
struct demux_packet *demux_read_packet(struct sh_stream *sh);
|
2014-07-18 13:08:05 +00:00
|
|
|
int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt);
|
2014-07-06 17:02:21 +00:00
|
|
|
bool demux_stream_is_selected(struct sh_stream *stream);
|
2013-07-11 17:10:33 +00:00
|
|
|
bool demux_has_packet(struct sh_stream *sh);
|
2014-07-05 14:57:56 +00:00
|
|
|
struct demux_packet *demux_read_any_packet(struct demuxer *demuxer);
|
2001-04-23 16:12:21 +00: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 20:44:53 +00:00
|
|
|
struct sh_stream *demux_get_stream(struct demuxer *demuxer, int index);
|
|
|
|
int demux_get_num_stream(struct demuxer *demuxer);
|
|
|
|
|
|
|
|
struct sh_stream *demux_alloc_sh_stream(enum stream_type type);
|
|
|
|
void demux_add_sh_stream(struct demuxer *demuxer, struct sh_stream *sh);
|
2013-07-11 17:35:09 +00:00
|
|
|
|
2015-02-20 20:21:14 +00:00
|
|
|
struct demuxer *demux_open(struct stream *stream, struct demuxer_params *params,
|
2013-12-21 19:24:20 +00:00
|
|
|
struct mpv_global *global);
|
2011-08-04 05:38:39 +00:00
|
|
|
|
2015-02-20 20:56:55 +00:00
|
|
|
struct mp_cancel;
|
|
|
|
struct demuxer *demux_open_url(const char *url,
|
|
|
|
struct demuxer_params *params,
|
|
|
|
struct mp_cancel *cancel,
|
|
|
|
struct mpv_global *global);
|
|
|
|
|
2014-07-16 20:40:21 +00:00
|
|
|
void demux_start_thread(struct demuxer *demuxer);
|
|
|
|
void demux_stop_thread(struct demuxer *demuxer);
|
|
|
|
void demux_set_wakeup_cb(struct demuxer *demuxer, void (*cb)(void *ctx), void *ctx);
|
|
|
|
|
2015-03-09 21:32:04 +00:00
|
|
|
bool demux_cancel_test(struct demuxer *demuxer);
|
|
|
|
|
2011-02-10 10:05:26 +00:00
|
|
|
void demux_flush(struct demuxer *demuxer);
|
2014-10-29 21:47:25 +00:00
|
|
|
int demux_seek(struct demuxer *demuxer, double rel_seek_secs, int flags);
|
2015-11-16 21:47:17 +00:00
|
|
|
void demux_set_ts_offset(struct demuxer *demuxer, double offset);
|
2001-04-23 16:12:21 +00:00
|
|
|
|
2011-02-10 10:05:26 +00:00
|
|
|
int demux_control(struct demuxer *demuxer, int cmd, void *arg);
|
2002-03-03 18:47:29 +00:00
|
|
|
|
2013-07-11 17:22:24 +00:00
|
|
|
void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream,
|
player: improve instant track switching
When switching tracks, we normally have the problem that data gets lost
due to readahead buffering. (Which in turn is because we're stubborn and
instruct the demuxers to discard data on unselected streams.) The
demuxer layer has a hack that re-reads discarded buffered data if a
stream is enabled mid-stream, so track switching will seem instant.
A somewhat similar problem is when all tracks of an external files were
disabled - when enabling the first track, we have to seek to the target
position.
Handle these with the same mechanism. Pass the "current time" to the
demuxer's stream switch function, and let the demuxer figure out what to
do. The demuxer will issue a refresh seek (if possible) to update the
new stream, or will issue a "normal" seek if there was no active stream
yet.
One case that changes is when a video/audio stream is enabled on an
external file with only a subtitle stream active, and the demuxer does
not support rrefresh seeks. This is a fuzzy case, because subtitles are
sparse, and the demuxer might have skipped large amounts of data. We
used to seek (and send the subtitle decoder some subtitle packets
twice). This case is sort of obscure and insane, and the fix would be
questionable, so we simply don't care.
Should mostly fix #3392.
2016-08-06 13:47:04 +00:00
|
|
|
double ref_pts, bool selected);
|
2014-07-16 20:40:21 +00:00
|
|
|
void demux_set_stream_autoselect(struct demuxer *demuxer, bool autoselect);
|
2003-01-19 00:21:54 +00:00
|
|
|
|
2013-12-21 19:24:20 +00:00
|
|
|
void demuxer_help(struct mp_log *log);
|
2006-08-06 18:55:34 +00:00
|
|
|
|
2015-06-24 12:18:51 +00:00
|
|
|
int demuxer_add_attachment(struct demuxer *demuxer, char *name,
|
|
|
|
char *type, void *data, size_t data_size);
|
|
|
|
int demuxer_add_chapter(demuxer_t *demuxer, char *name,
|
2014-11-02 16:20:04 +00:00
|
|
|
double pts, uint64_t demuxer_id);
|
2016-08-12 19:39:32 +00:00
|
|
|
void demux_set_stream_tags(struct demuxer *demuxer, struct sh_stream *sh,
|
|
|
|
struct mp_tags *tags);
|
2006-08-06 18:55:34 +00:00
|
|
|
|
2013-05-03 18:07:04 +00:00
|
|
|
double demuxer_get_time_length(struct demuxer *demuxer);
|
|
|
|
|
2014-07-16 20:40:21 +00:00
|
|
|
int demux_stream_control(demuxer_t *demuxer, int ctrl, void *arg);
|
|
|
|
|
2016-03-09 22:55:16 +00:00
|
|
|
void demux_run_on_thread(struct demuxer *demuxer, void (*fn)(void *), void *ctx);
|
2014-07-16 20:40:21 +00:00
|
|
|
|
|
|
|
void demux_changed(demuxer_t *demuxer, int events);
|
|
|
|
void demux_update(demuxer_t *demuxer);
|
|
|
|
|
2012-08-19 16:01:30 +00:00
|
|
|
struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d,
|
|
|
|
enum stream_type t, int id);
|
2008-03-30 16:55:46 +00:00
|
|
|
|
2014-11-02 16:20:04 +00:00
|
|
|
struct demux_chapter *demux_copy_chapter_data(struct demux_chapter *c, int num);
|
|
|
|
|
2013-10-07 00:49:12 +00:00
|
|
|
bool demux_matroska_uid_cmp(struct matroska_segment_uid *a,
|
|
|
|
struct matroska_segment_uid *b);
|
|
|
|
|
2014-02-15 15:48:56 +00:00
|
|
|
const char *stream_type_name(enum stream_type type);
|
|
|
|
|
2008-02-22 09:09:46 +00:00
|
|
|
#endif /* MPLAYER_DEMUXER_H */
|