Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mostly fixed resampling #28

Merged
merged 12 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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