diff options
| author | Thomas Richter <thomas.richter@iis.fraunhofer.de> | 2021-05-28 12:43:29 +0200 |
|---|---|---|
| committer | Thomas Richter <thomas.richter@iis.fraunhofer.de> | 2021-05-28 12:43:29 +0200 |
| commit | d1f386db72b5374b11c9df061a5ff2e6e8adc610 (patch) | |
| tree | 8a010d36b349fcd790fceeacbea5ca5306ccd8fb /src | |
| parent | f9d7fbc33aa571c547d916b145712469efd9f4b8 (diff) | |
Added a first version of JXS support for as-02-wrap.
Added recognition of JXS files in AS_DCP_MXF.
In case color specifications are missing from the original
picture descriptor, JXS_PDesc_to_MD() no longer fails, it
just does not fill in the Essence descriptor and leaves that
to the caller, e.g. as-02-wrap.
Diffstat (limited to 'src')
| -rw-r--r-- | src/AS_DCP_JXS.cpp | 4 | ||||
| -rwxr-xr-x | src/AS_DCP_MXF.cpp | 9 | ||||
| -rwxr-xr-x | src/as-02-wrap.cpp | 220 |
3 files changed, 232 insertions, 1 deletions
diff --git a/src/AS_DCP_JXS.cpp b/src/AS_DCP_JXS.cpp index 3dbbedc..bf4dbe6 100644 --- a/src/AS_DCP_JXS.cpp +++ b/src/AS_DCP_JXS.cpp @@ -203,6 +203,8 @@ ASDCP::JXS_PDesc_to_MD(const JXS::PictureDescriptor& PDesc, // switch(PDesc.Primaries) { + case 0: // If this is not set, do not update the essence descriptor. + break; case 1: EssenceDescriptor.ColorPrimaries = dict.ul(ASDCP::MDD_ColorPrimaries_ITU709); break; @@ -230,6 +232,8 @@ ASDCP::JXS_PDesc_to_MD(const JXS::PictureDescriptor& PDesc, } switch(PDesc.TransferCurve) { + case 0: + break; // If this is not set, do not update the transfer curve. case 1: case 6: EssenceDescriptor.TransferCharacteristic = dict.ul(ASDCP::MDD_TransferCharacteristic_ITU709); diff --git a/src/AS_DCP_MXF.cpp b/src/AS_DCP_MXF.cpp index 9cb4c15..7231b5a 100755 --- a/src/AS_DCP_MXF.cpp +++ b/src/AS_DCP_MXF.cpp @@ -33,6 +33,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <KM_xml.h> #include "AS_DCP_internal.h" #include "JP2K.h" +#include "JXS.h" #include "ACES.h" #include "MPEG.h" #include "Wav.h" @@ -344,6 +345,10 @@ ASDCP::RawEssenceType(const std::string& filename, EssenceType_t& type) { type = ESS_JPEG_2000; } + else if ( memcmp(FB.RoData(), ASDCP::JXS::Magic, sizeof(ASDCP::JXS::Magic)) == 0 ) + { + type = ESS_JPEG_XS; + } else if(memcmp(FB.RoData(), AS_02::ACES::Magic, sizeof(AS_02::ACES::Magic)) == 0) { type = ESS_AS02_ACES; @@ -424,6 +429,10 @@ ASDCP::RawEssenceType(const std::string& filename, EssenceType_t& type) { type = ESS_JPEG_2000; } + else if ( memcmp(FB.RoData(), ASDCP::JXS::Magic, sizeof(ASDCP::JXS::Magic)) == 0 ) + { + type = ESS_JPEG_XS; + } else if(memcmp(FB.RoData(), AS_02::ACES::Magic, sizeof(AS_02::ACES::Magic)) == 0) { type = ESS_AS02_ACES; diff --git a/src/as-02-wrap.cpp b/src/as-02-wrap.cpp index 713bcdb..b457716 100755 --- a/src/as-02-wrap.cpp +++ b/src/as-02-wrap.cpp @@ -1,6 +1,6 @@ /* Copyright (c) 2011-2020, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, -John Hurst, Wolfgang Ruppel +John Hurst, Wolfgang Ruppel, Thomas Richter All rights reserved. @@ -39,6 +39,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <KM_xml.h> #include <KM_prng.h> #include <AS_02.h> +#include "AS_02_JXS.h" #include "AS_02_ACES.h" #include <PCMParserList.h> #include <Metadata.h> @@ -1177,6 +1178,220 @@ write_JP2K_file(CommandOptions& Options) } + +//------------------------------------------------------------------------------------------ +// JPEG XS essence + +namespace ASDCP { + Result_t JXS_PDesc_to_MD(const ASDCP::JXS::PictureDescriptor& PDesc, + const ASDCP::Dictionary& dict, + ASDCP::MXF::GenericPictureEssenceDescriptor& GenericPictureEssenceDescriptor, + ASDCP::MXF::JPEGXSPictureSubDescriptor& EssenceSubDescriptor); + + Result_t PCM_ADesc_to_MD(ASDCP::PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj); +} + +// Write one or more plaintext JPEG XS codestreams to a plaintext AS-02 file +// Write one or more plaintext JPEG XS codestreams to a ciphertext AS-02 file +// +Result_t +write_JXS_file(CommandOptions& Options) +{ + AESEncContext* Context = 0; + HMACContext* HMAC = 0; + AS_02::JXS::MXFWriter Writer; + JXS::FrameBuffer FrameBuffer(Options.fb_size); + JXS::SequenceParser Parser; + ASDCP::MXF::FileDescriptor *essence_descriptor = 0; + ASDCP::MXF::InterchangeObject_list_t essence_sub_descriptors; + + // set up essence parser + Result_t result = Parser.OpenRead(Options.filenames.front().c_str()); + + // set up MXF writer + if ( ASDCP_SUCCESS(result) ) + { + ASDCP::JXS::PictureDescriptor PDesc; + Parser.FillPictureDescriptor(PDesc); + PDesc.EditRate = Options.edit_rate; + + if ( Options.verbose_flag ) + { + fprintf(stderr, "JPEG XS pictures\n"); + fputs("PictureDescriptor:\n", stderr); + fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size); + JXS::PictureDescriptorDump(PDesc); + } + + if ( Options.use_cdci_descriptor ) + { + ASDCP::MXF::CDCIEssenceDescriptor* tmp_dscr = new ASDCP::MXF::CDCIEssenceDescriptor(g_dict); + essence_sub_descriptors.push_back(new ASDCP::MXF::JPEGXSPictureSubDescriptor(g_dict)); + + result = ASDCP::JXS_PDesc_to_MD(PDesc, *g_dict, + *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr), + *static_cast<ASDCP::MXF::JPEGXSPictureSubDescriptor*>(essence_sub_descriptors.back())); + + if ( ASDCP_SUCCESS(result) ) + { + tmp_dscr->CodingEquations = Options.coding_equations; + tmp_dscr->TransferCharacteristic = Options.transfer_characteristic; + tmp_dscr->ColorPrimaries = Options.color_primaries; + tmp_dscr->PictureEssenceCoding = Options.picture_coding; + tmp_dscr->HorizontalSubsampling = Options.horizontal_subsampling; + tmp_dscr->VerticalSubsampling = Options.vertical_subsampling; + tmp_dscr->ComponentDepth = Options.component_depth; + tmp_dscr->FrameLayout = Options.frame_layout; + tmp_dscr->AspectRatio = Options.aspect_ratio; + tmp_dscr->FieldDominance = Options.field_dominance; + tmp_dscr->WhiteReflevel = Options.cdci_WhiteRefLevel; + tmp_dscr->BlackRefLevel = Options.cdci_BlackRefLevel; + tmp_dscr->ColorRange = Options.cdci_ColorRange; + if (Options.line_map_flag) tmp_dscr->VideoLineMap = Options.line_map; + + if ( Options.md_min_luminance || Options.md_max_luminance ) + { + tmp_dscr->MasteringDisplayMinimumLuminance = Options.md_min_luminance; + tmp_dscr->MasteringDisplayMaximumLuminance = Options.md_max_luminance; + } + + if ( Options.md_primaries.HasValue() ) + { + tmp_dscr->MasteringDisplayPrimaries = Options.md_primaries; + tmp_dscr->MasteringDisplayWhitePointChromaticity = Options.md_white_point; + } + + 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::JPEGXSPictureSubDescriptor(g_dict)); + + result = ASDCP::JXS_PDesc_to_MD(PDesc, *g_dict, + *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr), + *static_cast<ASDCP::MXF::JPEGXSPictureSubDescriptor*>(essence_sub_descriptors.back())); + + if ( ASDCP_SUCCESS(result) ) + { + tmp_dscr->CodingEquations = Options.coding_equations; + tmp_dscr->TransferCharacteristic = Options.transfer_characteristic; + tmp_dscr->ColorPrimaries = Options.color_primaries; + tmp_dscr->ScanningDirection = 0; + tmp_dscr->PictureEssenceCoding = Options.picture_coding; + tmp_dscr->ComponentMaxRef = Options.rgba_MaxRef; + tmp_dscr->ComponentMinRef = Options.rgba_MinRef; + if (Options.line_map_flag) tmp_dscr->VideoLineMap = Options.line_map; + + if ( Options.md_min_luminance || Options.md_max_luminance ) + { + tmp_dscr->MasteringDisplayMinimumLuminance = Options.md_min_luminance; + tmp_dscr->MasteringDisplayMaximumLuminance = Options.md_max_luminance; + } + + if ( Options.md_primaries.HasValue() ) + { + tmp_dscr->MasteringDisplayPrimaries = Options.md_primaries; + tmp_dscr->MasteringDisplayWhitePointChromaticity = Options.md_white_point; + } + + essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr); + } + } + } + + if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag ) + { + WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here + Info.LabelSetType = LS_MXF_SMPTE; + + if ( Options.asset_id_flag ) + memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen); + else + Kumu::GenRandomUUID(Info.AssetUUID); + +#ifdef HAVE_OPENSSL + // configure encryption + if( Options.key_flag ) + { + byte_t IV_buf[CBC_BLOCK_SIZE]; + Kumu::FortunaRNG RNG; + Kumu::GenRandomUUID(Info.ContextID); + Info.EncryptedEssence = true; + + if ( Options.key_id_flag ) + { + memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen); + } + else + { + create_random_uuid(Info.CryptographicKeyID); + } + + 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); + } + } +#endif // HAVE_OPENSSL + + if ( ASDCP_SUCCESS(result) ) + { + 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); + } + } + + if ( ASDCP_SUCCESS(result) ) + { + ui32_t duration = 0; + result = Parser.Reset(); + + while ( ASDCP_SUCCESS(result) && duration++ < Options.duration ) + { + result = Parser.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, 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; +} + //------------------------------------------------------------------------------------------ // ACES essence @@ -1983,6 +2198,9 @@ main(int argc, const char** argv) result = write_JP2K_file(Options); break; // PB + case ESS_JPEG_XS: + result = write_JXS_file(Options); + break; case ::ESS_AS02_ACES: result = write_ACES_file(Options); break; |
