1
mirror of https://github.com/mpv-player/mpv synced 2024-11-14 22:48:35 +01:00
mpv/libmpcodecs/vd_libmpeg2.c
rfelker 48ecb3e717 clean up field flags:
1) cosmetic change, no reason these need to be mpeg2-specific
2) add a flag to tell when fields are ordered, so we don't have to
assume bff (which would usually be wrong) when field flags are not
available.
3) add other flags for future use :)


git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@10664 b3059339-0415-0410-9bf9-f77b7e298cf2
2003-08-18 14:49:06 +00:00

184 lines
4.9 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#ifdef USE_LIBMPEG2
#include "mp_msg.h"
#include "vd_internal.h"
//#undef MPEG12_POSTPROC
static vd_info_t info =
{
"MPEG 1/2 Video decoder libmpeg2-v0.3.1",
"libmpeg2",
"A'rpi & Fabian Franz",
"Aaron & Walken",
"native"
};
LIBVD_EXTERN(libmpeg2)
//#include "libvo/video_out.h" // FIXME!!!
#include "libmpeg2/mpeg2.h"
#include "libmpeg2/mpeg2_internal.h"
//#include "libmpeg2/convert.h"
#include "../cpudetect.h"
// 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){
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;
if(gCpuCaps.hasAltiVec)
accel |= MPEG2_ACCEL_PPC_ALTIVEC;
#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
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){
mpeg2dec_t * mpeg2dec = sh->context;
mpeg2_close (mpeg2dec);
}
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];
// printf("draw_slice() y=%d \n",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);
}
// 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;
// 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;
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),
(info->sequence->picture_width+15)&(~15),
(info->sequence->picture_height+15)&(~15) );
if(!mpi) return 0; // VO ERROR!!!!!!!!
mpeg2_set_buf(mpeg2dec, mpi->planes, mpi);
if (info->current_picture->flags&PIC_FLAG_TOP_FIELD_FIRST)
mpi->fields |= MP_IMGFIELD_TOP_FIRST;
else mpi->fields &= ~MP_IMGFIELD_TOP_FIRST;
if (info->current_picture->flags&PIC_FLAG_REPEAT_FIRST_FIELD)
mpi->fields |= MP_IMGFIELD_REPEAT_FIRST;
else mpi->fields &= ~MP_IMGFIELD_REPEAT_FIRST;
mpi->fields |= MP_IMGFIELD_ORDERED;
#ifdef MPEG12_POSTPROC
if(!mpi->qscale){
mpi->qstride=(info->sequence->picture_width+15)>>4;
mpi->qscale=malloc(mpi->qstride*((info->sequence->picture_height+15)>>4));
}
mpeg2dec->decoder.quant_store=mpi->qscale;
mpeg2dec->decoder.quant_stride=mpi->qstride;
mpi->pict_type=type; // 1->I, 2->P, 3->B
mpi->qscale_type= 1;
#endif
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;
}
}
}
#endif