summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2016-01-14 22:05:56 +0000
committerCarl Hetherington <cth@carlh.net>2020-12-27 02:30:45 +0100
commita86a6cf14b3966348f4ea08571aacbba4e54013c (patch)
tree8af89cc155d13b6633993dca1b519ccc9883a12c /src
parent0decd2a4633592c4349a1fdbc5417a06835909e1 (diff)
Support hashing while writing MXFs.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/AS_DCP.h5
-rwxr-xr-xsrc/AS_DCP_JP2K.cpp24
-rwxr-xr-xsrc/AS_DCP_internal.h4
-rw-r--r--src/KM_fileio.cpp49
-rwxr-xr-xsrc/KM_fileio.h7
-rwxr-xr-xsrc/h__Writer.cpp18
6 files changed, 86 insertions, 21 deletions
diff --git a/src/AS_DCP.h b/src/AS_DCP.h
index 6abe237..5ba8f56 100755
--- a/src/AS_DCP.h
+++ b/src/AS_DCP.h
@@ -1260,9 +1260,10 @@ namespace ASDCP {
// Writes a frame of essence to the MXF file. If the optional AESEncContext
// argument is present, the essence is encrypted prior to writing.
+ // A MD5 hash of the data that we write is written to hash if it is not 0
// Fails if the file is not open, is finalized, or an operating system
// error occurs.
- Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+ Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0, std::string* hash = 0);
Result_t FakeWriteFrame(int size);
@@ -1381,7 +1382,7 @@ namespace ASDCP {
// RESULT_SPHASE will be returned if phase is reversed. The first frame
// written must be left eye.
Result_t WriteFrame(const FrameBuffer&, StereoscopicPhase_t phase,
- AESEncContext* = 0, HMACContext* = 0);
+ AESEncContext* = 0, HMACContext* = 0, std::string* hash = 0);
Result_t FakeWriteFrame(int size, StereoscopicPhase_t phase);
diff --git a/src/AS_DCP_JP2K.cpp b/src/AS_DCP_JP2K.cpp
index 898f138..652facc 100755
--- a/src/AS_DCP_JP2K.cpp
+++ b/src/AS_DCP_JP2K.cpp
@@ -1149,7 +1149,7 @@ public:
Result_t OpenWrite(const std::string&, EssenceType_t type, ui32_t HeaderSize, bool);
Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
- Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*);
+ Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*, std::string* hash = 0);
Result_t FakeWriteFrame(int size, bool add_index);
Result_t Finalize();
};
@@ -1255,7 +1255,7 @@ lh__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& l
//
ASDCP::Result_t
lh__Writer::WriteFrame(const JP2K::FrameBuffer& FrameBuf, bool add_index,
- AESEncContext* Ctx, HMACContext* HMAC)
+ AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
{
Result_t result = RESULT_OK;
@@ -1265,7 +1265,7 @@ lh__Writer::WriteFrame(const JP2K::FrameBuffer& FrameBuf, bool add_index,
ui64_t StreamOffset = m_StreamOffset;
if ( ASDCP_SUCCESS(result) )
- result = WriteEKLVPacket(FrameBuf, m_EssenceUL, MXF_BER_LENGTH, Ctx, HMAC);
+ result = WriteEKLVPacket(FrameBuf, m_EssenceUL, MXF_BER_LENGTH, Ctx, HMAC, hash);
if ( ASDCP_SUCCESS(result) && add_index )
{
@@ -1414,12 +1414,12 @@ ASDCP::JP2K::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo&
// Fails if the file is not open, is finalized, or an operating system
// error occurs.
ASDCP::Result_t
-ASDCP::JP2K::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
+ASDCP::JP2K::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
{
if ( m_Writer.empty() )
return RESULT_INIT;
- return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC);
+ return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC, hash);
}
ASDCP::Result_t
@@ -1462,7 +1462,7 @@ public:
//
Result_t WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
- AESEncContext* Ctx, HMACContext* HMAC)
+ AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
{
if ( m_NextPhase != phase )
return RESULT_SPHASE;
@@ -1470,11 +1470,11 @@ public:
if ( phase == SP_LEFT )
{
m_NextPhase = SP_RIGHT;
- return lh__Writer::WriteFrame(FrameBuf, true, Ctx, HMAC);
+ return lh__Writer::WriteFrame(FrameBuf, true, Ctx, HMAC, hash);
}
m_NextPhase = SP_LEFT;
- return lh__Writer::WriteFrame(FrameBuf, false, Ctx, HMAC);
+ return lh__Writer::WriteFrame(FrameBuf, false, Ctx, HMAC, hash);
}
Result_t FakeWriteFrame(int size, StereoscopicPhase_t phase)
@@ -1634,10 +1634,10 @@ ASDCP::JP2K::MXFSWriter::WriteFrame(const SFrameBuffer& FrameBuf, AESEncContext*
if ( m_Writer.empty() )
return RESULT_INIT;
- Result_t result = m_Writer->WriteFrame(FrameBuf.Left, SP_LEFT, Ctx, HMAC);
+ Result_t result = m_Writer->WriteFrame(FrameBuf.Left, SP_LEFT, Ctx, HMAC, 0);
if ( ASDCP_SUCCESS(result) )
- result = m_Writer->WriteFrame(FrameBuf.Right, SP_RIGHT, Ctx, HMAC);
+ result = m_Writer->WriteFrame(FrameBuf.Right, SP_RIGHT, Ctx, HMAC, 0);
return result;
}
@@ -1648,12 +1648,12 @@ ASDCP::JP2K::MXFSWriter::WriteFrame(const SFrameBuffer& FrameBuf, AESEncContext*
// error occurs.
ASDCP::Result_t
ASDCP::JP2K::MXFSWriter::WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
- AESEncContext* Ctx, HMACContext* HMAC)
+ AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
{
if ( m_Writer.empty() )
return RESULT_INIT;
- return m_Writer->WriteFrame(FrameBuf, phase, Ctx, HMAC);
+ return m_Writer->WriteFrame(FrameBuf, phase, Ctx, HMAC, hash);
}
ASDCP::Result_t
diff --git a/src/AS_DCP_internal.h b/src/AS_DCP_internal.h
index 55ea58c..43f032f 100755
--- a/src/AS_DCP_internal.h
+++ b/src/AS_DCP_internal.h
@@ -183,7 +183,7 @@ namespace ASDCP
const ASDCP::WriterInfo& Info, ASDCP::FrameBuffer& CtFrameBuf, ui32_t& FramesWritten,
ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
const ui32_t& MinEssenceElementBerLength,
- AESEncContext* Ctx, HMACContext* HMAC);
+ AESEncContext* Ctx, HMACContext* HMAC, std::string* hash = 0);
//
class KLReader : public ASDCP::KLVPacket
@@ -915,7 +915,7 @@ namespace ASDCP
Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
const ui32_t& MinEssenceElementBerLength,
- AESEncContext* Ctx, HMACContext* HMAC);
+ AESEncContext* Ctx, HMACContext* HMAC, std::string* hash = 0);
Result_t FakeWriteEKLVPacket(int size);
Result_t WriteASDCPFooter();
};
diff --git a/src/KM_fileio.cpp b/src/KM_fileio.cpp
index a5e2a8d..871c597 100644
--- a/src/KM_fileio.cpp
+++ b/src/KM_fileio.cpp
@@ -32,6 +32,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <KM_fileio.h>
#include <KM_log.h>
#include <fcntl.h>
+#include <iomanip>
#include <assert.h>
@@ -735,7 +736,9 @@ Kumu::FileReader::Size() const
// these are declared here instead of in the header file
// because we have a mem_ptr that is managing a hidden class
-Kumu::FileWriter::FileWriter() {}
+Kumu::FileWriter::FileWriter()
+ : m_Hashing(false)
+{}
Kumu::FileWriter::~FileWriter() {}
//
@@ -760,6 +763,41 @@ Kumu::FileWriter::Writev(const byte_t* buf, ui32_t buf_len)
return RESULT_OK;
}
+void
+Kumu::FileWriter::StartHashing()
+{
+ m_Hashing = true;
+ MD5_Init (&m_MD5Context);
+}
+
+void
+Kumu::FileWriter::MaybeHash(void const * data, int size)
+{
+ if (m_Hashing)
+ {
+ MD5_Update (&m_MD5Context, data, size);
+ }
+}
+
+std::string
+Kumu::FileWriter::StopHashing()
+{
+ m_Hashing = false;
+
+ unsigned char digest[MD5_DIGEST_LENGTH];
+ MD5_Final (digest, &m_MD5Context);
+
+ char hex[MD5_DIGEST_LENGTH * 2 + 1];
+ for (int i = 0; i < MD5_DIGEST_LENGTH; ++i)
+ {
+ sprintf(hex + i * 2, "%02x", digest[i]);
+ }
+
+ return hex;
+}
+
+
+
#ifdef KM_WIN32
#ifdef KM_WIN32_UTF8
@@ -1063,6 +1101,7 @@ Kumu::FileWriter::Writev(ui32_t* bytes_written)
break;
}
+ MaybeHash(iov->m_iovec[i].iov_base, iov->m_iovec[i].iov_len);
*bytes_written += tmp_count;
}
@@ -1093,6 +1132,8 @@ Kumu::FileWriter::Write(const byte_t* buf, ui32_t buf_len, ui32_t* bytes_written
if ( result == 0 || *bytes_written != buf_len )
return Kumu::RESULT_WRITEFAIL;
+ MaybeHash(buf, buf_len);
+
return Kumu::RESULT_OK;
}
@@ -1236,6 +1277,11 @@ Kumu::FileWriter::Writev(ui32_t* bytes_written)
if ( write_size == -1L || write_size != total_size )
return RESULT_WRITEFAIL;
+ for (int i = 0; i < iov->m_Count; ++i)
+ {
+ MaybeHash(iov->m_iovec[i].iov_base, iov->m_iovec[i].iov_len);
+ }
+
iov->m_Count = 0;
*bytes_written = write_size;
return RESULT_OK;
@@ -1255,6 +1301,7 @@ Kumu::FileWriter::Write(const byte_t* buf, ui32_t buf_len, ui32_t* bytes_written
return RESULT_STATE;
int write_size = write(m_Handle, buf, buf_len);
+ MaybeHash(buf, buf_len);
if ( write_size == -1L || (ui32_t)write_size != buf_len )
return RESULT_WRITEFAIL;
diff --git a/src/KM_fileio.h b/src/KM_fileio.h
index 60e1e6a..7537414 100755
--- a/src/KM_fileio.h
+++ b/src/KM_fileio.h
@@ -34,6 +34,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <KM_util.h>
#include <string>
+#include <openssl/md5.h>
#ifdef KM_WIN32
# include <io.h>
@@ -352,6 +353,8 @@ namespace Kumu
class h__iovec;
mem_ptr<h__iovec> m_IOVec;
KM_NO_COPY_CONSTRUCT(FileWriter);
+ bool m_Hashing;
+ MD5_CTX m_MD5Context;
public:
FileWriter();
@@ -371,6 +374,10 @@ namespace Kumu
// the iovec list will be written to disk before the given buffer,as though
// you had called Writev() first.
Result_t Write(const byte_t*, ui32_t, ui32_t* = 0); // write buffer to disk
+
+ void StartHashing();
+ void MaybeHash(void const *, int);
+ std::string StopHashing();
};
Result_t CreateDirectoriesInPath(const std::string& Path);
diff --git a/src/h__Writer.cpp b/src/h__Writer.cpp
index cc1dff2..870f5b6 100755
--- a/src/h__Writer.cpp
+++ b/src/h__Writer.cpp
@@ -302,12 +302,12 @@ ASDCP::h__ASDCPWriter::WriteASDCPHeader(const std::string& PackageLabel, const U
//
Result_t
ASDCP::h__ASDCPWriter::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
- const ui32_t& MinEssenceElementBerLength,
- AESEncContext* Ctx, HMACContext* HMAC)
+ const ui32_t& MinEssenceElementBerLength,
+ AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
{
return Write_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_CtFrameBuf, m_FramesWritten,
m_StreamOffset, FrameBuf, EssenceUL, MinEssenceElementBerLength,
- Ctx, HMAC);
+ Ctx, HMAC, hash);
}
Result_t
@@ -376,11 +376,16 @@ ASDCP::Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict,
const ASDCP::WriterInfo& Info, ASDCP::FrameBuffer& CtFrameBuf, ui32_t& FramesWritten,
ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
const ui32_t& MinEssenceElementBerLength,
- AESEncContext* Ctx, HMACContext* HMAC)
+ AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
{
Result_t result = RESULT_OK;
IntegrityPack IntPack;
+ if (hash)
+ {
+ File.StartHashing();
+ }
+
byte_t overhead[128];
Kumu::MemIOWriter Overhead(overhead, 128);
@@ -511,6 +516,11 @@ ASDCP::Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict,
if ( ASDCP_SUCCESS(result) )
result = File.Writev();
+ if (hash)
+ {
+ *hash = File.StopHashing();
+ }
+
return result;
}