summaryrefslogtreecommitdiff
path: root/src/as-02-wrap.cpp
diff options
context:
space:
mode:
authorjhurst <jhurst@cinecert.com>2013-12-15 23:34:13 +0000
committerjhurst <>2013-12-15 23:34:13 +0000
commit7f373b689817ee70fbe5d6a14cb0512b5260f77c (patch)
tree0b182f46691f1420e18be08ea1952a818c546f94 /src/as-02-wrap.cpp
parent1f41555bcf96369227cda526e36196fe512f464e (diff)
o Added preliminary support for timed-text wrapping for AS-02. This
work will require changes in SMPTE ST 429-5 and perhaps other standards work, so files created with this implementation are "speculative". Publication of the revised ST 429-5 may not occur until early 2015. o Moved LocalFilenameResolver into the AS_DCP public API so that it can be used by other modules including AS-02. o Fixed wave wrapping UL in clip-wrapped AS-02 files. Renamed some UL constants to reflect "clip" or "frame" wrapping. o Re-factored JP2K_PDesc_to_MD() and MD_to_JP2K_PDesc() to work with GenericPictureEssenceDescriptor objects. o Fixed a bug that was suppressing PictureComponentSizing, CodingStyleDefault and QuantizationDefault when writing the essence descriptor in a JP2K file (AS-DCP and AS-02). o Fixed the version byte on the following UL values: StereoscopicPictureSubDescriptor GenericPictureEssenceDescriptor_ColorPrimaries GenericPictureEssenceDescriptor_ActiveHeight GenericPictureEssenceDescriptor_ActiveWidth GenericPictureEssenceDescriptor_ActiveXOffset GenericPictureEssenceDescriptor_ActiveYOffset o Added some essence descriptor options to as-02-wrap. o Added TTML timed-text wrapping option to as-02-wrap. o Changed bit rate display in asdcp-info from mebi-bits/s to mega-bits/s. o Added "SMPTE" / "Interop" format type display to asdcp-info. o Modified asdcp-wrap to assume -L when wrapping timed-text (since there is no MXF text wrapping for Interop.) o Fixed missing-index-partion bugs for AS-02 files.
Diffstat (limited to 'src/as-02-wrap.cpp')
-rwxr-xr-xsrc/as-02-wrap.cpp191
1 files changed, 170 insertions, 21 deletions
diff --git a/src/as-02-wrap.cpp b/src/as-02-wrap.cpp
index 57515c4..0a31a60 100755
--- a/src/as-02-wrap.cpp
+++ b/src/as-02-wrap.cpp
@@ -179,6 +179,7 @@ public:
ui32_t start_frame; // frame number to begin processing
ui32_t duration; // number of frames to be processed
bool j2c_pedantic; // passed to JP2K::SequenceParser::OpenRead
+ bool use_cdci_descriptor; //
Rational edit_rate; // edit rate of JP2K sequence
ui32_t fb_size; // size of picture frame buffer
byte_t key_value[KeyLen]; // value of given encryption key (when key_flag is true)
@@ -190,6 +191,10 @@ public:
Kumu::PathList_t filenames; // list of filenames to be processed
UL channel_assignment;
ASDCP::MXF::AS02_MCAConfigParser mca_config;
+ ui32_t cdci_depth;
+ ui32_t rgba_MaxRef;
+ ui32_t rgba_MinRef;
+ ui32_t mxf_header_size;
//new attributes for AS-02 support
AS_02::IndexStrategy_t index_strategy; //Shim parameter index_strategy_frame/clip
@@ -200,9 +205,10 @@ public:
error_flag(true), key_flag(false), key_id_flag(false), asset_id_flag(false),
encrypt_header_flag(true), write_hmac(true), verbose_flag(false), fb_dump_size(0),
no_write_flag(false), version_flag(false), help_flag(false), start_frame(0),
- duration(0xffffffff), j2c_pedantic(true), edit_rate(24,1), fb_size(FRAME_BUFFER_SIZE),
+ duration(0xffffffff), j2c_pedantic(true), use_cdci_descriptor(false), edit_rate(24,1), fb_size(FRAME_BUFFER_SIZE),
show_ul_values_flag(false), index_strategy(AS_02::IS_FOLLOW), partition_space(60),
- mca_config(g_dict)
+ mca_config(g_dict), cdci_depth(0), rgba_MaxRef(1024), rgba_MinRef(0), mxf_header_size(16384)
+
{
memset(key_value, 0, KeyLen);
memset(key_id_value, 0, UUIDlen);
@@ -367,8 +373,8 @@ public:
namespace ASDCP {
Result_t JP2K_PDesc_to_MD(const ASDCP::JP2K::PictureDescriptor& PDesc,
const ASDCP::Dictionary& dict,
- ASDCP::MXF::RGBAEssenceDescriptor *EssenceDescriptor,
- ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor);
+ ASDCP::MXF::GenericPictureEssenceDescriptor& GenericPictureEssenceDescriptor,
+ ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor);
Result_t PCM_ADesc_to_MD(ASDCP::PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj);
}
@@ -386,7 +392,7 @@ write_JP2K_file(CommandOptions& Options)
JP2K::SequenceParser Parser;
byte_t IV_buf[CBC_BLOCK_SIZE];
Kumu::FortunaRNG RNG;
- ASDCP::MXF::RGBAEssenceDescriptor *essence_descriptor = 0;
+ ASDCP::MXF::FileDescriptor *essence_descriptor = 0;
ASDCP::MXF::InterchangeObject_list_t essence_sub_descriptors;
// set up essence parser
@@ -407,17 +413,47 @@ write_JP2K_file(CommandOptions& Options)
JP2K::PictureDescriptorDump(PDesc);
}
- // TODO: optionally set up CDCIEssenceDescriptor
- essence_descriptor = new ASDCP::MXF::RGBAEssenceDescriptor(g_dict);
- essence_sub_descriptors.push_back(new ASDCP::MXF::JPEG2000PictureSubDescriptor(g_dict));
+ if ( Options.use_cdci_descriptor )
+ {
+ ASDCP::MXF::CDCIEssenceDescriptor* tmp_dscr = new ASDCP::MXF::CDCIEssenceDescriptor(g_dict);
+ essence_sub_descriptors.push_back(new ASDCP::MXF::JPEG2000PictureSubDescriptor(g_dict));
+
+ result = ASDCP::JP2K_PDesc_to_MD(PDesc, *g_dict,
+ *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr),
+ *static_cast<ASDCP::MXF::JPEG2000PictureSubDescriptor*>(essence_sub_descriptors.back()));
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ // TODO, select profile
+ tmp_dscr->PictureEssenceCoding = UL(g_dict->ul(MDD_JP2KEssenceCompression_BroadcastProfile_1));
+ tmp_dscr->ComponentDepth = Options.cdci_depth;
+
+ // more options here
- result = ASDCP::JP2K_PDesc_to_MD(PDesc, *g_dict, essence_descriptor,
- reinterpret_cast<ASDCP::MXF::JPEG2000PictureSubDescriptor*>(essence_sub_descriptors.back()));
+ essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr);
+ }
+ }
+ else
+ { // use RGB
+ ASDCP::MXF::RGBAEssenceDescriptor* tmp_dscr = new ASDCP::MXF::RGBAEssenceDescriptor(g_dict);
+ essence_sub_descriptors.push_back(new ASDCP::MXF::JPEG2000PictureSubDescriptor(g_dict));
+
+ result = ASDCP::JP2K_PDesc_to_MD(PDesc, *g_dict,
+ *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr),
+ *static_cast<ASDCP::MXF::JPEG2000PictureSubDescriptor*>(essence_sub_descriptors.back()));
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ // TODO, select profile
+ tmp_dscr->PictureEssenceCoding = UL(g_dict->ul(MDD_JP2KEssenceCompression_BroadcastProfile_1));
+ tmp_dscr->ComponentMaxRef = Options.rgba_MaxRef;
+ tmp_dscr->ComponentMinRef = Options.rgba_MinRef;
- /// TODO: set with magic or some such thing
- essence_descriptor->PictureEssenceCoding = UL(g_dict->ul(MDD_JP2KEssenceCompression_BroadcastProfile_1));
- essence_descriptor->ComponentMaxRef = 4095;
- essence_descriptor->ComponentMinRef = 0;
+ // more options here
+
+ essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr);
+ }
+ }
}
if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
@@ -457,11 +493,8 @@ write_JP2K_file(CommandOptions& Options)
if ( ASDCP_SUCCESS(result) )
{
- result = Writer.OpenWrite(Options.out_file, Info,
- static_cast<ASDCP::MXF::FileDescriptor*>(essence_descriptor),
- essence_sub_descriptors,
- Options.edit_rate, 16384, Options.index_strategy, Options.partition_space);
- // TODO: make 16384 part of CommandOptions
+ result = Writer.OpenWrite(Options.out_file, Info, essence_descriptor, essence_sub_descriptors,
+ Options.edit_rate, Options.mxf_header_size, Options.index_strategy, Options.partition_space);
}
}
@@ -510,8 +543,8 @@ write_JP2K_file(CommandOptions& Options)
// PCM essence
-// Write one or more plaintext PCM audio streams to a plaintext ASDCP file
-// Write one or more plaintext PCM audio streams to a ciphertext ASDCP file
+// Write one or more plaintext PCM audio streams to a plaintext AS-02 file
+// Write one or more plaintext PCM audio streams to a ciphertext AS-02 file
//
Result_t
write_PCM_file(CommandOptions& Options)
@@ -659,6 +692,121 @@ write_PCM_file(CommandOptions& Options)
}
+//------------------------------------------------------------------------------------------
+// TimedText essence
+
+
+// Write one or more plaintext timed text streams to a plaintext AS-02 file
+// Write one or more plaintext timed text streams to a ciphertext AS-02 file
+//
+Result_t
+write_timed_text_file(CommandOptions& Options)
+{
+ AESEncContext* Context = 0;
+ HMACContext* HMAC = 0;
+ AS_02::TimedText::ST2052_TextParser Parser;
+ AS_02::TimedText::MXFWriter Writer;
+ TimedText::FrameBuffer FrameBuffer;
+ TimedText::TimedTextDescriptor TDesc;
+ byte_t IV_buf[CBC_BLOCK_SIZE];
+ Kumu::FortunaRNG RNG;
+
+ // set up essence parser
+ Result_t result = Parser.OpenRead(Options.filenames.front().c_str());
+
+ // set up MXF writer
+ if ( ASDCP_SUCCESS(result) )
+ {
+ Parser.FillTimedTextDescriptor(TDesc);
+ FrameBuffer.Capacity(Options.fb_size);
+
+ if ( Options.verbose_flag )
+ {
+ fputs("IMF Timed-Text Descriptor:\n", stderr);
+ TimedText::DescriptorDump(TDesc);
+ }
+ }
+
+ if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
+ {
+ WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
+ if ( Options.asset_id_flag )
+ memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
+ else
+ Kumu::GenRandomUUID(Info.AssetUUID);
+
+ // 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.c_str(), Info, TDesc);
+ }
+
+ if ( ASDCP_FAILURE(result) )
+ return result;
+
+ std::string XMLDoc;
+ TimedText::ResourceList_t::const_iterator ri;
+
+ result = Parser.ReadTimedTextResource(XMLDoc);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = Writer.WriteTimedTextResource(XMLDoc, Context, HMAC);
+
+ for ( ri = TDesc.ResourceList.begin() ; ri != TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ )
+ {
+ result = Parser.ReadAncillaryResource((*ri).ResourceID, FrameBuffer);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ if ( Options.verbose_flag )
+ FrameBuffer.Dump(stderr, Options.fb_dump_size);
+
+ if ( ! Options.no_write_flag )
+ {
+ result = Writer.WriteAncillaryResource(FrameBuffer, Context, HMAC);
+
+ // The Writer class will forward the last block of ciphertext
+ // to the encryption context for use as the IV for the next
+ // frame. If you want to use non-sequitur IV values, un-comment
+ // the following line of code.
+ // if ( ASDCP_SUCCESS(result) && Options.key_flag )
+ // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
+ }
+ }
+
+ if ( result == RESULT_ENDOFFILE )
+ result = RESULT_OK;
+ }
+
+ if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
+ result = Writer.Finalize();
+
+ return result;
+}
+
//
int
main(int argc, const char** argv)
@@ -666,6 +814,7 @@ main(int argc, const char** argv)
Result_t result = RESULT_OK;
char str_buf[64];
g_dict = &ASDCP::DefaultSMPTEDict();
+ assert(g_dict);
CommandOptions Options(argc, argv);