Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "avicodecrestrictions.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include <windows.h></windows.h>
Toshihiro Shimizu 890ddd
#include <vfw.h></vfw.h>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
HIC getCodec(const wstring &codecName, int &bpp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	HIC hic = 0;
Toshihiro Shimizu 890ddd
	ICINFO icinfo;
Toshihiro Shimizu 890ddd
	memset(&icinfo, 0, sizeof(ICINFO));
Toshihiro Shimizu 890ddd
	bool found = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	char descr[2048], name[2048];
Toshihiro Shimizu 890ddd
	DWORD fccType = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	BITMAPINFO inFmt;
Toshihiro Shimizu 890ddd
	memset(&inFmt, 0, sizeof(BITMAPINFO));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	inFmt.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Toshihiro Shimizu 890ddd
	inFmt.bmiHeader.biWidth = inFmt.bmiHeader.biHeight = 100;
Toshihiro Shimizu 890ddd
	inFmt.bmiHeader.biPlanes = 1;
Toshihiro Shimizu 890ddd
	inFmt.bmiHeader.biCompression = BI_RGB;
Toshihiro Shimizu 890ddd
	for (bpp = 32; (bpp >= 24) && !found; bpp -= 8) {
Toshihiro Shimizu 890ddd
		//find the codec.
Toshihiro Shimizu 890ddd
		inFmt.bmiHeader.biBitCount = bpp;
Toshihiro Shimizu 890ddd
		for (int i = 0; ICInfo(fccType, i, &icinfo); i++) {
Toshihiro Shimizu 890ddd
			hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_COMPRESS);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			ICGetInfo(hic, &icinfo, sizeof(ICINFO)); // Find out the compressor name
Toshihiro Shimizu 890ddd
			WideCharToMultiByte(CP_ACP, 0, icinfo.szDescription, -1, descr, sizeof(descr), 0, 0);
Toshihiro Shimizu 890ddd
			WideCharToMultiByte(CP_ACP, 0, icinfo.szName, -1, name, sizeof(name), 0, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			string compressorName;
Toshihiro Shimizu 890ddd
			compressorName = string(name) + " '" + toString(bpp) + "' " + string(descr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (hic) {
Toshihiro Shimizu 890ddd
				if (ICCompressQuery(hic, &inFmt, NULL) != ICERR_OK) {
Toshihiro Shimizu 890ddd
					ICClose(hic);
Toshihiro Shimizu 890ddd
					continue; // Skip this compressor if it can't handle the format.
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				if (toWideString(compressorName) == codecName) {
Toshihiro Shimizu 890ddd
					found = true;
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				ICClose(hic);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (found)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return hic;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool canWork(const HIC &hic, const TDimension &resolution, int bpp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int lx = resolution.lx, ly = resolution.ly;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	BITMAPINFO bi;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biPlanes = 1;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biCompression = BI_RGB;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biXPelsPerMeter = 80;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biYPelsPerMeter = 72;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biClrUsed = 0;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biClrImportant = 0;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biBitCount = bpp;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biWidth = lx;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biHeight = ly;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return ICERR_OK == ICCompressQuery(hic, &bi.bmiHeader, NULL);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void AviCodecRestrictions::getRestrictions(const wstring &codecName, QString &restrictions)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	restrictions.clear();
Toshihiro Shimizu 890ddd
	if (codecName == L"Uncompressed") {
Toshihiro Shimizu 890ddd
		restrictions = QObject::tr("No restrictions for uncompressed avi video");
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	//find the codec
Toshihiro Shimizu 890ddd
	int bpp;
Toshihiro Shimizu 890ddd
	HIC hic = getCodec(codecName, bpp);
Toshihiro Shimizu 890ddd
	if (!hic) {
Toshihiro Shimizu 890ddd
		restrictions = QObject::tr("It is not possible to communicate with the codec.\n Probably the codec cannot work correctly.");
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	BITMAPINFO bi;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biPlanes = 1;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biCompression = BI_RGB;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biXPelsPerMeter = 80;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biYPelsPerMeter = 72;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biClrUsed = 0;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biClrImportant = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int lx = 640, ly = 480;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biWidth = lx;
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biHeight = ly;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Loop until we can find a width, height, and depth that works!
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// check the x lenght
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biBitCount = bpp;
Toshihiro Shimizu 890ddd
	for (i = 3; i >= 0; i--) {
Toshihiro Shimizu 890ddd
		bi.bmiHeader.biWidth = lx + (1 << i);
Toshihiro Shimizu 890ddd
		bi.bmiHeader.biSizeImage = ((bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount + 31) / 32) * 4 * ly;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (ICERR_OK != ICCompressQuery(hic, &bi.bmiHeader, NULL))
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (i >= 0)
Toshihiro Shimizu 890ddd
		restrictions = QObject::tr("video width must be a multiple of %1").arg(QString::number(1 << (i + 1)));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// check the y lenght
Toshihiro Shimizu 890ddd
	bi.bmiHeader.biWidth = 640;
Toshihiro Shimizu 890ddd
	for (i = 3; i >= 0; i--) {
Toshihiro Shimizu 890ddd
		bi.bmiHeader.biHeight = ly + (1 << i);
Toshihiro Shimizu 890ddd
		bi.bmiHeader.biSizeImage = ((lx * bi.bmiHeader.biBitCount + 31) / 32) * 4 * bi.bmiHeader.biHeight;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (ICERR_OK != ICCompressQuery(hic, &bi.bmiHeader, NULL))
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (i >= 0)
Toshihiro Shimizu 890ddd
		restrictions = restrictions + "\n" + QObject::tr("video lenght must be a multiple of %1").arg(QString::number(1 << (i + 1)));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ICClose(hic);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (restrictions.isEmpty())
Toshihiro Shimizu 890ddd
		restrictions = QObject::tr("No restrictions for this codec");
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		restrictions.prepend(QObject::tr("Resolution restrictions:") + "\n");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool AviCodecRestrictions::canWriteMovie(const wstring &codecName, const TDimension &resolution)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (codecName == L"Uncompressed") {
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	//find the codec
Toshihiro Shimizu 890ddd
	int bpp;
Toshihiro Shimizu 890ddd
	HIC hic = getCodec(codecName, bpp);
Toshihiro Shimizu 890ddd
	if (!hic)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool test = canWork(hic, resolution, bpp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ICClose(hic);
Toshihiro Shimizu 890ddd
	return test;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool AviCodecRestrictions::canBeConfigured(const wstring &codecName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (codecName == L"Uncompressed")
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//find the codec
Toshihiro Shimizu 890ddd
	int bpp;
Toshihiro Shimizu 890ddd
	HIC hic = getCodec(codecName, bpp);
Toshihiro Shimizu 890ddd
	if (!hic)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool test = ICQueryConfigure(hic);
Toshihiro Shimizu 890ddd
	ICClose(hic);
Toshihiro Shimizu 890ddd
	return test;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void AviCodecRestrictions::openConfiguration(const wstring &codecName, void *winId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (codecName == L"Uncompressed")
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//find the codec
Toshihiro Shimizu 890ddd
	int bpp;
Toshihiro Shimizu 890ddd
	HIC hic = getCodec(codecName, bpp);
Toshihiro Shimizu 890ddd
	if (!hic)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ICConfigure(hic, winId);
Toshihiro Shimizu 890ddd
	ICClose(hic);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QMap<wstring, bool=""> AviCodecRestrictions::getUsableCodecs(const TDimension &resolution)</wstring,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMap<wstring, bool=""> codecs;</wstring,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	HIC hic = 0;
Toshihiro Shimizu 890ddd
	ICINFO icinfo;
Toshihiro Shimizu 890ddd
	memset(&icinfo, 0, sizeof(ICINFO));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	char descr[2048], name[2048];
Toshihiro Shimizu 890ddd
	DWORD fccType = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	BITMAPINFO inFmt;
Toshihiro Shimizu 890ddd
	memset(&inFmt, 0, sizeof(BITMAPINFO));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	inFmt.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Toshihiro Shimizu 890ddd
	inFmt.bmiHeader.biWidth = inFmt.bmiHeader.biHeight = 100;
Toshihiro Shimizu 890ddd
	inFmt.bmiHeader.biPlanes = 1;
Toshihiro Shimizu 890ddd
	inFmt.bmiHeader.biCompression = BI_RGB;
Toshihiro Shimizu 890ddd
	int bpp;
Toshihiro Shimizu 890ddd
	for (bpp = 32; (bpp >= 24); bpp -= 8) {
Toshihiro Shimizu 890ddd
		//find the codec.
Toshihiro Shimizu 890ddd
		inFmt.bmiHeader.biBitCount = bpp;
Toshihiro Shimizu 890ddd
		for (int i = 0; ICInfo(fccType, i, &icinfo); i++) {
Toshihiro Shimizu 890ddd
			hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_COMPRESS);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			ICGetInfo(hic, &icinfo, sizeof(ICINFO)); // Find out the compressor name
Toshihiro Shimizu 890ddd
			WideCharToMultiByte(CP_ACP, 0, icinfo.szDescription, -1, descr, sizeof(descr), 0, 0);
Toshihiro Shimizu 890ddd
			WideCharToMultiByte(CP_ACP, 0, icinfo.szName, -1, name, sizeof(name), 0, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			wstring compressorName;
Toshihiro Shimizu 890ddd
			compressorName = toWideString(string(name) + " '" + toString(bpp) + "' " + string(descr));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (hic) {
Toshihiro Shimizu 890ddd
				if (ICCompressQuery(hic, &inFmt, NULL) != ICERR_OK) {
Toshihiro Shimizu 890ddd
					ICClose(hic);
Toshihiro Shimizu 890ddd
					continue; // Skip this compressor if it can't handle the format.
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				codecs[compressorName] = canWork(hic, resolution, bpp);
Toshihiro Shimizu 890ddd
				ICClose(hic);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return codecs;
Toshihiro Shimizu 890ddd
}