import ctypes def XVID_MAKE_VERSION(a,b,c): return ((((a)&0xff)<<16) | (((b)&0xff)<<8) | ((c)&0xff)) XVID_VERSION=XVID_MAKE_VERSION(1,3,3) XVID_GBL_INIT=0 XVID_GBL_INFO=1 XVID_DEC_CREATE=0 XVID_DEC_DESTROY=1 XVID_DEC_DECODE=2 XVID_CSP_RGB=(1<<16) XVID_TYPE_VOL=-1 BUFFER_SIZE=2*1024*1024 BPP=3 XDIM=0 YDIM=0 class xvid_dec_create_t(ctypes.Structure): _fields_=[ ('version', ctypes.c_int), ('width', ctypes.c_int), ('height', ctypes.c_int), ('handle', ctypes.c_void_p), ('fourcc', ctypes.c_int), ('num_threads', ctypes.c_int), ] class xvid_gbl_init_t(ctypes.Structure): _fields_=[ ('version',ctypes.c_int), ('cpu_flags',ctypes.c_uint), ('debug',ctypes.c_int), ] class xvid_gbl_info_t(ctypes.Structure): _fields_=[ ('version',ctypes.c_int), ('actual_version',ctypes.c_int), ('build',ctypes.c_char_p), ('cpu_flags',ctypes.c_uint), ('num_threads',ctypes.c_int), ] class xvid_dec_stats_t__data__vol(ctypes.Structure): _fields_=[ ('general',ctypes.c_int), ('width',ctypes.c_int), ('height',ctypes.c_int), ('par',ctypes.c_int), ('par_width',ctypes.c_int), ('par_height',ctypes.c_int), ] class xvid_dec_stats_t__data__vop(ctypes.Structure): _fields_=[ ('general',ctypes.c_int), ('time_base',ctypes.c_int), ('time_increment',ctypes.c_int), ('qscale',ctypes.POINTER(ctypes.c_int)), ('qscale_stride',ctypes.c_int), ] class xvid_dec_stats_t__data(ctypes.Union): _fields_=[ ('vop',xvid_dec_stats_t__data__vop), ('vol',xvid_dec_stats_t__data__vol), ] class xvid_dec_stats_t(ctypes.Structure): _fields_=[ ('version',ctypes.c_int), ('type',ctypes.c_int), ('data',xvid_dec_stats_t__data), ] class xvid_image_t(ctypes.Structure): _fields_=[ ('csp',ctypes.c_int), ('plane',ctypes.c_void_p*4), ('stride',ctypes.c_int*4), ] class xvid_dec_frame_t(ctypes.Structure): _fields_=[ ('version',ctypes.c_int), ('general',ctypes.c_int), ('bitstream',ctypes.c_void_p), ('length',ctypes.c_int), ('output',xvid_image_t), ('brightness',ctypes.c_int), ] xvid_dec_create=None def xvid_init(): global xvid_dec_create xvid_gbl_info=xvid_gbl_info_t() xvid_gbl_info.version=XVID_VERSION ctypes.cdll.xvidcore.xvid_global(None,XVID_GBL_INFO,ctypes.byref(xvid_gbl_info),None) xvid_gbl_info.actual_version xvid_gbl_init=xvid_gbl_init_t() xvid_gbl_init.version=XVID_VERSION xvid_gbl_init.cpu_flags=0 ctypes.cdll.xvidcore.xvid_global(None,XVID_GBL_INIT,ctypes.byref(xvid_gbl_init),None) xvid_dec_create=xvid_dec_create_t() xvid_dec_create.version=XVID_VERSION xvid_dec_create.num_threads=xvid_gbl_info.num_threads return ctypes.cdll.xvidcore.xvid_decore(None,XVID_DEC_CREATE,ctypes.byref(xvid_dec_create),None) def xvid_quit(): global xvid_dec_create xvid_close() result=ctypes.cdll.xvidcore.xvid_decore(xvid_dec_create.handle,XVID_DEC_DESTROY,None,None) xvid_dec_create=None return result _xvid_input_file=None _xvid_input_file_eof=False _xvid_mp4_buffer=None _xvid_mp4_buffer_position=0 _xvid_mp4_ptr=None _xvid_out_buffer=None def xvid_open(fn): global _xvid_input_file,_xvid_mp4_buffer,_xvid_mp4_ptr,_xvid_mp4_buffer_position,_xvid_input_file_eof,xvid_dec_create if xvid_dec_create is None: xvid_init() xvid_close() _xvid_input_file=open(fn,'rb') _xvid_mp4_buffer=ctypes.create_string_buffer(BUFFER_SIZE) _xvid_mp4_buffer.value=_xvid_input_file.read(BUFFER_SIZE) _xvid_mp4_ptr=ctypes.pointer(_xvid_mp4_buffer) _xvid_mp4_buffer_position=0 _xvid_input_file_eof=False def xvid_close(): global _xvid_input_file,_xvid_mp4_buffer_position if _xvid_input_file is None: return _xvid_input_file.close() _xvid_input_file=None _xvid_mp4_buffer_position=0 def xvid_decode_frame(): global xvid_dec_create,_xvid_mp4_buffer,_xvid_mp4_buffer_position,_xvid_out_buffer,_xvid_mp4_ptr,_xvid_input_file,XDIM,YDIM,_xvid_input_file_eof if _xvid_mp4_buffer_position>BUFFER_SIZE-40: return False# shortest frames have around 38,39 bytes, at the end there could remain some (3 in my test vid) unusable bytes in buffer if xvid_dec_create is None: return False #input buffer check if _xvid_mp4_buffer_position>BUFFER_SIZE/2 and not _xvid_input_file_eof: chunksize=BUFFER_SIZE-_xvid_mp4_buffer_position chunk=_xvid_input_file.read(chunksize) if len(chunk)<chunksize: _xvid_input_file_eof=True _xvid_mp4_buffer.value=(_xvid_mp4_buffer.raw+chunk)[-BUFFER_SIZE:] _xvid_mp4_buffer_position=chunksize-len(chunk) _xvid_mp4_ptr=ctypes.pointer(_xvid_mp4_buffer) xvid_dec_stats=xvid_dec_stats_t() xvid_dec_stats.version=XVID_VERSION xvid_dec_frame=xvid_dec_frame_t() xvid_dec_frame.version=XVID_VERSION xvid_dec_frame.general=0 xvid_dec_frame.bitstream=ctypes.cast(_xvid_mp4_ptr,ctypes.c_void_p) xvid_dec_frame.length=len(_xvid_mp4_buffer)-_xvid_mp4_buffer_position xvid_dec_frame.output.plane[0]=ctypes.cast(_xvid_out_buffer,ctypes.c_void_p) xvid_dec_frame.output.stride[0]=XDIM*BPP xvid_dec_frame.output.csp=XVID_CSP_RGB used=ctypes.cdll.xvidcore.xvid_decore(xvid_dec_create.handle,XVID_DEC_DECODE,ctypes.byref(xvid_dec_frame),ctypes.byref(xvid_dec_stats)) _xvid_mp4_buffer_position+=used if used==0: print _xvid_mp4_buffer_position,BUFFER_SIZE,BUFFER_SIZE-_xvid_mp4_buffer_position _xvid_mp4_ptr=ctypes.cast(ctypes.cast(_xvid_mp4_buffer,ctypes.c_void_p).value+_xvid_mp4_buffer_position,ctypes.c_char_p) if xvid_dec_stats.type==XVID_TYPE_VOL: if XDIM*YDIM<xvid_dec_stats.data.vol.width*xvid_dec_stats.data.vol.height: XDIM=xvid_dec_stats.data.vol.width YDIM=xvid_dec_stats.data.vol.height _xvid_out_buffer=ctypes.create_string_buffer(XDIM*YDIM*4) return xvid_decode_frame() return _xvid_out_buffer.raw