hornetseye-ffmpeg 0.8.0 → 0.8.1
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/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
|