mirror of
https://github.com/qrtc/ffmpeg-dev-go.git
synced 2025-10-07 08:30:58 +08:00
2023-10-24 21:24:55 CST W43D2
This commit is contained in:
@@ -60,9 +60,10 @@ func decode(decCtx *ffmpeg.AVCodecContext, pkt *ffmpeg.AVPacket, frame *ffmpeg.A
|
||||
fmt.Fprintf(os.Stderr, "Failed to calculate data size\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
data := ffmpeg.SliceSlice(&frame.GetData()[0], decCtx.GetChannels(), frame.GetNbSamples()*dataSize)
|
||||
for i := int32(0); i < frame.GetNbSamples(); i++ {
|
||||
for ch := 0; ch < int(decCtx.GetChannels()); ch++ {
|
||||
outfile.Write(ffmpeg.ByteSliceWithOffset(frame.GetData()[ch], dataSize*i, dataSize))
|
||||
outfile.Write(data[ch][dataSize*i : dataSize*(i+1)])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
ffmpeg "github.com/qrtc/ffmpeg-dev-go"
|
||||
)
|
||||
@@ -16,8 +17,9 @@ const (
|
||||
func pgmSave(buf *uint8, wrap, xsize, ysize int32, filename string) {
|
||||
f, _ := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
|
||||
fmt.Fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255)
|
||||
bufSlice := unsafe.Slice(buf, xsize*ysize)
|
||||
for i := int32(0); i < ysize; i++ {
|
||||
f.Write(ffmpeg.ByteSliceWithOffset(buf, i+wrap, xsize))
|
||||
f.Write(bufSlice[i+wrap : i+wrap+xsize])
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
|
@@ -73,10 +73,9 @@ func encode(ctx *ffmpeg.AVCodecContext, frame *ffmpeg.AVFrame, pkt *ffmpeg.AVPac
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
output.Write(ffmpeg.ByteSlice(pkt.GetData(), pkt.GetSize()))
|
||||
output.Write(unsafe.Slice(pkt.GetData(), pkt.GetSize()))
|
||||
ffmpeg.AvPacketUnref(pkt)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@@ -1,5 +1,159 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
// http-multiclient README.txt http://localhost:8082
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
ffmpeg "github.com/qrtc/ffmpeg-dev-go"
|
||||
)
|
||||
|
||||
var (
|
||||
videoFrameCount int
|
||||
srcFilename string
|
||||
)
|
||||
|
||||
func decodePacket(videoDecCtx *ffmpeg.AVCodecContext,
|
||||
pkt *ffmpeg.AVPacket, frame *ffmpeg.AVFrame) (ret int32) {
|
||||
|
||||
if ret = ffmpeg.AvCodecSendPacket(videoDecCtx, pkt); ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Error while sending a packet to the decoder: %s\n", ffmpeg.AvErr2str(ret))
|
||||
return ret
|
||||
}
|
||||
|
||||
for ret >= 0 {
|
||||
ret = ffmpeg.AvCodecReceiveFrame(videoDecCtx, frame)
|
||||
if ret == ffmpeg.AVERROR(syscall.EAGAIN) || ret == ffmpeg.AVERROR_EOF {
|
||||
break
|
||||
} else if ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Error while receiving a frame from the decoder: %s\n", ffmpeg.AvErr2str(ret))
|
||||
return ret
|
||||
}
|
||||
|
||||
if ret > 0 {
|
||||
videoFrameCount++
|
||||
if sd := ffmpeg.AvFrameGetSideData(frame, ffmpeg.AV_FRAME_DATA_MOTION_VECTORS); sd != nil {
|
||||
mvs := (*ffmpeg.AVMotionVector)(unsafe.Pointer(sd.GetData()))
|
||||
nbMvs := int(sd.GetSize()) / int(unsafe.Sizeof(*mvs))
|
||||
for i := 0; i < nbMvs; i++ {
|
||||
mv := ffmpeg.PointerOffset(mvs, i)
|
||||
fmt.Fprintf(os.Stdout, "%d,%2d,%2d,%2d,%4d,%4d,%4d,%4d,0x%d\n",
|
||||
videoFrameCount, mv.GetSource(),
|
||||
mv.GetW(), mv.GetH(), mv.GetSrcX(), mv.GetSrcY(),
|
||||
mv.GetDstX(), mv.GetDstY(), mv.GetFlags())
|
||||
}
|
||||
}
|
||||
ffmpeg.AvFrameUnref(frame)
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func openCodecContext(fmtCtx *ffmpeg.AVFormatContext, _type ffmpeg.AVMediaType) (
|
||||
videoStreamIdx int32, videoStream *ffmpeg.AVStream, videoDecCtx *ffmpeg.AVCodecContext, ret int32) {
|
||||
var (
|
||||
dec *ffmpeg.AVCodec
|
||||
opt *ffmpeg.AVDictionary
|
||||
)
|
||||
ret = ffmpeg.AvFindBestStream(fmtCtx, _type, -1, -1, &dec, 0)
|
||||
if ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Could not find %s stream in input file '%s'\n",
|
||||
ffmpeg.AvGetMediaTypeString(_type), srcFilename)
|
||||
return 0, nil, nil, ret
|
||||
} else {
|
||||
videoStreamIdx = ret
|
||||
videoStream = fmtCtx.GetStreams()[videoStreamIdx]
|
||||
|
||||
if videoDecCtx = ffmpeg.AvCodecAllocContext3(dec); videoDecCtx == nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to allocate codec\n")
|
||||
return 0, nil, nil, ffmpeg.AVERROR(syscall.EINVAL)
|
||||
}
|
||||
|
||||
if ret = ffmpeg.AvCodecParametersToContext(videoDecCtx, videoStream.GetCodecpar()); ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Failed to copy codec parameters to codec context\n")
|
||||
return 0, nil, nil, ret
|
||||
}
|
||||
|
||||
// Init the video decoder
|
||||
ffmpeg.AvDictSet(&opt, "flags2", "+export_mvs", 0)
|
||||
if ret = ffmpeg.AvCodecOpen2(videoDecCtx, dec, &opt); ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Failed to open %s codec\n", ffmpeg.AvGetMediaTypeString(_type))
|
||||
return 0, nil, nil, ret
|
||||
}
|
||||
|
||||
}
|
||||
return videoStreamIdx, videoStream, videoDecCtx, 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
fmtCtx *ffmpeg.AVFormatContext
|
||||
videoDecCtx *ffmpeg.AVCodecContext
|
||||
videoStream *ffmpeg.AVStream
|
||||
videoStreamIdx int32
|
||||
frame *ffmpeg.AVFrame
|
||||
|
||||
pkt ffmpeg.AVPacket
|
||||
ret int32
|
||||
)
|
||||
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Fprintf(os.Stderr, "Usage: %s <video>\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
srcFilename = os.Args[1]
|
||||
|
||||
if ret = ffmpeg.AvFormatOpenInput(&fmtCtx, srcFilename, nil, nil); ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Could not open source file %s\n", srcFilename)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if ret = ffmpeg.AvFormatFindStreamInfo(fmtCtx, nil); ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Could not find stream information\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
videoStreamIdx, videoStream, videoDecCtx, ret = openCodecContext(fmtCtx, ffmpeg.AVMEDIA_TYPE_VIDEO)
|
||||
|
||||
ffmpeg.AvDumpFormat(fmtCtx, 0, srcFilename, 0)
|
||||
|
||||
if videoStream == nil {
|
||||
fmt.Fprintf(os.Stderr, "Could not find video stream in the input, aborting\n")
|
||||
ret = 1
|
||||
goto end
|
||||
}
|
||||
|
||||
if frame = ffmpeg.AvFrameAlloc(); frame == nil {
|
||||
fmt.Fprintf(os.Stderr, "Could not allocate frame\n")
|
||||
ret = ffmpeg.AVERROR(syscall.ENOMEM)
|
||||
goto end
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stdout, "framenum,source,blockw,blockh,srcx,srcy,dstx,dsty,flags\n")
|
||||
|
||||
// read frames from the file
|
||||
for ffmpeg.AvReadFrame(fmtCtx, &pkt) >= 0 {
|
||||
if pkt.GetStreamIndex() == videoStreamIdx {
|
||||
ret = decodePacket(videoDecCtx, &pkt, frame)
|
||||
}
|
||||
ffmpeg.AvPacketUnref(&pkt)
|
||||
if ret < 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// flush cached frames
|
||||
decodePacket(videoDecCtx, nil, frame)
|
||||
|
||||
end:
|
||||
ffmpeg.AvCodecFreeContext(&videoDecCtx)
|
||||
ffmpeg.AvFormatCloseInput(&fmtCtx)
|
||||
ffmpeg.AvFrameFree(&frame)
|
||||
if ret < 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/qrtc/ffmpeg-dev-go"
|
||||
ffmpeg "github.com/qrtc/ffmpeg-dev-go"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -166,11 +166,12 @@ func processOutput(md5 *ffmpeg.AVMD5, frame *ffmpeg.AVFrame) int32 {
|
||||
planeSize *= channels
|
||||
}
|
||||
|
||||
data := ffmpeg.SliceSlice(frame.GetExtendedData(), planes, planeSize)
|
||||
for i := 0; i < int(planes); i++ {
|
||||
var checksum [16]uint8
|
||||
|
||||
ffmpeg.AvMd5Init(md5)
|
||||
ffmpeg.AvMd5Sum(&checksum[0], frame.GetExtendedDataIdx(i), planeSize)
|
||||
ffmpeg.AvMd5Sum(&checksum[0], &data[i][0], planeSize)
|
||||
|
||||
fmt.Fprintf(os.Stdout, "plane %d: 0x", i)
|
||||
for j := 0; j < len(checksum); j++ {
|
||||
@@ -198,13 +199,10 @@ func getInput(frame *ffmpeg.AVFrame, frameNum int32) int32 {
|
||||
}
|
||||
|
||||
// Fill the data for each channel.
|
||||
data := ffmpeg.SliceSlice((**float32)(unsafe.Pointer(frame.GetExtendedData())), 5, frame.GetNbSamples())
|
||||
for i := 0; i < 5; i++ {
|
||||
dataLen := int(frame.GetNbSamples())
|
||||
data := (*float32)(unsafe.Pointer(frame.GetExtendedDataIdx(i)))
|
||||
dataSlice := unsafe.Slice(data, dataLen)
|
||||
|
||||
for j := 0; j < dataLen; j++ {
|
||||
dataSlice[j] = (float32)(math.Sin(2 * math.Pi * (float64)(int(frameNum)+j) * (float64)(i+1) / FRAME_SIZE))
|
||||
for j := 0; j < int(frame.GetNbSamples()); j++ {
|
||||
data[i][j] = (float32)(math.Sin(2 * math.Pi * (float64)(int(frameNum)+j) * (float64)(i+1) / FRAME_SIZE))
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,138 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
ffmpeg "github.com/qrtc/ffmpeg-dev-go"
|
||||
)
|
||||
|
||||
func processClient(client *ffmpeg.AVIOContext, inUri string) {
|
||||
var (
|
||||
input *ffmpeg.AVIOContext
|
||||
resource *C.char
|
||||
buf [1024]uint8
|
||||
resourceStr string
|
||||
ret int32
|
||||
replyCode int32
|
||||
)
|
||||
|
||||
for {
|
||||
if ret = ffmpeg.AvIOHandshake(client); ret > 0 {
|
||||
ffmpeg.AvOptGet(client, "resource",
|
||||
ffmpeg.AV_OPT_SEARCH_CHILDREN, (**uint8)(unsafe.Pointer(&resource)))
|
||||
// check for strlen(resource) is necessary, because av_opt_get()
|
||||
// may return empty string.
|
||||
resourceStr = C.GoString(resource)
|
||||
if resource != nil && len(resourceStr) > 0 {
|
||||
break
|
||||
}
|
||||
ffmpeg.AvFreep(&resource)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if ret < 0 {
|
||||
goto end
|
||||
}
|
||||
ffmpeg.AvLog(client, ffmpeg.AV_LOG_TRACE, "resource=%s\n", resourceStr)
|
||||
if resource != nil && resourceStr[0] == '/' && resourceStr[1:] == inUri {
|
||||
replyCode = 200
|
||||
} else {
|
||||
ffmpeg.AvLog(client, ffmpeg.AV_LOG_TRACE, "resource: %s", resourceStr)
|
||||
replyCode = ffmpeg.AVERROR_HTTP_NOT_FOUND
|
||||
}
|
||||
if ret = ffmpeg.AvOptSetInt(client, "reply_code", int64(replyCode), ffmpeg.AV_OPT_SEARCH_CHILDREN); ret < 0 {
|
||||
ffmpeg.AvLog(client, ffmpeg.AV_LOG_ERROR, "Failed to set reply_code: %s.\n", ffmpeg.AvErr2str(ret))
|
||||
goto end
|
||||
}
|
||||
ffmpeg.AvLog(client, ffmpeg.AV_LOG_TRACE, "Set reply code to %d\n", replyCode)
|
||||
|
||||
for {
|
||||
if ret = ffmpeg.AvIOHandshake(client); ret <= 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if ret < 0 {
|
||||
goto end
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "Handshake performed.\n")
|
||||
|
||||
if replyCode != 200 {
|
||||
goto end
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "Opening input file.\n")
|
||||
if ret = ffmpeg.AvIOOpen2(&input, inUri, ffmpeg.AVIO_FLAG_READ, nil, nil); ret < 0 {
|
||||
ffmpeg.AvLog(client, ffmpeg.AV_LOG_ERROR, "Failed to open input: %s: %s.\n", inUri, ffmpeg.AvErr2str(ret))
|
||||
goto end
|
||||
}
|
||||
for {
|
||||
n := ffmpeg.AvIORead(input, &buf[0], 1024)
|
||||
if n < 0 {
|
||||
if n == ffmpeg.AVERROR_EOF {
|
||||
break
|
||||
}
|
||||
ffmpeg.AvLog(client, ffmpeg.AV_LOG_ERROR, "Error reading from input: %s.\n", ffmpeg.AvErr2str(ret))
|
||||
break
|
||||
}
|
||||
ffmpeg.AvIOWrite(client, &buf[0], n)
|
||||
ffmpeg.AvIOFlush(client)
|
||||
}
|
||||
end:
|
||||
fmt.Fprintf(os.Stderr, "Flushing client\n")
|
||||
ffmpeg.AvIOFlush(client)
|
||||
fmt.Fprintf(os.Stderr, "Closing client\n")
|
||||
ffmpeg.AvIOClose(client)
|
||||
fmt.Fprintf(os.Stderr, "Closing input\n")
|
||||
ffmpeg.AvIOClose(input)
|
||||
ffmpeg.AvFreep(&resource)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
options *ffmpeg.AVDictionary
|
||||
client, server *ffmpeg.AVIOContext
|
||||
ret int32
|
||||
)
|
||||
if len(os.Args) < 3 {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s input http://hostname[:port]\n"+
|
||||
"API example program to serve http to multiple clients.\n"+
|
||||
"\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
inUri := os.Args[1]
|
||||
outUri := os.Args[2]
|
||||
|
||||
ffmpeg.AvFormatNetworkInit()
|
||||
ffmpeg.AvLogSetLevel(ffmpeg.AV_LOG_TRACE)
|
||||
|
||||
if ret = ffmpeg.AvDictSet(&options, "listen", "2", 0); ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Failed to set listen mode for server: %s\n", ffmpeg.AvErr2str(ret))
|
||||
os.Exit(int(ret))
|
||||
}
|
||||
if ret = ffmpeg.AvIOOpen2(&server, outUri, ffmpeg.AVIO_FLAG_WRITE, nil, &options); ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Failed to open server: %s\n", ffmpeg.AvErr2str(ret))
|
||||
os.Exit(int(ret))
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "Entering main loop.\n")
|
||||
for {
|
||||
if ret = ffmpeg.AvIOAccept(server, &client); ret < 0 {
|
||||
goto end
|
||||
}
|
||||
go processClient(client, inUri)
|
||||
}
|
||||
end:
|
||||
ffmpeg.AvIOClose(server)
|
||||
if ret < 0 && ret != ffmpeg.AVERROR_EOF {
|
||||
fmt.Fprintf(os.Stderr, "Some errors occurred: %s\n", ffmpeg.AvErr2str(ret))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user