Exemplo n.º 1
0
Arquivo: gst.go Projeto: reusee/oplay
func PipelineWatchBus(pipeline *C.GstPipeline) chan *C.GstMessage {
	bus := C.gst_pipeline_get_bus(pipeline)
	defer C.gst_object_unref(asGPtr(bus))
	messages := make(chan *C.GstMessage)
	C.add_bus_watch(bus, unsafe.Pointer(&messages))
	return messages
}
Exemplo n.º 2
0
Arquivo: main.go Projeto: 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)
}
Exemplo n.º 3
0
Arquivo: gst.go Projeto: reusee/oplay
func NewElementFromUri(t C.GstURIType, uri, name string) (*C.GstElement, error) {
	var err *C.GError
	element := C.gst_element_make_from_uri(t, toGStr(uri), toGStr(name), &err)
	if element == nil {
		defer C.g_error_free(err)
		return nil, errors.New(fmt.Sprintf("%s", err.message))
	}
	runtime.SetFinalizer(element, func(e *C.GstElement) {
		C.gst_object_unref(asGPtr(element))
	})
	return element, nil
}
Exemplo n.º 4
0
Arquivo: gst.go Projeto: reusee/oplay
func NewElement(factory string, name string) (*C.GstElement, error) {
	cFactory := toGStr(factory)
	cName := toGStr(name)
	element := C.gst_element_factory_make(cFactory, cName)
	if element == nil {
		return nil, errors.New(fmt.Sprintf("failed to create element %s:%s", factory, name))
	}
	runtime.SetFinalizer(element, func(e *C.GstElement) {
		C.gst_object_unref(asGPtr(element))
	})
	return element, nil
}
Exemplo n.º 5
0
// Unref is a wrapper around gst_object_unref(). This is for internal use.
func (v *Object) Unref() {
	C.gst_object_unref(C.gpointer(v.toObject()))
}
Exemplo n.º 6
0
Arquivo: main.go Projeto: 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)
}
Exemplo n.º 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()
		}

	}
}