diff options
author | Guenter Bartsch <guenter@users.sourceforge.net> | 2001-05-26 00:48:47 +0000 |
---|---|---|
committer | Guenter Bartsch <guenter@users.sourceforge.net> | 2001-05-26 00:48:47 +0000 |
commit | 65480cd3d11b465f0ede5f6c3d1b9f12e06dc98b (patch) | |
tree | 4601feb5b4f1639204ee480414899d9b86ae7d5f /src | |
parent | c463738e5a66020a5abf7482047b015929cf951d (diff) | |
download | xine-lib-65480cd3d11b465f0ede5f6c3d1b9f12e06dc98b.tar.gz xine-lib-65480cd3d11b465f0ede5f6c3d1b9f12e06dc98b.tar.bz2 |
implemented frame skipping for libmpeg2 as well as low-quality decoding for low-end systems
CVS patchset: 82
CVS date: 2001/05/26 00:48:47
Diffstat (limited to 'src')
-rw-r--r-- | src/libmpeg2/decode.c | 107 | ||||
-rw-r--r-- | src/libmpeg2/mpeg2.h | 8 | ||||
-rw-r--r-- | src/libmpeg2/mpeg2_internal.h | 2 | ||||
-rw-r--r-- | src/libmpeg2/slice.c | 9 | ||||
-rw-r--r-- | src/video_out/video_out_xv.c | 4 | ||||
-rw-r--r-- | src/xine-engine/video_out.c | 9 |
6 files changed, 113 insertions, 26 deletions
diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c index 8feb005dc..044f235f3 100644 --- a/src/libmpeg2/decode.c +++ b/src/libmpeg2/decode.c @@ -90,17 +90,14 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, if (((picture->picture_structure == FRAME_PICTURE) || (picture->second_field)) ) { + picture->current_frame->bFrameBad = mpeg2dec->drop_frame; + if (picture->picture_coding_type == B_TYPE) { - picture->current_frame->bFrameBad = mpeg2dec->drop_frame; - picture->current_frame->PTS = mpeg2dec->pts; - mpeg2dec->pts = 0; mpeg2dec->frames_to_drop = picture->current_frame->draw (picture->current_frame); picture->current_frame->free (picture->current_frame); picture->current_frame = NULL; + picture->throwaway_frame = NULL; } else { - picture->forward_reference_frame->bFrameBad = mpeg2dec->drop_frame; - picture->forward_reference_frame->PTS = mpeg2dec->pts; - mpeg2dec->pts = 0; mpeg2dec->frames_to_drop = picture->forward_reference_frame->draw (picture->forward_reference_frame); } @@ -117,8 +114,41 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, fprintf (stderr, "bad picture header\n"); exit (1); } - mpeg2dec->drop_frame = /* FIXME : skip P and I frames too if necc. */ - (mpeg2dec->frames_to_drop>0) && (picture->picture_coding_type == B_TYPE); + + /* find out if we want to skip this frame */ + mpeg2dec->drop_frame = 0; + + picture->skip_non_intra_dct = (mpeg2dec->frames_to_drop>0) ; + + + switch (picture->picture_coding_type) { + case B_TYPE: + + if (mpeg2dec->frames_to_drop>1) { + mpeg2dec->drop_frame = 1; + } else if (picture->forward_reference_frame->bFrameBad + || picture->backward_reference_frame->bFrameBad) { + mpeg2dec->drop_frame = 1; + } + break; + + case P_TYPE: + + if (mpeg2dec->frames_to_drop>2) { + mpeg2dec->drop_frame = 1; + } else if (picture->backward_reference_frame->bFrameBad) { + mpeg2dec->drop_frame = 1; + } + break; + + case I_TYPE: + + if (mpeg2dec->frames_to_drop>4) { + mpeg2dec->drop_frame = 1; + } + break; + } + break; case 0xb3: /* sequence_header_code */ @@ -170,7 +200,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, picture->picture_structure); else { if (picture->picture_coding_type == B_TYPE) - picture->current_frame = + picture->throwaway_frame = picture->current_frame = mpeg2dec->output->get_frame (mpeg2dec->output, picture->coded_picture_width, picture->coded_picture_height, @@ -191,6 +221,8 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, picture->backward_reference_frame; picture->backward_reference_frame = picture->current_frame; } + picture->current_frame->PTS = mpeg2dec->pts; + mpeg2dec->pts = 0; } } @@ -268,15 +300,64 @@ int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, uint8_t * current, uint8_t * end, void mpeg2_close (mpeg2dec_t * mpeg2dec) { static uint8_t finalizer[] = {0,0,1,0xb4}; + picture_t *picture = mpeg2dec->picture; mpeg2_decode_data (mpeg2dec, finalizer, finalizer+4, 0); - /* FIXME - if (! (mpeg2dec->is_sequence_needed)) - vo_draw (mpeg2dec->picture->backward_reference_frame); - */ + if (picture->throwaway_frame) + picture->throwaway_frame->free (picture->throwaway_frame); + + if (picture->forward_reference_frame) + picture->forward_reference_frame->free (picture->forward_reference_frame); + + if (picture->backward_reference_frame) + picture->backward_reference_frame->free (picture->backward_reference_frame); + /* FIXME free (mpeg2dec->chunk_buffer); free (mpeg2dec->picture); + */ +} + +void mpeg2_find_sequence_header (mpeg2dec_t * mpeg2dec, + uint8_t * current, uint8_t * end){ + + uint8_t code; + picture_t *picture = mpeg2dec->picture; + + while (current != end) { + code = mpeg2dec->code; + current = copy_chunk (mpeg2dec, current, end); + if (current == NULL) + return ; + + if (code == 0xb3) { /* sequence_header_code */ + if (header_process_sequence_header (picture, mpeg2dec->chunk_buffer)) { + fprintf (stderr, "bad sequence header\n"); + return; + } + + 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->forward_reference_frame->PTS = 0; + 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; + + } + } + } } diff --git a/src/libmpeg2/mpeg2.h b/src/libmpeg2/mpeg2.h index bca8f61b0..69a4ba03d 100644 --- a/src/libmpeg2/mpeg2.h +++ b/src/libmpeg2/mpeg2.h @@ -59,8 +59,10 @@ void mpeg2_init (mpeg2dec_t * mpeg2dec, void mpeg2_close (mpeg2dec_t * mpeg2dec); int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, - uint8_t * data_start, uint8_t * data_end, uint32_t pts); + uint8_t * data_start, uint8_t * data_end, + uint32_t pts); + +void mpeg2_find_sequence_header (mpeg2dec_t * mpeg2dec, + uint8_t * data_start, uint8_t * data_end); -void decode_free_image_buffers (mpeg2dec_t * mpeg2dec) ; -void mpeg2_drop (mpeg2dec_t * mpeg2dec, int flag); diff --git a/src/libmpeg2/mpeg2_internal.h b/src/libmpeg2/mpeg2_internal.h index 97c611d1c..bafd7abf9 100644 --- a/src/libmpeg2/mpeg2_internal.h +++ b/src/libmpeg2/mpeg2_internal.h @@ -124,6 +124,8 @@ typedef struct picture_s { int mpeg1; + int skip_non_intra_dct; + /* these things are not needed by the decoder */ /* this is a temporary interface, we will build a better one later. */ int aspect_ratio_information; diff --git a/src/libmpeg2/slice.c b/src/libmpeg2/slice.c index 819ff0f65..95c04e79f 100644 --- a/src/libmpeg2/slice.c +++ b/src/libmpeg2/slice.c @@ -1011,8 +1011,9 @@ static inline void slice_non_intra_DCT (picture_t * picture, uint8_t * dest, if (picture->mpeg1) get_mpeg1_non_intra_block (picture); else - get_non_intra_block (picture); - idct_block_add (picture->DCTblock, dest, stride); + get_non_intra_block (picture); + if (!picture->skip_non_intra_dct) + idct_block_add (picture->DCTblock, dest, stride); } #define MOTION_Y(table,offset_x,offset_y,motion_x,motion_y, \ @@ -1712,7 +1713,7 @@ void slice_process (picture_t * picture, uint8_t code, uint8_t * buffer) } coded_block_pattern = get_coded_block_pattern (picture); - + if (coded_block_pattern & 0x20) slice_non_intra_DCT (picture, dest[0] + offset, DCT_stride); @@ -1733,7 +1734,7 @@ void slice_process (picture_t * picture, uint8_t code, uint8_t * buffer) stride >> 1); if (coded_block_pattern & 0x1) slice_non_intra_DCT (picture, dest[2] + (offset >> 1), - stride >> 1); + stride >> 1); } picture->dc_dct_pred[0] = picture->dc_dct_pred[1] = diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index 9fe115d37..c62f8ce73 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_xv.c,v 1.21 2001/05/25 10:30:56 f1rmb Exp $ + * $Id: video_out_xv.c,v 1.22 2001/05/26 00:48:47 guenter Exp $ * * video_out_xv.c, X11 video extension interface for xine * @@ -151,7 +151,7 @@ static void xv_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen if ((frame->width != width) || (frame->height != height) || (frame->format != format)) { - printf ("video_out_xv: updating frame to %d x %d (ratio=%d, format=%08x)\n",width,height,ratio_code,format); + /* printf ("video_out_xv: updating frame to %d x %d (ratio=%d, format=%08x)\n",width,height,ratio_code,format); */ XLockDisplay (this->display); diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index c1a206a3e..543e141fb 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.c,v 1.8 2001/05/24 23:15:40 f1rmb Exp $ + * $Id: video_out.c,v 1.9 2001/05/26 00:48:47 guenter Exp $ * */ @@ -352,6 +352,7 @@ static int vo_frame_draw (vo_frame_t *img) { int32_t diff; uint32_t cur_vpts; uint32_t pic_vpts ; + int frames_to_skip; pic_vpts = this->metronom->got_video_frame (this->metronom, img->PTS); img->PTS = pic_vpts; @@ -364,13 +365,13 @@ static int vo_frame_draw (vo_frame_t *img) { cur_vpts = this->metronom->get_current_time(this->metronom); diff = pic_vpts - cur_vpts; + frames_to_skip = (-1 * diff) / this->pts_per_frame + 1; xprintf (VERBOSE|VIDEO,"video_out:: delivery diff : %d\n",diff); if (cur_vpts>0) { - if (diff<0) { - int frames_to_skip = diff / this->pts_per_frame; + if (diff<(-1 * this->pts_per_half_frame)) { this->num_frames_discarded++; xprintf (VERBOSE|VIDEO, "vo_frame_draw: rejected, %d frames to skip\n", frames_to_skip); @@ -410,7 +411,7 @@ static int vo_frame_draw (vo_frame_t *img) { this->num_frames_skipped = 0; } - return 0; /* no frames to skip */ + return frames_to_skip; } vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) { |