mirror of
https://github.com/asticode/go-astiav.git
synced 2025-10-12 03:20:35 +08:00
Initial commit
This commit is contained in:
140
examples/demuxing_decoding/main.go
Normal file
140
examples/demuxing_decoding/main.go
Normal file
@@ -0,0 +1,140 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/asticode/go-astiav"
|
||||
)
|
||||
|
||||
var (
|
||||
input = flag.String("i", "", "the input path")
|
||||
)
|
||||
|
||||
type stream struct {
|
||||
decCodec *astiav.Codec
|
||||
decCodecContext *astiav.CodecContext
|
||||
inputStream *astiav.Stream
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Handle ffmpeg logs
|
||||
astiav.SetLogLevel(astiav.LogLevelDebug)
|
||||
astiav.SetLogCallback(func(l astiav.LogLevel, msg, parent string) {
|
||||
log.Printf("ffmpeg log: %s (level: %d)\n", strings.TrimSpace(msg), 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 frame
|
||||
f := astiav.AllocFrame()
|
||||
defer f.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 input
|
||||
if err := inputFormatContext.OpenInput(*input, 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 streams
|
||||
streams := make(map[int]*stream) // Indexed by input stream index
|
||||
for _, is := range inputFormatContext.Streams() {
|
||||
// Only process audio or video
|
||||
if is.CodecParameters().MediaType() != astiav.MediaTypeAudio &&
|
||||
is.CodecParameters().MediaType() != astiav.MediaTypeVideo {
|
||||
continue
|
||||
}
|
||||
|
||||
// Create stream
|
||||
s := &stream{inputStream: is}
|
||||
|
||||
// Find decoder
|
||||
if s.decCodec = astiav.FindDecoder(is.CodecParameters().CodecID()); s.decCodec == nil {
|
||||
log.Fatal(errors.New("main: codec is nil"))
|
||||
}
|
||||
|
||||
// Alloc codec context
|
||||
if s.decCodecContext = astiav.AllocCodecContext(s.decCodec); s.decCodecContext == nil {
|
||||
log.Fatal(errors.New("main: codec context is nil"))
|
||||
}
|
||||
defer s.decCodecContext.Free()
|
||||
|
||||
// Update codec context
|
||||
if err := is.CodecParameters().ToCodecContext(s.decCodecContext); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: updating codec context failed: %w", err))
|
||||
}
|
||||
|
||||
// Open codec context
|
||||
if err := s.decCodecContext.Open(s.decCodec, nil); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: opening codec context failed: %w", err))
|
||||
}
|
||||
|
||||
// Add stream
|
||||
streams[is.Index()] = s
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
// Get stream
|
||||
s, ok := streams[pkt.StreamIndex()]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Send packet
|
||||
if err := s.decCodecContext.SendPacket(pkt); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: sending packet failed: %w", err))
|
||||
}
|
||||
|
||||
// Loop
|
||||
for {
|
||||
// Receive frame
|
||||
if err := s.decCodecContext.ReceiveFrame(f); err != nil {
|
||||
if errors.Is(err, astiav.ErrEof) || errors.Is(err, astiav.ErrEagain) {
|
||||
break
|
||||
}
|
||||
log.Fatal(fmt.Errorf("main: receiving frame failed: %w", err))
|
||||
}
|
||||
|
||||
// Do something with decoded frame
|
||||
log.Printf("new frame: stream %d - pts: %d", pkt.StreamIndex(), f.Pts())
|
||||
}
|
||||
}
|
||||
|
||||
// Success
|
||||
log.Println("success")
|
||||
}
|
Reference in New Issue
Block a user