示例#1
0
文件: main.go 项目: reusee/oplay
func oggplayer() {
	pipeline := C.gst_pipeline_new(toGStr("audio-player"))
	source, err := NewElement("filesrc", "file-source")
	if err != nil {
		log.Fatal(err)
	}
	demuxer, err := NewElement("oggdemux", "ogg-demuxer")
	if err != nil {
		log.Fatal(err)
	}
	decoder, err := NewElement("vorbisdec", "vorbis-decoder")
	if err != nil {
		log.Fatal(err)
	}
	conv, err := NewElement("audioconvert", "converter")
	if err != nil {
		log.Fatal(err)
	}
	sink, err := NewElement("autoaudiosink", "audio-output")
	if err != nil {
		log.Fatal(err)
	}

	ObjSet(asGObj(source), "location", os.Args[1])
	messages := PipelineWatchBus(asGstPipeline(pipeline))
	BinAdd(pipeline, source, demuxer, decoder, conv, sink)
	ElementLink(source, demuxer)
	ElementLink(decoder, conv, sink)
	ObjConnect(asGObj(demuxer), "pad-added", func(elem *C.GstElement, pad *C.GstPad) {
		sink := C.gst_element_get_static_pad(decoder, toGStr("sink"))
		C.gst_pad_link(pad, sink)
		C.gst_object_unref(asGPtr(sink))
	})
	C.gst_element_set_state(pipeline, C.GST_STATE_PLAYING)

	go func() {
		for msg := range messages {
			MessageDump(msg)
		}
	}()

	go func() {
		var pos, length C.gint64
		for _ = range time.NewTicker(time.Second * 1).C {
			C.gst_element_query_position(pipeline, C.GST_FORMAT_TIME, &pos)
			C.gst_element_query_duration(pipeline, C.GST_FORMAT_TIME, &length)
			p("%v / %v\n", time.Duration(pos), time.Duration(length))
			if time.Duration(pos) > time.Second*5 {
				C.gst_element_seek(pipeline, 1.0, C.GST_FORMAT_TIME, C.GST_SEEK_FLAG_FLUSH,
					C.GST_SEEK_TYPE_SET, 10,
					C.GST_SEEK_TYPE_NONE, C.GST_CLOCK_TIME_NONE)
			}
		}
	}()

	loop := C.g_main_loop_new(nil, False())
	C.g_main_loop_run(loop)
}
示例#2
0
// PipelineNew() is a wrapper around gst_pipeline_new().
func PipelineNew(name string) (*Pipeline, error) {
	cname := C.CString(name)
	defer C.free(unsafe.Pointer(cname))
	c := C.gst_pipeline_new((*C.gchar)(cname))
	if c == nil {
		return nil, nilPtrErr
	}
	obj := &glib.Object{glib.ToGObject(unsafe.Pointer(c))}
	b := wrapPipeline(obj)
	b.RefSink()
	runtime.SetFinalizer(&b.Object, (*Object).Unref)
	return b, nil
}
示例#3
0
文件: main.go 项目: reusee/oplay
// ranged playing
func ranged() {
	pipeline := C.gst_pipeline_new(toGStr("pipeline"))
	src, err := NewElement("uridecodebin", "src")
	if err != nil {
		log.Fatal(err)
	}
	csp, err := NewElement("videoconvert", "csp")
	if err != nil {
		log.Fatal(err)
	}
	vs, err := NewElement("videoscale", "vs")
	if err != nil {
		log.Fatal(err)
	}
	sink, err := NewElement("autovideosink", "sink")
	if err != nil {
		log.Fatal(err)
	}

	ObjSet(asGObj(src), "uri", os.Args[1])
	BinAdd(pipeline, src, csp, vs, sink)
	ElementLink(csp, vs, sink)
	//TODO sinkpad :=

	ObjConnect(asGObj(src), "pad-added", func(e *C.GstElement, pad *C.GstPad) {
		p("====\n")
		PadAddProbe(pad, C.GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, func(info *C.GstPadProbeInfo) C.GstPadProbeReturn {
			p("blocked\n")
			return C.GST_PAD_PROBE_OK
		})
		//C.gst_pad_link(pad, sinkpad)
	})
	ObjConnect(asGObj(src), "no-more-pads", func(e *C.GstElement) {
	})

	C.gst_element_set_state(pipeline, C.GST_STATE_PAUSED)

	messages := PipelineWatchBus(asGstPipeline(pipeline))
	go func() {
		for msg := range messages {
			MessageDump(msg)
		}
	}()

	loop := C.g_main_loop_new(nil, False())
	C.g_main_loop_run(loop)
}
示例#4
0
文件: play.go 项目: reusee/oplay
func play() {
	// element
	e, err := NewElement("fakesrc", "source")
	if err != nil {
		log.Fatal(err)
	}
	p("%v\n", e)

	name := C.gst_object_get_name(asGstObj(e))
	p("%s\n", fromGStr(name))

	// factory
	factory, err := NewFactory("fakesrc")
	if err != nil {
		log.Fatal(err)
	}
	p("%s\n", fromGStr(C.gst_object_get_name(asGstObj(factory))))
	p("%s\n", fromGStr(C.gst_element_factory_get_metadata(factory, asGStr(C.CString(C.GST_ELEMENT_METADATA_KLASS)))))
	p("%s\n", fromGStr(C.gst_element_factory_get_metadata(factory, asGStr(C.CString(C.GST_ELEMENT_METADATA_DESCRIPTION)))))

	// id pipeline
	pipeline := C.gst_pipeline_new(toGStr("pipeline"))
	source, _ := NewElement("fakesrc", "source")
	filter, _ := NewElement("identity", "filter")
	sink, _ := NewElement("fakesink", "sink")
	BinAdd(pipeline, source, filter, sink)
	ElementLink(source, filter, sink)
	C.gst_element_set_state(pipeline, C.GST_STATE_PLAYING)
	C.gst_element_sync_state_with_parent(filter)

	/*
		// bin
		bin := C.gst_bin_new(toGStr("bin"))
		source, _ = NewElement("fakesrc", "source")
		sink, _ = NewElement("fakesink", "sink")
		BinAdd(bin, source, sink)
		//C.gst_bin_remove(asGstBin(bin), source)
		ElementLink(source, sink)
		BinAdd(pipeline, bin)
		source = C.gst_bin_get_by_name(asGstBin(bin), toGStr("source"))
	*/

	// bus
	messages := PipelineWatchBus(asGstPipeline(pipeline))
	loop := C.g_main_loop_new(nil, 0)
	go func() {
		C.g_main_loop_run(loop)
	}()

	// message
loop:
	for msg := range messages {
		runtime.GC()
		p("=> %s from %s\n", fromGStr(C.gst_message_type_get_name(msg._type)),
			fromGStr(C.gst_object_get_name(asGstObj(msg.src))))
		switch msg._type {

		case C.GST_MESSAGE_ERROR:
			var err *C.GError
			var debug *C.gchar
			C.gst_message_parse_error(msg, &err, &debug)
			p("Error: %s\n%s\n", fromGStr(err.message), fromGStr(debug))
			C.g_error_free(err)
			C.g_free(asGPtr(debug))
			C.g_main_loop_quit(loop)
			break loop
		case C.GST_MESSAGE_WARNING:
		case C.GST_MESSAGE_INFO:

		case C.GST_MESSAGE_EOS:
			C.g_main_loop_quit(loop)
			break loop

		case C.GST_MESSAGE_TAG:
			var tags *C.GstTagList
			C.gst_message_parse_tag(msg, &tags)
			//TagListForeach(tags, ) TODO
			C.gst_tag_list_unref(tags)

		case C.GST_MESSAGE_STATE_CHANGED:
			var newState, oldState C.GstState
			C.gst_message_parse_state_changed(msg, &oldState, &newState, nil)
			p("%s -> %s\n", fromGStr(C.gst_element_state_get_name(oldState)),
				fromGStr(C.gst_element_state_get_name(newState)))

		}
	}
}
示例#5
0
文件: play.go 项目: reusee/oplay
func play2() {
	pipeline := C.gst_pipeline_new(toGStr("pipeline"))

	source, err := NewElement("filesrc", "source")
	if err != nil {
		log.Fatal(err)
	}
	ObjSet(asGObj(source), "location", os.Args[1])

	demux, err := NewElement("oggdemux", "demuxer")
	if err != nil {
		log.Fatal(err)
	}

	BinAdd(pipeline, source, demux)
	C.gst_element_link_pads(source, toGStr("src"), demux, toGStr("sink"))
	ObjConnect(asGObj(demux), "pad-added", func(demuxer *C.GstElement, pad *C.GstPad) {
		p("pad added %T %v\n", pad, pad)
	})

	// bus
	messages := PipelineWatchBus(asGstPipeline(pipeline))

	C.gst_element_set_state(pipeline, C.GST_STATE_PLAYING)

	loop := C.g_main_loop_new(nil, 0)
	go func() {
	loop:
		for msg := range messages {
			runtime.GC()
			p("=> %s: %s\n", fromGStr(C.gst_object_get_name(asGstObj(msg.src))),
				fromGStr(C.gst_message_type_get_name(msg._type)))
			switch msg._type {

			case C.GST_MESSAGE_ERROR:
				var err *C.GError
				var debug *C.gchar
				C.gst_message_parse_error(msg, &err, &debug)
				p("Error: %s\n%s\n", fromGStr(err.message), fromGStr(debug))
				C.g_error_free(err)
				C.g_free(asGPtr(debug))
				C.g_main_loop_quit(loop)
				break loop
			case C.GST_MESSAGE_WARNING:
			case C.GST_MESSAGE_INFO:

			case C.GST_MESSAGE_EOS:
				C.g_main_loop_quit(loop)
				break loop

			case C.GST_MESSAGE_TAG:
				var tags *C.GstTagList
				C.gst_message_parse_tag(msg, &tags)
				//TagListForeach(tags, ) TODO
				C.gst_tag_list_unref(tags)

			case C.GST_MESSAGE_STATE_CHANGED:
				var newState, oldState C.GstState
				C.gst_message_parse_state_changed(msg, &oldState, &newState, nil)
				p("%s -> %s\n", fromGStr(C.gst_element_state_get_name(oldState)),
					fromGStr(C.gst_element_state_get_name(newState)))

			}

			C.gst_message_unref(msg)
		}
		p("loop break.\n")
	}()

	runtime.LockOSThread()
	C.g_main_loop_run(loop)
	p("quit.\n")
}
示例#6
0
文件: main.go 项目: reusee/oplay
// pad probe
func probe() {
	pipeline := C.gst_pipeline_new(toGStr("pipeline"))
	src, err := NewElement("videotestsrc", "src")
	if err != nil {
		log.Fatal(err)
	}
	filter, err := NewElement("capsfilter", "filter")
	if err != nil {
		log.Fatal(err)
	}
	csp, err := NewElement("videoconvert", "csp")
	if err != nil {
		log.Fatal(err)
	}
	sink, err := NewElement("xvimagesink", "sink")
	if err != nil {
		log.Fatal(err)
	}

	BinAdd(pipeline, src, filter, csp, sink)
	ElementLink(src, filter, csp, sink)
	C.gst_element_set_state(pipeline, C.GST_STATE_PLAYING)
	messages := PipelineWatchBus(asGstPipeline(pipeline))

	width, height := 640, 480
	filtercaps := NewCapsSimple("video/x-raw",
		"format", "RGB16",
		"width", width,
		"height", height,
		"framerate", Fraction{25, 1})
	ObjSet(asGObj(filter), "caps", filtercaps)
	n := C.gst_caps_get_size(filtercaps)
	structure := C.gst_caps_get_structure(filtercaps, n-1)
	_ = structure
	C.gst_caps_unref(filtercaps)

	pad := C.gst_element_get_static_pad(src, toGStr("src"))
	PadAddProbe(pad, C.GST_PAD_PROBE_TYPE_BUFFER, func(info *C.GstPadProbeInfo) C.GstPadProbeReturn {
		buffer := (*C.GstBuffer)(unsafe.Pointer(info.data))
		buffer = asGstBuffer(C.gst_mini_object_make_writable(asGstMiniObject(buffer)))
		var mapInfo C.GstMapInfo
		C.gst_buffer_map(buffer, &mapInfo, C.GST_MAP_WRITE)
		var ptr []C.guint16
		header := (*reflect.SliceHeader)(unsafe.Pointer(&ptr))
		header.Len = int(mapInfo.size / 2)
		header.Cap = header.Len
		header.Data = uintptr(unsafe.Pointer(mapInfo.data))
		for y := 0; y < height; y++ {
			for x := 0; x < width/2; x++ {
				ptr[x], ptr[width-1-x] = ptr[width-1-x], ptr[x]
			}
			ptr = ptr[width:]
		}
		C.gst_buffer_unmap(buffer, &mapInfo)
		info.data = asGPtr(buffer)
		return C.GST_PAD_PROBE_OK
	})
	C.gst_object_unref(asGPtr(pad))

	go func() {
		for msg := range messages {
			MessageDump(msg)
		}
	}()

	loop := C.g_main_loop_new(nil, False())
	C.g_main_loop_run(loop)
}
示例#7
0
func mp3_play_process(cs chan byte, loop *C.GMainLoop) {
	wg := new(sync.WaitGroup)
	sig_in := make(chan bool)
	sig_out := make(chan bool)

	defer close(sig_in)
	defer close(sig_out)
	defer g_wg.Done()
	if g_isOutOfOrder {
		outOfOrder(g_list)
		debug.FreeOSMemory()
	}
	start := g_list.Front()
	end := g_list.Back()
	e := g_list.Front()

	for {
		fpath, ok := e.Value.(string)
		if ok {
			// fmt.Printf("filename[%s]\n", fpath)
			var pipeline, source, decoder, sink *C.GstElement // 定义组件
			var bus *C.GstBus

			switch filepath.Ext(fpath) {
			case ".mp3":
				v3 := GString("mad")
				v4 := GString("mad-decoder")
				decoder = C.gst_element_factory_make(v3, v4)
				GFree(C.gpointer(v4))
				GFree(C.gpointer(v3))
			case ".wav":
				v3 := GString("wavparse")
				v4 := GString("parser")
				decoder = C.gst_element_factory_make(v3, v4)
				GFree(C.gpointer(v3))
				GFree(C.gpointer(v4))
			case ".ogg":
				// v3 := GString("oggparse")
				// defer GFree(C.gpointer(v3))
				// v4 := GString("ogg-parser")
				// defer GFree(C.gpointer(v4))
				// decoder = C.gst_element_factory_make(v3, v4)
				fallthrough
			default:
				return
			}

			// fmt.Printf("FileName[%s]FileSize[%d]Dir[%v]\n", path, info.Size(), info.IsDir())

			// 创建管道和组件
			v0 := GString("audio-player")
			pipeline = C.gst_pipeline_new(v0)
			GFree(C.gpointer(v0))
			v1 := GString("filesrc")
			v2 := GString("file-source")
			source = C.gst_element_factory_make(v1, v2)
			GFree(C.gpointer(v1))
			GFree(C.gpointer(v2))

			// sink = gst_element_factory_make("autoaudiosink","audio-output");
			v5 := GString("alsasink")
			v6 := GString("alsa-output")
			sink = C.gst_element_factory_make(v5, v6)
			GFree(C.gpointer(v6))
			GFree(C.gpointer(v5))
			if pipeline == (*C.GstElement)(nil) ||
				source == (*C.GstElement)(nil) ||
				decoder == (*C.GstElement)(nil) ||
				sink == (*C.GstElement)(nil) {
				fmt.Println("One element could not be created.Exiting.")
			}

			// 设置 source的location 参数。即 文件地址.
			v7 := GString("location")
			cpath := GString(fpath)
			C.obj_set(unsafe.Pointer(source),
				unsafe.Pointer(v7), unsafe.Pointer(cpath))
			GFree(C.gpointer(v7))
			GFree(C.gpointer(cpath))

			// 得到 管道的消息总线
			bus = C.pipeline_get_bus(unsafe.Pointer(pipeline))
			if bus == (*C.GstBus)(nil) {
				fmt.Println("GstBus element could not be created.Exiting.")
				return
			}

			// 添加消息监视器
			C.bus_add_watch(unsafe.Pointer(bus), unsafe.Pointer(loop))
			C.gst_object_unref(C.gpointer(bus))

			// 把组件添加到管道中.管道是一个特殊的组件,可以更好的让数据流动
			C.bin_add_many(unsafe.Pointer(pipeline),
				unsafe.Pointer(source), unsafe.Pointer(decoder),
				unsafe.Pointer(sink))

			// 依次连接组件
			C.element_link_many(unsafe.Pointer(source),
				unsafe.Pointer(decoder), unsafe.Pointer(sink))

			// 开始播放
			C.mp3_ready(unsafe.Pointer(pipeline))
			C.mp3_play(unsafe.Pointer(pipeline))

			wg.Add(1)
			go func(p *C.GstElement) {
				defer wg.Done()
				// 开始循环
				C.g_main_loop_run(loop)
				C.mp3_stop(unsafe.Pointer(p))
				C.object_unref(unsafe.Pointer(p))

				select {
				case c := <-sig_in:
					if c {
						return
					}
				default:
					e = e.Next()
					if e == nil {
						sig_out <- true
						return
					}
				}
				sig_out <- false
			}(pipeline)
			lb := true
			for lb {
				select {
				case op := <-cs:
					switch op {
					case 's':
						C.mp3_pause(unsafe.Pointer(pipeline))
					case 'r':
						C.mp3_play(unsafe.Pointer(pipeline))
					case 'n':
						if e != end {
							e = e.Next()
						}
						C.g_main_loop_quit(loop)
						sig_in <- false
					case 'p':
						if e != start {
							e = e.Prev()
						}
						C.g_main_loop_quit(loop)
						sig_in <- false
					case 'q':
						C.g_main_loop_quit(loop)
						sig_in <- true
						wg.Wait()
						return
					}
				case c := <-sig_out:
					if c {
						return
					} else {
						lb = false
					}
				}
			}
			wg.Wait()
		}

	}
}