mirror of
https://github.com/asticode/go-astiav.git
synced 2025-09-26 20:21:15 +08:00
1. Adds hardware_frames_constraints to retrieve valid HWPixelFormats and SWPixelFormats for specific hardware frame configurations. (#151)
2. Implements a HardwareFramesConstraints method in hardware_device_context to obtain these constraints for a given hardware frames context.
This commit is contained in:
@@ -102,14 +102,16 @@ func main() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Merge decoder name with hardware device type name
|
||||
if *decoderCodecName == "" {
|
||||
*decoderCodecName = fmt.Sprintf("%s_%s", is.CodecParameters().CodecID().Name(), *hardwareDeviceTypeName)
|
||||
}
|
||||
|
||||
// Update input stream
|
||||
inputStream = is
|
||||
|
||||
// Find decoder
|
||||
decCodec = astiav.FindDecoder(is.CodecParameters().CodecID())
|
||||
if *decoderCodecName != "" {
|
||||
decCodec = astiav.FindDecoderByName(*decoderCodecName)
|
||||
}
|
||||
decCodec = astiav.FindDecoderByName(*decoderCodecName)
|
||||
|
||||
// No codec
|
||||
if decCodec == nil {
|
||||
@@ -122,20 +124,6 @@ func main() {
|
||||
}
|
||||
c.Add(decCodecContext.Free)
|
||||
|
||||
// Loop through codec hardware configs
|
||||
for _, p := range decCodec.HardwareConfigs() {
|
||||
// Valid hardware config
|
||||
if p.MethodFlags().Has(astiav.CodecHardwareConfigMethodFlagHwDeviceCtx) && p.HardwareDeviceType() == hardwareDeviceType {
|
||||
hardwarePixelFormat = p.PixelFormat()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// No valid hardware pixel format
|
||||
if hardwarePixelFormat == astiav.PixelFormatNone {
|
||||
log.Fatal(errors.New("main: hardware device type not supported by decoder"))
|
||||
}
|
||||
|
||||
// Update codec context
|
||||
if err := is.CodecParameters().ToCodecContext(decCodecContext); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: updating codec context failed: %w", err))
|
||||
@@ -148,6 +136,20 @@ func main() {
|
||||
}
|
||||
c.Add(hardwareDeviceContext.Free)
|
||||
|
||||
hardwareFramesConstraints := hardwareDeviceContext.HardwareFramesConstraints()
|
||||
if hardwareFramesConstraints == nil {
|
||||
log.Fatal("main: hardware frames constraints is nil")
|
||||
return
|
||||
}
|
||||
defer hardwareFramesConstraints.Free()
|
||||
|
||||
validHardwarePixelFormats := hardwareFramesConstraints.ValidHardwarePixelFormats()
|
||||
if len(validHardwarePixelFormats) == 0 {
|
||||
log.Fatal("main: no valid hardware pixel formats")
|
||||
return
|
||||
}
|
||||
hardwarePixelFormat = validHardwarePixelFormats[0]
|
||||
|
||||
// Update decoder context
|
||||
decCodecContext.SetHardwareDeviceContext(hardwareDeviceContext)
|
||||
decCodecContext.SetPixelFormatCallback(func(pfs []astiav.PixelFormat) astiav.PixelFormat {
|
||||
@@ -160,9 +162,9 @@ func main() {
|
||||
return astiav.PixelFormatNone
|
||||
})
|
||||
|
||||
// Open codec context
|
||||
// Open decoder context
|
||||
if err := decCodecContext.Open(decCodec, nil); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: opening codec context failed: %w", err))
|
||||
log.Fatal(fmt.Errorf("main: opening decoder context failed: %w", err))
|
||||
}
|
||||
break
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/asticode/go-astiav"
|
||||
@@ -55,6 +56,19 @@ func main() {
|
||||
}
|
||||
defer hardwareDeviceContext.Free()
|
||||
|
||||
hardwareFramesConstraints := hardwareDeviceContext.HardwareFramesConstraints()
|
||||
if hardwareFramesConstraints == nil {
|
||||
log.Fatal("main: hardware frames constraints is nil")
|
||||
return
|
||||
}
|
||||
defer hardwareFramesConstraints.Free()
|
||||
|
||||
validHardwarePixelFormats := hardwareFramesConstraints.ValidHardwarePixelFormats()
|
||||
if len(validHardwarePixelFormats) == 0 {
|
||||
log.Fatal("main: no valid hardware pixel formats")
|
||||
return
|
||||
}
|
||||
|
||||
// Find encoder codec
|
||||
encCodec := astiav.FindEncoderByName(*encoderCodecName)
|
||||
if encCodec == nil {
|
||||
@@ -72,6 +86,8 @@ func main() {
|
||||
hardwarePixelFormat := astiav.FindPixelFormatByName(*hardwarePixelFormatName)
|
||||
if hardwarePixelFormat == astiav.PixelFormatNone {
|
||||
log.Fatal("main: hardware pixel format not found")
|
||||
} else if !slices.Contains(validHardwarePixelFormats, hardwarePixelFormat) {
|
||||
log.Fatalf("main: hardware pixel format not supported : %s", hardwarePixelFormat)
|
||||
}
|
||||
|
||||
// Set codec context
|
||||
@@ -88,10 +104,18 @@ func main() {
|
||||
}
|
||||
defer hardwareFramesContext.Free()
|
||||
|
||||
validSoftwarePixelFormats := hardwareFramesConstraints.ValidSoftwarePixelFormats()
|
||||
if len(validSoftwarePixelFormats) == 0 {
|
||||
log.Fatal("main: no valid software pixel formats")
|
||||
return
|
||||
}
|
||||
|
||||
// Get software pixel format
|
||||
softwarePixelFormat := astiav.FindPixelFormatByName(*softwarePixelFormatName)
|
||||
if softwarePixelFormat == astiav.PixelFormatNone {
|
||||
log.Fatal("main: software pixel format not found")
|
||||
} else if !slices.Contains(validSoftwarePixelFormats, softwarePixelFormat) {
|
||||
log.Fatalf("main: software pixel format not supported : %s", softwarePixelFormat)
|
||||
}
|
||||
|
||||
// Set hardware frame content
|
||||
|
@@ -30,6 +30,11 @@ func CreateHardwareDeviceContext(t HardwareDeviceType, device string, options *D
|
||||
return &hdc, nil
|
||||
}
|
||||
|
||||
// https://ffmpeg.org/doxygen/7.0/hwcontext_8c.html#a80f4c1184e1758150b6d9bc0adf2c1df
|
||||
func (hdc *HardwareDeviceContext) HardwareFramesConstraints() *HardwareFramesConstraints {
|
||||
return newHardwareFramesConstraintsFromC(C.av_hwdevice_get_hwframe_constraints(hdc.c, nil))
|
||||
}
|
||||
|
||||
func (hdc *HardwareDeviceContext) Free() {
|
||||
if hdc.c != nil {
|
||||
C.av_buffer_unref(&hdc.c)
|
||||
|
70
hardware_frames_constraints.go
Normal file
70
hardware_frames_constraints.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package astiav
|
||||
|
||||
//#include <libavutil/hwcontext.h>
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
// https://ffmpeg.org/doxygen/7.0/structAVHWFramesConstraints.html
|
||||
type HardwareFramesConstraints struct {
|
||||
c *C.AVHWFramesConstraints
|
||||
}
|
||||
|
||||
func newHardwareFramesConstraintsFromC(c *C.AVHWFramesConstraints) *HardwareFramesConstraints {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return &HardwareFramesConstraints{c: c}
|
||||
}
|
||||
|
||||
func (hfc *HardwareFramesConstraints) pixelFormats(formats *C.enum_AVPixelFormat) (o []PixelFormat) {
|
||||
if formats == nil {
|
||||
return nil
|
||||
}
|
||||
size := unsafe.Sizeof(*formats)
|
||||
for i := 0; ; i++ {
|
||||
p := *(*C.int)(unsafe.Pointer(uintptr(unsafe.Pointer(formats)) + uintptr(i)*size))
|
||||
if p == C.AV_PIX_FMT_NONE {
|
||||
break
|
||||
}
|
||||
o = append(o, PixelFormat(p))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// https://ffmpeg.org/doxygen/7.0/structAVHWFramesConstraints.html#a4258bbe81f927b76b7ca5af44ba7ef6b
|
||||
func (hfc *HardwareFramesConstraints) ValidHardwarePixelFormats() (o []PixelFormat) {
|
||||
return hfc.pixelFormats(hfc.c.valid_hw_formats)
|
||||
}
|
||||
|
||||
// https://ffmpeg.org/doxygen/7.0/structAVHWFramesConstraints.html#aabea88093c6f85d6185ffb0852a2217f
|
||||
func (hfc *HardwareFramesConstraints) ValidSoftwarePixelFormats() (o []PixelFormat) {
|
||||
return hfc.pixelFormats(hfc.c.valid_sw_formats)
|
||||
}
|
||||
|
||||
// https://ffmpeg.org/doxygen/7.0/structAVHWFramesConstraints.html#af220776925452091085139081d5d7251
|
||||
func (hfc *HardwareFramesConstraints) MinWidth() int {
|
||||
return int(hfc.c.min_width)
|
||||
}
|
||||
|
||||
// https://ffmpeg.org/doxygen/7.0/structAVHWFramesConstraints.html#a3f1aec6d1c90f77837875c2a3598be46
|
||||
func (hfc *HardwareFramesConstraints) MinHeight() int {
|
||||
return int(hfc.c.min_height)
|
||||
}
|
||||
|
||||
// https://ffmpeg.org/doxygen/7.0/structAVHWFramesConstraints.html#a34e06e3397af2b83de9d78f893bf4168
|
||||
func (hfc *HardwareFramesConstraints) MaxWidth() int {
|
||||
return int(hfc.c.max_width)
|
||||
}
|
||||
|
||||
// https://ffmpeg.org/doxygen/7.0/structAVHWFramesConstraints.html#af5d3a683727f7b92abca7b7114d4e15c
|
||||
func (hfc *HardwareFramesConstraints) MaxHeight() int {
|
||||
return int(hfc.c.max_height)
|
||||
}
|
||||
|
||||
// https://ffmpeg.org/doxygen/7.0/hwcontext_8c.html#a29da7fa7ffa73266d1cbfccb116ed634
|
||||
func (hfc *HardwareFramesConstraints) Free() {
|
||||
if hfc.c != nil {
|
||||
C.av_hwframe_constraints_free(&hfc.c)
|
||||
hfc.c = nil
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user