summaryrefslogtreecommitdiffstats
path: root/libmpeg2/decode.c
diff options
context:
space:
mode:
authorhenry <henry@b3059339-0415-0410-9bf9-f77b7e298cf2>2004-08-02 11:26:43 +0000
committerhenry <henry@b3059339-0415-0410-9bf9-f77b7e298cf2>2004-08-02 11:26:43 +0000
commit943139cc78038c3aea0837229298cb2c08e3f8a2 (patch)
tree56b2a2dac2c09fe1016e3e146ec19cb2aae0777a /libmpeg2/decode.c
parent4779094c4be9af5ec0c5145d8a460b75e4a510c8 (diff)
downloadmpv-943139cc78038c3aea0837229298cb2c08e3f8a2.tar.bz2
mpv-943139cc78038c3aea0837229298cb2c08e3f8a2.tar.xz
Importing libmpeg2 from mpeg2dec-0.4.0b
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@12933 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpeg2/decode.c')
-rw-r--r--libmpeg2/decode.c255
1 files changed, 116 insertions, 139 deletions
diff --git a/libmpeg2/decode.c b/libmpeg2/decode.c
index fa87a824c1..bba2af4954 100644
--- a/libmpeg2/decode.c
+++ b/libmpeg2/decode.c
@@ -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 @@ static inline int skip_chunk (mpeg2dec_t * mpeg2dec, int bytes)
{
uint8_t * current;
uint32_t shift;
- uint8_t * chunk_ptr;
uint8_t * limit;
uint8_t byte;
@@ -53,7 +52,6 @@ static inline int skip_chunk (mpeg2dec_t * mpeg2dec, int bytes)
current = mpeg2dec->buf_start;
shift = mpeg2dec->shift;
- chunk_ptr = mpeg2dec->chunk_ptr;
limit = current + bytes;
do {
@@ -116,69 +114,54 @@ void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end)
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) {
- int state;
+ mpeg2_state_t state;
state = mpeg2dec->action (mpeg2dec);
- if (state)
+ if ((int)state >= 0)
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 @@ int mpeg2_parse (mpeg2dec_t * mpeg2dec)
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 @@ int mpeg2_parse (mpeg2dec_t * mpeg2dec)
}
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 mpeg2_parse_header (mpeg2dec_t * mpeg2dec)
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 @@ int mpeg2_parse_header (mpeg2dec_t * mpeg2dec)
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 @@ int mpeg2_parse_header (mpeg2dec_t * mpeg2dec)
}
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 @@ int mpeg2_parse_header (mpeg2dec_t * mpeg2dec)
/* 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 @@ int mpeg2_parse_header (mpeg2dec_t * mpeg2dec)
}
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;
-
- 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);
+ mpeg2_convert_init_t convert_init;
+ int error;
+
+ 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;
-
- 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;
+ return error;
+}
+
+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 @@ void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end)
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 @@ uint32_t mpeg2_accel (uint32_t accel)
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 @@ mpeg2dec_t * mpeg2_init (void)
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);
-
- 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;
+ MPEG2_ALLOC_CHUNK);
- /* 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);
}