|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifndef x64
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "texception.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tsound.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tconvert.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpropertytype.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "timageinfo.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tlevel_io.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "../avi/tiio_avi.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trasterimage.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tiio_mov.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "movsettings.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Local namespace stuff
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
3bfa54 |
const std::string firstFrameKey = "frst"; // First frame atom id
|
|
Toshihiro Shimizu |
890ddd |
const int firstFrameKeySize = 4 * sizeof(char); //
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class QuickTimeCleanUp;
|
|
Toshihiro Shimizu |
890ddd |
class QuickTimeStuff
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
static QuickTimeStuff *instance()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!m_singleton)
|
|
Toshihiro Shimizu |
890ddd |
m_singleton = new QuickTimeStuff();
|
|
Toshihiro Shimizu |
890ddd |
return m_singleton;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
OSErr getStatus() { return m_status; }
|
|
Toshihiro Shimizu |
890ddd |
~QuickTimeStuff()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
QuickTimeStuff() : m_status(noErr)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_status = InitializeQTML(0);
|
|
Toshihiro Shimizu |
890ddd |
EnterMovies();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static QuickTimeStuff *m_singleton;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
OSErr m_status;
|
|
Toshihiro Shimizu |
890ddd |
friend class QuickTimeCleanUp; //questa DEVE essere friend, cosi' posso controllare direttamente
|
|
Toshihiro Shimizu |
890ddd |
//lo stato del singleton.
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class QuickTimeCleanUp
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
QuickTimeCleanUp() {}
|
|
Toshihiro Shimizu |
890ddd |
~QuickTimeCleanUp()
|
|
Toshihiro Shimizu |
890ddd |
{ /*
|
|
Toshihiro Shimizu |
890ddd |
Nel caso si arrivasse qui senza il singleton instanziato, e si facesse direttamente
|
|
Toshihiro Shimizu |
890ddd |
'delete QuickTimeStuff::instance();' Quicktime non farebbe in tempo a terminare le
|
|
Toshihiro Shimizu |
890ddd |
sue routine di inizializzazione (che sono ANCHE su altri thread) e la chiamata a
|
|
Toshihiro Shimizu |
890ddd |
TerminateQTML() causerebbe un crash
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
if (QuickTimeStuff::m_singleton)
|
|
Toshihiro Shimizu |
890ddd |
delete QuickTimeStuff::m_singleton;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QuickTimeCleanUp cleanUp;
|
|
Toshihiro Shimizu |
890ddd |
QuickTimeStuff *QuickTimeStuff::m_singleton = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
enum QTLibError {
|
|
Toshihiro Shimizu |
890ddd |
QTNoError = 0x0000,
|
|
Toshihiro Shimizu |
890ddd |
QTNotInstalled,
|
|
Toshihiro Shimizu |
890ddd |
QTUnknownError,
|
|
Toshihiro Shimizu |
890ddd |
QTUnableToOpenFile,
|
|
Toshihiro Shimizu |
890ddd |
QTCantCreateFile,
|
|
Toshihiro Shimizu |
890ddd |
QTUnableToGetCompressorNames,
|
|
Toshihiro Shimizu |
890ddd |
QTUnableToCreateResource,
|
|
Toshihiro Shimizu |
890ddd |
QTUnableToUpdateMovie,
|
|
Toshihiro Shimizu |
890ddd |
QTBadTimeValue,
|
|
Toshihiro Shimizu |
890ddd |
QTUnableToDoMovieTask,
|
|
Toshihiro Shimizu |
890ddd |
QTUnableToSetTimeValue,
|
|
Toshihiro Shimizu |
890ddd |
QTUnableToSetMovieGWorld,
|
|
Toshihiro Shimizu |
890ddd |
QTUnableToSetMovieBox,
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
string buildQTErrorString(int ec)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
switch (ec) {
|
|
Toshihiro Shimizu |
890ddd |
case QTNotInstalled:
|
|
Toshihiro Shimizu |
890ddd |
return "Can't create; ensure that quicktime is correctly installed on your machine";
|
|
Toshihiro Shimizu |
890ddd |
case QTUnknownError:
|
|
Toshihiro Shimizu |
890ddd |
return "Unknown error";
|
|
Toshihiro Shimizu |
890ddd |
case QTUnableToOpenFile:
|
|
Toshihiro Shimizu |
890ddd |
return "can't open file";
|
|
Toshihiro Shimizu |
890ddd |
case QTCantCreateFile:
|
|
Toshihiro Shimizu |
890ddd |
return "can't create movie";
|
|
Toshihiro Shimizu |
890ddd |
case QTUnableToGetCompressorNames:
|
|
Toshihiro Shimizu |
890ddd |
return "unable to get compressor name";
|
|
Toshihiro Shimizu |
890ddd |
case QTUnableToCreateResource:
|
|
Toshihiro Shimizu |
890ddd |
return "can't create resource";
|
|
Toshihiro Shimizu |
890ddd |
case QTUnableToUpdateMovie:
|
|
Toshihiro Shimizu |
890ddd |
return "unable to update movie";
|
|
Toshihiro Shimizu |
890ddd |
case QTBadTimeValue:
|
|
Toshihiro Shimizu |
890ddd |
return "bad frame number";
|
|
Toshihiro Shimizu |
890ddd |
case QTUnableToDoMovieTask:
|
|
Toshihiro Shimizu |
890ddd |
return "unable to do movie task";
|
|
Toshihiro Shimizu |
890ddd |
case QTUnableToSetTimeValue:
|
|
Toshihiro Shimizu |
890ddd |
return "unable to set time value";
|
|
Toshihiro Shimizu |
890ddd |
case QTUnableToSetMovieGWorld:
|
|
Toshihiro Shimizu |
890ddd |
return "unable to set movie graphic world";
|
|
Toshihiro Shimizu |
890ddd |
case QTUnableToSetMovieBox:
|
|
Toshihiro Shimizu |
890ddd |
return "unable to set movie box";
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
default: {
|
|
Toshihiro Shimizu |
890ddd |
return "unknown error ('" + toString(ec) + "')";
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline LPSTR AtlW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars, UINT acp)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(lpw != NULL);
|
|
Toshihiro Shimizu |
890ddd |
assert(lpa != NULL);
|
|
Toshihiro Shimizu |
890ddd |
// verify that no illegal character present
|
|
Toshihiro Shimizu |
890ddd |
// since lpa was allocated based on the size of lpw
|
|
Toshihiro Shimizu |
890ddd |
// don't worry about the number of chars
|
|
Toshihiro Shimizu |
890ddd |
lpa[0] = '\0';
|
|
Toshihiro Shimizu |
890ddd |
WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL);
|
|
Toshihiro Shimizu |
890ddd |
return lpa;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline char *filePath2unichar(const TFilePath &path)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int _convert = 0;
|
|
Toshihiro Shimizu |
890ddd |
std::wstring ws = path.getWideString();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
LPCWSTR lpw = ws.c_str();
|
|
Toshihiro Shimizu |
890ddd |
char *name = NULL;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (lpw) {
|
|
Toshihiro Shimizu |
890ddd |
_convert = (lstrlenW(lpw) + 1) * 2;
|
|
Toshihiro Shimizu |
890ddd |
LPSTR pStr = new char[_convert];
|
|
Toshihiro Shimizu |
890ddd |
name = AtlW2AHelper(pStr, lpw, _convert, 0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
char *outName = new char[1024];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (QTMLGetCanonicalPathName(name, outName, 1024) == noErr) {
|
|
Toshihiro Shimizu |
890ddd |
delete[] name;
|
|
Toshihiro Shimizu |
890ddd |
return outName;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
delete[] outName;
|
|
Toshihiro Shimizu |
890ddd |
return name;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TFilePath getLegalName(const TFilePath &name)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (QuickTimeStuff::instance()->getStatus() != noErr)
|
|
Toshihiro Shimizu |
890ddd |
return name;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TFilePath legalName;
|
|
Toshihiro Shimizu |
890ddd |
char outDir[1024];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TFilePath dirName(name.getParentDir());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
char dirNameFp[1024] = "";
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
OSErr err = QTMLGetCanonicalPathName(dirNameFp, outDir, 1024);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (err == noErr)
|
|
Toshihiro Shimizu |
890ddd |
legalName = TFilePath(outDir) + name.withoutParentDir();
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
legalName = name;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return legalName;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
string long2fourchar(TINT32 fcc)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
string s;
|
|
Toshihiro Shimizu |
890ddd |
s += (char((fcc & 0xff000000) >> 24));
|
|
Toshihiro Shimizu |
890ddd |
s += (char((fcc & 0x00ff0000) >> 16));
|
|
Toshihiro Shimizu |
890ddd |
s += (char((fcc & 0x0000ff00) >> 8));
|
|
Toshihiro Shimizu |
890ddd |
s += (char((fcc & 0x000000ff) >> 0));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return s;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TimeScale frameRateToTimeScale(double frameRate)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return tround(frameRate * 100.0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
3bfa54 |
//const std::string CodecNamesId = "PU_CodecName";
|
|
Shinya Kitaoka |
3bfa54 |
//const std::string CodecQualityId = "PU_CodecQuality";
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} //namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool IsQuickTimeInstalled()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return QuickTimeStuff::instance()->getStatus() == noErr;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
// TImageWriterMov
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class TImageWriterMov : public TImageWriter
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterMov(const TFilePath &, int frameIndex, TLevelWriterMov *);
|
|
Toshihiro Shimizu |
890ddd |
~TImageWriterMov() { m_lwm->release(); }
|
|
Toshihiro Shimizu |
890ddd |
bool is64bitOutputSupported() { return false; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
//not implemented
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterMov(const TImageWriterMov &);
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterMov &operator=(const TImageWriterMov &src);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
void save(const TImageP &);
|
|
Toshihiro Shimizu |
890ddd |
int m_frameIndex;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
TLevelWriterMov *m_lwm;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
// TImageWriterMov
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterMov::TImageWriterMov(const TFilePath &path, int frameIndex, TLevelWriterMov *lwm)
|
|
Toshihiro Shimizu |
890ddd |
: TImageWriter(path), m_lwm(lwm), m_frameIndex(frameIndex)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_lwm->addRef();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
void copy(TRasterP rin, PixelXRGB *bufout, int lx, int ly)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TRaster32P rin32 = rin;
|
|
Toshihiro Shimizu |
890ddd |
assert(rin32);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PixelXRGB *rowout = &(bufout[(ly - 1) * lx]);
|
|
Toshihiro Shimizu |
890ddd |
rin32->lock();
|
|
Toshihiro Shimizu |
890ddd |
for (int y = 0; y < rin32->getLy(); y++) {
|
|
Toshihiro Shimizu |
890ddd |
PixelXRGB *pixout = rowout;
|
|
Toshihiro Shimizu |
890ddd |
TPixelRGBM32 *pixin = rin32->pixels(y);
|
|
Toshihiro Shimizu |
890ddd |
TPixelRGBM32 *pixinEnd = pixin + rin32->getLx();
|
|
Toshihiro Shimizu |
890ddd |
while (pixin < pixinEnd) {
|
|
Toshihiro Shimizu |
890ddd |
pixout->x = pixin->m;
|
|
Toshihiro Shimizu |
890ddd |
pixout->r = pixin->r;
|
|
Toshihiro Shimizu |
890ddd |
pixout->g = pixin->g;
|
|
Toshihiro Shimizu |
890ddd |
pixout->b = pixin->b;
|
|
Toshihiro Shimizu |
890ddd |
pixout++;
|
|
Toshihiro Shimizu |
890ddd |
pixin++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
rowout -= lx;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
rin32->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Shinya Kitaoka |
3bfa54 |
TWriterInfo *TWriterInfoMov::create(const std::string &)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return new TWriterInfoMov();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TWriterInfoMov::TWriterInfoMov(const TWriterInfoMov&src)
|
|
Toshihiro Shimizu |
890ddd |
:TWriterInfo(src)
|
|
Toshihiro Shimizu |
890ddd |
,m_codecTable(src.m_codecTable)
|
|
Toshihiro Shimizu |
890ddd |
,m_qualityTable(src.m_qualityTable)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TWriterInfo *TWriterInfoMov::clone() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return new TWriterInfoMov(*this);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
class MovWriterProperties : public TPropertyGroup {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TEnumProperty m_codec;
|
|
Toshihiro Shimizu |
890ddd |
TEnumProperty m_quality;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Tiio::TifWriterProperties::TifWriterProperties()
|
|
Toshihiro Shimizu |
890ddd |
: m_byteOrdering("Byte Order")
|
|
Toshihiro Shimizu |
890ddd |
, m_compressionType("Compression Type")
|
|
Toshihiro Shimizu |
890ddd |
, m_matte("Alpha Channel", true)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_byteOrdering.addValue(L"IBM PC");
|
|
Toshihiro Shimizu |
890ddd |
m_byteOrdering.addValue(L"Mac");
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Toshihiro Shimizu |
890ddd |
m_byteOrdering.setValue(L"IBM PC");
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Toshihiro Shimizu |
890ddd |
m_byteOrdering.setValue(L"Mac");
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_compressionType.addValue(L"NONE");
|
|
Toshihiro Shimizu |
890ddd |
m_compressionType.addValue(L"LZW");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bind(m_byteOrdering);
|
|
Toshihiro Shimizu |
890ddd |
bind(m_matte);
|
|
Toshihiro Shimizu |
890ddd |
bind(m_compressionType);
|
|
Toshihiro Shimizu |
890ddd |
m_compressionType.setValue(L"LZW");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
CodecType Tiio::MovWriterProperties::getCurrentCodec()const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
std::map<wstring, codectype="">::const_iterator it;</wstring,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
it = m_codecMap.find(m_codec.getValue());
|
|
Toshihiro Shimizu |
890ddd |
assert(it!=m_codecMap.end());
|
|
Toshihiro Shimizu |
890ddd |
return it->second;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
wstring Tiio::MovWriterProperties::getCurrentNameFromCodec(CodecType &cCodec)const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
std::map<wstring, codectype="">::const_iterator it;</wstring,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for(it=m_codecMap.begin();it!=m_codecMap.end();++it)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
CodecType tmp=it->second;
|
|
Toshihiro Shimizu |
890ddd |
if(it->second==cCodec) break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
assert(it!=m_codecMap.end());
|
|
Toshihiro Shimizu |
890ddd |
return it->first;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
wstring Tiio::MovWriterProperties::getCurrentQualityFromCodeQ(CodecQ &cCodecQ)const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
std::map<wstring, codecq="">::const_iterator it;</wstring,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for(it=m_qualityMap.begin();it!=m_qualityMap.end();++it)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
CodecQ tmp=it->second;
|
|
Toshihiro Shimizu |
890ddd |
if(it->second==cCodecQ) break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
assert(it!=m_qualityMap.end());
|
|
Toshihiro Shimizu |
890ddd |
return it->first;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CodecQ Tiio::MovWriterProperties::getCurrentQuality() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
std::map<wstring, codecq="">::const_iterator it;</wstring,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
it = m_qualityMap.find(m_quality.getValue());
|
|
Toshihiro Shimizu |
890ddd |
assert(it!=m_qualityMap.end());
|
|
Toshihiro Shimizu |
890ddd |
return it->second;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
TPropertyGroup* Tiio::MovWriterProperties::clone() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
MovWriterProperties*g = new MovWriterProperties();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
g->m_codec.setValue(m_codec.getValue());
|
|
Toshihiro Shimizu |
890ddd |
g->m_quality.setValue(m_quality.getValue());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return (TPropertyGroup*)g;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Tiio::MovWriterProperties::MovWriterProperties()
|
|
Toshihiro Shimizu |
890ddd |
//: m_codec("Codec")
|
|
Toshihiro Shimizu |
890ddd |
//, m_quality("Quality")
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (InitializeQTML(0) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ComponentInstance ci = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType);
|
|
Toshihiro Shimizu |
890ddd |
QTAtomContainer settings;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (SCGetSettingsAsAtomContainer(ci, &settings) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
assert(false);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
fromAtomsToProperties(settings, *this);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TImageWriterMov::save(const TImageP &img)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_lwm->save(img, m_frameIndex);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TLevelWriterMov::save(const TImageP &img, int frameIndex)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_firstFrame = tmin(frameIndex, m_firstFrame);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterImageP image(img);
|
|
Toshihiro Shimizu |
890ddd |
if (!image)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "Unsupported image type");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int lx = image->getRaster()->getLx();
|
|
Toshihiro Shimizu |
890ddd |
int ly = image->getRaster()->getLy();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int pixSize = image->getRaster()->getPixelSize();
|
|
Toshihiro Shimizu |
890ddd |
if (pixSize != 4)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "Unsupported pixel type");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker sl(&m_mutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_videoTrack) {
|
|
Toshihiro Shimizu |
890ddd |
if (!m_properties)
|
|
Toshihiro Shimizu |
890ddd |
m_properties = new Tiio::MovWriterProperties();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Tiio::MovWriterProperties *prop = (Tiio::MovWriterProperties *)(m_properties);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QTAtomContainer atoms;
|
|
Toshihiro Shimizu |
890ddd |
QTNewAtomContainer(&atoms);
|
|
Toshihiro Shimizu |
890ddd |
fromPropertiesToAtoms(*prop, atoms);
|
|
Toshihiro Shimizu |
890ddd |
m_ci = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType);
|
|
Toshihiro Shimizu |
890ddd |
if (SCSetSettingsFromAtomContainer(m_ci, atoms) != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
CloseComponent(m_ci);
|
|
Toshihiro Shimizu |
890ddd |
assert(!"cannot use that quickTime codec, use default");
|
|
Toshihiro Shimizu |
890ddd |
m_ci = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QTDisposeAtomContainer(atoms);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Rect frame;
|
|
Toshihiro Shimizu |
890ddd |
QDErr err;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (QuickTimeStuff::instance()->getStatus() != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTNotInstalled;
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, buildQTErrorString(m_IOError));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// First, set the movie's time scale to match a suitable multiple of m_frameRate.
|
|
Toshihiro Shimizu |
890ddd |
// The timeScale will be used for both the movie and media.
|
|
Toshihiro Shimizu |
890ddd |
TimeScale timeScale = ::frameRateToTimeScale(m_frameRate);
|
|
Toshihiro Shimizu |
890ddd |
SetMovieTimeScale(m_movie, timeScale);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_videoTrack = NewMovieTrack(m_movie, FixRatio((short)lx, 1), FixRatio((short)ly, 1), kNoVolume);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((err = GetMoviesError() != noErr))
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't create video track");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_videoMedia = NewTrackMedia(m_videoTrack, VideoMediaType, timeScale, 0, 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((err = GetMoviesError() != noErr))
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't create video media");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
frame.left = 0;
|
|
Toshihiro Shimizu |
890ddd |
frame.top = 0;
|
|
Toshihiro Shimizu |
890ddd |
frame.right = lx;
|
|
Toshihiro Shimizu |
890ddd |
frame.bottom = ly;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((err = NewGWorld(&(m_gworld), pixSize * 8, &frame, 0, 0, 0)) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't create movie buffer");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
LockPixels(m_gworld->portPixMap);
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
if ((err = ImageCodecGetMaxCompressionSize(Ci, m_gworld->portPixMap, &frame, 0,
|
|
Toshihiro Shimizu |
890ddd |
quality, codecType, anyCodec,
|
|
Toshihiro Shimizu |
890ddd |
&max_compressed_size))!=noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't get max compression size");
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((err = MemError()) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't allocate img handle");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_pixmap = GetGWorldPixMap(m_gworld);
|
|
Toshihiro Shimizu |
890ddd |
if (!LockPixels(m_pixmap))
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't lock pixels");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_buf = (PixelXRGB *)(*(m_pixmap))->baseAddr;
|
|
Toshihiro Shimizu |
890ddd |
buf_lx = lx;
|
|
Toshihiro Shimizu |
890ddd |
buf_ly = ly;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
OSErr err = noErr;
|
|
Toshihiro Shimizu |
890ddd |
if ((err = BeginMediaEdits(m_videoMedia)) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't begin edit video media");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Rect frame;
|
|
Toshihiro Shimizu |
890ddd |
ImageDescriptionHandle img_descr = 0;
|
|
Toshihiro Shimizu |
890ddd |
Handle compressedData = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
frame.left = 0;
|
|
Toshihiro Shimizu |
890ddd |
frame.top = 0;
|
|
Toshihiro Shimizu |
890ddd |
frame.right = lx;
|
|
Toshihiro Shimizu |
890ddd |
frame.bottom = ly;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterP ras = image->getRaster();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
copy(ras, m_buf, buf_lx, buf_ly);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((err = SCCompressImage(m_ci,
|
|
Toshihiro Shimizu |
890ddd |
m_gworld->portPixMap,
|
|
Toshihiro Shimizu |
890ddd |
&frame,
|
|
Toshihiro Shimizu |
890ddd |
&img_descr,
|
|
Toshihiro Shimizu |
890ddd |
&compressedData)) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't compress image");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
if ((err = CompressImage(m_gworld->portPixMap,
|
|
Toshihiro Shimizu |
890ddd |
&frame,
|
|
Toshihiro Shimizu |
890ddd |
quality, codecType,
|
|
Toshihiro Shimizu |
890ddd |
img_descr, compressed_data_ptr))!=noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't compress image");
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TimeValue sampleTime;
|
|
Toshihiro Shimizu |
890ddd |
if ((err = AddMediaSample(m_videoMedia, compressedData, 0,
|
|
Toshihiro Shimizu |
890ddd |
(*img_descr)->dataSize, 100, // 100 matches the length of 1 frame
|
|
Toshihiro Shimizu |
890ddd |
(SampleDescriptionHandle)img_descr, // in the movie/media's timeScale
|
|
Toshihiro Shimizu |
890ddd |
1, 0, &sampleTime)) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't add image to movie media");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((err = EndMediaEdits(m_videoMedia)) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't end edit media");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DisposeHandle(compressedData);
|
|
Toshihiro Shimizu |
890ddd |
DisposeHandle((Handle)img_descr);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_savedFrames.push_back(std::pair<int, timevalue="">(frameIndex, sampleTime));</int,>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
// TLevelWriterMov
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelWriterMov::TLevelWriterMov(const TFilePath &path, TPropertyGroup *winfo)
|
|
Toshihiro Shimizu |
890ddd |
: TLevelWriter(path, winfo), m_IOError(QTNoError), m_pixmap(0), m_gworld(0), m_videoMedia(0), m_soundMedia(0), m_videoTrack(0), m_soundTrack(0), m_movie(0), m_firstFrame((std::numeric_limits<int>::max)())</int>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_frameRate = 12.;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
char *pStr = filePath2unichar(m_path);
|
|
Toshihiro Shimizu |
890ddd |
QDErr err;
|
|
Toshihiro Shimizu |
890ddd |
FSSpec fspec;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((err = NativePathNameToFSSpec(pStr, &fspec, kFullNativePath)) != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
delete[] pStr;
|
|
Toshihiro Shimizu |
890ddd |
pStr = 0;
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTUnableToOpenFile;
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, buildQTErrorString(m_IOError));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
delete[] pStr;
|
|
Toshihiro Shimizu |
890ddd |
pStr = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (err = CreateMovieFile(&fspec, 'TVOD', smCurrentScript,
|
|
Toshihiro Shimizu |
890ddd |
createMovieFileDeleteCurFile | createMovieFileDontCreateResFile,
|
|
Toshihiro Shimizu |
890ddd |
&(m_refNum), &(m_movie)) != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTCantCreateFile;
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, buildQTErrorString(m_IOError));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
#define FailIf(cond, handler) \
|
|
Toshihiro Shimizu |
890ddd |
if (cond) { \
|
|
Toshihiro Shimizu |
890ddd |
DebugStr((ConstStr255Param) #cond " goto " #handler); \
|
|
Toshihiro Shimizu |
890ddd |
goto handler; \
|
|
Toshihiro Shimizu |
890ddd |
} else \
|
|
Toshihiro Shimizu |
890ddd |
0
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Toshihiro Shimizu |
890ddd |
#define FailIf(cond, handler) \
|
|
Toshihiro Shimizu |
890ddd |
if (cond) { \
|
|
Toshihiro Shimizu |
890ddd |
goto handler; \
|
|
Toshihiro Shimizu |
890ddd |
} else \
|
|
Toshihiro Shimizu |
890ddd |
0
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
#define FailWithAction(cond, action, handler) \
|
|
Toshihiro Shimizu |
890ddd |
if (cond) { \
|
|
Toshihiro Shimizu |
890ddd |
DebugStr((ConstStr255Param) #cond " goto " #handler); \
|
|
Toshihiro Shimizu |
890ddd |
{ \
|
|
Toshihiro Shimizu |
890ddd |
action; \
|
|
Toshihiro Shimizu |
890ddd |
} \
|
|
Toshihiro Shimizu |
890ddd |
goto handler; \
|
|
Toshihiro Shimizu |
890ddd |
} else \
|
|
Toshihiro Shimizu |
890ddd |
0
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Toshihiro Shimizu |
890ddd |
#define FailWithAction(cond, action, handler) \
|
|
Toshihiro Shimizu |
890ddd |
if (cond) { \
|
|
Toshihiro Shimizu |
890ddd |
{ \
|
|
Toshihiro Shimizu |
890ddd |
action; \
|
|
Toshihiro Shimizu |
890ddd |
} \
|
|
Toshihiro Shimizu |
890ddd |
goto handler; \
|
|
Toshihiro Shimizu |
890ddd |
} else \
|
|
Toshihiro Shimizu |
890ddd |
0
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TLevelWriterMov::saveSoundTrack(TSoundTrack *st)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
OSErr myErr = noErr;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!st)
|
|
Toshihiro Shimizu |
890ddd |
throw TException("null reference to soundtrack");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (st->getBitPerSample() != 16)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, "Only 16 bits per sample is supported");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_soundTrack == 0) {
|
|
Toshihiro Shimizu |
890ddd |
m_soundTrack = NewMovieTrack(m_movie, 0, 0, kFullVolume);
|
|
Toshihiro Shimizu |
890ddd |
myErr = GetMoviesError();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
FailIf(myErr != noErr, CompressErr);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_soundMedia = NewTrackMedia(m_soundTrack, SoundMediaType, st->getSampleRate(), NULL, 0); //track->rate >> 16
|
|
Toshihiro Shimizu |
890ddd |
myErr = GetMoviesError();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
FailIf(myErr != noErr, Exit);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
SoundDescriptionV1Handle mySampleDesc;
|
|
Toshihiro Shimizu |
890ddd |
Handle myDestHandle;
|
|
Toshihiro Shimizu |
890ddd |
SoundComponentData sourceInfo;
|
|
Toshihiro Shimizu |
890ddd |
SoundComponentData destInfo;
|
|
Toshihiro Shimizu |
890ddd |
SoundConverter converter;
|
|
Toshihiro Shimizu |
890ddd |
CompressionInfo compressionInfo;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
myDestHandle = NewHandle(0);
|
|
Toshihiro Shimizu |
890ddd |
FailWithAction(myDestHandle == NULL, myErr = MemError(), NoDest);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
*myDestHandle = (char *)st->getRawData();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// start a media editing session
|
|
Toshihiro Shimizu |
890ddd |
myErr = BeginMediaEdits(m_soundMedia);
|
|
Toshihiro Shimizu |
890ddd |
FailIf(myErr != noErr, Exit);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
sourceInfo.flags = 0x0;
|
|
Toshihiro Shimizu |
890ddd |
sourceInfo.format = kSoundNotCompressed;
|
|
Toshihiro Shimizu |
890ddd |
sourceInfo.numChannels = st->getChannelCount();
|
|
Toshihiro Shimizu |
890ddd |
sourceInfo.sampleSize = st->getBitPerSample();
|
|
Toshihiro Shimizu |
890ddd |
sourceInfo.sampleRate = st->getSampleRate();
|
|
Toshihiro Shimizu |
890ddd |
sourceInfo.sampleCount = st->getSampleCount();
|
|
Toshihiro Shimizu |
890ddd |
sourceInfo.buffer = (unsigned char *)st->getRawData();
|
|
Toshihiro Shimizu |
890ddd |
sourceInfo.reserved = 0x0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
destInfo.flags = kNoSampleRateConversion | kNoSampleSizeConversion |
|
|
Toshihiro Shimizu |
890ddd |
kNoSampleFormatConversion | kNoChannelConversion |
|
|
Toshihiro Shimizu |
890ddd |
kNoDecompression | kNoVolumeConversion |
|
|
Toshihiro Shimizu |
890ddd |
kNoRealtimeProcessing;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
destInfo.format = k16BitNativeEndianFormat;
|
|
Toshihiro Shimizu |
890ddd |
destInfo.numChannels = st->getChannelCount();
|
|
Toshihiro Shimizu |
890ddd |
destInfo.sampleSize = st->getBitPerSample();
|
|
Toshihiro Shimizu |
890ddd |
destInfo.sampleRate = st->getSampleRate();
|
|
Toshihiro Shimizu |
890ddd |
destInfo.sampleCount = st->getSampleCount();
|
|
Toshihiro Shimizu |
890ddd |
destInfo.buffer = (unsigned char *)st->getRawData();
|
|
Toshihiro Shimizu |
890ddd |
destInfo.reserved = 0x0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
SoundConverterOpen(&sourceInfo, &destInfo, &converter);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
myErr = SoundConverterGetInfo(converter, siCompressionFactor, &compressionInfo);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
myErr = SoundConverterGetInfo(converter, siCompressionFactor, &compressionInfo);
|
|
Toshihiro Shimizu |
890ddd |
myErr = GetCompressionInfo(fixedCompression, sourceInfo.format, sourceInfo.numChannels, sourceInfo.sampleSize, &compressionInfo);
|
|
Toshihiro Shimizu |
890ddd |
FailIf(myErr != noErr, ConverterErr);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
compressionInfo.bytesPerFrame = compressionInfo.bytesPerPacket * destInfo.numChannels;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//////////
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// create a sound sample description
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//////////
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// use the SoundDescription format 1 because it adds fields for data size information
|
|
Toshihiro Shimizu |
890ddd |
// and is required by AddSoundDescriptionExtension if an extension is required for the compression format
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
mySampleDesc = (SoundDescriptionV1Handle)NewHandleClear(sizeof(SoundDescriptionV1));
|
|
Toshihiro Shimizu |
890ddd |
FailWithAction(myErr != noErr, myErr = MemError(), Exit);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.descSize = sizeof(SoundDescriptionV1);
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.dataFormat = destInfo.format;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.resvd1 = 0;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.resvd2 = 0;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.dataRefIndex = 1;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.version = 1;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.revlevel = 0;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.vendor = 0;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.numChannels = destInfo.numChannels;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.sampleSize = destInfo.sampleSize;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.compressionID = 0;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.packetSize = 0;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).desc.sampleRate = st->getSampleRate() << 16;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).samplesPerPacket = compressionInfo.samplesPerPacket;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).bytesPerPacket = compressionInfo.bytesPerPacket;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).bytesPerFrame = compressionInfo.bytesPerFrame;
|
|
Toshihiro Shimizu |
890ddd |
(**mySampleDesc).bytesPerSample = compressionInfo.bytesPerSample;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//////////
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// add samples to the media
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//////////
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
myErr = AddMediaSample(m_soundMedia, myDestHandle,
|
|
Toshihiro Shimizu |
890ddd |
0,
|
|
Toshihiro Shimizu |
890ddd |
destInfo.sampleCount * compressionInfo.bytesPerFrame,
|
|
Toshihiro Shimizu |
890ddd |
1,
|
|
Toshihiro Shimizu |
890ddd |
(SampleDescriptionHandle)mySampleDesc,
|
|
Toshihiro Shimizu |
890ddd |
destInfo.sampleCount * compressionInfo.samplesPerPacket,
|
|
Toshihiro Shimizu |
890ddd |
0,
|
|
Toshihiro Shimizu |
890ddd |
NULL);
|
|
Toshihiro Shimizu |
890ddd |
FailIf(myErr != noErr, MediaErr);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
myErr = EndMediaEdits(m_soundMedia);
|
|
Toshihiro Shimizu |
890ddd |
FailIf(myErr != noErr, MediaErr);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// NOTE: Sound media is inserted into the movie track only at destruction
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ConverterErr: // Multiple bailout labels just to
|
|
Toshihiro Shimizu |
890ddd |
NoDest: // separate debugging strings, it seems.
|
|
Toshihiro Shimizu |
890ddd |
CompressErr: //
|
|
Toshihiro Shimizu |
890ddd |
Exit: // Should be done better...
|
|
Toshihiro Shimizu |
890ddd |
MediaErr: //
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (mySampleDesc != NULL)
|
|
Toshihiro Shimizu |
890ddd |
DisposeHandle((Handle)mySampleDesc);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (converter)
|
|
Toshihiro Shimizu |
890ddd |
SoundConverterClose(converter);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (myErr != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, "error saving audio track");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelWriterMov::~TLevelWriterMov()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_pixmap)
|
|
Toshihiro Shimizu |
890ddd |
UnlockPixels(m_pixmap);
|
|
Toshihiro Shimizu |
890ddd |
if (m_gworld && m_gworld->portPixMap)
|
|
Toshihiro Shimizu |
890ddd |
UnlockPixels(m_gworld->portPixMap);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_gworld)
|
|
Toshihiro Shimizu |
890ddd |
DisposeGWorld(m_gworld);
|
|
Toshihiro Shimizu |
890ddd |
if (m_ci)
|
|
Toshihiro Shimizu |
890ddd |
CloseComponent(m_ci);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QDErr err;
|
|
Toshihiro Shimizu |
890ddd |
OSStatus mderr;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_videoTrack) {
|
|
Toshihiro Shimizu |
890ddd |
// Insert the saved Frames into the track.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// NOTE: Holes in the frames sequence will be intended as still frames, rather than left blank.
|
|
Toshihiro Shimizu |
890ddd |
// I'm quite unsure whether this behavior is actually useful - or used at all.
|
|
Toshihiro Shimizu |
890ddd |
// In particular, the last frame is an exception, and does NOT drag to the end of the
|
|
Toshihiro Shimizu |
890ddd |
// movie (see below). I think it's not used - frames are consecutive AFAIK.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TimeValue movieTimeScale = GetMovieTimeScale(m_movie);
|
|
Toshihiro Shimizu |
890ddd |
int savedFramesSize = (int)m_savedFrames.size() - 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < savedFramesSize; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
TimeValue mediaPosition = m_savedFrames[i].second;
|
|
Toshihiro Shimizu |
890ddd |
TimeValue trackPosition = ((m_savedFrames[i].first - m_firstFrame) * movieTimeScale) / m_frameRate;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TimeValue duration = m_savedFrames[i + 1].first - m_savedFrames[i].first;
|
|
Toshihiro Shimizu |
890ddd |
Fixed ratio = tround(fixed1 / (double)duration);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((err =
|
|
Toshihiro Shimizu |
890ddd |
InsertMediaIntoTrack(m_videoTrack, trackPosition, mediaPosition, 100, ratio)) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't insert media into track");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (savedFramesSize >= 0) {
|
|
Toshihiro Shimizu |
890ddd |
TimeValue mediaPosition = m_savedFrames[i].second;
|
|
Toshihiro Shimizu |
890ddd |
TimeValue trackPosition = ((m_savedFrames[i].first - m_firstFrame) * movieTimeScale) / m_frameRate;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// The last frame has duration 1 (frame):
|
|
Toshihiro Shimizu |
890ddd |
// duration = 1 => ratio = fixed1
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((err =
|
|
Toshihiro Shimizu |
890ddd |
InsertMediaIntoTrack(m_videoTrack, trackPosition, mediaPosition, 100, fixed1)) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't insert media into track");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QTMetaDataRef metaDataRef;
|
|
Toshihiro Shimizu |
890ddd |
if ((mderr = QTCopyMovieMetaData(m_movie, &metaDataRef)) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't access metadata informations");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((mderr =
|
|
Toshihiro Shimizu |
890ddd |
QTMetaDataAddItem(
|
|
Toshihiro Shimizu |
890ddd |
metaDataRef,
|
|
Toshihiro Shimizu |
890ddd |
kQTMetaDataStorageFormatUserData,
|
|
Toshihiro Shimizu |
890ddd |
kQTMetaDataKeyFormatUserData,
|
|
Toshihiro Shimizu |
890ddd |
(const UInt8 *)firstFrameKey.c_str(),
|
|
Toshihiro Shimizu |
890ddd |
firstFrameKeySize,
|
|
Toshihiro Shimizu |
890ddd |
(const UInt8 *)(&m_firstFrame),
|
|
Toshihiro Shimizu |
890ddd |
sizeof(int),
|
|
Toshihiro Shimizu |
890ddd |
kQTMetaDataTypeUnsignedIntegerBE,
|
|
Toshihiro Shimizu |
890ddd |
0)) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't insert metadata informations");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QTMetaDataRelease(metaDataRef);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_soundTrack) {
|
|
Toshihiro Shimizu |
890ddd |
if (0 != (err = InsertMediaIntoTrack(m_soundTrack, 0, 0, GetMediaDuration(m_soundMedia), fixed1)))
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(getFilePath(), "can't insert sound into track");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
short resId = movieInDataForkResID;
|
|
Toshihiro Shimizu |
890ddd |
if (m_movie) {
|
|
Toshihiro Shimizu |
890ddd |
if ((err = AddMovieResource(m_movie, m_refNum, &resId, 0)) != noErr) // Why no thrown exception here?
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
} // throw TImageException(getFilePath(), "Can't add resource"); //
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_videoMedia) // And anyway, how exceptions
|
|
Toshihiro Shimizu |
890ddd |
DisposeTrackMedia(m_videoMedia); // deal with absence of corresponding
|
|
Toshihiro Shimizu |
890ddd |
if (m_videoTrack) // disposals?
|
|
Toshihiro Shimizu |
890ddd |
DisposeMovieTrack(m_videoTrack); // I guess se should use RAII here... -.-'
|
|
Toshihiro Shimizu |
890ddd |
if (m_soundMedia)
|
|
Toshihiro Shimizu |
890ddd |
DisposeTrackMedia(m_soundMedia);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_refNum)
|
|
Toshihiro Shimizu |
890ddd |
CloseMovieFile(m_refNum);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DisposeMovie(m_movie);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterP TLevelWriterMov::getFrameWriter(TFrameId fid)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_IOError)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, buildQTErrorString(m_IOError));
|
|
Toshihiro Shimizu |
890ddd |
if (fid.getLetter() != 0)
|
|
Toshihiro Shimizu |
890ddd |
return TImageWriterP(0);
|
|
Toshihiro Shimizu |
890ddd |
int index = fid.getNumber() - 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterMov *iwm = new TImageWriterMov(m_path, index, this);
|
|
Toshihiro Shimizu |
890ddd |
return TImageWriterP(iwm);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelReaderMov::TLevelReaderMov(const TFilePath &path)
|
|
Toshihiro Shimizu |
890ddd |
: TLevelReader(path), m_IOError(QTNoError), m_track(0), m_movie(0), m_depth(0), m_readAsToonzOutput(false), m_yMirror(true), m_loadTimecode(false)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
FSSpec fspec;
|
|
Toshihiro Shimizu |
890ddd |
QDErr err;
|
|
Toshihiro Shimizu |
890ddd |
Boolean dataRefWasChanged;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (QuickTimeStuff::instance()->getStatus() != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTNotInstalled;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
char *pStr = filePath2unichar(m_path);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((err = NativePathNameToFSSpec(pStr, &fspec, kFullNativePath)) != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
delete[] pStr;
|
|
Toshihiro Shimizu |
890ddd |
pStr = 0;
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(path, "can't open file");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
delete[] pStr;
|
|
Toshihiro Shimizu |
890ddd |
pStr = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((err = OpenMovieFile(&fspec, &m_refNum, fsRdPerm))) {
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTUnableToOpenFile;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
short resId = 0;
|
|
Toshihiro Shimizu |
890ddd |
Str255 name;
|
|
Toshihiro Shimizu |
890ddd |
err = NewMovieFromFile(&m_movie, m_refNum, &resId,
|
|
Toshihiro Shimizu |
890ddd |
name, fsRdPerm, &dataRefWasChanged);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int numTracks = GetMovieTrackCount(m_movie);
|
|
Toshihiro Shimizu |
890ddd |
if (numTracks < 1) {
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTUnableToOpenFile;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(numTracks == 1 || numTracks == 2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_track = GetMovieIndTrackType(m_movie, 1, VideoMediaType, movieTrackMediaType);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ImageDescriptionHandle imageH;
|
|
Toshihiro Shimizu |
890ddd |
imageH = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TINT32 index = 1;
|
|
Toshihiro Shimizu |
890ddd |
Media theMedia = GetTrackMedia(m_track);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
GetMediaSampleDescription(theMedia, index, (SampleDescriptionHandle)imageH);
|
|
Toshihiro Shimizu |
890ddd |
ImageDescriptionPtr imagePtr = *imageH;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((imagePtr->cType >> 16) == 0x4458 /*'DX'*/ && path.getType() == "avi") // DIVX - compressed, QT is unable to read it.
|
|
Toshihiro Shimizu |
890ddd |
{ // Done externally with the... AVI reader o_o.
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTUnableToDoMovieTask;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Retrieve the timecode media handler
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
Track tcTrack = GetMovieIndTrackType(m_movie, 1, TimeCodeMediaType, movieTrackMediaType);
|
|
Toshihiro Shimizu |
890ddd |
Media tcMedia = GetTrackMedia(tcTrack);
|
|
Toshihiro Shimizu |
890ddd |
m_timecodeHandler = GetMediaHandler(tcMedia);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_lx = imagePtr->width;
|
|
Toshihiro Shimizu |
890ddd |
m_ly = imagePtr->height;
|
|
Toshihiro Shimizu |
890ddd |
m_depth = imagePtr->depth;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_info = new TImageInfo();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_info->m_lx = m_lx;
|
|
Toshihiro Shimizu |
890ddd |
m_info->m_ly = m_ly;
|
|
Toshihiro Shimizu |
890ddd |
m_info->m_frameRate = GetMediaTimeScale(theMedia) / 100.0; // REMOVE THIS! Not all movs have this
|
|
Toshihiro Shimizu |
890ddd |
// kind of format - only those from Toonz...
|
|
Toshihiro Shimizu |
890ddd |
Tiio::MovWriterProperties *prop = new Tiio::MovWriterProperties();
|
|
Toshihiro Shimizu |
890ddd |
m_info->m_properties = prop;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DisposeHandle((Handle)imageH);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelReaderMov::~TLevelReaderMov()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
StopMovie(m_movie);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_refNum)
|
|
Toshihiro Shimizu |
890ddd |
CloseMovieFile(m_refNum);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_movie)
|
|
Toshihiro Shimizu |
890ddd |
DisposeMovie(m_movie);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TLevelReaderMov::loadedTimecode(UCHAR &hh, UCHAR &mm, UCHAR &ss, UCHAR &ff)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
hh = m_hh, mm = m_mm, ss = m_ss, ff = m_ff;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TLevelReaderMov::setYMirror(bool enabled)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_yMirror = enabled;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TLevelReaderMov::setLoadTimecode(bool enabled)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_loadTimecode = enabled;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TLevelReaderMov::enableRandomAccessRead(bool enable)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_readAsToonzOutput = enable;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
// TImageReaderMov
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class TImageReaderMov : public TImageReader
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TLevelReaderMov *m_lrm;
|
|
Toshihiro Shimizu |
890ddd |
TImageInfo *m_info;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
int m_frameIndex;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TImageReaderMov(const TFilePath &, int frameIndex, TLevelReaderMov *, TImageInfo *);
|
|
Toshihiro Shimizu |
890ddd |
~TImageReaderMov() { m_lrm->release(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageP load();
|
|
Toshihiro Shimizu |
890ddd |
void load(const TRasterP &rasP, const TPoint &pos = TPoint(0, 0), int shrinkX = 1, int shrinkY = 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TDimension getSize() const { return m_lrm->getSize(); }
|
|
Toshihiro Shimizu |
890ddd |
TRect getBBox() const { return m_lrm->getBBox(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TImageInfo *getImageInfo() const { return m_info; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
// Not copyable
|
|
Toshihiro Shimizu |
890ddd |
TImageReaderMov(const TImageReaderMov &);
|
|
Toshihiro Shimizu |
890ddd |
TImageReaderMov &operator=(const TImageReaderMov &);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageReaderMov::TImageReaderMov(const TFilePath &path, int frameIndex, TLevelReaderMov *lrm, TImageInfo *info)
|
|
Toshihiro Shimizu |
890ddd |
: TImageReader(path), m_lrm(lrm), m_frameIndex(frameIndex), m_info(info)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_lrm->addRef();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelP TLevelReaderMov::loadInfo()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_readAsToonzOutput) // Mov files written with Toonz support special
|
|
Toshihiro Shimizu |
890ddd |
return loadToonzOutputFormatInfo(); // metadata atoms - separate procedure
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Level is NOT a recognized mov from Toonz. Just read each movie's interesting image as a consecutive
|
|
Toshihiro Shimizu |
890ddd |
// level frame.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelP level;
|
|
Toshihiro Shimizu |
890ddd |
if (m_IOError != QTNoError)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, buildQTErrorString(m_IOError));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
OSType mediaType = VisualMediaCharacteristic;
|
|
Toshihiro Shimizu |
890ddd |
TimeValue nextTime, currentTime;
|
|
Toshihiro Shimizu |
890ddd |
currentTime = 0;
|
|
Toshihiro Shimizu |
890ddd |
nextTime = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int f = 0; // 0 is the first frame index
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// io vorrei fare '|', ma sul manuale c'e' scritto '+'
|
|
Toshihiro Shimizu |
890ddd |
GetMovieNextInterestingTime(m_movie, nextTimeMediaSample + nextTimeEdgeOK, 1, &mediaType, currentTime, 0, &nextTime, 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (nextTime != -1) {
|
|
Toshihiro Shimizu |
890ddd |
TFrameId frame(f + 1);
|
|
Toshihiro Shimizu |
890ddd |
level->setFrame(frame, TImageP());
|
|
Toshihiro Shimizu |
890ddd |
currentTimes[f] = nextTime;
|
|
Toshihiro Shimizu |
890ddd |
++f;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
currentTime = nextTime;
|
|
Toshihiro Shimizu |
890ddd |
while (nextTime != -1) {
|
|
Toshihiro Shimizu |
890ddd |
GetMovieNextInterestingTime(m_movie, nextTimeMediaSample, 1, &mediaType, currentTime, 0, &nextTime, 0);
|
|
Toshihiro Shimizu |
890ddd |
if (nextTime != -1) {
|
|
Toshihiro Shimizu |
890ddd |
TFrameId frame(f + 1);
|
|
Toshihiro Shimizu |
890ddd |
level->setFrame(frame, TImageP());
|
|
Toshihiro Shimizu |
890ddd |
currentTimes[f] = nextTime;
|
|
Toshihiro Shimizu |
890ddd |
++f;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
currentTime = nextTime;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return level;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelP TLevelReaderMov::loadToonzOutputFormatInfo()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TLevelP level;
|
|
Toshihiro Shimizu |
890ddd |
if (m_IOError != QTNoError)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, buildQTErrorString(m_IOError));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
OSStatus mderr;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Retrieve the first frame of movie. This info has been put in a metadata atom.
|
|
Toshihiro Shimizu |
890ddd |
QTMetaDataRef metaDataRef;
|
|
Toshihiro Shimizu |
890ddd |
if ((mderr = QTCopyMovieMetaData(m_movie, &metaDataRef)) != noErr)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, "can't access metadata informations");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QTMetaDataItem firstFrameItem;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Find the metadata atom
|
|
Toshihiro Shimizu |
890ddd |
mderr = QTMetaDataGetNextItem(
|
|
Toshihiro Shimizu |
890ddd |
metaDataRef,
|
|
Toshihiro Shimizu |
890ddd |
kQTMetaDataStorageFormatUserData,
|
|
Toshihiro Shimizu |
890ddd |
kQTMetaDataItemUninitialized,
|
|
Toshihiro Shimizu |
890ddd |
kQTMetaDataKeyFormatUserData,
|
|
Toshihiro Shimizu |
890ddd |
(const UInt8 *)firstFrameKey.c_str(),
|
|
Toshihiro Shimizu |
890ddd |
firstFrameKeySize,
|
|
Toshihiro Shimizu |
890ddd |
&firstFrameItem);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Try to read the value. If the atom was not found, just assume firstFrame = 0.
|
|
Toshihiro Shimizu |
890ddd |
int firstFrame = 0;
|
|
Toshihiro Shimizu |
890ddd |
if (mderr == noErr) {
|
|
Toshihiro Shimizu |
890ddd |
// The atom was found. Then, retrieve the value
|
|
Toshihiro Shimizu |
890ddd |
if ((mderr =
|
|
Toshihiro Shimizu |
890ddd |
QTMetaDataGetItemValue(
|
|
Toshihiro Shimizu |
890ddd |
metaDataRef,
|
|
Toshihiro Shimizu |
890ddd |
firstFrameItem,
|
|
Toshihiro Shimizu |
890ddd |
(UInt8 *)(&firstFrame),
|
|
Toshihiro Shimizu |
890ddd |
sizeof(int),
|
|
Toshihiro Shimizu |
890ddd |
0) != noErr))
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, "can't read metadata informations");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
mderr = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QTMetaDataRelease(metaDataRef);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
OSType mediaType = VisualMediaCharacteristic;
|
|
Toshihiro Shimizu |
890ddd |
TimeValue nextTime = 0, currentTime = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TimeValue movieDuration = GetMovieDuration(m_movie);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<timevalue> interestingTimeValues;</timevalue>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// io vorrei fare '|', ma sul manuale c'e' scritto '+'
|
|
Toshihiro Shimizu |
890ddd |
GetMovieNextInterestingTime(m_movie, nextTimeMediaSample + nextTimeEdgeOK, 1, &mediaType, currentTime, 0, &nextTime, 0);
|
|
Toshihiro Shimizu |
890ddd |
if (nextTime != -1) {
|
|
Toshihiro Shimizu |
890ddd |
interestingTimeValues.push_back(nextTime);
|
|
Toshihiro Shimizu |
890ddd |
currentTime = nextTime;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
while (nextTime != -1) {
|
|
Toshihiro Shimizu |
890ddd |
GetMovieNextInterestingTime(m_movie, nextTimeMediaSample, 1, &mediaType, currentTime, 0, &nextTime, 0);
|
|
Toshihiro Shimizu |
890ddd |
if (nextTime != -1) {
|
|
Toshihiro Shimizu |
890ddd |
interestingTimeValues.push_back(nextTime);
|
|
Toshihiro Shimizu |
890ddd |
currentTime = nextTime;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (currentTime != -1) {
|
|
Toshihiro Shimizu |
890ddd |
double frameRate = m_info->m_frameRate;
|
|
Toshihiro Shimizu |
890ddd |
TimeScale movieTimeScale = GetMovieTimeScale(m_movie);
|
|
Toshihiro Shimizu |
890ddd |
int firstFrameTimeValue = movieTimeScale * firstFrame;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<timevalue>::iterator it;</timevalue>
|
|
Toshihiro Shimizu |
890ddd |
for (it = interestingTimeValues.begin(); it != interestingTimeValues.end(); ++it) {
|
|
Toshihiro Shimizu |
890ddd |
int frame = firstFrame + tround((*it * frameRate) / (double)movieTimeScale); // (Daniele) There was a ceil here,
|
|
Toshihiro Shimizu |
890ddd |
TFrameId frameId(frame + 1); // before. But I honestly don't remember
|
|
Toshihiro Shimizu |
890ddd |
level->setFrame(frameId, TImageP()); // WHY I placed it there. Round seems more
|
|
Toshihiro Shimizu |
890ddd |
currentTimes[frame] = *it; // appropriate...
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return level;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageP TImageReaderMov::load()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TRasterPT<tpixelrgbm32> ret(m_lrm->getSize());</tpixelrgbm32>
|
|
Toshihiro Shimizu |
890ddd |
m_lrm->load(ret, m_frameIndex, TPointI(), 1, 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return TRasterImageP(ret);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TImageReaderMov::load(const TRasterP &rasP, const TPoint &pos, int shrinkX, int shrinkY)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if ((shrinkX != 1) || (shrinkY != 1) || (pos != TPoint(0, 0)))
|
|
Toshihiro Shimizu |
890ddd |
TImageReader::load(rasP, pos, shrinkX, shrinkY);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
m_lrm->load(rasP, m_frameIndex, pos, shrinkX, shrinkY);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void setMatteAndYMirror(const TRaster32P &ras)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
ras->lock();
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *upRow = ras->pixels();
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *dwRow = ras->pixels(ras->getLy() - 1);
|
|
Toshihiro Shimizu |
890ddd |
int hLy = (int)(ras->getLy() / 2. + 0.5); //piccola pessimizzazione...
|
|
Toshihiro Shimizu |
890ddd |
int wrap = ras->getWrap();
|
|
Toshihiro Shimizu |
890ddd |
int lx = ras->getLx();
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *upPix = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *lastPix = ras->pixels(hLy);
|
|
Toshihiro Shimizu |
890ddd |
while (upPix < lastPix) {
|
|
Toshihiro Shimizu |
890ddd |
upPix = upRow;
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *dwPix = dwRow;
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *endPix = upPix + lx;
|
|
Toshihiro Shimizu |
890ddd |
while (upPix < endPix) {
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 tmpPix(upPix->r, upPix->g, upPix->b, 0xff);
|
|
Toshihiro Shimizu |
890ddd |
*upPix = *dwPix;
|
|
Toshihiro Shimizu |
890ddd |
upPix->m = 0xff;
|
|
Toshihiro Shimizu |
890ddd |
*dwPix = tmpPix;
|
|
Toshihiro Shimizu |
890ddd |
++upPix;
|
|
Toshihiro Shimizu |
890ddd |
++dwPix;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
upRow += wrap;
|
|
Toshihiro Shimizu |
890ddd |
dwRow -= wrap;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TLevelReaderMov::load(const TRasterP &rasP, int frameIndex, const TPoint &pos, int shrinkX, int shrinkY)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
GWorldPtr offscreenGWorld = 0;
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker sl(&m_mutex);
|
|
Toshihiro Shimizu |
890ddd |
if (m_IOError != QTNoError)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, buildQTErrorString(m_IOError));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRaster32P ras = rasP;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Rect rect;
|
|
Toshihiro Shimizu |
890ddd |
rect.right = pos.x + ras->getLx();
|
|
Toshihiro Shimizu |
890ddd |
rect.left = pos.x;
|
|
Toshihiro Shimizu |
890ddd |
rect.bottom = pos.y + ras->getLy();
|
|
Toshihiro Shimizu |
890ddd |
rect.top = pos.y;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
OSErr err;
|
|
Toshihiro Shimizu |
890ddd |
ras->lock();
|
|
Toshihiro Shimizu |
890ddd |
err = QTNewGWorldFromPtr(
|
|
Toshihiro Shimizu |
890ddd |
&offscreenGWorld, k32BGRAPixelFormat,
|
|
Toshihiro Shimizu |
890ddd |
&rect, 0, 0, 0, ras->getRawData(), ras->getWrap() * 4);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (err != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTUnableToCreateResource;
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
SetMovieBox(m_movie, &rect);
|
|
Toshihiro Shimizu |
890ddd |
err = GetMoviesError();
|
|
Toshihiro Shimizu |
890ddd |
if (err != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTUnableToSetMovieBox;
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
SetMovieGWorld(m_movie, offscreenGWorld, GetGWorldDevice(offscreenGWorld));
|
|
Toshihiro Shimizu |
890ddd |
err = GetMoviesError();
|
|
Toshihiro Shimizu |
890ddd |
if (err != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTUnableToSetMovieGWorld;
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (currentTimes.empty())
|
|
Toshihiro Shimizu |
890ddd |
loadInfo();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::map<int, timevalue="">::iterator it = currentTimes.find(frameIndex);</int,>
|
|
Toshihiro Shimizu |
890ddd |
if (it == currentTimes.end())
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TimeValue currentTime = it->second;
|
|
Toshihiro Shimizu |
890ddd |
SetMovieTimeValue(m_movie, currentTime);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
err = GetMoviesError();
|
|
Toshihiro Shimizu |
890ddd |
if (err != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTUnableToSetTimeValue;
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
err = UpdateMovie(m_movie);
|
|
Toshihiro Shimizu |
890ddd |
if (err != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTUnableToUpdateMovie;
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
MoviesTask(m_movie, 0);
|
|
Toshihiro Shimizu |
890ddd |
err = GetMoviesError();
|
|
Toshihiro Shimizu |
890ddd |
if (err != noErr) {
|
|
Toshihiro Shimizu |
890ddd |
m_IOError = QTUnableToDoMovieTask;
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DisposeGWorld(offscreenGWorld);
|
|
Toshihiro Shimizu |
890ddd |
ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_yMirror) {
|
|
Toshihiro Shimizu |
890ddd |
if (m_depth != 32)
|
|
Toshihiro Shimizu |
890ddd |
setMatteAndYMirror(rasP);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
rasP->yMirror();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_loadTimecode) {
|
|
Toshihiro Shimizu |
890ddd |
//Also build current Timecode
|
|
Toshihiro Shimizu |
890ddd |
TimeCodeRecord tc;
|
|
Toshihiro Shimizu |
890ddd |
HandlerError err = TCGetCurrentTimeCode(m_timecodeHandler, 0, 0, &tc, 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_hh = tc.t.hours;
|
|
Toshihiro Shimizu |
890ddd |
m_mm = tc.t.minutes;
|
|
Toshihiro Shimizu |
890ddd |
m_ss = tc.t.seconds;
|
|
Toshihiro Shimizu |
890ddd |
m_ff = tc.t.frames;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
error:
|
|
Toshihiro Shimizu |
890ddd |
rasP->unlock();
|
|
Toshihiro Shimizu |
890ddd |
if (offscreenGWorld)
|
|
Toshihiro Shimizu |
890ddd |
DisposeGWorld(offscreenGWorld);
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, buildQTErrorString(m_IOError));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TLevelReaderMov::timecode(int frameIndex, UCHAR &hh, UCHAR &mm, UCHAR &ss, UCHAR &ff)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
hh = mm = ss = ff = 0xff;
|
|
Toshihiro Shimizu |
890ddd |
if (!m_timecodeHandler)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker sl(&m_mutex);
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_IOError != QTNoError)
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (currentTimes.empty())
|
|
Toshihiro Shimizu |
890ddd |
loadInfo();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::map<int, timevalue="">::iterator it = currentTimes.find(frameIndex);</int,>
|
|
Toshihiro Shimizu |
890ddd |
if (it == currentTimes.end())
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TimeValue currentTime = it->second;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TimeCodeRecord tc;
|
|
Toshihiro Shimizu |
890ddd |
HandlerError err = TCGetTimeCodeAtTime(m_timecodeHandler, currentTime,
|
|
Toshihiro Shimizu |
890ddd |
0, 0, &tc, 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
hh = tc.t.hours;
|
|
Toshihiro Shimizu |
890ddd |
mm = tc.t.minutes;
|
|
Toshihiro Shimizu |
890ddd |
ss = tc.t.seconds;
|
|
Toshihiro Shimizu |
890ddd |
ff = tc.t.frames;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
error:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, buildQTErrorString(m_IOError));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageReaderP TLevelReaderMov::getFrameReader(TFrameId fid)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_IOError != QTNoError)
|
|
Toshihiro Shimizu |
890ddd |
throw TImageException(m_path, buildQTErrorString(m_IOError));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (fid.getLetter() != 0)
|
|
Toshihiro Shimizu |
890ddd |
return TImageReaderP(0);
|
|
Toshihiro Shimizu |
890ddd |
int index = fid.getNumber() - 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageReaderMov *irm = new TImageReaderMov(m_path, index, this, m_info);
|
|
Toshihiro Shimizu |
890ddd |
return TImageReaderP(irm);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelReader *TLevelReaderMov::create(const TFilePath &f)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TLevelReaderMov *reader = new TLevelReaderMov(f);
|
|
Toshihiro Shimizu |
890ddd |
if (reader->m_IOError != QTNoError && f.getType() == "avi") {
|
|
Toshihiro Shimizu |
890ddd |
delete reader;
|
|
Toshihiro Shimizu |
890ddd |
return new TLevelReaderAvi(f);
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
return reader;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// You can use the SCSetInfo function with the scSettingsStateType selector to retrieve a handle
|
|
Toshihiro Shimizu |
890ddd |
// containing the current compression settings; this might be useful if you were allowing the user
|
|
Toshihiro Shimizu |
890ddd |
// to compress a series of images and wanted to preserve the user's settings from one image to the
|
|
Toshihiro Shimizu |
890ddd |
// next (instead of reverting to the defaults for every image). Note, however, that the data in
|
|
Toshihiro Shimizu |
890ddd |
// that handle is byte-ordered according to the platform the code is running on. As a result, you
|
|
Toshihiro Shimizu |
890ddd |
// should not store that data in a file and expect that file to be valid on other platforms. To
|
|
Toshihiro Shimizu |
890ddd |
// get a handle of data in a platform-independent format, use the function SCGetSettingsAsAtomContainer
|
|
Toshihiro Shimizu |
890ddd |
// (introduced in QuickTime 3); to restore the settings in that handle, use the related function
|
|
Toshihiro Shimizu |
890ddd |
// SCSetSettingsAsAtomContainer.
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|