
--- 1. Overview of library services ---

Plugin-based architecture that provides access to audio & video
compressors/decompressors for a wide range of formats.

Interfaces for reading from AVI & ASF files, with and without implicit
decompression.

Interfaces for writing to AVI files, with and without implicit compression.

Object that provides core of movie player for supported file types.

--- 2. Subdirectories ---

include/:			All header files which may be needed for 
				programmer to use the library.
				
plugins/:     			Main set of codec plugins.
plugins/libwin32/: 		Win32 DLL loading plugin.
plugins/libaudiodec/:		Audio decoder plugins for a few formats.
plugins/libmpeg_audiodec/:	MPEG layer-1..3 audio decoder plugin
plugins/libmp3lame_audioenc/:	MPEG layer-3 audio encoder plugin
plugins/libmp3lamebin_audioenc/:MPEG layer-3 audio encoder plugin loaded
                                at runtime using libmp3lame

lib/:				Core library.
lib/common/:			Set of utility functions and implementations
				of non-pure methods in plugin interfaces.
lib/aviread/:			Implementation of AVI & ASF readers.
lib/aviwrite/:			Implementation of AVI writer.
lib/aviplay/:			Implementation of AVI/ASF player.
				
player/:			Movie player.
samples/:			Various tools & examples of using library.

--- 3. Coding style conventions ---

 All methods of public interfaces are named in MFC style ( one or
more concatenated words, each word beginning with CAPITAL letter );
for example, IAviPlayer::SetColorSpace() or CImage::Width(). On the opposite,
internal function names start with lowercase letters
 ( AviPlayer::getVideoAsync() ).
Class member variables begin with capital letters and are prefixed with m_
and with appropriate type information:
p pointer
b bool
u unsigned
c char
s short
i 32-bit integer ( int, long )
l 64-bit integer ( long long )
f float
d double
 Code is indented in BSD style with 4-space tabs. Short if() expressions
may be written in one line, as in 'if(...) return; '.
 For imported parts of project ( such as lame mp3 encoder ) original coding
style is left untouched.

--- 4. Using codecs ---

 All codec object creation functions are declared in include/creators.h. To
avoid possible naming collisions, they were put into namespace Creators.
Decoder creation functions take pointer to compressed format description
structure ( which is WAVEFORMATEX for audio and BITMAPINFOHEADER for video;
both are declared in include/formats.h ). Encoder creators take pointer
to structure that describes uncompressed format and so-called FOURCC - 
which describes desired compression format.
 All of them look through the list of registered plugins and try to find
the codec matching request. They return pointer to initialized object on 
success and 0 on failure.
 When codec object is not needed any more, use one of Free* functions from
include/creators.h to destroy it. It frees all data structures and decrements
usage count of the plugin that provided the codec.
 Each codec interface includes function GetCodecInfo(). It returns reference
to CodecInfo structure with all known information about codec ( such as: is it
video or audio codec, does it support both encoding & decoding, etc. ) 
 Many codecs have 'attributes' which affect their performance, quality, etc.
These attributes can be enumerated using fields of CodecInfo structure. 
Attributes should be set before codec object starts operation. They can
be read and written with Creators::GetCodecAttr/Creators::SetCodecAttr.
Once set, these values will be stored in config file and reused every 
time codec is initialized.

--- 5. Video codecs specifics ---

 Some video codecs support run-time setting of attributes ( during the encoding
or decoding process ). For example, video decoder may suggest the option to
do post-processing with different levels of quality independently on each frame, 
or to adjust brightness of picture. This video decoder will inherit from
interface IRtConfig ( declared in include/videodecoder.h ). Do a dynamic_cast
on received interface to determine if it's the case. 
 Initial value for run-time attribute will be read from config file. If you 
want to permanently change it, do two calls - to Creators::SetCodecAttr and to
IRtConfig::SetValue with the same attribute name.
 Video decoders can produce data in any of the following formats: RGB 16-bit
( color weights 555 & 565 ), 24-bit, 32-bit, YUY2 and YV12. User can specify
desired format in call to IVideoDecoder::SetDestFmt(). However, internal video
decoder logic does not always support all these formats. For these cases library
provides a set of conversion functions between all supported formats. It is
optimal in terms of efficiency when the decoder itself performs the conversion
( it is especially important for conversions into YUV formats ). For this purpose,
video decoders have method GetCapabilities(), which can be used to determine
internal capabilities of decoder.
 Video decoders take a special attribute - 'flip' to the constructing function.
'True' here means that decoder shouldn't flip vertically picture. By default decoder
produces flipped picture: it allows to do simple memcpy() to X11 screen. 
Unfortunately, not all encoders are able to compress 'flipped' video formats,
which are indicated by negative value in biHeight field of BITMAPINFOHEADER
structure.

--- 6. Audio decoders specifics ---

 Audio decoder objects convert input compressed data into raw PCM ( 16-bit 
signed low-endian, suitable for	feeding to /dev/dsp ). Unlike with video decoders,
there's generally no need here to start/stop conversion because it's usually 
done on per-sample basis and samples are independent from each other.

--- 7. Audio encoders specifics ---

 Area of audio encoding is not well developed. There's only one experimental
audio encoder plugin, based on Lame MP3 encoder v. 3.70.

--- 8. ASF and AVI reading ( without decompression ) ---
 
 Direct ASF, MMS and AVI reading interface is described in include/ReadHandlers.h.
Reader object is created with CreateAVIReadHandler() ( for AVI ) and 
CreateASXReadHandler() ( for ASF family ).
 CreateAVIReadHandler() is synchronous. It either returns pointer to valid 
reader object, or throws an exception in one of formats from include/except.h.
 On the other hand, opening of ASF file may be an asynchronous operation.
That is, constructor only performs sanity checking on the file name, starts 
actual opening process ( in another thread ) and returns successfully. You should
periodically call IMediaReadHandler::isOpened() until it returns true, which
means that opening process has finished. After that, you can determine if it
was successful by calling IMediaReadHandler::isValid().	
 MMS URL or local ASX file may point to the 'redirector' - XML file that
includes copyrights, file information, etc. and other URLs. Call 
IMediaReadHandler::isRedirector() after isOpened() and isValid() returned true 
to determine if it's the case.
 After successful opening of non-redirector file you can read data from its
streams through IMediaReadStream* interfaces. You don't need to destroy
them manually when they are not needed any more, and multiple requests
for the interface to the same stream will return the same pointer.

--- 9. ASF and AVI reading with implicit decompression ---

 This interface is described in include/avifile.h. Reader object is created
with CreateIAviReadFile(). This function has the same semantics as object
creators from previous section. It tries to open passed URL as a local AVI file,
if it fails, as an ASF, and it it fails too, throws an exception.
 To read the data, use IAviReadStream interface. It acts as a 'wrapper' to
IMediaReadStream and I[Video|Audio]Decoder. To start reading uncompressed data,
call IAviReadStream::StartStreaming(). It returns 0 on success and negative
value if it fails to create decoder object.
 Audio data should be read using IAviReadStream::ReadFrames() and video data - 
using IAviReadStream::GetFrame() and IAviReadStream::ReadFrame().

--- 10. AVI writing ---

 This interface is also described in include/avifile.h. You can either use
implicit compression ( by writing into streams returned with 
IAviWriteFile::AddAudioStream() & IAviWriteFile::AddVideoStream() ) or write
directly into file ( IAviWriteFile::AddStream() ). File headers will be
updated and written to the disk each 1000 accesses to streams to minimize
damage of hardware or software failure. When writing is finished, delete the
object; it writes final version of headers, appends an index chunk and closes
the file.
 The library is able to write 'segmented' AVI files. It is a convenient way
to work-around 2 Gb file size limit which exists both because of AVI format
specification misfeature and because of limitations of most Linux kernels 
( >2Gb files are properly supported only in 2.4 series ). When such object is
created, you pass the file size limit as an argument to constructor. Each time
physical file grows beyond that size, library automatically closes it, changes
the name and starts a new one.

--- 11. Movie player core ---

 Movie player core is declared in include/aviplay.h. It suggests two choices.
If you want to do all GUI-related work by yourself, use interface IAviPlayer.
You'll have to pass to the core a pointer to draw function which will be called
when there's a need to draw new frame. Library will do all internal work, such
as opening file and ( if needed ) audio device, synchronizing audio with video,
etc. You will handle initialization, changing media ( in case of ASF redirectors ),
passing events from keyboard/mouse to the library and drawing.
 The second choice is to allow library to do drawing. Use interface IAviPlayer2
for it. If you want to have video output, establish the connection with X server
and pass the connection handle (Display*) to the library through construction
function. Library will accept NULL handle, which will mean that there'll be no
video output.

--- 12. Plugin system ---

 Important feature of the library is its ability to automatically discover
and use plugins with predefined interface to perform compression/decompression
of data. Plugins have to be dlopen()'able libtool libraries ( linked with -module
flag ) and be installed in predefined directory. By default it's /usr/lib/win32,
it can be changed during compilation ( with --with-win32-path configure 
parameter ) or after installation ith WIN32_PATH environment variable. Each
plugin exports several functions, which are defined and described in 
include/plugin.h.
 Plugin system is not tightly bound to avifile. One can compile and use its plugins
without core library. 
If you want to write your own plugin that can be used by avifile, take a look at
the opendivx plugin sample ( it can be found at http://divx.euro.ru/download.htm ).
It is made completely independent of avifile. You will notice that it includes a 
subset of avifile headers, ~40k total, which describe all necessary types and 
interfaces.
 Using these plugins by themselves is also possible. You'll have to do the following:
1) Copy API/ and common/ directories from opendivx plugin into your project.
Link your application against code in common/.
2) Search the plugin directory for files with .la extension. Parse them to find
line "dlname='...'". Dlopen() corresponding shared library.
3) Make sure that API versions of plugin and your code are the same.
4) Call exported functions of plugin to create codec objects.

--- 13. Image conversion speeds ----

 Numbers are approximate CPU cycles per pixel and measured on non-MMX processor
for 640x480 random image without overflows. Source format is the determined by 
the row. For typical 600 MHz processor 100 cycles/pixel correspond to 20 frames
per second with 640x480 image. Your numbers may differ, depending on processor
family, memory speed, etc.
 Many of these conversions can possibly be optimized ( so far the only
MMX-optimized conversion is RGB15->RGB16 ).

Without flipping:
	RGB15	RGB16	RGB24	RGB32	YUY2	YV12
RGB15	10	20	31	67	101	84	
RGB16	68	10	31	66	103	83	
RGB24	36	35	15	34	68	52	
RGB32	63	63	27	20	96	79	
YUY2	133	135	113	159	10	19	
YV12	133	132	97	132	20	7	

With flipping:
	RGB15	RGB16	RGB24	RGB32	YUY2	YV12
RGB15	10	18	30	76	101	82	
RGB16	70	10	30	78	101	84	
RGB24	41	40	15	46	68	53	
RGB32	72	66	26	19	96	79	
YUY2	138	137	98	142	10	18	
YV12	135	134	95	140	20	7	

	 				    Last modified; January 21, 2001