00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "ffmpegAudioCursor.h"
00016
00017 #ifdef HAVE_FFMPEG
00018
00019 #include "ffmpegAudio.h"
00020 extern "C" {
00021 #include "libavcodec/avcodec.h"
00022 #include "libavformat/avformat.h"
00023 }
00024
00025 TypeHandle FfmpegAudioCursor::_type_handle;
00026
00027 #if LIBAVFORMAT_VERSION_MAJOR < 53
00028 #define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO
00029 #endif
00030
00031
00032
00033
00034
00035
00036 FfmpegAudioCursor::
00037 FfmpegAudioCursor(FfmpegAudio *src) :
00038 MovieAudioCursor(src),
00039 _filename(src->_filename),
00040 _packet(0),
00041 _packet_data(0),
00042 _format_ctx(0),
00043 _audio_ctx(0),
00044 _buffer(0),
00045 _buffer_alloc(0)
00046 {
00047 if (!_ffvfile.open_vfs(_filename)) {
00048 cleanup();
00049 return;
00050 }
00051
00052 _format_ctx = _ffvfile.get_format_context();
00053 nassertv(_format_ctx != NULL);
00054
00055 if (av_find_stream_info(_format_ctx)<0) {
00056 cleanup();
00057 return;
00058 }
00059
00060
00061 for(int i = 0; i < (int)_format_ctx->nb_streams; i++) {
00062 if(_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
00063 _audio_index = i;
00064 _audio_ctx = _format_ctx->streams[i]->codec;
00065 _audio_timebase = av_q2d(_format_ctx->streams[i]->time_base);
00066 _audio_rate = _audio_ctx->sample_rate;
00067 _audio_channels = _audio_ctx->channels;
00068 }
00069 }
00070
00071 if (_audio_ctx == 0) {
00072 cleanup();
00073 return;
00074 }
00075
00076 AVCodec *pAudioCodec=avcodec_find_decoder(_audio_ctx->codec_id);
00077 if(pAudioCodec == 0) {
00078 cleanup();
00079 return;
00080 }
00081 if(avcodec_open(_audio_ctx, pAudioCodec)<0) {
00082 cleanup();
00083 return;
00084 }
00085
00086 _length = (_format_ctx->duration * 1.0) / AV_TIME_BASE;
00087 _can_seek = true;
00088 _can_seek_fast = true;
00089
00090 _packet = new AVPacket;
00091 _buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE / 2;
00092 _buffer_alloc = new PN_int16[_buffer_size + 128];
00093 if ((_packet == 0)||(_buffer_alloc == 0)) {
00094 cleanup();
00095 return;
00096 }
00097 memset(_packet, 0, sizeof(AVPacket));
00098
00099
00100
00101 _buffer = _buffer_alloc;
00102 while (((size_t)_buffer) & 15) {
00103 _buffer += 1;
00104 }
00105
00106 fetch_packet();
00107 _initial_dts = _packet->dts;
00108 _last_seek = 0;
00109 _samples_read = 0;
00110 _buffer_head = 0;
00111 _buffer_tail = 0;
00112 }
00113
00114
00115
00116
00117
00118
00119 FfmpegAudioCursor::
00120 ~FfmpegAudioCursor() {
00121 cleanup();
00122 }
00123
00124
00125
00126
00127
00128
00129 void FfmpegAudioCursor::
00130 cleanup() {
00131 if (_packet) {
00132 if (_packet->data) {
00133 av_free_packet(_packet);
00134 }
00135 delete _packet;
00136 _packet = NULL;
00137 }
00138
00139 if (_buffer_alloc) {
00140 delete[] _buffer_alloc;
00141 _buffer_alloc = 0;
00142 _buffer = NULL;
00143 }
00144
00145 if ((_audio_ctx)&&(_audio_ctx->codec)) {
00146 avcodec_close(_audio_ctx);
00147 }
00148 _audio_ctx = NULL;
00149
00150 if (_format_ctx) {
00151 _ffvfile.close();
00152 _format_ctx = NULL;
00153 }
00154
00155 _audio_index = -1;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164 void FfmpegAudioCursor::
00165 fetch_packet() {
00166 if (_packet->data) {
00167 av_free_packet(_packet);
00168 }
00169 while (av_read_frame(_format_ctx, _packet) >= 0) {
00170 if (_packet->stream_index == _audio_index) {
00171 _packet_size = _packet->size;
00172 _packet_data = _packet->data;
00173 return;
00174 }
00175 av_free_packet(_packet);
00176 }
00177 _packet->data = 0;
00178 _packet_size = 0;
00179 _packet_data = 0;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 bool FfmpegAudioCursor::
00191 reload_buffer() {
00192
00193
00194 while (_buffer_head == _buffer_tail) {
00195
00196 if (_packet->data == 0) {
00197 _buffer_head = 0;
00198 _buffer_tail = _buffer_size;
00199 memset(_buffer, 0, _buffer_size * 2);
00200 return true;
00201 } else if (_packet_size > 0) {
00202 int bufsize = _buffer_size * 2;
00203 #if LIBAVCODEC_VERSION_INT < 3414272
00204 #if LIBAVCODEC_VERSION_INT < 3349504
00205 int len = avcodec_decode_audio(_audio_ctx, _buffer, &bufsize,
00206 _packet_data, _packet_size);
00207 movies_debug("avcodec_decode_audio returned " << len);
00208 #else
00209 int len = avcodec_decode_audio2(_audio_ctx, _buffer, &bufsize,
00210 _packet_data, _packet_size);
00211 movies_debug("avcodec_decode_audio2 returned " << len);
00212 #endif
00213 #else
00214 AVPacket pkt;
00215 av_init_packet(&pkt);
00216 pkt.data = _packet_data;
00217 pkt.size = _packet_size;
00218 int len = avcodec_decode_audio3(_audio_ctx, _buffer, &bufsize, &pkt);
00219 movies_debug("avcodec_decode_audio3 returned " << len);
00220 av_free_packet(&pkt);
00221 #endif
00222 if (len < 0) {
00223 return false;
00224 } else if (len == 0){
00225 return true;
00226 }
00227 _packet_data += len;
00228 _packet_size -= len;
00229 if (bufsize > 0) {
00230 _buffer_head = 0;
00231 _buffer_tail = (bufsize/2);
00232 return true;
00233 }
00234 } else {
00235 fetch_packet();
00236 }
00237 }
00238 return true;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 void FfmpegAudioCursor::
00249 seek(double t) {
00250 PN_int64 target_ts = (PN_int64)(t / _audio_timebase);
00251 if (target_ts < (PN_int64)(_initial_dts)) {
00252
00253 target_ts = _initial_dts;
00254 }
00255 if (av_seek_frame(_format_ctx, _audio_index, target_ts, AVSEEK_FLAG_BACKWARD) < 0) {
00256 movies_cat.error() << "Seek failure. Shutting down movie.\n";
00257 cleanup();
00258 return;
00259 }
00260 avcodec_close(_audio_ctx);
00261 AVCodec *pAudioCodec=avcodec_find_decoder(_audio_ctx->codec_id);
00262 if(pAudioCodec == 0) {
00263 cleanup();
00264 return;
00265 }
00266 if(avcodec_open(_audio_ctx, pAudioCodec)<0) {
00267 cleanup();
00268 return;
00269 }
00270 _buffer_head = 0;
00271 _buffer_tail = 0;
00272 fetch_packet();
00273 double ts = _packet->dts * _audio_timebase;
00274 if (t > ts) {
00275 int skip = (int)((t-ts) * _audio_rate);
00276 read_samples(skip, 0);
00277 }
00278 _last_seek = t;
00279 _samples_read = 0;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 void FfmpegAudioCursor::
00291 read_samples(int n, PN_int16 *data) {
00292
00293
00294
00295 int desired = n * _audio_channels;
00296
00297 while (desired > 0) {
00298
00299 if (_buffer_head == _buffer_tail) {
00300 if(!reload_buffer()){
00301 break;
00302 }
00303 movies_debug("read_samples() Desired samples: " << desired << " N:" << n);
00304 }
00305 int available = _buffer_tail - _buffer_head;
00306 int ncopy = (desired > available) ? available : desired;
00307 if (ncopy) {
00308 if (data != 0) {
00309 memcpy(data, _buffer + _buffer_head, ncopy * 2);
00310 data += ncopy;
00311 }
00312 desired -= ncopy;
00313 _buffer_head += ncopy;
00314 }
00315
00316 }
00317 _samples_read += n;
00318 }
00319
00320
00321
00322 #endif // HAVE_FFMPEG