diff --git a/codec_parameters_test.go b/codec_parameters_test.go index 88aacdb..40cb28e 100644 --- a/codec_parameters_test.go +++ b/codec_parameters_test.go @@ -99,7 +99,5 @@ func TestCodecParameters(t *testing.T) { b := []byte("test") require.NoError(t, cp6.SetExtraData(b)) require.Equal(t, b, cp6.ExtraData()) - sd := cp6.SideData() - require.NoError(t, sd.Add(PacketSideDataTypeDisplaymatrix, b)) - require.Equal(t, b, sd.Get(PacketSideDataTypeDisplaymatrix)) + testPacketSideData(cp6.SideData(), t) } diff --git a/display_matrix.go b/display_matrix.go index be1c9d4..a8500f2 100644 --- a/display_matrix.go +++ b/display_matrix.go @@ -11,7 +11,7 @@ import ( // https://ffmpeg.org/doxygen/7.0/group__lavu__video__display.html type DisplayMatrix [9]uint32 -func NewDisplayMatrixFromBytes(b []byte) (m *DisplayMatrix, err error) { +func newDisplayMatrixFromBytes(b []byte) (m *DisplayMatrix, err error) { // Check length if len(b) < 36 { err = fmt.Errorf("astiav: invalid length %d < 36", len(b)) @@ -35,7 +35,7 @@ func NewDisplayMatrixFromRotation(angle float64) *DisplayMatrix { return m } -func (m DisplayMatrix) Bytes() []byte { +func (m DisplayMatrix) bytes() []byte { b := make([]byte, 0, 36) for _, v := range m { b = binary.LittleEndian.AppendUint32(b, v) diff --git a/display_matrix_test.go b/display_matrix_test.go index a3fa317..97b93c2 100644 --- a/display_matrix_test.go +++ b/display_matrix_test.go @@ -7,17 +7,17 @@ import ( ) func TestDisplayMatrix(t *testing.T) { - _, err := NewDisplayMatrixFromBytes([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) + _, err := newDisplayMatrixFromBytes([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) require.Error(t, err) b := []byte{0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64} - dm, err := NewDisplayMatrixFromBytes(b) + dm, err := newDisplayMatrixFromBytes(b) require.NoError(t, err) require.Equal(t, DisplayMatrix{0x0, 0xffff0000, 0x0, 0x10000, 0x0, 0x0, 0x0, 0x0, 0x40000000}, *dm) require.Equal(t, -90.0, dm.Rotation()) - require.Equal(t, b, dm.Bytes()) + require.Equal(t, b, dm.bytes()) dm = NewDisplayMatrixFromRotation(-90) require.Equal(t, -90.0, dm.Rotation()) - dm, err = NewDisplayMatrixFromBytes([]byte{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}) + dm, err = newDisplayMatrixFromBytes([]byte{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}) require.NoError(t, err) require.Equal(t, DisplayMatrix{0x0, 0x10000, 0x0, 0xffff0000, 0x0, 0x0, 0x0, 0x0, 0x40000000}, *dm) require.Equal(t, 90.0, dm.Rotation()) diff --git a/frame.go b/frame.go index c726bb6..38acf98 100644 --- a/frame.go +++ b/frame.go @@ -239,14 +239,9 @@ func (f *Frame) SetSampleRate(r int) { f.c.sample_rate = C.int(r) } -// https://ffmpeg.org/doxygen/7.0/group__lavu__frame.html#gae05843b941b79e56b955674e581a8262 -func (f *Frame) NewSideData(t FrameSideDataType, size uint64) *FrameSideData { - return newFrameSideDataFromC(C.av_frame_new_side_data(f.c, (C.enum_AVFrameSideDataType)(t), C.size_t(size))) -} - -// https://ffmpeg.org/doxygen/7.0/group__lavu__frame.html#gadec0efb470b1eead6a979333d9deca0c -func (f *Frame) SideData(t FrameSideDataType) *FrameSideData { - return newFrameSideDataFromC(C.av_frame_get_side_data(f.c, (C.enum_AVFrameSideDataType)(t))) +// https://ffmpeg.org/doxygen/7.0/structAVFrame.html#a44d40e03fe22a0511c9157dab22143ee +func (f *Frame) SideData() *FrameSideData { + return newFrameSideDataFromC(&f.c.side_data, &f.c.nb_side_data) } // https://ffmpeg.org/doxygen/7.0/structAVFrame.html#a1e71ce60cedd5f3b6811714a9f7f9e0a diff --git a/frame_side_data.c b/frame_side_data.c new file mode 100644 index 0000000..a1da7bd --- /dev/null +++ b/frame_side_data.c @@ -0,0 +1,5 @@ +#include + +AVRegionOfInterest* astiavConvertRegionsOfInterestFrameSideData(AVFrameSideData *sd) { + return (AVRegionOfInterest*)sd->data; +} \ No newline at end of file diff --git a/frame_side_data.go b/frame_side_data.go index a26195d..0328e99 100644 --- a/frame_side_data.go +++ b/frame_side_data.go @@ -1,38 +1,79 @@ package astiav //#include +//#include "frame_side_data.h" import "C" import ( + "errors" "math" "unsafe" ) // https://ffmpeg.org/doxygen/7.0/structAVFrameSideData.html +// https://ffmpeg.org/doxygen/7.0/group__lavu__frame.html#gae01fa7e427274293aacdf2adc17076bc type FrameSideData struct { - c *C.AVFrameSideData + sd ***C.AVFrameSideData + size *C.int } -func newFrameSideDataFromC(c *C.AVFrameSideData) *FrameSideData { - if c == nil { - return nil +func newFrameSideDataFromC(sd ***C.AVFrameSideData, size *C.int) *FrameSideData { + return &FrameSideData{ + sd: sd, + size: size, } - return &FrameSideData{c: c} } -// https://ffmpeg.org/doxygen/7.0/structAVFrameSideData.html#a76937ad48652a5a0cc4bff65fc6c886e -func (d *FrameSideData) Data() []byte { - return bytesFromC(func(size *C.size_t) *C.uint8_t { - *size = d.c.size - return d.c.data - }) +// https://ffmpeg.org/doxygen/7.0/group__lavu__frame.html#ggae01fa7e427274293aacdf2adc17076bcaf525ec92d2c5a78d44950bc3f29972aa +func (d *FrameSideData) RegionsOfInterest() *frameSideDataRegionsOfInterest { + return newFrameSideDataRegionsOfInterest(d) } -// https://ffmpeg.org/doxygen/7.0/structAVFrameSideData.html#a76937ad48652a5a0cc4bff65fc6c886e -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)))) +type frameSideDataRegionsOfInterest struct { + d *FrameSideData } -// https://ffmpeg.org/doxygen/7.0/structAVFrameSideData.html#a07ff3499827c124591ff4bae6f68eec0 -func (d *FrameSideData) Type() FrameSideDataType { - return FrameSideDataType(d.c._type) +func newFrameSideDataRegionsOfInterest(d *FrameSideData) *frameSideDataRegionsOfInterest { + return &frameSideDataRegionsOfInterest{d: d} +} + +func (d *frameSideDataRegionsOfInterest) data(sd *C.AVFrameSideData) *[(math.MaxInt32 - 1) / C.sizeof_AVRegionOfInterest]C.AVRegionOfInterest { + return (*[(math.MaxInt32 - 1) / C.sizeof_AVRegionOfInterest](C.AVRegionOfInterest))(unsafe.Pointer(C.astiavConvertRegionsOfInterestFrameSideData(sd))) +} + +func (d *frameSideDataRegionsOfInterest) Add(rois []RegionOfInterest) error { + sd := C.av_frame_side_data_new(d.d.sd, d.d.size, C.AV_FRAME_DATA_REGIONS_OF_INTEREST, C.size_t(C.sizeof_AVRegionOfInterest*len(rois)), 0) + if sd == nil { + return errors.New("astiav: nil pointer") + } + + crois := d.data(sd) + for i, roi := range rois { + crois[i].bottom = C.int(roi.Bottom) + crois[i].left = C.int(roi.Left) + crois[i].qoffset = roi.QuantisationOffset.c + crois[i].right = C.int(roi.Right) + crois[i].self_size = C.sizeof_AVRegionOfInterest + crois[i].top = C.int(roi.Top) + } + return nil +} + +func (d *frameSideDataRegionsOfInterest) Get() ([]RegionOfInterest, error) { + sd := C.av_frame_side_data_get(*d.d.sd, *d.d.size, C.AV_FRAME_DATA_REGIONS_OF_INTEREST) + if sd == nil { + return nil, nil + } + + crois := d.data(sd) + rois := make([]RegionOfInterest, int(sd.size/C.sizeof_AVRegionOfInterest)) + for i := range rois { + rois[i] = RegionOfInterest{ + Bottom: int(crois[i].bottom), + Left: int(crois[i].left), + QuantisationOffset: newRationalFromC(crois[i].qoffset), + Right: int(crois[i].right), + Top: int(crois[i].top), + } + } + return rois, nil } diff --git a/frame_side_data.h b/frame_side_data.h new file mode 100644 index 0000000..7f93b66 --- /dev/null +++ b/frame_side_data.h @@ -0,0 +1,3 @@ +#include + +AVRegionOfInterest* astiavConvertRegionsOfInterestFrameSideData(AVFrameSideData *sd); \ No newline at end of file diff --git a/frame_side_data_test.go b/frame_side_data_test.go new file mode 100644 index 0000000..0fe9968 --- /dev/null +++ b/frame_side_data_test.go @@ -0,0 +1,61 @@ +package astiav + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func testFrameSideData(sd *FrameSideData, t *testing.T) { + rois1 := []RegionOfInterest{ + { + Bottom: 1, + Left: 2, + QuantisationOffset: NewRational(3, 4), + Right: 5, + Top: 6, + }, + { + Bottom: 7, + Left: 8, + QuantisationOffset: NewRational(9, 10), + Right: 11, + Top: 12, + }, + } + require.NoError(t, sd.RegionsOfInterest().Add(rois1)) + rois2, err := sd.RegionsOfInterest().Get() + require.NoError(t, err) + require.Equal(t, rois1, rois2) +} + +func TestFrameSideData(t *testing.T) { + f := AllocFrame() + require.NotNil(t, f) + defer f.Free() + sd := f.SideData() + + rois1, err := sd.RegionsOfInterest().Get() + require.NoError(t, err) + require.Nil(t, rois1) + rois1 = []RegionOfInterest{ + { + Bottom: 1, + Left: 2, + QuantisationOffset: NewRational(3, 4), + Right: 5, + Top: 6, + }, + { + Bottom: 7, + Left: 8, + QuantisationOffset: NewRational(9, 10), + Right: 11, + Top: 12, + }, + } + require.NoError(t, sd.RegionsOfInterest().Add(rois1)) + rois2, err := sd.RegionsOfInterest().Get() + require.NoError(t, err) + require.Equal(t, rois1, rois2) +} diff --git a/frame_side_data_type.go b/frame_side_data_type.go deleted file mode 100644 index 415860b..0000000 --- a/frame_side_data_type.go +++ /dev/null @@ -1,32 +0,0 @@ -package astiav - -//#include -import "C" - -// https://ffmpeg.org/doxygen/7.0/group__lavu__frame.html#gae01fa7e427274293aacdf2adc17076bc -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) -) diff --git a/frame_test.go b/frame_test.go index 3e01fad..92f03dd 100644 --- a/frame_test.go +++ b/frame_test.go @@ -1,7 +1,6 @@ package astiav import ( - "bytes" "testing" "unsafe" @@ -90,18 +89,7 @@ func TestFrame(t *testing.T) { f5 := AllocFrame() require.NotNil(t, f5) defer f5.Free() - sd := f5.NewSideData(FrameSideDataTypeAudioServiceType, 4) - require.NotNil(t, sd) - sd.SetData([]byte{1, 2, 3}) - sd = f5.SideData(FrameSideDataTypeAudioServiceType) - require.NotNil(t, sd) - require.Equal(t, FrameSideDataTypeAudioServiceType, sd.Type()) - require.True(t, bytes.HasPrefix(sd.Data(), []byte{1, 2, 3})) - require.Len(t, sd.Data(), 4) - sd.SetData([]byte{1, 2, 3, 4, 5}) - sd = f5.SideData(FrameSideDataTypeAudioServiceType) - require.NotNil(t, sd) - require.Equal(t, []byte{1, 2, 3, 4}, sd.Data()) + testFrameSideData(f5.SideData(), t) f6 := AllocFrame() require.NotNil(t, f6) diff --git a/int_read_write.c b/int_read_write.c deleted file mode 100644 index 4369228..0000000 --- a/int_read_write.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -uint32_t astiavRL32(uint8_t *i) { - return AV_RL32(i); -} -uint32_t astiavRL32WithOffset(uint8_t *i, int o) { - return AV_RL32(i+o); -} \ No newline at end of file diff --git a/int_read_write.go b/int_read_write.go deleted file mode 100644 index eabd560..0000000 --- a/int_read_write.go +++ /dev/null @@ -1,21 +0,0 @@ -package astiav - -//#include "int_read_write.h" -import "C" -import "unsafe" - -// https://ffmpeg.org/doxygen/7.0/avr32_2intreadwrite_8h.html#ace46e41b9bd6cac88fb7109ffd657f9a -func RL32(i []byte) uint32 { - if len(i) == 0 { - return 0 - } - return uint32(C.astiavRL32((*C.uint8_t)(unsafe.Pointer(&i[0])))) -} - -// https://ffmpeg.org/doxygen/7.0/avr32_2intreadwrite_8h.html#ace46e41b9bd6cac88fb7109ffd657f9a -func RL32WithOffset(i []byte, offset uint) uint32 { - if len(i) == 0 { - return 0 - } - return uint32(C.astiavRL32WithOffset((*C.uint8_t)(unsafe.Pointer(&i[0])), C.int(offset))) -} diff --git a/int_read_write.h b/int_read_write.h deleted file mode 100644 index 6752389..0000000 --- a/int_read_write.h +++ /dev/null @@ -1,4 +0,0 @@ -#include - -uint32_t astiavRL32(uint8_t *i); -uint32_t astiavRL32WithOffset(uint8_t *i, int o); \ No newline at end of file diff --git a/int_read_write_test.go b/int_read_write_test.go deleted file mode 100644 index f7c82d6..0000000 --- a/int_read_write_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package astiav - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestIntReadWrite(t *testing.T) { - is := []uint8{1, 2, 3, 4, 5, 6, 7, 8} - require.Equal(t, uint32(0), RL32([]byte{})) - require.Equal(t, uint32(0x4030201), RL32(is)) - require.Equal(t, uint32(0), RL32WithOffset([]byte{}, 4)) - require.Equal(t, uint32(0x8070605), RL32WithOffset(is, 4)) -} diff --git a/packet_side_data.go b/packet_side_data.go index 004b97f..4604f56 100644 --- a/packet_side_data.go +++ b/packet_side_data.go @@ -8,6 +8,7 @@ import ( ) // https://ffmpeg.org/doxygen/7.0/structAVPacketSideData.html +// https://ffmpeg.org/doxygen/7.0/group__lavc__packet__side__data.html#ga9a80bfcacc586b483a973272800edb97 type PacketSideData struct { sd **C.AVPacketSideData size *C.int @@ -20,13 +21,63 @@ func newPacketSideDataFromC(sd **C.AVPacketSideData, size *C.int) *PacketSideDat } } +// https://ffmpeg.org/doxygen/7.0/group__lavc__packet__side__data.html#gga9a80bfcacc586b483a973272800edb97aab8c149a1e6c67aad340733becec87e1 +func (d *PacketSideData) DisplayMatrix() *packetSideDataDisplayMatrix { + return newPacketSideDataDisplayMatrix(d) +} + +type packetSideDataDisplayMatrix struct { + d *PacketSideData +} + +func newPacketSideDataDisplayMatrix(d *PacketSideData) *packetSideDataDisplayMatrix { + return &packetSideDataDisplayMatrix{d: d} +} + +func (d *packetSideDataDisplayMatrix) Add(m *DisplayMatrix) error { + return d.d.addBytes(C.AV_PKT_DATA_DISPLAYMATRIX, m.bytes()) +} + +func (d *packetSideDataDisplayMatrix) Get() (*DisplayMatrix, error) { + b := d.d.getBytes(C.AV_PKT_DATA_DISPLAYMATRIX) + if len(b) == 0 { + return nil, nil + } + return newDisplayMatrixFromBytes(b) +} + +// https://ffmpeg.org/doxygen/7.0/group__lavc__packet__side__data.html#gga9a80bfcacc586b483a973272800edb97a2093332d8086d25a04942ede61007f6a +func (d *PacketSideData) SkipSamples() *packetSideDataSkipSamples { + return newPacketSideDataSkipSamples(d) +} + +type packetSideDataSkipSamples struct { + d *PacketSideData +} + +func newPacketSideDataSkipSamples(d *PacketSideData) *packetSideDataSkipSamples { + return &packetSideDataSkipSamples{d: d} +} + +func (d *packetSideDataSkipSamples) Add(ss *SkipSamples) error { + return d.d.addBytes(C.AV_PKT_DATA_SKIP_SAMPLES, ss.bytes()) +} + +func (d *packetSideDataSkipSamples) Get() (*SkipSamples, error) { + b := d.d.getBytes(C.AV_PKT_DATA_SKIP_SAMPLES) + if len(b) == 0 { + return nil, nil + } + return newSkipSamplesFromBytes(b) +} + // https://ffmpeg.org/doxygen/7.0/group__lavc__packet__side__data.html#gad208a666db035802403ea994912a83db -func (d *PacketSideData) Add(t PacketSideDataType, b []byte) error { +func (d *PacketSideData) addBytes(t C.enum_AVPacketSideDataType, b []byte) error { if len(b) == 0 { return nil } - sd := C.av_packet_side_data_new(d.sd, d.size, (C.enum_AVPacketSideDataType)(t), C.size_t(len(b)), 0) + sd := C.av_packet_side_data_new(d.sd, d.size, t, C.size_t(len(b)), 0) if sd == nil { return errors.New("astiav: nil pointer") } @@ -36,12 +87,12 @@ func (d *PacketSideData) Add(t PacketSideDataType, b []byte) error { } // https://ffmpeg.org/doxygen/7.0/group__lavc__packet__side__data.html#ga61a3a0fba92a308208c8ab957472d23c -func (d *PacketSideData) Get(t PacketSideDataType) []byte { +func (d *PacketSideData) getBytes(t C.enum_AVPacketSideDataType) []byte { return bytesFromC(func(size *C.size_t) *C.uint8_t { if d.sd == nil || d.size == nil { return nil } - sd := C.av_packet_side_data_get(*d.sd, *d.size, (C.enum_AVPacketSideDataType)(t)) + sd := C.av_packet_side_data_get(*d.sd, *d.size, t) if sd == nil { return nil } diff --git a/packet_side_data_test.go b/packet_side_data_test.go index faec347..74eb2be 100644 --- a/packet_side_data_test.go +++ b/packet_side_data_test.go @@ -6,11 +6,39 @@ import ( "github.com/stretchr/testify/require" ) +func testPacketSideData(sd *PacketSideData, t *testing.T) { + m1 := NewDisplayMatrixFromRotation(90) + require.NoError(t, sd.DisplayMatrix().Add(m1)) + m2, err := sd.DisplayMatrix().Get() + require.NoError(t, err) + require.Equal(t, m1.Rotation(), m2.Rotation()) +} + func TestPacketSideData(t *testing.T) { cp := AllocCodecParameters() defer cp.Free() - b := []byte("test") sd := cp.SideData() - require.NoError(t, sd.Add(PacketSideDataTypeDisplaymatrix, b)) - require.Equal(t, b, sd.Get(PacketSideDataTypeDisplaymatrix)) + + m1, err := sd.DisplayMatrix().Get() + require.NoError(t, err) + require.Nil(t, m1) + m1 = NewDisplayMatrixFromRotation(90) + require.NoError(t, sd.DisplayMatrix().Add(m1)) + m2, err := sd.DisplayMatrix().Get() + require.NoError(t, err) + require.Equal(t, m1.Rotation(), m2.Rotation()) + + ss1, err := sd.SkipSamples().Get() + require.NoError(t, err) + require.Nil(t, ss1) + ss1 = &SkipSamples{ + ReasonEnd: 1, + ReasonStart: 2, + SkipEnd: 3, + SkipStart: 4, + } + require.NoError(t, sd.SkipSamples().Add(ss1)) + ss2, err := sd.SkipSamples().Get() + require.NoError(t, err) + require.Equal(t, ss1, ss2) } diff --git a/packet_side_data_type.go b/packet_side_data_type.go deleted file mode 100644 index a157b16..0000000 --- a/packet_side_data_type.go +++ /dev/null @@ -1,47 +0,0 @@ -package astiav - -//#include -import "C" - -// https://ffmpeg.org/doxygen/7.0/group__lavc__packet__side__data.html#ga9a80bfcacc586b483a973272800edb97 -type PacketSideDataType C.enum_AVPacketSideDataType - -const ( - PacketSideDataTypeA53Cc = PacketSideDataType(C.AV_PKT_DATA_A53_CC) - PacketSideDataTypeAfd = PacketSideDataType(C.AV_PKT_DATA_AFD) - PacketSideDataTypeAudioServiceType = PacketSideDataType(C.AV_PKT_DATA_AUDIO_SERVICE_TYPE) - PacketSideDataTypeContentLightLevel = PacketSideDataType(C.AV_PKT_DATA_CONTENT_LIGHT_LEVEL) - PacketSideDataTypeCpbProperties = PacketSideDataType(C.AV_PKT_DATA_CPB_PROPERTIES) - PacketSideDataTypeDisplaymatrix = PacketSideDataType(C.AV_PKT_DATA_DISPLAYMATRIX) - PacketSideDataTypeEncryptionInfo = PacketSideDataType(C.AV_PKT_DATA_ENCRYPTION_INFO) - PacketSideDataTypeEncryptionInitInfo = PacketSideDataType(C.AV_PKT_DATA_ENCRYPTION_INIT_INFO) - PacketSideDataTypeFallbackTrack = PacketSideDataType(C.AV_PKT_DATA_FALLBACK_TRACK) - PacketSideDataTypeH263MbInfo = PacketSideDataType(C.AV_PKT_DATA_H263_MB_INFO) - PacketSideDataTypeJpDualmono = PacketSideDataType(C.AV_PKT_DATA_JP_DUALMONO) - PacketSideDataTypeMasteringDisplayMetadata = PacketSideDataType(C.AV_PKT_DATA_MASTERING_DISPLAY_METADATA) - PacketSideDataTypeMatroskaBlockadditional = PacketSideDataType(C.AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL) - PacketSideDataTypeMetadataUpdate = PacketSideDataType(C.AV_PKT_DATA_METADATA_UPDATE) - PacketSideDataTypeMpegtsStreamId = PacketSideDataType(C.AV_PKT_DATA_MPEGTS_STREAM_ID) - PacketSideDataTypeNb = PacketSideDataType(C.AV_PKT_DATA_NB) - PacketSideDataTypeNewExtradata = PacketSideDataType(C.AV_PKT_DATA_NEW_EXTRADATA) - PacketSideDataTypePalette = PacketSideDataType(C.AV_PKT_DATA_PALETTE) - PacketSideDataTypeParamChange = PacketSideDataType(C.AV_PKT_DATA_PARAM_CHANGE) - PacketSideDataTypeQualityStats = PacketSideDataType(C.AV_PKT_DATA_QUALITY_STATS) - PacketSideDataTypeReplaygain = PacketSideDataType(C.AV_PKT_DATA_REPLAYGAIN) - PacketSideDataTypeSkipSamples = PacketSideDataType(C.AV_PKT_DATA_SKIP_SAMPLES) - PacketSideDataTypeSpherical = PacketSideDataType(C.AV_PKT_DATA_SPHERICAL) - PacketSideDataTypeStereo3D = PacketSideDataType(C.AV_PKT_DATA_STEREO3D) - PacketSideDataTypeStringsMetadata = PacketSideDataType(C.AV_PKT_DATA_STRINGS_METADATA) - PacketSideDataTypeSubtitlePosition = PacketSideDataType(C.AV_PKT_DATA_SUBTITLE_POSITION) - PacketSideDataTypeWebvttIdentifier = PacketSideDataType(C.AV_PKT_DATA_WEBVTT_IDENTIFIER) - PacketSideDataTypeWebvttSettings = PacketSideDataType(C.AV_PKT_DATA_WEBVTT_SETTINGS) -) - -// https://ffmpeg.org/doxygen/7.0/group__lavc__packet__side__data.html#ga78c05e43a5d021eb10e63b28a541bce3 -func (t PacketSideDataType) Name() string { - return C.GoString(C.av_packet_side_data_name((C.enum_AVPacketSideDataType)(t))) -} - -func (t PacketSideDataType) String() string { - return t.Name() -} diff --git a/packet_side_data_type_test.go b/packet_side_data_type_test.go deleted file mode 100644 index bb11e97..0000000 --- a/packet_side_data_type_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package astiav - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestPacketSideDataType(t *testing.T) { - require.Equal(t, "Display Matrix", PacketSideDataTypeDisplaymatrix.Name()) - require.Equal(t, "Display Matrix", PacketSideDataTypeDisplaymatrix.String()) -} diff --git a/packet_test.go b/packet_test.go index d2c3620..554588f 100644 --- a/packet_test.go +++ b/packet_test.go @@ -74,10 +74,7 @@ func TestPacket(t *testing.T) { pkt5 := AllocPacket() require.NotNil(t, pkt5) defer pkt5.Free() - b = []byte{1, 2, 3, 4} - sd := pkt5.SideData() - require.NoError(t, sd.Add(PacketSideDataTypeAudioServiceType, b)) - require.Equal(t, b, sd.Get(PacketSideDataTypeAudioServiceType)) + testPacketSideData(pkt5.SideData(), t) pkt6 := AllocPacket() require.NotNil(t, pkt6) diff --git a/region_of_interest.go b/region_of_interest.go new file mode 100644 index 0000000..e1c8ebb --- /dev/null +++ b/region_of_interest.go @@ -0,0 +1,13 @@ +package astiav + +//#include +import "C" + +// https://ffmpeg.org/doxygen/7.0/structAVRegionOfInterest.html +type RegionOfInterest struct { + Bottom int + Left int + QuantisationOffset Rational + Right int + Top int +} diff --git a/skip_samples.go b/skip_samples.go new file mode 100644 index 0000000..0e48b37 --- /dev/null +++ b/skip_samples.go @@ -0,0 +1,34 @@ +package astiav + +import ( + "encoding/binary" + "fmt" +) + +// https://ffmpeg.org/doxygen/7.0/group__lavc__packet__side__data.html#gga9a80bfcacc586b483a973272800edb97a2093332d8086d25a04942ede61007f6a +// https://ffmpeg.org/doxygen/7.0/group__lavu__frame.html#ggae01fa7e427274293aacdf2adc17076bca6b0b1ee4315f322922710f65d02a146b +type SkipSamples struct { + ReasonEnd uint8 + ReasonStart uint8 + SkipEnd uint32 + SkipStart uint32 +} + +func newSkipSamplesFromBytes(b []byte) (*SkipSamples, error) { + if len(b) < 10 { + return nil, fmt.Errorf("astiav: invalid length %d < 10", len(b)) + } + return &SkipSamples{ + ReasonEnd: b[9], + ReasonStart: b[8], + SkipEnd: binary.LittleEndian.Uint32(b[4:8]), + SkipStart: binary.LittleEndian.Uint32(b[0:4]), + }, nil +} + +func (ss *SkipSamples) bytes() (b []byte) { + b = binary.LittleEndian.AppendUint32(b, ss.SkipStart) + b = binary.LittleEndian.AppendUint32(b, ss.SkipEnd) + b = append(b, ss.ReasonStart, ss.ReasonEnd) + return b +} diff --git a/skip_samples_test.go b/skip_samples_test.go new file mode 100644 index 0000000..c14fadd --- /dev/null +++ b/skip_samples_test.go @@ -0,0 +1,23 @@ +package astiav + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSkipSamples(t *testing.T) { + _, err := newSkipSamplesFromBytes([]byte("123456789")) + require.Error(t, err) + ss1 := &SkipSamples{ + ReasonEnd: 1, + ReasonStart: 2, + SkipEnd: 3, + SkipStart: 4, + } + b1 := ss1.bytes() + require.Equal(t, []byte{0x4, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x2, 0x1}, b1) + ss2, err := newSkipSamplesFromBytes(b1) + require.NoError(t, err) + require.Equal(t, ss1, ss2) +}