diff options
Diffstat (limited to 'demux/demux.h')
-rw-r--r-- | demux/demux.h | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/demux/demux.h b/demux/demux.h new file mode 100644 index 0000000..08904f2 --- /dev/null +++ b/demux/demux.h @@ -0,0 +1,361 @@ +/* + * This file is part of mpv. + * + * 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. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef MPLAYER_DEMUXER_H +#define MPLAYER_DEMUXER_H + +#include <sys/types.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#include "misc/bstr.h" +#include "common/common.h" +#include "common/tags.h" +#include "packet.h" +#include "stheader.h" + +#define MAX_SEEK_RANGES 10 + +struct demux_seek_range { + double start, end; +}; + +struct demux_reader_state { + bool eof, underrun, idle; + bool bof_cached, eof_cached; + double ts_duration; + double ts_reader; // approx. timerstamp of decoder position + double ts_end; // approx. timestamp of end of buffered range + int64_t total_bytes; + int64_t fw_bytes; + int64_t file_cache_bytes; + double seeking; // current low level seek target, or NOPTS + int low_level_seeks; // number of started low level seeks + uint64_t byte_level_seeks; // number of byte stream level seeks + double ts_last; // approx. timestamp of demuxer position + uint64_t bytes_per_second; // low level statistics + // Positions that can be seeked to without incurring the latency of a low + // level seek. + int num_seek_ranges; + struct demux_seek_range seek_ranges[MAX_SEEK_RANGES]; +}; + +extern const struct m_sub_options demux_conf; + +struct demux_opts { + int enable_cache; + bool disk_cache; + int64_t max_bytes; + int64_t max_bytes_bw; + bool donate_fw; + double min_secs; + double hyst_secs; + bool force_seekable; + double min_secs_cache; + bool access_references; + int seekable_cache; + int index_mode; + double mf_fps; + char *mf_type; + bool create_ccs; + char *record_file; + int video_back_preroll; + int audio_back_preroll; + int back_batch[STREAM_TYPE_COUNT]; + double back_seek_size; + char *meta_cp; + bool force_retry_eof; +}; + +#define SEEK_FACTOR (1 << 1) // argument is in range [0,1] +#define SEEK_FORWARD (1 << 2) // prefer later time if not exact + // (if unset, prefer earlier time) +#define SEEK_CACHED (1 << 3) // allow packet cache seeks only +#define SEEK_SATAN (1 << 4) // enable backward demuxing +#define SEEK_HR (1 << 5) // hr-seek (this is a weak hint only) +#define SEEK_FORCE (1 << 6) // ignore unseekable flag +#define SEEK_BLOCK (1 << 7) // upon successfully queued seek, block readers + // (simplifies syncing multiple reader threads) + +// 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 +}; + +enum demux_event { + 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_DURATION = 1 << 3, // duration updated + DEMUX_EVENT_ALL = 0xFFFF, +}; + +struct demuxer; +struct timeline; + +/** + * Demuxer description structure + */ +typedef struct demuxer_desc { + const char *name; // Demuxer name, used with -demuxer switch + const char *desc; // Displayed to user + + // If non-NULL, these are added to the global option list. + const struct m_sub_options *options; + + // Return 0 on success, otherwise -1 + int (*open)(struct demuxer *demuxer, enum demux_check check); + // The following functions are all optional + // Try to read a packet. Return false on EOF. If true is returned, the + // demuxer may set *pkt to a new packet (the reference goes to the caller). + // If *pkt is NULL (the value when this function is called), the call + // will be repeated. + bool (*read_packet)(struct demuxer *demuxer, struct demux_packet **pkt); + void (*close)(struct demuxer *demuxer); + void (*seek)(struct demuxer *demuxer, double rel_seek_secs, int flags); + void (*switched_tracks)(struct demuxer *demuxer); + // See timeline.c + void (*load_timeline)(struct timeline *tl); +} demuxer_desc_t; + +typedef struct demux_chapter +{ + int original_index; + double pts; + struct mp_tags *metadata; + uint64_t demuxer_id; // for mapping to internal demuxer data structures +} demux_chapter_t; + +struct demux_edition { + uint64_t demuxer_id; + bool default_edition; + struct mp_tags *metadata; +}; + +struct matroska_segment_uid { + unsigned char segment[16]; + uint64_t edition; +}; + +struct matroska_data { + struct matroska_segment_uid uid; + // Ordered chapter information if any + struct matroska_chapter { + uint64_t start; + uint64_t end; + bool has_segment_uid; + struct matroska_segment_uid uid; + char *name; + } *ordered_chapters; + int num_ordered_chapters; +}; + +struct replaygain_data { + float track_gain; + float track_peak; + float album_gain; + float album_peak; +}; + +typedef struct demux_attachment +{ + char *name; + char *type; + void *data; + unsigned int data_size; +} demux_attachment_t; + +struct demuxer_params { + bool is_top_level; // if true, it's not a sub-demuxer (enables cache etc.) + char *force_format; + int matroska_num_wanted_uids; + struct matroska_segment_uid *matroska_wanted_uids; + int matroska_wanted_segment; + bool *matroska_was_valid; + struct timeline *timeline; + bool disable_timeline; + bstr init_fragment; + bool skip_lavf_probing; + bool stream_record; // if true, enable stream recording if option is set + int stream_flags; + struct stream *external_stream; // if set, use this, don't open or close streams + // result + bool demuxer_failed; +}; + +typedef struct demuxer { + const demuxer_desc_t *desc; ///< Demuxer description structure + const char *filetype; // format name when not identified by demuxer (libavformat) + int64_t filepos; // input stream current pos. + int64_t filesize; + char *filename; // same as stream->url + bool seekable; + bool partially_seekable; // true if _maybe_ seekable; implies seekable=true + double start_time; + double duration; // -1 if unknown + // File format allows PTS resets (even if the current file is without) + bool ts_resets_possible; + // 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; + bool is_network; // opened directly from a network stream + bool is_streaming; // implies a "slow" input, such as network or FUSE + int stream_origin; // any STREAM_ORIGIN_* (set from source stream) + bool access_references; // allow opening other files/URLs + + struct demux_opts *opts; + struct m_config_cache *opts_cache; + + // Bitmask of DEMUX_EVENT_* + int events; + + struct demux_edition *editions; + int num_editions; + int edition; + + struct demux_chapter *chapters; + int num_chapters; + + struct demux_attachment *attachments; + int num_attachments; + + struct matroska_data matroska_data; + + // If the file is a playlist file + struct playlist *playlist; + + struct mp_tags *metadata; + + void *priv; // demuxer-specific internal data + struct mpv_global *global; + struct mp_log *log, *glog; + struct demuxer_params *params; + + // internal to demux.c + struct demux_internal *in; + + // Triggered when ending demuxing forcefully. Usually bound to the stream too. + struct mp_cancel *cancel; + + // 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. + // Also note that the stream can get replaced if fully_read is set. + struct stream *stream; +} demuxer_t; + +void demux_free(struct demuxer *demuxer); +void demux_cancel_and_free(struct demuxer *demuxer); + +struct demux_free_async_state; +struct demux_free_async_state *demux_free_async(struct demuxer *demuxer); +void demux_free_async_force(struct demux_free_async_state *state); +bool demux_free_async_finish(struct demux_free_async_state *state); + +void demuxer_feed_caption(struct sh_stream *stream, demux_packet_t *dp); + +int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt); +int demux_read_packet_async_until(struct sh_stream *sh, double min_pts, + struct demux_packet **out_pkt); +bool demux_stream_is_selected(struct sh_stream *stream); +void demux_set_stream_wakeup_cb(struct sh_stream *sh, + void (*cb)(void *ctx), void *ctx); +struct demux_packet *demux_read_any_packet(struct demuxer *demuxer); + +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); + +struct mp_cancel; +struct demuxer *demux_open_url(const char *url, + struct demuxer_params *params, + struct mp_cancel *cancel, + struct mpv_global *global); + +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); +void demux_start_prefetch(struct demuxer *demuxer); + +bool demux_cancel_test(struct demuxer *demuxer); + +void demux_flush(struct demuxer *demuxer); +int demux_seek(struct demuxer *demuxer, double rel_seek_secs, int flags); +void demux_set_ts_offset(struct demuxer *demuxer, double offset); + +void demux_get_bitrate_stats(struct demuxer *demuxer, double *rates); +void demux_get_reader_state(struct demuxer *demuxer, struct demux_reader_state *r); + +void demux_block_reading(struct demuxer *demuxer, bool block); + +void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream, + double ref_pts, bool selected); +void demuxer_refresh_track(struct demuxer *demuxer, struct sh_stream *stream, + double ref_pts); + +int demuxer_help(struct mp_log *log, const m_option_t *opt, struct bstr name); + +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, + double pts, uint64_t demuxer_id); +void demux_stream_tags_changed(struct demuxer *demuxer, struct sh_stream *sh, + struct mp_tags *tags, double pts); +void demux_close_stream(struct demuxer *demuxer); + +void demux_metadata_changed(demuxer_t *demuxer); +void demux_update(demuxer_t *demuxer, double playback_pts); + +bool demux_cache_dump_set(struct demuxer *demuxer, double start, double end, + char *file); +int demux_cache_dump_get_status(struct demuxer *demuxer); + +double demux_probe_cache_dump_target(struct demuxer *demuxer, double pts, + bool for_end); + +bool demux_is_network_cached(demuxer_t *demuxer); + +void demux_report_unbuffered_read_bytes(struct demuxer *demuxer, int64_t new); +int64_t demux_get_bytes_read_hack(struct demuxer *demuxer); + +struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d, + enum stream_type t, int id); + +struct demux_chapter *demux_copy_chapter_data(struct demux_chapter *c, int num); + +bool demux_matroska_uid_cmp(struct matroska_segment_uid *a, + struct matroska_segment_uid *b); + +const char *stream_type_name(enum stream_type type); + +#endif /* MPLAYER_DEMUXER_H */ |