mirror of
https://github.com/asticode/go-astiav.git
synced 2025-09-27 04:26:30 +08:00
Now compatible with n6.1.1
This commit is contained in:
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
env:
|
||||
FFMPEG_VERSION: n5.1.2
|
||||
FFMPEG_VERSION: n6.1.1
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
2
Makefile
2
Makefile
@@ -1,4 +1,4 @@
|
||||
version=n5.1.2
|
||||
version=n6.1.1
|
||||
srcPath=tmp/$(version)/src
|
||||
patchPath=
|
||||
platform=
|
||||
|
26
README.md
26
README.md
@@ -5,7 +5,7 @@
|
||||
|
||||
`astiav` is a Golang library providing C bindings for [ffmpeg](https://github.com/FFmpeg/FFmpeg)
|
||||
|
||||
It's only compatible with `ffmpeg` `n5.1.2`.
|
||||
It's only compatible with `ffmpeg` `n6.1.1`.
|
||||
|
||||
Its main goals are to:
|
||||
|
||||
@@ -14,23 +14,23 @@ Its main goals are to:
|
||||
- typed constants and flags
|
||||
- struct-based functions
|
||||
- ...
|
||||
- [x] provide the GO version of [ffmpeg examples](https://github.com/FFmpeg/FFmpeg/tree/n5.1.2/doc/examples)
|
||||
- [x] provide the GO version of [ffmpeg examples](https://github.com/FFmpeg/FFmpeg/tree/n6.1.1/doc/examples)
|
||||
- [x] be fully tested
|
||||
|
||||
# Examples
|
||||
|
||||
Examples are located in the [examples](examples) directory and mirror as much as possible the [ffmpeg examples](https://github.com/FFmpeg/FFmpeg/tree/n5.1.2/doc/examples).
|
||||
Examples are located in the [examples](examples) directory and mirror as much as possible the [ffmpeg examples](https://github.com/FFmpeg/FFmpeg/tree/n6.1.1/doc/examples).
|
||||
|
||||
|name|astiav|ffmpeg|
|
||||
|---|---|---|
|
||||
|BitStream Filtering|[see](examples/bit_stream_filtering/main.go)|X
|
||||
|Custom IO Demuxing|[see](examples/custom_io_demuxing/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/doc/examples/avio_reading.c)
|
||||
|Demuxing/Decoding|[see](examples/demuxing_decoding/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/doc/examples/demuxing_decoding.c)
|
||||
|Filtering|[see](examples/filtering/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/doc/examples/filtering_video.c)
|
||||
|Hardware Decoding|[see](examples/hardware_decoding/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/doc/examples/hw_decode.c)
|
||||
|Remuxing|[see](examples/remuxing/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/doc/examples/remuxing.c)
|
||||
|Scaling|[see](examples/scaling/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/doc/examples/scaling_video.c)
|
||||
|Transcoding|[see](examples/transcoding/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/doc/examples/transcoding.c)
|
||||
|Custom IO Demuxing|[see](examples/custom_io_demuxing/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n6.1.1/doc/examples/avio_reading.c)
|
||||
|Demuxing/Decoding|[see](examples/demuxing_decoding/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n6.1.1/doc/examples/demuxing_decoding.c)
|
||||
|Filtering|[see](examples/filtering/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n6.1.1/doc/examples/filtering_video.c)
|
||||
|Hardware Decoding|[see](examples/hardware_decoding/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n6.1.1/doc/examples/hw_decode.c)
|
||||
|Remuxing|[see](examples/remuxing/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n6.1.1/doc/examples/remuxing.c)
|
||||
|Scaling|[see](examples/scaling/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n6.1.1/doc/examples/scaling_video.c)
|
||||
|Transcoding|[see](examples/transcoding/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n6.1.1/doc/examples/transcoding.c)
|
||||
|
||||
*Tip: you can use the video sample located in the `testdata` directory for your tests*
|
||||
|
||||
@@ -49,9 +49,9 @@ For your GO code to pick up `ffmpeg` dependency automatically, you'll need to ad
|
||||
(don't forget to replace `{{ path to your working directory }}` with the absolute path to your working directory)
|
||||
|
||||
```sh
|
||||
export CGO_LDFLAGS="-L{{ path to your working directory }}/tmp/n5.1.2/lib/",
|
||||
export CGO_CFLAGS="-I{{ path to your working directory }}/tmp/n5.1.2/include/",
|
||||
export PKG_CONFIG_PATH="{{ path to your working directory }}/tmp/n5.1.2/lib/pkgconfig",
|
||||
export CGO_LDFLAGS="-L{{ path to your working directory }}/tmp/n6.1.1/lib/",
|
||||
export CGO_CFLAGS="-I{{ path to your working directory }}/tmp/n6.1.1/include/",
|
||||
export PKG_CONFIG_PATH="{{ path to your working directory }}/tmp/n6.1.1/lib/pkgconfig",
|
||||
```
|
||||
|
||||
# Why astiav?
|
||||
|
@@ -23,6 +23,7 @@ AVChannelLayout *c2goChannelLayout5Point1Back = &(AVChannelLayout)AV_CHANNEL
|
||||
AVChannelLayout *c2goChannelLayout6Point0 = &(AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT0;
|
||||
AVChannelLayout *c2goChannelLayout6Point0Front = &(AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT0_FRONT;
|
||||
AVChannelLayout *c2goChannelLayoutHexagonal = &(AVChannelLayout)AV_CHANNEL_LAYOUT_HEXAGONAL;
|
||||
AVChannelLayout *c2goChannelLayout3Point1Point2 = &(AVChannelLayout)AV_CHANNEL_LAYOUT_3POINT1POINT2;
|
||||
AVChannelLayout *c2goChannelLayout6Point1 = &(AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT1;
|
||||
AVChannelLayout *c2goChannelLayout6Point1Back = &(AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT1_BACK;
|
||||
AVChannelLayout *c2goChannelLayout6Point1Front = &(AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT1_FRONT;
|
||||
@@ -31,9 +32,16 @@ AVChannelLayout *c2goChannelLayout7Point0Front = &(AVChannelLayout)AV_CHANNEL
|
||||
AVChannelLayout *c2goChannelLayout7Point1 = &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1;
|
||||
AVChannelLayout *c2goChannelLayout7Point1Wide = &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1_WIDE;
|
||||
AVChannelLayout *c2goChannelLayout7Point1WideBack = &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK;
|
||||
AVChannelLayout *c2goChannelLayout5Point1Point2Back = &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1POINT2_BACK;
|
||||
AVChannelLayout *c2goChannelLayoutOctagonal = &(AVChannelLayout)AV_CHANNEL_LAYOUT_OCTAGONAL;
|
||||
AVChannelLayout *c2goChannelLayoutCube = &(AVChannelLayout)AV_CHANNEL_LAYOUT_CUBE;
|
||||
AVChannelLayout *c2goChannelLayout5Point1Point4Back = &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1POINT4_BACK;
|
||||
AVChannelLayout *c2goChannelLayout7Point1Point2 = &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1POINT2;
|
||||
AVChannelLayout *c2goChannelLayout7Point1Point4Back = &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1POINT4_BACK;
|
||||
AVChannelLayout *c2goChannelLayoutHexadecagonal = &(AVChannelLayout)AV_CHANNEL_LAYOUT_HEXADECAGONAL;
|
||||
AVChannelLayout *c2goChannelLayoutStereoDownmix = &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX;
|
||||
AVChannelLayout *c2goChannelLayout22Point2 = &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2;
|
||||
AVChannelLayout *c2goChannelLayout7Point1TopBack = &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1_TOP_BACK;
|
||||
|
||||
*/
|
||||
import "C"
|
||||
@@ -58,6 +66,7 @@ var (
|
||||
ChannelLayout6Point0 = newChannelLayoutFromC(C.c2goChannelLayout6Point0)
|
||||
ChannelLayout6Point0Front = newChannelLayoutFromC(C.c2goChannelLayout6Point0Front)
|
||||
ChannelLayoutHexagonal = newChannelLayoutFromC(C.c2goChannelLayoutHexagonal)
|
||||
ChannelLayout3Point1Point2 = newChannelLayoutFromC(C.c2goChannelLayout3Point1Point2)
|
||||
ChannelLayout6Point1 = newChannelLayoutFromC(C.c2goChannelLayout6Point1)
|
||||
ChannelLayout6Point1Back = newChannelLayoutFromC(C.c2goChannelLayout6Point1Back)
|
||||
ChannelLayout6Point1Front = newChannelLayoutFromC(C.c2goChannelLayout6Point1Front)
|
||||
@@ -66,9 +75,16 @@ var (
|
||||
ChannelLayout7Point1 = newChannelLayoutFromC(C.c2goChannelLayout7Point1)
|
||||
ChannelLayout7Point1Wide = newChannelLayoutFromC(C.c2goChannelLayout7Point1Wide)
|
||||
ChannelLayout7Point1WideBack = newChannelLayoutFromC(C.c2goChannelLayout7Point1WideBack)
|
||||
ChannelLayout5Point1Point2Back = newChannelLayoutFromC(C.c2goChannelLayout5Point1Point2Back)
|
||||
ChannelLayoutOctagonal = newChannelLayoutFromC(C.c2goChannelLayoutOctagonal)
|
||||
ChannelLayoutCube = newChannelLayoutFromC(C.c2goChannelLayoutCube)
|
||||
ChannelLayout5Point1Point4Back = newChannelLayoutFromC(C.c2goChannelLayout5Point1Point4Back)
|
||||
ChannelLayout7Point1Point2 = newChannelLayoutFromC(C.c2goChannelLayout7Point1Point2)
|
||||
ChannelLayout7Point1Point4Back = newChannelLayoutFromC(C.c2goChannelLayout7Point1Point4Back)
|
||||
ChannelLayoutHexadecagonal = newChannelLayoutFromC(C.c2goChannelLayoutHexadecagonal)
|
||||
ChannelLayoutStereoDownmix = newChannelLayoutFromC(C.c2goChannelLayoutStereoDownmix)
|
||||
ChannelLayout22Point2 = newChannelLayoutFromC(C.c2goChannelLayout22Point2)
|
||||
ChannelLayout7Point1TopBack = newChannelLayoutFromC(C.c2goChannelLayout7Point1TopBack)
|
||||
)
|
||||
|
||||
type ChannelLayout struct {
|
||||
@@ -97,6 +113,9 @@ func (l ChannelLayout) Describe(b []byte) (int, error) {
|
||||
if ret < 0 {
|
||||
return 0, newError(ret)
|
||||
}
|
||||
if ret > 0 && b[ret-1] == '\x00' {
|
||||
ret -= 1
|
||||
}
|
||||
return int(ret), nil
|
||||
}
|
||||
|
||||
|
@@ -18,7 +18,6 @@ const (
|
||||
CodecContextFlagLoopFilter = CodecContextFlag(C.AV_CODEC_FLAG_LOOP_FILTER)
|
||||
CodecContextFlagGray = CodecContextFlag(C.AV_CODEC_FLAG_GRAY)
|
||||
CodecContextFlagPsnr = CodecContextFlag(C.AV_CODEC_FLAG_PSNR)
|
||||
CodecContextFlagTruncated = CodecContextFlag(C.AV_CODEC_FLAG_TRUNCATED)
|
||||
CodecContextFlagInterlacedDct = CodecContextFlag(C.AV_CODEC_FLAG_INTERLACED_DCT)
|
||||
CodecContextFlagLowDelay = CodecContextFlag(C.AV_CODEC_FLAG_LOW_DELAY)
|
||||
CodecContextFlagGlobalHeader = CodecContextFlag(C.AV_CODEC_FLAG_GLOBAL_HEADER)
|
||||
@@ -35,11 +34,11 @@ const (
|
||||
CodecFlag2Fast = CodecContextFlag2(C.AV_CODEC_FLAG2_FAST)
|
||||
CodecFlag2NoOutput = CodecContextFlag2(C.AV_CODEC_FLAG2_NO_OUTPUT)
|
||||
CodecFlag2LocalHeader = CodecContextFlag2(C.AV_CODEC_FLAG2_LOCAL_HEADER)
|
||||
CodecFlag2DropFrameTimecode = CodecContextFlag2(C.AV_CODEC_FLAG2_DROP_FRAME_TIMECODE)
|
||||
CodecFlag2Chunks = CodecContextFlag2(C.AV_CODEC_FLAG2_CHUNKS)
|
||||
CodecFlag2IgnoreCrop = CodecContextFlag2(C.AV_CODEC_FLAG2_IGNORE_CROP)
|
||||
CodecFlag2ShowAll = CodecContextFlag2(C.AV_CODEC_FLAG2_SHOW_ALL)
|
||||
CodecFlag2ExportMvs = CodecContextFlag2(C.AV_CODEC_FLAG2_EXPORT_MVS)
|
||||
CodecFlag2SkipManual = CodecContextFlag2(C.AV_CODEC_FLAG2_SKIP_MANUAL)
|
||||
CodecFlag2RoFlushNoop = CodecContextFlag2(C.AV_CODEC_FLAG2_RO_FLUSH_NOOP)
|
||||
CodecFlag2IccProfiles = CodecContextFlag2(C.AV_CODEC_FLAG2_ICC_PROFILES)
|
||||
)
|
||||
|
@@ -160,6 +160,10 @@ func (cp *CodecParameters) SetSampleAspectRatio(r Rational) {
|
||||
cp.c.sample_aspect_ratio = r.c
|
||||
}
|
||||
|
||||
func (cp *CodecParameters) SideData() *PacketSideData {
|
||||
return newPacketSideDataFromC(&cp.c.coded_side_data, &cp.c.nb_coded_side_data)
|
||||
}
|
||||
|
||||
func (cp *CodecParameters) SampleFormat() SampleFormat {
|
||||
return SampleFormat(cp.c.format)
|
||||
}
|
||||
|
@@ -102,4 +102,7 @@ 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))
|
||||
}
|
||||
|
@@ -28,6 +28,10 @@ func TestCodec(t *testing.T) {
|
||||
ChannelLayout5Point0Back,
|
||||
ChannelLayout5Point1Back,
|
||||
ChannelLayout7Point1WideBack,
|
||||
ChannelLayout6Point1Back,
|
||||
ChannelLayout7Point1,
|
||||
ChannelLayout22Point2,
|
||||
ChannelLayout5Point1Point2Back,
|
||||
}
|
||||
gls := c.ChannelLayouts()
|
||||
require.Len(t, gls, len(els))
|
||||
|
@@ -20,7 +20,6 @@ const (
|
||||
FormatContextFlagFlushPackets = FormatContextFlag(C.AVFMT_FLAG_FLUSH_PACKETS)
|
||||
FormatContextFlagBitexact = FormatContextFlag(C.AVFMT_FLAG_BITEXACT)
|
||||
FormatContextFlagSortDts = FormatContextFlag(C.AVFMT_FLAG_SORT_DTS)
|
||||
FormatContextFlagPrivOpt = FormatContextFlag(C.AVFMT_FLAG_PRIV_OPT)
|
||||
FormatContextFlagFastSeek = FormatContextFlag(C.AVFMT_FLAG_FAST_SEEK)
|
||||
FormatContextFlagShortest = FormatContextFlag(C.AVFMT_FLAG_SHORTEST)
|
||||
FormatContextFlagAutoBsf = FormatContextFlag(C.AVFMT_FLAG_AUTO_BSF)
|
||||
|
@@ -13,9 +13,9 @@ func TestFormatContext(t *testing.T) {
|
||||
require.Len(t, ss, 2)
|
||||
s1 := ss[0]
|
||||
|
||||
require.Equal(t, int64(607583), fc1.BitRate())
|
||||
require.Equal(t, int64(607664), fc1.BitRate())
|
||||
require.Equal(t, NewFormatContextCtxFlags(0), fc1.CtxFlags())
|
||||
require.Equal(t, int64(5014000), fc1.Duration())
|
||||
require.Equal(t, int64(5013333), fc1.Duration())
|
||||
require.True(t, fc1.EventFlags().Has(FormatEventFlagMetadataUpdated))
|
||||
require.True(t, fc1.Flags().Has(FormatContextFlagAutoBsf))
|
||||
require.Equal(t, NewRational(24, 1), fc1.GuessFrameRate(s1, nil))
|
||||
@@ -33,7 +33,7 @@ func TestFormatContext(t *testing.T) {
|
||||
|
||||
sdp, err := fc1.SDPCreate()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "v=0\r\no=- 0 0 IN IP4 127.0.0.1\r\ns=Big Buck Bunny\r\nt=0 0\r\na=tool:libavformat LIBAVFORMAT_VERSION\r\nm=video 0 RTP/AVP 96\r\nb=AS:441\r\na=rtpmap:96 H264/90000\r\na=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z0LADasgKDPz4CIAAAMAAgAAAwBhHihUkA==,aM48gA==; profile-level-id=42C00D\r\na=control:streamid=0\r\nm=audio 0 RTP/AVP 97\r\nb=AS:161\r\na=rtpmap:97 MPEG4-GENERIC/48000/2\r\na=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=1190\r\na=control:streamid=1\r\n", sdp)
|
||||
require.Equal(t, "v=0\r\no=- 0 0 IN IP4 127.0.0.1\r\ns=Big Buck Bunny\r\nt=0 0\r\na=tool:libavformat 60.16.100\r\nm=video 0 RTP/AVP 96\r\nb=AS:441\r\na=rtpmap:96 H264/90000\r\na=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z0LADasgKDPz4CIAAAMAAgAAAwBhHihUkA==,aM48gA==; profile-level-id=42C00D\r\na=control:streamid=0\r\nm=audio 0 RTP/AVP 97\r\nb=AS:161\r\na=rtpmap:97 MPEG4-GENERIC/48000/2\r\na=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=1190\r\na=control:streamid=1\r\n", sdp)
|
||||
|
||||
fc2, err := AllocOutputFormatContext(nil, "", "/tmp/test.mp4")
|
||||
require.NoError(t, err)
|
||||
|
@@ -15,7 +15,7 @@ WORKDIR /opt/ffmpeg/src
|
||||
|
||||
RUN \
|
||||
git clone https://github.com/FFmpeg/FFmpeg /opt/ffmpeg/src && \
|
||||
git checkout n5.1.2
|
||||
git checkout n6.1.1
|
||||
|
||||
RUN \
|
||||
./configure --prefix=.. && \
|
||||
|
18
packet.go
18
packet.go
@@ -74,22 +74,8 @@ func (p *Packet) SetPts(v int64) {
|
||||
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 {
|
||||
return bytesFromC(func(size *C.size_t) *C.uint8_t {
|
||||
return C.av_packet_get_side_data(p.c, (C.enum_AVPacketSideDataType)(t), size)
|
||||
})
|
||||
func (p *Packet) SideData() *PacketSideData {
|
||||
return newPacketSideDataFromC(&p.c.side_data, &p.c.side_data_elems)
|
||||
}
|
||||
|
||||
func (p *Packet) Size() int {
|
||||
|
50
packet_side_data.go
Normal file
50
packet_side_data.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package astiav
|
||||
|
||||
//#cgo pkg-config: libavcodec
|
||||
//#include <libavcodec/avcodec.h>
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// https://github.com/FFmpeg/FFmpeg/blob/n6.1.1/libavcodec/packet.h#L342
|
||||
type PacketSideData struct {
|
||||
sd **C.struct_AVPacketSideData
|
||||
size *C.int
|
||||
}
|
||||
|
||||
func newPacketSideDataFromC(sd **C.struct_AVPacketSideData, size *C.int) *PacketSideData {
|
||||
return &PacketSideData{
|
||||
sd: sd,
|
||||
size: size,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *PacketSideData) Add(t PacketSideDataType, 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)
|
||||
if sd == nil {
|
||||
return errors.New("astiav: nil pointer")
|
||||
}
|
||||
|
||||
C.memcpy(unsafe.Pointer(sd.data), unsafe.Pointer(&b[0]), C.size_t(len(b)))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *PacketSideData) Get(t PacketSideDataType) []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))
|
||||
if sd == nil {
|
||||
return nil
|
||||
}
|
||||
*size = sd.size
|
||||
return sd.data
|
||||
})
|
||||
}
|
16
packet_side_data_test.go
Normal file
16
packet_side_data_test.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package astiav
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
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))
|
||||
}
|
@@ -37,3 +37,11 @@ const (
|
||||
PacketSideDataTypeWebvttIdentifier = PacketSideDataType(C.AV_PKT_DATA_WEBVTT_IDENTIFIER)
|
||||
PacketSideDataTypeWebvttSettings = PacketSideDataType(C.AV_PKT_DATA_WEBVTT_SETTINGS)
|
||||
)
|
||||
|
||||
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()
|
||||
}
|
||||
|
12
packet_side_data_type_test.go
Normal file
12
packet_side_data_type_test.go
Normal file
@@ -0,0 +1,12 @@
|
||||
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())
|
||||
}
|
@@ -75,8 +75,9 @@ func TestPacket(t *testing.T) {
|
||||
require.NotNil(t, pkt5)
|
||||
defer pkt5.Free()
|
||||
b = []byte{1, 2, 3, 4}
|
||||
require.NoError(t, pkt5.AddSideData(PacketSideDataTypeAudioServiceType, b))
|
||||
require.Equal(t, b, pkt5.SideData(PacketSideDataTypeAudioServiceType))
|
||||
sd := pkt5.SideData()
|
||||
require.NoError(t, sd.Add(PacketSideDataTypeAudioServiceType, b))
|
||||
require.Equal(t, b, sd.Get(PacketSideDataTypeAudioServiceType))
|
||||
|
||||
pkt6 := AllocPacket()
|
||||
require.NotNil(t, pkt6)
|
||||
|
24
stream.go
24
stream.go
@@ -3,10 +3,6 @@ package astiav
|
||||
//#cgo pkg-config: libavformat
|
||||
//#include <libavformat/avformat.h>
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// https://github.com/FFmpeg/FFmpeg/blob/n5.0/libavformat/avformat.h#L937
|
||||
type Stream struct {
|
||||
@@ -80,26 +76,6 @@ func (s *Stream) SetSampleAspectRatio(r Rational) {
|
||||
s.c.sample_aspect_ratio = r.c
|
||||
}
|
||||
|
||||
func (s *Stream) SideData(t PacketSideDataType) []byte {
|
||||
return bytesFromC(func(size *C.size_t) *C.uint8_t {
|
||||
return C.av_stream_get_side_data(s.c, (C.enum_AVPacketSideDataType)(t), size)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Stream) AddSideData(t PacketSideDataType, d []byte) error {
|
||||
if len(d) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ptr := C.av_stream_new_side_data(s.c, (C.enum_AVPacketSideDataType)(t), C.size_t(len(d)))
|
||||
if ptr == nil {
|
||||
return errors.New("astiav: nil pointer")
|
||||
}
|
||||
|
||||
C.memcpy(unsafe.Pointer(ptr), unsafe.Pointer(&d[0]), C.size_t(len(d)))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Stream) StartTime() int64 {
|
||||
return int64(s.c.start_time)
|
||||
}
|
||||
|
@@ -23,7 +23,6 @@ func TestStream(t *testing.T) {
|
||||
require.Equal(t, int64(120), s1.NbFrames())
|
||||
require.Equal(t, NewRational(24, 1), s1.RFrameRate())
|
||||
require.Equal(t, NewRational(1, 1), s1.SampleAspectRatio())
|
||||
require.Equal(t, []byte{}, s1.SideData(PacketSideDataTypeNb))
|
||||
require.Equal(t, int64(0), s1.StartTime())
|
||||
require.Equal(t, NewRational(1, 12288), s1.TimeBase())
|
||||
|
||||
@@ -44,8 +43,6 @@ func TestStream(t *testing.T) {
|
||||
require.Equal(t, NewRational(2, 1), s1.RFrameRate())
|
||||
s1.SetSampleAspectRatio(NewRational(2, 1))
|
||||
require.Equal(t, NewRational(2, 1), s1.SampleAspectRatio())
|
||||
require.NoError(t, s1.AddSideData(PacketSideDataTypeEncryptionInfo, []byte("test")))
|
||||
require.Equal(t, []byte("test"), s1.SideData(PacketSideDataTypeEncryptionInfo))
|
||||
s1.SetTimeBase(NewRational(1, 1))
|
||||
require.Equal(t, NewRational(1, 1), s1.TimeBase())
|
||||
}
|
||||
|
Reference in New Issue
Block a user