summaryrefslogtreecommitdiff
path: root/src/libmpeg2new/xine_decoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmpeg2new/xine_decoder.c')
-rw-r--r--src/libmpeg2new/xine_decoder.c226
1 files changed, 194 insertions, 32 deletions
diff --git a/src/libmpeg2new/xine_decoder.c b/src/libmpeg2new/xine_decoder.c
index 8d0445898..5b78782a8 100644
--- a/src/libmpeg2new/xine_decoder.c
+++ b/src/libmpeg2new/xine_decoder.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: xine_decoder.c,v 1.4 2003/06/11 00:22:57 jcdutton Exp $
+ * $Id: xine_decoder.c,v 1.5 2003/06/13 00:52:47 jcdutton Exp $
*
* stuff needed to turn libmpeg2 into a xine decoder plugin
*/
@@ -30,18 +30,18 @@
#include <fcntl.h>
#include <unistd.h>
#include <inttypes.h>
-#include <mpeg2dec/mpeg2.h>
#include <assert.h>
+#include "./include/mpeg2.h"
#include "xine_internal.h"
#include "video_out.h"
#include "buffer.h"
#define LOG
-/*
+
#define LOG_FRAME_ALLOC_FREE
-*/
+
typedef struct {
video_decoder_class_t decoder_class;
@@ -53,8 +53,44 @@ typedef struct mpeg2_video_decoder_s {
mpeg2dec_t *mpeg2dec;
mpeg2_class_t *class;
xine_stream_t *stream;
+ int32_t force_aspect;
+ int32_t aspect_ratio;
+ int32_t aspect_ratio_float;
+ uint32_t img_state[30];
+ uint32_t frame_number;
+
} mpeg2_video_decoder_t;
+
+static void mpeg2_video_print_bad_state(uint32_t * img_state) {
+ int32_t n,m;
+ m=0;
+ for(n=0;n<30;n++) {
+ if (img_state[n]>0) {
+ printf("%d = %u\n",n, img_state[n]);
+ m++;
+ }
+ }
+ if (m > 3) assert(0);
+ if (m == 0) printf("NO FRAMES\n");
+}
+
+static void mpeg2_video_print_fbuf(const mpeg2_fbuf_t * fbuf) {
+ printf("%p",fbuf);
+ vo_frame_t * img;
+ if (fbuf) {
+ img = (vo_frame_t *) fbuf->id;
+ if (img) {
+ printf (", img=%p, (id=%d)\n",
+ img, img->id);
+ } else {
+ printf (", img=NULL\n");
+ }
+ } else {
+ printf ("\n");
+ }
+}
+
static void mpeg2_video_decode_data (video_decoder_t *this_gen, buf_element_t *buf_element) {
mpeg2_video_decoder_t *this = (mpeg2_video_decoder_t *) this_gen;
uint8_t * current = buf_element->content;
@@ -63,76 +99,198 @@ static void mpeg2_video_decode_data (video_decoder_t *this_gen, buf_element_t *b
uint32_t pts;
mpeg2_state_t state;
vo_frame_t * img;
+ /* handle aspect hints from xine-dvdnav */
+ if (buf_element->decoder_flags & BUF_FLAG_SPECIAL) {
+ if (buf_element->decoder_info[1] == BUF_SPECIAL_ASPECT) {
+ this->force_aspect = buf_element->decoder_info[2];
+ if (buf_element->decoder_info[3] == 0x1 && buf_element->decoder_info[2] == XINE_VO_ASPECT_ANAMORPHIC)
+ /* letterboxing is denied, we have to do pan&scan */
+ this->force_aspect = XINE_VO_ASPECT_PAN_SCAN;
+ }
+ printf("libmpeg2:decode_data: forced aspect to=%d\n", this->force_aspect);
+
+ return;
+ }
+
if (buf_element->decoder_flags != 0) return;
+
+ printf ("libmpeg2:decode_data:buffer\n");
pts=buf_element->pts;
mpeg2_buffer (this->mpeg2dec, current, end);
info = mpeg2_info (this->mpeg2dec);
while ((state = mpeg2_parse (this->mpeg2dec)) != STATE_BUFFER) {
+ printf("libmpeg2:decode_data:current_fbuf=");
+ mpeg2_video_print_fbuf(info->current_fbuf);
+ printf("libmpeg2:decode_data:display_fbuf=");
+ mpeg2_video_print_fbuf(info->display_fbuf);
+ printf("libmpeg2:decode_data:discard_fbuf=");
+ mpeg2_video_print_fbuf(info->discard_fbuf);
+
switch (state) {
case STATE_SEQUENCE:
/* might set nb fbuf, convert format, stride */
/* might set fbufs */
- mpeg2_custom_fbuf (this->mpeg2dec, 1); /* <- Force libmpeg2 to use xine frame buffers. */
+ printf ("libmpeg2:decode_data:STATE_SEQUENCE\n");
this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = info->sequence->picture_width;
this->stream->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = info->sequence->picture_height;
this->stream->stream_info[XINE_STREAM_INFO_FRAME_DURATION] = info->sequence->frame_period / 300;
- switch (info->sequence->pixel_width) {
- case XINE_VO_ASPECT_PAN_SCAN:
- case XINE_VO_ASPECT_ANAMORPHIC:
- this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 16.0 /9.0;
- break;
- case XINE_VO_ASPECT_DVB: /* 2.11:1 */
- this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 2.11/1.0;
- break;
- case XINE_VO_ASPECT_SQUARE: /* square pels */
- this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000;
- break;
- default:
- this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 4.0 / 3.0;
- break;
+ if (this->force_aspect > 0) {
+ this->aspect_ratio = this->force_aspect;
+ switch (info->sequence->pixel_width) {
+ case XINE_VO_ASPECT_PAN_SCAN:
+ case XINE_VO_ASPECT_ANAMORPHIC:
+ this->aspect_ratio_float = 10000 * 16.0 /9.0;
+ break;
+ case XINE_VO_ASPECT_DVB: /* 2.11:1 */
+ this->aspect_ratio_float = 10000 * 2.11/1.0;
+ break;
+ case XINE_VO_ASPECT_SQUARE: /* square pels */
+ this->aspect_ratio_float = 10000;
+ break;
+ default:
+ this->aspect_ratio_float = 10000 * 4.0 / 3.0;
+ break;
+ }
+ } else {
+ this->aspect_ratio_float = (10000 * info->sequence->pixel_width) / info->sequence->pixel_height;
+ printf("libmpeg2:decode_data: pixel_width=%d, height=%d\n",
+ info->sequence->pixel_width,
+ info->sequence->pixel_height);
+ if (this->aspect_ratio_float > 20000) {
+ this->aspect_ratio = XINE_VO_ASPECT_DVB;
+ } else if (this->aspect_ratio_float > 15000) {
+ this->aspect_ratio = XINE_VO_ASPECT_ANAMORPHIC;
+ } else if (this->aspect_ratio_float > 12000) {
+ this->aspect_ratio = XINE_VO_ASPECT_4_3;
+ } else {
+ this->aspect_ratio = XINE_VO_ASPECT_SQUARE;
+ }
}
- this->stream->meta_info[XINE_META_INFO_VIDEOCODEC] = strdup ("MPEG-new");
+ this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = this->aspect_ratio_float;
+
+
+ if (info->sequence->flags & SEQ_FLAG_MPEG2) {
+ this->stream->meta_info[XINE_META_INFO_VIDEOCODEC] = strdup ("MPEG 2 (libmpeg2new)");
+ } else {
+ this->stream->meta_info[XINE_META_INFO_VIDEOCODEC] = strdup ("MPEG 1 (libmpeg2new)");
+ }
+
break;
case STATE_PICTURE:
/* might skip */
/* might set fbuf */
-
+ printf ("libmpeg2:decode_data:STATE_PICTURE\n");
+ if (info->current_picture) {
+ printf ("libmpeg2:decode_data:current picture nb_fields = %d, flags = %x type = %d\n",
+ info->current_picture->nb_fields,
+ info->current_picture->flags,
+ info->current_picture->flags & 7);
+ }
+ if (info->current_picture_2nd) {
+ printf ("libmpeg2:decode_data:current2 picture nb_fields = %d, flags = %x\n",
+ info->current_picture_2nd->nb_fields,
+ info->current_picture_2nd->flags);
+ }
+ if (info->display_picture) {
+ printf ("libmpeg2:decode_data:display picture nb_fields = %d, flags = %x\n",
+ info->display_picture->nb_fields,
+ info->display_picture->flags);
+ }
+ if (info->display_picture_2nd) {
+ printf ("libmpeg2:decode_data:display2 picture nb_fields = %d, flags = %x\n",
+ info->display_picture_2nd->nb_fields,
+ info->display_picture_2nd->flags);
+ }
img = this->stream->video_out->get_frame (this->stream->video_out,
info->sequence->picture_width,
info->sequence->picture_height,
- info->sequence->pixel_width, /* Aspect ratio */
+ this->aspect_ratio, /* Aspect ratio */
XINE_IMGFMT_YV12,
//picture->picture_structure);
0);
- img->pts=buf_element->pts;
+ this->frame_number++;
+ printf("libmpeg2:frame_number=%u\n",this->frame_number);
+ //img->pts=buf_element->pts;
#ifdef LOG_FRAME_ALLOC_FREE
- printf ("libmpeg2:decode_data:get_frame id=%d\n", img->id);
+ printf ("libmpeg2:decode_data:get_frame %p (id=%d)\n", img,img->id);
#endif
+ if (this->img_state[img->id] != 0) {
+ printf ("libmpeg2:decode_data:get_frame id=%d BAD STATE:%d\n", img->id, this->img_state[img->id]);
+ assert(0);
+ }
+
+ this->img_state[img->id] = 1;
mpeg2_set_buf (this->mpeg2dec, img->base, img);
break;
case STATE_SLICE:
case STATE_END:
+ printf ("libmpeg2:decode_data:STATE_SLICE/END\n");
/* draw current picture */
/* might free frame buffer */
- if (info->display_fbuf) {
+ if (info->current_picture) {
+ printf ("libmpeg2:decode_data:current picture nb_fields = %d, flags = %x type = %d\n",
+ info->current_picture->nb_fields,
+ info->current_picture->flags,
+ info->current_picture->flags & 7);
+ }
+ if (info->current_picture_2nd) {
+ printf ("libmpeg2:decode_data:current2 picture nb_fields = %d, flags = %x\n",
+ info->current_picture_2nd->nb_fields,
+ info->current_picture_2nd->flags);
+ }
+ if (info->display_picture) {
+ printf ("libmpeg2:decode_data:display picture nb_fields = %d, flags = %x\n",
+ info->display_picture->nb_fields,
+ info->display_picture->flags);
+ }
+ if (info->display_picture_2nd) {
+ printf ("libmpeg2:decode_data:display2 picture nb_fields = %d, flags = %x\n",
+ info->display_picture_2nd->nb_fields,
+ info->display_picture_2nd->flags);
+ }
+ if (info->display_fbuf && info->display_fbuf->id) {
img = (vo_frame_t *) info->display_fbuf->id;
img->duration=info->sequence->frame_period / 300;
#ifdef LOG_FRAME_ALLOC_FREE
- printf ("libmpeg2:decode_data:draw_frame id=%d\n", img->id);
+ printf ("libmpeg2:decode_data:draw_frame %p, id=%d \n", info->display_fbuf, img->id);
#endif
- img->draw (img, this->stream);
+ if (this->img_state[img->id] != 1) {
+ printf ("libmpeg2:decode_data:draw_frame id=%d BAD STATE:%d\n", img->id, this->img_state[img->id]);
+ assert(0);
+ }
+ if (this->img_state[img->id] == 1) {
+ img->draw (img, this->stream);
+ this->img_state[img->id] = 2;
+ }
+
+ }
+ if (info->discard_fbuf && !info->discard_fbuf->id) {
+ printf ("libmpeg2:decode_data:BAD free_frame discard_fbuf=%p\n", info->discard_fbuf);
+ assert(0);
}
- img = (vo_frame_t *) info->discard_fbuf->id;
- if (info->discard_fbuf && img) {
+ if (info->discard_fbuf && info->discard_fbuf->id) {
+ img = (vo_frame_t *) info->discard_fbuf->id;
#ifdef LOG_FRAME_ALLOC_FREE
- printf ("libmpeg2:decode_data:free_frame id=%d\n", img->id);
+ printf ("libmpeg2:decode_data:free_frame %p,id=%d\n", info->discard_fbuf, img->id);
#endif
- img->free(img);
+ if (this->img_state[img->id] != 2) {
+ printf ("libmpeg2:decode_data:free_frame id=%d BAD STATE:%d\n", img->id, this->img_state[img->id]);
+ assert(0);
+ }
+ if (this->img_state[img->id] == 2) {
+ img->free(img);
+ this->img_state[img->id] = 0;
+ }
}
+ mpeg2_video_print_bad_state(this->img_state);
+ break;
+ case STATE_GOP:
+ printf ("libmpeg2:decode_data:STATE_GOP\n");
break;
default:
+ printf ("libmpeg2:decode_data:UNKNOWN STATE!!!=%d\n", state);
break;
}
@@ -185,6 +343,7 @@ static void mpeg2_video_dispose (video_decoder_t *this_gen) {
static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) {
mpeg2_video_decoder_t *this ;
+ int32_t n;
this = (mpeg2_video_decoder_t *) malloc (sizeof (mpeg2_video_decoder_t));
memset(this, 0, sizeof (mpeg2_video_decoder_t));
@@ -196,10 +355,13 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre
this->video_decoder.dispose = mpeg2_video_dispose;
this->stream = stream;
this->class = (mpeg2_class_t *) class_gen;
+ this->frame_number=0;
this->mpeg2dec = mpeg2_init ();
+ mpeg2_custom_fbuf (this->mpeg2dec, 1); /* <- Force libmpeg2 to use xine frame buffers. */
stream->video_out->open(stream->video_out, stream);
-/* this->mpeg2.force_aspect = 0; */
+ this->force_aspect = 0;
+ for(n=0;n<30;n++) this->img_state[n]=0;
return &this->video_decoder;
}