Panda3D
|
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