ffruby 0.0.1 → 0.2.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.
- data/LICENSE +504 -0
- data/README.rdoc +44 -0
- data/Rakefile +40 -139
- data/VERSION +1 -0
- data/ext/ffruby/extconf.rb +20 -7
- data/ext/ffruby/ffruby.c +41 -6
- data/ext/ffruby/ffruby.h +34 -0
- data/ext/ffruby/ffrubyfile.c +56 -31
- data/ext/ffruby/ffrubystream.c +78 -52
- metadata +59 -46
- data/README +0 -1
- data/lib/ffruby/version.rb +0 -9
    
        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  | 
| 2 | 
            -
            require  | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
            require  | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 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 | 
            -
               | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 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 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 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 | 
            -
             | 
| 138 | 
            -
             | 
| 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 | 
            -
             | 
| 146 | 
            -
               | 
| 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
         | 
    
        data/ext/ffruby/extconf.rb
    CHANGED
    
    | @@ -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 | 
            -
             | 
| 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 | 
            -
            # | 
| 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 | 
             
            }
         | 
    
        data/ext/ffruby/ffruby.h
    ADDED
    
    | @@ -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
         | 
    
        data/ext/ffruby/ffrubyfile.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,21 +18,17 @@ | |
| 18 18 | 
             
             * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
         | 
| 19 19 | 
             
             */
         | 
| 20 20 |  | 
| 21 | 
            -
            # | 
| 22 | 
            -
            #include < | 
| 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 | 
            -
             | 
| 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 | 
            -
             | 
| 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 | 
            -
             | 
| 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 | 
            -
            		 | 
| 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 | 
            -
            		 | 
| 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 =  | 
| 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);
         |