package ffmpeg /* #include static enum AVMediaType codec_get_type(const AVCodec *c) { return c->type; } */ import "C" import "unsafe" // CodecType represents the type of codec type CodecType int const ( CodecTypeVideo CodecType = CodecType(C.AVMEDIA_TYPE_VIDEO) CodecTypeAudio CodecType = CodecType(C.AVMEDIA_TYPE_AUDIO) CodecTypeSubtitle CodecType = CodecType(C.AVMEDIA_TYPE_SUBTITLE) ) // Codec represents an FFmpeg codec type Codec struct { ptr *C.AVCodec } // FindDecoder finds a decoder by name func FindDecoder(name string) (*Codec, error) { cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) ptr := C.avcodec_find_decoder_by_name(cName) if ptr == nil { return nil, ErrCodecNotFound } return &Codec{ptr: ptr}, nil } // FindEncoder finds an encoder by name func FindEncoder(name string) (*Codec, error) { cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) ptr := C.avcodec_find_encoder_by_name(cName) if ptr == nil { return nil, ErrCodecNotFound } return &Codec{ptr: ptr}, nil } // CodecFromC converts a C pointer to Codec func CodecFromC(ptr *C.AVCodec) *Codec { return &Codec{ptr: ptr} } // CPtr returns the underlying C pointer func (c *Codec) CPtr() *C.AVCodec { return c.ptr } // Name returns the codec name func (c *Codec) Name() string { if c.ptr == nil { return "" } return C.GoString(c.ptr.name) } // LongName returns the codec long name func (c *Codec) LongName() string { if c.ptr == nil { return "" } return C.GoString(c.ptr.long_name) } // Type returns the codec type func (c *Codec) Type() CodecType { if c.ptr == nil { return CodecType(0) } t := C.codec_get_type(c.ptr) return CodecType(t) } // ID returns the codec ID func (c *Codec) ID() int { if c.ptr == nil { return 0 } return int(c.ptr.id) } // Context represents a codec context type Context struct { ptr *C.AVCodecContext } // AllocContext allocates a codec context func AllocContext() *Context { return &Context{ ptr: C.avcodec_alloc_context3(nil), } } // Free frees the codec context func (c *Context) Free() { if c.ptr != nil { C.avcodec_free_context(&c.ptr) c.ptr = nil } } // ContextFromC converts a C pointer to Context func ContextFromC(ptr *C.AVCodecContext) *Context { return &Context{ptr: ptr} } // CPtr returns the underlying C pointer func (c *Context) CPtr() *C.AVCodecContext { return c.ptr } // SetCodec sets the codec for this context func (c *Context) SetCodec(codec *Codec) error { if c.ptr == nil || codec == nil || codec.ptr == nil { return ErrInvalidCodec } C.avcodec_free_context(&c.ptr) c.ptr = C.avcodec_alloc_context3(codec.ptr) if c.ptr == nil { return ErrInvalidCodec } return nil } // Width returns the width func (c *Context) Width() int { if c.ptr == nil { return 0 } return int(c.ptr.width) } // SetWidth sets the width func (c *Context) SetWidth(width int) { if c.ptr != nil { c.ptr.width = C.int(width) } } // Height returns the height func (c *Context) Height() int { if c.ptr == nil { return 0 } return int(c.ptr.height) } // SetHeight sets the height func (c *Context) SetHeight(height int) { if c.ptr != nil { c.ptr.height = C.int(height) } } // Format returns the pixel/sample format func (c *Context) Format() int { if c.ptr == nil { return -1 } return int(c.ptr.sample_fmt) } // SetFormat sets the pixel/sample format func (c *Context) SetFormat(format int) { if c.ptr != nil { // Use unsafe.Pointer to assign to the enum field *(*C.int)(unsafe.Pointer(&c.ptr.sample_fmt)) = C.int(format) } } // BitRate returns the bit rate func (c *Context) BitRate() int64 { if c.ptr == nil { return 0 } return int64(c.ptr.bit_rate) } // SetBitRate sets the bit rate func (c *Context) SetBitRate(br int64) { if c.ptr != nil { c.ptr.bit_rate = C.int64_t(br) } } // TimeBase returns the time base func (c *Context) TimeBase() Rational { if c.ptr == nil { return Rational{} } return Rational{ num: int(c.ptr.time_base.num), den: int(c.ptr.time_base.den), } } // SetTimeBase sets the time base func (c *Context) SetTimeBase(r Rational) { if c.ptr != nil { c.ptr.time_base.num = C.int(r.num) c.ptr.time_base.den = C.int(r.den) } } // SetChannelLayout sets the channel layout func (c *Context) SetChannelLayout(layout uint64) { if c.ptr != nil { c.ptr.channel_layout = C.uint64_t(layout) } } // SetSampleRate sets the sample rate func (c *Context) SetSampleRate(rate int) { if c.ptr != nil { c.ptr.sample_rate = C.int(rate) } } // Channels returns the number of channels func (c *Context) Channels() int { if c.ptr == nil { return 0 } return int(c.ptr.channels) } // Open opens the codec func (c *Context) Open(codec *Codec) error { if c.ptr == nil || codec == nil || codec.ptr == nil { return ErrInvalidCodec } ret := C.avcodec_open2(c.ptr, codec.ptr, nil) if ret < 0 { return &FFmpegError{ Code: int(ret), Message: "failed to open codec", Op: "Open", } } return nil } // CopyParameters copies parameters from CodecParameters to this context func (c *Context) CopyParameters(cp *CodecParameters) error { if c.ptr == nil || cp == nil || cp.ptr == nil { return ErrInvalidCodec } ret := C.avcodec_parameters_to_context(c.ptr, cp.ptr) if ret < 0 { return &FFmpegError{ Code: int(ret), Message: "failed to copy parameters", Op: "CopyParameters", } } return nil } // SendPacket sends a packet to the decoder func (c *Context) SendPacket(pkt *Packet) error { if c.ptr == nil { return ErrInvalidCodec } ret := C.avcodec_send_packet(c.ptr, pkt.CPtr()) if ret < 0 { return &FFmpegError{ Code: int(ret), Message: "failed to send packet", Op: "SendPacket", } } return nil } // ReceiveFrame receives a frame from the decoder func (c *Context) ReceiveFrame(frame *Frame) error { if c.ptr == nil { return ErrInvalidCodec } ret := C.avcodec_receive_frame(c.ptr, frame.CPtr()) if ret < 0 { return &FFmpegError{ Code: int(ret), Message: "failed to receive frame", Op: "ReceiveFrame", } } return nil } // SendFrame sends a frame to the encoder func (c *Context) SendFrame(frame *Frame) error { if c.ptr == nil { return ErrInvalidCodec } ret := C.avcodec_send_frame(c.ptr, frame.CPtr()) if ret < 0 { return &FFmpegError{ Code: int(ret), Message: "failed to send frame", Op: "SendFrame", } } return nil } // ReceivePacket receives a packet from the encoder func (c *Context) ReceivePacket(pkt *Packet) error { if c.ptr == nil { return ErrInvalidCodec } ret := C.avcodec_receive_packet(c.ptr, pkt.CPtr()) if ret < 0 { return &FFmpegError{ Code: int(ret), Message: "failed to receive packet", Op: "ReceivePacket", } } return nil } // Close closes the codec func (c *Context) Close() { if c.ptr != nil { C.avcodec_close(c.ptr) } }