change: change code style to Linux style except indent.
This commit is contained in:
+208
-198
@@ -22,266 +22,276 @@
|
||||
|
||||
#include "node/color/colormanager/colormanager.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
ExportTask::ExportTask(ViewerOutput *viewer_node,
|
||||
ColorManager* color_manager,
|
||||
const EncodingParams& params) :
|
||||
params_(params)
|
||||
namespace olive
|
||||
{
|
||||
// Create a copy of the project
|
||||
copier_ = new ProjectCopier(this);
|
||||
copier_->SetProject(viewer_node->project());
|
||||
|
||||
set_viewer(copier_->GetCopy(viewer_node));
|
||||
color_manager_ = copier_->GetCopiedProject()->color_manager();
|
||||
ExportTask::ExportTask(ViewerOutput *viewer_node, ColorManager *color_manager,
|
||||
const EncodingParams ¶ms)
|
||||
: params_(params)
|
||||
{
|
||||
// Create a copy of the project
|
||||
copier_ = new ProjectCopier(this);
|
||||
copier_->SetProject(viewer_node->project());
|
||||
|
||||
// Adjust video params to have no divider
|
||||
VideoParams vp = viewer_node->GetVideoParams();
|
||||
vp.set_divider(1);
|
||||
vp.set_time_base(params.video_params().time_base());
|
||||
vp.set_frame_rate(params.video_params().frame_rate());
|
||||
set_video_params(vp);
|
||||
set_viewer(copier_->GetCopy(viewer_node));
|
||||
color_manager_ = copier_->GetCopiedProject()->color_manager();
|
||||
|
||||
set_audio_params(viewer_node->GetAudioParams());
|
||||
// Adjust video params to have no divider
|
||||
VideoParams vp = viewer_node->GetVideoParams();
|
||||
vp.set_divider(1);
|
||||
vp.set_time_base(params.video_params().time_base());
|
||||
vp.set_frame_rate(params.video_params().frame_rate());
|
||||
set_video_params(vp);
|
||||
|
||||
SetTitle(tr("Exporting \"%1\"").arg(viewer_node->GetLabel()));
|
||||
SetNativeProgressSignallingEnabled(false);
|
||||
set_audio_params(viewer_node->GetAudioParams());
|
||||
|
||||
SetTitle(tr("Exporting \"%1\"").arg(viewer_node->GetLabel()));
|
||||
SetNativeProgressSignallingEnabled(false);
|
||||
}
|
||||
|
||||
bool ExportTask::Run()
|
||||
{
|
||||
// For safety, if we're overwriting, we save to a temporary filename and then only overwrite it
|
||||
// at the end
|
||||
QString real_filename = params_.filename();
|
||||
if (QFileInfo::exists(params_.filename())) {
|
||||
// Generate a filename that definitely doesn't exist
|
||||
params_.SetFilename(FileFunctions::GetSafeTemporaryFilename(real_filename));
|
||||
}
|
||||
// For safety, if we're overwriting, we save to a temporary filename and then only overwrite it
|
||||
// at the end
|
||||
QString real_filename = params_.filename();
|
||||
if (QFileInfo::exists(params_.filename())) {
|
||||
// Generate a filename that definitely doesn't exist
|
||||
params_.SetFilename(
|
||||
FileFunctions::GetSafeTemporaryFilename(real_filename));
|
||||
}
|
||||
|
||||
// If we're exporting to a sidecar subtitle file, disable the subtitles in the main encoder
|
||||
bool subtitles_enabled = params_.subtitles_enabled();
|
||||
EncodingParams sidecar_params = params_;
|
||||
if (subtitles_enabled && params_.subtitles_are_sidecar()) {
|
||||
params_.DisableSubtitles();
|
||||
}
|
||||
// If we're exporting to a sidecar subtitle file, disable the subtitles in the main encoder
|
||||
bool subtitles_enabled = params_.subtitles_enabled();
|
||||
EncodingParams sidecar_params = params_;
|
||||
if (subtitles_enabled && params_.subtitles_are_sidecar()) {
|
||||
params_.DisableSubtitles();
|
||||
}
|
||||
|
||||
encoder_ = std::shared_ptr<Encoder>(Encoder::CreateFromParams(params_));
|
||||
encoder_ = std::shared_ptr<Encoder>(Encoder::CreateFromParams(params_));
|
||||
|
||||
if (!encoder_) {
|
||||
SetError(tr("Failed to create encoder"));
|
||||
return false;
|
||||
}
|
||||
if (!encoder_) {
|
||||
SetError(tr("Failed to create encoder"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!encoder_->Open()) {
|
||||
SetError(tr("Failed to open file: %1").arg(encoder_->GetError()));
|
||||
return false;
|
||||
}
|
||||
if (!encoder_->Open()) {
|
||||
SetError(tr("Failed to open file: %1").arg(encoder_->GetError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (subtitles_enabled && params_.subtitles_are_sidecar()) {
|
||||
// Construct sidecar params
|
||||
sidecar_params.DisableVideo();
|
||||
sidecar_params.DisableAudio();
|
||||
if (subtitles_enabled && params_.subtitles_are_sidecar()) {
|
||||
// Construct sidecar params
|
||||
sidecar_params.DisableVideo();
|
||||
sidecar_params.DisableAudio();
|
||||
|
||||
QString sidecar_filename;
|
||||
{
|
||||
QFileInfo fi(real_filename);
|
||||
sidecar_filename = fi.completeBaseName();
|
||||
sidecar_filename.append('.');
|
||||
sidecar_filename.append(ExportFormat::GetExtension(sidecar_params.subtitle_sidecar_fmt()));
|
||||
sidecar_filename = fi.dir().filePath(sidecar_filename);
|
||||
}
|
||||
sidecar_params.SetFilename(sidecar_filename);
|
||||
QString sidecar_filename;
|
||||
{
|
||||
QFileInfo fi(real_filename);
|
||||
sidecar_filename = fi.completeBaseName();
|
||||
sidecar_filename.append('.');
|
||||
sidecar_filename.append(ExportFormat::GetExtension(
|
||||
sidecar_params.subtitle_sidecar_fmt()));
|
||||
sidecar_filename = fi.dir().filePath(sidecar_filename);
|
||||
}
|
||||
sidecar_params.SetFilename(sidecar_filename);
|
||||
|
||||
subtitle_encoder_ = std::shared_ptr<Encoder>(Encoder::CreateFromFormat(sidecar_params.subtitle_sidecar_fmt(), sidecar_params));
|
||||
if (!subtitle_encoder_) {
|
||||
SetError(tr("Failed to create subtitle encoder"));
|
||||
return false;
|
||||
}
|
||||
subtitle_encoder_ = std::shared_ptr<Encoder>(Encoder::CreateFromFormat(
|
||||
sidecar_params.subtitle_sidecar_fmt(), sidecar_params));
|
||||
if (!subtitle_encoder_) {
|
||||
SetError(tr("Failed to create subtitle encoder"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!subtitle_encoder_->Open()) {
|
||||
SetError(tr("Failed to open subtitle sidecar file: %1").arg(sidecar_filename));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
subtitle_encoder_ = encoder_;
|
||||
}
|
||||
if (!subtitle_encoder_->Open()) {
|
||||
SetError(tr("Failed to open subtitle sidecar file: %1")
|
||||
.arg(sidecar_filename));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
subtitle_encoder_ = encoder_;
|
||||
}
|
||||
|
||||
if (params_.has_custom_range()) {
|
||||
// Render custom range only
|
||||
export_range_ = params_.custom_range();
|
||||
} else {
|
||||
// Render entire sequence
|
||||
export_range_ = TimeRange(0, viewer()->GetLength());
|
||||
}
|
||||
if (params_.has_custom_range()) {
|
||||
// Render custom range only
|
||||
export_range_ = params_.custom_range();
|
||||
} else {
|
||||
// Render entire sequence
|
||||
export_range_ = TimeRange(0, viewer()->GetLength());
|
||||
}
|
||||
|
||||
frame_time_ = 0;
|
||||
frame_time_ = 0;
|
||||
|
||||
QSize video_force_size;
|
||||
QMatrix4x4 video_force_matrix;
|
||||
QSize video_force_size;
|
||||
QMatrix4x4 video_force_matrix;
|
||||
|
||||
if (params_.video_enabled()) {
|
||||
if (params_.video_enabled()) {
|
||||
// If a transformation matrix is applied to this video, create it here
|
||||
if (video_params().width() != params_.video_params().width() ||
|
||||
video_params().height() != params_.video_params().height()) {
|
||||
video_force_size = QSize(params_.video_params().width(),
|
||||
params_.video_params().height());
|
||||
|
||||
// If a transformation matrix is applied to this video, create it here
|
||||
if (video_params().width() != params_.video_params().width()
|
||||
|| video_params().height() != params_.video_params().height()) {
|
||||
video_force_size = QSize(params_.video_params().width(), params_.video_params().height());
|
||||
if (params_.video_scaling_method() != EncodingParams::kStretch) {
|
||||
video_force_matrix = EncodingParams::GenerateMatrix(
|
||||
params_.video_scaling_method(), video_params().width(),
|
||||
video_params().height(), params_.video_params().width(),
|
||||
params_.video_params().height());
|
||||
}
|
||||
} else {
|
||||
// Disables forcing size in the renderer
|
||||
video_force_size = QSize(0, 0);
|
||||
}
|
||||
|
||||
if (params_.video_scaling_method() != EncodingParams::kStretch) {
|
||||
video_force_matrix = EncodingParams::GenerateMatrix(params_.video_scaling_method(),
|
||||
video_params().width(),
|
||||
video_params().height(),
|
||||
params_.video_params().width(),
|
||||
params_.video_params().height());
|
||||
}
|
||||
} else {
|
||||
// Disables forcing size in the renderer
|
||||
video_force_size = QSize(0, 0);
|
||||
}
|
||||
// Create color processor
|
||||
color_processor_ = ColorProcessor::Create(
|
||||
color_manager_, color_manager_->GetReferenceColorSpace(),
|
||||
params_.color_transform());
|
||||
}
|
||||
|
||||
// Create color processor
|
||||
color_processor_ = ColorProcessor::Create(color_manager_,
|
||||
color_manager_->GetReferenceColorSpace(),
|
||||
params_.color_transform());
|
||||
}
|
||||
// Start render process
|
||||
TimeRangeList video_range, audio_range;
|
||||
TimeRange subtitle_range;
|
||||
|
||||
// Start render process
|
||||
TimeRangeList video_range, audio_range;
|
||||
TimeRange subtitle_range;
|
||||
if (params_.video_enabled()) {
|
||||
if (export_range_.in() > 0) {
|
||||
export_range_.set_in(Timecode::snap_time_to_timebase(
|
||||
export_range_.in(), video_params().frame_rate_as_time_base()));
|
||||
}
|
||||
|
||||
if (params_.video_enabled()) {
|
||||
if (export_range_.in() > 0) {
|
||||
export_range_.set_in(Timecode::snap_time_to_timebase(export_range_.in(), video_params().frame_rate_as_time_base()));
|
||||
}
|
||||
video_range = { export_range_ };
|
||||
}
|
||||
|
||||
video_range = {export_range_};
|
||||
}
|
||||
if (params_.audio_enabled()) {
|
||||
audio_range = { export_range_ };
|
||||
}
|
||||
|
||||
if (params_.audio_enabled()) {
|
||||
audio_range = {export_range_};
|
||||
}
|
||||
if (subtitles_enabled) {
|
||||
subtitle_range = export_range_;
|
||||
}
|
||||
|
||||
if (subtitles_enabled) {
|
||||
subtitle_range = export_range_;
|
||||
}
|
||||
Render(color_manager_, video_range, audio_range, subtitle_range,
|
||||
RenderMode::kOnline, nullptr, video_force_size, video_force_matrix,
|
||||
encoder_->GetDesiredPixelFormat(), VideoParams::kRGBAChannelCount,
|
||||
color_processor_);
|
||||
|
||||
Render(color_manager_, video_range, audio_range, subtitle_range, RenderMode::kOnline, nullptr,
|
||||
video_force_size, video_force_matrix, encoder_->GetDesiredPixelFormat(),
|
||||
VideoParams::kRGBAChannelCount, color_processor_);
|
||||
bool success = true;
|
||||
|
||||
bool success = true;
|
||||
encoder_->Close();
|
||||
if (!encoder_->GetError().isEmpty()) {
|
||||
SetError(encoder_->GetError());
|
||||
success = false;
|
||||
}
|
||||
|
||||
encoder_->Close();
|
||||
if (!encoder_->GetError().isEmpty()) {
|
||||
SetError(encoder_->GetError());
|
||||
success = false;
|
||||
}
|
||||
if (subtitle_encoder_ != encoder_) {
|
||||
subtitle_encoder_->Close();
|
||||
if (!subtitle_encoder_->GetError().isEmpty()) {
|
||||
SetError(subtitle_encoder_->GetError());
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (subtitle_encoder_ != encoder_) {
|
||||
subtitle_encoder_->Close();
|
||||
if (!subtitle_encoder_->GetError().isEmpty()) {
|
||||
SetError(subtitle_encoder_->GetError());
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
// If cancelled, delete the file we made, which is always a file we created since we write to a
|
||||
// temp file during the actual encoding process
|
||||
if (IsCancelled()) {
|
||||
QFile::remove(params_.filename());
|
||||
} else if (params_.filename() != real_filename) {
|
||||
// If we were writing to a temp file, overwrite now
|
||||
if (!FileFunctions::RenameFileAllowOverwrite(params_.filename(),
|
||||
real_filename)) {
|
||||
SetError(
|
||||
tr("Failed to overwrite \"%1\". Export has been saved as \"%2\" instead.")
|
||||
.arg(real_filename, params_.filename()));
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If cancelled, delete the file we made, which is always a file we created since we write to a
|
||||
// temp file during the actual encoding process
|
||||
if (IsCancelled()) {
|
||||
QFile::remove(params_.filename());
|
||||
} else if (params_.filename() != real_filename) {
|
||||
// If we were writing to a temp file, overwrite now
|
||||
if (!FileFunctions::RenameFileAllowOverwrite(params_.filename(), real_filename)) {
|
||||
SetError(tr("Failed to overwrite \"%1\". Export has been saved as \"%2\" instead.")
|
||||
.arg(real_filename, params_.filename()));
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ExportTask::FrameDownloaded(FramePtr f, const rational &time)
|
||||
{
|
||||
rational actual_time = time - export_range_.in();
|
||||
rational actual_time = time - export_range_.in();
|
||||
|
||||
time_map_.insert(actual_time, f);
|
||||
time_map_.insert(actual_time, f);
|
||||
|
||||
while (!IsCancelled()) {
|
||||
rational real_time = Timecode::timestamp_to_time(frame_time_,
|
||||
video_params().frame_rate_as_time_base());
|
||||
while (!IsCancelled()) {
|
||||
rational real_time = Timecode::timestamp_to_time(
|
||||
frame_time_, video_params().frame_rate_as_time_base());
|
||||
|
||||
if (!time_map_.contains(real_time)) {
|
||||
break;
|
||||
}
|
||||
if (!time_map_.contains(real_time)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Unfortunately this can't be done in another thread since the frames need to be sent
|
||||
// one after the other chronologically.
|
||||
if (!encoder_->WriteFrame(time_map_.take(real_time), real_time)) {
|
||||
SetError(encoder_->GetError());
|
||||
return false;
|
||||
}
|
||||
// Unfortunately this can't be done in another thread since the frames need to be sent
|
||||
// one after the other chronologically.
|
||||
if (!encoder_->WriteFrame(time_map_.take(real_time), real_time)) {
|
||||
SetError(encoder_->GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
frame_time_++;
|
||||
emit ProgressChanged(double(frame_time_) / double(GetTotalNumberOfFrames()));
|
||||
}
|
||||
frame_time_++;
|
||||
emit ProgressChanged(double(frame_time_) /
|
||||
double(GetTotalNumberOfFrames()));
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExportTask::AudioDownloaded(const TimeRange &range, const SampleBuffer &samples)
|
||||
bool ExportTask::AudioDownloaded(const TimeRange &range,
|
||||
const SampleBuffer &samples)
|
||||
{
|
||||
TimeRange adjusted_range = range - export_range_.in();
|
||||
TimeRange adjusted_range = range - export_range_.in();
|
||||
|
||||
if (adjusted_range.in() == audio_time_) {
|
||||
if (!WriteAudioLoop(adjusted_range, samples)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
audio_map_.insert(adjusted_range, samples);
|
||||
}
|
||||
if (adjusted_range.in() == audio_time_) {
|
||||
if (!WriteAudioLoop(adjusted_range, samples)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
audio_map_.insert(adjusted_range, samples);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExportTask::EncodeSubtitle(const SubtitleBlock *sub)
|
||||
{
|
||||
if (!subtitle_encoder_->WriteSubtitle(sub)) {
|
||||
SetError(subtitle_encoder_->GetError());
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
if (!subtitle_encoder_->WriteSubtitle(sub)) {
|
||||
SetError(subtitle_encoder_->GetError());
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ExportTask::WriteAudioLoop(const TimeRange& time, const SampleBuffer &samples)
|
||||
bool ExportTask::WriteAudioLoop(const TimeRange &time,
|
||||
const SampleBuffer &samples)
|
||||
{
|
||||
if (!encoder_->WriteAudio(samples)) {
|
||||
SetError(encoder_->GetError());
|
||||
return false;
|
||||
}
|
||||
if (!encoder_->WriteAudio(samples)) {
|
||||
SetError(encoder_->GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
audio_time_ = time.out();
|
||||
audio_time_ = time.out();
|
||||
|
||||
for (auto it=audio_map_.begin(); it!=audio_map_.end(); it++) {
|
||||
TimeRange t = it.key();
|
||||
SampleBuffer s = it.value();
|
||||
for (auto it = audio_map_.begin(); it != audio_map_.end(); it++) {
|
||||
TimeRange t = it.key();
|
||||
SampleBuffer s = it.value();
|
||||
|
||||
if (t.in() == audio_time_) {
|
||||
// Erase from audio map since we're just about to write it
|
||||
audio_map_.erase(it);
|
||||
if (t.in() == audio_time_) {
|
||||
// Erase from audio map since we're just about to write it
|
||||
audio_map_.erase(it);
|
||||
|
||||
// Call recursively to write the next sample buffer
|
||||
if (!WriteAudioLoop(t, s)) {
|
||||
return false;
|
||||
}
|
||||
// Call recursively to write the next sample buffer
|
||||
if (!WriteAudioLoop(t, s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Break out of loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Break out of loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user