summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Richter <thomas.richter@iis.fraunhofer.de>2021-06-25 15:00:37 +0200
committerThomas Richter <thomas.richter@iis.fraunhofer.de>2021-06-25 15:00:37 +0200
commita62423a866d9348a2d9a97337e01b995497a4e05 (patch)
tree10c939c5222b4deb81b32b4e24f1fe5b326a1158 /src
parent7e3380f5eb9c9441c26646415be3ffec4d01b2c0 (diff)
Updated to John's latest branch.
Diffstat (limited to 'src')
-rw-r--r--src/AS_02_JXS.cpp58
-rw-r--r--src/AS_02_JXS.h6
-rw-r--r--src/AS_DCP_JXS.cpp608
-rw-r--r--src/AS_DCP_JXS.h163
-rwxr-xr-xsrc/AS_DCP_MXF.cpp17
-rw-r--r--src/JXS.cpp177
-rw-r--r--src/JXS.h120
-rw-r--r--src/JXS_Codestream_Parser.cpp79
-rw-r--r--src/JXS_Sequence_Parser.cpp29
-rw-r--r--src/Makefile.am9
-rw-r--r--src/as-02-info.cpp174
-rwxr-xr-xsrc/as-02-unwrap.cpp158
-rwxr-xr-xsrc/as-02-wrap.cpp259
13 files changed, 471 insertions, 1386 deletions
diff --git a/src/AS_02_JXS.cpp b/src/AS_02_JXS.cpp
index eb43b32..53a1e01 100644
--- a/src/AS_02_JXS.cpp
+++ b/src/AS_02_JXS.cpp
@@ -33,7 +33,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "AS_02_internal.h"
-#include "AS_DCP_JXS.h"
+#include "JXS.h"
#include <iostream>
#include <iomanip>
@@ -312,8 +312,9 @@ public:
virtual ~h__Writer(){}
- Result_t OpenWrite(const std::string&, ASDCP::MXF::FileDescriptor* essence_descriptor,
- ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
+ Result_t OpenWrite(const std::string&,
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_sub_descriptor,
const AS_02::IndexStrategy_t& IndexStrategy,
const ui32_t& PartitionSpace, const ui32_t& HeaderSize);
Result_t SetSourceStream(const std::string& label, const ASDCP::Rational& edit_rate);
@@ -326,10 +327,10 @@ public:
// the operation cannot be completed.
Result_t
AS_02::JXS::MXFWriter::h__Writer::OpenWrite(const std::string& filename,
- ASDCP::MXF::FileDescriptor* essence_descriptor,
- ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
- const AS_02::IndexStrategy_t& IndexStrategy,
- const ui32_t& PartitionSpace_sec, const ui32_t& HeaderSize)
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_sub_descriptor,
+ const AS_02::IndexStrategy_t& IndexStrategy,
+ const ui32_t& PartitionSpace_sec, const ui32_t& HeaderSize)
{
if ( ! m_State.Test_BEGIN() )
{
@@ -351,30 +352,23 @@ AS_02::JXS::MXFWriter::h__Writer::OpenWrite(const std::string& filename,
m_PartitionSpace = PartitionSpace_sec; // later converted to edit units by SetSourceStream()
m_HeaderSize = HeaderSize;
- if ( essence_descriptor->GetUL() != UL(m_Dict->ul(MDD_RGBAEssenceDescriptor))
- && essence_descriptor->GetUL() != UL(m_Dict->ul(MDD_CDCIEssenceDescriptor)) )
+ if ( picture_descriptor.GetUL() != UL(m_Dict->ul(MDD_RGBAEssenceDescriptor))
+ && picture_descriptor.GetUL() != UL(m_Dict->ul(MDD_CDCIEssenceDescriptor)) )
{
DefaultLogSink().Error("Essence descriptor is not a RGBAEssenceDescriptor or CDCIEssenceDescriptor.\n");
- essence_descriptor->Dump();
+ picture_descriptor.Dump();
return RESULT_AS02_FORMAT;
}
- m_EssenceDescriptor = essence_descriptor;
+ m_EssenceDescriptor = new ASDCP::MXF::GenericPictureEssenceDescriptor(m_Dict);
+ m_EssenceDescriptor->Copy(picture_descriptor);
- ASDCP::MXF::InterchangeObject_list_t::iterator i;
- for ( i = essence_sub_descriptor_list.begin(); i != essence_sub_descriptor_list.end(); ++i )
- {
- if ( (*i)->GetUL() != UL(m_Dict->ul(MDD_JPEGXSPictureSubDescriptor)) )
- {
- DefaultLogSink().Error("Essence sub-descriptor is not a JPEGXSPictureSubDescriptor.\n");
- (*i)->Dump();
- }
+ ASDCP::MXF::JPEGXSPictureSubDescriptor *jxs_subdesc = new ASDCP::MXF::JPEGXSPictureSubDescriptor(m_Dict);
+ jxs_subdesc->Copy(jxs_sub_descriptor);
- m_EssenceSubDescriptorList.push_back(*i);
- GenRandomValue((*i)->InstanceUID);
- m_EssenceDescriptor->SubDescriptors.push_back((*i)->InstanceUID);
- *i = 0; // parent will only free the ones we don't keep
- }
+ m_EssenceSubDescriptorList.push_back(jxs_subdesc);
+ GenRandomValue(jxs_subdesc->InstanceUID);
+ m_EssenceDescriptor->SubDescriptors.push_back(jxs_subdesc->InstanceUID);
result = m_State.Goto_INIT();
}
@@ -523,21 +517,15 @@ AS_02::JXS::MXFWriter::RIP()
// the operation cannot be completed.
Result_t
AS_02::JXS::MXFWriter::OpenWrite(const std::string& filename, const ASDCP::WriterInfo& Info,
- ASDCP::MXF::FileDescriptor* essence_descriptor,
- ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
- const ASDCP::Rational& edit_rate, const ui32_t& header_size,
- const IndexStrategy_t& strategy, const ui32_t& partition_space)
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_sub_descriptor,
+ const ASDCP::Rational& edit_rate, const ui32_t& header_size,
+ const IndexStrategy_t& strategy, const ui32_t& partition_space)
{
- if ( essence_descriptor == 0 )
- {
- DefaultLogSink().Error("Essence descriptor object required.\n");
- return RESULT_PARAM;
- }
-
m_Writer = new AS_02::JXS::MXFWriter::h__Writer(&DefaultSMPTEDict());
m_Writer->m_Info = Info;
- Result_t result = m_Writer->OpenWrite(filename, essence_descriptor, essence_sub_descriptor_list,
+ Result_t result = m_Writer->OpenWrite(filename, picture_descriptor, jxs_sub_descriptor,
strategy, partition_space, header_size);
if ( KM_SUCCESS(result) )
diff --git a/src/AS_02_JXS.h b/src/AS_02_JXS.h
index 1fef4f1..06b4145 100644
--- a/src/AS_02_JXS.h
+++ b/src/AS_02_JXS.h
@@ -49,7 +49,7 @@ NOTE: ciphertext support for clip-wrapped PCM is not yet complete.
#include "Metadata.h"
#include "AS_02.h"
-#include "AS_DCP_JXS.h"
+#include "JXS.h"
namespace AS_02
{
@@ -77,8 +77,8 @@ namespace AS_02
// the operation cannot be completed or if nonsensical data is discovered
// in the essence descriptor.
Result_t OpenWrite(const std::string& filename, const ASDCP::WriterInfo&,
- ASDCP::MXF::FileDescriptor* essence_descriptor,
- ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_sub_descriptor,
const ASDCP::Rational& edit_rate, const ui32_t& header_size = 16384,
const IndexStrategy_t& strategy = IS_FOLLOW, const ui32_t& partition_space = 10);
diff --git a/src/AS_DCP_JXS.cpp b/src/AS_DCP_JXS.cpp
index bf4dbe6..5fec863 100644
--- a/src/AS_DCP_JXS.cpp
+++ b/src/AS_DCP_JXS.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2004-2016, John Hurst,
+Copyright (c) 2004-2021, John Hurst,
Copyright (c) 2020, Thomas Richter Fraunhofer IIS
All rights reserved.
@@ -39,451 +39,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace ASDCP::JXS;
using Kumu::GenRandomValue;
-//------------------------------------------------------------------------------------------
-
static std::string JXS_PACKAGE_LABEL = "File Package: SMPTE 2124 frame wrapping of JPEG XS codestreams";
//static std::string JP2K_S_PACKAGE_LABEL = "File Package: SMPTE 429-10 frame wrapping of stereoscopic JPEG XS codestreams";
static std::string PICT_DEF_LABEL = "Picture Track";
-static int s_exp_lookup[16] = { 0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,2048, 4096, 8192, 16384, 32768 };
-
-//
-std::ostream&
-ASDCP::JXS::operator << (std::ostream& strm, const PictureDescriptor& PDesc)
-{
- strm << " AspectRatio: " << PDesc.AspectRatio.Numerator << "/" << PDesc.AspectRatio.Denominator << std::endl;
- strm << " EditRate: " << PDesc.EditRate.Numerator << "/" << PDesc.EditRate.Denominator << std::endl;
- strm << " SampleRate: " << PDesc.SampleRate.Numerator << "/" << PDesc.SampleRate.Denominator << std::endl;
- strm << " StoredWidth: " << (unsigned) PDesc.StoredWidth << std::endl;
- strm << " StoredHeight: " << (unsigned) PDesc.StoredHeight << std::endl;
- strm << " Wf: " << (unsigned) PDesc.Wf << std::endl; // width of the frame
- strm << " Hf: " << (unsigned) PDesc.Hf << std::endl; // height of the frame
- strm << " ContainerDuration: " << (unsigned) PDesc.ContainerDuration << std::endl;
-
- strm << "-- JPEG XS Metadata --" << std::endl;
- strm << " ImageComponents:" << std::endl;
- strm << " bits h-sep v-sep" << std::endl;
-
- ui32_t i;
- for ( i = 0; i < PDesc.Nc && i < MaxComponents; ++i )
- {
- strm << " " << std::setw(4) << PDesc.ImageComponents[i].Bc
- << " " << std::setw(5) << PDesc.ImageComponents[i].Sx
- << " " << std::setw(5) << PDesc.ImageComponents[i].Sy
- << std::endl;
- }
-
- strm << " Slice height: " << (short) PDesc.Hsl << std::endl;
- strm << " Profile: " << (short) PDesc.Ppih << std::endl;
- strm << " Level: " << (short) (PDesc.Plev >> 8) << std::endl;
- strm << " Sublevel: " << (short) (PDesc.Plev & 0xff) << std::endl;
- strm << " Column Width: " << (short) (PDesc.Cw) << std::endl;
- strm << " Maximum Bit Rate: " << (PDesc.MaximumBitRate) << std::endl;
- strm << " Primaries: " << (short) (PDesc.Primaries) << std::endl;
- strm << " Transfer Curve: " << (short) (PDesc.TransferCurve) << std::endl;
- strm << " Matrix: " << (short) (PDesc.Matrix) << std::endl;
- strm << " full range: " << (PDesc.fullRange?("yes"):("no")) << std::endl;
- /*
- ** thor: at this point, do not print the CAP marker
- */
-
- return strm;
-}
-
-//
-void
-ASDCP::JXS::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream)
-{
- if ( stream == 0 )
- stream = stderr;
-
- fprintf(stream, "\
- AspectRatio: %d/%d\n\
- EditRate: %d/%d\n\
- SampleRate: %d/%d\n\
- StoredWidth: %u\n\
- StoredHeight: %u\n\
- Wf: %u\n\
- Hf: %u\n\
- Profile: %u\n\
- Level: %u\n\
- Sublevel: %u\n\
- Maximum BitRate: %u\n\
- ContainerDuration: %u\n\
- Primaries: %u\n\
- Transfer Curve: %u\n\
- Matrix: %u\n\
- full range: %s\n",
- PDesc.AspectRatio.Numerator, PDesc.AspectRatio.Denominator,
- PDesc.EditRate.Numerator, PDesc.EditRate.Denominator,
- PDesc.SampleRate.Numerator, PDesc.SampleRate.Denominator,
- PDesc.StoredWidth,
- PDesc.StoredHeight,
- PDesc.Wf,
- PDesc.Hf,
- PDesc.Ppih,
- PDesc.Plev >> 4,
- PDesc.Plev & 0x0f,
- PDesc.MaximumBitRate,
- PDesc.ContainerDuration,
- PDesc.Primaries,
- PDesc.TransferCurve,
- PDesc.Matrix,
- PDesc.fullRange?("yes"):("no")
- );
-
- fprintf(stream, "-- JPEG XS Metadata --\n");
- fprintf(stream, " ImageComponents:\n");
- fprintf(stream, " bits h-sep v-sep\n");
-
- ui32_t i;
- for ( i = 0; i < PDesc.Nc && i < MaxComponents; i++ )
- {
- fprintf(stream, " %4d %5d %5d\n",
- PDesc.ImageComponents[i].Bc,
- PDesc.ImageComponents[i].Sx,
- PDesc.ImageComponents[i].Sy
- );
- }
-}
-
-//
-ASDCP::Result_t
-ASDCP::JXS_PDesc_to_MD(const JXS::PictureDescriptor& PDesc,
- const ASDCP::Dictionary&dict,
- ASDCP::MXF::GenericPictureEssenceDescriptor& EssenceDescriptor,
- ASDCP::MXF::JPEGXSPictureSubDescriptor& EssenceSubDescriptor)
-{
- EssenceDescriptor.ContainerDuration = PDesc.ContainerDuration;
- EssenceDescriptor.SampleRate = PDesc.EditRate;
- EssenceDescriptor.FrameLayout = 0;
- EssenceDescriptor.StoredWidth = PDesc.StoredWidth;
- EssenceDescriptor.StoredHeight = PDesc.StoredHeight;
- EssenceDescriptor.AspectRatio = PDesc.AspectRatio;
-
- EssenceSubDescriptor.JPEGXSPpih = PDesc.Ppih;
- EssenceSubDescriptor.JPEGXSPlev = PDesc.Plev;
- EssenceSubDescriptor.JPEGXSWf = PDesc.Wf;
- EssenceSubDescriptor.JPEGXSHf = PDesc.Hf;
- EssenceSubDescriptor.JPEGXSNc = PDesc.Nc;
-
- // Copy the value of the columns, but only if there are some
- if (PDesc.Cw) {
- EssenceSubDescriptor.JPEGXSCw = optional_property<ui16_t>(PDesc.Cw);
- } else {
- EssenceSubDescriptor.JPEGXSCw.set_has_value(false);
- }
-
- // Copy the slice height. Actually, this is optional
- // and does not necessarily require copying all the time,
- // but let's copy it nevertheless.
- EssenceSubDescriptor.JPEGXSHsl = optional_property<ui16_t>(PDesc.Hsl);
-
- if (PDesc.MaximumBitRate) {
- EssenceSubDescriptor.JPEGXSMaximumBitRate = PDesc.MaximumBitRate;
- } else {
- EssenceSubDescriptor.JPEGXSMaximumBitRate.set_has_value(false);
- }
-
- const ui32_t cdt_buffer_len = 8 * 2; // at most 8 components.
- byte_t tmp_buffer[cdt_buffer_len];
- int i,comps = (PDesc.Nc > 8)?8:PDesc.Nc;
- EssenceSubDescriptor.JPEGXSComponentTable.Length(4 + (comps << 1));
- // thor: unclear whether the marker size is part of this data.
- tmp_buffer[0] = 0xff;
- tmp_buffer[1] = 0x13; // the marker
- tmp_buffer[2] = 0x00;
- tmp_buffer[3] = comps * 2 + 2; // The size.
- for(i = 0;i < comps;i++) {
- tmp_buffer[4 + (i << 1)] = PDesc.ImageComponents[i].Bc;
- tmp_buffer[5 + (i << 1)] = (PDesc.ImageComponents[i].Sx << 4) | (PDesc.ImageComponents[i].Sy);
- }
-
- memcpy(EssenceSubDescriptor.JPEGXSComponentTable.Data(), tmp_buffer, 4 + (comps << 1));
-
- //
- 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;
- case 5:
- EssenceDescriptor.ColorPrimaries = dict.ul(ASDCP::MDD_ColorPrimaries_ITU470_PAL);
- break;
- case 6:
- EssenceDescriptor.ColorPrimaries = dict.ul(ASDCP::MDD_ColorPrimaries_SMPTE170M);
- break;
- case 9:
- EssenceDescriptor.ColorPrimaries = dict.ul(ASDCP::MDD_ColorPrimaries_ITU2020);
- break;
- case 10:
- EssenceDescriptor.ColorPrimaries = dict.ul(ASDCP::MDD_ColorPrimaries_SMPTE_DCDM);
- break;
- case 11:
- EssenceDescriptor.ColorPrimaries = dict.ul(ASDCP::MDD_TheatricalViewingEnvironment);
- break;
- case 12:
- EssenceDescriptor.ColorPrimaries = dict.ul(ASDCP::MDD_ColorPrimaries_P3D65);
- break;
- default:
- return RESULT_PARAM;
- break;
- }
-
- 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);
- break;
- case 5: // Display Gamma 2.8, BT.470-6 This does not seem to be supported
- case 9: // Log(100:1) range This does not seem to be supported
- case 10:// Log(100*Sqrt(10):1 range)
- return Kumu::RESULT_NOTIMPL;
- break;
- case 8:
- EssenceDescriptor.TransferCharacteristic = dict.ul(ASDCP::MDD_TransferCharacteristic_linear);
- break;
- case 11:
- EssenceDescriptor.TransferCharacteristic = dict.ul(ASDCP::MDD_TransferCharacteristic_IEC6196624_xvYCC);
- break;
- case 13:
- EssenceDescriptor.TransferCharacteristic = dict.ul(ASDCP::MDD_TransferCharacteristic_sRGB);
- break;
- case 14:
- case 15:
- EssenceDescriptor.TransferCharacteristic = dict.ul(ASDCP::MDD_TransferCharacteristic_ITU2020);
- break;
- case 16:
- EssenceDescriptor.TransferCharacteristic = dict.ul(ASDCP::MDD_TransferCharacteristic_SMPTEST2084);
- break;
- case 17:
- EssenceDescriptor.TransferCharacteristic = dict.ul(ASDCP::MDD_TransferCharacteristic_ST428);
- break;
- case 18: // HLG
- EssenceDescriptor.TransferCharacteristic = dict.ul(ASDCP::MDD_TransferCharacteristic_HLG);
- break;
- case 12: // Rec. BT.1361
- EssenceDescriptor.TransferCharacteristic = dict.ul(ASDCP::MDD_TransferCharacteristic_BT1361);
- break;
- case 4: // Rec. BT.470
- EssenceDescriptor.TransferCharacteristic = dict.ul(ASDCP::MDD_TransferCharacteristic_BT470);
- break;
- case 7: // SMPTE 240M
- EssenceDescriptor.TransferCharacteristic = dict.ul(ASDCP::MDD_TransferCharacteristic_ST240M);
- break;
- case 2: // Unspecified. This leaves the data intentionally undefined.
- EssenceDescriptor.TransferCharacteristic.set_has_value(false);
- break;
- default:
- return RESULT_PARAM;
- break;
- }
- //
- switch(PDesc.Matrix) {
- case 0: // Identity matrix. Use the BGR coding equations.
- EssenceDescriptor.CodingEquations = dict.ul(ASDCP::MDD_CodingEquations_BGR);
- break;
- case 4: // Title 47.
- case 10: // ITU 2020 constant luminance? Does not seem to be supported
- case 11: // SMPTE ST-2085
- return Kumu::RESULT_NOTIMPL;
- case 1:
- EssenceDescriptor.CodingEquations = dict.ul(ASDCP::MDD_CodingEquations_709);
- break;
- // Note: Matrix=2 does not set the optional parameter. This is intentional.
- case 5:
- case 6:
- EssenceDescriptor.CodingEquations = dict.ul(ASDCP::MDD_CodingEquations_601);
- break;
- case 9: // ITU 2020 non-constant luminance?
- EssenceDescriptor.CodingEquations = dict.ul(ASDCP::MDD_CodingEquations_Rec2020);
- break;
- case 2: // This is unspecified. The metadata item remains undefined on purpose.
- EssenceDescriptor.CodingEquations.set_has_value(false);
- break;
- case 7: // ST 240M
- EssenceDescriptor.CodingEquations = dict.ul(ASDCP::MDD_CodingEquations_ST240M);
- break;
- case 8: // YCgCo
- EssenceDescriptor.CodingEquations = dict.ul(ASDCP::MDD_CodingEquations_YCGCO);
- break;
- default:
- return RESULT_PARAM;
- break;
- }
- //
-#if 0
- if (rgba) {
- byte_t layout[ASDCP::MXF::RGBAValueLength];
- if (m_bFullRange) {
- rgba->ComponentMaxRef = (1UL << m_ucPrecision) - 1;
- rgba->ComponentMinRef = 0;
- } else {
- rgba->ComponentMaxRef = 235 * (1UL << (m_ucPrecision - 8));
- rgba->ComponentMinRef = 16 * (1UL << (m_ucPrecision - 8));
- }
- layout[0] = 'R';
- layout[1] = m_ucPrecision;
- layout[2] = 'G';
- layout[3] = m_ucPrecision;
- layout[4] = 'B';
- layout[5] = m_ucPrecision;
- layout[6] = 0;
-#endif
- return RESULT_OK;
-}
-
-//
-ASDCP::Result_t
-ASDCP::MD_to_JXS_PDesc(const ASDCP::MXF::GenericPictureEssenceDescriptor& EssenceDescriptor,
- const ASDCP::MXF::JPEGXSPictureSubDescriptor& EssenceSubDescriptor,
- const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
- ASDCP::JXS::PictureDescriptor& PDesc)
-{
- const Dictionary *dict = &ASDCP::DefaultSMPTEDict();
- const ASDCP::MXF::RGBAEssenceDescriptor *rgba = dynamic_cast<const ASDCP::MXF::RGBAEssenceDescriptor *>(&EssenceDescriptor);
- const ASDCP::MXF::CDCIEssenceDescriptor *cdci = dynamic_cast<const ASDCP::MXF::CDCIEssenceDescriptor *>(&EssenceDescriptor);
- memset(&PDesc, 0, sizeof(PDesc));
-
- PDesc.EditRate = EditRate;
- PDesc.SampleRate = SampleRate;
- assert(EssenceDescriptor.ContainerDuration.const_get() <= 0xFFFFFFFFL);
- PDesc.ContainerDuration = static_cast<ui32_t>(EssenceDescriptor.ContainerDuration.const_get());
- PDesc.StoredWidth = EssenceDescriptor.StoredWidth;
- PDesc.StoredHeight = EssenceDescriptor.StoredHeight;
- PDesc.AspectRatio = EssenceDescriptor.AspectRatio;
-
- PDesc.Ppih = EssenceSubDescriptor.JPEGXSPpih;
- PDesc.Plev = EssenceSubDescriptor.JPEGXSPlev;
- PDesc.Wf = EssenceSubDescriptor.JPEGXSWf;
- PDesc.Hf = EssenceSubDescriptor.JPEGXSHf;
- PDesc.Nc = EssenceSubDescriptor.JPEGXSNc;
-
- if (EssenceDescriptor.ColorPrimaries.empty()) {
- PDesc.Primaries = 1; // If not set, let us assume 709 primaries. Yuck!
- } else if (EssenceDescriptor.ColorPrimaries == dict->ul(ASDCP::MDD_ColorPrimaries_ITU709)) {
- PDesc.Primaries = 1;
- } else if (EssenceDescriptor.ColorPrimaries == dict->ul(ASDCP::MDD_ColorPrimaries_ITU470_PAL)) {
- PDesc.Primaries = 5;
- } else if (EssenceDescriptor.ColorPrimaries == dict->ul(ASDCP::MDD_ColorPrimaries_SMPTE170M)) {
- PDesc.Primaries = 6;
- } else if (EssenceDescriptor.ColorPrimaries == dict->ul(ASDCP::MDD_ColorPrimaries_ITU2020)) {
- PDesc.Primaries = 9;
- } else if (EssenceDescriptor.ColorPrimaries == dict->ul(ASDCP::MDD_ColorPrimaries_SMPTE_DCDM)) {
- PDesc.Primaries = 10;
- } else if (EssenceDescriptor.ColorPrimaries == dict->ul(ASDCP::MDD_TheatricalViewingEnvironment)) {
- PDesc.Primaries = 11;
- } else if (EssenceDescriptor.ColorPrimaries == dict->ul(ASDCP::MDD_ColorPrimaries_P3D65)) {
- PDesc.Primaries = 12;
- } else {
- PDesc.Primaries = 0;
- }
-
- if (EssenceDescriptor.TransferCharacteristic.empty()) {
- PDesc.TransferCurve = 2; // Unspecified
- } else if (EssenceDescriptor.TransferCharacteristic == dict->ul(ASDCP::MDD_TransferCharacteristic_ITU709)) {
- PDesc.TransferCurve = 1;
- } else if (EssenceDescriptor.TransferCharacteristic == dict->ul(ASDCP::MDD_TransferCharacteristic_linear)) {
- PDesc.TransferCurve = 8;
- } else if (EssenceDescriptor.TransferCharacteristic == dict->ul(ASDCP::MDD_TransferCharacteristic_IEC6196624_xvYCC)) {
- PDesc.TransferCurve = 11;
- } else if (EssenceDescriptor.TransferCharacteristic == dict->ul(ASDCP::MDD_TransferCharacteristic_sRGB)) {
- PDesc.TransferCurve = 13;
- } else if (EssenceDescriptor.TransferCharacteristic == dict->ul(ASDCP::MDD_TransferCharacteristic_SMPTEST2084)) {
- PDesc.TransferCurve = 16;
- } else if (EssenceDescriptor.TransferCharacteristic == dict->ul(ASDCP::MDD_TransferCharacteristic_ST428)) {
- PDesc.TransferCurve = 17;
- } else if (EssenceDescriptor.TransferCharacteristic == dict->ul(ASDCP::MDD_TransferCharacteristic_HLG)) {
- PDesc.TransferCurve = 18;
- } else if (EssenceDescriptor.TransferCharacteristic == dict->ul(ASDCP::MDD_TransferCharacteristic_BT1361)) {
- PDesc.TransferCurve = 12;
- } else if (EssenceDescriptor.TransferCharacteristic == dict->ul(ASDCP::MDD_TransferCharacteristic_BT470)) {
- PDesc.TransferCurve = 4;
- } else if (EssenceDescriptor.TransferCharacteristic == dict->ul(ASDCP::MDD_TransferCharacteristic_ST240M)) {
- PDesc.TransferCurve = 7;
- } else {
- PDesc.TransferCurve = 0;
- }
-
- if (EssenceDescriptor.CodingEquations.empty()) {
- PDesc.Matrix = 2;
- } else if (EssenceDescriptor.CodingEquations == dict->ul(ASDCP::MDD_CodingEquations_BGR)) {
- PDesc.Matrix = 0;
- } else if (EssenceDescriptor.CodingEquations == dict->ul(ASDCP::MDD_CodingEquations_709)) {
- PDesc.Matrix = 1;
- } else if (EssenceDescriptor.CodingEquations == dict->ul(ASDCP::MDD_CodingEquations_601)) {
- PDesc.Matrix = 5;
- } else if (EssenceDescriptor.CodingEquations == dict->ul(ASDCP::MDD_CodingEquations_Rec2020)) {
- PDesc.Matrix = 9;
- } else if (EssenceDescriptor.CodingEquations == dict->ul(ASDCP::MDD_CodingEquations_ST240M)) {
- PDesc.Matrix = 7;
- } else if (EssenceDescriptor.CodingEquations == dict->ul(ASDCP::MDD_CodingEquations_YCGCO)) {
- PDesc.Matrix = 8;
- } else {
- PDesc.Matrix = 0;
- }
-
- if (EssenceSubDescriptor.JPEGXSCw.const_get()==0 || EssenceSubDescriptor.JPEGXSCw.const_get() == 0)
- PDesc.Cw = 0;
- else
- PDesc.Cw = static_cast<ui16_t>(EssenceSubDescriptor.JPEGXSCw.const_get());
-
- PDesc.Hsl = static_cast<ui16_t>(EssenceSubDescriptor.JPEGXSHsl.const_get());
-
- PDesc.MaximumBitRate = static_cast<ui32_t>(EssenceSubDescriptor.JPEGXSMaximumBitRate.const_get());
-
- // JPEGXSComponentTable
- ui32_t tmp_size = EssenceSubDescriptor.JPEGXSComponentTable.Length();
-
- if (tmp_size > 4 && (tmp_size & 1) == 0 && (PDesc.Nc << 1) + 4 == tmp_size) {
- const byte_t *data = EssenceSubDescriptor.JPEGXSComponentTable.RoData() + 4;
- for(int i = 0;i < PDesc.Nc;i++) {
- PDesc.ImageComponents[i].Bc = data[0];
- PDesc.ImageComponents[i].Sy = data[1] >> 4;
- PDesc.ImageComponents[i].Sx = data[1] & 0x0f;
- data += 2;
- }
- } else {
- return RESULT_FAIL;
- }
-
- if (rgba) {
- if (rgba->ComponentMinRef.empty()) {
- if (rgba->ComponentMaxRef.empty()) {
- PDesc.fullRange = false;
- } else if (rgba->ComponentMaxRef == (1UL << PDesc.ImageComponents[0].Bc) - 1) {
- PDesc.fullRange = true;
- } else {
- PDesc.fullRange = false;
- }
- } else if (rgba->ComponentMinRef == 0) {
- PDesc.fullRange = true;
- } else {
- PDesc.fullRange = false;
- }
- } else if (cdci) {
- if (cdci->BlackRefLevel.empty()) {
- if (cdci->WhiteReflevel.empty()) {
- PDesc.fullRange = false;
- } else if (cdci->WhiteReflevel == (1UL << PDesc.ImageComponents[0].Bc) - 1) {
- PDesc.fullRange = true;
- } else {
- PDesc.fullRange = false;
- }
- } else if (cdci->BlackRefLevel == 0) {
- PDesc.fullRange = true;
- } else {
- PDesc.fullRange = false;
- }
- } else {
- PDesc.fullRange = false;
- }
-
- return RESULT_OK;
-}
//------------------------------------------------------------------------------------------
@@ -502,7 +61,6 @@ class ih__Reader : public ASDCP::h__ASDCPReader
ASDCP_NO_COPY_CONSTRUCT(ih__Reader);
public:
- PictureDescriptor m_PDesc; // codestream parameter list
ih__Reader(const Dictionary *d) :
ASDCP::h__ASDCPReader(d), m_EssenceDescriptor(0), m_EssenceSubDescriptor(0), m_Format(ESS_UNKNOWN) {}
@@ -674,8 +232,6 @@ ih__Reader::OpenRead(const std::string& filename, EssenceType_t type)
DefaultLogSink().Error("'type' argument unexpected: %x\n", type);
return RESULT_STATE;
}
-
- result = MD_to_JXS_PDesc(*m_EssenceDescriptor, *m_EssenceSubDescriptor, m_EditRate, m_SampleRate, m_PDesc);
}
return result;
@@ -715,26 +271,6 @@ public:
};
-
-//------------------------------------------------------------------------------------------
-
-
-//
-void
-ASDCP::JXS::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const
-{
- if ( stream == 0 )
- stream = stderr;
-
- fprintf(stream, "Frame: %06u, %7u bytes", m_FrameNumber, m_Size);
-
- fputc('\n', stream);
-
- if ( dump_len > 0 )
- Kumu::hexdump(m_Data, dump_len, stream);
-}
-
-
//------------------------------------------------------------------------------------------
ASDCP::JXS::MXFReader::MXFReader()
@@ -833,21 +369,6 @@ ASDCP::JXS::MXFReader::LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset,
// Fill the struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
ASDCP::Result_t
-ASDCP::JXS::MXFReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
-{
- if ( m_Reader && m_Reader->m_File.IsOpen() )
- {
- PDesc = m_Reader->m_PDesc;
- return RESULT_OK;
- }
-
- return RESULT_INIT;
-}
-
-
-// Fill the struct with the values from the file's header.
-// Returns RESULT_INIT if the file is not open.
-ASDCP::Result_t
ASDCP::JXS::MXFReader::FillWriterInfo(WriterInfo& Info) const
{
if ( m_Reader && m_Reader->m_File.IsOpen() )
@@ -901,7 +422,6 @@ class ih__Writer : public ASDCP::h__ASDCPWriter
JPEGXSPictureSubDescriptor* m_EssenceSubDescriptor;
public:
- PictureDescriptor m_PDesc;
byte_t m_EssenceUL[SMPTE_UL_LENGTH];
ih__Writer(const Dictionary *d) : ASDCP::h__ASDCPWriter(d), m_EssenceSubDescriptor(0) {
@@ -911,8 +431,10 @@ public:
virtual ~ih__Writer(){}
Result_t OpenWrite(const std::string&, EssenceType_t type, ui32_t HeaderSize);
- Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
- ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
+ Result_t SetSourceStream(ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_sub_descriptor,
+ const std::string& label,
+ const ASDCP::Rational& edit_rate);
Result_t WriteFrame(const JXS::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*);
Result_t Finalize();
};
@@ -961,72 +483,87 @@ ih__Writer::OpenWrite(const std::string& filename, EssenceType_t type, ui32_t He
// Automatically sets the MXF file's metadata from the first jpeg codestream stream.
ASDCP::Result_t
-ih__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& label, ASDCP::Rational LocalEditRate)
+ih__Writer::SetSourceStream(
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_sub_descriptor,
+ const std::string& label,
+ const ASDCP::Rational& edit_rate)
{
assert(m_Dict);
if ( ! m_State.Test_INIT() )
return RESULT_STATE;
- if ( LocalEditRate == ASDCP::Rational(0,0) )
- LocalEditRate = PDesc.EditRate;
+ if ( edit_rate == ASDCP::Rational(0,0) )
+ {
+ DefaultLogSink().Error("Edit rate not set before call to ih__Writer::SetSourceStream.\n");
+ return RESULT_PARAM;
+ }
- m_PDesc = PDesc;
- assert(m_Dict);
assert(m_EssenceDescriptor);
+ m_EssenceDescriptor->Copy(picture_descriptor);
+
assert(m_EssenceSubDescriptor);
- Result_t result = JXS_PDesc_to_MD(m_PDesc, *m_Dict,
- *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(m_EssenceDescriptor),
- *m_EssenceSubDescriptor);
+ m_EssenceSubDescriptor->Copy(jxs_sub_descriptor);
- if ( ASDCP_SUCCESS(result) )
- {
- ASDCP::MXF::GenericPictureEssenceDescriptor *gpe = static_cast<ASDCP::MXF::RGBAEssenceDescriptor*>(m_EssenceDescriptor);
- switch(PDesc.Ppih) {
- case 0: // Profile_Unrestricted
- gpe->PictureEssenceCoding.Set(m_Dict->ul(MDD_JPEGXSUnrestrictedCodestream));
- break;
- case 0x1500: // Profile_Light422
- gpe->PictureEssenceCoding.Set(m_Dict->ul(MDD_JPEGXSLight422_10Profile));
- break;
- case 0x1a00: // Profile_Light444
- gpe->PictureEssenceCoding.Set(m_Dict->ul(MDD_JPEGXSLight444_12Profile));
- break;
- case 0x2500: // Profile_LightSubline
- gpe->PictureEssenceCoding.Set(m_Dict->ul(MDD_JPEGXSLightSubline422_10Profile));
- break;
- case 0x3540: // Profile_Main422
- gpe->PictureEssenceCoding.Set(m_Dict->ul(MDD_JPEGXSMain422_10Profile));
- break;
- case 0x3a40: // Profile_Main444
- gpe->PictureEssenceCoding.Set(m_Dict->ul(MDD_JPEGXSMain444_12Profile));
- break;
- case 0x3e40: // Profile_Main4444
- gpe->PictureEssenceCoding.Set(m_Dict->ul(MDD_JPEGXSMain4444_12Profile));
- break;
- case 0x4a40: // Profile_High444
- gpe->PictureEssenceCoding.Set(m_Dict->ul(MDD_JPEGXSHigh444_12Profile));
- break;
- case 0x4e40: // Profile_High4444
- gpe->PictureEssenceCoding.Set(m_Dict->ul(MDD_JPEGXSHigh4444_12Profile));
- break;
- default:
- return RESULT_PARAM;
- }
- memcpy(m_EssenceUL, m_Dict->ul(MDD_JPEGXSEssence), SMPTE_UL_LENGTH);
- m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
- result = m_State.Goto_READY();
- }
+ memcpy(m_EssenceUL, m_Dict->ul(MDD_JPEGXSEssence), SMPTE_UL_LENGTH);
+ m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
+
+ Result_t result = m_State.Goto_READY();
if ( ASDCP_SUCCESS(result) )
{
result = WriteASDCPHeader(label, UL(m_Dict->ul(MDD_MXFGCFUFrameWrappedPictureElement)),
PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_PictureDataDef)),
- LocalEditRate, derive_timecode_rate_from_edit_rate(m_PDesc.EditRate));
+ edit_rate, derive_timecode_rate_from_edit_rate(edit_rate));
}
return result;
}
+//
+bool
+ASDCP::JXS::lookup_PictureEssenceCoding(int value, ASDCP::UL& ul)
+{
+ const ASDCP::Dictionary& dict = DefaultSMPTEDict();
+ switch ( value )
+ {
+ case 0: // Profile_Unrestricted
+ ul = dict.ul(MDD_JPEGXSUnrestrictedCodestream);
+ break;
+ case 0x1500: // Profile_Light422
+ ul = dict.ul(MDD_JPEGXSLight422_10Profile);
+ break;
+ case 0x1a00: // Profile_Light444
+ ul = dict.ul(MDD_JPEGXSLight444_12Profile);
+ break;
+ case 0x2500: // Profile_LightSubline
+ ul = dict.ul(MDD_JPEGXSLightSubline422_10Profile);
+ break;
+ case 0x3540: // Profile_Main422
+ ul = dict.ul(MDD_JPEGXSMain422_10Profile);
+ break;
+ case 0x3a40: // Profile_Main444
+ ul = dict.ul(MDD_JPEGXSMain444_12Profile);
+ break;
+ case 0x3e40: // Profile_Main4444
+ ul = dict.ul(MDD_JPEGXSMain4444_12Profile);
+ break;
+ case 0x4a40: // Profile_High444
+ ul = dict.ul(MDD_JPEGXSHigh444_12Profile);
+ break;
+ case 0x4e40: // Profile_High4444
+ ul = dict.ul(MDD_JPEGXSHigh4444_12Profile);
+ break;
+
+ default:
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+
// 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
@@ -1143,8 +680,11 @@ ASDCP::JXS::MXFWriter::RIP()
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed.
ASDCP::Result_t
-ASDCP::JXS::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info,
- const PictureDescriptor& PDesc, ui32_t HeaderSize)
+ASDCP::JXS::MXFWriter::OpenWrite(
+ const std::string& filename, const WriterInfo& Info,
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_sub_descriptor,
+ const ASDCP::Rational& edit_rate, ui32_t HeaderSize)
{
if ( Info.LabelSetType == LS_MXF_SMPTE )
m_Writer = new h__Writer(&DefaultSMPTEDict());
@@ -1154,9 +694,9 @@ ASDCP::JXS::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo&
m_Writer->m_Info = Info;
Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_XS, HeaderSize);
-
+
if ( ASDCP_SUCCESS(result) )
- result = m_Writer->SetSourceStream(PDesc, JXS_PACKAGE_LABEL);
+ result = m_Writer->SetSourceStream(picture_descriptor, jxs_sub_descriptor, JXS_PACKAGE_LABEL, edit_rate);
if ( ASDCP_FAILURE(result) )
m_Writer.release();
diff --git a/src/AS_DCP_JXS.h b/src/AS_DCP_JXS.h
index dcd98e0..fd334df 100644
--- a/src/AS_DCP_JXS.h
+++ b/src/AS_DCP_JXS.h
@@ -79,16 +79,8 @@ This project depends upon the following libraries:
#ifndef _AS_DCP_JXS_H_
#define _AS_DCP_JXS_H_
-#include <KM_error.h>
-#include <KM_fileio.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <math.h>
-#include <iosfwd>
-#include <string>
-#include <cstring>
-#include <list>
#include "AS_DCP.h"
+#include "JXS.h"
#include "Metadata.h"
//--------------------------------------------------------------------------------
@@ -100,134 +92,7 @@ namespace ASDCP {
//
namespace JXS
{
- const ui32_t MaxComponents = 4; // ISO 21122-1 Annex A.2 up to 8 components
- const ui32_t MaxHorizontalLevels = 15;
- const ui32_t MaxVerticalLevels = 2;
-
-#pragma pack(1)
- struct ImageComponent_t // Essentially, a lookalike of the CDT marker, just with less bit-packing
- {
- ui8_t Bc; // Bitdepth (literal, not -1)
- ui8_t Sx;
- ui8_t Sy; // Subsampling factors, horizontal and vertically. Bit-packed in the marker.
- };
-#pragma pack()
-
- struct PictureDescriptor
- {
- Rational EditRate;
- ui32_t ContainerDuration;
- Rational SampleRate;
- ui32_t StoredWidth;
- ui32_t StoredHeight;
- Rational AspectRatio;
- ui16_t Ppih; // Profile, copy from the PIH marker
- ui16_t Plev; // Level and sublevel, copy from the PIH marker
- ui16_t Wf; // Frame width, copy from the PIH marker
- ui16_t Hf; // Frame height, copy from the PIH marker
- ui16_t Hsl; // slice height, copy from the PIH marker
- ui16_t Cw; // column width, or 0 for no columns, copy from the PIH marker
- ui8_t Nc; // number of components, copy from the PIH marker
- ui32_t MaximumBitRate; // bit rate in MB/sec, or 0 if not known
- ui8_t Primaries; // Color primaries as defined by CICP
- ui8_t TransferCurve; // Transfer curve as defined by CICP
- ui8_t Matrix; // Transform matrix, as defined by CICP
- bool fullRange; // If true, no head and toe region
- ImageComponent_t ImageComponents[MaxComponents]; // These are copies from the CDT (component table)
- };
- // Print debugging information to std::ostream
- std::ostream& operator << (std::ostream& strm, const PictureDescriptor& pdesc);
- // Print debugging information to stream (stderr default)
- void PictureDescriptorDump(const PictureDescriptor&, FILE* = 0);
-
- //
- class FrameBuffer : public ASDCP::FrameBuffer
- {
- public:
- FrameBuffer() {}
- FrameBuffer(ui32_t size) { Capacity(size); }
- virtual ~FrameBuffer() {}
-
- // Print debugging information to stream (stderr default)
- void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
- };
-
-
- // An object which opens and reads a JPEG XS codestream file. The file is expected
- // to contain exactly one complete frame of picture essence as an unwrapped (raw)
- // ISO/IEC 21122 codestream.
- class CodestreamParser
- {
- class h__CodestreamParser;
- mem_ptr<h__CodestreamParser> m_Parser;
- ASDCP_NO_COPY_CONSTRUCT(CodestreamParser);
-
- public:
- CodestreamParser();
- virtual ~CodestreamParser();
-
- // Opens a file for reading, parses enough data to provide a complete
- // set of stream metadata for the MXFWriter below.
- // The frame buffer's PlaintextOffset parameter will be set to the first
- // byte of the data segment. Set this value to zero if you want
- // encrypted headers.
- Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const;
-
- // Fill a PictureDescriptor struct with the values from the file's codestream.
- // Returns RESULT_INIT if the file is not open.
- Result_t FillPictureDescriptor(PictureDescriptor&) const;
- };
-
- // Parses the data in the frame buffer to fill in the picture descriptor. Copies
- // the offset of the image data into start_of_data. Returns error if the parser fails.
- Result_t ParseMetadataIntoDesc(const FrameBuffer&, PictureDescriptor&, byte_t* start_of_data = 0);
-
- // An object which reads a sequence of files containing JPEG XS pictures.
- class SequenceParser
- {
- class h__SequenceParser;
- mem_ptr<h__SequenceParser> m_Parser;
- ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
-
- public:
- SequenceParser();
- virtual ~SequenceParser();
-
- // Opens a directory for reading. The directory is expected to contain one or
- // more files, each containing the codestream for exactly one picture. The
- // files must be named such that the frames are in temporal order when sorted
- // alphabetically by filename. The parser will automatically parse enough data
- // from the first file to provide a complete set of stream metadata for the
- // MXFWriter below. If the "pedantic" parameter is given and is true, the
- // parser will check the metadata for each codestream and fail if a
- // mismatch is detected.
- Result_t OpenRead(const std::string& filename) const;
-
- // Opens a file sequence for reading. The sequence is expected to contain one or
- // more filenames, each naming a file containing the codestream for exactly one
- // picture. The parser will automatically parse enough data
- // from the first file to provide a complete set of stream metadata for the
- // MXFWriter below. If the "pedantic" parameter is given and is true, the
- // parser will check the metadata for each codestream and fail if a
- // mismatch is detected.
- Result_t OpenRead(const std::list<std::string>& file_list) const;
-
- // Fill a PictureDescriptor struct with the values from the first file's codestream.
- // Returns RESULT_INIT if the directory is not open.
- Result_t FillPictureDescriptor(PictureDescriptor&) const;
-
- // Rewind the directory to the beginning.
- Result_t Reset() const;
-
- // Reads the next sequential frame in the directory and places it in the
- // frame buffer. Fails if the buffer is too small or the direcdtory
- // contains no more files.
- // The frame buffer's PlaintextOffset parameter will be set to the first
- // byte of the data segment. Set this value to zero if you want
- // encrypted headers.
- Result_t ReadFrame(FrameBuffer&) const;
- };
-
+ bool lookup_PictureEssenceCoding(int value, ASDCP::UL& ul);
//
class MXFWriter
@@ -250,7 +115,9 @@ namespace ASDCP {
// the operation cannot be completed or if nonsensical data is discovered
// in the essence descriptor.
Result_t OpenWrite(const std::string& filename, const WriterInfo&,
- const PictureDescriptor&, ui32_t HeaderSize = 16384);
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_sub_descriptor,
+ const ASDCP::Rational& edit_rate, ui32_t header_size = 16384);
// Writes a frame of essence to the MXF file. If the optional AESEncContext
// argument is present, the essence is encrypted prior to writing.
@@ -286,10 +153,6 @@ namespace ASDCP {
// 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;
@@ -318,16 +181,12 @@ namespace ASDCP {
void DumpIndex(FILE* = 0) const;
};
}
- Result_t MD_to_JXS_PDesc(const ASDCP::MXF::GenericPictureEssenceDescriptor& EssenceDescriptor,
- const ASDCP::MXF::JPEGXSPictureSubDescriptor& EssenceSubDescriptor,
- const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
- ASDCP::JXS::PictureDescriptor& PDesc);
-
- Result_t JXS_PDesc_to_MD(const JXS::PictureDescriptor& PDesc,
- const ASDCP::Dictionary& dict,
- ASDCP::MXF::GenericPictureEssenceDescriptor& EssenceDescriptor,
- ASDCP::MXF::JPEGXSPictureSubDescriptor& EssenceSubDescriptor);
};
///
-#endif
+#endif // _AS_DCP_JXS_H_
+
+
+//
+// end AS_DCP_JXS.h
+//
diff --git a/src/AS_DCP_MXF.cpp b/src/AS_DCP_MXF.cpp
index 3ee13c9..9cb4c15 100755
--- a/src/AS_DCP_MXF.cpp
+++ b/src/AS_DCP_MXF.cpp
@@ -33,7 +33,6 @@ 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"
@@ -196,10 +195,6 @@ ASDCP::EssenceType(const std::string& filename, EssenceType_t& type)
type = ESS_JPEG_2000;
}
}
- else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(JPEGXSPictureSubDescriptor))) )
- {
- type = ESS_JPEG_XS;
- }
else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor), &md_object)) )
{
assert(md_object);
@@ -253,10 +248,6 @@ ASDCP::EssenceType(const std::string& filename, EssenceType_t& type)
{
type = ESS_AS02_JPEG_2000;
}
- else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(JPEGXSPictureSubDescriptor))) )
- {
- type = ESS_AS02_JPEG_XS;
- }
else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor), &md_object)) )
{
assert(md_object);
@@ -353,10 +344,6 @@ 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;
@@ -437,10 +424,6 @@ 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/JXS.cpp b/src/JXS.cpp
index 0cb6eed..7be7ce9 100644
--- a/src/JXS.cpp
+++ b/src/JXS.cpp
@@ -120,19 +120,19 @@ ASDCP::JXS::Accessor::PIH::Dump(FILE* stream) const
fprintf(stream, "PIH: \n");
fprintf(stream, " LpihSize: %hu\n", LpihSize());
- fprintf(stream, " LcodSize: %hu\n", LcodSize());
+ fprintf(stream, " LcodSize: %u\n", LcodSize());
fprintf(stream, " Ppih: %hu\n", Ppih());
fprintf(stream, " Plev: %hu\n", Plev());
fprintf(stream, " Wf: %hu\n", Wf());
fprintf(stream, " Hf: %hu\n", Hf());
fprintf(stream, " Cw: %hu\n", Cw());
fprintf(stream, " Hsl: %hu\n", Hsl());
- fprintf(stream, " Nc: %hu\n", Nc());
- fprintf(stream, " Ng: %hu\n", Ng());
- fprintf(stream, " Ss: %hu\n", Ss());
- fprintf(stream, " Cpih: %hu\n", Cpih());
- fprintf(stream, " Nlx: %hu\n", Nlx());
- fprintf(stream, " Nly: %hu\n", Nly());
+ fprintf(stream, " Nc: %hhu\n", Nc());
+ fprintf(stream, " Ng: %hhu\n", Ng());
+ fprintf(stream, " Ss: %hhu\n", Ss());
+ fprintf(stream, " Cpih: %hhu\n", Cpih());
+ fprintf(stream, " Nlx: %hhu\n", Nlx());
+ fprintf(stream, " Nly: %hhu\n", Nly());
Kumu::hexdump(m_MarkerData, m_DataSize, stream);
}
@@ -146,11 +146,168 @@ ASDCP::JXS::Accessor::CDT::Dump(FILE* stream) const
fprintf(stream, "CDT: \n");
for (ui32_t i = 0; i < 3; i++) {
- fprintf(stream, " Component %u Bc: %hu\n", i,Bc(i));
- fprintf(stream, " Component %u Sx: %hu\n", i,Sx(i));
- fprintf(stream, " Component %u Sy: %hu\n", i,Sy(i));
+ fprintf(stream, " Component %u Bc: %hhu\n", i,Bc(i));
+ fprintf(stream, " Component %u Sx: %hhu\n", i,Sx(i));
+ fprintf(stream, " Component %u Sy: %hhu\n", i,Sy(i));
}
}
+
+//
+bool
+ASDCP::JXS::lookup_ColorPrimaries(int cicp_value, ASDCP::UL& ul)
+{
+ const ASDCP::Dictionary& dict = DefaultSMPTEDict();
+ switch ( cicp_value )
+ {
+ case 1:
+ ul = dict.ul(ASDCP::MDD_ColorPrimaries_ITU709);
+ break;
+ case 5:
+ ul = dict.ul(ASDCP::MDD_ColorPrimaries_ITU470_PAL);
+ break;
+ case 6:
+ ul = dict.ul(ASDCP::MDD_ColorPrimaries_SMPTE170M);
+ break;
+ case 9:
+ ul = dict.ul(ASDCP::MDD_ColorPrimaries_ITU2020);
+ break;
+ case 10:
+ ul = dict.ul(ASDCP::MDD_ColorPrimaries_SMPTE_DCDM);
+ break;
+ case 11:
+ ul = dict.ul(ASDCP::MDD_TheatricalViewingEnvironment);
+ break;
+ case 12:
+ ul = dict.ul(ASDCP::MDD_ColorPrimaries_P3D65);
+ break;
+
+ default:
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+//
+bool
+ASDCP::JXS::lookup_TransferCharacteristic(int cicp_value, ASDCP::UL& ul)
+{
+ const ASDCP::Dictionary& dict = DefaultSMPTEDict();
+ switch ( cicp_value )
+ {
+ case 1:
+ case 6:
+ ul = dict.ul(ASDCP::MDD_TransferCharacteristic_ITU709);
+ break;
+ case 5: // Display Gamma 2.8, BT.470-6 This does not seem to be supported
+ case 9: // Log(100:1) range This does not seem to be supported
+ case 10:// Log(100*Sqrt(10):1 range)
+ return Kumu::RESULT_NOTIMPL;
+ break;
+ case 8:
+ ul = dict.ul(ASDCP::MDD_TransferCharacteristic_linear);
+ break;
+ case 11:
+ ul = dict.ul(ASDCP::MDD_TransferCharacteristic_IEC6196624_xvYCC);
+ break;
+ case 13:
+ ul = dict.ul(ASDCP::MDD_TransferCharacteristic_sRGB);
+ break;
+ case 14:
+ case 15:
+ ul = dict.ul(ASDCP::MDD_TransferCharacteristic_ITU2020);
+ break;
+ case 16:
+ ul = dict.ul(ASDCP::MDD_TransferCharacteristic_SMPTEST2084);
+ break;
+ case 17:
+ ul = dict.ul(ASDCP::MDD_TransferCharacteristic_ST428);
+ break;
+ case 18: // HLG
+ ul = dict.ul(ASDCP::MDD_TransferCharacteristic_HLG);
+ break;
+ case 12: // Rec. BT.1361
+ ul = dict.ul(ASDCP::MDD_TransferCharacteristic_BT1361);
+ break;
+ case 4: // Rec. BT.470
+ ul = dict.ul(ASDCP::MDD_TransferCharacteristic_BT470);
+ break;
+ case 7: // SMPTE 240M
+ ul = dict.ul(ASDCP::MDD_TransferCharacteristic_ST240M);
+ break;
+ case 2: // Unspecified. This leaves the data intentionally undefined.
+ break;
+
+ default:
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+//
+bool
+ASDCP::JXS::lookup_CodingEquations(int value, ASDCP::UL& ul)
+{
+ const ASDCP::Dictionary& dict = DefaultSMPTEDict();
+ switch ( value )
+ {
+ case 0: // Identity matrix. Use the BGR coding equations.
+ ul = dict.ul(ASDCP::MDD_CodingEquations_BGR);
+ break;
+ case 4: // Title 47.
+ case 10: // ITU 2020 constant luminance? Does not seem to be supported
+ case 11: // SMPTE ST-2085
+ return Kumu::RESULT_NOTIMPL;
+ case 1:
+ ul = dict.ul(ASDCP::MDD_CodingEquations_709);
+ break;
+ // Note: Matrix=2 does not set the optional parameter. This is intentional.
+ case 5:
+ case 6:
+ ul = dict.ul(ASDCP::MDD_CodingEquations_601);
+ break;
+ case 9: // ITU 2020 non-constant luminance?
+ ul = dict.ul(ASDCP::MDD_CodingEquations_Rec2020);
+ break;
+ case 2: // This is unspecified. The metadata item remains undefined on purpose.
+ break;
+ case 7: // ST 240M
+ ul = dict.ul(ASDCP::MDD_CodingEquations_ST240M);
+ break;
+ case 8: // YCgCo
+ ul = dict.ul(ASDCP::MDD_CodingEquations_YCGCO);
+ break;
+
+ default:
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+
+//------------------------------------------------------------------------------------------
+
+
+//
+void
+ASDCP::JXS::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const
+{
+ if ( stream == 0 )
+ stream = stderr;
+
+ fprintf(stream, "Frame: %06u, %7u bytes", m_FrameNumber, m_Size);
+
+ fputc('\n', stream);
+
+ if ( dump_len > 0 )
+ Kumu::hexdump(m_Data, dump_len, stream);
+}
+
//
// end JXS.cpp
//
diff --git a/src/JXS.h b/src/JXS.h
index bdfc57e..4155f94 100644
--- a/src/JXS.h
+++ b/src/JXS.h
@@ -40,14 +40,31 @@ support parsing picture metadata from a codestream header.
// AS_DCP.h is included only for it's base type definitions.
#include <KM_platform.h>
#include <KM_util.h>
-#include <AS_DCP.h>
+#include <Metadata.h>
#include <assert.h>
namespace ASDCP
{
namespace JXS
{
- const byte_t Magic[] = { 0xff, 0x10, 0xff };
+ const ui32_t MaxComponents = 4; // ISO 21122-1 Annex A.2 up to 8 components
+ const ui32_t MaxHorizontalLevels = 15;
+ const ui32_t MaxVerticalLevels = 2;
+
+#pragma pack(1)
+ struct ImageComponent_t // Essentially, a lookalike of the CDT marker, just with less bit-packing
+ {
+ ui8_t Bc; // Bitdepth (literal, not -1)
+ ui8_t Sx;
+ ui8_t Sy; // Subsampling factors, horizontal and vertically. Bit-packed in the marker.
+ };
+#pragma pack()
+
+ const byte_t Magic[] = { 0xff, 0x10, 0xff };
+
+ bool lookup_ColorPrimaries(int value, ASDCP::UL& ul);
+ bool lookup_TransferCharacteristic(int value, ASDCP::UL& ul);
+ bool lookup_CodingEquations(int value, ASDCP::UL& ul);
enum Marker_t
{
@@ -229,11 +246,106 @@ namespace ASDCP
void Dump(FILE* stream = 0) const;
};
}
+
+ //
+ class FrameBuffer : public ASDCP::FrameBuffer
+ {
+ public:
+ FrameBuffer() {}
+ FrameBuffer(ui32_t size) { Capacity(size); }
+ virtual ~FrameBuffer() {}
+
+ // Print debugging information to stream (stderr default)
+ void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
+ };
+
+ // An object which opens and reads a JPEG XS codestream file. The file is expected
+ // to contain exactly one complete frame of picture essence as an unwrapped (raw)
+ // ISO/IEC 21122 codestream.
+ class CodestreamParser
+ {
+ class h__CodestreamParser;
+ mem_ptr<h__CodestreamParser> m_Parser;
+ ASDCP_NO_COPY_CONSTRUCT(CodestreamParser);
+
+ public:
+ CodestreamParser();
+ virtual ~CodestreamParser();
+
+ // Opens a file for reading, parses enough data to provide a complete
+ // set of stream metadata for the MXFWriter below.
+ // The frame buffer's PlaintextOffset parameter will be set to the first
+ // byte of the data segment. Set this value to zero if you want
+ // encrypted headers.
+ Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const;
+
+ // Fill the MXF descriptor objects with the values from the file's codestream.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillPictureDescriptor(
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_subdescriptor) const;
+ };
+
+ // Parses the data in the frame buffer to fill in the picture descriptor. Copies
+ // the offset of the image data into start_of_data. Returns error if the parser fails.
+ Result_t ParseMetadataIntoDesc(const FrameBuffer&,
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_subdescriptor,
+ byte_t* start_of_data = 0);
+
+ // An object which reads a sequence of files containing JPEG XS pictures.
+ class SequenceParser
+ {
+ class h__SequenceParser;
+ mem_ptr<h__SequenceParser> m_Parser;
+ ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
+
+ public:
+ SequenceParser();
+ virtual ~SequenceParser();
+
+ // Opens a directory for reading. The directory is expected to contain one or
+ // more files, each containing the codestream for exactly one picture. The
+ // files must be named such that the frames are in temporal order when sorted
+ // alphabetically by filename. The parser will automatically parse enough data
+ // from the first file to provide a complete set of stream metadata for the
+ // MXFWriter below. If the "pedantic" parameter is given and is true, the
+ // parser will check the metadata for each codestream and fail if a
+ // mismatch is detected.
+ Result_t OpenRead(const std::string& filename) const;
+
+ // Opens a file sequence for reading. The sequence is expected to contain one or
+ // more filenames, each naming a file containing the codestream for exactly one
+ // picture. The parser will automatically parse enough data
+ // from the first file to provide a complete set of stream metadata for the
+ // MXFWriter below. If the "pedantic" parameter is given and is true, the
+ // parser will check the metadata for each codestream and fail if a
+ // mismatch is detected.
+ Result_t OpenRead(const std::list<std::string>& file_list) const;
+
+ // Fill a PictureDescriptor struct with the values from the first file's codestream.
+ // Returns RESULT_INIT if the directory is not open.
+ Result_t FillPictureDescriptor(
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_subdescriptor) const;
+
+ // Rewind the directory to the beginning.
+ Result_t Reset() const;
+
+ // Reads the next sequential frame in the directory and places it in the
+ // frame buffer. Fails if the buffer is too small or the direcdtory
+ // contains no more files.
+ // The frame buffer's PlaintextOffset parameter will be set to the first
+ // byte of the data segment. Set this value to zero if you want
+ // encrypted headers.
+ Result_t ReadFrame(FrameBuffer&) const;
+ };
+
} //namespace JXS
} // namespace ASDCP
#endif // _JXS_H_
//
-// end JP2K.h
-// \ No newline at end of file
+// end JXS.h
+//
diff --git a/src/JXS_Codestream_Parser.cpp b/src/JXS_Codestream_Parser.cpp
index bb7b729..4d08c80 100644
--- a/src/JXS_Codestream_Parser.cpp
+++ b/src/JXS_Codestream_Parser.cpp
@@ -32,8 +32,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <KM_fileio.h>
-#include <AS_DCP.h>
-#include <AS_DCP_JXS.h>
#include <JXS.h>
#include <assert.h>
#include <KM_log.h>
@@ -46,15 +44,12 @@ class ASDCP::JXS::CodestreamParser::h__CodestreamParser
ASDCP_NO_COPY_CONSTRUCT(h__CodestreamParser);
public:
- PictureDescriptor m_PDesc;
+ ASDCP::MXF::GenericPictureEssenceDescriptor m_PDesc;
+ ASDCP::MXF::JPEGXSPictureSubDescriptor m_JxsSubdesc;
Kumu::FileReader m_File;
- h__CodestreamParser()
- {
- memset(&m_PDesc, 0, sizeof(m_PDesc));
- m_PDesc.EditRate = Rational(24, 1);
- m_PDesc.SampleRate = m_PDesc.EditRate;
- }
+ h__CodestreamParser()
+ : m_PDesc(&DefaultSMPTEDict()), m_JxsSubdesc(&DefaultSMPTEDict()) {}
~h__CodestreamParser() {}
@@ -85,7 +80,7 @@ public:
if (ASDCP_SUCCESS(result))
{
byte_t start_of_data = 0; // out param
- result = ParseMetadataIntoDesc(FB, m_PDesc, &start_of_data);
+ result = ParseMetadataIntoDesc(FB, m_PDesc, m_JxsSubdesc, &start_of_data);
if (ASDCP_SUCCESS(result))
FB.PlaintextOffset(start_of_data);
@@ -96,7 +91,8 @@ public:
};
ASDCP::Result_t
-ASDCP::JXS::ParseMetadataIntoDesc(const FrameBuffer& FB, PictureDescriptor& PDesc, byte_t* start_of_data)
+ASDCP::JXS::ParseMetadataIntoDesc(const FrameBuffer& FB, ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_subdescriptor, byte_t* start_of_data)
{
Result_t result = RESULT_OK;
Marker NextMarker;
@@ -108,6 +104,8 @@ ASDCP::JXS::ParseMetadataIntoDesc(const FrameBuffer& FB, PictureDescriptor& PDes
bool pih = false;
bool havesoc = false;
+ ImageComponent_t image_components[MaxComponents];
+
while (p < end_p && ASDCP_SUCCESS(result))
{
result = GetNextMarker(&p, NextMarker);
@@ -158,23 +156,23 @@ ASDCP::JXS::ParseMetadataIntoDesc(const FrameBuffer& FB, PictureDescriptor& PDes
// size of the bitstream: ignore, just store away.
size = PIH_.LcodSize();
// Profile and level
- PDesc.Ppih = PIH_.Ppih();
- PDesc.Plev = PIH_.Plev();
+ jxs_subdescriptor.JPEGXSPpih = PIH_.Ppih();
+ jxs_subdescriptor.JPEGXSPlev = PIH_.Plev();
// Width and Height
- PDesc.AspectRatio = Rational(PIH_.Wf(), PIH_.Hf());
- PDesc.StoredWidth = PIH_.Wf();
- PDesc.StoredHeight = PIH_.Hf();
- PDesc.Wf = PIH_.Wf();
- PDesc.Hf = PIH_.Hf();
- PDesc.Cw = PIH_.Cw();
- PDesc.Hsl = PIH_.Hsl();
+ picture_descriptor.AspectRatio = Rational(PIH_.Wf(), PIH_.Hf());
+ picture_descriptor.StoredWidth = PIH_.Wf();
+ picture_descriptor.StoredHeight = PIH_.Hf();
+ jxs_subdescriptor.JPEGXSWf = PIH_.Wf();
+ jxs_subdescriptor.JPEGXSHf = PIH_.Hf();
+ jxs_subdescriptor.JPEGXSCw = PIH_.Cw();
+ jxs_subdescriptor.JPEGXSHsl = PIH_.Hsl();
if (PIH_.Hsl() < 1 || PIH_.Hsl() > 0xffff) // This includes the EOF check
DefaultLogSink().Error("JXS::ParseMetadataIntoDesc: unsupported slice height specified, must be > 0 and < 65536");
// Number of compoennts.
- PDesc.Nc = PIH_.Nc();
- if (PDesc.Nc != 3)
+ jxs_subdescriptor.JPEGXSNc = PIH_.Nc();
+ if (jxs_subdescriptor.JPEGXSNc != 3)
{
- DefaultLogSink().Error("Unexpected number of components: %u\n", PDesc.Nc);
+ DefaultLogSink().Error("Unexpected number of components: %u\n", jxs_subdescriptor.JPEGXSNc);
return RESULT_RAW_FORMAT;
}
// A lot of settings that must be fixed right now.
@@ -196,10 +194,10 @@ ASDCP::JXS::ParseMetadataIntoDesc(const FrameBuffer& FB, PictureDescriptor& PDes
Accessor::CDT CDT_(NextMarker);
int i, count = NextMarker.m_DataSize >> 1;
- for (i = 0; i < count && i < PDesc.Nc; i++) {
- PDesc.ImageComponents[i].Bc = CDT_.Bc(i);
- PDesc.ImageComponents[i].Sx = CDT_.Sx(i);
- PDesc.ImageComponents[i].Sy = CDT_.Sy(i);
+ for (i = 0; i < count && i < jxs_subdescriptor.JPEGXSNc; i++) {
+ image_components[i].Bc = CDT_.Bc(i);
+ image_components[i].Sx = CDT_.Sx(i);
+ image_components[i].Sy = CDT_.Sy(i);
}
}
else {
@@ -213,10 +211,28 @@ ASDCP::JXS::ParseMetadataIntoDesc(const FrameBuffer& FB, PictureDescriptor& PDes
p = end_p;
break;
+ }
}
-}
+
+ const ui32_t cdt_buffer_len = 8 * 2; // at most 8 components.
+ byte_t tmp_buffer[cdt_buffer_len];
+ int comps = (jxs_subdescriptor.JPEGXSNc > 8)?8:jxs_subdescriptor.JPEGXSNc;
+ jxs_subdescriptor.JPEGXSComponentTable.Length(4 + (comps << 1));
+
+ // thor: unclear whether the marker size is part of this data.
+ tmp_buffer[0] = 0xff;
+ tmp_buffer[1] = 0x13; // the marker
+ tmp_buffer[2] = 0x00;
+ tmp_buffer[3] = comps * 2 + 2; // The size.
+ for(int j = 0;j < comps;j++) {
+ tmp_buffer[4 + (j << 1)] = image_components[j].Bc;
+ tmp_buffer[5 + (j << 1)] = (image_components[j].Sx << 4) | (image_components[j].Sy);
+ }
+
+ memcpy(jxs_subdescriptor.JPEGXSComponentTable.Data(), tmp_buffer, 4 + (comps << 1));
return result;
}
+
//------------------------------------------------------------------------------------------
ASDCP::JXS::CodestreamParser::CodestreamParser()
@@ -238,12 +254,15 @@ ASDCP::JXS::CodestreamParser::OpenReadFrame(const std::string& filename, FrameBu
//
ASDCP::Result_t
-ASDCP::JXS::CodestreamParser::FillPictureDescriptor(PictureDescriptor& PDesc) const
+ASDCP::JXS::CodestreamParser::FillPictureDescriptor(
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_subdescriptor) const
{
if (m_Parser.empty())
return RESULT_INIT;
- PDesc = m_Parser->m_PDesc;
+ picture_descriptor = m_Parser->m_PDesc;
+ jxs_subdescriptor = m_Parser->m_JxsSubdesc;
return RESULT_OK;
}
diff --git a/src/JXS_Sequence_Parser.cpp b/src/JXS_Sequence_Parser.cpp
index 38b8de4..331f0e3 100644
--- a/src/JXS_Sequence_Parser.cpp
+++ b/src/JXS_Sequence_Parser.cpp
@@ -31,16 +31,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\brief AS-DCP library, JPEG XS sequence codestream essence reader implementation
*/
-#include <AS_DCP.h>
-#include <AS_DCP_JXS.h>
-#include <KM_fileio.h>
-#include <KM_log.h>
-#include <list>
-#include <string>
-#include <algorithm>
-#include <string.h>
-#include <assert.h>
-
+#include <JXS.h>
using namespace ASDCP;
//------------------------------------------------------------------------------------------
@@ -107,13 +98,10 @@ class ASDCP::JXS::SequenceParser::h__SequenceParser
ASDCP_NO_COPY_CONSTRUCT(h__SequenceParser);
public:
- PictureDescriptor m_PDesc;
+ ASDCP::MXF::GenericPictureEssenceDescriptor m_PDesc;
+ ASDCP::MXF::JPEGXSPictureSubDescriptor m_JxsSubdesc;
- h__SequenceParser() : m_FramesRead(0)
- {
- memset(&m_PDesc, 0, sizeof(m_PDesc));
- m_PDesc.EditRate = Rational(24, 1);
- }
+ h__SequenceParser() : m_FramesRead(0), m_PDesc(&DefaultSMPTEDict()), m_JxsSubdesc(&DefaultSMPTEDict()) {}
~h__SequenceParser()
{
@@ -157,7 +145,7 @@ ASDCP::JXS::SequenceParser::h__SequenceParser::OpenRead()
result = Parser.OpenReadFrame((*m_CurrentFile).c_str(), TmpBuffer);
if (ASDCP_SUCCESS(result))
- result = Parser.FillPictureDescriptor(m_PDesc);
+ result = Parser.FillPictureDescriptor(m_PDesc, m_JxsSubdesc);
// how big is it?
if (ASDCP_SUCCESS(result))
@@ -268,12 +256,15 @@ ASDCP::JXS::SequenceParser::ReadFrame(FrameBuffer& FB) const
//
ASDCP::Result_t
-ASDCP::JXS::SequenceParser::FillPictureDescriptor(PictureDescriptor& PDesc) const
+ASDCP::JXS::SequenceParser::FillPictureDescriptor(
+ ASDCP::MXF::GenericPictureEssenceDescriptor& picture_descriptor,
+ ASDCP::MXF::JPEGXSPictureSubDescriptor& jxs_subdescriptor) const
{
if (m_Parser.empty())
return RESULT_INIT;
- PDesc = m_Parser->m_PDesc;
+ picture_descriptor = m_Parser->m_PDesc;
+ jxs_subdescriptor = m_Parser->m_JxsSubdesc;
return RESULT_OK;
}
diff --git a/src/Makefile.am b/src/Makefile.am
index 00a784f..5a7f9ed 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -144,7 +144,6 @@ endif
if USE_ASDCP_JXS
libasdcp_la_SOURCES += JXS_Codestream_Parser.cpp JXS_Sequence_Parser.cpp JXS.cpp AS_DCP_JXS.cpp
-AM_CPPFLAGS += -DUSE_ASDCP_JXS
endif
libasdcp_la_LDFLAGS = -release @VERSION@
@@ -153,6 +152,10 @@ libasdcp_la_LIBADD = libkumu.la
libasdcp_la_CPPFLAGS = -DASDCP_PLATFORM=\"@host@\"
if USE_AS_02
+if ! USE_ASDCP_JXS
+libasdcp_la_SOURCES += JXS_Codestream_Parser.cpp JXS_Sequence_Parser.cpp JXS.cpp
+endif
+
# sources for as-02 library
libas02_la_SOURCES = \
AS_02.h \
@@ -213,6 +216,7 @@ bin_PROGRAMS = \
if USE_AS_02
bin_PROGRAMS += \
as-02-wrap \
+ as-02-wrap-jxs \
as-02-unwrap \
as-02-info
endif
@@ -270,6 +274,9 @@ if USE_AS_02
as_02_wrap_SOURCES = as-02-wrap.cpp
as_02_wrap_LDADD = libas02.la libasdcp.la libkumu.la
+as_02_wrap_jxs_SOURCES = as-02-wrap-jxs.cpp
+as_02_wrap_jxs_LDADD = libas02.la libasdcp.la libkumu.la
+
as_02_unwrap_SOURCES = as-02-unwrap.cpp
as_02_unwrap_LDADD = libas02.la libasdcp.la libkumu.la
diff --git a/src/as-02-info.cpp b/src/as-02-info.cpp
index 1878f6b..dd769a8 100644
--- a/src/as-02-info.cpp
+++ b/src/as-02-info.cpp
@@ -1,4 +1,3 @@
-
/*
Copyright (c) 2003-2016, John Hurst, Wolfgang Ruppel
@@ -41,10 +40,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <AS_DCP.h>
#include <AS_02.h>
#include <JP2K.h>
-#ifdef USE_ASDCP_JXS
-#include <AS_02_JXS.h>
-#include <JXS.h>
-#endif
#include <AS_02_ACES.h>
#include <ACES.h>
#include <MXF.h>
@@ -371,114 +366,6 @@ class MyPictureDescriptor : public JP2K::PictureDescriptor
}
};
-#ifdef USE_ASDCP_JXS
-class MyXSPictureDescriptor : public JXS::PictureDescriptor
-{
- RGBAEssenceDescriptor *m_RGBADescriptor;
- CDCIEssenceDescriptor *m_CDCIDescriptor;
- JPEGXSPictureSubDescriptor *m_JXSSubDescriptor;
-
- public:
- MyXSPictureDescriptor() :
- m_RGBADescriptor(0),
- m_CDCIDescriptor(0),
- m_JXSSubDescriptor(0) {}
-
- void FillDescriptor(AS_02::JXS::MXFReader& Reader)
- {
- m_CDCIDescriptor = get_descriptor_by_type<AS_02::JXS::MXFReader, CDCIEssenceDescriptor>
- (Reader, DefaultCompositeDict().ul(MDD_CDCIEssenceDescriptor));
-
- m_RGBADescriptor = get_descriptor_by_type<AS_02::JXS::MXFReader, RGBAEssenceDescriptor>
- (Reader, DefaultCompositeDict().ul(MDD_RGBAEssenceDescriptor));
-
- if ( m_RGBADescriptor != 0 )
- {
- SampleRate = m_RGBADescriptor->SampleRate;
- if ( ! m_RGBADescriptor->ContainerDuration.empty() )
- {
- ContainerDuration = m_RGBADescriptor->ContainerDuration;
- }
- }
- else if ( m_CDCIDescriptor != 0 )
- {
- SampleRate = m_CDCIDescriptor->SampleRate;
- if ( ! m_CDCIDescriptor->ContainerDuration.empty() )
- {
- ContainerDuration = m_CDCIDescriptor->ContainerDuration;
- }
- }
- else
- {
- DefaultLogSink().Error("Picture descriptor not found.\n");
- }
-
- m_JXSSubDescriptor = get_descriptor_by_type<AS_02::JXS::MXFReader, JPEGXSPictureSubDescriptor>
- (Reader, DefaultCompositeDict().ul(MDD_JPEGXSPictureSubDescriptor));
-
- if ( m_JXSSubDescriptor == 0 )
- {
- DefaultLogSink().Error("JPEGXSPictureSubDescriptor not found.\n");
- }
-
- std::list<InterchangeObject*> ObjectList;
- Reader.OP1aHeader().GetMDObjectsByType(DefaultCompositeDict().ul(MDD_Track), ObjectList);
-
- if ( ObjectList.empty() )
- {
- DefaultLogSink().Error("MXF Metadata contains no Track Sets.\n");
- }
-
- EditRate = ((Track*)ObjectList.front())->EditRate;
- }
-
- void MyDump(FILE* stream) {
- if ( stream == 0 )
- {
- stream = stderr;
- }
-
- if ( m_CDCIDescriptor != 0 )
- {
- m_CDCIDescriptor->Dump(stream);
- }
- else if ( m_RGBADescriptor != 0 )
- {
- m_RGBADescriptor->Dump(stream);
- }
- else
- {
- return;
- }
-
- if ( m_JXSSubDescriptor != 0 )
- {
- m_JXSSubDescriptor->Dump(stream);
-
- fprintf(stream, " ImageComponents: (max=%d)\n", JXS::MaxComponents);
-
- //
- ui32_t component_sizing = m_JXSSubDescriptor->JPEGXSComponentTable.Length();
-
- if ( component_sizing == m_JXSSubDescriptor->JPEGXSNc * 2 + 4)
- {
- fprintf(stream, " bits h-sep v-sep\n");
- const byte_t *src = m_JXSSubDescriptor->JPEGXSComponentTable.RoData() + 4;
- for(int i = 0;i < m_JXSSubDescriptor->JPEGXSNc && i < JXS::MaxComponents; i++ ) {
- fprintf(stream, " %4d %5d %5d\n",
- src[0],src[1] >> 4,src[1] & 0x0f);
- src += 2;
- }
- }
- else
- {
- DefaultLogSink().Warn("Unexpected PictureComponentSizing size: %u, should be 17.\n", component_sizing);
- }
- }
- }
-};
-#endif
-
class MyACESPictureDescriptor : public AS_02::ACES::PictureDescriptor
{
RGBAEssenceDescriptor *m_RGBADescriptor;
@@ -724,36 +611,9 @@ init_rate_info()
rate_ul = DefaultCompositeDict().ul(MDD_ACESUncompressedMonoscopicWithAlpha);
g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, DBL_MAX, "ST 2065-5")));
+}
-#ifdef USE_ASDCP_JXS
- rate_ul = DefaultCompositeDict().ul(MDD_JPEGXSUnrestrictedCodestream);
- g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, DBL_MAX, "ST 2124 JPEG XS Unrestricted Profile")));
-
- rate_ul = DefaultCompositeDict().ul(MDD_JPEGXSMain422_10Profile);
- g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, DBL_MAX, "ST 2124 JPEG XS Main 422 10 Profile")));
-
- rate_ul = DefaultCompositeDict().ul(MDD_JPEGXSMain444_12Profile);
- g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, DBL_MAX, "ST 2124 JPEG XS Main 444 12 Profile")));
-
- rate_ul = DefaultCompositeDict().ul(MDD_JPEGXSMain4444_12Profile);
- g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, DBL_MAX, "ST 2124 JPEG XS Main 4444 12 Profile")));
-
- rate_ul = DefaultCompositeDict().ul(MDD_JPEGXSLight422_10Profile);
- g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, DBL_MAX, "ST 2124 JPEG XS Light 422 10 Profile")));
-
- rate_ul = DefaultCompositeDict().ul(MDD_JPEGXSLight444_12Profile);
- g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, DBL_MAX, "ST 2124 JPEG XS Light 444 12 Profile")));
-
- rate_ul = DefaultCompositeDict().ul(MDD_JPEGXSLightSubline422_10Profile);
- g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, DBL_MAX, "ST 2124 JPEG XS Light Subline 422 10 Profile")));
-
- rate_ul = DefaultCompositeDict().ul(MDD_JPEGXSHigh444_12Profile);
- g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, DBL_MAX, "ST 2124 JPEG XS High 444 12 Profile")));
- rate_ul = DefaultCompositeDict().ul(MDD_JPEGXSHigh4444_12Profile);
- g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, DBL_MAX, "ST 2124 JPEG XS High 4444 12 Profile")));
-#endif
-}
//
//
template<class ReaderT, class DescriptorT>
@@ -958,12 +818,10 @@ public:
static const double mega_const = 1.0 / ( 1000000 / 8.0 );
// we did not accumulate the last, so duration -= 1
- if (duration > 1) {
- double avg_bytes_frame = (double)(total_frame_bytes / ( duration - 1 ));
- m_AvgBitrate = avg_bytes_frame * mega_const * m_Desc.EditRate.Quotient();
- }
-
+ double avg_bytes_frame = (double)(total_frame_bytes / ( duration - 1 ));
+
m_MaxBitrate = largest_frame * mega_const * m_Desc.EditRate.Quotient();
+ m_AvgBitrate = avg_bytes_frame * mega_const * m_Desc.EditRate.Quotient();
}
}
@@ -1028,31 +886,7 @@ show_file_info(CommandOptions& Options)
result = wrapper.test_rates(Options, stdout);
}
}
-#ifdef USE_ASDCP_JXS
- else if ( EssenceType == ESS_AS02_JPEG_XS )
- {
- FileInfoWrapper<AS_02::JXS::MXFReader, MyXSPictureDescriptor> wrapper;
- result = wrapper.file_info(Options, "JPEG XS pictures");
-
- if ( KM_SUCCESS(result) )
- {
- wrapper.get_PictureEssenceCoding();
- wrapper.calc_Bitrate(stdout);
-
- if ( Options.showcoding_flag )
- {
- wrapper.dump_PictureEssenceCoding(stdout);
- }
-
- if ( Options.showrate_flag )
- {
- wrapper.dump_Bitrate(stdout);
- }
- result = wrapper.test_rates(Options, stdout);
- }
- }
-#endif
else if ( EssenceType == ESS_AS02_ACES )
{
FileInfoWrapper<AS_02::ACES::MXFReader, MyACESPictureDescriptor> wrapper;
diff --git a/src/as-02-unwrap.cpp b/src/as-02-unwrap.cpp
index a50b76e..64a399a 100755
--- a/src/as-02-unwrap.cpp
+++ b/src/as-02-unwrap.cpp
@@ -38,9 +38,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <KM_fileio.h>
#include <AS_02.h>
-#ifdef USE_ASDCP_JXS
-#include "AS_02_JXS.h"
-#endif
#include "AS_02_ACES.h"
#include <WavFileWriter.h>
@@ -434,156 +431,6 @@ read_JP2K_file(CommandOptions& Options)
//------------------------------------------------------------------------------------------
-// JPEG XS essence
-
-#ifdef USE_ASDCP_JXS
-// Read one or more plaintext JPEG XS codestreams from a plaintext ASDCP file
-// Read one or more plaintext JPEG XS codestreams from a ciphertext ASDCP file
-// Read one or more ciphertext JPEG XS codestreams from a ciphertext ASDCP file
-//
-Result_t
-read_JXS_file(CommandOptions& Options)
-{
- AESDecContext* Context = 0;
- HMACContext* HMAC = 0;
- AS_02::JXS::MXFReader Reader;
- JXS::FrameBuffer FrameBuffer(Options.fb_size);
- ui32_t frame_count = 0;
-
- Result_t result = Reader.OpenRead(Options.input_filename);
-
- if (ASDCP_SUCCESS(result))
- {
- if (Options.verbose_flag)
- {
- fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
- }
-
- ASDCP::MXF::RGBAEssenceDescriptor *rgba_descriptor = 0;
- ASDCP::MXF::CDCIEssenceDescriptor *cdci_descriptor = 0;
-
- result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_RGBAEssenceDescriptor),
- reinterpret_cast<MXF::InterchangeObject**>(&rgba_descriptor));
-
- if (KM_SUCCESS(result))
- {
- assert(rgba_descriptor);
- if (!rgba_descriptor->ContainerDuration.empty())
- {
- frame_count = (ui32_t)rgba_descriptor->ContainerDuration;
- }
- if (Options.verbose_flag)
- {
- rgba_descriptor->Dump();
- }
- }
- else
- {
- result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_CDCIEssenceDescriptor),
- reinterpret_cast<MXF::InterchangeObject**>(&cdci_descriptor));
-
- if (KM_SUCCESS(result))
- {
- assert(cdci_descriptor);
- if (!cdci_descriptor->ContainerDuration.empty())
- {
- frame_count = (ui32_t)cdci_descriptor->ContainerDuration;
- }
- if (Options.verbose_flag)
- {
- cdci_descriptor->Dump();
- }
- }
- else
- {
- fprintf(stderr, "File does not contain an essence descriptor.\n");
- frame_count = Reader.AS02IndexReader().GetDuration();
- }
- }
-
- if (frame_count == 0)
- {
- frame_count = Reader.AS02IndexReader().GetDuration();
- }
-
- if (frame_count == 0)
- {
- fprintf(stderr, "Unable to determine file duration.\n");
- return RESULT_FAIL;
- }
- }
-
-#ifdef HAVE_OPENSSL
- if (ASDCP_SUCCESS(result) && Options.key_flag)
- {
- Context = new AESDecContext;
- result = Context->InitKey(Options.key_value);
-
- if (ASDCP_SUCCESS(result) && Options.read_hmac)
- {
- WriterInfo Info;
- Reader.FillWriterInfo(Info);
-
- if (Info.UsesHMAC)
- {
- HMAC = new HMACContext;
- result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
- }
- else
- {
- fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
- }
- }
- }
-#endif
-
- ui32_t last_frame = Options.start_frame + (Options.duration ? Options.duration : frame_count);
- if (last_frame > frame_count)
- last_frame = frame_count;
-
- char name_format[64];
- snprintf(name_format, 64, "%%s%%0%du.jxc", Options.number_width);
-
- for (ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++)
- {
- result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);
-
- char filename[1024];
- snprintf(filename, 1024, name_format, Options.file_prefix, i);
-
- if (ASDCP_SUCCESS(result) && Options.verbose_flag)
- {
- printf("Frame %d, %d bytes", i, FrameBuffer.Size());
-
- if (!Options.no_write_flag)
- {
- printf(" -> %s", filename);
- }
-
- printf("\n");
- }
-
- if (ASDCP_SUCCESS(result) && (!Options.no_write_flag))
- {
- Kumu::FileWriter OutFile;
- ui32_t write_count;
- result = OutFile.OpenWrite(filename);
-
- if (ASDCP_SUCCESS(result))
- result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);
-
- if (ASDCP_SUCCESS(result) && Options.verbose_flag)
- {
- FrameBuffer.Dump(stderr, Options.fb_dump_size);
- }
- }
- }
-
- return result;
-}
-#endif
-
-//------------------------------------------------------------------------------------------
// ACES essence
//
@@ -1172,11 +1019,6 @@ main(int argc, const char** argv)
result = read_JP2K_file(Options);
break;
//PB
-#ifdef USE_ASDCP_JXS
- case ESS_AS02_JPEG_XS:
- result = read_JXS_file(Options);
- break;
-#endif
case ESS_AS02_ACES:
result = read_ACES_file(Options);
break;
diff --git a/src/as-02-wrap.cpp b/src/as-02-wrap.cpp
index f3e31ee..713bcdb 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, Thomas Richter
+John Hurst, Wolfgang Ruppel
All rights reserved.
@@ -39,9 +39,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <KM_xml.h>
#include <KM_prng.h>
#include <AS_02.h>
-#ifdef USE_ASDCP_JXS
-#include "AS_02_JXS.h"
-#endif
#include "AS_02_ACES.h"
#include <PCMParserList.h>
#include <Metadata.h>
@@ -956,6 +953,11 @@ public:
out_file = filenames.back();
filenames.pop_back();
+ if ( ! picture_coding.HasValue() )
+ {
+ picture_coding = UL(g_dict->ul(MDD_JP2KEssenceCompression_BroadcastProfile_1));
+ }
+
error_flag = false;
}
};
@@ -996,11 +998,6 @@ write_JP2K_file(CommandOptions& Options)
ASDCP::JP2K::PictureDescriptor PDesc;
Parser.FillPictureDescriptor(PDesc);
PDesc.EditRate = Options.edit_rate;
-
- if ( ! Options.picture_coding.HasValue() )
- {
- Options.picture_coding = UL(g_dict->ul(MDD_JP2KEssenceCompression_BroadcastProfile_1));
- }
if ( Options.verbose_flag )
{
@@ -1180,245 +1177,6 @@ write_JP2K_file(CommandOptions& Options)
}
-
-//------------------------------------------------------------------------------------------
-// JPEG XS essence
-#ifdef USE_ASDCP_JXS
-
-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());
-
- if ( ! Options.picture_coding.HasValue() )
- {
- Options.picture_coding = UL(g_dict->ul(MDD_JPEGXSUnrestrictedCodestream));
- }
-
- if (ASDCP_SUCCESS(result) )
- {
- // verify the picture essence coding.
- if (!((UL(g_dict->ul(MDD_JPEGXSUnrestrictedCodestream)) == Options.picture_coding) ||
- (UL(g_dict->ul(MDD_JPEGXSMain422_10Profile)) == Options.picture_coding) ||
- (UL(g_dict->ul(MDD_JPEGXSMain444_12Profile)) == Options.picture_coding) ||
- (UL(g_dict->ul(MDD_JPEGXSMain4444_12Profile)) == Options.picture_coding) ||
- (UL(g_dict->ul(MDD_JPEGXSLight422_10Profile)) == Options.picture_coding) ||
- (UL(g_dict->ul(MDD_JPEGXSLight444_12Profile)) == Options.picture_coding) ||
- (UL(g_dict->ul(MDD_JPEGXSLightSubline422_10Profile)) == Options.picture_coding) ||
- (UL(g_dict->ul(MDD_JPEGXSHigh444_12Profile)) == Options.picture_coding) ||
- (UL(g_dict->ul(MDD_JPEGXSHigh4444_12Profile)) == Options.picture_coding)))
- {
- result = RESULT_PARAM;
- }
- }
-
- // 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;
-}
-#endif
-
//------------------------------------------------------------------------------------------
// ACES essence
@@ -2225,11 +1983,6 @@ main(int argc, const char** argv)
result = write_JP2K_file(Options);
break;
// PB
-#ifdef USE_ASDCP_JXS
- case ESS_JPEG_XS:
- result = write_JXS_file(Options);
- break;
-#endif
case ::ESS_AS02_ACES:
result = write_ACES_file(Options);
break;