Class: FilesHunter::Decoders::RIFF
- Inherits:
-
BeginPatternDecoder
- Object
- FilesHunter::Decoder
- BeginPatternDecoder
- FilesHunter::Decoders::RIFF
- Defined in:
- lib/fileshunter/Decoders/RIFF.rb
Overview
WAV files can contain MP3 files
Constant Summary collapse
- BEGIN_PATTERN_RIFF =
'RIFF'
- BEGIN_PATTERN_RIFX =
'RIFX'
- BEGIN_PATTERN_JUNK =
'JUNK'
- BEGIN_PATTERN_FILE =
Regexp.new("RIF(F|X)", nil, 'n')
- INFO_ELEMENTS_ID =
INFO elements
{ 'AGES' => :Rated, 'CMNT' => :Comment, 'CODE' => :EncodedBy, 'COMM' => :Comments, 'DIRC' => :Directory, 'DISP' => :SoundSchemeTitle, 'DTIM' => :DateTimeOriginal, 'GENR' => :Genre, 'IARL' => :ArchivalLocation, 'IART' => :Artist, 'IAS1' => :FirstLanguage, 'IAS2' => :SecondLanguage, 'IAS3' => :ThirdLanguage, 'IAS4' => :FourthLanguage, 'IAS5' => :FifthLanguage, 'IAS6' => :SixthLanguage, 'IAS7' => :SeventhLanguage, 'IAS8' => :EighthLanguage, 'IAS9' => :NinthLanguage, 'IBSU' => :BaseURL, 'ICAS' => :DefaultAudioStream, 'ICDS' => :CostumeDesigner, 'ICMS' => :Commissioned, 'ICMT' => :Comment, 'ICNM' => :Cinematographer, 'ICNT' => :Country, 'ICOP' => :Copyright, 'ICRD' => :DateCreated, 'ICRP' => :Cropped, 'IDIM' => :Dimensions, 'IDPI' => :DotsPerInch, 'IDST' => :DistributedBy, 'IEDT' => :EditedBy, 'IENC' => :EncodedBy, 'IENG' => :Engineer, 'IGNR' => :Genre, 'IKEY' => :Keywords, 'ILGT' => :Lightness, 'ILGU' => :LogoURL, 'ILIU' => :LogoIconURL, 'ILNG' => :Language, 'IMBI' => :MoreInfoBannerImage, 'IMBU' => :MoreInfoBannerURL, 'IMED' => :Medium, 'IMIT' => :MoreInfoText, 'IMIU' => :MoreInfoURL, 'IMUS' => :MusicBy, 'INAM' => :Title, 'IPDS' => :ProductionDesigner, 'IPLT' => :NumColors, 'IPRD' => :Product, 'IPRO' => :ProducedBy, 'IRIP' => :RippedBy, 'IRTD' => :Rating, 'ISBJ' => :Subject, 'ISFT' => :Software, 'ISGN' => :SecondaryGenre, 'ISHP' => :Sharpness, 'ISRC' => :Source, 'ISRF' => :SourceForm, 'ISTD' => :ProductionStudio, 'ISTR' => :Starring, 'ITCH' => :Technician, 'IWMU' => :WatermarkURL, 'IWRI' => :WrittenBy, 'LANG' => :Language, 'LOCA' => :Location, 'PRT1' => :Part, 'PRT2' => :NumberOfParts, 'RATE' => :Rate, 'STAR' => :Starring, 'STAT' => :Statistics, 'TAPE' => :TapeName, 'TCDO' => :EndTimecode, 'TCOD' => :StartTimecode, 'TITL' => :Title, 'TLEN' => :Length, 'TORG' => :Organization, 'TRCK' => :TrackNumber, 'TURL' => :URL, 'TVER' => :Version, 'VMAJ' => :VegasVersionMajor, 'VMIN' => :VegasVersionMinor, 'YEAR' => :Year, # Exif tags 'ecor' => :Make, 'emdl' => :Model, 'emnt' => :MakerNotes, 'erel' => :RelatedImageFile, 'etim' => :TimeCreated, 'eucm' => :UserComment, 'ever' => :ExifVersion }
- ELEMENT_ID_WAVE =
Wave elements
'WAVE'
- ELEMENT_ID_FORMAT =
'fmt '
- ELEMENT_ID_DATA =
'data'
- ELEMENT_ID_FACT =
'fact'
- ELEMENT_ID_AVI =
AVI elements
'AVI '
- ELEMENT_ID_STRH =
'strh'
- ELEMENT_ID_STRF =
'strf'
- ELEMENT_ID_MOVI =
'movi'
- ELEMENT_ID_IDX1 =
'idx1'
- ELEMENT_ID_DMLH =
'dmlh'
- ELEMENT_ID_IDIT =
'IDIT'
- HDLR_ELEMENTS =
{ ELEMENT_ID_IDIT => nil, 'ISMP' => nil, 'avih' => nil }
- STREAM_ELEMENTS =
{ 'strd' => nil, 'strf' => nil, 'strh' => nil, 'strn' => nil, 'indx' => nil }
- ODML_IDX_ELEMENTS =
{}
- ELEMENT_ID_ANI =
ANI elements
'ACON'
- ELEMENT_ID_ANIH =
'anih'
- ELEMENT_ID_ICON =
'icon'
- ELEMENT_ID_SEQ =
'seq '
- ELEMENT_ID_RATE =
'rate'
- RIFF_INFO_ELEMENTS =
{}
- ELEMENT_ID_LIST =
'LIST'
- RIFF_GENERIC_ELEMENTS =
{ BEGIN_PATTERN_JUNK => nil, ELEMENT_ID_LIST => { 'INFO' => RIFF_INFO_ELEMENTS, # AVI elements 'hdrl' => HDLR_ELEMENTS, 'strl' => STREAM_ELEMENTS, ELEMENT_ID_MOVI => nil, 'ncdt' => { :element_info => { :ignore_unknown_elements => true } }, 'odml' => { ELEMENT_ID_DMLH => nil }, # ANI elements 'fram' => { ELEMENT_ID_ICON => nil } }.merge(ODML_IDX_ELEMENTS) }
- RIFF_ROOT_ELEMENTS =
{ # Wave elements ELEMENT_ID_WAVE => { ELEMENT_ID_FORMAT => nil, ELEMENT_ID_DATA => nil, ELEMENT_ID_FACT => nil }, # AVI elements ELEMENT_ID_AVI => nil, ELEMENT_ID_IDX1 => nil, # ANI elements ELEMENT_ID_ANI => { ELEMENT_ID_ANIH => nil, ELEMENT_ID_SEQ => nil, ELEMENT_ID_RATE => nil } }
- RIFF_ELEMENTS =
{ BEGIN_PATTERN_RIFF => RIFF_ROOT_ELEMENTS, BEGIN_PATTERN_RIFX => RIFF_ROOT_ELEMENTS }
- RIFF_ELEMENTS_WITH_SIZE =
[ BEGIN_PATTERN_RIFF, BEGIN_PATTERN_RIFX, BEGIN_PATTERN_JUNK, ELEMENT_ID_LIST, # WAVE elements ELEMENT_ID_FORMAT, ELEMENT_ID_DATA, ELEMENT_ID_FACT, # AVI elements ELEMENT_ID_IDX1, ELEMENT_ID_DMLH, # ANI elements ELEMENT_ID_ANIH, ELEMENT_ID_ICON, ELEMENT_ID_SEQ, ELEMENT_ID_RATE ] + RIFF_INFO_ELEMENTS.keys + HDLR_ELEMENTS.keys + STREAM_ELEMENTS.keys + ODML_IDX_ELEMENTS.keys
- AVI_STREAM_TYPES =
[ 'db', 'dc', 'pc', 'wb' ]
- TRAILING_00_REGEXP =
Regexp.new("\x00*$".force_encoding(Encoding::ASCII_8BIT), nil, 'n')
Instance Method Summary collapse
Methods inherited from BeginPatternDecoder
Methods inherited from FilesHunter::Decoder
Instance Method Details
#decode(offset) ⇒ Object
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/fileshunter/Decoders/RIFF.rb', line 231 def decode(offset) ending_offset = nil # Check endianness name = @data[offset..offset+3] @bindata_16 = BinData::Uint16le @bindata_32 = BinData::Uint32le if (name == BEGIN_PATTERN_RIFX) @bindata_16 = BinData::Uint16be @bindata_32 = BinData::Uint32be end # Parse RIFF found_RIFF = false found_WAVE_data = false found_AVI_data = false extension = nil cursor, nbr_elements = parse_riff_element(offset, RIFF_ELEMENTS) do |element_hierarchy, element_cursor, size, container_end_offset| element_name = element_hierarchy[-1] if ((element_name == BEGIN_PATTERN_RIFF) or (element_name == BEGIN_PATTERN_RIFX)) # Check we are not getting on a second RIFF file if found_RIFF ending_offset = element_cursor - 8 next nil end found_RIFF = true elsif (INFO_ELEMENTS_ID[element_name] != nil) # Standard info ( INFO_ELEMENTS_ID[element_name] => read_ascii(element_cursor, size) ) else # Special cases case element_name # Wave elements when ELEMENT_ID_WAVE extension = :wav found_relevant_data(extension) when ELEMENT_ID_FORMAT invalid_data("@#{cursor} - Wave file having an invalid fmt size: #{size}") if (size < 16) # Decode header audio_format = @bindata_16.read(@data[element_cursor..element_cursor+1]) num_channels = @bindata_16.read(@data[element_cursor+2..element_cursor+3]) sample_rate = @bindata_32.read(@data[element_cursor+4..element_cursor+7]) byte_rate = @bindata_32.read(@data[element_cursor+8..element_cursor+11]) block_align = @bindata_16.read(@data[element_cursor+12..element_cursor+13]) bits_per_sample = @bindata_16.read(@data[element_cursor+14..element_cursor+15]) ( :audio_format => audio_format, :num_channels => num_channels, :sample_rate => sample_rate, :byte_rate => byte_rate, :block_align => block_align, :bits_per_sample => bits_per_sample ) when ELEMENT_ID_DATA found_WAVE_data = true # AVI elements when ELEMENT_ID_AVI extension = :avi found_relevant_data(:avi) when ELEMENT_ID_MOVI # Parse the following RIFF tags manually cursor = element_cursor stream_id = @data[cursor..cursor+1] stream_type = @data[cursor+2..cursor+3] while ((cursor < container_end_offset) and (stream_id.match(/^\d\d$/) != nil) and (AVI_STREAM_TYPES.include?(stream_type))) # Read size stream_size = @bindata_32.read(@data[cursor+4..cursor+7]) stream_size += 1 if stream_size.odd? log_debug "@#{cursor} - Found AVI stream #{stream_id}#{stream_type} of size #{stream_size}" cursor += 8 + stream_size stream_id = @data[cursor..cursor+1] stream_type = @data[cursor+2..cursor+3] end found_AVI_data = true next cursor when ELEMENT_ID_IDIT ( :date_time_original => read_ascii(element_cursor, size) ) # ANI elements when ELEMENT_ID_ANI extension = :ani found_relevant_data(:ani) end end # By default: no data next element_cursor end ( :nbr_elements => nbr_elements ) invalid_data("@#{cursor} - Missing WAVE data.") if ((extension == :wav) and (!found_WAVE_data)) invalid_data("@#{cursor} - Missing AVI data.") if ((extension == :avi) and (!found_AVI_data)) ending_offset = cursor if (ending_offset == nil) return ending_offset end |
#get_begin_pattern ⇒ Object
227 228 229 |
# File 'lib/fileshunter/Decoders/RIFF.rb', line 227 def get_begin_pattern return BEGIN_PATTERN_FILE, { :offset_inc => 4, :max_regexp_size => 4 } end |