Skip to content

Commit

Permalink
Merge pull request #28 from mutablelogic/ffmpeg61
Browse files Browse the repository at this point in the history
Mostly fixed resampling
  • Loading branch information
djthorpe authored Jul 2, 2024
2 parents 7ea948e + 7128226 commit fef25db
Show file tree
Hide file tree
Showing 53 changed files with 1,768 additions and 743 deletions.
16 changes: 13 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,22 @@ docker-push: docker-dep
test: go-dep
@echo Test
@${GO} mod tidy
@echo ... test sys/ffmpeg61
@${GO} test ./sys/ffmpeg61
@echo ... test pkg/ffmpeg
@${GO} test -v ./pkg/ffmpeg
@echo ... test sys/chromaprint
@${GO} test ./sys/chromaprint
@echo ... test pkg/chromaprint
@${GO} test ./pkg/chromaprint
@echo ... test pkg/file
@${GO} test ./pkg/file
@echo ... test pkg/generator
@${GO} test ./pkg/generator
@echo ... test pkg/image
@${GO} test ./pkg/image
@echo ... test pkg
@${GO} test ./pkg/...
@${GO} test .

container-test: go-dep
@echo Test
Expand All @@ -56,8 +68,6 @@ container-test: go-dep
@${GO} test --tags=container ./pkg/...
@${GO} test --tags=container .



cli: go-dep mkdir
@echo Build media tool
@${GO} build ${BUILD_FLAGS} -o ${BUILD_DIR}/media ./cmd/cli
Expand Down
72 changes: 69 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func main() {
}
```

### Decoding - Video Frames
### Decoding - Video

This example shows you how to decode video frames from a media file into images.

Expand Down Expand Up @@ -156,9 +156,75 @@ func main() {
}
```

### Encoding
### Encoding - Audio and Video

TODO
This example shows you how to encode video and audio frames into a media file.

```go
package main

import (
"io"
"log"
"os"
"time"

media "github.com/mutablelogic/go-media"
ffmpeg "github.com/mutablelogic/go-media/pkg/ffmpeg"
generator "github.com/mutablelogic/go-media/pkg/generator"
ff "github.com/mutablelogic/go-media/sys/ffmpeg61"
)

func main() {
// Create a new file with an audio and video stream
// 30fps and 22050Hz mono audio
file, err := ffmpeg.Create(os.Args[1],
ffmpeg.OptStream(1, ffmpeg.VideoPar("yuv420p", "640x480", 30)),
ffmpeg.OptStream(2, ffmpeg.AudioPar("fltp", "mono", 22050)),
)
if err != nil {
log.Fatal(err)
}
defer file.Close()

// Make an video generator which can generate YUV420P frames
// with the same parameters as the video stream
video, err := generator.NewYUV420P(file.Stream(1).Par())
if err != nil {
log.Fatal(err)
}
defer video.Close()

// Make an audio generator which can generate a 440Hz tone
// at -5dB with the same parameters as the audio stream
audio, err := generator.NewSine(440, -5, file.Stream(2).Par())
if err != nil {
log.Fatal(err)
}
defer audio.Close()

// Write 1 min of frames, passing video and audio frames to the encoder
// and returning io.EOF when the duration is reached
duration := time.Minute
if err := file.Encode(func(stream int) (*ff.AVFrame, error) {
var frame media.Frame
switch stream {
case 1:
frame = video.Frame()
case 2:
frame = audio.Frame()
}
if frame.Time() >= duration {
return nil, io.EOF
} else {
log.Println("Frame", stream, "=>", frame.Time().Truncate(time.Millisecond))
return frame.(*ffmpeg.Frame).AVFrame(), nil
}
}, nil); err != nil {
log.Fatal(err)
}
}
```

### Multiplexing

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
62 changes: 62 additions & 0 deletions cmd/examples/encode/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package main

import (
"io"
"log"
"os"
"time"

media "github.com/mutablelogic/go-media"
ffmpeg "github.com/mutablelogic/go-media/pkg/ffmpeg"
generator "github.com/mutablelogic/go-media/pkg/generator"
ff "github.com/mutablelogic/go-media/sys/ffmpeg61"
)

func main() {
// Create a new file with an audio and video stream
file, err := ffmpeg.Create(os.Args[1],
ffmpeg.OptStream(1, ffmpeg.VideoPar("yuv420p", "640x480", 30)),
ffmpeg.OptStream(2, ffmpeg.AudioPar("fltp", "mono", 22050)),
)
if err != nil {
log.Fatal(err)
}
defer file.Close()

// Make an video generator which can generate YUV420P frames
// with the same parameters as the video stream
video, err := generator.NewYUV420P(file.Stream(1).Par())
if err != nil {
log.Fatal(err)
}
defer video.Close()

// Make an audio generator which can generate a 440Hz tone
// at -5dB with the same parameters as the audio stream
audio, err := generator.NewSine(440, -5, file.Stream(2).Par())
if err != nil {
log.Fatal(err)
}
defer audio.Close()

// Write 1 min of frames, passing video and audio frames to the encoder
// and returning io.EOF when the duration is reached
duration := time.Minute
if err := file.Encode(func(stream int) (*ff.AVFrame, error) {
var frame media.Frame
switch stream {
case 1:
frame = video.Frame()
case 2:
frame = audio.Frame()
}
if frame.Time() >= duration {
return nil, io.EOF
} else {
log.Println("Frame", stream, "=>", frame.Time().Truncate(time.Millisecond))
return frame.(*ffmpeg.Frame).AVFrame(), nil
}
}, nil); err != nil {
log.Fatal(err)
}
}
Binary file added etc/test/sample.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added etc/test/sample.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added etc/test/sample_resized.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 9 additions & 9 deletions interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ type Manager interface {
// Return supported input formats which match any filter, which can be
// a name, extension (with preceeding period) or mimetype. The MediaType
// can be NONE (for any) or combinations of DEVICE and STREAM.
InputFormats(MediaType, ...string) []Format
InputFormats(Type, ...string) []Format

// Return supported output formats which match any filter, which can be
// a name, extension (with preceeding period) or mimetype. The MediaType
// can be NONE (for any) or combinations of DEVICE and STREAM.
OutputFormats(MediaType, ...string) []Format
OutputFormats(Type, ...string) []Format

// Return supported devices for a given format.
// Not all devices may be supported on all platforms or listed
Expand Down Expand Up @@ -105,7 +105,7 @@ type Device interface {
Description() string

// Flags indicating the type INPUT or OUTPUT, AUDIO or VIDEO
Type() MediaType
Type() Type

// Whether this is the default device
Default() bool
Expand All @@ -129,7 +129,7 @@ type Format interface {

// Flags indicating the type. INPUT for a demuxer or source, OUTPUT for a muxer or
// sink, DEVICE for a device, FILE for a file. Plus AUDIO, VIDEO, DATA, SUBTITLE.
Type() MediaType
Type() Type
}

// Media represents a media stream, which can be input or output. A new media
Expand All @@ -150,7 +150,7 @@ type Media interface {

// Return INPUT for a demuxer or source, OUTPUT for a muxer or
// sink, DEVICE for a device, FILE for a file or stream.
Type() MediaType
Type() Type

// Return the metadata for the media, filtering by keys if any
// are included. Use the "artwork" key to return only artwork.
Expand All @@ -168,7 +168,7 @@ type DecoderMapFunc func(Stream) (Parameters, error)
// within a media file
type Stream interface {
// Return AUDIO, VIDEO, SUBTITLE or DATA
Type() MediaType
Type() Type

// Return the stream parameters
Parameters() Parameters
Expand All @@ -195,7 +195,7 @@ type Parameters interface {
VideoParameters

// Return the media type (AUDIO, VIDEO, SUBTITLE, DATA)
Type() MediaType
Type() Type

// Return the stream id for encoding, or zero if not set
Id() int
Expand Down Expand Up @@ -254,14 +254,14 @@ type Codec interface {
Description() string

// Return the codec type (AUDIO, VIDEO, SUBTITLE, DATA, INPUT, OUTPUT)
Type() MediaType
Type() Type
}

// Packet represents a packet of demultiplexed data, or a packet
// to be multiplexed.
type Packet interface {
// The packet can be audio, video, subtitle or data.
Type() MediaType
Type() Type

// The stream identifier for the packet
Id() int
Expand Down
Loading

0 comments on commit fef25db

Please sign in to comment.