2022-02-05 17:27:03 +08:00
|
|
|
package astiav
|
|
|
|
|
2023-03-23 21:59:40 +08:00
|
|
|
//#cgo pkg-config: libavcodec libavutil
|
2022-02-05 17:27:03 +08:00
|
|
|
//#include <libavcodec/avcodec.h>
|
2023-03-23 21:59:40 +08:00
|
|
|
//#include <libavutil/channel_layout.h>
|
2022-02-05 17:27:03 +08:00
|
|
|
import "C"
|
|
|
|
import (
|
|
|
|
"unsafe"
|
|
|
|
)
|
|
|
|
|
|
|
|
// https://github.com/FFmpeg/FFmpeg/blob/n5.0/libavcodec/codec.h#L202
|
|
|
|
type Codec struct {
|
|
|
|
c *C.struct_AVCodec
|
|
|
|
}
|
|
|
|
|
|
|
|
func newCodecFromC(c *C.struct_AVCodec) *Codec {
|
|
|
|
if c == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return &Codec{c: c}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Codec) Name() string {
|
|
|
|
return C.GoString(c.c.name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Codec) String() string {
|
|
|
|
return c.Name()
|
|
|
|
}
|
|
|
|
|
2023-09-28 21:21:32 +08:00
|
|
|
func (c *Codec) ChannelLayouts() (o []ChannelLayout) {
|
2023-03-23 21:59:40 +08:00
|
|
|
if c.c.ch_layouts == nil {
|
2022-02-05 17:27:03 +08:00
|
|
|
return nil
|
|
|
|
}
|
2023-03-23 21:59:40 +08:00
|
|
|
size := unsafe.Sizeof(*c.c.ch_layouts)
|
2022-02-05 17:27:03 +08:00
|
|
|
for i := 0; ; i++ {
|
2023-09-28 21:21:32 +08:00
|
|
|
v, _ := newChannelLayoutFromC((*C.struct_AVChannelLayout)(unsafe.Pointer(uintptr(unsafe.Pointer(c.c.ch_layouts)) + uintptr(i)*size))).clone()
|
2023-03-23 21:59:40 +08:00
|
|
|
if !v.Valid() {
|
2022-02-05 17:27:03 +08:00
|
|
|
break
|
|
|
|
}
|
2023-03-23 21:59:40 +08:00
|
|
|
o = append(o, v)
|
2022-02-05 17:27:03 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Codec) IsDecoder() bool {
|
|
|
|
return int(C.av_codec_is_decoder(c.c)) != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Codec) IsEncoder() bool {
|
|
|
|
return int(C.av_codec_is_encoder(c.c)) != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Codec) PixelFormats() (o []PixelFormat) {
|
|
|
|
if c.c.pix_fmts == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
size := unsafe.Sizeof(*c.c.pix_fmts)
|
|
|
|
for i := 0; ; i++ {
|
|
|
|
p := *(*C.int)(unsafe.Pointer(uintptr(unsafe.Pointer(c.c.pix_fmts)) + uintptr(i)*size))
|
|
|
|
if p == C.AV_PIX_FMT_NONE {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
o = append(o, PixelFormat(p))
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Codec) SampleFormats() (o []SampleFormat) {
|
|
|
|
if c.c.sample_fmts == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
size := unsafe.Sizeof(*c.c.sample_fmts)
|
|
|
|
for i := 0; ; i++ {
|
|
|
|
p := *(*C.int)(unsafe.Pointer(uintptr(unsafe.Pointer(c.c.sample_fmts)) + uintptr(i)*size))
|
|
|
|
if p == C.AV_SAMPLE_FMT_NONE {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
o = append(o, SampleFormat(p))
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func FindDecoder(id CodecID) *Codec {
|
|
|
|
return newCodecFromC(C.avcodec_find_decoder((C.enum_AVCodecID)(id)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func FindDecoderByName(n string) *Codec {
|
|
|
|
cn := C.CString(n)
|
|
|
|
defer C.free(unsafe.Pointer(cn))
|
|
|
|
return newCodecFromC(C.avcodec_find_decoder_by_name(cn))
|
|
|
|
}
|
|
|
|
|
|
|
|
func FindEncoder(id CodecID) *Codec {
|
|
|
|
return newCodecFromC(C.avcodec_find_encoder((C.enum_AVCodecID)(id)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func FindEncoderByName(n string) *Codec {
|
|
|
|
cn := C.CString(n)
|
|
|
|
defer C.free(unsafe.Pointer(cn))
|
|
|
|
return newCodecFromC(C.avcodec_find_encoder_by_name(cn))
|
|
|
|
}
|
2024-01-25 01:23:12 +08:00
|
|
|
|
|
|
|
func (c *Codec) HardwareConfigs(dt HardwareDeviceType) []CodecHardwareConfig {
|
|
|
|
var configs []CodecHardwareConfig
|
|
|
|
var i int
|
|
|
|
|
|
|
|
for {
|
|
|
|
config := C.avcodec_get_hw_config(c.c, C.int(i))
|
|
|
|
if config == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
configs = append(configs, CodecHardwareConfig{c: config})
|
|
|
|
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
return configs
|
|
|
|
}
|