pion/webrtc · error

data is not a H264 bitstream

Error message

data is not a H264 bitstream

What it means

Returned when the first bytes read from the stream do not look like an H264 Annex-B bitstream: fewer than 3 bytes were read, or no valid start-code prefix (00 00 01 / 00 00 00 01) is found at the head of the data. The reader validates the bitstream prefix before parsing NAL units.

Source

Thrown at pkg/media/h264reader/h264reader.go:26

	"bytes"
	"errors"
	"io"
)

// H264Reader reads data from stream and constructs h264 nal units.
type H264Reader struct {
	stream                      io.Reader
	nalBuffer                   []byte
	countOfConsecutiveZeroBytes int
	nalPrefixParsed             bool
	readBuffer                  []byte
	tmpReadBuf                  []byte
	includeSEI                  bool
}

var (
	errNilReader           = errors.New("stream is nil")
	errDataIsNotH264Stream = errors.New("data is not a H264 bitstream")
)

// NewReader creates new H264Reader.
func NewReader(in io.Reader) (*H264Reader, error) {
	if in == nil {
		return nil, errNilReader
	}

	reader := &H264Reader{
		stream:          in,
		nalBuffer:       make([]byte, 0),
		nalPrefixParsed: false,
		readBuffer:      make([]byte, 0),
		tmpReadBuf:      make([]byte, 4096),
		includeSEI:      false,
	}

	return reader, nil

View on GitHub (pinned to 8c25dc09fa)

Solutions

  1. Verify the input is actually H264 Annex-B (starts with 00 00 00 01) before handing it to the reader.
  2. If the source is HEVC, use h265reader instead; if it's MP4/matroska, remux or extract an Annex-B elementary stream first.
  3. Check the file isn't empty or truncated (size < 4 bytes).

Example fix

// before
rdr, _ := h264reader.NewReader(hevcFile) // wrong codec
// after
if !bytes.HasPrefix(head, []byte{0, 0, 0, 1}) {
    return fmt.Errorf("input is not H264 Annex-B bitstream")
}
rdr, err := h264reader.NewReader(h264File)
Defensive patterns

Strategy: validation

Validate before calling

head := make([]byte, 4)
n, _ := io.ReadFull(stream, head)
if n < 4 || !bytes.Equal(head[3:], []byte{1}) || head[0] != 0 || head[1] != 0 {
    return errors.New("not an H264 Annex-B bitstream")
}
stream.Seek(0, io.SeekStart)

Try / catch

_, err := reader.NextNAL()
if err == errDataIsNotH264Stream {
    return fmt.Errorf("input is not H264 Annex-B: %w", err)
}

Prevention

When it happens

Trigger: Calling ParseNextClosure/NextNAL on a stream whose first bytes lack an H264 start code, or a stream shorter than 3 bytes; bitStreamStartsWithH264Prefix fails.

Common situations: Feeding an H265/HEVC file to the H264 reader, feeding raw NAL units without Annex-B start codes, empty or truncated files, MP4 containers (length-prefixed, no start codes) passed directly.

Related errors


AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03). Data as JSON: /api/errors/9cd26e4ddbeb2e00. Report an issue: GitHub.