ffruby 0.0.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,44 @@
1
+ = FFruby
2
+
3
+ FFruby is a Ruby interface to FFmpeg's libavformat and libavcodec. It allows you to query metadata from a wide variety of media files through some simple classes. FFmpeg's libraries are required and also the development headers if building.
4
+
5
+ == FAQ
6
+
7
+ === Where do I go for support and contributions?
8
+
9
+ We are hosted by RubyForge at http://rubyforge.org/projects/ffruby.
10
+
11
+ === Where do I get the latest version?
12
+
13
+ It should be available through RubyGems as ffruby. Failing that, try RubyForge.
14
+
15
+ === What about transcoding?
16
+
17
+ I still start FFmpeg through a subshell when I need to transcode something. There is little to be gained from doing this within Ruby itself. Other than requiring a fair amount of work, one major disadvantage is that if FFmpeg segfaults (which it has been known to do), it will bring the entire Ruby process down with it, which is probably something you want to avoid.
18
+
19
+ === So what is this good for?
20
+
21
+ Being able to reliably read the source file's metadata is very important in deciding how it should be transcoded, or whether it even needs to be transcoded at all. This is not something you want to rely on a subshell for as that would involve awkward parsing of FFmpeg's output, which does change between versions.
22
+
23
+ == Changes
24
+
25
+ === 0.2.0 (2010/11/24)
26
+
27
+ - Reworked class structure under common FFruby module.
28
+ - Compatibility with old and new FFmpeg versions.
29
+ - Methods to query supported formats and codecs.
30
+ - Safer memory handling.
31
+ - RDoc documentation.
32
+ - Repackaged using Jeweler.
33
+
34
+ === 0.1 (2007/07/26), 0.0.1 (2008/01/11)
35
+
36
+ - More or less the same original version. Latter was the initial gem release.
37
+
38
+ == Authors
39
+
40
+ - James Le Cuirot <chewi@aura-online.co.uk>
41
+
42
+ == Copyright
43
+
44
+ Copyright (c) 2007-2010 James Le Cuirot. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,147 +1,48 @@
1
- require "rake"
2
- require "rake/clean"
3
- require "rake/gempackagetask"
4
- require "rake/rdoctask"
5
- require "rake/testtask"
6
- require "fileutils"
7
- require "yaml"
8
- include FileUtils
9
- require "lib/ffruby/version"
10
-
11
- GEM_NAME = "ffruby"
12
- REV = nil
13
-
14
- GEM_VERSION = FFruby::VERSION::STRING + (REV ? ".#{REV}" : "")
15
- CLEAN.include [
16
- "ext/ffruby/*.{bundle,so,obj,pdb,lib,def,exp}",
17
- "ext/ffruby/Makefile",
18
- "**/.*.sw?",
19
- "*.gem",
20
- ".config"
21
- ]
22
- RDOC_OPTS = ["--quiet", "--title", "FFruby Reference", "--main", "README", "--inline-source"]
23
-
24
- @config_file = "~/.rubyforge/user-config.yml"
25
- @config = nil
26
- def rubyforge_username
27
- unless @config
28
- begin
29
- @config = YAML.load(File.read(File.expand_path(@config_file)))
30
- rescue
31
- puts <<-EOS
32
- ERROR: No rubyforge config file found: #{@config_file}"
33
- Run 'rubyforge setup' to prepare your env for access to Rubyforge
34
- - See http://newgem.rubyforge.org/rubyforge.html for more details
35
- EOS
36
- exit
37
- end
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ RDOC_FILES = [ "README.rdoc", "ext/ffruby/ffruby{file,stream,}.c" ]
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = "ffruby"
10
+ gem.version = File.read('VERSION')
11
+ gem.license = "LGPL-2.1"
12
+ gem.author = "James Le Cuirot"
13
+ gem.email = "chewi@aura-online.co.uk"
14
+ gem.rubyforge_project = "ffruby"
15
+ gem.homepage = "http://rubyforge.org/projects/ffruby/"
16
+ gem.summary = "A Ruby interface to FFmpeg's libavformat and libavcodec."
17
+ gem.description = "A Ruby interface to FFmpeg's libavformat and libavcodec. It allows you to query metadata from a wide variety of media files through some simple classes."
18
+ gem.requirements = "FFmpeg libraries and also development headers if building."
19
+ gem.files = RDOC_FILES + [ "LICENSE", "Rakefile", "VERSION", "ext/ffruby/{extconf.rb,ffruby.h}" ]
20
+ gem.extra_rdoc_files = RDOC_FILES
38
21
  end
39
- @rubyforge_username ||= @config["username"]
40
- end
41
-
42
- desc "Does a full compile, test run"
43
- task :default => [:compile, :test]
44
-
45
- desc "Compiles all extensions"
46
- task :compile => [:ffruby] do
47
- if Dir.glob(File.join("lib","ffruby*.*")).length == 0
48
- STDERR.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
49
- STDERR.puts "Gem actually failed to build. Your system is"
50
- STDERR.puts "NOT configured properly to build ffruby."
51
- STDERR.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
52
- exit(1)
22
+ Jeweler::GemcutterTasks.new
23
+ Jeweler::RubyforgeTasks.new do |rubyforge|
24
+ rubyforge.doc_task = "rdoc"
25
+ rubyforge.remote_doc_path = ""
53
26
  end
27
+ rescue LoadError
28
+ puts "To prepare a gem, please install the jeweler gem."
54
29
  end
55
30
 
56
- desc "Packages up FFruby."
57
- task :package => [:clean]
58
-
59
- desc "Releases packages for all FFruby packages and platforms."
60
- task :release => [:package]
61
-
62
- desc "Run all the tests"
63
- Rake::TestTask.new do | test_task |
64
- test_task.libs << "test"
65
- test_task.test_files = FileList["test/test_*.rb"]
66
- test_task.verbose = true
67
- end
68
-
69
- Rake::RDocTask.new do | rdoc |
70
- rdoc.rdoc_dir = "doc/rdoc"
71
- rdoc.options += RDOC_OPTS
72
- rdoc.main = "README"
73
- rdoc.rdoc_files.add ["README", "lib/**/*.rb"]
74
- end
75
-
76
- spec =
77
- Gem::Specification.new do | specification |
78
- specification.name = GEM_NAME
79
- specification.version = GEM_VERSION
80
- specification.platform = Gem::Platform::RUBY
81
- specification.has_rdoc = true
82
- specification.rdoc_options += RDOC_OPTS
83
- specification.extra_rdoc_files = ["README"]
84
- specification.summary = "a library that does something with media files!"
85
- specification.description = specification.summary
86
- specification.author = "ffruby: James Le Cuirot, gem: Wayne E. Seguin"
87
- specification.email = "wayneeseguin at gmail dot com"
88
- specification.homepage = "ffruby.rubyforge.org"
89
-
90
- specification.files = %w(README Rakefile) +
91
- Dir.glob("{bin,doc,test,lib,extras}/**/*") +
92
- Dir.glob("ext/**/*.{h,c,rb,rl}") +
93
- %w[ext/ffruby/ffruby.c] # needed because it's generated later
94
-
95
- specification.require_path = "lib"
96
- specification.extensions = FileList["ext/**/extconf.rb"].to_a
97
- specification.bindir = "bin"
98
- end
99
-
100
- Rake::GemPackageTask.new(spec) do | package |
101
- package.need_tar = true
102
- package.gem_spec = spec
103
- end
104
-
105
- extension = "ffruby"
106
- ext = "ext/ffruby"
107
- ext_so = "#{ext}/#{extension}.#{Config::CONFIG["DLEXT"]}"
108
- ext_files = FileList[
109
- "#{ext}/*.c",
110
- "#{ext}/*.h",
111
- "#{ext}/*.rl",
112
- "#{ext}/extconf.rb",
113
- "#{ext}/Makefile",
114
- "lib"
115
- ]
116
-
117
- task "lib" do
118
- directory "lib"
119
- end
120
-
121
- desc "Builds just the #{extension} extension"
122
- task extension.to_sym => ["#{ext}/Makefile", ext_so ]
123
-
124
- file "#{ext}/Makefile" => ["#{ext}/extconf.rb"] do
125
- #Dir.chdir(ext) do
126
- if `uname.a`.match(/Darwin Kernel Version 9\.0\.0:.*i386/)
127
- ENV["ARCHFLAGS"] = "-arch i386"
128
- end
129
- ruby "extconf.rb"
130
- #end
131
- end
132
-
133
- file ext_so => ext_files do
134
- Dir.chdir(ext) do
135
- sh(PLATFORM =~ /win32/ ? "nmake" : "make")
31
+ begin
32
+ require 'rake/rdoctask'
33
+ Rake::RDocTask.new do |rdoc|
34
+ rdoc.rdoc_dir = 'rdoc'
35
+ rdoc.title = "FFruby " + File.read('VERSION')
36
+ rdoc.rdoc_files.include *RDOC_FILES
136
37
  end
137
- cp ext_so, "lib"
138
- end
139
-
140
- task :install do
141
- sh %{rake package}
142
- sh %{sudo gem install pkg/#{GEM_NAME}-#{GEM_VERSION}}
38
+ rescue LoadError
39
+ puts "To build the documentation, please install the rdoc gem."
143
40
  end
144
41
 
145
- task :uninstall => [:clean] do
146
- sh %{sudo gem uninstall #{GEM_NAME}}
42
+ begin
43
+ require 'rake/extensiontask'
44
+ Rake::ExtensionTask.new('ffruby')
45
+ task :default => :compile
46
+ rescue LoadError
47
+ puts "To build the library, please install the rake-compiler gem."
147
48
  end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -1,13 +1,26 @@
1
- #!/bin/env ruby
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  require "mkmf"
4
+
4
5
  dir_config("ffmpeg")
6
+
7
+ %w( avformat avcodec ).each do |lib|
8
+ header = "#{lib}.h"
9
+ result = false
10
+
11
+ [ "lib#{lib}", "ffmpeg" ].each do |dir|
12
+ path = File.join(dir, header)
13
+
14
+ if checking_for(path) { try_cpp(cpp_include(path)) }
15
+ result = path
16
+ break
17
+ end
18
+ end
19
+
20
+ $defs.push "-D#{lib.upcase}_H_PATH=\"<#{result || header}>\""
21
+ end
22
+
5
23
  have_library("avformat")
6
24
  have_library("avcodec")
7
- create_makefile("ffruby")
8
25
 
9
- # avcodec is not built for ppc
10
- if `uname -a`.match(/i386/)
11
- `sed '1,$s/-arch ppc//' Makefile >> ./Makefile.tmp`
12
- `mv ./Makefile.tmp Makefile`
13
- end
26
+ create_makefile("ffruby")
data/ext/ffruby/ffruby.c CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2007 James Le Cuirot
2
+ * Copyright (c) 2007-2010 James Le Cuirot
3
3
  *
4
4
  * This file is part of FFruby.
5
5
  *
@@ -18,18 +18,53 @@
18
18
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
19
  */
20
20
 
21
- #define _GNU_SOURCE
22
- #include <ruby.h>
23
- #include <ffmpeg/avformat.h>
24
- #include <ffmpeg/avcodec.h>
21
+ #include "ffruby.h"
25
22
 
26
23
  extern void Init_ffrf();
27
24
  extern void Init_ffrs();
28
25
 
26
+ /* Returns an array of the input and output formats supported by
27
+ * FFmpeg. This method will hopefully be expanded to return more than
28
+ * just names in the future. */
29
+ static VALUE ffruby_formats(VALUE self, VALUE klass)
30
+ {
31
+ AVInputFormat *ifmt;
32
+ AVOutputFormat *ofmt;
33
+ VALUE array = rb_ary_new();
34
+
35
+ for (ifmt = av_iformat_next(NULL); ifmt; ifmt = av_iformat_next(ifmt))
36
+ rb_ary_push(array, rb_str_new2(ifmt->name));
37
+
38
+ for (ofmt = av_oformat_next(NULL); ofmt; ofmt = av_oformat_next(ofmt))
39
+ rb_ary_push(array, rb_str_new2(ofmt->name));
40
+
41
+ return rb_funcall(rb_funcall(array, rb_intern("uniq"), 0), rb_intern("sort"), 0);
42
+ }
43
+
44
+ /* Returns an array of the codecs supported by FFmpeg. This method
45
+ * will hopefully be expanded to return more than just names in the
46
+ * future. */
47
+ static VALUE ffruby_codecs(VALUE self, VALUE klass)
48
+ {
49
+ AVCodec *codec;
50
+ VALUE array = rb_ary_new();
51
+
52
+ for (codec = av_codec_next(NULL); codec; codec = av_codec_next(codec))
53
+ rb_ary_push(array, rb_str_new2(codec->name));
54
+
55
+ return rb_funcall(rb_funcall(array, rb_intern("uniq"), 0), rb_intern("sort"), 0);
56
+ }
57
+
58
+ /* Top level module for the FFruby classes. Provides access to
59
+ * information about FFmpeg itself. */
29
60
  void Init_ffruby()
30
61
  {
31
62
  av_register_all();
32
-
63
+
64
+ mFFruby = rb_define_module("FFruby");
65
+ rb_define_module_function(mFFruby, "formats", ffruby_formats, 0);
66
+ rb_define_module_function(mFFruby, "codecs", ffruby_codecs, 0);
67
+
33
68
  Init_ffrf();
34
69
  Init_ffrs();
35
70
  }
@@ -0,0 +1,34 @@
1
+ /*
2
+ * Copyright (c) 2007-2010 James Le Cuirot
3
+ *
4
+ * This file is part of FFruby.
5
+ *
6
+ * FFruby is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFruby is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+ #ifndef _FFRUBY_H_
22
+ #define _FFRUBY_H_
23
+
24
+ #include <ruby.h>
25
+ #include AVFORMAT_H_PATH
26
+ #include AVCODEC_H_PATH
27
+
28
+ VALUE mFFruby;
29
+ VALUE cFFrubyFile;
30
+ VALUE cFFrubyStream;
31
+ VALUE cFFrubyVideoStream;
32
+ VALUE cFFrubyAudioStream;
33
+
34
+ #endif
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2007 James Le Cuirot
2
+ * Copyright (c) 2007-2010 James Le Cuirot
3
3
  *
4
4
  * This file is part of FFruby.
5
5
  *
@@ -18,21 +18,17 @@
18
18
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
19
  */
20
20
 
21
- #define _GNU_SOURCE
22
- #include <ruby.h>
23
- #include <ffmpeg/avformat.h>
24
- #include <ffmpeg/avcodec.h>
21
+ #include "ffruby.h"
22
+ #include <string.h>
25
23
  #include <stdio.h>
26
24
 
27
- VALUE cFFrubyFile;
28
-
29
- extern VALUE cFFrubyVideoStream;
30
- extern VALUE cFFrubyAudioStream;
25
+ /* Satisfy stupid RDoc. This hopefully gets optimised away. */
26
+ static void rdoc() { mFFruby = rb_define_module("FFruby"); }
31
27
 
32
28
  static void ffrf_free(AVFormatContext *fmt)
33
29
  {
34
30
  unsigned int i;
35
-
31
+
36
32
  if (fmt != NULL)
37
33
  {
38
34
  for (i = 0; i < fmt->nb_streams; i++)
@@ -40,11 +36,16 @@ static void ffrf_free(AVFormatContext *fmt)
40
36
  if (fmt->streams[i]->codec->codec != NULL)
41
37
  avcodec_close(fmt->streams[i]->codec);
42
38
  }
43
-
39
+
44
40
  av_close_input_file(fmt);
45
41
  }
46
42
  }
47
43
 
44
+ static VALUE ffrf_alloc(VALUE klass)
45
+ {
46
+ return Data_Wrap_Struct(klass, 0, ffrf_free, NULL);
47
+ }
48
+
48
49
  static AVFormatContext* ffrf_get_fmt(VALUE self)
49
50
  {
50
51
  AVFormatContext *fmt;
@@ -52,97 +53,104 @@ static AVFormatContext* ffrf_get_fmt(VALUE self)
52
53
  return fmt;
53
54
  }
54
55
 
55
- static VALUE ffrf_alloc(VALUE klass)
56
- {
57
- return Data_Wrap_Struct(klass, 0, ffrf_free, NULL);
58
- }
59
-
56
+ /* Returns the title string. */
60
57
  static VALUE ffrf_title(VALUE self)
61
58
  {
62
59
  AVFormatContext *fmt = ffrf_get_fmt(self);
63
60
  return rb_str_new2(fmt->title);
64
61
  }
65
62
 
63
+ /* Returns the author string. */
66
64
  static VALUE ffrf_author(VALUE self)
67
65
  {
68
66
  AVFormatContext *fmt = ffrf_get_fmt(self);
69
67
  return rb_str_new2(fmt->author);
70
68
  }
71
69
 
70
+ /* Returns the copyright string. */
72
71
  static VALUE ffrf_copyright(VALUE self)
73
72
  {
74
73
  AVFormatContext *fmt = ffrf_get_fmt(self);
75
74
  return rb_str_new2(fmt->copyright);
76
75
  }
77
76
 
77
+ /* Returns the comment string. */
78
78
  static VALUE ffrf_comment(VALUE self)
79
79
  {
80
80
  AVFormatContext *fmt = ffrf_get_fmt(self);
81
81
  return rb_str_new2(fmt->comment);
82
82
  }
83
83
 
84
+ /* Returns the album string. */
84
85
  static VALUE ffrf_album(VALUE self)
85
86
  {
86
87
  AVFormatContext *fmt = ffrf_get_fmt(self);
87
88
  return rb_str_new2(fmt->album);
88
89
  }
89
90
 
91
+ /* Returns the genre string. */
90
92
  static VALUE ffrf_genre(VALUE self)
91
93
  {
92
94
  AVFormatContext *fmt = ffrf_get_fmt(self);
93
95
  return rb_str_new2(fmt->genre);
94
96
  }
95
97
 
98
+ /* Returns the year. */
96
99
  static VALUE ffrf_year(VALUE self)
97
100
  {
98
101
  AVFormatContext *fmt = ffrf_get_fmt(self);
99
102
  return INT2NUM(fmt->year);
100
103
  }
101
104
 
105
+ /* Returns the track number. */
102
106
  static VALUE ffrf_track(VALUE self)
103
107
  {
104
108
  AVFormatContext *fmt = ffrf_get_fmt(self);
105
109
  return INT2NUM(fmt->track);
106
110
  }
107
111
 
112
+ /* Returns the duration in seconds as a float. */
108
113
  static VALUE ffrf_duration(VALUE self)
109
114
  {
110
115
  AVFormatContext *fmt = ffrf_get_fmt(self);
111
116
  return rb_float_new((double) fmt->duration / (double) AV_TIME_BASE);
112
117
  }
113
118
 
119
+ /* Returns the bit rate. */
114
120
  static VALUE ffrf_bit_rate(VALUE self)
115
121
  {
116
122
  AVFormatContext *fmt = ffrf_get_fmt(self);
117
123
  return INT2NUM(fmt->bit_rate);
118
124
  }
119
125
 
126
+ /* Returns the format name. */
120
127
  static VALUE ffrf_format(VALUE self)
121
128
  {
122
129
  AVFormatContext *fmt = ffrf_get_fmt(self);
123
130
  return rb_str_new2(fmt->iformat->name);
124
131
  }
125
132
 
133
+ /* Returns an array of streams contained within this file. */
126
134
  static VALUE ffrf_streams(VALUE self)
127
135
  {
128
136
  unsigned int i;
129
137
  AVFormatContext *fmt;
130
138
  VALUE streams;
131
139
  VALUE* args;
132
-
140
+
133
141
  if ((streams = rb_iv_get(self, "@streams")) == Qnil)
134
142
  {
135
143
  fmt = ffrf_get_fmt(self);
136
144
  streams = rb_ary_new();
137
145
  rb_iv_set(self, "@streams", streams);
138
-
146
+
139
147
  args = (VALUE*) ALLOCA_N(VALUE*, 2);
140
148
  args[0] = self;
141
-
149
+
142
150
  for (i = 0; i < fmt->nb_streams; i++)
143
151
  {
144
152
  args[1] = INT2FIX(i);
145
-
153
+
146
154
  switch (fmt->streams[i]->codec->codec_type)
147
155
  {
148
156
  case CODEC_TYPE_VIDEO:
@@ -156,7 +164,7 @@ static VALUE ffrf_streams(VALUE self)
156
164
  }
157
165
  }
158
166
  }
159
-
167
+
160
168
  return streams;
161
169
  }
162
170
 
@@ -166,60 +174,77 @@ static VALUE ffrf_av_streams(VALUE self, VALUE klass)
166
174
  VALUE streams;
167
175
  VALUE typed_streams;
168
176
  unsigned int i;
169
-
177
+
170
178
  streams = rb_funcall(self, rb_intern("streams"), 0);
171
179
  typed_streams = rb_ary_new();
172
180
  Check_Type(streams, T_ARRAY);
173
-
181
+
174
182
  for (i = 0; i < RARRAY(streams)->len; i++)
175
183
  {
176
184
  if (rb_obj_is_kind_of((stream = rb_ary_entry(streams, i)), klass))
177
185
  rb_ary_push(typed_streams, stream);
178
186
  }
179
-
187
+
180
188
  return typed_streams;
181
189
  }
182
190
 
191
+ /* Returns an array of video streams contained within this file. */
183
192
  static VALUE ffrf_video_streams(VALUE self)
184
193
  {
185
194
  return ffrf_av_streams(self, cFFrubyVideoStream);
186
195
  }
187
196
 
197
+ /* Returns an array of audio streams contained within this file. */
188
198
  static VALUE ffrf_audio_streams(VALUE self)
189
199
  {
190
200
  return ffrf_av_streams(self, cFFrubyAudioStream);
191
201
  }
192
202
 
203
+ /* call-seq:
204
+ * new(filename) -> FFruby::File
205
+ *
206
+ * Creates an FFruby::File instance using the given filename. */
193
207
  static VALUE ffrf_initialize(VALUE self, VALUE filename)
194
208
  {
209
+ size_t len;
195
210
  char* msg;
196
211
  AVFormatContext *fmt;
197
212
  VALUE exception;
213
+
198
214
  VALUE filename_str = rb_funcall(filename, rb_intern("to_s"), 0);
199
-
200
- if (av_open_input_file(&fmt, RSTRING(filename_str)->ptr, NULL, 0, NULL) != 0)
215
+ char* filename_ptr = RSTRING(filename_str)->ptr;
216
+
217
+ if (av_open_input_file(&fmt, filename_ptr, NULL, 0, NULL) != 0)
201
218
  {
202
- asprintf(&msg, "Cannot open file %s!", RSTRING(filename_str)->ptr);
219
+ len = strlen("Cannot open file !") + strlen(filename_ptr) + 1;
220
+ msg = ALLOC_N(char, len);
221
+ snprintf(msg, len, "Cannot open file %s!", filename_ptr);
203
222
  exception = rb_exc_new2(rb_eIOError, msg);
204
223
  free(msg);
205
224
  rb_exc_raise(exception);
206
225
  }
207
-
226
+
208
227
  if (av_find_stream_info(fmt) < 0)
209
228
  {
210
- asprintf(&msg, "Problem reading file %s!", RSTRING(filename_str)->ptr);
229
+ len = strlen("Problem reading file !") + strlen(filename_ptr) + 1;
230
+ msg = ALLOC_N(char, len);
231
+ snprintf(msg, len, "Problem reading file %s!", filename_ptr);
211
232
  exception = rb_exc_new2(rb_eIOError, msg);
212
233
  free(msg);
213
234
  rb_exc_raise(exception);
214
235
  }
215
-
236
+
216
237
  DATA_PTR(self) = fmt;
217
238
  return self;
218
239
  }
219
240
 
241
+ /* Document-class: FFruby::File
242
+ *
243
+ * An interface to FFmpeg on existing files. Provides access to
244
+ * metadata and stream instances. */
220
245
  void Init_ffrf()
221
246
  {
222
- cFFrubyFile = rb_define_class("FFrubyFile", rb_cObject);
247
+ cFFrubyFile = rb_define_class_under(mFFruby, "File", rb_cObject);
223
248
  rb_define_alloc_func(cFFrubyFile, ffrf_alloc);
224
249
  rb_define_method(cFFrubyFile, "initialize", ffrf_initialize, 1);
225
250
  rb_define_method(cFFrubyFile, "title", ffrf_title, 0);