|
justburner |
64e039 |
|
|
justburner |
64e039 |
#include "tsystem.h"
|
|
justburner |
64e039 |
#include "tiio_ff_mov.h"
|
|
justburner |
64e039 |
#include "trasterimage.h"
|
|
justburner |
64e039 |
#include "timageinfo.h"
|
|
justburner |
64e039 |
#include "tsound.h"
|
|
justburner |
64e039 |
#include "toonz/stage.h"
|
|
justburner |
64e039 |
#include <qstringlist></qstringlist>
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//===========================================================
|
|
justburner |
64e039 |
//
|
|
justburner |
64e039 |
// TImageWriterFFMov
|
|
justburner |
64e039 |
//
|
|
justburner |
64e039 |
//===========================================================
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
class TImageWriterFFMov : public TImageWriter {
|
|
justburner |
64e039 |
public:
|
|
justburner |
64e039 |
int m_frameIndex;
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TImageWriterFFMov(const TFilePath &path, int frameIndex,
|
|
justburner |
64e039 |
TLevelWriterFFMov *lwg)
|
|
justburner |
64e039 |
: TImageWriter(path), m_frameIndex(frameIndex), m_lwg(lwg) {
|
|
justburner |
64e039 |
m_lwg->addRef();
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
~TImageWriterFFMov() { m_lwg->release(); }
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
bool is64bitOutputSupported() override { return false; }
|
|
justburner |
64e039 |
void save(const TImageP &img) override { m_lwg->save(img, m_frameIndex); }
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
private:
|
|
justburner |
64e039 |
TLevelWriterFFMov *m_lwg;
|
|
justburner |
64e039 |
};
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//===========================================================
|
|
justburner |
64e039 |
//
|
|
justburner |
64e039 |
// TLevelWriterFFMov;
|
|
justburner |
64e039 |
//
|
|
justburner |
64e039 |
//===========================================================
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TLevelWriterFFMov::TLevelWriterFFMov(const TFilePath &path,
|
|
justburner |
64e039 |
TPropertyGroup *winfo)
|
|
justburner |
64e039 |
: TLevelWriter(path, winfo) {
|
|
justburner |
64e039 |
if (!m_properties) m_properties = new Tiio::FFMovWriterProperties();
|
|
justburner |
64e039 |
if (m_properties->getPropertyCount() == 0) {
|
|
justburner |
64e039 |
m_scale = 100;
|
|
justburner |
64e039 |
m_vidQuality = 100;
|
|
justburner |
64e039 |
} else {
|
|
justburner |
64e039 |
std::string scale = m_properties->getProperty("Scale")->getValueAsString();
|
|
justburner |
64e039 |
m_scale = QString::fromStdString(scale).toInt();
|
|
justburner |
64e039 |
std::string quality =
|
|
justburner |
64e039 |
m_properties->getProperty("Quality")->getValueAsString();
|
|
justburner |
64e039 |
m_vidQuality = QString::fromStdString(quality).toInt();
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
ffmpegWriter = new Ffmpeg();
|
|
justburner |
64e039 |
ffmpegWriter->setPath(m_path);
|
|
justburner |
64e039 |
if (TSystem::doesExistFileOrLevel(m_path)) TSystem::deleteFile(m_path);
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//-----------------------------------------------------------
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TLevelWriterFFMov::~TLevelWriterFFMov() {
|
|
justburner |
64e039 |
QStringList preIArgs;
|
|
justburner |
64e039 |
QStringList postIArgs;
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
int outLx = m_lx;
|
|
justburner |
64e039 |
int outLy = m_ly;
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
// set scaling
|
|
justburner |
64e039 |
if (m_scale != 0) {
|
|
justburner |
64e039 |
outLx = m_lx * m_scale / 100;
|
|
justburner |
64e039 |
outLy = m_ly * m_scale / 100;
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
// ffmpeg doesn't like resolutions that aren't divisible by 2.
|
|
justburner |
64e039 |
if (outLx % 2 != 0) outLx++;
|
|
justburner |
64e039 |
if (outLy % 2 != 0) outLy++;
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
// calculate quality (bitrate)
|
|
justburner |
64e039 |
int pixelCount = m_lx * m_ly;
|
|
justburner |
64e039 |
int bitRate = pixelCount / 150; // crude but gets decent values
|
|
justburner |
64e039 |
double quality = m_vidQuality / 100.0;
|
|
justburner |
64e039 |
double tempRate = (double)bitRate * quality;
|
|
justburner |
64e039 |
int finalBitrate = (int)tempRate;
|
|
justburner |
64e039 |
int crf = 51 - (m_vidQuality * 51 / 100);
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
preIArgs << "-framerate";
|
|
justburner |
64e039 |
preIArgs << QString::number(m_frameRate);
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
postIArgs << "-c:v";
|
|
justburner |
64e039 |
postIArgs << "prores_ks";
|
|
justburner |
64e039 |
postIArgs << "-pix_fmt";
|
|
justburner |
64e039 |
postIArgs << "yuva444p10le";
|
|
justburner |
64e039 |
postIArgs << "-profile:v";
|
|
justburner |
64e039 |
postIArgs << "4";
|
|
justburner |
64e039 |
postIArgs << "-s";
|
|
justburner |
64e039 |
postIArgs << QString::number(outLx) + "x" + QString::number(outLy);
|
|
justburner |
64e039 |
postIArgs << "-b";
|
|
justburner |
64e039 |
postIArgs << QString::number(finalBitrate) + "k";
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
ffmpegWriter->runFfmpeg(preIArgs, postIArgs, false, false, true);
|
|
justburner |
64e039 |
ffmpegWriter->cleanUpFiles();
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//-----------------------------------------------------------
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TImageWriterP TLevelWriterFFMov::getFrameWriter(TFrameId fid) {
|
|
justburner |
64e039 |
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
|
|
justburner |
64e039 |
int index = fid.getNumber();
|
|
justburner |
64e039 |
TImageWriterFFMov *iwg = new TImageWriterFFMov(m_path, index, this);
|
|
justburner |
64e039 |
return TImageWriterP(iwg);
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//-----------------------------------------------------------
|
|
justburner |
64e039 |
void TLevelWriterFFMov::setFrameRate(double fps) {
|
|
justburner |
64e039 |
m_frameRate = fps;
|
|
justburner |
64e039 |
ffmpegWriter->setFrameRate(fps);
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
void TLevelWriterFFMov::saveSoundTrack(TSoundTrack *st) {
|
|
justburner |
64e039 |
ffmpegWriter->saveSoundTrack(st);
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//-----------------------------------------------------------
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
void TLevelWriterFFMov::save(const TImageP &img, int frameIndex) {
|
|
justburner |
64e039 |
TRasterImageP image(img);
|
|
justburner |
64e039 |
m_lx = image->getRaster()->getLx();
|
|
justburner |
64e039 |
m_ly = image->getRaster()->getLy();
|
|
justburner |
64e039 |
ffmpegWriter->createIntermediateImage(img, frameIndex);
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//===========================================================
|
|
justburner |
64e039 |
//
|
|
justburner |
64e039 |
// TImageReaderFFMov
|
|
justburner |
64e039 |
//
|
|
justburner |
64e039 |
//===========================================================
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
class TImageReaderFFMov final : public TImageReader {
|
|
justburner |
64e039 |
public:
|
|
justburner |
64e039 |
int m_frameIndex;
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TImageReaderFFMov(const TFilePath &path, int index, TLevelReaderFFMov *lra,
|
|
justburner |
64e039 |
TImageInfo *info)
|
|
justburner |
64e039 |
: TImageReader(path), m_lra(lra), m_frameIndex(index), m_info(info) {
|
|
justburner |
64e039 |
m_lra->addRef();
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
~TImageReaderFFMov() { m_lra->release(); }
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TImageP load() override { return m_lra->load(m_frameIndex); }
|
|
justburner |
64e039 |
TDimension getSize() const { return m_lra->getSize(); }
|
|
justburner |
64e039 |
TRect getBBox() const { return TRect(); }
|
|
justburner |
64e039 |
const TImageInfo *getImageInfo() const override { return m_info; }
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
private:
|
|
justburner |
64e039 |
TLevelReaderFFMov *m_lra;
|
|
justburner |
64e039 |
TImageInfo *m_info;
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
// not implemented
|
|
justburner |
64e039 |
TImageReaderFFMov(const TImageReaderFFMov &);
|
|
justburner |
64e039 |
TImageReaderFFMov &operator=(const TImageReaderFFMov &src);
|
|
justburner |
64e039 |
};
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//===========================================================
|
|
justburner |
64e039 |
//
|
|
justburner |
64e039 |
// TLevelReaderFFMov
|
|
justburner |
64e039 |
//
|
|
justburner |
64e039 |
//===========================================================
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TLevelReaderFFMov::TLevelReaderFFMov(const TFilePath &path)
|
|
justburner |
64e039 |
: TLevelReader(path) {
|
|
justburner |
64e039 |
ffmpegReader = new Ffmpeg();
|
|
justburner |
64e039 |
ffmpegReader->setPath(m_path);
|
|
justburner |
64e039 |
ffmpegReader->disablePrecompute();
|
|
justburner |
64e039 |
ffmpegFileInfo tempInfo = ffmpegReader->getInfo();
|
|
justburner |
64e039 |
double fps = tempInfo.m_frameRate;
|
|
justburner |
64e039 |
m_frameCount = tempInfo.m_frameCount;
|
|
justburner |
64e039 |
m_size = TDimension(tempInfo.m_lx, tempInfo.m_ly);
|
|
justburner |
64e039 |
m_lx = m_size.lx;
|
|
justburner |
64e039 |
m_ly = m_size.ly;
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
// set values
|
|
justburner |
64e039 |
m_info = new TImageInfo();
|
|
justburner |
64e039 |
m_info->m_frameRate = fps;
|
|
justburner |
64e039 |
m_info->m_lx = m_lx;
|
|
justburner |
64e039 |
m_info->m_ly = m_ly;
|
|
justburner |
64e039 |
m_info->m_bitsPerSample = 8;
|
|
justburner |
64e039 |
m_info->m_samplePerPixel = 4;
|
|
justburner |
64e039 |
m_info->m_dpix = Stage::standardDpi;
|
|
justburner |
64e039 |
m_info->m_dpiy = Stage::standardDpi;
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
//-----------------------------------------------------------
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TLevelReaderFFMov::~TLevelReaderFFMov() {}
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//-----------------------------------------------------------
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TLevelP TLevelReaderFFMov::loadInfo() {
|
|
justburner |
64e039 |
if (m_frameCount == -1) return TLevelP();
|
|
justburner |
64e039 |
TLevelP level;
|
|
justburner |
64e039 |
for (int i = 1; i <= m_frameCount; i++) level->setFrame(i, TImageP());
|
|
justburner |
64e039 |
return level;
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//-----------------------------------------------------------
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TImageReaderP TLevelReaderFFMov::getFrameReader(TFrameId fid) {
|
|
justburner |
64e039 |
if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
|
|
justburner |
64e039 |
int index = fid.getNumber();
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TImageReaderFFMov *irm = new TImageReaderFFMov(m_path, index, this, m_info);
|
|
justburner |
64e039 |
return TImageReaderP(irm);
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//------------------------------------------------------------------------------
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TDimension TLevelReaderFFMov::getSize() { return m_size; }
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
//------------------------------------------------
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
TImageP TLevelReaderFFMov::load(int frameIndex) {
|
|
justburner |
64e039 |
if (!ffmpegFramesCreated) {
|
|
justburner |
64e039 |
ffmpegReader->getFramesFromMovie();
|
|
justburner |
64e039 |
ffmpegFramesCreated = true;
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
return ffmpegReader->getImage(frameIndex);
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
Tiio::FFMovWriterProperties::FFMovWriterProperties()
|
|
justburner |
64e039 |
: m_vidQuality("Quality", 1, 100, 90), m_scale("Scale", 1, 100, 100) {
|
|
justburner |
64e039 |
bind(m_vidQuality);
|
|
justburner |
64e039 |
bind(m_scale);
|
|
justburner |
64e039 |
}
|
|
justburner |
64e039 |
|
|
justburner |
64e039 |
void Tiio::FFMovWriterProperties::updateTranslation() {
|
|
justburner |
64e039 |
m_vidQuality.setQStringName(tr("Quality"));
|
|
justburner |
64e039 |
m_scale.setQStringName(tr("Scale"));
|
|
justburner |
64e039 |
}
|