package ffmpeg

/*
#include <libavutil/frame.h>
*/
import "C"
import "unsafe"

// Frame represents a decoded video/audio frame
type Frame struct {
	ptr *C.AVFrame
}

// AllocFrame allocates an empty frame
func AllocFrame() *Frame {
	return &Frame{
		ptr: C.av_frame_alloc(),
	}
}

// FreeFrame frees the frame
func (p *Frame) Free() {
	if p.ptr != nil {
		C.av_frame_free(&p.ptr)
		p.ptr = nil
	}
}

// FrameFromC converts a C pointer to Frame
func FrameFromC(ptr *C.AVFrame) *Frame {
	return &Frame{ptr: ptr}
}

// CPtr returns the underlying C pointer
func (f *Frame) CPtr() *C.AVFrame {
	return f.ptr
}

// Width returns the frame width
func (f *Frame) Width() int {
	if f.ptr == nil {
		return 0
	}
	return int(f.ptr.width)
}

// Height returns the frame height
func (f *Frame) Height() int {
	if f.ptr == nil {
		return 0
	}
	return int(f.ptr.height)
}

// Format returns the pixel/sample format
func (f *Frame) Format() int {
	if f.ptr == nil {
		return -1
	}
	return int(f.ptr.format)
}

// Linesize returns the line size
func (f *Frame) Linesize(i int) int {
	if f.ptr == nil || i < 0 || i >= C.AVMEDIA_TYPE_NB {
		return 0
	}
	return int(f.ptr.linesize[i])
}

// Data returns the frame data
func (f *Frame) Data(i int) []byte {
	if f.ptr == nil || i < 0 || i >= C.AVMEDIA_TYPE_NB {
		return nil
	}
	size := f.Linesize(i) * f.Height()
	if size <= 0 {
		return nil
	}
	return C.GoBytes(unsafe.Pointer(f.ptr.data[i]), C.int(size))
}

// NbSamples returns the number of audio samples
func (f *Frame) NbSamples() int {
	if f.ptr == nil {
		return 0
	}
	return int(f.ptr.nb_samples)
}

// PTS returns the presentation timestamp
func (f *Frame) PTS() int64 {
	if f.ptr == nil {
		return 0
	}
	return int64(f.ptr.pts)
}

// SetPTS sets the presentation timestamp
func (f *Frame) SetPTS(pts int64) {
	if f.ptr != nil {
		f.ptr.pts = C.int64_t(pts)
	}
}

// Unref unreferences the frame
func (f *Frame) Unref() {
	if f.ptr != nil {
		C.av_frame_unref(f.ptr)
	}
}
