Skip to content

Commit

Permalink
Added custom io demuxing + writable to AllocIOContext
Browse files Browse the repository at this point in the history
  • Loading branch information
asticode committed May 16, 2024
1 parent f43c80d commit a83963b
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Examples are located in the [examples](examples) directory and mirror as much as
|name|astiav|ffmpeg|
|---|---|---|
|BitStream Filtering|[see](examples/bit_stream_filtering/main.go)|X
|Custom IO Demuxing|[see](examples/custom_io_demuxing/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/doc/examples/avio_reading.c)
|Demuxing/Decoding|[see](examples/demuxing_decoding/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/doc/examples/demuxing_decoding.c)
|Filtering|[see](examples/filtering/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/doc/examples/filtering_video.c)
|Hardware Decoding|[see](examples/hardware_decoding/main.go)|[see](https://github.com/FFmpeg/FFmpeg/blob/n5.1.2/doc/examples/hw_decode.c)
Expand Down
105 changes: 105 additions & 0 deletions examples/custom_io_demuxing/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package main

import (
"errors"
"flag"
"fmt"
"log"
"os"
"strings"

"github.com/asticode/go-astiav"
)

var (
input = flag.String("i", "", "the input path")
)

func main() {
// Handle ffmpeg logs
astiav.SetLogLevel(astiav.LogLevelDebug)
astiav.SetLogCallback(func(c astiav.Classer, l astiav.LogLevel, fmt, msg string) {
var cs string
if c != nil {
if cl := c.Class(); cl != nil {
cs = " - class: " + cl.String()
}
}
log.Printf("ffmpeg log: %s%s - level: %d\n", strings.TrimSpace(msg), cs, l)
})

// Parse flags
flag.Parse()

// Usage
if *input == "" {
log.Println("Usage: <binary path> -i <input path>")
return
}

// Alloc packet
pkt := astiav.AllocPacket()
defer pkt.Free()

// Alloc input format context
inputFormatContext := astiav.AllocFormatContext()
if inputFormatContext == nil {
log.Fatal(errors.New("main: input format context is nil"))
}
defer inputFormatContext.Free()

// Open file
f, err := os.Open(*input)
if err != nil {
log.Fatal(fmt.Errorf("main: opening %s failed: %w", *input, err))
}
defer f.Close()

// Alloc io context
ioContext, err := astiav.AllocIOContext(
4096,
false,
func(b []byte) (n int, err error) {
return f.Read(b)
},
func(offset int64, whence int) (n int64, err error) {
return f.Seek(offset, whence)
},
nil,
)
if err != nil {
log.Fatal(fmt.Errorf("main: allocating io context failed: %w", err))
}
defer ioContext.Free()

// Store io context
inputFormatContext.SetPb(ioContext)

// Open input
if err := inputFormatContext.OpenInput("", nil, nil); err != nil {
log.Fatal(fmt.Errorf("main: opening input failed: %w", err))
}
defer inputFormatContext.CloseInput()

// Find stream info
if err := inputFormatContext.FindStreamInfo(nil); err != nil {
log.Fatal(fmt.Errorf("main: finding stream info failed: %w", err))
}

// Loop through packets
for {
// Read frame
if err := inputFormatContext.ReadFrame(pkt); err != nil {
if errors.Is(err, astiav.ErrEof) {
break
}
log.Fatal(fmt.Errorf("main: reading frame failed: %w", err))
}

// Do something with the packet
log.Printf("new packet: stream %d - pts: %d", pkt.StreamIndex(), pkt.Pts())
}

// Success
log.Println("success")
}
7 changes: 5 additions & 2 deletions format_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,11 @@ func (fc *FormatContext) SetStrictStdCompliance(strictStdCompliance StrictStdCom
}

func (fc *FormatContext) OpenInput(url string, fmt *InputFormat, d *Dictionary) error {
urlc := C.CString(url)
defer C.free(unsafe.Pointer(urlc))
var urlc *C.char
if url != "" {
urlc = C.CString(url)
defer C.free(unsafe.Pointer(urlc))
}
var dc **C.struct_AVDictionary
if d != nil {
dc = &d.c
Expand Down
10 changes: 8 additions & 2 deletions io_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type IOContextSeekFunc func(offset int64, whence int) (n int64, err error)

type IOContextWriteFunc func(b []byte) (n int, err error)

func AllocIOContext(bufferSize int, readFunc IOContextReadFunc, seekFunc IOContextSeekFunc, writeFunc IOContextWriteFunc) (ic *IOContext, err error) {
func AllocIOContext(bufferSize int, writable bool, readFunc IOContextReadFunc, seekFunc IOContextSeekFunc, writeFunc IOContextWriteFunc) (ic *IOContext, err error) {
// Invalid buffer size
if bufferSize <= 0 {
err = errors.New("astiav: buffer size <= 0")
Expand Down Expand Up @@ -81,8 +81,14 @@ func AllocIOContext(bufferSize int, readFunc IOContextReadFunc, seekFunc IOConte
cWriteFunc = (*[0]byte)(C.astiavIOContextWriteFunc)
}

// Get write flag
wf := C.int(0)
if writable {
wf = C.int(1)
}

// Alloc io context
cic := C.avio_alloc_context((*C.uchar)(buffer), C.int(bufferSize), 1, handlerID, cReadFunc, cWriteFunc, cSeekFunc)
cic := C.avio_alloc_context((*C.uchar)(buffer), C.int(bufferSize), wf, handlerID, cReadFunc, cWriteFunc, cSeekFunc)
if cic == nil {
err = errors.New("astiav: allocating io context failed: %w")
return
Expand Down
2 changes: 1 addition & 1 deletion io_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func TestIOContext(t *testing.T) {
rb := []byte("read")
wb := []byte("write")
var written []byte
c, err := AllocIOContext(8, func(b []byte) (int, error) {
c, err := AllocIOContext(8, true, func(b []byte) (int, error) {
copy(b, rb)
return len(rb), nil
}, func(offset int64, whence int) (n int64, err error) {
Expand Down

0 comments on commit a83963b

Please sign in to comment.