summaryrefslogtreecommitdiffstats
path: root/DOCS/tech-overview.txt
blob: fd6a7a1fb7cdac527dbcac72d70093a941fe9e7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
This file intends to give a big picture overview of how mpv is structured.

player/*.c:
    Essentially makes up the player applications, including the main() function
    and the playback loop.

    Generally, it accesses all other subsystems, initializes them, and pushes
    data between them during playback.

    The structure is as follows (as of commit e13c05366557cb):
    * main():
        * basic initializations (e.g. init_libav() and more)
        * pre-parse command line (verbosity level, config file locations)
        * load config files (parse_cfgfiles())
        * parse command line, add files from the command line to playlist
          (m_config_parse_mp_command_line())
        * check help options etc. (call handle_help_options()), possibly exit
        * call play_files() function that works down the playlist:
            * run idle loop (idle_loop()), until there are files in the
                playlist or an exit command was given (only if --idle it set)
            * actually load and play a file in play_current_file():
                * run all the dozens of functions to load the file and
                  initialize playback
                * run a small loop that does normal playback, until the file is
                  done or a command terminates playback
                  (on each iteration, run_playloop() is called, which is rather
                   big and complicated - it decodes some audio and video on
                   each frame, waits for input, etc.)
                * uninitialize playback
            * determine next entry on the playlist to play
            * loop, or exit if no next file or quit is requested
              (see enum stop_play_reason)
        * call exit_player_with_rc()
    * run_playloop():
        * calls fill_audio_out_buffers()
            This checks whether new audio needs to be decoded, and pushes it
            to the AO.
        * calls write_video()
            Decode new video, and push it to the VO.
        * determines whether playback of the current file has ended
        * determines when to start playback after seeks
        * and calls a whole lot of other stuff
            (Really, this function does everything.)

    Things worth saying about the playback core:
    - most state is in MPContext (core.h), which is not available to the
      subsystems
    - the currently played tracks are in mpctx->current_tracks, and decoder
      state in d_video/d_audio/d_sub
    - the timeline stuff is used only with MKV ordered chapters (and some other
      minor features: cue, edl)
    - the other subsystems rarely call back into the frontend, and the frontend
      polls them instead (probably a good thing)
    - one exceptions are wakeup callbacks, which notify a "higher" component
      of a changed situation in a subsystem

    I like to call the player/*.c files the "frontend".

talloc.h & talloc.c:
    Hierarchical memory manager copied from Samba. It's like a malloc() with
    more features. Most importantly, each talloc allocation can have a parent,
    and if the parent is free'd, all children will be free'd as well. The
    parent is an arbitrary talloc allocation. It's either set by the allocation
    call by passing a talloc parent, usually as first argument to the allocation
    function. It can also be set or reset later by other calls (at least
    talloc_steal()). A talloc allocation that is used as parent is often called
    a talloc context.

    Lots of code still uses malloc() proper, and you should be careful what
    type of allocation you're dealing with when returning or free'ing an
    allocation. (Needless to say, talloc_free() and free() are completely
    different things.)

    The copy in mpv has been modified to abort on OOM conditions. An
    allocation call will never return NULL.

    One very useful feature of talloc is fast tracking of memory leaks. ("Fast"
    as in it doesn't require valgrind.) You can enable it by passing the option
    --leak-report as first parameter, or better, setting the
    MPV_LEAK_REPORT environment variable to "1":
        export MPV_LEAK_REPORT=1
    This will list all unfree'd allocations on exit.

    Documentation can be found here:
        http://git.samba.org/?p=samba.git;a=blob;f=lib/talloc/talloc.h;hb=HEAD

    Note: unlike tcmalloc, jemalloc, etc., talloc() is not actually a malloc
          replacement. It works on top of system malloc and provides additional
          features that are supposed to make memory management easier.

    Warning: actually, we're not using talloc anymore. talloc in mpv has been
             replaced by a custom re-implementation (TA in ta/). It provides
             some talloc emulation (just the parts needed by mpv). We will get
             rid of the talloc emulation later and use TA natively.
             (See ta/README for details.)

player/command.c:
    This contains the implementation for client API commands and properties.
    Properties are essentially dynamic variables changed by certain commands.
    This is basically responsible for all user commands, like initiating
    seeking, switching tracks, etc. It calls into other player/*.c files,
    where most of the work is done, but also calls other parts of mpv.

player/core.h:
    Data structures and function prototypes for most of player/*.c. They are
    usually not accessed by other parts of mpv for the sake of modularization.

player/client.c:
    This implements the client API (libmpv/client.h). For the most part, this
    just calls into other parts of the player. This also manages a ringbuffer
    of events from player to clients.

options/options.h, options/options.c
    options.h contains the global option struct MPOpts. The option declarations
    (option names, types, and MPOpts offsets for the option parser) are in
    options.c. Most default values for options and MPOpts are in
    mp_default_opts at the end of options.c.

    MPOpts is unfortunately quite monolithic, and virtually accessed by
    everything.But some components (like video outputs and video filters) have
    their own sub-option tables separate from MPOpts.

    The actual option parser is spread over m_option.c, m_config.c, and
    parser-mpcmd.c, and uses the option table in options.c.

input/input.c:
    This translates keyboard input comming from VOs and other sources (such
    as remote control devices like Apple IR or client API commands) to the
    key bindings listed in the user's (or the builtin) input.conf and turns
    them into items of type struct mp_cmd. These commands are queued, and read
    by playloop.c. They get pushed with run_command() to command.c.

    Note that keyboard input and commands used by the client API are the same.
    The client API only uses the command parser though, and has its own queue
    of input commands somewhere else.

common/msg.h:
    All terminal output must go through mp_msg().

stream/*:
    File input is implemented here. stream.h/.c provides a simple stream based
    interface (like reading a number of bytes at a given offset). mpv can
    also play from http streams and such, which is implemented here.

    E.g. if mpv sees "http://something" on the command line, it will pick
    stream_lavf.c based on the prefix, and pass the rest of the filename to it.

    Some stream inputs are quite special: stream_dvd.c turns DVDs into mpeg
    streams (DVDs are actually a bunch of vob files etc. on a filesystem),
    stream_tv.c provides TV input including channel switching.

    Some stream inputs are just there to invoke special demuxers, like
    stream_mf.c. (Basically to make the prefix "mf://" do something special.)

    cache.c is a caching wrapper around streams implementations, needed for
    smooth network playback.

demux/:
    Demuxers split data streams into audio/video/sub streams, which in turn
    are split in packets. Packets (see demux_packet.h) are mostly byte chunks
    tagged with a playback time (PTS). These packets are passed to the decoders.

    Most demuxers have been removed from this fork, and the only important and
    "actual" demuxers left are demux_mkv.c and demux_lavf.c (uses libavformat).
    There are some pseudo demuxers like demux_cue.c, which exist only to invoke
    other frontend code (tl_cue.c in this case).

    The main interface is in demux.h. The stream headers are in stheader.h.
    There is a stream header for each audio/video/sub stream, and each of them
    holds codec information about the stream and other information.

video/:
    This contains several things related to audio/video decoding, as well as
    video filters.

    mp_image.h and img_format.h define how mpv stores decoded video frames
    internally.

video/decode/:
    vd_*.c are video decoders. (There's only vd_lavc.c left.) dec_video.c/vd.c
    handle most of connecting the frontend with the actual decoder.

video/filter/:
    vf_*.c and vf.c form the video filter chain. They are fed by the video
    decoder, and output the filtered images to the VOs though vf_vo.c. By
    default, no video filters (except vf_vo) are used. vf_scale is automatically
    inserted if the video output can't handle the video format used by the
    decoder.

video/out/:
    Video output. They also create GUI windows and handle user input. In most
    cases, the windowing code is shared among VOs, like x11_common.c for X11 and
    w32_common.c for Windows. The VOs stand between frontend and windowing code.
    vo_opengl can pick a windowing system at runtime, e.g. the same binary can
    provide both X11 and Cocoa support on OSX.

    VOs can be reconfigured at runtime. A vo_config() call can change the video
    resolution and format, without destroying the window.

    vo_vdpau and vo_opengl should be taken as reference.

audio/:
    format.h/format.c define the uncompressed audio formats. (As well as some
    compressed formats used for spdif.)

audio/decode/:
    ad_*.c and dec_audio.c/ad.c handle audio decoding. ad_lavc.c is the
    decoder using ffmpeg. ad_spdif.c is not really a decoder, but is used for
    compressed audio passthrough.

audio/filter/:
    Audio filter chain. af_lavrresample is inserted if any form of conversion
    between audio formats is needed. (af_convert24.c and af_convertsignendian.c
    are also used for some formats not directly supported by FFmpeg.)

audio/out/:
    Audio outputs.

    Unlike VOs, AOs can't be reconfigured on a format change. On audio format
    changes, the AO will simply be closed and re-opened.

    There are wrappers to support for two types of audio APIs: push.c and
    pull.c. ao.c calls into one of these. They contain generic code to deal
    with the data flow these APIs impose.

    Note that mpv synchronizes the video to the audio. That's the reason
    why buggy audio drivers can have a bad influence on playback quality.

sub/:
    Contains subtitle and OSD rendering.

    osd.c/.h is actually the OSD code. It queries dec_sub.c to retrieve
    decoded/rendered subtitles. osd_libass.c is the actual implementation of
    the OSD text renderer (which uses libass, and takes care of all the tricky
    fontconfig/freetype API usage and text layouting).

    The VOs call osd.c to render OSD and subtitle (via e.g. osd_draw()). osd.c
    in turn asks dec_sub.c for subtitle overlay bitmaps, which relays the
    request to one of the sd_*.c subtitle decoders/renderers.

    Subtitle loading is in demux/. The MPlayer subreader.c is mostly gone - parts
    of it survive in demux_subreader.c. It's used as last fallback, or to handle
    some text subtitle types on Libav. It should go away eventually. Normally,
    subtitles are loaded via demux_lavf.c.

    The subtitles are passed to dec_sub.c and the subtitle decoders in sd_*.c
    as they are demuxed. All text subtitles are rendered by sd_ass.c. If text
    subtitles are not in the ASS format, subtitle converters are inserted, for
    example sd_srt.c, which is used to convert SRT->ASS. sd_srt.c is also used
    as general converter for text->ASS (to prevent interpretation of text as
    ASS tags).

    Text subtitles can be preloaded, in which case they are read fully as soon
    as the subtitle is selected, and then effectively stored in an ASS_Track.
    It's used for external text subtitles, and required to make codepage
    detection as well as timing postprocessing work. (Timing postprocessing
    removes tiny gaps or overlaps between subtitle events.)

player/timeline/:
    A timeline is the abstraction used by loadfile.c to combine several files
    into one seemingly linear video. It's mainly used for ordered chapters
    playback. The high level code to find and load other files containing the
    segments for playing an ordered chapters file is in tl_matroska.c.

etc/:
    The file input.conf is actually integrated into the mpv binary by the
    build system. It contains the default keybindings.