static HRESULT WINAPI AVICompressorIn_CheckMediaType(BasePin *base, const AM_MEDIA_TYPE *pmt) { AVICompressor *This = impl_from_BasePin(base); VIDEOINFOHEADER *videoinfo; HRESULT hres; DWORD res; TRACE("(%p)->(AM_MEDIA_TYPE(%p))\n", base, pmt); dump_AM_MEDIA_TYPE(pmt); if(!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) return S_FALSE; if(!IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) { FIXME("formattype %s unsupported\n", debugstr_guid(&pmt->formattype)); return S_FALSE; } hres = ensure_driver(This); if(hres != S_OK) return hres; videoinfo = (VIDEOINFOHEADER*)pmt->pbFormat; res = ICCompressQuery(This->hic, &videoinfo->bmiHeader, NULL); return res == ICERR_OK ? S_OK : S_FALSE; }
/* 对捕获的视频做编码、解码处理 */ void CMainFrame::OnVfwCodec() { // TODO: 在此添加命令处理程序代码 DWORD fsize; /* VCM initialization */ hic1 = ICOpen(mmioFOURCC('v','i','d','c'), mmioFOURCC('X','V','I','D'), ICMODE_COMPRESS); if (hic1 == 0) AfxMessageBox(_T("打开编码器失败!")); hic2 = ICOpen(mmioFOURCC('v','i','d','c'), mmioFOURCC('X','V','I','D'), ICMODE_DECOMPRESS); if (hic2 == 0) AfxMessageBox(_T("打开解码器失败!")); fsize = capGetVideoFormatSize(m_hWndCap); capGetVideoFormat(m_hWndCap, lpbiIn, fsize); InitAVIWriteOpt(); lpbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); lpbiOut->bmiHeader.biWidth = lpbiIn->bmiHeader.biWidth; lpbiOut->bmiHeader.biHeight = lpbiIn->bmiHeader.biHeight; lpbiOut->bmiHeader.biPlanes = 1; lpbiOut->bmiHeader.biBitCount = 24; lpbiOut->bmiHeader.biCompression = BI_RGB; lpbiOut->bmiHeader.biSizeImage = lpbiIn->bmiHeader.biWidth*lpbiIn->bmiHeader.biHeight*3; lpbiOut->bmiHeader.biXPelsPerMeter = 0; lpbiOut->bmiHeader.biYPelsPerMeter = 0; lpbiOut->bmiHeader.biClrUsed = 0; lpbiOut->bmiHeader.biClrImportant = 0; // get the format of the input video if (ICCompressGetFormat(hic1,lpbiIn,lpbiTmp)!=ICERR_OK) AfxMessageBox(_T("编码器不能读取输出格式!")); if (ICCompressQuery(hic1,lpbiIn,lpbiTmp) != ICERR_OK) AfxMessageBox(_T("不能处理编码器输入输出格式!")); // set the parameters of the CODEC pc.cbSize = sizeof(COMPVARS); //结构体大小 pc.dwFlags = ICMF_COMPVARS_VALID; pc.hic = hic1; //编码器句柄 pc.fccType = mmioFOURCC('v','i','d','c'); pc.fccHandler = mmioFOURCC('X','V','I','D'); pc.lpbiOut = lpbiTmp; //输出格式 pc.lKey = 100; //key帧频率 pc.lQ = 10000; //图像质量 if(!ICSeqCompressFrameStart(&pc, lpbiIn)) return; ICDecompressBegin(hic2,lpbiTmp,lpbiOut); m_vfwState = ENCDEC; }
static BOOL enum_compressors(HWND list, COMPVARS *pcv, BOOL enum_all) { UINT id, total = 0; ICINFO icinfo; id = 0; while (ICInfo(pcv->fccType, id, &icinfo)) { struct codec_info *ic; DWORD idx; HIC hic; id++; hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_COMPRESS); if (hic) { /* for unknown reason fccHandler reported by the driver * doesn't always work, use the one returned by ICInfo instead. */ DWORD fccHandler = icinfo.fccHandler; if (!enum_all && pcv->lpbiIn) { if (ICCompressQuery(hic, pcv->lpbiIn, NULL) != ICERR_OK) { TRACE("fccHandler %s doesn't support input DIB format %d\n", wine_dbgstr_fcc(icinfo.fccHandler), pcv->lpbiIn->bmiHeader.biCompression); ICClose(hic); continue; } } ICGetInfo(hic, &icinfo, sizeof(icinfo)); icinfo.fccHandler = fccHandler; idx = SendMessageW(list, CB_ADDSTRING, 0, (LPARAM)icinfo.szDescription); ic = HeapAlloc(GetProcessHeap(), 0, sizeof(struct codec_info)); ic->icinfo = icinfo; ic->hic = hic; SendMessageW(list, CB_SETITEMDATA, idx, (LPARAM)ic); } total++; } return total != 0; }
QMap<std::wstring, bool> AviCodecRestrictions::getUsableCodecs(const TDimension &resolution) { QMap<std::wstring, bool> codecs; HIC hic = 0; ICINFO icinfo; memset(&icinfo, 0, sizeof(ICINFO)); char descr[2048], name[2048]; DWORD fccType = 0; BITMAPINFO inFmt; memset(&inFmt, 0, sizeof(BITMAPINFO)); inFmt.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); inFmt.bmiHeader.biWidth = inFmt.bmiHeader.biHeight = 100; inFmt.bmiHeader.biPlanes = 1; inFmt.bmiHeader.biCompression = BI_RGB; int bpp; for (bpp = 32; (bpp >= 24); bpp -= 8) { //find the codec. inFmt.bmiHeader.biBitCount = bpp; for (int i = 0; ICInfo(fccType, i, &icinfo); i++) { hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_COMPRESS); ICGetInfo(hic, &icinfo, sizeof(ICINFO)); // Find out the compressor name WideCharToMultiByte(CP_ACP, 0, icinfo.szDescription, -1, descr, sizeof(descr), 0, 0); WideCharToMultiByte(CP_ACP, 0, icinfo.szName, -1, name, sizeof(name), 0, 0); std::wstring compressorName; compressorName = toWideString(std::string(name) + " '" + toString(bpp) + "' " + std::string(descr)); if (hic) { if (ICCompressQuery(hic, &inFmt, NULL) != ICERR_OK) { ICClose(hic); continue; // Skip this compressor if it can't handle the format. } codecs[compressorName] = canWork(hic, resolution, bpp); ICClose(hic); } } } return codecs; }
void CAviFile::GetCompressorList( CStringList &List, BITMAPINFO &SourceBitmapInfo ) { /////////////////////////////////////////////////////////// LPBITMAPINFOHEADER lpbi = 0; HIC hIC; ICINFO icinfo; int fccType = ICTYPE_VIDEO; //0 to get all installed codecs for (int i=0; ICInfo(fccType, i, &icinfo); i++) { hIC = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_QUERY); if (hIC) { //Find out the compressor name. ICGetInfo(hIC, &icinfo, sizeof(icinfo)); //Skip this compressor if it can't handle the format. if (fccType == ICTYPE_VIDEO ) { if( icinfo.dwFlags != 0 ) { if( ICCompressQuery( hIC, &SourceBitmapInfo, NULL ) == ICERR_OK ) { CString Temp = CString( icinfo.szDescription ); if( icinfo.fccHandler == 1129730893 ) Temp += " - Low Resolution"; Temp += " ("; Temp.Append( (const char*)&icinfo.fccHandler, 4 ); // Assuming little endian system. Temp += ")"; List.AddTail( Temp ); } } } //check here whether it is the driver you want ICClose(hIC); } } }
static int vfw_start_encoder(BITMAPINFOHEADER *input_bih, BITMAPINFOHEADER *output_bih){ HRESULT ret; int temp_len=output_bih->biSize; int i; ret = ICCompressGetFormat(encoder_hic, input_bih, output_bih); if(ret < 0){ unsigned char* temp=(unsigned char*)output_bih; mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressGetFormat failed: Error %d (0x%X)\n", (int)ret, (int)ret); for (i=0; i < temp_len; i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02x ", temp[i]); return 0; } mp_msg(MSGT_WIN32,MSGL_V,"ICCompressGetFormat OK\n"); if (temp_len > sizeof(BITMAPINFOHEADER)) { unsigned char* temp=(unsigned char*)output_bih; mp_msg(MSGT_WIN32, MSGL_V, "Extra info in o_bih (%d bytes)!\n", temp_len-sizeof(BITMAPINFOHEADER)); for(i=sizeof(output_bih);i<temp_len;i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02X ",temp[i]); } // if( mp_msg_test(MSGT_WIN32,MSGL_V) ) { printf("Starting compression:\n"); printf(" Input format:\n"); printf(" biSize %ld\n", input_bih->biSize); printf(" biWidth %ld\n", input_bih->biWidth); printf(" biHeight %ld\n", input_bih->biHeight); printf(" biPlanes %d\n", input_bih->biPlanes); printf(" biBitCount %d\n", input_bih->biBitCount); printf(" biCompression 0x%lx ('%.4s')\n", input_bih->biCompression, (char *)&input_bih->biCompression); printf(" biSizeImage %ld\n", input_bih->biSizeImage); printf(" Output format:\n"); printf(" biSize %ld\n", output_bih->biSize); printf(" biWidth %ld\n", output_bih->biWidth); printf(" biHeight %ld\n", output_bih->biHeight); printf(" biPlanes %d\n", output_bih->biPlanes); printf(" biBitCount %d\n", output_bih->biBitCount); printf(" biCompression 0x%lx ('%.4s')\n", output_bih->biCompression, (char *)&output_bih->biCompression); printf(" biSizeImage %ld\n", output_bih->biSizeImage); // } output_bih->biWidth=input_bih->biWidth; output_bih->biHeight=input_bih->biHeight; ret = ICCompressQuery(encoder_hic, input_bih, output_bih); if(ret){ mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressQuery failed: Error %d\n", (int)ret); return 0; } else mp_msg(MSGT_WIN32,MSGL_V,"ICCompressQuery OK\n"); ret = ICCompressBegin(encoder_hic, input_bih, output_bih); if(ret){ mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressBegin failed: Error %d\n", (int)ret); // return 0; } else mp_msg(MSGT_WIN32,MSGL_V,"ICCompressBegin OK\n"); mp_msg(MSGT_WIN32,MSGL_INFO," Output format after query/begin:\n"); mp_msg(MSGT_WIN32,MSGL_INFO," biSize %ld\n", output_bih->biSize); mp_msg(MSGT_WIN32,MSGL_INFO," biWidth %ld\n", output_bih->biWidth); mp_msg(MSGT_WIN32,MSGL_INFO," biHeight %ld\n", output_bih->biHeight); mp_msg(MSGT_WIN32,MSGL_INFO," biPlanes %d\n", output_bih->biPlanes); mp_msg(MSGT_WIN32,MSGL_INFO," biBitCount %d\n", output_bih->biBitCount); mp_msg(MSGT_WIN32,MSGL_INFO," biCompression 0x%lx ('%.4s')\n", output_bih->biCompression, (char *)&output_bih->biCompression); mp_msg(MSGT_WIN32,MSGL_INFO," biSizeImage %ld\n", output_bih->biSizeImage); encoder_buf_size=input_bih->biSizeImage; encoder_buf=malloc(encoder_buf_size); encoder_frameno=0; mp_msg(MSGT_WIN32,MSGL_V,"VIDEO CODEC Init OK!!! ;-)\n"); return 1; }
int AVInfo::GetCodecListSize(int width, int height) { if (m_plCodecList) { for (int i=0; i<m_codecListSize; ++i) delete m_plCodecList[i]; delete[] m_plCodecList; m_plCodecList = NULL; m_codecListSize = 0; } BITMAPINFO bmi; Make24BitRGB(&bmi.bmiHeader, width, height); ICINFO icInfo; ZeroMemory(&icInfo, sizeof ICINFO); icInfo.dwSize = sizeof ICINFO; int count = 0; std::vector<CODECINFO *> codecList; // The first codec is always uncompressed RGB // data. We can be sure this is the case here CODECINFO *pInfo = new CODECINFO; pInfo->fcc = MAKEFOURCC('D', 'I', 'B', ' '); pInfo->alternativeFcc = BI_RGB; pInfo->bHasAboutDialog = false; pInfo->bHasConfigureDialog = false; pInfo->bSupportsKeyframes = false; pInfo->bSupportsQuality = false; pInfo->nDefaultKeyframeRate = 1; pInfo->nDefaultQuality = 100; _tcscpy(pInfo->tszDescription, _T("DIB : <uncompressed>")); codecList.push_back(pInfo); while (ICInfo(ICTYPE_VIDEO, count, &icInfo)) { HIC hic = ICOpen(icInfo.fccType, icInfo.fccHandler, ICMODE_QUERY); if (hic) { ICINFO moreInfo; ZeroMemory(&moreInfo, sizeof ICINFO); moreInfo.dwSize = sizeof ICINFO; if (ICGetInfo(hic, &moreInfo, sizeof ICINFO) > 0) { // Ignore MSVC/CRAM if (moreInfo.fccHandler != 'CVSM' && moreInfo.fccHandler != 'MARC') { if (ICERR_OK == ICCompressQuery(hic, &bmi, NULL)) { // Ok, this codec seems to be ok; put that // into the list CODECINFO *pInfo = new CODECINFO; ZeroMemory(pInfo, sizeof CODECINFO); char szFcc[5]; if (moreInfo.fccHandler != BI_RGB) { szFcc[0] = (moreInfo.fccHandler & 0x000000ff); szFcc[1] = (moreInfo.fccHandler & 0x0000ff00) >> 8; szFcc[2] = (moreInfo.fccHandler & 0x00ff0000) >> 16; szFcc[3] = (moreInfo.fccHandler & 0xff000000) >> 24; szFcc[4] = 0; } else strcpy(szFcc, "DIB "); bool bIsReallyOk = true; // We know that IV50 has restrictions. if (moreInfo.fccHandler == '05vi' || moreInfo.fccHandler == '05VI') { if (width % 4 != 0 || height % 4 != 0) bIsReallyOk = false; } // The following code should normally check if the codec // is really able encode a certain BITMAPINFO type. But, // This will fail for the HuffYUV codec. Thus, we have to // assume that it might fail for other codecs, too. /* if (moreInfo.fccHandler == BI_RGB) { bIsReallyOk = true; } else { // The codec says that the input format is ok. // Let's try to create an output format and try // again. For some resolutions, e.g. Indeo Video 5 // now fails to compress the format. AM_MEDIA_TYPE mtTmp; ZeroMemory(&mtTmp, sizeof AM_MEDIA_TYPE); bool cool = CreateStreamFormat(moreInfo.fccHandler, width, height, &mtTmp); if (cool) { BITMAPINFO bmiOut; ZeroMemory(&bmiOut, sizeof BITMAPINFO); bmiOut.bmiHeader = ((VIDEOINFOHEADER *) mtTmp.pbFormat)->bmiHeader; DWORD dwOk = ICCompressBegin(hic, &bmi, &bmiOut); if (ICERR_OK == dwOk) { // It's really ok to use this codec. bIsReallyOk = true; ICCompressEnd(hic); } } FreeMediaType(mtTmp); } */ if (bIsReallyOk) { // Copy the name #ifndef _UNICODE _TCHAR tszDesc[128]; if (WideCharToMultiByte(CP_ACP, 0, moreInfo.szDescription, -1, tszDesc, 128, NULL, NULL) == 0) strcpy(tszDesc, "<unknown>"); sprintf(pInfo->tszDescription, "(%s): %s", szFcc, tszDesc); #else _stprintf(pInfo->tszDescription, _T("(%S): %s"), szFcc, moreInfo.szDescription); #endif pInfo->fcc = moreInfo.fccHandler; pInfo->alternativeFcc = icInfo.fccHandler; pInfo->bSupportsKeyframes = (moreInfo.dwFlags & VIDCF_TEMPORAL) > 0; pInfo->bSupportsQuality = (moreInfo.dwFlags & VIDCF_QUALITY) > 0; if (pInfo->bSupportsKeyframes) pInfo->nDefaultKeyframeRate = ICGetDefaultKeyFrameRate(hic); else pInfo->nDefaultKeyframeRate = 0; if (pInfo->bSupportsQuality) pInfo->nDefaultQuality = ICGetDefaultQuality(hic) / 100; else pInfo->nDefaultQuality = 0; pInfo->bHasConfigureDialog = ICQueryConfigure(hic) == TRUE ? true : false; pInfo->bHasAboutDialog = ICQueryAbout(hic) == TRUE ? true : false; codecList.push_back(pInfo); } } } }
int PGRAviFile::enumerateCompressors( int iRows, int iCols, int iBPP, ICINFO* picinfo, int iNumICInfo ) { // If picinfo is NULL, then we are retreiving the number of // usable compressors at the current settings so we can allocate // enough memory. bool bpicinfoNull = picinfo == NULL; ICINFO* picinfoTemp = new ICINFO[ 50 ]; HIC hic; BITMAPINFOHEADER bih; // Initialize the bitmap structure. bih.biSize = sizeof( BITMAPINFOHEADER ); bih.biPlanes = 1; bih.biCompression = BI_RGB; bih.biXPelsPerMeter = 100; bih.biYPelsPerMeter = 100; bih.biClrUsed = 0; bih.biClrImportant = 0; bih.biWidth = iCols; bih.biHeight = iRows; bih.biBitCount = (unsigned short)iBPP; bih.biSizeImage = bih.biWidth * bih.biHeight * ( bih.biBitCount / 8 ); int iNumCompressors = 0; bool bICInfoFull = false; for( int i = 0; ICInfo( 0, i, &picinfoTemp[ i ] ) && !bICInfoFull; i++ ) { // Open the compressor so we can query it. hic = ICOpen( picinfoTemp[ i ].fccType, picinfoTemp[ i ].fccHandler, ICMODE_QUERY ); if( hic ) { // Skip this compressor if it can't handle the format. if( ICCompressQuery( hic, &bih, 0 ) != ICERR_OK ) { ICClose( hic ); continue; } // Find out the compressor info. if( !bpicinfoNull ) { ICGetInfo( hic, &picinfo[ iNumCompressors ], sizeof( ICINFO ) ); } iNumCompressors++; if( !bpicinfoNull && (iNumCompressors == iNumICInfo) ) { bICInfoFull = true; } // Close the compressor. ICClose( hic ); } } delete [] picinfoTemp; return iNumCompressors; }
void AviCodecRestrictions::getRestrictions(const std::wstring &codecName, QString &restrictions) { restrictions.clear(); if (codecName == L"Uncompressed") { restrictions = QObject::tr("No restrictions for uncompressed avi video"); return; } //find the codec int bpp; HIC hic = getCodec(codecName, bpp); if (!hic) { restrictions = QObject::tr("It is not possible to communicate with the codec.\n Probably the codec cannot work correctly."); return; } BITMAPINFO bi; bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biXPelsPerMeter = 80; bi.bmiHeader.biYPelsPerMeter = 72; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; int lx = 640, ly = 480; bi.bmiHeader.biWidth = lx; bi.bmiHeader.biHeight = ly; // Loop until we can find a width, height, and depth that works! int i; // check the x lenght bi.bmiHeader.biBitCount = bpp; for (i = 3; i >= 0; i--) { bi.bmiHeader.biWidth = lx + (1 << i); bi.bmiHeader.biSizeImage = ((bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount + 31) / 32) * 4 * ly; if (ICERR_OK != ICCompressQuery(hic, &bi.bmiHeader, NULL)) break; } if (i >= 0) restrictions = QObject::tr("video width must be a multiple of %1").arg(QString::number(1 << (i + 1))); // check the y lenght bi.bmiHeader.biWidth = 640; for (i = 3; i >= 0; i--) { bi.bmiHeader.biHeight = ly + (1 << i); bi.bmiHeader.biSizeImage = ((lx * bi.bmiHeader.biBitCount + 31) / 32) * 4 * bi.bmiHeader.biHeight; if (ICERR_OK != ICCompressQuery(hic, &bi.bmiHeader, NULL)) break; } if (i >= 0) restrictions = restrictions + "\n" + QObject::tr("video lenght must be a multiple of %1").arg(QString::number(1 << (i + 1))); ICClose(hic); if (restrictions.isEmpty()) restrictions = QObject::tr("No restrictions for this codec"); else restrictions.prepend(QObject::tr("Resolution restrictions:") + "\n"); }