Class: WahWah::Mp4::Atom

Inherits:
Object
  • Object
show all
Includes:
LazyRead
Defined in:
lib/wahwah/mp4/atom.rb

Constant Summary collapse

VERSIONED_ATOMS =
%w[meta stsd]
FLAGGED_ATOMS =
%w[stsd]
HEADER_SIZE =
8
HEADER_SIZE_FIELD_SIZE =
4
EXTENDED_HEADER_SIZE =
8

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from LazyRead

#data, prepended, #skip

Constructor Details

#initializeAtom

An atom header consists of the following fields:

Atom size: A 32-bit integer that indicates the size of the atom, including both the atom header and the atom’s contents, including any contained atoms. Normally, the size field contains the actual size of the atom.

Type: A 32-bit integer that contains the type of the atom. This can often be usefully treated as a four-character field with a mnemonic value .



45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/wahwah/mp4/atom.rb', line 45

def initialize
  @size, @type = @file_io.read(HEADER_SIZE)&.unpack("Na4")
  return unless valid?

  # If the size field of an atom is set to 1, the type field is followed by a 64-bit extended size field,
  # which contains the actual size of the atom as a 64-bit unsigned integer.
  @size = @file_io.read(EXTENDED_HEADER_SIZE).unpack1("Q>") - EXTENDED_HEADER_SIZE if @size == 1

  # If the size field of an atom is set to 0, which is allowed only for a top-level atom,
  # designates the last atom in the file and indicates that the atom extends to the end of the file.
  @size = @file_io.size if @size == 0
  @size -= HEADER_SIZE
end

Instance Attribute Details

#typeObject (readonly)

Returns the value of attribute type.



14
15
16
# File 'lib/wahwah/mp4/atom.rb', line 14

def type
  @type
end

Class Method Details

.find(file_io, *atom_path) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/wahwah/mp4/atom.rb', line 16

def self.find(file_io, *atom_path)
  file_io.rewind

  atom_type = atom_path.shift

  until file_io.eof?
    atom = new(file_io)

    next unless atom.valid?
    file_io.seek(atom.size, IO::SEEK_CUR)
    next unless atom.type == atom_type

    return atom if atom_path.empty?
    return atom.find(*atom_path)
  end

  # Return empty atom if can not found
  new(StringIO.new(""))
end

Instance Method Details

#childrenObject



74
75
76
# File 'lib/wahwah/mp4/atom.rb', line 74

def children
  @children ||= parse_children_atoms
end

#find(*atom_path) ⇒ Object



63
64
65
66
67
68
69
70
71
72
# File 'lib/wahwah/mp4/atom.rb', line 63

def find(*atom_path)
  child_atom_index = data.index(atom_path.first)

  # Return empty atom if can not found
  return self.class.new(StringIO.new("")) if child_atom_index.nil?

  # Because before atom type field there are 4 bytes of size field,
  # So the child_atom_index should reduce 4.
  self.class.find(StringIO.new(data[child_atom_index - HEADER_SIZE_FIELD_SIZE..]), *atom_path)
end

#valid?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/wahwah/mp4/atom.rb', line 59

def valid?
  !@size.nil? && @size >= HEADER_SIZE
end