[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog backend/sound_handler_sdl.cpp
From: |
Tomas Groth |
Subject: |
[Gnash-commit] gnash ChangeLog backend/sound_handler_sdl.cpp |
Date: |
Wed, 08 Nov 2006 15:40:30 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Tomas Groth <tgc> 06/11/08 15:40:30
Modified files:
. : ChangeLog
backend : sound_handler_sdl.cpp
Log message:
* backend/sound_handler_sdl.cpp: Made ffmpeg error handling
more robust. Fixed a deadlock. Added a notice that upgrading
ffmpeg might fix mp3-errror. Made stop_all_sounds() thread
safe.
Make mp3-decoding with mad work when the stream is not fully
loaded when playback starts.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.1560&r2=1.1561
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_sdl.cpp?cvsroot=gnash&r1=1.34&r2=1.35
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.1560
retrieving revision 1.1561
diff -u -b -r1.1560 -r1.1561
--- ChangeLog 8 Nov 2006 10:08:41 -0000 1.1560
+++ ChangeLog 8 Nov 2006 15:40:30 -0000 1.1561
@@ -1,3 +1,11 @@
+2006-11-08 Tomas Groth Christensen <address@hidden>
+
+ * backend/sound_handler_sdl.cpp: Made ffmpeg error handling
+ more robust. Fixed a deadlock. Added a notice that upgrading
+ ffmpeg might fix mp3-errror. Made stop_all_sounds() thread safe.
+ Make mp3-decoding with mad work when the stream is not fully
+ loaded when playback starts.
+
2006-11-08 Sandro Santilli <address@hidden>
* libbase/smart_ptr.h: *fixed* invariant testing (well, at
Index: backend/sound_handler_sdl.cpp
===================================================================
RCS file: /sources/gnash/gnash/backend/sound_handler_sdl.cpp,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -b -r1.34 -r1.35
--- backend/sound_handler_sdl.cpp 3 Nov 2006 11:17:06 -0000 1.34
+++ backend/sound_handler_sdl.cpp 8 Nov 2006 15:40:30 -0000 1.35
@@ -219,13 +219,6 @@
for(uint32_t i=0; i <
m_sound_data[handle_id]->m_active_sounds.size(); i++) {
m_sound_data[handle_id]->m_active_sounds[i]->data =
m_sound_data[handle_id]->data;
m_sound_data[handle_id]->m_active_sounds[i]->data_size
= m_sound_data[handle_id]->data_size;
-#ifdef USE_MAD
- uint64_t this_frame = (const
Uint8*)m_sound_data[handle_id]->m_active_sounds[i]->stream.this_frame -
m_sound_data[handle_id]->m_active_sounds[i]->data;
- uint64_t next_frame = (const
Uint8*)m_sound_data[handle_id]->m_active_sounds[i]->stream.next_frame -
m_sound_data[handle_id]->m_active_sounds[i]->data;
-
mad_stream_buffer(&m_sound_data[handle_id]->m_active_sounds[i]->stream,
m_sound_data[handle_id]->data, m_sound_data[handle_id]->data_size);
-
m_sound_data[handle_id]->m_active_sounds[i]->stream.this_frame += this_frame;
-
m_sound_data[handle_id]->m_active_sounds[i]->stream.next_frame += next_frame;
-#endif
}
} else {
@@ -267,10 +260,12 @@
sound->data = m_sound_data[sound_handle]->data;
// Set the given options of the sound
- sound->position = start_position;
if (start_position < 0) sound->position = 0;
- sound->offset = (m_sound_data[sound_handle]->stereo ? offset :
offset*2); // offset is stored as stereo
+ else sound->position = start_position;
+
if (offset < 0) sound->offset = 0;
+ else sound->offset = (m_sound_data[sound_handle]->stereo ? offset :
offset*2); // offset is stored as stereo
+
sound->envelopes = envelopes;
sound->current_env = 0;
sound->samples_played = 0;
@@ -306,7 +301,6 @@
mad_stream_init(&sound->stream);
mad_frame_init(&sound->frame);
mad_synth_init(&sound->synth);
- mad_stream_buffer(&sound->stream, sound->data+sound->position,
sound->data_size-sound->position);
sound->raw_data = 0;
sound->raw_data_size = 0;
@@ -398,9 +392,35 @@
// for what sounds is associated with what SWF.
void SDL_sound_handler::stop_all_sounds()
{
+ pthread_mutex_lock(&mutex);
+
int32_t num_sounds = (int32_t) m_sound_data.size()-1;
- for (int32_t i = num_sounds; i > -1; i--) //Optimized
- stop_sound(i);
+ for (int32_t j = num_sounds; j > -1; j--) {//Optimized
+ int32_t num_active_sounds = (int32_t)
m_sound_data[j]->m_active_sounds.size()-1;
+ for (int32_t i = num_active_sounds; i > -1; i--) {
+
+ // Stop sound, remove it from the active list (mp3)
+ if (m_sound_data[j]->format == 2) {
+#ifdef USE_FFMPEG
+
avcodec_close(m_sound_data[j]->m_active_sounds[i]->cc);
+
av_parser_close(m_sound_data[j]->m_active_sounds[i]->parser);
+#elif defined(USE_MAD)
+
mad_synth_finish(&m_sound_data[j]->m_active_sounds[i]->synth);
+
mad_frame_finish(&m_sound_data[j]->m_active_sounds[i]->frame);
+
mad_stream_finish(&m_sound_data[j]->m_active_sounds[i]->stream);
+#endif
+ delete[]
m_sound_data[j]->m_active_sounds[i]->raw_data;
+
m_sound_data[j]->m_active_sounds.erase(m_sound_data[j]->m_active_sounds.begin()
+ i);
+ soundsPlaying--;
+
+ // Stop sound, remove it from the active list
(adpcm/native16)
+ } else {
+
m_sound_data[i]->m_active_sounds.erase(m_sound_data[j]->m_active_sounds.begin()
+ i);
+ soundsPlaying--;
+ }
+ }
+ }
+ pthread_mutex_unlock(&mutex);
}
@@ -632,13 +652,14 @@
next_env_pos =
(*sound->envelopes)[sound->current_env+1].m_mark44;
}
- int startpos = 0;
+ unsigned int startpos = 0;
// Make sure we start adjusting at the right sample
if (sound->current_env == 0 &&
(*sound->envelopes)[sound->current_env].m_mark44 > sound->samples_played) {
startpos = sound->raw_position +
((*sound->envelopes)[sound->current_env].m_mark44 - sound->samples_played)*2;
} else {
startpos = sound->raw_position;
}
+ assert(sound->raw_data_size > startpos);
int16_t* data = (int16_t*) (sound->raw_data + startpos);
for (unsigned int i=0; i < length/2; i+=2) {
@@ -662,7 +683,14 @@
}
-// The callback function which refills the buffer with data
+/// The callback function which refills the buffer with data
+/// We run through all of the sounds, and mix all of the active sounds
+/// into the stream given by the callback.
+/// If sound is compresssed (mp3) a mp3-frame is decoded into a buffer,
+/// and resampled if needed. When the buffer has been sampled, another
+/// frame is decoded until all frames has been decoded.
+/// If a sound is looping it will be decoded from the beginning again.
+
static void
sdl_audio_callback (void *udata, Uint8 *stream, int buffer_length_in)
{
@@ -675,11 +703,7 @@
unsigned int buffer_length = static_cast<unsigned
int>(buffer_length_in);
- // We run through all of the sounds, and mix all of the active sounds
- // into the stream given by the callback.
- // If a sound is looping it will be decoded from the beginning again.
- // When a sound is finished the empty space in the stream will be set
to 0.
-
+ // Get the soundhandler
SDL_sound_handler* handler = static_cast<SDL_sound_handler*>(udata);
// If nothing to play there is no reason to play
@@ -692,7 +716,7 @@
pthread_mutex_lock(&handler->mutex);
// Mixed sounddata buffer
- Uint8* buffer = stream; //new Uint8[len];
+ Uint8* buffer = stream;
memset(buffer, 0, buffer_length);
@@ -738,9 +762,13 @@
sound->raw_data_size -
sound->raw_position,
handler->m_sound_data[i]->volume);
} else if (sound->envelopes != NULL) {
- assert(sound->raw_data_size >=
sound->raw_position);
+ assert(sound->raw_data_size >
sound->raw_position);
use_envelopes(sound,
sound->raw_data_size - sound->raw_position);
}
+
+ // Test if we will get problems...
Should not happen...
+ assert(sound->raw_data_size >
sound->raw_position);
+
SDL_MixAudio(stream, (const
Uint8*)(sound->raw_data + sound->raw_position),
sound->raw_data_size -
sound->raw_position,
SDL_MIX_MAXVOLUME);
@@ -751,13 +779,17 @@
// Then we decode some data
int outsize = 0;
-#ifdef USE_FFMPEG
+
// If we need to loop, we reset the data pointer
if (sound->data_size == sound->position &&
sound->loop_count != 0) {
sound->loop_count--;
sound->position = 0;
}
+ // Test if we will get problems... Should not
happen...
+ assert(sound->data_size > sound->position);
+
+#ifdef USE_FFMPEG
if (sound->raw_data_size > 0)
memset(sound->raw_data, 0, sound->raw_data_size);
long bytes_decoded = 0;
@@ -773,11 +805,12 @@
int tmp = 0;
tmp = avcodec_decode_audio(sound->cc,
(int16_t *)sound->raw_data, &outsize, frame, framesize);
- if (bytes_decoded < 0) {
- gnash::log_error("Error while
decoding MP3-stream\n");
- // TODO: Remove the sound from
the active list
+ if (bytes_decoded < 0 || tmp < 0 ||
outsize < 0) {
+ gnash::log_error("Error while
decoding MP3-stream. Upgrading ffmpeg/libavcodec might fix this issue.\n");
+ // Setting data position to
data size will get the sound removed
+ // from the active sound list
later on.
sound->position =
sound->data_size;
- continue;
+ break;
}
sound->position += bytes_decoded;
@@ -785,32 +818,40 @@
#elif defined(USE_MAD)
- // If we need to loop, we reset the data
pointer, and tell mad about it
- if (sound->data_size == sound->position &&
sound->loop_count != 0) {
- sound->position = 0;
- mad_stream_buffer(&sound->stream,
sound->data, sound->data_size);
- sound->loop_count--;
- }
+ // Setup the mad decoder
+ mad_stream_buffer(&sound->stream,
sound->data+sound->position, sound->data_size-sound->position);
int ret;
+ const unsigned char* old_next_frame =
sound->stream.next_frame;
+ int loops = 0;
while(true) {
+
ret = mad_frame_decode(&sound->frame,
&sound->stream);
+ loops++;
// There is always some junk in front
of the data,
// so we continue until we get past it.
if (ret && sound->stream.error ==
MAD_ERROR_LOSTSYNC) continue;
+ // Error handling is done by relooping
(max. 8 times) and just hooping that it will work...
+ if (loops > 8) break;
+ if (ret == -1 && sound->stream.error !=
MAD_ERROR_BUFLEN && MAD_RECOVERABLE(sound->stream.error)) {
+ gnash::log_warning("Recoverable
error while decoding MP3-stream, MAD error: %s", mad_stream_errorstr
(&sound->stream));
+ continue;
+ }
+
break;
}
if (ret == -1 && sound->stream.error !=
MAD_ERROR_BUFLEN) {
- gnash::log_error("Error while decoding
MP3-stream, MAD error: %d", sound->stream.error);
+ gnash::log_error("Unrecoverable error
while decoding MP3-stream, MAD error: %s", mad_stream_errorstr
(&sound->stream));
+ sound->position = sound->data_size;
continue;
} else if (ret == -1 && sound->stream.error ==
MAD_ERROR_BUFLEN) {
// the buffer is empty, no more to
decode!
sound->position = sound->data_size;
} else {
- sound->position +=
sound->stream.next_frame - sound->stream.buffer - sound->position;
+ sound->position +=
sound->stream.next_frame - old_next_frame;
}
mad_synth_frame (&sound->synth, &sound->frame);
@@ -886,18 +927,20 @@
use_envelopes(sound, buffer_length -
index);
}
+ // Test if we will get problems... Should not
happen...
+ assert(sound->raw_position + buffer_length -
index < sound->raw_data_size);
+
// Then we mix the newly decoded data
SDL_MixAudio((Uint8*)(stream+index),(const
Uint8*) sound->raw_data,
buffer_length - index,
SDL_MIX_MAXVOLUME);
sound->raw_position = buffer_length - index;
-
sound->samples_played += buffer_length - index;
// When the current sound has enough decoded data to
fill
// the buffer, we do just that.
- } else if (sound->raw_data_size - sound->raw_position
>= buffer_length ) {
+ } else if (sound->raw_data_size - sound->raw_position >
buffer_length ) {
// If the volume needs adjustments we call a
function to do that
if (handler->m_sound_data[i]->volume != 100) {
@@ -914,13 +957,12 @@
SDL_MIX_MAXVOLUME);
sound->raw_position += buffer_length;
-
sound->samples_played += buffer_length;
// When the current sound doesn't have anymore data to
decode,
// and doesn't loop (anymore), but still got unplayed
data,
// we put the last data on the stream
- } else if (sound->raw_data_size - sound->raw_position <
buffer_length && sound->raw_data_size > sound->raw_position) {
+ } else if (sound->raw_data_size - sound->raw_position
<= buffer_length && sound->raw_data_size > sound->raw_position+1) {
// If the volume needs adjustments we call a
function to do that
if (handler->m_sound_data[i]->volume != 100) {
@@ -936,8 +978,6 @@
sound->raw_data_size -
sound->raw_position,
SDL_MIX_MAXVOLUME);
sound->raw_position = sound->raw_data_size;
-
- } else {
}
// Sound is done, remove it from the active list (mp3)