ffruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +1 -0
- data/Rakefile +147 -0
- data/ext/ffruby/extconf.rb +13 -0
- data/ext/ffruby/ffruby.c +35 -0
- data/ext/ffruby/ffrubyfile.c +239 -0
- data/ext/ffruby/ffrubystream.c +196 -0
- data/lib/ffruby/version.rb +9 -0
- metadata +65 -0
data/README
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
README
|
data/Rakefile
ADDED
@@ -0,0 +1,147 @@
|
|
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
|
38
|
+
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)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
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")
|
136
|
+
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}}
|
143
|
+
end
|
144
|
+
|
145
|
+
task :uninstall => [:clean] do
|
146
|
+
sh %{sudo gem uninstall #{GEM_NAME}}
|
147
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
|
3
|
+
require "mkmf"
|
4
|
+
dir_config("ffmpeg")
|
5
|
+
have_library("avformat")
|
6
|
+
have_library("avcodec")
|
7
|
+
create_makefile("ffruby")
|
8
|
+
|
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
|
data/ext/ffruby/ffruby.c
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2007 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
|
+
#define _GNU_SOURCE
|
22
|
+
#include <ruby.h>
|
23
|
+
#include <ffmpeg/avformat.h>
|
24
|
+
#include <ffmpeg/avcodec.h>
|
25
|
+
|
26
|
+
extern void Init_ffrf();
|
27
|
+
extern void Init_ffrs();
|
28
|
+
|
29
|
+
void Init_ffruby()
|
30
|
+
{
|
31
|
+
av_register_all();
|
32
|
+
|
33
|
+
Init_ffrf();
|
34
|
+
Init_ffrs();
|
35
|
+
}
|
@@ -0,0 +1,239 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2007 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
|
+
#define _GNU_SOURCE
|
22
|
+
#include <ruby.h>
|
23
|
+
#include <ffmpeg/avformat.h>
|
24
|
+
#include <ffmpeg/avcodec.h>
|
25
|
+
#include <stdio.h>
|
26
|
+
|
27
|
+
VALUE cFFrubyFile;
|
28
|
+
|
29
|
+
extern VALUE cFFrubyVideoStream;
|
30
|
+
extern VALUE cFFrubyAudioStream;
|
31
|
+
|
32
|
+
static void ffrf_free(AVFormatContext *fmt)
|
33
|
+
{
|
34
|
+
unsigned int i;
|
35
|
+
|
36
|
+
if (fmt != NULL)
|
37
|
+
{
|
38
|
+
for (i = 0; i < fmt->nb_streams; i++)
|
39
|
+
{
|
40
|
+
if (fmt->streams[i]->codec->codec != NULL)
|
41
|
+
avcodec_close(fmt->streams[i]->codec);
|
42
|
+
}
|
43
|
+
|
44
|
+
av_close_input_file(fmt);
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
static AVFormatContext* ffrf_get_fmt(VALUE self)
|
49
|
+
{
|
50
|
+
AVFormatContext *fmt;
|
51
|
+
Data_Get_Struct(self, AVFormatContext, fmt);
|
52
|
+
return fmt;
|
53
|
+
}
|
54
|
+
|
55
|
+
static VALUE ffrf_alloc(VALUE klass)
|
56
|
+
{
|
57
|
+
return Data_Wrap_Struct(klass, 0, ffrf_free, NULL);
|
58
|
+
}
|
59
|
+
|
60
|
+
static VALUE ffrf_title(VALUE self)
|
61
|
+
{
|
62
|
+
AVFormatContext *fmt = ffrf_get_fmt(self);
|
63
|
+
return rb_str_new2(fmt->title);
|
64
|
+
}
|
65
|
+
|
66
|
+
static VALUE ffrf_author(VALUE self)
|
67
|
+
{
|
68
|
+
AVFormatContext *fmt = ffrf_get_fmt(self);
|
69
|
+
return rb_str_new2(fmt->author);
|
70
|
+
}
|
71
|
+
|
72
|
+
static VALUE ffrf_copyright(VALUE self)
|
73
|
+
{
|
74
|
+
AVFormatContext *fmt = ffrf_get_fmt(self);
|
75
|
+
return rb_str_new2(fmt->copyright);
|
76
|
+
}
|
77
|
+
|
78
|
+
static VALUE ffrf_comment(VALUE self)
|
79
|
+
{
|
80
|
+
AVFormatContext *fmt = ffrf_get_fmt(self);
|
81
|
+
return rb_str_new2(fmt->comment);
|
82
|
+
}
|
83
|
+
|
84
|
+
static VALUE ffrf_album(VALUE self)
|
85
|
+
{
|
86
|
+
AVFormatContext *fmt = ffrf_get_fmt(self);
|
87
|
+
return rb_str_new2(fmt->album);
|
88
|
+
}
|
89
|
+
|
90
|
+
static VALUE ffrf_genre(VALUE self)
|
91
|
+
{
|
92
|
+
AVFormatContext *fmt = ffrf_get_fmt(self);
|
93
|
+
return rb_str_new2(fmt->genre);
|
94
|
+
}
|
95
|
+
|
96
|
+
static VALUE ffrf_year(VALUE self)
|
97
|
+
{
|
98
|
+
AVFormatContext *fmt = ffrf_get_fmt(self);
|
99
|
+
return INT2NUM(fmt->year);
|
100
|
+
}
|
101
|
+
|
102
|
+
static VALUE ffrf_track(VALUE self)
|
103
|
+
{
|
104
|
+
AVFormatContext *fmt = ffrf_get_fmt(self);
|
105
|
+
return INT2NUM(fmt->track);
|
106
|
+
}
|
107
|
+
|
108
|
+
static VALUE ffrf_duration(VALUE self)
|
109
|
+
{
|
110
|
+
AVFormatContext *fmt = ffrf_get_fmt(self);
|
111
|
+
return rb_float_new((double) fmt->duration / (double) AV_TIME_BASE);
|
112
|
+
}
|
113
|
+
|
114
|
+
static VALUE ffrf_bit_rate(VALUE self)
|
115
|
+
{
|
116
|
+
AVFormatContext *fmt = ffrf_get_fmt(self);
|
117
|
+
return INT2NUM(fmt->bit_rate);
|
118
|
+
}
|
119
|
+
|
120
|
+
static VALUE ffrf_format(VALUE self)
|
121
|
+
{
|
122
|
+
AVFormatContext *fmt = ffrf_get_fmt(self);
|
123
|
+
return rb_str_new2(fmt->iformat->name);
|
124
|
+
}
|
125
|
+
|
126
|
+
static VALUE ffrf_streams(VALUE self)
|
127
|
+
{
|
128
|
+
unsigned int i;
|
129
|
+
AVFormatContext *fmt;
|
130
|
+
VALUE streams;
|
131
|
+
VALUE* args;
|
132
|
+
|
133
|
+
if ((streams = rb_iv_get(self, "@streams")) == Qnil)
|
134
|
+
{
|
135
|
+
fmt = ffrf_get_fmt(self);
|
136
|
+
streams = rb_ary_new();
|
137
|
+
rb_iv_set(self, "@streams", streams);
|
138
|
+
|
139
|
+
args = (VALUE*) ALLOCA_N(VALUE*, 2);
|
140
|
+
args[0] = self;
|
141
|
+
|
142
|
+
for (i = 0; i < fmt->nb_streams; i++)
|
143
|
+
{
|
144
|
+
args[1] = INT2FIX(i);
|
145
|
+
|
146
|
+
switch (fmt->streams[i]->codec->codec_type)
|
147
|
+
{
|
148
|
+
case CODEC_TYPE_VIDEO:
|
149
|
+
rb_ary_push(streams, rb_class_new_instance(2, args, cFFrubyVideoStream));
|
150
|
+
break;
|
151
|
+
case CODEC_TYPE_AUDIO:
|
152
|
+
rb_ary_push(streams, rb_class_new_instance(2, args, cFFrubyAudioStream));
|
153
|
+
break;
|
154
|
+
default:
|
155
|
+
break;
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
159
|
+
|
160
|
+
return streams;
|
161
|
+
}
|
162
|
+
|
163
|
+
static VALUE ffrf_av_streams(VALUE self, VALUE klass)
|
164
|
+
{
|
165
|
+
VALUE stream;
|
166
|
+
VALUE streams;
|
167
|
+
VALUE typed_streams;
|
168
|
+
unsigned int i;
|
169
|
+
|
170
|
+
streams = rb_funcall(self, rb_intern("streams"), 0);
|
171
|
+
typed_streams = rb_ary_new();
|
172
|
+
Check_Type(streams, T_ARRAY);
|
173
|
+
|
174
|
+
for (i = 0; i < RARRAY(streams)->len; i++)
|
175
|
+
{
|
176
|
+
if (rb_obj_is_kind_of((stream = rb_ary_entry(streams, i)), klass))
|
177
|
+
rb_ary_push(typed_streams, stream);
|
178
|
+
}
|
179
|
+
|
180
|
+
return typed_streams;
|
181
|
+
}
|
182
|
+
|
183
|
+
static VALUE ffrf_video_streams(VALUE self)
|
184
|
+
{
|
185
|
+
return ffrf_av_streams(self, cFFrubyVideoStream);
|
186
|
+
}
|
187
|
+
|
188
|
+
static VALUE ffrf_audio_streams(VALUE self)
|
189
|
+
{
|
190
|
+
return ffrf_av_streams(self, cFFrubyAudioStream);
|
191
|
+
}
|
192
|
+
|
193
|
+
static VALUE ffrf_initialize(VALUE self, VALUE filename)
|
194
|
+
{
|
195
|
+
char* msg;
|
196
|
+
AVFormatContext *fmt;
|
197
|
+
VALUE exception;
|
198
|
+
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)
|
201
|
+
{
|
202
|
+
asprintf(&msg, "Cannot open file %s!", RSTRING(filename_str)->ptr);
|
203
|
+
exception = rb_exc_new2(rb_eIOError, msg);
|
204
|
+
free(msg);
|
205
|
+
rb_exc_raise(exception);
|
206
|
+
}
|
207
|
+
|
208
|
+
if (av_find_stream_info(fmt) < 0)
|
209
|
+
{
|
210
|
+
asprintf(&msg, "Problem reading file %s!", RSTRING(filename_str)->ptr);
|
211
|
+
exception = rb_exc_new2(rb_eIOError, msg);
|
212
|
+
free(msg);
|
213
|
+
rb_exc_raise(exception);
|
214
|
+
}
|
215
|
+
|
216
|
+
DATA_PTR(self) = fmt;
|
217
|
+
return self;
|
218
|
+
}
|
219
|
+
|
220
|
+
void Init_ffrf()
|
221
|
+
{
|
222
|
+
cFFrubyFile = rb_define_class("FFrubyFile", rb_cObject);
|
223
|
+
rb_define_alloc_func(cFFrubyFile, ffrf_alloc);
|
224
|
+
rb_define_method(cFFrubyFile, "initialize", ffrf_initialize, 1);
|
225
|
+
rb_define_method(cFFrubyFile, "title", ffrf_title, 0);
|
226
|
+
rb_define_method(cFFrubyFile, "author", ffrf_author, 0);
|
227
|
+
rb_define_method(cFFrubyFile, "copyright", ffrf_copyright, 0);
|
228
|
+
rb_define_method(cFFrubyFile, "comment", ffrf_comment, 0);
|
229
|
+
rb_define_method(cFFrubyFile, "album", ffrf_album, 0);
|
230
|
+
rb_define_method(cFFrubyFile, "genre", ffrf_genre, 0);
|
231
|
+
rb_define_method(cFFrubyFile, "year", ffrf_year, 0);
|
232
|
+
rb_define_method(cFFrubyFile, "track", ffrf_track, 0);
|
233
|
+
rb_define_method(cFFrubyFile, "duration", ffrf_duration, 0);
|
234
|
+
rb_define_method(cFFrubyFile, "bit_rate", ffrf_bit_rate, 0);
|
235
|
+
rb_define_method(cFFrubyFile, "format", ffrf_format, 0);
|
236
|
+
rb_define_method(cFFrubyFile, "streams", ffrf_streams, 0);
|
237
|
+
rb_define_method(cFFrubyFile, "video_streams", ffrf_video_streams, 0);
|
238
|
+
rb_define_method(cFFrubyFile, "audio_streams", ffrf_audio_streams, 0);
|
239
|
+
}
|
@@ -0,0 +1,196 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2007 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
|
+
#define _GNU_SOURCE
|
22
|
+
#include <ruby.h>
|
23
|
+
#include <ffmpeg/avformat.h>
|
24
|
+
#include <ffmpeg/avcodec.h>
|
25
|
+
|
26
|
+
VALUE cFFrubyStream;
|
27
|
+
VALUE cFFrubyVideoStream;
|
28
|
+
VALUE cFFrubyAudioStream;
|
29
|
+
|
30
|
+
static void ffrs_open_codec(AVStream* stream)
|
31
|
+
{
|
32
|
+
AVCodec *codec;
|
33
|
+
|
34
|
+
if (stream->codec->codec == NULL)
|
35
|
+
{
|
36
|
+
if ((codec = avcodec_find_decoder(stream->codec->codec_id)) == NULL)
|
37
|
+
rb_raise(rb_eIOError, "Cannot find codec!");
|
38
|
+
|
39
|
+
if (avcodec_open(stream->codec, codec) < 0)
|
40
|
+
rb_raise(rb_eIOError, "Cannot open codec!");
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
static AVStream* ffrs_get_stream(VALUE self)
|
45
|
+
{
|
46
|
+
AVStream *stream;
|
47
|
+
Data_Get_Struct(self, AVStream, stream);
|
48
|
+
return stream;
|
49
|
+
}
|
50
|
+
|
51
|
+
static VALUE ffrs_codec(VALUE self)
|
52
|
+
{
|
53
|
+
AVStream *stream = ffrs_get_stream(self);
|
54
|
+
ffrs_open_codec(stream);
|
55
|
+
return rb_str_new2(stream->codec->codec->name);
|
56
|
+
}
|
57
|
+
|
58
|
+
static VALUE ffrs_tag(VALUE self)
|
59
|
+
{
|
60
|
+
char tag[4];
|
61
|
+
signed int i, j;
|
62
|
+
AVStream *stream = ffrs_get_stream(self);
|
63
|
+
|
64
|
+
i = stream->codec->codec_tag;
|
65
|
+
|
66
|
+
for (j = 3; j >= 0; j -= 1)
|
67
|
+
{
|
68
|
+
tag[j] = i >> (j * 8);
|
69
|
+
i -= tag[j] << (j * 8);
|
70
|
+
}
|
71
|
+
|
72
|
+
for (j = 3; j >= 0; j -= 1)
|
73
|
+
{
|
74
|
+
if (tag[j] != '\0')
|
75
|
+
break;
|
76
|
+
}
|
77
|
+
|
78
|
+
return rb_str_new(tag, j + 1);
|
79
|
+
}
|
80
|
+
|
81
|
+
static VALUE ffrs_bit_rate(VALUE self)
|
82
|
+
{
|
83
|
+
AVStream *stream = ffrs_get_stream(self);
|
84
|
+
return INT2NUM(stream->codec->bit_rate);
|
85
|
+
}
|
86
|
+
|
87
|
+
static VALUE ffrs_alloc(VALUE klass)
|
88
|
+
{
|
89
|
+
return Data_Wrap_Struct(klass, 0, 0, NULL);
|
90
|
+
}
|
91
|
+
|
92
|
+
static VALUE ffrs_initialize(VALUE self, VALUE file, VALUE index)
|
93
|
+
{
|
94
|
+
AVFormatContext *fmt;
|
95
|
+
AVStream *stream;
|
96
|
+
unsigned int i = FIX2UINT(index);
|
97
|
+
|
98
|
+
Data_Get_Struct(file, AVFormatContext, fmt);
|
99
|
+
|
100
|
+
if (i < 0 || i >= fmt->nb_streams)
|
101
|
+
rb_raise(rb_eIndexError, "Stream index out of range!");
|
102
|
+
|
103
|
+
DATA_PTR(self) = fmt->streams[i];
|
104
|
+
stream = ffrs_get_stream(self);
|
105
|
+
|
106
|
+
return self;
|
107
|
+
}
|
108
|
+
|
109
|
+
static VALUE ffrvs_width(VALUE self)
|
110
|
+
{
|
111
|
+
AVStream *stream = ffrs_get_stream(self);
|
112
|
+
return INT2NUM(stream->codec->width);
|
113
|
+
}
|
114
|
+
|
115
|
+
static VALUE ffrvs_height(VALUE self)
|
116
|
+
{
|
117
|
+
AVStream *stream = ffrs_get_stream(self);
|
118
|
+
return INT2NUM(stream->codec->height);
|
119
|
+
}
|
120
|
+
|
121
|
+
static VALUE ffrvs_frame_aspect_ratio(VALUE self)
|
122
|
+
{
|
123
|
+
AVStream *stream = ffrs_get_stream(self);
|
124
|
+
|
125
|
+
if (stream->codec->width == 0 || stream->codec->height == 0)
|
126
|
+
return Qnil;
|
127
|
+
else
|
128
|
+
return rb_funcall(rb_mKernel, rb_intern("Rational"), 2, INT2NUM(stream->codec->width), INT2NUM(stream->codec->height));
|
129
|
+
}
|
130
|
+
|
131
|
+
static VALUE ffrvs_sample_aspect_ratio(VALUE self)
|
132
|
+
{
|
133
|
+
AVStream *stream = ffrs_get_stream(self);
|
134
|
+
|
135
|
+
if (stream->codec->sample_aspect_ratio.den == 0 || stream->codec->sample_aspect_ratio.num == 0)
|
136
|
+
return rb_funcall(rb_mKernel, rb_intern("Rational"), 2, INT2FIX(1), INT2FIX(1));
|
137
|
+
else
|
138
|
+
return rb_funcall(rb_mKernel, rb_intern("Rational"), 2, INT2NUM(stream->codec->sample_aspect_ratio.num), INT2NUM(stream->codec->sample_aspect_ratio.den));
|
139
|
+
}
|
140
|
+
|
141
|
+
static VALUE ffrvs_real_aspect_ratio(VALUE self)
|
142
|
+
{
|
143
|
+
VALUE x, y;
|
144
|
+
x = ffrvs_frame_aspect_ratio(self);
|
145
|
+
y = ffrvs_sample_aspect_ratio(self);
|
146
|
+
|
147
|
+
if (x == Qnil || y == Qnil)
|
148
|
+
return Qnil;
|
149
|
+
else
|
150
|
+
return rb_funcall(x, rb_intern("*"), 1, y);
|
151
|
+
}
|
152
|
+
|
153
|
+
static VALUE ffrvs_frame_rate(VALUE self)
|
154
|
+
{
|
155
|
+
AVStream *stream = ffrs_get_stream(self);
|
156
|
+
ffrs_open_codec(stream);
|
157
|
+
|
158
|
+
if (stream->r_frame_rate.den && stream->r_frame_rate.num)
|
159
|
+
return rb_funcall(rb_mKernel, rb_intern("Rational"), 2, INT2NUM(stream->r_frame_rate.num), INT2NUM(stream->r_frame_rate.den));
|
160
|
+
else
|
161
|
+
return rb_funcall(rb_mKernel, rb_intern("Rational"), 2, INT2NUM(stream->codec->time_base.den), INT2NUM(stream->codec->time_base.num));
|
162
|
+
}
|
163
|
+
|
164
|
+
static VALUE ffras_channels(VALUE self)
|
165
|
+
{
|
166
|
+
AVStream *stream = ffrs_get_stream(self);
|
167
|
+
return INT2FIX(stream->codec->channels);
|
168
|
+
}
|
169
|
+
|
170
|
+
static VALUE ffras_sample_rate(VALUE self)
|
171
|
+
{
|
172
|
+
AVStream *stream = ffrs_get_stream(self);
|
173
|
+
return INT2NUM(stream->codec->sample_rate);
|
174
|
+
}
|
175
|
+
|
176
|
+
void Init_ffrs()
|
177
|
+
{
|
178
|
+
cFFrubyStream = rb_define_class("FFrubyStream", rb_cObject);
|
179
|
+
rb_define_alloc_func(cFFrubyStream, ffrs_alloc);
|
180
|
+
rb_define_method(cFFrubyStream, "initialize", ffrs_initialize, 2);
|
181
|
+
rb_define_method(cFFrubyStream, "codec", ffrs_codec, 0);
|
182
|
+
rb_define_method(cFFrubyStream, "tag", ffrs_tag, 0);
|
183
|
+
rb_define_method(cFFrubyStream, "bit_rate", ffrs_bit_rate, 0);
|
184
|
+
|
185
|
+
cFFrubyVideoStream = rb_define_class("FFrubyVideoStream", cFFrubyStream);
|
186
|
+
rb_define_method(cFFrubyVideoStream, "width", ffrvs_width, 0);
|
187
|
+
rb_define_method(cFFrubyVideoStream, "height", ffrvs_height, 0);
|
188
|
+
rb_define_method(cFFrubyVideoStream, "frame_aspect_ratio", ffrvs_frame_aspect_ratio, 0);
|
189
|
+
rb_define_method(cFFrubyVideoStream, "sample_aspect_ratio", ffrvs_sample_aspect_ratio, 0);
|
190
|
+
rb_define_method(cFFrubyVideoStream, "real_aspect_ratio", ffrvs_real_aspect_ratio, 0);
|
191
|
+
rb_define_method(cFFrubyVideoStream, "frame_rate", ffrvs_frame_rate, 0);
|
192
|
+
|
193
|
+
cFFrubyAudioStream = rb_define_class("FFrubyAudioStream", cFFrubyStream);
|
194
|
+
rb_define_method(cFFrubyAudioStream, "channels", ffras_channels, 0);
|
195
|
+
rb_define_method(cFFrubyAudioStream, "sample_rate", ffras_sample_rate, 0);
|
196
|
+
}
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4.6
|
3
|
+
specification_version: 2
|
4
|
+
name: ffruby
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2007-11-06 00:00:00 -05:00
|
8
|
+
summary: a library that does something with media files!
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: wayneeseguin at gmail dot com
|
12
|
+
homepage: ffruby.rubyforge.org
|
13
|
+
rubyforge_project:
|
14
|
+
description: a library that does something with media files!
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: "0"
|
30
|
+
version:
|
31
|
+
platform: ruby
|
32
|
+
signing_key:
|
33
|
+
cert_chain: []
|
34
|
+
|
35
|
+
post_install_message:
|
36
|
+
authors:
|
37
|
+
- "ffruby: James Le Cuirot, gem: Wayne E. Seguin"
|
38
|
+
files:
|
39
|
+
- README
|
40
|
+
- Rakefile
|
41
|
+
- lib/ffruby
|
42
|
+
- lib/ffruby/version.rb
|
43
|
+
- ext/ffruby/ffruby.c
|
44
|
+
- ext/ffruby/ffrubyfile.c
|
45
|
+
- ext/ffruby/ffrubystream.c
|
46
|
+
- ext/ffruby/extconf.rb
|
47
|
+
test_files: []
|
48
|
+
|
49
|
+
rdoc_options:
|
50
|
+
- --quiet
|
51
|
+
- --title
|
52
|
+
- FFruby Reference
|
53
|
+
- --main
|
54
|
+
- README
|
55
|
+
- --inline-source
|
56
|
+
extra_rdoc_files:
|
57
|
+
- README
|
58
|
+
executables: []
|
59
|
+
|
60
|
+
extensions:
|
61
|
+
- ext/ffruby/extconf.rb
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
dependencies: []
|
65
|
+
|