mirror of
https://github.com/mpv-player/mpv
synced 2024-12-20 22:02:59 +00:00
48ecb3e717
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
184 lines
4.9 KiB
C
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
|