            The video codec interfaces for Acorn Replay
            ===========================================

Introduction
------------

The Replay "ARMovie" format allows for different sound and video compression
formats. Interfaces inside the ARMovie Player program ("!ARMovie.Player") allow
introduction of new video decompression code, an appropriate compression
program and allow other programs to use the ARMovie video decompressors. Sound
format 2 provides similar independence for sound compression methods: the
format directly names the sound decompression code which will be used -
provided this is located in <ARMovie$SoundDir> (see ToUseSound for more
details).

There are two ways to introduce new video compression formats: total
replacement of the Player program (provide a !ARMovie.Decomp<N>.!RunImage for a
new compression type <N> which implements the entire ProgIf command interface)
or provide a decompressor which uses the Player interface (provide a
!ARMovie.Decomp<N>.Decompress file). A batch compression interface is defined
for compression programs which are named !ARMovie.Decomp<N>.BatchComp and will
be called automatically by !AREncode (and, presumably, other utilities). Named
video decompressors are stored under !ARMovie.Decomp15.<name> - see AE7Doc.

Total replacement decompression interface
=========================================

When a Replay ARMovie file is to be played, the resource !ARMovie.Player gets
called with a command string by the operating system. Player would normally use
the software decompression interface and paint the movie on the screen itself,
but it can also relinquish the entire task (e.g. for a format which is
decompressed by hardware and video overlayed onto the screen) if that is
required. After a minimal check that the ARMovie file is valid, !ARMovie.Player
reads the video format number and checks the appropriate Decomp directory for
the existence of a '!RunImage' file. If this exists, Player will run it with
the ARMovie file and other arguments (many of them are in ARMovie$ExtraArgs)
which were passed to Player.

The replacement routine should obey as much of the command set of Player as
possible (though -shape may be asking too much in the above example!). The
replacement program is free to get its data from anywhere, but it is
recommended that ARMovie files are present with standard headers in order that
general multimedia programs will see something they understand.

Video decompression interface
=============================

The total replacement of !ARMovie.Player is a very large task; it is much
easier to provide a new video decompressor only and rely on the !ARMovie.Player
program doing the rest of the work. Acorn currently provide 10 video
decompressors using this interface and many of them are provided with source.

Using this interface means keeping most of the architecture of the Player
system:

- EITHER decompressor called from IRQ mode; should run with interrupts (mostly)
  enabled OR decompressor called in SWI mode with interrupts enabled (allows
  r14/C to be used)
- flags between disc loader and decompressor
- flags between decompressor and screen painter
- decompressor provides the colour looked up output (or provides an index into
  the colour table in the case of Dec8 and Dec16).

File IO needs to be performed either using the AE7 format or calling a Fetcher.
Details of using the sound system are in 'ToUseSound': either the current Acorn
Replay sound code can be used or new sound formats added by sound code
implementing the current interface (described from the point of view of the
client in ToUseSound) can be added using format 2 to name the sound code. No
changes to Player programs is required.

In order to start some of the decompressors (MovingLines, for example) at any
position, the use of key frames is possible. The compressor stores the state of
the stream at the start of each chunk, uncompressed, in the key frame data
structure. The Player program will load the uncompressed file from the data
structure in order to start decompression at an arbitrary point, providing the
'previous frame' state (see below). Decompressors which can start at the
beginning of any chunk use an ARMovie file without the key frame data structure
(by giving a -1 offset to the keys in the header).

The decompressor is called from IRQ mode or SWI mode with interrupts enabled in
order to decompress the next frame: see below for the two variants of this.
Code in the Player handles semaphores between decompression and painting frames
and between loading the video chunks and decompressing frames. Other code in
the Player takes data from the decompressed frames buffer and paints it onto
the screen (with interrupts enabled also) and code waits for compressed data
buffers to be empty and refills them from the filing system (in User mode as
the foreground task). To allow these other tasks to run, the decompress code
must leave interrupts enabled for as much time as possible (the MovingLines
decompressor leaves interrupts enabled for all of its work). In any case IRQ
must not be disabled for longer than 1 full sound buffer: about 2mS.

Decompressors can either handle mapping colours to the screen or can rely on
the screen painting algorithms to do it. The former case is particularly useful
if the decompressor can avoid mapping the colours of all pixels on each frame
(e.g. by copying pixels from the previous frames which are already colour
mapped or using already colour mapped data). The latter case is most useful
when all pixels in each frame would be colour mapped or when the packed
representation of the pixels is smaller than the colour mapped form (e.g.
decompress to 16 bit values which the paint colour mapping code expands to 32
bit ones). Its also easier to write a non-colour mapping decompressor in C and
rely on Player to do the colour mapping at paint time.

The disc loader works in a double buffered manner: two buffers each containing
either one or two chunks of data (2 or 4 seconds per buffer conventionally).
The addresses of the two buffers and one or two chunks per buffer are all
chosen dynamically and the Player program knows from the ARMovie header how
many times to call the decompression code. The two buffers will always start on
word addresses.

Using the interface play with existing Decompress code
------------------------------------------------------

As well as being able to provide new compression formats by using the Player/
Decompress interface, other programs can also use the Decompress code, in
effect pretending to be the Player program as far as the Decompress code is
concerned. This greatly extends the capability of the Replay system: programs
could be written to play ARMovie files (or other formats via Fetchers) in the
desktop while multitasking (obviously non-real time). Or sections of an ARMovie
file could be decompressed to memory and edited. Or... The ability to patch the
Decompress code allows player programs to load two copies of a Decompress code:
patch one to generate data for one format and patch the other to generate data
for a different format (e.g. non-dithered for the screen).

Such a playing program has to do all the tasks normally done by the
!ARMovie.Player program:

- read the file header to discover the data
- establish the colour lookup table for the screen if needed
  (usually by calling Player with -claimtable!)
- load the right decompress code, patch and initialise it
- load the key frame if required
- load the chunks from the file (or use Fetchers)
- call the decompress entry point for each frame in the block

but it need do no more than this. It can structure its data structures as it
wishes.

The Acorn provided BatchComp programs use ARMovie files as input and use the
Decompress code in order to convert the data into a form they understand
(indeed, they will use Decompress code even if the !RunImage total takeover
exists) and thus get total isolation from the video compression method of the
input ARMovie file.

Decompress "Info" file
----------------------

In order that Decompress code providers can incorporate their own names for
formats, provide format origination text, provide compress and edit routines
with hints on various formats, an Info file called Decomp<N>.Info can be
provided (the !ARMovie.Player does not need this file unless the C calling
process is to be used). It contains the following information:

Name of format
Originator
number of bits per pixel (or empty if this is variable), calling sequence
desired x multiple; minimum x size; maximum x size
desired y multiple; minimum y size; maximum y size
temporal (or empty if temporal information is not required)
list of colour spaces which can be held in the format

For example:

Moving Lines
 Acorn Computers 1993

1;1;1280
1;1;1024
Temporal
YUV 5,5,5; RGB 5,5,5

The colour space information allows programs like !AREncode to present the
user with valid options.

There are two possible calling sequences that can be used to call a
decompressor: a high speed one run entirely in IRQ mode, and a more C friendly
one which runs in SWI mode - allowing R14 to be used. This latter calling
sequence will only be used if the number of bits per pixel line ends with C.

It is usual to provide particular sets of decompression routines depending on
the source bits per pixel. It is helpful to always provide a Decompress file,
even if it isn't the most efficient way of doing something, since that provides
a uniform access method to all files.

For movies sourced at 8 bits per pixel (or less), Dec8 should be provided.
Player will exclusively use Dec8 (if it is provided) since it is advantageous
to have decompressed pixels being bytes and the cost of colour mapping is quite
low since the entire colour map table can live in the CPUs cache.

For movies sourced at 16 bits per pixel, there are two basic choices.If the
format handles colour mapping efficiently, then provide DecompresB, DecompresH
and Decompress (there's only a small advantage to DecompresB). If the format
doesn't handle colour mapping efficiently, then provide Dec16 only (and
Decompress, though Player can survive without it). It may be be worth providing
Dec24 and Dec21 routines if there are colour accuracy problems in 24bpp modes
or if there is a way to colour convert to these formats quickly. If you expect
a lot of work in 8bpp -small, then also provide DecompresB.

For movies sourced at more than 16 bits per pixel, provide Decompress,
DecompresH, Dec24 (solely for use for recompression) and FastDec24 routines.

Formal interface: "Decompress" file (any file type can be used)
---------------------------------------------------------------

The Player program loads the decompress code at a quad word aligned address in
memory. It then processes the patch table and then calls the init point. Later
on the player calls the decompressor in USR mode to decompress the first
chunk's worth of frames (or to do -explode). For a full play, the player will
call the decompressor from IRQ mode, either quickly and directly, or by first
swapping to SWI mode (for the C call sequence). In both cases interrupts will
be enabled.

First word: patch table offset
(32 bit word at byte offset 0)

 Purpose: to allow the player to insert pixel colour lookup in the
          decompressor. May in future allow other values to patched.
          Note that an unpatched decompressor should still work!!

 The offset table consists of words. Each word has the bottom 16 bits as the
 byte offset of a word (usually an instruction) from the start of the
 decompressor. The top 4 bits are an opcode number. The remaining 12
 bits may have a meaning for that opcode. The list is terminated by a
 word of -1.

 Opcode 0: patch in colour lookup
  bits 27..24: destination register
  bits 23..20: source register
  bits 19..17: pixel lookup table register
 The Player alters the word to lookup the pixel colour. The value of
 the source register and the size of the result in the destination
 register may change for different decompressors. For MovingLines the
 source register value is either RGB or YUV 15 bits and the destination
 value is always a word value. An unpatched MovingLines decompressor
 produces RGB or YUV output. Other colour spaces may be in use - see the
 ColourIF file.

Second word: init entry point
(byte offset 4)

 Purpose: to allow the decompressor to initialise any tables or other
          values that are needed. These will be inside the Decompress
          code space or allocated by the init routine.
             To aid the Decompress code in allocating memory, some
          parameters from the file can be passed to it.

 On entry:
   r0 - source x size of movie
   r1 - source y size of movie
   r2 - "PARM" (note - if r2 is not "PARM" then (a) there is no
        parameter list and (b) the finalisation call will not happen)
   r3 - points to parameter list in memory:
        zeroth word: number of parameters
        subsequent words: word type: 0 for integer, 1 for string
                          aligned word for an integer entry
                          or a zero terminated string
        e.g. 0: 2
             4: 0
             8: 42
            12: 1
            16: 'Hell'
            20: 'o' 0,0,0
   r4..r12 - undefined: scratch
   r13 - stack
   r14 - return address
   processor mode: USR
 On exit
   r0-r12 may be corrupted
   r13 - same as on entry
   flags - V set signals error: r0 points to an error block

 Purpose: tidy close down. The playing program will call this routine
          after playing is over.

 On entry:
   r0 - source x size of movie
   r1 - source y size of movie
   r2 - "SHUT"
   r4..r12 - undefined: scratch
   r13 - stack
   r14 - return address
   processor mode: USR
 On exit
   r0-r12 may be corrupted
   r13 - same as on entry
   flags - V set signals error: r0 points to an error block

Third word: decompress entry point

 Purpose: decompress precisely one frame

 On entry:
   r0 to r4 are set up by Player as follows:
   r0 - source byte pointer
   r1 - output pointer - save output pixels here (word aligned)
   r2 - previous output pointer (allows copying from previous frame)
   r3 - pixel dither lookup table
   r4 - return address (default call sequence)
   r5..r12 - scratch
   r13 - small stack (RISC OS irq stack)
   r14 - return address (for C calling sequence only)
   processor mode: IRQ, interrupts ENABLED (usually) (default call sequence)
   processor mode: SWI, interrupts ENABLED (usually) (for C calling sequence)
   flags - irrelevant
 OR  processor mode: USR in which case an error may be raised
 On exit
   r0 - next value of source byte pointer
   r1..r12 - irrelevant
   r13 - must be same value as on entry
   r14 - irrelevant
   processor mode: IRQ, interrupts ENABLED
   flags - irrelevant

 Decompressed pixels are stored as Words!!! For the MovingLines decompressor
 to work, the source pointer (r0) must be half word aligned.

Note that when using the C calling sequence, all calls map onto C function
calls with 3 or 4 arguments passed in registers.

The 'DecompresH' file
---------------------

This has exactly the same interface as the Decompress file, but stores output
pixels as half words. This allows the Player program to use less store (and run
slightly faster) in some screen modes (in particular, mode 15).

Programs which use the decompression programs must not assume the existence of
'DecompresH' forms of decompressors and must be capable of using the
'Decompress' file instead. For some compression formats, the gain in the Player
of using the half word output may be completely lost by inefficiency in the
decompressor.

Note that a DecompresH writer cannot trust the values returned from the pixel
dither lookup table to have the top 16 bits cleared.

The 'DecompresB' file
---------------------

This has exactly the same interface as the Decompress file, but stores output
pixels as bytes. It uses less store (and runs faster) in any screen modes mode
where the number of bits to describe a pixel is 8 or less (e.g. an 8bpp mode
with magx=1, magy=1).

Programs which use the decompression programs must not assume the existence of
'DecompresB' forms of decompressors and must be capable of using the
'Decompress' file instead.

The 'Dec16' file
----------------

This has exactly the same interface as the Decompress file, but stores output
pixels as half words *with no colour transformation done on them*. Naturally
this is only possible for situations where the source bits per pixels is <=16.
This allows the Player program to use less store (and run slightly faster) in
most screen modes (in particular, interpolating ones). The patch table should
just contain a -1.

Programs which use the decompression programs must not assume the existence of
'Dec16' forms of decompressors and must be capable of using the 'Decompress'
file instead.

The 'Dec8' file
---------------

This has exactly the same interface as the Decompress file, but stores output
pixels as bytes *with no colour transformation done on them*. Naturally this is
only possible for situations where the source bits per pixels is <=8. This
allows the Player program to use less store (and run slightly faster) in all
screen modes. The patch table should just contain a -1.

Programs which use the decompression programs must not assume the existence of
'Dec8' forms of decompressors and must be capable of using the 'Decompress'
file instead.

The 'Dec24' file
----------------

The 16 bit per pixel format allows fast colour lookup, but may not allow an
accurate representation of a colour. The 'Dec24' file has an identical
structure to the 'Decompress' file, but writes output colours as 24bpp values
(in words) in the original colour space (i.e. the colour space conversion by
table does not exist). Note that it is perfectly possible to have a file with
24bpp values used in the video stream where the original ARMovie file header
still claims 16bpp, provided a 'Decompress' file is also present (for example,
see Decomp8). The values are written:

                 00000000 BBBBBBBB GGGGGGGG RRRRRRRR
                          76543210 76543210 76543210

where R, G and B are the names of each of the colour components (and only
equate to displayed RGB in the case where the colour space is RGB - if the
colour space is YUV, then that will appear).

The 'Dec21' file
----------------

The 'Dec21' file has an identical structure to the 'Dec24' file, but writes
output colours as 21bpp values (in words) in the original colour space (i.e.
the colour space conversion by table does not exist) such that interpolation
can be quickly performed. Note that it is perfectly possible to have a file
with 21bpp values used in the video stream where the original ARMovie file
header still claims 16bpp, provided a 'Decompress' file is also present (for
example, see Decomp8). The values are written:

                 00000000 BBBBBBB0 GGGGGGG0 RRRRRRR0
                          7654321  7654321  7654321 

where R, G and B are the names of each of the colour components (and only
equate to displayed RGB in the case where the colour space is RGB).

The 'Dec24xxxxx' and 'Dec21xxxxx' files
---------------------------------------

These files have the same interfaces as 'Dec24' and 'Dec21', but write their
output in the 24bpp RGB colour space. An up to five character suffix represents
which colour space the source comes from - e.g. 'Dec24YUV' or 'Dec24YIQ' - and
this suffix should also be present in the ARMovie header at the end of the bits
per pixel line. Note that no suffix is possible, defaulting back to 'Dec24'
which provides no colour space translation (and so had better imply an RGB
colour space source!).

NOTE: Dec24xxx writers - the target colour space is 8 bit R G B with each value
in the range 0..255 (off..on), assumed gamma corrected (i.e. they will be
presented directly to DACs and then to the CRT with no extra
correction/changes). Player will use Dec24 or Dec21 when output is to be in
24bpp modes, and use Decompress or DecompresH otherwise.

The 'FastDec24' file
--------------------

The presence of FastDec24 in a codec directory overrides use of any other
decompressor when the output is to a 32bpp screen mode - if Decompress and
Dec24/Dec21 are provided, they will be ignored by Player apart from when the
RGB colour space is used (but Decompress is obviously used in other screen
modes and Dec24 should be provided in the cases the format is used as source
for compression). (and therefore it is assumed that FastDec24 is better than
Dec24xxxxx etc)

FastDec24 uses the additive colour tables provided by the colour space xxx24
(e.g. YUV24) to provide output of the form R<<0 OR B<<10 OR G*4<<20 which the
paint programs will subsequently reorder for the screen. See ColourIf for the
basic details of the colour tables.

The code in a FastDec24 file needs to be carefully written in order to go fast!
Here is an example of converting a horizontally chroma subsampled word (held as
YUYV) into two pixels. It is also worth studying the Acorn provided source for
Decomp8, 9, 10 and 11's FastDec24 where extra tricks are played...

;enter with r6=YYUV
;           r2=&FF
;           r3=base of tables
;           r8=1<<8 OR 1<<18 OR 1<<30

;the value of fsv is 255 for FastDec24

;output two pixels into r9 and r10

      AND r12,r2,r6,LSR #24   ;extract the V value
      ADD r7,r3,#256*4*2      ;compute the base address of the V table
                              ;note that this could be shared with more pixels
      LDR r12,[r3,r12,LSL #2] ;index the V value into its table
      AND r11,r2,r6,LSR #16   ;extract the U value
      ADD r7,r3,#256*4        ;compute the base address of the U table
                              ;note that this could be shared with more pixels
      LDR r11,[r7,r11,LSL #2] ;index the U value into its table
      ADD r11,r11,r12         ;sum of U and V tables - keep for two pixels
      AND r9,r2,r6            ;extract the first Y
      LDR r9,[r3,r9,LSL #2]   ;index the Y value into its table
      ADD r9,r9,r11           ;do the sum for the first Y value
      AND r10,r2,r6,LSR #8    ;extract the second Y value
      LDR r10,[r3,r10,LSL #2] ;index Y
      ADD r10,r10,r11         ;do the sum for the second Y value
      TST r9,r8               ;detect out of range values for first pixel
      TSTEQ r10,r8            ;and for second pixel
      BNE r9or10over          ;oops.. out of range value detected - go and fix it
.r10d                         ;continue main code (or rejoin from fixup routine)
;now have to convert from computation form into display form
      AND r12,r9,#fsv            ;red value into r12 (fsv is 255)
      AND r11,r9,#fsv<<22        ;green value into r11
      ORR r12,r12,r11,LSR #22-8  ;put red and green together
      AND r9,r9,#fsv<<10         ;extract blue value
      ORR r9,r12,r9,LSL #16-10   ;and put it into the final form
      AND r12,r10,#fsv           ;now do it all again for next pixel
      AND r11,r10,#fsv<<22
      ORR r12,r12,r11,LSR #22-8
      AND r10,r10,#fsv<<10
      ORR r10,r12,r10,LSL #16-10
;now have r9 and r10 ready for storing
; do what ever comes next


;out of line fixup code
;r9/r10 pixel fixup routine - at least one of these pixels is out of range
.r9or10over
      TEQ r8,r9,LSL #31-8     ;test first pixel red
      ORRMI r9,r9,#fsv        ;if minus, then out of range and over or underflow
      BICCC r9,r9,#fsv        ;if cc, then out of range and definitely underflow
      TEQ r8,r9,LSL #31-18    ;test first pixel blue
      ORRMI r9,r9,#fsv<<10    ;if minus, then out of range and over or underflow
      BICCC r9,r9,#fsv<<10    ;if cc, then out of range and definitely underflow
      TEQ r8,r9,LSL #31-30    ;test first pixel green
      ORRMI r9,r9,#fsv*4<<20  ;if minus, then out of range and over or underflow
      BICCS r9,r9,#fsv*4<<20  ;if cs, then out of range and definitely underflow

      TEQ r8,r10,LSL #31-8    ;test second pixel red
      ORRMI r10,r10,#fsv      ;if minus, then out of range and over or underflow
      BICCC r10,r10,#fsv      ;if cc, then out of range and definitely underflow
      TEQ r8,r10,LSL #31-18   ;test second pixel blue
      ORRMI r10,r10,#fsv<<10  ;if minus, then out of range and over or underflow
      BICCC r10,r10,#fsv<<10  ;if cc, then out of range and definitely underflow
      TEQ r8,r10,LSL #31-30   ;test second pixel green
      ORRMI r10,r10,#fsv*4<<20;if minus, then out of range and over or underflow
      BICCS r10,r10,#fsv*4<<20;if cs, then out of range and definitely underflow
      B r10d                  ;go back to main routine having fixed it...

The 'FastDec21' file
--------------------

The FastDec21 file is exactly like the FastDec24 file, giving the pixel results
of the Dec21. For FastDec21, fsv is 254 (&FE) in the above code.

The 'FastDecYUV' file
---------------------

FastDecYUV writes its output data in 4:2:2 YUV in ARMovie format 21 format
(thus it manages to use only 16 bits per pixel which halves the video decoder
write bandwidth for the output frame and also halves the painter read bandwidth
for reading that frame). Colour conversion for 24 bit modes only is done by the
Replay painter. FastDecYUV will only be used for no interpolation or horizontal
interpolation only, in which case it is used in preference to either FastDec21
or FastDec24. FastDecYUV is recommended if:

- the source data is 4:2:2

- the source data is 4:2:0 or 4:1:1 and memory overheads of creating the
  FastDec24 32bit per pixel data dominate.

FastDecYUV is not recommended if:

- the source data is 4:1:0 (the performance lost in the 4:2:2 YUV -> RGB
  conversion is considerable).

- the source data is 4:2:0 or 4:1:1, but the costs of writing the 32bpp data
  is insignificant in the decoder.

Thus, FastDecYUV is a natural choice for a format 9 or format 21 decoder, and
an equivocal one for a format 10 decoder (the format 10 decoder has a lot of
time to spare waiting for the write buffer).

The Batch Compression interface
===============================

A program 'BatchComp' can be provided in the Decomp<N> directory. The program
should obey the compression parameters given below and take an ARMovie file as
source (for example, by using the Decompress interface) and compress it to
produce some of the basic building blocks of an ARMovie file which will later
be turned into a final ARMovie file using 'Join' [aside: the mechanics of
produce a multitrack ARMovie file are sufficiently complex that it is best to
have all the capability in one program]. BatchComp should read a provided
ARMovie Header file in order to work out what to do: it can use the header file
to determine the number of frames per second, the number of frames per chunk
and the volume of the sound data per chunk. It is then able to calculate (based
on the supplied latency and bandwidth of the target decompression device) how
many bytes it can allocate to each frame of video data. Larger numbers of
frames per chunk mean more tolerance of device latency, but larger chunks mean
the movie takes more memory to decompress and takes longer to start playing
(since it has to read the first chunk). Headers should be set up for 2 second
chunks by default.

CAUTION: BatchComp programs may only manage simple resampling to generate
movies at different frame rates from the source. For example,
MovingLine.BatchComp can make a 12.5 fps movie from a 25 fps source (or a 30
fps one from a 60 fps) but not make 12.5 from 30 (or 60) [and obviously not
make 25 from 12.5...]

BatchComp writes video chunks and optionally key frames (key frames permit the
video data to be started from any point in the file, but they take up space,
being uncompressed 16bit per pixel data, so if the file only needs to play from
the start, or the video decompressor does not need key frames they can be
omitted). BatchComp writes all data in the specified destination directory
(which is where the the ARMovie header file is, called "Header") and the video
chunks will be filed separately using the following name for each chunk:

 "Images"+STR$(chunk%DIV77)+"."+RIGHT$("0"+STR$(chunk%MOD77),2)

If writing key frames they are filed as:

 "Keys"+STR$(chunk%DIV77)+"."+RIGHT$("0"+STR$(chunk%MOD77),2)

These data files form part of the input data for the 'Join' program which is
used to make an ARMovie file after the compressor has run.

BatchComp may write a log of all the work it has done, this is stored as Log in
the destination, and may write similar information to the screen (the Acorn
compressors do). If the BatchComp process is slow (it is for the Acorn software
compressors), then BatchComp should periodically (e.g. 20 minute intervals)
save enough data so that it can continue in case the computer stops
unexpectedly: (Acorn compressors save this is in three files "StoppedD",
"StoppedC" and "StoppedF" in the destination directory - for the correct
working of !AREncode it is recommended that the files begin with "Stopped").

Similarly, it is recommended that BatchComp be suspendable such that it can be
restarted. Pressing the space bar should be used as the trigger for this so
that your BatchComp behaves that same as other BatchComps. It is expected that
a similar set of Stopped files be used for restarting BatchComp some time
later.

It can be convenient for several collections of header/images/keys to be stored
in the same directory: the compressor parameter -index N allows any number of
collections to be stored with names Header/Images/Keys/Log (default)
1Header/1Images/1Keys/1Log etc. Stopped files are also prefixed by the index.

If a compression program has a BASIC shell (or is written entirely in BASIC)
then there is a common front end library (<ARMovie$Dir>.Tools.CompLib) which
provides much of the mechanics for writing a BatchComp. The Moving Lines and
Moving Blocks compressors use this.

The parameters are:

-arm2      limit the size of a frame to something that can be decompressed
           by an 8MHz ARM2 machine, if this has any meaning for that
           decompressor.

-batch     set batch mode: BatchComp should not attempt to detect the space
           bar being pressed to suspend it. This is to stop command files
           being sucked in a byte at a time each time a detect for space bar
           being pressed was made.

-dest b.   set directory for destination (compressed) data: the Header, Images,
           Keys are here. If a full pathname is used for this and the source,
           then the BatchComp program should be able to continue processing
           whatever else is happening (it may be multitasking in a task
           window for example). [aside: if the destination doesn't end in a
           directory separator, then add one!]

-dirty     specifies a 'quick and dirty' approach to compression if
           possible. For example, in the MovingLines compressor it tells the
           compressor to use a faster but less accurate method of varying
           the quality to attain the target frame size. Parameter is ignored
           by compressors which can attach no meaning to this hint.

-display N causes BatchComp to switch to screen mode N and display the
           images being compressed. Typically the original image would be
           displayed on the bottom right of the screen and the compressed
           image on the bottom left. If the compressed image can't be fitted
           then only the uncompressed image would be displayed. N may be a
           RISC OS 3.5 mode description string. Using this option when
           invoking BatchComp from a TaskWindow is not recommended!

-double    assume the decompressor will be using double buffered data
           (default: single) when it plays the movie back: this makes the
           number of bytes available for a frame larger for devices with
           high latency (such as CDROM) and thus improves the quality of the
           movie. The only result of asserting this is to change the text
           printed by the compressor when it calculates the amount of
           memory needed to decompress the movie (which is, of course,
           specific to a codec).

-filter    invoke filter or list of filters separated by ';' characters.
           Filters are stored in directory <ARMovie$Dir>.Tools.Filters.
           Filters are applied in the specified order:

              -filter TClamp;Median

           applies the temporal clamp first, then the spatial median. See
           below for filter machine code interface.

-index N   select different Header, Images, Keys, Log combination (default
           is no prefix). Different header files can be used to make
           different movies from the same source - for example with
           different sound tracks or with different frame per second rates.

-nokeys    prevents the key frames being written: this results in a smaller
           movie file which can only be started at the beginning (or at
           other "natural" cut points - for example where the movie changes
           from all white to all black). If the key frame data structure was
           written, a movie without keys can still be made if required.
           If keys are not important to the video compression algorithm, then
           this parameter is ignored.

-notext    suppresses all textual output

-quality N set quality mode and the quality: in the normal mode, BatchComp
           programs adjust the quality to maintain the average frame size at
           the required value. However, this may take time and can produce a
           movie with frames of poor quality. Using -quality will produce a
           movie with a particular quality for all frames, but the frame
           size varies. Quality numbers are higher for poor quality frames,
           lower for frames which are very accurately matched to the source
           frames. Users should make a small test run to find a suitable
           quality value for a particular movie and compression program -
           values for different Decomp<N>.BatchComp for a similar visual
           quality may well be very different (and produce different amounts
           of output). Quality 0 is taken to mean IDENTICAL with the source,
           there is no specified upper limit (users should be referred to
           information on the values for a particular BatchComp).

-restart   continue processing using the "Stopped" files. Only -dest,
           -index and -source need be given. It is recommended that the
           StoppedD file be used to store all the other parameters.
           New values for -batch and -display are required.

-size N    set frame size to N (may come from a data/latency computation).
           Values in the range 5000 to 10000 are reasonable for playback
           from hard discs.

-source f  set name of source file

-startat N set initial start point from the source file in centiseconds
           (default zero). (just like -startat when playing a movie).

Any not understood parameters should be ignored. Parameter strings may have got
too long for the RISC OS 256 character limit on command strings, so some of the
parameters may be in 'ARMovie$ExtraArgs': if this exists and has a non-zero
length, then it should also be read for input parameters, then set to a null
string. Programmers are encouraged to read the MovingLine.BatchComp source...

Note that it is possible to make 'BatchComp' a directory and embed more
resources within it, the entry BatchComp.!Run being used automatically by the
operating system.

The calculations to go from bandwidth/latency to frame size are:

  size=((chunktime*double-latency)/double*datarate-soundbytes ANDNOT1023)/fpf

where the variables are:

chunktime: time for a chunk           (e.g. 2 seconds)
double:    1 for single buffer
           2 for double buffer
latency:   latency time               (e.g. 0.4 seconds)
datarate:  data rate for time base    (e.g. 150*1024 bytes per second)
soundbytes:number of bytes of sound data in a chunk
fpf:       frames per chunk

The soundbytes value is calculated from reading all the sound track information
in the header. Chunktime and fpf values are also from the header.

The program should claim as much application workspace (only) as it requires.

ARMovie$CompressionStatus is an OS variable that the compressor writes to as it
exits (for whatever reason). It can take the following values:

 - does not exist: no error, job successful

 - exists and contains SUSPEND: job suspended, new stopped files written
   for continuation later.

 - else: contains textual error (reason why BatchComp stopped). The compression
   job has been aborted 'due to unforeseen circumstances'. If stopped files
   are present it can be continued (the files may be historical!)

The value must be read and remembered by the calling program on the exit from
BatchComp - it may be reset by any other compression tasks which are floating
around the machine when the next task swap occurs.

Filters
-------

Image processing filters can make a big difference to the quality of compressed
scenes. If dithering has been used, however, the filters may dramatically
reduce the colour range. It is also possible to use the filter code in other
programs. The interface is as follows:

Callers load the filter code at a quad word aligned address in memory. The init
routine is called. Then the filter routine is called as necessary.

First word: init entry point
(byte offset 0)

 Purpose: allows filter to initialise any values it needs (these are stored
          inside the filter's code space or allocated by the init routine).

 On entry:
   r0 - source x size of movie
   r1 - source y size of movie
   r2 - colour space of movie: 0: RGB 5,5,5
                               1: YUV 5,5,5
                               2: Y 8
                               3: RGB 8,8,8
                               4: YUV 8,8,8
   r3..r12 - undefined: scratch
   r13 - stack
   r14 - return address
   processor mode: USR
 On exit
   r0-r12 - may be corrupted
   r13 - same as on entry
   flags - V set signals error: r0 points to an error block

Second word: filter one frame

 Purpose: apply the filter and produce one filtered frame

 On entry:
   r0 - buffer to be filtered (word aligned)
   r1 - previous output pointer (allows temporal filtering from previous frame)
        (0 if no previous frame available)
   r2 - result pointer - save output pixels here (word aligned)
   r3..r12 - scratch
   r13 - stack
   r14 - return address
   processor mode: USR *or* SWI, interrupts ENABLED (usually)
   flags - irrelevant
 On exit
   r0..r12 - irrelevant
   r13 - must be same value as on entry
   r14 - irrelevant
   processor mode: same as called mode
   flags - irrelevant

 Pixels are stored as Words!!! (well, the bottom 15 bits of one, anyway)
