AvBindings to libavformat. The interface is the one of spec/avformat.md §4.
A container is an opened media file, network stream or device. An input container demultiplexes packets and can decode them to frames. An output container multiplexes packets and can encode frames to them. Loading this module initialises FFmpeg's network layer for the process.
A container is released by close, or by the garbage collector when it is unreachable. Every stream value, every uninitialized_stream_copy and the value of input_obj keeps its container alive. Only close finalises an output: a collected output is truncated.
An operation on a closed container, or on a stream of one, raises Error (`Failure "Container closed!"). An output on which a stream creation failed half-way is failed: every operation on it except close raises Error (`Failure "Object failed!").
A failure reported by FFmpeg raises Avutil.Error with the mapped code. A condition the binding detects itself raises Error (`Failure message). An exception raised by a function given to open_input, read_input or write_frame propagates unchanged.
The functions that open, probe, read, seek, create an encoding stream, write, flush, tell and close release the OCaml runtime lock while FFmpeg works, so other OCaml threads run meanwhile.
One container serves one modifying operation at a time. read_input, seek, the stream creations, the setters, the writes, flush, tell and close are exclusive; the getters and the stream lists may run together. An operation that finds the container taken in a conflicting way, by another thread or domain, raises Error (`Failure "Object in use!") at once; it does not wait. Streams share the guard of their container.
A function taking ?opts hands the entries of the table to FFmpeg. After a successful call the table holds exactly the entries FFmpeg did not consume. After a failure the table is untouched.
val avformat_version : Avutil.versionThe version of the libavformat loaded at run time, read once when this module is loaded.
val container_options : Avutil.Options.tThe option class of containers, for listing the container options with Avutil.Options.
module Format : sig ... endFFmpeg's input and output formats: demuxers, muxers and devices. A format value is a handle on a static FFmpeg object and needs no release.
type 'media stream_config = {codec : ('media, Avcodec.decode) Avcodec.codec option;opts : Avutil.opts option;}What a configure_*_stream function of open_input answers for one stream.
codec: the preferred decoder of the stream. It decodes the stream when read_input reads it as frames, and may serve to probe it. None selects FFmpeg's default decoder for the stream's codec.opts: options for the decoder of the stream. They are given to probing and to the decoder when it is opened. The table is read once, is not modified, and unused entries are not reported.val open_input :
?interrupt:(unit -> bool) ->
?format:(Avutil.input, _) Avutil.format ->
?opts:Avutil.opts ->
?configure_audio_stream:
(Avutil.audio Avcodec.params -> Avutil.audio stream_config) ->
?configure_video_stream:
(Avutil.video Avcodec.params -> Avutil.video stream_config) ->
?configure_subtitle_stream:
(Avutil.subtitle Avcodec.params -> Avutil.subtitle stream_config) ->
string ->
Avutil.input Avutil.containeropen_input url opens url for reading and probes its streams. It blocks while FFmpeg opens and probes, with the runtime lock released.
In order: the demuxer is opened on url; each stream then present is offered, in index order, to the configure function of its media type; the streams are probed. FFmpeg's probing takes one forced decoder per media type: the preferred decoder of the first stream of each type that has one. When a later stream of the same type prefers another decoder, a warning goes to FFmpeg's log. A stream that the demuxer adds later has no configuration.
Any failure, an exception of a configure function included, releases everything opened so far before it reaches the caller.
A custom read function. read buffer offset length stores at most length bytes into buffer from offset and returns the number of bytes stored. length is at least 1 and at most the size of the container's I/O buffer.
length, and an exception, fail the read: the operation in progress raises the error FFmpeg propagates, and the text of the exception goes to FFmpeg's log.buffer belongs to the binding and is meaningful during the call only: the function must not keep it. The function runs with the runtime lock held, inside the container operation that triggered it, normally on that operation's thread. An operation on the same container called from it raises the in-use error.
A custom write function. write buffer offset length consumes at most length bytes of buffer from offset and returns the number of bytes consumed. When it consumed fewer than length, it is called again with the remainder.
length, and an exception, fail the write.The bytes received, concatenated, are exactly the bytes the same output would write to a file. The rules of read on the buffer, the lock and the container apply.
A custom seek function. seek offset whence moves the position of the custom I/O by offset bytes relative to whence and returns the new position. A negative result is given to FFmpeg as an error code, and an exception fails the seek. FFmpeg's size queries are answered as unsupported without calling the function.
val open_input_stream :
?format:(Avutil.input, _) Avutil.format ->
?opts:Avutil.opts ->
?seek:seek ->
read ->
Avutil.input Avutil.containeropen_input_stream read opens an input that reads through read instead of a URL, and probes its streams, as open_input does. It takes no interrupt function and no stream configuration. It blocks while FFmpeg opens and probes, calling read and seek, with the runtime lock released around FFmpeg's work.
The container keeps read, seek and its I/O buffer alive until it is released.
val get_input_duration :
?format:Avutil.Time_format.t ->
Avutil.input Avutil.container ->
Stdlib.Int64.t optionThe duration of the input in units of format, rounded to the nearest unit. None when FFmpeg does not know it, and when it rounds to 0.
val get_input_start_time :
?format:Avutil.Time_format.t ->
Avutil.input Avutil.container ->
Stdlib.Int64.t optionThe start time of the input (the timestamp of its first frame, as FFmpeg reports it) in units of format, rounded to the nearest unit. None when FFmpeg does not know it, and when it rounds to 0.
val get_input_metadata :
Avutil.input Avutil.container ->
(string * string) listThe metadata of the container, as key and value pairs in the order FFmpeg stores them.
val get_input_format :
Avutil.input Avutil.container ->
(Avutil.input, _) Avutil.format optionThe format the demuxer detected or was given.
val input_obj : Avutil.input Avutil.container -> Avutil.Options.objThe container as an option-bearing object, for reading the current value of its options with Avutil.Options. The result keeps the container alive; reading through it after the container is closed raises the closed error.
A stream of a container: the container and a stream index. It has no resource of its own and keeps its container alive.
The three parameters are phantom. 'line is input or output. 'media is the media type of the stream. 'mode is `Packet or `Frame: whether the stream is read or written as packets or as frames. For an output it is fixed by the function that creates the stream; for the stream lists and the find_best_*_stream functions the caller chooses it.
Some demuxers add streams while packets are read. An operation on a stream whose index the container does not have raises Error (`Failure _).
val get_audio_streams :
'a Avutil.container ->
(int * ('a, Avutil.audio, 'b) stream * Avutil.audio Avcodec.params) listThe current audio streams of the container, in ascending index order. Each element is the stream index, a stream value, and an independent copy of the codec parameters of the stream. It works on inputs and outputs.
val get_video_streams :
'a Avutil.container ->
(int * ('a, Avutil.video, 'b) stream * Avutil.video Avcodec.params) listAs get_audio_streams, for the video streams.
val get_subtitle_streams :
'a Avutil.container ->
(int * ('a, Avutil.subtitle, 'b) stream * Avutil.subtitle Avcodec.params)
listAs get_audio_streams, for the subtitle streams.
val get_data_streams :
'a Avutil.container ->
(int * ('a, [ `Data ], 'b) stream * [ `Data ] Avcodec.params) listAs get_audio_streams, for the data streams.
val find_best_audio_stream :
Avutil.input Avutil.container ->
int * (Avutil.input, Avutil.audio, 'a) stream * Avutil.audio Avcodec.paramsThe audio stream FFmpeg considers the best of the input, with no preference given: its index, a stream value, and a copy of its codec parameters. It releases the runtime lock.
val find_best_video_stream :
Avutil.input Avutil.container ->
int * (Avutil.input, Avutil.video, 'a) stream * Avutil.video Avcodec.paramsAs find_best_audio_stream, for video.
val find_best_subtitle_stream :
Avutil.input Avutil.container ->
int
* (Avutil.input, Avutil.subtitle, 'a) stream
* Avutil.subtitle Avcodec.paramsAs find_best_audio_stream, for subtitles.
val get_input : (Avutil.input, _, _) stream -> Avutil.input Avutil.containerThe container of an input stream. It reads the stream value only and succeeds on a closed container.
val get_index : (_, _, _) stream -> intThe index of the stream in its container. It reads the stream value only and succeeds on a closed container.
val get_output : (Avutil.output, _, _) stream -> Avutil.output Avutil.containerThe container of an output stream. It reads the stream value only and succeeds on a closed container.
val get_codec_params : (_, 'media, _) stream -> 'media Avcodec.paramsAn independent copy of the codec parameters of the stream.
val get_avg_frame_rate : (_, Avutil.video, _) stream -> Avutil.rational optionThe average frame rate of the stream; None when it is unset.
val set_avg_frame_rate :
(_, Avutil.video, _) stream ->
Avutil.rational option ->
unitSets the average frame rate of the stream; None unsets it. On an output it is accepted until the header is written.
val get_time_base : (_, _, _) stream -> Avutil.rationalThe time base of the stream: the unit, in seconds, of the timestamps of its packets. Each stream has its own. On an output, the muxer may replace it when it writes the header, so read it after the first write.
val set_time_base : (_, _, _) stream -> Avutil.rational -> unitSets the time base of the stream. It does not change the time base of the stream's encoder. On an output it is accepted until the header is written, and the muxer may still replace the value when it writes the header.
val get_frame_size : (Avutil.output, Avutil.audio, _) stream -> intThe number of samples per channel the encoder of the stream wants in each frame; 0 for an encoder that accepts any.
val get_pixel_aspect : (_, Avutil.video, _) stream -> Avutil.rational optionThe sample aspect ratio of the stream: the width of a pixel divided by its height. None when it is unknown.
val get_duration :
?format:Avutil.Time_format.t ->
(Avutil.input, _, _) stream ->
Stdlib.Int64.t optionThe duration of the stream in units of format, rounded to the nearest unit. None when FFmpeg does not know it, and when it rounds to 0.
val get_metadata : (Avutil.input, _, _) stream -> (string * string) listThe metadata of the stream, as key and value pairs in the order FFmpeg stores them.
type packet_result = [ | `Audio_packet of int * Avutil.audio Avcodec.Packet.t| `Video_packet of int * Avutil.video Avcodec.Packet.t| `Subtitle_packet of int * Avutil.subtitle Avcodec.Packet.t| `Data_packet of int * [ `Data ] Avcodec.Packet.t ]A packet read from an input, with the index of its stream. The tag follows the actual media type of the stream.
type frame_result = [ | `Audio_frame of int * Avutil.audio Avutil.frame| `Video_frame of int * Avutil.video Avutil.frame| `Subtitle_frame of int * Avutil.Subtitle.frame ]A frame decoded from an input, with the index of its stream.
What one call of read_input returns.
val read_input :
?on_unhandled_packet:(packet_result -> unit) ->
?audio_packet:(Avutil.input, Avutil.audio, [ `Packet ]) stream list ->
?audio_frame:(Avutil.input, Avutil.audio, [ `Frame ]) stream list ->
?video_packet:(Avutil.input, Avutil.video, [ `Packet ]) stream list ->
?video_frame:(Avutil.input, Avutil.video, [ `Frame ]) stream list ->
?subtitle_packet:(Avutil.input, Avutil.subtitle, [ `Packet ]) stream list ->
?subtitle_frame:(Avutil.input, Avutil.subtitle, [ `Frame ]) stream list ->
?data_packet:(Avutil.input, [ `Data ], [ `Packet ]) stream list ->
Avutil.input Avutil.container ->
input_resultread_input container returns the next packet or frame of the selected streams. It blocks while FFmpeg reads and decodes, with the runtime lock released.
The *_packet lists select streams to return as packets, the *_frame lists streams to decode and return as frames. All default to empty. A stream in both is returned as packets. Each call returns one result or raises, in this order:
on_unhandled_packet, and the next one is read.Error `Eof, and so does every later call until a seek.With empty selections the call consumes the whole input and raises Error `Eof.
A decoder is opened the first time a packet of its stream is decoded: the preferred decoder given to open_input, else FFmpeg's default for the codec, with the options configured for the stream. When the opening fails the call raises and a later call attempts it again.
A returned packet or frame is independent of the container: later reads do not change it. A decoded subtitle with no timestamp takes the one of its packet. A subtitle with a zero end display time takes the duration of its packet, in milliseconds, when that is positive.
The flags of seek, with the meaning of FFmpeg's AVSEEK_FLAG_* constants: Seek_flag_backward seeks backward, Seek_flag_byte takes the positions as byte offsets, Seek_flag_any accepts any frame, non-key frames included, and Seek_flag_frame takes the positions as frame numbers.
val seek :
?flags:seek_flag list ->
?stream:(Avutil.input, _, _) stream ->
?min_ts:Stdlib.Int64.t ->
?max_ts:Stdlib.Int64.t ->
fmt:Avutil.Time_format.t ->
ts:Stdlib.Int64.t ->
Avutil.input Avutil.container ->
unitseek ~fmt ~ts container repositions the input at time ts. It blocks while FFmpeg seeks, with the runtime lock released.
On success every opened decoder of the container is reset and every frame decoded before the seek is discarded: the first frame read_input returns afterwards belongs to the new position. The end-of-input condition is cleared. On failure the decoders are unchanged.
val open_output :
?interrupt:(unit -> bool) ->
?format:(Avutil.output, _) Avutil.format ->
?interleaved:bool ->
?opts:Avutil.opts ->
string ->
Avutil.output Avutil.containeropen_output url opens url for writing. It blocks while FFmpeg opens the I/O, with the runtime lock released. Nothing is written yet: streams are added next, and the header is written by the first write.
An output is open, then started once its header is written, then closed. The header is written by the first write_packet, write_frame or write_subtitle_frame, or by close. A failed header write leaves the output open and the next write attempts it again. Streams, metadata, time bases and frame rates are accepted until the header is written.
Any failure releases everything opened so far.
For a format that needs no file, a device for one, no I/O is opened.
val open_output_format :
?interleaved:bool ->
?opts:Avutil.opts ->
(Avutil.output, _) Avutil.format ->
Avutil.output Avutil.containeropen_output_format format opens an output of a format that needs no file, a device for one. interleaved is as for open_output. opts is consumed by the generic container options, then by the private options of the muxer.
val open_output_stream :
?opts:Avutil.opts ->
?interleaved:bool ->
?seek:seek ->
write ->
(Avutil.output, _) Avutil.format ->
Avutil.output Avutil.containeropen_output_stream write format opens an output of the given format that writes through write instead of a URL. interleaved and opts are as for open_output_format.
The container keeps write, seek and its I/O buffer alive until it is released. The writes, flush and close call the functions.
val output_started : Avutil.output Avutil.container -> boolWhether the header of the output is written.
val set_output_metadata :
Avutil.output Avutil.container ->
(string * string) list ->
unitReplaces the whole metadata of the output with the list. Entries absent from the list are removed; a key that appears twice keeps its last value. On failure the metadata is unchanged.
val set_metadata : (_, _, _) stream -> (string * string) list -> unitAs set_output_metadata, for the metadata of one stream. It accepts input streams too.
val new_stream_copy :
params:'mode Avcodec.params ->
Avutil.output Avutil.container ->
(Avutil.output, 'mode, [ `Packet ]) streamnew_stream_copy ~params output adds a stream that receives packets encoded elsewhere, through write_packet. It is new_uninitialized_stream_copy followed by initialize_stream_copy.
The stream gets a copy of params, with the codec tag cleared so that the muxer chooses its own. Only the codec parameters are copied. The time base is the muxer's choice unless set_time_base is called. The average frame rate is not part of the codec parameters: set it with set_avg_frame_rate, typically from get_avg_frame_rate of the source stream.
A stream reserved in an output and not yet given its codec parameters. It keeps the output alive.
val new_uninitialized_stream_copy :
Avutil.output Avutil.container ->
uninitialized_stream_copyReserves a stream in the output, so that its index is known before its codec parameters are. The stream is added at once and takes the next index.
val initialize_stream_copy :
params:'mode Avcodec.params ->
uninitialized_stream_copy ->
(Avutil.output, 'mode, [ `Packet ]) streamGives a reserved stream a copy of params, as new_stream_copy does, and returns the stream.
val new_audio_stream :
?opts:Avutil.opts ->
?side_data:Avutil.Frame_side_data.raw list ->
channel_layout:Avutil.Channel_layout.t ->
sample_rate:int ->
sample_format:Avutil.Sample_format.t ->
time_base:Avutil.rational ->
codec:[ `Encoder ] Avcodec.Audio.t ->
Avutil.output Avutil.container ->
(Avutil.output, Avutil.audio, [ `Frame ]) streamnew_audio_stream ~channel_layout ~sample_rate ~sample_format ~time_base ~codec output adds a stream that receives audio frames through write_frame and encodes them with codec. It releases the runtime lock while the encoder is opened.
The encoder is created and opened first, then the muxer accepts the stream, then the stream takes the time base and the codec parameters of the encoder. The output owns the encoder and frees it when it is released. When the output format wants codec headers out of band, the encoder is asked for global headers. A failure of the encoder leaves the output unchanged. A failure after the muxer accepted the stream leaves the output failed.
val new_video_stream :
?opts:Avutil.opts ->
?side_data:Avutil.Frame_side_data.raw list ->
?frame_rate:Avutil.rational ->
?hardware_context:Avcodec.Video.hardware_context ->
pixel_format:Avutil.Pixel_format.t ->
width:int ->
height:int ->
time_base:Avutil.rational ->
codec:[ `Encoder ] Avcodec.Video.t ->
Avutil.output Avutil.container ->
(Avutil.output, Avutil.video, [ `Frame ]) streamAs new_audio_stream, for a stream that receives video frames.
val new_subtitle_stream :
?opts:Avutil.opts ->
?header:string ->
time_base:Avutil.rational ->
codec:[ `Encoder ] Avcodec.Subtitle.t ->
Avutil.output Avutil.container ->
(Avutil.output, Avutil.subtitle, [ `Frame ]) streamAs new_audio_stream, for a stream that receives subtitles through write_subtitle_frame.
val new_data_stream :
time_base:Avutil.rational ->
codec:Avcodec.Unknown.id ->
Avutil.output Avutil.container ->
(Avutil.output, [ `Data ], [ `Packet ]) streamAdds a data stream of the given codec identifier and time base, with no encoder. It receives packets through write_packet.
val codec_attr : (_, _, _) stream -> string optionThe codec string of the stream for an HLS playlist, in the style of RFC 6381, computed from its codec parameters:
avc1. and the profile, constraint and level bytes of the SPS in hexadecimal, when the extradata starts with an Annex-B SPS.hvc1.<profile>.4.L<level>.B01 when the codec tag is hvc1 and the profile and level are known; else, for a codec tag that is set, the tag as its four characters.mp4a.40. and the profile plus one, when the profile is known.mp4a.40.33. MP3: mp4a.40.34. AC-3: ac-3. E-AC-3: ec-3. FLAC: fLaC.None for every other codec and case.
val bitrate : (_, _, _) stream -> int optionThe bit rate of the stream, in bits per second, when its codec parameters give one; else the maximum bit rate of its coded-picture-buffer properties when it has them and it is not 0; else None.
val write_packet :
(Avutil.output, 'media, [ `Packet ]) stream ->
Avutil.rational ->
'media Avcodec.Packet.t ->
unitwrite_packet stream time_base packet writes a packet to the stream. time_base is the time base of the timestamps and duration of packet; they are converted to the time base of the stream. The header of the output is written first when it is not written yet. It blocks while FFmpeg writes, with the runtime lock released.
The muxer takes a reference of its own: packet is unchanged and stays usable. With an interleaved output the muxer may hold the packet until packets of the other streams arrive; flush and close write it out.
type encoded_packet = {key : bool;pts : Stdlib.Int64.t option;dts : Stdlib.Int64.t option;time_base : Avutil.rational;}A packet an encoder produced, as write_frame reports it before the muxer receives it: its key flag, and its timestamps in time_base, the time base of the stream's encoder.
val write_frame :
?on_packet:(encoded_packet -> unit) ->
(Avutil.output, 'media, [ `Frame ]) stream ->
'media Avutil.frame ->
unitwrite_frame stream frame encodes frame with the encoder of the stream and writes every packet that becomes available. The header of the output is written first when it is not written yet. It blocks while FFmpeg encodes and writes, with the runtime lock released.
The timestamps of the packets are converted from the time base of the encoder to the time base of the stream. A frame that produces no packet is not an error: the encoder may hold frames, and close writes what it still holds. With a hardware frame context the frame is uploaded first, its properties included. frame is unchanged.
val write_subtitle_frame :
(Avutil.output, Avutil.subtitle, [ `Frame ]) stream ->
Avutil.Subtitle.frame ->
unitwrite_subtitle_frame stream subtitle encodes a subtitle and writes it as one packet. The header of the output is written first when it is not written yet. It releases the runtime lock.
The timestamp of the packet is the timestamp of the subtitle plus its start display time; its duration is the end display time minus the start display time. A subtitle that encodes to nothing writes no packet. subtitle is read only.
val write_header : Avutil.output Avutil.container -> unitWrites the header of an output whose header is not written yet, then flushes the I/O. Packets the muxer buffers are not written out. All the streams of the output must exist. It blocks, with the runtime lock released.
val flush : Avutil.output Avutil.container -> unitOn an output whose header is written, makes the muxer write out the packets it buffers and flushes the I/O. Encoders are not flushed: the frames they hold are written by close. On an output whose header is not written it does nothing. It blocks, with the runtime lock released.
val tell : _ Avutil.container -> int optionThe byte position of the I/O of the container; None for a container with no I/O of its own. It takes the container exclusively, so it raises the in-use error from a custom I/O function of the same container.
val close : _ Avutil.container -> unitCloses the container and releases what it owns: the I/O it opened, the decoders or encoders of its streams, and the functions installed on it. It blocks, with the runtime lock released. On a closed container it does nothing. A container in use by another operation raises the in-use error and stays open.
On an output that is not failed, close first finalises the file. It flushes every audio and video encoder into the muxer, in stream order, which writes the header when it is not written yet. Then, when the header is written, it writes the trailer and flushes the I/O. An output with no stream, or with only copy and data streams to which nothing was written, is closed with no header and no trailer.
Every step is attempted even when an earlier one failed, and the container is closed in every case.