> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/bluenviron/gortsplib/llms.txt
> Use this file to discover all available pages before exploring further.

# Video formats

> H264, H265, AV1, VP8, VP9, MJPEG, MPEG-4 Video, and MPEG-1/2 Video.

## Supported video formats

| Struct | Codec | Payload type | RFC / spec | Encoder | Decoder |
| - | - | - | - | - | - |
| `format.H264` | H.264 / AVC | dynamic (96–127) or 35 | RFC 6184 | Yes | Yes |
| `format.H265` | H.265 / HEVC | dynamic (96–127) | RFC 7798 | Yes | Yes |
| `format.AV1` | AV1 | dynamic (96–127) | AV1 RTP Payload v1.0 | Yes | Yes |
| `format.VP9` | VP9 | dynamic (96–127) | RFC 9628 | Yes | Yes |
| `format.VP8` | VP8 | dynamic (96–127) | RFC 7741 | Yes | Yes |
| `format.MJPEG` | Motion-JPEG | 26 (static) | RFC 2435 | Yes | Yes |
| `format.MPEG4Video` | MPEG-4 Visual | dynamic (96–127) | RFC 6416 | Yes | Yes |
| `format.MPEG1Video` | MPEG-1/2 Video | 32 (static) | RFC 2250 | Yes | Yes |

***

<AccordionGroup>
  <Accordion title="H264">
    **Package path:** `github.com/bluenviron/gortsplib/v5/pkg/format`

    **Specification:** RFC 6184

    ### Struct fields

    ```go theme={null}
    type H264 struct {
        // RTP payload type (96–127 or 35).
        PayloadTyp uint8

        // Sequence Parameter Set, parsed from sprop-parameter-sets in SDP.
        // May be nil if not present in SDP.
        SPS []byte

        // Picture Parameter Set, parsed from sprop-parameter-sets in SDP.
        // May be nil if not present in SDP.
        PPS []byte

        // Packetization mode (0, 1, or 2). Use 1 for most cameras and encoders.
        PacketizationMode int
    }
    ```

    ### Recording example

    Declare the format when starting a recording session:

    ```go theme={null}
    forma := &format.H264{
        PayloadTyp:        96,
        PacketizationMode: 1,
    }
    desc := &description.Session{
        Medias: []*description.Media{{
            Type:    description.MediaTypeVideo,
            Formats: []format.Format{forma},
        }},
    }

    c := gortsplib.Client{}
    err := c.StartRecording("rtsp://myuser:mypass@localhost:8554/mystream", desc)
    if err != nil {
        panic(err)
    }
    defer c.Close()

    // create RTP encoder
    rtpEnc, err := forma.CreateEncoder()
    if err != nil {
        panic(err)
    }

    // encode an H264 access unit into RTP packets
    pkts, err := rtpEnc.Encode(accessUnit)
    if err != nil {
        panic(err)
    }
    for _, pkt := range pkts {
        pkt.Timestamp += uint32(int64(randomStart) + pts)
        c.WritePacketRTP(desc.Medias[0], pkt)
    }
    ```

    ### Playback example

    ```go theme={null}
    // find the H264 media and format
    var forma *format.H264
    medi := desc.FindFormat(&forma)
    if medi == nil {
        panic("media not found")
    }

    // setup RTP -> H264 decoder
    rtpDec, err := forma.CreateDecoder()
    if err != nil {
        panic(err)
    }

    // if SPS and PPS are present in the SDP, send them to any downstream decoder
    if forma.SPS != nil {
        // process forma.SPS
    }
    if forma.PPS != nil {
        // process forma.PPS
    }

    _, err = c.Setup(desc.BaseURL, medi, 0, 0)
    if err != nil {
        panic(err)
    }

    c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
        pts, ok := c.PacketPTS(medi, pkt)
        if !ok {
            return
        }

        au, err := rtpDec.Decode(pkt)
        if err != nil {
            if err != rtph264.ErrNonStartingPacketAndNoPrevious && err != rtph264.ErrMorePacketsNeeded {
                log.Printf("ERR: %v", err)
            }
            return
        }

        // au is [][]byte — a slice of NAL units
        log.Printf("received H264 access unit with PTS %v, %d NAL units", pts, len(au))
    })
    ```

    <Note>
      `rtph264.ErrNonStartingPacketAndNoPrevious` and `rtph264.ErrMorePacketsNeeded` are non-fatal: the decoder is waiting for more packets to reassemble a complete access unit.
    </Note>
  </Accordion>

  <Accordion title="H265">
    **Package path:** `github.com/bluenviron/gortsplib/v5/pkg/format`

    **Specification:** RFC 7798

    ### Struct fields

    ```go theme={null}
    type H265 struct {
        // RTP payload type (96–127).
        PayloadTyp uint8

        // Video Parameter Set, parsed from sprop-vps in SDP. May be nil.
        VPS []byte

        // Sequence Parameter Set, parsed from sprop-sps in SDP. May be nil.
        SPS []byte

        // Picture Parameter Set, parsed from sprop-pps in SDP. May be nil.
        PPS []byte

        // Maximum Decoding Order Number Difference.
        MaxDONDiff int
    }
    ```

    ### Playback example

    ```go theme={null}
    // find the H265 media and format
    var forma *format.H265
    medi := desc.FindFormat(&forma)
    if medi == nil {
        panic("media not found")
    }

    // setup RTP -> H265 decoder
    rtpDec, err := forma.CreateDecoder()
    if err != nil {
        panic(err)
    }

    // if VPS, SPS and PPS are present in the SDP, pass them to any downstream decoder
    if forma.VPS != nil {
        // process forma.VPS
    }
    if forma.SPS != nil {
        // process forma.SPS
    }
    if forma.PPS != nil {
        // process forma.PPS
    }

    _, err = c.Setup(desc.BaseURL, medi, 0, 0)
    if err != nil {
        panic(err)
    }

    c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
        pts, ok := c.PacketPTS(medi, pkt)
        if !ok {
            return
        }

        au, err := rtpDec.Decode(pkt)
        if err != nil {
            if err != rtph265.ErrNonStartingPacketAndNoPrevious && err != rtph265.ErrMorePacketsNeeded {
                log.Printf("ERR: %v", err)
            }
            return
        }

        // au is [][]byte — a slice of NAL units
        log.Printf("received H265 access unit with PTS %v, %d NAL units", pts, len(au))
    })
    ```
  </Accordion>

  <Accordion title="AV1">
    **Package path:** `github.com/bluenviron/gortsplib/v5/pkg/format`

    **Specification:** RTP Payload Format For AV1 (v1.0)

    ### Struct fields

    ```go theme={null}
    type AV1 struct {
        // RTP payload type (96–127).
        PayloadTyp uint8

        // Optional AV1 level index from the fmtp line.
        LevelIdx *int

        // Optional AV1 profile from the fmtp line.
        Profile *int

        // Optional AV1 tier from the fmtp line.
        Tier *int
    }
    ```

    ### Playback example

    ```go theme={null}
    // find the AV1 media and format
    var forma *format.AV1
    medi := desc.FindFormat(&forma)
    if medi == nil {
        panic("media not found")
    }

    // setup RTP -> AV1 decoder
    rtpDec, err := forma.CreateDecoder()
    if err != nil {
        panic(err)
    }

    _, err = c.Setup(desc.BaseURL, medi, 0, 0)
    if err != nil {
        panic(err)
    }

    c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
        pts, ok := c.PacketPTS(medi, pkt)
        if !ok {
            return
        }

        // extract AV1 temporal units from RTP packets
        tu, err := rtpDec.Decode(pkt)
        if err != nil {
            if err != rtpav1.ErrNonStartingPacketAndNoPrevious && err != rtpav1.ErrMorePacketsNeeded {
                log.Printf("ERR: %v", err)
            }
            return
        }

        // tu is [][]byte — a slice of OBUs forming a temporal unit
        log.Printf("received AV1 temporal unit with PTS %v, %d OBUs", pts, len(tu))
    })
    ```
  </Accordion>

  <Accordion title="VP9">
    **Package path:** `github.com/bluenviron/gortsplib/v5/pkg/format`

    **Specification:** RFC 9628

    ### Struct fields

    ```go theme={null}
    type VP9 struct {
        // RTP payload type (96–127).
        PayloadTyp uint8

        // Optional maximum frame rate from fmtp.
        MaxFR *int

        // Optional maximum frame size from fmtp.
        MaxFS *int

        // Optional VP9 profile ID from fmtp.
        ProfileID *int
    }
    ```

    ### Usage

    ```go theme={null}
    var forma *format.VP9
    medi := desc.FindFormat(&forma)
    if medi == nil {
        panic("media not found")
    }

    rtpDec, err := forma.CreateDecoder()
    if err != nil {
        panic(err)
    }

    _, err = c.Setup(desc.BaseURL, medi, 0, 0)
    if err != nil {
        panic(err)
    }

    c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
        pts, ok := c.PacketPTS(medi, pkt)
        if !ok {
            return
        }

        frame, err := rtpDec.Decode(pkt)
        if err != nil {
            log.Printf("ERR: %v", err)
            return
        }

        log.Printf("received VP9 frame with PTS %v, size %d", pts, len(frame))
    })
    ```
  </Accordion>

  <Accordion title="VP8">
    **Package path:** `github.com/bluenviron/gortsplib/v5/pkg/format`

    **Specification:** RFC 7741

    ### Struct fields

    ```go theme={null}
    type VP8 struct {
        // RTP payload type (96–127).
        PayloadTyp uint8

        // Optional maximum frame rate from fmtp.
        MaxFR *int

        // Optional maximum frame size from fmtp.
        MaxFS *int
    }
    ```

    ### Usage

    ```go theme={null}
    var forma *format.VP8
    medi := desc.FindFormat(&forma)
    if medi == nil {
        panic("media not found")
    }

    rtpDec, err := forma.CreateDecoder()
    if err != nil {
        panic(err)
    }

    _, err = c.Setup(desc.BaseURL, medi, 0, 0)
    if err != nil {
        panic(err)
    }

    c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
        pts, ok := c.PacketPTS(medi, pkt)
        if !ok {
            return
        }

        frame, err := rtpDec.Decode(pkt)
        if err != nil {
            log.Printf("ERR: %v", err)
            return
        }

        log.Printf("received VP8 frame with PTS %v, size %d", pts, len(frame))
    })
    ```
  </Accordion>

  <Accordion title="M-JPEG">
    **Package path:** `github.com/bluenviron/gortsplib/v5/pkg/format`

    **Specification:** RFC 2435

    **Static payload type:** 26

    ### Struct fields

    ```go theme={null}
    // MJPEG has no configurable fields — payload type 26 is fixed by RFC 3551.
    type MJPEG struct{}
    ```

    ### Usage

    ```go theme={null}
    var forma *format.MJPEG
    medi := desc.FindFormat(&forma)
    if medi == nil {
        panic("media not found")
    }

    rtpDec, err := forma.CreateDecoder()
    if err != nil {
        panic(err)
    }

    _, err = c.Setup(desc.BaseURL, medi, 0, 0)
    if err != nil {
        panic(err)
    }

    c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
        pts, ok := c.PacketPTS(medi, pkt)
        if !ok {
            return
        }

        frame, err := rtpDec.Decode(pkt)
        if err != nil {
            log.Printf("ERR: %v", err)
            return
        }

        // frame is a complete JPEG image
        log.Printf("received MJPEG frame with PTS %v, size %d", pts, len(frame))
    })
    ```
  </Accordion>

  <Accordion title="MPEG-4 Video">
    **Package path:** `github.com/bluenviron/gortsplib/v5/pkg/format`

    **Specification:** RFC 6416, section 7.1

    ### Struct fields

    ```go theme={null}
    type MPEG4Video struct {
        // RTP payload type (96–127).
        PayloadTyp uint8

        // Profile and level indication. Defaults to 1.
        ProfileLevelID int

        // Decoder configuration, parsed from the config fmtp parameter.
        Config []byte
    }
    ```

    ### Usage

    ```go theme={null}
    var forma *format.MPEG4Video
    medi := desc.FindFormat(&forma)
    if medi == nil {
        panic("media not found")
    }

    rtpDec, err := forma.CreateDecoder()
    if err != nil {
        panic(err)
    }

    _, err = c.Setup(desc.BaseURL, medi, 0, 0)
    if err != nil {
        panic(err)
    }

    c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
        pts, ok := c.PacketPTS(medi, pkt)
        if !ok {
            return
        }

        frame, err := rtpDec.Decode(pkt)
        if err != nil {
            log.Printf("ERR: %v", err)
            return
        }

        log.Printf("received MPEG-4 Video frame with PTS %v, size %d", pts, len(frame))
    })
    ```
  </Accordion>

  <Accordion title="MPEG-1/2 Video">
    **Package path:** `github.com/bluenviron/gortsplib/v5/pkg/format`

    **Specification:** RFC 2250

    **Static payload type:** 32

    ### Struct fields

    ```go theme={null}
    // MPEG1Video has no configurable fields — payload type 32 is fixed by RFC 3551.
    type MPEG1Video struct{}
    ```

    ### Usage

    ```go theme={null}
    var forma *format.MPEG1Video
    medi := desc.FindFormat(&forma)
    if medi == nil {
        panic("media not found")
    }

    rtpDec, err := forma.CreateDecoder()
    if err != nil {
        panic(err)
    }

    _, err = c.Setup(desc.BaseURL, medi, 0, 0)
    if err != nil {
        panic(err)
    }

    c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
        pts, ok := c.PacketPTS(medi, pkt)
        if !ok {
            return
        }

        frame, err := rtpDec.Decode(pkt)
        if err != nil {
            log.Printf("ERR: %v", err)
            return
        }

        log.Printf("received MPEG-1/2 Video frame with PTS %v, size %d", pts, len(frame))
    })
    ```
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.