Пример #1
1
func NewCapture(driver, device string) (*Capture, error) {
	id := Capture{index: -1}
	id.context = C.avformat_alloc_context()
	if id.context == (*C.AVFormatContext)(null) {
		return nil, fmt.Errorf("allocate output format context failed")
	}
	_driver := C.CString(driver)
	defer C.free(unsafe.Pointer(_driver))
	ifmt := C.av_find_input_format(_driver)
	if ifmt == (*C.AVInputFormat)(null) {
		return nil, fmt.Errorf("cannot find input driver: %s", driver)
	}
	dev := C.CString(device)
	defer C.free(unsafe.Pointer(dev))
	if C.avformat_open_input(&(id.context), dev, ifmt, (**C.AVDictionary)(null)) < 0 {
		return nil, fmt.Errorf("cannot open device %s", device)
	}
	if C.avformat_find_stream_info(id.context, (**C.AVDictionary)(null)) < 0 {
		return nil, fmt.Errorf("cannot find stream information")
	}
	num := int(id.context.nb_streams)
	streams := (*[1 << 30]*C.AVStream)(unsafe.Pointer(id.context.streams))
	var deCtx *C.AVCodecContext
	for i := 0; i < num; i++ {
		if streams[i].codec.codec_type == C.AVMEDIA_TYPE_VIDEO {
			deCtx = streams[i].codec
			id.index = i
			break
		}
	}
	if id.index == -1 {
		return nil, fmt.Errorf("cannot find video stream")
	}
	codec := C.avcodec_find_decoder(deCtx.codec_id)
	if codec == (*C.AVCodec)(null) {
		return nil, fmt.Errorf("cannot find decode codec")
	}
	id.codec = C.avcodec_alloc_context3(codec)
	if C.avcodec_copy_context(id.codec, deCtx) != 0 {
		return nil, fmt.Errorf("cannot copy codec context")
	}
	if C.avcodec_open2(id.codec, codec, (**C.struct_AVDictionary)(null)) < 0 {
		return nil, fmt.Errorf("cannot open decode codec")
	}
	id.sws = C.sws_getContext(id.codec.width,
		id.codec.height,
		id.codec.pix_fmt,
		id.codec.width,
		id.codec.height,
		C.AV_PIX_FMT_YUV420P, C.SWS_BILINEAR, (*C.struct_SwsFilter)(null), (*C.struct_SwsFilter)(null), (*C.double)(null))
	id.frame = C.av_frame_alloc()
	return &id, nil
}
Пример #2
0
func avcodec_open(cctx _CodecContext, codec _Codec) int {
	avcodec_mutex.Lock()
	res := C.avcodec_open2(cctx.ctx, codec.codec, nil)
	avcodec_mutex.Unlock()
	return int(res)

}
Пример #3
0
func (m *Muxer) AddVideoStream(codecId uint32, width, height int) bool {
	codec := C.avcodec_find_encoder(codecId)
	if codec == (*C.AVCodec)(null) {
		return false
	}
	m.context.oformat.video_codec = codecId
	stream := C.avformat_new_stream(m.context, codec)
	if stream == (*C.AVStream)(null) {
		return false
	}
	m.videoStream = Stream{stream, 0}
	c := m.videoStream.stream.codec
	c.codec_id = codecId
	c.codec_type = C.AVMEDIA_TYPE_VIDEO
	c.bit_rate = 400000
	c.width = C.int(width)
	c.height = C.int(height)
	m.videoStream.stream.time_base = C.AVRational{1, 30}
	c.time_base = m.videoStream.stream.time_base
	c.gop_size = 12
	c.pix_fmt = C.AV_PIX_FMT_YUV420P
	if m.context.oformat.flags&C.AVFMT_GLOBALHEADER != 0 {
		c.flags |= C.CODEC_FLAG_GLOBAL_HEADER
	}
	if C.avcodec_open2(c, (*C.AVCodec)(null), (**C.AVDictionary)(null)) < 0 {
		return false
	}
	m.recl = append(m.recl, func() {
		C.avcodec_close(c)
	})
	return true
}
Пример #4
0
func (stream *Stream) init() error {
	// need to allocate this first so that it can be closed on error
	stream.Frames = make(chan *Frame)

	if stream.avstream == nil {
		close(stream.Frames)
		return errors.New("nil avstream")
	}

	if stream.cdcctx != nil {
		stream.freeCodecContext()
	}
	stream.cdcctx = stream.avstream.codec

	if decoder := C.avcodec_find_decoder(stream.cdcctx.codec_id); decoder == nil || C.avcodec_open2(stream.cdcctx, decoder, nil) < 0 {
		stream.cdcctx = nil
		close(stream.Frames)
		return errors.New("Cannot find decoder for " + C.GoString(C.avcodec_get_name(stream.cdcctx.codec_id)))
	}

	stream.packets = make(chan *C.AVPacket)
	stream.frame = &Frame{}
	switch stream.avstream.codec.codec_type {
	case C.AVMEDIA_TYPE_AUDIO:
		stream.decodeF = avcodec_decode_audio
	case C.AVMEDIA_TYPE_VIDEO:
		stream.decodeF = avcodec_decode_video
	default:
		stream.freeCodecContext()
		close(stream.Frames)
		return errors.New("unsupported codec")
	}

	return nil
}
Пример #5
0
func (codecContext *CodecContext) Codec() *Codec {
	if codecContext.CodecIsOpen() == false {
		codec := C.avcodec_find_decoder(codecContext.codec_id)
		if codec == nil {
			panic("Codec not found")
		}

		C.avcodec_open2((*C.struct_AVCodecContext)(codecContext), codec, nil)
	}

	return (*Codec)(codecContext.codec)
}
Пример #6
0
func NewDecoder(filename string) (*Decoder, error) {
	self := new(Decoder)

	// format context
	var formatContext *C.AVFormatContext
	if C.avformat_open_input(&formatContext, C.CString(filename), nil, nil) != C.int(0) {
		return nil, errors.New(fmt.Sprintf("can't open %d", filename))
	}
	if C.avformat_find_stream_info(formatContext, nil) < 0 {
		return nil, errors.New("find stream info error")
	}
	C.av_dump_format(formatContext, 0, C.CString(filename), 0)
	self.FormatContext = formatContext

	// streams
	var streams []*C.AVStream
	header := (*reflect.SliceHeader)(unsafe.Pointer(&streams))
	header.Cap = int(formatContext.nb_streams)
	header.Len = int(formatContext.nb_streams)
	header.Data = uintptr(unsafe.Pointer(formatContext.streams))
	self.Streams = streams
	for _, stream := range streams {
		switch stream.codec.codec_type {
		case C.AVMEDIA_TYPE_VIDEO:
			self.VideoStreams = append(self.VideoStreams, stream)
		case C.AVMEDIA_TYPE_AUDIO:
			self.AudioStreams = append(self.AudioStreams, stream)
		default: //TODO other stream
		}
	}

	// codecs
	for _, stream := range self.Streams {
		codec := C.avcodec_find_decoder(stream.codec.codec_id)
		if codec == nil {
			continue
		}
		var options *C.AVDictionary
		if C.avcodec_open2(stream.codec, codec, &options) < 0 {
			return nil, errors.New(fmt.Sprintf("open codec error %v", stream.codec))
		}
		self.openedCodecs = append(self.openedCodecs, stream.codec)
	}

	// output channels
	self.audioFrames = make(chan *AudioFrame, 1024)
	self.timedFrames = make(chan *C.AVFrame)

	return self, nil
}
Пример #7
0
func (this *CodecCtx) Open(dict *Dict) error {
	if this.IsOpen() {
		return nil
	}

	var avDict *C.struct_AVDictionary
	if dict != nil {
		avDict = dict.avDict
	}

	if averr := C.avcodec_open2(this.avCodecCtx, this.codec.avCodec, &avDict); averr < 0 {
		return errors.New(fmt.Sprintf("Error opening codec '%s:%s', averror: %s", this.codec.Name(), this.codec.LongName(), AvError(int(averr))))
	}

	return nil
}
Пример #8
0
func (m *Muxer) AddAudioStream(codecId uint32) bool {
	codec := C.avcodec_find_encoder(codecId)
	if codec == (*C.AVCodec)(null) {
		return false
	}
	m.context.oformat.audio_codec = codecId
	stream := C.avformat_new_stream(m.context, codec)
	if stream == (*C.AVStream)(null) {
		return false
	}
	m.audioStream = Stream{stream, 0}
	c := m.audioStream.stream.codec
	c.bit_rate = 48000
	c.sample_fmt = C.AV_SAMPLE_FMT_S16
	if C.check_sample_fmt(codec, c.sample_fmt) == 0 {
		return false
	}
	c.channels = 1
	c.channel_layout = C.uint64_t(C.av_get_default_channel_layout(c.channels))
	c.sample_rate = 44100
	m.audioStream.stream.time_base = C.AVRational{1, c.sample_rate}
	c.time_base = m.audioStream.stream.time_base
	if m.context.oformat.flags&C.AVFMT_GLOBALHEADER != 0 {
		c.flags |= C.CODEC_FLAG_GLOBAL_HEADER
	}
	if codecId == C.AV_CODEC_ID_AAC {
		m.fifo = C.av_audio_fifo_alloc(c.sample_fmt, c.channels, 1)
		if m.fifo == (*C.AVAudioFifo)(null) {
			return false
		}
		m.recl = append(m.recl, func() {
			C.av_audio_fifo_free(m.fifo)
		})
	}
	if C.avcodec_open2(c, (*C.AVCodec)(null), (**C.AVDictionary)(null)) < 0 {
		return false
	}
	m.recl = append(m.recl, func() {
		C.avcodec_close(c)
	})
	if c.codec.capabilities&C.CODEC_CAP_VARIABLE_FRAME_SIZE != 0 {
		c.frame_size = 10000
	}
	return true
}
Пример #9
0
func NewEncoder(codec uint32, in image.Image, out io.Writer) (*Encoder, error) {
	_codec := C.avcodec_find_encoder(codec)
	if _codec == nil {
		return nil, fmt.Errorf("could not find codec")
	}

	c := C.avcodec_alloc_context3(_codec)
	f := C.avcodec_alloc_frame()

	c.bit_rate = 400000

	// resolution must be a multiple of two
	w, h := C.int(in.Bounds().Dx()), C.int(in.Bounds().Dy())
	if w%2 == 1 || h%2 == 1 {
		return nil, fmt.Errorf("Bad image dimensions (%d, %d), must be even", w, h)
	}

	log.Printf("Encoder dimensions: %d, %d", w, h)

	c.width = w
	c.height = h
	c.time_base = C.AVRational{1, 25} // FPS
	c.gop_size = 10                   // emit one intra frame every ten frames
	c.max_b_frames = 1

	underlying_im := image.NewYCbCr(in.Bounds(), image.YCbCrSubsampleRatio420)
	c.pix_fmt = C.PIX_FMT_YUV420P
	f.data[0] = ptr(underlying_im.Y)
	f.data[1] = ptr(underlying_im.Cb)
	f.data[2] = ptr(underlying_im.Cr)
	f.linesize[0] = w
	f.linesize[1] = w / 2
	f.linesize[2] = w / 2

	if C.avcodec_open2(c, _codec, nil) < 0 {
		return nil, fmt.Errorf("could not open codec")
	}

	_swscontext := C.sws_getContext(w, h, C.PIX_FMT_RGB0, w, h, C.PIX_FMT_YUV420P,
		C.SWS_BICUBIC, nil, nil, nil)

	e := &Encoder{codec, in, underlying_im, out, _codec, c, _swscontext, f, make([]byte, 16*1024)}
	return e, nil
}
Пример #10
0
//Initialize the Context to use the given Codec
func (ctxt *Context) AvcodecOpen2(c *Codec, d **Dictionary) int {
	return int(C.avcodec_open2((*C.struct_AVCodecContext)(ctxt), (*C.struct_AVCodec)(c), (**C.struct_AVDictionary)(unsafe.Pointer(d))))
}
Пример #11
0
// NewGenerator returns new generator of screenshots for the video file fn.
func NewGenerator(fn string) (_ *Generator, err error) {
	avfCtx := C.avformat_alloc_context()
	cfn := C.CString(fn)
	defer C.free(unsafe.Pointer(cfn))
	if C.avformat_open_input(&avfCtx, cfn, nil, nil) != 0 {
		return nil, errors.New("can't open input stream")
	}
	defer func() {
		if err != nil {
			C.avformat_close_input(&avfCtx)
		}
	}()
	if C.avformat_find_stream_info(avfCtx, nil) < 0 {
		return nil, errors.New("can't get stream info")
	}
	duration := int64(avfCtx.duration) / 1000
	bitrate := int(avfCtx.bit_rate) / 1000
	numberOfStreams := int(avfCtx.nb_streams)
	hdr := reflect.SliceHeader{
		Data: uintptr(unsafe.Pointer(avfCtx.streams)),
		Len:  numberOfStreams,
		Cap:  numberOfStreams,
	}
	streams := *(*[]*C.struct_AVStream)(unsafe.Pointer(&hdr))
	vStreamIndex := -1
	aStreamIndex := -1
	for i := 0; i < numberOfStreams; i++ {
		if streams[i].codec.codec_type == C.AVMEDIA_TYPE_VIDEO {
			vStreamIndex = i
		} else if streams[i].codec.codec_type == C.AVMEDIA_TYPE_AUDIO {
			aStreamIndex = i
		}
	}
	if vStreamIndex == -1 {
		return nil, errors.New("no video stream")
	}
	avcCtx := streams[vStreamIndex].codec
	vCodec := C.avcodec_find_decoder(avcCtx.codec_id)
	if vCodec == nil {
		return nil, errors.New("can't find decoder")
	}
	if C.avcodec_open2(avcCtx, vCodec, nil) != 0 {
		return nil, errors.New("can't initialize codec context")
	}
	width := int(avcCtx.width)
	height := int(avcCtx.height)
	fps := (float64(streams[vStreamIndex].r_frame_rate.num) /
		float64(streams[vStreamIndex].r_frame_rate.den))
	vCodecName := strings.ToUpper(C.GoString(vCodec.name))
	vCodecHuman := C.GoString(vCodec.long_name)

	aCodecName := ""
	aCodecHuman := ""
	if aStreamIndex != -1 {
		aacCtx := streams[aStreamIndex].codec
		aCodec := C.avcodec_find_decoder(aacCtx.codec_id)
		if aCodec != nil {
			aCodecName = strings.ToUpper(C.GoString(aCodec.name))
			aCodecHuman = C.GoString(aCodec.long_name)
		}
	}

	return &Generator{
		Width:              width,
		Height:             height,
		Duration:           duration,
		VideoCodec:         vCodecName,
		VideoCodecLongName: vCodecHuman,
		AudioCodec:         aCodecName,
		AudioCodecLongName: aCodecHuman,
		numberOfStreams:    numberOfStreams,
		vStreamIndex:       vStreamIndex,
		aStreamIndex:       aStreamIndex,
		FPS:                fps,
		Bitrate:            bitrate,
		streams:            streams,
		avfContext:         avfCtx,
		avcContext:         avcCtx,
	}, nil
}