diff libmpeg2/decode.c @ 12932:d0a8810e155c

Importing libmpeg2 from mpeg2dec-0.4.0b
author henry
date Mon, 02 Aug 2004 11:26:43 +0000
parents 9af61fc7955c
children 1385ec491ffb
line wrap: on
line diff
--- a/libmpeg2/decode.c	Mon Aug 02 07:58:21 2004 +0000
+++ b/libmpeg2/decode.c	Mon Aug 02 11:26:43 2004 +0000
@@ -1,6 +1,6 @@
 /*
  * decode.c
- * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
  * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
  *
  * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
@@ -28,8 +28,8 @@
 #include <inttypes.h>
 
 #include "mpeg2.h"
+#include "attributes.h"
 #include "mpeg2_internal.h"
-#include "convert.h"
 
 static int mpeg2_accels = 0;
 
@@ -44,7 +44,6 @@
 {
     uint8_t * current;
     uint32_t shift;
-    uint8_t * chunk_ptr;
     uint8_t * limit;
     uint8_t byte;
 
@@ -53,7 +52,6 @@
 
     current = mpeg2dec->buf_start;
     shift = mpeg2dec->shift;
-    chunk_ptr = mpeg2dec->chunk_ptr;
     limit = current + bytes;
 
     do {
@@ -116,69 +114,54 @@
     mpeg2dec->buf_end = end;
 }
 
-static inline int seek_chunk (mpeg2dec_t * mpeg2dec)
+int mpeg2_getpos (mpeg2dec_t * mpeg2dec)
+{
+    return mpeg2dec->buf_end - mpeg2dec->buf_start;
+}
+
+static inline mpeg2_state_t seek_chunk (mpeg2dec_t * mpeg2dec)
 {
     int size, skipped;
 
     size = mpeg2dec->buf_end - mpeg2dec->buf_start;
     skipped = skip_chunk (mpeg2dec, size);
     if (!skipped) {
-	mpeg2dec->bytes_since_pts += size;
-	return -1;
+	mpeg2dec->bytes_since_tag += size;
+	return STATE_BUFFER;
     }
-    mpeg2dec->bytes_since_pts += skipped;
+    mpeg2dec->bytes_since_tag += skipped;
     mpeg2dec->code = mpeg2dec->buf_start[-1];
-    return 0;
+    return (mpeg2_state_t)-1;
 }
 
-int mpeg2_seek_header (mpeg2dec_t * mpeg2dec)
+mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec)
 {
     while (mpeg2dec->code != 0xb3 &&
 	   ((mpeg2dec->code != 0xb7 && mpeg2dec->code != 0xb8 &&
-	     mpeg2dec->code) || mpeg2dec->sequence.width == -1))
-	if (seek_chunk (mpeg2dec))
-	    return -1;
+	     mpeg2dec->code) || mpeg2dec->sequence.width == (unsigned)-1))
+	if (seek_chunk (mpeg2dec) == STATE_BUFFER)
+	    return STATE_BUFFER;
     mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
-    return mpeg2_parse_header (mpeg2dec);
-}
-
-int mpeg2_seek_sequence (mpeg2dec_t * mpeg2dec)
-{
-    mpeg2dec->sequence.width = -1;
-    return mpeg2_seek_header (mpeg2dec);
+    mpeg2dec->user_data_len = 0;
+    return (mpeg2dec->code ? mpeg2_parse_header (mpeg2dec) :
+	    mpeg2_header_picture_start (mpeg2dec));
 }
 
 #define RECEIVED(code,state) (((state) << 8) + (code))
 
-int mpeg2_parse (mpeg2dec_t * mpeg2dec)
+mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec)
 {
     int size_buffer, size_chunk, copied;
 
-    if(mpeg2dec->code==0xff){
-	// FIXME: we need to resync stream (esp. mpeg2dec-->code) as we
-	// left parser at 0x1FF last time at the end of prev. chunk.
-	// Why? mpeg2dec->action is set to mpeg2_header_picture_start, but
-	// it will call mpeg2_parse_header() too...
-	//
-	// following code copied from mpeg2_seek_header():
-	while (mpeg2dec->code != 0xb3 &&
-	   ((mpeg2dec->code != 0xb7 && mpeg2dec->code != 0xb8 &&
-	     mpeg2dec->code) || mpeg2dec->sequence.width == -1))
-	    if (seek_chunk (mpeg2dec))
-		return -1;
-	mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
+    if (mpeg2dec->action) {
+	mpeg2_state_t state;
+
+	state = mpeg2dec->action (mpeg2dec);
+	if ((int)state >= 0)
+	    return state;
     }
 
-    if (mpeg2dec->action) {
-	int state;
-
-	state = mpeg2dec->action (mpeg2dec);
-	if (state)
-	    return state;
-    }
-    
     while (1) {
-	//printf("code=0x%X       \n",mpeg2dec->code);
 	while ((unsigned) (mpeg2dec->code - mpeg2dec->first_decode_slice) <
 	       mpeg2dec->nb_decode_slices) {
 	    size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
@@ -187,20 +170,20 @@
 	    if (size_buffer <= size_chunk) {
 		copied = copy_chunk (mpeg2dec, size_buffer);
 		if (!copied) {
-		    mpeg2dec->bytes_since_pts += size_buffer;
+		    mpeg2dec->bytes_since_tag += size_buffer;
 		    mpeg2dec->chunk_ptr += size_buffer;
-		    return -1;
+		    return STATE_BUFFER;
 		}
 	    } else {
 		copied = copy_chunk (mpeg2dec, size_chunk);
 		if (!copied) {
 		    /* filled the chunk buffer without finding a start code */
-		    mpeg2dec->bytes_since_pts += size_chunk;
+		    mpeg2dec->bytes_since_tag += size_chunk;
 		    mpeg2dec->action = seek_chunk;
 		    return STATE_INVALID;
 		}
 	    }
-	    mpeg2dec->bytes_since_pts += copied;
+	    mpeg2dec->bytes_since_tag += copied;
 
 	    mpeg2_slice (&(mpeg2dec->decoder), mpeg2dec->code,
 			 mpeg2dec->chunk_start);
@@ -209,37 +192,29 @@
 	}
 	if ((unsigned) (mpeg2dec->code - 1) >= 0xb0 - 1)
 	    break;
-	if (seek_chunk (mpeg2dec))
-	    return -1;
-    }
-    
-    //printf("next_code=0x%X  state=%d     \n",mpeg2dec->code,mpeg2dec->state);
-    
-    if(mpeg2dec->code==0xff){
-	mpeg2dec->action = mpeg2_header_picture_start; //mpeg2_seek_header;
-	return mpeg2dec->state;
+	if (seek_chunk (mpeg2dec) == STATE_BUFFER)
+	    return STATE_BUFFER;
     }
 
-    switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) {
-    case RECEIVED (0x00, STATE_SLICE_1ST):
-    case RECEIVED (0x00, STATE_SLICE):
+    switch (mpeg2dec->code) {
+    case 0x00:
 	mpeg2dec->action = mpeg2_header_picture_start;
-	break;
-    case RECEIVED (0xb7, STATE_SLICE):
+	return mpeg2dec->state;
+    case 0xb7:
 	mpeg2dec->action = mpeg2_header_end;
 	break;
-    case RECEIVED (0xb3, STATE_SLICE):
-    case RECEIVED (0xb8, STATE_SLICE):
+    case 0xb3:
+    case 0xb8:
 	mpeg2dec->action = mpeg2_parse_header;
 	break;
     default:
-	mpeg2dec->action = mpeg2_seek_header;
+	mpeg2dec->action = seek_chunk;
 	return STATE_INVALID;
     }
-    return mpeg2dec->state;
+    return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID;
 }
 
-int mpeg2_parse_header (mpeg2dec_t * mpeg2dec)
+mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec)
 {
     static int (* process_header[]) (mpeg2dec_t * mpeg2dec) = {
 	mpeg2_header_picture, mpeg2_header_extension, mpeg2_header_user_data,
@@ -248,6 +223,7 @@
     int size_buffer, size_chunk, copied;
 
     mpeg2dec->action = mpeg2_parse_header;
+    mpeg2dec->info.user_data = NULL;	mpeg2dec->info.user_data_len = 0;
     while (1) {
 	size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
 	size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE -
@@ -255,26 +231,21 @@
 	if (size_buffer <= size_chunk) {
 	    copied = copy_chunk (mpeg2dec, size_buffer);
 	    if (!copied) {
-		mpeg2dec->bytes_since_pts += size_buffer;
+		mpeg2dec->bytes_since_tag += size_buffer;
 		mpeg2dec->chunk_ptr += size_buffer;
-		return -1;
+		return STATE_BUFFER;
 	    }
 	} else {
 	    copied = copy_chunk (mpeg2dec, size_chunk);
 	    if (!copied) {
 		/* filled the chunk buffer without finding a start code */
-		mpeg2dec->bytes_since_pts += size_chunk;
+		mpeg2dec->bytes_since_tag += size_chunk;
 		mpeg2dec->code = 0xb4;
 		mpeg2dec->action = mpeg2_seek_header;
 		return STATE_INVALID;
 	    }
 	}
-	mpeg2dec->bytes_since_pts += copied;
-
-    //printf("header_code=0x%X    state=%d   \n",mpeg2dec->code,mpeg2dec->state);
-    
-//    if(!mpeg2dec->code && mpeg2dec->state==7)
-	
+	mpeg2dec->bytes_since_tag += copied;
 
 	if (process_header[mpeg2dec->code & 0x0b] (mpeg2dec)) {
 	    mpeg2dec->code = mpeg2dec->buf_start[-1];
@@ -283,9 +254,6 @@
 	}
 
 	mpeg2dec->code = mpeg2dec->buf_start[-1];
-
-    //printf("next_header_code=0x%X    state=%d   \n",mpeg2dec->code,mpeg2dec->state);
-
 	switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) {
 
 	/* state transition after a sequence header */
@@ -297,10 +265,12 @@
 
 	/* other legal state transitions */
 	case RECEIVED (0x00, STATE_GOP):
+	    mpeg2_header_gop_finalize (mpeg2dec);
 	    mpeg2dec->action = mpeg2_header_picture_start;
 	    break;
 	case RECEIVED (0x01, STATE_PICTURE):
 	case RECEIVED (0x01, STATE_PICTURE_2ND):
+	    mpeg2_header_picture_finalize (mpeg2dec, mpeg2_accels);
 	    mpeg2dec->action = mpeg2_header_slice_start;
 	    break;
 
@@ -321,56 +291,58 @@
 	}
 
 	mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
+	mpeg2dec->user_data_len = 0;
 	return mpeg2dec->state;
     }
 }
 
-void mpeg2_convert (mpeg2dec_t * mpeg2dec,
-		    void (* convert) (int, int, uint32_t, void *,
-				      struct convert_init_s *), void * arg)
+int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg)
 {
-    convert_init_t convert_init;
-    int size;
+    mpeg2_convert_init_t convert_init;
+    int error;
 
-    convert_init.id = NULL;
-    convert (mpeg2dec->decoder.width, mpeg2dec->decoder.height,
-	     mpeg2_accels, arg, &convert_init);
-    if (convert_init.id_size) {
-	convert_init.id = mpeg2dec->convert_id =
-	    mpeg2_malloc (convert_init.id_size, ALLOC_CONVERT_ID);
-	convert (mpeg2dec->decoder.width, mpeg2dec->decoder.height,
-		 mpeg2_accels, arg, &convert_init);
+    error = convert (MPEG2_CONVERT_SET, NULL, &(mpeg2dec->sequence), 0,
+		     mpeg2_accels, arg, &convert_init);
+    if (!error) {
+	mpeg2dec->convert = convert;
+	mpeg2dec->convert_arg = arg;
+	mpeg2dec->convert_id_size = convert_init.id_size;
+	mpeg2dec->convert_stride = 0;
     }
-    mpeg2dec->convert_size[0] = size = convert_init.buf_size[0];
-    mpeg2dec->convert_size[1] = size += convert_init.buf_size[1];
-    mpeg2dec->convert_size[2] = size += convert_init.buf_size[2];
-    mpeg2dec->convert_start = convert_init.start;
-    mpeg2dec->convert_copy = convert_init.copy;
+    return error;
+}
 
-    size = mpeg2dec->decoder.width * mpeg2dec->decoder.height >> 2;
-    mpeg2dec->yuv_buf[0][0] = (uint8_t *) mpeg2_malloc (6 * size, ALLOC_YUV);
-    mpeg2dec->yuv_buf[0][1] = mpeg2dec->yuv_buf[0][0] + 4 * size;
-    mpeg2dec->yuv_buf[0][2] = mpeg2dec->yuv_buf[0][0] + 5 * size;
-    mpeg2dec->yuv_buf[1][0] = (uint8_t *) mpeg2_malloc (6 * size, ALLOC_YUV);
-    mpeg2dec->yuv_buf[1][1] = mpeg2dec->yuv_buf[1][0] + 4 * size;
-    mpeg2dec->yuv_buf[1][2] = mpeg2dec->yuv_buf[1][0] + 5 * size;
-    size = mpeg2dec->decoder.width * 8;
-    mpeg2dec->yuv_buf[2][0] = (uint8_t *) mpeg2_malloc (6 * size, ALLOC_YUV);
-    mpeg2dec->yuv_buf[2][1] = mpeg2dec->yuv_buf[2][0] + 4 * size;
-    mpeg2dec->yuv_buf[2][2] = mpeg2dec->yuv_buf[2][0] + 5 * size;
+int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride)
+{
+    if (!mpeg2dec->convert) {
+	if (stride < (int) mpeg2dec->sequence.width)
+	    stride = mpeg2dec->sequence.width;
+	mpeg2dec->decoder.stride_frame = stride;
+    } else {
+	mpeg2_convert_init_t convert_init;
+
+	stride = mpeg2dec->convert (MPEG2_CONVERT_STRIDE, NULL,
+				    &(mpeg2dec->sequence), stride,
+				    mpeg2_accels, mpeg2dec->convert_arg,
+				    &convert_init);
+	mpeg2dec->convert_id_size = convert_init.id_size;
+	mpeg2dec->convert_stride = stride;
+    }
+    return stride;
 }
 
 void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[3], void * id)
 {
-    fbuf_t * fbuf;
+    mpeg2_fbuf_t * fbuf;
 
     if (mpeg2dec->custom_fbuf) {
-	mpeg2_set_fbuf (mpeg2dec, mpeg2dec->decoder.coding_type);
-	fbuf = mpeg2dec->fbuf[0];
 	if (mpeg2dec->state == STATE_SEQUENCE) {
 	    mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1];
 	    mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0];
 	}
+	mpeg2_set_fbuf (mpeg2dec, (mpeg2dec->decoder.coding_type ==
+				   PIC_FLAG_CODING_TYPE_B));
+	fbuf = mpeg2dec->fbuf[0];
     } else {
 	fbuf = &(mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf);
 	mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index;
@@ -409,12 +381,14 @@
     mpeg2dec->nb_decode_slices = end - start;
 }
 
-void mpeg2_pts (mpeg2dec_t * mpeg2dec, uint32_t pts)
+void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2)
 {
-    mpeg2dec->pts_previous = mpeg2dec->pts_current;
-    mpeg2dec->pts_current = pts;
-    mpeg2dec->num_pts++;
-    mpeg2dec->bytes_since_pts = 0;
+    mpeg2dec->tag_previous = mpeg2dec->tag_current;
+    mpeg2dec->tag2_previous = mpeg2dec->tag2_current;
+    mpeg2dec->tag_current = tag;
+    mpeg2dec->tag2_current = tag2;
+    mpeg2dec->num_tags++;
+    mpeg2dec->bytes_since_tag = 0;
 }
 
 uint32_t mpeg2_accel (uint32_t accel)
@@ -430,6 +404,27 @@
     return mpeg2_accels & ~MPEG2_ACCEL_DETECT;
 }
 
+void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset)
+{
+    mpeg2dec->buf_start = mpeg2dec->buf_end = NULL;
+    mpeg2dec->num_tags = 0;
+    mpeg2dec->shift = 0xffffff00;
+    mpeg2dec->code = 0xb4;
+    mpeg2dec->action = mpeg2_seek_header;
+    mpeg2dec->state = STATE_INVALID;
+    mpeg2dec->first = 1;
+
+    mpeg2_reset_info(&(mpeg2dec->info));
+    mpeg2dec->info.gop = NULL;
+    mpeg2dec->info.user_data = NULL;
+    mpeg2dec->info.user_data_len = 0;
+    if (full_reset) {
+	mpeg2dec->info.sequence = NULL;
+	mpeg2_header_state_init (mpeg2dec);
+    }
+
+}
+
 mpeg2dec_t * mpeg2_init (void)
 {
     mpeg2dec_t * mpeg2dec;
@@ -437,43 +432,25 @@
     mpeg2_accel (MPEG2_ACCEL_DETECT);
 
     mpeg2dec = (mpeg2dec_t *) mpeg2_malloc (sizeof (mpeg2dec_t),
-					    ALLOC_MPEG2DEC);
+					    MPEG2_ALLOC_MPEG2DEC);
     if (mpeg2dec == NULL)
 	return NULL;
 
-    memset (mpeg2dec, 0, sizeof (mpeg2dec_t));
+    memset (mpeg2dec->decoder.DCTblock, 0, 64 * sizeof (int16_t));
+    memset (mpeg2dec->quantizer_matrix, 0, 4 * 64 * sizeof (uint8_t));
 
     mpeg2dec->chunk_buffer = (uint8_t *) mpeg2_malloc (BUFFER_SIZE + 4,
-						       ALLOC_CHUNK);
+						       MPEG2_ALLOC_CHUNK);
 
-    mpeg2dec->shift = 0xffffff00;
-    mpeg2dec->action = mpeg2_seek_sequence;
-    mpeg2dec->code = 0xb4;
-    mpeg2dec->first_decode_slice = 1;
-    mpeg2dec->nb_decode_slices = 0xb0 - 1;
-    mpeg2dec->convert_id = NULL;
-
-    /* initialize substructures */
-    mpeg2_header_state_init (mpeg2dec);
+    mpeg2dec->sequence.width = (unsigned)-1;
+    mpeg2_reset (mpeg2dec, 1);
 
     return mpeg2dec;
 }
 
 void mpeg2_close (mpeg2dec_t * mpeg2dec)
 {
-    int i;
-
-    /* static uint8_t finalizer[] = {0,0,1,0xb4}; */
-    /* mpeg2_decode_data (mpeg2dec, finalizer, finalizer+4); */
-
+    mpeg2_header_state_init (mpeg2dec);
     mpeg2_free (mpeg2dec->chunk_buffer);
-    if (!mpeg2dec->custom_fbuf)
-	for (i = mpeg2dec->alloc_index_user; i < mpeg2dec->alloc_index; i++)
-	    mpeg2_free (mpeg2dec->fbuf_alloc[i].fbuf.buf[0]);
-    if (mpeg2dec->convert_start)
-	for (i = 0; i < 3; i++)
-	    mpeg2_free (mpeg2dec->yuv_buf[i][0]);
-    if (mpeg2dec->convert_id)
-	mpeg2_free (mpeg2dec->convert_id);
     mpeg2_free (mpeg2dec);
 }