mirror of
https://github.com/qrtc/ffmpeg-dev-go.git
synced 2025-10-30 02:11:49 +08:00
2023-10-22 11:46:19 CST W43D0
This commit is contained in:
@@ -1,5 +1,113 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
ffmpeg "github.com/qrtc/ffmpeg-dev-go"
|
||||
)
|
||||
|
||||
func typeString(_type int32) string {
|
||||
switch _type {
|
||||
case ffmpeg.AVIO_ENTRY_DIRECTORY:
|
||||
return "<DIR>"
|
||||
case ffmpeg.AVIO_ENTRY_FILE:
|
||||
return "<FILE>"
|
||||
case ffmpeg.AVIO_ENTRY_BLOCK_DEVICE:
|
||||
return "<BLOCK DEVICE>"
|
||||
case ffmpeg.AVIO_ENTRY_CHARACTER_DEVICE:
|
||||
return "<CHARACTER DEVICE>"
|
||||
case ffmpeg.AVIO_ENTRY_NAMED_PIPE:
|
||||
return "<PIPE>"
|
||||
case ffmpeg.AVIO_ENTRY_SYMBOLIC_LINK:
|
||||
return "<LINK>"
|
||||
case ffmpeg.AVIO_ENTRY_SOCKET:
|
||||
return "<SOCKET>"
|
||||
case ffmpeg.AVIO_ENTRY_SERVER:
|
||||
return "<SERVER>"
|
||||
case ffmpeg.AVIO_ENTRY_SHARE:
|
||||
return "<SHARE>"
|
||||
case ffmpeg.AVIO_ENTRY_WORKGROUP:
|
||||
return "<WORKGROUP>"
|
||||
case ffmpeg.AVIO_ENTRY_UNKNOWN:
|
||||
default:
|
||||
break
|
||||
}
|
||||
return "<UNKNOWN>"
|
||||
}
|
||||
|
||||
func listOp(inputDir string) int32 {
|
||||
var entry *ffmpeg.AVIODirEntry
|
||||
var ctx *ffmpeg.AVIODirContext
|
||||
var cnt, ret int32
|
||||
var filemode, uidAndGid string
|
||||
|
||||
if ret = ffmpeg.AvIOOpenDir(&ctx, inputDir, nil); ret < 0 {
|
||||
ffmpeg.AvLog(nil, ffmpeg.AV_LOG_ERROR, "Cannot open directory: %s.\n", ffmpeg.AvErr2str(ret))
|
||||
goto fail
|
||||
}
|
||||
|
||||
for {
|
||||
if ret = ffmpeg.AvIOReadDir(ctx, &entry); ret < 0 {
|
||||
ffmpeg.AvLog(nil, ffmpeg.AV_LOG_ERROR, "Cannot list directory: %s.\n", ffmpeg.AvErr2str(ret))
|
||||
goto fail
|
||||
}
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
if entry.GetFilemode() == -1 {
|
||||
filemode = "???"
|
||||
} else {
|
||||
filemode = fmt.Sprintf("%3d", entry.GetFilemode())
|
||||
}
|
||||
uidAndGid = fmt.Sprintf("%d(%d)", entry.GetUserId(), entry.GetGroupId())
|
||||
if cnt == 0 {
|
||||
ffmpeg.AvLog(nil, ffmpeg.AV_LOG_INFO, "%-9s %12s %30s %10s %s %16s %16s %16s\n",
|
||||
"TYPE", "SIZE", "NAME", "UID(GID)", "UGO", "MODIFIED",
|
||||
"ACCESSED", "STATUS_CHANGED")
|
||||
}
|
||||
ffmpeg.AvLog(nil, ffmpeg.AV_LOG_INFO, "%-9s %12d %30s %10s %s %d %d %d\n",
|
||||
typeString(entry.GetType()),
|
||||
entry.GetSize(),
|
||||
entry.GetName(),
|
||||
uidAndGid,
|
||||
filemode,
|
||||
entry.GetModificationTimestamp(),
|
||||
entry.GetAccessTimestamp(),
|
||||
entry.GetStatusChangeTimestamp())
|
||||
ffmpeg.AvIOFreeDirectoryEntry(&entry)
|
||||
cnt++
|
||||
}
|
||||
|
||||
fail:
|
||||
ffmpeg.AvIOCloseDir(&ctx)
|
||||
return ret
|
||||
}
|
||||
|
||||
func usage(programName string) {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s input_dir\n"+
|
||||
"API example program to show how to list files in directory "+
|
||||
"accessed through AVIOContext.\n", programName)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var ret int32
|
||||
|
||||
ffmpeg.AvLogSetLevel(ffmpeg.AV_LOG_DEBUG)
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
usage(os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
ffmpeg.AvFormatNetworkInit()
|
||||
|
||||
ret = listOp(os.Args[1])
|
||||
|
||||
ffmpeg.AvFormatNetworkDeinit()
|
||||
|
||||
if ret < 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,118 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
int readPacket(void* opaque, uint8_t *buf, int bufSize);
|
||||
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime/cgo"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
ffmpeg "github.com/qrtc/ffmpeg-dev-go"
|
||||
)
|
||||
|
||||
type bufferData struct {
|
||||
ptr *uint8
|
||||
size uintptr
|
||||
}
|
||||
|
||||
//export readPacket
|
||||
func readPacket(opaque unsafe.Pointer, buf *uint8, bufSize int32) int32 {
|
||||
bd := (*(*cgo.Handle)(opaque)).Value().(*bufferData)
|
||||
bufSize = ffmpeg.FFMIN(bufSize, int32(bd.size))
|
||||
|
||||
if bufSize == 0 {
|
||||
return ffmpeg.AVERROR_EOF
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "ptr:%p size:%d\n", bd.ptr, bd.size)
|
||||
|
||||
// copy internal buffer data to buf
|
||||
bd.ptr = ffmpeg.PointerOffset(bd.ptr, bufSize)
|
||||
bd.size -= uintptr(bufSize)
|
||||
|
||||
return bufSize
|
||||
}
|
||||
|
||||
func main() {
|
||||
var fmtCtx *ffmpeg.AVFormatContext
|
||||
var avioCtx *ffmpeg.AVIOContext
|
||||
var buffer, avioCtxBuffer *uint8
|
||||
var bufferSize uintptr
|
||||
var avioCtxBufferSize uint = 4096
|
||||
var ret int32
|
||||
var bd bufferData
|
||||
var opaqueHandle cgo.Handle
|
||||
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s input_file\n"+
|
||||
"API example program to show how to read from a custom buffer "+
|
||||
"accessed through AVIOContext.\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
inputFilename := os.Args[1]
|
||||
|
||||
// slurp file content into buffer
|
||||
if ret = ffmpeg.AvFileMap(inputFilename, &buffer, &bufferSize, 0, nil); ret < 0 {
|
||||
goto end
|
||||
}
|
||||
|
||||
// fill opaque structure used by the AVIOContext read callback
|
||||
bd.ptr = buffer
|
||||
bd.size = bufferSize
|
||||
|
||||
if fmtCtx = ffmpeg.AvFormatAllocContext(); fmtCtx == nil {
|
||||
ret = ffmpeg.AVERROR(syscall.ENOMEM)
|
||||
goto end
|
||||
}
|
||||
|
||||
if avioCtxBuffer = (*uint8)(ffmpeg.AvMalloc(avioCtxBufferSize)); avioCtxBuffer == nil {
|
||||
ret = ffmpeg.AVERROR(syscall.ENOMEM)
|
||||
goto end
|
||||
}
|
||||
|
||||
opaqueHandle = cgo.NewHandle(&bd)
|
||||
if avioCtx = ffmpeg.AvIOAllocContext(avioCtxBuffer, int32(avioCtxBufferSize), 0,
|
||||
&opaqueHandle, (ffmpeg.AVIOContextReadPacketFunc)(C.readPacket), nil, nil); avioCtx == nil {
|
||||
ret = ffmpeg.AVERROR(syscall.ENOMEM)
|
||||
goto end
|
||||
}
|
||||
fmtCtx.SetPb(avioCtx)
|
||||
|
||||
if ret = ffmpeg.AvFormatOpenInput(&fmtCtx, ffmpeg.NIL, nil, nil); ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Could not open input\n")
|
||||
goto end
|
||||
}
|
||||
|
||||
if ret = ffmpeg.AvFormatFindStreamInfo(fmtCtx, nil); ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Could not find stream information\n")
|
||||
goto end
|
||||
}
|
||||
|
||||
ffmpeg.AvDumpFormat(fmtCtx, 0, inputFilename, 0)
|
||||
|
||||
end:
|
||||
ffmpeg.AvFormatCloseInput(&fmtCtx)
|
||||
|
||||
if opaqueHandle != 0 {
|
||||
opaqueHandle.Delete()
|
||||
}
|
||||
|
||||
// note: the internal buffer could have changed, and be != avio_ctx_buffer
|
||||
if avioCtx != nil {
|
||||
ffmpeg.AvFreep(avioCtx.GetBufferAddr())
|
||||
}
|
||||
ffmpeg.AvIOContextFree(&avioCtx)
|
||||
|
||||
ffmpeg.AvFileUnmap(buffer, bufferSize)
|
||||
|
||||
if ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Error occurred: %s\n", ffmpeg.AvErr2str(ret))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ func getFormatFromSampleFmt(sampleFmt ffmpeg.AVSampleFormat) (string, int32) {
|
||||
|
||||
fmt.Fprintf(os.Stderr, "sample format %s is not supported as output format\n",
|
||||
ffmpeg.AvGetSampleFmtName(sampleFmt))
|
||||
return "", -1
|
||||
return ffmpeg.NIL, -1
|
||||
}
|
||||
|
||||
func decode(decCtx *ffmpeg.AVCodecContext, pkt *ffmpeg.AVPacket, frame *ffmpeg.AVFrame, outfile *os.File) {
|
||||
@@ -62,7 +62,7 @@ func decode(decCtx *ffmpeg.AVCodecContext, pkt *ffmpeg.AVPacket, frame *ffmpeg.A
|
||||
}
|
||||
for i := int32(0); i < frame.GetNbSamples(); i++ {
|
||||
for ch := 0; ch < int(decCtx.GetChannels()); ch++ {
|
||||
outfile.Write(ffmpeg.ByteSliceWithOffset(frame.GetDataIdx(ch), dataSize*i, dataSize))
|
||||
outfile.Write(ffmpeg.ByteSliceWithOffset(frame.GetData()[ch], dataSize*i, dataSize))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func decode(decCtx *ffmpeg.AVCodecContext, frame *ffmpeg.AVFrame, pkt *ffmpeg.AV
|
||||
|
||||
// the picture is allocated by the decoder. no need to free it
|
||||
fname := fmt.Sprintf("%s-%d", filename, decCtx.GetFrameNumber())
|
||||
pgmSave(frame.GetDataIdx(0), frame.GetLinesizeIdx(0), frame.GetWidth(), frame.GetHeight(), fname)
|
||||
pgmSave(frame.GetData()[0], frame.GetLinesize()[0], frame.GetWidth(), frame.GetHeight(), fname)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ func main() {
|
||||
if ret := ffmpeg.AvFrameMakeWritable(frame); ret < 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
samples := unsafe.Slice((*uint16)(unsafe.Pointer(frame.GetDataIdx(0))), 2*avctx.GetFrameSize()+avctx.GetChannels())
|
||||
samples := unsafe.Slice((*uint16)(unsafe.Pointer(frame.GetData()[0])), avctx.GetFrameSize()*avctx.GetChannels())
|
||||
|
||||
for j := 0; j < int(avctx.GetFrameSize()); j++ {
|
||||
samples[2*j] = (uint16)(math.Sin(t) * 10000)
|
||||
|
||||
@@ -120,20 +120,20 @@ func main() {
|
||||
}
|
||||
|
||||
// prepare a dummy image
|
||||
data0 := unsafe.Slice(frame.GetDataIdx(0), avctx.GetHeight()*frame.GetLinesizeIdx(0)+avctx.GetWidth())
|
||||
data1 := unsafe.Slice(frame.GetDataIdx(1), (avctx.GetHeight()/2)*frame.GetLinesizeIdx(1)+(avctx.GetWidth()/2))
|
||||
data2 := unsafe.Slice(frame.GetDataIdx(2), (avctx.GetHeight()/2)*frame.GetLinesizeIdx(2)+(avctx.GetWidth()/2))
|
||||
data0 := unsafe.Slice(frame.GetData()[0], avctx.GetHeight()*frame.GetLinesize()[0])
|
||||
data1 := unsafe.Slice(frame.GetData()[1], (avctx.GetHeight()/2)*frame.GetLinesize()[1])
|
||||
data2 := unsafe.Slice(frame.GetData()[2], (avctx.GetHeight()/2)*frame.GetLinesize()[2])
|
||||
// Y
|
||||
for y := 0; y < int(avctx.GetHeight()); y++ {
|
||||
for x := 0; x < int(avctx.GetWidth()); x++ {
|
||||
data0[y*int(frame.GetLinesizeIdx(0))+x] = uint8(x + y + i*3)
|
||||
data0[y*int(frame.GetLinesize()[0])+x] = uint8(x + y + i*3)
|
||||
}
|
||||
}
|
||||
// Cb and Cr
|
||||
for y := 0; y < int(avctx.GetHeight()/2); y++ {
|
||||
for x := 0; x < int(avctx.GetWidth()/2); x++ {
|
||||
data1[y*int(frame.GetLinesizeIdx(1))+x] = uint8(128 + y + i*2)
|
||||
data2[y*int(frame.GetLinesizeIdx(2))+x] = uint8(64 + x + i*5)
|
||||
data1[y*int(frame.GetLinesize()[1])+x] = uint8(128 + y + i*2)
|
||||
data2[y*int(frame.GetLinesize()[2])+x] = uint8(64 + x + i*5)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package main
|
||||
|
||||
// filter-audio 0.05
|
||||
// plane 0: 0x3A1E227C0C1A0DA59EAA91C35653125C
|
||||
// plane 0: 0xA7922B09261B407E49C545A68B671572
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
@@ -22,7 +22,7 @@ int get_hw_format(struct AVCodecContext *ctx, const int *pix_fmts)
|
||||
{
|
||||
const int *p;
|
||||
|
||||
fprintf(stderr, "get_hw_format called.\n");
|
||||
fprintf(stderr, "get_hw_format ballback has been invoked.\n");
|
||||
for (p = pix_fmts; *p != -1; p++) {
|
||||
if (*p == hw_pix_fmt)
|
||||
return *p;
|
||||
@@ -44,20 +44,20 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
hwDeviceCtx *ffmpeg.AVBufferRef
|
||||
outputFile *os.File
|
||||
// Note: Gobal variable as argument pass to C world may be cause panic.
|
||||
// `runtime error: cgo argument has Go pointer to unpinned Go pointer`
|
||||
)
|
||||
|
||||
func hwDecoderInit(ctx *ffmpeg.AVCodecContext, hwType ffmpeg.AVHWDeviceType) (ret int32) {
|
||||
if ret := ffmpeg.AvHWDeviceCtxCreate(&hwDeviceCtx, hwType, "", nil, 0); ret < 0 {
|
||||
func hwDecoderInit(ctx *ffmpeg.AVCodecContext, hwType ffmpeg.AVHWDeviceType) (hwDeviceCtx *ffmpeg.AVBufferRef, ret int32) {
|
||||
if ret := ffmpeg.AvHWDeviceCtxCreate(&hwDeviceCtx, hwType, ffmpeg.NIL, nil, 0); ret < 0 {
|
||||
fmt.Fprintf(os.Stderr, "Failed to create specified HW device.\n")
|
||||
return ret
|
||||
return nil, ret
|
||||
}
|
||||
ctx.SetHwDeviceCtx(ffmpeg.AvBufferRef(hwDeviceCtx))
|
||||
return ret
|
||||
return hwDeviceCtx, ret
|
||||
}
|
||||
|
||||
func decodeWrite(avctx *ffmpeg.AVCodecContext, packet *ffmpeg.AVPacket) (ret int32) {
|
||||
func decodeWrite(avctx *ffmpeg.AVCodecContext, packet *ffmpeg.AVPacket, outputFile *os.File) (ret int32) {
|
||||
var frame, swFrame, tmpFrame *ffmpeg.AVFrame
|
||||
var buffer *uint8
|
||||
var size int32
|
||||
@@ -129,6 +129,8 @@ func decodeWrite(avctx *ffmpeg.AVCodecContext, packet *ffmpeg.AVPacket) (ret int
|
||||
}
|
||||
|
||||
func main() {
|
||||
var outputFile *os.File
|
||||
var hwDeviceCtx *ffmpeg.AVBufferRef
|
||||
var inputCtx *ffmpeg.AVFormatContext
|
||||
var videoStream, ret int32
|
||||
var video *ffmpeg.AVStream
|
||||
@@ -182,7 +184,6 @@ func main() {
|
||||
}
|
||||
if (config.GetMethods()&ffmpeg.AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) != 0 &&
|
||||
config.GetDeviceType() == hwType {
|
||||
fmt.Fprintf(os.Stdout, "Support set_hw_pix_fmt. \n")
|
||||
C.set_hw_pix_fmt((C.int)(config.GetPixFmt()))
|
||||
break
|
||||
}
|
||||
@@ -192,14 +193,14 @@ func main() {
|
||||
os.Exit(int(ffmpeg.AVERROR(syscall.ENOMEM)))
|
||||
}
|
||||
|
||||
video = inputCtx.GetStreamsIdx(int(videoStream))
|
||||
video = inputCtx.GetStreams()[videoStream]
|
||||
if ret = ffmpeg.AvCodecParametersToContext(decoderCtx, video.GetCodecpar()); ret < 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
decoderCtx.SetGetFormat((ffmpeg.AVCodecContextGetFormatFunc)(C.get_hw_format))
|
||||
|
||||
if ret = hwDecoderInit(decoderCtx, hwType); ret < 0 {
|
||||
if hwDeviceCtx, ret = hwDecoderInit(decoderCtx, hwType); ret < 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -217,7 +218,7 @@ func main() {
|
||||
break
|
||||
}
|
||||
if videoStream == packet.GetStreamIndex() {
|
||||
ret = decodeWrite(decoderCtx, &packet)
|
||||
ret = decodeWrite(decoderCtx, &packet, outputFile)
|
||||
}
|
||||
|
||||
ffmpeg.AvPacketUnref(&packet)
|
||||
@@ -226,7 +227,7 @@ func main() {
|
||||
// flush the decoder
|
||||
packet.SetData(nil)
|
||||
packet.SetSize(0)
|
||||
ret = decodeWrite(decoderCtx, &packet)
|
||||
ret = decodeWrite(decoderCtx, &packet, outputFile)
|
||||
ffmpeg.AvPacketUnref(&packet)
|
||||
|
||||
if outputFile != nil {
|
||||
|
||||
@@ -1,5 +1,40 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
ffmpeg "github.com/qrtc/ffmpeg-dev-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var fmtCtx *ffmpeg.AVFormatContext
|
||||
var tag *ffmpeg.AVDictionaryEntry
|
||||
var ret int32
|
||||
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s <input_file>\n"+
|
||||
"example program to demonstrate the use of the libavformat metadata API.\n"+
|
||||
"\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if ret = ffmpeg.AvFormatOpenInput(&fmtCtx, os.Args[1], nil, nil); ret != 0 {
|
||||
os.Exit(int(ret))
|
||||
}
|
||||
|
||||
if ret = ffmpeg.AvFormatFindStreamInfo(fmtCtx, nil); ret < 0 {
|
||||
ffmpeg.AvLog(nil, ffmpeg.AV_LOG_ERROR, "Cannot find stream information\n")
|
||||
os.Exit(int(ret))
|
||||
}
|
||||
|
||||
for {
|
||||
if tag = ffmpeg.AvDictGet(fmtCtx.GetMetadata(), "", tag, ffmpeg.AV_DICT_IGNORE_SUFFIX); tag == nil {
|
||||
break
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "%s=%s\n", tag.GetKey(), tag.GetValue())
|
||||
}
|
||||
|
||||
ffmpeg.AvFormatCloseInput(&fmtCtx)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
|
||||
func fillYuvImage(data [4]*uint8, linesize [4]int32, width, height, frameIndex int32) {
|
||||
// Y
|
||||
data0 := unsafe.Slice(data[0], height*linesize[0]+width)
|
||||
data0 := unsafe.Slice(data[0], height*linesize[0])
|
||||
for y := int32(0); y < height; y++ {
|
||||
for x := int32(0); x < width; x++ {
|
||||
data0[y*linesize[0]+x] = (uint8)(x + y + frameIndex*3)
|
||||
|
||||
@@ -100,7 +100,7 @@ func openOutputFile(filename string, inputCodecContext *ffmpeg.AVCodecContext) (
|
||||
outputFormatContext.SetPb(outputIOContext)
|
||||
|
||||
// Guess the desired container format based on the file extension.
|
||||
outputFormatContext.SetOformat(ffmpeg.AvGuessFormat("", filename, ""))
|
||||
outputFormatContext.SetOformat(ffmpeg.AvGuessFormat(ffmpeg.NIL, filename, ffmpeg.NIL))
|
||||
if outputFormatContext.GetOformat() == nil {
|
||||
fmt.Fprintf(os.Stderr, "Could not find output file format\n")
|
||||
goto cleanup
|
||||
|
||||
Reference in New Issue
Block a user