Răsfoiți Sursa

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.

treeform 17 ani în urmă
părinte
comite
83803724e6
2 a modificat fișierele cu 40 adăugiri și 13 ștergeri
  1. 27 13
      panda/src/movies/ffmpegAudioCursor.cxx
  2. 13 0
      panda/src/movies/movieAudio.h

+ 27 - 13
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="<<n);
+
   int desired = n * _audio_channels;
-  while (desired) {
+
+  // give up after 100 tries to fetch data
+  int give_up_after = 100;
+
+  while (desired && give_up_after > 0) {
+
     if (_buffer_head == _buffer_tail) {
       reload_buffer();
+      give_up_after --;
+      movies_debug("reload_buffer will give up in "<<give_up_after);
     }
     int available = _buffer_tail - _buffer_head;
     int ncopy = (desired > available) ? available : desired;
@@ -272,6 +285,7 @@ read_samples(int n, PN_int16 *data) {
       desired -= ncopy;
       _buffer_head += ncopy;
     }
+
   }
   _samples_read += n;
 }

+ 13 - 0
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