|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <openquicktime.h></openquicktime.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <colormodels.h></colormodels.h>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tiio_movL.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "traster.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trasterimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tsound.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tconvert.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trop.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tsystem.h"
|
|
Toshihiro Shimizu |
890ddd |
//#define DUMP_KEYFRAMES
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool IsQuickTimeInstalled() { return true; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
enum {
|
|
Shinya Kitaoka |
120a6e |
QTNoError = 0,
|
|
Shinya Kitaoka |
120a6e |
QTUnableToOpenFile,
|
|
Shinya Kitaoka |
120a6e |
QTUnableToSeekToKeyFrame,
|
|
Shinya Kitaoka |
120a6e |
QTNoSuchFile,
|
|
Shinya Kitaoka |
120a6e |
QTUnsupportedVideoFormat
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class TQTException : public TImageException {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
TQTException(const TFilePath &fp, int ec)
|
|
Shinya Kitaoka |
120a6e |
: TImageException(fp, getErrorMessage(ec)) {}
|
|
Shinya Kitaoka |
120a6e |
TQTException(const TFilePath &fp, int ec, int v)
|
|
Shinya Kitaoka |
120a6e |
: TImageException(fp, getErrorMessage(ec) + toString(v)) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
~TQTException() {}
|
|
Shinya Kitaoka |
120a6e |
static string getErrorMessage(int ec) {
|
|
Shinya Kitaoka |
120a6e |
switch (ec) {
|
|
Shinya Kitaoka |
120a6e |
case QTNoError:
|
|
Shinya Kitaoka |
120a6e |
return "No error";
|
|
Shinya Kitaoka |
120a6e |
case QTUnableToOpenFile:
|
|
Shinya Kitaoka |
120a6e |
return "unable to open file";
|
|
Shinya Kitaoka |
120a6e |
case QTUnableToSeekToKeyFrame:
|
|
Shinya Kitaoka |
120a6e |
return "unable to seek to keyframe";
|
|
Shinya Kitaoka |
120a6e |
case QTNoSuchFile:
|
|
Shinya Kitaoka |
120a6e |
return "no such file";
|
|
Shinya Kitaoka |
120a6e |
case QTUnsupportedVideoFormat:
|
|
Shinya Kitaoka |
120a6e |
return "Unsupported video format";
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return "unknown error";
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
// TImageWriterMov
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class TImageWriterMov : public TImageWriter {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
TImageWriterMov(const TFilePath &, int frameIndex, TLevelWriterMov *);
|
|
Shinya Kitaoka |
120a6e |
~TImageWriterMov() {}
|
|
Shinya Kitaoka |
120a6e |
bool is64bitOutputSupported() { return false; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
// not implemented
|
|
Shinya Kitaoka |
120a6e |
TImageWriterMov(const TImageWriterMov &);
|
|
Shinya Kitaoka |
120a6e |
TImageWriterMov &operator=(const TImageWriterMov &src);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
void save(const TImageP &);
|
|
Shinya Kitaoka |
120a6e |
int m_frameIndex;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
TLevelWriterMov *m_lwm;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
// TImageReaderMov
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
class TImageReaderMov : public TImageReader {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
TImageReaderMov(const TFilePath &, int frameIndex, TLevelReaderMov *);
|
|
Shinya Kitaoka |
120a6e |
~TImageReaderMov() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
// not implemented
|
|
Shinya Kitaoka |
120a6e |
TImageReaderMov(const TImageReaderMov &);
|
|
Shinya Kitaoka |
120a6e |
TImageReaderMov &operator=(const TImageReaderMov &src);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
TImageP load();
|
|
Shinya Kitaoka |
120a6e |
int m_frameIndex;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TDimension getSize() const { return TDimension(m_lrm->m_lx, m_lrm->m_ly); }
|
|
Shinya Kitaoka |
120a6e |
TRect getBBox() const {
|
|
Shinya Kitaoka |
120a6e |
return TRect(0, 0, m_lrm->m_lx - 1, m_lrm->m_ly - 1);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
TLevelReaderMov *m_lrm;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
// TImageWriterMov
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TImageWriterMov::TImageWriterMov(const TFilePath &path, int frameIndex,
|
|
Shinya Kitaoka |
120a6e |
TLevelWriterMov *lwm)
|
|
Shinya Kitaoka |
120a6e |
: TImageWriter(path), m_lwm(lwm), m_frameIndex(frameIndex) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TImageWriterMov::save(const TImageP &img) { assert(false); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
// TLevelWriterMov
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
class TWriterInfoMov : public TWriterInfo {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TWriterInfoMov() : TWriterInfo() { assert(!"Not implemented"); }
|
|
Toshihiro Shimizu |
890ddd |
~TWriterInfoMov() {}
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelWriterMov::TLevelWriterMov(const TFilePath &path, TWriterInfo *info)
|
|
Shinya Kitaoka |
120a6e |
: TLevelWriter(path, info)
|
|
Toshihiro Shimizu |
890ddd |
//,m_initDone(false)
|
|
Toshihiro Shimizu |
890ddd |
//,m_rate(25)
|
|
Toshihiro Shimizu |
890ddd |
//,m_IOError(QTNoError)
|
|
Toshihiro Shimizu |
890ddd |
//,quality(DM_IMAGE_QUALITY_NORMAL)
|
|
Toshihiro Shimizu |
890ddd |
//,compression(DM_IMAGE_QT_ANIM)
|
|
Toshihiro Shimizu |
890ddd |
//,m_writerInfo(new TWriterInfoMov())
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TLevelWriterMov::saveSoundTrack(TSoundTrack *) {
|
|
Shinya Kitaoka |
120a6e |
throw TImageException(m_path,
|
|
Shinya Kitaoka |
120a6e |
"TLevelWriterMov::saveSoundTrack not Implemented");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
TWriterInfo *TLevelWriterMov::getWriterInfo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return m_writerInfo;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TLevelWriterMov::~TLevelWriterMov() { assert(0); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TImageWriterP TLevelWriterMov::getFrameWriter(TFrameId fid) { assert(false); }
|
|
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 |
|
|
Shinya Kitaoka |
120a6e |
TImageReaderMov::TImageReaderMov(const TFilePath &path, int frameIndex,
|
|
Shinya Kitaoka |
120a6e |
TLevelReaderMov *lrm)
|
|
Shinya Kitaoka |
120a6e |
: TImageReader(path), m_lrm(lrm), m_frameIndex(frameIndex) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace std;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelReaderMov::TLevelReaderMov(const TFilePath &path)
|
|
Shinya Kitaoka |
120a6e |
: TLevelReader(path)
|
|
Shinya Kitaoka |
120a6e |
, m_IOError(QTNoError)
|
|
Shinya Kitaoka |
120a6e |
, m_lastFrameDecoded(-1)
|
|
Shinya Kitaoka |
120a6e |
, m_fileMov(0)
|
|
Shinya Kitaoka |
120a6e |
, m_lx(0)
|
|
Shinya Kitaoka |
120a6e |
, m_ly(0) {
|
|
Shinya Kitaoka |
120a6e |
if (!TFileStatus(path).doesExist()) {
|
|
Shinya Kitaoka |
120a6e |
m_IOError = QTNoSuchFile;
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_fileMov = oqt_open((char *)path.getString().c_str());
|
|
Shinya Kitaoka |
120a6e |
if (!m_fileMov) {
|
|
Shinya Kitaoka |
120a6e |
m_IOError = QTUnableToOpenFile;
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
oqt_read_headers(m_fileMov);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
if(!oqt_get_video_track_count(m_fileMov))
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
m_status = !DM_SUCCESS;
|
|
Shinya Kitaoka |
120a6e |
m_IOError = QTCheckLibError;
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_lx = oqt_get_video_width(m_fileMov, 0);
|
|
Shinya Kitaoka |
120a6e |
m_ly = oqt_get_video_height(m_fileMov, 0);
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
char *vc = oqt_get_video_compressor(m_fileMov, 0);
|
|
Shinya Kitaoka |
120a6e |
cout << "video compressor = " << vc[0] << vc[1] << vc[2] << vc[3] << endl;
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TLevelReaderMov::~TLevelReaderMov() {
|
|
Shinya Kitaoka |
120a6e |
if (m_fileMov) oqt_close(m_fileMov);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TLevelP TLevelReaderMov::loadInfo() {
|
|
Shinya Kitaoka |
120a6e |
TLevelP level;
|
|
Shinya Kitaoka |
120a6e |
if (m_IOError != QTNoError) {
|
|
Shinya Kitaoka |
120a6e |
throw TQTException(m_path, m_IOError);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (oqt_supported_video(m_fileMov, 0) == 0) {
|
|
Shinya Kitaoka |
120a6e |
m_IOError = QTUnsupportedVideoFormat;
|
|
Shinya Kitaoka |
120a6e |
throw TQTException(m_path, m_IOError);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int frameCount = oqt_get_video_length(m_fileMov, 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (int i = 1; i <= frameCount; i++) level->setFrame(TFrameId(i), TImageP());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DUMP_KEYFRAMES
|
|
Shinya Kitaoka |
120a6e |
for (int k = 1; k < frameCount; k++) {
|
|
Shinya Kitaoka |
120a6e |
cout << "frame = " << k << "; keyframe before = "
|
|
Shinya Kitaoka |
120a6e |
<< oqt_get_video_keyframe_before(m_fileMov, 0, k)
|
|
Shinya Kitaoka |
120a6e |
<< "; keyframe after = "
|
|
Shinya Kitaoka |
120a6e |
<< oqt_get_video_keyframe_after(m_fileMov, 0, k) << endl;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return level;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TImageP TImageReaderMov::load() {
|
|
Shinya Kitaoka |
120a6e |
if (m_lrm->m_IOError != QTNoError)
|
|
Shinya Kitaoka |
120a6e |
throw TQTException(m_path, m_lrm->m_IOError);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TThread::ScopedLock sl(m_lrm->m_mutex);
|
|
Shinya Kitaoka |
120a6e |
int rc;
|
|
Shinya Kitaoka |
120a6e |
TRaster32P ret(m_lrm->m_lx, m_lrm->m_ly);
|
|
Shinya Kitaoka |
120a6e |
unsigned char **data =
|
|
Shinya Kitaoka |
120a6e |
(unsigned char **)malloc(m_lrm->m_ly * sizeof(unsigned char *));
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_lrm->m_ly; ++i) {
|
|
Shinya Kitaoka |
120a6e |
unsigned char *ptr = (unsigned char *)ret->pixels(i);
|
|
Shinya Kitaoka |
120a6e |
data[i] = ptr;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
int cmodel = BC_RGBA8888;
|
|
Shinya Kitaoka |
120a6e |
int frame;
|
|
Shinya Kitaoka |
120a6e |
if (m_lrm->m_lastFrameDecoded != (m_frameIndex - 1)) {
|
|
Shinya Kitaoka |
120a6e |
oqt_int64_t kfb =
|
|
Shinya Kitaoka |
120a6e |
oqt_get_video_keyframe_before(m_lrm->m_fileMov, 0, m_frameIndex);
|
|
Shinya Kitaoka |
120a6e |
assert(kfb <= m_frameIndex);
|
|
Shinya Kitaoka |
120a6e |
rc = oqt_set_video_position(m_lrm->m_fileMov, 0, kfb);
|
|
Shinya Kitaoka |
120a6e |
if (rc) {
|
|
Shinya Kitaoka |
120a6e |
throw TQTException(m_lrm->m_path, QTUnableToSeekToKeyFrame, kfb);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
frame = kfb - 1;
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
frame = m_lrm->m_lastFrameDecoded;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
do {
|
|
Shinya Kitaoka |
120a6e |
rc = oqt_decode_video(m_lrm->m_fileMov, 0, cmodel, data);
|
|
Shinya Kitaoka |
120a6e |
frame++;
|
|
Shinya Kitaoka |
120a6e |
} while (frame != m_frameIndex);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_lrm->m_lastFrameDecoded = m_frameIndex;
|
|
Shinya Kitaoka |
120a6e |
ret->yMirror();
|
|
Shinya Kitaoka |
120a6e |
free(data);
|
|
Shinya Kitaoka |
120a6e |
return TRasterImageP(ret);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TImageReaderP TLevelReaderMov::getFrameReader(TFrameId fid) {
|
|
Shinya Kitaoka |
120a6e |
if (m_IOError != QTNoError) {
|
|
Shinya Kitaoka |
120a6e |
throw TQTException(m_path, m_IOError);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (fid.getLetter() != 0) return TImageReaderP(0);
|
|
Shinya Kitaoka |
120a6e |
int index = fid.getNumber() - 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TImageReaderMov *irm = new TImageReaderMov(m_path, index, this);
|
|
Shinya Kitaoka |
120a6e |
return TImageReaderP(irm);
|
|
Toshihiro Shimizu |
890ddd |
}
|