mpg

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 31, 2022 License: MIT Imports: 11 Imported by: 0

README

MPG-Go

Pure Go mpg decoding made from pl_mpeg

GoDoc GoReportCard

Mpg-go is a pure Go (no CGo) MPG decoder and player. It is made by transpiling pl_mpeg from C to Go using the cxgo translation tool.

Mpg-go's Goal is to provide an easy to use, pure Go software video and audio decoder. It provides functions meant for drawing frames to image/draw's Images, as well as writing directly to image's RGBA.Pix, and provides and easy to use audio reader made to work effortlessly in Ebiten or Oto. For a working example project showing many features of mpg-go, see player.

As pl_mpeg and cxgo are both experimental, mpg-go should also be experimental as well.

Encoding

Pl_mpeg supports mpg file container with MPEG1 ("mpeg1") video encoding and MPEG1 Audio Layer II ("mp2") audio encoding. While MPEG1 and MP2 is seen as outdated and inefficient, it's patents should have expired by now making it

You can encode your own videos to mpg with FFMPEG using the following command:

ffmpeg -i <YOUR_ORIGINAL_VIDEO> -c:v mpeg1video -c:a mp2 -q:v 0 <YOUR_OUTPUT_VIDEO>.mpg

This will convert the video from <YOUR_ORIGINAL_VIDEO> to <YOUR_OUTPUT_VIDEO>.mpg with the right codec and variable bitrate.

Getting started

Running example

To run the example, run this command:

go install github.com/crazyinfin8/mpg-go/example/player@latest
go run github.com/crazyinfin8/mpg-go/example/player

Install

To install this library for use in your own project, run the following command:

go get github.com/crazyinfin8/mpg-go

Usage

A new player can be created using one of the following functions

import "github.com/crazyinfin8/mpg-go"

player, err := mpg.NewPlayerFromFile(*io.File)
player, err := mpg.NewPlayerFromFilename(string)
player, err := mpg.NewPlayerFromBytes([]byte)

Set up your graphics library

import "github.com/crazyinfin8/mpg-go"
import "image"

if player.HasVideo() {
    width, height := player.Width(), player.Height()
    img := image.NewRGBA(image.Rect(0, 0, width, height))
    
    // if using functions ReadRGBA and ReadRGBAAt,
    // set alpha channels because those functions do not set them.
    mpg.SetAlpha(img.Pix)
}

Set up your audio library

import "github.com/hajimehoshi/ebiten/v2/audio"
import "time"

var ctx *audio.Context
var stream *audio.Player

if player.HasAudio() {
    samplerate := player.SampleRate()
    ctx = audio.NewContext(samplerate)
    stream = ctx.NewPlayer(player)
    player.SetByteDepth(2) // Ebiten uses 16-bit audio

    // Using default buffer size
    stream.SetBufferSize(player.AudioLeadTime())

    //setting a custom buffer size
    stream.SetBufferSize(50 * time.Millisecond)
    player.SetAudioLeadTime(50 * time.Millisecond)

    stream.Play()
}

Decode video and audio.

import "time"

framerate := player.FrameRate()

// Call this every frame to progress through and decode the video
//
// This moves at a fized rate for each frame, however it might be more smooth to 
// calculate a time delta per frame.
player.Decode(time.Duration(1 / framerate * float64(time.Second)))

Display the video (audio using Ebiten's audio.Player should already be playing)

if player.HasNewFrame() {
    // Sets a pixel byte array directly. Note that the pixel array should be the
    // same size as the frame i.e. width*height*4.
    player.ReadRGBA(img.Pix)
    // Draws itself to a "draw.Image"
    player.DrawTo(img)

    // Audio is already playing through the Ebiten audio stream.
}

Cleanup when finished

if player.Finished() {
    // video playback is done!
}

player.Close()

TODO

  • Add functions to just decode all frames and audio.
  • Make it easier to use mpg-go in other graphic libraries such as SDL and Raylib.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SetAlpha

func SetAlpha(a byte, data []byte)

SetAlpha is a helper function intended to set the alpha channel of "*image.RGBA.Pix" byte array since functions like "ReadRGBA" and "ReadRGBAAt" does not set alpha.

Types

type ExpectedHeader

type ExpectedHeader struct{}

ExpectedHeader is returned by "NewPlayer" functions when a file could not be processed

func (ExpectedHeader) Error

func (err ExpectedHeader) Error() string

type Player

type Player struct {
	// contains filtered or unexported fields
}

Player processes and decodes video and audio in MPG format (MPEG1 video encoding and MP2 audio encoding)

func NewPlayerFromBytes

func NewPlayerFromBytes(data []byte) (*Player, error)

NewPlayerFromBytes creates a new player from a list of raw bytes.

func NewPlayerFromFile

func NewPlayerFromFile(f *os.File) (*Player, error)

NewPlayerFromFile creates a new player from a given file. The file is not closed when the player is closed.

func NewPlayerFromFilename

func NewPlayerFromFilename(file string) (*Player, error)

NewPlayerFromFile creates a new player from a given filename.

func (*Player) AudioEnabled

func (plm *Player) AudioEnabled() bool

AudioEnabled returns true if decoding audio is enabled.

func (*Player) AudioLeadTime

func (plm *Player) AudioLeadTime() time.Duration

AudioLeadTime is how long the audio is decoded in advance or behind the video decode time.

func (*Player) ByteDepth

func (plm *Player) ByteDepth() int

ByteDepth is how many bytes are in each.

func (*Player) ClearAudioBuffer

func (plm *Player) ClearAudioBuffer()

ClearAudioBuffer clears the audio buffer.

func (*Player) Close

func (plm *Player) Close()

Close closes the internal player and discards data.

func (*Player) Decode

func (plm *Player) Decode(elapsed time.Duration)

Decode processes the video accordingly to the duration "elapsed".

func (*Player) DrawFrameAt

func (plm *Player) DrawFrameAt(img draw.Image, elapsed time.Duration, exact bool) bool

DrawFrameAt seeks to the specified time and draws the current frame to the image in "img".

If "exact" is false, this will seek to the nearest intra frame. If "exact" is true, this will seek to the exact time. this can be slower as each frame since the last intra frame would need to be decoded.

DrawFrameAt returns true when successful.

func (*Player) DrawTo

func (plm *Player) DrawTo(img draw.Image)

DrawTo draws the current frame to the image in "img".

func (*Player) Duration

func (plm *Player) Duration() time.Duration

Duration is how long the entire video is.

func (*Player) Finished

func (plm *Player) Finished() bool

Finished returns true when the video has ended. This is always false when looping.

func (*Player) FrameRate

func (plm *Player) FrameRate() float64

FrameRate is the number of frames in a second.

func (*Player) HasAudio

func (plm *Player) HasAudio() bool

HasAudio returns true if this file contains audio.

func (*Player) HasNewAudio

func (plm *Player) HasNewAudio() bool

HasNewAudio returns true if the audio buffer still contains unread data.

func (*Player) HasNewFrame

func (plm *Player) HasNewFrame() bool

HasNewFrame returns true if a new frame has been decoded. Drawing the current frame sets this to false

func (*Player) HasVideo

func (plm *Player) HasVideo() bool

HasVideo returns true if this file contains video.

func (*Player) Height

func (plm *Player) Height() int

Height is the height of the video.

func (*Player) Loop

func (plm *Player) Loop() bool

Loop returns true if the video was set to loop when finished.

func (*Player) NumAudioStreams

func (plm *Player) NumAudioStreams() int

NumAudioStreams returns the number of audio channels that are present in the file. (0-4)

func (*Player) NumVideoStreams

func (plm *Player) NumVideoStreams() int

NumVideoStreams returns the number of video channels present in the file. (0-1)

func (*Player) Read

func (plm *Player) Read(buf []byte) (n int, err error)

Read consumes and reads data from the audio buffer. If the audio buffer does not have any audio, it sends 0 to buf until it is full.

This is intended to make it easy to create an Ebiten or Oto player straight from this *Player

func (*Player) ReadRGBA

func (plm *Player) ReadRGBA(data []byte)

ReadRGBA overwrites the passed byte array in "data" in RGBA format. Intended for writing the current frame directly to "image.RGBA.Pix".

Alpha channels remain unchanged.

ReadRGBA panics if the size of data does not match the size of the frame (width * height * 4).

func (*Player) ReadRGBAAt

func (plm *Player) ReadRGBAAt(data []byte, elapsed time.Duration, exact bool) bool

ReadRGBAAt seeks to the specified time and overwrites the passed byte array in "data" in RGBA format. Intended mainly for writing the current frame directly to "image.RGBA.Pix".

If "exact" is false, this will seek to the nearest intra frame. If "exact" is true, this will seek to the exact time. this can be slower as each frame since the last intra frame would need to be decoded.

ReadRGBAAt returns true when successful.

Alpha channels remain unchanged.

ReadRGBAAt panics if the size of data does not match the size of the frame (width * height * 4).

func (*Player) Rewind

func (plm *Player) Rewind()

Rewind moves to the beginning.

func (*Player) SampleRate

func (plm *Player) SampleRate() int

SampleRate is how many samples per second in the audio stream.

func (*Player) Seek

func (plm *Player) Seek(time time.Duration, exact bool) bool

Seek to the specified time.

If "exact" is false, this will seek to the nearest intra frame. If "exact" is true, this will seek to the exact time. this can be slower as each frame since the last intra frame would need to be decoded.

Seek returns true when successful.

func (*Player) SetAudioEnabled

func (plm *Player) SetAudioEnabled(enabled bool)

SetAudioEnabled sets whether audio should be decoded.

func (*Player) SetAudioLeadTime

func (plm *Player) SetAudioLeadTime(time time.Duration)

SetAudioLeadTime sets how long the audio is decoded in advance or behind the video decode time. this is typically set to the duration of the buffer of your audio API.

func (*Player) SetByteDepth

func (plm *Player) SetByteDepth(depth int)

SetByteDepth sets how many bytes per sample audio is decoded as. Currently the values 1 (8-bit), 2 (16-bit), and 4 (32-bit) are supported.

func (*Player) SetLoop

func (plm *Player) SetLoop(set bool)

SetLoop sets whether the video should loop when finished.

func (*Player) SetVideoEnabled

func (plm *Player) SetVideoEnabled(enabled bool)

SetVideoEnabled sets whether video should be decododed.

func (*Player) Time

func (plm *Player) Time() time.Duration

Time is how far the video has progressed.

func (*Player) VideoEnabled

func (plm *Player) VideoEnabled() bool

VideoEnabled returns true if decoding video is enabled.

func (*Player) Width

func (plm *Player) Width() int

Width is the width of the video

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL