Files
ffmpeg-dev-go/examples/scaling-video/main.go
2023-10-22 09:27:27 +08:00

116 lines
3.3 KiB
Go

package main
import (
"fmt"
"os"
"syscall"
"unsafe"
ffmpeg "github.com/qrtc/ffmpeg-dev-go"
)
func fillYuvImage(data [4]*uint8, linesize [4]int32, width, height, frameIndex int32) {
// Y
data0 := unsafe.Slice(data[0], height*linesize[0]+width)
for y := int32(0); y < height; y++ {
for x := int32(0); x < width; x++ {
data0[y*linesize[0]+x] = (uint8)(x + y + frameIndex*3)
}
}
// Cb and Cr
data1 := unsafe.Slice(data[1], height*width/4)
data2 := unsafe.Slice(data[2], height*width/4)
for y := int32(0); y < height/2; y++ {
for x := int32(0); x < width/2; x++ {
data1[y*linesize[1]+x] = (uint8)(128 + y + frameIndex*2)
data2[y*linesize[2]+x] = (uint8)(64 + x + frameIndex*5)
}
}
}
func main() {
var ret int32
var dstBufsize int32
var srcW int32 = 320
var srcH int32 = 240
var dstW, dstH int32
var srcData, dstData [4]*uint8
var srcLinesize, dstLinesize [4]int32
var srcPixFmt = ffmpeg.AV_PIX_FMT_YUV420P
var dstPixFmt = ffmpeg.AV_PIX_FMT_RGB24
if len(os.Args) != 3 {
fmt.Fprintf(os.Stderr, "Usage: %s output_file output_size\n"+
"API example program to show how to scale an image with libswscale.\n"+
"This program generates a series of pictures, rescales them to the given "+
"output_size and saves them to an output file named output_file\n."+
"\n", os.Args[0])
os.Exit(1)
}
dstFilename := os.Args[1]
dstSize := os.Args[2]
if ret = ffmpeg.AvParseVideoSize(&dstW, &dstH, dstSize); ret < 0 {
fmt.Fprintf(os.Stderr,
"Invalid size '%s', must be in the form WxH or a valid size abbreviation\n", dstSize)
os.Exit(1)
}
dstFile, err := os.OpenFile(dstFilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not open %s\n", dstFilename)
os.Exit(1)
}
// create scaling context
swsCtx := ffmpeg.SwsGetContext(srcW, srcH, srcPixFmt,
dstW, dstH, dstPixFmt,
ffmpeg.SWS_BILINEAR, nil, nil, nil)
if swsCtx == nil {
fmt.Fprintf(os.Stderr, "Impossible to create scale context for the conversion "+
"fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n",
ffmpeg.AvGetPixFmtName(srcPixFmt), srcW, srcH,
ffmpeg.AvGetPixFmtName(dstPixFmt), dstW, dstH)
ret = ffmpeg.AVERROR(syscall.EINVAL)
goto end
}
// allocate source and destination image buffers
if ret = ffmpeg.AvImageAlloc(srcData[:], srcLinesize[:], srcW, srcH, srcPixFmt, 16); ret < 0 {
fmt.Fprintf(os.Stderr, "Could not allocate source image\n")
goto end
}
// buffer is going to be written to rawvideo file, no alignment
if ret = ffmpeg.AvImageAlloc(dstData[:], dstLinesize[:], dstW, dstH, dstPixFmt, 1); ret < 0 {
fmt.Fprintf(os.Stderr, "Could not allocate destination image\n")
goto end
}
dstBufsize = ret
for i := int32(0); i < 100; i++ {
// generate synthetic video
fillYuvImage(srcData, srcLinesize, srcW, srcH, i)
// convert to destination format
ffmpeg.SwsScale(swsCtx, srcData[:], srcLinesize[:], 0, srcH, dstData[:], dstLinesize[:])
// write scaled image to file
dstFile.Write(unsafe.Slice(dstData[0], dstBufsize))
}
fmt.Fprintf(os.Stderr, "Scaling succeeded. Play the output file with the command:\n"+
"ffplay -f rawvideo -pix_fmt %s -video_size %dx%d %s\n",
ffmpeg.AvGetPixFmtName(dstPixFmt), dstW, dstH, dstFilename)
end:
dstFile.Close()
ffmpeg.AvFreep(&srcData[0])
ffmpeg.AvFreep(&dstData[0])
ffmpeg.SwsFreeContext(swsCtx)
if ret < 0 {
os.Exit(1)
}
}