// to set/get/query special features/parameters static int control(sh_video_t *sh,int cmd,void* arg,...){ vd_vfw_ctx *priv = sh->context; switch(cmd){ case VDCTRL_QUERY_MAX_PP_LEVEL: return 9; case VDCTRL_SET_PP_LEVEL: vfw_set_postproc(sh,10*(*((int*)arg))); return CONTROL_OK; // FIXME: make this optional... case VDCTRL_QUERY_FORMAT: { HRESULT ret; if(!(sh->codec->outflags[sh->outfmtidx]&CODECS_FLAG_QUERY)) return CONTROL_UNKNOWN; // do not query! set_csp(priv->o_bih,*((int*)arg)); #ifdef BUILD_VFWEX ret = ICDecompressQueryEx(priv->handle, sh->bih, priv->o_bih); #else ret = ICDecompressQuery(priv->handle, sh->bih, priv->o_bih); #endif if (ret) { mp_msg(MSGT_WIN32, MSGL_DBG2, "ICDecompressQuery failed:: Error %d\n", (int)ret); return CONTROL_FALSE; } return CONTROL_TRUE; } } return CONTROL_UNKNOWN; }
/*********************************************************************** * ICGetDisplayFormat [MSVFW32.@] */ HIC VFWAPI ICGetDisplayFormat( HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut, INT depth,INT dx,INT dy) { HIC tmphic = hic; TRACE("(%p,%p,%p,%d,%d,%d)!\n",hic,lpbiIn,lpbiOut,depth,dx,dy); if (!tmphic) { tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS); if (!tmphic) return tmphic; } if ((dy == lpbiIn->biHeight) && (dx == lpbiIn->biWidth)) dy = dx = 0; /* no resize needed */ /* Can we decompress it ? */ if (ICDecompressQuery(tmphic,lpbiIn,NULL) != 0) goto errout; /* no, sorry */ ICSendMessage(tmphic, ICM_DECOMPRESS_GET_FORMAT, (DWORD_PTR)lpbiIn, (DWORD_PTR)lpbiOut); if (lpbiOut->biCompression != 0) { FIXME("Ooch, how come decompressor outputs compressed data (%d)??\n", lpbiOut->biCompression); } if (lpbiOut->biSize < sizeof(*lpbiOut)) { FIXME("Ooch, size of output BIH is too small (%d)\n", lpbiOut->biSize); lpbiOut->biSize = sizeof(*lpbiOut); } if (!depth) { HDC hdc; hdc = GetDC(0); depth = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES); ReleaseDC(0,hdc); if (depth==15) depth = 16; if (depth<8) depth = 8; } if (lpbiIn->biBitCount == 8) depth = 8; TRACE("=> %p\n", tmphic); return tmphic; errout: if (hic!=tmphic) ICClose(tmphic); TRACE("=> 0\n"); return 0; }
static HRESULT WINAPI AVIDec_SetMediaType(TransformFilter *tf, PIN_DIRECTION dir, const AM_MEDIA_TYPE * pmt) { AVIDecImpl* This = (AVIDecImpl*)tf; HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED; TRACE("(%p)->(%p)\n", This, pmt); if (dir != PINDIR_INPUT) return S_OK; /* Check root (GUID w/o FOURCC) */ if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) && (!memcmp(((const char *)&pmt->subtype)+4, ((const char *)&MEDIATYPE_Video)+4, sizeof(GUID)-4))) { VIDEOINFOHEADER *format1 = (VIDEOINFOHEADER *)pmt->pbFormat; VIDEOINFOHEADER2 *format2 = (VIDEOINFOHEADER2 *)pmt->pbFormat; BITMAPINFOHEADER *bmi; if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) bmi = &format1->bmiHeader; else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) bmi = &format2->bmiHeader; else goto failed; TRACE("Fourcc: %s\n", debugstr_an((const char *)&pmt->subtype.Data1, 4)); This->hvid = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, bmi, NULL, ICMODE_DECOMPRESS); if (This->hvid) { AM_MEDIA_TYPE* outpmt = &This->tf.pmt; const CLSID* outsubtype; DWORD bih_size; DWORD output_depth = bmi->biBitCount; DWORD result; FreeMediaType(outpmt); switch(bmi->biBitCount) { case 32: outsubtype = &MEDIASUBTYPE_RGB32; break; case 24: outsubtype = &MEDIASUBTYPE_RGB24; break; case 16: outsubtype = &MEDIASUBTYPE_RGB565; break; case 8: outsubtype = &MEDIASUBTYPE_RGB8; break; default: WARN("Non standard input depth %d, forced output depth to 32\n", bmi->biBitCount); outsubtype = &MEDIASUBTYPE_RGB32; output_depth = 32; break; } /* Copy bitmap header from media type to 1 for input and 1 for output */ bih_size = bmi->biSize + bmi->biClrUsed * 4; This->pBihIn = CoTaskMemAlloc(bih_size); if (!This->pBihIn) { hr = E_OUTOFMEMORY; goto failed; } This->pBihOut = CoTaskMemAlloc(bih_size); if (!This->pBihOut) { hr = E_OUTOFMEMORY; goto failed; } memcpy(This->pBihIn, bmi, bih_size); memcpy(This->pBihOut, bmi, bih_size); /* Update output format as non compressed bitmap */ This->pBihOut->biCompression = 0; This->pBihOut->biBitCount = output_depth; This->pBihOut->biSizeImage = This->pBihOut->biWidth * This->pBihOut->biHeight * This->pBihOut->biBitCount / 8; TRACE("Size: %u\n", This->pBihIn->biSize); result = ICDecompressQuery(This->hvid, This->pBihIn, This->pBihOut); if (result != ICERR_OK) { ERR("Unable to found a suitable output format (%d)\n", result); goto failed; } /* Update output media type */ CopyMediaType(outpmt, pmt); outpmt->subtype = *outsubtype; if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) memcpy(&(((VIDEOINFOHEADER *)outpmt->pbFormat)->bmiHeader), This->pBihOut, This->pBihOut->biSize); else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) memcpy(&(((VIDEOINFOHEADER2 *)outpmt->pbFormat)->bmiHeader), This->pBihOut, This->pBihOut->biSize); else assert(0); TRACE("Connection accepted\n"); return S_OK; } TRACE("Unable to find a suitable VFW decompressor\n"); } failed: TRACE("Connection refused\n"); return hr; }
// init driver static int init(sh_video_t *sh){ HRESULT ret; // unsigned int outfmt=sh->codec->outfmt[sh->outfmtidx]; int i, o_bih_len; vd_vfw_ctx *priv; const char *dll = codec_idx2str(sh->codec->dll_idx); /* Hack for VSSH codec: new dll can't decode old files * In my samples old files have no extradata, so use that info * to decide what dll should be used (here and in vd_dshow). */ if (!strcmp(dll, "vssh264.dll") && (sh->bih->biSize > 40)) return 0; priv = malloc(sizeof(vd_vfw_ctx)); if (!priv) return 0; memset(priv, 0, sizeof(vd_vfw_ctx)); sh->context = priv; mp_msg(MSGT_WIN32,MSGL_V,"======= Win32 (VFW) VIDEO Codec init =======\n"); // win32_codec_name = dll; // sh->hic = ICOpen( 0x63646976, sh->bih->biCompression, ICMODE_FASTDECOMPRESS); // priv->handle = ICOpen( 0x63646976, sh->bih->biCompression, ICMODE_DECOMPRESS); priv->handle = ICOpen( (long)(dll), sh->bih->biCompression, ICMODE_DECOMPRESS); if(!priv->handle){ mp_msg(MSGT_WIN32,MSGL_ERR,"ICOpen failed! unknown codec / wrong parameters?\n"); return 0; } // sh->bih->biBitCount=32; o_bih_len = ICDecompressGetFormatSize(priv->handle, sh->bih); if(o_bih_len < sizeof(BITMAPINFOHEADER)){ mp_msg(MSGT_WIN32,MSGL_ERR,"ICDecompressGetFormatSize returned a bogus value: %d\n", o_bih_len); return 0; } priv->o_bih = malloc(o_bih_len); memset(priv->o_bih, 0, o_bih_len); mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetFormatSize ret: %d\n", o_bih_len); ret = ICDecompressGetFormat(priv->handle, sh->bih, priv->o_bih); if(ret < 0){ mp_msg(MSGT_WIN32,MSGL_ERR,"ICDecompressGetFormat failed: Error %d\n", (int)ret); for (i=0; i < o_bih_len; i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02x ", priv->o_bih[i]); return 0; } mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetFormat OK\n"); #if 0 // workaround for pegasus MJPEG: if(!sh_video->o_bih.biWidth) sh_video->o_bih.biWidth=sh_video->bih->biWidth; if(!sh_video->o_bih.biHeight) sh_video->o_bih.biHeight=sh_video->bih->biHeight; if(!sh_video->o_bih.biPlanes) sh_video->o_bih.biPlanes=sh_video->bih->biPlanes; #endif // ok let libvo and vd core to handshake and decide the optimal csp: if(!mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YUY2)) return 0; if (!(sh->codec->outflags[sh->outfmtidx]&CODECS_FLAG_FLIP)) { priv->o_bih->biHeight=-sh->bih->biHeight; // flip image! } // ok, let's set the choosen colorspace: set_csp(priv->o_bih,sh->codec->outfmt[sh->outfmtidx]); // fake it to RGB for broken DLLs (divx3) if(sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_YUVHACK) priv->o_bih->biCompression = 0; // sanity check: #ifdef BUILD_VFWEX ret = ICDecompressQueryEx(priv->handle, sh->bih, priv->o_bih); #else ret = ICDecompressQuery(priv->handle, sh->bih, priv->o_bih); #endif if (ret) { mp_msg(MSGT_WIN32,MSGL_WARN,"ICDecompressQuery failed: Error %d\n", (int)ret); // return 0; } else mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressQuery OK\n"); #ifdef BUILD_VFWEX ret = ICDecompressBeginEx(priv->handle, sh->bih, priv->o_bih); #else ret = ICDecompressBegin(priv->handle, sh->bih, priv->o_bih); #endif if (ret) { mp_msg(MSGT_WIN32,MSGL_WARN,"ICDecompressBegin failed: Error %d\n", (int)ret); // return 0; } // for broken codecs set it again: if(sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_YUVHACK) set_csp(priv->o_bih,sh->codec->outfmt[sh->outfmtidx]); mp_msg(MSGT_WIN32, MSGL_V, "Input format:\n"); if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh->bih,MSGL_V); mp_msg(MSGT_WIN32, MSGL_V, "Output format:\n"); if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(priv->o_bih,MSGL_V); // set postprocessing level in xvid/divx4 .dll ICSendMessage(priv->handle, ICM_USER+80, (long)(&divx_quality), 0); // don't do this palette mess always, it makes div3 dll crashing... if(sh->codec->outfmt[sh->outfmtidx]==IMGFMT_BGR8){ if(ICDecompressGetPalette(priv->handle, sh->bih, priv->o_bih)){ priv->palette = (unsigned char*)(priv->o_bih+1); mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetPalette OK\n"); } else { if(sh->bih->biSize>=40+4*4) priv->palette = (unsigned char*)(sh->bih+1); } } mp_msg(MSGT_DECVIDEO,MSGL_V,"INFO: Win32 video codec init OK!\n"); return 1; }
static void test_Locate(void) { static BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER),32,8, 1,8, BI_RLE8, 0,100000,100000, 0,0}; static BITMAPINFOHEADER bo = {sizeof(BITMAPINFOHEADER),32,8, 1,8, BI_RGB, 0,100000,100000, 0,0}; HIC h; DWORD err; /* Oddly, MSDN documents that ICLocate takes BITMAPINFOHEADER * pointers, while ICDecompressQuery takes the larger * BITMAPINFO. Probably it's all the same as long as the * variable length color quads are present when they are * needed. */ h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h != 0, "RLE8->RGB failed\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biHeight = - bo.biHeight; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h == 0, "RLE8->RGB height<0 succeeded\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biHeight = - bo.biHeight; bi.biCompression = mmioFOURCC('c','v','i','d'); /* Cinepak */ h = ICOpen(ICTYPE_VIDEO, mmioFOURCC('c','v','i','d'), ICMODE_DECOMPRESS); if (h == 0) win_skip("Cinepak/ICCVID codec not found\n"); else { bo.biBitCount = bi.biBitCount = 32; err = ICDecompressQuery(h, &bi, &bo); ok(err == ICERR_OK, "Query cvid->RGB32: %d\n", err); err = ICDecompressQuery(h, &bi, NULL); ok(err == ICERR_OK, "Query cvid 32: %d\n", err); bo.biHeight = -bo.biHeight; err = ICDecompressQuery(h, &bi, &bo); ok(err == ICERR_OK, "Query cvid->RGB32 height<0: %d\n", err); bo.biHeight = -bo.biHeight; ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biBitCount = bi.biBitCount = 8; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); todo_wine ok(h != 0, "cvid->RGB8 failed\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biHeight = - bo.biHeight; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); todo_wine ok(h != 0, "cvid->RGB8 height<0 failed\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biHeight = - bo.biHeight; bo.biBitCount = bi.biBitCount = 16; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h != 0, "cvid->RGB16 failed\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biHeight = - bo.biHeight; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h != 0, "cvid->RGB16 height<0 failed\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biHeight = - bo.biHeight; bo.biBitCount = bi.biBitCount = 32; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h != 0, "cvid->RGB32 failed\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biHeight = - bo.biHeight; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h != 0, "cvid->RGB32 height<0 failed\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biHeight = - bo.biHeight; bi.biCompression = mmioFOURCC('C','V','I','D'); /* Unlike ICOpen, upper case fails with ICLocate. */ h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h == 0, "CVID->RGB32 upper case succeeded\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); } bi.biCompression = mmioFOURCC('M','S','V','C'); /* MS Video 1 */ bo.biBitCount = bi.biBitCount = 16; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h != 0, "MSVC->RGB16 failed\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biHeight = - bo.biHeight; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); todo_wine ok(h != 0, "MSVC->RGB16 height<0 failed\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biHeight = - bo.biHeight; bo.biHeight--; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h == 0, "MSVC->RGB16 height too small succeeded\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bo.biHeight++; /* ICLocate wants upper case MSVC */ bi.biCompression = mmioFOURCC('m','s','v','c'); h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h == 0, "msvc->RGB16 succeeded\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bi.biCompression = mmioFOURCC('M','S','V','C'); h = ICOpen(ICTYPE_VIDEO, mmioFOURCC('M','S','V','C'), ICMODE_DECOMPRESS); ok(h != 0, "No MSVC codec installed!?\n"); if (h != 0) { err = ICDecompressQuery(h, &bi, &bo); ok(err == ICERR_OK, "Query MSVC->RGB16: %d\n", err); err = ICDecompressQuery(h, &bi, NULL); ok(err == ICERR_OK, "Query MSVC 16: %d\n", err); bo.biHeight = -bo.biHeight; err = ICDecompressQuery(h, &bi, &bo); todo_wine ok(err == ICERR_OK, "Query MSVC->RGB16 height<0: %d\n", err); bo.biHeight = -bo.biHeight; bi.biCompression = mmioFOURCC('m','s','v','c'); err = ICDecompressQuery(h, &bi, &bo); ok(err == ICERR_BADFORMAT, "Query msvc->RGB16: %d\n", err); ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); } bi.biCompression = BI_RGB; bo.biBitCount = bi.biBitCount = 8; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h != 0, "RGB8->RGB identity failed\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); bi.biCompression = BI_RLE8; h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); ok(h != 0, "RLE8->RGB again failed\n"); if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); }
/*********************************************************************** * ICGetDisplayFormat [MSVFW32.@] */ HIC VFWAPI ICGetDisplayFormat(HIC hic, BITMAPINFOHEADER *in, BITMAPINFOHEADER *out, int depth, int width, int height) { HIC tmphic = hic; TRACE("(%p, %p, %p, %d, %d, %d)\n", hic, in, out, depth, width, height); if (!tmphic) { tmphic = ICLocate(ICTYPE_VIDEO, 0, in, NULL, ICMODE_DECOMPRESS); if (!tmphic) return NULL; } if (ICDecompressQuery(tmphic, in, NULL)) goto err; if (width <= 0 || height <= 0) { width = in->biWidth; height = in->biHeight; } if (!depth) depth = 32; *out = *in; out->biSize = sizeof(*out); out->biWidth = width; out->biHeight = height; out->biCompression = BI_RGB; out->biSizeImage = get_size_image(width, height, depth); /* first try the given depth */ out->biBitCount = depth; out->biSizeImage = get_size_image(width, height, out->biBitCount); if (!ICDecompressQuery(tmphic, in, out)) { if (depth == 8) ICDecompressGetPalette(tmphic, in, out); return tmphic; } /* then try 16, both with BI_RGB and BI_BITFIELDS */ if (depth <= 16) { out->biBitCount = 16; out->biSizeImage = get_size_image(width, height, out->biBitCount); if (!ICDecompressQuery(tmphic, in, out)) return tmphic; out->biCompression = BI_BITFIELDS; if (!ICDecompressQuery(tmphic, in, out)) return tmphic; out->biCompression = BI_RGB; } /* then try 24 */ if (depth <= 24) { out->biBitCount = 24; out->biSizeImage = get_size_image(width, height, out->biBitCount); if (!ICDecompressQuery(tmphic, in, out)) return tmphic; } /* then try 32 */ if (depth <= 32) { out->biBitCount = 32; out->biSizeImage = get_size_image(width, height, out->biBitCount); if (!ICDecompressQuery(tmphic, in, out)) return tmphic; } /* as a last resort, try 32 bpp with the original width and height */ out->biWidth = in->biWidth; out->biHeight = in->biHeight; out->biBitCount = 32; out->biSizeImage = get_size_image(out->biWidth, out->biHeight, out->biBitCount); if (!ICDecompressQuery(tmphic, in, out)) return tmphic; /* finally, ask the compressor for its default output format */ if (!ICSendMessage(tmphic, ICM_DECOMPRESS_GET_FORMAT, (DWORD_PTR)in, (DWORD_PTR)out)) return tmphic; err: if (hic != tmphic) ICClose(tmphic); return NULL; }