aviglitch 0.1.6 → 0.2.2
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/.github/workflows/ruby.yml +5 -21
- data/.gitignore +1 -0
- data/ChangeLog.md +14 -0
- data/Gemfile +5 -0
- data/LICENSE +1 -1
- data/README.md +0 -4
- data/aviglitch.gemspec +1 -2
- data/bin/datamosh +13 -3
- data/lib/aviglitch/avi.rb +557 -0
- data/lib/aviglitch/base.rb +31 -59
- data/lib/aviglitch/frame.rb +20 -0
- data/lib/aviglitch/frames.rb +187 -185
- data/lib/aviglitch.rb +12 -5
- data/spec/avi2_spec.rb +41 -0
- data/spec/aviglitch_spec.rb +20 -18
- data/spec/datamosh_spec.rb +4 -14
- data/spec/frames_spec.rb +39 -28
- data/spec/spec_helper.rb +45 -0
- metadata +7 -6
- data/spec/files/sample.avi +0 -0
data/lib/aviglitch/frame.rb
CHANGED
@@ -58,6 +58,26 @@ module AviGlitch
|
|
58
58
|
@id[2, 2] == 'wb'
|
59
59
|
end
|
60
60
|
|
61
|
+
##
|
62
|
+
# Returns if it is a frame in +frame_type+.
|
63
|
+
def is? frame_type
|
64
|
+
return true if frame_type == :all
|
65
|
+
detection = "is_#{frame_type.to_s.sub(/frames$/, 'frame')}?"
|
66
|
+
begin
|
67
|
+
self.send detection
|
68
|
+
rescue NoMethodError => e
|
69
|
+
false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Compares its content.
|
75
|
+
def == other
|
76
|
+
self.id == other.id &&
|
77
|
+
self.flag == other.flag &&
|
78
|
+
self.data == other.data
|
79
|
+
end
|
80
|
+
|
61
81
|
end
|
62
82
|
end
|
63
83
|
|
data/lib/aviglitch/frames.rb
CHANGED
@@ -18,45 +18,13 @@ module AviGlitch
|
|
18
18
|
class Frames
|
19
19
|
include Enumerable
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
##
|
24
|
-
SAFE_FRAMES_COUNT = 150000
|
25
|
-
@@warn_if_frames_are_too_large = true
|
26
|
-
|
27
|
-
# :startdoc:
|
28
|
-
|
29
|
-
attr_reader :meta
|
21
|
+
attr_reader :avi
|
30
22
|
|
31
23
|
##
|
32
24
|
# Creates a new AviGlitch::Frames object.
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
while io.read(4) =~ /^(?:LIST|JUNK)$/ do
|
37
|
-
s = io.read(4).unpack('V').first
|
38
|
-
@pos_of_movi = io.pos - 4 if io.read(4) == 'movi'
|
39
|
-
io.pos += s - 4
|
40
|
-
end
|
41
|
-
@pos_of_idx1 = io.pos - 4 # here must be idx1
|
42
|
-
s = io.read(4).unpack('V').first + io.pos
|
43
|
-
@meta = []
|
44
|
-
while chunk_id = io.read(4) do
|
45
|
-
break if io.pos >= s
|
46
|
-
@meta << {
|
47
|
-
:id => chunk_id,
|
48
|
-
:flag => io.read(4).unpack('V').first,
|
49
|
-
:offset => io.read(4).unpack('V').first,
|
50
|
-
:size => io.read(4).unpack('V').first,
|
51
|
-
}
|
52
|
-
end
|
53
|
-
fix_offsets_if_needed io
|
54
|
-
unless safe_frames_count? @meta.size
|
55
|
-
io.close!
|
56
|
-
exit
|
57
|
-
end
|
58
|
-
io.rewind
|
59
|
-
@io = io
|
25
|
+
# It takes AviGlitch::Avi as an argument.
|
26
|
+
def initialize avi
|
27
|
+
@avi = avi
|
60
28
|
end
|
61
29
|
|
62
30
|
##
|
@@ -64,10 +32,29 @@ module AviGlitch
|
|
64
32
|
# It returns Enumerator if a block is not given.
|
65
33
|
def each &block
|
66
34
|
if block_given?
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
35
|
+
Tempfile.open('aviglitch-temp', @avi.tmpdir, binmode: true) do |newmovi|
|
36
|
+
@avi.process_movi do |indices, movi|
|
37
|
+
newindices = indices.select do |m|
|
38
|
+
movi.pos = m[:offset] + 8 # 8 for id and size
|
39
|
+
frame = Frame.new(movi.read(m[:size]), m[:id], m[:flag])
|
40
|
+
block.call frame
|
41
|
+
unless frame.data.nil?
|
42
|
+
m[:offset] = newmovi.pos
|
43
|
+
m[:size] = frame.data.size
|
44
|
+
m[:flag] = frame.flag
|
45
|
+
m[:id] = frame.id
|
46
|
+
newmovi.print m[:id]
|
47
|
+
newmovi.print [frame.data.size].pack('V')
|
48
|
+
newmovi.print frame.data
|
49
|
+
newmovi.print "\0" if frame.data.size % 2 == 1
|
50
|
+
true
|
51
|
+
else
|
52
|
+
false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
[newindices, newmovi]
|
56
|
+
end
|
57
|
+
end
|
71
58
|
else
|
72
59
|
self.enum_for :each
|
73
60
|
end
|
@@ -76,84 +63,34 @@ module AviGlitch
|
|
76
63
|
##
|
77
64
|
# Returns the number of frames.
|
78
65
|
def size
|
79
|
-
@
|
66
|
+
@avi.indices.size
|
80
67
|
end
|
81
68
|
|
82
69
|
##
|
83
70
|
# Returns the number of the specific +frame_type+.
|
84
71
|
def size_of frame_type
|
85
|
-
|
86
|
-
|
87
|
-
Frame.new(nil, m[:id], m[:flag]).send detection
|
72
|
+
@avi.indices.select { |m|
|
73
|
+
Frame.new(nil, m[:id], m[:flag]).is? frame_type
|
88
74
|
}.size
|
89
75
|
end
|
90
76
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
unless frame.data.nil?
|
99
|
-
m[:offset] = io.pos + 4 # 4 for 'movi'
|
100
|
-
m[:size] = frame.data.size
|
101
|
-
m[:flag] = frame.flag
|
102
|
-
m[:id] = frame.id
|
103
|
-
io.print m[:id]
|
104
|
-
io.print [frame.data.size].pack('V')
|
105
|
-
io.print frame.data
|
106
|
-
io.print "\000" if frame.data.size % 2 == 1
|
107
|
-
true
|
108
|
-
else
|
109
|
-
false
|
110
|
-
end
|
77
|
+
##
|
78
|
+
# Returns the data size of total frames.
|
79
|
+
def data_size
|
80
|
+
size = 0
|
81
|
+
@avi.process_movi do |indices, movi|
|
82
|
+
size = movi.size
|
83
|
+
[indices, movi]
|
111
84
|
end
|
112
|
-
|
113
|
-
end
|
114
|
-
|
115
|
-
def overwrite data #:nodoc:
|
116
|
-
unless safe_frames_count? @meta.size
|
117
|
-
@io.close!
|
118
|
-
exit
|
119
|
-
end
|
120
|
-
# Overwrite the file
|
121
|
-
@io.pos = @pos_of_movi - 4 # 4 for size
|
122
|
-
@io.print [data.pos + 4].pack('V') # 4 for 'movi'
|
123
|
-
@io.print 'movi'
|
124
|
-
data.rewind
|
125
|
-
while d = data.read(BUFFER_SIZE) do
|
126
|
-
@io.print d
|
127
|
-
end
|
128
|
-
@io.print 'idx1'
|
129
|
-
@io.print [@meta.size * 16].pack('V')
|
130
|
-
idx = @meta.collect { |m|
|
131
|
-
m[:id] + [m[:flag], m[:offset], m[:size]].pack('V3')
|
132
|
-
}.join
|
133
|
-
@io.print idx
|
134
|
-
eof = @io.pos
|
135
|
-
@io.truncate eof
|
136
|
-
|
137
|
-
# Fix info
|
138
|
-
## file size
|
139
|
-
@io.pos = 4
|
140
|
-
@io.print [eof - 8].pack('V')
|
141
|
-
## frame count
|
142
|
-
@io.pos = 48
|
143
|
-
vid_frames = @meta.select do |m|
|
144
|
-
id = m[:id]
|
145
|
-
id[2, 2] == 'db' || id[2, 2] == 'dc'
|
146
|
-
end
|
147
|
-
@io.print [vid_frames.size].pack('V')
|
148
|
-
|
149
|
-
@io.pos
|
85
|
+
size
|
150
86
|
end
|
151
87
|
|
152
88
|
##
|
153
89
|
# Removes all frames and returns self.
|
154
90
|
def clear
|
155
|
-
@
|
156
|
-
|
91
|
+
@avi.process_movi do |indices, movi|
|
92
|
+
[[], StringIO.new]
|
93
|
+
end
|
157
94
|
self
|
158
95
|
end
|
159
96
|
|
@@ -162,27 +99,24 @@ module AviGlitch
|
|
162
99
|
# It is destructive like Array does.
|
163
100
|
def concat other_frames
|
164
101
|
raise TypeError unless other_frames.kind_of?(Frames)
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
102
|
+
@avi.process_movi do |this_indices, this_movi|
|
103
|
+
this_size = this_movi.size
|
104
|
+
this_movi.pos = this_size
|
105
|
+
other_frames.avi.process_movi do |other_indices, other_movi|
|
106
|
+
while d = other_movi.read(BUFFER_SIZE) do
|
107
|
+
this_movi.print d
|
108
|
+
end
|
109
|
+
other_meta = other_indices.collect do |m|
|
110
|
+
x = m.dup
|
111
|
+
x[:offset] += this_size
|
112
|
+
x
|
113
|
+
end
|
114
|
+
this_indices.concat other_meta
|
115
|
+
[other_indices, other_movi]
|
116
|
+
end
|
117
|
+
[this_indices, this_movi]
|
181
118
|
end
|
182
|
-
|
183
|
-
# close
|
184
|
-
overwrite this_data
|
185
|
-
this_data.close!
|
119
|
+
|
186
120
|
self
|
187
121
|
end
|
188
122
|
|
@@ -203,6 +137,7 @@ module AviGlitch
|
|
203
137
|
times.times do
|
204
138
|
result.concat frames
|
205
139
|
end
|
140
|
+
frames.terminate
|
206
141
|
result
|
207
142
|
end
|
208
143
|
|
@@ -242,7 +177,12 @@ module AviGlitch
|
|
242
177
|
l = 1 if l.nil?
|
243
178
|
tail = self.slice((b + l)..-1)
|
244
179
|
self.clear
|
245
|
-
|
180
|
+
temp = head + tail
|
181
|
+
self.concat temp
|
182
|
+
temp.terminate
|
183
|
+
head.terminate
|
184
|
+
tail.terminate
|
185
|
+
|
246
186
|
sliced
|
247
187
|
end
|
248
188
|
|
@@ -266,16 +206,25 @@ module AviGlitch
|
|
266
206
|
|
267
207
|
self.clear
|
268
208
|
self.concat new_frames
|
209
|
+
|
210
|
+
new_frames.terminate
|
211
|
+
head.terminate
|
212
|
+
rest.terminate
|
269
213
|
end
|
270
214
|
|
271
215
|
##
|
272
216
|
# Returns one Frame object at the given index.
|
273
217
|
def at n
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
218
|
+
frame = nil
|
219
|
+
@avi.process_movi do |indices, movi|
|
220
|
+
m = indices[n]
|
221
|
+
unless m.nil?
|
222
|
+
movi.pos = m[:offset] + 8
|
223
|
+
frame = Frame.new(movi.read(m[:size]), m[:id], m[:flag])
|
224
|
+
movi.rewind
|
225
|
+
end
|
226
|
+
[indices, movi]
|
227
|
+
end
|
279
228
|
frame
|
280
229
|
end
|
281
230
|
|
@@ -291,28 +240,101 @@ module AviGlitch
|
|
291
240
|
self.slice(self.size - 1)
|
292
241
|
end
|
293
242
|
|
243
|
+
##
|
244
|
+
# Returns the first Frame object in +frame_type+.
|
245
|
+
def first_of frame_type
|
246
|
+
frame = nil
|
247
|
+
@avi.process_movi do |indices, movi|
|
248
|
+
indices.each do |m|
|
249
|
+
movi.pos = m[:offset] + 8
|
250
|
+
f = Frame.new(movi.read(m[:size]), m[:id], m[:flag])
|
251
|
+
if f.is?(frame_type)
|
252
|
+
frame = f
|
253
|
+
break
|
254
|
+
end
|
255
|
+
end
|
256
|
+
[indices, movi]
|
257
|
+
end
|
258
|
+
frame
|
259
|
+
end
|
260
|
+
|
261
|
+
##
|
262
|
+
# Returns the last Frame object in +frame_type+.
|
263
|
+
def last_of frame_type
|
264
|
+
frame = nil
|
265
|
+
@avi.process_movi do |indices, movi|
|
266
|
+
indices.reverse.each do |m|
|
267
|
+
movi.pos = m[:offset] + 8
|
268
|
+
f = Frame.new(movi.read(m[:size]), m[:id], m[:flag])
|
269
|
+
if f.is?(frame_type)
|
270
|
+
frame = f
|
271
|
+
break
|
272
|
+
end
|
273
|
+
end
|
274
|
+
[indices, movi]
|
275
|
+
end
|
276
|
+
frame
|
277
|
+
end
|
278
|
+
|
279
|
+
##
|
280
|
+
# Returns an index of the first found +frame+.
|
281
|
+
def index frame
|
282
|
+
n = -1
|
283
|
+
@avi.process_movi do |indices, movi|
|
284
|
+
indices.each_with_index do |m, i|
|
285
|
+
movi.pos = m[:offset] + 8
|
286
|
+
f = Frame.new(movi.read(m[:size]), m[:id], m[:flag])
|
287
|
+
if f == frame
|
288
|
+
n = i
|
289
|
+
break
|
290
|
+
end
|
291
|
+
end
|
292
|
+
[indices, movi]
|
293
|
+
end
|
294
|
+
n
|
295
|
+
end
|
296
|
+
|
297
|
+
##
|
298
|
+
# Alias for index
|
299
|
+
alias_method :find_index, :index
|
300
|
+
|
301
|
+
##
|
302
|
+
# Returns an index of the first found +frame+, starting from the last.
|
303
|
+
def rindex frame
|
304
|
+
n = -1
|
305
|
+
@avi.process_movi do |indices, movi|
|
306
|
+
indices.reverse.each_with_index do |m, i|
|
307
|
+
movi.pos = m[:offset] + 8
|
308
|
+
f = Frame.new(movi.read(m[:size]), m[:id], m[:flag])
|
309
|
+
if f == frame
|
310
|
+
n = indices.size - 1 - i
|
311
|
+
break
|
312
|
+
end
|
313
|
+
end
|
314
|
+
[indices, movi]
|
315
|
+
end
|
316
|
+
n
|
317
|
+
end
|
318
|
+
|
294
319
|
##
|
295
320
|
# Appends the given Frame into the tail of self.
|
296
321
|
def push frame
|
297
322
|
raise TypeError unless frame.kind_of? Frame
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
# close
|
314
|
-
overwrite this_data
|
315
|
-
this_data.close!
|
323
|
+
@avi.process_movi do |indices, movi|
|
324
|
+
this_size = movi.size
|
325
|
+
movi.pos = this_size
|
326
|
+
movi.print frame.id
|
327
|
+
movi.print [frame.data.size].pack('V')
|
328
|
+
movi.print frame.data
|
329
|
+
movi.print "\0" if frame.data.size % 2 == 1
|
330
|
+
indices << {
|
331
|
+
:id => frame.id,
|
332
|
+
:flag => frame.flag,
|
333
|
+
:offset => this_size,
|
334
|
+
:size => frame.data.size,
|
335
|
+
}
|
336
|
+
[indices, movi]
|
337
|
+
end
|
316
338
|
self
|
317
339
|
end
|
318
340
|
|
@@ -331,6 +353,7 @@ module AviGlitch
|
|
331
353
|
|
332
354
|
self.clear
|
333
355
|
self.concat new_frames
|
356
|
+
new_frames.terminate
|
334
357
|
self
|
335
358
|
end
|
336
359
|
|
@@ -355,17 +378,24 @@ module AviGlitch
|
|
355
378
|
##
|
356
379
|
# Returns true if +other+'s frames are same as self's frames.
|
357
380
|
def == other
|
358
|
-
@
|
381
|
+
@avi == other.avi
|
382
|
+
end
|
383
|
+
|
384
|
+
##
|
385
|
+
# Closes the internal temp file explicitly. This instance becomes unusable.
|
386
|
+
def terminate
|
387
|
+
@avi.close
|
388
|
+
@avi = nil
|
359
389
|
end
|
360
390
|
|
361
391
|
##
|
362
392
|
# Generates new AviGlitch::Base instance using self.
|
363
393
|
def to_avi
|
364
|
-
AviGlitch.
|
394
|
+
AviGlitch::Base.new @avi.clone
|
365
395
|
end
|
366
396
|
|
367
|
-
def inspect
|
368
|
-
"#<#{self.class.name}:#{sprintf("0x%x", object_id)}
|
397
|
+
def inspect #:nodoc:
|
398
|
+
"#<#{self.class.name}:#{sprintf("0x%x", object_id)} size=#{self.size}>"
|
369
399
|
end
|
370
400
|
|
371
401
|
def get_beginning_and_length *args #:nodoc:
|
@@ -373,46 +403,18 @@ module AviGlitch
|
|
373
403
|
if args.first.kind_of? Range
|
374
404
|
r = args.first
|
375
405
|
b = r.begin
|
376
|
-
e = r.end >= 0 ? r.end :
|
406
|
+
e = r.end >= 0 ? r.end : self.size + r.end
|
377
407
|
l = e - b + 1
|
378
408
|
end
|
379
|
-
b = b >= 0 ? b :
|
409
|
+
b = b >= 0 ? b : self.size + b
|
380
410
|
[b, l]
|
381
411
|
end
|
382
412
|
|
383
413
|
def safe_frames_count? count #:nodoc:
|
384
|
-
|
385
|
-
|
386
|
-
trap(:INT) do
|
387
|
-
@io.close!
|
388
|
-
exit
|
389
|
-
end
|
390
|
-
m = ["WARNING: The avi data has too many frames (#{count}).\n",
|
391
|
-
"It may use a large memory to process. ",
|
392
|
-
"We recommend to chop the movie to smaller chunks before you glitch.\n",
|
393
|
-
"Do you want to continue anyway? [yN] "].join('')
|
394
|
-
a = Readline.readline m
|
395
|
-
r = a == 'y'
|
396
|
-
@@warn_if_frames_are_too_large = !r
|
397
|
-
end
|
398
|
-
r
|
399
|
-
end
|
400
|
-
|
401
|
-
def fix_offsets_if_needed io #:nodoc:
|
402
|
-
# rarely data offsets begin from 0 of the file
|
403
|
-
return if @meta.empty?
|
404
|
-
pos = io.pos
|
405
|
-
m = @meta.first
|
406
|
-
io.pos = @pos_of_movi + m[:offset]
|
407
|
-
unless io.read(4) == m[:id]
|
408
|
-
@meta.each do |x|
|
409
|
-
x[:offset] -= @pos_of_movi
|
410
|
-
end
|
411
|
-
end
|
412
|
-
io.pos = pos
|
414
|
+
warn "[DEPRECATION] `safe_frames_count?` is deprecated."
|
415
|
+
true
|
413
416
|
end
|
414
417
|
|
415
|
-
|
416
|
-
private :overwrite, :get_beginning_and_length, :fix_offsets_if_needed
|
418
|
+
private :get_beginning_and_length
|
417
419
|
end
|
418
420
|
end
|
data/lib/aviglitch.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'tempfile'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'readline'
|
4
2
|
require 'pathname'
|
5
3
|
require 'stringio'
|
4
|
+
require 'aviglitch/avi'
|
6
5
|
require 'aviglitch/base'
|
7
6
|
require 'aviglitch/frame'
|
8
7
|
require 'aviglitch/frames'
|
@@ -29,9 +28,16 @@ require 'aviglitch/frames'
|
|
29
28
|
# end
|
30
29
|
# avi.output '/path/to/broken.avi'
|
31
30
|
#
|
31
|
+
# Since v0.2.2, it allows to specify the temporary directory. This library
|
32
|
+
# duplicates and processes a input file in the temporary directory, which
|
33
|
+
# by default is +Dir.tmpdir+. To specify the custom temporary directory, use
|
34
|
+
# +tmpdir:+ option, like:
|
35
|
+
#
|
36
|
+
# avi = AviGlitch.open '/path/to/your.avi', tmpdir: '/path/to/tmpdir'
|
37
|
+
#
|
32
38
|
module AviGlitch
|
33
39
|
|
34
|
-
VERSION = '0.
|
40
|
+
VERSION = '0.2.2'
|
35
41
|
|
36
42
|
BUFFER_SIZE = 2 ** 24
|
37
43
|
|
@@ -39,11 +45,12 @@ module AviGlitch
|
|
39
45
|
##
|
40
46
|
# Returns AviGlitch::Base instance.
|
41
47
|
# It requires +path_or_frames+ as String or Pathname, or Frames instance.
|
42
|
-
|
48
|
+
# Additionally, it allows +tmpdir:+ as the internal temporary directory.
|
49
|
+
def open path_or_frames, tmpdir: nil
|
43
50
|
if path_or_frames.kind_of?(Frames)
|
44
51
|
path_or_frames.to_avi
|
45
52
|
else
|
46
|
-
AviGlitch::Base.new(Pathname(path_or_frames))
|
53
|
+
AviGlitch::Base.new(Pathname(path_or_frames), tmpdir: tmpdir)
|
47
54
|
end
|
48
55
|
end
|
49
56
|
end
|
data/spec/avi2_spec.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe AviGlitch, 'AVI2.0' do
|
4
|
+
|
5
|
+
it 'should save same file when nothing has changed' do
|
6
|
+
avi = AviGlitch.open @in2
|
7
|
+
avi.glitch do |d|
|
8
|
+
d
|
9
|
+
end
|
10
|
+
avi.output @out
|
11
|
+
FileUtils.cmp(@in2, @out).should be true
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should be AVI1.0 when its size has reduced less than 1GB' do
|
15
|
+
a = AviGlitch.open @in2
|
16
|
+
size = 0
|
17
|
+
a.glitch do |d|
|
18
|
+
size += d.size
|
19
|
+
size < 1024 ** 3 ? d : nil
|
20
|
+
end
|
21
|
+
a.output @out
|
22
|
+
b = AviGlitch.open @out
|
23
|
+
b.avi.was_avi2?.should be false
|
24
|
+
b.close
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should be AVI2.0 when its size has increased over 1GB' do
|
28
|
+
a = AviGlitch.open @in
|
29
|
+
n = Math.log(1024.0 ** 3 / a.frames.data_size.to_f, 2).ceil
|
30
|
+
f = a.frames[0..-1]
|
31
|
+
n.times do
|
32
|
+
fx = f[0..-1]
|
33
|
+
f.concat fx
|
34
|
+
fx.terminate
|
35
|
+
end
|
36
|
+
f.to_avi.output @out
|
37
|
+
b = AviGlitch.open @out
|
38
|
+
b.avi.was_avi2?.should be true
|
39
|
+
b.close
|
40
|
+
end
|
41
|
+
end
|
data/spec/aviglitch_spec.rb
CHANGED
@@ -2,24 +2,10 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
2
|
|
3
3
|
describe AviGlitch do
|
4
4
|
|
5
|
-
before :all do
|
6
|
-
FileUtils.mkdir OUTPUT_DIR unless File.exist? OUTPUT_DIR
|
7
|
-
@in = FILES_DIR + 'sample.avi'
|
8
|
-
@out = OUTPUT_DIR + 'out.avi'
|
9
|
-
end
|
10
|
-
|
11
|
-
after :each do
|
12
|
-
FileUtils.rm Dir.glob((OUTPUT_DIR + '*').to_s)
|
13
|
-
end
|
14
|
-
|
15
|
-
after :all do
|
16
|
-
FileUtils.rmdir OUTPUT_DIR
|
17
|
-
end
|
18
|
-
|
19
5
|
it 'should raise an error against unsupported files' do
|
20
6
|
lambda {
|
21
7
|
avi = AviGlitch.open __FILE__
|
22
|
-
}.should raise_error
|
8
|
+
}.should raise_error(RuntimeError)
|
23
9
|
end
|
24
10
|
|
25
11
|
it 'should return AviGlitch::Base object through the method #open' do
|
@@ -106,7 +92,7 @@ describe AviGlitch do
|
|
106
92
|
}.should raise_error(IOError)
|
107
93
|
end
|
108
94
|
|
109
|
-
it 'can
|
95
|
+
it 'can close the file explicitly' do
|
110
96
|
avi = AviGlitch.open @in
|
111
97
|
avi.close
|
112
98
|
lambda {
|
@@ -174,7 +160,7 @@ describe AviGlitch do
|
|
174
160
|
end
|
175
161
|
end
|
176
162
|
|
177
|
-
it 'should check if keyframes exist
|
163
|
+
it 'should check if keyframes exist' do
|
178
164
|
a = AviGlitch.open @in
|
179
165
|
a.has_keyframe?.should be true
|
180
166
|
a.glitch :keyframe do |f|
|
@@ -203,9 +189,25 @@ describe AviGlitch do
|
|
203
189
|
end
|
204
190
|
|
205
191
|
expect(dc1).to eq(dc2)
|
192
|
+
end
|
206
193
|
|
194
|
+
it 'can be set custom temp dir' do
|
195
|
+
custom_tmpdir = Pathname.new(OUTPUT_DIR) + 'custom_tmpdir'
|
196
|
+
Dir.mkdir custom_tmpdir unless File.exist? custom_tmpdir
|
207
197
|
|
208
|
-
|
198
|
+
c = Dir.glob((custom_tmpdir + '*').to_s).size
|
199
|
+
b = AviGlitch.open @in, tmpdir: custom_tmpdir
|
200
|
+
b2 = b.frames[0, 100].to_avi
|
201
|
+
b2.frames.each do |f|
|
202
|
+
Dir.glob((custom_tmpdir + '*').to_s).size.should >= c
|
203
|
+
end
|
209
204
|
end
|
210
205
|
|
206
|
+
it 'shoud raise an error when specified temp dir is not writable' do
|
207
|
+
custom_tmpdir = Pathname.new(OUTPUT_DIR) + 'not_dir'
|
208
|
+
lambda {
|
209
|
+
AviGlitch.open @in, tmpdir: custom_tmpdir
|
210
|
+
}.should raise_error(SystemCallError)
|
211
|
+
end
|
212
|
+
|
211
213
|
end
|