/******************************************************************* Killer Tomate - MPEG-2 VIDEO VFAPI Plug-In *******************************************************************/ #include #include #include #include "vfapi.h" #include "vfapi_edit_ext.h" #include "mpeg2video.h" #include "mpeg2edit.h" HRESULT _stdcall vfGetPluginInfo(LPVF_PluginInfo info); HRESULT _stdcall vfGetPluginFunc(LPVF_PluginFunc func); HRESULT _stdcall vfGetPluginFuncEditExt(LPVF_PluginFuncEditExt func_edit_ext); HRESULT _stdcall open_file(char *path, LPVF_FileHandle out); HRESULT _stdcall close_file(VF_FileHandle p); HRESULT _stdcall get_file_info(VF_FileHandle in, LPVF_FileInfo out); HRESULT _stdcall get_stream_info(VF_FileHandle in, DWORD s, void *out); HRESULT _stdcall read_data(VF_FileHandle in, DWORD s, void *out); HRESULT _stdcall get_frame_type(VF_FileHandle in, LPVF_FrameType out); HRESULT _stdcall cut(VF_FileHandle in, LPVF_CutOption opt); HRESULT _stdcall vfGetPluginInfo(LPVF_PluginInfo info) { if(info == NULL){ return VF_ERROR; } if(info->dwSize != sizeof(VF_PluginInfo)){ return VF_ERROR; } info->dwAPIVersion = 1; info->dwVersion = 1; info->dwSupportStreamType = VF_STREAM_VIDEO; strcpy(info->cPluginInfo, "MPEG-2 VIDEO Plug-In"); strcpy(info->cFileType, "MPEG-2 Stream (*.m2p;*.mpg;*.m2v;*.vob)|*.m2p;*.mpg;*.m2v;*.vob"); return VF_OK; } HRESULT _stdcall vfGetPluginFunc(LPVF_PluginFunc func) { if(func == NULL){ return VF_ERROR; } if(func->dwSize != sizeof(VF_PluginFunc)){ return VF_ERROR; } func->OpenFile = open_file; func->CloseFile = close_file; func->GetFileInfo = get_file_info; func->GetStreamInfo = get_stream_info; func->ReadData = read_data; return VF_OK; } HRESULT _stdcall vfGetPluginFuncEditExt(LPVF_PluginFuncEditExt func_edit_ext) { if(func_edit_ext == NULL){ return VF_ERROR; } if(func_edit_ext->dwSize != sizeof(VF_PluginFuncEditExt)){ return VF_ERROR; } func_edit_ext->GetFrameType = get_frame_type; func_edit_ext->Cut = cut; return VF_OK; } HRESULT _stdcall open_file(char *path, LPVF_FileHandle out) { MPEG2VIDEO **w; w = (MPEG2VIDEO **)out; *w = (MPEG2VIDEO *)malloc(sizeof(MPEG2VIDEO)); if(*w == NULL){ return VF_ERROR; } if(! open_mpeg2video(path, *w)){ free(*w); *w = NULL; return VF_ERROR; } return VF_OK; } HRESULT _stdcall close_file(VF_FileHandle p) { MPEG2VIDEO *w; w = (MPEG2VIDEO *)p; close_mpeg2video(w); free(w); return VF_OK; } HRESULT _stdcall get_file_info(VF_FileHandle in, LPVF_FileInfo out) { UNREFERENCED_PARAMETER(in); if(out == NULL){ return VF_ERROR; } if(out->dwSize != sizeof(VF_FileInfo)){ return VF_ERROR; } out->dwHasStreams = VF_STREAM_VIDEO; return VF_OK; } HRESULT _stdcall get_stream_info(VF_FileHandle in, DWORD s, void *out) { MPEG2VIDEO *w; LPVF_StreamInfo_Video r; if(s != VF_STREAM_VIDEO){ return VF_ERROR; } w = (MPEG2VIDEO *)in; r = (LPVF_StreamInfo_Video)out; if(r == NULL){ return VF_ERROR; } if(r->dwSize != sizeof(VF_StreamInfo_Video)){ return VF_ERROR; } r->dwLengthL = (DWORD)(w->total & 0xffffffff); r->dwLengthH = (DWORD)(w->total >> 32); r->dwRate = w->rate; r->dwScale = w->scale; r->dwWidth = w->bgr_prm.width; r->dwHeight = w->bgr_prm.height; r->dwBitCount = 24; return VF_OK; } HRESULT _stdcall read_data(VF_FileHandle in, DWORD s, void *out) { MPEG2VIDEO *w; LPVF_ReadData_Video r; OUT_BUFFER_ELEMENT *top; OUT_BUFFER_ELEMENT *bottom; unsigned char *dst; __int64 frame; if(s != VF_STREAM_VIDEO){ return VF_ERROR; } w = (MPEG2VIDEO *)in; r = (LPVF_ReadData_Video)out; if(r == NULL){ return VF_ERROR; } if(r->dwSize != sizeof(VF_ReadData_Video)){ return VF_ERROR; } frame = r->dwFrameNumberL; frame += ((__int64)r->dwFrameNumberH) << 32; switch(w->config.field_mode){ case 0: /* keep original frame */ top = read_frame(w, frame); bottom = top; if(top == NULL){ __asm{emms}; return VF_ERROR; } break; case 1: /* top field first */ top = read_frame(w, frame); if(top == NULL){ __asm{emms}; return VF_ERROR; } bottom = NULL; if( (!top->prm.top_field_first) && (!top->prm.repeat_first_field) ){ bottom = read_frame(w, frame+1); } if(bottom == NULL){ bottom = top; } break; case 2: /* bottom field first */ bottom = read_frame(w, frame); if(bottom == NULL){ __asm{emms}; return VF_ERROR; } top = NULL; if( bottom->prm.top_field_first && (!bottom->prm.repeat_first_field) ){ top = read_frame(w, frame+1); } if(top == NULL){ top = bottom; } break; default: top = read_frame(w, frame); bottom = top; if(top == NULL){ __asm{emms}; return VF_ERROR; } } dst = (unsigned char *)r->lpData; w->bgr_prm.out_step = r->lPitch; w->yuv2bgr(top->data, bottom->data, dst, &(w->bgr_prm)); __asm{emms}; return VF_OK; } HRESULT _stdcall get_frame_type(VF_FileHandle in, LPVF_FrameType out) { __int64 frame; MPEG2VIDEO *w; int type; if(out == NULL){ return VF_ERROR; } if(out->dwSize != sizeof(VF_FrameType)){ return VF_ERROR; } w = (MPEG2VIDEO *)in; if(w == NULL){ return VF_ERROR; } frame = out->dwFrameNumberL; frame += ((__int64)(out->dwFrameNumberH)) << 32; type = get_picture_coding_type(w, frame); switch(type){ case 1: out->dwFrameType = VF_FRAME_TYPE_STARTABLE|VF_FRAME_TYPE_ENDABLE; break; case 2: out->dwFrameType = VF_FRAME_TYPE_ENDABLE; break; case 3: default: out->dwFrameType = VF_FRAME_TYPE_UNEDITABLE; } return VF_OK; } HRESULT _stdcall cut(VF_FileHandle in, LPVF_CutOption opt) { __int64 in_frame; __int64 out_frame; MPEG2VIDEO *w; MPEG2EDIT mpeg2edit; if(opt == NULL){ return VF_ERROR; } if(opt->dwSize != sizeof(VF_CutOption)){ return VF_ERROR; } w = (MPEG2VIDEO *)in; if(w == NULL){ return VF_ERROR; } if( !open_mpeg2edit(w->bitstream.path, &mpeg2edit) ){ return VF_ERROR; } if(opt->Callback != NULL){ mpeg2edit.callback = opt->Callback; } in_frame = opt->dwInPointH; in_frame <<= 32; in_frame += opt->dwInPointL; out_frame = opt->dwOutPointH; out_frame <<= 32; out_frame += opt->dwOutPointL; mpeg2edit.edit(&mpeg2edit, opt->lpOutputFileName, in_frame, out_frame); mpeg2edit.close(&mpeg2edit); return VF_OK; }