hornetseye-ffmpeg 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'rake/packagetask'
6
6
  require 'rbconfig'
7
7
 
8
8
  PKG_NAME = 'hornetseye-ffmpeg'
9
- PKG_VERSION = '0.1.0'
9
+ PKG_VERSION = '0.2.0'
10
10
  CXX = ENV[ 'CXX' ] || 'g++'
11
11
  STRIP = ENV[ 'STRIP' ] || 'strip'
12
12
  RB_FILES = FileList[ 'lib/**/*.rb' ]
data/ext/avinput.cc CHANGED
@@ -15,13 +15,19 @@
15
15
  along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
16
  #include "avinput.hh"
17
17
 
18
+ #if !defined(INT64_C)
19
+ #define INT64_C(c) c ## LL
20
+ #endif
21
+
22
+ // Also see FFMPEG tutorial at http://dranger.com/ffmpeg/
23
+
18
24
  using namespace std;
19
25
 
20
26
  VALUE AVInput::cRubyClass = Qnil;
21
27
 
22
28
  AVInput::AVInput( const string &mrl ) throw (Error):
23
29
  m_mrl( mrl ), m_ic( NULL ), m_enc( NULL ), m_codec( NULL ), m_idx( -1 ),
24
- m_frame( NULL )
30
+ m_pts( 0 ), m_frame( NULL )
25
31
  {
26
32
  try {
27
33
  int err = av_open_input_file( &m_ic, mrl.c_str(), NULL, 0, NULL );
@@ -86,7 +92,9 @@ FramePtr AVInput::read(void) throw (Error)
86
92
  packet.data, packet.size );
87
93
  ERRORMACRO( err >= 0, Error, ,
88
94
  "Error decoding frame of video \"" << m_mrl << "\"" );
95
+
89
96
  if ( frameFinished ) {
97
+ if ( packet.dts != AV_NOPTS_VALUE ) m_pts = packet.dts;
90
98
  av_free_packet( &packet );
91
99
  AVFrame frame;
92
100
  m_data = boost::shared_array< char >( new char[ m_enc->width *
@@ -102,7 +110,7 @@ FramePtr AVInput::read(void) throw (Error)
102
110
  struct SwsContext *swsContext =
103
111
  sws_getContext( m_enc->width, m_enc->height, m_enc->pix_fmt,
104
112
  m_enc->width, m_enc->height, PIX_FMT_YUV420P,
105
- SWS_BILINEAR, 0, 0, 0 );
113
+ SWS_FAST_BILINEAR, 0, 0, 0 );
106
114
  sws_scale( swsContext, m_frame->data, m_frame->linesize, 0,
107
115
  m_enc->height, frame.data, frame.linesize );
108
116
  sws_freeContext( swsContext );
@@ -117,13 +125,40 @@ FramePtr AVInput::read(void) throw (Error)
117
125
  return retVal;
118
126
  }
119
127
 
128
+ AVRational AVInput::timeBase(void) throw (Error)
129
+ {
130
+ ERRORMACRO( m_ic != NULL, Error, , "Video \"" << m_mrl << "\" is not open. "
131
+ "Did you call \"close\" before?" );
132
+ return m_ic->streams[ m_idx ]->time_base;
133
+ }
134
+
135
+ void AVInput::seek( long timestamp ) throw (Error)
136
+ {
137
+ ERRORMACRO( m_ic != NULL, Error, , "Video \"" << m_mrl << "\" is not open. "
138
+ "Did you call \"close\" before?" );
139
+ ERRORMACRO( av_seek_frame( m_ic, -1, timestamp, 0 ) >= 0,
140
+ Error, , "Error seeking in video \"" << m_mrl << "\"" );
141
+ avcodec_flush_buffers( m_enc );
142
+ }
143
+
144
+ long long AVInput::pts(void) throw (Error)
145
+ {
146
+ ERRORMACRO( m_ic != NULL, Error, , "Video \"" << m_mrl << "\" is not open. "
147
+ "Did you call \"close\" before?" );
148
+ return m_pts;
149
+ }
150
+
120
151
  VALUE AVInput::registerRubyClass( VALUE rbModule )
121
152
  {
122
153
  av_register_all();
123
154
  cRubyClass = rb_define_class_under( rbModule, "AVInput", rb_cObject );
124
155
  rb_define_singleton_method( cRubyClass, "new",
125
156
  RUBY_METHOD_FUNC( wrapNew ), 1 );
157
+ rb_define_const( cRubyClass, "AV_TIME_BASE", INT2NUM( AV_TIME_BASE ) );
126
158
  rb_define_method( cRubyClass, "read", RUBY_METHOD_FUNC( wrapRead ), 0 );
159
+ rb_define_method( cRubyClass, "time_base", RUBY_METHOD_FUNC( wrapTimeBase ), 0 );
160
+ rb_define_method( cRubyClass, "seek", RUBY_METHOD_FUNC( wrapSeek ), 1 );
161
+ rb_define_method( cRubyClass, "pts", RUBY_METHOD_FUNC( wrapPTS ), 0 );
127
162
  }
128
163
 
129
164
  void AVInput::deleteRubyObject( void *ptr )
@@ -157,3 +192,42 @@ VALUE AVInput::wrapRead( VALUE rbSelf )
157
192
  };
158
193
  return retVal;
159
194
  }
195
+
196
+ VALUE AVInput::wrapTimeBase( VALUE rbSelf )
197
+ {
198
+ VALUE retVal = Qnil;
199
+ try {
200
+ AVInputPtr *self; Data_Get_Struct( rbSelf, AVInputPtr, self );
201
+ AVRational time_base = (*self)->timeBase();
202
+ retVal = rb_funcall( rb_cObject, rb_intern( "Rational" ), 2,
203
+ INT2NUM( time_base.num ), INT2NUM( time_base.den ) );
204
+ } catch( exception &e ) {
205
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
206
+ };
207
+ return retVal;
208
+ }
209
+
210
+ VALUE AVInput::wrapSeek( VALUE rbSelf, VALUE rbPos )
211
+ {
212
+ VALUE retVal = Qnil;
213
+ try {
214
+ AVInputPtr *self; Data_Get_Struct( rbSelf, AVInputPtr, self );
215
+ (*self)->seek( NUM2LL( rbPos ) );
216
+ } catch( exception &e ) {
217
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
218
+ };
219
+ return retVal;
220
+ }
221
+
222
+ VALUE AVInput::wrapPTS( VALUE rbSelf )
223
+ {
224
+ VALUE retVal = Qnil;
225
+ try {
226
+ AVInputPtr *self; Data_Get_Struct( rbSelf, AVInputPtr, self );
227
+ retVal = LL2NUM( (*self)->pts() );
228
+ } catch( exception &e ) {
229
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
230
+ };
231
+ return retVal;
232
+ }
233
+
data/ext/avinput.hh CHANGED
@@ -32,17 +32,24 @@ public:
32
32
  virtual ~AVInput(void);
33
33
  void close(void);
34
34
  FramePtr read(void) throw (Error);
35
+ AVRational timeBase(void) throw (Error);
36
+ void seek( long timestamp ) throw (Error);
37
+ long long pts(void) throw (Error);
35
38
  static VALUE cRubyClass;
36
39
  static VALUE registerRubyClass( VALUE rbModule );
37
40
  static void deleteRubyObject( void *ptr );
38
41
  static VALUE wrapNew( VALUE rbClass, VALUE rbMRL );
39
42
  static VALUE wrapRead( VALUE rbSelf );
43
+ static VALUE wrapTimeBase( VALUE rbSelf );
44
+ static VALUE wrapSeek( VALUE rbSelf, VALUE rbPos );
45
+ static VALUE wrapPTS( VALUE rbSelf );
40
46
  protected:
41
47
  std::string m_mrl;
42
48
  AVFormatContext *m_ic;
43
49
  AVCodecContext *m_enc;
44
50
  AVCodec *m_codec;
45
51
  int m_idx;
52
+ long long m_pts;
46
53
  AVFrame *m_frame;
47
54
  boost::shared_array< char > m_data;
48
55
  };
data/ext/frame.cc CHANGED
@@ -24,9 +24,13 @@ Frame::Frame( const char *typecode, int width, int height, char *data ):
24
24
  VALUE mModule = rb_define_module( "Hornetseye" );
25
25
  VALUE cMalloc = rb_define_class_under( mModule, "Malloc", rb_cObject );
26
26
  VALUE cFrame = rb_define_class_under( mModule, "Frame", rb_cObject );
27
- VALUE memory = Data_Wrap_Struct( cMalloc, 0, 0, (void *)data );
27
+ VALUE rbSize = rb_funcall( cFrame, rb_intern( "typesize" ), 3,
28
+ rb_const_get( mModule, rb_intern( typecode ) ),
29
+ INT2NUM( width ), INT2NUM( height ) );
30
+ VALUE rbMemory = Data_Wrap_Struct( cMalloc, 0, 0, (void *)data );
31
+ rb_ivar_set( rbMemory, rb_intern( "@size" ), rbSize );
28
32
  m_frame = rb_funcall( cFrame, rb_intern( "import" ), 4,
29
33
  rb_const_get( mModule, rb_intern( typecode ) ),
30
34
  INT2NUM( width ), INT2NUM( height ),
31
- memory );
35
+ rbMemory );
32
36
  }
@@ -0,0 +1,57 @@
1
+ # hornetseye-frame - Colourspace conversions and compression
2
+ # Copyright (C) 2010 Jan Wedekind
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ # Namespace of Hornetseye computer vision library
18
+ module Hornetseye
19
+
20
+ class AVInput
21
+
22
+ class << self
23
+
24
+ alias_method :orig_new, :new
25
+
26
+ def new( mrl )
27
+ retval = orig_new mrl
28
+ retval.instance_eval { @frame = nil }
29
+ retval
30
+ end
31
+
32
+ end
33
+
34
+ alias_method :orig_read, :read
35
+
36
+ def read
37
+ @frame = orig_read
38
+ end
39
+
40
+ def pos=( timestamp )
41
+ unless @frame
42
+ begin
43
+ read
44
+ rescue Exception
45
+ end
46
+ end
47
+ seek timestamp * AV_TIME_BASE
48
+ end
49
+
50
+ def pos
51
+ pts * time_base
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
@@ -15,4 +15,5 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
 
17
17
  require 'hornetseye_frame'
18
+ require 'hornetseye-ffmpeg/avinput'
18
19
 
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jan Wedekind
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-09-26 00:00:00 +01:00
17
+ date: 2010-09-28 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -85,6 +85,7 @@ files:
85
85
  - README.md
86
86
  - COPYING
87
87
  - .document
88
+ - lib/hornetseye-ffmpeg/avinput.rb
88
89
  - lib/hornetseye_ffmpeg_ext.rb
89
90
  - ext/avinput.cc
90
91
  - ext/init.cc