format_parser 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/lib/format_parser/version.rb +1 -1
- data/lib/parsers/moov_parser/decoder.rb +19 -0
- data/lib/parsers/moov_parser.rb +36 -4
- data/lib/video.rb +2 -0
- data/spec/parsers/moov_parser_spec.rb +2 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e49394510e191185e3be1f3560ca182a103b9446225a1163294f2db6a912ae76
|
4
|
+
data.tar.gz: 4f52d761857020a0957711528ad4d10ee885c74745897fa14a5e69292abf0cc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 829bd488d021cb0db5ce2b718aa661bdf3d4f86a55e55808c8279367e955d35b2bdccdd2bdf805ff736cef6d49f8c0f425c1ec65c0d7f07ada2db684581d4c1f
|
7
|
+
data.tar.gz: ed76f04c157a865de03df0d614d0d353b53e1e9c9b0a164ac6b2a6612a358643ae210b00fd92b91fec6cefd8c8c71e6ff559e63df3343b13ce161175425dbd3a
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
@@ -72,6 +72,7 @@ class FormatParser::MOOVParser::Decoder
|
|
72
72
|
|
73
73
|
trak_atoms.find do |trak_atom|
|
74
74
|
hdlr_atom = find_first_atom_by_path([trak_atom], 'trak', 'mdia', 'hdlr')
|
75
|
+
next if hdlr_atom.nil?
|
75
76
|
hdlr_atom.atom_fields[:component_type] == 'mhlr' && hdlr_atom.atom_fields[:component_subtype] == 'vide'
|
76
77
|
end
|
77
78
|
end
|
@@ -111,6 +112,24 @@ class FormatParser::MOOVParser::Decoder
|
|
111
112
|
}
|
112
113
|
end
|
113
114
|
|
115
|
+
def parse_stts_atom(io, _)
|
116
|
+
version = read_byte_value(io)
|
117
|
+
is_v1 = version == 1
|
118
|
+
stts = {
|
119
|
+
version: version,
|
120
|
+
flags: read_bytes(io, 3),
|
121
|
+
number_of_entries: is_v1 ? read_64bit_uint(io) : read_32bit_uint(io),
|
122
|
+
entries: []
|
123
|
+
}
|
124
|
+
stts[:number_of_entries].times {
|
125
|
+
stts[:entries] << {
|
126
|
+
sample_count: read_32bit_uint(io),
|
127
|
+
sample_duration: read_32bit_uint(io)
|
128
|
+
}
|
129
|
+
}
|
130
|
+
stts
|
131
|
+
end
|
132
|
+
|
114
133
|
def parse_mdhd_atom(io, _)
|
115
134
|
version = read_byte_value(io)
|
116
135
|
is_v1 = version == 1
|
data/lib/parsers/moov_parser.rb
CHANGED
@@ -48,9 +48,9 @@ class FormatParser::MOOVParser
|
|
48
48
|
width, height = parse_dimensions(decoder, atom_tree)
|
49
49
|
|
50
50
|
# Try to find the "topmost" duration (respecting edits)
|
51
|
-
if
|
52
|
-
timescale =
|
53
|
-
duration =
|
51
|
+
if mvhd = decoder.find_first_atom_by_path(atom_tree, 'moov', 'mvhd')
|
52
|
+
timescale = mvhd.field_value(:tscale)
|
53
|
+
duration = mvhd.field_value(:duration)
|
54
54
|
media_duration_s = duration / timescale.to_f
|
55
55
|
end
|
56
56
|
|
@@ -64,13 +64,15 @@ class FormatParser::MOOVParser
|
|
64
64
|
intrinsics: atom_tree,
|
65
65
|
)
|
66
66
|
else
|
67
|
+
frame_rate = parse_sample_atom(decoder, atom_tree)&.truncate(2)
|
67
68
|
FormatParser::Video.new(
|
68
69
|
format: format_from_moov_type(file_type),
|
69
70
|
width_px: width,
|
70
71
|
height_px: height,
|
72
|
+
frame_rate: frame_rate,
|
71
73
|
media_duration_seconds: media_duration_s,
|
72
74
|
content_type: MP4_MIXED_MIME_TYPE,
|
73
|
-
intrinsics: atom_tree
|
75
|
+
intrinsics: atom_tree
|
74
76
|
)
|
75
77
|
end
|
76
78
|
end
|
@@ -115,5 +117,35 @@ class FormatParser::MOOVParser
|
|
115
117
|
maybe_atom_size >= minimum_ftyp_atom_size && maybe_ftyp_atom_signature == 'ftyp'
|
116
118
|
end
|
117
119
|
|
120
|
+
# Sample information is found in the 'time-to-sample' stts atom.
|
121
|
+
# The media atom mdhd is needed too in order to get the movie timescale
|
122
|
+
def parse_sample_atom(decoder, atom_tree)
|
123
|
+
video_trak_atom = decoder.find_video_trak_atom(atom_tree)
|
124
|
+
|
125
|
+
stts = if video_trak_atom
|
126
|
+
decoder.find_first_atom_by_path([video_trak_atom], 'trak', 'mdia', 'minf', 'stbl', 'stts')
|
127
|
+
else
|
128
|
+
decoder.find_first_atom_by_path(atom_tree, 'moov', 'trak', 'mdia', 'minf', 'stbl', 'stts')
|
129
|
+
end
|
130
|
+
|
131
|
+
mdhd = if video_trak_atom
|
132
|
+
decoder.find_first_atom_by_path([video_trak_atom], 'trak', 'mdia', 'mdhd')
|
133
|
+
else
|
134
|
+
decoder.find_first_atom_by_path(atom_tree, 'moov', 'trak', 'mdia', 'mdhd')
|
135
|
+
end
|
136
|
+
|
137
|
+
if stts && mdhd
|
138
|
+
timescale = mdhd.atom_fields[:tscale]
|
139
|
+
sample_duration = stts.field_value(:entries).first[:sample_duration]
|
140
|
+
if timescale.nil? || timescale == 0 || sample_duration.nil? || sample_duration == 0
|
141
|
+
nil
|
142
|
+
else
|
143
|
+
timescale.to_f / sample_duration
|
144
|
+
end
|
145
|
+
else
|
146
|
+
nil
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
118
150
|
FormatParser.register_parser new, natures: :video, formats: FTYP_MAP.values, priority: 1
|
119
151
|
end
|
data/lib/video.rb
CHANGED
@@ -106,6 +106,7 @@ describe FormatParser::MOOVParser do
|
|
106
106
|
expect(result.format).to eq(:mov)
|
107
107
|
expect(result.width_px).to eq(160)
|
108
108
|
expect(result.height_px).to eq(90)
|
109
|
+
expect(result.frame_rate).to eq(14.98)
|
109
110
|
end
|
110
111
|
|
111
112
|
it 'provides filename hints' do
|
@@ -122,6 +123,7 @@ describe FormatParser::MOOVParser do
|
|
122
123
|
expect(result.format).to eq(:mov)
|
123
124
|
expect(result.width_px).to eq(640)
|
124
125
|
expect(result.height_px).to eq(360)
|
126
|
+
expect(result.frame_rate).to eq(30)
|
125
127
|
end
|
126
128
|
|
127
129
|
it 'does not raise error when a meta atom has size 0' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: format_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Berman
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-01
|
12
|
+
date: 2022-04-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ks
|
@@ -315,7 +315,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
315
315
|
- !ruby/object:Gem::Version
|
316
316
|
version: '0'
|
317
317
|
requirements: []
|
318
|
-
rubygems_version: 3.
|
318
|
+
rubygems_version: 3.3.4
|
319
319
|
signing_key:
|
320
320
|
specification_version: 4
|
321
321
|
summary: A library for efficient parsing of file metadata
|