Added frame side data

This commit is contained in:
Quentin Renard
2022-09-18 17:48:10 +02:00
parent c54ec4ba3c
commit 7412da73bd
6 changed files with 110 additions and 1 deletions

View File

@@ -140,6 +140,14 @@ func (f *Frame) SetSampleRate(r int) {
f.c.sample_rate = C.int(r) f.c.sample_rate = C.int(r)
} }
func (f *Frame) NewSideData(t FrameSideDataType, size int) *FrameSideData {
return newFrameSideDataFromC(C.av_frame_new_side_data(f.c, (C.enum_AVFrameSideDataType)(t), C.int(size)))
}
func (f *Frame) SideData(t FrameSideDataType) *FrameSideData {
return newFrameSideDataFromC(C.av_frame_get_side_data(f.c, (C.enum_AVFrameSideDataType)(t)))
}
func (f *Frame) Width() int { func (f *Frame) Width() int {
return int(f.c.width) return int(f.c.width)
} }

36
frame_side_data.go Normal file
View File

@@ -0,0 +1,36 @@
package astiav
//#cgo pkg-config: libavutil
//#include <libavutil/frame.h>
import "C"
import (
"math"
"unsafe"
)
// https://github.com/FFmpeg/FFmpeg/blob/n5.0/libavutil/frame.h#L223
type FrameSideData struct {
c *C.struct_AVFrameSideData
}
func newFrameSideDataFromC(c *C.struct_AVFrameSideData) *FrameSideData {
if c == nil {
return nil
}
return &FrameSideData{c: c}
}
func (d *FrameSideData) Data() []byte {
return bytesFromC(func(size *C.int) *C.uint8_t {
*size = d.c.size
return d.c.data
})
}
func (d *FrameSideData) SetData(b []byte) {
C.memcpy(unsafe.Pointer(d.c.data), unsafe.Pointer(&b[0]), C.size_t(math.Min(float64(len(b)), float64(d.c.size))))
}
func (d *FrameSideData) Type() FrameSideDataType {
return FrameSideDataType(d.c._type)
}

33
frame_side_data_type.go Normal file
View File

@@ -0,0 +1,33 @@
package astiav
//#cgo pkg-config: libavutil
//#include <libavutil/frame.h>
import "C"
// https://github.com/FFmpeg/FFmpeg/blob/n5.0/libavutil/frame.h#L48
type FrameSideDataType C.enum_AVFrameSideDataType
const (
FrameSideDataTypePanscan = FrameSideDataType(C.AV_FRAME_DATA_PANSCAN)
FrameSideDataTypeA53Cc = FrameSideDataType(C.AV_FRAME_DATA_A53_CC)
FrameSideDataTypeStereo3D = FrameSideDataType(C.AV_FRAME_DATA_STEREO3D)
FrameSideDataTypeMatrixencoding = FrameSideDataType(C.AV_FRAME_DATA_MATRIXENCODING)
FrameSideDataTypeDownmixInfo = FrameSideDataType(C.AV_FRAME_DATA_DOWNMIX_INFO)
FrameSideDataTypeReplaygain = FrameSideDataType(C.AV_FRAME_DATA_REPLAYGAIN)
FrameSideDataTypeDisplaymatrix = FrameSideDataType(C.AV_FRAME_DATA_DISPLAYMATRIX)
FrameSideDataTypeAfd = FrameSideDataType(C.AV_FRAME_DATA_AFD)
FrameSideDataTypeMotionVectors = FrameSideDataType(C.AV_FRAME_DATA_MOTION_VECTORS)
FrameSideDataTypeSkipSamples = FrameSideDataType(C.AV_FRAME_DATA_SKIP_SAMPLES)
FrameSideDataTypeAudioServiceType = FrameSideDataType(C.AV_FRAME_DATA_AUDIO_SERVICE_TYPE)
FrameSideDataTypeMasteringDisplayMetadata = FrameSideDataType(C.AV_FRAME_DATA_MASTERING_DISPLAY_METADATA)
FrameSideDataTypeGopTimecode = FrameSideDataType(C.AV_FRAME_DATA_GOP_TIMECODE)
FrameSideDataTypeSpherical = FrameSideDataType(C.AV_FRAME_DATA_SPHERICAL)
FrameSideDataTypeContentLightLevel = FrameSideDataType(C.AV_FRAME_DATA_CONTENT_LIGHT_LEVEL)
FrameSideDataTypeIccProfile = FrameSideDataType(C.AV_FRAME_DATA_ICC_PROFILE)
FrameSideDataTypeS12MTimecode = FrameSideDataType(C.AV_FRAME_DATA_S12M_TIMECODE)
FrameSideDataTypeDynamicHdrPlus = FrameSideDataType(C.AV_FRAME_DATA_DYNAMIC_HDR_PLUS)
FrameSideDataTypeRegionsOfInterest = FrameSideDataType(C.AV_FRAME_DATA_REGIONS_OF_INTEREST)
FrameSideDataTypeVideoEncParams = FrameSideDataType(C.AV_FRAME_DATA_VIDEO_ENC_PARAMS)
FrameSideDataTypeSeiUnregistered = FrameSideDataType(C.AV_FRAME_DATA_SEI_UNREGISTERED)
FrameSideDataTypeFilmGrainParams = FrameSideDataType(C.AV_FRAME_DATA_FILM_GRAIN_PARAMS)
)

View File

@@ -187,4 +187,19 @@ func TestFrame(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
err = f4.AllocSamples(0) err = f4.AllocSamples(0)
require.NoError(t, err) require.NoError(t, err)
f5 := astiav.AllocFrame()
require.NotNil(t, f5)
defer f5.Free()
sd := f5.NewSideData(astiav.FrameSideDataTypeAudioServiceType, 4)
require.NotNil(t, sd)
sd.SetData([]byte{1, 2, 3})
sd = f5.SideData(astiav.FrameSideDataTypeAudioServiceType)
require.NotNil(t, sd)
require.Equal(t, astiav.FrameSideDataTypeAudioServiceType, sd.Type())
require.Equal(t, []byte{1, 2, 3, 0}, sd.Data())
sd.SetData([]byte{1, 2, 3, 4, 5})
sd = f5.SideData(astiav.FrameSideDataTypeAudioServiceType)
require.NotNil(t, sd)
require.Equal(t, []byte{1, 2, 3, 4}, sd.Data())
} }

View File

@@ -74,6 +74,18 @@ func (p *Packet) SetPts(v int64) {
p.c.pts = C.int64_t(v) p.c.pts = C.int64_t(v)
} }
func (p *Packet) AddSideData(t PacketSideDataType, data []byte) error {
// Create buf
buf := (*C.uint8_t)(C.av_malloc(C.size_t(len(data))))
if buf == nil {
return errors.New("astiav: allocating buffer failed")
}
C.memcpy(unsafe.Pointer(buf), unsafe.Pointer(&data[0]), C.size_t(len(data)))
// Add
return newError(C.av_packet_add_side_data(p.c, (C.enum_AVPacketSideDataType)(t), buf, C.size_t(len(data))))
}
func (p *Packet) SideData(t PacketSideDataType) []byte { func (p *Packet) SideData(t PacketSideDataType) []byte {
return bytesFromC(func(size *C.int) *C.uint8_t { return bytesFromC(func(size *C.int) *C.uint8_t {
return C.av_packet_get_side_data(p.c, (C.enum_AVPacketSideDataType)(t), size) return C.av_packet_get_side_data(p.c, (C.enum_AVPacketSideDataType)(t), size)

View File

@@ -101,5 +101,10 @@ func TestPacket(t *testing.T) {
require.NoError(t, pkt4.FromData(b)) require.NoError(t, pkt4.FromData(b))
require.Equal(t, b, pkt4.Data()) require.Equal(t, b, pkt4.Data())
// TODO Test SideData pkt5 := astiav.AllocPacket()
require.NotNil(t, pkt5)
defer pkt5.Free()
b = []byte{1, 2, 3, 4}
require.NoError(t, pkt5.AddSideData(astiav.PacketSideDataTypeAudioServiceType, b))
require.Equal(t, b, pkt5.SideData(astiav.PacketSideDataTypeAudioServiceType))
} }