class AviGlitch::Frames
Frames
provides the interface to access each frame in the AVI file. It is implemented as Enumerable. You can access this object through AviGlitch#frames, for example:
avi = AviGlitch.new '/path/to/your.avi' frames = avi.frames frames.each do |frame| ## frame is a reference of an AviGlitch::Frame object frame.data = frame.data.gsub(/\d/, '0') end
In the block passed into iteration method, the parameter is a reference of AviGlitch::Frame
object.
Attributes
Public Class Methods
Creates a new AviGlitch::Frames
object. It takes AviGlitch::Avi
as an argument.
# File lib/aviglitch/frames.rb, line 26 def initialize avi @avi = avi end
Public Instance Methods
Returns true if other
‘s frames are same as self’s frames.
# File lib/aviglitch/frames.rb, line 380 def == other @avi == other.avi end
Removes frame(s) at the given index or the range (same as []). Inserts the given Frame
or Frames’s contents into the removed index.
# File lib/aviglitch/frames.rb, line 192 def []= *args value = args.pop b, l = get_beginning_and_length *args ll = l.nil? ? 1 : l head = self.slice(0, b) rest = self.slice((b + ll)..-1) if l.nil? || value.kind_of?(Frame) head.push value elsif value.kind_of?(Frames) head.concat value else raise TypeError end new_frames = head + rest self.clear self.concat new_frames new_frames.terminate head.terminate rest.terminate end
Returns one Frame
object at the given index.
# File lib/aviglitch/frames.rb, line 217 def at n frame = nil @avi.process_movi do |indices, movi| m = indices[n] unless m.nil? movi.pos = m[:offset] + 8 frame = Frame.new(movi.read(m[:size]), m[:id], m[:flag]) movi.rewind end [indices, movi] end frame end
Removes all frames and returns self.
# File lib/aviglitch/frames.rb, line 90 def clear @avi.process_movi do |indices, movi| [[], StringIO.new] end self end
Appends the frames in the other Frames
into the tail of self. It is destructive like Array does.
# File lib/aviglitch/frames.rb, line 100 def concat other_frames raise TypeError unless other_frames.kind_of?(Frames) @avi.process_movi do |this_indices, this_movi| this_size = this_movi.size this_movi.pos = this_size other_frames.avi.process_movi do |other_indices, other_movi| while d = other_movi.read(BUFFER_SIZE) do this_movi.print d end other_meta = other_indices.collect do |m| x = m.dup x[:offset] += this_size x end this_indices.concat other_meta [other_indices, other_movi] end [this_indices, this_movi] end self end
Returns the data size of total frames.
# File lib/aviglitch/frames.rb, line 79 def data_size size = 0 @avi.process_movi do |indices, movi| size = movi.size [indices, movi] end size end
Deletes one Frame
at the given index.
# File lib/aviglitch/frames.rb, line 362 def delete_at n self.slice! n end
Enumerates the frames. It returns Enumerator if a block is not given.
# File lib/aviglitch/frames.rb, line 33 def each &block if block_given? Tempfile.open('aviglitch-temp', @avi.tmpdir, binmode: true) do |newmovi| @avi.process_movi do |indices, movi| newindices = indices.select do |m| movi.pos = m[:offset] + 8 # 8 for id and size frame = Frame.new(movi.read(m[:size]), m[:id], m[:flag]) block.call frame unless frame.data.nil? m[:offset] = newmovi.pos m[:size] = frame.data.size m[:flag] = frame.flag m[:id] = frame.id newmovi.print m[:id] newmovi.print [frame.data.size].pack('V') newmovi.print frame.data newmovi.print "\0" if frame.data.size % 2 == 1 true else false end end [newindices, newmovi] end end else self.enum_for :each end end
Returns the first Frame
object.
# File lib/aviglitch/frames.rb, line 233 def first self.slice(0) end
Returns the first Frame
object in frame_type
.
# File lib/aviglitch/frames.rb, line 245 def first_of frame_type frame = nil @avi.process_movi do |indices, movi| indices.each do |m| movi.pos = m[:offset] + 8 f = Frame.new(movi.read(m[:size]), m[:id], m[:flag]) if f.is?(frame_type) frame = f break end end [indices, movi] end frame end
Returns an index of the first found frame
.
# File lib/aviglitch/frames.rb, line 281 def index frame n = -1 @avi.process_movi do |indices, movi| indices.each_with_index do |m, i| movi.pos = m[:offset] + 8 f = Frame.new(movi.read(m[:size]), m[:id], m[:flag]) if f == frame n = i break end end [indices, movi] end n end
Inserts the given Frame
objects into the given index.
# File lib/aviglitch/frames.rb, line 347 def insert n, *args new_frames = self.slice(0, n) args.each do |f| new_frames.push f end new_frames.concat self.slice(n..-1) self.clear self.concat new_frames new_frames.terminate self end
Returns the last Frame
object.
# File lib/aviglitch/frames.rb, line 239 def last self.slice(self.size - 1) end
Returns the last Frame
object in frame_type
.
# File lib/aviglitch/frames.rb, line 263 def last_of frame_type frame = nil @avi.process_movi do |indices, movi| indices.reverse.each do |m| movi.pos = m[:offset] + 8 f = Frame.new(movi.read(m[:size]), m[:id], m[:flag]) if f.is?(frame_type) frame = f break end end [indices, movi] end frame end
Mutates keyframes into deltaframes at given range, or all.
# File lib/aviglitch/frames.rb, line 368 def mutate_keyframes_into_deltaframes! range = nil range = 0..self.size if range.nil? self.each_with_index do |frame, i| if range.include? i frame.flag = 0 if frame.is_keyframe? end end self end
Appends the given Frame
into the tail of self.
# File lib/aviglitch/frames.rb, line 321 def push frame raise TypeError unless frame.kind_of? Frame @avi.process_movi do |indices, movi| this_size = movi.size movi.pos = this_size movi.print frame.id movi.print [frame.data.size].pack('V') movi.print frame.data movi.print "\0" if frame.data.size % 2 == 1 indices << { :id => frame.id, :flag => frame.flag, :offset => this_size, :size => frame.data.size, } [indices, movi] end self end
Returns an index of the first found frame
, starting from the last.
# File lib/aviglitch/frames.rb, line 303 def rindex frame n = -1 @avi.process_movi do |indices, movi| indices.reverse.each_with_index do |m, i| movi.pos = m[:offset] + 8 f = Frame.new(movi.read(m[:size]), m[:id], m[:flag]) if f == frame n = indices.size - 1 - i break end end [indices, movi] end n end
Returns the number of frames.
# File lib/aviglitch/frames.rb, line 65 def size @avi.indices.size end
Returns the number of the specific frame_type
.
# File lib/aviglitch/frames.rb, line 71 def size_of frame_type @avi.indices.select { |m| Frame.new(nil, m[:id], m[:flag]).is? frame_type }.size end
Returns the Frame
object at the given index or returns new Frames
object that sliced with the given index and length or with the Range. Just like Array.
# File lib/aviglitch/frames.rb, line 149 def slice *args b, l = get_beginning_and_length *args if l.nil? self.at b else e = b + l - 1 r = self.to_avi r.frames.each_with_index do |f, i| unless i >= b && i <= e f.data = nil end end r.frames end end
Removes frame(s) at the given index or the range (same as slice). Returns the new Frames
contains removed frames.
# File lib/aviglitch/frames.rb, line 172 def slice! *args b, l = get_beginning_and_length *args head, sliced, tail = () sliced = l.nil? ? self.slice(b) : self.slice(b, l) head = self.slice(0, b) l = 1 if l.nil? tail = self.slice((b + l)..-1) self.clear temp = head + tail self.concat temp temp.terminate head.terminate tail.terminate sliced end
Closes the internal temp file explicitly. This instance becomes unusable.
# File lib/aviglitch/frames.rb, line 386 def terminate @avi.close @avi = nil end
Generates new AviGlitch::Base
instance using self.
# File lib/aviglitch/frames.rb, line 393 def to_avi AviGlitch::Base.new @avi.clone end