diff options
Diffstat (limited to 'libmpcodecs')
-rw-r--r-- | libmpcodecs/vd_libmpeg2.c | 369 |
1 files changed, 118 insertions, 251 deletions
diff --git a/libmpcodecs/vd_libmpeg2.c b/libmpcodecs/vd_libmpeg2.c index 3e525172b5..7637925bc0 100644 --- a/libmpcodecs/vd_libmpeg2.c +++ b/libmpcodecs/vd_libmpeg2.c @@ -8,301 +8,168 @@ #include "vd_internal.h" +//#undef MPEG12_POSTPROC + static vd_info_t info = { - "MPEG 1/2 Video decoder v2.0", + "MPEG 1/2 Video decoder libmpeg2-v0.3.1", "libmpeg2", - "A'rpi", + "A'rpi & Fabian Franz", "Aaron & Walken", "native" }; LIBVD_EXTERN(libmpeg2) -#define USE_SIGJMP_TRICK - -#ifdef USE_SIGJMP_TRICK -#include <signal.h> -#include <setjmp.h> -#endif - -//#include "libmpdemux/parse_es.h" - -#include "libvo/video_out.h" // FIXME!!! +//#include "libvo/video_out.h" // FIXME!!! #include "libmpeg2/mpeg2.h" #include "libmpeg2/mpeg2_internal.h" -#include "libmpeg2/mm_accel.h" +//#include "libmpeg2/convert.h" #include "../cpudetect.h" -mpeg2_config_t config; // FIXME!!! -static picture_t *picture=NULL; // exported from libmpeg2/decode.c - -static int table_init_state=0; - // to set/get/query special features/parameters static int control(sh_video_t *sh,int cmd,void* arg,...){ return CONTROL_UNKNOWN; } -static vo_frame_t frames[3]; - // init driver static int init(sh_video_t *sh){ - - config.flags = 0; -if(gCpuCaps.hasMMX) - config.flags |= MM_ACCEL_X86_MMX; -if(gCpuCaps.hasMMX2) - config.flags |= MM_ACCEL_X86_MMXEXT; -if(gCpuCaps.has3DNow) - config.flags |= MM_ACCEL_X86_3DNOW; -#ifdef HAVE_MLIB - config.flags |= MM_ACCEL_MLIB; -#endif - - picture=malloc(sizeof(picture_t)); // !!! NEW HACK :) !!! - memset(picture,0,sizeof(picture_t)); - header_state_init (picture); - - if(!table_init_state){ - idct_init (); - motion_comp_init (); - table_init_state=1; - } - - picture->pp_options=divx_quality; - - memset(frames,0,3*sizeof(vo_frame_t)); + mpeg2dec_t * mpeg2dec; + const mpeg2_info_t * info; + int accel; + + accel = 0; + if(gCpuCaps.hasMMX) + accel |= MPEG2_ACCEL_X86_MMX; + if(gCpuCaps.hasMMX2) + accel |= MPEG2_ACCEL_X86_MMXEXT; + if(gCpuCaps.has3DNow) + accel |= MPEG2_ACCEL_X86_3DNOW; + #ifdef HAVE_MLIB + accel |= MPEG2_ACCEL_MLIB; + #endif + mpeg2_accel(accel); + + mpeg2dec = mpeg2_init (); + + if(!mpeg2dec) return 0; + + mpeg2_custom_fbuf(mpeg2dec,1); // enable DR1 - picture->forward_reference_frame=&frames[0]; - picture->backward_reference_frame=&frames[1]; - picture->temp_frame=&frames[2]; - picture->current_frame=NULL; - - // send seq header to the decoder: *** HACK *** -// mpeg2_decode_data(NULL,videobuffer,videobuffer+videobuf_len,0); -// mpeg2_allocate_image_buffers (picture); - return mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YV12); + sh->context=mpeg2dec; + + return 1; + //return mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YV12); } // uninit driver static void uninit(sh_video_t *sh){ -// mpeg2_free_image_buffers (picture); + mpeg2dec_t * mpeg2dec = sh->context; + mpeg2_close (mpeg2dec); } -static void draw_slice (vo_frame_t * frame, uint8_t ** src){ +static void draw_slice (void * _sh, uint8_t ** src, unsigned int y){ + sh_video_t* sh = (sh_video_t*) _sh; + mpeg2dec_t* mpeg2dec = sh->context; + const mpeg2_info_t * info = mpeg2_info (mpeg2dec); int stride[3]; - int y=picture->slice<<4; - stride[0]=picture->coded_picture_width; - stride[1]=stride[2]=stride[0]/2; + printf("draw_slice() y=%d \n",y); - mpcodecs_draw_slice(frame->vo, src, - stride, picture->display_picture_width, - (y+16<=picture->display_picture_height) ? 16 : - picture->display_picture_height-y, + stride[0]=mpeg2dec->decoder.stride; + stride[1]=stride[2]=mpeg2dec->decoder.uv_stride; + + mpcodecs_draw_slice(sh, (uint8_t **)src, + stride, info->sequence->display_width, + (y+16<=info->sequence->display_height) ? 16 : + info->sequence->display_height-y, 0, y); - - ++picture->slice; } -static int in_slice_flag=0; // FIXME! move to picture struct -static int drop_frame=0; // FIXME! move to picture struct - -static mp_image_t* parse_chunk (sh_video_t* sh, int code, uint8_t * buffer, int framedrop){ +// decode a frame +static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ + mpeg2dec_t * mpeg2dec = sh->context; + const mpeg2_info_t * info = mpeg2_info (mpeg2dec); mp_image_t* mpi=NULL; + int drop_frame, framedrop=flags&3; -// stats_header (code, buffer); - - if (in_slice_flag && ((!code) || (code >= 0xb0))) { - // ok, we've completed decoding a frame/field! - in_slice_flag = 0; - mpi=picture->display_frame->mpi; - if(picture->picture_structure!=FRAME_PICTURE && !picture->second_field) - mpi=NULL; // we don't draw first fields! - } - - switch (code) { - case 0x00: /* picture_start_code */ - if (header_process_picture_header (picture, buffer)) { - printf ("bad picture header\n"); - } - drop_frame = framedrop && (picture->picture_coding_type == B_TYPE); - drop_frame |= framedrop>=2; // hard drop - break; + // append extra 'end of frame' code: + ((char*)data+len)[0]=0; + ((char*)data+len)[1]=0; + ((char*)data+len)[2]=1; + ((char*)data+len)[3]=0xff; + len+=4; - case 0xb3: /* sequence_header_code */ - if (header_process_sequence_header (picture, buffer)) { - printf ("bad sequence header\n"); - } - break; - - case 0xb5: /* extension_start_code */ - if (header_process_extension (picture, buffer)) { - printf ("bad extension\n"); - } - break; - - default: - if (code >= 0xb0) break; - - if (!in_slice_flag) { - in_slice_flag = 1; + mpeg2_buffer (mpeg2dec, data, data+len); + + while(1){ + int state=mpeg2_parse (mpeg2dec); + switch(state){ + case -1: + // parsing of the passed buffer finished, return. +// if(!mpi) printf("\nNO PICTURE!\n"); + return mpi; + case STATE_SEQUENCE: + // video parameters inited/changed, (re)init libvo: + if(!mpcodecs_config_vo(sh, + info->sequence->width, + info->sequence->height, IMGFMT_YV12)) return 0; + break; + case STATE_PICTURE: { + int type=info->current_picture->flags&PIC_MASK_CODING_TYPE; + mp_image_t* mpi; + + printf("\mlibmpeg2: TYPE=%d\n",type); + + drop_frame = framedrop && (mpeg2dec->decoder.coding_type == B_TYPE); + drop_frame |= framedrop>=2; // hard drop + if (drop_frame) { + mpeg2_skip(mpeg2dec, 1); + //printf("Dropping Frame ...\n"); + break; + } + mpeg2_skip(mpeg2dec, 0); //mpeg2skip skips frames until set again to 0 + + // get_buffer "callback": + mpi=mpcodecs_get_image(sh,MP_IMGTYPE_IPB, + (type==PIC_FLAG_CODING_TYPE_B) + ? ((!framedrop && vd_use_slices && + (info->current_picture->flags&PIC_FLAG_PROGRESSIVE_FRAME)) ? + MP_IMGFLAG_DRAW_CALLBACK:0) + : (MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE), + info->sequence->picture_width, + info->sequence->picture_height); + if(!mpi) return 0; // VO ERROR!!!!!!!! + mpeg2_set_buf(mpeg2dec, mpi->planes, mpi); - // set current_frame pointer: - if (!picture->second_field){ - mp_image_t* mpi; - int flags; - if (picture->picture_coding_type == B_TYPE){ - flags=(!framedrop && vd_use_slices && - picture->picture_structure==FRAME_PICTURE) ? - MP_IMGFLAG_DRAW_CALLBACK:0; - picture->display_frame= - picture->current_frame = picture->temp_frame; - } else { - flags=MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE; - picture->current_frame = picture->forward_reference_frame; - picture->display_frame= - picture->forward_reference_frame = picture->backward_reference_frame; - picture->backward_reference_frame = picture->current_frame; - } - mpi=mpcodecs_get_image(sh,MP_IMGTYPE_IPB, flags, - picture->coded_picture_width, - picture->coded_picture_height); - // ok, lets see what did we get: - if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK && - !(mpi->flags&MP_IMGFLAG_DIRECT)){ - // nice, filter/vo likes draw_callback :) - picture->current_frame->copy=draw_slice; - } else - picture->current_frame->copy=NULL; - // let's, setup pointers! - picture->current_frame->base[0]=mpi->planes[0]; - picture->current_frame->base[1]=mpi->planes[1]; - picture->current_frame->base[2]=mpi->planes[2]; - picture->current_frame->mpi=mpi; // tricky! -#if 1 - if(!picture->forward_reference_frame->base[0]){ - // workaround for sig11 - picture->forward_reference_frame->base[0]=mpi->planes[0]; - picture->forward_reference_frame->base[1]=mpi->planes[1]; - picture->forward_reference_frame->base[2]=mpi->planes[2]; - } - if(!picture->backward_reference_frame->base[0]){ - // workaround for sig11 - picture->backward_reference_frame->base[0]=mpi->planes[0]; - picture->backward_reference_frame->base[1]=mpi->planes[1]; - picture->backward_reference_frame->base[2]=mpi->planes[2]; - } -#endif #ifdef MPEG12_POSTPROC - mpi->qscale=&picture->current_frame->quant_store[1][1]; - mpi->qstride=(MPEG2_MBC+1); -#endif - mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"mpeg2: [%c] %p %s \n", - (picture->picture_coding_type == B_TYPE) ? 'B':'P', - mpi, (mpi->flags&MP_IMGFLAG_DIRECT)?"DR!":""); + if(!mpi->qscale){ + mpi->qstride=info->sequence->picture_width>>4; + mpi->qscale=malloc(mpi->qstride*(info->sequence->picture_height>>4)); } - - picture->current_frame->vo=sh; - picture->slice=0; - - } - - if (!drop_frame) { - slice_process (picture, code, buffer); -#ifdef ARCH_X86 - if (config.flags & MM_ACCEL_X86_MMX) __asm__ __volatile__ ("emms"); + mpeg2dec->decoder.quant_store=mpi->qscale; + mpeg2dec->decoder.quant_stride=mpi->qstride; + mpi->pict_type=type; // 1->I, 2->P, 3->B #endif - } - } - return mpi; -} - -#ifdef USE_SIGJMP_TRICK - -static jmp_buf mpeg2_jmp_buf; - -static void mpeg2_sighandler(int sig){ - longjmp(mpeg2_jmp_buf,1); -} -#endif - -// decode a frame -static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ - static uint32_t code; - static uint8_t* pos; - static uint8_t* current; - uint8_t* end=data+len; - static mp_image_t* mpi; - mp_image_t* ret=NULL; - int framedrop=flags&3; - void* old_sigh; - - // Note: static is REQUIRED because of longjmp() may destroy stack! - pos=NULL; - current=data; - mpi=NULL; - -#ifdef USE_SIGJMP_TRICK - old_sigh=signal(SIGSEGV,mpeg2_sighandler); -#endif - -while(current<end){ - // FIND NEXT HEAD: - static unsigned int head; - static uint8_t c; - head=-1; - //-------------------- - while(current<end){ - c=current[0]; - ++current; - head<<=8; - if(head==0x100) break; // synced - head|=c; - } - //-------------------- - if(pos){ -#ifdef USE_SIGJMP_TRICK - if(setjmp(mpeg2_jmp_buf)){ -#ifdef ARCH_X86 - if (config.flags & MM_ACCEL_X86_MMX) __asm__ __volatile__ ("emms"); -#endif - printf("@@@ libmpeg2 returned from sig11... (bad file?) @@@\n"); - } else -#endif - { - ret=parse_chunk(sh, code&0xFF, pos, framedrop); - if(ret) mpi=ret; - } - } - //-------------------- - pos=current;code=head|c; -} - -#ifdef USE_SIGJMP_TRICK - signal(SIGSEGV,old_sigh); // restore sighandler -#endif - -// if(code==0x1FF){ - ret=parse_chunk(sh, 0xFF, NULL, framedrop); // send 'end of frame' - if(ret) mpi=ret; -// } - - if(mpi){ - static int last_non_b_type= 0; - - if(picture->picture_coding_type == B_TYPE) - mpi->pict_type= B_TYPE; - else{ - mpi->pict_type= last_non_b_type; - last_non_b_type= picture->picture_coding_type; + if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK && + !(mpi->flags&MP_IMGFLAG_DIRECT)){ + // nice, filter/vo likes draw_callback :) + mpeg2dec->decoder.convert=draw_slice; + mpeg2dec->decoder.fbuf_id=sh; + } else + mpeg2dec->decoder.convert=NULL; + break; + } + case STATE_SLICE: + case STATE_END: + // decoding done: + if(mpi) printf("AJAJJJJJJJJ2!\n"); + if(info->display_fbuf) mpi=info->display_fbuf->id; +// return mpi; } } - - return mpi; } #endif |