gstreamer 0.90.6
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +1157 -0
- data/README +33 -0
- data/Rakefile +15 -0
- data/ext/gstreamer/Makefile +162 -0
- data/ext/gstreamer/depend +5 -0
- data/ext/gstreamer/extconf.rb +63 -0
- data/ext/gstreamer/gst.so +0 -0
- data/ext/gstreamer/misc.c +62 -0
- data/ext/gstreamer/misc.o +0 -0
- data/ext/gstreamer/rbgst-bin.c +466 -0
- data/ext/gstreamer/rbgst-bin.o +0 -0
- data/ext/gstreamer/rbgst-buffer.c +365 -0
- data/ext/gstreamer/rbgst-buffer.o +0 -0
- data/ext/gstreamer/rbgst-bus.c +92 -0
- data/ext/gstreamer/rbgst-bus.o +0 -0
- data/ext/gstreamer/rbgst-caps.c +441 -0
- data/ext/gstreamer/rbgst-caps.o +0 -0
- data/ext/gstreamer/rbgst-child-proxy.c +33 -0
- data/ext/gstreamer/rbgst-child-proxy.o +0 -0
- data/ext/gstreamer/rbgst-clock.c +108 -0
- data/ext/gstreamer/rbgst-clock.o +0 -0
- data/ext/gstreamer/rbgst-element-factory.c +255 -0
- data/ext/gstreamer/rbgst-element-factory.o +0 -0
- data/ext/gstreamer/rbgst-element.c +1053 -0
- data/ext/gstreamer/rbgst-element.o +0 -0
- data/ext/gstreamer/rbgst-event.c +351 -0
- data/ext/gstreamer/rbgst-event.o +0 -0
- data/ext/gstreamer/rbgst-ghost-pad.c +42 -0
- data/ext/gstreamer/rbgst-ghost-pad.o +0 -0
- data/ext/gstreamer/rbgst-index-factory.c +67 -0
- data/ext/gstreamer/rbgst-index-factory.o +0 -0
- data/ext/gstreamer/rbgst-message.c +784 -0
- data/ext/gstreamer/rbgst-message.o +0 -0
- data/ext/gstreamer/rbgst-mini-object.c +220 -0
- data/ext/gstreamer/rbgst-mini-object.o +0 -0
- data/ext/gstreamer/rbgst-object.c +81 -0
- data/ext/gstreamer/rbgst-object.o +0 -0
- data/ext/gstreamer/rbgst-pad-template.c +124 -0
- data/ext/gstreamer/rbgst-pad-template.o +0 -0
- data/ext/gstreamer/rbgst-pad.c +338 -0
- data/ext/gstreamer/rbgst-pad.o +0 -0
- data/ext/gstreamer/rbgst-pipeline.c +90 -0
- data/ext/gstreamer/rbgst-pipeline.o +0 -0
- data/ext/gstreamer/rbgst-plugin-feature.c +134 -0
- data/ext/gstreamer/rbgst-plugin-feature.o +0 -0
- data/ext/gstreamer/rbgst-plugin.c +164 -0
- data/ext/gstreamer/rbgst-plugin.o +0 -0
- data/ext/gstreamer/rbgst-private.c +89 -0
- data/ext/gstreamer/rbgst-private.h +37 -0
- data/ext/gstreamer/rbgst-private.o +0 -0
- data/ext/gstreamer/rbgst-query.c +289 -0
- data/ext/gstreamer/rbgst-query.o +0 -0
- data/ext/gstreamer/rbgst-seek.c +36 -0
- data/ext/gstreamer/rbgst-seek.o +0 -0
- data/ext/gstreamer/rbgst-static-caps.c +49 -0
- data/ext/gstreamer/rbgst-static-caps.o +0 -0
- data/ext/gstreamer/rbgst-static-pad-template.c +64 -0
- data/ext/gstreamer/rbgst-static-pad-template.o +0 -0
- data/ext/gstreamer/rbgst-structure.c +300 -0
- data/ext/gstreamer/rbgst-structure.o +0 -0
- data/ext/gstreamer/rbgst-system-clock.c +45 -0
- data/ext/gstreamer/rbgst-system-clock.o +0 -0
- data/ext/gstreamer/rbgst-type-find-factory.c +124 -0
- data/ext/gstreamer/rbgst-type-find-factory.o +0 -0
- data/ext/gstreamer/rbgst-value.c +517 -0
- data/ext/gstreamer/rbgst-value.o +0 -0
- data/ext/gstreamer/rbgst-x-overlay.c +132 -0
- data/ext/gstreamer/rbgst-x-overlay.o +0 -0
- data/ext/gstreamer/rbgst.c +279 -0
- data/ext/gstreamer/rbgst.h +197 -0
- data/ext/gstreamer/rbgst.o +0 -0
- data/ext/gstreamer/rbgstclockentry.c +268 -0
- data/ext/gstreamer/rbgstclockentry.o +0 -0
- data/ext/gstreamer/rbgstformat.c +159 -0
- data/ext/gstreamer/rbgstformat.o +0 -0
- data/ext/gstreamer/rbgstindex.c +314 -0
- data/ext/gstreamer/rbgstindex.o +0 -0
- data/ext/gstreamer/rbgstindexentry.c +96 -0
- data/ext/gstreamer/rbgstindexentry.o +0 -0
- data/ext/gstreamer/rbgstparse.c +66 -0
- data/ext/gstreamer/rbgstparse.o +0 -0
- data/ext/gstreamer/rbgstquerytype.c +159 -0
- data/ext/gstreamer/rbgstquerytype.o +0 -0
- data/ext/gstreamer/rbgstregistry.c +278 -0
- data/ext/gstreamer/rbgstregistry.o +0 -0
- data/ext/gstreamer/rbgsttag.c +111 -0
- data/ext/gstreamer/rbgsttag.o +0 -0
- data/ext/gstreamer/rbgsttagsetter.c +50 -0
- data/ext/gstreamer/rbgsttagsetter.o +0 -0
- data/ext/gstreamer/rbgstxml.c +189 -0
- data/ext/gstreamer/rbgstxml.o +0 -0
- data/ext/gstreamer/ruby-gstreamer.pc +3 -0
- data/extconf.rb +49 -0
- data/lib/gst.rb +19 -0
- data/sample/audio-player.rb +54 -0
- data/sample/gst-inspect.rb +417 -0
- data/sample/media-type.rb +55 -0
- data/sample/media-type2.rb +268 -0
- data/sample/ogg-audio-player.rb +54 -0
- data/sample/type-find.rb +46 -0
- data/sample/video-player.rb +57 -0
- data/sample/xml-player.rb +60 -0
- data/test/gst-test-utils.rb +18 -0
- data/test/run-test.rb +25 -0
- data/test/test_bin.rb +167 -0
- data/test/test_buffer.rb +174 -0
- data/test/test_caps.rb +24 -0
- data/test/test_clock.rb +7 -0
- data/test/test_element.rb +87 -0
- data/test/test_element_factory.rb +28 -0
- data/test/test_event.rb +10 -0
- data/test/test_index_factory.rb +7 -0
- data/test/test_message.rb +191 -0
- data/test/test_mini_object.rb +38 -0
- data/test/test_object.rb +10 -0
- data/test/test_pad.rb +68 -0
- data/test/test_plugin.rb +6 -0
- data/test/test_plugin_feature.rb +20 -0
- data/test/test_seek.rb +17 -0
- data/test/test_static_caps.rb +18 -0
- data/test/test_static_pad_template.rb +16 -0
- data/test/test_structure.rb +159 -0
- data/test/test_thread_handling.rb +58 -0
- data/test/test_type_find_factory.rb +8 -0
- data/test/test_value.rb +69 -0
- metadata +208 -0
@@ -0,0 +1,268 @@
|
|
1
|
+
|
2
|
+
# This is a Ruby implementation of the GStreamer media-info library,
|
3
|
+
# graciously provided by Nikolai Weilbull <lone-star@home.se>.
|
4
|
+
#
|
5
|
+
# It works exactly like media-type.rb.
|
6
|
+
|
7
|
+
require 'gst'
|
8
|
+
|
9
|
+
class MediaInfoStream
|
10
|
+
def initialize
|
11
|
+
@length_tracks = 0
|
12
|
+
@length_time = 0
|
13
|
+
@bitrate = 0
|
14
|
+
@seekable = false
|
15
|
+
@path = nil
|
16
|
+
@mime = nil
|
17
|
+
@tracks = []
|
18
|
+
end
|
19
|
+
attr_accessor :length_time, :length_tracks, :path, :mime, :bitrate, :tracks
|
20
|
+
end
|
21
|
+
|
22
|
+
class MediaInfoTrack
|
23
|
+
def initialize
|
24
|
+
@metadata = nil
|
25
|
+
@streaminfo = nil
|
26
|
+
@format = nil
|
27
|
+
@length_time = 0
|
28
|
+
@con_streams = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_accessor :metadata, :streaminfo, :format
|
32
|
+
end
|
33
|
+
|
34
|
+
class MediaInfo
|
35
|
+
# TODO: add signals
|
36
|
+
INFO_ALL = (0..4).to_a.length - 1
|
37
|
+
INFO_STREAM, INFO_MIME, INFO_METADATA, INFO_STREAMINFO, INFO_FORMAT = *(0..4).to_a
|
38
|
+
def initialize(source_element)
|
39
|
+
@pipeline = Gst::Pipeline.new 'media-info'
|
40
|
+
@typefind = Gst::ElementFactory.make 'typefind', 'typefind'
|
41
|
+
@source_element = source_element
|
42
|
+
@source = Gst::ElementFactory.make @source_element, 'source'
|
43
|
+
if @source != nil
|
44
|
+
@pipeline.add @source
|
45
|
+
else
|
46
|
+
@source_element = nil
|
47
|
+
@source = nil
|
48
|
+
end
|
49
|
+
@decoder = @type = @format = @metadata = @stream = nil
|
50
|
+
@decoders = Hash.new
|
51
|
+
@pipeline.signal_connect 'deep_notify' do |obj, origin, pspec|
|
52
|
+
case pspec.name
|
53
|
+
when 'metadata'
|
54
|
+
@metadata = origin.metadata
|
55
|
+
when 'caps'
|
56
|
+
@format = origin.caps if origin == @decoder_pad
|
57
|
+
when 'streaminfo'
|
58
|
+
@streaminfo = origin.streaminfo
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def reset
|
64
|
+
@format = nil
|
65
|
+
@metadata = nil
|
66
|
+
@stream = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def seek_to_track(track)
|
70
|
+
track_format = Gst::Format.find 'logical_stream'
|
71
|
+
return false if track_format == nil
|
72
|
+
@pipeline.play
|
73
|
+
# XXX: todo, need Gst::Event
|
74
|
+
event = gst_event_new_seek(format.id | Gst::EventSeek::METHOD_SET |
|
75
|
+
Gst::EventSeek::FLAG_FLUSH)
|
76
|
+
return false if event == nil
|
77
|
+
@metadata = nil
|
78
|
+
@streaminfo = nil
|
79
|
+
return true
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_decoder(mime)
|
83
|
+
decoder = @decoders[mime]
|
84
|
+
if decoder == nil
|
85
|
+
factories = {
|
86
|
+
'application/x-ogg' => 'vorbisfile',
|
87
|
+
'audio/x-mp3' => 'mad',
|
88
|
+
'audio/x-wav' => 'wavparse'
|
89
|
+
}
|
90
|
+
factory = factories[mime]
|
91
|
+
return nil if factory == nil
|
92
|
+
decoder = Gst::ElementFactory.make factory, 'decoder'
|
93
|
+
@decoders[mime] = decoder if decoder != nil
|
94
|
+
end
|
95
|
+
return decoder
|
96
|
+
end
|
97
|
+
|
98
|
+
def find_type(location)
|
99
|
+
@type = nil
|
100
|
+
@pipeline.add @typefind
|
101
|
+
@source.location = location
|
102
|
+
@source >> @typefind
|
103
|
+
@typefind.signal_connect 'have-type' do |typefind, type|
|
104
|
+
@type = type
|
105
|
+
end
|
106
|
+
@pipeline.play
|
107
|
+
while @type == nil && @pipeline.iterate do end
|
108
|
+
@pipeline.ready
|
109
|
+
# TODO: this is different
|
110
|
+
@source.unlink_pads @typefind
|
111
|
+
@pipeline.remove @typefind
|
112
|
+
end
|
113
|
+
|
114
|
+
def get_stream(stream)
|
115
|
+
@pipeline.play
|
116
|
+
while @format == nil && @pipeline.iterate do end
|
117
|
+
@pipeline.pause
|
118
|
+
return nil if @format == nil
|
119
|
+
track_format = Gst::Format.find 'logical_stream'
|
120
|
+
@decoder_pad.formats.each do |format|
|
121
|
+
value = @decoder_pad.query(Gst::QueryType::TOTAL, format.type_id)
|
122
|
+
case format.type_id
|
123
|
+
when Gst::Format::TIME
|
124
|
+
stream.length_time = value ? value : 1
|
125
|
+
else
|
126
|
+
stream.length_tracks = value if format == track_format && value != nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
stream.length_tracks = 1 if stream.length_tracks == 0
|
130
|
+
value = @source_pad.query(Gst::QueryType::TOTAL, Gst::Format::BYTES)
|
131
|
+
if value
|
132
|
+
seconds = stream.length_time.to_f / Gst::SECOND
|
133
|
+
bits = value * 8
|
134
|
+
stream.bitrate = bits / seconds
|
135
|
+
end
|
136
|
+
return stream
|
137
|
+
end
|
138
|
+
|
139
|
+
def find_metadata
|
140
|
+
@pipeline.play
|
141
|
+
while @metadata == nil && @pipeline.iterate do end
|
142
|
+
@pipeline.pause
|
143
|
+
metadata = @metadata
|
144
|
+
@metadata = nil
|
145
|
+
return metadata
|
146
|
+
end
|
147
|
+
|
148
|
+
def find_streaminfo
|
149
|
+
@pipeline.play
|
150
|
+
while @streaminfo == nil && @pipeline.iterate do end
|
151
|
+
@pipeline.pause
|
152
|
+
streaminfo = @streaminfo
|
153
|
+
@streaminfo = nil
|
154
|
+
|
155
|
+
track_format = Gst::Format.find 'logical_stream'
|
156
|
+
if track_format != nil
|
157
|
+
start = @decoder_pad.query(Gst::QueryType::POSITION, track_format.type_id)
|
158
|
+
track_num = start
|
159
|
+
# XXX: need Gst::Pad#convert
|
160
|
+
end
|
161
|
+
return streaminfo
|
162
|
+
end
|
163
|
+
|
164
|
+
def find_format
|
165
|
+
@pipeline.play
|
166
|
+
while @format == nil && @pipeline.iterate do end
|
167
|
+
@pipeline.pause
|
168
|
+
format = @format
|
169
|
+
@format = nil
|
170
|
+
return format
|
171
|
+
end
|
172
|
+
|
173
|
+
def clear_decoder
|
174
|
+
if @decoder != nil
|
175
|
+
@pipeline.ready
|
176
|
+
@source.unlink_pads @decoder
|
177
|
+
@pipeline.remove @decoder
|
178
|
+
@decoder = nil
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def set_decoder(decoder)
|
183
|
+
@decoder = decoder
|
184
|
+
@pipeline.add @decoder
|
185
|
+
@source >> @decoder
|
186
|
+
@decoder_pad = @decoder.get_pad 'src'
|
187
|
+
@source_pad = @source.get_pad 'src'
|
188
|
+
end
|
189
|
+
|
190
|
+
def set_source(source)
|
191
|
+
src = Gst::ElementFactory.make source, 'new-source'
|
192
|
+
return false if src == nil
|
193
|
+
if @source != nil
|
194
|
+
@pipeline.remove @source
|
195
|
+
@source_element = nil if @source_element != nil
|
196
|
+
end
|
197
|
+
src.name = 'source'
|
198
|
+
@pipeline.add src
|
199
|
+
@source = src
|
200
|
+
@source_element = source
|
201
|
+
return true
|
202
|
+
end
|
203
|
+
|
204
|
+
def read(location, flags)
|
205
|
+
reset
|
206
|
+
find_type location
|
207
|
+
return nil if @type == nil
|
208
|
+
stream = MediaInfoStream.new
|
209
|
+
mime = @type.mime
|
210
|
+
stream.mime = mime if flags & INFO_MIME
|
211
|
+
stream.path = location
|
212
|
+
decoder = get_decoder mime
|
213
|
+
return nil if decoder == nil
|
214
|
+
set_decoder decoder
|
215
|
+
stream = get_stream stream
|
216
|
+
stream.length_tracks.times do |i|
|
217
|
+
track = MediaInfoTrack.new
|
218
|
+
track.metadata = find_metadata if flags & INFO_METADATA
|
219
|
+
track.streaminfo = find_streaminfo if flags & INFO_STREAMINFO
|
220
|
+
track.format = find_format if flags & INFO_FORMAT
|
221
|
+
stream.tracks << track
|
222
|
+
end
|
223
|
+
clear_decoder
|
224
|
+
return stream
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def usage
|
229
|
+
puts "Usage: #{__FILE__} FILE..."
|
230
|
+
exit 1
|
231
|
+
end
|
232
|
+
|
233
|
+
def print_caps(caps)
|
234
|
+
return if caps == nil
|
235
|
+
caps.each_property do |name, value, fixed|
|
236
|
+
puts " #{name}: #{value}"
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def print_info(path, stream)
|
241
|
+
if stream
|
242
|
+
puts "#{path}:"
|
243
|
+
puts " mime type: #{stream.mime}"
|
244
|
+
puts " length: #{stream.length_time / Gst::SECOND} seconds"
|
245
|
+
puts " bitrate: #{stream.bitrate / 1000.0} kbps"
|
246
|
+
puts " number of tracks: #{stream.length_tracks}"
|
247
|
+
puts " tracks:"
|
248
|
+
stream.tracks.each_with_index do |track, i|
|
249
|
+
puts " - track #{i + 1}:"
|
250
|
+
puts " metadata:"
|
251
|
+
print_caps track.metadata
|
252
|
+
puts " streaminfo:"
|
253
|
+
print_caps track.streaminfo
|
254
|
+
puts " format:"
|
255
|
+
print_caps track.format
|
256
|
+
end
|
257
|
+
else
|
258
|
+
puts "No media info found for file #{path}"
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
usage if ARGV.empty?
|
263
|
+
Gst.init
|
264
|
+
mediainfo = MediaInfo.new 'filesrc'
|
265
|
+
ARGV.each do |path|
|
266
|
+
print_info path, mediainfo.read(path, MediaInfo::INFO_ALL)
|
267
|
+
end
|
268
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
if ARGV.size != 1
|
4
|
+
puts "Usage: #{$0} ogg-audio-file"
|
5
|
+
exit
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'gst'
|
9
|
+
|
10
|
+
loop = GLib::MainLoop.new(nil, false)
|
11
|
+
|
12
|
+
pipeline = Gst::Pipeline.new("ogg-audio-player")
|
13
|
+
source = Gst::ElementFactory.make("filesrc", "file-source")
|
14
|
+
parser = Gst::ElementFactory.make("oggdemux", "ogg-parser")
|
15
|
+
decoder = Gst::ElementFactory.make("vorbisdec", "vorbis-decoder")
|
16
|
+
converter = Gst::ElementFactory.make("audioconvert", "converter")
|
17
|
+
sink = Gst::ElementFactory.make("alsasink", "alsa-output")
|
18
|
+
|
19
|
+
source.location = ARGV.shift
|
20
|
+
|
21
|
+
bus = pipeline.bus
|
22
|
+
bus.add_watch do |bus, message|
|
23
|
+
case message.type
|
24
|
+
when Gst::Message::EOS
|
25
|
+
loop.quit
|
26
|
+
when Gst::Message::ERROR
|
27
|
+
p message.parse
|
28
|
+
loop.quit
|
29
|
+
end
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
pipeline.add(source, parser, decoder, converter, sink)
|
35
|
+
source >> parser
|
36
|
+
decoder >> converter >> sink
|
37
|
+
|
38
|
+
parser.signal_connect("pad-added") do |element, pad|
|
39
|
+
sink_pad = decoder.get_pad("sink")
|
40
|
+
pad.link(sink_pad)
|
41
|
+
end
|
42
|
+
|
43
|
+
puts "Setting to PLAYING"
|
44
|
+
pipeline.play
|
45
|
+
puts "Running"
|
46
|
+
begin
|
47
|
+
loop.run
|
48
|
+
print "Returned, "
|
49
|
+
rescue Interrupt
|
50
|
+
print "Interrupted, "
|
51
|
+
ensure
|
52
|
+
puts "stopping playback"
|
53
|
+
pipeline.stop
|
54
|
+
end
|
data/sample/type-find.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'gst'
|
4
|
+
|
5
|
+
def type_find(file)
|
6
|
+
pipeline = Gst::Pipeline.new("pipeline")
|
7
|
+
|
8
|
+
source = Gst::ElementFactory.make("filesrc", "source")
|
9
|
+
type_find = Gst::ElementFactory.make("typefind", "type-find")
|
10
|
+
sink = Gst::ElementFactory.make("fakesink", "sink")
|
11
|
+
|
12
|
+
pipeline.add(source, type_find, sink)
|
13
|
+
source >> type_find >> sink
|
14
|
+
|
15
|
+
found_caps = nil
|
16
|
+
type_find.signal_connect("have-type") do |element, probability, caps|
|
17
|
+
found_caps = caps
|
18
|
+
end
|
19
|
+
|
20
|
+
loop = GLib::MainLoop.new
|
21
|
+
source.location = file
|
22
|
+
bus = pipeline.bus
|
23
|
+
bus.add_watch do |bus, message|
|
24
|
+
case message.type
|
25
|
+
when Gst::Message::STATE_CHANGED, Gst::Message::EOS
|
26
|
+
loop.quit
|
27
|
+
when Gst::Message::ERROR
|
28
|
+
p message.parse
|
29
|
+
loop.quit
|
30
|
+
end
|
31
|
+
true
|
32
|
+
end
|
33
|
+
pipeline.pause
|
34
|
+
loop.run
|
35
|
+
pipeline.stop
|
36
|
+
|
37
|
+
if found_caps
|
38
|
+
puts("#{file} - #{found_caps}")
|
39
|
+
else
|
40
|
+
puts("#{file} - No type found")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
ARGV.each do |file|
|
45
|
+
type_find(file)
|
46
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
if ARGV.size != 1
|
4
|
+
$stderr.puts "Usage: #{$0} uri"
|
5
|
+
exit 1
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'gtk2'
|
9
|
+
require 'gst'
|
10
|
+
require 'uri'
|
11
|
+
|
12
|
+
def normalize_uri(uri)
|
13
|
+
uri = URI(uri)
|
14
|
+
uri.scheme ||= "file"
|
15
|
+
if uri.scheme == "file"
|
16
|
+
"file://#{uri.path}"
|
17
|
+
else
|
18
|
+
uri.to_s
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
play_bin = Gst::ElementFactory.make('playbin')
|
23
|
+
bus = play_bin.bus
|
24
|
+
bus.add_watch do |bus, message|
|
25
|
+
case message.type
|
26
|
+
when Gst::Message::EOS
|
27
|
+
puts "end of stream"
|
28
|
+
Gtk.main_quit
|
29
|
+
when Gst::Message::ERROR
|
30
|
+
$stderr.puts "Error: #{message.parse}"
|
31
|
+
Gtk.main_quit
|
32
|
+
end
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
play_bin.uri = normalize_uri(ARGV.first)
|
37
|
+
video_sink = Gst::ElementFactory.make('xvimagesink')
|
38
|
+
play_bin.video_sink = video_sink
|
39
|
+
|
40
|
+
window = Gtk::Window.new
|
41
|
+
window.signal_connect('destroy') do
|
42
|
+
play_bin.stop
|
43
|
+
Gtk.main_quit
|
44
|
+
end
|
45
|
+
window.signal_connect('expose-event') do
|
46
|
+
video_sink.xwindow_id = window.window.xid
|
47
|
+
end
|
48
|
+
window.show_all
|
49
|
+
|
50
|
+
puts "Streaming #{play_bin.uri}..."
|
51
|
+
play_bin.play
|
52
|
+
|
53
|
+
begin
|
54
|
+
Gtk.main
|
55
|
+
rescue Interrupt
|
56
|
+
window.destroy
|
57
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
### TODO: I want to set link in build_pipeline.
|
4
|
+
|
5
|
+
unless ARGV.size == 1
|
6
|
+
puts "Usage: #{$0} [file]"
|
7
|
+
exit 1
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'gst'
|
11
|
+
|
12
|
+
XML_FILE = "/tmp/pipeline.xml"
|
13
|
+
PIPELINE_NAME = "our-pipeline"
|
14
|
+
|
15
|
+
def build_pipeline(file)
|
16
|
+
source = Gst::ElementFactory.make("filesrc")
|
17
|
+
decoder = Gst::ElementFactory.make("decodebin")
|
18
|
+
audio_converter = Gst::ElementFactory.make("audioconvert")
|
19
|
+
audio_resample = Gst::ElementFactory.make("audioresample")
|
20
|
+
audio_sink = Gst::ElementFactory.make("autoaudiosink")
|
21
|
+
source.location = file
|
22
|
+
pipeline = Gst::Pipeline.new(PIPELINE_NAME)
|
23
|
+
pipeline.add(source, decoder, audio_converter, audio_resample, audio_sink)
|
24
|
+
pipeline
|
25
|
+
end
|
26
|
+
|
27
|
+
def write_pipeline(pipeline, file)
|
28
|
+
Gst::XML.write_file(pipeline, file)
|
29
|
+
end
|
30
|
+
|
31
|
+
def read_pipeline(file)
|
32
|
+
xml = Gst::XML.new
|
33
|
+
xml.parse_file(file)
|
34
|
+
pipeline = xml.get_element(PIPELINE_NAME)
|
35
|
+
children = pipeline.children
|
36
|
+
source, decoder, audio_converter, audio_resample, audio_sink = children
|
37
|
+
source >> decoder
|
38
|
+
audio_converter >> audio_resample >> audio_sink
|
39
|
+
decoder.signal_connect("new-decoded-pad") do |element, pad|
|
40
|
+
sink_pad = audio_converter.get_pad("sink")
|
41
|
+
pad.link(sink_pad)
|
42
|
+
end
|
43
|
+
pipeline
|
44
|
+
end
|
45
|
+
|
46
|
+
def play_pipeline(pipeline)
|
47
|
+
pipeline.play
|
48
|
+
loop = GLib::MainLoop.new(nil, false)
|
49
|
+
begin
|
50
|
+
loop.run
|
51
|
+
rescue Interrupt
|
52
|
+
ensure
|
53
|
+
pipeline.stop
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
pipeline = build_pipeline(ARGV.first)
|
58
|
+
write_pipeline(pipeline, XML_FILE)
|
59
|
+
pipeline = read_pipeline(XML_FILE)
|
60
|
+
play_pipeline(pipeline)
|