summaryrefslogtreecommitdiff
path: root/src/libmpeg2/decode.c
diff options
context:
space:
mode:
authorGuenter Bartsch <guenter@users.sourceforge.net>2001-04-23 00:34:59 +0000
committerGuenter Bartsch <guenter@users.sourceforge.net>2001-04-23 00:34:59 +0000
commit2d61e7f5cd4f5add1aaab63fe54a17a416fe275a (patch)
treeb3348bc8a5d92ef84e4433bad8d897716c0c31d9 /src/libmpeg2/decode.c
parent6f114fb0e414ba8fab9627558d7b299436fece19 (diff)
downloadxine-lib-2d61e7f5cd4f5add1aaab63fe54a17a416fe275a.tar.gz
xine-lib-2d61e7f5cd4f5add1aaab63fe54a17a416fe275a.tar.bz2
further decoder plugin fixes (mpeg2)
CVS patchset: 16 CVS date: 2001/04/23 00:34:59
Diffstat (limited to 'src/libmpeg2/decode.c')
-rw-r--r--src/libmpeg2/decode.c357
1 files changed, 198 insertions, 159 deletions
diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c
index 010eed0f5..c4d456fa1 100644
--- a/src/libmpeg2/decode.c
+++ b/src/libmpeg2/decode.c
@@ -26,51 +26,37 @@
#include <stdlib.h>
#include <inttypes.h>
-/* Xine specific */
-#include "buffer.h"
-#include "xine_internal.h"
-
#include "video_out.h"
#include "mpeg2.h"
#include "mpeg2_internal.h"
#include "cpu_accel.h"
-#include "attributes.h"
-
-#ifdef HAVE_MEMALIGN
-/* some systems have memalign() but no declaration for it */
-void * memalign (size_t align, size_t size);
-#else
-/* assume malloc alignment is sufficient */
-#define memalign(align,size) malloc (size)
-#endif
-
-#define BUFFER_SIZE (224 * 1024)
+#include "utils.h"
mpeg2_config_t config;
-void mpeg2_init (mpeg2dec_t * mpeg2dec, uint32_t mm_accel,
- vo_instance_t * output)
+void mpeg2_init (mpeg2dec_t * mpeg2dec,
+ vo_instance_t * output)
{
static int do_init = 1;
if (do_init) {
do_init = 0;
- config.flags = mm_accel;
+ config.flags = mm_accel();
idct_init ();
motion_comp_init ();
}
- mpeg2dec->chunk_buffer = memalign (16, BUFFER_SIZE + 4);
- mpeg2dec->picture = memalign (16, sizeof (picture_t));
+ mpeg2dec->chunk_buffer = xmalloc_aligned (16, 224 * 1024 + 4);
+ mpeg2dec->picture = xmalloc_aligned (16, sizeof (picture_t));
- mpeg2dec->shift = 0xffffff00;
+ mpeg2dec->shift = 0;
mpeg2dec->is_sequence_needed = 1;
- mpeg2dec->drop_flag = 0;
- mpeg2dec->drop_frame = 0;
+ mpeg2dec->frames_to_drop = 0;
+ mpeg2dec->skip_slices = 0;
mpeg2dec->in_slice = 0;
- mpeg2dec->output = output;
mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
- mpeg2dec->code = 0xb4;
+ mpeg2dec->code = 0xff;
+ mpeg2dec->output = output;
memset (mpeg2dec->picture, 0, sizeof (picture_t));
@@ -78,11 +64,91 @@ void mpeg2_init (mpeg2dec_t * mpeg2dec, uint32_t mm_accel,
header_state_init (mpeg2dec->picture);
}
-static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
- uint8_t * buffer, uint32_t pts)
+void decode_free_image_buffers (mpeg2dec_t * mpeg2dec) {
+
+ picture_t *picture = mpeg2dec->picture;
+
+ if (picture->forward_reference_frame) {
+ picture->forward_reference_frame->free (picture->forward_reference_frame);
+ picture->forward_reference_frame = NULL;
+ }
+
+ if (picture->backward_reference_frame) {
+ picture->backward_reference_frame->free (picture->backward_reference_frame);
+ picture->backward_reference_frame = NULL;
+ }
+
+ if (picture->throwaway_frame) {
+ picture->throwaway_frame->free (picture->throwaway_frame);
+ picture->throwaway_frame = NULL;
+ }
+}
+
+static void decode_reorder_frames (mpeg2dec_t * mpeg2dec)
+{
+ picture_t *picture = mpeg2dec->picture;
+
+ if (picture->picture_coding_type != B_TYPE) {
+
+ if (picture->forward_reference_frame)
+ picture->forward_reference_frame->free (picture->forward_reference_frame);
+
+ /*
+ * make the backward reference frame the new forward reference frame
+ */
+
+ picture->forward_reference_frame = picture->backward_reference_frame;
+
+ /*
+ * allocate new backward reference frame
+ */
+
+
+ picture->backward_reference_frame = mpeg2dec->output->get_frame (mpeg2dec->output,
+ picture->coded_picture_width,
+ picture->coded_picture_height,
+ picture->aspect_ratio_information,
+ IMGFMT_YV12,
+ picture->frame_duration);;
+ picture->backward_reference_frame->PTS = 0;
+ picture->backward_reference_frame->bFrameBad = 1;
+
+ /*
+ * make it the current frame
+ */
+
+ picture->current_frame = picture->backward_reference_frame;
+
+ } else {
+
+ /*
+ * allocate new throwaway frame
+ */
+
+ picture->throwaway_frame = mpeg2dec->output->get_frame (mpeg2dec->output,
+ picture->coded_picture_width,
+ picture->coded_picture_height,
+ picture->aspect_ratio_information,
+ IMGFMT_YV12,
+ picture->frame_duration);;
+ picture->throwaway_frame->PTS = 0;
+ picture->throwaway_frame->bFrameBad = 1;
+
+ /*
+ * make it the current frame
+ */
+
+ picture->current_frame = picture->throwaway_frame;
+ }
+}
+
+
+
+static int parse_chunk (mpeg2dec_t * mpeg2dec, int code, uint8_t * buffer, uint32_t pts)
{
picture_t * picture;
int is_frame_done;
+ int bFlipPage;
/* wait for sequence_header_code */
if (mpeg2dec->is_sequence_needed && (code != 0xb3))
@@ -96,18 +162,17 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
if (is_frame_done) {
mpeg2dec->in_slice = 0;
- if (((picture->picture_structure == FRAME_PICTURE) ||
- (picture->second_field)) &&
- (!(mpeg2dec->drop_frame))) {
- if (picture->picture_coding_type == B_TYPE)
- picture->current_frame->draw (picture->current_frame);
- else
+ if ((picture->picture_structure == FRAME_PICTURE) ||
+ (picture->second_field)) {
+ if (picture->picture_coding_type == B_TYPE) {
+ picture->throwaway_frame->draw (picture->throwaway_frame);
+ picture->throwaway_frame->free (picture->throwaway_frame);
+ } else {
picture->forward_reference_frame->draw (picture->forward_reference_frame);
-#ifdef ARCH_X86
- if (config.flags & MM_ACCEL_X86_MMX)
- emms ();
-#endif
- }
+ }
+ bFlipPage = 1;
+ } else
+ bFlipPage = 0;
}
switch (code) {
@@ -117,13 +182,60 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
exit (1);
}
+ if (bFlipPage)
+ decode_reorder_frames (mpeg2dec);
+
if (mpeg2dec->pts) {
picture->current_frame->PTS = mpeg2dec->pts;
mpeg2dec->pts = 0;
}
- mpeg2dec->drop_frame =
- mpeg2dec->drop_flag && (picture->picture_coding_type == B_TYPE);
+
+ /*
+ * find out if we want to skip this frame
+ */
+
+ mpeg2dec->drop_frame = 0;
+ switch (picture->picture_coding_type) {
+ case B_TYPE:
+
+ if (mpeg2dec->frames_to_drop) {
+ mpeg2dec->drop_frame = 1;
+ mpeg2dec->frames_to_drop--;
+ }
+ if (!picture->forward_reference_frame
+ || !picture->backward_reference_frame
+ || picture->forward_reference_frame->bFrameBad
+ || picture->backward_reference_frame->bFrameBad) {
+ mpeg2dec->drop_frame = 1;
+ mpeg2dec->frames_to_drop--;
+ }
+
+ break;
+ case P_TYPE:
+
+ if (mpeg2dec->frames_to_drop>2) {
+ mpeg2dec->drop_frame = 1;
+ mpeg2dec->frames_to_drop--;
+ }
+
+ if (!picture->forward_reference_frame
+ || picture->forward_reference_frame->bFrameBad) {
+ mpeg2dec->drop_frame = 1;
+ mpeg2dec->frames_to_drop--;
+ }
+
+ break;
+ case I_TYPE:
+
+ if (mpeg2dec->frames_to_drop>4) {
+ mpeg2dec->drop_frame = 1;
+ mpeg2dec->frames_to_drop--;
+ }
+
+ break;
+ }
+
break;
case 0xb3: /* sequence_header_code */
@@ -131,20 +243,9 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
fprintf (stderr, "bad sequence header\n");
exit (1);
}
- if (mpeg2dec->is_sequence_needed) {
+ if (mpeg2dec->is_sequence_needed)
mpeg2dec->is_sequence_needed = 0;
- picture->forward_reference_frame =
- mpeg2dec->output->get_frame (mpeg2dec->output,picture->coded_picture_width,
- picture->coded_picture_height,
- picture->aspect_ratio_information, IMGFMT_YV12,
- picture->frame_duration);
- picture->backward_reference_frame =
- mpeg2dec->output->get_frame (mpeg2dec->output,picture->coded_picture_width,
- picture->coded_picture_height,
- picture->aspect_ratio_information, IMGFMT_YV12,
- picture->frame_duration);
- }
break;
case 0xb5: /* extension_start_code */
@@ -165,102 +266,83 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
mpeg2dec->in_slice = 1;
if (picture->second_field)
- picture->current_frame->field (picture->current_frame, picture->picture_structure);
+ picture->current_frame->field (picture->current_frame,
+ picture->picture_structure);
+ /*
else {
if (picture->picture_coding_type == B_TYPE)
picture->current_frame =
- mpeg2dec->output->get_frame (mpeg2dec->output,picture->coded_picture_width,
- picture->coded_picture_height,
- picture->aspect_ratio_information, IMGFMT_YV12,
- picture->frame_duration);
- /* vo_get_frame (mpeg2dec->output,
- picture->picture_structure); */
+ vo_get_frame (mpeg2dec->output,
+ picture->picture_structure);
else {
picture->current_frame =
- mpeg2dec->output->get_frame (mpeg2dec->output,picture->coded_picture_width,
- picture->coded_picture_height,
- picture->aspect_ratio_information, IMGFMT_YV12,
- picture->frame_duration);
- /*
vo_get_frame (mpeg2dec->output,
(VO_PREDICTION_FLAG |
picture->picture_structure));
- */
picture->forward_reference_frame =
picture->backward_reference_frame;
picture->backward_reference_frame = picture->current_frame;
}
}
+ */
}
if (!(mpeg2dec->drop_frame)) {
slice_process (picture, code, buffer);
-
-#ifdef ARCH_X86
- if (config.flags & MM_ACCEL_X86_MMX)
- emms ();
-#endif
}
}
return is_frame_done;
}
-static inline uint8_t * copy_chunk (mpeg2dec_t * mpeg2dec,
- uint8_t * current, uint8_t * end)
+int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, uint8_t * current, uint8_t * end,
+ uint32_t pts)
{
uint32_t shift;
uint8_t * chunk_ptr;
- uint8_t * limit;
uint8_t byte;
+ int ret = 0;
shift = mpeg2dec->shift;
chunk_ptr = mpeg2dec->chunk_ptr;
- limit = current + (mpeg2dec->chunk_buffer + BUFFER_SIZE - chunk_ptr);
- if (limit > end)
- limit = end;
-
- while (1) {
- byte = *current++;
- if (shift != 0x00000100) {
- shift = (shift | byte) << 8;
- *chunk_ptr++ = byte;
- if (current < limit)
- continue;
- if (current == end) {
+ mpeg2dec->pts = pts;
+
+ while (current != end) {
+ while (1) {
+ byte = *current++;
+ if (shift != 0x00000100) {
+ *chunk_ptr++ = byte;
+ shift = (shift | byte) << 8;
+ if (current != end)
+ continue;
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;
+#ifdef ARCH_X86
+ if (config.flags & MM_ACCEL_X86_MMX)
+ emms();
+#endif
+
+ return ret;
}
+ break;
}
- mpeg2dec->code = byte;
- mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
- mpeg2dec->shift = 0xffffff00;
- return current;
- }
-}
-int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, uint8_t * current,
- uint8_t * end, uint32_t pts)
-{
- int ret;
- uint8_t code;
+ /* found start_code following chunk */
- ret = 0;
+ ret += parse_chunk (mpeg2dec, mpeg2dec->code, mpeg2dec->chunk_buffer, pts);
- mpeg2dec->pts = pts;
- while (current != end) {
- code = mpeg2dec->code;
- current = copy_chunk (mpeg2dec, current, end);
- if (current == NULL)
- return ret;
- ret += parse_chunk (mpeg2dec, code, mpeg2dec->chunk_buffer, pts);
+ /* done with header or slice, prepare for next one */
+
+ mpeg2dec->code = byte;
+ chunk_ptr = mpeg2dec->chunk_buffer;
+ shift = 0xffffff00;
}
+ mpeg2dec->chunk_ptr = chunk_ptr;
+ mpeg2dec->shift = shift;
+#ifdef ARCH_X86
+ if (config.flags & MM_ACCEL_X86_MMX)
+ emms();
+#endif
return ret;
}
@@ -268,63 +350,20 @@ void mpeg2_close (mpeg2dec_t * mpeg2dec)
{
static uint8_t finalizer[] = {0,0,1,0};
- mpeg2_decode_data (mpeg2dec, finalizer, finalizer+4, mpeg2dec->pts);
+ mpeg2_decode_data (mpeg2dec, finalizer, finalizer+4, 0);
if (! (mpeg2dec->is_sequence_needed))
- mpeg2dec->picture->backward_reference_frame->draw (mpeg2dec->picture->backward_reference_frame);
+ mpeg2dec->picture->backward_reference_frame->draw (mpeg2dec->picture->backward_reference_frame);
+
+ mpeg2dec->output->close (mpeg2dec->output);
free (mpeg2dec->chunk_buffer);
free (mpeg2dec->picture);
}
-void mpeg2_drop (mpeg2dec_t * mpeg2dec, int flag)
+void mpeg2_skip_frames (mpeg2dec_t * mpeg2dec, int num_frames)
{
- mpeg2dec->drop_flag = flag;
-}
-
-/*
- * xine specific stuff
- */
-
-int mpeg2dec_get_version () {
- return 1;
-}
-
-int mpeg2dec_can_handle (int buf_type) {
- return (buf_type == BUF_VIDEO_MPEG) ;
-}
-
-
-static mpeg2dec_t gMpeg2;
-
-void mpeg2dec_init (vo_instance_t *video_out) {
- uint32_t mmacc = mm_accel();
-
- mpeg2_init (&gMpeg2, mmacc, video_out);
-}
-
-void mpeg2dec_decode_data (buf_element_t *buf) {
- mpeg2_decode_data (&gMpeg2, buf->content, buf->content + buf->size,
- buf->PTS);
+ mpeg2dec->frames_to_drop = num_frames;
}
-void mpeg2dec_release_img_buffers () {
- // decode_free_image_buffers (&gMpeg2);
-}
-void mpeg2dec_close () {
- mpeg2_close (&gMpeg2);
-}
-
-static video_decoder_t vd_mpeg2dec = {
- mpeg2dec_get_version,
- mpeg2dec_can_handle,
- mpeg2dec_init,
- mpeg2dec_decode_data,
- mpeg2dec_release_img_buffers,
- mpeg2dec_close
-};
-
-video_decoder_t *init_video_decoder_mpeg2dec () {
- return &vd_mpeg2dec;
-}