/* * 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"enumdemux_ctrl{DEMUXER_CTRL_SWITCHED_TRACKS=1,DEMUXER_CTRL_RESYNC,DEMUXER_CTRL_IDENTIFY_PROGRAM,DEMUXER_CTRL_STREAM_CTRL,DEMUXER_CTRL_GET_READER_STATE,DEMUXER_CTRL_GET_BITRATE_STATS,// double[STREAM_TYPE_COUNT]DEMUXER_CTRL_REPLACE_STREAM,};#define MAX_SEEK_RANGES 10structdemux_seek_range{doublestart,end;};structdemux_ctrl_reader_state{booleof,underrun,idle;doublets_duration;doublets_reader;// approx. timerstamp of decoder positiondoublets_end;// approx. timestamp of end of buffered rangeint64_ttotal_bytes;int64_tfw_bytes;doubleseeking;// current low level seek target, or NOPTSintlow_level_seeks;// number of started low level seeksdoublets_last;// approx. timestamp of demuxer position// Positions that can be seeked to without incurring the latency of a low// level seek.intnum_seek_ranges;structdemux_seek_rangeseek_ranges[MAX_SEEK_RANGES];};structdemux_ctrl_stream_ctrl{intctrl;void*arg;intres;};#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_HR (1 << 5) // hr-seek (this is a weak hint only)// 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.enumdemux_check{DEMUX_CHECK_FORCE,// force format if possibleDEMUX_CHECK_UNSAFE,// risky/fuzzy detectionDEMUX_CHECK_REQUEST,// requested by user or stream implementationDEMUX_CHECK_NORMAL,// normal, safe detection};enumdemux_event{DEMUX_EVENT_INIT=1<<0,// complete (re-)initializationDEMUX_EVENT_STREAMS=1<<1,// a stream was addedDEMUX_EVENT_METADATA=1<<2,// metadata or stream_metadata changedDEMUX_EVENT_DURATION=1<<3,// duration updatedDEMUX_EVENT_ALL=0xFFFF,};structdemuxer;structtimeline;/** * Demuxer description structure */typedefstructdemuxer_desc{constchar*name;// Demuxer name, used with -demuxer switchconstchar*desc;// Displayed to user// Return 0 on success, otherwise -1int(*open)(structdemuxer*demuxer,enumdemux_checkcheck);// The following functions are all optionalint(*fill_buffer)(structdemuxer*demuxer);// 0 on EOF, otherwise 1void(*close)(structdemuxer*demuxer);void(*seek)(structdemuxer*demuxer,doublerel_seek_secs,intflags);int(*control)(structdemuxer*demuxer,intcmd,void*arg);// See timeline.cvoid(*load_timeline)(structtimeline*tl);}demuxer_desc_t;typedefstructdemux_chapter{intoriginal_index;doublepts;structmp_tags*metadata;uint64_tdemuxer_id;// for mapping to internal demuxer data structures}demux_chapter_t;structdemux_edition{uint64_tdemuxer_id;booldefault_edition;structmp_tags*metadata;};structmatroska_segment_uid{unsignedcharsegment[16];uint64_tedition;};structmatroska_data{structmatroska_segment_uiduid;// Ordered chapter information if anystructmatroska_chapter{uint64_tstart;uint64_tend;boolhas_segment_uid;structmatroska_segment_uiduid;char*name;}*ordered_chapters;intnum_ordered_chapters;};structreplaygain_data{floattrack_gain;floattrack_peak;floatalbum_gain;floatalbum_peak;};typedefstructdemux_attachment{char*name;char*type;void*data;unsignedintdata_size;}demux_attachment_t;structdemuxer_params{char*force_format;intmatroska_num_wanted_uids;structmatroska_segment_uid*matroska_wanted_uids;intmatroska_wanted_segment;bool*matroska_was_valid;structtimeline*timeline;booldisable_timeline;boolinitial_readahead;bstrinit_fragment;boolskip_lavf_probing;// -- demux_open_url() onlyintstream_flags;booldisable_cache;// resultbooldemuxer_failed;};typedefstructdemuxer{constdemuxer_desc_t*desc;///< Demuxer description structureconstchar*filetype;// format name when not identified by demuxer (libavformat)int64_tfilepos;// input stream current pos.char*filename;// same as stream->urlboolseekable;boolpartially_seekable;// true if _maybe_ seekable; implies seekable=truedoublestart_time;doubleduration;// -1 if unknown// File format allows PTS resets (even if the current file is without)boolts_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, playlistsboolfully_read;boolis_network;// opened directly from a network streamboolaccess_references;// allow opening other files/URLs// Bitmask of DEMUX_EVENT_*intevents;structdemux_edition*editions;intnum_editions;intedition;structdemux_chapter*chapters;intnum_chapters;structdemux_attachment*attachments;intnum_attachments;structmatroska_datamatroska_data;// If the file is a playlist filestructplaylist*playlist;structmp_tags*metadata;void*priv;// demuxer-specific internal datastructmpv_global*global;structmp_log*log,*glog;structdemuxer_params*params;// internal to demux.cstructdemux_internal*in;structmp_tags**update_stream_tags;intnum_update_stream_tags;// 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.// Also note that the stream can get replaced if fully_read is set.structstream*stream;}demuxer_t;typedefstruct{intprogid;//program idintaid,vid,sid;//audio, video and subtitle id}demux_program_t;voidfree_demuxer(structdemuxer*demuxer);voidfree_demuxer_and_stream(structdemuxer*demuxer);voiddemux_add_packet(structsh_stream*stream,demux_packet_t*dp);voiddemuxer_feed_caption(structsh_stream*stream,demux_packet_t*dp);structdemux_packet*demux_read_packet(structsh_stream*sh);intdemux_read_packet_async(structsh_stream*sh,structdemux_packet**out_pkt);booldemux_stream_is_selected(structsh_stream*stream);booldemux_has_packet(structsh_stream*sh);structdemux_packet*demux_read_any_packet(structdemuxer*demuxer);structsh_stream*demux_get_stream(structdemuxer*demuxer,intindex);intdemux_get_num_stream(structdemuxer*demuxer);structsh_stream*demux_alloc_sh_stream(enumstream_typetype);voiddemux_add_sh_stream(structdemuxer*demuxer,structsh_stream*sh);structdemuxer*demux_open(structstream*stream,structdemuxer_params*params,structmpv_global*global);structmp_cancel;structdemuxer*demux_open_url(constchar*url,structdemuxer_params*params,structmp_cancel*cancel,structmpv_global*global);voiddemux_start_thread(structdemuxer*demuxer);voiddemux_stop_thread(structdemuxer*demuxer);voiddemux_set_wakeup_cb(structdemuxer*demuxer,void(*cb)(void*ctx),void*ctx);booldemux_cancel_test(structdemuxer*demuxer);voiddemux_flush(structdemuxer*demuxer);intdemux_seek(structdemuxer*demuxer,doublerel_seek_secs,intflags);voiddemux_set_ts_offset(structdemuxer*demuxer,doubleoffset);intdemux_control(structdemuxer*demuxer,intcmd,void*arg);voiddemux_block_reading(structdemuxer*demuxer,boolblock);voiddemuxer_select_track(structdemuxer*demuxer,structsh_stream*stream,doubleref_pts,boolselected);voiddemux_set_stream_autoselect(structdemuxer*demuxer,boolautoselect);voiddemuxer_help(structmp_log*log);intdemuxer_add_attachment(structdemuxer*demuxer,char*name,char*type,void*data,size_tdata_size);intdemuxer_add_chapter(demuxer_t*demuxer,char*name,doublepts,uint64_tdemuxer_id);voiddemux_set_stream_tags(structdemuxer*demuxer,structsh_stream*sh,structmp_tags*tags);intdemux_stream_control(demuxer_t*demuxer,intctrl,void*arg);voiddemux_changed(demuxer_t*demuxer,intevents);voiddemux_update(demuxer_t*demuxer);voiddemux_disable_cache(demuxer_t*demuxer);structsh_stream*demuxer_stream_by_demuxer_id(structdemuxer*d,enumstream_typet,intid);structdemux_chapter*demux_copy_chapter_data(structdemux_chapter*c,intnum);booldemux_matroska_uid_cmp(structmatroska_segment_uid*a,structmatroska_segment_uid*b);constchar*stream_type_name(enumstream_typetype);#endif /* MPLAYER_DEMUXER_H */