Panda3D

ffmpegAudioCursor.cxx

00001 // Filename: ffmpegAudioCursor.cxx
00002 // Created by: jyelon (01Aug2007)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
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 //     Function: FfmpegAudioCursor::Constructor
00033 //       Access: Protected
00034 //  Description: xxx
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   // Find the audio stream
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   // Align the buffer to a 16-byte boundary
00100   // The ffmpeg codec likes this, because it uses SSE/SSE2.
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 //     Function: FfmpegAudioCursor::Destructor
00116 //       Access: Protected, Virtual
00117 //  Description: xxx
00118 ////////////////////////////////////////////////////////////////////
00119 FfmpegAudioCursor::
00120 ~FfmpegAudioCursor() {
00121   cleanup();
00122 }
00123 
00124 ////////////////////////////////////////////////////////////////////
00125 //     Function: FfmpegAudioCursor::cleanup
00126 //       Access: Public
00127 //  Description: Reset to a standard inactive state.
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 //     Function: FfmpegAudioCursor::fetch_packet
00160 //       Access: Protected
00161 //  Description: Fetches an audio packet and stores it in the
00162 //               packet buffer.  Also sets packet_size and packet_data.
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 //     Function: FfmpegAudioCursor::reload_buffer
00184 //       Access: Protected
00185 //  Description: Reloads the audio buffer by decoding audio packets
00186 //               until one of those audio packets finally yields
00187 //               some samples.  If we encounter the end of the
00188 //               stream, we synthesize silence.
00189 ////////////////////////////////////////////////////////////////////
00190 bool FfmpegAudioCursor::
00191 reload_buffer() {
00192 
00193 
00194   while (_buffer_head == _buffer_tail) {
00195     // If we're out of packets, generate silence.
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); // Not sure about this
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 //     Function: FfmpegAudioCursor::seek
00243 //       Access: Protected
00244 //  Description: Seeks to a target location.  Afterward, the
00245 //               packet_time is guaranteed to be less than or
00246 //               equal to the specified time.
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     // Attempts to seek before the first packet will fail.
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 //     Function: FfmpegAudioCursor::read_samples
00284 //       Access: Public, Virtual
00285 //  Description: Read audio samples from the stream.  N is the
00286 //               number of samples you wish to read.  Your buffer
00287 //               must be equal in size to N * channels.
00288 //               Multiple-channel audio will be interleaved.
00289 ////////////////////////////////////////////////////////////////////
00290 void FfmpegAudioCursor::
00291 read_samples(int n, PN_int16 *data) {
00292 
00293   //movies_debug("here!!! FfmpegAudioCursor n="<<n);
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
 All Classes Functions Variables Enumerations