--- xine-cvs/xine-lib/src/libmpeg2/decode.c	2006-12-09 22:04:30.000000000 +0100
+++ xine-lib/src/libmpeg2/decode.c	2006-12-15 23:24:46.000000000 +0100
@@ -87,6 +87,13 @@ void mpeg2_init (mpeg2dec_t * mpeg2dec, 
     mpeg2dec->code = 0xb4;
     mpeg2dec->seek_mode = 0;
 
+    /* initialize AFD storage */
+    mpeg2dec->afd_stack[0] = -1;
+    mpeg2dec->afd_stack[1] = -1;
+    mpeg2dec->afd_stack[2] = -1;
+    mpeg2dec->afd_index = -1;
+    mpeg2dec->afd_value = -2;
+
     memset (mpeg2dec->picture, 0, sizeof (picture_t));
 
     /* initialize substructures */
@@ -236,7 +243,7 @@ static void remember_metainfo (mpeg2dec_
 }
 
 static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
-			       uint8_t * buffer)
+			       uint8_t * buffer, int next_code)
 {
     picture_t * picture;
     int is_frame_done;
@@ -303,6 +310,10 @@ static inline int parse_chunk (mpeg2dec_
 	    abort();
 	}
 
+        /* reset picture AFD data and set index to picture */
+        mpeg2dec->afd_stack[2] = -1;
+        mpeg2dec->afd_index = 2;
+
 	mpeg2dec->is_frame_needed=0;
 
 	if (!picture->second_field) {
@@ -393,6 +404,17 @@ static inline int parse_chunk (mpeg2dec_
 	    /* abort(); */
 	    break;
 	}
+
+        /* reset squence, group and picture AFD data and set index to sequence */
+        mpeg2dec->afd_stack[0] = -1;
+        mpeg2dec->afd_stack[1] = -1;
+        mpeg2dec->afd_stack[2] = -1;
+        mpeg2dec->afd_index = 0;
+
+        /* according to ISO/IEC 13818-2, an extension start code will follow.
+         * Otherwise the stream follows ISO/IEC 11172-2 which means MPEG1 */ 
+        picture->mpeg1 = (next_code != 0xb5);
+
 	if (mpeg2dec->force_aspect) picture->aspect_ratio_information = mpeg2dec->force_aspect;
 
 	if (mpeg2dec->is_sequence_needed ) {
@@ -457,6 +479,12 @@ static inline int parse_chunk (mpeg2dec_
 	  printf ("libmpeg2: bad group of pictures\n");
 	  abort();
 	}
+
+        /* reset group and picture AFD data and set index to group */
+        mpeg2dec->afd_stack[1] = -1;
+        mpeg2dec->afd_stack[2] = -1;
+        mpeg2dec->afd_index = 1;
+
     default:
         if ((code >= 0xb9) && (code != 0xe4)) {
 	  printf("Not multiplexed? 0x%x\n",code);
@@ -464,6 +492,22 @@ static inline int parse_chunk (mpeg2dec_
 	if (code >= 0xb0)
 	    break;
 
+        /* check for AFD change once per picture */
+        if (0 <= mpeg2dec->afd_index && mpeg2dec->afd_index <= 2) {
+            int afd = (mpeg2dec->afd_stack[2] == -1) ? (mpeg2dec->afd_stack[1] == -1) ? mpeg2dec->afd_stack[0] : mpeg2dec->afd_stack[1] : mpeg2dec->afd_stack[2];
+            mpeg2dec->afd_index = -1;
+            /* AFD data should better be stored in current_frame to have it */
+            /* ready and synchronous with other data like width or height. */
+            /* An AFD change should then be detected when a new frame is emitted */
+            /* from the decoder to report the AFD change in display order and not */
+            /* in decoding order like it happens below for now. */
+            if (mpeg2dec->afd_value != afd) {
+                mpeg2dec->afd_value = afd;
+                _x_stream_info_set(mpeg2dec->stream, XINE_STREAM_INFO_VIDEO_AFD, mpeg2dec->afd_value);
+fprintf(stderr, "AFD changed to: %d\n", afd);
+            }
+        }
+
 	if (!(mpeg2dec->in_slice)) {
 	    mpeg2dec->in_slice = 1;
 
@@ -574,45 +618,135 @@ static inline int parse_chunk (mpeg2dec_
     return is_frame_done;
 }
 
+static inline int find_start_code (mpeg2dec_t * mpeg2dec,
+                                   uint8_t ** current, uint8_t * limit)
+{
+    uint8_t * p;
+
+    if (*current >= limit)
+	return 0;
+    if (mpeg2dec->shift == 0x00000100)
+	return 1;
+
+    mpeg2dec->shift = (mpeg2dec->shift | *(*current)++) << 8;
+
+    if (*current >= limit)
+	return 0;
+    if (mpeg2dec->shift == 0x00000100)
+	return 1;
+
+    mpeg2dec->shift = (mpeg2dec->shift | *(*current)++) << 8;
+
+    if (*current >= limit)
+	return 0;
+    if (mpeg2dec->shift == 0x00000100)
+	return 1;
+
+    limit--;
+
+    if (*current >= limit) {
+	mpeg2dec->shift = (mpeg2dec->shift | *(*current)++) << 8;
+	return 0;
+    }
+
+    p = *current;
+
+    while (p < limit && (p = (uint8_t *)memchr(p, 0x01, limit - p))) {
+	if (p[-2] || p[-1])
+	    p += 3;
+	else {
+	    *current = ++p;
+	    return 1;
+	}
+    }
+
+    *current = ++limit;
+    p = limit - 3;
+    mpeg2dec->shift = (mpeg2dec->shift | *p++) << 8;
+    mpeg2dec->shift = (mpeg2dec->shift | *p++) << 8;
+    mpeg2dec->shift = (mpeg2dec->shift | *p++) << 8;
+
+    return 0;
+}
+
 static inline uint8_t * copy_chunk (mpeg2dec_t * mpeg2dec,
 				    uint8_t * current, uint8_t * end)
 {
-    uint32_t shift;
-    uint8_t * chunk_ptr;
     uint8_t * limit;
-    uint8_t byte;
 
-    shift = mpeg2dec->shift;
-    chunk_ptr = mpeg2dec->chunk_ptr;
-    limit = current + (mpeg2dec->chunk_buffer + BUFFER_SIZE - chunk_ptr);
+    /* sequence end code 0xb7 doesn't have any data and there might be the case
+     * that no start code will follow this code for quite some time (e. g. in case
+     * of a still image.
+     * Therefore, return immediately with a chunk_size of 0. Setting code to 0xb4
+     * will eat up any trailing garbage next time.
+     */
+    if (mpeg2dec->code == 0xb7) {
+       mpeg2dec->code = 0xb4;
+       mpeg2dec->chunk_size = 0;
+       return current;
+    }
+
+    limit = current + (mpeg2dec->chunk_buffer + BUFFER_SIZE - mpeg2dec->chunk_ptr);
     if (limit > end)
 	limit = end;
+#if 0
+    {
+	uint32_t shift = mpeg2dec->shift;
+	uint8_t * chunk_ptr = mpeg2dec->chunk_ptr;
 
-    while (1) {
+	while (1) {
 
-	byte = *current++;
-	if (shift != 0x00000100) {
-	    shift = (shift | byte) << 8;
-	    *chunk_ptr++ = byte;
-	    if (current < limit)
-		continue;
-	    if (current == end) {
-		mpeg2dec->chunk_ptr = chunk_ptr;
-		mpeg2dec->shift = shift;
-		return NULL;
-	    } else {
-		/* we filled the chunk buffer without finding a start code */
-		mpeg2dec->code = 0xb4;	/* sequence_error_code */
-		mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
-		return current;
+	    uint8_t byte = *current++;
+	    if (shift != 0x00000100) {
+		shift = (shift | byte) << 8;
+		*chunk_ptr++ = byte;
+		if (current < limit)
+		    continue;
+		if (current == end) {
+		    mpeg2dec->chunk_ptr = chunk_ptr;
+		    mpeg2dec->shift = shift;
+		    return NULL;
+		} else {
+		    /* we filled the chunk buffer without finding a start code */
+		    mpeg2dec->code = 0xb4;	/* sequence_error_code */
+		    mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
+		    return current;
+		}
 	    }
+	    mpeg2dec->code = byte;
+	    mpeg2dec->chunk_size = chunk_ptr - mpeg2dec->chunk_buffer - 3;
+	    mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
+	    mpeg2dec->shift = 0xffffff00;
+	    return current;
 	}
-	mpeg2dec->code = byte;
-	mpeg2dec->chunk_size = chunk_ptr - mpeg2dec->chunk_buffer - 3;
+    }
+#else
+    {
+	uint8_t * data = current;
+	int found = find_start_code(mpeg2dec, &current, limit);
+	int bite = current - data;
+        if (bite) {
+	    xine_fast_memcpy(mpeg2dec->chunk_ptr, data, bite);
+	    mpeg2dec->chunk_ptr += bite;
+	}
+
+	if (found) {
+	    mpeg2dec->code = *current++;
+	    mpeg2dec->chunk_size = mpeg2dec->chunk_ptr - mpeg2dec->chunk_buffer - 3;
+	    mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
+	    mpeg2dec->shift = 0xffffff00;
+	    return current;
+	}
+    
+	if (current == end)
+	    return NULL;
+
+	/* we filled the chunk buffer without finding a start code */
+	mpeg2dec->code = 0xb4;	/* sequence_error_code */
 	mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
-	mpeg2dec->shift = 0xffffff00;
 	return current;
     }
+#endif
 }
 
 int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, uint8_t * current, uint8_t * end,
@@ -633,12 +767,12 @@ int mpeg2_decode_data (mpeg2dec_t * mpeg
     if (pts)
       mpeg2dec->pts = pts;
 
-    while (current != end) {
+    while (current != end || mpeg2dec->code == 0xb7) {
 	code = mpeg2dec->code;
 	current = copy_chunk (mpeg2dec, current, end);
 	if (current == NULL) 
 	    break;
-	ret += parse_chunk (mpeg2dec, code, mpeg2dec->chunk_buffer);
+	ret += parse_chunk (mpeg2dec, code, mpeg2dec->chunk_buffer, mpeg2dec->code);
     }
 
     libmpeg2_accel_frame_completion(&mpeg2dec->accel, mpeg2dec->frame_format, 
@@ -805,7 +939,7 @@ void mpeg2_close (mpeg2dec_t * mpeg2dec)
 void mpeg2_find_sequence_header (mpeg2dec_t * mpeg2dec,
 				 uint8_t * current, uint8_t * end){
 
-  uint8_t code;
+  uint8_t code, next_code;
   picture_t *picture = mpeg2dec->picture;
 
   mpeg2dec->seek_mode = 1;
@@ -815,6 +949,7 @@ void mpeg2_find_sequence_header (mpeg2de
     current = copy_chunk (mpeg2dec, current, end);
     if (current == NULL)
       return ;
+    next_code = mpeg2dec->code;
 
     /* printf ("looking for sequence header... %02x\n", code);  */
 
@@ -825,6 +960,11 @@ void mpeg2_find_sequence_header (mpeg2de
 	printf ("libmpeg2: bad sequence header\n");
 	continue;
       }
+
+      /* according to ISO/IEC 13818-2, an extension start code will follow.
+       * Otherwise the stream follows ISO/IEC 11172-2 which means MPEG1 */ 
+      picture->mpeg1 = (next_code != 0xb5);
+
       if (mpeg2dec->force_aspect) picture->aspect_ratio_information = mpeg2dec->force_aspect;
 	  
       if (mpeg2dec->is_sequence_needed) {
@@ -919,8 +1059,10 @@ static void process_userdata(mpeg2dec_t 
   /* check Active Format Description ETSI TS 101 154 V1.5.1 */
   else if (buffer[0] == 0x44 && buffer[1] == 0x54 && buffer[2] == 0x47 && buffer[3] == 0x31)
   {
-    int afd = (buffer[4] & 0x40) ? (buffer[5] & 0x0f) : -1;
-    _x_stream_info_set(mpeg2dec->stream, XINE_STREAM_INFO_VIDEO_AFD, afd);
-    
+    if (0 <= mpeg2dec->afd_index && mpeg2dec->afd_index <= 2)
+    {
+      mpeg2dec->afd_stack[mpeg2dec->afd_index] = (buffer[4] & 0x40) ? (buffer[5] & 0x0f) : -1;
+fprintf(stderr, "AFD detected at %c %d\n", "SGP"[mpeg2dec->afd_index], mpeg2dec->afd_stack[mpeg2dec->afd_index]);
+    }
   }
 }
--- xine-cvs/xine-lib/src/libmpeg2/mpeg2.h	2005-04-11 20:29:46.000000000 +0200
+++ xine-lib/src/libmpeg2/mpeg2.h	2006-12-15 22:37:06.000000000 +0100
@@ -57,6 +57,14 @@ typedef struct mpeg2dec_s {
     int force_aspect;
     int force_pan_scan;
 
+    /* AFD data can be found after a sequence, group or picture start code */
+    /* afd_stack[] stores the AFD value and afd_index specifies at which */
+    /* array element the data has to be written to: 0, 1, or 2 */
+    int afd_stack[3];
+    int afd_index;
+    /* afd_value stores the last determined AFD data for change detection */
+    int afd_value;
+
     xine_stream_t *stream;
     
     /* a spu decoder for possible closed captions */
