Skip to content

Commit 1b26786

Browse files
Option for computing the hash of the output file while checking it.
1 parent 5047e91 commit 1b26786

File tree

8 files changed

+90
-2
lines changed

8 files changed

+90
-2
lines changed

Source/CLI/Global.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ int global::SetOutputFileName(const char* FileName)
3434
return 0;
3535
}
3636

37+
//---------------------------------------------------------------------------
38+
int global::SetComputeOutputHash()
39+
{
40+
Actions.set(Action_ComputeOutputHash, true);
41+
return 0;
42+
}
43+
3744
//---------------------------------------------------------------------------
3845
int global::SetBinName(const char* FileName)
3946
{
@@ -304,6 +311,8 @@ int global::SetAll(bool Value)
304311
return ReturnValue;
305312
if (int ReturnValue = SetHash(Value))
306313
return ReturnValue;
314+
if (int ReturnValue = SetComputeOutputHash())
315+
return ReturnValue;
307316
return 0;
308317
}
309318

@@ -726,6 +735,12 @@ int global::ManageCommandLine(const char* argv[], int argc)
726735
if (Value)
727736
return Value;
728737
}
738+
else if (strcmp(argv[i], "--compute-output-hash") == 0)
739+
{
740+
int Value = SetComputeOutputHash();
741+
if (Value)
742+
return Value;
743+
}
729744
else if (strcmp(argv[i], "--quick-check") == 0)
730745
{
731746
int Value = SetQuickCheck();

Source/CLI/Global.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class global
8585
int SetVersion(const char* Value);
8686
int SetOption(const char* argv[], int& i, int argc);
8787
int SetOutputFileName(const char* FileName);
88+
int SetComputeOutputHash();
8889
int SetBinName(const char* FileName);
8990
int SetLicenseKey(const char* Key, bool Add);
9091
int SetSubLicenseId(uint64_t Id);

Source/CLI/Help.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ ReturnValue Help(const char* Name)
109109
" ${Input}.mkv if the input is a folder, or ${Input}.RAWcooked if\n"
110110
" input is a file, such as a DPX.\n"
111111
"\n"
112+
" --compute-output-hash\n"
113+
" Compute the hash of the output file while checking it.\n"
114+
"\n"
112115
" --output-version value\n"
113116
" Set the version of the output..\n"
114117
" The default output value is 1.\n"

Source/CLI/rawcooked.1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ Set the name of the output file or folder to \fIvalue\fR.
6767
.br
6868
The default output value is opposite to the input. Expect \fI${Input}.mkv\fR if the input is a folder, or \fI${Input}.RAWcooked\fR if input is a file, such as a DPX.
6969
.TP
70+
.B --compute-output-hash
71+
Compute the hash of the output file while checking it.
72+
.TP
7073
.B --output-version \fIvalue\fR
7174
Set the version of the output.
7275
.br

Source/Lib/Compressed/Matroska/Matroska.cpp

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
#include <iomanip>
2727
#include <iostream>
2828
#include <thread>
29+
extern "C"
30+
{
31+
#include "md5.h"
32+
}
2933
//---------------------------------------------------------------------------
3034

3135
//---------------------------------------------------------------------------
@@ -71,6 +75,35 @@ static_assert(error::type_Max == sizeof(ErrorTexts) / sizeof(const char**), Inco
7175

7276
using namespace matroska_issue;
7377

78+
//---------------------------------------------------------------------------
79+
// Hash
80+
81+
struct output_hash {
82+
const uint8_t* Buffer;
83+
MD5_CTX MD5;
84+
uint64_t Offset = 0;
85+
bool Disabled = false;
86+
87+
output_hash(const uint8_t* Buffer_)
88+
: Buffer (Buffer_)
89+
{
90+
MD5_Init(&MD5);
91+
}
92+
93+
void Update(size_t Size)
94+
{
95+
MD5_Update(&MD5, Buffer + Offset, Size);
96+
Offset += Size;
97+
}
98+
99+
md5 MD5_Final()
100+
{
101+
md5 MD5_Result;
102+
::MD5_Final(MD5_Result.data(), &MD5);
103+
return MD5_Result;
104+
}
105+
};
106+
74107
//---------------------------------------------------------------------------
75108
// Matroska parser
76109

@@ -307,6 +340,8 @@ void matroska::ParseBuffer()
307340

308341
Buffer_Offset = 0;
309342
Level = 0;
343+
if ((Actions[Action_Decode] || Actions[Action_Check]) && Actions[Action_ComputeOutputHash])
344+
OutputHash = new output_hash(Buffer.Data());
310345

311346
// Progress indicator
312347
Cluster_Timestamp = 0;
@@ -356,8 +391,18 @@ void matroska::ParseBuffer()
356391
}
357392
}
358393

394+
auto NeedRemap = Buffer_Offset - Buffer_Offset_LowerLimit >= 0x100000; // TODO: when multi-threaded frame decoding is implemented, we need to check that all thread don't need anymore memory below this value
395+
396+
// Compute MD5 of the whole file
397+
if (OutputHash && !OutputHash->Disabled)
398+
{
399+
auto Hash_Size = Buffer_Offset - OutputHash->Offset;
400+
if (NeedRemap || Hash_Size >= 0x100000)
401+
OutputHash->Update(Hash_Size);
402+
}
403+
359404
// Check if we can indicate the system that we'll not need anymore memory below this value, without indicating it too much
360-
if (Buffer_Offset > Buffer_Offset_LowerLimit + 1024 * 1024 && Buffer_Offset < Buffer.Size()) // TODO: when multi-threaded frame decoding is implemented, we need to check that all thread don't need anymore memory below this value
405+
if (NeedRemap)
361406
{
362407
FileMap->Remap(Buffer_Offset, Buffer_Offset + 256 * 1024 * 1024);
363408
Buffer = *FileMap;
@@ -378,6 +423,8 @@ void matroska::ParseBuffer()
378423
Level = Cluster_Level;
379424
Buffer_Offset = Cluster_Offset;
380425
Cluster_Level = (size_t)-1;
426+
if (OutputHash)
427+
OutputHash->Disabled = false;
381428

382429
FileMap->Remap(Buffer_Offset, 256 * 1024 * 1024);
383430
Buffer = *FileMap;
@@ -413,6 +460,17 @@ void matroska::ParseBuffer()
413460
ProgressIndicator_Thread->join();
414461
delete ProgressIndicator_Thread;
415462
}
463+
464+
// Show MD5
465+
if (OutputHash && !OutputHash->Disabled)
466+
{
467+
OutputHash->Update(Buffer_Offset - OutputHash->Offset);
468+
auto MD5_Result = OutputHash->MD5_Final();
469+
std::cout << "\nInfo: Output file MD5 is ";
470+
for (size_t i = 0; i < MD5_Result.size(); i++)
471+
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)MD5_Result[i];
472+
std::cout << '.' << std::endl;
473+
}
416474
}
417475

418476
//---------------------------------------------------------------------------
@@ -799,7 +857,7 @@ void matroska::Segment_Attachments_AttachedFile_FileData_RawCookedTrack_LibraryV
799857
RejectIncompatibleVersions();
800858
}
801859

802-
//---------------------------------------------------------------------------
860+
//--------------------------------- ------------------------------------------
803861
void matroska::Segment_Cluster()
804862
{
805863
if (RAWcooked_LibraryName.empty())
@@ -808,6 +866,10 @@ void matroska::Segment_Cluster()
808866
Cluster_Offset = Element_Begin_Offset;
809867
Cluster_Level = Level;
810868
Level--;
869+
if (OutputHash) {
870+
OutputHash->Update(Buffer_Offset - OutputHash->Offset);
871+
OutputHash->Disabled = true;
872+
}
811873
return;
812874
}
813875

Source/Lib/Compressed/Matroska/Matroska.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class ThreadPool;
3737
class hashes;
3838
class track_info;
3939
class frame_writer;
40+
struct output_hash;
4041

4142
class matroska : public input_base
4243
{
@@ -50,6 +51,7 @@ class matroska : public input_base
5051
bool NoOutputCheck = false;
5152
hashes* Hashes_FromRAWcooked = nullptr;
5253
hashes* Hashes_FromAttachments = nullptr;
54+
output_hash* OutputHash = nullptr;
5355

5456
// Theading relating functions
5557
void ProgressIndicator_Show();

Source/Lib/Uncompressed/DPX/DPX.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ void dpx::ParseBuffer()
260260
uint32_t* HeaderCopy32 = (uint32_t*)HeaderCopy;
261261
const uint32_t* Buffer32 = (const uint32_t*)Buffer.Data();
262262
memmove(HeaderCopy + 36, Buffer.Data() + 36, 160 - 36); // Image filename + Creation date/time: yyyy:mm:dd:hh:mm:ssLTZ
263+
memmove(HeaderCopy + 1532, Buffer.Data() + 1532, 24); // Image filename + Creation date/time: yyyy:mm:dd:hh:mm:ssLTZ
263264
HeaderCopy32[1676 / 4] = Buffer32[1676 / 4]; // Count
264265
HeaderCopy32[1712 / 4] = Buffer32[1712 / 4]; // Frame position in sequence
265266
HeaderCopy32[1920 / 4] = Buffer32[1920 / 4]; // SMPTE time code

Source/Lib/Utils/FileIO/Input_Base.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ enum action : uint8_t
4040
Action_Info,
4141
Action_FrameMd5,
4242
Action_FrameMd5An,
43+
Action_ComputeOutputHash,
4344
Action_QuickCheckAfterEncode, // Internal, indicating the 2nd pass
4445
Action_Max
4546
};

0 commit comments

Comments
 (0)