[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