/** \mainpage MythTV Architecture \section intro Introduction Over the last couple years %MythTV has grown into a rather large application. The purpose of these pages is to provide a portal into the code for developers to get their heads around it. This is intended for both those new to %MythTV and experienced with it to get familiar with different aspects of the code base. If you are just looking for the code formatting standards, see the official %MythTV wiki article coding standards. If you are looking for the bug tracker, it can be found on the official pages. If you haven't already, you should subscribe to the developer mailing list and the SVN commits mailing list If you just stumbled onto the developer pages by accident, maybe you want to go to the official %MythTV Installation page. There is also a good unofficial Fedora %MythTV installation page, and a Gentoo %MythTV installation page. If you are new to Qt programming it is essential that you keep in mind that almost all Qt objects are not thread-safe, including QString. Almost all Qt container objects, including QString, make shallow copies on assignment, the two copies of the object must only be used in one thread unless you use a lock on the object. You can use the QDeepCopy template on most Qt containers to make a copy you can use in another thread. There are also special dangers when \ref qobject_dangers "using QObject" outside the Qt event thread. The is also short HOWTO on \ref profiling_mythtv available in addition to documentation on the code itself. \section libs Libraries %MythTV is divided up into eleven libraries:
libmyth
Core %MythTV library. Used by the Plugins. The \ref database_subsystem "database", \ref audio_subsystem "audio", \ref lcd_subsystem "LCD", \ref osd_subsystem "OSD", \ref lirc_subsystem "LIRC", and the \ref myth_network_protocol "myth network protocol" are supported by libmyth.
libmythtv
%MythTV %TV functionality library. The \ref recorder_subsystem "recorders", \ref video_subsystem "video" and \ref av_player_subsystem "A/V players" are supported by libmythtv.
libmythui
Main user interface rendering library
libavcodec/libavformat/libavutil
This is the ffmpeg A/V decoding library (aka avlib). Documented Externally.
libmythmpeg2
Alternate MPEG-1/2 A/V decoding library. External Website.
libmythsamplerate
Audio resampling library Documented Externally. We use this to support a different output sample rates than the sample rate used in the audio streams we play.
libmythsoundtouch
Pitch preserving audio resampling library. External Website. We use this for the time-stretch feature.
libmythdvdnav
Used for navigating DVD menus when using the internal player
libmythfreemheg
UK interactive %TV viewer
libmythlivemedia
Support for the FreeBox recorder device
libmythupnp
Initial uPnP (universal Plug and Play) support
Two libraries libmythmpeg2 and libmythsamplerate appear redundant, but libmpeg2 decodes MPEG-2 more quickly than ffmpeg on some systems, and libmythsamplerate resamples audio with better quality when we only need to match the hardware sample rate to the A/V streams audio sample rate. \section db Database Schema The database schema is documented here \ref db_schema. \section apps Applications %MythTV contains 14 applications:
mythbackend
This is the backend which runs the recorders.
mythfrontend
This is the frontend which is the main application for viewing programs and using the %MythTV plugins.
mythtv-setup
This is the program which sets up the database to use a machine as a backend server.
mythtv
This was an "External Player" used to play videos from within mythfrontend. Setting the player command to "internal" does the same thing now. This is handy for testing the audio and videoout code, though.
mythtvosd
This is used externally by programs that want to pop-up an on screen display in %MythTV while one is watching a recording.
mythfilldatabase
This is used both internally and externally to fetch program listings. Tribune Media provides listings in exchange for demographic information in the USA, and Australia uses a community-driven TV guide originally developed for OzTiVo. Other markets are served by the XMLTV web spiders.
mythtranscode
This is used both internally and externally to transcode videos from one format to another. This is used to shrink HDTV programs to lower quality recordings that match the hardware the user has.
mythjobqueue
This is used internally by mythfrontend to schedule jobs such as commercial flagging and transcoding.
mythcommflag
This is used internally by mythfrontend to flag commercials.
mythepg
This is used internally by mythfrontend to find upcoming programs to record based on the channel and time.
mythprogfind
This is used internally by mythfrontend to find programs to record based on the first letter of the program name.
mythuitest
This is a test program for libmythui development.
mythlcdserver
This is an interface between a number of Myth clients and a small text display (LCDProc server).
mythwelcome/mythshutdown
These programs manage Power Saving (shutdown/wakeup) on your Myth PCs.
\section fe_plugins Frontend Plugins
mytharchive
Creates themed Video DVDs from recordings (and other video files).
mythbrowser
Provides a simple web browser.
mythcontrols
Editor for Myth Key bindings, \e et \e c.
mythflix
mythgallery
A simple picture viewer for your %TV.
mythgame
Launches the xmame classic game system emulator.
mythmovies
mythmusic
A simple music player for your %TV.
mythnews
Browses RSS news feeds.
mythphone
SIP based video phone.
mythvideo
Launch DVD players, and a Video Browser for other files (non-%MythTV recordings).
mythweather
Presents your local weather report.
mythzoneminder
\section be_plugins Backend Plugins
mythweb
Provides a PHP based web pages to control mythbackend.
\section spt_scripts Support Scripts These tools are in the contrib directory of the source tree:
osx-packager.pl
Downloads and builds all dependencies, then the source, of %MythTV and all the official plugins, on Mac OS 10.3 thru 10.5
win32-packager.pl
Similar tool for Windows XP
*/ /** \defgroup database_subsystem Database Subsystem \todo No one is working on documenting the database subsystem. There are a few classes that deal directly with the database: MythContext, MSqlDatabase, DBStorage, MDBManager, SimpleDBStorage. And one function UpgradeTVDatabaseSchema() located in dbcheck.cpp. MythTV's Configurable widgets also do save and restore their values from the database automagically when used in %MythTV's window classes. */ /** \defgroup audio_subsystem Audio Subsystem \todo Ed W will be documenting the audio subsystem. */ /** \defgroup lcd_subsystem LCD Subsystem \todo No one is working on documenting the LCD Subsystem */ /** \defgroup osd_subsystem OSD Subsystem \todo No one is working on documenting the OSD Subsystem */ /** \defgroup lirc_subsystem LIRC Subsystem \todo No one is working on documenting the LIRC Subsystem */ /** \defgroup video_subsystem Video Subsystem \todo No one is working on documenting the video subsystem */ /** \defgroup recorder_subsystem Recorder Subsystem This line is filler that is ignored by Doxygen. TVRec is the main class for handling recording. It is passed a ProgramInfo for the current and next recordings, and in turn creates three main worker classes:
RecorderBase
Recordings from device into RingBuffer.
ChannelBase
Changes the channel and other recording device attributes. Optional.
RingBuffer
Handles A/V file I/O, including streaming.
%TVRec also presents the public face of a recordings to the \ref myth_network_protocol, and hence the rest of %MythTV. This means that any call to the %RecorderBase, %RingBuffer, or %ChannelBase is marshalled via methods in the %TVRec. RecorderBase contains classes for recording %MythTV's specialized Nuppel Video files, as well as classes for handling various hardware encoding devices such as MPEG2, HDTV, DVB and Firewire recorders. ChannelBase meanwhile only contains three subclasses, %Channel for handling v4l and v4l2 devices, and %DVBChannel and %FirewireChannel, for handling DVB and Firewire respectively. Other channel changing hardware use ChannelBase's external channel changing program support. Finally, RingBuffer does all reading and writing of A/V files for both TV (playback) and %TVRec, including streaming over network connections to the frontend's %RingBuffer. %TVRec has four active states, the first three of which correspond to the same states in %TV: kState_WatchingLiveTV, kState_WatchingPreRecorded, kState_WatchingRecording, and kState_RecordingOnly. When watching "Live TV" the recorder records whatever the frontend requests and streams it out using the %RingBuffer, this may be to disk or over the network. When watching pre-recorded programs %TVRec simply streams a file on disk out using the %RingBuffer. When just watching a recording, %TVRec continues a recording started as recording-only while simultaneously streaming out using the %RingBuffer. Finally, when in the recording-only mode the recording is only saved to disk using %RingBuffer and no streaming to the frontend is performed. %TVRec also has three additional states: kState_Error, kState_None, kState_ChangingState. The error state allows %MythTV to know when something has gone wrong. The null or none state means the recorder is not doing anything and is ready for commands. Finally, the "ChangingState" state tells us that a state change request is pending, so other state changing commands should not be issued. \todo Check if the TVRec is actually still passed a ProgramInfo for the current and next recordings \todo Document the massive changes Daniel has made in the Vid and MultiRec branches */ /** \defgroup av_player_subsystem A/V Player Subsystem This line is filler that is ignored by Doxygen. TV is the main class for handling playback. It instantiates several important classes:
NuppelVideoPlayer
Decodes audio and video from the RingBuffer, then plays and displays them, resp.
RemoteEncoder
Communicates with TVRec on the backend.
OSD
Creates on-screen-display for NuppelVideoPlayer to display.
RingBuffer
Handles A/V file I/O, including streaming.
NuppelVideoPlayer is a bit of a misnomer. This class plays all video formats that %MythTV can handle. It creates AudioOutput to handle the audio, a FilterChain to perform post-processing on the video, a DecoderBase class to do the actual video decoding, and a VideoOutput class to do the actual video output. See that class for more on what it does. %TV has three active states that correspond to the same states in TVRec: kState_WatchingLiveTV, kState_WatchingPreRecorded, kState_WatchingRecording. When watching "LiveTV" the %TVRec via RemoteEncoder responds to channel changing and other commands from %TV while streaming the recording to %TV's %RingBuffer. When watching a pre-recorded stream, a recording is streamed from TVRec's %RingBuffer to %TV's %RingBuffer, but no channel changing commands can be sent to TVRec. When watching an 'in-progress' recording things work pretty much as when watching a pre-recorded stream, except %TV must be prevented from seeking too far ahead in the program, and keyframe and commercial flags must be synced from the recorder periodically. %TV also has three additional states: kState_Error, kState_None, kState_ChangingState. The error state allows %MythTV to know when something has gone wrong. The null or none state means the player is not doing anything and is ready for commands. Finally, the "ChangingState" state tells us that a state change request is pending, so other state changing commands should not be issued. */ /** \defgroup plugin_arch Plugin Architecture This line is filler that is ignored by Doxygen. MythPlugins are shared object files (i.e. libraries) which are loaded from a specific directory (%e.g. /usr/local/lib/mythtv/plugins). Currently, all plugins are written in the C++ language, but there is nothing preventing other languages being used (the functions are in the C name space). int mythplugin_init(const char *libversion); is invoked whenever mythfrontend is started. This typically handles upgrading any database records - it will be the first method called after a new version of the plugin has been installed. int mythplugin_run(); is invoked when the action attribute of a menu item requests it via the PLUGIN directive. This is when the user chooses to enter the plugin from the main menu or the appropriate submenu. int mythplugin_config(); is invoked when the action attribute of a menu item requests it via the CONFIGPLUGIN directive. This should be when the users wishes to change the plugin's settings (in the main Setup menu). Other plugin functions are listed in the file \link mythpluginapi.h \endlink (see also the \link MythPlugin \endlink and \link MythPluginManager \endlink classes.) */ /** \defgroup mtd MTD (the Myth Transcoding Daemon) This line is filler that is ignored by Doxygen. The %MTD is a simple program that is used by the MythVideo plugin. It currently \b only transcodes tracks from DVDs, but could in the future also rip CD/VCD tracks, transcode %TV recordings, \e et \e cetera. The DVD Rip screen will offer to start %MTD if it is not running. It does \b not currently shut it down afterwards, though. By default, the %MTD listens on port 2442, for commands of this format: \verbatim halt quit shutdown \endverbatim - Tells the %MTD to wait for all jobs to finish, stop listening, and exit. \verbatim hello \endverbatim - Send a trivial response if the %MTD is listening. \verbatim status \endverbatim \verbatim status dvd summary 1 status dvd job 0 overall 0.0262568 ISO copy of UNTITLED status dvd job 0 subjob 0.0262568 Ripping to file ~ 00:08/05:04 status dvd complete \endverbatim - Sends a response listing the status of all jobs. \verbatim media \endverbatim \verbatim media dvd summary 1 UNTITLED media dvd title 1 1 1 0 5 27 8 media dvd title-audio 1 1 2 nl ac3 2Ch media dvd complete \endverbatim - Sends a detailed list of titles/tracks on the current disk. \verbatim job dvd TITLE AUDIOTRK QUALITY AC3 SUBTITLETRK DESTPATH \endverbatim \verbatim e.g. job dvd 1 1 -1 0 -1 /myth/video/UNTITLED \endverbatim - Starts a transcoding job. TITLE, AUDIOTRK and SUBTITLETRK are integers to select the track details. AC3 is 0 or 1. DESTPATH is the output file. QUALITY is one of enum \ref RIP_QUALITIES (-1, 0 or 1). \verbatim abort dvd job NNNN \endverbatim - Stops the job identified by the job number NNNN. \verbatim use dvd PATH \endverbatim - Check dvd PATH is usable, and if so set the current drive to it. \verbatim no dvd \endverbatim - Forget about the current dvd path, ending any jobs that are trying to read it. \verbatim no dvd PATH \endverbatim - End any jobs that are reading from dvd PATH, and if it is the current drive, forget about it. */ /** \defgroup myth_media Myth Media Manager This line is filler that is ignored by Doxygen. The Myth Media Manager is a thread in the frontend which looks for any changes to removable media, and sends events to any Frontend Plugins which are interested in that media. At startup, it creates a list of MythMediaDevice objects (currently MythHDD or MythCDROM and its subclasses) for each removable device configured on the system. A runtime loop then monitors each of these via its checkMedia() method. When any of these devices change status, a MediaEvent object is created. If the device has a status which is usable, the window jumps to the main menu (to allow the registered jump to work correctly), and the event is dispatched to the relevant plugin's registered media handler. If the device status is unusable (%e.g. ejected), the plugin's media handler is called directly (so it can "forget" about this device). The following tables show typical status transitions for CD/DVD and USB flash drive devices: \verbatim CD/DVD USB/FireWire HDD State Action State Action -------------------------------------------------- NODISK NODISK eject attach OPEN USEABLE insert disk, close detach USEABLE UNPLUGGED mount MOUNTED unmount NOTMOUNTED -------------------------------------------------- \endverbatim */ /** \defgroup myth_network_protocol Myth Network Protocol This line is filler that is ignored by Doxygen. The MythTV backend process currently opens sockets for three different types of commands; a custom protocol (by default at port 6543), an HTML server (by default http://127.0.0.1:6544 for the status, and other services under that, like < HREF="http://127.0.0.1:6544/Myth/GetMusic?Id=1"> http://127.0.0.1:6544/Myth/GetMusic?Id=1 ), and a UPnP media server (several ports that I cannot remember right now that throw around lots of little bits of XML :-) The custom protocol is an ASCII encoded length and command string. Command sequences can be easily sent to the backend using telnet. %e.g. \verbatim telnet 127.0.0.1 5432 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'.\endverbatim \verbatim21 MYTH_PROTO_VERSION 36 23 ANN Playback hostname 1 10 QUERY_LOAD 4DONE\endverbatim \verbatim13 ACCEPT[]:[]362 OK34 0.919922[]:[]0.908203[]:[]0.856445Connection closed by foreign host.\endverbatim The command string is prefixed by 8 characters, containing the length of the forthcoming command. This can be justified in any way (as the above example shows) The backend responds with a length, and the response to the command. This can be numbers (up to 32 bit, represented in ASCII), a single string, or an ASCII encoding of a QStringList. The 5 byte sequence "[]:[]" seperates items in the stringlist. Any 64 bit numbers are represented as a stringlist of two 32bit words (MSB first). \section commands Commands There are three main types of networking interactions in MythTV; identification commands (which tell the backend about this client), query commands that are sent to the master backend (%e.g. listing recordings or viewing guide data), and file streaming commands (when a frontend is watching or editing a recording). Until a client is identified to the backend (via the ANN commands), any of the query or file streaming commands will silently fail. The following summarises some of these commands. For a full understanding of all the commands, either read the source code (programs/mythbackend/mainserver.cpp), or look on the Wiki (http://www.mythtv.org/wiki/index.php/Myth_Protocol_Command_List). */ /** \defgroup qobject_dangers QObject is dangerous for your health This line is filler that is ignored by Doxygen. QObject derived classes can be quite useful, they can send and receive signals, get keyboard events, translate strings into another language and use QTimers. But they also can't be \ref qobject_delete "deleted" easily, they are not \ref qobject_threadsafe "thread-safe", can't participate as equals in multiple \ref qobject_inheritence "inheritence", can not be used at all in virtual \ref qobject_inheritence "inheritence". \section qobject_delete Deleting QObjects The problem with deleting QObjects has to do with signals, and events. These can arrive from any thread, and often arrive from the Qt event thread even if you have not explicitly requested them. If you have not explicitly connected any signals or slots, and the only events you might get are dispatched with qApp->postEvent(), not qApp->sendEvent(), then it is safe to delete the QObject in the Qt event thread. If your QObject is a GUI object you've passed given to Qt for it to delete all is good. If your object is only deleted in response to a posted event or a signal from the Qt event thread (say from a QTimer()) then you are OK as well. If your class may be deleted outside a Qt thread, but it does not explicitly connect any signals or slots, and the only events it might get are dispatched with qApp->postEvent(), then you can safely use deleteLater() to queue your object up for deletion in the event thread. %MythTV is a very much a multithreaded program so you may need to have a QObject that may get events from another thread if you send signals but do not get any signals and or events from outside the Qt event thread, then you can use deleteLater() or delete depending on whether you are deleteing the QObject in the event thread, see above. But if you are not in the Qt event thread then you need to call disconnect() in the thread that is sending the signals, before calling deleteLater(). This prevents your object from sending events after you consider it deleted (and begin to delete other QObjects that may still be getting signals from your object.) What about if you are getting events via qApp->sendEvent() or a signal from another thread? In this case things get complicated, so we highly discourage this in %MythTV and prefer that you use callbacks if at all possible. But in say you need to do this, then you need to disconnect all the signals being sent to your QObject. But disconnect() itself is not atomic. That is you may still get a signal after you disconnect it. What you need to is disconnect the signal from your slot in the thread that is sending the signal. This prevents the signal from being emitted while you are disconnecting. Doing this gracefully is left as an excersize for the reader. Ok, so the above is not entirely complete, for instance you could wrap every signal emit in an instance lock and reimplement a disconnect that uses that instance lock. But if you've figured this or another solution out already all you need to know is that almost all Qt objects are reenterant but not thread-safe, and that QObjects recieve events and signals from the Qt event thread and from other threads if you use qApp->sendEvent() or send signals to it from another thread. \section qobject_threadsafe QObject thread-safety The only thread-safe classes in Qt are QThread and the mutex classes. when you call any non-static QObject method you must have a lock on it or make sure only thread ever calls that function. QObject itself is pretty safe because when you assign one QObject to another you make a copy. Qt's container classes, including QString do not make a copy but rather pass a reference counted pointer to the data when you assign one to another. This reference counter is not protected by a mutex so you can not use regular assignment when passing a QString or other Qt container from one thread to another. In order to use these classes safely you must use QDeepCopy when passing them from one thread to another. This is thankfully quite easy to use. \code QString original = "hello world"; QString unsafe = original; QString safe = QDeepCopy(original); \endcode In this case safe and original can be used by two seperate threads, while unsafe can only be used in the same thread as originalStr. The QDeepCopy template will work on the most popular Qt containers, for the ones it doesn't support you will have to copy manually. \section qobject_inheritence QObject inheritence You can not inherit more than one QObject derived class. This is because of how signals and slots are implemented. What happens is that each slot is transformed into an integer that is used to find the right function pointer quickly when a signal is sent. But if you have more than one QObject in the inheritence tree the integers will alias so that signals intended for the second slot in parent class B might get sent to the second slot in parent class A instead. Badness ensues. For the similar reason you can not inherit a QObject derived class virtually, in this case the badness is a little more complicated. The result is the same however, signals arrive at the wrong slot. Usually, what happens is that the developer tries to inherit two QObject derived classes but gets linking errors, so they make one or more of the classes virtual, or inherit a QObject non-virtually but then also inherit one or more QObject derived classes virtually. The linker doesn't complain, but strange unexplainable behaviour ensues when the application is run and signals start showing up on the wrong slots. */ /** \defgroup profiling_mythtv Profiling MythTV This line is filler that is ignored by Doxygen. You can use any sampling profiler to profile %MythTV, the most popular GPL one is OProfile and this section tells you how to use it to profile %MythTV. For Intel also makes VTune, AMD makes CodeAnalyst, and Apple makes Shark. These all work similarly to oprofile, so the %MythTV portions are the same. This do not describe how to install oprofile. There are a few cotchas on installation: You must have APIC enabled to use performance counters. This is usually the default, but you may want to check this in your kernel configuration. You also need the oprofile module, this is part of the kernel config in Linux 2.6+, but must be compiled seperately for earlier kernels. Finally, some RedHat kernels does not work with the standard oprofile, so you must use the RedHat version of oprofile, or compile your own kernel. \section prof_compile Compiling MythTV for profiling The first thing you need to do is compile with profiling in mind. %MythTV has three compile types "release", "debug" and "profile". The "release" type enables optimizations that make debugging practically impossible, while "debug" has so few optimizations that profiling it usually won't tell you where the real performance problems are. The "profile" compile type enables the all the optimizations in "release" but also enables debugging symbols, so that you know which functions are the CPU hogs. So we configure thusly: \code make distclean ./configure --compile-type=profile --enable-proc-opt [+your normal opts] \endcode The "make distclean" clears out all your old binaries and the the configure sets the compile type approriately. You may not want the "--enable-proc-opt" if you plan on making a package for other CPUs. This only makes about a 10% difference in playback speed because MMX and CMOV are enabled for CPUs that support them regardless of this option. Next, you compile and install %MythTV as you normally would. \code qmake; make -j2 -k su make install \endcode \section prof_init Initializing profiler Most sampling profilers, OProfile included, require a kernel module so this module must be loaded. In oprofile's case the module gets confused when it has been loaded a long time, so it is best to begin each session by shutting down the OProfile server and reloading the module: \code opcontrol --deinit opcontrol --init \endcode You also will want to tell the profiler whether to profile the kernel as well, if you want the kernel profiled, and assuming your compiled kernel is in /usr/src/linux, issue this command: \code opcontrol --vmlinux=/usr/src/linux/vmlinux \endcode If you don't want it in your profile report, use this command: \code opcontrol --no-vmlinux \endcode Normally, you don't need it when profiling %MythTV, but there are times when the kernel is a bottleneck. For example when writing streams to disk is taking too long. Now all CPU's are not profiled the same way. In the days of olde, a sampling profiler would hook into the clock interupt and record the instuction pointer's location at the instant the interrupt was triggered. But the wall clock timer still ticks as often as it did when CPU's ran at 5 Mhz, and now they run almost a thousand times faster. Such a profile would now take a thousand times longer than it did in 1985. So modern processors include explicit support for profiling. For, example the Pentium Pro has the INST_RETIRED counter, the Pentium 4 has the INSTR_RETIRED counter, the AMD64 has the RETIRED_INSNS counter, etc. For a full list see the OProfile documentation. You need to find a performance counter you can use for your CPU, after you've run "opcontrol --init" you can run the following command: \code opcontrol --list-events \endcode And it will list all the performance counters available with your CPU. You need to pick the best one for what you want to measure, for overall performance you want something line INSTR_RETIRED. For an Intel Pentium 4, the following will work \code opcontrol -e INSTR_RETIRED:6000:0x0f:0:1 \endcode This tells OProfile to schedule an interrupt on every 6000th instruction that finishes and matches the flag 0x0f. You could also count cycles when not in idle for the same type of measurements. The last two numbers tell OProfile it should not profile the kernel and should profile userspace, if you want to profile the kernel as well you need to replace the zero with a one. It is possible to profile in oprofile the old fashioned way, by using the real-time-clock. But you must compile your Linux kernel WITHOUT RTC support, and run %MythTV significantly longer to get enough samples for a good report. \section prof_run Running Profiler Normally, oprofile will tell you about everything running in its reports. You can limit what information is collected by running a opcontrol command such as: \code opcontrol --image=/usr/local/bin/mythfrontend \endcode This tells OProfile to only profile the frontend. Now you want to start %MythTV as usual: Then begin doing whatever you want to profile, then issue these commands: \code opcontrol --reset ; opcontrol --start \endcode After a few seconds/minutes your should have collected enough data. Then you want to issue the following commands: \code opcontrol --shutdown opreport --merge tgid -l --image-path=/usr/local/bin > report.txt \endcode Now you can peruse the report at your pleasure. This should be enough to get you started with finding and fixing performance problems in %MythTV, but there is more information available from the OProfile manual. This includes information on constructing callgraphs, producing an annotated versions of the code, and saving results. */ // The file ac3.h in ffmpeg contains no Doxygen markup, // but for some reason generates the following modules: // * Coded elements // * Derived values // // They add nothing useful to this programmer doco, so I camouflage these // by manually defining the block here. Same thing for the few modules // in ffmpeg that are documented; Macroblock and VC9 bitplanes from vc1.c, // Monkey Audio from apedec.c, multithreaded slicing from h264.h, /** @defgroup coded . @defgroup derived . @defgroup block . @defgroup std_mb . @defgroup rangecoder . @defgroup multithreading . @defgroup bitplane . */