Working tutorial; More hooks to libav API; removes debbuging print

Missing constants, additional functions, remove errors
This commit is contained in:
Corebreaker
2019-04-07 13:45:00 -04:00
committed by Hab Giorgis
parent 821716f76b
commit 001779d032
27 changed files with 861 additions and 302 deletions
+2
View File
@@ -0,0 +1,2 @@
.idea/
.vscode/
-1
View File
@@ -1 +0,0 @@
theme: jekyll-theme-slate
+33
View File
@@ -33,6 +33,7 @@ type (
BitStreamFilterContext C.struct_AVBitStreamFilterContext
Rational C.struct_AVRational
Class C.struct_AVClass
AvCodecParameters C.struct_AVCodecParameters
AvHWAccel C.struct_AVHWAccel
AvPacketSideData C.struct_AVPacketSideData
AvPanScan C.struct_AVPanScan
@@ -56,6 +57,30 @@ type (
AvSampleFormat C.enum_AVSampleFormat
)
func (cp *AvCodecParameters) AvCodecGetId() CodecId {
return *((*CodecId)(unsafe.Pointer(&cp.codec_id)))
}
func (cp *AvCodecParameters) AvCodecGetType() MediaType {
return *((*MediaType)(unsafe.Pointer(&cp.codec_type)))
}
func (cp *AvCodecParameters) AvCodecGetWidth() int {
return *((*int)(unsafe.Pointer(&cp.width)))
}
func (cp *AvCodecParameters) AvCodecGetHeight() int {
return *((*int)(unsafe.Pointer(&cp.height)))
}
func (cp *AvCodecParameters) AvCodecGetChannels() int {
return *((*int)(unsafe.Pointer(&cp.channels)))
}
func (cp *AvCodecParameters) AvCodecGetSampleRate() int {
return *((*int)(unsafe.Pointer(&cp.sample_rate)))
}
func (c *Codec) AvCodecGetMaxLowres() int {
return int(C.av_codec_get_max_lowres((*C.struct_AVCodec)(c)))
}
@@ -136,6 +161,10 @@ func AvsubtitleFree(s *AvSubtitle) {
C.avsubtitle_free((*C.struct_AVSubtitle)(s))
}
func AvPacketAlloc() *Packet {
return (*Packet)(C.av_packet_alloc())
}
//Pack a dictionary for use in side_data.
func AvPacketPackDictionary(d *Dictionary, s *int) *uint8 {
return (*uint8)(C.av_packet_pack_dictionary((*C.struct_AVDictionary)(d), (*C.int)(unsafe.Pointer(s))))
@@ -151,6 +180,10 @@ func AvcodecFindDecoder(id CodecId) *Codec {
return (*Codec)(C.avcodec_find_decoder((C.enum_AVCodecID)(id)))
}
func AvCodecIterate(p *unsafe.Pointer) *Codec {
return (*Codec)(C.av_codec_iterate(p))
}
//Find a registered decoder with the specified name.
func AvcodecFindDecoderByName(n string) *Codec {
return (*Codec)(C.avcodec_find_decoder_by_name(C.CString(n)))
+13 -12
View File
@@ -8,22 +8,15 @@ package avcodec
import "C"
import (
"unsafe"
"github.com/selfmodify/goav/common"
)
func (ctxt *Context) AvCodecGetPktTimebase() Rational {
return (Rational)(C.av_codec_get_pkt_timebase((*C.struct_AVCodecContext)(ctxt)))
return Rational(C.av_codec_get_pkt_timebase((*C.struct_AVCodecContext)(ctxt)))
}
// AvCodecGetPktTimebase2 returns the timebase rational number as numerator and denominator
func (ctxt *Context) AvCodecGetPktTimebase2() (timebase common.AVRational) {
r := ctxt.AvCodecGetPktTimebase()
timebase = common.AVRational{
Num: int(r.num),
Den: int(r.den),
}
return
func (ctxt *Context) AvCodecGetPktTimebase2() Rational {
return ctxt.AvCodecGetPktTimebase()
}
func (ctxt *Context) AvCodecSetPktTimebase(r Rational) {
@@ -179,7 +172,7 @@ func (ctxt *Context) SetTimebase(num1 int, den1 int) {
ctxt.time_base.den = C.int(den1)
}
func (ctxt *Context) SetEncodeParams2(width int, height int, pxlFmt common.PixelFormat, hasBframes bool, gopSize int) {
func (ctxt *Context) SetEncodeParams2(width int, height int, pxlFmt PixelFormat, hasBframes bool, gopSize int) {
ctxt.width = C.int(width)
ctxt.height = C.int(height)
// ctxt.bit_rate = 1000000
@@ -197,6 +190,14 @@ func (ctxt *Context) SetEncodeParams2(width int, height int, pxlFmt common.Pixel
// C.av_opt_set(ctxt.priv_data, "preset", "ultrafast", 0)
}
func (ctxt *Context) SetEncodeParams(width int, height int, pxlFmt common.PixelFormat) {
func (ctxt *Context) SetEncodeParams(width int, height int, pxlFmt PixelFormat) {
ctxt.SetEncodeParams2(width, height, pxlFmt, false /*no b frames*/, 10)
}
func (ctxt *Context) AvcodecSendPacket(packet *Packet) int {
return (int)(C.avcodec_send_packet((*C.struct_AVCodecContext)(ctxt), (*C.struct_AVPacket)(packet)))
}
func (ctxt *Context) AvcodecReceiveFrame(frame *Frame) int {
return (int)(C.avcodec_receive_frame((*C.struct_AVCodecContext)(ctxt), (*C.struct_AVFrame)(frame)))
}
+39
View File
@@ -0,0 +1,39 @@
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.
// Giorgis (habtom@giorgis.io)
package avcodec
//#cgo pkg-config: libavcodec
//#include <libavcodec/avcodec.h>
import "C"
const (
AV_CODEC_FLAG_UNALIGNED = int(C.AV_CODEC_FLAG_UNALIGNED)
AV_CODEC_FLAG_QSCALE = int(C.AV_CODEC_FLAG_QSCALE)
AV_CODEC_FLAG_4MV = int(C.AV_CODEC_FLAG_4MV)
AV_CODEC_FLAG_OUTPUT_CORRUPT = int(C.AV_CODEC_FLAG_OUTPUT_CORRUPT)
AV_CODEC_FLAG_QPEL = int(C.AV_CODEC_FLAG_QPEL)
AV_CODEC_FLAG_PASS1 = int(C.AV_CODEC_FLAG_PASS1)
AV_CODEC_FLAG_PASS2 = int(C.AV_CODEC_FLAG_PASS2)
AV_CODEC_FLAG_LOOP_FILTER = int(C.AV_CODEC_FLAG_LOOP_FILTER)
AV_CODEC_FLAG_GRAY = int(C.AV_CODEC_FLAG_GRAY)
AV_CODEC_FLAG_PSNR = int(C.AV_CODEC_FLAG_PSNR)
AV_CODEC_FLAG_TRUNCATED = int(C.AV_CODEC_FLAG_TRUNCATED)
AV_CODEC_FLAG_INTERLACED_DCT = int(C.AV_CODEC_FLAG_INTERLACED_DCT)
AV_CODEC_FLAG_LOW_DELAY = int(C.AV_CODEC_FLAG_LOW_DELAY)
AV_CODEC_FLAG_GLOBAL_HEADER = int(C.AV_CODEC_FLAG_GLOBAL_HEADER)
AV_CODEC_FLAG_BITEXACT = int(C.AV_CODEC_FLAG_BITEXACT)
AV_CODEC_FLAG_AC_PRED = int(C.AV_CODEC_FLAG_AC_PRED)
AV_CODEC_FLAG_INTERLACED_ME = int(C.AV_CODEC_FLAG_INTERLACED_ME)
AV_CODEC_FLAG_CLOSED_GOP = int(C.AV_CODEC_FLAG_CLOSED_GOP)
AV_CODEC_FLAG2_FAST = int(C.AV_CODEC_FLAG2_FAST)
AV_CODEC_FLAG2_NO_OUTPUT = int(C.AV_CODEC_FLAG2_NO_OUTPUT)
AV_CODEC_FLAG2_LOCAL_HEADER = int(C.AV_CODEC_FLAG2_LOCAL_HEADER)
AV_CODEC_FLAG2_DROP_FRAME_TIMECODE = int(C.AV_CODEC_FLAG2_DROP_FRAME_TIMECODE)
AV_CODEC_FLAG2_CHUNKS = int(C.AV_CODEC_FLAG2_CHUNKS)
AV_CODEC_FLAG2_IGNORE_CROP = int(C.AV_CODEC_FLAG2_IGNORE_CROP)
AV_CODEC_FLAG2_SHOW_ALL = int(C.AV_CODEC_FLAG2_SHOW_ALL)
AV_CODEC_FLAG2_EXPORT_MVS = int(C.AV_CODEC_FLAG2_EXPORT_MVS)
AV_CODEC_FLAG2_SKIP_MANUAL = int(C.AV_CODEC_FLAG2_SKIP_MANUAL)
AV_CODEC_FLAG2_RO_FLUSH_NOOP = int(C.AV_CODEC_FLAG2_RO_FLUSH_NOOP)
)
+8
View File
@@ -10,9 +10,17 @@ import (
"unsafe"
)
const (
AV_PKT_FLAG_KEY = int(C.AV_PKT_FLAG_KEY)
AV_PKT_FLAG_CORRUPT = int(C.AV_PKT_FLAG_CORRUPT)
AV_PKT_FLAG_DISCARD = int(C.AV_PKT_FLAG_DISCARD)
)
//Initialize optional fields of a packet with default values.
func (p *Packet) AvInitPacket() {
C.av_init_packet((*C.struct_AVPacket)(p))
p.size = 0
p.data = nil
}
//Allocate the payload of a packet and initialize its fields with default values.
+12
View File
@@ -16,6 +16,9 @@ func (p *Packet) Duration() int {
func (p *Packet) Flags() int {
return int(p.flags)
}
func (p *Packet) SetFlags(flags int) {
p.flags = C.int(flags)
}
func (p *Packet) SideDataElems() int {
return int(p.side_data_elems)
}
@@ -25,18 +28,27 @@ func (p *Packet) Size() int {
func (p *Packet) StreamIndex() int {
return int(p.stream_index)
}
func (p *Packet) SetStreamIndex(idx int) {
p.stream_index = C.int(idx)
}
func (p *Packet) ConvergenceDuration() int64 {
return int64(p.convergence_duration)
}
func (p *Packet) Dts() int64 {
return int64(p.dts)
}
func (p *Packet) SetDts(dts int64) {
p.dts = C.int64_t(dts)
}
func (p *Packet) Pos() int64 {
return int64(p.pos)
}
func (p *Packet) Pts() int64 {
return int64(p.pts)
}
func (p *Packet) SetPts(pts int64) {
p.dts = C.int64_t(pts)
}
func (p *Packet) Data() *uint8 {
return (*uint8)(p.data)
}
+171
View File
@@ -0,0 +1,171 @@
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.
// Giorgis (habtom@giorgis.io)
//Package avcodec contains the codecs (decoders and encoders) provided by the libavcodec library
//Provides some generic global options, which can be set on all the encoders and decoders.
package avcodec
//#cgo pkg-config: libavformat libavcodec libavutil
//#include <stdio.h>
//#include <stdlib.h>
//#include <inttypes.h>
//#include <stdint.h>
//#include <string.h>
//#include <libavformat/avformat.h>
//#include <libavcodec/avcodec.h>
//#include <libavutil/avutil.h>
//#include <libswscale/swscale.h>
import "C"
const (
AV_PIX_FMT_YUV = 0
AV_PIX_FMT_YUV420P9 = C.AV_PIX_FMT_YUV420P9
AV_PIX_FMT_YUV422P9 = C.AV_PIX_FMT_YUV422P9
AV_PIX_FMT_YUV444P9 = C.AV_PIX_FMT_YUV444P9
AV_PIX_FMT_YUV420P10 = C.AV_PIX_FMT_YUV420P10
AV_PIX_FMT_YUV422P10 = C.AV_PIX_FMT_YUV422P10
AV_PIX_FMT_YUV440P10 = C.AV_PIX_FMT_YUV440P10
AV_PIX_FMT_YUV444P10 = C.AV_PIX_FMT_YUV444P10
AV_PIX_FMT_YUV420P12 = C.AV_PIX_FMT_YUV420P12
AV_PIX_FMT_YUV422P12 = C.AV_PIX_FMT_YUV422P12
AV_PIX_FMT_YUV440P12 = C.AV_PIX_FMT_YUV440P12
AV_PIX_FMT_YUV444P12 = C.AV_PIX_FMT_YUV444P12
AV_PIX_FMT_YUV420P14 = C.AV_PIX_FMT_YUV420P14
AV_PIX_FMT_YUV422P14 = C.AV_PIX_FMT_YUV422P14
AV_PIX_FMT_YUV444P14 = C.AV_PIX_FMT_YUV444P14
AV_PIX_FMT_YUV420P16 = C.AV_PIX_FMT_YUV420P16
AV_PIX_FMT_YUV422P16 = C.AV_PIX_FMT_YUV422P16
AV_PIX_FMT_YUV444P16 = C.AV_PIX_FMT_YUV444P16
AV_PIX_FMT_YUVA420P9 = C.AV_PIX_FMT_YUVA420P9
AV_PIX_FMT_YUVA422P9 = C.AV_PIX_FMT_YUVA422P9
AV_PIX_FMT_YUVA444P9 = C.AV_PIX_FMT_YUVA444P9
AV_PIX_FMT_YUVA420P10 = C.AV_PIX_FMT_YUVA420P10
AV_PIX_FMT_YUVA422P10 = C.AV_PIX_FMT_YUVA422P10
AV_PIX_FMT_YUVA444P10 = C.AV_PIX_FMT_YUVA444P10
AV_PIX_FMT_YUVA420P16 = C.AV_PIX_FMT_YUVA420P16
AV_PIX_FMT_YUVA422P16 = C.AV_PIX_FMT_YUVA422P16
AV_PIX_FMT_YUVA444P16 = C.AV_PIX_FMT_YUVA444P16
AV_PIX_FMT_RGB24 = C.AV_PIX_FMT_RGB24
AV_PIX_FMT_RGBA = C.AV_PIX_FMT_RGBA
SWS_FAST_BILINEAR = C.SWS_FAST_BILINEAR
SWS_BILINEAR = C.SWS_BILINEAR
SWS_BICUBIC = C.SWS_BICUBIC
SWS_X = C.SWS_X
SWS_POINT = C.SWS_POINT
SWS_AREA = C.SWS_AREA
SWS_BICUBLIN = C.SWS_BICUBLIN
SWS_GAUSS = C.SWS_GAUSS
SWS_SINC = C.SWS_SINC
SWS_LANCZOS = C.SWS_LANCZOS
SWS_SPLINE = C.SWS_SPLINE
SWS_SRC_V_CHR_DROP_MASK = C.SWS_SRC_V_CHR_DROP_MASK
SWS_SRC_V_CHR_DROP_SHIFT = C.SWS_SRC_V_CHR_DROP_SHIFT
SWS_PARAM_DEFAULT = C.SWS_PARAM_DEFAULT
SWS_PRINT_INFO = C.SWS_PRINT_INFO
SWS_FULL_CHR_H_INT = C.SWS_FULL_CHR_H_INT
SWS_FULL_CHR_H_INP = C.SWS_FULL_CHR_H_INP
SWS_DIRECT_BGR = C.SWS_DIRECT_BGR
SWS_ACCURATE_RND = C.SWS_ACCURATE_RND
SWS_BITEXACT = C.SWS_BITEXACT
SWS_ERROR_DIFFUSION = C.SWS_ERROR_DIFFUSION
SWS_MAX_REDUCE_CUTOFF = C.SWS_MAX_REDUCE_CUTOFF
SWS_CS_ITU709 = C.SWS_CS_ITU709
SWS_CS_FCC = C.SWS_CS_FCC
SWS_CS_ITU601 = C.SWS_CS_ITU601
SWS_CS_ITU624 = C.SWS_CS_ITU624
SWS_CS_SMPTE170M = C.SWS_CS_SMPTE170M
SWS_CS_SMPTE240M = C.SWS_CS_SMPTE240M
SWS_CS_DEFAULT = C.SWS_CS_DEFAULT
SWS_CS_BT2020 = C.SWS_CS_BT2020
)
func (pf PixelFormat) String() string {
switch int(pf) {
case AV_PIX_FMT_YUV420P9:
return "YUV420P9"
case AV_PIX_FMT_YUV422P9:
return "YUV422P9"
case AV_PIX_FMT_YUV444P9:
return "YUV444P9"
case AV_PIX_FMT_YUV420P10:
return "YUV420P10"
case AV_PIX_FMT_YUV422P10:
return "YUV422P10"
case AV_PIX_FMT_YUV440P10:
return "YUV440P10"
case AV_PIX_FMT_YUV444P10:
return "YUV444P10"
case AV_PIX_FMT_YUV420P12:
return "YUV420P12"
case AV_PIX_FMT_YUV422P12:
return "YUV422P12"
case AV_PIX_FMT_YUV440P12:
return "YUV440P12"
case AV_PIX_FMT_YUV444P12:
return "YUV444P12"
case AV_PIX_FMT_YUV420P14:
return "YUV420P14"
case AV_PIX_FMT_YUV422P14:
return "YUV422P14"
case AV_PIX_FMT_YUV444P14:
return "YUV444P14"
case AV_PIX_FMT_YUV420P16:
return "YUV420P16"
case AV_PIX_FMT_YUV422P16:
return "YUV422P16"
case AV_PIX_FMT_YUV444P16:
return "YUV444P16"
case AV_PIX_FMT_YUVA420P9:
return "YUVA420P9"
case AV_PIX_FMT_YUVA422P9:
return "YUVA422P9"
case AV_PIX_FMT_YUVA444P9:
return "YUVA444P9"
case AV_PIX_FMT_YUVA420P10:
return "YUVA420P10"
case AV_PIX_FMT_YUVA422P10:
return "YUVA422P10"
case AV_PIX_FMT_YUVA444P10:
return "YUVA444P10"
case AV_PIX_FMT_YUVA420P16:
return "YUVA420P16"
case AV_PIX_FMT_YUVA422P16:
return "YUVA422P16"
case AV_PIX_FMT_YUVA444P16:
return "YUVA444P16"
case AV_PIX_FMT_RGB24:
return "RGB24"
case AV_PIX_FMT_RGBA:
return "RGBA"
}
return "{UNKNOWN}"
}
+45
View File
@@ -0,0 +1,45 @@
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.
// Giorgis (habtom@giorgis.io)
//Package avcodec contains the codecs (decoders and encoders) provided by the libavcodec library
//Provides some generic global options, which can be set on all the encoders and decoders.
package avcodec
//#cgo pkg-config: libavformat libavcodec libavutil
//#include <stdio.h>
//#include <stdlib.h>
//#include <inttypes.h>
//#include <stdint.h>
//#include <string.h>
//#include <libavformat/avformat.h>
//#include <libavcodec/avcodec.h>
//#include <libavutil/avutil.h>
import "C"
import "fmt"
func (r Rational) Num() int {
return int(r.num)
}
func (r Rational) Den() int {
return int(r.den)
}
func (r Rational) String() string {
return fmt.Sprintln("%d/%d", int(r.num), int(r.den))
}
func (r *Rational) Assign(o Rational) {
r.Set(o.Num(), o.Den())
}
func (r *Rational) Set(num, den int) {
r.num, r.den = C.int(num), C.int(den)
}
func NewRational(num, den int) Rational {
return Rational{
num: C.int(num),
den: C.int(den),
}
}
+24 -10
View File
@@ -20,6 +20,9 @@ package avformat
import "C"
import (
"unsafe"
"github.com/giorgisio/goav/avcodec"
"github.com/giorgisio/goav/avutil"
)
type (
@@ -35,10 +38,8 @@ type (
AvProgram C.struct_AVProgram
AvChapter C.struct_AVChapter
AvPacketList C.struct_AVPacketList
Packet C.struct_AVPacket
CodecParserContext C.struct_AVCodecParserContext
AvIOContext C.struct_AVIOContext
Rational C.struct_AVRational
AvCodec C.struct_AVCodec
AvCodecTag C.struct_AVCodecTag
Class C.struct_AVClass
@@ -57,13 +58,17 @@ type (
type File C.FILE
//Allocate and read the payload of a packet and initialize its fields with default values.
func (ctxt *AvIOContext) AvGetPacket(pkt *Packet, s int) int {
return int(C.av_get_packet((*C.struct_AVIOContext)(ctxt), (*C.struct_AVPacket)(pkt), C.int(s)))
func (ctxt *AvIOContext) AvGetPacket(pkt *avcodec.Packet, s int) int {
return int(C.av_get_packet((*C.struct_AVIOContext)(ctxt), toCPacket(pkt), C.int(s)))
}
//Read data and append it to the current content of the Packet.
func (ctxt *AvIOContext) AvAppendPacket(pkt *Packet, s int) int {
return int(C.av_append_packet((*C.struct_AVIOContext)(ctxt), (*C.struct_AVPacket)(pkt), C.int(s)))
func (ctxt *AvIOContext) AvAppendPacket(pkt *avcodec.Packet, s int) int {
return int(C.av_append_packet((*C.struct_AVIOContext)(ctxt), toCPacket(pkt), C.int(s)))
}
func (ctxt *AvIOContext) Close() error {
return avutil.ErrorFromCode(int(C.avio_close((*C.AVIOContext)(unsafe.Pointer(ctxt)))))
}
func (f *InputFormat) AvRegisterInputFormat() {
@@ -190,13 +195,13 @@ func AvHexDumpLog(a, l int, b *uint8, s int) {
}
//Send a nice dump of a packet to the specified file stream.
func AvPktDump2(f *File, pkt *Packet, dp int, st *Stream) {
C.av_pkt_dump2((*C.FILE)(f), (*C.struct_AVPacket)(pkt), C.int(dp), (*C.struct_AVStream)(st))
func AvPktDump2(f *File, pkt *avcodec.Packet, dp int, st *Stream) {
C.av_pkt_dump2((*C.FILE)(f), toCPacket(pkt), C.int(dp), (*C.struct_AVStream)(st))
}
//Send a nice dump of a packet to the log.
func AvPktDumpLog2(a int, l int, pkt *Packet, dp int, st *Stream) {
C.av_pkt_dump_log2(unsafe.Pointer(&a), C.int(l), (*C.struct_AVPacket)(pkt), C.int(dp), (*C.struct_AVStream)(st))
func AvPktDumpLog2(a int, l int, pkt *avcodec.Packet, dp int, st *Stream) {
C.av_pkt_dump_log2(unsafe.Pointer(&a), C.int(l), toCPacket(pkt), C.int(dp), (*C.struct_AVStream)(st))
}
//enum CodecId av_codec_get_id (const struct AvCodecTag *const *tags, unsigned int tag)
@@ -273,3 +278,12 @@ func AvformatGetMovVideoTags() *AvCodecTag {
func AvformatGetMovAudioTags() *AvCodecTag {
return (*AvCodecTag)(C.avformat_get_mov_audio_tags())
}
func AvIOOpen(url string, flags int) (res *AvIOContext, err error) {
urlStr := C.CString(url)
defer C.free(unsafe.Pointer(urlStr))
err = avutil.ErrorFromCode(int(C.avio_open((**C.AVIOContext)(unsafe.Pointer(&res)), urlStr, C.int(flags))))
return
}
+150
View File
@@ -0,0 +1,150 @@
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.
// Giorgis (habtom@giorgis.io)
//Package avformat provides some generic global options, which can be set on all the muxers and demuxers.
//In addition each muxer or demuxer may support so-called private options, which are specific for that component.
//Supported formats (muxers and demuxers) provided by the libavformat library
package avformat
//#cgo pkg-config: libavformat libavcodec libavutil libavdevice libavfilter libswresample libswscale
//#include <stdio.h>
//#include <stdlib.h>
//#include <inttypes.h>
//#include <stdint.h>
//#include <string.h>
//#include <libavformat/avformat.h>
//#include <libavcodec/avcodec.h>
import "C"
import (
"reflect"
"unsafe"
"github.com/giorgisio/goav/avcodec"
)
func (cctxt *CodecContext) Type() MediaType {
return MediaType(cctxt.codec_type)
}
func (cctxt *CodecContext) SetBitRate(br int64) {
cctxt.bit_rate = C.int64_t(br)
}
func (cctxt *CodecContext) GetCodecId() CodecId {
return CodecId(cctxt.codec_id)
}
func (cctxt *CodecContext) SetCodecId(codecId CodecId) {
cctxt.codec_id = C.enum_AVCodecID(codecId)
}
func (cctxt *CodecContext) GetCodecType() MediaType {
return MediaType(cctxt.codec_type)
}
func (cctxt *CodecContext) SetCodecType(ctype MediaType) {
cctxt.codec_type = C.enum_AVMediaType(ctype)
}
func (cctxt *CodecContext) GetTimeBase() avcodec.Rational {
return newRational(cctxt.time_base)
}
func (cctxt *CodecContext) SetTimeBase(timeBase avcodec.Rational) {
cctxt.time_base.num = C.int(timeBase.Num())
cctxt.time_base.den = C.int(timeBase.Den())
}
func (cctx *CodecContext) GetWidth() int {
return int(cctx.width)
}
func (cctx *CodecContext) SetWidth(w int) {
cctx.width = C.int(w)
}
func (cctx *CodecContext) GetHeight() int {
return int(cctx.height)
}
func (cctx *CodecContext) SetHeight(h int) {
cctx.height = C.int(h)
}
func (cctx *CodecContext) GetPixelFormat() avcodec.PixelFormat {
return avcodec.PixelFormat(C.int(cctx.pix_fmt))
}
func (cctx *CodecContext) SetPixelFormat(fmt avcodec.PixelFormat) {
cctx.pix_fmt = C.enum_AVPixelFormat(C.int(fmt))
}
func (cctx *CodecContext) GetFlags() int {
return int(cctx.flags)
}
func (cctx *CodecContext) SetFlags(flags int) {
cctx.flags = C.int(flags)
}
func (cctx *CodecContext) GetMeRange() int {
return int(cctx.me_range)
}
func (cctx *CodecContext) SetMeRange(r int) {
cctx.me_range = C.int(r)
}
func (cctx *CodecContext) GetMaxQDiff() int {
return int(cctx.max_qdiff)
}
func (cctx *CodecContext) SetMaxQDiff(v int) {
cctx.max_qdiff = C.int(v)
}
func (cctx *CodecContext) GetQMin() int {
return int(cctx.qmin)
}
func (cctx *CodecContext) SetQMin(v int) {
cctx.qmin = C.int(v)
}
func (cctx *CodecContext) GetQMax() int {
return int(cctx.qmax)
}
func (cctx *CodecContext) SetQMax(v int) {
cctx.qmax = C.int(v)
}
func (cctx *CodecContext) GetQCompress() float32 {
return float32(cctx.qcompress)
}
func (cctx *CodecContext) SetQCompress(v float32) {
cctx.qcompress = C.float(v)
}
func (cctx *CodecContext) GetExtraData() []byte {
header := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cctx.extradata)),
Len: int(cctx.extradata_size),
Cap: int(cctx.extradata_size),
}
return *((*[]byte)(unsafe.Pointer(&header)))
}
func (cctx *CodecContext) SetExtraData(data []byte) {
header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
cctx.extradata = (*C.uint8_t)(unsafe.Pointer(header.Data))
cctx.extradata_size = C.int(header.Len)
}
func (cctx *CodecContext) Release() {
C.avcodec_close((*C.struct_AVCodecContext)(unsafe.Pointer(cctx)))
C.av_freep(unsafe.Pointer(cctx))
}
+14 -15
View File
@@ -10,8 +10,7 @@ import (
"time"
"unsafe"
"github.com/selfmodify/goav/avcodec"
"github.com/selfmodify/goav/common"
"github.com/giorgisio/goav/avcodec"
)
const (
@@ -106,7 +105,7 @@ func AvFindBestStream(ic *Context, t MediaType, ws, rs int, c **AvCodec, f int)
//Return the next frame of a stream.
func (s *Context) AvReadFrame(pkt *avcodec.Packet) int {
return int(C.av_read_frame((*C.struct_AVFormatContext)(unsafe.Pointer(s)), (*C.struct_AVPacket)(unsafe.Pointer(pkt))))
return int(C.av_read_frame((*C.struct_AVFormatContext)(unsafe.Pointer(s)), toCPacket(pkt)))
}
//Seek to the keyframe at timestamp.
@@ -116,8 +115,8 @@ func (s *Context) AvSeekFrame(st int, t int64, f int) int {
// AvSeekFrameTime seeks to a specified time location.
// |timebase| is codec specific and can be obtained by calling AvCodecGetPktTimebase2
func (s *Context) AvSeekFrameTime(st int, at time.Duration, timebase common.AVRational) int {
t2 := C.double(C.double(at.Seconds())*C.double(timebase.Den)) / (C.double(timebase.Num))
func (s *Context) AvSeekFrameTime(st int, at time.Duration, timebase avcodec.Rational) int {
t2 := C.double(C.double(at.Seconds())*C.double(timebase.Den())) / (C.double(timebase.Num()))
// log.Printf("Seeking to time :%v TimebaseTime:%v ActualTimebase:%v", at, t2, timebase)
return int(C.av_seek_frame((*C.struct_AVFormatContext)(s), C.int(st), C.int64_t(t2), AvseekFlagBackward))
}
@@ -139,7 +138,7 @@ func (s *Context) AvReadPause() int {
//Close an opened input Context.
func (s *Context) AvformatCloseInput() {
C.avformat_close_input((**C.struct_AVFormatContext)(unsafe.Pointer(s)))
C.avformat_close_input((**C.struct_AVFormatContext)(unsafe.Pointer(&s)))
}
//Allocate the stream private data and write the stream header to an output media file.
@@ -148,13 +147,13 @@ func (s *Context) AvformatWriteHeader(o **Dictionary) int {
}
//Write a packet to an output media file.
func (s *Context) AvWriteFrame(pkt *Packet) int {
return int(C.av_write_frame((*C.struct_AVFormatContext)(s), (*C.struct_AVPacket)(pkt)))
func (s *Context) AvWriteFrame(pkt *avcodec.Packet) int {
return int(C.av_write_frame((*C.struct_AVFormatContext)(s), toCPacket(pkt)))
}
//Write a packet to an output media file ensuring correct interleaving.
func (s *Context) AvInterleavedWriteFrame(pkt *Packet) int {
return int(C.av_interleaved_write_frame((*C.struct_AVFormatContext)(s), (*C.struct_AVPacket)(pkt)))
func (s *Context) AvInterleavedWriteFrame(pkt *avcodec.Packet) int {
return int(C.av_interleaved_write_frame((*C.struct_AVFormatContext)(s), toCPacket(pkt)))
}
//Write a uncoded frame to an output media file.
@@ -192,13 +191,13 @@ func (s *Context) AvDumpFormat(i int, url string, io int) {
}
//Guess the sample aspect ratio of a frame, based on both the stream and the frame aspect ratio.
func (s *Context) AvGuessSampleAspectRatio(st *Stream, fr *Frame) Rational {
return (Rational)(C.av_guess_sample_aspect_ratio((*C.struct_AVFormatContext)(s), (*C.struct_AVStream)(st), (*C.struct_AVFrame)(fr)))
func (s *Context) AvGuessSampleAspectRatio(st *Stream, fr *Frame) avcodec.Rational {
return newRational(C.av_guess_sample_aspect_ratio((*C.struct_AVFormatContext)(s), (*C.struct_AVStream)(st), (*C.struct_AVFrame)(fr)))
}
//Guess the frame rate, based on both the container and codec information.
func (s *Context) AvGuessFrameRate(st *Stream, fr *Frame) Rational {
return (Rational)(C.av_guess_frame_rate((*C.struct_AVFormatContext)(s), (*C.struct_AVStream)(st), (*C.struct_AVFrame)(fr)))
func (s *Context) AvGuessFrameRate(st *Stream, fr *Frame) avcodec.Rational {
return newRational(C.av_guess_frame_rate((*C.struct_AVFormatContext)(s), (*C.struct_AVStream)(st), (*C.struct_AVFrame)(fr)))
}
//Check if the stream st contained in s is matched by the stream specifier spec.
@@ -212,7 +211,7 @@ func (s *Context) AvformatQueueAttachedPictures() int {
func (s *Context) AvformatNewStream2(c *AvCodec) *Stream {
stream := (*Stream)(C.avformat_new_stream((*C.struct_AVFormatContext)(s), (*C.struct_AVCodec)(c)))
stream.codec.pix_fmt = int32(common.AV_PIX_FMT_YUV)
stream.codec.pix_fmt = int32(avcodec.AV_PIX_FMT_YUV)
stream.codec.width = 640
stream.codec.height = 480
stream.time_base.num = 1
+17 -4
View File
@@ -7,6 +7,7 @@ package avformat
//#include <libavformat/avformat.h>
import "C"
import (
"reflect"
"unsafe"
)
@@ -42,12 +43,24 @@ func (ctxt *Context) InterruptCallback() AvIOInterruptCB {
return AvIOInterruptCB(ctxt.interrupt_callback)
}
func (ctxt *Context) Programs() **AvProgram {
return (**AvProgram)(unsafe.Pointer(ctxt.programs))
func (ctxt *Context) Programs() []*AvProgram {
header := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(ctxt.programs)),
Len: int(ctxt.NbPrograms()),
Cap: int(ctxt.NbPrograms()),
}
return *((*[]*AvProgram)(unsafe.Pointer(&header)))
}
func (ctxt *Context) Streams() *Stream {
return (*Stream)(unsafe.Pointer(*ctxt.streams))
func (ctxt *Context) Streams() []*Stream {
header := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(ctxt.streams)),
Len: int(ctxt.NbStreams()),
Cap: int(ctxt.NbStreams()),
}
return *((*[]*Stream)(unsafe.Pointer(&header)))
}
func (ctxt *Context) Filename() string {
+23
View File
@@ -0,0 +1,23 @@
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.
// Giorgis (habtom@giorgis.io)
//Package avformat provides some generic global options, which can be set on all the muxers and demuxers.
//In addition each muxer or demuxer may support so-called private options, which are specific for that component.
//Supported formats (muxers and demuxers) provided by the libavformat library
package avformat
//#cgo pkg-config: libavformat libavcodec libavutil libavdevice libavfilter libswresample libswscale
//#include <stdio.h>
//#include <stdlib.h>
//#include <inttypes.h>
//#include <stdint.h>
//#include <string.h>
//#include <libavformat/avformat.h>
//#include <libavformat/avio.h>
import "C"
const (
AVIO_FLAG_READ = int(C.AVIO_FLAG_READ)
AVIO_FLAG_WRITE = int(C.AVIO_FLAG_WRITE)
AVIO_FLAG_READ_WRITE = int(C.AVIO_FLAG_READ_WRITE)
)
+17
View File
@@ -0,0 +1,17 @@
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.
package avformat
//#cgo pkg-config: libavutil
//#include <libavutil/avutil.h>
import "C"
const (
AVMEDIA_TYPE_UNKNOWN = C.AVMEDIA_TYPE_UNKNOWN
AVMEDIA_TYPE_VIDEO = C.AVMEDIA_TYPE_VIDEO
AVMEDIA_TYPE_AUDIO = C.AVMEDIA_TYPE_AUDIO
AVMEDIA_TYPE_DATA = C.AVMEDIA_TYPE_DATA
AVMEDIA_TYPE_SUBTITLE = C.AVMEDIA_TYPE_SUBTITLE
AVMEDIA_TYPE_ATTACHMENT = C.AVMEDIA_TYPE_ATTACHMENT
AVMEDIA_TYPE_NB = C.AVMEDIA_TYPE_NB
)
+21
View File
@@ -0,0 +1,21 @@
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.
// Giorgis (habtom@giorgis.io)
package avformat
//#cgo pkg-config: libavformat
//#include <libavformat/avformat.h>
import "C"
import (
"unsafe"
"github.com/giorgisio/goav/avcodec"
)
func toCPacket(pkt *avcodec.Packet) *C.struct_AVPacket {
return (*C.struct_AVPacket)(unsafe.Pointer(pkt))
}
func fromCPacket(pkt *C.struct_AVPacket) *avcodec.Packet {
return (*avcodec.Packet)(unsafe.Pointer(pkt))
}
+13
View File
@@ -0,0 +1,13 @@
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.
// Giorgis (habtom@giorgis.io)
package avformat
//#cgo pkg-config: libavutil
//#include <libavutil/avutil.h>
import "C"
import "github.com/giorgisio/goav/avcodec"
func newRational(r C.struct_AVRational) avcodec.Rational {
return avcodec.NewRational(int(r.num), int(r.den))
}
+12 -4
View File
@@ -6,15 +6,23 @@ package avformat
//#cgo pkg-config: libavformat
//#include <libavformat/avformat.h>
import "C"
import (
"github.com/giorgisio/goav/avcodec"
)
//Rational av_stream_get_r_frame_rate (const Stream *s)
func (s *Stream) AvStreamGetRFrameRate() Rational {
return (Rational)(C.av_stream_get_r_frame_rate((*C.struct_AVStream)(s)))
func (s *Stream) AvStreamGetRFrameRate() avcodec.Rational {
return newRational(C.av_stream_get_r_frame_rate((*C.struct_AVStream)(s)))
}
//void av_stream_set_r_frame_rate (Stream *s, Rational r)
func (s *Stream) AvStreamSetRFrameRate(r Rational) {
C.av_stream_set_r_frame_rate((*C.struct_AVStream)(s), (C.struct_AVRational)(r))
func (s *Stream) AvStreamSetRFrameRate(r avcodec.Rational) {
rat := C.struct_AVRational{
num: C.int(r.Num()),
den: C.int(r.Den()),
}
C.av_stream_set_r_frame_rate((*C.struct_AVStream)(s), rat)
}
//struct CodecParserContext * av_stream_get_parser (const Stream *s)
+20 -10
View File
@@ -8,8 +8,14 @@ package avformat
import "C"
import (
"unsafe"
"github.com/giorgisio/goav/avcodec"
)
func (avs *Stream) CodecParameters() *avcodec.AvCodecParameters {
return (*avcodec.AvCodecParameters)(unsafe.Pointer(avs.codecpar))
}
func (avs *Stream) Codec() *CodecContext {
return (*CodecContext)(unsafe.Pointer(avs.codec))
}
@@ -22,8 +28,8 @@ func (avs *Stream) IndexEntries() *AvIndexEntry {
return (*AvIndexEntry)(unsafe.Pointer(avs.index_entries))
}
func (avs *Stream) AttachedPic() Packet {
return Packet(avs.attached_pic)
func (avs *Stream) AttachedPic() avcodec.Packet {
return *fromCPacket(&avs.attached_pic)
}
func (avs *Stream) SideData() *AvPacketSideData {
@@ -34,24 +40,24 @@ func (avs *Stream) ProbeData() AvProbeData {
return AvProbeData(avs.probe_data)
}
func (avs *Stream) AvgFrameRate() Rational {
return Rational(avs.avg_frame_rate)
func (avs *Stream) AvgFrameRate() avcodec.Rational {
return newRational(avs.avg_frame_rate)
}
// func (avs *Stream) DisplayAspectRatio() *Rational {
// return (*Rational)(unsafe.Pointer(avs.display_aspect_ratio))
// }
func (avs *Stream) RFrameRate() Rational {
return Rational(avs.r_frame_rate)
func (avs *Stream) RFrameRate() avcodec.Rational {
return newRational(avs.r_frame_rate)
}
func (avs *Stream) SampleAspectRatio() Rational {
return Rational(avs.sample_aspect_ratio)
func (avs *Stream) SampleAspectRatio() avcodec.Rational {
return newRational(avs.sample_aspect_ratio)
}
func (avs *Stream) TimeBase() Rational {
return Rational(avs.time_base)
func (avs *Stream) TimeBase() avcodec.Rational {
return newRational(avs.time_base)
}
// func (avs *Stream) RecommendedEncoderConfiguration() string {
@@ -225,3 +231,7 @@ func (avs *Stream) PtsReorderErrorCount() uint8 {
func (avs *Stream) IndexEntriesAllocatedSize() uint {
return uint(avs.index_entries_allocated_size)
}
func (avs *Stream) Free() {
C.av_freep(unsafe.Pointer(avs))
}
+1
View File
@@ -22,6 +22,7 @@ type (
Rational C.struct_AVRational
MediaType C.enum_AVMediaType
AvPictureType C.enum_AVPictureType
PixelFormat C.enum_AVPixelFormat
File C.FILE
)
+28
View File
@@ -0,0 +1,28 @@
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.
// Giorgis (habtom@giorgis.io)
// Package avutil is a utility library to aid portable multimedia programming.
// It contains safe portable string functions, random number generators, data structures,
// additional mathematics functions, cryptography and multimedia related functionality.
// Some generic features and utilities provided by the libavutil library
package avutil
//#cgo pkg-config: libavutil
//#include <libavutil/error.h>
//#include <stdlib.h>
//static const char *error2string(int code) { return av_err2str(code); }
import "C"
import "errors"
const (
AvErrorEOF = -('E' | ('O' << 8) | ('F' << 16) | (' ' << 24))
AvErrorEAGAIN = -35
)
func ErrorFromCode(code int) error {
if code >= 0 {
return nil
}
return errors.New(C.GoString(C.error2string(C.int(code))))
}
+4 -4
View File
@@ -25,9 +25,9 @@ type (
AvFrameSideDataType C.enum_AVFrameSideDataType
)
// func AvprivFrameGetMetadatap(f *Frame) **Dictionary {
// return (**Dictionary)(unsafe.Pointer(C.avpriv_frame_get_metadatap((*C.struct_AVFrame)(unsafe.Pointer(f)))))
// }
func AvprivFrameGetMetadatap(f *Frame) *Dictionary {
return (*Dictionary)(unsafe.Pointer(f.metadata))
}
func AvFrameSetQpTable(f *Frame, b *AvBufferRef, s, q int) int {
return int(C.av_frame_set_qp_table((*C.struct_AVFrame)(unsafe.Pointer(f)), (*C.struct_AVBufferRef)(unsafe.Pointer(b)), C.int(s), C.int(q)))
@@ -44,7 +44,7 @@ func AvFrameAlloc() *Frame {
//Free the frame and any dynamically allocated objects in it, e.g.
func AvFrameFree(f *Frame) {
C.av_frame_free((**C.struct_AVFrame)(unsafe.Pointer(f)))
C.av_frame_free((**C.struct_AVFrame)(unsafe.Pointer(&f)))
}
//Allocate new buffer(s) for audio or video data.
-19
View File
@@ -1,19 +0,0 @@
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.
package common
// Common types used across all av packages.
// AVRational exposes the numerator and denominator part of the undrelying 'Rational' structure.
type AVRational struct {
Num int
Den int
}
type PixelFormat int
const (
AV_PIX_FMT_YUV PixelFormat = 0
AV_PIX_FMT_RGB24 = 3
AV_PIX_FMT_RGBA = 28
)
+182 -222
View File
@@ -1,247 +1,207 @@
//Example 01
package main
// tutorial01.c
// Code based on a tutorial at http://dranger.com/ffmpeg/tutorial01.html
// A small sample program that shows how to use libavformat and libavcodec to
// read video from a file.
//
// Use
//
// gcc -o tutorial01 tutorial01.c -lavformat -lavcodec -lswscale -lz
//
// to build (assuming libavformat and libavcodec are correctly installed
// your system).
//
// Run using
//
// tutorial01 myvideofile.mpg
//
// to write the first five frames from "myvideofile.mpg" to disk in PPM
// format.
import (
"fmt"
"github.com/giorgisio/goav/avcodec"
"github.com/giorgisio/goav/avformat"
"github.com/giorgisio/goav/avutil"
"github.com/giorgisio/goav/swscale"
"log"
"os"
"unsafe"
"github.com/giorgisio/goav/swscale"
"github.com/giorgisio/goav/avcodec"
"github.com/giorgisio/goav/avformat"
"github.com/giorgisio/goav/avutil"
)
// SaveFrame writes a single frame to disk as a PPM file
func SaveFrame(frame *avutil.Frame, width, height, frameNumber int) {
// Open file
fileName := fmt.Sprintf("frame%d.ppm", frameNumber)
file, err := os.Create(fileName)
if err != nil {
log.Println("Error Reading")
}
defer file.Close()
// Write header
header := fmt.Sprintf("P6\n%d %d\n255\n", width, height)
file.Write([]byte(header))
// Write pixel data
for y := 0; y < height; y++ {
data0 := avutil.Data(frame)[0]
buf := make([]byte, width*3)
startPos := uintptr(unsafe.Pointer(data0)) + uintptr(y)*uintptr(avutil.Linesize(frame)[0])
for i := 0; i < width*3; i++ {
element := *(*uint8)(unsafe.Pointer(startPos + uintptr(i)))
buf[i] = element
}
file.Write(buf)
}
}
func main() {
filename := "sample.mp4"
var (
ctxtFormat *avformat.Context
ctxtSource *avcodec.Context
ctxtDest *avcodec.Context
videoCodec *avcodec.Codec
videoFrame *avutil.Frame
videoFrameRGB *avutil.Frame
packet *avcodec.Packet
ctxtSws *swscale.Context
videoStream int
frameFinished int
numBytes int
url string
)
//media_type *avutil.MediaType
// Register all formats and codecs
avformat.AvRegisterAll()
if len(os.Args) < 2 {
fmt.Println("Please provide a movie file")
os.Exit(1)
}
// Open video file
if avformat.AvformatOpenInput(&ctxtFormat, filename, nil, nil) != 0 {
log.Println("Error: Couldn't open file.")
return
pFormatContext := avformat.AvformatAllocContext()
if avformat.AvformatOpenInput(&pFormatContext, os.Args[1], nil, nil) != 0 {
fmt.Printf("Unable to open file %s\n", os.Args[1])
os.Exit(1)
}
// Retrieve stream information
if ctxtFormat.AvformatFindStreamInfo(nil) < 0 {
log.Println("Error: Couldn't find stream information.")
return
if pFormatContext.AvformatFindStreamInfo(nil) < 0 {
fmt.Println("Couldn't find stream information")
os.Exit(1)
}
// Dump information about file onto standard error
ctxtFormat.AvDumpFormat(0, url, 0)
pFormatContext.AvDumpFormat(0, os.Args[1], 0)
// Find the first video stream
videoStream = -1
for i := 0; i < int(pFormatContext.NbStreams()); i++ {
switch pFormatContext.Streams()[i].CodecParameters().AvCodecGetType() {
case avformat.AVMEDIA_TYPE_VIDEO:
//ctxtFormat->nb_streams
n := ctxtFormat.NbStreams()
//ctxtFormat->streams[]
s := ctxtFormat.Streams()
//s2 := avformat.StreamsOne(ctxtFormat, 1)
log.Print("Number of Streams:", n)
for i := 0; i < int(n); i++ {
// ctxtFormat->streams[i]->codec->codec_type
log.Println("Stream Number:", i)
//FIX: AvMEDIA_TYPE_VIDEO
if (*avformat.CodecContext)(s.Codec()) != nil {
videoStream = i
break
}
}
if videoStream == -1 {
log.Println("Couldn't find a video stream")
return
}
codec := s.Codec()
// Get a pointer to the codec context for the video stream
//ctxtSource = ctxtFormat.streams[videoStream].codec
ctxtSource = (*avcodec.Context)(unsafe.Pointer(&codec))
log.Println("Bit Rate:", ctxtSource.BitRate())
log.Println("Channels:", ctxtSource.Channels())
log.Println("Coded_height:", ctxtSource.CodedHeight())
log.Println("Coded_width:", ctxtSource.CodedWidth())
log.Println("Coder_type:", ctxtSource.CoderType())
log.Println("Height:", ctxtSource.Height())
log.Println("Profile:", ctxtSource.Profile())
log.Println("Width:", ctxtSource.Width())
log.Println("Codec ID:", ctxtSource.CodecId())
//C.enum_AVCodecID
codec_id := ctxtSource.CodecId()
// Find the decoder for the video stream
videoCodec = avcodec.AvcodecFindDecoder(codec_id)
if videoCodec == nil {
log.Println("Error: Unsupported codec!")
return // Codec not found
}
// Copy context
ctxtDest = videoCodec.AvcodecAllocContext3()
if ctxtDest.AvcodecCopyContext(ctxtSource) != 0 {
log.Println("Error: Couldn't copy codec context")
return // Error copying codec context
}
// Open codec
if ctxtDest.AvcodecOpen2(videoCodec, nil) < 0 {
return // Could not open codec
}
// Allocate video frame
videoFrame = avutil.AvFrameAlloc()
// Allocate an Frame structure
if videoFrameRGB = avutil.AvFrameAlloc(); videoFrameRGB == nil {
return
}
//##TODO
var a swscale.PixelFormat
var b int
//avcodec.PixelFormat
//avcodec.PIX_FMT_RGB24
//avcodec.SWS_BILINEAR
w := ctxtDest.Width()
h := ctxtDest.Height()
pix_fmt := ctxtDest.PixFmt()
// Determine required buffer size and allocate buffer
numBytes = avcodec.AvpictureGetSize((avcodec.PixelFormat)(a), w, h)
buffer := avutil.AvMalloc(uintptr(numBytes))
// Assign appropriate parts of buffer to image planes in videoFrameRGB
// Note that videoFrameRGB is an Frame, but Frame is a superset
// of Picture
avp := (*avcodec.Picture)(unsafe.Pointer(videoFrameRGB))
avp.AvpictureFill((*uint8)(buffer), (avcodec.PixelFormat)(a), w, h)
// initialize SWS context for software scaling
ctxtSws = swscale.SwsGetcontext(w,
h,
(swscale.PixelFormat)(pix_fmt),
w,
h,
a,
b,
nil,
nil,
nil,
)
// Read frames and save first five frames to disk
i := 0
for ctxtFormat.AvReadFrame(packet) >= 0 {
// Is this a packet from the video stream?
s := packet.StreamIndex()
if s == videoStream {
// Decode video frame
ctxtDest.AvcodecDecodeVideo2((*avcodec.Frame)(unsafe.Pointer(videoFrame)), &frameFinished, packet)
// Did we get a video frame?
if frameFinished > 0 {
// Convert the image from its native format to RGB
d := avutil.Data(videoFrame)
l := avutil.Linesize(videoFrame)
dr := avutil.Data(videoFrameRGB)
lr := avutil.Linesize(videoFrameRGB)
swscale.SwsScale(ctxtSws,
d,
l,
0,
h,
dr,
lr,
)
// Save the frame to disk
if i <= 5 {
saveFrame(videoFrameRGB, w, h, i)
}
i++
// Get a pointer to the codec context for the video stream
pCodecCtxOrig := pFormatContext.Streams()[i].Codec()
// Find the decoder for the video stream
pCodec := avcodec.AvcodecFindDecoder(avcodec.CodecId(pCodecCtxOrig.GetCodecId()))
if pCodec == nil {
fmt.Println("Unsupported codec!")
os.Exit(1)
}
// Copy context
pCodecCtx := pCodec.AvcodecAllocContext3()
if pCodecCtx.AvcodecCopyContext((*avcodec.Context)(unsafe.Pointer(pCodecCtxOrig))) != 0 {
fmt.Println("Couldn't copy codec context")
os.Exit(1)
}
// Open codec
if pCodecCtx.AvcodecOpen2(pCodec, nil) < 0 {
fmt.Println("Could not open codec")
os.Exit(1)
}
// Allocate video frame
pFrame := avutil.AvFrameAlloc()
// Allocate an AVFrame structure
pFrameRGB := avutil.AvFrameAlloc()
if pFrameRGB == nil {
fmt.Println("Unable to allocate RGB Frame")
os.Exit(1)
}
// Determine required buffer size and allocate buffer
numBytes := uintptr(avcodec.AvpictureGetSize(avcodec.AV_PIX_FMT_RGB24, pCodecCtx.Width(),
pCodecCtx.Height()))
buffer := avutil.AvMalloc(numBytes)
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
avp := (*avcodec.Picture)(unsafe.Pointer(pFrameRGB))
avp.AvpictureFill((*uint8)(buffer), avcodec.AV_PIX_FMT_RGB24, pCodecCtx.Width(), pCodecCtx.Height())
// initialize SWS context for software scaling
swsCtx := swscale.SwsGetcontext(
pCodecCtx.Width(),
pCodecCtx.Height(),
(swscale.PixelFormat)(pCodecCtx.PixFmt()),
pCodecCtx.Width(),
pCodecCtx.Height(),
avcodec.AV_PIX_FMT_RGB24,
avcodec.SWS_BILINEAR,
nil,
nil,
nil,
)
// Read frames and save first five frames to disk
frameNumber := 1
packet := avcodec.AvPacketAlloc()
for pFormatContext.AvReadFrame(packet) >= 0 {
// Is this a packet from the video stream?
if packet.StreamIndex() == i {
// Decode video frame
response := pCodecCtx.AvcodecSendPacket(packet)
if response < 0 {
fmt.Printf("Error while sending a packet to the decoder: %s\n", avutil.ErrorFromCode(response))
}
for response >= 0 {
response = pCodecCtx.AvcodecReceiveFrame((*avcodec.Frame)(unsafe.Pointer(pFrame)))
if response == avutil.AvErrorEAGAIN || response == avutil.AvErrorEOF {
break
} else if response < 0 {
fmt.Printf("Error while receiving a frame from the decoder: %s\n", avutil.ErrorFromCode(response))
return
}
if frameNumber <= 5 {
// Convert the image from its native format to RGB
swscale.SwsScale2(swsCtx, avutil.Data(pFrame),
avutil.Linesize(pFrame), 0, pCodecCtx.Height(),
avutil.Data(pFrameRGB), avutil.Linesize(pFrameRGB))
// Save the frame to disk
fmt.Printf("Writing frame %d\n", frameNumber)
SaveFrame(pFrameRGB, pCodecCtx.Width(), pCodecCtx.Height(), frameNumber)
} else {
return
}
frameNumber++
}
}
// Free the packet that was allocated by av_read_frame
packet.AvFreePacket()
}
// Free the RGB image
avutil.AvFree(buffer)
avutil.AvFrameFree(pFrameRGB)
// Free the YUV frame
avutil.AvFrameFree(pFrame)
// Close the codecs
pCodecCtx.AvcodecClose()
(*avcodec.Context)(unsafe.Pointer(pCodecCtxOrig)).AvcodecClose()
// Close the video file
pFormatContext.AvformatCloseInput()
// Stop after saving frames of first video straem
break
default:
fmt.Println("Didn't find a video stream")
os.Exit(1)
}
// Free the packet that was allocated by av_read_frame
packet.AvFreePacket()
}
// Free the RGB image
avutil.AvFree(buffer)
avutil.AvFrameFree(videoFrameRGB)
// Free the YUV frame
avutil.AvFrameFree(videoFrame)
// Close the codecs
ctxtDest.AvcodecClose()
ctxtSource.AvcodecClose()
// Close the video file
ctxtFormat.AvformatCloseInput()
}
func saveFrame(videoFrame *avutil.Frame, width int, height int, iFrame int) {
var szFilename string
var y int
var file *os.File
var err error
szFilename = ""
// Open file
szFilename = fmt.Sprintf("frame%d.ppm", iFrame)
if file, err = os.Open(szFilename); err != nil {
log.Println("Error Reading")
}
// Write header
fh := fmt.Sprintf("P6\n%d %d\n255\n", width, height)
log.Println(fh)
// Write pixel data
for y = 0; y < height; y++ {
// d := avutil.Data(videoFrame)
// l := avutil.Linesize(videoFrame)
//##TODO
f := make([]byte, 100)
file.Write(f)
}
file.Close()
}
+2 -1
View File
@@ -1,6 +1,8 @@
package main
import (
"log"
"github.com/giorgisio/goav/avcodec"
"github.com/giorgisio/goav/avdevice"
"github.com/giorgisio/goav/avfilter"
@@ -8,7 +10,6 @@ import (
"github.com/giorgisio/goav/avutil"
"github.com/giorgisio/goav/swresample"
"github.com/giorgisio/goav/swscale"
"log"
)
func main() {
+6
View File
@@ -0,0 +1,6 @@
module github.com/giorgisio/goav
require (
github.com/gosuri/uilive v0.0.0-20170323041506-ac356e6e42cd // indirect
github.com/gosuri/uiprogress v0.0.0-20170224063937-d0567a9d84a1 // indirect
)
+4
View File
@@ -0,0 +1,4 @@
github.com/gosuri/uilive v0.0.0-20170323041506-ac356e6e42cd h1:1e+0Z+T4t1mKL5xxvxXh5FkjuiToQGKreCobLu7lR3Y=
github.com/gosuri/uilive v0.0.0-20170323041506-ac356e6e42cd/go.mod h1:qkLSc0A5EXSP6B04TrN4oQoxqFI7A8XvoXSlJi8cwk8=
github.com/gosuri/uiprogress v0.0.0-20170224063937-d0567a9d84a1 h1:4iPLwzjiWGBQnYdtKbg/JNlGlEEvklrrMdjypdA1LKQ=
github.com/gosuri/uiprogress v0.0.0-20170224063937-d0567a9d84a1/go.mod h1:C1RTYn4Sc7iEyf6j8ft5dyoZ4212h8G1ol9QQluh5+0=