Beispiel #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
}
Beispiel #2
0
func Open(name string) (*MediaFile, error) {
	file := &MediaFile{
		Name:    name,
		packets: make(chan *C.AVPacket, 8),
	}

	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))

	if C.avformat_open_input(&file.fmtctx, cName, nil, nil) < 0 {
		return nil, errors.New("cannot open file " + name)
	}
	runtime.SetFinalizer(file, (*MediaFile).Close)

	if C.avformat_find_stream_info(file.fmtctx, nil) < 0 {
		return nil, errors.New("cannot find stream info for file " + name)
	}

	file.Streams = make([]Stream, file.fmtctx.nb_streams)
	for i := range file.Streams {
		file.Streams[i] = Stream{
			avstream: C.AVFormatContext_GetStream(file.fmtctx, C.int(i)),
		}
	}

	return file, nil
}
Beispiel #3
0
func av_open_input_file(ctx *FormatContext, filename string, format *InputFormat, bufsize int, params *FormatParameters) int {
	cfilename := C.CString(filename)
	//defer C.free(unsafe.Pointer(cfilename))
	return int(C.avformat_open_input(
		&ctx.ctx,
		cfilename,
		/*(*C.AVInputFormat)(unsafe.Pointer(&format))*/ nil,
		nil))
}
Beispiel #4
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
}
Beispiel #5
0
func (this *FmtCtx) OpenInput(filename string) error {
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))

	if averr := C.avformat_open_input(&this.avCtx, cfilename, nil, nil); averr < 0 {
		return errors.New(fmt.Sprintf("Error opening input '%s': %s", filename, AvError(int(averr))))
	}

	if averr := C.avformat_find_stream_info(this.avCtx, nil); averr < 0 {
		return errors.New(fmt.Sprintf("Unable to find stream info: %s", AvError(int(averr))))
	}

	// C.av_opt_set_int(this.avCtx.codec, "refcounted_frames", 1, 0)

	return nil
}
Beispiel #6
0
func (ctx *Context) OpenInput(fileName string, input *Input, options *avutil.Dictionary) error {
	cFileName := C.CString(fileName)
	defer C.free(unsafe.Pointer(cFileName))
	var cInput *C.AVInputFormat
	if input != nil {
		cInput = input.CAVInputFormat
	}
	var cOptions **C.AVDictionary
	if options != nil {
		cOptions = (**C.AVDictionary)(unsafe.Pointer(&options.CAVDictionary))
	}
	code := C.avformat_open_input(&ctx.CAVFormatContext, cFileName, cInput, cOptions)
	if code < 0 {
		return avutil.NewErrorFromCode(avutil.ErrorCode(code))
	}
	return nil
}
Beispiel #7
0
func main() {

	var (
		fmt_ctx          *C.AVFormatContext
		video_stream_idx C.int
		pkt              C.AVPacket
		fn               string
	)
	flag.StringVar(&fn, "i", fn, "Input filename")
	flag.Parse()
	if fn == "" {
		flag.PrintDefaults()
		os.Exit(1)
	}
	cfn := C.CString(fn)
	defer C.free(unsafe.Pointer(cfn))
	C.av_register_all()
	if err := C.avformat_open_input(&fmt_ctx, cfn, nil, nil); err < 0 {
		log.Fatalf("Could not open source file %s, %d\n", fn, err)
	}
	// The smd codecs aren't too happy with missing PTS
	fmt_ctx.flags |= C.AVFMT_FLAG_GENPTS
	defer C.avformat_close_input(&fmt_ctx)
	if err := C.avformat_find_stream_info(fmt_ctx, nil); err < 0 {
		log.Fatalf("Could not find stream information: %d", err)
	}
	if err := open_codec_context(&video_stream_idx, fmt_ctx, C.AVMEDIA_TYPE_VIDEO); err < 0 {
		log.Fatalf("Could not open codec context: %d", err)
	}
	log.Printf("fmt_ctx: %+v", fmt_ctx)
	streams := (*[32]*C.AVStream)(unsafe.Pointer(fmt_ctx.streams))
	log.Printf("video stream codec: %+v", streams[video_stream_idx].codec.codec_id)

	log.Printf("time_base: %+v", streams[video_stream_idx].time_base)
	num := 1000000 * float64(streams[video_stream_idx].time_base.num)
	den := float64(streams[video_stream_idx].time_base.den)

	var codec C.ismd_codec_type_t
	switch vc := streams[video_stream_idx].codec.codec_id; vc {
	case C.AV_CODEC_ID_H264:
		codec = C.ISMD_CODEC_TYPE_H264
	case C.AV_CODEC_ID_MPEG1VIDEO:
		fallthrough
	case C.AV_CODEC_ID_MPEG2VIDEO:
		codec = C.ISMD_CODEC_TYPE_MPEG2
	case C.AV_CODEC_ID_MPEG4:
		codec = C.ISMD_CODEC_TYPE_MPEG4
	default:
		log.Fatalf("Unhandled video codec: %d", vc)
	}

	Init(codec, C.GDL_PLANE_ID_UPP_C)
	defer Destroy()

	C.av_init_packet(&pkt)
	pkt.data = nil
	pkt.size = 0

	running := true
	go func() {
		os.Stdin.Read(make([]byte, 1))
		running = false
	}()
	frame := 0
	for running && C.av_read_frame(fmt_ctx, &pkt) >= 0 {
		orig_pkt := pkt
		wrote := false
		for pkt.stream_index == video_stream_idx && (pkt.size > 0) {
			pts := num * float64(pkt.pts) / den
			WriteToInputPort(uintptr(unsafe.Pointer(pkt.data)), C.size_t(pkt.size), pts, 32*1024)
			wrote = true
			break
		}
		if wrote {
			frame++
			if frame%100 == 0 {
				var stat C.ismd_vidrend_stats_t
				C.ismd_vidrend_get_stats(m_video_render, &stat)
				log.Printf("%+v", stat)
			}
		}

		C.av_free_packet(&orig_pkt)
	}
}
Beispiel #8
0
//Open an input stream and read the header.
func AvformatOpenInput(ps **Context, fi string, fmt *InputFormat, d **Dictionary) int {
	return int(C.avformat_open_input((**C.struct_AVFormatContext)(unsafe.Pointer(ps)), C.CString(fi), (*C.struct_AVInputFormat)(fmt), (**C.struct_AVDictionary)(unsafe.Pointer(d))))
}
Beispiel #9
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
}