[mythtv] [PATCH] mono support, take three

Jim Radford mythtv-dev@snowman.net
Sat, 23 Nov 2002 21:53:41 -0800


Hi John and Isaac,

Here is the latest version of my mono and 8bit support patch.  Mono
should work both uncompressed and compressed while 8bit only works
uncompressed.  I got rid of the dynamic configuration by changing the
init order as was suggested.  It works well for me.

-Jim

Index: libs/libNuppelVideo/NuppelVideoPlayer.cpp
===================================================================
RCS file: /var/lib/cvs/MC/libs/libNuppelVideo/NuppelVideoPlayer.cpp,v
retrieving revision 1.99
diff -u -r1.99 NuppelVideoPlayer.cpp
--- libs/libNuppelVideo/NuppelVideoPlayer.cpp	24 Nov 2002 01:57:46 -0000	1.99
+++ libs/libNuppelVideo/NuppelVideoPlayer.cpp	24 Nov 2002 05:41:32 -0000
@@ -83,7 +83,11 @@
     weMadeBuffer = false;
 
     osd = NULL;
+    audio_bits = 16;
+    audio_channels = 2;
     audio_samplerate = 44100;
+    audio_bytes_per_sample = audio_channels * audio_bits/8;
+
     editmode = false;
     advancevideo = resetvideo = advancedecoder = false;
 
@@ -245,13 +249,13 @@
 
 void NuppelVideoPlayer::InitSound(void)
 {
-    int bits = 16, stereo = 1, speed = audio_samplerate, caps;
+    int caps;
 
     if (usingextradata)
     {
-        bits = extradata.audio_bits_per_sample;
-        stereo = (extradata.audio_channels == 2);
-        speed = extradata.audio_sample_rate;
+        audio_bits = extradata.audio_bits_per_sample;
+        audio_channels = extradata.audio_channels;
+        audio_samplerate = extradata.audio_sample_rate;
     }
 
     if (disableaudio)
@@ -268,29 +272,21 @@
 	return;
     }
 
-    if (ioctl(audiofd, SNDCTL_DSP_SAMPLESIZE, &bits) < 0)
-    {
-        cerr << "problem setting sample size, exiting\n";
+    if (ioctl(audiofd, SNDCTL_DSP_SAMPLESIZE, &audio_bits) < 0 ||
+        ioctl(audiofd, SNDCTL_DSP_CHANNELS, &audio_channels) < 0 ||
+        ioctl(audiofd, SNDCTL_DSP_SPEED, &audio_samplerate) < 0)
+    {
+        cerr << "player: " << audiodevice 
+             << ": error setting audio output device to "
+             << audio_samplerate << "kHz/" 
+             << audio_bits << "bits/"
+             << audio_channels << "channel\n";
         close(audiofd);
         audiofd = -1;
         return;
     }
 
-    if (ioctl(audiofd, SNDCTL_DSP_STEREO, &stereo) < 0) 
-    {
-        cerr << "problem setting to stereo, exiting\n";
-        close(audiofd);
-        audiofd = -1;
-        return;
-    }
-
-    if (ioctl(audiofd, SNDCTL_DSP_SPEED, &speed) < 0) 
-    {
-        cerr << "problem setting sample rate, exiting\n";
-        close(audiofd);
-        audiofd = -1;
-        return;
-    }
+    audio_bytes_per_sample = audio_channels * audio_bits/8;
 
     if (ioctl(audiofd, SNDCTL_DSP_GETCAPS, &caps) >= 0 && 
         !(caps & DSP_CAP_REALTIME))
@@ -559,7 +555,12 @@
     foundit = 0;
     effdsp = audio_samplerate;
     if (usingextradata)
+    {
         effdsp = extradata.audio_sample_rate;
+        audio_channels = extradata.audio_channels;
+        audio_bits = extradata.audio_bits_per_sample;
+        audio_bytes_per_sample = audio_channels * audio_bits/8;
+    }
 
     while (!foundit) 
     {
@@ -979,8 +980,8 @@
     ioctl(audiofd, SNDCTL_DSP_GETODELAY, &soundcard_buffer); // bytes
     totalbuffer = audiolen(false) + soundcard_buffer;
                
-    audiotime = audbuf_timecode - (int)((double)totalbuffer * 25000.0 /
-                                        (double)effdsp);
+    audiotime = audbuf_timecode - 
+      (int)(totalbuffer * 100000.0 / (audio_bytes_per_sample * effdsp));
  
     gettimeofday(&audiotime_updated, NULL);
 
@@ -1096,7 +1097,6 @@
             else if (frameheader.comptype=='3') 
             {
                 int lameret = 0;
-                int len = 0;
                 short int pcmlbuffer[audio_samplerate]; 
                 short int pcmrbuffer[audio_samplerate];
                 int packetlen = frameheader.packetlength;
@@ -1113,9 +1113,9 @@
                         int itemp = 0;
                         int afree = audiofree(false);
 
-                        if (lameret * 4 > afree)
+                        if (lameret * audio_bytes_per_sample > afree)
                         {
-                            lameret = afree / 4;
+                            lameret = afree / audio_bytes_per_sample;
                             cout << "Audio buffer overflow, audio data lost!\n";
                         }
 
@@ -1124,10 +1124,9 @@
                         for (itemp = 0; itemp < lameret; itemp++)
                         {
                             saudbuffer[waud / 2] = pcmlbuffer[itemp];
-                            saudbuffer[waud / 2 + 1] = pcmrbuffer[itemp];
-                           
-                            waud += 4;
-                            len += 4;
+                            if(audio_channels == 2)
+                                saudbuffer[waud / 2 + 1] = pcmrbuffer[itemp];
+                            waud += audio_bytes_per_sample;
                             if (waud >= AUDBUFSIZE)
                                 waud -= AUDBUFSIZE;
                         }
@@ -1518,8 +1517,8 @@
         /* do audio output */
 	
         /* approximate # of audio bytes for each frame. */
-        bytesperframe = 4 * (int)((1.0/video_frame_rate) *
-                                  ((double)effdsp/100.0) + 0.5);
+        bytesperframe = audio_bytes_per_sample * 
+          (int)(effdsp / 100.0 / video_frame_rate + 0.5);
 	
         // wait for the buffer to fill with enough to play
         if (bytesperframe >= audiolen(true))
Index: libs/libNuppelVideo/NuppelVideoPlayer.h
===================================================================
RCS file: /var/lib/cvs/MC/libs/libNuppelVideo/NuppelVideoPlayer.h,v
retrieving revision 1.49
diff -u -r1.49 NuppelVideoPlayer.h
--- libs/libNuppelVideo/NuppelVideoPlayer.h	20 Nov 2002 23:37:33 -0000	1.49
+++ libs/libNuppelVideo/NuppelVideoPlayer.h	24 Nov 2002 05:41:33 -0000
@@ -190,6 +190,9 @@
     unsigned char *directbuf;
     char lastct;
     int effdsp; // from the recorded stream
+    int audio_channels; // from the recorded stream
+    int audio_bits; // per channel per sample
+    int audio_bytes_per_sample;
     int audio_samplerate; // rate to tell the output device
     int filesize;
     int startpos;
Index: libs/libNuppelVideo/NuppelVideoRecorder.cpp
===================================================================
RCS file: /var/lib/cvs/MC/libs/libNuppelVideo/NuppelVideoRecorder.cpp,v
retrieving revision 1.63
diff -u -r1.63 NuppelVideoRecorder.cpp
--- libs/libNuppelVideo/NuppelVideoRecorder.cpp	20 Nov 2002 23:37:33 -0000	1.63
+++ libs/libNuppelVideo/NuppelVideoRecorder.cpp	24 Nov 2002 05:41:34 -0000
@@ -71,7 +71,10 @@
     keyframedist = KEYFRAMEDIST;
 
     audiobytes = 0;
+    audio_bits = 16;
+    audio_channels = 2;
     audio_samplerate = 44100;
+    audio_bytes_per_sample = audio_channels * audio_bits/8;
 
     picture_format = PIX_FMT_YUV420P;
 
@@ -253,15 +256,25 @@
     int videomegs;
     int audiomegs = 2;
     
+    if (AudioInit() != 0)
+    {
+        cerr << "Could not detect audio blocksize\n";
+    }
+
     if (compressaudio)
     {
         gf = lame_init();
 	lame_set_bWriteVbrTag(gf, 0);
 	lame_set_quality(gf, mp3quality);
 	lame_set_compression_ratio(gf, 11);
+        lame_set_mode(gf, audio_channels == 2 ? STEREO : MONO);
+        lame_set_num_channels(gf, audio_channels);
         lame_set_out_samplerate(gf, audio_samplerate);
         lame_set_in_samplerate(gf, audio_samplerate);
 	lame_init_params(gf);
+        if(audio_bits != 16) {
+            cerr << "lame support requires 16bit audio\n";
+        }
     }
 
     if (codec == "hardware-mjpeg")
@@ -282,11 +295,6 @@
 
     video_buffer_count = (videomegs * 1000 * 1000) / video_buffer_size;
 
-    if (AudioInit() != 0)
-    {
-        cerr << "Could not detect audio blocksize\n";
-    }
-
     if (audio_buffer_size != 0)
         audio_buffer_count = (audiomegs * 1000 * 1000) / audio_buffer_size;
     else
@@ -313,7 +321,7 @@
 int NuppelVideoRecorder::AudioInit(void)
 {
     int afmt, afd;
-    int frag, channels, rate, blocksize = 4096;
+    int frag, blocksize = 4096;
 
     if (-1 == (afd = open(audiodevice.ascii(), O_RDONLY)))
     {
@@ -334,22 +342,19 @@
         return(1);
     }
 
-    channels = 2;
-    ioctl(afd, SNDCTL_DSP_CHANNELS, &channels);
-
-    /* sample rate */
-    rate = audio_samplerate;
-    if (ioctl(afd, SNDCTL_DSP_SPEED, &rate) < 0)
-    {
-        cerr << "setting sample rate failed, exiting\n";
+    if (ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &audio_bits) < 0 ||
+        ioctl(afd, SNDCTL_DSP_CHANNELS, &audio_channels) < 0 ||
+        ioctl(afd, SNDCTL_DSP_SPEED, &audio_samplerate) < 0)
+    {
+        cerr << "recorder: " << audiodevice 
+             << ": error setting audio input device to "
+             << audio_samplerate << "kHz/" 
+             << audio_bits << "bits/"
+             << audio_channels << "channel\n";
         return 1;
     }
 
-    if (rate != audio_samplerate)
-    {
-        cerr << "setting sample rate to " << audio_samplerate << " failed\n";
-        return 1;
-    }
+    audio_bytes_per_sample = audio_channels * audio_bits/8;
 
     if (-1 == ioctl(afd, SNDCTL_DSP_GETBLKSIZE, &blocksize)) 
     {
@@ -1107,7 +1112,7 @@
     }
 
     moredata.audio_sample_rate = audio_samplerate;
-    moredata.audio_channels = 2;
+    moredata.audio_channels = audio_channels;
     moredata.audio_bits_per_sample = 16;
 
     extendeddataOffset = ringBuffer->GetFileWritePosition();
@@ -1238,7 +1243,7 @@
 {
     int afmt = 0, trigger = 0;
     int afd = 0, act = 0, lastread = 0;
-    int frag = 0, channels = 0, rate = 0, blocksize = 0;
+    int frag = 0, blocksize = 0;
     unsigned char *buffer;
     audio_buf_info ispace;
     struct timeval anow;
@@ -1265,12 +1270,20 @@
         return;
     }
 
-    channels = 2;
-    ioctl(afd, SNDCTL_DSP_CHANNELS, &channels);
+    if (ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &audio_bits) < 0 ||
+        ioctl(afd, SNDCTL_DSP_CHANNELS, &audio_channels) < 0 ||
+        ioctl(afd, SNDCTL_DSP_SPEED, &audio_samplerate) < 0)
+    {
+        cerr << "recorder: " << audiodevice 
+             << ": error setting audio input device to "
+             << audio_samplerate << "kHz/" 
+             << audio_bits << "bits/"
+             << audio_channels << "channel\n";
+        close(afd);
+        return;
+    }
 
-    /* sample rate */
-    rate = audio_samplerate;
-    ioctl(afd, SNDCTL_DSP_SPEED, &rate);
+    audio_bytes_per_sample = audio_channels * audio_bits/8;
 
     if (-1 == ioctl(afd, SNDCTL_DSP_GETBLKSIZE,  &blocksize)) 
     {
@@ -1339,8 +1352,8 @@
 	/* Back up the timecode. The more stuff is in the hw buffer,
 	   the earlier this audio was actually recorded. */
 	audiobuffer[act]->timecode -=
-	    (int) ( ( (double)ispace.fragments * (double)ispace.fragsize * 1000.0 ) /
-		    ( (double)audio_samplerate * 4.0 ) );
+	    (int)(ispace.fragments * ispace.fragsize * 1000.0 /
+                  (audio_samplerate * audio_bytes_per_sample));
 
         memcpy(audiobuffer[act]->buffer, buffer, audio_buffer_size);
 
@@ -1718,12 +1731,12 @@
                                      // wrong guess ;-)
         // need seconds instead of msec's
         //mt = (double)timecode/1000.0;
-        mt = (double)timecode;
+        mt = timecode;
         if (mt > 0.0) 
         {
             //eff = (abytes/4.0)/mt;
             //effectivedsp=(int)(100.0*eff);
-            eff = (abytes/mt)*((double)100000.0/(double)4.0);
+            eff = (abytes/mt)*(100000.0 / audio_bytes_per_sample);
             effectivedsp=(int)eff;
         }
     }
@@ -1735,10 +1748,21 @@
         int gaplesssize = 0;
         int lameret = 0;
 
-        lameret = lame_encode_buffer_interleaved(gf, (short int *)buf,
-                                                 audio_buffer_size / 4,
-                                                 (unsigned char *)mp3buf,
-                                                 mp3buf_size);
+        if(audio_channels == 2)
+        {
+            lameret = lame_encode_buffer_interleaved(gf, (short int *)buf,
+                                                     audio_buffer_size / audio_bytes_per_sample,
+                                                     (unsigned char *)mp3buf,
+                                                     mp3buf_size);
+        }
+        else
+        {
+            lameret = lame_encode_buffer(gf, (short int *)buf, (short int *)buf,
+                                         audio_buffer_size / audio_bytes_per_sample,
+                                         (unsigned char *)mp3buf,
+                                         mp3buf_size);
+        }
+
         if (lameret < 0)
         {
             cerr << "lame error, exiting\n";
Index: libs/libNuppelVideo/NuppelVideoRecorder.h
===================================================================
RCS file: /var/lib/cvs/MC/libs/libNuppelVideo/NuppelVideoRecorder.h,v
retrieving revision 1.25
diff -u -r1.25 NuppelVideoRecorder.h
--- libs/libNuppelVideo/NuppelVideoRecorder.h	18 Nov 2002 01:59:38 -0000	1.25
+++ libs/libNuppelVideo/NuppelVideoRecorder.h	24 Nov 2002 05:41:34 -0000
@@ -126,6 +126,9 @@
     int compression;
     int compressaudio;
     unsigned long long audiobytes;
+    int audio_channels; // channels to request from sounddevice
+    int audio_bits; // per channel per sample
+    int audio_bytes_per_sample;
     int audio_samplerate; // rate we request from sounddevice
     int effectivedsp; // actual measured rate