// 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);
// 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);
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();
};
//
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;
ui64_t StreamOffset = m_StreamOffset;
if ( ASDCP_SUCCESS(result) )
- result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
+ result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC, hash);
if ( ASDCP_SUCCESS(result) && add_index )
{
// 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
//
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;
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)
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;
}
// 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
Result_t Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader& HeaderPart,
const ASDCP::WriterInfo& Info, ASDCP::FrameBuffer& CtFrameBuf, ui32_t& FramesWritten,
ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
- AESEncContext* Ctx, HMACContext* HMAC);
+ AESEncContext* Ctx, HMACContext* HMAC, std::string* hash = 0);
//
class KLReader : public ASDCP::KLVPacket
Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
- AESEncContext* Ctx, HMACContext* HMAC);
+ AESEncContext* Ctx, HMACContext* HMAC, std::string* hash = 0);
Result_t FakeWriteEKLVPacket(int size);
Result_t WriteASDCPFooter();
};
#include <KM_fileio.h>
#include <KM_log.h>
#include <fcntl.h>
+#include <sstream>
+#include <iomanip>
#include <assert.h>
// 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() {}
//
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);
+
+ std::stringstream s;
+ for (int i = 0; i < MD5_DIGEST_LENGTH; ++i)
+ {
+ s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]);
+ }
+
+ return s.str ();
+}
+
+
+
#ifdef KM_WIN32
//------------------------------------------------------------------------------------------
break;
}
+ MaybeHash(iov->m_iovec[i].iov_base, iov->m_iovec[i].iov_len);
*bytes_written += tmp_count;
}
if ( result == 0 || *bytes_written != buf_len )
return Kumu::RESULT_WRITEFAIL;
+ MaybeHash(buf, buf_len);
+
return Kumu::RESULT_OK;
}
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;
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;
#include <KM_util.h>
#include <string>
#include <boost/filesystem.hpp>
+#include <openssl/md5.h>
#ifdef KM_WIN32
# include <io.h>
class h__iovec;
mem_ptr<h__iovec> m_IOVec;
KM_NO_COPY_CONSTRUCT(FileWriter);
+ bool m_Hashing;
+ MD5_CTX m_MD5Context;
public:
FileWriter();
// 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);
//
Result_t
ASDCP::h__ASDCPWriter::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
- AESEncContext* Ctx, HMACContext* HMAC)
+ 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, Ctx, HMAC);
+ m_StreamOffset, FrameBuf, EssenceUL, Ctx, HMAC, hash);
}
Result_t
ASDCP::Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader&,
const ASDCP::WriterInfo& Info, ASDCP::FrameBuffer& CtFrameBuf, ui32_t& FramesWritten,
ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
- 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);
if ( ASDCP_SUCCESS(result) )
result = File.Writev();
+ if (hash)
+ {
+ *hash = File.StopHashing();
+ }
+
return result;
}