AS-DCP, is described in series of separate documents which include but
may not be limited to:
- o AS-DCP Track File Specification
- o AS-DCP Track File Essence Encryption Specification
- o AS-DCP Operational Constraints Specification
+ o MXF Interop Track File Specification
+ o MXF Interop Track File Essence Encryption Specification
+ o MXF Interop Operational Constraints Specification
+ o SMPTE 429-3-2006 Track File Specification
+ o SMPTE 429-4-2006 JPEG 2000 for D-Cinema
+ o SMPTE 429-5-200X Timed Text Track File
+ o SMPTE 429-6-2006 Essence Encryption Specification
+ o SMPTE 429-10-2006 Stereoscopic Image Track File
o SMPTE 330M - UMID
o SMPTE 336M - KLV
o SMPTE 377M - MXF
o SMPTE 390M - OP-Atom
o SMPTE 379M - Generic Container
o SMPTE 381M - MPEG2 picture
- o SMPTE XXXM - JPEG 2000 picture
+ o SMPTE 422M - JPEG 2000 picture
o SMPTE 382M - WAV/PCM sound
o IETF RFC 2104 - HMAC/SHA1
o NIST FIPS 197 - AES (Rijndael)
// in file format, and if no changes were made to AS_DCP.h, the new version would be
// 1.0.1. If changes were also required in AS_DCP.h, the new version would be 1.1.1.
const ui32_t VERSION_MAJOR = 1;
- const ui32_t VERSION_APIMINOR = 1;
- const ui32_t VERSION_IMPMINOR = 15;
+ const ui32_t VERSION_APIMINOR = 2;
+ const ui32_t VERSION_IMPMINOR = 16;
const char* Version();
// UUIDs are passed around as strings of UUIDlen bytes
const Kumu::Result_t RESULT_CRYPT_INIT (-111, "Error initializing block cipher context.");
const Kumu::Result_t RESULT_EMPTY_FB (-112, "Empty frame buffer.");
const Kumu::Result_t RESULT_KLV_CODING (-113, "KLV coding error.");
+ const Kumu::Result_t RESULT_SPHASE (-114, "Stereoscopic phase mismatch.");
//---------------------------------------------------------------------------------
// file identification
ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs
ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs
ESS_TIMED_TEXT, // the file contains an XML timed text document and one or more resources
+ ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic)
};
// Determine the type of essence contained in the given MXF file. RESULT_OK
// common edit rates, use these instead of hard coded constants
const Rational EditRate_24(24,1);
- const Rational EditRate_23_98(24000,1001);
+ const Rational EditRate_23_98(24000,1001); // Not a DCI-compliant value!
const Rational EditRate_48(48,1);
const Rational SampleRate_48k(48000,1);
+ const Rational SampleRate_96k(96000,1);
// Non-reference counting container for internal member objects.
// Please do not use this class for any other purpose.
void DumpHeaderMetadata(FILE* = 0) const;
void DumpIndex(FILE* = 0) const;
};
+
+
+ // Stereoscopic Image support
+ //
+
+ enum StereoscopicPhase_t
+ {
+ SP_LEFT,
+ SP_RIGHT
+ };
+
+
+ class MXFSWriter
+ {
+ class h__SWriter;
+ mem_ptr<h__SWriter> m_Writer;
+ ASDCP_NO_COPY_CONSTRUCT(MXFSWriter);
+
+ public:
+ MXFSWriter();
+ virtual ~MXFSWriter();
+
+ // Open the file for writing. The file must not exist. Returns error if
+ // the operation cannot be completed or if nonsensical data is discovered
+ // in the essence descriptor.
+ Result_t OpenWrite(const char* filename, const WriterInfo&,
+ const PictureDescriptor&, ui32_t HeaderSize = 16384);
+
+ // Writes a frame of essence to the MXF file. If the optional AESEncContext
+ // argument is present, the essence is encrypted prior to writing.
+ // Fails if the file is not open, is finalized, or an operating system
+ // error occurs. Frames must be written in the proper phase (L-R-L-R),
+ // 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);
+
+ // Closes the MXF file, writing the index and revised header. Returns
+ // RESULT_SPHASE if WriteFrame was called an odd number of times.
+ Result_t Finalize();
+ };
+
+ //
+ class MXFSReader
+ {
+ class h__SReader;
+ mem_ptr<h__SReader> m_Reader;
+ ASDCP_NO_COPY_CONSTRUCT(MXFSReader);
+
+ public:
+ MXFSReader();
+ virtual ~MXFSReader();
+
+ // Open the file for reading. The file must exist. Returns error if the
+ // operation cannot be completed.
+ Result_t OpenRead(const char* filename) const;
+
+ // Returns RESULT_INIT if the file is not open.
+ Result_t Close() const;
+
+ // Fill an AudioDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillPictureDescriptor(PictureDescriptor&) const;
+
+ // Fill a WriterInfo struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillWriterInfo(WriterInfo&) const;
+
+ // Reads a frame of essence from the MXF file. If the optional AESEncContext
+ // argument is present, the essence is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadFrame(ui32_t frame_number, StereoscopicPhase_t phase,
+ FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Print debugging information to stream
+ void DumpHeaderMetadata(FILE* = 0) const;
+ void DumpIndex(FILE* = 0) const;
+ };
} // namespace JP2K
} // namespace ASDCP
/*
-Copyright (c) 2004-2006, John Hurst
+Copyright (c) 2004-2007, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
//------------------------------------------------------------------------------------------
static std::string JP2K_PACKAGE_LABEL = "File Package: SMPTE 429-4 frame wrapping of JPEG 2000 codestreams";
+static std::string JP2K_S_PACKAGE_LABEL = "File Package: SMPTE 429-10 frame wrapping of stereoscopic JPEG 2000 codestreams";
static std::string PICT_DEF_LABEL = "Picture Track";
//
//------------------------------------------------------------------------------------------
+using namespace ASDCP::JP2K;
//
-class ASDCP::JP2K::MXFWriter::h__Writer : public ASDCP::h__Writer
+class lh__Writer : public ASDCP::h__Writer
{
JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
PictureDescriptor m_PDesc;
byte_t m_EssenceUL[SMPTE_UL_LENGTH];
- ASDCP_NO_COPY_CONSTRUCT(h__Writer);
+ ASDCP_NO_COPY_CONSTRUCT(lh__Writer);
- h__Writer() : m_EssenceSubDescriptor(0) {
+ lh__Writer() : m_EssenceSubDescriptor(0) {
memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
}
- ~h__Writer(){}
+ ~lh__Writer(){}
Result_t OpenWrite(const char*, ui32_t HeaderSize);
- Result_t SetSourceStream(const PictureDescriptor&);
- Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+ 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 Finalize();
Result_t JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc);
};
//
ASDCP::Result_t
-ASDCP::JP2K::MXFWriter::h__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc)
+lh__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc)
{
assert(m_EssenceDescriptor);
assert(m_EssenceSubDescriptor);
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed.
ASDCP::Result_t
-ASDCP::JP2K::MXFWriter::h__Writer::OpenWrite(const char* filename, ui32_t HeaderSize)
+lh__Writer::OpenWrite(const char* filename, ui32_t HeaderSize)
{
if ( ! m_State.Test_BEGIN() )
return RESULT_STATE;
// Automatically sets the MXF file's metadata from the first jpeg codestream stream.
ASDCP::Result_t
-ASDCP::JP2K::MXFWriter::h__Writer::SetSourceStream(const PictureDescriptor& PDesc)
+lh__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& label, ASDCP::Rational LocalEditRate)
{
if ( ! m_State.Test_INIT() )
return RESULT_STATE;
+ if ( LocalEditRate == ASDCP::Rational(0,0) )
+ LocalEditRate = m_PDesc.EditRate;
+
m_PDesc = PDesc;
Result_t result = JP2K_PDesc_to_MD(m_PDesc);
if ( ASDCP_SUCCESS(result) )
- result = WriteMXFHeader(JP2K_PACKAGE_LABEL, UL(Dict::ul(MDD_JPEG_2000Wrapping)),
+ result = WriteMXFHeader(label, UL(Dict::ul(MDD_JPEG_2000Wrapping)),
PICT_DEF_LABEL, UL(Dict::ul(MDD_PictureDataDef)),
- m_PDesc.EditRate, 24 /* TCFrameRate */);
+ LocalEditRate, 24 /* TCFrameRate */);
if ( ASDCP_SUCCESS(result) )
{
// error occurs.
//
ASDCP::Result_t
-ASDCP::JP2K::MXFWriter::h__Writer::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx,
- HMACContext* HMAC)
+lh__Writer::WriteFrame(const JP2K::FrameBuffer& FrameBuf, bool add_index,
+ AESEncContext* Ctx, HMACContext* HMAC)
{
Result_t result = RESULT_OK;
if ( m_State.Test_READY() )
result = m_State.Goto_RUNNING(); // first time through
- IndexTableSegment::IndexEntry Entry;
- Entry.StreamOffset = m_StreamOffset;
+ ui64_t StreamOffset = m_StreamOffset;
if ( ASDCP_SUCCESS(result) )
result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
- if ( ASDCP_SUCCESS(result) )
+ if ( ASDCP_SUCCESS(result) && add_index )
{
+ IndexTableSegment::IndexEntry Entry;
+ Entry.StreamOffset = StreamOffset;
m_FooterPart.PushIndexEntry(Entry);
m_FramesWritten++;
}
// Closes the MXF file, writing the index and other closing information.
//
ASDCP::Result_t
-ASDCP::JP2K::MXFWriter::h__Writer::Finalize()
+lh__Writer::Finalize()
{
if ( ! m_State.Test_RUNNING() )
return RESULT_STATE;
}
+//
+class ASDCP::JP2K::MXFWriter::h__Writer : public lh__Writer
+{
+};
+
+
//------------------------------------------------------------------------------------------
if ( ASDCP_SUCCESS(result) )
{
m_Writer->m_Info = Info;
- result = m_Writer->SetSourceStream(PDesc);
+ result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL);
}
if ( ASDCP_FAILURE(result) )
if ( m_Writer.empty() )
return RESULT_INIT;
- return m_Writer->WriteFrame(FrameBuf, Ctx, HMAC);
+ return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC);
}
// Closes the MXF file, writing the index and other closing information.
}
+//------------------------------------------------------------------------------------------
+//
+
+//
+class ASDCP::JP2K::MXFSWriter::h__SWriter : public lh__Writer
+{
+ StereoscopicPhase_t m_NextPhase;
+
+public:
+ h__SWriter() : m_NextPhase(SP_LEFT) {}
+
+ //
+ Result_t WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
+ AESEncContext* Ctx, HMACContext* HMAC)
+ {
+ if ( m_NextPhase != phase )
+ return RESULT_SPHASE;
+
+ if ( phase == SP_LEFT )
+ {
+ m_NextPhase = SP_RIGHT;
+ return lh__Writer::WriteFrame(FrameBuf, true, Ctx, HMAC);
+ }
+
+ m_NextPhase = SP_LEFT;
+ return lh__Writer::WriteFrame(FrameBuf, false, Ctx, HMAC);
+ }
+
+ //
+ Result_t Finalize()
+ {
+ if ( m_NextPhase != SP_LEFT )
+ return RESULT_SPHASE;
+
+ return lh__Writer::Finalize();
+ }
+};
+
+
+//
+ASDCP::JP2K::MXFSWriter::MXFSWriter()
+{
+}
+
+ASDCP::JP2K::MXFSWriter::~MXFSWriter()
+{
+}
+
+
+// Open the file for writing. The file must not exist. Returns error if
+// the operation cannot be completed.
+ASDCP::Result_t
+ASDCP::JP2K::MXFSWriter::OpenWrite(const char* filename, const WriterInfo& Info,
+ const PictureDescriptor& PDesc, ui32_t HeaderSize)
+{
+ m_Writer = new h__SWriter;
+
+ if ( PDesc.EditRate != ASDCP::EditRate_24 )
+ {
+ DefaultLogSink().Error("Stereoscopic wrapping requires 24 fps input streams.\n");
+ return RESULT_FORMAT;
+ }
+
+ Result_t result = m_Writer->OpenWrite(filename, HeaderSize);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ m_Writer->m_Info = Info;
+ PictureDescriptor TmpPDesc = PDesc;
+ TmpPDesc.EditRate = ASDCP::EditRate_48;
+
+ result = m_Writer->SetSourceStream(TmpPDesc, JP2K_S_PACKAGE_LABEL, ASDCP::EditRate_24);
+ }
+
+ if ( ASDCP_FAILURE(result) )
+ m_Writer.release();
+
+ return result;
+}
+
+
+// Writes a frame of essence to the MXF file. If the optional AESEncContext
+// argument is present, the essence is encrypted prior to writing.
+// Fails if the file is not open, is finalized, or an operating system
+// error occurs.
+ASDCP::Result_t
+ASDCP::JP2K::MXFSWriter::WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
+ AESEncContext* Ctx, HMACContext* HMAC)
+{
+ if ( m_Writer.empty() )
+ return RESULT_INIT;
+
+ return m_Writer->WriteFrame(FrameBuf, phase, Ctx, HMAC);
+}
+
+// Closes the MXF file, writing the index and other closing information.
+ASDCP::Result_t
+ASDCP::JP2K::MXFSWriter::Finalize()
+{
+ if ( m_Writer.empty() )
+ return RESULT_INIT;
+
+ return m_Writer->Finalize();
+}
+
//
// end AS_DCP_JP2K.cpp
//
type = ESS_UNKNOWN;
if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor))) )
type = ESS_JPEG_2000;
- else
- {
- if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor))) )
- type = ESS_PCM_24b_48k;
- else
- {
- if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(MPEG2VideoDescriptor))) )
- type = ESS_MPEG2_VES;
- else
- {
- if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DCTimedTextDescriptor))) )
- type = ESS_TIMED_TEXT;
- }
- }
- }
+ else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor))) )
+ type = ESS_PCM_24b_48k;
+ else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(MPEG2VideoDescriptor))) )
+ type = ESS_MPEG2_VES;
+ else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DCTimedTextDescriptor))) )
+ type = ESS_TIMED_TEXT;
}
return result;
if ( m_KeyStart != 0 )
{
assert(m_ValueStart);
-
- for ( ui32_t i = 0; i < SMPTE_UL_LENGTH; i++ )
- fprintf(stream, "%02x.", m_KeyStart[i]);
+ UL TmpUL(m_KeyStart);
+ char buf[64];
+ fprintf(stream, "%s", TmpUL.EncodeString(buf, 64));
const MDDEntry* Entry = Dict::FindUL(m_KeyStart);
- fprintf(stream, "\b len: %7u (%s)\n", m_ValueLength, (Entry ? Entry->name : "Unknown"));
+ fprintf(stream, " len: %7u (%s)\n", m_ValueLength, (Entry ? Entry->name : "Unknown"));
if ( show_hex && m_ValueLength < 1000 )
Kumu::hexdump(m_ValueStart, Kumu::xmin(m_ValueLength, (ui32_t)64), stream);
KLVFilePacket::Dump(stream, false);
PairArray.Dump(stream, false);
-
- fputs("==========================================================================\n", stream);
}
//------------------------------------------------------------------------------------------
fprintf(stream, " BodySID = %u\n", BodySID);
fprintf(stream, " OperationalPattern = %s\n", OperationalPattern.EncodeString(identbuf, IdentBufferLen));
fputs("Essence Containers:\n", stream); EssenceContainers.Dump(stream, false);
-
- fputs("==========================================================================\n", stream);
}
const MDDEntry* Entry = Dict::FindUL((*i).UL.Value());
fprintf(stream, " %s %s\n", (*i).EncodeString(identbuf, IdentBufferLen), (Entry ? Entry->name : "Unknown"));
}
-
- fputs("==========================================================================\n", stream);
}
if ( stream == 0 )
stream = stderr;
- if ( m_HasRIP )
- m_RIP.Dump(stream);
-
Partition::Dump(stream);
m_Primer.Dump(stream);
if ( m_Preface == 0 )
fputs("No Preface loaded\n", stream);
- else
- m_Preface->Dump(stream);
std::list<InterchangeObject*>::iterator i = m_PacketList->m_List.begin();
for ( ; i != m_PacketList->m_List.end(); i++ )
//---------------------------------------------------------------------------------
//
- class h__PacketList; // See MXF.cpp
class Identification;
class SourcePackage;
usage(FILE* stream = stdout)
{
fprintf(stream, "\
-USAGE: %s -c <output-file> [-b <buffer-size>] [-d <duration>] [-e|-E]\n\
+USAGE: %s -c <output-file> [-3] [-b <buffer-size>] [-d <duration>] [-e|-E]\n\
[-f <start-frame>] [-j <key-id-string>] [-k <key-string>] [-L] [-M]\n\
[-p <frame-rate>] [-R] [-s <num>] [-v] [-W]\n\
- <input-file> [<input-file2> ...]\n\
+ <input-file> [<input-file-2> ...]\n\
\n\
%s [-h|-help] [-V]\n\
\n\
fprintf(stream, "\
Major modes:\n\
- -c <output-file> - Create AS-DCP track file from input(s)\n\
+ -3 - Create a stereoscopic image file. Expects two dir-\n\
+ ectories of JP2K codestreams (directories must have\n\
+ an equal number of frames; left eye is first).\n\
+ -c <output-file> - Create an AS-DCP track file from input(s)\n\
-g - Generate a random 16 byte value to stdout\n\
-G - Perform GOP start lookup test on MXF+Interop MPEG file\n\
-h | -help - Show help\n\
bool no_write_flag; // true if no output files are to be written
bool version_flag; // true if the version display option was selected
bool help_flag; // true if the help display option was selected
+ bool stereo_image_flag; // if true, expect stereoscopic JP2K input (left eye first)
ui32_t start_frame; // frame number to begin processing
ui32_t duration; // number of frames to be processed
bool duration_flag; // true if duration argument given
mode(MMT_NONE), error_flag(true), key_flag(false), key_id_flag(false), encrypt_header_flag(true),
write_hmac(true), read_hmac(false), split_wav(false), mono_wav(false),
verbose_flag(false), fb_dump_size(0), showindex_flag(false), showheader_flag(false),
- no_write_flag(false), version_flag(false), help_flag(false), start_frame(0),
+ no_write_flag(false), version_flag(false), help_flag(false), stereo_image_flag(false), start_frame(0),
duration(0xffffffff), duration_flag(false), do_repeat(false), use_smpte_labels(false),
picture_rate(24), fb_size(FRAME_BUFFER_SIZE), file_count(0), file_root(0), out_file(0)
{
{
case '1': mono_wav = true; break;
case '2': split_wav = true; break;
+ case '3': stereo_image_flag = true; break;
case 'i': mode = MMT_INFO; break;
case 'G': mode = MMT_GOP_START; break;
case 'W': no_write_flag = true; break;
//------------------------------------------------------------------------------------------
// JPEG 2000 essence
+// Write one or more plaintext JPEG 2000 stereoscopic codestream pairs to a plaintext ASDCP file
+// Write one or more plaintext JPEG 2000 stereoscopic codestream pairs to a ciphertext ASDCP file
+//
+Result_t
+write_JP2K_S_file(CommandOptions& Options)
+{
+ AESEncContext* Context = 0;
+ HMACContext* HMAC = 0;
+ JP2K::MXFSWriter Writer;
+ JP2K::FrameBuffer FrameBuffer(Options.fb_size);
+ JP2K::PictureDescriptor PDesc;
+ JP2K::SequenceParser ParserLeft, ParserRight;
+ byte_t IV_buf[CBC_BLOCK_SIZE];
+ Kumu::FortunaRNG RNG;
+
+ fprintf(stderr, "Hello, stereoscopic world!\n");
+
+ if ( Options.file_count != 2 )
+ {
+ fprintf(stderr, "Two inputs are required for stereoscopic option.\n");
+ return RESULT_FAIL;
+ }
+
+ // set up essence parser
+ Result_t result = ParserLeft.OpenRead(Options.filenames[0]);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = ParserRight.OpenRead(Options.filenames[1]);
+
+ // set up MXF writer
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ParserLeft.FillPictureDescriptor(PDesc);
+ PDesc.EditRate = Options.PictureRate();
+
+ if ( Options.verbose_flag )
+ {
+ fputs("JPEG 2000 stereoscopic pictures\nPictureDescriptor:\n", stderr);
+ fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
+ JP2K::PictureDescriptorDump(PDesc);
+ }
+ }
+
+ if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
+ {
+ WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
+ Kumu::GenRandomUUID(Info.AssetUUID);
+
+ if ( Options.use_smpte_labels )
+ {
+ Info.LabelSetType = LS_MXF_SMPTE;
+ fprintf(stderr, "ATTENTION! Writing SMPTE Universal Labels\n");
+ }
+
+ // configure encryption
+ if( Options.key_flag )
+ {
+ Kumu::GenRandomUUID(Info.ContextID);
+ Info.EncryptedEssence = true;
+
+ if ( Options.key_id_flag )
+ memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
+ else
+ RNG.FillRandom(Info.CryptographicKeyID, UUIDlen);
+
+ Context = new AESEncContext;
+ result = Context->InitKey(Options.key_value);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
+
+ if ( ASDCP_SUCCESS(result) && Options.write_hmac )
+ {
+ Info.UsesHMAC = true;
+ HMAC = new HMACContext;
+ result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
+ }
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ result = Writer.OpenWrite(Options.out_file, Info, PDesc);
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ui32_t duration = 0;
+ result = ParserLeft.Reset();
+ if ( ASDCP_SUCCESS(result) ) result = ParserRight.Reset();
+
+ while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
+ {
+ result = ParserLeft.ReadFrame(FrameBuffer);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ if ( Options.verbose_flag )
+ FrameBuffer.Dump(stderr, Options.fb_dump_size);
+
+ if ( Options.encrypt_header_flag )
+ FrameBuffer.PlaintextOffset(0);
+ }
+
+ if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
+ result = Writer.WriteFrame(FrameBuffer, JP2K::SP_LEFT, Context, HMAC);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = ParserRight.ReadFrame(FrameBuffer);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ if ( Options.verbose_flag )
+ FrameBuffer.Dump(stderr, Options.fb_dump_size);
+
+ if ( Options.encrypt_header_flag )
+ FrameBuffer.PlaintextOffset(0);
+ }
+
+ if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
+ result = Writer.WriteFrame(FrameBuffer, JP2K::SP_RIGHT, Context, HMAC);
+ }
+
+ if ( result == RESULT_ENDOFFILE )
+ result = RESULT_OK;
+ }
+
+ if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
+ result = Writer.Finalize();
+
+ return result;
+}
+
// Write one or more plaintext JPEG 2000 codestreams to a plaintext ASDCP file
// Write one or more plaintext JPEG 2000 codestreams to a ciphertext ASDCP file
//
fputs("File essence type is JPEG 2000 pictures.\n", stdout);
FileInfoWrapper<ASDCP::JP2K::MXFReader, MyPictureDescriptor>::file_info(Options);
}
+ else if ( EssenceType == ESS_JPEG_2000_S )
+ {
+ fputs("File essence type is JPEG 2000 stereoscopic pictures.\n", stdout);
+ FileInfoWrapper<ASDCP::JP2K::MXFReader, MyPictureDescriptor>::file_info(Options);
+ }
#ifdef ASDCP_WITH_TIMED_TEXT
else if ( EssenceType == ESS_TIMED_TEXT )
{
break;
case ESS_JPEG_2000:
- result = write_JP2K_file(Options);
+ if ( Options.stereo_image_flag )
+ result = write_JP2K_S_file(Options);
+
+ else
+ result = write_JP2K_file(Options);
+
break;
case ESS_PCM_24b_48k:
/*
-Copyright (c) 2005-2006, John Hurst
+Copyright (c) 2005-2007, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
{
fprintf(stream, "\n\
%s (asdcplib %s)\n\n\
-Copyright (c) 2005-2006 John Hurst\n\
+Copyright (c) 2005-2007 John Hurst\n\
%s is part of the asdcplib DCP tools package.\n\
asdcplib may be copied only under the terms of the license found at\n\
the top of every file in the asdcplib distribution kit.\n\n\
\n\
%s [-h|-help] [-V]\n\
\n\
- -h | -help - Show help\n\
- -r - When KLV data is an OPAtom file, additionally\n\
- display OPAtom headers\n\
- -v - Verbose. Prints informative messages to stderr\n\
- -V - Show version information\n\
+ -h | -help - Show help\n\
+ -r - When KLV data is an MXF OPAtom file, display OPAtom headers\n\
+ -v - Verbose. Prints informative messages to stderr\n\
+ -V - Show version information\n\
\n\
NOTES: o There is no option grouping, all options must be distinct arguments.\n\
o All option arguments must be separated from the option by whitespace.\n\
{
switch ( argv[i][1] )
{
-
case 'h': help_flag = true; break;
case 'r': read_mxf_flag = true; break;
case 'V': version_flag = true; break;
if ( ASDCP_SUCCESS(result) )
result = Header.InitFromFile(Reader);
- Header.Dump(stdout);
+ if ( ASDCP_SUCCESS(result) )
+ Header.Dump(stdout);
- if ( ASDCP_SUCCESS(result) && Header.m_RIP.PairArray.size() > 3 )
+ if ( ASDCP_SUCCESS(result) && Header.m_RIP.PairArray.size() > 2 )
{
MXF::Array<MXF::RIP::Pair>::const_iterator pi = Header.m_RIP.PairArray.begin();
if ( ASDCP_SUCCESS(result) )
Index.Dump(stdout);
}
+
+ if ( ASDCP_SUCCESS(result) )
+ Header.m_RIP.Dump(stdout);
}
else // dump klv
{