[mythtv] Audio Update - Another patch

Jesper Sörensen jesper at datapartner.se
Sat Oct 23 11:53:54 UTC 2004


Ed Wildgoose wrote:

> Here is a link to the latest version of my audio patch.  This is an 
> interim version and is not for cvs, but mainly so that David and 
> Jesper can check what I have done versus their stuff.


Thanks! Getting some problems here:

g++ -c -pipe -Wall -W -g -D_REENTRANT  -D_GNU_SOURCE 
-D_FILE_OFFSET_BITS=64 -DPREFIX=\"/usr\" -DMMX -DCONFIG_VIDEO4LINUX 
-DUSING_OSS -DUSING_DVB -DQT_THREAD_SUPPORT -DQT_SHARED -DQT_NO_DEBUG 
-I/usr/share/qt3/mkspecs/default -I. -I../../libs -I../../libs/libmyth 
-I../../libs/libmythtv -I../../libs/libavcodec -I../../libs/libavformat 
-I/usr/include -I/usr/local/include -I/usr/include/qt3 -o transcode.o 
transcode.cpp
transcode.cpp: In member function `int Transcode::TranscodeFile(char*, 
char*,
   QString, bool, bool, bool, QString)':
transcode.cpp:276: error: cannot allocate an object of type `
   AudioReencodeBuffer'
transcode.cpp:276: error:   because the following virtual functions are
   abstract:
../../libs/libmyth/audiooutput.h:50: error:     virtual int
   AudioOutput::GetVolumeChannel(int)
../../libs/libmyth/audiooutput.h:51: error:     virtual void
   AudioOutput::SetVolumeChannel(int, int)
make[3]: *** [transcode.o] Error 1

> Jesper could you check that I have your core audio patches included 
> correctly.


If you mean my little Alsa patch, it is *not* included in your 
patch/files. It's attached to this e-mail in case you lost it or if 
someone else would like to take a look at it.

Apply with "patch -p2 -s -i alsa_crash_fix.patch" or similar.

What it does, in short:
- Fixes NULL device crash
- Handle errors better (don't close the device!)
- Various logging/debugging changes and some minor cleanup

Tested with Linux 2.6.8.1 and Alsa lib 1.0.6a or something like that. 
Works fine on my Revo.

Please note: This patch is against Ed's patch - it probably won't work 
against CVS.

Rgds,
Jesper

-------------- next part --------------
--- cvs.old/mythtv/libs/libmyth/audiooutputalsa.cpp	2004-10-11 17:48:54.000000000 +0200
+++ cvs/mythtv/libs/libmyth/audiooutputalsa.cpp	2004-10-11 23:16:21.000000000 +0200
@@ -29,19 +29,11 @@
 
 bool AudioOutputALSA::OpenDevice()
 {
-    snd_pcm_t *new_pcm_handle;
     snd_pcm_format_t format;
     unsigned int buffer_time = 500000, period_time = 100000;
-
     int err;
 
-    new_pcm_handle = pcm_handle;
     pcm_handle = NULL;
-
-//    if (new_pcm_handle != NULL)
-//        snd_pcm_hw_free(new_pcm_handle);
-
-    
     numbadioctls = 0;
     
     err = snd_pcm_open(&pcm_handle, audiodevice,
@@ -49,7 +41,7 @@
 
     if (err < 0)
     { 
-        Error(QString("snd_pcm_open(%1) error %2")
+        Error(QString("snd_pcm_open(%1): %2")
               .arg(audiodevice).arg(snd_strerror(err)));
     }
 
@@ -58,7 +50,7 @@
     snd_pcm_uframes_t avail = 0;
     snd_pcm_hw_params_t *hw_params;
     if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
-        Error(QString("cannot allocate hardware parameter structure (%1)")
+        Error(QString("snd_pcm_hw_params_malloc: %1")
               .arg(snd_strerror(err)));
     }
     snd_pcm_hw_params_current(pcm_handle, hw_params);
@@ -87,8 +79,7 @@
                         period_time);
     if (err < 0) 
     {
-        snd_pcm_close(pcm_handle);
-        pcm_handle = NULL;
+        CloseDevice();
         return false;
     }    
 
@@ -108,21 +99,25 @@
 
 void AudioOutputALSA::WriteAudio(unsigned char *aubuf, int size)
 {
-    if (pcm_handle == NULL)
-        return;
-
     unsigned char *tmpbuf;
     int lw = 0;
     int frames = size / audio_bytes_per_sample;
 
+    if (pcm_handle == NULL)
+    {
+        VERBOSE(VB_IMPORTANT, QString("WriteAudio() called with pcm_handle == NULL!"));
+        return;
+    }
+
     tmpbuf = aubuf;
 
-    VERBOSE(VB_AUDIO, QString("Preparing %1 bytes (%2 frames) in WriteAudio")
+    VERBOSE(VB_AUDIO, QString("WriteAudio: Preparing %1 bytes (%2 frames)")
             .arg(size).arg(frames));
     
     while (frames > 0) 
     {
         lw = snd_pcm_mmap_writei(pcm_handle, tmpbuf, frames);
+
         if (lw >= 0)
         {
             frames -= lw;
@@ -130,34 +125,53 @@
         } 
         else if (lw == -EAGAIN)
         {
-            VERBOSE(VB_AUDIO, QString("Soundcard is blocked.  Waiting for card to become ready"));
+            VERBOSE(VB_AUDIO, QString("WriteAudio: device is blocked - waiting"));
+
             snd_pcm_wait(pcm_handle, 10);
         }
-        else if (lw == -EPIPE &&
-                 snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN &&
-                 snd_pcm_prepare(pcm_handle) == 0)
+        else if (lw == -EPIPE)
         {
-            VERBOSE(VB_AUDIO, "WriteAudio: xrun (buffer underrun)");
-            continue;
+            VERBOSE(VB_IMPORTANT, "WriteAudio: buffer underrun");
+
+            if ((lw = snd_pcm_prepare(pcm_handle)) < 0)
+            {
+                Error(QString("WriteAudio: unable to recover from xrun: %1")
+                      .arg(snd_strerror(lw)));
+                return;
+            }
         }
-        else if (lw == -EPIPE &&
-                 snd_pcm_state(pcm_handle) == SND_PCM_STATE_SUSPENDED)
+        else if (lw == -ESTRPIPE)
         {
-            VERBOSE(VB_AUDIO, "WriteAudio: suspended");
+            VERBOSE(VB_IMPORTANT, "WriteAudio: device is suspended");
 
             while ((lw = snd_pcm_resume(pcm_handle)) == -EAGAIN)
                 usleep(200);
 
-            if (lw < 0 && (lw = snd_pcm_prepare(pcm_handle)) == 0)
-                continue;
+            if (lw < 0)
+            {
+                VERBOSE(VB_IMPORTANT, "WriteAudio: resume failed");
+
+                if ((lw = snd_pcm_prepare(pcm_handle)) < 0)
+                {
+                    Error(QString("WriteAudio: unable to recover from suspend: %1")
+                          .arg(snd_strerror(lw)));
+                    return;
+                }
+            }
         }
+        else if (lw == -EBADFD)
+        {
+            VERBOSE(VB_IMPORTANT, QString("WriteAudio: device is in a bad state (state = %1)").arg(snd_pcm_state(pcm_handle)));
 
-        if (lw < 0)
+            return;
+        }
+        else
         {
-            Error(QString("snd_pcm_mmap_writei(%1,frames=%2) error %3: %4")
-                  .arg(audiodevice).arg(frames).arg(snd_strerror(lw)));
-            snd_pcm_close(pcm_handle);
-            pcm_handle = NULL;
+            VERBOSE(VB_IMPORTANT, QString("snd_pcm_mmap_writei: %3 (%4)")
+                  .arg(snd_strerror(lw)).arg(lw));
+            VERBOSE(VB_IMPORTANT, QString("WriteAudio: snd_pcm_state == %1").arg(snd_pcm_state(pcm_handle)));
+
+            // CloseDevice();
             return;
         }
     }
@@ -168,6 +182,13 @@
     int err;
     snd_pcm_uframes_t soundcard_buffer = 0;
     snd_pcm_hw_params_t *hw_params;
+
+    if (pcm_handle == NULL)
+    {
+        VERBOSE(VB_IMPORTANT, QString("getBufferedOnSoundcard() called with pcm_handle == NULL!"));
+        return 0;
+    }
+
     if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
         Error(QString("cannot allocate hardware parameter structure (%1)")
               .arg(snd_strerror(err)));
@@ -188,12 +209,15 @@
     int err = 0;
 
     if (pcm_handle == NULL)
-      return 0;
+    {
+        VERBOSE(VB_IMPORTANT, QString("getSpaceOnSoundcard() called with pcm_handle == NULL!"));
+        return 0;
+    }
 
     snd_pcm_uframes_t soundcard_buffer = 0; // total buffer on soundcard
     snd_pcm_hw_params_t *hw_params;
     if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
-        Error(QString("cannot allocate hardware parameter structure (%1)")
+        Error(QString("snd_pcm_hw_params_malloc: %1")
               .arg(snd_strerror(err)));
     }
     snd_pcm_hw_params_current(pcm_handle, hw_params);
@@ -207,7 +231,7 @@
     // make sure that we are actually in the running state otherwise
     // snd_pcm_delay return is meaningless
     if (snd_pcm_state(pcm_handle) < SND_PCM_STATE_RUNNING)
-        VERBOSE(VB_IMPORTANT, QString("Not in the running state, state=%1")
+        VERBOSE(VB_AUDIO, QString("Not in the running state, state=%1")
                 .arg(snd_pcm_state(pcm_handle)));
 
     // Free space is the total buffer minus the frames waiting to be written
@@ -249,6 +273,12 @@
                               "rate=%3, buffer_time=%4, period_time=%5")
             .arg(format).arg(channels).arg(rate).arg(buffer_time).arg(period_time));
     
+    if (pcm_handle == NULL)
+    {
+        VERBOSE(VB_IMPORTANT, QString("SetParameters() called with pcm_handle == NULL!"));
+        return 0;
+    }
+
     snd_pcm_hw_params_alloca(&params);
     snd_pcm_sw_params_alloca(&swparams);
     


More information about the mythtv-dev mailing list