# Writing a file

The following commands are good for writing to a file.

Immediately after opening the file, set up some tracks to write with these commands:

`quicktime_set_audio(quicktime_t *file, int channels, long sample_rate, int bits, char *compressor);
quicktime_set_video(quicktime_t *file, int tracks, int frame_w, int frame_h, float frame_rate, char *compressor);`

Don't call the audio command if you don't intend to store any audio data. Likewise, don't call the video command if you're just going to save audio.

Notice the channels argument for audio channels but there is no argument for total audio tracks. Currently the library only supports writing one audio track of any number of channels.

If you intend to use the library's built-in compression routines specify a compressor #define from quicktime.h as the compressor argument. If you want to write your own compression routine, specify any 4 byte identifier you want but don't expect the library to handle compression. The compressor applies to all tracks of the same media type, for sanity reasons.

Once these routines are called you can optionally call

`void quicktime_set_parameter(quicktime_t *file, char *key, void *value);`

to set compression parameters for the codecs. Each parameter for a codec consists of a unique string and a pointer to a value. The string is unique to the codec and the parameter. The value is in a specific data type recognized by the parameter.

To set a jpeg compression quality of 80, for example, do the following:

`int quality = 80;
quicktime_set_parameter(file, "jpeg_quality", &quality);
`

The data type of the value depends on the parameter. Currently the best way to determine what parameters and value data types a particular codec supports is to look at the codec's source code. A better way may become available in the future.

If you don't call quicktime_set_parameter the codecs will use default parameters.

## NOTE FOR AVI FILES

After the above sequence and only after it, call `quicktime_set_avi` to make the library generate an AVI file.

# Encoding video

The library generates compressed video frames from a frame buffer of any colormodel in colormodels.h. First use

`int quicktime_supported_video(quicktime_t *file, int track);`

to find out if the codec for the track is in the library. This returns 1 if it is and 0 if it isn't supported. Then use

`int quicktime_writes_cmodel(quicktime_t *file, int colormodel, int track);`

To query the library for a colormodel which doesn't require downsampling to drive the codec. colormodels.h contains a set of colormodel #defines which supply the colormodel argument. The function returns True or False depending on whether the colormodel argument is optimum. When a colormodel doesn't require downsampling it returns 1. Then call

`quicktime_set_cmodel(quicktime_t *file, int colormodel);`

to set the colormodel your frame buffer is in. Finally call

`int quicktime_encode_video(quicktime_t *file, unsigned char **row_pointers, int track);`

to compress the frame pointed to by **row_pointers, write it at the current position of the track and advance the current position. The return value is always 1 for failure and 0 for success. The row pointers must point to rows stored in the colormodel. Planar colormodels use only the first 3 row pointers, each pointing to one of the planes.

# Encoding audio

The library also supports encoding certain audio codecs. Before writing a buffer of samples, try

`int quicktime_supported_audio(quicktime_t *file, int track);`

The track argument is really hypothetical here, since you should only pass 0 for it. If you get a TRUE return value, you are free to use

`int quicktime_encode_audio(quicktime_t *file, int16_t **input_i, float **input_f, long samples);`

to encode the sample buffer. Pass an array of buffers to either the int16_t** or the float** argument, depending on what format your data is in. Pass a NULL to the undesired format. The array of buffers is one buffer of samples for each channel. This means all the channels have to be written simultaneously. The return value is 0 on success.

# Writing raw video

For writing raw data, you need to supply a buffer of data exactly as you intend the read operations to see it, with the encoding done, then call one of these functions to write it. For video, specify the number of bytes in the frame buffer and the track this frame belongs to. Video can only be written one frame at a time.

`int quicktime_write_frame(quicktime_t *file, unsigned char *video_buffer, long bytes, int track);`

Now some of you are going to want to write frames directly to a file descriptor using another library like libjpeg or something. For every frame start by calling quicktime_write_frame_init to initialize the output.

`int quicktime_write_frame_init(quicktime_t *file, int track);`

Then write your raw, compressed data to the file descriptor given by quicktime_get_fd.

`FILE* quicktime_get_fd(quicktime_t *file);`

End the frame by calling quicktime_write_frame_end.

`int quicktime_write_frame_end(quicktime_t *file, int track);`

Repeat starting at quicktime_write_frame_init for every frame.

# Writing Keyframes

Quicktime offers very simple support for keyframes: a table of all the keyframe numbers in a track. Many students think there's a massive keyframe programming language in Quicktime. Really all there is is a table.

There are two things you can with the keyframe table: insert keyframe numbers and retrieve keyframe numbers.

`void quicktime_insert_keyframe(quicktime_t *file, long frame, int track)`

Inserts a keyframe number corresponding to the frame argument in the table.

# Writing raw audio data

This functionality is obsolete due to the idiosyncracies in compressed audio handling. If you want to write uncompressed audio, use the twos codec.

When you're done, call quicktime_close to close the file.

`int quicktime_close(file);`