Membrane.H26x.ParsingEngine (Membrane H.264 and H.265 plugin v0.11.0)

Copy Markdown View Source

Membrane-agnostic H26x parsing engine.

Splits incoming payloads into NAL units, parses them and groups them into access units, optionally generating best-effort timestamps. Codec-specific behaviour is selected via the :codec field of config/0.

Summary

Types

An access unit - a list of logically associated NAL units.

Configuration of the parsing engine

If set to a map, timestamps are generated based on the provided constant framerate (available only for the :bytestream input alignment). :add_dts_offset shifts DTS values so that they don't exceed PTS values, defaults to true.

Alignment of the payloads fed to the engine - an arbitrary stream of bytes (:bytestream), a single NAL unit per payload (:nalu) or a whole access unit per payload (:au).

The structure of the input stream.

Structure of the H26x stream - either Annex B, where the NALus are separated by a start code (0x(00)000001), or length-prefixed (as described in ISO/IEC 14496-15), where each NALu is prefixed with its length.

Functions

Drains all buffered data into access units. To be used on an input alignment change or end of stream.

Returns the NALu's payload with the prefix fitting the given stream structure.

Creates a parser for the given input stream structure and alignment.

Schedules raw (unprefixed) parameter set payloads to be parsed just before the next pushed payload, as if they preceded it in the stream.

Feeds a payload through the parser, returning the access units completed by it.

Changes the input alignment, keeping the accumulated parsing state. To be used after flush/1 when the input alignment changes mid-stream.

Types

access_unit()

@type access_unit() :: [Membrane.H26x.NALu.t()]

An access unit - a list of logically associated NAL units.

codec()

@type codec() :: :h264 | :h265

config()

@type config() :: %{
  :codec => codec(),
  :input_stream_structure => input_stream_structure(),
  :input_alignment => input_alignment(),
  optional(:generate_best_effort_timestamps) =>
    generate_best_effort_timestamps()
}

Configuration of the parsing engine:

generate_best_effort_timestamps()

@type generate_best_effort_timestamps() ::
  false
  | %{
      :framerate => {frames :: pos_integer(), seconds :: pos_integer()},
      optional(:add_dts_offset) => boolean()
    }

If set to a map, timestamps are generated based on the provided constant framerate (available only for the :bytestream input alignment). :add_dts_offset shifts DTS values so that they don't exceed PTS values, defaults to true.

input_alignment()

@type input_alignment() :: :bytestream | :nalu | :au

Alignment of the payloads fed to the engine - an arbitrary stream of bytes (:bytestream), a single NAL unit per payload (:nalu) or a whole access unit per payload (:au).

input_stream_structure()

@type input_stream_structure() ::
  stream_structure()
  | {codec_tag :: :avc1 | :avc3 | :hvc1 | :hev1, dcr :: binary()}

The structure of the input stream.

For the length-prefixed structures (:avc1, :avc3, :hvc1, :hev1), instead of the NALu length size, a Decoder Configuration Record binary (e.g. coming from an MP4 container) may be provided - the NALu length size is then read from it and the parameter sets it carries are scheduled to be parsed before the first pushed payload.

stream_structure()

@type stream_structure() ::
  :annexb
  | {codec_tag :: :avc1 | :avc3 | :hvc1 | :hev1,
     nalu_length_size :: pos_integer()}

Structure of the H26x stream - either Annex B, where the NALus are separated by a start code (0x(00)000001), or length-prefixed (as described in ISO/IEC 14496-15), where each NALu is prefixed with its length.

Functions

flush(engine)

@spec flush(t()) :: {[access_unit()], t()}

Drains all buffered data into access units. To be used on an input alignment change or end of stream.

get_prefixed_nalu_payload(nalu, stream_structure)

@spec get_prefixed_nalu_payload(Membrane.H26x.NALu.t(), stream_structure()) ::
  binary()

Returns the NALu's payload with the prefix fitting the given stream structure.

new(config)

@spec new(config()) :: t()

Creates a parser for the given input stream structure and alignment.

Raises an ArgumentError if the configured codec is not supported.

prepend_parameter_sets(engine, parameter_sets)

@spec prepend_parameter_sets(t(), [binary()]) :: t()

Schedules raw (unprefixed) parameter set payloads to be parsed just before the next pushed payload, as if they preceded it in the stream.

push(engine, payload, timestamps \\ {nil, nil})

@spec push(t(), binary(), Membrane.H26x.NALu.timestamps()) :: {[access_unit()], t()}

Feeds a payload through the parser, returning the access units completed by it.

set_input_alignment(engine, input_alignment)

@spec set_input_alignment(t(), input_alignment()) :: t()

Changes the input alignment, keeping the accumulated parsing state. To be used after flush/1 when the input alignment changes mid-stream.