chiark / gitweb /
drop 0s at end of rtp packets
[disorder] / clients / playrtp.c
index 68926e6d84e6b8b4a4d77c2e7b4156c421269f62..fe9d1e287fa330bcb5ad94dcbeb432e66bac6678 100644 (file)
@@ -51,6 +51,9 @@
 /** @brief RTP socket */
 static int rtpfd;
 
+/** @brief Log output */
+static FILE *logfp;
+
 /** @brief Output device */
 static const char *device;
 
@@ -200,8 +203,10 @@ static void *listen_thread(void attribute((unused)) *arg) {
       }
     }
     /* Ignore too-short packets */
-    if((size_t)n <= sizeof (struct rtp_header))
+    if((size_t)n <= sizeof (struct rtp_header)) {
+      info("ignored a short packet");
       continue;
+    }
     p->timestamp = ntohl(packet.header.timestamp);
     /* Ignore packets in the past */
     if(active && lt(p->timestamp, next_timestamp)) {
@@ -218,7 +223,7 @@ static void *listen_thread(void attribute((unused)) *arg) {
       {
         size_t i;
 
-        for(i = 0; i < p->nsamples; ++n)
+        for(i = 0; i < p->nsamples; ++i)
           p->samples_float[i] = (int16_t)ntohs(samples[i]) * (0.5f / 32767);
       }
 #else
@@ -232,13 +237,20 @@ static void *listen_thread(void attribute((unused)) *arg) {
       fatal(0, "unsupported RTP payload type %d",
             packet.header.mpt & 0x7F);
     }
+    if(logfp)
+      fprintf(logfp, "sequence %u timestamp %"PRIx32" length %"PRIx32" end %"PRIx32"\n",
+              ntohs(packet.header.seq), 
+              p->timestamp, p->nsamples, p->timestamp + p->nsamples);
     pthread_mutex_lock(&lock);
     /* Stop reading if we've reached the maximum.
      *
      * This is rather unsatisfactory: it means that if packets get heavily
      * out of order then we guarantee dropouts.  But for now... */
-    while(nsamples >= maxbuffer)
-      pthread_cond_wait(&cond, &lock);
+    if(nsamples >= maxbuffer) {
+      info("buffer full");
+      while(nsamples >= maxbuffer)
+        pthread_cond_wait(&cond, &lock);
+    }
     for(pp = &packets;
         *pp && lt((*pp)->timestamp, p->timestamp);
         pp = &(*pp)->next)
@@ -288,13 +300,14 @@ static OSStatus adioproc
         if(le(packet_end, next_timestamp)) {
           /* This packet is in the past */
           info("dropping buffered past packet %"PRIx32" < %"PRIx32,
-               packets->timestamp, next_timestamp);
+               packet_start, next_timestamp);
+          drop_first_packet();
           continue;
         }
         if(ge(next_timestamp, packet_start)
            && lt(next_timestamp, packet_end)) {
           /* This packet is suitable */
-          const uint32_t offset = next_timestamp - packets->timestamp;
+          const uint32_t offset = next_timestamp - packet_start;
           uint32_t samples_available = packet_end - next_timestamp;
           if(samples_available > samplesOutLeft)
             samples_available = samplesOutLeft;
@@ -303,6 +316,7 @@ static OSStatus adioproc
                  samples_available * sizeof(float));
           samplesOut += samples_available;
           next_timestamp += samples_available;
+          samplesOutLeft -= samples_available;
           if(ge(next_timestamp, packet_end))
             drop_first_packet();
           continue;
@@ -316,17 +330,17 @@ static OSStatus adioproc
         
         if(samples_available > samplesOutLeft)
           samples_available = samplesOutLeft;
+        info("infill by %"PRIu32, samples_available);
         /* Convniently the buffer is 0 to start with */
         next_timestamp += samples_available;
         samplesOut += samples_available;
         samplesOutLeft -= samples_available;
-        /* TODO log infill */
       } else {
         /* There's no next packet at all */
+        info("infilled by %zu", samplesOutLeft);
         next_timestamp += samplesOutLeft;
         samplesOut += samplesOutLeft;
         samplesOutLeft = 0;
-        /* TODO log infill */
       }
     }
     ++ab;
@@ -605,9 +619,13 @@ static void play_rtp(void) {
     pthread_mutex_lock(&lock);
     for(;;) {
       /* Wait for the buffer to fill up a bit */
+      info("Buffering...");
       while(nsamples < readahead)
         pthread_cond_wait(&cond, &lock);
       /* Start playing now */
+      info("Playing...");
+      next_timestamp = packets->timestamp;
+      active = 1;
       status = AudioDeviceStart(adid, adioproc);
       if(status)
         fatal(0, "AudioDeviceStart: %d", (int)status);
@@ -618,6 +636,7 @@ static void play_rtp(void) {
       status = AudioDeviceStop(adid, adioproc);
       if(status)
         fatal(0, "AudioDeviceStop: %d", (int)status);
+      active = 0;
       /* Go back round */
     }
   }
@@ -668,7 +687,7 @@ int main(int argc, char **argv) {
 
   mem_init();
   if(!setlocale(LC_CTYPE, "")) fatal(errno, "error calling setlocale");
-  while((n = getopt_long(argc, argv, "hVdD:m:b:x:", options, 0)) >= 0) {
+  while((n = getopt_long(argc, argv, "hVdD:m:b:x:L:", options, 0)) >= 0) {
     switch(n) {
     case 'h': help();
     case 'V': version();
@@ -677,6 +696,7 @@ int main(int argc, char **argv) {
     case 'm': minbuffer = 2 * atol(optarg); break;
     case 'b': readahead = 2 * atol(optarg); break;
     case 'x': maxbuffer = 2 * atol(optarg); break;
+    case 'L': logfp = fopen(optarg, "w"); break;
     default: fatal(0, "invalid option");
     }
   }