Skip to content

Commit

Permalink
Allows per output xml and cc files
Browse files Browse the repository at this point in the history
Signed-off-by: Maxime Gervais <[email protected]>
  • Loading branch information
g-maxime committed Aug 6, 2024
1 parent 10280e8 commit e7f6147
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 85 deletions.
53 changes: 37 additions & 16 deletions Source/CLI/CommandLine_Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,14 @@ return_value Parse(Core &C, int argc, const char* argv_ansi[], const MediaInfoNa
return_value ReturnValue = ReturnValue_OK;
bool ClearInput = false;
caption_kind CaptionKind = Caption_Unknown;
const char* Xml_OutputFileName = nullptr;
const char* Webvtt_OutputFileName = nullptr;
const char* MergeInfo_OutputFileName = nullptr;
const char* Merge_Rewind_BaseName = nullptr;
bitset<Flag_Max> Flags;
bool OutputFrames_Speed = false;
bool OutputFrames_Speed_StdOut = false;
bool OutputFrames_Concealed = false;
bool OutputFrames_Concealed_StdOut = false;
bool OutputFrames_Speed = true;
bool OutputFrames_Speed_StdOut = true;
bool OutputFrames_Concealed = true;
bool OutputFrames_Concealed_StdOut = true;

// Commands in priority
for (int i = 1; i < argc; i++)
Expand Down Expand Up @@ -318,7 +317,9 @@ return_value Parse(Core &C, int argc, const char* argv_ansi[], const MediaInfoNa
CurrentCaptionKind = CaptionKind;
CaptionKind = Caption_Unknown;
}
C.CaptionsFileNames[CurrentCaptionKind] = move(CurrentFileName);
Core::OutFile CaptionFile;
CaptionFile.Name = move(CurrentFileName);
C.CaptionsFileNames[CurrentCaptionKind].push_back(CaptionFile);
}
else if (!strcmp(argv_ansi[i], "--capture") || !strcmp(argv_ansi[i], "-capture"))
{
Expand Down Expand Up @@ -357,6 +358,15 @@ return_value Parse(Core &C, int argc, const char* argv_ansi[], const MediaInfoNa
OutputFrames_Speeds.push_back(OutputFrames_Speed);
OutputFrames_Concealeds.push_back(OutputFrames_Concealed);
}

if (!C.XmlFiles.empty() && C.XmlFiles.back().Merge_OutputFileName.empty())
C.XmlFiles.back().Merge_OutputFileName = argv_ansi[i];

for (auto& CaptionFileNames : C.CaptionsFileNames)
{
if (CaptionFileNames.second.back().Merge_OutputFileName.empty())
CaptionFileNames.second.back().Merge_OutputFileName = argv_ansi[i];
}
}
else if (!strcmp(argv_ansi[i], "--merge-log"))
{
Expand Down Expand Up @@ -719,7 +729,10 @@ return_value Parse(Core &C, int argc, const char* argv_ansi[], const MediaInfoNa
*C.Err << "Error: missing XML output file name after " << argv_ansi[i-1] << ".\n";
return ReturnValue_ERROR;
}
Xml_OutputFileName = argv_ansi[i];

Core::OutFile XmlFile;
XmlFile.Name = argv_ansi[i];
C.XmlFiles.push_back(XmlFile);
}
else if (!strcmp(argv_ansi[i], "-n"))
{
Expand Down Expand Up @@ -779,7 +792,7 @@ return_value Parse(Core &C, int argc, const char* argv_ansi[], const MediaInfoNa
}
else
{
if (Webvtt_OutputFileName || Xml_OutputFileName || !Merge_OutputFileNames.empty() || Merge_OutputFileNames_IncludesStdOut)
if (Webvtt_OutputFileName || !C.XmlFiles.empty() || !Merge_OutputFileNames.empty() || Merge_OutputFileNames_IncludesStdOut)
{
if (C.Err)
*C.Err << "Error: in order to avoid mistakes, provide output file names after input file names.\n";
Expand Down Expand Up @@ -904,16 +917,13 @@ return_value Parse(Core &C, int argc, const char* argv_ansi[], const MediaInfoNa
Merge_Out.push_back(Temp);
}

for (Core::OutFile& OutputFile : C.XmlFiles)
OutputFiles_OpenError |= OpenTruncateFile(OutputFile.File, OutputFile.Name.c_str(), C, Flags);

if ((OutputFiles_OpenError)
|| (Xml_OutputFileName && OpenTruncateFile(C.XmlFile, Xml_OutputFileName, C, Flags))
|| (Webvtt_OutputFileName && OpenTruncateFile(C.WebvttFile, Webvtt_OutputFileName, C, Flags))
|| (MergeInfo_OutputFileName && OpenTruncateFile(MergeInfo_Out, MergeInfo_OutputFileName, C, Flags)))
{
if (C.XmlFile)
{
delete C.XmlFile;
remove(Xml_OutputFileName);
}
if (C.WebvttFile)
{
delete C.WebvttFile;
Expand All @@ -925,6 +935,14 @@ return_value Parse(Core &C, int argc, const char* argv_ansi[], const MediaInfoNa
remove(MergeInfo_OutputFileName);
}

for (Core::OutFile& OutputFile : C.XmlFiles)
{
if (OutputFile.File && OutputFile.File != C.Out)
delete OutputFile.File;
remove(OutputFile.Name.c_str());
}
C.XmlFiles.clear();

for (FILE* OutputFile : Merge_Out)
fclose(OutputFile);
Merge_Out.clear();
Expand Down Expand Up @@ -986,6 +1004,9 @@ void Clean(Core& C)
// We previously set some output file pointers, deleting them
if (C.WebvttFile != C.Out)
delete C.WebvttFile;
if (C.XmlFile != C.Out)
delete C.XmlFile;
for (Core::OutFile& OutputFile : C.XmlFiles)
{
if (OutputFile.File && OutputFile.File != C.Out)
delete OutputFile.File;
}
}
41 changes: 23 additions & 18 deletions Source/Common/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,23 @@ return_value Core::Process()
if (!Merge_Out.empty())
{
PerFile[0]->Merge_Finish();
if (!XmlFile)
if (XmlFiles.empty())
return ToReturn;
}

// Set output defaults
if (!XmlFile)
XmlFile = Out;
if (XmlFiles.empty())
{
//TODO: select first output, last output or input in that case?
OutFile XmlFile;
XmlFile.File = Out;
XmlFiles.push_back(XmlFile);
}

// XML
if (XmlFile)
for (OutFile& XmlFile : XmlFiles)
{
if (auto ToReturn2 = Output_Xml(*XmlFile, PerFile, Options, Err))
if (auto ToReturn2 = Output_Xml(XmlFile, PerFile, Options, Err))
ToReturn = ToReturn2;
}

Expand All @@ -104,23 +109,23 @@ return_value Core::Process()
}

// Closed Captions
if (!CaptionsFileNames.empty())
for (const auto& Caption : CaptionsFileNames)
{
// SCC
auto SccFileName = CaptionsFileNames.find(Caption_Scc);
if (SccFileName != CaptionsFileNames.end())
if (Caption.first == Caption_Scc)
{
if (auto ToReturn2 = Output_Captions_Scc(SccFileName->second, OffsetTimeCode, PerFile, Err))
ToReturn = ToReturn2;
for (const auto& OutFile : Caption.second)
{
if (auto ToReturn2 = Output_Captions_Scc(OutFile, OffsetTimeCode, PerFile, Err))
ToReturn = ToReturn2;
}
}

// Decode (Screen or SRT)
auto ScreenFileName = CaptionsFileNames.find(Caption_Screen);
auto SrtFileName = CaptionsFileNames.find(Caption_Srt);
if (ScreenFileName != CaptionsFileNames.end() || SrtFileName != CaptionsFileNames.end())
else if (Caption.first == Caption_Screen || Caption.first == Caption_Srt)
{
if (auto ToReturn2 = Output_Captions_Caption(ScreenFileName != CaptionsFileNames.end() ? ScreenFileName->second : string(), SrtFileName != CaptionsFileNames.end() ? SrtFileName->second : string(), OffsetTimeCode, PerFile, Err))
ToReturn = ToReturn2;
for (const auto& OutFile : Caption.second)
{
if (auto ToReturn2 = Output_Captions_Caption(Caption.first == Caption_Screen ? OutFile : Core::OutFile(), Caption.first == Caption_Srt ? OutFile : Core::OutFile(), OffsetTimeCode, PerFile, Err))
ToReturn = ToReturn2;
}
}
}

Expand Down
14 changes: 12 additions & 2 deletions Source/Common/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,26 @@ enum caption_kind
class Core
{
public:
//Object
struct OutFile
{
ostream* File = nullptr;
string Name;

// Reference file, input if empty
string Merge_OutputFileName;
};

// Constructor/Destructor
Core();
~Core();

// Input
vector<String> Inputs;
map<caption_kind, string> CaptionsFileNames; // We don't directly open an ostream because file name may change if cc are not same and/or 2nd field and/or no cc
map<caption_kind, vector<OutFile>> CaptionsFileNames; // We don't directly open an ostream because file name may change if cc are not same and/or 2nd field and/or no cc
TimeCode* OffsetTimeCode = nullptr;
ostream* WebvttFile = nullptr;
ostream* XmlFile = nullptr;
vector<OutFile> XmlFiles;
ostream* Out = nullptr;
ostream* Err = nullptr;
bitset<Option_Max> Options;
Expand Down
46 changes: 41 additions & 5 deletions Source/Common/Output_Captions_Decode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "ccdecoder_line21.h"
#include "ccdecoder_subrip.h"
#include "ccdecoder_onscreen.h"
#include <algorithm>
#include <fstream>
//---------------------------------------------------------------------------

Expand Down Expand Up @@ -172,7 +173,7 @@ struct decoded_data
//***************************************************************************

//---------------------------------------------------------------------------
static return_value Output_Captions_Decode(const string& ScreenOutName, const string& SrtOutName, const vector<file::captions_fielddata>& PerFrame_Captions, int Field, ostream* Err)
static return_value Output_Captions_Decode(const string& ScreenOutName, const string& SrtOutName, const vector<file::captions_fielddata>& PerFrame_Captions, const vector<size_t>& IgnoredFrames, int Field, ostream* Err)
{
auto ToReturn = ReturnValue_OK;

Expand All @@ -185,6 +186,9 @@ static return_value Output_Captions_Decode(const string& ScreenOutName, const st
// By Frame - For each line
for (const auto& Frame : PerFrame_Captions)
{
if (find(IgnoredFrames.begin(), IgnoredFrames.end(), Frame.StartFrameNumber) != IgnoredFrames.end())
continue;

for (size_t i = 0; i < Frame.Captions.size(); i++)
{
const auto& Caption = Frame.Captions[i];
Expand Down Expand Up @@ -279,28 +283,60 @@ static return_value Output_Captions_Decode(const string& ScreenOutName, const st
}

//---------------------------------------------------------------------------
return_value Output_Captions_Caption(const string& ScreenOutName, const string& SrtOutName, const TimeCode* OffsetTimeCode, std::vector<file*>& PerFile, ostream* Err)
return_value Output_Captions_Caption(const Core::OutFile& ScreenOut, const Core::OutFile& SrtOut, const TimeCode* OffsetTimeCode, std::vector<file*>& PerFile, ostream* Err)
{
auto ToReturn = ReturnValue_OK;

bool OutputFrames_Speed = true;
bool OutputFrames_Concealed = true;

auto It = find(Merge_OutputFileNames.begin(), Merge_OutputFileNames.end(), ScreenOut.Merge_OutputFileName.size() ? ScreenOut.Merge_OutputFileName : SrtOut.Merge_OutputFileName);
if (It != Merge_OutputFileNames.end())
{
size_t Pos = It - Merge_OutputFileNames.begin();
OutputFrames_Speed = OutputFrames_Speeds[Pos];
OutputFrames_Concealed = OutputFrames_Concealeds[Pos];
}

for (const auto& File : PerFile)
{
if (File->PerFrame_Captions_PerSeq_PerField.empty())
continue; // Show the file only if there is some captions content

// filter
vector<size_t> IgnoredFrames;
if (!OutputFrames_Speed || !OutputFrames_Concealed)
{
for (auto Frame = File->PerFrame.begin(); Frame < File->PerFrame.end(); ++Frame)
{
coherency_flags Coherency(*Frame);
if (!OutputFrames_Concealed && Coherency.full_conceal())
{
IgnoredFrames.push_back(Frame - File->PerFrame.begin());
continue;
}

if (!OutputFrames_Speed && !GetDvSpeedIsNormalPlayback(GetDvSpeed(**Frame)))
{
IgnoredFrames.push_back(Frame - File->PerFrame.begin());
continue;
}
}
}

// Per Dseq
for (size_t i = 0; i < File->PerFrame_Captions_PerSeq_PerField.size(); i++) // Per Dseq
{
for (int j = 0; j < 2; j++) // Per field
{
string ScreenOutNameWithDseq(ScreenOutName);
string ScreenOutNameWithDseq(ScreenOut.Name);
if (!ScreenOutNameWithDseq.empty() && File->PerFrame_Captions_PerSeq_PerField.size() > 1)
InjectBeforeExtension(ScreenOutNameWithDseq, ".dseq", i);
string SrtOutNameWithDseq(SrtOutName);
string SrtOutNameWithDseq(SrtOut.Name);
if (!SrtOutNameWithDseq.empty() && File->PerFrame_Captions_PerSeq_PerField.size() > 1)
InjectBeforeExtension(SrtOutNameWithDseq, ".dseq", i);

if (!File->PerFrame_Captions_PerSeq_PerField[i].FieldData[j].empty() && !Output_Captions_Decode(ScreenOutNameWithDseq, SrtOutNameWithDseq, File->PerFrame_Captions_PerSeq_PerField[i].FieldData[j], j, Err))
if (!File->PerFrame_Captions_PerSeq_PerField[i].FieldData[j].empty() && !Output_Captions_Decode(ScreenOutNameWithDseq, SrtOutNameWithDseq, File->PerFrame_Captions_PerSeq_PerField[i].FieldData[j], IgnoredFrames, j, Err))
ToReturn = ReturnValue_ERROR;
}
}
Expand Down
3 changes: 2 additions & 1 deletion Source/Common/Output_Captions_Decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
#pragma once
#include <vector>
#include <ostream>
#include "Common/Core.h"
using namespace std;
class file;
//---------------------------------------------------------------------------

return_value Output_Captions_Caption(const string& ScreenOutName, const string& SrtOutName, const TimeCode* OffsetTimeCode, vector<file*>& PerFile, ostream* Err = nullptr);
return_value Output_Captions_Caption(const Core::OutFile& ScreenOut, const Core::OutFile& SrtOut, const TimeCode* OffsetTimeCode, vector<file*>& PerFile, ostream* Err = nullptr);
Loading

0 comments on commit e7f6147

Please sign in to comment.