summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Richter <thomas.richter@iis.fraunhofer.de>2021-05-28 12:43:29 +0200
committerThomas Richter <thomas.richter@iis.fraunhofer.de>2021-05-28 12:43:29 +0200
commitd1f386db72b5374b11c9df061a5ff2e6e8adc610 (patch)
tree8a010d36b349fcd790fceeacbea5ca5306ccd8fb /src
parentf9d7fbc33aa571c547d916b145712469efd9f4b8 (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.cpp4
-rwxr-xr-xsrc/AS_DCP_MXF.cpp9
-rwxr-xr-xsrc/as-02-wrap.cpp220
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;