diff options
| author | jhurst <jhurst@cinecert.com> | 2013-12-15 23:34:13 +0000 |
|---|---|---|
| committer | jhurst <> | 2013-12-15 23:34:13 +0000 |
| commit | 7f373b689817ee70fbe5d6a14cb0512b5260f77c (patch) | |
| tree | 0b182f46691f1420e18be08ea1952a818c546f94 /src/as-02-wrap.cpp | |
| parent | 1f41555bcf96369227cda526e36196fe512f464e (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-x | src/as-02-wrap.cpp | 191 |
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); |
