diff options
Diffstat (limited to 'src/libmpeg2new/xine_decoder.c')
-rw-r--r-- | src/libmpeg2new/xine_decoder.c | 226 |
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; } |