2002-03-09 02:18:33 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "config.h"
|
2002-11-01 16:40:15 +00:00
|
|
|
#ifdef USE_LIBMPEG2
|
|
|
|
|
2002-03-09 02:18:33 +00:00
|
|
|
#include "mp_msg.h"
|
|
|
|
|
|
|
|
#include "vd_internal.h"
|
|
|
|
|
2003-04-06 16:43:46 +00:00
|
|
|
//#undef MPEG12_POSTPROC
|
|
|
|
|
2002-03-09 02:18:33 +00:00
|
|
|
static vd_info_t info =
|
|
|
|
{
|
2003-04-06 16:43:46 +00:00
|
|
|
"MPEG 1/2 Video decoder libmpeg2-v0.3.1",
|
2002-03-09 02:18:33 +00:00
|
|
|
"libmpeg2",
|
2003-04-06 16:43:46 +00:00
|
|
|
"A'rpi & Fabian Franz",
|
2002-03-09 02:18:33 +00:00
|
|
|
"Aaron & Walken",
|
|
|
|
"native"
|
|
|
|
};
|
|
|
|
|
|
|
|
LIBVD_EXTERN(libmpeg2)
|
|
|
|
|
2003-04-06 16:43:46 +00:00
|
|
|
//#include "libvo/video_out.h" // FIXME!!!
|
2002-03-09 02:18:33 +00:00
|
|
|
|
|
|
|
#include "libmpeg2/mpeg2.h"
|
|
|
|
#include "libmpeg2/mpeg2_internal.h"
|
2003-04-06 16:43:46 +00:00
|
|
|
//#include "libmpeg2/convert.h"
|
2002-04-03 02:39:02 +00:00
|
|
|
|
|
|
|
#include "../cpudetect.h"
|
|
|
|
|
2002-03-09 02:18:33 +00:00
|
|
|
// to set/get/query special features/parameters
|
|
|
|
static int control(sh_video_t *sh,int cmd,void* arg,...){
|
|
|
|
return CONTROL_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
// init driver
|
|
|
|
static int init(sh_video_t *sh){
|
2003-04-06 16:43:46 +00:00
|
|
|
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;
|
2003-06-09 12:10:42 +00:00
|
|
|
if(gCpuCaps.hasAltiVec)
|
|
|
|
accel |= MPEG2_ACCEL_PPC_ALTIVEC;
|
2003-04-06 16:43:46 +00:00
|
|
|
#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
|
2002-04-18 15:03:08 +00:00
|
|
|
|
2003-04-06 16:43:46 +00:00
|
|
|
sh->context=mpeg2dec;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
//return mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YV12);
|
2002-03-09 02:18:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// uninit driver
|
|
|
|
static void uninit(sh_video_t *sh){
|
2003-04-06 16:43:46 +00:00
|
|
|
mpeg2dec_t * mpeg2dec = sh->context;
|
|
|
|
mpeg2_close (mpeg2dec);
|
2002-03-09 02:18:33 +00:00
|
|
|
}
|
|
|
|
|
2003-04-06 16:43:46 +00:00
|
|
|
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);
|
2002-04-03 02:39:02 +00:00
|
|
|
int stride[3];
|
|
|
|
|
2003-04-19 14:33:38 +00:00
|
|
|
// printf("draw_slice() y=%d \n",y);
|
2002-04-03 02:39:02 +00:00
|
|
|
|
2003-04-06 16:43:46 +00:00
|
|
|
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,
|
2002-04-03 02:39:02 +00:00
|
|
|
0, y);
|
|
|
|
}
|
|
|
|
|
2003-04-06 16:43:46 +00:00
|
|
|
// 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);
|
2002-04-03 02:39:02 +00:00
|
|
|
mp_image_t* mpi=NULL;
|
2003-04-06 16:43:46 +00:00
|
|
|
int drop_frame, framedrop=flags&3;
|
2002-04-03 02:39:02 +00:00
|
|
|
|
2003-10-11 11:21:54 +00:00
|
|
|
if(len<=0) return NULL; // skipped null frame
|
|
|
|
|
2003-04-06 16:43:46 +00:00
|
|
|
// 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;
|
2002-04-03 02:39:02 +00:00
|
|
|
|
2003-04-06 16:43:46 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
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),
|
2003-06-06 19:12:08 +00:00
|
|
|
(info->sequence->picture_width+15)&(~15),
|
|
|
|
(info->sequence->picture_height+15)&(~15) );
|
2003-04-06 16:43:46 +00:00
|
|
|
if(!mpi) return 0; // VO ERROR!!!!!!!!
|
|
|
|
mpeg2_set_buf(mpeg2dec, mpi->planes, mpi);
|
2003-08-03 12:09:58 +00:00
|
|
|
if (info->current_picture->flags&PIC_FLAG_TOP_FIELD_FIRST)
|
2003-08-18 14:49:06 +00:00
|
|
|
mpi->fields |= MP_IMGFIELD_TOP_FIRST;
|
|
|
|
else mpi->fields &= ~MP_IMGFIELD_TOP_FIRST;
|
2003-08-03 12:09:58 +00:00
|
|
|
if (info->current_picture->flags&PIC_FLAG_REPEAT_FIRST_FIELD)
|
2003-08-18 14:49:06 +00:00
|
|
|
mpi->fields |= MP_IMGFIELD_REPEAT_FIRST;
|
|
|
|
else mpi->fields &= ~MP_IMGFIELD_REPEAT_FIRST;
|
|
|
|
mpi->fields |= MP_IMGFIELD_ORDERED;
|
2002-04-03 02:39:02 +00:00
|
|
|
|
2002-04-07 16:34:15 +00:00
|
|
|
#ifdef MPEG12_POSTPROC
|
2003-04-06 16:43:46 +00:00
|
|
|
if(!mpi->qscale){
|
2003-06-06 19:12:08 +00:00
|
|
|
mpi->qstride=(info->sequence->picture_width+15)>>4;
|
|
|
|
mpi->qscale=malloc(mpi->qstride*((info->sequence->picture_height+15)>>4));
|
2002-04-03 02:39:02 +00:00
|
|
|
}
|
2003-04-06 16:43:46 +00:00
|
|
|
mpeg2dec->decoder.quant_store=mpi->qscale;
|
|
|
|
mpeg2dec->decoder.quant_stride=mpi->qstride;
|
|
|
|
mpi->pict_type=type; // 1->I, 2->P, 3->B
|
2003-04-18 13:18:59 +00:00
|
|
|
mpi->qscale_type= 1;
|
2002-04-03 02:39:02 +00:00
|
|
|
#endif
|
|
|
|
|
2003-04-06 16:43:46 +00:00
|
|
|
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;
|
2002-10-29 11:26:26 +00:00
|
|
|
}
|
|
|
|
}
|
2002-04-03 02:39:02 +00:00
|
|
|
}
|
2002-11-01 16:40:15 +00:00
|
|
|
#endif
|