Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef x64
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "texception.h"
Toshihiro Shimizu 890ddd
#include "tiio_3gp.h"
Toshihiro Shimizu 890ddd
#include "tsound.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include "tpropertytype.h"
Toshihiro Shimizu 890ddd
//#include "trop.h"
Toshihiro Shimizu 890ddd
#include "../mov/tiio_mov.h"
Toshihiro Shimizu 890ddd
//#include "timageinfo.h"
Toshihiro Shimizu 890ddd
#include "movsettings.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int CompressionNoneId = 0;
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
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
const string CodecNamesId = "PU_CodecName";
Toshihiro Shimizu 890ddd
const string CodecQualityId = "PU_CodecQuality";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace
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
class TImageWriter3gp : public TImageWriter
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TImageWriter3gp(const TFilePath &, int frameIndex, TLevelWriter3gp *);
Toshihiro Shimizu 890ddd
	~TImageWriter3gp() { 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
	TImageWriter3gp(const TImageWriter3gp &);
Toshihiro Shimizu 890ddd
	TImageWriter3gp &operator=(const TImageWriter3gp &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
	TLevelWriter3gp *m_lwm;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
//  TImageReaderv
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
class TImageReader3gp : public TImageReader
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TImageReader3gp(const TFilePath &, int frameIndex, TLevelReader3gp *);
Toshihiro Shimizu 890ddd
	~TImageReader3gp() { m_lrm->release(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	//not implemented
Toshihiro Shimizu 890ddd
	TImageReader3gp(const TImageReader3gp &);
Toshihiro Shimizu 890ddd
	TImageReader3gp &operator=(const TImageReader3gp &src);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
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
	int m_frameIndex;
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
private:
Toshihiro Shimizu 890ddd
	TLevelReader3gp *m_lrm;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
//        TImageWriter3gp
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TImageWriter3gp::TImageWriter3gp(const TFilePath &path, int frameIndex, TLevelWriter3gp *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
	rin->lock();
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
	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
	rin->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
void TImageWriter3gp::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 TLevelWriter3gp::save(const TImageP &img, int frameIndex)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_cancelled)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	string msg;
Toshihiro Shimizu 890ddd
	QMutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRasterImageP image(img);
Toshihiro Shimizu 890ddd
	TRasterP ras = image->getRaster();
Toshihiro Shimizu 890ddd
	int lx = ras->getLx();
Toshihiro Shimizu 890ddd
	int ly = ras->getLy();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ras->lock();
Toshihiro Shimizu 890ddd
	void *buffer = image->getRaster()->getRawData();
Toshihiro Shimizu 890ddd
	int pixSize = image->getRaster()->getPixelSize();
Toshihiro Shimizu 890ddd
	if (pixSize != 4) {
Toshihiro Shimizu 890ddd
		msg = "Unsupported pixel type";
Toshihiro Shimizu 890ddd
		goto error;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
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
	ComponentInstance ci = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType);
Toshihiro Shimizu 890ddd
	if (SCSetSettingsFromAtomContainer(ci, atoms))
Toshihiro Shimizu 890ddd
		assert(false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
CodecType compression = prop->getCurrentCodec();
Toshihiro Shimizu 890ddd
CodecQ quality = prop->getCurrentQuality();
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_initDone) {
Toshihiro Shimizu 890ddd
		Rect frame;
Toshihiro Shimizu 890ddd
		QDErr err;
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
			msg = "can't create video track";
Toshihiro Shimizu 890ddd
			goto error;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_dataRef = nil;
Toshihiro Shimizu 890ddd
		m_hMovieData = NewHandle(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Construct the Handle data reference
Toshihiro Shimizu 890ddd
		err = PtrToHand(&m_hMovieData, &m_dataRef, sizeof(Handle));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if ((err = GetMoviesError() != noErr)) {
Toshihiro Shimizu 890ddd
			msg = "can't create Data Ref";
Toshihiro Shimizu 890ddd
			goto error;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_videoMedia = NewTrackMedia(m_videoTrack, VideoMediaType, (TINT32)m_frameRate, m_dataRef, HandleDataHandlerSubType);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		OpenADefaultComponent(MovieExportType, '3gpp', &m_myExporter);
Toshihiro Shimizu 890ddd
		if (TSystem::doHaveMainLoop())
Toshihiro Shimizu 890ddd
			err = (short)MovieExportDoUserDialog(m_myExporter, m_movie, 0, 0, 0, &m_cancelled);
Toshihiro Shimizu 890ddd
		if (m_cancelled) {
Toshihiro Shimizu 890ddd
			msg = "user abort of 3gp creation";
Toshihiro Shimizu 890ddd
			goto error;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if ((err = GetMoviesError() != noErr)) {
Toshihiro Shimizu 890ddd
			msg = "can't create video media";
Toshihiro Shimizu 890ddd
			goto error;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if ((err = BeginMediaEdits(m_videoMedia)) != noErr) {
Toshihiro Shimizu 890ddd
			msg = "can't begin edit video media";
Toshihiro Shimizu 890ddd
			goto error;
Toshihiro Shimizu 890ddd
		}
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
			msg = "can't create movie buffer";
Toshihiro Shimizu 890ddd
			goto error;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		LockPixels(m_gworld->portPixMap);
Toshihiro Shimizu 890ddd
		/*if ((err = GetMaxCompressionSize(m_gworld->portPixMap, &frame, 0, 
Toshihiro Shimizu 890ddd
                                quality,  compression,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
			msg = "can't allocate compressed data for movie";
Toshihiro Shimizu 890ddd
			goto error;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if ((err = MemError()) != noErr) {
Toshihiro Shimizu 890ddd
			msg = "can't allocate img handle";
Toshihiro Shimizu 890ddd
			goto error;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_pixmap = GetGWorldPixMap(m_gworld);
Toshihiro Shimizu 890ddd
		if (!LockPixels(m_pixmap)) {
Toshihiro Shimizu 890ddd
			msg = "can't lock pixels";
Toshihiro Shimizu 890ddd
			goto error;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		buf = (PixelXRGB *)(*(m_pixmap))->baseAddr;
Toshihiro Shimizu 890ddd
		buf_lx = lx;
Toshihiro Shimizu 890ddd
		buf_ly = ly;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_initDone = true;
Toshihiro Shimizu 890ddd
	}
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
	QDErr err;
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
	copy(ras, buf, buf_lx, buf_ly);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((err = (QDErr)SCCompressImage(
Toshihiro Shimizu 890ddd
			 ci,
Toshihiro Shimizu 890ddd
			 m_gworld->portPixMap,
Toshihiro Shimizu 890ddd
			 &frame,
Toshihiro Shimizu 890ddd
			 &img_descr,
Toshihiro Shimizu 890ddd
			 &compressedData)) != noErr) {
Toshihiro Shimizu 890ddd
		msg = "can't compress image";
Toshihiro Shimizu 890ddd
		goto error;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
if ((err = CompressImage(m_gworld->portPixMap, 
Toshihiro Shimizu 890ddd
	                       &frame, 
Toshihiro Shimizu 890ddd
												 quality, compression,
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
	if ((err = AddMediaSample(m_videoMedia, compressedData, 0,
Toshihiro Shimizu 890ddd
							  (*img_descr)->dataSize, 1,
Toshihiro Shimizu 890ddd
							  (SampleDescriptionHandle)img_descr,
Toshihiro Shimizu 890ddd
							  1, 0, 0)) != noErr) {
Toshihiro Shimizu 890ddd
		msg = "can't add image to movie media";
Toshihiro Shimizu 890ddd
		goto error;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DisposeHandle((Handle)img_descr);
Toshihiro Shimizu 890ddd
	DisposeHandle(compressedData);
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
	return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
error:
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
	throw TImageException(getFilePath(), msg);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
//        TLevelWriterMov
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TLevelWriter3gp::TLevelWriter3gp(const TFilePath &path, TPropertyGroup *winfo)
Toshihiro Shimizu 890ddd
	: TLevelWriter(path, winfo), m_initDone(false), m_IOError(QTNoError), m_pixmap(0), m_gworld(0), m_videoMedia(0), m_videoTrack(0), m_movie(0), m_cancelled(false), m_soundDataRef(0), m_hSoundMovieData(0)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_frameRate = 12.;
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
	QDErr err;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_movie = NewMovie(0);
Toshihiro Shimizu 890ddd
	if ((err = GetMoviesError() != noErr))
Toshihiro Shimizu 890ddd
		throw TImageException(getFilePath(), "can't create movie");
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 TLevelWriter3gp::saveSoundTrack(TSoundTrack *st)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Track theTrack;
Toshihiro Shimizu 890ddd
	OSErr myErr = noErr;
Toshihiro Shimizu 890ddd
	SoundDescriptionV1Handle mySampleDesc;
Toshihiro Shimizu 890ddd
	Media myMedia;
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
	int err;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_cancelled)
Toshihiro Shimizu 890ddd
		return;
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
Toshihiro Shimizu 890ddd
	theTrack = 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
	myDestHandle = NewHandle(0);
Toshihiro Shimizu 890ddd
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
	//////////
Toshihiro Shimizu 890ddd
	//
Toshihiro Shimizu 890ddd
	// create a media for the track passed in
Toshihiro Shimizu 890ddd
	//
Toshihiro Shimizu 890ddd
	//////////
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// set new track to be a sound track
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_soundDataRef = nil;
Toshihiro Shimizu 890ddd
	m_hSoundMovieData = NewHandle(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Construct the Handle data reference
Toshihiro Shimizu 890ddd
	err = PtrToHand(&m_hSoundMovieData, &m_soundDataRef, sizeof(Handle));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((err = GetMoviesError() != noErr))
Toshihiro Shimizu 890ddd
		throw TImageException(getFilePath(), "can't create Data Ref");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	myMedia = NewTrackMedia(theTrack, SoundMediaType, st->getSampleRate(), m_soundDataRef, HandleDataHandlerSubType); //track->rate >> 16
Toshihiro Shimizu 890ddd
	myErr = GetMoviesError();
Toshihiro Shimizu 890ddd
	FailIf(myErr != noErr, Exit);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// start a media editing session
Toshihiro Shimizu 890ddd
	myErr = BeginMediaEdits(myMedia);
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
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(myMedia, 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(myMedia);
Toshihiro Shimizu 890ddd
	FailIf(myErr != noErr, MediaErr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//////////
Toshihiro Shimizu 890ddd
	//
Toshihiro Shimizu 890ddd
	// insert the media into the track
Toshihiro Shimizu 890ddd
	//
Toshihiro Shimizu 890ddd
	//////////
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	myErr = InsertMediaIntoTrack(theTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
Toshihiro Shimizu 890ddd
	FailIf(myErr != noErr, MediaErr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	goto Done;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ConverterErr:
Toshihiro Shimizu 890ddd
NoDest:
Toshihiro Shimizu 890ddd
CompressErr:
Toshihiro Shimizu 890ddd
Exit:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Done:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MediaErr:
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
TLevelWriter3gp::~TLevelWriter3gp()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_pixmap)
Toshihiro Shimizu 890ddd
		UnlockPixels(m_pixmap);
Toshihiro Shimizu 890ddd
	if (m_gworld)
Toshihiro Shimizu 890ddd
		DisposeGWorld(m_gworld);
Toshihiro Shimizu 890ddd
	QDErr err;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_videoMedia)
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
	if (m_videoTrack)
Toshihiro Shimizu 890ddd
		if ((err = InsertMediaIntoTrack(m_videoTrack, 0, 0,
Toshihiro Shimizu 890ddd
										GetMediaDuration(m_videoMedia), fixed1))) {
Toshihiro Shimizu 890ddd
		} // throw TImageException(getFilePath(), "can't insert media into track");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	short resId = movieInDataForkResID;
Toshihiro Shimizu 890ddd
	if (m_movie) {
Toshihiro Shimizu 890ddd
		FSSpec fspec;
Toshihiro Shimizu 890ddd
		long myFlags = 0L;
Toshihiro Shimizu 890ddd
		OSErr myErr = noErr;
Toshihiro Shimizu 890ddd
		UCHAR myCancelled = FALSE;
Toshihiro Shimizu 890ddd
		char *pStr = filePath2unichar(m_path);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		NativePathNameToFSSpec(pStr, &fspec, kFullNativePath);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		myFlags = createMovieFileDeleteCurFile; // |
Toshihiro Shimizu 890ddd
												//movieFileSpecValid | movieToFileOnlyExport;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		myErr = ConvertMovieToFile(
Toshihiro Shimizu 890ddd
			m_movie,				// the movie to convert
Toshihiro Shimizu 890ddd
			NULL,					// all tracks in the movie
Toshihiro Shimizu 890ddd
			&fspec,					// the output file
Toshihiro Shimizu 890ddd
			'3gpp',					// the output file type
Toshihiro Shimizu 890ddd
			FOUR_CHAR_CODE('TVOD'), // the output file creator
Toshihiro Shimizu 890ddd
			smSystemScript,			// the script
Toshihiro Shimizu 890ddd
			&resId,					// no resource ID to be returned
Toshihiro Shimizu 890ddd
			myFlags,				// export flags
Toshihiro Shimizu 890ddd
			m_myExporter);			// no specific exp
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DisposeHandle(m_hMovieData);
Toshihiro Shimizu 890ddd
	DisposeHandle(m_dataRef);
Toshihiro Shimizu 890ddd
	if (m_hSoundMovieData)
Toshihiro Shimizu 890ddd
		DisposeHandle(m_hMovieData);
Toshihiro Shimizu 890ddd
	if (m_hSoundMovieData)
Toshihiro Shimizu 890ddd
		DisposeHandle(m_hSoundMovieData);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_refNum)
Toshihiro Shimizu 890ddd
		CloseMovieFile(m_refNum);
Toshihiro Shimizu 890ddd
	DisposeMovie(m_movie);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TImageWriterP TLevelWriter3gp::getFrameWriter(TFrameId fid)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_cancelled)
Toshihiro Shimizu 890ddd
		return 0;
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
	TImageWriter3gp *iwm = new TImageWriter3gp(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
TLevelReader3gp::TLevelReader3gp(const TFilePath &path)
Toshihiro Shimizu 890ddd
	: TLevelReader(path), m_IOError(QTNoError), m_track(0), m_movie(0), m_depth(0)
Toshihiro Shimizu 890ddd
//                ,m_timeScale(0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FSSpec fspec;
Toshihiro Shimizu 890ddd
	QDErr err;
Toshihiro Shimizu 890ddd
	Boolean dataRefWasChanged;
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
	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
	m_resId = 0;
Toshihiro Shimizu 890ddd
	Str255 name;
Toshihiro Shimizu 890ddd
	err = NewMovieFromFile(&m_movie, m_refNum, &m_resId,
Toshihiro Shimizu 890ddd
						   name, fsRdPerm, &dataRefWasChanged);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int numTracks = GetMovieTrackCount(m_movie);
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
	//m_track=GetMovieTrack(m_movie,numTracks);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ImageDescriptionHandle imageH;
Toshihiro Shimizu 890ddd
	imageH = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
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
	m_lx = imagePtr->width;
Toshihiro Shimizu 890ddd
	m_ly = imagePtr->height;
Toshihiro Shimizu 890ddd
	m_depth = imagePtr->depth;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DisposeHandle((Handle)imageH);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//m_info->m_frameRate = GetMediaTimeScale(theMedia);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
// TImageReaderMov
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TImageReader3gp::TImageReader3gp(const TFilePath &path, int frameIndex, TLevelReader3gp *lrm)
Toshihiro Shimizu 890ddd
	: TImageReader(path), m_lrm(lrm), m_frameIndex(frameIndex)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_lrm->addRef();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TLevelReader3gp::~TLevelReader3gp()
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
	if (m_movie)
Toshihiro Shimizu 890ddd
		DisposeMovie(m_movie);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TLevelP TLevelReader3gp::loadInfo()
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
	//per il primo
Toshihiro Shimizu 890ddd
	int f = 1;
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
		TFrameId frame(f);
Toshihiro Shimizu 890ddd
		level->setFrame(frame, TImageP());
Toshihiro Shimizu 890ddd
		currentTimes.push_back(nextTime);
Toshihiro Shimizu 890ddd
		f++;
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);
Toshihiro Shimizu 890ddd
			level->setFrame(frame, TImageP());
Toshihiro Shimizu 890ddd
			currentTimes.push_back(nextTime);
Toshihiro Shimizu 890ddd
			f++;
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
TImageP TImageReader3gp::load()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRasterPT<tpixelrgbm32> ret(m_lrm->getSize());</tpixelrgbm32>
Toshihiro Shimizu 890ddd
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 TImageReader3gp::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
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
	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 TLevelReader3gp::load(const TRasterP &rasP, int frameIndex, const TPoint &pos, int shrinkX, int shrinkY)
Toshihiro Shimizu 890ddd
{
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
		GWorldPtr offscreenGWorld;
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
			DisposeGWorld(offscreenGWorld);
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
			DisposeGWorld(offscreenGWorld);
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
			DisposeGWorld(offscreenGWorld);
Toshihiro Shimizu 890ddd
			goto error;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TimeValue currentTime = currentTimes[frameIndex];
Toshihiro Shimizu 890ddd
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
			DisposeGWorld(offscreenGWorld);
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
			DisposeGWorld(offscreenGWorld);
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
			DisposeGWorld(offscreenGWorld);
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_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
	return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
error:
Toshihiro Shimizu 890ddd
	rasP->unlock();
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 TLevelReader3gp::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
	TImageReader3gp *irm = new TImageReader3gp(m_path, index, this);
Toshihiro Shimizu 890ddd
	return TImageReaderP(irm);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif