puremotion 0.0.1 → 0.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.
Files changed (54) hide show
  1. data/.yardopts +1 -0
  2. data/README.md +69 -0
  3. data/Rakefile +23 -11
  4. data/examples/progress_reporting.rb +26 -0
  5. data/examples/simple.rb +22 -0
  6. data/ext/puremotion/audio.c +38 -0
  7. data/ext/puremotion/extconf.rb +34 -0
  8. data/ext/puremotion/frame.c +176 -0
  9. data/ext/puremotion/media.c +175 -0
  10. data/ext/puremotion/puremotion.c +26 -0
  11. data/ext/puremotion/puremotion.h +38 -0
  12. data/ext/puremotion/stream.c +128 -0
  13. data/ext/puremotion/stream_collection.c +44 -0
  14. data/ext/puremotion/utils.c +81 -0
  15. data/ext/puremotion/utils.h +6 -0
  16. data/ext/puremotion/video.c +141 -0
  17. data/lib/{puremotion/events → events}/event.rb +0 -0
  18. data/lib/{puremotion/events → events}/generator.rb +0 -0
  19. data/lib/media.rb +89 -0
  20. data/lib/preset/audio/audio.rb +42 -0
  21. data/lib/preset/file.rb +19 -0
  22. data/lib/preset/general.rb +28 -0
  23. data/lib/preset/metadata.rb +41 -0
  24. data/lib/preset/preset.rb +120 -0
  25. data/lib/preset/video/crop.rb +29 -0
  26. data/lib/preset/video/pad.rb +31 -0
  27. data/lib/preset/video/video.rb +130 -0
  28. data/lib/puremotion.rb +20 -12
  29. data/lib/puremotion_native.so +0 -0
  30. data/lib/threading.rb +54 -0
  31. data/lib/{puremotion/tools → tools}/ffmpeg.rb +12 -50
  32. data/lib/transcode/transcode.rb +142 -0
  33. data/spec/spec_helper.rb +7 -0
  34. data/spec/units/media_spec.rb +13 -0
  35. data/spec/units/preset_spec.rb +91 -0
  36. metadata +52 -44
  37. data/.document +0 -5
  38. data/.gitignore +0 -21
  39. data/README.rdoc +0 -18
  40. data/VERSION +0 -1
  41. data/lib/puremotion/codecs.rb +0 -59
  42. data/lib/puremotion/media.rb +0 -490
  43. data/lib/puremotion/media/stream.rb +0 -4
  44. data/lib/puremotion/media/stream/audio.rb +0 -0
  45. data/lib/puremotion/media/stream/base.rb +0 -7
  46. data/lib/puremotion/media/stream/collection.rb +0 -5
  47. data/lib/puremotion/media/stream/video.rb +0 -61
  48. data/lib/puremotion/recipes/ipod.yml +0 -12
  49. data/lib/puremotion/thread.rb +0 -153
  50. data/lib/puremotion/transcode/recipe.rb +0 -250
  51. data/lib/puremotion/transcode/transcode.rb +0 -153
  52. data/puremotion.gemspec +0 -68
  53. data/test/helper.rb +0 -10
  54. data/test/test_puremotion.rb +0 -7
@@ -1,22 +1,30 @@
1
1
  req = File.expand_path(File.dirname(__FILE__)) + '/'
2
2
 
3
- require 'rubygems'
3
+ #require 'rubygems'
4
4
 
5
5
  module PureMotion
6
6
 
7
7
  end
8
8
 
9
- require req + 'puremotion/events/event'
10
- require req + 'puremotion/events/generator'
9
+ require req + 'puremotion_native'
10
+ require req + 'events/event'
11
+ require req + 'events/generator'
11
12
 
12
13
  Object.extend(PureMotion::Events::Generator)
13
14
 
14
- require req + 'puremotion/thread'
15
- require req + 'puremotion/media'
16
- require req + 'puremotion/media/stream'
17
- require req + 'puremotion/media/stream/base'
18
- require req + 'puremotion/media/stream/video'
19
- require req + 'puremotion/codecs'
20
- require req + 'puremotion/transcode/transcode'
21
- require req + 'puremotion/transcode/recipe'
22
- require req + 'puremotion/tools/ffmpeg'
15
+ require req + 'preset/preset'
16
+
17
+ require req + 'preset/general'
18
+ require req + 'preset/file'
19
+ require req + 'preset/metadata'
20
+ require req + 'preset/video/video'
21
+ require req + 'preset/video/crop'
22
+ require req + 'preset/video/pad'
23
+ require req + 'preset/audio/audio'
24
+
25
+
26
+ require req + 'threading'
27
+ require req + 'media'
28
+ require req + 'codecs'
29
+ require req + 'transcode/transcode'
30
+ require req + 'tools/ffmpeg'
Binary file
@@ -0,0 +1,54 @@
1
+ # Author:: Jared Kuolt (mailto:me@superjared.com)
2
+ # Copyright:: Copyright (c) 2009 Jared Kuolt
3
+ # License:: MIT License
4
+ #
5
+ # See README.rdoc[link:files/README_rdoc.html] for usage
6
+ #
7
+
8
+ module PureMotion
9
+ class Thread
10
+
11
+ attr_reader :thread, :exception
12
+ attr_accessor :name
13
+
14
+ def initialize(config={}, &block)
15
+ args = (config[:args] or [])
16
+ self.class.init_exit_handler
17
+ @thread = ::Thread.new(*args) do |*targs|
18
+ begin
19
+ block.call(*targs)
20
+ rescue Exception => e
21
+ @exception = e
22
+ # Handle?
23
+ end
24
+ end
25
+ self.name = config[:name] || @thread.inspect
26
+ self.class.threads << self
27
+ self.class.init_exit_handler
28
+ end
29
+
30
+ class << self
31
+ attr_accessor :logger, :exit_thread, :exit_handler_initialized, :callbacks
32
+
33
+ def threads
34
+ @threads ||= []
35
+ end
36
+
37
+ def init_exit_handler
38
+ return if self.exit_handler_initialized
39
+ self.exit_thread = false
40
+ at_exit do
41
+ self.exit_thread = true
42
+ begin
43
+ self.threads.each do |thread|
44
+ thread.thread.join
45
+ end
46
+ rescue Interrupt
47
+ end
48
+ end
49
+ self.exit_handler_initialized = true
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -12,7 +12,8 @@ module PureMotion::Tools
12
12
  ERROR = 32
13
13
 
14
14
  end
15
-
15
+
16
+ attr_reader :pid
16
17
  attr_reader :args
17
18
  attr_accessor :output
18
19
 
@@ -20,12 +21,8 @@ module PureMotion::Tools
20
21
  event :complete
21
22
  event :exited
22
23
  event :status_change
23
-
24
- @status = Status::NOT_STARTED
25
-
26
- def self.run(args = {})
27
- FFmpeg.new( args )
28
- end
24
+
25
+ @pid = nil
29
26
 
30
27
  def initialize(params = {})
31
28
  if params.class != Hash then raise ArgumentError, "Invalid parameters" end
@@ -44,17 +41,15 @@ module PureMotion::Tools
44
41
  end
45
42
 
46
43
  @output = []
47
-
48
- go
49
44
  end
50
45
 
51
- def go
52
-
53
- @pio = IO.popen("ffmpeg #{@options} 2>&1")
54
-
46
+ def run
47
+
55
48
  temp = ''
56
49
 
57
- PureMotion::Thread.new do
50
+ @thread = PureMotion::Thread.new do
51
+ @pio = IO.popen("ffmpeg #{@options} 2>&1")
52
+ @pid = @pio.pid
58
53
  @pio.each_byte do |l|
59
54
  if l == 10 or l == 13 then
60
55
  @output.push temp
@@ -70,6 +65,9 @@ module PureMotion::Tools
70
65
  if @pio.eof? then
71
66
  @done = true
72
67
  complete(true)
68
+ @pid = nil
69
+ @pio.close
70
+ exited(true)
73
71
  end
74
72
  end
75
73
 
@@ -78,7 +76,6 @@ module PureMotion::Tools
78
76
  def ran?
79
77
  @pio.eof? unless @pio.nil?
80
78
  false
81
- #!find(/^FFmpeg/).nil?
82
79
  end
83
80
 
84
81
  def ended?
@@ -101,41 +98,6 @@ module PureMotion::Tools
101
98
  @status
102
99
  end
103
100
 
104
- private
105
-
106
- def prepare_args
107
- @args = []
108
- @args << ['i', @input]
109
-
110
- args = []
111
-
112
- strings = []
113
-
114
- @args.each do |arg, value|
115
- if value.nil? then value = '' end
116
- value = '"' + value.to_s + '"' unless value.index(' ').nil?
117
-
118
- args << [ arg, value]
119
-
120
- if value.empty? or value =~ /^\s*$/ then
121
- value = ''
122
- else
123
- value = ' ' << value
124
- end
125
-
126
- strings << ( '-' << arg << value )
127
- end
128
-
129
- if !@output.nil? then strings << '"' + @output + '"' end
130
-
131
- @args = strings.join(' ')
132
- end
133
-
134
- def status=(status_const)
135
- @status = status_const
136
- status_change(status_const)
137
- end
138
-
139
101
  end
140
102
 
141
103
  end
@@ -0,0 +1,142 @@
1
+ def Transcode(*args, &block)
2
+
3
+ raise ArgumentError, "No block given for transcode preset" unless block_given?
4
+
5
+ preset = PureMotion::Preset.new(:dsl)
6
+ preset.instance_eval(&block)
7
+
8
+ options = {
9
+ :input => preset.input,
10
+ :output => preset.output,
11
+ :preset => preset
12
+ }
13
+
14
+ options[:log] = preset.log unless preset.log.nil?
15
+
16
+ transcode = PureMotion::Transcode::Transcode.new(options)
17
+
18
+ transcode.run
19
+
20
+ return transcode
21
+
22
+ end
23
+
24
+ module PureMotion::Transcode
25
+
26
+ class Transcode < Object
27
+
28
+ event :progress
29
+ event :complete
30
+ event :output
31
+
32
+ @ffmpeg = nil
33
+ @input = nil
34
+
35
+ def initialize(options)
36
+
37
+ default_options = {
38
+ :output => nil,
39
+ :preset => nil,
40
+ :input => nil
41
+ }
42
+
43
+ raise ArgumentError, "Invalid transcode parameters given" unless options.is_a?(Hash)
44
+
45
+ options = default_options.merge(options)
46
+
47
+ raise ArgumentError, "No output file given" if options[:output].nil?
48
+
49
+ if options[:input].is_a?(String) then
50
+ @input = PureMotion::Media.new(options[:input])
51
+ else
52
+ @input = options[:input]
53
+ end
54
+ @preset = options[:preset]
55
+ @output = options[:output]
56
+
57
+ validate
58
+
59
+ wire_events
60
+
61
+ if options[:log] then
62
+ @log = File.new(options[:log], 'w')
63
+ self.output + lambda do |t, line|
64
+ @log.puts line
65
+ end
66
+ self.complete + lambda do |t, complete|
67
+ @log.close
68
+ end
69
+ end
70
+
71
+ # Raise error if output file exists and overwrite not set
72
+
73
+ @ffmpeg = PureMotion::Tools::FFmpeg.new(:options => @preset.arguments)
74
+
75
+ @ffmpeg.line + lambda do |ffmpeg, line|
76
+ handle_output line
77
+ end
78
+
79
+ @ffmpeg.exited + lambda do |ffmpeg, exited|
80
+ complete(true)
81
+ end
82
+
83
+ end
84
+
85
+ def run
86
+ @ffmpeg.run
87
+ end
88
+
89
+ def cancel
90
+ # TODO : Implement
91
+ end
92
+
93
+ def cancel!
94
+ # TODO : Implement - kill process dead
95
+ end
96
+
97
+ private
98
+
99
+ def handle_output line
100
+ output line
101
+ # /^frame=\s*(?<frame>\d*)\s*fps=\s*(?<fps>\d*)\s*q=(?<q>\S*)\s*size=\s*(?<size>[\d]*)(?<size_unit>[kmg]B)\s*time=\s*(?<time>[\d.]*)\s*bitrate=\s*(?<bitrate>[\d.]*)(?<bitrate_unit>[km]b).*$/
102
+ progress_line = /frame=\s*(\d*)\s*fps=\s*(\d*)\s*q=(\S*)\s*[L]?size=\s*([\d]*)([kmg]B)\s*time=\s*([\d.]*)\s*bitrate=\s*([\d.]*)([km]b)/
103
+ # The regex is documentated above and the matches it should give below
104
+ # 1 => frame
105
+ # 2 => fps
106
+ # 3 => q
107
+ # 4 => size
108
+ # 5 => size_unit
109
+ # 6 => time
110
+ # 7 => bitrate
111
+ # 8 => bitrate_unit
112
+ handle_progress(progress_line.match(line)) if progress_line.match(line)
113
+ end
114
+
115
+ def handle_progress line
116
+ if line[4].to_i == 0 then return false end
117
+ p = {
118
+ :frame => line[1].to_i,
119
+ :fps => line[2].to_i,
120
+ :q => line[3].to_f,
121
+ :size => line[4].to_i,
122
+ :time => line[6].to_f,
123
+ :bitrate => line[7].to_f,
124
+ :percent => ((100.00 / @input.duration) * line[6].to_f).to_i
125
+ }
126
+ p[:percent] = 100 if p[:percent] > 100 unless p[:percent].nil?
127
+ progress(p)
128
+ end
129
+
130
+ def validate
131
+
132
+ end
133
+
134
+ def wire_events
135
+ self.complete += @preset.event_handlers[:complete] unless @preset.event_handlers[:complete].nil?
136
+ self.progress += @preset.event_handlers[:progress] unless @preset.event_handlers[:progress].nil?
137
+ end
138
+
139
+ end
140
+
141
+
142
+ end
@@ -0,0 +1,7 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ require 'puremotion'
4
+
5
+ def sample_path
6
+ ::File.expand_path(::File.join(::File.dirname(__FILE__), "samples", "sample.ogv"))
7
+ end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe PureMotion::Media do
4
+
5
+ it "should read supported formats" do
6
+ lambda do
7
+ PureMotion::Media.new(sample_path)
8
+ end.should_not raise_error
9
+ end
10
+
11
+
12
+
13
+ end
@@ -0,0 +1,91 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe PureMotion::Preset do
4
+
5
+ it "should support all possible inputs" do
6
+ begin
7
+ PureMotion::Preset.build do
8
+
9
+ input sample_path
10
+
11
+ overwrite!
12
+
13
+ seek 2
14
+ duration 10
15
+
16
+ file do
17
+
18
+ size_limit 10_000_000
19
+
20
+ end
21
+
22
+ metadata do
23
+
24
+ title "Test"
25
+ author "Me"
26
+ copyright "None whatsoever"
27
+ album "Test"
28
+ track 2
29
+ comment "Brilliant"
30
+ year 1989
31
+
32
+ end
33
+
34
+ video do
35
+
36
+ disable
37
+
38
+ buffer '200'
39
+
40
+ bitrate '300k'
41
+ bitrate 300
42
+
43
+ same_quality
44
+
45
+ frames 100
46
+
47
+ framerate 25
48
+ fps 25
49
+
50
+ resolution 320, 240
51
+ resolution [320, 240]
52
+ resolution '320x240'
53
+ resolution :vga
54
+
55
+ crop do
56
+ top 10
57
+ bottom 20
58
+ left 30
59
+ right 40
60
+ end
61
+
62
+ pad do
63
+ top 40
64
+ bottom 30
65
+ left 20
66
+ right 10
67
+
68
+ color "333333"
69
+ end
70
+
71
+ end
72
+
73
+ audio do
74
+
75
+ disable
76
+
77
+ channels 2
78
+ sampling 44100
79
+ frames 100
80
+
81
+ language :eng
82
+
83
+ end
84
+
85
+ output "output.mp4"
86
+
87
+ end
88
+ end.should_not raise_error
89
+ end
90
+
91
+ end