Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "avicodecrestrictions.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include <windows.h></windows.h>
Toshihiro Shimizu 890ddd
#include <vfw.h></vfw.h>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
HIC getCodec(const std::wstring &codecName, int &bpp) {
Shinya Kitaoka 120a6e
  HIC hic = 0;
Shinya Kitaoka 120a6e
  ICINFO icinfo;
Shinya Kitaoka 120a6e
  memset(&icinfo, 0, sizeof(ICINFO));
Shinya Kitaoka 120a6e
  bool found = false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  char descr[2048], name[2048];
Shinya Kitaoka 120a6e
  DWORD fccType = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  BITMAPINFO inFmt;
Shinya Kitaoka 120a6e
  memset(&inFmt, 0, sizeof(BITMAPINFO));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  inFmt.bmiHeader.biSize  = sizeof(BITMAPINFOHEADER);
Shinya Kitaoka 120a6e
  inFmt.bmiHeader.biWidth = inFmt.bmiHeader.biHeight = 100;
Shinya Kitaoka 120a6e
  inFmt.bmiHeader.biPlanes                           = 1;
Shinya Kitaoka 120a6e
  inFmt.bmiHeader.biCompression                      = BI_RGB;
Shinya Kitaoka 120a6e
  for (bpp = 32; (bpp >= 24) && !found; bpp -= 8) {
Shinya Kitaoka 120a6e
    // find the codec.
Shinya Kitaoka 120a6e
    inFmt.bmiHeader.biBitCount = bpp;
Shinya Kitaoka 120a6e
    for (int i = 0; ICInfo(fccType, i, &icinfo); i++) {
Shinya Kitaoka 120a6e
      hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_COMPRESS);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      ICGetInfo(hic, &icinfo, sizeof(ICINFO));  // Find out the compressor name
Shinya Kitaoka 120a6e
      WideCharToMultiByte(CP_ACP, 0, icinfo.szDescription, -1, descr,
Shinya Kitaoka 120a6e
                          sizeof(descr), 0, 0);
Shinya Kitaoka 120a6e
      WideCharToMultiByte(CP_ACP, 0, icinfo.szName, -1, name, sizeof(name), 0,
Shinya Kitaoka 120a6e
                          0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      std::string compressorName;
Shinya Kitaoka 120a6e
      compressorName = std::string(name) + " '" + std::to_string(bpp) + "' " +
Shinya Kitaoka 120a6e
                       std::string(descr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (hic) {
Shinya Kitaoka 120a6e
        if (ICCompressQuery(hic, &inFmt, NULL) != ICERR_OK) {
Shinya Kitaoka 120a6e
          ICClose(hic);
Shinya Kitaoka 120a6e
          continue;  // Skip this compressor if it can't handle the format.
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        if (::to_wstring(compressorName) == codecName) {
Shinya Kitaoka 120a6e
          found = true;
Shinya Kitaoka 120a6e
          break;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        ICClose(hic);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (found) break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return hic;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool canWork(const HIC &hic, const TDimension &resolution, int bpp) {
Shinya Kitaoka 120a6e
  int lx = resolution.lx, ly = resolution.ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  BITMAPINFO bi;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
Shinya Kitaoka 120a6e
  bi.bmiHeader.biPlanes        = 1;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biCompression   = BI_RGB;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biXPelsPerMeter = 80;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biYPelsPerMeter = 72;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biClrUsed       = 0;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biClrImportant  = 0;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biBitCount      = bpp;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biWidth         = lx;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biHeight        = ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return ICERR_OK == ICCompressQuery(hic, &bi.bmiHeader, NULL);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void AviCodecRestrictions::getRestrictions(const std::wstring &codecName,
Shinya Kitaoka 120a6e
                                           QString &restrictions) {
Shinya Kitaoka 120a6e
  restrictions.clear();
Shinya Kitaoka 120a6e
  if (codecName == L"Uncompressed") {
Shinya Kitaoka 120a6e
    restrictions = QObject::tr("No restrictions for uncompressed avi video");
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // find the codec
Shinya Kitaoka 120a6e
  int bpp;
Shinya Kitaoka 120a6e
  HIC hic = getCodec(codecName, bpp);
Shinya Kitaoka 120a6e
  if (!hic) {
Shinya Kitaoka 120a6e
    restrictions = QObject::tr(
Shinya Kitaoka 120a6e
        "It is not possible to communicate with the codec.\n Probably the "
Shinya Kitaoka 120a6e
        "codec cannot work correctly.");
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  BITMAPINFO bi;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
Shinya Kitaoka 120a6e
  bi.bmiHeader.biPlanes        = 1;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biCompression   = BI_RGB;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biXPelsPerMeter = 80;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biYPelsPerMeter = 72;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biClrUsed       = 0;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biClrImportant  = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lx = 640, ly = 480;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biWidth  = lx;
Shinya Kitaoka 120a6e
  bi.bmiHeader.biHeight = ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Loop until we can find a width, height, and depth that works!
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
MCCCS a0ce32
  // check the x length
Shinya Kitaoka 120a6e
  bi.bmiHeader.biBitCount = bpp;
Shinya Kitaoka 120a6e
  for (i = 3; i >= 0; i--) {
Shinya Kitaoka 120a6e
    bi.bmiHeader.biWidth = lx + (1 << i);
Shinya Kitaoka 120a6e
    bi.bmiHeader.biSizeImage =
Shinya Kitaoka 120a6e
        ((bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount + 31) / 32) * 4 * ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (ICERR_OK != ICCompressQuery(hic, &bi.bmiHeader, NULL)) break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (i >= 0)
Shinya Kitaoka 120a6e
    restrictions = QObject::tr("video width must be a multiple of %1")
Shinya Kitaoka 120a6e
                       .arg(QString::number(1 << (i + 1)));
Shinya Kitaoka 120a6e
MCCCS a0ce32
  // check the y length
Shinya Kitaoka 120a6e
  bi.bmiHeader.biWidth = 640;
Shinya Kitaoka 120a6e
  for (i = 3; i >= 0; i--) {
Shinya Kitaoka 120a6e
    bi.bmiHeader.biHeight = ly + (1 << i);
Shinya Kitaoka 120a6e
    bi.bmiHeader.biSizeImage =
Shinya Kitaoka 120a6e
        ((lx * bi.bmiHeader.biBitCount + 31) / 32) * 4 * bi.bmiHeader.biHeight;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (ICERR_OK != ICCompressQuery(hic, &bi.bmiHeader, NULL)) break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (i >= 0)
Shinya Kitaoka 120a6e
    restrictions = restrictions + "\n" +
MCCCS a0ce32
                   QObject::tr("video length must be a multiple of %1")
Shinya Kitaoka 120a6e
                       .arg(QString::number(1 << (i + 1)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ICClose(hic);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (restrictions.isEmpty())
Shinya Kitaoka 120a6e
    restrictions = QObject::tr("No restrictions for this codec");
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    restrictions.prepend(QObject::tr("Resolution restrictions:") + "\n");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool AviCodecRestrictions::canWriteMovie(const std::wstring &codecName,
Shinya Kitaoka 120a6e
                                         const TDimension &resolution) {
Shinya Kitaoka 120a6e
  if (codecName == L"Uncompressed") {
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // find the codec
Shinya Kitaoka 120a6e
  int bpp;
Shinya Kitaoka 120a6e
  HIC hic = getCodec(codecName, bpp);
Shinya Kitaoka 120a6e
  if (!hic) return false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool test = canWork(hic, resolution, bpp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ICClose(hic);
Shinya Kitaoka 120a6e
  return test;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool AviCodecRestrictions::canBeConfigured(const std::wstring &codecName) {
Shinya Kitaoka 120a6e
  if (codecName == L"Uncompressed") return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // find the codec
Shinya Kitaoka 120a6e
  int bpp;
Shinya Kitaoka 120a6e
  HIC hic = getCodec(codecName, bpp);
Shinya Kitaoka 120a6e
  if (!hic) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool test = ICQueryConfigure(hic);
Shinya Kitaoka 120a6e
  ICClose(hic);
Shinya Kitaoka 120a6e
  return test;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void AviCodecRestrictions::openConfiguration(const std::wstring &codecName,
Shinya Kitaoka 120a6e
                                             void *winId) {
Shinya Kitaoka 120a6e
  if (codecName == L"Uncompressed") return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // find the codec
Shinya Kitaoka 120a6e
  int bpp;
Shinya Kitaoka 120a6e
  HIC hic = getCodec(codecName, bpp);
Shinya Kitaoka 120a6e
  if (!hic) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ICConfigure(hic, winId);
Shinya Kitaoka 120a6e
  ICClose(hic);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QMap<std::wstring, bool=""> AviCodecRestrictions::getUsableCodecs(</std::wstring,>
Shinya Kitaoka 120a6e
    const TDimension &resolution) {
Shinya Kitaoka 120a6e
  QMap<std::wstring, bool=""> codecs;</std::wstring,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  HIC hic = 0;
Shinya Kitaoka 120a6e
  ICINFO icinfo;
Shinya Kitaoka 120a6e
  memset(&icinfo, 0, sizeof(ICINFO));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  char descr[2048], name[2048];
Shinya Kitaoka 120a6e
  DWORD fccType = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  BITMAPINFO inFmt;
Shinya Kitaoka 120a6e
  memset(&inFmt, 0, sizeof(BITMAPINFO));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  inFmt.bmiHeader.biSize  = sizeof(BITMAPINFOHEADER);
Shinya Kitaoka 120a6e
  inFmt.bmiHeader.biWidth = inFmt.bmiHeader.biHeight = 100;
Shinya Kitaoka 120a6e
  inFmt.bmiHeader.biPlanes                           = 1;
Shinya Kitaoka 120a6e
  inFmt.bmiHeader.biCompression                      = BI_RGB;
Shinya Kitaoka 120a6e
  int bpp;
Shinya Kitaoka 120a6e
  for (bpp = 32; (bpp >= 24); bpp -= 8) {
Shinya Kitaoka 120a6e
    // find the codec.
Shinya Kitaoka 120a6e
    inFmt.bmiHeader.biBitCount = bpp;
Shinya Kitaoka 120a6e
    for (int i = 0; ICInfo(fccType, i, &icinfo); i++) {
Shinya Kitaoka 120a6e
      hic = ICOpen(icinfo.fccType, icinfo.fccHandler, ICMODE_COMPRESS);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      ICGetInfo(hic, &icinfo, sizeof(ICINFO));  // Find out the compressor name
Shinya Kitaoka 120a6e
      WideCharToMultiByte(CP_ACP, 0, icinfo.szDescription, -1, descr,
Shinya Kitaoka 120a6e
                          sizeof(descr), 0, 0);
Shinya Kitaoka 120a6e
      WideCharToMultiByte(CP_ACP, 0, icinfo.szName, -1, name, sizeof(name), 0,
Shinya Kitaoka 120a6e
                          0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      std::wstring compressorName;
Shinya Kitaoka 120a6e
      compressorName =
Shinya Kitaoka 120a6e
          ::to_wstring(std::string(name) + " '" + std::to_string(bpp) + "' " +
Shinya Kitaoka 120a6e
                       std::string(descr));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (hic) {
Shinya Kitaoka 120a6e
        if (ICCompressQuery(hic, &inFmt, NULL) != ICERR_OK) {
Shinya Kitaoka 120a6e
          ICClose(hic);
Shinya Kitaoka 120a6e
          continue;  // Skip this compressor if it can't handle the format.
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        codecs[compressorName] = canWork(hic, resolution, bpp);
Shinya Kitaoka 120a6e
        ICClose(hic);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return codecs;
Toshihiro Shimizu 890ddd
}