diff options
author | Guenter Bartsch <guenter@users.sourceforge.net> | 2001-04-23 00:34:59 +0000 |
---|---|---|
committer | Guenter Bartsch <guenter@users.sourceforge.net> | 2001-04-23 00:34:59 +0000 |
commit | 2d61e7f5cd4f5add1aaab63fe54a17a416fe275a (patch) | |
tree | b3348bc8a5d92ef84e4433bad8d897716c0c31d9 /src/libmpeg2/decode.c | |
parent | 6f114fb0e414ba8fab9627558d7b299436fece19 (diff) | |
download | xine-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.c | 357 |
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; -} |