Skip to content

Commit 1db5528

Browse files
shim: add codec field helpers for FFmpeg 7+; use shim on macOS
1 parent 4874413 commit 1db5528

File tree

6 files changed

+376
-3
lines changed

6 files changed

+376
-3
lines changed

avcodec/avcodec.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/ebitengine/purego"
1212
"github.com/obinnaokechukwu/ffgo/avutil"
1313
"github.com/obinnaokechukwu/ffgo/internal/bindings"
14+
ffshim "github.com/obinnaokechukwu/ffgo/internal/shim"
1415
)
1516

1617
// Codec is an opaque FFmpeg AVCodec pointer.
@@ -523,6 +524,9 @@ func GetCtxWidth(ctx Context) int32 {
523524
if ctx == nil {
524525
return 0
525526
}
527+
if v, err := ffshim.CodecCtxWidth(ctx); err == nil {
528+
return v
529+
}
526530
return *(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxWidth))
527531
}
528532

@@ -531,6 +535,9 @@ func SetCtxWidth(ctx Context, width int32) {
531535
if ctx == nil {
532536
return
533537
}
538+
if err := ffshim.CodecCtxSetWidth(ctx, width); err == nil {
539+
return
540+
}
534541
*(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxWidth)) = width
535542
}
536543

@@ -539,6 +546,9 @@ func GetCtxHeight(ctx Context) int32 {
539546
if ctx == nil {
540547
return 0
541548
}
549+
if v, err := ffshim.CodecCtxHeight(ctx); err == nil {
550+
return v
551+
}
542552
return *(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxHeight))
543553
}
544554

@@ -547,6 +557,9 @@ func SetCtxHeight(ctx Context, height int32) {
547557
if ctx == nil {
548558
return
549559
}
560+
if err := ffshim.CodecCtxSetHeight(ctx, height); err == nil {
561+
return
562+
}
550563
*(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxHeight)) = height
551564
}
552565

@@ -555,6 +568,9 @@ func GetCtxPixFmt(ctx Context) int32 {
555568
if ctx == nil {
556569
return -1
557570
}
571+
if v, err := ffshim.CodecCtxPixFmt(ctx); err == nil {
572+
return v
573+
}
558574
return *(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxPixFmt))
559575
}
560576

@@ -563,6 +579,9 @@ func SetCtxPixFmt(ctx Context, fmt int32) {
563579
if ctx == nil {
564580
return
565581
}
582+
if err := ffshim.CodecCtxSetPixFmt(ctx, fmt); err == nil {
583+
return
584+
}
566585
*(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxPixFmt)) = fmt
567586
}
568587

@@ -571,6 +590,9 @@ func SetCtxTimeBase(ctx Context, num, den int32) {
571590
if ctx == nil {
572591
return
573592
}
593+
if err := ffshim.CodecCtxSetTimeBase(ctx, num, den); err == nil {
594+
return
595+
}
574596
*(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxTimeBase)) = num
575597
*(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxTimeBase + 4)) = den
576598
}
@@ -620,6 +642,9 @@ func SetCtxFramerate(ctx Context, num, den int32) {
620642
if ctx == nil {
621643
return
622644
}
645+
if err := ffshim.CodecCtxSetFramerate(ctx, num, den); err == nil {
646+
return
647+
}
623648
*(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxFramerate)) = num
624649
*(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxFramerate + 4)) = den
625650
}
@@ -752,6 +777,9 @@ func GetCtxTimeBase(ctx Context) avutil.Rational {
752777
if ctx == nil {
753778
return avutil.Rational{}
754779
}
780+
if num, den, err := ffshim.CodecCtxTimeBase(ctx); err == nil {
781+
return avutil.NewRational(num, den)
782+
}
755783
num := *(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxTimeBase))
756784
den := *(*int32)(unsafe.Pointer(uintptr(ctx) + offsetCtxTimeBase + 4))
757785
return avutil.NewRational(num, den)

avformat/avformat.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/obinnaokechukwu/ffgo/avcodec"
1313
"github.com/obinnaokechukwu/ffgo/avutil"
1414
"github.com/obinnaokechukwu/ffgo/internal/bindings"
15+
ffshim "github.com/obinnaokechukwu/ffgo/internal/shim"
1516
)
1617

1718
// FormatContext is an opaque FFmpeg AVFormatContext pointer.
@@ -704,6 +705,9 @@ func GetCodecParWidth(par avcodec.Parameters) int32 {
704705
if par == nil {
705706
return 0
706707
}
708+
if v, err := ffshim.CodecParWidth(par); err == nil {
709+
return v
710+
}
707711
return *(*int32)(unsafe.Pointer(uintptr(par) + offsetCodecParWidth))
708712
}
709713

@@ -712,6 +716,9 @@ func GetCodecParHeight(par avcodec.Parameters) int32 {
712716
if par == nil {
713717
return 0
714718
}
719+
if v, err := ffshim.CodecParHeight(par); err == nil {
720+
return v
721+
}
715722
return *(*int32)(unsafe.Pointer(uintptr(par) + offsetCodecParHeight))
716723
}
717724

@@ -720,6 +727,9 @@ func GetCodecParFormat(par avcodec.Parameters) int32 {
720727
if par == nil {
721728
return -1
722729
}
730+
if v, err := ffshim.CodecParFormat(par); err == nil {
731+
return v
732+
}
723733
return *(*int32)(unsafe.Pointer(uintptr(par) + offsetCodecParFormat))
724734
}
725735

@@ -728,6 +738,9 @@ func GetCodecParSampleRate(par avcodec.Parameters) int32 {
728738
if par == nil {
729739
return 0
730740
}
741+
if v, err := ffshim.CodecParSampleRate(par); err == nil {
742+
return v
743+
}
731744
return *(*int32)(unsafe.Pointer(uintptr(par) + offsetCodecParSampleRate))
732745
}
733746

@@ -736,6 +749,9 @@ func GetCodecParChannels(par avcodec.Parameters) int32 {
736749
if par == nil {
737750
return 0
738751
}
752+
if v, err := ffshim.CodecParChannels(par); err == nil {
753+
return v
754+
}
739755
return *(*int32)(unsafe.Pointer(uintptr(par) + offsetCodecParChannels))
740756
}
741757

internal/shim/shim.go

Lines changed: 198 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,25 @@ var (
6363

6464
// AVFrame offset discovery helpers
6565
shimAVFrameColorOffsets func(outRange, outSpace, outPrimaries, outTransfer *int32) int32
66+
67+
// AVCodecParameters field helpers (optional)
68+
shimCodecParWidth func(par uintptr) int32
69+
shimCodecParHeight func(par uintptr) int32
70+
shimCodecParFormat func(par uintptr) int32
71+
shimCodecParSampleRate func(par uintptr) int32
72+
shimCodecParChannels func(par uintptr) int32
73+
74+
// AVCodecContext field helpers (optional)
75+
shimCodecCtxWidth func(ctx uintptr) int32
76+
shimCodecCtxSetWidth func(ctx uintptr, width int32)
77+
shimCodecCtxHeight func(ctx uintptr) int32
78+
shimCodecCtxSetHeight func(ctx uintptr, height int32)
79+
shimCodecCtxPixFmt func(ctx uintptr) int32
80+
shimCodecCtxSetPixFmt func(ctx uintptr, pixFmt int32)
81+
shimCodecCtxTimeBase func(ctx uintptr, outNum, outDen *int32)
82+
shimCodecCtxSetTimeBase func(ctx uintptr, num, den int32)
83+
shimCodecCtxFramerate func(ctx uintptr, outNum, outDen *int32)
84+
shimCodecCtxSetFramerate func(ctx uintptr, num, den int32)
6685
)
6786

6887
// Load attempts to load the ffshim library.
@@ -231,6 +250,25 @@ func registerBindings() {
231250
registerOptionalLibFunc(&shimAVDeviceListInputSources, libShim, "ffshim_avdevice_list_input_sources")
232251
registerOptionalLibFunc(&shimAVDeviceFreeStringArray, libShim, "ffshim_avdevice_free_string_array")
233252
registerOptionalLibFunc(&shimAVFrameColorOffsets, libShim, "ffshim_avframe_color_offsets")
253+
254+
// AVCodecParameters field helpers (optional)
255+
registerOptionalLibFunc(&shimCodecParWidth, libShim, "ffshim_codecpar_width")
256+
registerOptionalLibFunc(&shimCodecParHeight, libShim, "ffshim_codecpar_height")
257+
registerOptionalLibFunc(&shimCodecParFormat, libShim, "ffshim_codecpar_format")
258+
registerOptionalLibFunc(&shimCodecParSampleRate, libShim, "ffshim_codecpar_sample_rate")
259+
registerOptionalLibFunc(&shimCodecParChannels, libShim, "ffshim_codecpar_channels")
260+
261+
// AVCodecContext field helpers (optional)
262+
registerOptionalLibFunc(&shimCodecCtxWidth, libShim, "ffshim_codecctx_width")
263+
registerOptionalLibFunc(&shimCodecCtxSetWidth, libShim, "ffshim_codecctx_set_width")
264+
registerOptionalLibFunc(&shimCodecCtxHeight, libShim, "ffshim_codecctx_height")
265+
registerOptionalLibFunc(&shimCodecCtxSetHeight, libShim, "ffshim_codecctx_set_height")
266+
registerOptionalLibFunc(&shimCodecCtxPixFmt, libShim, "ffshim_codecctx_pix_fmt")
267+
registerOptionalLibFunc(&shimCodecCtxSetPixFmt, libShim, "ffshim_codecctx_set_pix_fmt")
268+
registerOptionalLibFunc(&shimCodecCtxTimeBase, libShim, "ffshim_codecctx_time_base")
269+
registerOptionalLibFunc(&shimCodecCtxSetTimeBase, libShim, "ffshim_codecctx_set_time_base")
270+
registerOptionalLibFunc(&shimCodecCtxFramerate, libShim, "ffshim_codecctx_framerate")
271+
registerOptionalLibFunc(&shimCodecCtxSetFramerate, libShim, "ffshim_codecctx_set_framerate")
234272
}
235273

236274
func registerOptionalLibFunc(fptr any, handle uintptr, name string) {
@@ -296,9 +334,9 @@ func NewChapter(ctx unsafe.Pointer, id int64, tbNum, tbDen int32, start, end int
296334
// AVDeviceListInputSources lists available input devices for a given avdevice input format.
297335
//
298336
// Returns:
299-
// - count: number of devices
300-
// - names/descs: pointers to shim-allocated string arrays (char**). Caller MUST free both arrays
301-
// using AVDeviceFreeStringArray.
337+
// - count: number of devices
338+
// - names/descs: pointers to shim-allocated string arrays (char**). Caller MUST free both arrays
339+
// using AVDeviceFreeStringArray.
302340
//
303341
// This requires a shim build that links against libavdevice (built with -DFFSHIM_HAVE_AVDEVICE=1).
304342
func AVDeviceListInputSources(formatName, deviceName string, avdictOpts unsafe.Pointer) (count int, names, descs unsafe.Pointer, err error) {
@@ -346,6 +384,163 @@ func AVFrameColorOffsets() (rangeOff, spaceOff, primariesOff, transferOff int32,
346384
return r, s, p, t, nil
347385
}
348386

387+
func CodecParWidth(par unsafe.Pointer) (int32, error) {
388+
if par == nil {
389+
return 0, nil
390+
}
391+
if !loaded || shimCodecParWidth == nil {
392+
return 0, ErrShimNotLoaded
393+
}
394+
return shimCodecParWidth(uintptr(par)), nil
395+
}
396+
397+
func CodecParHeight(par unsafe.Pointer) (int32, error) {
398+
if par == nil {
399+
return 0, nil
400+
}
401+
if !loaded || shimCodecParHeight == nil {
402+
return 0, ErrShimNotLoaded
403+
}
404+
return shimCodecParHeight(uintptr(par)), nil
405+
}
406+
407+
func CodecParFormat(par unsafe.Pointer) (int32, error) {
408+
if par == nil {
409+
return -1, nil
410+
}
411+
if !loaded || shimCodecParFormat == nil {
412+
return 0, ErrShimNotLoaded
413+
}
414+
return shimCodecParFormat(uintptr(par)), nil
415+
}
416+
417+
func CodecParSampleRate(par unsafe.Pointer) (int32, error) {
418+
if par == nil {
419+
return 0, nil
420+
}
421+
if !loaded || shimCodecParSampleRate == nil {
422+
return 0, ErrShimNotLoaded
423+
}
424+
return shimCodecParSampleRate(uintptr(par)), nil
425+
}
426+
427+
func CodecParChannels(par unsafe.Pointer) (int32, error) {
428+
if par == nil {
429+
return 0, nil
430+
}
431+
if !loaded || shimCodecParChannels == nil {
432+
return 0, ErrShimNotLoaded
433+
}
434+
return shimCodecParChannels(uintptr(par)), nil
435+
}
436+
437+
func CodecCtxWidth(ctx unsafe.Pointer) (int32, error) {
438+
if ctx == nil {
439+
return 0, nil
440+
}
441+
if !loaded || shimCodecCtxWidth == nil {
442+
return 0, ErrShimNotLoaded
443+
}
444+
return shimCodecCtxWidth(uintptr(ctx)), nil
445+
}
446+
447+
func CodecCtxSetWidth(ctx unsafe.Pointer, width int32) error {
448+
if ctx == nil {
449+
return nil
450+
}
451+
if !loaded || shimCodecCtxSetWidth == nil {
452+
return ErrShimNotLoaded
453+
}
454+
shimCodecCtxSetWidth(uintptr(ctx), width)
455+
return nil
456+
}
457+
458+
func CodecCtxHeight(ctx unsafe.Pointer) (int32, error) {
459+
if ctx == nil {
460+
return 0, nil
461+
}
462+
if !loaded || shimCodecCtxHeight == nil {
463+
return 0, ErrShimNotLoaded
464+
}
465+
return shimCodecCtxHeight(uintptr(ctx)), nil
466+
}
467+
468+
func CodecCtxSetHeight(ctx unsafe.Pointer, height int32) error {
469+
if ctx == nil {
470+
return nil
471+
}
472+
if !loaded || shimCodecCtxSetHeight == nil {
473+
return ErrShimNotLoaded
474+
}
475+
shimCodecCtxSetHeight(uintptr(ctx), height)
476+
return nil
477+
}
478+
479+
func CodecCtxPixFmt(ctx unsafe.Pointer) (int32, error) {
480+
if ctx == nil {
481+
return -1, nil
482+
}
483+
if !loaded || shimCodecCtxPixFmt == nil {
484+
return 0, ErrShimNotLoaded
485+
}
486+
return shimCodecCtxPixFmt(uintptr(ctx)), nil
487+
}
488+
489+
func CodecCtxSetPixFmt(ctx unsafe.Pointer, pixFmt int32) error {
490+
if ctx == nil {
491+
return nil
492+
}
493+
if !loaded || shimCodecCtxSetPixFmt == nil {
494+
return ErrShimNotLoaded
495+
}
496+
shimCodecCtxSetPixFmt(uintptr(ctx), pixFmt)
497+
return nil
498+
}
499+
500+
func CodecCtxTimeBase(ctx unsafe.Pointer) (num, den int32, err error) {
501+
if ctx == nil {
502+
return 0, 0, nil
503+
}
504+
if !loaded || shimCodecCtxTimeBase == nil {
505+
return 0, 0, ErrShimNotLoaded
506+
}
507+
shimCodecCtxTimeBase(uintptr(ctx), &num, &den)
508+
return num, den, nil
509+
}
510+
511+
func CodecCtxSetTimeBase(ctx unsafe.Pointer, num, den int32) error {
512+
if ctx == nil {
513+
return nil
514+
}
515+
if !loaded || shimCodecCtxSetTimeBase == nil {
516+
return ErrShimNotLoaded
517+
}
518+
shimCodecCtxSetTimeBase(uintptr(ctx), num, den)
519+
return nil
520+
}
521+
522+
func CodecCtxFramerate(ctx unsafe.Pointer) (num, den int32, err error) {
523+
if ctx == nil {
524+
return 0, 0, nil
525+
}
526+
if !loaded || shimCodecCtxFramerate == nil {
527+
return 0, 0, ErrShimNotLoaded
528+
}
529+
shimCodecCtxFramerate(uintptr(ctx), &num, &den)
530+
return num, den, nil
531+
}
532+
533+
func CodecCtxSetFramerate(ctx unsafe.Pointer, num, den int32) error {
534+
if ctx == nil {
535+
return nil
536+
}
537+
if !loaded || shimCodecCtxSetFramerate == nil {
538+
return ErrShimNotLoaded
539+
}
540+
shimCodecCtxSetFramerate(uintptr(ctx), num, den)
541+
return nil
542+
}
543+
349544
// findShimLibrary looks for the shim library in standard locations.
350545
func findShimLibrary() (string, error) {
351546
var names []string

0 commit comments

Comments
 (0)