Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef x64
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9eb50d
#include <cstdint></cstdint>
Shinya Kitaoka 9eb50d
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 "../mov/tiio_mov.h"
Toshihiro Shimizu 890ddd
#include "movsettings.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 6526c7
#include "tiio_3gp.h"
Shinya Kitaoka 6526c7
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int CompressionNoneId = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class QuickTimeCleanUp;
Shinya Kitaoka 120a6e
class QuickTimeStuff {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  static QuickTimeStuff *instance() {
Shinya Kitaoka 120a6e
    if (!m_singleton) m_singleton = new QuickTimeStuff();
Shinya Kitaoka 120a6e
    return m_singleton;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  OSErr getStatus() { return m_status; }
Shinya Kitaoka 120a6e
  ~QuickTimeStuff() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  QuickTimeStuff() : m_status(noErr) {
Shinya Kitaoka 120a6e
    m_status = InitializeQTML(0);
Shinya Kitaoka 120a6e
    EnterMovies();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  static QuickTimeStuff *m_singleton;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  OSErr m_status;
Shinya Kitaoka 120a6e
  friend class QuickTimeCleanUp;  // questa DEVE essere friend, cosi' posso
Shinya Kitaoka 120a6e
                                  // controllare direttamente
Shinya Kitaoka 120a6e
  // lo stato del singleton.
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class QuickTimeCleanUp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  QuickTimeCleanUp() {}
Shinya Kitaoka 120a6e
  ~QuickTimeCleanUp() { /*
Shinya Kitaoka 120a6e
                                      Nel caso si arrivasse qui senza il
Shinya Kitaoka 120a6e
                           singleton instanziato, e si facesse direttamente
Shinya Kitaoka 120a6e
                                      'delete QuickTimeStuff::instance();'
Shinya Kitaoka 120a6e
                           Quicktime non farebbe in tempo a terminare le
Shinya Kitaoka 120a6e
                                      sue routine di inizializzazione (che sono
Shinya Kitaoka 120a6e
                           ANCHE su altri thread) e la chiamata a
Shinya Kitaoka 120a6e
                                      TerminateQTML() causerebbe un crash
Shinya Kitaoka 120a6e
                                      */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (QuickTimeStuff::m_singleton) delete QuickTimeStuff::m_singleton;
Shinya Kitaoka 120a6e
  }
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 {
Shinya Kitaoka 120a6e
  QTNoError = 0x0000,
Shinya Kitaoka 120a6e
  QTNotInstalled,
Shinya Kitaoka 120a6e
  QTUnknownError,
Shinya Kitaoka 120a6e
  QTUnableToOpenFile,
Shinya Kitaoka 120a6e
  QTCantCreateFile,
Shinya Kitaoka 120a6e
  QTUnableToGetCompressorNames,
Shinya Kitaoka 120a6e
  QTUnableToCreateResource,
Shinya Kitaoka 120a6e
  QTUnableToUpdateMovie,
Shinya Kitaoka 120a6e
  QTBadTimeValue,
Shinya Kitaoka 120a6e
  QTUnableToDoMovieTask,
Shinya Kitaoka 120a6e
  QTUnableToSetTimeValue,
Shinya Kitaoka 120a6e
  QTUnableToSetMovieGWorld,
Shinya Kitaoka 120a6e
  QTUnableToSetMovieBox,
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
string buildQTErrorString(int ec) {
Shinya Kitaoka 120a6e
  switch (ec) {
Shinya Kitaoka 120a6e
  case QTNotInstalled:
Shinya Kitaoka 120a6e
    return "Can't create; ensure that quicktime is correctly installed on your "
Shinya Kitaoka 120a6e
           "machine";
Shinya Kitaoka 120a6e
  case QTUnknownError:
Shinya Kitaoka 120a6e
    return "Unknown error";
Shinya Kitaoka 120a6e
  case QTUnableToOpenFile:
Shinya Kitaoka 120a6e
    return "can't open file";
Shinya Kitaoka 120a6e
  case QTCantCreateFile:
Shinya Kitaoka 120a6e
    return "can't create movie";
Shinya Kitaoka 120a6e
  case QTUnableToGetCompressorNames:
Shinya Kitaoka 120a6e
    return "unable to get compressor name";
Shinya Kitaoka 120a6e
  case QTUnableToCreateResource:
Shinya Kitaoka 120a6e
    return "can't create resource";
Shinya Kitaoka 120a6e
  case QTUnableToUpdateMovie:
Shinya Kitaoka 120a6e
    return "unable to update movie";
Shinya Kitaoka 120a6e
  case QTBadTimeValue:
Shinya Kitaoka 120a6e
    return "bad frame number";
Shinya Kitaoka 120a6e
  case QTUnableToDoMovieTask:
Shinya Kitaoka 120a6e
    return "unable to do movie task";
Shinya Kitaoka 120a6e
  case QTUnableToSetTimeValue:
Shinya Kitaoka 120a6e
    return "unable to set time value";
Shinya Kitaoka 120a6e
  case QTUnableToSetMovieGWorld:
Shinya Kitaoka 120a6e
    return "unable to set movie graphic world";
Shinya Kitaoka 120a6e
  case QTUnableToSetMovieBox:
Shinya Kitaoka 120a6e
    return "unable to set movie box";
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  default: { return "unknown error ('" + std::to_string(ec) + "')"; }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline LPSTR AtlW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars, UINT acp) {
Shinya Kitaoka 120a6e
  assert(lpw != NULL);
Shinya Kitaoka 120a6e
  assert(lpa != NULL);
Shinya Kitaoka 120a6e
  // verify that no illegal character present
Shinya Kitaoka 120a6e
  // since lpa was allocated based on the size of lpw
Shinya Kitaoka 120a6e
  // don't worry about the number of chars
Shinya Kitaoka 120a6e
  lpa[0] = '\0';
Shinya Kitaoka 120a6e
  WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL);
Shinya Kitaoka 120a6e
  return lpa;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline char *filePath2unichar(const TFilePath &path) {
Shinya Kitaoka 120a6e
  int _convert    = 0;
Shinya Kitaoka 120a6e
  std::wstring ws = path.getWideString();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  LPCWSTR lpw = ws.c_str();
Shinya Kitaoka 120a6e
  char *name  = NULL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (lpw) {
Shinya Kitaoka 120a6e
    _convert   = (lstrlenW(lpw) + 1) * 2;
Shinya Kitaoka 120a6e
    LPSTR pStr = new char[_convert];
Shinya Kitaoka 120a6e
    name       = AtlW2AHelper(pStr, lpw, _convert, 0);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  char *outName = new char[1024];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (QTMLGetCanonicalPathName(name, outName, 1024) == noErr) {
Shinya Kitaoka 120a6e
    delete[] name;
Shinya Kitaoka 120a6e
    return outName;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  delete[] outName;
Shinya Kitaoka 120a6e
  return name;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath getLegalName(const TFilePath &name) {
Shinya Kitaoka 120a6e
  if (QuickTimeStuff::instance()->getStatus() != noErr) return name;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFilePath legalName;
Shinya Kitaoka 120a6e
  char outDir[1024];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFilePath dirName(name.getParentDir());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  char dirNameFp[1024] = "";
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  OSErr err = QTMLGetCanonicalPathName(dirNameFp, outDir, 1024);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (err == noErr)
Shinya Kitaoka 120a6e
    legalName = TFilePath(outDir) + name.withoutParentDir();
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    legalName = name;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return legalName;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------`----------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
string long2fourchar(TINT32 fcc) {
Shinya Kitaoka 120a6e
  string s;
Shinya Kitaoka 120a6e
  s += (char((fcc & 0xff000000) >> 24));
Shinya Kitaoka 120a6e
  s += (char((fcc & 0x00ff0000) >> 16));
Shinya Kitaoka 120a6e
  s += (char((fcc & 0x0000ff00) >> 8));
Shinya Kitaoka 120a6e
  s += (char((fcc & 0x000000ff) >> 0));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return s;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const std::string CodecNamesId   = "PU_CodecName";
Shinya Kitaoka 3bfa54
const std::string CodecQualityId = "PU_CodecQuality";
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//  TImageWriterMov
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class TImageWriter3gp final : public TImageWriter {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TImageWriter3gp(const TFilePath &, int frameIndex, TLevelWriter3gp *);
Shinya Kitaoka 120a6e
  ~TImageWriter3gp() { m_lwm->release(); }
Shinya Kitaoka 473e70
  bool is64bitOutputSupported() override { return false; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  // not implemented
Shinya Kitaoka 120a6e
  TImageWriter3gp(const TImageWriter3gp &);
Shinya Kitaoka 120a6e
  TImageWriter3gp &operator=(const TImageWriter3gp &src);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 473e70
  void save(const TImageP &) override;
Shinya Kitaoka 120a6e
  int m_frameIndex;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  TLevelWriter3gp *m_lwm;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
//  TImageReaderv
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Shinya Kitaoka d1f6c4
class TImageReader3gp final : public TImageReader {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TImageReader3gp(const TFilePath &, int frameIndex, TLevelReader3gp *);
Shinya Kitaoka 120a6e
  ~TImageReader3gp() { m_lrm->release(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  // not implemented
Shinya Kitaoka 120a6e
  TImageReader3gp(const TImageReader3gp &);
Shinya Kitaoka 120a6e
  TImageReader3gp &operator=(const TImageReader3gp &src);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 473e70
  TImageP load() override;
Shinya Kitaoka 120a6e
  void load(const TRasterP &rasP, const TPoint &pos = TPoint(0, 0),
Shinya Kitaoka 120a6e
            int shrinkX = 1, int shrinkY = 1);
Shinya Kitaoka 120a6e
  int m_frameIndex;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TDimension getSize() const { return m_lrm->getSize(); }
Shinya Kitaoka 120a6e
  TRect getBBox() const { return m_lrm->getBBox(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  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
Shinya Kitaoka 120a6e
TImageWriter3gp::TImageWriter3gp(const TFilePath &path, int frameIndex,
Shinya Kitaoka 120a6e
                                 TLevelWriter3gp *lwm)
Shinya Kitaoka 120a6e
    : TImageWriter(path), m_lwm(lwm), m_frameIndex(frameIndex) {
Shinya Kitaoka 120a6e
  m_lwm->addRef();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
void copy(TRasterP rin, PixelXRGB *bufout, int lx, int ly) {
Shinya Kitaoka 120a6e
  rin->lock();
Shinya Kitaoka 120a6e
  TRaster32P rin32 = rin;
Shinya Kitaoka 120a6e
  assert(rin32);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  PixelXRGB *rowout = &(bufout[(ly - 1) * lx]);
Shinya Kitaoka 120a6e
  for (int y = 0; y < rin32->getLy(); y++) {
Shinya Kitaoka 120a6e
    PixelXRGB *pixout      = rowout;
Shinya Kitaoka 120a6e
    TPixelRGBM32 *pixin    = rin32->pixels(y);
Shinya Kitaoka 120a6e
    TPixelRGBM32 *pixinEnd = pixin + rin32->getLx();
Shinya Kitaoka 120a6e
    while (pixin < pixinEnd) {
Shinya Kitaoka 120a6e
      pixout->x = pixin->m;
Shinya Kitaoka 120a6e
      pixout->r = pixin->r;
Shinya Kitaoka 120a6e
      pixout->g = pixin->g;
Shinya Kitaoka 120a6e
      pixout->b = pixin->b;
Shinya Kitaoka 120a6e
      pixout++;
Shinya Kitaoka 120a6e
      pixin++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    rowout -= lx;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  rin->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Shinya Kitaoka 120a6e
void TImageWriter3gp::save(const TImageP &img) {
Shinya Kitaoka 120a6e
  m_lwm->save(img, m_frameIndex);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TLevelWriter3gp::save(const TImageP &img, int frameIndex) {
Shinya Kitaoka 120a6e
  if (m_cancelled) return;
Shinya Kitaoka 120a6e
  string msg;
Shinya Kitaoka 120a6e
  QMutexLocker sl(&m_mutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRasterImageP image(img);
Shinya Kitaoka 120a6e
  TRasterP ras = image->getRaster();
Shinya Kitaoka 120a6e
  int lx       = ras->getLx();
Shinya Kitaoka 120a6e
  int ly       = ras->getLy();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ras->lock();
Shinya Kitaoka 120a6e
  void *buffer = image->getRaster()->getRawData();
Shinya Kitaoka 120a6e
  int pixSize  = image->getRaster()->getPixelSize();
Shinya Kitaoka 120a6e
  if (pixSize != 4) {
Shinya Kitaoka 120a6e
    msg = "Unsupported pixel type";
Shinya Kitaoka 120a6e
    goto error;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_properties) m_properties = new Tiio::MovWriterProperties();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Tiio::MovWriterProperties *prop = (Tiio::MovWriterProperties *)(m_properties);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QTAtomContainer atoms;
Shinya Kitaoka 120a6e
  QTNewAtomContainer(&atoms);
Shinya Kitaoka 120a6e
  fromPropertiesToAtoms(*prop, atoms);
Shinya Kitaoka 120a6e
  ComponentInstance ci =
Shinya Kitaoka 120a6e
      OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType);
Shinya Kitaoka 120a6e
  if (SCSetSettingsFromAtomContainer(ci, atoms)) assert(false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*
Toshihiro Shimizu 890ddd
CodecType compression = prop->getCurrentCodec();
Toshihiro Shimizu 890ddd
CodecQ quality = prop->getCurrentQuality();
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_initDone) {
Shinya Kitaoka 120a6e
    Rect frame;
Shinya Kitaoka 120a6e
    QDErr err;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_videoTrack = NewMovieTrack(m_movie, FixRatio((short)lx, 1),
Shinya Kitaoka 120a6e
                                 FixRatio((short)ly, 1), kNoVolume);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if ((err = GetMoviesError() != noErr)) {
Shinya Kitaoka 120a6e
      msg = "can't create video track";
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_dataRef    = nil;
Shinya Kitaoka 120a6e
    m_hMovieData = NewHandle(0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Construct the Handle data reference
Shinya Kitaoka 120a6e
    err = PtrToHand(&m_hMovieData, &m_dataRef, sizeof(Handle));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if ((err = GetMoviesError() != noErr)) {
Shinya Kitaoka 120a6e
      msg = "can't create Data Ref";
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_videoMedia =
Shinya Kitaoka 120a6e
        NewTrackMedia(m_videoTrack, VideoMediaType, (TINT32)m_frameRate,
Shinya Kitaoka 120a6e
                      m_dataRef, HandleDataHandlerSubType);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    OpenADefaultComponent(MovieExportType, '3gpp', &m_myExporter);
Shinya Kitaoka 120a6e
    if (TSystem::doHaveMainLoop())
Shinya Kitaoka 120a6e
      err = (short)MovieExportDoUserDialog(m_myExporter, m_movie, 0, 0, 0,
Shinya Kitaoka 120a6e
                                           &m_cancelled);
Shinya Kitaoka 120a6e
    if (m_cancelled) {
Shinya Kitaoka 120a6e
      msg = "user abort of 3gp creation";
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if ((err = GetMoviesError() != noErr)) {
Shinya Kitaoka 120a6e
      msg = "can't create video media";
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if ((err = BeginMediaEdits(m_videoMedia)) != noErr) {
Shinya Kitaoka 120a6e
      msg = "can't begin edit video media";
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    frame.left   = 0;
Shinya Kitaoka 120a6e
    frame.top    = 0;
Shinya Kitaoka 120a6e
    frame.right  = lx;
Shinya Kitaoka 120a6e
    frame.bottom = ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if ((err = NewGWorld(&(m_gworld), pixSize * 8, &frame, 0, 0, 0)) != noErr) {
Shinya Kitaoka 120a6e
      msg = "can't create movie buffer";
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    LockPixels(m_gworld->portPixMap);
Shinya Kitaoka 120a6e
    /*if ((err = GetMaxCompressionSize(m_gworld->portPixMap, &frame, 0,
Shinya Kitaoka 120a6e
                    quality,  compression,anyCodec,
Shinya Kitaoka 120a6e
                                                                                                                     &max_compressed_size))!=noErr)
Shinya Kitaoka 120a6e
throw TImageException(getFilePath(), "can't get max compression size");
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if ((err = MemError()) != noErr) {
Shinya Kitaoka 120a6e
      msg = "can't allocate compressed data for movie";
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if ((err = MemError()) != noErr) {
Shinya Kitaoka 120a6e
      msg = "can't allocate img handle";
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_pixmap = GetGWorldPixMap(m_gworld);
Shinya Kitaoka 120a6e
    if (!LockPixels(m_pixmap)) {
Shinya Kitaoka 120a6e
      msg = "can't lock pixels";
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    buf    = (PixelXRGB *)(*(m_pixmap))->baseAddr;
Shinya Kitaoka 120a6e
    buf_lx = lx;
Shinya Kitaoka 120a6e
    buf_ly = ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_initDone = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Rect frame;
Shinya Kitaoka 120a6e
  ImageDescriptionHandle img_descr = 0;
Shinya Kitaoka 120a6e
  Handle compressedData            = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QDErr err;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  frame.left   = 0;
Shinya Kitaoka 120a6e
  frame.top    = 0;
Shinya Kitaoka 120a6e
  frame.right  = lx;
Shinya Kitaoka 120a6e
  frame.bottom = ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  copy(ras, buf, buf_lx, buf_ly);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((err = (QDErr)SCCompressImage(ci, m_gworld->portPixMap, &frame,
Shinya Kitaoka 120a6e
                                    &img_descr, &compressedData)) != noErr) {
Shinya Kitaoka 120a6e
    msg = "can't compress image";
Shinya Kitaoka 120a6e
    goto error;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
if ((err = CompressImage(m_gworld->portPixMap,
Shinya Kitaoka 120a6e
                         &frame,
Shinya Kitaoka 120a6e
                                                                                           quality, compression,
Shinya Kitaoka 120a6e
                                                                                           img_descr, compressed_data_ptr))!=noErr)
Shinya Kitaoka 120a6e
throw TImageException(getFilePath(), "can't compress image");
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
  if ((err = AddMediaSample(
Shinya Kitaoka 120a6e
           m_videoMedia, compressedData, 0, (*img_descr)->dataSize, 1,
Shinya Kitaoka 120a6e
           (SampleDescriptionHandle)img_descr, 1, 0, 0)) != noErr) {
Shinya Kitaoka 120a6e
    msg = "can't add image to movie media";
Shinya Kitaoka 120a6e
    goto error;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  DisposeHandle((Handle)img_descr);
Shinya Kitaoka 120a6e
  DisposeHandle(compressedData);
Shinya Kitaoka 120a6e
  ras->unlock();
Shinya Kitaoka 120a6e
  return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
error:
Shinya Kitaoka 120a6e
  ras->unlock();
Shinya Kitaoka 120a6e
  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)
Shinya Kitaoka 120a6e
    : TLevelWriter(path, winfo)
Shinya Kitaoka 120a6e
    , m_initDone(false)
Shinya Kitaoka 120a6e
    , m_IOError(QTNoError)
Shinya Kitaoka 120a6e
    , m_pixmap(0)
Shinya Kitaoka 120a6e
    , m_gworld(0)
Shinya Kitaoka 120a6e
    , m_videoMedia(0)
Shinya Kitaoka 120a6e
    , m_videoTrack(0)
Shinya Kitaoka 120a6e
    , m_movie(0)
Shinya Kitaoka 120a6e
    , m_cancelled(false)
Shinya Kitaoka 120a6e
    , m_soundDataRef(0)
Shinya Kitaoka 120a6e
    , m_hSoundMovieData(0)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
  m_frameRate = 12.;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (QuickTimeStuff::instance()->getStatus() != noErr) {
Shinya Kitaoka 120a6e
    m_IOError = QTNotInstalled;
Shinya Kitaoka 120a6e
    throw TImageException(m_path, buildQTErrorString(m_IOError));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QDErr err;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_movie = NewMovie(0);
Shinya Kitaoka 120a6e
  if ((err = GetMoviesError() != noErr))
Shinya Kitaoka 120a6e
    throw TImageException(getFilePath(), "can't create movie");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
#define FailIf(cond, handler)                                                  \
Shinya Kitaoka 120a6e
  if (cond) {                                                                  \
Shinya Kitaoka 120a6e
    DebugStr((ConstStr255Param) #cond " goto " #handler);                      \
Shinya Kitaoka 120a6e
    goto handler;                                                              \
Shinya Kitaoka 120a6e
  } else                                                                       \
Shinya Kitaoka 120a6e
    0
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
#define FailIf(cond, handler)                                                  \
Shinya Kitaoka 120a6e
  if (cond) {                                                                  \
Shinya Kitaoka 120a6e
    goto handler;                                                              \
Shinya Kitaoka 120a6e
  } else                                                                       \
Shinya Kitaoka 120a6e
    0
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
#define FailWithAction(cond, action, handler)                                  \
Shinya Kitaoka 120a6e
  if (cond) {                                                                  \
Shinya Kitaoka 120a6e
    DebugStr((ConstStr255Param) #cond " goto " #handler);                      \
Shinya Kitaoka 120a6e
    { action; }                                                                \
Shinya Kitaoka 120a6e
    goto handler;                                                              \
Shinya Kitaoka 120a6e
  } else                                                                       \
Shinya Kitaoka 120a6e
    0
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
#define FailWithAction(cond, action, handler)                                  \
Shinya Kitaoka 120a6e
  if (cond) {                                                                  \
Shinya Kitaoka 120a6e
    { action; }                                                                \
Shinya Kitaoka 120a6e
    goto handler;                                                              \
Shinya Kitaoka 120a6e
  } else                                                                       \
Shinya Kitaoka 120a6e
    0
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TLevelWriter3gp::saveSoundTrack(TSoundTrack *st) {
Shinya Kitaoka 120a6e
  Track theTrack;
Shinya Kitaoka 120a6e
  OSErr myErr = noErr;
Shinya Kitaoka 120a6e
  SoundDescriptionV1Handle mySampleDesc;
Shinya Kitaoka 120a6e
  Media myMedia;
Shinya Kitaoka 120a6e
  Handle myDestHandle;
Shinya Kitaoka 120a6e
  SoundComponentData sourceInfo;
Shinya Kitaoka 120a6e
  SoundComponentData destInfo;
Shinya Kitaoka 120a6e
  SoundConverter converter;
Shinya Kitaoka 120a6e
  CompressionInfo compressionInfo;
Shinya Kitaoka 120a6e
  int err;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_cancelled) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!st) throw TException("null reference to soundtrack");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (st->getBitPerSample() != 16) {
Shinya Kitaoka 120a6e
    throw TImageException(m_path, "Only 16 bits per sample is supported");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  theTrack = NewMovieTrack(m_movie, 0, 0, kFullVolume);
Shinya Kitaoka 120a6e
  myErr    = GetMoviesError();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  FailIf(myErr != noErr, CompressErr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  myDestHandle = NewHandle(0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  FailWithAction(myDestHandle == NULL, myErr = MemError(), NoDest);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  *myDestHandle = (char *)st->getRawData();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //////////
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  // create a media for the track passed in
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //////////
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // set new track to be a sound track
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_soundDataRef    = nil;
Shinya Kitaoka 120a6e
  m_hSoundMovieData = NewHandle(0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Construct the Handle data reference
Shinya Kitaoka 120a6e
  err = PtrToHand(&m_hSoundMovieData, &m_soundDataRef, sizeof(Handle));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((err = GetMoviesError() != noErr))
Shinya Kitaoka 120a6e
    throw TImageException(getFilePath(), "can't create Data Ref");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  myMedia = NewTrackMedia(theTrack, SoundMediaType, st->getSampleRate(),
Shinya Kitaoka 120a6e
                          m_soundDataRef,
Shinya Kitaoka 120a6e
                          HandleDataHandlerSubType);  // track->rate >> 16
Shinya Kitaoka 120a6e
  myErr = GetMoviesError();
Shinya Kitaoka 120a6e
  FailIf(myErr != noErr, Exit);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // start a media editing session
Shinya Kitaoka 120a6e
  myErr = BeginMediaEdits(myMedia);
Shinya Kitaoka 120a6e
  FailIf(myErr != noErr, Exit);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  sourceInfo.flags       = 0x0;
Shinya Kitaoka 120a6e
  sourceInfo.format      = kSoundNotCompressed;
Shinya Kitaoka 120a6e
  sourceInfo.numChannels = st->getChannelCount();
Shinya Kitaoka 120a6e
  sourceInfo.sampleSize  = st->getBitPerSample();
Shinya Kitaoka 120a6e
  sourceInfo.sampleRate  = st->getSampleRate();
Shinya Kitaoka 120a6e
  sourceInfo.sampleCount = st->getSampleCount();
Shinya Kitaoka 120a6e
  sourceInfo.buffer      = (unsigned char *)st->getRawData();
Shinya Kitaoka 120a6e
  sourceInfo.reserved    = 0x0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  destInfo.flags = kNoSampleRateConversion | kNoSampleSizeConversion |
Shinya Kitaoka 120a6e
                   kNoSampleFormatConversion | kNoChannelConversion |
Shinya Kitaoka 120a6e
                   kNoDecompression | kNoVolumeConversion |
Shinya Kitaoka 120a6e
                   kNoRealtimeProcessing;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  destInfo.format = k16BitNativeEndianFormat;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  destInfo.numChannels = st->getChannelCount();
Shinya Kitaoka 120a6e
  destInfo.sampleSize  = st->getBitPerSample();
Shinya Kitaoka 120a6e
  destInfo.sampleRate  = st->getSampleRate();
Shinya Kitaoka 120a6e
  destInfo.sampleCount = st->getSampleCount();
Shinya Kitaoka 120a6e
  destInfo.buffer      = (unsigned char *)st->getRawData();
Shinya Kitaoka 120a6e
  destInfo.reserved    = 0x0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  SoundConverterOpen(&sourceInfo, &destInfo, &converter);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  myErr =
Shinya Kitaoka 120a6e
      SoundConverterGetInfo(converter, siCompressionFactor, &compressionInfo);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  myErr =
Shinya Kitaoka 120a6e
      SoundConverterGetInfo(converter, siCompressionFactor, &compressionInfo);
Shinya Kitaoka 120a6e
  myErr = GetCompressionInfo(fixedCompression, sourceInfo.format,
Shinya Kitaoka 120a6e
                             sourceInfo.numChannels, sourceInfo.sampleSize,
Shinya Kitaoka 120a6e
                             &compressionInfo);
Shinya Kitaoka 120a6e
  FailIf(myErr != noErr, ConverterErr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  compressionInfo.bytesPerFrame =
Shinya Kitaoka 120a6e
      compressionInfo.bytesPerPacket * destInfo.numChannels;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //////////
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  // create a sound sample description
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //////////
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // use the SoundDescription format 1 because it adds fields for data size
Shinya Kitaoka 120a6e
  // information
Shinya Kitaoka 120a6e
  // and is required by AddSoundDescriptionExtension if an extension is required
Shinya Kitaoka 120a6e
  // for the compression format
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  mySampleDesc =
Shinya Kitaoka 120a6e
      (SoundDescriptionV1Handle)NewHandleClear(sizeof(SoundDescriptionV1));
Shinya Kitaoka 120a6e
  FailWithAction(myErr != noErr, myErr = MemError(), Exit);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.descSize      = sizeof(SoundDescriptionV1);
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.dataFormat    = destInfo.format;
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.resvd1        = 0;
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.resvd2        = 0;
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.dataRefIndex  = 1;
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.version       = 1;
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.revlevel      = 0;
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.vendor        = 0;
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.numChannels   = destInfo.numChannels;
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.sampleSize    = destInfo.sampleSize;
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.compressionID = 0;
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.packetSize    = 0;
Shinya Kitaoka 120a6e
  (**mySampleDesc).desc.sampleRate    = st->getSampleRate() << 16;
Shinya Kitaoka 120a6e
  (**mySampleDesc).samplesPerPacket   = compressionInfo.samplesPerPacket;
Shinya Kitaoka 120a6e
  (**mySampleDesc).bytesPerPacket     = compressionInfo.bytesPerPacket;
Shinya Kitaoka 120a6e
  (**mySampleDesc).bytesPerFrame      = compressionInfo.bytesPerFrame;
Shinya Kitaoka 120a6e
  (**mySampleDesc).bytesPerSample     = compressionInfo.bytesPerSample;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //////////
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  // add samples to the media
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //////////
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  myErr = AddMediaSample(
Shinya Kitaoka 120a6e
      myMedia, myDestHandle, 0,
Shinya Kitaoka 120a6e
      destInfo.sampleCount * compressionInfo.bytesPerFrame, 1,
Shinya Kitaoka 120a6e
      (SampleDescriptionHandle)mySampleDesc,
Shinya Kitaoka 120a6e
      destInfo.sampleCount * compressionInfo.samplesPerPacket, 0, NULL);
Shinya Kitaoka 120a6e
  FailIf(myErr != noErr, MediaErr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  myErr = EndMediaEdits(myMedia);
Shinya Kitaoka 120a6e
  FailIf(myErr != noErr, MediaErr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //////////
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  // insert the media into the track
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //////////
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  myErr =
Shinya Kitaoka 120a6e
      InsertMediaIntoTrack(theTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
Shinya Kitaoka 120a6e
  FailIf(myErr != noErr, MediaErr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  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:
Shinya Kitaoka 120a6e
  if (mySampleDesc != NULL) DisposeHandle((Handle)mySampleDesc);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (converter) SoundConverterClose(converter);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (myErr != noErr) throw TImageException(m_path, "error saving audio track");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TLevelWriter3gp::~TLevelWriter3gp() {
Shinya Kitaoka 120a6e
  if (m_pixmap) UnlockPixels(m_pixmap);
Shinya Kitaoka 120a6e
  if (m_gworld) DisposeGWorld(m_gworld);
Shinya Kitaoka 120a6e
  QDErr err;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_videoMedia)
Shinya Kitaoka 120a6e
    if ((err = EndMediaEdits(m_videoMedia)) != noErr) {
Shinya Kitaoka 120a6e
    }  // throw TImageException(getFilePath(), "can't end edit media");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_videoTrack)
Shinya Kitaoka 120a6e
    if ((err = InsertMediaIntoTrack(m_videoTrack, 0, 0,
Shinya Kitaoka 120a6e
                                    GetMediaDuration(m_videoMedia), fixed1))) {
Shinya Kitaoka 120a6e
    }  // throw TImageException(getFilePath(), "can't insert media into track");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  short resId = movieInDataForkResID;
Shinya Kitaoka 120a6e
  if (m_movie) {
Shinya Kitaoka 120a6e
    FSSpec fspec;
Shinya Kitaoka 120a6e
    long myFlags      = 0L;
Shinya Kitaoka 120a6e
    OSErr myErr       = noErr;
Shinya Kitaoka 120a6e
    UCHAR myCancelled = FALSE;
Shinya Kitaoka 120a6e
    char *pStr        = filePath2unichar(m_path);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    NativePathNameToFSSpec(pStr, &fspec, kFullNativePath);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    myFlags = createMovieFileDeleteCurFile;  // |
Shinya Kitaoka 120a6e
    // movieFileSpecValid | movieToFileOnlyExport;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    myErr =
Shinya Kitaoka 120a6e
        ConvertMovieToFile(m_movie,                 // the movie to convert
Shinya Kitaoka 120a6e
                           NULL,                    // all tracks in the movie
Shinya Kitaoka 120a6e
                           &fspec,                  // the output file
Shinya Kitaoka 120a6e
                           '3gpp',                  // the output file type
Shinya Kitaoka 120a6e
                           FOUR_CHAR_CODE('TVOD'),  // the output file creator
Shinya Kitaoka 120a6e
                           smSystemScript,          // the script
Shinya Kitaoka 120a6e
                           &resId,         // no resource ID to be returned
Shinya Kitaoka 120a6e
                           myFlags,        // export flags
Shinya Kitaoka 120a6e
                           m_myExporter);  // no specific exp
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  DisposeHandle(m_hMovieData);
Shinya Kitaoka 120a6e
  DisposeHandle(m_dataRef);
Shinya Kitaoka 120a6e
  if (m_hSoundMovieData) DisposeHandle(m_hMovieData);
Shinya Kitaoka 120a6e
  if (m_hSoundMovieData) DisposeHandle(m_hSoundMovieData);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_refNum) CloseMovieFile(m_refNum);
Shinya Kitaoka 120a6e
  DisposeMovie(m_movie);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TImageWriterP TLevelWriter3gp::getFrameWriter(TFrameId fid) {
Shinya Kitaoka 120a6e
  if (m_cancelled) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_IOError) throw TImageException(m_path, buildQTErrorString(m_IOError));
Shinya Kitaoka 120a6e
  if (fid.getLetter() != 0) return TImageWriterP(0);
Shinya Kitaoka 120a6e
  int index = fid.getNumber() - 1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TImageWriter3gp *iwm = new TImageWriter3gp(m_path, index, this);
Shinya Kitaoka 120a6e
  return TImageWriterP(iwm);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TLevelReader3gp::TLevelReader3gp(const TFilePath &path)
Shinya Kitaoka 120a6e
    : TLevelReader(path)
Shinya Kitaoka 120a6e
    , m_IOError(QTNoError)
Shinya Kitaoka 120a6e
    , m_track(0)
Shinya Kitaoka 120a6e
    , m_movie(0)
Shinya Kitaoka 120a6e
    , m_depth(0)
Toshihiro Shimizu 890ddd
//                ,m_timeScale(0)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
  FSSpec fspec;
Shinya Kitaoka 120a6e
  QDErr err;
Shinya Kitaoka 120a6e
  Boolean dataRefWasChanged;
Shinya Kitaoka 120a6e
  if (QuickTimeStuff::instance()->getStatus() != noErr) {
Shinya Kitaoka 120a6e
    m_IOError = QTNotInstalled;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  char *pStr = filePath2unichar(m_path);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((err = NativePathNameToFSSpec(pStr, &fspec, kFullNativePath)) != noErr) {
Shinya Kitaoka 120a6e
    delete[] pStr;
Shinya Kitaoka 120a6e
    pStr = 0;
Shinya Kitaoka 120a6e
    throw TImageException(path, "can't open file");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  delete[] pStr;
Shinya Kitaoka 120a6e
  pStr = 0;
Shinya Kitaoka 120a6e
  if ((err = OpenMovieFile(&fspec, &m_refNum, fsRdPerm))) {
Shinya Kitaoka 120a6e
    m_IOError = QTUnableToOpenFile;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_resId = 0;
Shinya Kitaoka 120a6e
  Str255 name;
Shinya Kitaoka 120a6e
  err = NewMovieFromFile(&m_movie, m_refNum, &m_resId, name, fsRdPerm,
Shinya Kitaoka 120a6e
                         &dataRefWasChanged);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int numTracks = GetMovieTrackCount(m_movie);
Shinya Kitaoka 120a6e
  assert(numTracks == 1 || numTracks == 2);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_track =
Shinya Kitaoka 120a6e
      GetMovieIndTrackType(m_movie, 1, VideoMediaType, movieTrackMediaType);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // m_track=GetMovieTrack(m_movie,numTracks);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ImageDescriptionHandle imageH;
Shinya Kitaoka 120a6e
  imageH = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
Shinya Kitaoka 120a6e
  TINT32 index   = 1;
Shinya Kitaoka 120a6e
  Media theMedia = GetTrackMedia(m_track);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  GetMediaSampleDescription(theMedia, index, (SampleDescriptionHandle)imageH);
Shinya Kitaoka 120a6e
  ImageDescriptionPtr imagePtr = *imageH;
Shinya Kitaoka 120a6e
  m_lx                         = imagePtr->width;
Shinya Kitaoka 120a6e
  m_ly                         = imagePtr->height;
Shinya Kitaoka 120a6e
  m_depth                      = imagePtr->depth;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  DisposeHandle((Handle)imageH);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // 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
Shinya Kitaoka 120a6e
TImageReader3gp::TImageReader3gp(const TFilePath &path, int frameIndex,
Shinya Kitaoka 120a6e
                                 TLevelReader3gp *lrm)
Shinya Kitaoka 120a6e
    : TImageReader(path), m_lrm(lrm), m_frameIndex(frameIndex) {
Shinya Kitaoka 120a6e
  m_lrm->addRef();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TLevelReader3gp::~TLevelReader3gp() {
Shinya Kitaoka 120a6e
  StopMovie(m_movie);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_refNum) CloseMovieFile(m_refNum);
Shinya Kitaoka 120a6e
  if (m_movie) DisposeMovie(m_movie);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TLevelP TLevelReader3gp::loadInfo() {
Shinya Kitaoka 120a6e
  TLevelP level;
Shinya Kitaoka 120a6e
  if (m_IOError != QTNoError)
Shinya Kitaoka 120a6e
    throw TImageException(m_path, buildQTErrorString(m_IOError));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  OSType mediaType = VisualMediaCharacteristic;
Shinya Kitaoka 120a6e
  TimeValue nextTime, currentTime;
Shinya Kitaoka 120a6e
  currentTime = 0;
Shinya Kitaoka 120a6e
  nextTime    = 0;
Shinya Kitaoka 120a6e
  // per il primo
Shinya Kitaoka 120a6e
  int f = 1;
Shinya Kitaoka 120a6e
  // io vorrei fare '|', ma sul manuale c'e' scritto '+'
Shinya Kitaoka 120a6e
  GetMovieNextInterestingTime(m_movie, nextTimeMediaSample + nextTimeEdgeOK, 1,
Shinya Kitaoka 120a6e
                              &mediaType, currentTime, 0, &nextTime, 0);
Shinya Kitaoka 120a6e
  if (nextTime != -1) {
Shinya Kitaoka 120a6e
    TFrameId frame(f);
Shinya Kitaoka 120a6e
    level->setFrame(frame, TImageP());
Shinya Kitaoka 120a6e
    currentTimes.push_back(nextTime);
Shinya Kitaoka 120a6e
    f++;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  currentTime = nextTime;
Shinya Kitaoka 120a6e
  while (nextTime != -1) {
Shinya Kitaoka 120a6e
    GetMovieNextInterestingTime(m_movie, nextTimeMediaSample, 1, &mediaType,
Shinya Kitaoka 120a6e
                                currentTime, 0, &nextTime, 0);
Shinya Kitaoka 120a6e
    if (nextTime != -1) {
Shinya Kitaoka 120a6e
      TFrameId frame(f);
Shinya Kitaoka 120a6e
      level->setFrame(frame, TImageP());
Shinya Kitaoka 120a6e
      currentTimes.push_back(nextTime);
Shinya Kitaoka 120a6e
      f++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    currentTime = nextTime;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return level;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TImageP TImageReader3gp::load() {
Shinya Kitaoka 120a6e
  TRasterPT<tpixelrgbm32> ret(m_lrm->getSize());</tpixelrgbm32>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_lrm->load(ret, m_frameIndex, TPointI(), 1, 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return TRasterImageP(ret);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TImageReader3gp::load(const TRasterP &rasP, const TPoint &pos, int shrinkX,
Shinya Kitaoka 120a6e
                           int shrinkY) {
Shinya Kitaoka 120a6e
  if ((shrinkX != 1) || (shrinkY != 1) || (pos != TPoint(0, 0))) {
Shinya Kitaoka 120a6e
    TImageReader::load(rasP, pos, shrinkX, shrinkY);
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    m_lrm->load(rasP, m_frameIndex, pos, shrinkX, shrinkY);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//------------------------------------------------
Shinya Kitaoka 120a6e
inline void setMatteAndYMirror(const TRaster32P &ras) {
Shinya Kitaoka 120a6e
  ras->lock();
Shinya Kitaoka 38fd86
  TPixel32 *upRow = ras->pixels();
Shinya Kitaoka 38fd86
  TPixel32 *dwRow = ras->pixels(ras->getLy() - 1);
Shinya Kitaoka 38fd86
  int hLy  = (int)(ras->getLy() / 2. + 0.5);  // piccola pessimizzazione...
Shinya Kitaoka 38fd86
  int wrap = ras->getWrap();
Shinya Kitaoka 38fd86
  int lx   = ras->getLx();
Shinya Kitaoka 120a6e
  TPixel32 *upPix   = 0;
Shinya Kitaoka 120a6e
  TPixel32 *lastPix = ras->pixels(hLy);
Shinya Kitaoka 120a6e
  while (upPix < lastPix) {
Shinya Kitaoka 120a6e
    upPix            = upRow;
Shinya Kitaoka 120a6e
    TPixel32 *dwPix  = dwRow;
Shinya Kitaoka 120a6e
    TPixel32 *endPix = upPix + lx;
Shinya Kitaoka 120a6e
    while (upPix < endPix) {
Shinya Kitaoka 120a6e
      TPixel32 tmpPix(upPix->r, upPix->g, upPix->b, 0xff);
Shinya Kitaoka 120a6e
      *upPix   = *dwPix;
Shinya Kitaoka 120a6e
      upPix->m = 0xff;
Shinya Kitaoka 120a6e
      *dwPix   = tmpPix;
Shinya Kitaoka 120a6e
      ++upPix;
Shinya Kitaoka 120a6e
      ++dwPix;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    upRow += wrap;
Shinya Kitaoka 120a6e
    dwRow -= wrap;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TLevelReader3gp::load(const TRasterP &rasP, int frameIndex,
Shinya Kitaoka 120a6e
                           const TPoint &pos, int shrinkX, int shrinkY) {
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    QMutexLocker sl(&m_mutex);
Shinya Kitaoka 120a6e
    if (m_IOError != QTNoError)
Shinya Kitaoka 120a6e
      throw TImageException(m_path, buildQTErrorString(m_IOError));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRaster32P ras = rasP;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    Rect rect;
Shinya Kitaoka 120a6e
    rect.right  = pos.x + ras->getLx();
Shinya Kitaoka 120a6e
    rect.left   = pos.x;
Shinya Kitaoka 120a6e
    rect.bottom = pos.y + ras->getLy();
Shinya Kitaoka 120a6e
    rect.top    = pos.y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    GWorldPtr offscreenGWorld;
Shinya Kitaoka 120a6e
    OSErr err;
Shinya Kitaoka 120a6e
    ras->lock();
Shinya Kitaoka 120a6e
    err = QTNewGWorldFromPtr(&offscreenGWorld, k32BGRAPixelFormat, &rect, 0, 0,
Shinya Kitaoka 120a6e
                             0, ras->getRawData(), ras->getWrap() * 4);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (err != noErr) {
Shinya Kitaoka 120a6e
      m_IOError = QTUnableToCreateResource;
Shinya Kitaoka 120a6e
      DisposeGWorld(offscreenGWorld);
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    SetMovieBox(m_movie, &rect);
Shinya Kitaoka 120a6e
    err = GetMoviesError();
Shinya Kitaoka 120a6e
    if (err != noErr) {
Shinya Kitaoka 120a6e
      m_IOError = QTUnableToSetMovieBox;
Shinya Kitaoka 120a6e
      DisposeGWorld(offscreenGWorld);
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    SetMovieGWorld(m_movie, offscreenGWorld, GetGWorldDevice(offscreenGWorld));
Shinya Kitaoka 120a6e
    err = GetMoviesError();
Shinya Kitaoka 120a6e
    if (err != noErr) {
Shinya Kitaoka 120a6e
      m_IOError = QTUnableToSetMovieGWorld;
Shinya Kitaoka 120a6e
      DisposeGWorld(offscreenGWorld);
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TimeValue currentTime = currentTimes[frameIndex];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    SetMovieTimeValue(m_movie, currentTime);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    err = GetMoviesError();
Shinya Kitaoka 120a6e
    if (err != noErr) {
Shinya Kitaoka 120a6e
      m_IOError = QTUnableToSetTimeValue;
Shinya Kitaoka 120a6e
      DisposeGWorld(offscreenGWorld);
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    err = UpdateMovie(m_movie);
Shinya Kitaoka 120a6e
    if (err != noErr) {
Shinya Kitaoka 120a6e
      m_IOError = QTUnableToUpdateMovie;
Shinya Kitaoka 120a6e
      DisposeGWorld(offscreenGWorld);
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    MoviesTask(m_movie, 0);
Shinya Kitaoka 120a6e
    err = GetMoviesError();
Shinya Kitaoka 120a6e
    if (err != noErr) {
Shinya Kitaoka 120a6e
      m_IOError = QTUnableToDoMovieTask;
Shinya Kitaoka 120a6e
      DisposeGWorld(offscreenGWorld);
Shinya Kitaoka 120a6e
      goto error;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    DisposeGWorld(offscreenGWorld);
Shinya Kitaoka 120a6e
    ras->unlock();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_depth != 32) {
Shinya Kitaoka 120a6e
    setMatteAndYMirror(rasP);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    rasP->yMirror();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
error:
Shinya Kitaoka 120a6e
  rasP->unlock();
Shinya Kitaoka 120a6e
  throw TImageException(m_path, buildQTErrorString(m_IOError));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TImageReaderP TLevelReader3gp::getFrameReader(TFrameId fid) {
Shinya Kitaoka 120a6e
  if (m_IOError != QTNoError)
Shinya Kitaoka 120a6e
    throw TImageException(m_path, buildQTErrorString(m_IOError));
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
  TImageReader3gp *irm = new TImageReader3gp(m_path, index, this);
Shinya Kitaoka 120a6e
  return TImageReaderP(irm);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif