Skip to content

Commit

Permalink
Added format/codec context private data + options
Browse files Browse the repository at this point in the history
  • Loading branch information
asticode committed Dec 10, 2024
1 parent 09052ff commit 8bf2b04
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 0 deletions.
5 changes: 5 additions & 0 deletions codec_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ func (cc *CodecContext) SetPixelFormat(pixFmt PixelFormat) {
cc.c.pix_fmt = C.enum_AVPixelFormat(pixFmt)
}

// https://ffmpeg.org/doxygen/7.0/structAVCodecContext.html#af3379123060ad8cc9c321c29af4f8360
func (cc *CodecContext) PrivateData() *PrivateData {
return newPrivateDataFromC(cc.c.priv_data)
}

// https://ffmpeg.org/doxygen/7.0/structAVCodecContext.html#a7abe7095de73df98df4895bf9e25fc6b
func (cc *CodecContext) Profile() Profile {
return Profile(cc.c.profile)
Expand Down
1 change: 1 addition & 0 deletions codec_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func TestCodecContext(t *testing.T) {
require.Equal(t, Level(13), cc1.Level())
require.Equal(t, MediaTypeVideo, cc1.MediaType())
require.Equal(t, PixelFormatYuv420P, cc1.PixelFormat())
require.NotNil(t, cc1.PrivateData())
require.Equal(t, ProfileH264ConstrainedBaseline, cc1.Profile())
require.Equal(t, NewRational(1, 1), cc1.SampleAspectRatio())
require.Equal(t, StrictStdComplianceNormal, cc1.StrictStdCompliance())
Expand Down
20 changes: 20 additions & 0 deletions flags.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions flags_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions format_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,11 @@ func (fc *FormatContext) SetPb(i *IOContext) {
fc.c.pb = i.c
}

// https://ffmpeg.org/doxygen/7.0/structAVFormatContext.html#ac4c0777e54085af2f3f1b27130e2b21b
func (fc *FormatContext) PrivateData() *PrivateData {
return newPrivateDataFromC(fc.c.priv_data)
}

// https://ffmpeg.org/doxygen/7.0/structAVFormatContext.html#a2590129e00adfa726ab2033a10e905e9
func (fc *FormatContext) StartTime() int64 {
return int64(fc.c.start_time)
Expand Down
1 change: 1 addition & 0 deletions format_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func TestFormatContext(t *testing.T) {
require.Equal(t, IOContextFlags(0), fc1.IOFlags())
require.Equal(t, int64(0), fc1.MaxAnalyzeDuration())
require.Equal(t, "isom", fc1.Metadata().Get("major_brand", nil, NewDictionaryFlags()).Value())
require.NotNil(t, fc1.PrivateData())
require.Equal(t, int64(0), fc1.StartTime())
require.Equal(t, 2, fc1.NbStreams())
require.Len(t, fc1.Streams(), 2)
Expand Down
1 change: 1 addition & 0 deletions internal/cmd/flags/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var list = []listItem{
{Name: "FormatEvent"},
{Name: "IOContext"},
{Name: "IOFormat"},
{Name: "OptionSearch"},
{Name: "Packet"},
{Name: "Seek"},
{Name: "SoftwareScaleContext"},
Expand Down
12 changes: 12 additions & 0 deletions option.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <libavutil/opt.h>

int astiavOptionGet(void *obj, const char *name, const char **value, int flags)
{
uint8_t *v = NULL;
int ret = av_opt_get(obj, name, flags, &v);
if (ret < 0) {
return ret;
}
*value = (const char *)v;
return 0;
}
60 changes: 60 additions & 0 deletions option.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package astiav

//#include <libavutil/opt.h>
//#include "option.h"
import "C"
import (
"unsafe"
)

type Options struct {
c unsafe.Pointer
}

func newOptionsFromC(c unsafe.Pointer) *Options {
if c == nil {
return nil
}
return &Options{c: c}
}

type Option struct {
Name string
}

// https://www.ffmpeg.org/doxygen/7.0/group__opt__mng.html#gabc75970cd87d1bf47a4ff449470e9225
func (os *Options) List() (list []Option) {
var prev *C.AVOption
for {
o := C.av_opt_next(os.c, prev)
if o == nil {
return
}
list = append(list, Option{Name: C.GoString(o.name)})
prev = o
}
}

// https://www.ffmpeg.org/doxygen/7.0/group__opt__set__funcs.html#ga5fd4b92bdf4f392a2847f711676a7537
func (os *Options) Set(name, value string, f OptionSearchFlags) error {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
cvalue := C.CString(value)
defer C.free(unsafe.Pointer(cvalue))
return newError(C.av_opt_set(os.c, cname, cvalue, C.int(f)))
}

// https://www.ffmpeg.org/doxygen/7.0/group__opt__get__funcs.html#gaf31144e60f9ce89dbe8cbea57a0b232c
func (os *Options) Get(name string, f OptionSearchFlags) (string, error) {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
var cvalue *C.char = nil
if err := newError(C.astiavOptionGet(os.c, cname, &cvalue, C.int(f))); err != nil {
return "", err
}
if cvalue == nil {
return "", nil
}
defer C.av_freep(unsafe.Pointer(&cvalue))
return C.GoString(cvalue), nil
}
1 change: 1 addition & 0 deletions option.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int astiavOptionGet(void *obj, const char *name, const char **value, int flags);
12 changes: 12 additions & 0 deletions option_search_flag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package astiav

//#include <libavutil/opt.h>
import "C"

// https://ffmpeg.org/doxygen/7.0/group__opt__mng.html#ga25801ba4fc9b5313eb33ec84e082dd72
type OptionSearchFlag int64

const (
OptionSearchFlagChildren = CodecContextFlag(C.AV_OPT_SEARCH_CHILDREN)
OptionSearchFlagFakeObject = CodecContextFlag(C.AV_OPT_SEARCH_FAKE_OBJ)
)
28 changes: 28 additions & 0 deletions option_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package astiav

import (
"testing"

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

func TestOption(t *testing.T) {
fc, err := AllocOutputFormatContext(nil, "mp4", "")
require.NoError(t, err)
pd := fc.PrivateData()
require.NotNil(t, pd)
os := pd.Options()
require.NotNil(t, os)
require.Equal(t, []Option{{Name: "brand"}, {Name: "empty_hdlr_name"}, {Name: "encryption_key"}, {Name: "encryption_kid"}, {Name: "encryption_scheme"}, {Name: "frag_duration"}, {Name: "frag_interleave"}, {Name: "frag_size"}, {Name: "fragment_index"}, {Name: "iods_audio_profile"}, {Name: "iods_video_profile"}, {Name: "ism_lookahead"}, {Name: "movflags"}, {Name: "cmaf"}, {Name: "dash"}, {Name: "default_base_moof"}, {Name: "delay_moov"}, {Name: "disable_chpl"}, {Name: "empty_moov"}, {Name: "faststart"}, {Name: "frag_custom"}, {Name: "frag_discont"}, {Name: "frag_every_frame"}, {Name: "frag_keyframe"}, {Name: "global_sidx"}, {Name: "isml"}, {Name: "moov_size"}, {Name: "negative_cts_offsets"}, {Name: "omit_tfhd_offset"}, {Name: "prefer_icc"}, {Name: "rtphint"}, {Name: "separate_moof"}, {Name: "skip_sidx"}, {Name: "skip_trailer"}, {Name: "use_metadata_tags"}, {Name: "write_colr"}, {Name: "write_gama"}, {Name: "min_frag_duration"}, {Name: "mov_gamma"}, {Name: "movie_timescale"}, {Name: "rtpflags"}, {Name: "latm"}, {Name: "rfc2190"}, {Name: "skip_rtcp"}, {Name: "h264_mode0"}, {Name: "send_bye"}, {Name: "skip_iods"}, {Name: "use_editlist"}, {Name: "use_stream_ids_as_track_ids"}, {Name: "video_track_timescale"}, {Name: "write_btrt"}, {Name: "write_prft"}, {Name: "pts"}, {Name: "wallclock"}, {Name: "write_tmcd"}}, os.List())
_, err = os.Get("invalid", NewOptionSearchFlags())
require.Error(t, err)
v, err := os.Get("brand", NewOptionSearchFlags())
require.NoError(t, err)
require.Equal(t, "", v)
require.Error(t, os.Set("invalid", "", NewOptionSearchFlags()))
const brand = "test"
require.NoError(t, os.Set("brand", brand, NewOptionSearchFlags()))
v, err = os.Get("brand", NewOptionSearchFlags())
require.NoError(t, err)
require.Equal(t, brand, v)
}
18 changes: 18 additions & 0 deletions private_data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package astiav

import "unsafe"

type PrivateData struct {
c unsafe.Pointer
}

func newPrivateDataFromC(c unsafe.Pointer) *PrivateData {
if c == nil {
return nil
}
return &PrivateData{c: c}
}

func (pd *PrivateData) Options() *Options {
return newOptionsFromC(pd.c)
}

0 comments on commit 8bf2b04

Please sign in to comment.