|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#if _MSC_VER >= 1400
|
|
Toshihiro Shimizu |
890ddd |
#define _CRT_SECURE_NO_DEPRECATE 1
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define _WIN32_DCOM
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define _WIN32_WINNT 0x0500
|
|
Toshihiro Shimizu |
890ddd |
#include "tsystem.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <windows.h></windows.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <objbase.h></objbase.h>
|
|
Toshihiro Shimizu |
890ddd |
#include "texception.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tiio_avi.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tsound.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tconvert.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "timageinfo.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trasterimage.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define DibPtr(lpbi) (LPBYTE)(DibColors(lpbi) + (UINT)(lpbi)->biClrUsed)
|
|
Toshihiro Shimizu |
890ddd |
#define DibColors(lpbi) ((LPRGBQUAD)((LPBYTE)(lpbi) + (int)(lpbi)->biSize))
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void WideChar2Char(LPCWSTR wideCharStr, char *str, int strBuffSize) {
|
|
Shinya Kitaoka |
120a6e |
WideCharToMultiByte(CP_ACP, 0, wideCharStr, -1, str, strBuffSize, 0, 0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string buildAVIExceptionString(int rc) {
|
|
Shinya Kitaoka |
120a6e |
switch (rc) {
|
|
Shinya Kitaoka |
120a6e |
case AVIERR_BADFORMAT:
|
|
Shinya Kitaoka |
120a6e |
return "The file couldn't be read, indicating a corrupt file or an "
|
|
Shinya Kitaoka |
120a6e |
"unrecognized format.";
|
|
Shinya Kitaoka |
120a6e |
case AVIERR_MEMORY:
|
|
Shinya Kitaoka |
120a6e |
return "The file could not be opened because of insufficient memory.";
|
|
Shinya Kitaoka |
120a6e |
case AVIERR_FILEREAD:
|
|
Shinya Kitaoka |
120a6e |
return "A disk error occurred while reading the file.";
|
|
Shinya Kitaoka |
120a6e |
case AVIERR_FILEOPEN:
|
|
Shinya Kitaoka |
120a6e |
return "A disk error occurred while opening the file.";
|
|
Shinya Kitaoka |
120a6e |
case REGDB_E_CLASSNOTREG:
|
|
Shinya Kitaoka |
120a6e |
return "According to the registry, the type of file specified in "
|
|
Shinya Kitaoka |
120a6e |
"m_aviFileOpen does not have a handler to process it.";
|
|
Shinya Kitaoka |
120a6e |
case AVIERR_UNSUPPORTED:
|
|
Shinya Kitaoka |
120a6e |
return "Format unsupported";
|
|
Shinya Kitaoka |
120a6e |
case AVIERR_INTERNAL:
|
|
Shinya Kitaoka |
120a6e |
return "Internal error";
|
|
Shinya Kitaoka |
120a6e |
case AVIERR_NODATA:
|
|
Shinya Kitaoka |
120a6e |
return "No data";
|
|
Shinya Kitaoka |
120a6e |
default:
|
|
Shinya Kitaoka |
120a6e |
return "Unable to create avi.";
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string SplitFourCC(DWORD fcc) {
|
|
Shinya Kitaoka |
120a6e |
std::string s;
|
|
Shinya Kitaoka |
120a6e |
s += (char((fcc & 0x000000ff) >> 0));
|
|
Shinya Kitaoka |
120a6e |
s += (char((fcc & 0x0000ff00) >> 8));
|
|
Shinya Kitaoka |
120a6e |
s += (char((fcc & 0x00ff0000) >> 16));
|
|
Shinya Kitaoka |
120a6e |
s += (char((fcc & 0xff000000) >> 24));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return s;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRaster32P DIBToRaster(UCHAR *pDIBImage, int width, int height) {
|
|
Shinya Kitaoka |
120a6e |
assert(pDIBImage);
|
|
Shinya Kitaoka |
120a6e |
if (!pDIBImage) return TRaster32P();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// BITMAPINFOHEADER *bihdr = reinterpret_cast<bitmapinfoheader *="">(pDIBImage);</bitmapinfoheader>
|
|
Shinya Kitaoka |
120a6e |
UCHAR *rawData = pDIBImage;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRaster32P rasOut32(width, height);
|
|
Shinya Kitaoka |
120a6e |
// ULONG imgSize = bihdr->biSizeImage;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int ly = rasOut32->getLy();
|
|
Shinya Kitaoka |
120a6e |
int n = 0;
|
|
Shinya Kitaoka |
120a6e |
rasOut32->lock();
|
|
Shinya Kitaoka |
120a6e |
while (n < ly) {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *pix = rasOut32->pixels(n);
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *endPix = pix + rasOut32->getLx();
|
|
Shinya Kitaoka |
120a6e |
while (pix < endPix) {
|
|
Shinya Kitaoka |
120a6e |
pix->b = *rawData;
|
|
Shinya Kitaoka |
120a6e |
rawData++;
|
|
Shinya Kitaoka |
120a6e |
pix->g = *rawData;
|
|
Shinya Kitaoka |
120a6e |
rawData++;
|
|
Shinya Kitaoka |
120a6e |
pix->r = *rawData;
|
|
Shinya Kitaoka |
120a6e |
rawData++;
|
|
Shinya Kitaoka |
120a6e |
pix->m = 255;
|
|
Shinya Kitaoka |
120a6e |
++pix;
|
|
Shinya Kitaoka |
120a6e |
// rawData += 3;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
++n;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
rasOut32->unlock();
|
|
Shinya Kitaoka |
120a6e |
return rasOut32;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int getPrevKeyFrame(PAVISTREAM videoStream, int index) {
|
|
Shinya Kitaoka |
120a6e |
return AVIStreamFindSample(videoStream, index, FIND_PREV | FIND_KEY);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool isAKeyFrame(PAVISTREAM videoStream, int index) {
|
|
Shinya Kitaoka |
120a6e |
return index == getPrevKeyFrame(videoStream, index);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
}; // end of namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// TImageWriterAvi
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class TImageWriterAvi final : public TImageWriter {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
int m_frameIndex;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TImageWriterAvi(const TFilePath &path, int frameIndex, TLevelWriterAvi *lwa)
|
|
Shinya Kitaoka |
120a6e |
: TImageWriter(path), m_frameIndex(frameIndex), m_lwa(lwa) {
|
|
Shinya Kitaoka |
120a6e |
m_lwa->addRef();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
~TImageWriterAvi() { m_lwa->release(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
473e70 |
bool is64bitOutputSupported() override { return false; }
|
|
Shinya Kitaoka |
473e70 |
void save(const TImageP &img) override { m_lwa->save(img, m_frameIndex); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
TLevelWriterAvi *m_lwa;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// not implemented
|
|
Shinya Kitaoka |
120a6e |
TImageWriterAvi(const TImageWriterAvi &);
|
|
Shinya Kitaoka |
120a6e |
TImageWriterAvi &operator=(const TImageWriterAvi &src);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// TLevelWriterAvi;
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelWriterAvi::TLevelWriterAvi(const TFilePath &path, TPropertyGroup *winfo)
|
|
Shinya Kitaoka |
120a6e |
: TLevelWriter(path, winfo)
|
|
Shinya Kitaoka |
120a6e |
, m_aviFile(0)
|
|
Shinya Kitaoka |
120a6e |
, m_videoStream(0)
|
|
Shinya Kitaoka |
120a6e |
, m_audioStream(0)
|
|
Shinya Kitaoka |
120a6e |
, m_bitmapinfo(0)
|
|
Shinya Kitaoka |
120a6e |
, m_outputFmt(0)
|
|
Shinya Kitaoka |
120a6e |
, m_hic(0)
|
|
Shinya Kitaoka |
120a6e |
, m_initDone(false)
|
|
Shinya Kitaoka |
120a6e |
, IOError(0)
|
|
Shinya Kitaoka |
120a6e |
, m_st(0)
|
|
Shinya Kitaoka |
120a6e |
, m_bpp(32)
|
|
Shinya Kitaoka |
120a6e |
, m_maxDataSize(0)
|
|
Shinya Kitaoka |
120a6e |
, m_buffer(0)
|
|
Shinya Kitaoka |
120a6e |
, m_firstframe(-1) {
|
|
Shinya Kitaoka |
120a6e |
CoInitializeEx(0, COINIT_MULTITHREADED);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_frameRate = 12.;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
AVIFileInit();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (TSystem::doesExistFileOrLevel(m_path)) TSystem::deleteFile(m_path);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int rc = AVIFileOpenW(&m_aviFile, m_path.getWideString().c_str(),
|
|
Shinya Kitaoka |
120a6e |
OF_CREATE | OF_WRITE, 0);
|
|
Shinya Kitaoka |
120a6e |
if (rc != 0) throw TImageException(getFilePath(), "Unable to create file");
|
|
Shinya Kitaoka |
120a6e |
m_delayedFrames.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TLevelWriterAvi::~TLevelWriterAvi() {
|
|
Shinya Kitaoka |
120a6e |
// controllo che non ci siano ancora dei frame in coda nel codec (alcuni codec
|
|
Shinya Kitaoka |
120a6e |
// sono asincroni!)
|
|
Shinya Kitaoka |
120a6e |
while (!m_delayedFrames.empty()) {
|
|
Shinya Kitaoka |
120a6e |
LONG lSampWritten, lBytesWritten;
|
|
Shinya Kitaoka |
120a6e |
int frameIndex = m_delayedFrames.front();
|
|
Shinya Kitaoka |
120a6e |
DWORD flagsOut = 0;
|
|
Shinya Kitaoka |
120a6e |
DWORD flagsIn = !frameIndex ? AVIIF_KEYFRAME : 0;
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFOHEADER outHeader;
|
|
Shinya Kitaoka |
120a6e |
void *bufferOut = 0;
|
|
Shinya Kitaoka |
120a6e |
int res =
|
|
Shinya Kitaoka |
120a6e |
compressFrame(&outHeader, &bufferOut, frameIndex, flagsIn, flagsOut);
|
|
Shinya Kitaoka |
120a6e |
if (res != ICERR_OK) {
|
|
Shinya Kitaoka |
120a6e |
if (bufferOut) _aligned_free(bufferOut);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (AVIStreamWrite(m_videoStream, frameIndex, 1, bufferOut,
|
|
Shinya Kitaoka |
120a6e |
outHeader.biSizeImage, flagsOut, &lSampWritten,
|
|
Shinya Kitaoka |
120a6e |
&lBytesWritten)) {
|
|
Shinya Kitaoka |
120a6e |
if (bufferOut) _aligned_free(bufferOut);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_delayedFrames.pop_front();
|
|
Shinya Kitaoka |
120a6e |
if (bufferOut) _aligned_free(bufferOut);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_st) {
|
|
Shinya Kitaoka |
120a6e |
doSaveSoundTrack();
|
|
Shinya Kitaoka |
120a6e |
m_st = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_hic) {
|
|
Shinya Kitaoka |
120a6e |
ICCompressEnd(m_hic);
|
|
Shinya Kitaoka |
120a6e |
ICClose(m_hic);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_bitmapinfo) free(m_bitmapinfo);
|
|
Shinya Kitaoka |
120a6e |
if (m_outputFmt) free(m_outputFmt);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_videoStream) AVIStreamClose(m_videoStream);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_audioStream) AVIStreamClose(m_audioStream);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_aviFile) AVIFileClose(m_aviFile);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
AVIFileExit();
|
|
Shinya Kitaoka |
120a6e |
CoUninitialize();
|
|
Shinya Kitaoka |
120a6e |
if (!m_delayedFrames.empty())
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(
|
|
Shinya Kitaoka |
120a6e |
getFilePath(),
|
|
Shinya Kitaoka |
120a6e |
"error compressing frame " + std::to_string(m_delayedFrames.front()));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TLevelWriterAvi::searchForCodec() {
|
|
Shinya Kitaoka |
120a6e |
if (!m_properties) m_properties = new Tiio::AviWriterProperties();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TEnumProperty *p = (TEnumProperty *)m_properties->getProperty("Codec");
|
|
Shinya Kitaoka |
120a6e |
assert(p);
|
|
Shinya Kitaoka |
120a6e |
std::wstring codecName = p->getValue();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
//-------- // cerco compressorName fra i codec
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
HIC hic = 0;
|
|
Shinya Kitaoka |
120a6e |
ICINFO icinfo;
|
|
Shinya Kitaoka |
120a6e |
memset(&icinfo, 0, sizeof(ICINFO));
|
|
Shinya Kitaoka |
120a6e |
bool found = false;
|
|
Shinya Kitaoka |
120a6e |
if (codecName != L"Uncompressed") {
|
|
Shinya Kitaoka |
120a6e |
char descr[2048], name[2048];
|
|
Shinya Kitaoka |
120a6e |
DWORD fccType = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFO inFmt;
|
|
Shinya Kitaoka |
120a6e |
memset(&inFmt, 0, sizeof(BITMAPINFO));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
inFmt.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
Shinya Kitaoka |
120a6e |
inFmt.bmiHeader.biWidth = inFmt.bmiHeader.biHeight = 100;
|
|
Shinya Kitaoka |
120a6e |
inFmt.bmiHeader.biPlanes = 1;
|
|
Shinya Kitaoka |
120a6e |
inFmt.bmiHeader.biCompression = BI_RGB;
|
|
Shinya Kitaoka |
120a6e |
found = false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int bpp = 32; (bpp >= 24) && !found; bpp -= 8) {
|
|
Shinya Kitaoka |
120a6e |
inFmt.bmiHeader.biBitCount = bpp;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; ICInfo(fccType, i, &icinfo); i++) {
|
|
Shinya Kitaoka |
120a6e |
hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_COMPRESS);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ICGetInfo(hic, &icinfo,
|
|
Shinya Kitaoka |
120a6e |
sizeof(ICINFO)); // Find out the compressor name
|
|
Shinya Kitaoka |
120a6e |
WideChar2Char(icinfo.szDescription, descr, sizeof(descr));
|
|
Shinya Kitaoka |
120a6e |
WideChar2Char(icinfo.szName, name, sizeof(name));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::string compressorName;
|
|
Shinya Kitaoka |
120a6e |
compressorName = std::string(name) + " '" + std::to_string(bpp) + "' " +
|
|
Shinya Kitaoka |
120a6e |
std::string(descr);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (hic) {
|
|
Shinya Kitaoka |
120a6e |
if (ICCompressQuery(hic, &inFmt, NULL) != ICERR_OK) {
|
|
Shinya Kitaoka |
120a6e |
ICClose(hic);
|
|
Shinya Kitaoka |
120a6e |
continue; // Skip this compressor if it can't handle the format.
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (::to_wstring(compressorName) == codecName) {
|
|
Shinya Kitaoka |
120a6e |
found = true;
|
|
Shinya Kitaoka |
120a6e |
m_bpp = bpp;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ICClose(hic);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_hic = hic;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TLevelWriterAvi::createBitmap(int lx, int ly) {
|
|
Shinya Kitaoka |
120a6e |
const RGBQUAD NOMASK = {0x00, 0x00, 0x00, 0x00};
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo =
|
|
Shinya Kitaoka |
120a6e |
(BITMAPINFO *)calloc(1, sizeof(BITMAPINFOHEADER) + 255 * sizeof(RGBQUAD));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biWidth = lx;
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biHeight = ly;
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biPlanes = 1;
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biBitCount = m_bpp;
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biCompression = BI_RGB;
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biSizeImage = lx * ly * m_bpp / 8;
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biXPelsPerMeter = 0;
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biYPelsPerMeter = 0;
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biClrUsed = 0;
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biClrImportant = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiColors[0] = NOMASK;
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiColors[1] = NOMASK;
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiColors[2] = NOMASK;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_buffer = _aligned_malloc(m_bitmapinfo->bmiHeader.biSizeImage, 128);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TImageWriterP TLevelWriterAvi::getFrameWriter(TFrameId fid) {
|
|
Shinya Kitaoka |
120a6e |
if (IOError != 0)
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(m_path, buildAVIExceptionString(IOError));
|
|
Shinya Kitaoka |
120a6e |
if (fid.getLetter() != 0) return TImageWriterP(0);
|
|
Shinya Kitaoka |
120a6e |
int index = fid.getNumber() - 1;
|
|
Shinya Kitaoka |
120a6e |
TImageWriterAvi *iwa = new TImageWriterAvi(m_path, index, this);
|
|
Shinya Kitaoka |
120a6e |
return TImageWriterP(iwa);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TLevelWriterAvi::save(const TImageP &img, int frameIndex) {
|
|
Shinya Kitaoka |
120a6e |
CoInitializeEx(0, COINIT_MULTITHREADED);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_firstframe < 0) m_firstframe = frameIndex;
|
|
Shinya Kitaoka |
120a6e |
int index = frameIndex - m_firstframe;
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP image(img);
|
|
Shinya Kitaoka |
120a6e |
int lx = image->getRaster()->getLx();
|
|
Shinya Kitaoka |
120a6e |
int ly = image->getRaster()->getLy();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int pixelSize = image->getRaster()->getPixelSize();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (pixelSize != 4)
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(), "Unsupported pixel type");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
QMutexLocker sl(&m_mutex);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!m_initDone) {
|
|
Shinya Kitaoka |
120a6e |
searchForCodec();
|
|
Shinya Kitaoka |
120a6e |
createBitmap(lx, ly);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
DWORD num = DWORD(tround(m_frameRate * 100.0));
|
|
Shinya Kitaoka |
120a6e |
DWORD den = 100;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
AVISTREAMINFO psi;
|
|
Shinya Kitaoka |
120a6e |
memset(&psi, 0, sizeof(AVISTREAMINFO));
|
|
Shinya Kitaoka |
120a6e |
psi.fccType = streamtypeVIDEO;
|
|
Shinya Kitaoka |
120a6e |
if (m_hic) {
|
|
Shinya Kitaoka |
120a6e |
ICINFO icinfo;
|
|
Shinya Kitaoka |
120a6e |
ICGetInfo(m_hic, &icinfo, sizeof(ICINFO));
|
|
Shinya Kitaoka |
120a6e |
psi.fccHandler = icinfo.fccHandler;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
psi.dwScale = den;
|
|
Shinya Kitaoka |
120a6e |
psi.dwRate = num;
|
|
Shinya Kitaoka |
120a6e |
psi.dwQuality = ICQUALITY_DEFAULT;
|
|
Shinya Kitaoka |
120a6e |
psi.rcFrame.right = lx;
|
|
Shinya Kitaoka |
120a6e |
psi.rcFrame.bottom = ly;
|
|
Shinya Kitaoka |
120a6e |
::strcpy(psi.szName, m_path.getName().c_str());
|
|
Shinya Kitaoka |
120a6e |
int rc;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (AVIFileCreateStream(m_aviFile, &(m_videoStream), &(psi)))
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(), "Unable to create video stream");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!m_hic) {
|
|
Shinya Kitaoka |
120a6e |
if (AVIStreamSetFormat(m_videoStream, 0, &m_bitmapinfo->bmiHeader,
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biSize))
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(), "unable to set format");
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
m_outputFmt = (BITMAPINFO *)calloc(
|
|
Shinya Kitaoka |
120a6e |
1, sizeof(BITMAPINFOHEADER) + 255 * sizeof(RGBQUAD));
|
|
Shinya Kitaoka |
120a6e |
m_outputFmt->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rc = ICCompressGetFormat(m_hic, m_bitmapinfo, m_outputFmt);
|
|
Shinya Kitaoka |
120a6e |
if (rc != ICERR_OK)
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(),
|
|
Shinya Kitaoka |
120a6e |
"Error codec (ec = " + std::to_string(rc) + ")");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ICCOMPRESSFRAMES icf;
|
|
Shinya Kitaoka |
120a6e |
memset(&icf, 0, sizeof icf);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
icf.dwFlags = (DWORD)&icf.lKeyRate;
|
|
Shinya Kitaoka |
120a6e |
icf.lStartFrame = index;
|
|
Shinya Kitaoka |
120a6e |
icf.lFrameCount = 0;
|
|
Shinya Kitaoka |
120a6e |
icf.lQuality = ICQUALITY_DEFAULT;
|
|
Shinya Kitaoka |
120a6e |
icf.lDataRate = 0;
|
|
Shinya Kitaoka |
120a6e |
icf.lKeyRate = (DWORD)(num / den);
|
|
Shinya Kitaoka |
120a6e |
icf.dwRate = num;
|
|
Shinya Kitaoka |
120a6e |
icf.dwScale = den;
|
|
Shinya Kitaoka |
120a6e |
ICSendMessage(m_hic, ICM_COMPRESS_FRAMES_INFO, (WPARAM)&icf,
|
|
Shinya Kitaoka |
120a6e |
sizeof(ICCOMPRESSFRAMES));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_maxDataSize = ICCompressGetSize(m_hic, m_bitmapinfo, m_outputFmt);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rc = ICCompressBegin(m_hic, m_bitmapinfo, m_outputFmt);
|
|
Shinya Kitaoka |
120a6e |
if (rc != ICERR_OK)
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(), "Error starting codec (ec = " +
|
|
Shinya Kitaoka |
120a6e |
std::to_string(rc) + ")");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (AVIStreamSetFormat(m_videoStream, 0, &m_outputFmt->bmiHeader,
|
|
Shinya Kitaoka |
120a6e |
m_outputFmt->bmiHeader.biSize))
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(), "unable to set format");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_initDone = true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// copio l'immagine nella bitmap che ho creato in createBitmap
|
|
Shinya Kitaoka |
120a6e |
image->getRaster()->lock();
|
|
Shinya Kitaoka |
120a6e |
void *buffin = image->getRaster()->getRawData();
|
|
Shinya Kitaoka |
120a6e |
assert(buffin);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterGR8P raux;
|
|
Shinya Kitaoka |
120a6e |
if (m_bpp == 24) {
|
|
Shinya Kitaoka |
120a6e |
int newlx = lx * 3;
|
|
Shinya Kitaoka |
120a6e |
raux = TRasterGR8P(newlx, ly);
|
|
Shinya Kitaoka |
120a6e |
raux->lock();
|
|
Shinya Kitaoka |
120a6e |
UCHAR *buffout24 = (UCHAR *)raux->getRawData(); // new UCHAR[newlx*ly];
|
|
Shinya Kitaoka |
120a6e |
TPixel *buffin32 = (TPixel *)buffin;
|
|
Shinya Kitaoka |
120a6e |
buffin = buffout24;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < ly; i++) {
|
|
Shinya Kitaoka |
120a6e |
UCHAR *pix = buffout24 + newlx * i;
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < lx; j++, buffin32++) {
|
|
Shinya Kitaoka |
120a6e |
*pix++ = buffin32->b;
|
|
Shinya Kitaoka |
120a6e |
*pix++ = buffin32->g;
|
|
Shinya Kitaoka |
120a6e |
*pix++ = buffin32->r;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
raux->unlock();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
memcpy(m_buffer, buffin, lx * ly * m_bpp / 8);
|
|
Shinya Kitaoka |
120a6e |
image->getRaster()->unlock();
|
|
Shinya Kitaoka |
120a6e |
raux = TRasterGR8P();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
LONG lSampWritten, lBytesWritten;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
lSampWritten = 0;
|
|
Shinya Kitaoka |
120a6e |
lBytesWritten = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!m_hic) {
|
|
Shinya Kitaoka |
120a6e |
if (AVIStreamWrite(m_videoStream, index, 1, m_buffer,
|
|
Shinya Kitaoka |
120a6e |
m_bitmapinfo->bmiHeader.biSizeImage, AVIIF_KEYFRAME,
|
|
Shinya Kitaoka |
120a6e |
&lSampWritten, &lBytesWritten)) {
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(), "error writing frame");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFOHEADER outHeader;
|
|
Shinya Kitaoka |
120a6e |
void *bufferOut = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
DWORD flagsOut = 0;
|
|
Shinya Kitaoka |
120a6e |
DWORD flagsIn = !index ? ICCOMPRESS_KEYFRAME : 0;
|
|
Shinya Kitaoka |
120a6e |
int res = compressFrame(&outHeader, &bufferOut, index, flagsIn, flagsOut);
|
|
Shinya Kitaoka |
120a6e |
if (res != ICERR_OK) {
|
|
Shinya Kitaoka |
120a6e |
if (bufferOut) _aligned_free(bufferOut);
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(),
|
|
Shinya Kitaoka |
120a6e |
"error compressing frame " + std::to_string(index));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (outHeader.biCompression == '05xd' ||
|
|
Shinya Kitaoka |
120a6e |
outHeader.biCompression == '05XD' ||
|
|
Shinya Kitaoka |
120a6e |
outHeader.biCompression == 'divx' || outHeader.biCompression == 'DIVX')
|
|
Shinya Kitaoka |
120a6e |
if (outHeader.biSizeImage == 1 && *(char *)bufferOut == 0x7f) {
|
|
Shinya Kitaoka |
120a6e |
m_delayedFrames.push_back(index);
|
|
Shinya Kitaoka |
120a6e |
if (bufferOut) _aligned_free(bufferOut);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (!m_delayedFrames.empty()) {
|
|
Shinya Kitaoka |
120a6e |
m_delayedFrames.push_back(index);
|
|
Shinya Kitaoka |
120a6e |
index = m_delayedFrames.front();
|
|
Shinya Kitaoka |
120a6e |
m_delayedFrames.pop_front();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (AVIStreamWrite(m_videoStream, index, 1, bufferOut,
|
|
Shinya Kitaoka |
120a6e |
outHeader.biSizeImage, !index ? flagsOut : 0,
|
|
Shinya Kitaoka |
120a6e |
&lSampWritten, &lBytesWritten)) {
|
|
Shinya Kitaoka |
120a6e |
if (bufferOut) _aligned_free(bufferOut);
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(), "error writing frame");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (bufferOut) _aligned_free(bufferOut);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int TLevelWriterAvi::compressFrame(BITMAPINFOHEADER *outHeader,
|
|
Shinya Kitaoka |
120a6e |
void **bufferOut, int frameIndex,
|
|
Shinya Kitaoka |
120a6e |
DWORD flagsIn, DWORD &flagsOut) {
|
|
Shinya Kitaoka |
120a6e |
*bufferOut = _aligned_malloc(m_maxDataSize, 128);
|
|
Shinya Kitaoka |
120a6e |
*outHeader = m_outputFmt->bmiHeader;
|
|
Shinya Kitaoka |
120a6e |
DWORD chunkId = 0;
|
|
Shinya Kitaoka |
120a6e |
if (flagsIn) flagsOut = AVIIF_KEYFRAME;
|
|
Shinya Kitaoka |
120a6e |
int res = ICCompress(m_hic, flagsIn, outHeader, *bufferOut,
|
|
Shinya Kitaoka |
120a6e |
&m_bitmapinfo->bmiHeader, m_buffer, &chunkId, &flagsOut,
|
|
Shinya Kitaoka |
120a6e |
frameIndex, frameIndex ? 0 : 0xFFFFFF, 0, NULL, NULL);
|
|
Shinya Kitaoka |
120a6e |
return res;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TLevelWriterAvi::TLevelWriterAvi(const TFilePath &path) : TLevelWriter(path) {}
|
|
Toshihiro Shimizu |
890ddd |
TLevelWriterAvi::~TLevelWriterAvi() {}
|
|
Shinya Kitaoka |
120a6e |
TImageWriterP TLevelWriterAvi::getFrameWriter(TFrameId) {
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(), "not supported");
|
|
Shinya Kitaoka |
120a6e |
return TImageWriterP(iwa);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
void TImageWriterAvi::save(const TImageP &) {
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(m_path, "AVI file format not supported");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TLevelWriterAvi::saveSoundTrack(TSoundTrack *st) {
|
|
Shinya Kitaoka |
120a6e |
if (!m_aviFile) throw TException("unable to save soundtrack");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (!st) throw TException("null reference to soundtrack");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_st =
|
|
Shinya Kitaoka |
120a6e |
st; // prima devo aver salvato tutto il video, salvo l'audio alla fine!
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TLevelWriterAvi::doSaveSoundTrack() {
|
|
Shinya Kitaoka |
120a6e |
WAVEFORMATEX waveinfo;
|
|
Shinya Kitaoka |
120a6e |
int ret;
|
|
Shinya Kitaoka |
120a6e |
LONG lSampWritten, lBytesWritten;
|
|
Shinya Kitaoka |
120a6e |
int rc;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rc = FALSE;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
AVISTREAMINFO audioStreamInfo;
|
|
Shinya Kitaoka |
120a6e |
memset(&audioStreamInfo, 0, sizeof(AVISTREAMINFO));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.fccType = streamtypeAUDIO;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.fccHandler = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwFlags = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwCaps = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.wPriority = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.wLanguage = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwScale = 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwRate = m_st->getSampleRate();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwStart = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwLength = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwInitialFrames = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwSuggestedBufferSize = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwQuality = (ULONG)-1;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwSampleSize = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.rcFrame.left = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.rcFrame.top = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.rcFrame.right = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.rcFrame.bottom = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwEditCount = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.dwFormatChangeCount = 0;
|
|
Shinya Kitaoka |
120a6e |
audioStreamInfo.szName[0] = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
38fd86 |
waveinfo.wFormatTag = WAVE_FORMAT_PCM; // WAVE_FORMAT_DRM
|
|
Shinya Kitaoka |
38fd86 |
waveinfo.nChannels = m_st->getChannelCount();
|
|
Shinya Kitaoka |
38fd86 |
waveinfo.nSamplesPerSec = m_st->getSampleRate();
|
|
Shinya Kitaoka |
38fd86 |
waveinfo.wBitsPerSample = m_st->getBitPerSample();
|
|
Shinya Kitaoka |
38fd86 |
waveinfo.nBlockAlign = waveinfo.nChannels * waveinfo.wBitsPerSample >> 3;
|
|
Shinya Kitaoka |
120a6e |
waveinfo.nAvgBytesPerSec = waveinfo.nSamplesPerSec * waveinfo.nBlockAlign;
|
|
Shinya Kitaoka |
120a6e |
waveinfo.cbSize = sizeof(WAVEFORMATEX);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const UCHAR *buffer = m_st->getRawData();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (AVIFileCreateStream(m_aviFile, &m_audioStream, &audioStreamInfo))
|
|
Shinya Kitaoka |
120a6e |
throw TException("error creating soundtrack stream");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (AVIStreamSetFormat(m_audioStream, 0, &waveinfo, sizeof(WAVEFORMATEX)))
|
|
Shinya Kitaoka |
120a6e |
throw TException("error setting soundtrack format");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
LONG count = m_st->getSampleCount();
|
|
Shinya Kitaoka |
120a6e |
LONG bufSize = m_st->getSampleCount() * m_st->getSampleSize();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (ret = AVIStreamWrite(m_audioStream, 0, count, (char *)buffer, bufSize,
|
|
Shinya Kitaoka |
120a6e |
AVIIF_KEYFRAME, &lSampWritten, &lBytesWritten))
|
|
Shinya Kitaoka |
120a6e |
throw TException("error writing soundtrack samples");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// TImageReaderAvi
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class TImageReaderAvi final : public TImageReader {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
int m_frameIndex;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TImageReaderAvi(const TFilePath &path, int index, TLevelReaderAvi *lra)
|
|
Shinya Kitaoka |
120a6e |
: TImageReader(path), m_lra(lra), m_frameIndex(index) {
|
|
Shinya Kitaoka |
120a6e |
m_lra->addRef();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
~TImageReaderAvi() { m_lra->release(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
473e70 |
TImageP load() override { return m_lra->load(m_frameIndex); }
|
|
Shinya Kitaoka |
120a6e |
TDimension getSize() const { return m_lra->getSize(); }
|
|
Shinya Kitaoka |
120a6e |
TRect getBBox() const { return TRect(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
TLevelReaderAvi *m_lra;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// not implemented
|
|
Shinya Kitaoka |
120a6e |
TImageReaderAvi(const TImageReaderAvi &);
|
|
Shinya Kitaoka |
120a6e |
TImageReaderAvi &operator=(const TImageReaderAvi &src);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// TLevelReaderAvi
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Toshihiro Shimizu |
890ddd |
TLevelReaderAvi::TLevelReaderAvi(const TFilePath &path)
|
|
Shinya Kitaoka |
120a6e |
: TLevelReader(path)
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Shinya Kitaoka |
120a6e |
, m_srcBitmapInfo(0)
|
|
Shinya Kitaoka |
120a6e |
, m_dstBitmapInfo(0)
|
|
Shinya Kitaoka |
120a6e |
, m_hic(0)
|
|
Shinya Kitaoka |
120a6e |
, IOError(0)
|
|
Shinya Kitaoka |
120a6e |
, m_prevFrame(-1)
|
|
Shinya Kitaoka |
120a6e |
, m_decompressedBuffer(0)
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
CoInitializeEx(0, COINIT_MULTITHREADED);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
AVIFileInit();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int rc = AVIStreamOpenFromFileW(&m_videoStream, path.getWideString().c_str(),
|
|
Shinya Kitaoka |
120a6e |
streamtypeVIDEO, 0, OF_READ, 0);
|
|
Shinya Kitaoka |
120a6e |
if (rc != 0) {
|
|
Shinya Kitaoka |
120a6e |
IOError = rc;
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(m_path, buildAVIExceptionString(IOError));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
LONG size = sizeof(BITMAPINFO);
|
|
Shinya Kitaoka |
120a6e |
m_srcBitmapInfo = (BITMAPINFO *)calloc(1, size);
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo = (BITMAPINFO *)calloc(1, size);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rc = AVIStreamReadFormat(m_videoStream, 0, m_srcBitmapInfo, &size);
|
|
Shinya Kitaoka |
120a6e |
if (rc) throw TImageException(getFilePath(), "error reading info.");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
*m_dstBitmapInfo = *m_srcBitmapInfo;
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biCompression = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
AVISTREAMINFO si;
|
|
Shinya Kitaoka |
120a6e |
rc = AVIStreamInfo(m_videoStream, &si, sizeof(AVISTREAMINFO));
|
|
Shinya Kitaoka |
120a6e |
if (rc) throw TImageException(getFilePath(), "error reading info.");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_info = new TImageInfo();
|
|
Shinya Kitaoka |
120a6e |
m_info->m_frameRate = si.dwRate / double(si.dwScale);
|
|
Shinya Kitaoka |
120a6e |
m_info->m_lx = si.rcFrame.right - si.rcFrame.left;
|
|
Shinya Kitaoka |
120a6e |
m_info->m_ly = si.rcFrame.bottom - si.rcFrame.top;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int bpp = m_srcBitmapInfo->bmiHeader.biBitCount;
|
|
Shinya Kitaoka |
120a6e |
switch (bpp) {
|
|
Shinya Kitaoka |
120a6e |
case 32: {
|
|
Shinya Kitaoka |
120a6e |
m_info->m_bitsPerSample = 8;
|
|
Shinya Kitaoka |
120a6e |
m_info->m_samplePerPixel = 4;
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biSizeImage =
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biWidth *
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biHeight * 4;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
case 24: {
|
|
Shinya Kitaoka |
120a6e |
m_info->m_bitsPerSample = 8;
|
|
Shinya Kitaoka |
120a6e |
m_info->m_samplePerPixel = 3;
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biSizeImage =
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biWidth *
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biHeight * 3;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
case 16: {
|
|
Shinya Kitaoka |
120a6e |
m_info->m_bitsPerSample = 8;
|
|
Shinya Kitaoka |
120a6e |
m_info->m_samplePerPixel = 2;
|
|
Shinya Kitaoka |
120a6e |
// chiedo al decoder di decomprimerla in un'immagine a 24 bit (sperando che
|
|
Shinya Kitaoka |
120a6e |
// lo permetta)
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biBitCount = 24;
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biSizeImage =
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biWidth *
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biHeight * 3;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
default: {
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(),
|
|
Shinya Kitaoka |
120a6e |
"unable to find a decompressor for this format");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Tiio::AviWriterProperties *prop = new Tiio::AviWriterProperties();
|
|
Shinya Kitaoka |
120a6e |
m_info->m_properties = prop;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_srcBitmapInfo->bmiHeader.biCompression != 0) {
|
|
Shinya Kitaoka |
120a6e |
// ci sono dei codec (es. Xvid) che non decomprimono bene dentro immagini a
|
|
Shinya Kitaoka |
120a6e |
// 32 bit.
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biBitCount = 24;
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biSizeImage =
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biWidth *
|
|
Shinya Kitaoka |
120a6e |
m_dstBitmapInfo->bmiHeader.biHeight * 3;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ICINFO icinfo;
|
|
Shinya Kitaoka |
120a6e |
memset(&icinfo, 0, sizeof(ICINFO));
|
|
Shinya Kitaoka |
120a6e |
ICInfo(ICTYPE_VIDEO, si.fccHandler, &icinfo);
|
|
Shinya Kitaoka |
120a6e |
m_hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_DECOMPRESS);
|
|
Shinya Kitaoka |
120a6e |
if (!m_hic) {
|
|
Shinya Kitaoka |
120a6e |
m_hic = findCandidateDecompressor();
|
|
Shinya Kitaoka |
120a6e |
if (!m_hic)
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(),
|
|
Shinya Kitaoka |
120a6e |
"unable to find a decompressor for this format");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
DWORD result = ICDecompressQuery(m_hic, m_srcBitmapInfo, m_dstBitmapInfo);
|
|
Shinya Kitaoka |
120a6e |
if (result != ICERR_OK)
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(),
|
|
Shinya Kitaoka |
120a6e |
"unable to find a decompressor for this format");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
result = ICDecompressBegin(m_hic, m_srcBitmapInfo, m_dstBitmapInfo);
|
|
Shinya Kitaoka |
120a6e |
if (result != ICERR_OK)
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(getFilePath(),
|
|
Shinya Kitaoka |
120a6e |
"unable to initializate the decompressor");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
char descr[2048], name[2048];
|
|
Shinya Kitaoka |
120a6e |
ICGetInfo(m_hic, &icinfo, sizeof(ICINFO)); // Find out the compressor name
|
|
Shinya Kitaoka |
120a6e |
WideChar2Char(icinfo.szDescription, descr, sizeof(descr));
|
|
Shinya Kitaoka |
120a6e |
WideChar2Char(icinfo.szName, name, sizeof(name));
|
|
Shinya Kitaoka |
120a6e |
std::string compressorName;
|
|
Shinya Kitaoka |
120a6e |
compressorName = std::string(name) + " '" +
|
|
Shinya Kitaoka |
120a6e |
std::to_string(m_dstBitmapInfo->bmiHeader.biBitCount) +
|
|
Shinya Kitaoka |
120a6e |
"' " + std::string(descr);
|
|
Shinya Kitaoka |
120a6e |
TEnumProperty *p =
|
|
Shinya Kitaoka |
120a6e |
(TEnumProperty *)m_info->m_properties->getProperty("Codec");
|
|
Shinya Kitaoka |
120a6e |
p->setValue(::to_wstring(compressorName));
|
|
Shinya Kitaoka |
120a6e |
m_decompressedBuffer =
|
|
Shinya Kitaoka |
120a6e |
_aligned_malloc(m_dstBitmapInfo->bmiHeader.biSizeImage, 128);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
m_hic = 0;
|
|
Shinya Kitaoka |
120a6e |
TEnumProperty *p =
|
|
Shinya Kitaoka |
120a6e |
(TEnumProperty *)m_info->m_properties->getProperty("Codec");
|
|
Shinya Kitaoka |
120a6e |
p->setValue(L"Uncompressed");
|
|
Shinya Kitaoka |
120a6e |
m_decompressedBuffer = _aligned_malloc(si.dwSuggestedBufferSize, 128);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TLevelReaderAvi::~TLevelReaderAvi() {
|
|
Shinya Kitaoka |
120a6e |
if (m_hic) {
|
|
Shinya Kitaoka |
120a6e |
ICDecompressEnd(m_hic);
|
|
Shinya Kitaoka |
120a6e |
ICClose(m_hic);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (m_srcBitmapInfo) free(m_srcBitmapInfo);
|
|
Shinya Kitaoka |
120a6e |
if (m_dstBitmapInfo) free(m_dstBitmapInfo);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (m_videoStream) AVIStreamClose(m_videoStream);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
AVIFileExit();
|
|
Shinya Kitaoka |
120a6e |
_aligned_free(m_decompressedBuffer);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
HIC TLevelReaderAvi::findCandidateDecompressor() {
|
|
Shinya Kitaoka |
120a6e |
ICINFO info = {0};
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFO srcInfo = *m_srcBitmapInfo;
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFO dstInfo = *m_dstBitmapInfo;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (DWORD id = 0; ICInfo(ICTYPE_VIDEO, id, &info); ++id) {
|
|
Shinya Kitaoka |
120a6e |
info.dwSize = sizeof(
|
|
Shinya Kitaoka |
120a6e |
ICINFO); // I don't think this is necessary, but just in case....
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
HIC hic = ICOpen(info.fccType, info.fccHandler, ICMODE_DECOMPRESS);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!hic) continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
DWORD result = ICDecompressQuery(hic, &srcInfo, &dstInfo);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (result == ICERR_OK) {
|
|
Shinya Kitaoka |
120a6e |
// Check for a codec that doesn't actually support what it says it does.
|
|
Shinya Kitaoka |
120a6e |
// We ask the codec whether it can do a specific conversion that it can't
|
|
Shinya Kitaoka |
120a6e |
// possibly support. If it does it, then we call BS and ignore the codec.
|
|
Shinya Kitaoka |
120a6e |
// The Grand Tech Camera Codec and Panasonic DV codecs are known to do
|
|
Shinya Kitaoka |
120a6e |
// this.
|
|
Shinya Kitaoka |
120a6e |
//
|
|
Shinya Kitaoka |
120a6e |
// (general idea from Raymond Chen's blog)
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFOHEADER testSrc = {// note: can't be static const since
|
|
Shinya Kitaoka |
120a6e |
// IsBadWritePtr() will get called on it
|
|
Shinya Kitaoka |
120a6e |
sizeof(BITMAPINFOHEADER),
|
|
Shinya Kitaoka |
120a6e |
320,
|
|
Shinya Kitaoka |
120a6e |
240,
|
|
Shinya Kitaoka |
120a6e |
1,
|
|
Shinya Kitaoka |
120a6e |
24,
|
|
Shinya Kitaoka |
120a6e |
0x2E532E42,
|
|
Shinya Kitaoka |
120a6e |
320 * 240 * 3,
|
|
Shinya Kitaoka |
120a6e |
0,
|
|
Shinya Kitaoka |
120a6e |
0,
|
|
Shinya Kitaoka |
120a6e |
0,
|
|
Shinya Kitaoka |
120a6e |
0};
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
DWORD res = ICDecompressQuery(hic, &testSrc, NULL);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (ICERR_OK == res) { // Don't need to wrap this, as it's OK if testSrc
|
|
Shinya Kitaoka |
120a6e |
// gets modified.
|
|
Shinya Kitaoka |
120a6e |
ICINFO info = {sizeof(ICINFO)};
|
|
Shinya Kitaoka |
120a6e |
ICGetInfo(hic, &info, sizeof info);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Okay, let's give the codec a chance to redeem itself. Reformat the
|
|
Shinya Kitaoka |
120a6e |
// input format into
|
|
Shinya Kitaoka |
120a6e |
// a plain 24-bit RGB image, and ask it what the compressed format is.
|
|
Shinya Kitaoka |
120a6e |
// If it produces
|
|
Shinya Kitaoka |
120a6e |
// a FOURCC that matches, allow it to handle the format. This should
|
|
Shinya Kitaoka |
120a6e |
// allow at least
|
|
Shinya Kitaoka |
120a6e |
// the codec's primary format to work. Otherwise, drop it on the ground.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_srcBitmapInfo) {
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFOHEADER unpackedSrc = {sizeof(BITMAPINFOHEADER),
|
|
Shinya Kitaoka |
120a6e |
m_srcBitmapInfo->bmiHeader.biWidth,
|
|
Shinya Kitaoka |
120a6e |
m_srcBitmapInfo->bmiHeader.biHeight,
|
|
Shinya Kitaoka |
120a6e |
1,
|
|
Shinya Kitaoka |
120a6e |
24,
|
|
Shinya Kitaoka |
120a6e |
BI_RGB,
|
|
Shinya Kitaoka |
120a6e |
0,
|
|
Shinya Kitaoka |
120a6e |
0,
|
|
Shinya Kitaoka |
120a6e |
0,
|
|
Shinya Kitaoka |
120a6e |
0,
|
|
Shinya Kitaoka |
120a6e |
0};
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
unpackedSrc.biSizeImage =
|
|
Shinya Kitaoka |
120a6e |
((unpackedSrc.biWidth * 3 + 3) & ~3) * abs(unpackedSrc.biHeight);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
LONG size = ICCompressGetFormatSize(hic, &unpackedSrc);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (size >= sizeof(BITMAPINFOHEADER)) {
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFOHEADER tmp;
|
|
Shinya Kitaoka |
120a6e |
if (ICERR_OK == ICCompressGetFormat(hic, &unpackedSrc, &tmp) &&
|
|
Shinya Kitaoka |
120a6e |
tmp.biCompression == m_srcBitmapInfo->bmiHeader.biCompression)
|
|
Shinya Kitaoka |
120a6e |
return hic;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
return hic;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ICClose(hic);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return NULL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TLevelP TLevelReaderAvi::loadInfo() {
|
|
Shinya Kitaoka |
120a6e |
if (IOError) throw TImageException(m_path, buildAVIExceptionString(IOError));
|
|
Shinya Kitaoka |
120a6e |
int nFrames = AVIStreamLength(m_videoStream);
|
|
Shinya Kitaoka |
120a6e |
if (nFrames == -1) return TLevelP();
|
|
Shinya Kitaoka |
120a6e |
TLevelP level;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 1; i <= nFrames; i++) level->setFrame(i, TImageP());
|
|
Shinya Kitaoka |
120a6e |
return level;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TImageReaderP TLevelReaderAvi::getFrameReader(TFrameId fid) {
|
|
Shinya Kitaoka |
120a6e |
if (IOError != 0)
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(m_path, buildAVIExceptionString(IOError));
|
|
Shinya Kitaoka |
120a6e |
if (fid.getLetter() != 0) return TImageReaderP(0);
|
|
Shinya Kitaoka |
120a6e |
int index = fid.getNumber() - 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TImageReaderAvi *ira = new TImageReaderAvi(m_path, index, this);
|
|
Shinya Kitaoka |
120a6e |
return TImageReaderP(ira);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TDimension TLevelReaderAvi::getSize() {
|
|
Shinya Kitaoka |
120a6e |
QMutexLocker sl(&m_mutex);
|
|
Shinya Kitaoka |
120a6e |
AVISTREAMINFO psi;
|
|
Shinya Kitaoka |
120a6e |
AVIStreamInfo(m_videoStream, &psi, sizeof(AVISTREAMINFO));
|
|
Shinya Kitaoka |
120a6e |
return TDimension(psi.rcFrame.right - psi.rcFrame.left,
|
|
Shinya Kitaoka |
120a6e |
psi.rcFrame.bottom - psi.rcFrame.top);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TImageP TLevelReaderAvi::load(int frameIndex) {
|
|
Shinya Kitaoka |
120a6e |
AVISTREAMINFO si;
|
|
Shinya Kitaoka |
120a6e |
int rc = AVIStreamInfo(m_videoStream, &si, sizeof(AVISTREAMINFO));
|
|
Shinya Kitaoka |
120a6e |
if (rc) throw TImageException(getFilePath(), "error reading info.");
|
|
Shinya Kitaoka |
120a6e |
void *bufferOut = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!m_hic) {
|
|
Shinya Kitaoka |
120a6e |
rc = readFrameFromStream(m_decompressedBuffer, si.dwSuggestedBufferSize,
|
|
Shinya Kitaoka |
120a6e |
frameIndex);
|
|
Shinya Kitaoka |
120a6e |
if (rc) {
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(m_path, "unable read frame " +
|
|
Shinya Kitaoka |
120a6e |
std::to_string(frameIndex) +
|
|
Shinya Kitaoka |
120a6e |
"from video stream.");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
int prevKeyFrame = m_prevFrame == frameIndex - 1
|
|
Shinya Kitaoka |
120a6e |
? frameIndex
|
|
Shinya Kitaoka |
120a6e |
: getPrevKeyFrame(m_videoStream, frameIndex);
|
|
Shinya Kitaoka |
120a6e |
while (prevKeyFrame <= frameIndex) {
|
|
Shinya Kitaoka |
120a6e |
bufferOut = _aligned_malloc(si.dwSuggestedBufferSize, 128);
|
|
Shinya Kitaoka |
120a6e |
DWORD bytesRead = si.dwSuggestedBufferSize;
|
|
Shinya Kitaoka |
120a6e |
rc = readFrameFromStream(bufferOut, bytesRead, prevKeyFrame);
|
|
Shinya Kitaoka |
120a6e |
if (rc) {
|
|
Shinya Kitaoka |
120a6e |
_aligned_free(bufferOut);
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(m_path, "unable read frame " +
|
|
Shinya Kitaoka |
120a6e |
std::to_string(frameIndex) +
|
|
Shinya Kitaoka |
120a6e |
"from video stream.");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
DWORD res = decompressFrame(bufferOut, bytesRead, m_decompressedBuffer,
|
|
Shinya Kitaoka |
120a6e |
prevKeyFrame, frameIndex);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
_aligned_free(bufferOut);
|
|
Shinya Kitaoka |
120a6e |
if (res != ICERR_OK) {
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(
|
|
Shinya Kitaoka |
120a6e |
m_path, "error decompressing frame " + std::to_string(frameIndex));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
prevKeyFrame++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int width = m_srcBitmapInfo->bmiHeader.biWidth;
|
|
Shinya Kitaoka |
120a6e |
int height = m_srcBitmapInfo->bmiHeader.biHeight;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int bpp = m_dstBitmapInfo->bmiHeader.biBitCount;
|
|
Shinya Kitaoka |
120a6e |
m_prevFrame = frameIndex;
|
|
Shinya Kitaoka |
120a6e |
switch (bpp) {
|
|
Shinya Kitaoka |
120a6e |
case 32: {
|
|
Shinya Kitaoka |
120a6e |
TRasterPT<tpixelrgbm32> ret;</tpixelrgbm32>
|
|
Shinya Kitaoka |
120a6e |
ret.create(width, height);
|
|
Shinya Kitaoka |
120a6e |
ret->lock();
|
|
Shinya Kitaoka |
120a6e |
memcpy(ret->getRawData(), m_decompressedBuffer, width * height * 4);
|
|
Shinya Kitaoka |
120a6e |
ret->unlock();
|
|
Shinya Kitaoka |
120a6e |
return TRasterImageP(ret);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
case 24: {
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP i(DIBToRaster((UCHAR *)m_decompressedBuffer, width, height));
|
|
Shinya Kitaoka |
120a6e |
return i;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
default: {
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(m_path,
|
|
Shinya Kitaoka |
120a6e |
std::to_string(bpp) + " to 32 bit not supported\n");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return TRasterImageP();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int TLevelReaderAvi::readFrameFromStream(void *bufferOut, DWORD &bufferSize,
|
|
Shinya Kitaoka |
120a6e |
int frameIndex) const {
|
|
Shinya Kitaoka |
120a6e |
assert(bufferOut && bufferSize > 0);
|
|
Shinya Kitaoka |
120a6e |
LONG bytesReaded = 0;
|
|
Shinya Kitaoka |
120a6e |
LONG samplesReaded = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int rc = AVIStreamRead(m_videoStream, frameIndex, 1, bufferOut, bufferSize,
|
|
Shinya Kitaoka |
120a6e |
&bytesReaded, &samplesReaded);
|
|
Shinya Kitaoka |
120a6e |
if (!rc) {
|
|
Shinya Kitaoka |
120a6e |
assert(samplesReaded == 1); // deve aver letto un frame!!!
|
|
Shinya Kitaoka |
120a6e |
assert(bytesReaded <=
|
|
Shinya Kitaoka |
120a6e |
(LONG)bufferSize); // deve aver letto un numero di byte
|
|
Shinya Kitaoka |
120a6e |
// minore o uguale di quello che ci aspettiamo
|
|
Shinya Kitaoka |
120a6e |
bufferSize = bytesReaded;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return rc;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
DWORD TLevelReaderAvi::decompressFrame(void *srcBuffer, int srcSize,
|
|
Shinya Kitaoka |
120a6e |
void *dstBuffer, int currentFrame,
|
|
Shinya Kitaoka |
120a6e |
int desiredFrame) {
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFOHEADER srcHeader = m_srcBitmapInfo->bmiHeader;
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFOHEADER dstHeader = m_dstBitmapInfo->bmiHeader;
|
|
Shinya Kitaoka |
120a6e |
srcHeader.biSizeImage = srcSize;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
DWORD dwFlags = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!isAKeyFrame(m_videoStream, currentFrame))
|
|
Shinya Kitaoka |
120a6e |
dwFlags |= ICDECOMPRESS_NOTKEYFRAME;
|
|
Shinya Kitaoka |
120a6e |
if (currentFrame < desiredFrame) dwFlags |= ICDECOMPRESS_PREROLL;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
DWORD res = ICDecompress(m_hic, dwFlags, &srcHeader, srcBuffer, &dstHeader,
|
|
Shinya Kitaoka |
120a6e |
dstBuffer);
|
|
Shinya Kitaoka |
120a6e |
return res;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Shinya Kitaoka |
120a6e |
TLevelReaderAvi::TLevelReaderAvi(const TFilePath &path)::TLevelReader(path) {}
|
|
Toshihiro Shimizu |
890ddd |
TLevelReaderAvi::~TLevelReaderAvi() {}
|
|
Toshihiro Shimizu |
890ddd |
TLevelP TLevelReaderAvi::loadInfo() { return TLevelP(); }
|
|
Shinya Kitaoka |
120a6e |
TImageReaderP TLevelReaderAvi::getFrameReader(TFrameId fid) {
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(m_path, "AVI not supported");
|
|
Shinya Kitaoka |
120a6e |
return TImageReaderP(0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
TDimension TLevelReaderAvi::getSize() { return TDimension(); }
|
|
Shinya Kitaoka |
120a6e |
TImageP TLevelReaderAvi::load(int frameIndex) {
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(m_path, "AVI not supported");
|
|
Shinya Kitaoka |
120a6e |
return TImageP(0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// Tiio::AviWriterProperties
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Shinya Kitaoka |
ba547e |
|
|
Shinya Kitaoka |
ba547e |
namespace {
|
|
Shinya Kitaoka |
120a6e |
BOOL safe_ICInfo(DWORD fccType, DWORD fccHandler, ICINFO *lpicinfo) {
|
|
Shinya Kitaoka |
ba547e |
#ifdef _MSC_VER
|
|
Shinya Kitaoka |
120a6e |
__try {
|
|
Shinya Kitaoka |
120a6e |
return ICInfo(fccType, fccHandler, lpicinfo);
|
|
Shinya Kitaoka |
120a6e |
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return FALSE;
|
|
Shinya Kitaoka |
ba547e |
#else
|
|
Shinya Kitaoka |
120a6e |
return ICInfo(fccType, fccHandler, lpicinfo);
|
|
Shinya Kitaoka |
ba547e |
#endif
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
ba547e |
|
|
Shinya Kitaoka |
120a6e |
LRESULT safe_ICClose(HIC hic) {
|
|
Shinya Kitaoka |
ba547e |
#ifdef _MSC_VER
|
|
Shinya Kitaoka |
120a6e |
__try {
|
|
Shinya Kitaoka |
120a6e |
if (hic) {
|
|
Shinya Kitaoka |
120a6e |
return ICClose(hic);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
ba547e |
#else
|
|
Shinya Kitaoka |
120a6e |
if (hic) {
|
|
Shinya Kitaoka |
120a6e |
return ICClose(hic);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
ba547e |
#endif
|
|
Shinya Kitaoka |
120a6e |
return ICERR_OK;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
ba547e |
|
|
Shinya Kitaoka |
120a6e |
using hic_t =
|
|
Shinya Kitaoka |
120a6e |
std::unique_ptr<std::remove_pointer_t<hic>, decltype(&safe_ICClose)>;</std::remove_pointer_t<hic>
|
|
Shinya Kitaoka |
ba547e |
|
|
Shinya Kitaoka |
120a6e |
hic_t safe_ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode) {
|
|
Shinya Kitaoka |
ba547e |
#ifdef _MSC_VER
|
|
Shinya Kitaoka |
120a6e |
HIC const hic = [fccType, fccHandler, wMode]() -> HIC {
|
|
Shinya Kitaoka |
120a6e |
__try {
|
|
Shinya Kitaoka |
120a6e |
return ICOpen(fccType, fccHandler, wMode);
|
|
Shinya Kitaoka |
120a6e |
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return nullptr;
|
|
Shinya Kitaoka |
120a6e |
}();
|
|
Shinya Kitaoka |
ba547e |
#else
|
|
Shinya Kitaoka |
120a6e |
HIC hic = nullptr;
|
|
Shinya Kitaoka |
120a6e |
try {
|
|
Shinya Kitaoka |
120a6e |
hic = ICOpen(fccType, fccHandler, wMode);
|
|
Shinya Kitaoka |
120a6e |
} catch (...) {
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
ba547e |
#endif
|
|
Shinya Kitaoka |
120a6e |
return hic_t(hic, safe_ICClose);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
ba547e |
|
|
Shinya Kitaoka |
120a6e |
LRESULT safe_ICGetInfo(hic_t const &hic, ICINFO *picinfo, DWORD cb) {
|
|
Shinya Kitaoka |
ba547e |
#ifdef _MSC_VER
|
|
Shinya Kitaoka |
120a6e |
__try {
|
|
Shinya Kitaoka |
120a6e |
return ICGetInfo(hic.get(), picinfo, cb);
|
|
Shinya Kitaoka |
120a6e |
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return 0; // return copied size in bytes (0 means an error)
|
|
Shinya Kitaoka |
ba547e |
#else
|
|
Shinya Kitaoka |
120a6e |
return ICGetInfo(hic.get(), picinfo, cb);
|
|
Shinya Kitaoka |
ba547e |
#endif
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
ba547e |
|
|
Shinya Kitaoka |
120a6e |
LRESULT safe_ICCompressQuery(hic_t const &hic, BITMAPINFO *lpbiInput,
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFO *lpbiOutput) {
|
|
Shinya Kitaoka |
ba547e |
#ifdef _MSC_VER
|
|
Shinya Kitaoka |
120a6e |
__try {
|
|
Shinya Kitaoka |
120a6e |
return ICCompressQuery(hic.get(), lpbiInput, lpbiOutput);
|
|
Shinya Kitaoka |
120a6e |
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return ICERR_INTERNAL;
|
|
Shinya Kitaoka |
ba547e |
#else
|
|
Shinya Kitaoka |
120a6e |
return ICCompressQuery(hic.get(), lpbiInput, lpbiOutput);
|
|
Shinya Kitaoka |
ba547e |
#endif
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
ba547e |
}
|
|
Shinya Kitaoka |
ba547e |
|
|
Shinya Kitaoka |
120a6e |
Tiio::AviWriterProperties::AviWriterProperties() : m_codec("Codec") {
|
|
Shinya Kitaoka |
120a6e |
if (m_defaultCodec.getRange().empty()) {
|
|
Shinya Kitaoka |
120a6e |
char descr[2048], name[2048];
|
|
Shinya Kitaoka |
120a6e |
DWORD fccType = 0;
|
|
Shinya Kitaoka |
120a6e |
ICINFO icinfo;
|
|
Shinya Kitaoka |
120a6e |
BITMAPINFO inFmt;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_defaultCodec.addValue(L"Uncompressed");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
memset(&inFmt, 0, sizeof(BITMAPINFO));
|
|
Shinya Kitaoka |
120a6e |
inFmt.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
Shinya Kitaoka |
120a6e |
inFmt.bmiHeader.biWidth = 100;
|
|
Shinya Kitaoka |
120a6e |
inFmt.bmiHeader.biHeight = 100;
|
|
Shinya Kitaoka |
120a6e |
inFmt.bmiHeader.biPlanes = 1;
|
|
Shinya Kitaoka |
120a6e |
inFmt.bmiHeader.biCompression = BI_RGB;
|
|
Shinya Kitaoka |
120a6e |
for (int bpp = 32; bpp >= 24; bpp -= 8) {
|
|
Shinya Kitaoka |
120a6e |
inFmt.bmiHeader.biBitCount = bpp;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0;; i++) {
|
|
Shinya Kitaoka |
120a6e |
memset(&icinfo, 0, sizeof icinfo);
|
|
Shinya Kitaoka |
120a6e |
if (!safe_ICInfo(fccType, i, &icinfo)) {
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
auto const hic =
|
|
Shinya Kitaoka |
120a6e |
safe_ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_QUERY);
|
|
Shinya Kitaoka |
120a6e |
if (!hic) {
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Find out the compressor name
|
|
Shinya Kitaoka |
120a6e |
if (safe_ICGetInfo(hic, &icinfo, sizeof(ICINFO)) == 0) {
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
WideChar2Char(icinfo.szDescription, descr, sizeof(descr));
|
|
Shinya Kitaoka |
120a6e |
WideChar2Char(icinfo.szName, name, sizeof(name));
|
|
Shinya Kitaoka |
120a6e |
if ((strstr(name, "IYUV") != 0) ||
|
|
Shinya Kitaoka |
120a6e |
((strstr(name, "IR32") != 0) && (bpp == 24))) {
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::string compressorName;
|
|
Shinya Kitaoka |
120a6e |
compressorName = std::string(name) + " '" + std::to_string(bpp) + "' " +
|
|
Shinya Kitaoka |
120a6e |
std::string(descr);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// per il momento togliamo i codec indeo
|
|
Shinya Kitaoka |
120a6e |
if (std::string(compressorName).find("Indeo") != -1) {
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (safe_ICCompressQuery(hic, &inFmt, nullptr) != ICERR_OK) {
|
|
Shinya Kitaoka |
120a6e |
continue; // Skip this compressor if it can't handle the format.
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_defaultCodec.addValue(::to_wstring(compressorName));
|
|
Shinya Kitaoka |
120a6e |
if (compressorName.find("inepak") != -1) {
|
|
Shinya Kitaoka |
120a6e |
m_defaultCodec.setValue(::to_wstring(compressorName));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_codec = m_defaultCodec;
|
|
Shinya Kitaoka |
120a6e |
bind(m_codec);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TEnumProperty Tiio::AviWriterProperties::m_defaultCodec =
|
|
Shinya Kitaoka |
120a6e |
TEnumProperty("Codec");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|