Class: FLV::FLVStream
- Inherits:
-
Object
- Object
- FLV::FLVStream
- Defined in:
- lib/flv/stream.rb
Instance Attribute Summary collapse
-
#signatur ⇒ Object
Returns the value of attribute signatur.
-
#stream_log ⇒ Object
Returns the value of attribute stream_log.
-
#tags ⇒ Object
Returns the value of attribute tags.
-
#type_flags_audio ⇒ Object
Returns the value of attribute type_flags_audio.
-
#type_flags_video ⇒ Object
Returns the value of attribute type_flags_video.
-
#version ⇒ Object
Returns the value of attribute version.
Instance Method Summary collapse
- #<<(tags) ⇒ Object
- #add_meta_tag(meta_data = {}) ⇒ Object
-
#add_tags(tags, stick_on_framerate = true, overwrite = true) ⇒ Object
general.
- #audio_tags ⇒ Object
- #audiocodecid ⇒ Object
- #audiodatarate ⇒ Object
- #audiodelay ⇒ Object
- #audiosamplerate ⇒ Object
- #audiosamplesize ⇒ Object
- #audiosize ⇒ Object
- #canSeekToEnd ⇒ Object
- #close ⇒ Object
- #cue_points ⇒ Object
- #cut(options = []) ⇒ Object
- #datasize ⇒ Object
- #duration ⇒ Object
-
#empty_tag_type_cache ⇒ Object
views on tags.
- #filesize ⇒ Object
- #find_nearest_keyframe_video_tag(position) ⇒ Object
-
#frame_sequence ⇒ Object
FIXME: Could be less complicate and run faster.
- #framerate ⇒ Object
- #has_audio? ⇒ Boolean
- #has_cue_points? ⇒ Boolean
- #has_keyframes? ⇒ Boolean
- #has_meta_data? ⇒ Boolean
- #has_video? ⇒ Boolean
- #height ⇒ Object
-
#initialize(in_stream, out_stream = nil, stream_log = false) ⇒ FLVStream
constructor
A new instance of FLVStream.
- #keyframe_video_tags ⇒ Object
- #keyframes ⇒ Object
- #lastkeyframetimestamp ⇒ Object
- #lasttimestamp ⇒ Object
- #meta_tags ⇒ Object
- #on_cue_point_tags ⇒ Object
- #on_meta_data_tag ⇒ Object
- #stereo ⇒ Object
- #video_tags ⇒ Object
- #videocodecid ⇒ Object
- #videodatarate ⇒ Object
- #videosize ⇒ Object
- #width ⇒ Object
- #write ⇒ Object
Constructor Details
#initialize(in_stream, out_stream = nil, stream_log = false) ⇒ FLVStream
Returns a new instance of FLVStream.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/flv/stream.rb', line 48 def initialize(in_stream, out_stream = nil, stream_log = false) @stream_log = stream_log ? (File.open('stream.log', File::CREAT|File::WRONLY|File::TRUNC) rescue AMFStringBuffer.new) : AMFStringBuffer.new @in_stream = in_stream @out_stream = out_stream || in_stream unless eof? begin read_header rescue Object => e log e raise e ensure @stream_log.close end else @version = 1 @type_flags_audio = false @type_flags_video = false @extra_data = '' @tags = [] end end |
Instance Attribute Details
#signatur ⇒ Object
Returns the value of attribute signatur.
41 42 43 |
# File 'lib/flv/stream.rb', line 41 def signatur @signatur end |
#stream_log ⇒ Object
Returns the value of attribute stream_log.
41 42 43 |
# File 'lib/flv/stream.rb', line 41 def stream_log @stream_log end |
#tags ⇒ Object
Returns the value of attribute tags.
41 42 43 |
# File 'lib/flv/stream.rb', line 41 def @tags end |
#type_flags_audio ⇒ Object
Returns the value of attribute type_flags_audio.
41 42 43 |
# File 'lib/flv/stream.rb', line 41 def type_flags_audio @type_flags_audio end |
#type_flags_video ⇒ Object
Returns the value of attribute type_flags_video.
41 42 43 |
# File 'lib/flv/stream.rb', line 41 def type_flags_video @type_flags_video end |
#version ⇒ Object
Returns the value of attribute version.
41 42 43 |
# File 'lib/flv/stream.rb', line 41 def version @version end |
Instance Method Details
#<<(tags) ⇒ Object
380 381 382 |
# File 'lib/flv/stream.rb', line 380 def <<() , true end |
#add_meta_tag(meta_data = {}) ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/flv/stream.rb', line 127 def ( = {}) = FLVMetaTag.new .event = 'onMetaData' ['framerate'] = framerate ['duration'] = duration ['lasttimestamp'] = ['videosize'] = videosize ['audiosize'] = audiosize ['datasize'] = 0 # calculate after tag was added ['filesize'] = 0 # calculate after tag was added ['width'] = (width == 0 && ) ? .['width'] : width ['height'] = (height == 0 && ) ? .['height'] : height ['videodatarate'] = videodatarate ['audiodatarate'] = audiodatarate ['lastkeyframetimestamp'] = ['audiocodecid'] = audiocodecid ['videocodecid'] = videocodecid ['audiodelay'] = audiodelay ['canSeekToEnd'] = canSeekToEnd ['stereo'] = stereo ['audiosamplerate'] = audiosamplerate ['audiosamplesize'] = audiosamplesize ['cuePoints'] = cue_points ['keyframes'] = keyframes ['hasVideo'] = has_video? ['hasAudio'] = has_audio? ['hasMetadata'] = true ['hasCuePoints'] = has_cue_points? ['hasKeyframes'] = has_keyframes? ..merge!() () # recalculate values those need meta tag data size or presence ['keyframes'] = keyframes ['datasize'] = datasize ['filesize'] = filesize ['hasMetadata'] = end |
#add_tags(tags, stick_on_framerate = true, overwrite = true) ⇒ Object
general
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/flv/stream.rb', line 76 def (, stick_on_framerate = true, overwrite = true) = [] unless .kind_of? Array .each do |tag| # FIXME: Does not really work for video or audio tags, because tags are # inserted next to same kind. Normally audio and video tags are # alternating. if stick_on_framerate && !framerate.nil? &&framerate != 0 && tag. % (1000 / framerate) != 0 raise FLVTagError, "Could not insert tag. Timestamp #{tag.} does not fit into framerate." next end after_tag = @tags.detect { |_tag| _tag. >= tag. } if after_tag.nil? @tags << tag next end if tag. == after_tag. && tag.class == after_tag.class if tag.kind_of?(FLVMetaTag) && ( ( tag.event != after_tag.event ) || ( tag.event == after_tag.event && !overwrite ) ) @tags.insert( @tags.index(after_tag), tag ) else @tags[@tags.index(after_tag)] = tag end else @tags.insert( @tags.index(after_tag), tag ) end empty_tag_type_cache end @tags end |
#audio_tags ⇒ Object
211 212 213 |
# File 'lib/flv/stream.rb', line 211 def @audio_tags_cache ||= @tags.find_all { |tag| tag.kind_of? FLVAudioTag } end |
#audiocodecid ⇒ Object
346 347 348 |
# File 'lib/flv/stream.rb', line 346 def audiocodecid .first && .first.sound_format end |
#audiodatarate ⇒ Object
327 328 329 330 331 332 |
# File 'lib/flv/stream.rb', line 327 def audiodatarate data_size = .inject(0) do |size, tag| size += tag.data_size end return data_size == 0 ? 0 : data_size / duration * 8 / 1000 # kBits/sec end |
#audiodelay ⇒ Object
355 356 357 358 |
# File 'lib/flv/stream.rb', line 355 def audiodelay return 0 unless has_video? .first..nil? ? 0 : .first. / 1000.0 end |
#audiosamplerate ⇒ Object
338 339 340 |
# File 'lib/flv/stream.rb', line 338 def audiosamplerate .first && .first.sound_rate end |
#audiosamplesize ⇒ Object
342 343 344 |
# File 'lib/flv/stream.rb', line 342 def audiosamplesize .first && .first.sound_sample_size end |
#audiosize ⇒ Object
297 298 299 |
# File 'lib/flv/stream.rb', line 297 def audiosize .inject(0) { |size, tag| size += tag.size } end |
#canSeekToEnd ⇒ Object
360 361 362 363 |
# File 'lib/flv/stream.rb', line 360 def canSeekToEnd return true unless has_video? .last.frame_type == FLVVideoTag::KEYFRAME end |
#close ⇒ Object
185 186 187 188 |
# File 'lib/flv/stream.rb', line 185 def close @in_stream.close @out_stream.close end |
#cue_points ⇒ Object
376 377 378 |
# File 'lib/flv/stream.rb', line 376 def cue_points .collect { |tag| tag. } end |
#cut(options = []) ⇒ Object
112 113 114 115 116 117 118 119 |
# File 'lib/flv/stream.rb', line 112 def cut( = []) @tags.delete_if { |tag| tag. < ( [:in_point] || 0 ) || tag. > ( [:out_point] || .last. ) } if [:collapse] difference = @tags.first. @tags.each { |tag| tag. -= difference } end empty_tag_type_cache end |
#datasize ⇒ Object
301 302 303 |
# File 'lib/flv/stream.rb', line 301 def datasize videosize + audiosize + (.inject(0) { |size, tag| size += tag.size}) end |
#duration ⇒ Object
273 274 275 |
# File 'lib/flv/stream.rb', line 273 def duration end |
#empty_tag_type_cache ⇒ Object
views on tags
193 194 195 196 197 198 199 |
# File 'lib/flv/stream.rb', line 193 def empty_tag_type_cache @video_tags_cache = nil @keyframe_video_tags_cache = nil @audio_tags_cache = nil @meta_tags_cache = nil @on_cue_point_tags_cache = nil end |
#filesize ⇒ Object
305 306 307 308 |
# File 'lib/flv/stream.rb', line 305 def filesize # header + data + backpointers @data_offset + datasize + ((@tags.length + 1) * 4) end |
#find_nearest_keyframe_video_tag(position) ⇒ Object
121 122 123 124 125 |
# File 'lib/flv/stream.rb', line 121 def find_nearest_keyframe_video_tag(position) .sort do |tag_a, tag_b| (position - tag_a.).abs <=> (position - tag_b.).abs end.first end |
#frame_sequence ⇒ Object
FIXME: Could be less complicate and run faster
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/flv/stream.rb', line 250 def frame_sequence return nil unless has_video? raise(FLVStreamError, 'File has to contain at least 2 video tags to calculate frame sequence') if .length < 2 @frame_sequence ||= begin sequences = .collect do |tag| # find all sequences [.index(tag) + 1]. - tag. unless tag == .last end.compact uniq_sequences = (sequences.uniq - [0]).sort # remove 0 and try smallest intervall first sequence_appearances = uniq_sequences.collect { |sequence| sequences.find_all { |_sequence| sequence == _sequence }.size } # count apperance of each sequence uniq_sequences[ sequence_appearances.index( sequence_appearances.max ) ] # return the sequence that appears most end end |
#framerate ⇒ Object
268 269 270 271 |
# File 'lib/flv/stream.rb', line 268 def framerate return nil unless has_video? frame_sequence == 0 ? 0 : 1000 / frame_sequence end |
#has_audio? ⇒ Boolean
231 232 233 |
# File 'lib/flv/stream.rb', line 231 def has_audio? .size > 0 end |
#has_cue_points? ⇒ Boolean
239 240 241 |
# File 'lib/flv/stream.rb', line 239 def has_cue_points? .size > 0 end |
#has_keyframes? ⇒ Boolean
243 244 245 |
# File 'lib/flv/stream.rb', line 243 def has_keyframes? .size > 0 end |
#has_meta_data? ⇒ Boolean
235 236 237 |
# File 'lib/flv/stream.rb', line 235 def !.nil? end |
#has_video? ⇒ Boolean
227 228 229 |
# File 'lib/flv/stream.rb', line 227 def has_video? .size > 0 end |
#height ⇒ Object
315 316 317 318 |
# File 'lib/flv/stream.rb', line 315 def height return nil unless has_video? .first.height || 0 end |
#keyframe_video_tags ⇒ Object
205 206 207 208 209 |
# File 'lib/flv/stream.rb', line 205 def @keyframe_video_tags_cache ||= @tags.find_all do |tag| tag.kind_of?(FLVVideoTag) && tag.frame_type == FLVVideoTag::KEYFRAME end end |
#keyframes ⇒ Object
365 366 367 368 369 370 371 372 373 374 |
# File 'lib/flv/stream.rb', line 365 def keyframes object = Object.new calculate_tag_byte_offsets object.instance_variable_set( :@times, .collect { |video_tag| video_tag. / 1000.0 } ) object.instance_variable_set( :@filepositions, .collect { |video_tag| video_tag.byte_offset } ) return object end |
#lastkeyframetimestamp ⇒ Object
288 289 290 291 |
# File 'lib/flv/stream.rb', line 288 def return nil unless has_video? (.last.nil? || .last..nil?) ? 0 : .last. / 1000.0 end |
#lasttimestamp ⇒ Object
277 278 279 280 281 282 283 284 285 286 |
# File 'lib/flv/stream.rb', line 277 def last_tag = if has_video? .last elsif has_audio? .last else .last end last_tag..nil? ? 0 : last_tag. / 1000.0 end |
#meta_tags ⇒ Object
215 216 217 |
# File 'lib/flv/stream.rb', line 215 def @meta_tags_cache ||= @tags.find_all { |tag| tag.kind_of? FLVMetaTag } end |
#on_cue_point_tags ⇒ Object
223 224 225 |
# File 'lib/flv/stream.rb', line 223 def @on_cue_point_tags_cache ||= @tags.find_all { |tag| tag.kind_of?(FLVMetaTag) && tag.event == 'onCuePoint' } # FIXME: Cannot be cached end |
#on_meta_data_tag ⇒ Object
219 220 221 |
# File 'lib/flv/stream.rb', line 219 def @tags.find { |tag| tag.kind_of?(FLVMetaTag) && tag.event == 'onMetaData' } # FIXME: Cannot be cached end |
#stereo ⇒ Object
334 335 336 |
# File 'lib/flv/stream.rb', line 334 def stereo .first && .first.sound_type == FLVAudioTag::STEREO end |
#video_tags ⇒ Object
201 202 203 |
# File 'lib/flv/stream.rb', line 201 def @video_tags_cache ||= @tags.find_all { |tag| tag.kind_of? FLVVideoTag } end |
#videocodecid ⇒ Object
350 351 352 353 |
# File 'lib/flv/stream.rb', line 350 def videocodecid return nil unless has_video? .first.codec_id end |
#videodatarate ⇒ Object
320 321 322 323 324 325 |
# File 'lib/flv/stream.rb', line 320 def videodatarate data_size = .inject(0) do |size, tag| size += tag.data_size end return data_size == 0 ? 0 : data_size / duration * 8 / 1000 # kBits/sec end |
#videosize ⇒ Object
293 294 295 |
# File 'lib/flv/stream.rb', line 293 def videosize .inject(0) { |size, tag| size += tag.size } end |
#width ⇒ Object
310 311 312 313 |
# File 'lib/flv/stream.rb', line 310 def width return nil unless has_video? .first.width || 0 end |
#write ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/flv/stream.rb', line 169 def write begin @out_stream.seek( 0 ) rescue Object => e end write_header begin @out_stream.truncate( @out_stream.pos ) rescue Object => e end end |