summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGuenter Bartsch <guenter@users.sourceforge.net>2001-05-26 00:48:47 +0000
committerGuenter Bartsch <guenter@users.sourceforge.net>2001-05-26 00:48:47 +0000
commit65480cd3d11b465f0ede5f6c3d1b9f12e06dc98b (patch)
tree4601feb5b4f1639204ee480414899d9b86ae7d5f /src
parentc463738e5a66020a5abf7482047b015929cf951d (diff)
downloadxine-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.c107
-rw-r--r--src/libmpeg2/mpeg2.h8
-rw-r--r--src/libmpeg2/mpeg2_internal.h2
-rw-r--r--src/libmpeg2/slice.c9
-rw-r--r--src/video_out/video_out_xv.c4
-rw-r--r--src/xine-engine/video_out.c9
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) {