package formats import ( "C" "errors" "fmt" "github.com/bluenviron/gortsplib/v4" "github.com/bluenviron/gortsplib/v4/pkg/description" "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpav1" "github.com/bluenviron/mediacommon/v2/pkg/codecs/av1" "github.com/pion/rtp" "image" ) // FindAV1Format finds the AV1 media and format. func FindAV1Format(desc *description.Session) (*format.AV1, *description.Media, error) { var av1Format *format.AV1 av1Media := desc.FindFormat(&av1Format) if av1Media == nil { return nil, nil, errors.New("media AV1 not found") } return av1Format, av1Media, nil } // ProcessAV1 processes AV1 flow and returns PTS and IMG. func ProcessAV1( c *gortsplib.Client, av1Media *description.Media, av1RTPDec *rtpav1.Decoder, pkt *rtp.Packet, av1Dec *AV1Decoder, firstRandomReceived bool, ) ( int64, *image.RGBA, error) { // Decode timestamp. pts, ok := c.PacketPTS2(av1Media, pkt) if !ok { return 0, nil, fmt.Errorf("waiting for timestamp\n") } // Extract AV1 temporal units from RTP packets. tu, err := av1RTPDec.Decode(pkt) if err != rtpav1.ErrNonStartingPacketAndNoPrevious && err != rtpav1.ErrMorePacketsNeeded { return 0, nil, fmt.Errorf("decoding RTP packet error: %w", err) } // Wait for a random access unit. IsRandomAccess2, _ := av1.IsRandomAccess(tu) if !firstRandomReceived && !IsRandomAccess2 { return 0, nil, fmt.Errorf("waiting for a random access unit\n") } firstRandomReceived = true // Convert AV1 temporal units into RGBA frames. img, err := av1Dec.Decode(tu) if err != nil { return 0, nil, fmt.Errorf("convert into RGBA frames error\n") } // Wait for a frame. if img == nil { return 0, nil, fmt.Errorf("frame not found\n") } return pts, img, nil }