mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-26 18:52:44 +01:00
examples/video: put a video file in a separate server
This change also fixes an issue where a file could be closed before the video play ends. Closes #3116
This commit is contained in:
parent
f78025a3e3
commit
d0db7e1b60
@ -1,9 +0,0 @@
|
|||||||
# License
|
|
||||||
|
|
||||||
## `shibuya.mpg`
|
|
||||||
|
|
||||||
https://commons.wikimedia.org/wiki/File:Shibuya_Crossing,_Tokyo,_Japan_(video).webm
|
|
||||||
|
|
||||||
"Shibuya Crossing, Tokyo, Japan (video).webm" by Basile Morin
|
|
||||||
|
|
||||||
The Creative Commons Attribution-Share Alike 4.0 International license
|
|
@ -15,12 +15,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
@ -28,8 +27,12 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed shibuya.mpg
|
// mpgURL is a URL of an example MPEG-1 video. The license is the following:
|
||||||
var shibuya_mpg []byte
|
//
|
||||||
|
// https://commons.wikimedia.org/wiki/File:Shibuya_Crossing,_Tokyo,_Japan_(video).webm
|
||||||
|
// "Shibuya Crossing, Tokyo, Japan (video).webm" by Basile Morin
|
||||||
|
// The Creative Commons Attribution-Share Alike 4.0 International license
|
||||||
|
const mpgURL = "https://example-resources.ebitengine.org/shibuya.mpg"
|
||||||
|
|
||||||
type Game struct {
|
type Game struct {
|
||||||
player *mpegPlayer
|
player *mpegPlayer
|
||||||
@ -67,22 +70,23 @@ func main() {
|
|||||||
// ffmpeg -i YOUR_VIDEO -c:v mpeg1video -q:v 8 -c:a mp2 -format mpeg -ar 48000 output.mpg
|
// ffmpeg -i YOUR_VIDEO -c:v mpeg1video -q:v 8 -c:a mp2 -format mpeg -ar 48000 output.mpg
|
||||||
//
|
//
|
||||||
// You can adjust quality by changing -q:v value. A lower value indicates better quality.
|
// You can adjust quality by changing -q:v value. A lower value indicates better quality.
|
||||||
var in io.ReadSeeker
|
var in io.ReadCloser
|
||||||
if len(os.Args) > 1 {
|
if len(os.Args) > 1 {
|
||||||
f, err := os.Open(os.Args[1])
|
f, err := os.Open(os.Args[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
defer func() {
|
|
||||||
_ = f.Close()
|
|
||||||
}()
|
|
||||||
in = f
|
in = f
|
||||||
} else {
|
} else {
|
||||||
in = bytes.NewReader(shibuya_mpg)
|
res, err := http.Get(mpgURL)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
in = res.Body
|
||||||
fmt.Println("Play the default video. You can specify a video file as an argument.")
|
fmt.Println("Play the default video. You can specify a video file as an argument.")
|
||||||
}
|
}
|
||||||
|
|
||||||
player, err := newMPEGPlayer(bufio.NewReader(in))
|
player, err := newMPEGPlayer(in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -50,10 +50,14 @@ type mpegPlayer struct {
|
|||||||
// These members are used when the video doesn't have an audio stream.
|
// These members are used when the video doesn't have an audio stream.
|
||||||
refTime time.Time
|
refTime time.Time
|
||||||
|
|
||||||
|
src io.ReadCloser
|
||||||
|
|
||||||
|
closeOnce sync.Once
|
||||||
|
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMPEGPlayer(src io.Reader) (*mpegPlayer, error) {
|
func newMPEGPlayer(src io.ReadCloser) (*mpegPlayer, error) {
|
||||||
mpg, err := mpeg.New(src)
|
mpg, err := mpeg.New(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -70,6 +74,7 @@ func newMPEGPlayer(src io.Reader) (*mpegPlayer, error) {
|
|||||||
yCbCrImage: ebiten.NewImage(mpg.Width(), mpg.Height()),
|
yCbCrImage: ebiten.NewImage(mpg.Width(), mpg.Height()),
|
||||||
yCbCrBytes: make([]byte, 4*mpg.Width()*mpg.Height()),
|
yCbCrBytes: make([]byte, 4*mpg.Width()*mpg.Height()),
|
||||||
frameImage: ebiten.NewImage(mpg.Width(), mpg.Height()),
|
frameImage: ebiten.NewImage(mpg.Width(), mpg.Height()),
|
||||||
|
src: src,
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := ebiten.NewShader([]byte(`package main
|
s, err := ebiten.NewShader([]byte(`package main
|
||||||
@ -140,7 +145,14 @@ func (p *mpegPlayer) updateFrame() error {
|
|||||||
video := p.mpg.Video()
|
video := p.mpg.Video()
|
||||||
if video.HasEnded() {
|
if video.HasEnded() {
|
||||||
p.frameImage.Clear()
|
p.frameImage.Clear()
|
||||||
return nil
|
var err error
|
||||||
|
p.closeOnce.Do(func() {
|
||||||
|
fmt.Println("The video has ended.")
|
||||||
|
if err1 := p.src.Close(); err1 != nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
d := 1 / p.mpg.Framerate()
|
d := 1 / p.mpg.Framerate()
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user