[MPlayer-users] Re: BUG - Garbled output playing realaudio

Bryan Alton balton at eircom.net
Tue Oct 4 09:01:17 CEST 2005


Neil Sleightholm wrote:

> Bryan Alton wrote:
> 
>> I have posted the patch to the developer mailing list. Solving the
>> problem with other RealAudio formats delayed this posting.
> 
> Bryan, I couldn't find the patch on the dev list. Could you post is
> here?
> 
> Neil

No problem. 

As I haven't posted before to the dev list - I think they are considering
it carefully. I thought they would be quicker.


Index: demux_real.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/demux_real.c,v
retrieving revision 1.72
diff -u -r1.72 demux_real.c
--- demux_real.c        5 Aug 2005 19:57:46 -0000       1.72
+++ demux_real.c        3 Oct 2005 06:59:31 -0000
@@ -92,6 +92,13 @@
     int a_bitrate; ///< Audio bitrate
     int v_bitrate; ///< Video bitrate
     int stream_switch; ///< Flag used to switch audio/video demuxing
+
+    /*  Variables to fix missing buffer in stream audio */
+    int live_stream;            // Flag to indicate that it is a suitable live audio only stream
+    int ms_per_packet;          // estimated millisec per packet 
+    int ms_per_block;           // estimated millisec per block which is a multiple of packets defined by stream parameters
+    int ms_per_packet_safety;  //  estimated millisec per packet with a margin 
+    char *previous_pkt,*previous_pkt2;         // Copy of previous packet
 } real_priv_t;
 
 /* originally from FFmpeg */
@@ -687,6 +694,41 @@
                priv->audio_need_keyframe = 0;
            }else 
                dp->pts = (priv->a_pts==timestamp) ? 0 : (timestamp/1000.0f);
+/*
+ *            Only use this method of packet loss detection & fix for live audio streams of cook V5 decoder - typically from BBC live streams  
+ */
+            if ( (priv->live_stream == 1) && (((sh_audio_t *)ds->sh)->format == mmioFOURCC('c','o','o','k')) ){ 
+                demux_packet_t *dp1;
+                int toggle =0;
+
+               if (((timestamp - priv->a_pts) > priv->ms_per_packet_safety) && ((timestamp - priv->a_pts) < priv->ms_per_block))
+                     mp_msg(MSGT_DEMUX,MSGL_V, "Packets lost: timestamp gap  Actual %d msec Expected %d Flags %02X\n", timestamp-priv->a_pts, priv->ms_per_packet,dp->flags);
+               if ((timestamp - priv->a_pts) < (priv->ms_per_packet-2))   // This is a diagnostic msg - allow a margin of 2 based on observations of streams to reduce "noise"
+                     mp_msg(MSGT_DEMUX,MSGL_V, "Packet timestamp gap too short  Actual %d msec Expected %d Flags %02X\n", timestamp-priv->a_pts, priv->ms_per_packet,dp->flags);
+
+/*              Detected some packets dropped by server by gap in the timestamp.  This loops fills in the missing packets with copies of previous packets 
+ *              as an empty buffer would be heard as a click. Packets are striped but also alternate - so previous packet is not the packet closest in time.
+ */
+                if ((timestamp - priv->a_pts) < priv->ms_per_block)                // Only insert buffer if it is not a whole block missing 
+                 while( ((timestamp - priv->a_pts) > priv->ms_per_packet_safety) ) {
+                   dp1 = new_demux_packet(len);
+                   if (toggle == 1) {                           // This chooses which previous packet to pick that is closest in time to the missing packet
+                     memcpy(dp1->buffer,priv->previous_pkt,len);
+                     toggle = 0;
+                   }
+                   else {                                       // When there is more than one missing packet toggle chooses which previous packet is most suitable.
+                     memcpy(dp1->buffer,priv->previous_pkt2,len);
+                     toggle = 1;
+                  }    
+                  priv->a_pts=priv->a_pts + priv->ms_per_packet;
+                  dp1->pos = demuxer->filepos;
+                  dp1->flags = 0;
+                  ds_add_packet(ds, dp1);
+                 }
+            memcpy(priv->previous_pkt2,priv->previous_pkt,len);  // Ensure that the last two good packets are kept to use to replace missing packets
+            memcpy(priv->previous_pkt,dp->buffer,len);
+             }
+
            priv->a_pts=timestamp;
            dp->pos = demuxer->filepos;
            dp->flags = (flags & 0x2) ? 0x10 : 0;
@@ -1358,6 +1400,28 @@
                            ((short*)(sh->wf+1))[4]=codecdata_length;
 //                         stream_read(demuxer->stream, ((char*)(sh->wf+1))+6, 24); // extras
                            stream_read(demuxer->stream, ((char*)(sh->wf+1))+10, codecdata_length); // extras
+/*
+ *                      Initialise variables used for packet loss detection in live audio streams using cook V5        
+ *                       Although in case "cook" Test for cook format because 'sipr' & 'atrc' fall through into cook  
+ */
+                           if ( (sh->format == MKTAG('c', 'o', 'o', 'k')) && (version == 5) && strstr(mimet,"x-pn-multirate-realaudio-live")) {
+                             priv->live_stream = 1; 
+                            priv->ms_per_packet = (long) ( (coded_frame_size*8*1000L)/(sh->wf->nAvgBytesPerSec)); // Variable name nAvgBitsPerSec would be more appropriate
+                            priv->ms_per_packet_safety = priv->ms_per_packet + (priv->ms_per_packet/5) ;          // Add 20% for the safety margin as packet timing based on AvgBitsPerSec is not accurate
+                            priv->ms_per_block = priv->ms_per_packet * sub_packet_h;
+
+                            mp_msg(MSGT_DEMUX,MSGL_V,"Live stream: Subpacksize %d sub packet h %d  Flavour %d coded frame size %d codecdatalength %d avg byte/sec %d channels %d\n",sub_packet_size,sub_packet_h,flavor,coded_frame_size,codecdata_length,  sh->wf->nAvgBytesPerSec, sh->channels);
+                            mp_msg(MSGT_DEMUX,MSGL_V,"Live stream: Expected range ms/packet %d to %d     ms per block   %d\n",priv->ms_per_packet,priv->ms_per_packet_safety, priv->ms_per_block);
+
+                            priv->previous_pkt  = malloc(coded_frame_size);
+                            priv->previous_pkt2 = malloc(coded_frame_size);
+                            if (!priv->previous_pkt || !priv->previous_pkt2){
+                              mp_msg(MSGT_DEMUX,MSGL_V,"Couldn't allocate memory to a packet buffer\n");
+                            memset(priv->previous_pkt, 0, coded_frame_size);
+                            memset(priv->previous_pkt2, 0, coded_frame_size);
+
+                             }
+                           }
                            break;
                        case MKTAG('r', 'a', 'a', 'c'):
                        case MKTAG('r', 'a', 'c', 'p'):
@@ -1742,6 +1806,10 @@
        for(i=0; i<MAX_STREAMS; i++)
            if(priv->index_table[i])
                free(priv->index_table[i]);
+        if(priv->previous_pkt)
+              free(priv->previous_pkt);
+        if(priv->previous_pkt2)
+               free(priv->previous_pkt2);
        free(priv);
     }
 




More information about the MPlayer-users mailing list