ffi-ffmpeg 0.7.0beae74ee3d7 → 0.8.525a2f4a3ce0

Sign up to get free protection for your applications and to get access to all the features.
data/.hgignore CHANGED
@@ -5,6 +5,7 @@ Gemfire.lock
5
5
  pkg/*
6
6
 
7
7
  *.png
8
+ *.ppm
8
9
  .*.sw[a-z]
9
10
  .AppleDouble
10
11
  .DS_Store
data/README.md CHANGED
@@ -4,7 +4,7 @@ http://github.com/dmlary/ffi-ffmpeg
4
4
 
5
5
  Description
6
6
  -----------
7
- Ruby-FFI bindings and wrappers for FFmpeg libraries.
7
+ Ruby-FFI bindings and wrappers for FFmpeg libraries, version 0.5.1.
8
8
 
9
9
  Features
10
10
  --------
@@ -16,9 +16,51 @@ What's missing
16
16
  * Execute ffmpeg cleanup when Reader, Stream, Frame instances are gc'ed
17
17
  * Encoding
18
18
 
19
+ OMG, FFmpeg 0.5.1 is so old
20
+ ---------------------------
21
+ While working with ffmpeg in python, I got sick of constantly having to
22
+ build and install a new version ffmpeg from source every time I upgraded
23
+ the ffmpeg wraper. When I decided to write this ruby gem I selected the
24
+ version that was available as a pre-built package for my servers which
25
+ happen to run Ubuntu 10.04 LTS (lucid). This version will not change
26
+ until sometime after the next LTS release (mid-2012 ... that's a lot sooner
27
+ that I expected).
28
+
29
+ Getting 0.5.1 on OS X 10.6
30
+ --------------------------
31
+ You can either download, build and install ffmpeg from source, but it's
32
+ much easier to use macports. To get FFmpeg 0.5.1 via macports, you'll need
33
+ to use an older revision of the port:
34
+
35
+ cd /tmp
36
+ svn co -r 66961 http://svn.macports.org/repository/macports/trunk/dports/multimedia/ffmpeg
37
+ cd ffmpeg
38
+ sudo port install
39
+
40
+ This may fail while building some of the documentation for ffmpeg. If it
41
+ does fail, you can edit the top-level Makefile in the work directory and
42
+ remove the html document targets:
43
+
44
+ --- Makefile 2011-11-20 21:42:28.000000000 -0600
45
+ +++ Makefile 2011-11-20 21:42:34.000000000 -0600
46
+ @@ -113,9 +113,7 @@
47
+ VHOOK_DEPS = $(HOOKS:$(SLIBSUF)=.d)
48
+ depend dep: $(VHOOK_DEPS)
49
+
50
+ -documentation: $(addprefix doc/, ffmpeg-doc.html faq.html ffserver-doc.html \
51
+ - ffplay-doc.html general.html hooks.html \
52
+ - $(ALLMANPAGES))
53
+ +documentation: $(addprefix doc/, $(ALLMANPAGES))
54
+
55
+ doc/%.html: doc/%.texi
56
+ texi2html -monolithic -number $<
57
+
58
+ You may also need to set your DYLD_LIBRARY_PATH to point at /opt/local/lib
59
+ for dlopen() to be able to find the macports compiled libraries.
60
+
19
61
  Usage
20
62
  -----
21
- ruby
63
+
22
64
  require 'ffi-ffmpeg'
23
65
 
24
66
  # Allocate a reader for our video file
@@ -1,12 +1,58 @@
1
1
  require 'ffi'
2
+ require 'rbconfig'
3
+ require 'dl'
2
4
 
3
5
  module FFI
4
6
  module FFmpeg
5
7
  extend FFI::Library
6
8
 
7
- AV_NOPTS_VALUE = 0x8000000000000000
9
+ LIBRARY_FILENAME = {
10
+ :avutil => ENV['FFI_FFMPEG_LIBAVUTIL'],
11
+ :avformat => ENV['FFI_FFMPEG_LIBAVFORMAT'],
12
+ :avcodec => ENV['FFI_FFMPEG_LIBAVCODEC'],
13
+ :swscale => ENV['FFI_FFMPEG_LIBSWSCALE']
14
+ }
15
+
16
+ case Config::CONFIG['target_os']
17
+ when /linux/
18
+ LIBRARY_FILENAME[:avutil] ||= "libavutil.so.49"
19
+ LIBRARY_FILENAME[:avformat] ||= "libavformat.so.52"
20
+ LIBRARY_FILENAME[:avcodec] ||= "libavcodec.so.52"
21
+ LIBRARY_FILENAME[:swscale] ||= "libswscale.so.0"
22
+ when /darwin/
23
+ LIBRARY_FILENAME[:avutil] ||= "libavutil.49"
24
+ LIBRARY_FILENAME[:avformat] ||= "libavformat.52"
25
+ LIBRARY_FILENAME[:avcodec] ||= "libavcodec.52"
26
+
27
+ # Ok, this is stupid, but macports increments the major revision
28
+ # number from 0 to 1 to make some of their code work. We check
29
+ # for this case here and try libswscale.0 failing back to
30
+ # libswscale.1.
31
+ #
32
+ # See this commit for details:
33
+ # https://svn.macports.org/changeset/43550
34
+ LIBRARY_FILENAME[:swscale] ||= begin
35
+ DL.dlopen("libswscale.0.dylib").close
36
+ "libswscale.0"
37
+ rescue DL::DLError
38
+ "libswscale.1"
39
+ end
40
+ end
8
41
 
9
- ffi_lib "libavutil.so.49"
42
+ ###################################################
43
+ # #
44
+ # Definitions #
45
+ # #
46
+ ###################################################
47
+
48
+ AV_NOPTS_VALUE = 0x8000000000000000
49
+ MAX_STREAMS = 20
50
+ MAX_REORDER_DELAY = 16
51
+ AVSEEK_FLAG_BACKWARD = 1
52
+ AVSEEK_FLAG_BYTE = 2
53
+ AVSEEK_FLAG_ANY = 4
54
+ AV_TIME_BASE = 1000000
55
+ AV_PARSER_PTS_NB = 4
10
56
 
11
57
  AVMediaType = enum :unknown, -1,
12
58
  :video,
@@ -15,7 +61,7 @@ module FFI
15
61
  :subtitle,
16
62
  :attachment
17
63
 
18
- BIG_ENDIAN = [1].pack("I") == [1].pack("N")
64
+ big_endian = [1].pack("I") == [1].pack("N")
19
65
  PixelFormat = enum :none, -1,
20
66
  :yuv420p,
21
67
  :yuyv422,
@@ -44,12 +90,12 @@ module FFI
44
90
  :rgb4_byte,
45
91
  :nv12,
46
92
  :nv21,
47
- BIG_ENDIAN ? :rgb32 : :bgr32_1, # :argb
48
- BIG_ENDIAN ? :rgb32_1 : :bgr32, # :rgba
49
- BIG_ENDIAN ? :bgr32 : :rgb32_1, # :abgr
50
- BIG_ENDIAN ? :bgr32_1 : :rgb32, # :bgra
51
- BIG_ENDIAN ? :gray16 : :gray16_1, # :gray16be
52
- BIG_ENDIAN ? :gray16_1 : :gray16, # :gray16le
93
+ big_endian ? :rgb32 : :bgr32_1, # :argb
94
+ big_endian ? :rgb32_1 : :bgr32, # :rgba
95
+ big_endian ? :bgr32 : :rgb32_1, # :abgr
96
+ big_endian ? :bgr32_1 : :rgb32, # :bgra
97
+ big_endian ? :gray16 : :gray16_1, # :gray16be
98
+ big_endian ? :gray16_1 : :gray16, # :gray16le
53
99
  :yuv440p,
54
100
  :yuvj440p,
55
101
  :yuva420p,
@@ -58,115 +104,51 @@ module FFI
58
104
  :vdpau_mpeg2,
59
105
  :vdpau_wmv3,
60
106
  :vdpau_vc1,
61
- BIG_ENDIAN ? :rgb48 : :rgb48_1, # :rgb48be
62
- BIG_ENDIAN ? :rgb48_1 : :rgb48, # :rgb48le
63
- BIG_ENDIAN ? :rgb565 : :rgb565_1, # :rgb565be
64
- BIG_ENDIAN ? :rgb565_1 : :rgb565, # :rgb565le
65
- BIG_ENDIAN ? :rgb555 : :rgb555_1, # :rgb555be
66
- BIG_ENDIAN ? :rgb555_1 : :rgb555, # :rgb555le
67
- BIG_ENDIAN ? :bgr565 : :bgr565_1, # :bgr565be
68
- BIG_ENDIAN ? :bgr565_1 : :bgr565, # :bgr565le
69
- BIG_ENDIAN ? :bgr555 : :bgr555_1, # :bgr555be
70
- BIG_ENDIAN ? :bgr555_1 : :bgr555, # :bgr555le
107
+ big_endian ? :rgb48 : :rgb48_1, # :rgb48be
108
+ big_endian ? :rgb48_1 : :rgb48, # :rgb48le
109
+ big_endian ? :rgb565 : :rgb565_1, # :rgb565be
110
+ big_endian ? :rgb565_1 : :rgb565, # :rgb565le
111
+ big_endian ? :rgb555 : :rgb555_1, # :rgb555be
112
+ big_endian ? :rgb555_1 : :rgb555, # :rgb555le
113
+ big_endian ? :bgr565 : :bgr565_1, # :bgr565be
114
+ big_endian ? :bgr565_1 : :bgr565, # :bgr565le
115
+ big_endian ? :bgr555 : :bgr555_1, # :bgr555be
116
+ big_endian ? :bgr555_1 : :bgr555, # :bgr555le
71
117
  :vaapi_moco,
72
118
  :vaapi_idct,
73
119
  :vaapi_vld,
74
- BIG_ENDIAN ? :yuv420p16_1 : :yuv420p16, # :yuv420p16le
75
- BIG_ENDIAN ? :yuv420p16 : :yuv420p16_1, # :yuv420p16be
76
- BIG_ENDIAN ? :yuv422p16_1 : :yuv422p16, # :yuv422p16le
77
- BIG_ENDIAN ? :yuv422p16 : :yuv422p16_1, # :yuv422p16be
78
- BIG_ENDIAN ? :yuv444p16_1 : :yuv444p16, # :yuv444p16le
79
- BIG_ENDIAN ? :yuv444p16 : :yuv444p16_1, # :yuv444p16be
120
+ big_endian ? :yuv420p16_1 : :yuv420p16, # :yuv420p16le
121
+ big_endian ? :yuv420p16 : :yuv420p16_1, # :yuv420p16be
122
+ big_endian ? :yuv422p16_1 : :yuv422p16, # :yuv422p16le
123
+ big_endian ? :yuv422p16 : :yuv422p16_1, # :yuv422p16be
124
+ big_endian ? :yuv444p16_1 : :yuv444p16, # :yuv444p16le
125
+ big_endian ? :yuv444p16 : :yuv444p16_1, # :yuv444p16be
80
126
  :vdpau_mpeg4,
81
127
  :dxva2_vld,
82
- BIG_ENDIAN ? :rgb444 : :rgb444_1, # :rgb444be
83
- BIG_ENDIAN ? :rgb444_1 : :rgb444, # :rgb444le
84
- BIG_ENDIAN ? :bgr444 : :bgr444_1, # :bgr444be
85
- BIG_ENDIAN ? :bgr444_1 : :bgr444, # :bgr444le
128
+ big_endian ? :rgb444 : :rgb444_1, # :rgb444be
129
+ big_endian ? :rgb444_1 : :rgb444, # :rgb444le
130
+ big_endian ? :bgr444 : :bgr444_1, # :bgr444be
131
+ big_endian ? :bgr444_1 : :bgr444, # :bgr444le
86
132
  :y400a
87
133
 
88
134
  # Not actually an enum in libavutil.h, but we make it one here to
89
135
  # make the api prettier.
90
- AVLogLevel = enum :quiet, -8,
91
- :panic, 0,
92
- :fatal, 8,
93
- :error, 16,
94
- :warning, 24,
95
- :info, 32,
96
- :verbose, 40,
97
- :debug, 48
98
-
99
- attach_function :av_log_get_level, [], AVLogLevel
100
- attach_function :av_log_set_level, [AVLogLevel], :void
101
- attach_function :av_free, [:pointer], :void
102
- attach_function :av_malloc, [:uint], :pointer
103
-
104
- ffi_lib "libavformat.so.52"
105
-
106
- MAX_STREAMS = 20
107
- MAX_REORDER_DELAY = 16
108
-
109
- AVSEEK_FLAG_BACKWARD = 1
110
- AVSEEK_FLAG_BYTE = 2
111
- AVSEEK_FLAG_ANY = 4
112
-
113
- attach_function :av_register_all, [], :void
114
- attach_function :av_open_input_file,
115
- [:pointer, :string, :pointer, :int, :pointer],
116
- :int
117
- attach_function :av_find_stream_info, [:pointer], :int
118
- attach_function :dump_format,
119
- [:pointer, :int, :string, :int],
120
- :void
121
- attach_function :av_read_frame, [:pointer, :pointer], :int
122
- attach_function :av_seek_frame, [:pointer, :int, :long_long, :int], :int
123
- attach_function :av_find_default_stream_index, [ :pointer ], :int
136
+ AVLogLevel = enum :quiet, -8,
137
+ :panic, 0,
138
+ :fatal, 8,
139
+ :error, 16,
140
+ :warning, 24,
141
+ :info, 32,
142
+ :verbose, 40,
143
+ :debug, 48
144
+
145
+ AVDiscard = enum :none, -16,
146
+ :default, 0,
147
+ :nonref, 8,
148
+ :bidir, 16,
149
+ :nonkey, 32,
150
+ :all, 48
124
151
 
125
- # Defining this manually since it's a static inline:
126
- #
127
- # static inline void av_free_packet(AVPacket *pkt)
128
- # {
129
- # if (pkt && pkt->destruct) {
130
- # pkt->destruct(pkt);
131
- # }
132
- # }
133
- #
134
- def self.av_free_packet(pkt)
135
- return unless pkt and pkt[:destruct]
136
-
137
- FFI::Function.new(:void, [:pointer], pkt[:destruct],
138
- :blocking => true).call(pkt)
139
- end
140
-
141
- def av_free_packet(pkt)
142
- FFI::FFmpeg.av_free_packet(pkt)
143
- end
144
-
145
- ffi_lib "libavcodec.so.52"
146
- AV_TIME_BASE = 1000000
147
- AV_PARSER_PTS_NB = 4
148
-
149
- AVDiscard = enum :none, -16,
150
- :default, 0,
151
- :nonref, 8,
152
- :bidir, 16,
153
- :nonkey, 32,
154
- :all, 48
155
-
156
- attach_function :avcodec_find_decoder, [:int], :pointer
157
- attach_function :avcodec_open, [:pointer, :pointer], :int
158
- attach_function :avcodec_alloc_frame, [], :pointer
159
- attach_function :avpicture_get_size, [PixelFormat, :int, :int], :int
160
- attach_function :avpicture_fill,
161
- [:pointer, :pointer, PixelFormat, :int, :int],
162
- :int
163
- attach_function :avcodec_decode_video, [:pointer, :pointer, :pointer,
164
- :pointer, :int], :int,
165
- { :blocking => true }
166
- attach_function :avcodec_default_get_buffer, [:pointer, :pointer], :int
167
- attach_function :avcodec_default_release_buffer, [:pointer, :pointer], :int
168
-
169
- ffi_lib "libswscale.so.0"
170
152
  SWScaleFlags = enum :fast_bilinear, 0x001,
171
153
  :bilinear, 0x002,
172
154
  :bicubic, 0x004,
@@ -179,19 +161,13 @@ module FFI
179
161
  :lanczos, 0x200,
180
162
  :spline, 0x400
181
163
 
182
- attach_function :sws_getContext,
183
- [:int, :int, PixelFormat, :int, :int, PixelFormat,
184
- SWScaleFlags, :pointer, :pointer, :pointer],
185
- :pointer
186
- attach_function :sws_freeContext,
187
- [:pointer],
188
- :void
189
- attach_function :sws_scale,
190
- [:pointer, :pointer, :pointer, :int,
191
- :int, :pointer, :pointer],
192
- :int,
193
- { :blocking => true }
164
+ callback :av_codec_context_get_buffer, [:pointer, :pointer], :int
194
165
 
166
+ ###################################################
167
+ # #
168
+ # Data Structures #
169
+ # #
170
+ ###################################################
195
171
 
196
172
  class AVRational < FFI::Struct
197
173
  layout :num, :int,
@@ -314,8 +290,6 @@ module FFI
314
290
  end
315
291
  end
316
292
 
317
- callback :av_codec_context_get_buffer, [:pointer, :pointer], :int
318
-
319
293
  class AVCodecContext < FFI::Struct
320
294
  layout :av_class, :pointer,
321
295
  :bit_rate, :int,
@@ -625,6 +599,83 @@ module FFI
625
599
  :reordered_opaque, :long_long
626
600
  end
627
601
 
602
+ ###################################################
603
+ # #
604
+ # Functions #
605
+ # #
606
+ ###################################################
607
+
608
+ ffi_lib LIBRARY_FILENAME[:avutil]
609
+
610
+ attach_function :av_log_get_level, [], AVLogLevel
611
+ attach_function :av_log_set_level, [AVLogLevel], :void
612
+ attach_function :av_free, [:pointer], :void
613
+ attach_function :av_malloc, [:uint], :pointer
614
+
615
+ ffi_lib LIBRARY_FILENAME[:avformat]
616
+ attach_function :av_register_all, [], :void
617
+ attach_function :av_open_input_file,
618
+ [:pointer, :string, :pointer, :int, :pointer],
619
+ :int
620
+ attach_function :av_find_stream_info, [:pointer], :int
621
+ attach_function :dump_format,
622
+ [:pointer, :int, :string, :int],
623
+ :void
624
+ attach_function :av_read_frame, [:pointer, :pointer], :int
625
+ attach_function :av_seek_frame, [:pointer, :int, :long_long, :int], :int
626
+ attach_function :av_find_default_stream_index, [ :pointer ], :int
627
+
628
+ # This function is inlined in avformat, defining it here
629
+ # for convenience.
630
+ #
631
+ # Original definition:
632
+ # static inline void av_free_packet(AVPacket *pkt)
633
+ # {
634
+ # if (pkt && pkt->destruct) {
635
+ # pkt->destruct(pkt);
636
+ # }
637
+ # }
638
+ #
639
+ def self.av_free_packet(pkt)
640
+ return unless pkt and pkt[:destruct]
641
+
642
+ FFI::Function.new(:void, [:pointer], pkt[:destruct],
643
+ :blocking => true).call(pkt)
644
+ end
645
+
646
+ def av_free_packet(pkt)
647
+ FFI::FFmpeg.av_free_packet(pkt)
648
+ end
649
+
650
+ ffi_lib LIBRARY_FILENAME[:avcodec]
651
+ attach_function :avcodec_find_decoder, [:int], :pointer
652
+ attach_function :avcodec_open, [:pointer, :pointer], :int
653
+ attach_function :avcodec_alloc_frame, [], :pointer
654
+ attach_function :avpicture_get_size, [PixelFormat, :int, :int], :int
655
+ attach_function :avpicture_fill,
656
+ [:pointer, :pointer, PixelFormat, :int, :int],
657
+ :int
658
+ attach_function :avcodec_decode_video, [:pointer, :pointer, :pointer,
659
+ :pointer, :int], :int,
660
+ { :blocking => true }
661
+ attach_function :avcodec_default_get_buffer, [:pointer, :pointer], :int
662
+ attach_function :avcodec_default_release_buffer, [:pointer, :pointer], :int
663
+
664
+ ffi_lib LIBRARY_FILENAME[:swscale]
665
+ attach_function :sws_getContext,
666
+ [:int, :int, PixelFormat, :int, :int, PixelFormat,
667
+ SWScaleFlags, :pointer, :pointer, :pointer],
668
+ :pointer
669
+ attach_function :sws_freeContext,
670
+ [:pointer],
671
+ :void
672
+ attach_function :sws_scale,
673
+ [:pointer, :pointer, :pointer, :int,
674
+ :int, :pointer, :pointer],
675
+ :int,
676
+ { :blocking => true }
677
+
678
+ callback :av_codec_context_get_buffer, [:pointer, :pointer], :int
628
679
 
629
680
  end # module FFmpeg
630
681
  end # module FFI
@@ -27,7 +27,7 @@ class FFmpeg::Reader
27
27
 
28
28
  # Video duration in (fractional) seconds
29
29
  def duration
30
- @av_format_ctx[:duration].to_f / AV_TIME_BASE
30
+ @duration ||= @av_format_ctx[:duration].to_f / AV_TIME_BASE
31
31
  end
32
32
 
33
33
  def each_frame(&block)
@@ -1,3 +1,3 @@
1
1
  module FFmpeg
2
- VERSION = "0.7"
2
+ VERSION = "0.8"
3
3
  end
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-ffmpeg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0beae74ee3d7
5
- prerelease: 5
4
+ version: 0.8.525a2f4a3ce0
5
+ prerelease: 7
6
6
  platform: ruby
7
7
  authors:
8
8
  - David M. Lary
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-06 00:00:00.000000000Z
12
+ date: 2011-11-26 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
16
- requirement: &14840620 !ruby/object:Gem::Requirement
16
+ requirement: &17824180 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *14840620
24
+ version_requirements: *17824180
25
25
  description: Ruby FFI bindings for libavformat, libavcodec, libavutil, and libswscale
26
26
  email:
27
27
  - dmlary@gmail.com