hornetseye-ffmpeg 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/ext/avinput.cc +27 -5
- data/ext/avinput.hh +4 -2
- data/ext/avoutput.cc +118 -72
- data/ext/avoutput.hh +12 -8
- data/lib/hornetseye-ffmpeg/avinput.rb +10 -2
- data/lib/hornetseye-ffmpeg/avoutput.rb +5 -4
- metadata +2 -2
data/Rakefile
CHANGED
data/ext/avinput.cc
CHANGED
@@ -282,13 +282,20 @@ long long AVInput::duration(void) throw (Error)
|
|
282
282
|
return m_ic->streams[ m_videoStream ]->duration;
|
283
283
|
}
|
284
284
|
|
285
|
-
long long AVInput::
|
285
|
+
long long AVInput::videoStartTime(void) throw (Error)
|
286
286
|
{
|
287
|
-
ERRORMACRO(
|
287
|
+
ERRORMACRO( m_videoStream != -1, Error, , "Video \"" << m_mrl << "\" is not open. "
|
288
288
|
"Did you call \"close\" before?" );
|
289
289
|
return m_ic->streams[ m_videoStream ]->start_time;
|
290
290
|
}
|
291
291
|
|
292
|
+
long long AVInput::audioStartTime(void) throw (Error)
|
293
|
+
{
|
294
|
+
ERRORMACRO( m_audioStream != -1, Error, , "Audio \"" << m_mrl << "\" is not open. "
|
295
|
+
"Did you call \"close\" before?" );
|
296
|
+
return m_ic->streams[ m_audioStream ]->start_time;
|
297
|
+
}
|
298
|
+
|
292
299
|
void AVInput::seek( long long timestamp ) throw (Error)
|
293
300
|
{
|
294
301
|
ERRORMACRO( m_ic != NULL, Error, , "Video \"" << m_mrl << "\" is not open. "
|
@@ -332,7 +339,10 @@ VALUE AVInput::registerRubyClass( VALUE rbModule )
|
|
332
339
|
rb_define_method( cRubyClass, "sample_rate", RUBY_METHOD_FUNC( wrapSampleRate ), 0 );
|
333
340
|
rb_define_method( cRubyClass, "channels", RUBY_METHOD_FUNC( wrapChannels ), 0 );
|
334
341
|
rb_define_method( cRubyClass, "duration", RUBY_METHOD_FUNC( wrapDuration ), 0 );
|
335
|
-
rb_define_method( cRubyClass, "
|
342
|
+
rb_define_method( cRubyClass, "video_start_time",
|
343
|
+
RUBY_METHOD_FUNC( wrapVideoStartTime ), 0 );
|
344
|
+
rb_define_method( cRubyClass, "audio_start_time",
|
345
|
+
RUBY_METHOD_FUNC( wrapAudioStartTime ), 0 );
|
336
346
|
rb_define_method( cRubyClass, "width", RUBY_METHOD_FUNC( wrapWidth ), 0 );
|
337
347
|
rb_define_method( cRubyClass, "height", RUBY_METHOD_FUNC( wrapHeight ), 0 );
|
338
348
|
rb_define_method( cRubyClass, "has_audio?", RUBY_METHOD_FUNC( wrapHasAudio ), 0 );
|
@@ -488,12 +498,24 @@ VALUE AVInput::wrapDuration( VALUE rbSelf )
|
|
488
498
|
return retVal;
|
489
499
|
}
|
490
500
|
|
491
|
-
VALUE AVInput::
|
501
|
+
VALUE AVInput::wrapVideoStartTime( VALUE rbSelf )
|
502
|
+
{
|
503
|
+
VALUE retVal = Qnil;
|
504
|
+
try {
|
505
|
+
AVInputPtr *self; Data_Get_Struct( rbSelf, AVInputPtr, self );
|
506
|
+
retVal = LL2NUM( (*self)->videoStartTime() );
|
507
|
+
} catch ( exception &e ) {
|
508
|
+
rb_raise( rb_eRuntimeError, "%s", e.what() );
|
509
|
+
};
|
510
|
+
return retVal;
|
511
|
+
}
|
512
|
+
|
513
|
+
VALUE AVInput::wrapAudioStartTime( VALUE rbSelf )
|
492
514
|
{
|
493
515
|
VALUE retVal = Qnil;
|
494
516
|
try {
|
495
517
|
AVInputPtr *self; Data_Get_Struct( rbSelf, AVInputPtr, self );
|
496
|
-
retVal = LL2NUM( (*self)->
|
518
|
+
retVal = LL2NUM( (*self)->audioStartTime() );
|
497
519
|
} catch ( exception &e ) {
|
498
520
|
rb_raise( rb_eRuntimeError, "%s", e.what() );
|
499
521
|
};
|
data/ext/avinput.hh
CHANGED
@@ -56,7 +56,8 @@ public:
|
|
56
56
|
int sampleRate(void) throw (Error);
|
57
57
|
int channels(void) throw (Error);
|
58
58
|
long long duration(void) throw (Error);
|
59
|
-
long long
|
59
|
+
long long videoStartTime(void) throw (Error);
|
60
|
+
long long audioStartTime(void) throw (Error);
|
60
61
|
void seek( long long timestamp ) throw (Error);
|
61
62
|
long long videoPts(void) throw (Error);
|
62
63
|
long long audioPts(void) throw (Error);
|
@@ -75,7 +76,8 @@ public:
|
|
75
76
|
static VALUE wrapSampleRate( VALUE rbSelf );
|
76
77
|
static VALUE wrapChannels( VALUE rbSelf );
|
77
78
|
static VALUE wrapDuration( VALUE rbSelf );
|
78
|
-
static VALUE
|
79
|
+
static VALUE wrapVideoStartTime( VALUE rbSelf );
|
80
|
+
static VALUE wrapAudioStartTime( VALUE rbSelf );
|
79
81
|
static VALUE wrapWidth( VALUE rbSelf );
|
80
82
|
static VALUE wrapHeight( VALUE rbSelf );
|
81
83
|
static VALUE wrapHasAudio( VALUE rbSelf );
|
data/ext/avoutput.cc
CHANGED
@@ -35,9 +35,9 @@ AVOutput::AVOutput( const string &mrl, int videoBitRate, int width, int height,
|
|
35
35
|
int aspectRatioDen, enum CodecID videoCodec,
|
36
36
|
int audioBitRate, int sampleRate, int channels,
|
37
37
|
enum CodecID audioCodec ) throw (Error):
|
38
|
-
m_mrl( mrl ), m_oc( NULL ),
|
39
|
-
|
40
|
-
|
38
|
+
m_mrl( mrl ), m_oc( NULL ), m_videoStream( NULL ), m_audioStream( NULL),
|
39
|
+
m_videoCodecOpen( false ), m_audioCodecOpen( false ), m_videoBuf( NULL ),
|
40
|
+
m_audioBuf( NULL ), m_fileOpen( false ), m_headerWritten( false ),
|
41
41
|
m_swsContext( NULL ), m_frame( NULL )
|
42
42
|
{
|
43
43
|
try {
|
@@ -56,11 +56,11 @@ AVOutput::AVOutput( const string &mrl, int videoBitRate, int width, int height,
|
|
56
56
|
snprintf( m_oc->filename, sizeof( m_oc->filename ), "%s", mrl.c_str() );
|
57
57
|
ERRORMACRO( format->video_codec != CODEC_ID_NONE, Error, ,
|
58
58
|
"Output format does not support video" );
|
59
|
-
|
60
|
-
ERRORMACRO(
|
61
|
-
|
62
|
-
|
63
|
-
AVCodecContext *c =
|
59
|
+
m_videoStream = av_new_stream( m_oc, 0 );
|
60
|
+
ERRORMACRO( m_videoStream != NULL, Error, , "Could not allocate video stream" );
|
61
|
+
m_videoStream->sample_aspect_ratio.num = aspectRatioNum;
|
62
|
+
m_videoStream->sample_aspect_ratio.den = aspectRatioDen;
|
63
|
+
AVCodecContext *c = m_videoStream->codec;
|
64
64
|
c->codec_id = videoCodec != CODEC_ID_NONE ? videoCodec : format->video_codec;
|
65
65
|
c->codec_type = CODEC_TYPE_VIDEO;
|
66
66
|
c->bit_rate = videoBitRate;
|
@@ -75,9 +75,9 @@ AVOutput::AVOutput( const string &mrl, int videoBitRate, int width, int height,
|
|
75
75
|
if ( m_oc->oformat->flags & AVFMT_GLOBALHEADER )
|
76
76
|
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
77
77
|
if ( channels > 0 ) {
|
78
|
-
|
79
|
-
ERRORMACRO(
|
80
|
-
AVCodecContext *c =
|
78
|
+
m_audioStream = av_new_stream( m_oc, 0 );
|
79
|
+
ERRORMACRO( m_audioStream != NULL, Error, , "Could not allocate audio stream" );
|
80
|
+
AVCodecContext *c = m_audioStream->codec;
|
81
81
|
c->codec_id = audioCodec != CODEC_ID_NONE ? audioCodec : format->audio_codec;
|
82
82
|
c->codec_type = CODEC_TYPE_AUDIO;
|
83
83
|
c->bit_rate = audioBitRate;
|
@@ -94,23 +94,23 @@ AVOutput::AVOutput( const string &mrl, int videoBitRate, int width, int height,
|
|
94
94
|
ERRORMACRO( avcodec_open( c, codec ) >= 0, Error, ,
|
95
95
|
"Error opening video codec \"" << codec->name << "\": "
|
96
96
|
<< strerror( errno ) );
|
97
|
-
|
97
|
+
m_videoCodecOpen = true;
|
98
98
|
if ( !( m_oc->oformat->flags & AVFMT_RAWPICTURE ) ) {
|
99
|
-
|
100
|
-
ERRORMACRO(
|
99
|
+
m_videoBuf = (char *)av_malloc( VIDEO_BUF_SIZE );
|
100
|
+
ERRORMACRO( m_videoBuf != NULL, Error, ,
|
101
101
|
"Error allocating video output buffer" );
|
102
102
|
};
|
103
103
|
if ( channels > 0 ) {
|
104
|
-
AVCodecContext *c =
|
104
|
+
AVCodecContext *c = m_audioStream->codec;
|
105
105
|
AVCodec *codec = avcodec_find_encoder( c->codec_id );
|
106
106
|
ERRORMACRO( codec != NULL, Error, , "Could not find audio codec "
|
107
107
|
<< c->codec_id );
|
108
108
|
ERRORMACRO( avcodec_open( c, codec ) >= 0, Error, ,
|
109
109
|
"Error opening audio codec \"" << codec->name << "\": "
|
110
110
|
<< strerror( errno ) );
|
111
|
-
|
112
|
-
|
113
|
-
ERRORMACRO(
|
111
|
+
m_audioCodecOpen = true;
|
112
|
+
m_audioBuf = (char *)av_malloc( AUDIO_BUF_SIZE );
|
113
|
+
ERRORMACRO( m_audioBuf != NULL, Error, ,
|
114
114
|
"Error allocating audio output buffer" );
|
115
115
|
#ifndef NDEBUG
|
116
116
|
cerr << "audio frame size = " << c->frame_size << " samples" << endl;
|
@@ -119,12 +119,12 @@ AVOutput::AVOutput( const string &mrl, int videoBitRate, int width, int height,
|
|
119
119
|
if ( !( format->flags & AVFMT_NOFILE ) ) {
|
120
120
|
ERRORMACRO( url_fopen( &m_oc->pb, mrl.c_str(), URL_WRONLY ) >= 0, Error, ,
|
121
121
|
"Could not open \"" << mrl << "\"" );
|
122
|
-
|
122
|
+
m_fileOpen = true;
|
123
123
|
};
|
124
124
|
ERRORMACRO( av_write_header( m_oc ) >= 0, Error, ,
|
125
125
|
"Error writing header of video \"" << mrl << "\": "
|
126
126
|
<< strerror( errno ) );
|
127
|
-
|
127
|
+
m_headerWritten = true;
|
128
128
|
m_swsContext = sws_getContext( width, height, PIX_FMT_YUV420P,
|
129
129
|
width, height, PIX_FMT_YUV420P,
|
130
130
|
SWS_FAST_BILINEAR, 0, 0, 0 );
|
@@ -158,63 +158,95 @@ void AVOutput::close(void)
|
|
158
158
|
sws_freeContext( m_swsContext );
|
159
159
|
m_swsContext = NULL;
|
160
160
|
};
|
161
|
-
if (
|
161
|
+
if ( m_headerWritten ) {
|
162
162
|
av_write_trailer( m_oc );
|
163
|
-
|
163
|
+
m_headerWritten = false;
|
164
164
|
};
|
165
|
-
if (
|
166
|
-
if (
|
167
|
-
avcodec_close(
|
168
|
-
|
165
|
+
if ( m_audioStream ) {
|
166
|
+
if ( m_audioCodecOpen ) {
|
167
|
+
avcodec_close( m_audioStream->codec );
|
168
|
+
m_audioCodecOpen = false;
|
169
169
|
};
|
170
170
|
};
|
171
|
-
if (
|
172
|
-
if (
|
173
|
-
avcodec_close(
|
174
|
-
|
171
|
+
if ( m_videoStream ) {
|
172
|
+
if ( m_videoCodecOpen ) {
|
173
|
+
avcodec_close( m_videoStream->codec );
|
174
|
+
m_videoCodecOpen = false;
|
175
175
|
};
|
176
176
|
};
|
177
|
-
if (
|
178
|
-
av_free(
|
179
|
-
|
177
|
+
if ( m_audioBuf ) {
|
178
|
+
av_free( m_audioBuf );
|
179
|
+
m_audioBuf = NULL;
|
180
180
|
};
|
181
|
-
if (
|
182
|
-
av_free(
|
183
|
-
|
181
|
+
if ( m_videoBuf ) {
|
182
|
+
av_free( m_videoBuf );
|
183
|
+
m_videoBuf = NULL;
|
184
184
|
};
|
185
185
|
if ( m_oc ) {
|
186
186
|
for ( unsigned int i = 0; i < m_oc->nb_streams; i++ ) {
|
187
187
|
av_freep( &m_oc->streams[i]->codec );
|
188
188
|
av_freep( &m_oc->streams[i] );
|
189
189
|
};
|
190
|
-
|
191
|
-
|
192
|
-
if (
|
190
|
+
m_audioStream = NULL;
|
191
|
+
m_videoStream = NULL;
|
192
|
+
if ( m_fileOpen ) {
|
193
193
|
#ifdef HAVE_BYTEIO_PTR
|
194
194
|
url_fclose( m_oc->pb );
|
195
195
|
#else
|
196
196
|
url_fclose( &m_oc->pb );
|
197
197
|
#endif
|
198
|
-
|
198
|
+
m_fileOpen = false;
|
199
199
|
};
|
200
200
|
av_free( m_oc );
|
201
201
|
m_oc = NULL;
|
202
202
|
};
|
203
203
|
}
|
204
204
|
|
205
|
+
AVRational AVOutput::videoTimeBase(void) throw (Error)
|
206
|
+
{
|
207
|
+
ERRORMACRO( m_videoStream != NULL, Error, , "Video \"" << m_mrl << "\" is not open. "
|
208
|
+
"Did you call \"close\" before?" );
|
209
|
+
return m_videoStream->time_base;
|
210
|
+
}
|
211
|
+
|
212
|
+
AVRational AVOutput::audioTimeBase(void) throw (Error)
|
213
|
+
{
|
214
|
+
ERRORMACRO( m_audioStream != NULL, Error, , "Audio \"" << m_mrl << "\" is not open. "
|
215
|
+
"Did you call \"close\" before?" );
|
216
|
+
return m_audioStream->time_base;
|
217
|
+
}
|
218
|
+
|
219
|
+
int AVOutput::frameSize(void) throw (Error)
|
220
|
+
{
|
221
|
+
ERRORMACRO( m_oc != NULL, Error, , "Video \"" << m_mrl << "\" is not open. "
|
222
|
+
"Did you call \"close\" before?" );
|
223
|
+
ERRORMACRO( m_audioStream != NULL, Error, , "Video \"" << m_mrl << "\" does not have "
|
224
|
+
"an audio stream" );
|
225
|
+
return m_audioStream->codec->frame_size;
|
226
|
+
}
|
227
|
+
|
228
|
+
int AVOutput::channels(void) throw (Error)
|
229
|
+
{
|
230
|
+
ERRORMACRO( m_oc != NULL, Error, , "Video \"" << m_mrl << "\" is not open. "
|
231
|
+
"Did you call \"close\" before?" );
|
232
|
+
ERRORMACRO( m_audioStream != NULL, Error, , "Video \"" << m_mrl << "\" does not have "
|
233
|
+
"an audio stream" );
|
234
|
+
return m_audioStream->codec->channels;
|
235
|
+
}
|
236
|
+
|
205
237
|
void AVOutput::writeVideo( FramePtr frame ) throw (Error)
|
206
238
|
{
|
207
239
|
ERRORMACRO( m_oc != NULL, Error, , "Video \"" << m_mrl << "\" is not open. "
|
208
240
|
"Did you call \"close\" before?" );
|
209
|
-
ERRORMACRO(
|
210
|
-
|
241
|
+
ERRORMACRO( m_videoStream->codec->width == frame->width() &&
|
242
|
+
m_videoStream->codec->height == frame->height(), Error, ,
|
211
243
|
"Resolution of frame is " << frame->width() << 'x'
|
212
244
|
<< frame->height() << " but video resolution is "
|
213
|
-
<<
|
245
|
+
<< m_videoStream->codec->width << 'x' << m_videoStream->codec->height );
|
214
246
|
if ( m_oc->oformat->flags & AVFMT_RAWPICTURE ) {
|
215
247
|
ERRORMACRO( false, Error, , "Raw picture encoding not implemented yet" );
|
216
248
|
} else {
|
217
|
-
AVCodecContext *c =
|
249
|
+
AVCodecContext *c = m_videoStream->codec;
|
218
250
|
AVFrame picture;
|
219
251
|
int
|
220
252
|
width = c->width,
|
@@ -231,7 +263,7 @@ void AVOutput::writeVideo( FramePtr frame ) throw (Error)
|
|
231
263
|
picture.linesize[2] = width2a;
|
232
264
|
sws_scale( m_swsContext, picture.data, picture.linesize, 0,
|
233
265
|
c->height, m_frame->data, m_frame->linesize );
|
234
|
-
int packetSize = avcodec_encode_video( c, (uint8_t *)
|
266
|
+
int packetSize = avcodec_encode_video( c, (uint8_t *)m_videoBuf,
|
235
267
|
VIDEO_BUF_SIZE, m_frame );
|
236
268
|
ERRORMACRO( packetSize >= 0, Error, , "Error encoding video frame" );
|
237
269
|
if ( packetSize > 0 ) {
|
@@ -239,11 +271,11 @@ void AVOutput::writeVideo( FramePtr frame ) throw (Error)
|
|
239
271
|
av_init_packet( &packet );
|
240
272
|
if ( c->coded_frame->pts != AV_NOPTS_VALUE )
|
241
273
|
packet.pts = av_rescale_q( c->coded_frame->pts, c->time_base,
|
242
|
-
|
274
|
+
m_videoStream->time_base );
|
243
275
|
if ( c->coded_frame->key_frame )
|
244
276
|
packet.flags |= PKT_FLAG_KEY;
|
245
|
-
packet.stream_index =
|
246
|
-
packet.data = (uint8_t *)
|
277
|
+
packet.stream_index = m_videoStream->index;
|
278
|
+
packet.data = (uint8_t *)m_videoBuf;
|
247
279
|
packet.size = packetSize;
|
248
280
|
ERRORMACRO( av_interleaved_write_frame( m_oc, &packet ) >= 0, Error, ,
|
249
281
|
"Error writing video frame of video \"" << m_mrl << "\": "
|
@@ -252,35 +284,17 @@ void AVOutput::writeVideo( FramePtr frame ) throw (Error)
|
|
252
284
|
};
|
253
285
|
}
|
254
286
|
|
255
|
-
int AVOutput::frameSize(void) throw (Error)
|
256
|
-
{
|
257
|
-
ERRORMACRO( m_oc != NULL, Error, , "Video \"" << m_mrl << "\" is not open. "
|
258
|
-
"Did you call \"close\" before?" );
|
259
|
-
ERRORMACRO( m_audio_st != NULL, Error, , "Video \"" << m_mrl << "\" does not have "
|
260
|
-
"an audio stream" );
|
261
|
-
return m_audio_st->codec->frame_size;
|
262
|
-
}
|
263
|
-
|
264
|
-
int AVOutput::channels(void) throw (Error)
|
265
|
-
{
|
266
|
-
ERRORMACRO( m_oc != NULL, Error, , "Video \"" << m_mrl << "\" is not open. "
|
267
|
-
"Did you call \"close\" before?" );
|
268
|
-
ERRORMACRO( m_audio_st != NULL, Error, , "Video \"" << m_mrl << "\" does not have "
|
269
|
-
"an audio stream" );
|
270
|
-
return m_audio_st->codec->channels;
|
271
|
-
}
|
272
|
-
|
273
287
|
void AVOutput::writeAudio( SequencePtr frame ) throw (Error)
|
274
288
|
{
|
275
289
|
ERRORMACRO( m_oc != NULL, Error, , "Video \"" << m_mrl << "\" is not open. "
|
276
290
|
"Did you call \"close\" before?" );
|
277
|
-
ERRORMACRO(
|
291
|
+
ERRORMACRO( m_audioStream != NULL, Error, , "Video \"" << m_mrl << "\" does not have "
|
278
292
|
"an audio stream" );
|
279
|
-
AVCodecContext *c =
|
293
|
+
AVCodecContext *c = m_audioStream->codec;
|
280
294
|
ERRORMACRO( frame->size() == c->frame_size * 2 * c->channels, Error, , "Size of "
|
281
295
|
"audio frame is " << frame->size() << " bytes (but should be "
|
282
296
|
<< c->frame_size * 2 * c->channels << " bytes)" );
|
283
|
-
int packetSize = avcodec_encode_audio( c, (uint8_t *)
|
297
|
+
int packetSize = avcodec_encode_audio( c, (uint8_t *)m_audioBuf,
|
284
298
|
AUDIO_BUF_SIZE, (short *)frame->data() );
|
285
299
|
ERRORMACRO( packetSize >= 0, Error, , "Error encoding audio frame" );
|
286
300
|
if ( packetSize > 0 ) {
|
@@ -288,10 +302,10 @@ void AVOutput::writeAudio( SequencePtr frame ) throw (Error)
|
|
288
302
|
av_init_packet( &packet );
|
289
303
|
if ( c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE )
|
290
304
|
packet.pts = av_rescale_q( c->coded_frame->pts, c->time_base,
|
291
|
-
|
305
|
+
m_audioStream->time_base );
|
292
306
|
packet.flags |= PKT_FLAG_KEY;
|
293
|
-
packet.stream_index =
|
294
|
-
packet.data = (uint8_t *)
|
307
|
+
packet.stream_index = m_audioStream->index;
|
308
|
+
packet.data = (uint8_t *)m_audioBuf;
|
295
309
|
packet.size = packetSize;
|
296
310
|
ERRORMACRO( av_interleaved_write_frame( m_oc, &packet ) >= 0, Error, ,
|
297
311
|
"Error writing audio frame of video \"" << m_mrl << "\": "
|
@@ -775,6 +789,10 @@ VALUE AVOutput::registerRubyClass( VALUE rbModule )
|
|
775
789
|
rb_define_const( cRubyClass, "CODEC_ID_MP1",
|
776
790
|
INT2FIX( CODEC_ID_MP1 ) );
|
777
791
|
rb_define_method( cRubyClass, "close", RUBY_METHOD_FUNC( wrapClose ), 0 );
|
792
|
+
rb_define_method( cRubyClass, "video_time_base",
|
793
|
+
RUBY_METHOD_FUNC( wrapVideoTimeBase ), 0 );
|
794
|
+
rb_define_method( cRubyClass, "audio_time_base",
|
795
|
+
RUBY_METHOD_FUNC( wrapAudioTimeBase ), 0 );
|
778
796
|
rb_define_method( cRubyClass, "frame_size", RUBY_METHOD_FUNC( wrapFrameSize ), 0 );
|
779
797
|
rb_define_method( cRubyClass, "channels", RUBY_METHOD_FUNC( wrapChannels ), 0 );
|
780
798
|
rb_define_method( cRubyClass, "write_video", RUBY_METHOD_FUNC( wrapWriteVideo ), 1 );
|
@@ -819,6 +837,34 @@ VALUE AVOutput::wrapClose( VALUE rbSelf )
|
|
819
837
|
return rbSelf;
|
820
838
|
}
|
821
839
|
|
840
|
+
VALUE AVOutput::wrapVideoTimeBase( VALUE rbSelf )
|
841
|
+
{
|
842
|
+
VALUE retVal = Qnil;
|
843
|
+
try {
|
844
|
+
AVOutputPtr *self; Data_Get_Struct( rbSelf, AVOutputPtr, self );
|
845
|
+
AVRational videoTimeBase = (*self)->videoTimeBase();
|
846
|
+
retVal = rb_funcall( rb_cObject, rb_intern( "Rational" ), 2,
|
847
|
+
INT2NUM( videoTimeBase.num ), INT2NUM( videoTimeBase.den ) );
|
848
|
+
} catch ( exception &e ) {
|
849
|
+
rb_raise( rb_eRuntimeError, "%s", e.what() );
|
850
|
+
};
|
851
|
+
return retVal;
|
852
|
+
}
|
853
|
+
|
854
|
+
VALUE AVOutput::wrapAudioTimeBase( VALUE rbSelf )
|
855
|
+
{
|
856
|
+
VALUE retVal = Qnil;
|
857
|
+
try {
|
858
|
+
AVOutputPtr *self; Data_Get_Struct( rbSelf, AVOutputPtr, self );
|
859
|
+
AVRational audioTimeBase = (*self)->audioTimeBase();
|
860
|
+
retVal = rb_funcall( rb_cObject, rb_intern( "Rational" ), 2,
|
861
|
+
INT2NUM( audioTimeBase.num ), INT2NUM( audioTimeBase.den ) );
|
862
|
+
} catch ( exception &e ) {
|
863
|
+
rb_raise( rb_eRuntimeError, "%s", e.what() );
|
864
|
+
};
|
865
|
+
return retVal;
|
866
|
+
}
|
867
|
+
|
822
868
|
VALUE AVOutput::wrapFrameSize( VALUE rbSelf )
|
823
869
|
{
|
824
870
|
VALUE rbRetVal = Qnil;
|
data/ext/avoutput.hh
CHANGED
@@ -48,6 +48,8 @@ public:
|
|
48
48
|
enum CodecID audioCodec ) throw (Error);
|
49
49
|
virtual ~AVOutput(void);
|
50
50
|
void close(void);
|
51
|
+
AVRational videoTimeBase(void) throw (Error);
|
52
|
+
AVRational audioTimeBase(void) throw (Error);
|
51
53
|
int frameSize(void) throw (Error);
|
52
54
|
int channels(void) throw (Error);
|
53
55
|
void writeVideo( FramePtr frame ) throw (Error);
|
@@ -61,6 +63,8 @@ public:
|
|
61
63
|
VALUE rbVideoCodec, VALUE rbAudioBitRate, VALUE rbSampleRate,
|
62
64
|
VALUE rbChannels, VALUE rbAudioCodec );
|
63
65
|
static VALUE wrapClose( VALUE rbSelf );
|
66
|
+
static VALUE wrapVideoTimeBase( VALUE rbSelf );
|
67
|
+
static VALUE wrapAudioTimeBase( VALUE rbSelf );
|
64
68
|
static VALUE wrapFrameSize( VALUE rbSelf );
|
65
69
|
static VALUE wrapChannels( VALUE rbSelf );
|
66
70
|
static VALUE wrapWriteVideo( VALUE rbSelf, VALUE rbFrame );
|
@@ -68,14 +72,14 @@ public:
|
|
68
72
|
protected:
|
69
73
|
std::string m_mrl;
|
70
74
|
AVFormatContext *m_oc;
|
71
|
-
AVStream *
|
72
|
-
AVStream *
|
73
|
-
bool
|
74
|
-
bool
|
75
|
-
char *
|
76
|
-
char *
|
77
|
-
bool
|
78
|
-
bool
|
75
|
+
AVStream *m_videoStream;
|
76
|
+
AVStream *m_audioStream;
|
77
|
+
bool m_videoCodecOpen;
|
78
|
+
bool m_audioCodecOpen;
|
79
|
+
char *m_videoBuf;
|
80
|
+
char *m_audioBuf;
|
81
|
+
bool m_fileOpen;
|
82
|
+
bool m_headerWritten;
|
79
83
|
struct SwsContext *m_swsContext;
|
80
84
|
AVFrame *m_frame;
|
81
85
|
};
|
@@ -93,10 +93,18 @@ module Hornetseye
|
|
93
93
|
orig_duration == AV_NOPTS_VALUE ? nil : orig_duration * video_time_base
|
94
94
|
end
|
95
95
|
|
96
|
-
alias_method :
|
96
|
+
alias_method :orig_video_start_time, :video_start_time
|
97
97
|
|
98
98
|
def video_start_time
|
99
|
-
|
99
|
+
retval = orig_video_start_time
|
100
|
+
retval == AV_NOPTS_VALUE ? nil : retval * video_time_base
|
101
|
+
end
|
102
|
+
|
103
|
+
alias_method :orig_audio_start_time, :audio_start_time
|
104
|
+
|
105
|
+
def audio_start_time
|
106
|
+
retval = orig_audio_start_time
|
107
|
+
retval == AV_NOPTS_VALUE ? nil : retval * audio_time_base
|
100
108
|
end
|
101
109
|
|
102
110
|
alias_method :orig_aspect_ratio, :aspect_ratio
|
@@ -48,14 +48,14 @@ module Hornetseye
|
|
48
48
|
|
49
49
|
end
|
50
50
|
|
51
|
-
alias_method :write, :write_video
|
52
|
-
|
53
51
|
alias_method :orig_write_video, :write_video
|
54
52
|
|
55
53
|
def write_video( frame )
|
56
54
|
orig_write_video frame.to_yv12
|
57
55
|
end
|
58
56
|
|
57
|
+
alias_method :write, :write_video
|
58
|
+
|
59
59
|
alias_method :orig_write_audio, :write_audio
|
60
60
|
|
61
61
|
def write_audio( frame )
|
@@ -86,8 +86,9 @@ module Hornetseye
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
if remaining.shape.last > 0
|
89
|
-
@audio_buffer[ 0 ... channels,
|
90
|
-
|
89
|
+
@audio_buffer[ 0 ... channels, @audio_samples ... @audio_samples +
|
90
|
+
remaining.shape.last ] = remaining
|
91
|
+
@audio_samples += remaining.shape.last
|
91
92
|
end
|
92
93
|
frame
|
93
94
|
end
|