changeset 18248:595d94213ad0

when muxing mpeg audio streams analyze the first 32 KB of data to obtain the most likely correct layer, otherwise every misdetection during parse_audio() will lead to wrong timestamps and loss of synchrony
author nicodvb
date Mon, 24 Apr 2006 14:04:10 +0000
parents 3c1418657a36
children 00864f9fb5c0
files libmpdemux/muxer_mpeg.c
diffstat 1 files changed, 51 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/libmpdemux/muxer_mpeg.c	Mon Apr 24 14:03:58 2006 +0000
+++ b/libmpdemux/muxer_mpeg.c	Mon Apr 24 14:04:10 2006 +0000
@@ -169,6 +169,7 @@
 	int frames;
 	int last_frame_rest; 	//the rest of the previous frame
 	int is_ready;
+	int mpa_layer;
 } muxer_headers_t;
 
 #define PULLDOWN32 1
@@ -2040,6 +2041,38 @@
 	return idx;
 }
 
+static int analyze_mpa(muxer_stream_t *s)
+{
+	int i = 0, len, max, chans, srate, spf, layer;
+	int score[4] = {0, 0, 0, 0};
+	
+	while(i < s->b_buffer_len + 3)
+	{
+		if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xE0) == 0xE0))
+		{
+			len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL);
+			if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))
+			{
+				score[layer]++;
+				i += len;
+			}
+		}
+		i++;
+	}
+
+	max = 0;
+	layer = 2;
+	for(i = 1; i <= 3; i++)
+	{
+		if(score[i] >= max)
+		{
+			max = score[i];
+			layer = i;
+		}
+	}
+
+	return layer;	//actual layer with the highest score
+}
 
 extern int aac_parse_frame(uint8_t *buf, int *srate, int *num);
 
@@ -2071,7 +2104,8 @@
 				if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xE0) == 0xE0))
 				{
 					len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL);
-					if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))
+					if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len) 
+						&& layer == spriv->mpa_layer)
 					{
 						dur = (double) spf / (double) srate;
 						idur = (27000000ULL * spf) / srate;
@@ -2200,6 +2234,7 @@
 
 	if(stream->type == MUXER_TYPE_AUDIO)
 	{
+		spriv->is_ready = 1;
 		spriv->max_buffer_size = 4*1024;
 		if(stream->wf->wFormatTag == AUDIO_A52)
 		{
@@ -2213,6 +2248,8 @@
 		{
 			priv->use_psm = 1;
 		}
+		else if(stream->wf->wFormatTag == AUDIO_MP2 || stream->wf->wFormatTag == AUDIO_MP3)
+			spriv->is_ready = 0;
 	}
 	else	//video
 	{
@@ -2294,8 +2331,6 @@
   	spriv->type = 0;
 	stream_format = s->wf->wFormatTag;
 
-	if(! spriv->vframes)
-		mp_msg(MSGT_MUXER, MSGL_INFO, "AINIT: %.3lf\r\n", (double) spriv->last_pts/27000000.0f);	
 	if(s->b_buffer_size - s->b_buffer_len < len)
 	{
 		s->b_buffer = realloc(s->b_buffer, len  + s->b_buffer_len);
@@ -2311,9 +2346,22 @@
 	memcpy(&(s->b_buffer[s->b_buffer_ptr + s->b_buffer_len]), s->buffer, len);
 	s->b_buffer_len += len;
 	
+	if(!spriv->is_ready)
+	{
+		if(s->b_buffer_len >= 32*1024)
+		{
+			spriv->mpa_layer = analyze_mpa(s);
+			spriv->is_ready = 1;
+		}
+	}
+	else
+	{
 	parse_audio(s, 0, &nf, &fake_timer, priv->init_adelay, priv->drop);
 	spriv->vframes += nf;
 	sz = max(len, 2 * priv->packet_size);
+	if(! spriv->vframes)
+		mp_msg(MSGT_MUXER, MSGL_INFO, "AINIT: %.3lf\r\n", (double) spriv->last_pts/27000000.0f);	
+	}
   }