Skip to content

Commit

Permalink
Add bit stream filter support (#61)
Browse files Browse the repository at this point in the history
* add bit stream filter support

* bit stream filter is not a class

* add pr suggestions

* add tests for bit stream filter

* create a separated test helper method

* search for first h264 video stream

* add pr suggestions

* remove free since bsfc is taking ownership of it
  • Loading branch information
leandromoreira authored May 14, 2024
1 parent 338c4df commit d884495
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 0 deletions.
35 changes: 35 additions & 0 deletions bit_stream_filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package astiav

//#cgo pkg-config: libavcodec
//#include <libavcodec/bsf.h>
//#include <stdlib.h>
import "C"
import (
"unsafe"
)

// https://github.com/FFmpeg/FFmpeg/blob/release/5.1/libavcodec/bsf.h#L111
type BitStreamFilter struct {
c *C.struct_AVBitStreamFilter
}

func newBitStreamFilterFromC(c *C.struct_AVBitStreamFilter) *BitStreamFilter {
if c == nil {
return nil
}
return &BitStreamFilter{c: c}
}

func FindBitStreamFilterByName(n string) *BitStreamFilter {
cn := C.CString(n)
defer C.free(unsafe.Pointer(cn))
return newBitStreamFilterFromC(C.av_bsf_get_by_name(cn))
}

func (bsf *BitStreamFilter) Name() string {
return C.GoString(bsf.c.name)
}

func (bsf *BitStreamFilter) String() string {
return bsf.Name()
}
82 changes: 82 additions & 0 deletions bit_stream_filter_context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package astiav

//#cgo pkg-config: libavcodec
//#include <libavcodec/bsf.h>
import "C"
import (
"errors"
"unsafe"
)

// https://github.com/FFmpeg/FFmpeg/blob/release/5.1/libavcodec/bsf.h#L68
type BitStreamFilterContext struct {
c *C.struct_AVBSFContext
}

func newBSFContextFromC(c *C.struct_AVBSFContext) *BitStreamFilterContext {
if c == nil {
return nil
}
bsfc := &BitStreamFilterContext{c: c}
classers.set(bsfc)
return bsfc
}

var _ Classer = (*BitStreamFilterContext)(nil)

func AllocBitStreamFilterContext(f *BitStreamFilter) (*BitStreamFilterContext, error) {
if f == nil {
return nil, errors.New("astiav: bit stream filter must not be nil")
}

var bsfc *C.struct_AVBSFContext
if err := newError(C.av_bsf_alloc(f.c, &bsfc)); err != nil {
return nil, err
}

return newBSFContextFromC(bsfc), nil
}

func (bsfc *BitStreamFilterContext) Class() *Class {
return newClassFromC(unsafe.Pointer(bsfc.c))
}

func (bsfc *BitStreamFilterContext) Initialize() error {
return newError(C.av_bsf_init(bsfc.c))
}

func (bsfc *BitStreamFilterContext) SendPacket(p *Packet) error {
var pc *C.struct_AVPacket
if p != nil {
pc = p.c
}
return newError(C.av_bsf_send_packet(bsfc.c, pc))
}

func (bsfc *BitStreamFilterContext) ReceivePacket(p *Packet) error {
if p == nil {
return errors.New("astiav: packet must not be nil")
}
return newError(C.av_bsf_receive_packet(bsfc.c, p.c))
}

func (bsfc *BitStreamFilterContext) Free() {
classers.del(bsfc)
C.av_bsf_free(&bsfc.c)
}

func (bsfc *BitStreamFilterContext) TimeBaseIn() Rational {
return newRationalFromC(bsfc.c.time_base_in)
}

func (bsfc *BitStreamFilterContext) SetTimeBaseIn(r Rational) {
bsfc.c.time_base_in = r.c
}

func (bsfc *BitStreamFilterContext) CodecParametersIn() *CodecParameters {
return newCodecParametersFromC(bsfc.c.par_in)
}

func (bsfc *BitStreamFilterContext) SetCodecParametersIn(cp *CodecParameters) {
bsfc.c.par_in = cp.c
}
33 changes: 33 additions & 0 deletions bit_stream_filter_context_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package astiav

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestBitStreamFilterContext(t *testing.T) {
bsf := FindBitStreamFilterByName("null")
require.NotNil(t, bsf)

bsfc, err := AllocBitStreamFilterContext(bsf)
require.NotNil(t, bsfc)
require.NoError(t, err)
defer bsfc.Free()

cl := bsfc.Class()
require.NotNil(t, cl)
require.Equal(t, "AVBSFContext", cl.Name())

bsfc.SetTimeBaseIn(NewRational(15, 1))
require.Equal(t, NewRational(15, 1), bsfc.TimeBaseIn())

cp1 := AllocCodecParameters()
require.NotNil(t, cp1)
cp1.SetCodecID(CodecIDH264)

bsfc.SetCodecParametersIn(cp1)
require.Equal(t, CodecIDH264, bsfc.CodecParametersIn().CodecID())

// TODO: add tests for send and receive packet flows
}
18 changes: 18 additions & 0 deletions bit_stream_filter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package astiav

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestBitStreamFilter(t *testing.T) {
fn := "null"
f := FindBitStreamFilterByName(fn)
require.NotNil(t, f)
require.Equal(t, f.Name(), fn)
require.Equal(t, f.String(), fn)

f = FindBitStreamFilterByName("foobar_non_existing_bsf")
require.Nil(t, f)
}

0 comments on commit d884495

Please sign in to comment.