From 83803724e6a7cbe004b4824c28e3bb91ceed8704 Mon Sep 17 00:00:00 2001 From: treeform Date: Sun, 28 Dec 2008 06:24:14 +0000 Subject: [PATCH] i was working on openAL and found one bug which would cause infinite loop when if avcodec_decode_audio (ffmpeg function) returned 0 in the loop its in and when fixed in the loop above it. see post http://panda3d.org/phpbb2/viewtopic.php?p=30331#30331 most changes are to ffmpegAudioCursor.cxx and movieAudio.h It basically changes to proper error handling with 0 as DONE - if (len < 0) { + if (len <= 0) { and create a give up counter + // give up after 100 tries to fetch data + int give_up_after = 100; + + while (desired && give_up_after > 0) { + give_up_after --; and some helpful debug messages for the next poor coder to step into this code. --- panda/src/movies/ffmpegAudioCursor.cxx | 40 +++++++++++++++++--------- panda/src/movies/movieAudio.h | 13 +++++++++ 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/panda/src/movies/ffmpegAudioCursor.cxx b/panda/src/movies/ffmpegAudioCursor.cxx index bbd2c2712f..175f671863 100644 --- a/panda/src/movies/ffmpegAudioCursor.cxx +++ b/panda/src/movies/ffmpegAudioCursor.cxx @@ -44,12 +44,12 @@ FfmpegAudioCursor(FfmpegAudio *src) : cleanup(); return; } - + if (av_find_stream_info(_format_ctx)<0) { cleanup(); return; } - + // Find the audio stream for(int i=0; i<_format_ctx->nb_streams; i++) { if(_format_ctx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) { @@ -60,12 +60,12 @@ FfmpegAudioCursor(FfmpegAudio *src) : _audio_channels = _audio_ctx->channels; } } - + if (_audio_ctx == 0) { cleanup(); return; } - + AVCodec *pAudioCodec=avcodec_find_decoder(_audio_ctx->codec_id); if(pAudioCodec == 0) { cleanup(); @@ -88,14 +88,14 @@ FfmpegAudioCursor(FfmpegAudio *src) : return; } memset(_packet, 0, sizeof(AVPacket)); - + // Align the buffer to a 16-byte boundary // The ffmpeg codec likes this, because it uses SSE/SSE2. _buffer = _buffer_alloc; while (((size_t)_buffer) & 15) { _buffer += 1; } - + fetch_packet(); _initial_dts = _packet->dts; _last_seek = 0; @@ -148,7 +148,7 @@ cleanup() { //////////////////////////////////////////////////////////////////// // Function: FfmpegAudioCursor::fetch_packet // Access: Protected -// Description: Fetches an audio packet and stores it in the +// Description: Fetches an audio packet and stores it in the // packet buffer. Also sets packet_size and packet_data. //////////////////////////////////////////////////////////////////// void FfmpegAudioCursor:: @@ -179,6 +179,8 @@ fetch_packet() { //////////////////////////////////////////////////////////////////// void FfmpegAudioCursor:: reload_buffer() { + + while (_buffer_head == _buffer_tail) { // If we're out of packets, generate silence. if (_packet->data == 0) { @@ -188,9 +190,10 @@ reload_buffer() { return; } else if (_packet_size > 0) { int bufsize = _buffer_size * 2; - int len = avcodec_decode_audio(_audio_ctx, _buffer, &bufsize, + int len = avcodec_decode_audio(_audio_ctx, _buffer, &bufsize, _packet_data, _packet_size); - if (len < 0) { + movies_debug("avcodec_decode_audio returned " << len); + if (len <= 0) { break; } _packet_data += len; @@ -210,7 +213,7 @@ reload_buffer() { // Function: FfmpegAudioCursor::seek // Access: Protected // Description: Seeks to a target location. Afterward, the -// packet_time is guaranteed to be less than or +// packet_time is guaranteed to be less than or // equal to the specified time. //////////////////////////////////////////////////////////////////// void FfmpegAudioCursor:: @@ -252,15 +255,25 @@ seek(double t) { // Access: Public, Virtual // Description: Read audio samples from the stream. N is the // number of samples you wish to read. Your buffer -// must be equal in size to N * channels. -// Multiple-channel audio will be interleaved. +// must be equal in size to N * channels. +// Multiple-channel audio will be interleaved. //////////////////////////////////////////////////////////////////// void FfmpegAudioCursor:: read_samples(int n, PN_int16 *data) { + + //movies_debug("here!!! FfmpegAudioCursor n="< 0) { + if (_buffer_head == _buffer_tail) { reload_buffer(); + give_up_after --; + movies_debug("reload_buffer will give up in "< available) ? available : desired; @@ -272,6 +285,7 @@ read_samples(int n, PN_int16 *data) { desired -= ncopy; _buffer_head += ncopy; } + } _samples_read += n; } diff --git a/panda/src/movies/movieAudio.h b/panda/src/movies/movieAudio.h index 6dd1d269a0..139f3893a8 100644 --- a/panda/src/movies/movieAudio.h +++ b/panda/src/movies/movieAudio.h @@ -21,6 +21,19 @@ #include "typedWritableReferenceCount.h" class MovieAudioCursor; + +#ifdef NOTIFY_DEBUG //[ + // Non-release build: + #define movies_debug(msg) \ + if (movies_cat.is_debug()) { \ + movies_cat->debug() << msg << endl; \ + } else {} +#else //][ + // Release build: + #define movies_debug(msg) ((void)0); +#endif //] + + //////////////////////////////////////////////////////////////////// // Class : MovieAudio // Description : A MovieAudio is actually any source that provides