#include #include "../nsvlib.h" #include "../dec_if.h" #include "vfw.h" class VP5_Decoder : public IVideoDecoder { public: VP5_Decoder(int w, int h); ~VP5_Decoder(); int decode(int need_kf, void *in, int in_len, void **out, // out is set to a pointer to data unsigned int *out_type, // 'Y','V','1','2' is currently defined int *is_kf); void flush() { } int m_err; private: int width,height; BITMAPINFO vp5_bmo,vp5_bmi; HIC vp5_hic; unsigned char *vidbufdec; }; VP5_Decoder::VP5_Decoder(int w, int h) { width=w; height=h; m_err=0; vp5_hic=0; vidbufdec=(unsigned char*)malloc(sizeof(YV12_PLANES) + w*h*3/2); // init vp5 decode memset((void *) &vp5_bmi,0,sizeof(BITMAPINFO)); memset((void *) &vp5_bmo,0,sizeof(BITMAPINFO)); vp5_bmi.bmiHeader.biCompression = mmioFOURCC('V','P','5','0'); vp5_bmi.bmiHeader.biHeight=h; vp5_bmi.bmiHeader.biWidth =w; vp5_bmo.bmiHeader.biCompression = mmioFOURCC('Y','V','1','2'); vp5_bmo.bmiHeader.biHeight=h; vp5_bmo.bmiHeader.biWidth =w; vp5_bmo.bmiHeader.biBitCount = 12; vp5_hic = ICOpen(ICTYPE_VIDEO, vp5_bmi.bmiHeader.biCompression, ICMODE_DECOMPRESS); vp5_bmo.bmiHeader.biHeight*=-1; if(!vp5_hic || ICERR_OK !=ICDecompressBegin(vp5_hic, &vp5_bmi, &vp5_bmo)) { m_err=1; return; } } VP5_Decoder::~VP5_Decoder() { if (vp5_hic) { ICDecompressEnd(vp5_hic); ICClose(vp5_hic); } free(vidbufdec); } int VP5_Decoder::decode(int need_kf, void *in, int in_len, void **out, // out is set to a pointer to data unsigned int *out_type, // 'Y','V','1','2' is currently defined int *is_kf) { *out_type=NSV_MAKETYPE('Y','V','1','2'); vp5_bmi.bmiHeader.biSizeImage = in_len; if(ICERR_OK == ICDecompress(vp5_hic,0,(BITMAPINFOHEADER *) &vp5_bmi, (char*)in,(BITMAPINFOHEADER *) &vp5_bmo, (char*)vidbufdec+sizeof(YV12_PLANES))) { *is_kf=!(!in_len || ((unsigned char *)in)[0] > 0x7f); if (need_kf && !*is_kf) { return 0; } YV12_PLANES *image_vbd=(YV12_PLANES *)vidbufdec; image_vbd->y.baseAddr=(unsigned char *)(image_vbd+1); image_vbd->v.baseAddr=((unsigned char *)(image_vbd+1)) + width*height; image_vbd->u.baseAddr=((unsigned char *)(image_vbd+1)) + width*height*5/4; image_vbd->y.rowBytes=width; image_vbd->v.rowBytes=width/2; image_vbd->u.rowBytes=width/2; *out=(void*)vidbufdec; return 0; } return -1; } IVideoDecoder *VP5_CREATE(int w, int h, double framerate, unsigned int fmt, int *flip) { if (fmt == NSV_MAKETYPE('V','P','5','0')) { *flip=0; VP5_Decoder *a=new VP5_Decoder(w,h); if (a->m_err) { delete a; return NULL; } return a; } return NULL; }