flvtool2 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,120 @@
1
+ # Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions
6
+ # are met:
7
+ # 1. Redistributions of source code must retain the above copyright
8
+ # notice, this list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright
10
+ # notice, this list of conditions and the following disclaimer in the
11
+ # documentation and/or other materials provided with the distribution.
12
+ # 3. The name of the author may not be used to endorse or promote products
13
+ # derived from this software without specific prior written permission.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
+ # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
+ # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
+ # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
+ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ require 'flv/core_extensions'
27
+ require 'flv/stream'
28
+
29
+
30
+ module FLV
31
+
32
+ class FLVTag
33
+
34
+ AUDIO = 8
35
+ VIDEO = 9
36
+ META = 18
37
+ UNDEFINED = 0
38
+
39
+ attr_accessor :tag_type,
40
+ :timestamp,
41
+ :byte_offset
42
+
43
+ def initialize(stream = nil)
44
+ @tag_type = UNDEFINED
45
+ @byte_offset = nil
46
+
47
+ unless stream.nil?
48
+ data_size = stream.read__UI24
49
+ @timestamp = stream.read__UI24
50
+ stream.read__UI32
51
+ @data = stream.read(data_size)
52
+ else
53
+ @timestamp = 0
54
+ @data = ''
55
+ end
56
+ after_initialize(stream.nil?) if respond_to? :after_initialize
57
+ end
58
+
59
+ def size
60
+ # header(11) + body(data_size)
61
+ 11 + data_size
62
+ end
63
+
64
+ def name
65
+ 'Unknown Tag'
66
+ end
67
+
68
+ def data
69
+ @data
70
+ end
71
+
72
+ def data_size
73
+ data.length
74
+ end
75
+
76
+ def serialize(stream)
77
+ stream.write__UI8 tag_type
78
+ stream.write__UI24 data_size
79
+ stream.write__UI24 timestamp
80
+ stream.write__UI32 0
81
+ stream.write__STRING data
82
+ end
83
+
84
+ def info
85
+ "#{name}: timestamp #{timestamp}, size #{size}, data size #{data_size}"
86
+ end
87
+
88
+ def inspect
89
+ out = ["tag: #{self.class}"]
90
+ out << "timestamp: #{@timestamp}"
91
+ out << "size: #{size}"
92
+ out << "data_size: #{data_size}"
93
+ out
94
+ end
95
+
96
+ def self.type2name(type)
97
+ case type
98
+ when AUDIO
99
+ 'audio'
100
+ when VIDEO
101
+ 'video'
102
+ when META
103
+ 'meta'
104
+ when UNDEFINED
105
+ 'undefined'
106
+ else
107
+ "unknown(#{type})"
108
+ end
109
+ end
110
+
111
+ private
112
+ def bit2uint(sequence)
113
+ int = 0
114
+ sequence.split(//).each_with_index do |character, i|
115
+ int += 2 ** (sequence.length - i - 1) if character == '1'
116
+ end
117
+ int
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,114 @@
1
+ # Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions
6
+ # are met:
7
+ # 1. Redistributions of source code must retain the above copyright
8
+ # notice, this list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright
10
+ # notice, this list of conditions and the following disclaimer in the
11
+ # documentation and/or other materials provided with the distribution.
12
+ # 3. The name of the author may not be used to endorse or promote products
13
+ # derived from this software without specific prior written permission.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
+ # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
+ # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
+ # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
+ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ require 'flv/amf_string_buffer'
27
+
28
+ module FLV
29
+
30
+ class FLVVideoTag < FLVTag
31
+
32
+ H263VIDEOPACKET = 2
33
+ SCREENVIDEOPACKET = 3
34
+ ON2VP6 = 4
35
+
36
+ KEYFRAME = 1
37
+ INTERFRAME = 2
38
+ DISPOSABLEINTERFRAME = 3
39
+
40
+ attr_reader :frame_type,
41
+ :codec_id,
42
+ :width,
43
+ :height
44
+
45
+ def after_initialize(new_object)
46
+ @tag_type = VIDEO
47
+ read_header
48
+ end
49
+
50
+ def name
51
+ case frame_type
52
+ when KEYFRAME
53
+ 'Video Tag (Keyframe)'
54
+ when INTERFRAME
55
+ 'Video Tag (Interframe)'
56
+ when DISPOSABLEINTERFRAME
57
+ 'Video Tag (disposable Interframe)'
58
+ else
59
+ 'Video Tag'
60
+ end
61
+ end
62
+
63
+ def keyframe?
64
+ frame_type == KEYFRAME
65
+ end
66
+
67
+ def interframe?
68
+ frame_type == INTERFRAME || frame_type == DISPOSABLEINTERFRAME
69
+ end
70
+
71
+ def read_header
72
+ data_stream = AMFStringBuffer.new(@data)
73
+
74
+ # the sequence is swaped in the swf-file-format description
75
+ # frame_type <-> codec_id (description: 1. codec_id, 2. frame_type)
76
+ codec_id_and_frame_type = data_stream.read__UI8
77
+ @frame_type = codec_id_and_frame_type >> 4
78
+ @codec_id = codec_id_and_frame_type & 0xf
79
+
80
+ bit_sequence = data_stream.read(9).unpack('B72').to_s
81
+
82
+ if @codec_id == H263VIDEOPACKET
83
+ @width, @height = case bit2uint bit_sequence[30,3]
84
+ when 0
85
+ [bit2uint(bit_sequence[33,8]), bit2uint(bit_sequence[41,8])]
86
+ when 1
87
+ [bit2uint(bit_sequence[33,16]), bit2uint(bit_sequence[49,16])]
88
+ when 2
89
+ [352, 288]
90
+ when 3
91
+ [176, 144]
92
+ when 4
93
+ [128, 96]
94
+ when 5
95
+ [320, 240]
96
+ when 6
97
+ [160, 120]
98
+ end
99
+ elsif @codec_id == SCREENVIDEOPACKET
100
+ @width, @height = bit2uint(bit_sequence[4,12]), bit2uint(bit_sequence[16,12])
101
+ end
102
+ end
103
+
104
+ def inspect
105
+ out = super
106
+ out << "frame_type: #{%w{ Keyframe Interframe DisposableInterframe }[@frame_type]}"
107
+ out << "codec_id: #{@codec_id}"
108
+ out << "width: #{@width}"
109
+ out << "height: #{@height}"
110
+ out << "data_size: #{data_size}"
111
+ out
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,230 @@
1
+ # Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions
6
+ # are met:
7
+ # 1. Redistributions of source code must retain the above copyright
8
+ # notice, this list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright
10
+ # notice, this list of conditions and the following disclaimer in the
11
+ # documentation and/or other materials provided with the distribution.
12
+ # 3. The name of the author may not be used to endorse or promote products
13
+ # derived from this software without specific prior written permission.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
+ # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
+ # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
+ # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
+ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ require 'flvtool2/version'
27
+ require 'flvtool2/base'
28
+
29
+ module FLVTool2
30
+
31
+ SHELL_COMMAND_NAME = (RUBY_PLATFORM =~ /win32/) ? 'flvtool2.exe' : 'flvtool2'
32
+ SWITCHES = %w{ s v r p x c i o k t n l a }
33
+ COMMANDS = %w{ U C P D A V }
34
+
35
+ def self.parse_arguments
36
+ options = {}
37
+ options[:commands] = []
38
+ options[:metadatacreator] = "inlet media FLVTool2 v#{PROGRAMM_VERSION.join('.')} - http://www.inlet-media.de/flvtool2"
39
+ options[:metadata] = {}
40
+ options[:in_path] = nil
41
+ options[:in_pipe] = false
42
+ options[:out_path] = nil
43
+ options[:out_pipe] = false
44
+ options[:simulate] = false
45
+ options[:verbose] = false
46
+ options[:recursive] = false
47
+ options[:preserve] = false
48
+ options[:xml] = false
49
+ options[:compatibility_mode] = false
50
+ options[:in_point] = nil
51
+ options[:out_point] = nil
52
+ options[:keyframe_mode] = false
53
+ options[:tag_file] = nil
54
+ options[:tag_number] = nil
55
+ options[:stream_log] = false
56
+ options[:collapse] = false
57
+
58
+ while (arg = ARGV.shift)
59
+ case arg
60
+ when /^-([a-zA-Z0-9]+?):(.+)$/
61
+ options[:metadata][$1] = $2
62
+ when /^-([a-zA-Z0-9]+?)#([0-9]+)$/
63
+ options[:metadata][$1] = $2.to_f
64
+ when /^-([a-zA-Z0-9]+?)@(\d{4,})-(\d{2,})-(\d{2,}) (\d{2,}):(\d{2,}):(\d{2,})$/
65
+ options[:metadata][$1] = Time.local($2, $3, $4, $5, $6, $7)
66
+ when /^-(.+)$/
67
+ $1.split(//).flatten.each do |switch|
68
+ case switch
69
+ when 's'
70
+ options[:simulate] = true
71
+ when 'v'
72
+ options[:verbose] = true
73
+ when 'r'
74
+ options[:recursive] = true
75
+ when 'p'
76
+ options[:preserve] = true
77
+ when 'x'
78
+ options[:xml] = true
79
+ when 'c'
80
+ options[:compatibility_mode] = true
81
+ when 'i'
82
+ options[:in_point] = ARGV.shift.to_i
83
+ when 'o'
84
+ options[:out_point] = ARGV.shift.to_i
85
+ when 'k'
86
+ options[:keyframe_mode] = true
87
+ when 't'
88
+ options[:tag_file] = ARGV.shift
89
+ when 'n'
90
+ options[:tag_number] = ARGV.shift.to_i
91
+ when 'l'
92
+ options[:stream_log] = true
93
+ when 'a'
94
+ options[:collapse] = true
95
+ when 'U'
96
+ options[:commands] << :update
97
+ when 'P'
98
+ options[:commands] << :print
99
+ when 'C'
100
+ options[:commands] << :cut
101
+ when 'D'
102
+ options[:commands] << :debug
103
+ when 'A'
104
+ options[:commands] << :add
105
+ when 'H'
106
+ options[:commands] << :help
107
+ when 'V'
108
+ options[:commands] << :version
109
+ end
110
+ end
111
+ when /^([^-].*)$/
112
+ if options[:in_path].nil?
113
+ options[:in_path] = $1
114
+ if options[:in_path].downcase =~ /stdin|pipe/
115
+ options[:in_pipe] = true
116
+ options[:in_path] = 'pipe'
117
+ else
118
+ options[:in_path] = File.expand_path( options[:in_path] )
119
+ end
120
+ else
121
+ options[:out_path] = $1
122
+ if options[:out_path].downcase =~ /stdout|pipe/
123
+ options[:out_pipe] = true
124
+ options[:out_path] = 'pipe'
125
+ else
126
+ options[:out_path] = File.expand_path( options[:out_path] )
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ return options
133
+ end
134
+
135
+ def self.validate_options( options )
136
+ if options[:commands].empty?
137
+ show_usage
138
+ exit 0
139
+ end
140
+
141
+ options[:commands].each do |command|
142
+ case command
143
+ when :print
144
+ if options[:out_pipe]
145
+ throw_error "Could not use print command in conjunction with output piping or redirection"
146
+ exit 1
147
+ end
148
+ when :debug
149
+ if options[:out_pipe]
150
+ throw_error "Could not use debug command in conjunction with output piping or redirection"
151
+ exit 1
152
+ end
153
+ when :help
154
+ show_usage
155
+ exit 0
156
+ when :version
157
+ show_version
158
+ exit 0
159
+ end
160
+ end
161
+ options
162
+ end
163
+
164
+ def self.execute!(options)
165
+ if options[:commands].include? :help
166
+ show_usage
167
+ else
168
+ FLVTool2::Base::execute!( options )
169
+ end
170
+ end
171
+
172
+ def self.show_version
173
+ puts "FLVTool2 #{version}"
174
+ end
175
+
176
+ def self.show_usage
177
+ self.show_version
178
+ puts "Copyright (c) 2005-2007 Norman Timmler (inlet media e.K., Hamburg, Germany)\n"
179
+ puts "Get the latest version from http://www.inlet-media.de/flvtool2\n"
180
+ puts "This program is published under the BSD license.\n"
181
+ puts "\n"
182
+ puts "Usage: #{SHELL_COMMAND_NAME} [-#{COMMANDS.sort.join}#{SWITCHES.sort.join}]... [-key:value]... in-path|stdin [out-path|stdout]\n"
183
+ puts "\n"
184
+ puts "If out-path is omitted, in-path will be overwritten.\n"
185
+ puts "In-path can be a single file, or a directory. If in-path is a directory,\n"
186
+ puts "out-path has to be likewise, or can be omitted. Directory recursion\n"
187
+ puts "is controlled by the -r switch. You can use stdin and stdout keywords\n"
188
+ puts "as in- and out-path for piping or redirecting.\n"
189
+ puts "\n"
190
+ puts "Chain commands like that: -UP (updates FLV file than prints out meta data)\n"
191
+ puts "\n"
192
+ puts "Commands:\n"
193
+ puts " -A Adds tags from -t tags-file\n"
194
+ puts " -C Cuts file using -i inpoint and -o outpoint\n"
195
+ puts " -D Debugs file (writes a lot to stdout)\n"
196
+ puts " -H Helpscreen will be shown\n"
197
+ puts " -P Prints out meta data to stdout\n"
198
+ puts " -U Updates FLV with an onMetaTag event\n"
199
+ puts "\n"
200
+ puts "Switches:\n"
201
+ puts " -a Collapse space between cutted regions\n"
202
+ puts " -c Compatibility mode calculates some onMetaTag values different\n"
203
+ puts " -key:value Key-value-pair for onMetaData tag (overwrites generated values)\n"
204
+ puts " -i timestamp Inpoint for cut command in miliseconds\n"
205
+ puts " -k Keyframe mode slides onCuePoint(navigation) tags added by the\n"
206
+ puts " add command to nearest keyframe position\n"
207
+ puts " -l Logs FLV stream reading to stream.log in current directory\n"
208
+ puts " -n Number of tag to debug\n"
209
+ puts " -o timestamp Outpoint for cut command in miliseconds\n"
210
+ puts " -p Preserve mode only updates FLVs that have not been processed\n"
211
+ puts " before\n"
212
+ puts " -r Recursion for directory processing\n"
213
+ puts " -s Simulation mode never writes FLV data to out-path\n"
214
+ puts " -t path Tagfile (MetaTags written in XML)\n"
215
+ puts " -v Verbose mode\n"
216
+ puts " -x XML mode instead of YAML mode\n"
217
+ puts "\n"
218
+ puts "REPORT BUGS at http://projects.inlet-media.de/flvtool2"
219
+ puts "Powered by Riva VX, http://rivavx.com\n"
220
+ end
221
+
222
+ def self.throw_error(error)
223
+ puts "ERROR: #{error}"
224
+ end
225
+ end
226
+
227
+
228
+ FLVTool2::execute!( FLVTool2::validate_options( FLVTool2::parse_arguments ) )
229
+ exit 0
230
+