Class: Ogg::Decoder
- Inherits:
-
Object
- Object
- Ogg::Decoder
- Defined in:
- lib/ogg.rb
Overview
Ogg::Decoder is used to decode Ogg bitstreams. The easiest way of properly parsing an Ogg file is to read consecutive packets with the read_packet method. For example:
require 'ogg'
open("file.ogg", "rb") do |file|
dec = Ogg::Decoder.new(file)
packet = dec.read_packet
# Do something with the packet...
end
The terms “page” and “packet” have special meanings when dealing with Ogg. A packet is a section of data which is encoded in the Ogg container. A page is a section of the Ogg container used as a means of storing packets. Since packets are what contain the “juicy bits” of the file, Ogg::Decoder provides sufficient abstraction to make handling of individual pages unnecessary. However, if you do need to read pages, that functionality is available via the read_page method.
Instance Attribute Summary collapse
-
#verify_checksum ⇒ Object
This property determines whether the integrity of pages should be checked using CRCs (a lot slower but more robust).
Instance Method Summary collapse
-
#initialize(io, opts = {}) ⇒ Decoder
constructor
Create a new Decoder from an IO which should be open for binary reading.
-
#read_last_page ⇒ Object
Seek to and read the last page in the bitstream.
-
#read_packet ⇒ Object
Seek to and read the next packet in the bitstream.
-
#read_page ⇒ Object
Seek to and read the next page from the bitstream.
-
#seek_to_page(capture = 'OggS') ⇒ Object
Moves the file cursor forward to the next potential page.
Constructor Details
#initialize(io, opts = {}) ⇒ Decoder
Create a new Decoder from an IO which should be open for binary reading.
40 41 42 43 44 45 46 47 48 49 |
# File 'lib/ogg.rb', line 40 def initialize io, opts={} @io = io @packets = [] opts = { :verify_checksum => false, }.merge!(Hash[opts.map {|k, v| [k.to_s.downcase.to_sym, v]}]) @verify_checksum = opts[:verify_checksum] end |
Instance Attribute Details
#verify_checksum ⇒ Object
This property determines whether the integrity of pages should be checked using CRCs (a lot slower but more robust).
37 38 39 |
# File 'lib/ogg.rb', line 37 def verify_checksum @verify_checksum end |
Instance Method Details
#read_last_page ⇒ Object
Seek to and read the last page in the bitstream.
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 111 112 113 114 115 116 117 118 |
# File 'lib/ogg.rb', line 86 def read_last_page raise 'Last page can only be read from a file stream' unless @io.is_a? File buffer_size = 1024 pos = @io.stat.size - buffer_size while pos > 0 @io.seek pos, IO::SEEK_SET sio = StringIO.new @io.read(buffer_size) dec = Decoder.new(sio) sub_pos = nil # Find last page in buffer loop do begin sub_pos = dec.seek_to_page sio.pos += 1 rescue break end end if sub_pos @io.seek(pos + sub_pos, IO::SEEK_SET) page = read_page return page end pos -= buffer_size * 2 - ('OggS'.size - 1) end # This means that the Ogg file contains no pages raise MalformedFileError end |
#read_packet ⇒ Object
Seek to and read the next packet in the bitstream. Returns a string containing the packet’s binary data or nil if there are no packets left.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/ogg.rb', line 123 def read_packet return @packets.pop unless @packets.empty? while @packets.empty? page = read_page raise EOFError.new("End of file reached") if page.nil? input = StringIO.new(page.data) page.segment_table.each do |seg| @partial ||= "" @partial << input.read(seg) if seg != 255 @packets.insert(0, @partial) @partial = nil end end end return @packets.pop end |
#read_page ⇒ Object
Seek to and read the next page from the bitstream. Returns a Page or nil if there are no pages left.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/ogg.rb', line 70 def read_page page = nil while not @io.eof? begin seek_to_page page = Page.read @io page = nil if @verify_checksum and not page.correct_checksum? break rescue Exception => ex # False alarm, keep looking... end end return page end |
#seek_to_page(capture = 'OggS') ⇒ Object
Moves the file cursor forward to the next potential page. You probably wish to use the read_page method, which does some validation and actually returns the parsed page.
54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/ogg.rb', line 54 def seek_to_page(capture='OggS') buffer = @io.read(capture.size) page = nil while not @io.eof? if buffer == capture @io.pos -= capture.size return @io.pos end (buffer = buffer[1..-1] << @io.read(1)) rescue Exception end raise EOFError end |