/*
Copyright (c) 2011-2018, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
-John Hurst
+John Hurst, Wolfgang Ruppel
All rights reserved.
#include <KM_fileio.h>
#include <KM_prng.h>
+#include <KM_xml.h>
#include <AS_02.h>
+#include "AS_02_ACES.h"
#include <PCMParserList.h>
#include <Metadata.h>
return; \
}
+#define TEST_EXTRA_ARG_STRING(i,s) \
+ if ( ++i >= argc || argv[(i)][0] == '-' ) { \
+ fprintf(stderr, "Argument not found for option -%s.\n", (s)); \
+ return; \
+ }
+
//
static void
-F (0|1) - Set field dominance for interlaced image (default: 0)\n\
-g <rfc-5646-code>\n\
- Create MCA labels having the given RFC 5646 language code\n\
- (requires option \"-m\")\n\
+ (requires option \"-m\") -- Also used with -G to set the\n\
+ value of the TextMIMEMediaType property\n\
+ -G <filename> - Filename of XML resource to be carried per RP 2057 Generic\n\
+ Stream. May be issued multiple times.\n\
-i - Indicates input essence is interlaced fields (forces -Y)\n\
-j <key-id-str> - Write key ID instead of creating a random value\n\
-k <key-string> - Use key for ciphertext operations\n\
-l <first>,<second>\n\
- - Integer values that set the VideoLineMap when creating\n\
- interlaced YCbCr files\n\
+ - Integer values that set the VideoLineMap\n\
-m <expr> - Write MCA labels using <expr>. Example:\n\
51(L,R,C,LFE,Ls,Rs,),HI,VIN\n\
-M - Do not create HMAC values when writing\n\
-t <min> - Set RGB component minimum code value (default: 0)\n\
-T <max> - Set RGB component maximum code value (default: 1023)\n\
-u - Print UL catalog to stdout\n\
+ -U <URI> - ISXD (RDD47) document URI (use 'auto' to read the\n\
+ namespace name from the first edit unit)\n\
-v - Verbose, prints informative messages to stderr\n\
-W - Read input file only, do not write source file\n\
-x <int> - Horizontal subsampling degree (default: 2)\n\
940,64,897, indicating 10 bit standard Video Range\n\
-z - Fail if j2c inputs have unequal parameters (default)\n\
-Z - Ignore unequal parameters in j2c inputs\n\
+\n\
+ --mca-audio-content-kind <string>\n\
+ - UL value for MCA descriptor MCAAudioContentKind property\n\
+ --mca-audio-element-kind <string>\n\
+ - UL value for MCA descriptor MCAAudioElementKind property\n\
+\n\
+\n\
+Options specific to ACES ST2067-50:\n\
+ -suba <string> - Create ACES Picture SubDescriptor, set <string> as ACESAuthoringInformation,\n\
+ uses values from -o and -O, if present\n\
+ -subt <directoryPath> - \n\
+ Create one Target Frame SubDescriptor per PNG or TIFF file in <directoryPath>,\n\
+ and wrap each PNG or TIFF file as ancillary resource\n\
+ Requires additional options -tfi, -tft, -tfc, -tfr\n\
+ -tfi <int>[,<int>*] - \n\
+ List of TargetFrameIndex values in Target Frame SubDescriptor corresponding to the \n\
+ list of Target Frame frame files in <directoryPath> as given by option -subt\n\
+ -tft <string> - Target Frame Transfer Characteristics Symbol, e.g. TransferCharacteristic_ITU709\n\
+ -tfc <string> - Target Frame Color Primaries Symbol, e.g. ColorPrimaries_ITU709\n\
+ -tfr <min>,<max> - Target Frame Component Min/Max Ref in Target Frame SubDescriptor\n\
+ -tfv <string> - Target Frame Viewing Environment Symbol, e.g. HDTVReferenceViewingEnvironment\n\
+\n\
\n\
NOTES: o There is no option grouping, all options must be distinct arguments.\n\
o All option arguments must be separated from the option by whitespace.\n\n");
bool key_id_flag; // true if a key ID was given
byte_t key_id_value[UUIDlen];// value of given key ID (when key_id_flag is true)
byte_t asset_id_value[UUIDlen];// value of asset ID (when asset_id_flag is true)
- bool show_ul_values_flag; /// if true, dump the UL table before going tp work.
+ bool show_ul_values_flag; // if true, dump the UL table before going tp work.
Kumu::PathList_t filenames; // list of filenames to be processed
UL channel_assignment, picture_coding, transfer_characteristic, color_primaries, coding_equations;
ASDCP::MXF::AS02_MCAConfigParser mca_config;
- std::string mca_language;
+ std::string language;
ui32_t rgba_MaxRef;
ui32_t rgba_MinRef;
ui32_t component_depth;
ui8_t frame_layout;
ASDCP::Rational aspect_ratio;
+ bool aspect_ratio_flag;
ui8_t field_dominance;
ui32_t mxf_header_size;
ui32_t cdci_BlackRefLevel;
AS_02::IndexStrategy_t index_strategy; //Shim parameter index_strategy_frame/clip
ui32_t partition_space; //Shim parameter partition_spacing
+ // ISXD
+ std::string isxd_document_namespace;
+ std::list<std::string> global_isxd_metadata;
+
//
MXF::LineMapPair line_map;
+ bool line_map_flag;
std::string out_file, profile_name; //
-
+ std::string mca_audio_element_kind, mca_audio_content_kind;
+
+ //ST 2067-50 options
+ bool aces_authoring_information_flag, aces_picture_subdescriptor_flag, target_frame_subdescriptor_flag, target_frame_index_flag;
+ bool target_frame_transfer_characteristics_flag, target_frame_color_primaries_flag, target_frame_min_max_ref_flag;
+ bool target_frame_viewing_environment_flag;
+ std::string aces_authoring_information;
+ std::string target_frame_directory;
+ std::list <ui64_t> target_frame_index_list;
+ UL target_frame_transfer_characteristics, target_frame_color_primaries, target_frame_viewing_environment;
+ ui32_t target_frame_min_ref, target_frame_max_ref;
//
bool set_video_line_map(const std::string& arg)
{
// Application 2 (ST 2067-20)
case '1':
coding_equations = g_dict->ul(MDD_CodingEquations_601);
- transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_709);
+ transfer_characteristic = g_dict->ul(MDD_TransferCharacteristic_ITU709);
color_primaries = g_dict->ul(MDD_ColorPrimaries_ITU470_PAL);
use_cdci_descriptor = true;
break;
case '2':
coding_equations = g_dict->ul(MDD_CodingEquations_601);
- transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_709);
+ transfer_characteristic = g_dict->ul(MDD_TransferCharacteristic_ITU709);
color_primaries = g_dict->ul(MDD_ColorPrimaries_SMPTE170M);
use_cdci_descriptor = true;
break;
case '3':
coding_equations = g_dict->ul(MDD_CodingEquations_709);
- transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_709);
- color_primaries = g_dict->ul(MDD_ColorPrimaries_BT709);
+ transfer_characteristic = g_dict->ul(MDD_TransferCharacteristic_ITU709);
+ color_primaries = g_dict->ul(MDD_ColorPrimaries_ITU709);
use_cdci_descriptor = true;
break;
// Application 2e (ST 2067-21)
case '4':
coding_equations = g_dict->ul(MDD_CodingEquations_709);
- transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_xvYCC);
- color_primaries = g_dict->ul(MDD_ColorPrimaries_BT709);
+ transfer_characteristic = g_dict->ul(MDD_TransferCharacteristic_IEC6196624_xvYCC);
+ color_primaries = g_dict->ul(MDD_ColorPrimaries_ITU709);
use_cdci_descriptor = true;
break;
case '5':
coding_equations = g_dict->ul(MDD_CodingEquations_709);
- transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_2020);
- color_primaries = g_dict->ul(MDD_ColorPrimaries_BT2020);
+ transfer_characteristic = g_dict->ul(MDD_TransferCharacteristic_ITU2020);
+ color_primaries = g_dict->ul(MDD_ColorPrimaries_ITU2020);
use_cdci_descriptor = true;
break;
return true;
}
+ bool set_target_frame_min_max_code_value(const std::string& arg)
+ {
+ std::list<std::string> range_tokens = Kumu::km_token_split(arg, ",");
+ if ( range_tokens.size() != 2 )
+ {
+ fprintf(stderr, "Expecting a code value pair.\n");
+ return false;
+ }
+
+ target_frame_min_ref = strtol(range_tokens.front().c_str(), 0 , 10);
+ target_frame_max_ref = strtol(range_tokens.back().c_str(), 0 , 10);
+
+ return true;
+ }
+
+ bool set_target_frame_index_list(const std::string& arg, std::list<ui64_t>& r_target_frame_index_list)
+ {
+ std::list<std::string> index_tokens = Kumu::km_token_split(arg, ",");
+ if ( index_tokens.size() == 0 )
+ {
+ fprintf(stderr, "Expecting at least one Target Frame Index.\n");
+ return false;
+ }
+
+
+ std::list<std::string>::const_iterator i;
+ for (i = index_tokens.begin(); i != index_tokens.end(); i++) {
+ r_target_frame_index_list.push_back(strtoll(i->c_str(), 0, 10));
+ }
+
+ return true;
+ }
+
+
CommandOptions(int argc, const char** argv) :
error_flag(true), key_flag(false), key_id_flag(false), asset_id_flag(false),
encrypt_header_flag(true), write_hmac(true), verbose_flag(false), fb_dump_size(0),
show_ul_values_flag(false), index_strategy(AS_02::IS_FOLLOW), partition_space(60),
mca_config(g_dict), rgba_MaxRef(1023), rgba_MinRef(0),
horizontal_subsampling(2), vertical_subsampling(2), component_depth(10),
- frame_layout(0), aspect_ratio(ASDCP::Rational(4,3)), field_dominance(0),
+ frame_layout(0), aspect_ratio(ASDCP::Rational(4,3)), aspect_ratio_flag(false), field_dominance(0),
mxf_header_size(16384), cdci_WhiteRefLevel(940), cdci_BlackRefLevel(64), cdci_ColorRange(897),
- md_min_luminance(0), md_max_luminance(0), line_map(0,0)
+ md_min_luminance(0), md_max_luminance(0), line_map(0,0), line_map_flag(false),
+ aces_authoring_information_flag(false), aces_picture_subdescriptor_flag(false), target_frame_subdescriptor_flag(false),
+ target_frame_index_flag(false), target_frame_transfer_characteristics_flag(false), target_frame_color_primaries_flag(false),
+ target_frame_min_max_ref_flag(false), target_frame_viewing_environment_flag(false)
{
memset(key_value, 0, KeyLen);
memset(key_id_value, 0, UUIDlen);
coding_equations = g_dict->ul(MDD_CodingEquations_709);
- color_primaries = g_dict->ul(MDD_ColorPrimaries_BT709);
- transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_709);
+ color_primaries = g_dict->ul(MDD_ColorPrimaries_ITU709);
+ transfer_characteristic = g_dict->ul(MDD_TransferCharacteristic_ITU709);
std::string mca_config_str;
for ( int i = 1; i < argc; i++ )
continue;
}
+ if ( (strcmp( argv[i], "-suba") == 0) )
+ {
+ aces_picture_subdescriptor_flag = true;
+ if ((++i < argc) && (argv[i][0] != '-')) {
+ aces_authoring_information = argv[i];
+ aces_authoring_information_flag = true;
+ } else i--;
+ continue;
+ }
+
+ if ( (strcmp( argv[i], "-subt") == 0) )
+ {
+ target_frame_subdescriptor_flag = true;
+ TEST_EXTRA_ARG_STRING(i, "subt");
+ target_frame_directory = argv[i];
+ continue;
+ }
+
+ if ( (strcmp( argv[i], "-tfi") == 0) )
+ {
+ TEST_EXTRA_ARG_STRING(i, "tfi");
+ if (set_target_frame_index_list(argv[i], target_frame_index_list)) {
+ target_frame_index_flag = true;
+ }
+ continue;
+ }
+
+ if ( (strcmp( argv[i], "-tft") == 0) )
+ {
+ TEST_EXTRA_ARG_STRING(i, "tft");
+ //
+ const ASDCP::MDDEntry* entry = g_dict->FindSymbol(std::string(argv[i]));
+ if (entry) {
+ target_frame_transfer_characteristics_flag = true;
+ target_frame_transfer_characteristics = entry->ul;
+ fprintf(stderr, "target_frame_transfer_characteristic %s\n", entry->name);
+ }
+ continue;
+ }
+
+ if ( (strcmp( argv[i], "-tfc") == 0) )
+ {
+ TEST_EXTRA_ARG_STRING(i, "tfc");
+ //
+ const ASDCP::MDDEntry* entry = g_dict->FindSymbol(std::string(argv[i]));
+ if (entry) {
+ target_frame_color_primaries_flag = true;
+ target_frame_color_primaries = entry->ul;
+ fprintf(stderr, "target_frame_color_primaries %s\n", entry->name);
+ }
+ continue;
+ }
+
+ if ( (strcmp( argv[i], "-tfr") == 0) )
+ {
+ TEST_EXTRA_ARG(i, 'o');
+ if ( ! set_target_frame_min_max_code_value(argv[i]) )
+ {
+ return;
+ }
+ target_frame_min_max_ref_flag = true;
+ continue;
+ }
+
+ if ( (strcmp( argv[i], "-tfv") == 0) )
+ {
+ TEST_EXTRA_ARG_STRING(i, "tfv");
+ //
+ const ASDCP::MDDEntry* entry = g_dict->FindSymbol(std::string(argv[i]));
+ if (entry) {
+ target_frame_viewing_environment_flag = true;
+ target_frame_viewing_environment = entry->ul;
+ fprintf(stderr, "target_frame_viewing_environment %s\n", entry->name);
+ }
+ continue;
+ }
+
+
if ( argv[i][0] == '-'
&& ( isalpha(argv[i][1]) || isdigit(argv[i][1]) )
&& argv[i][2] == 0 )
fprintf(stderr, "Error decoding aspect ratio value: %s\n", argv[i]);
return;
}
+ else
+ {
+ aspect_ratio_flag = true;
+ }
break;
case 'a':
case 'g':
TEST_EXTRA_ARG(i, 'g');
- mca_language = argv[i];
+ language = argv[i];
+ break;
+
+ case 'G':
+ TEST_EXTRA_ARG(i, 'G');
+ global_isxd_metadata.push_back(argv[i]);
break;
case 'h': help_flag = true; break;
if ( ! set_video_line_map(argv[i]) )
{
return;
+ } else {
+ line_map_flag = true;
}
break;
case 'u': show_ul_values_flag = true; break;
+ case 'U':
+ TEST_EXTRA_ARG(i, 'U');
+ isxd_document_namespace = argv[i];
+ break;
+
case 'V': version_flag = true; break;
case 'v': verbose_flag = true; break;
case 'W': no_write_flag = true; break;
return;
}
}
- else
+ else if ( argv[i][0] == '-' && argv[i][1] == '-' && isalpha(argv[i][2]) )
{
+ if ( strcmp(argv[i]+2, "mca-audio-content-kind") == 0 )
+ {
+ if ( ++i >= argc || argv[(i)][0] == '-' )
+ {
+ fprintf(stderr, "Argument not found for option -mca-audio-content-kind.\n");
+ return;
+ }
+
+ mca_audio_content_kind = argv[i];
+ }
+ else if ( strcmp(argv[i]+2, "mca-audio-element-kind") == 0 )
+ {
+ if ( ++i >= argc || argv[(i)][0] == '-' )
+ {
+ fprintf(stderr, "Argument not found for option -mca-audio-element-kind.\n");
+ return;
+ }
+ mca_audio_element_kind = argv[i];
+ }
+ else
+ {
+ fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
+ return;
+ }
+ }
+ else
+ {
if ( argv[i][0] != '-' )
{
filenames.push_back(argv[i]);
if ( ! mca_config_str.empty() )
{
- if ( mca_language.empty() )
+ if ( language.empty() )
{
if ( ! mca_config.DecodeString(mca_config_str) )
{
}
else
{
- if ( ! mca_config.DecodeString(mca_config_str, mca_language) )
+ if ( ! mca_config.DecodeString(mca_config_str, language) )
{
return;
}
tmp_dscr->WhiteReflevel = Options.cdci_WhiteRefLevel;
tmp_dscr->BlackRefLevel = Options.cdci_BlackRefLevel;
tmp_dscr->ColorRange = Options.cdci_ColorRange;
- tmp_dscr->VideoLineMap = Options.line_map;
+ if (Options.line_map_flag) tmp_dscr->VideoLineMap = Options.line_map;
if ( Options.md_min_luminance || Options.md_max_luminance )
{
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 )
{
return result;
}
+
//------------------------------------------------------------------------------------------
-// PCM essence
+// ACES essence
+
+
+// Write one or more plaintext ACES codestreams to a plaintext AS-02 file
+// Write one or more plaintext ACES codestreams to a ciphertext AS-02 file
+//
+Result_t
+write_ACES_file(CommandOptions& Options)
+{
+ AESEncContext* Context = 0;
+ HMACContext* HMAC = 0;
+ AS_02::ACES::MXFWriter Writer;
+ AS_02::ACES::FrameBuffer FrameBuffer(Options.fb_size);
+ AS_02::ACES::SequenceParser Parser;
+ byte_t IV_buf[CBC_BLOCK_SIZE];
+ Kumu::FortunaRNG RNG;
+ ASDCP::MXF::FileDescriptor *essence_descriptor = 0;
+ ASDCP::MXF::InterchangeObject_list_t essence_sub_descriptors;
+ AS_02::ACES::PictureDescriptor PDesc;
+ AS_02::ACES::ResourceList_t resource_list_t;
+
+ // set up essence parser
+ //Result_t result = Parser.OpenRead(Options.filenames.front().c_str(), Options.j2c_aces_pedantic);
+ // set up essence parser
+ std::list<std::string> target_frame_file_list;
+ if (Options.target_frame_subdescriptor_flag)
+ {
+ Kumu::DirScannerEx dir_reader;
+ Kumu::DirectoryEntryType_t ft;
+ std::string next_item;
+ Result_t result = dir_reader.Open(Options.target_frame_directory);
+ if ( KM_SUCCESS(result) )
+ {
+ while ( KM_SUCCESS(dir_reader.GetNext(next_item, ft)) )
+ {
+ if ( next_item[0] == '.' ) continue; // no hidden files
+ std::string tmp_path = Kumu::PathJoin(Options.target_frame_directory, next_item);
+ target_frame_file_list.push_back(tmp_path);
+ }
+ }
+ }
+ Result_t result = Parser.OpenRead(Options.filenames.front().c_str(), Options.j2c_pedantic, target_frame_file_list);
+
+ // set up MXF writer
+ if (ASDCP_SUCCESS(result))
+ {
+ Parser.FillPictureDescriptor(PDesc);
+ Parser.FillResourceList(resource_list_t);
+ PDesc.EditRate = Options.edit_rate;
+
+ if (Options.verbose_flag)
+ {
+ fprintf(stderr, "ACES pictures\n");
+ fputs("PictureDescriptor:\n", stderr);
+ fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
+ AS_02::ACES::PictureDescriptorDump(PDesc);
+ }
+
+ ASDCP::MXF::RGBAEssenceDescriptor* tmp_dscr = new ASDCP::MXF::RGBAEssenceDescriptor(g_dict);
+ Kumu::GenRandomValue(tmp_dscr->InstanceUID);
+ ASDCP::MXF::ACESPictureSubDescriptor* aces_picture_subdescriptor = new ASDCP::MXF::ACESPictureSubDescriptor(g_dict);
+ Kumu::GenRandomValue(aces_picture_subdescriptor->InstanceUID);
+ result = AS_02::ACES::ACES_PDesc_to_MD(PDesc, *g_dict, *tmp_dscr);
+
+ if (ASDCP_SUCCESS(result))
+ {
+ if (Options.aspect_ratio_flag) tmp_dscr->AspectRatio = Options.aspect_ratio;
+
+ if (Options.aces_picture_subdescriptor_flag)
+ {
+ if (Options.aces_authoring_information_flag) aces_picture_subdescriptor->ACESAuthoringInformation = Options.aces_authoring_information;
+ if (Options.md_primaries.HasValue())
+ {
+ aces_picture_subdescriptor->ACESMasteringDisplayPrimaries = Options.md_primaries;
+ aces_picture_subdescriptor->ACESMasteringDisplayWhitePointChromaticity = Options.md_white_point;
+ }
+ if (Options.md_min_luminance && Options.md_max_luminance)
+ {
+ aces_picture_subdescriptor->ACESMasteringDisplayMinimumLuminance = Options.md_min_luminance;
+ aces_picture_subdescriptor->ACESMasteringDisplayMaximumLuminance = Options.md_max_luminance;
+ }
+ essence_sub_descriptors.push_back(aces_picture_subdescriptor);
+ }
+
+ if (Options.target_frame_subdescriptor_flag)
+ {
+ AS_02::ACES::ResourceList_t::iterator it;
+ ui32_t EssenceStreamID = 10; //start with 10, same value in AncillaryResourceWriter
+ for (it = resource_list_t.begin(); it != resource_list_t.end(); it++ )
+ {
+ ASDCP::MXF::TargetFrameSubDescriptor* target_frame_subdescriptor = new ASDCP::MXF::TargetFrameSubDescriptor(g_dict);
+ Kumu::GenRandomValue(target_frame_subdescriptor->InstanceUID);
+ target_frame_subdescriptor->TargetFrameAncillaryResourceID.Set(it->ResourceID);
+ target_frame_subdescriptor->MediaType.assign(AS_02::ACES::MIME2str(it->Type));
+ target_frame_subdescriptor->TargetFrameEssenceStreamID = EssenceStreamID++;
+ if (Options.target_frame_index_flag)
+ {
+ if (Options.target_frame_index_list.size() > 0)
+ {
+ target_frame_subdescriptor->TargetFrameIndex = Options.target_frame_index_list.front();
+ Options.target_frame_index_list.pop_front();
+ } else
+ {
+ fprintf(stderr, "Insufficient number of Target Frame Index values provided\n");
+ fprintf(stderr, "Number of Target Frames (%lu) should match number of Target Frame Index values\n", resource_list_t.size());
+ }
+ }
+ if (Options.target_frame_transfer_characteristics_flag) target_frame_subdescriptor->TargetFrameTransferCharacteristic = Options.target_frame_transfer_characteristics;
+ if (Options.target_frame_color_primaries_flag) target_frame_subdescriptor->TargetFrameColorPrimaries = Options.target_frame_color_primaries;
+ if (Options.target_frame_min_max_ref_flag)
+ {
+ target_frame_subdescriptor->TargetFrameComponentMinRef = Options.target_frame_min_ref;
+ target_frame_subdescriptor->TargetFrameComponentMaxRef = Options.target_frame_max_ref;
+ }
+ if (Options.aces_picture_subdescriptor_flag) target_frame_subdescriptor->ACESPictureSubDescriptorInstanceID = aces_picture_subdescriptor->InstanceUID;
+ essence_sub_descriptors.push_back(target_frame_subdescriptor);
+ }
+ }
+
+ essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr);
+ if (Options.line_map_flag) tmp_dscr->VideoLineMap = Options.line_map;
+ }
+ }
+
+ 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);
+
+ // configure encryption
+ if (Options.key_flag)
+ {
+ Kumu::GenRandomUUID(Info.ContextID);
+ Info.EncryptedEssence = true;
+
+ if (Options.key_id_flag)
+ {
+ memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
+ }
+ else
+ {
+ 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);
+ }
+ }
+
+ if (ASDCP_SUCCESS(result))
+ {
+ result = Writer.OpenWrite(Options.out_file, Info, essence_descriptor, essence_sub_descriptors,
+ Options.edit_rate, AS_02::ACES::ResourceList_t(), 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.key_flag && 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;
+ }
+ AS_02::ACES::ResourceList_t::const_iterator ri;
+ for ( ri = resource_list_t.begin() ; ri != resource_list_t.end() && ASDCP_SUCCESS(result); ri++ )
+ {
+ result = Parser.ReadAncillaryResource((*ri).filePath, FrameBuffer);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ if ( Options.verbose_flag )
+ FrameBuffer.Dump(stderr, Options.fb_dump_size);
+
+ if ( ! Options.no_write_flag )
+ {
+ result = Writer.WriteAncillaryResource(FrameBuffer, Context, HMAC);
+
+ // The Writer class will forward the last block of ciphertext
+ // to the encryption context for use as the IV for the next
+ // frame. If you want to use non-sequitur IV values, un-comment
+ // the following line of code.
+ // if ( ASDCP_SUCCESS(result) && Options.key_flag )
+ // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
+ }
+ }
+ if ( result == RESULT_ENDOFFILE )
+ result = RESULT_OK;
+ }
+
+
+
+ if (ASDCP_SUCCESS(result) && !Options.no_write_flag)
+ result = Writer.Finalize();
+
+ return result;
+}
+
+
+
+
+//------------------------------------------------------------------------------------------
+// PCM essence
// Write one or more plaintext PCM audio streams to a plaintext AS-02 file
// Write one or more plaintext PCM audio streams to a ciphertext AS-02 file
//
return RESULT_FAIL;
}
- // this is the d-cinema MCA label, what is the one for IMF?
+ // This marks all soundfield groups using the same MCA property values
+ MXF::InterchangeObject_list_t::iterator i;
+ for ( i = Options.mca_config.begin(); i != Options.mca_config.end(); ++i )
+ {
+ MXF::SoundfieldGroupLabelSubDescriptor * desc = dynamic_cast<MXF::SoundfieldGroupLabelSubDescriptor*>(*i);
+ if ( desc != 0 )
+ {
+ if ( ! Options.mca_audio_content_kind.empty() )
+ {
+ desc->MCAAudioContentKind = Options.mca_audio_content_kind;
+ }
+ if ( ! Options.mca_audio_element_kind.empty() )
+ {
+ desc->MCAAudioElementKind = Options.mca_audio_element_kind;
+ }
+ }
+ }
+
essence_descriptor->ChannelAssignment = g_dict->ul(MDD_IMFAudioChannelCfg_MCA);
}
}
return result;
}
+//
+bool
+get_current_dms_text_descriptor(AS_02::ISXD::MXFWriter& writer, ASDCP::MXF::GenericStreamTextBasedSet *&text_object)
+{
+ std::list<MXF::InterchangeObject*> object_list;
+ writer.OP1aHeader().GetMDObjectsByType(DefaultSMPTEDict().ul(MDD_GenericStreamTextBasedSet), object_list);
+
+ if ( object_list.empty() )
+ {
+ return false;
+ }
+
+ text_object = dynamic_cast<MXF::GenericStreamTextBasedSet*>(object_list.back());
+ assert(text_object != 0);
+ return true;
+}
+
+
+// Write one or more plaintext Aux Data bytestreams to a plaintext AS-02 file
+// Write one or more plaintext Aux Data bytestreams to a ciphertext AS-02 file
+//
+Result_t
+write_isxd_file(CommandOptions& Options)
+{
+ AESEncContext* Context = 0;
+ HMACContext* HMAC = 0;
+ AS_02::ISXD::MXFWriter Writer;
+ DCData::FrameBuffer FrameBuffer(Options.fb_size);
+ DCData::SequenceParser Parser;
+ byte_t IV_buf[CBC_BLOCK_SIZE];
+ Kumu::FortunaRNG RNG;
+
+ // set up essence parser
+ Result_t result = Parser.OpenRead(Options.filenames.front());
+
+ // set up MXF writer
+ if ( ASDCP_SUCCESS(result) )
+ {
+
+ if ( Options.verbose_flag )
+ {
+ fprintf(stderr, "ISXD Data\n");
+ fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
+ }
+ }
+
+ if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
+ {
+ WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
+ if ( Options.asset_id_flag )
+ memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
+ else
+ Kumu::GenRandomUUID(Info.AssetUUID);
+
+ Info.LabelSetType = LS_MXF_SMPTE;
+
+ // configure encryption
+ if( Options.key_flag )
+ {
+ Kumu::GenRandomUUID(Info.ContextID);
+ Info.EncryptedEssence = true;
+
+ if ( Options.key_id_flag )
+ {
+ memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
+ }
+ else
+ {
+ 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);
+ }
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ if ( Options.isxd_document_namespace == "auto" )
+ {
+ // get ns of first item
+ std::string ns_prefix, type_name, namespace_name;
+ result = Parser.ReadFrame(FrameBuffer);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ Kumu::AttributeList doc_attr_list;
+ result = GetXMLDocType(FrameBuffer.RoData(), FrameBuffer.Size(), ns_prefix, type_name,
+ namespace_name, doc_attr_list) ? RESULT_OK : RESULT_FAIL;
+ }
+
+ if ( ASDCP_SUCCESS(result) && ! namespace_name.empty() )
+ {
+ Options.isxd_document_namespace = namespace_name;
+ }
+ else
+ {
+ fprintf(stderr, "Unable to parse an XML namespace name from the input document.\n");
+ return RESULT_FAIL;
+ }
+ }
+
+ result = Writer.OpenWrite(Options.out_file, Info, Options.isxd_document_namespace, Options.edit_rate);
+ }
+ }
+
+ 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 ( KM_SUCCESS(result) && ! Options.no_write_flag )
+ {
+ ASDCP::FrameBuffer global_metadata;
+ std::list<std::string>::iterator i;
+
+ for ( i = Options.global_isxd_metadata.begin(); i != Options.global_isxd_metadata.end(); ++i )
+ {
+ ui32_t file_size = Kumu::FileSize(*i);
+ result = global_metadata.Capacity(file_size);
+
+ if ( KM_SUCCESS(result) )
+ {
+ ui32_t read_count = 0;
+ Kumu::FileReader Reader;
+ std::string namespace_name;
+
+ result = Reader.OpenRead(*i);
+
+ if ( KM_SUCCESS(result) )
+ {
+ result = Reader.Read(global_metadata.Data(), file_size, &read_count);
+ }
+
+ if ( KM_SUCCESS(result) )
+ {
+ if ( file_size != read_count)
+ return RESULT_READFAIL;
+
+ global_metadata.Size(read_count);
+
+ std::string ns_prefix, type_name;
+ Kumu::AttributeList doc_attr_list;
+ result = GetXMLDocType(global_metadata.RoData(), global_metadata.Size(), ns_prefix, type_name,
+ namespace_name, doc_attr_list) ? RESULT_OK : RESULT_FAIL;
+ }
+
+ if ( KM_SUCCESS(result) )
+ {
+ result = Writer.AddDmsGenericPartUtf8Text(global_metadata, Context, HMAC);
+ }
+
+ if ( KM_SUCCESS(result) )
+ {
+ ASDCP::MXF::GenericStreamTextBasedSet *text_object = 0;
+ get_current_dms_text_descriptor(Writer, text_object);
+ assert(text_object);
+ text_object->TextMIMEMediaType = "text/xml";
+ text_object->TextDataDescription = namespace_name;
+
+ // this is not really useful when inserting multiple objects because
+ // it cannot be set per object without some other CLI syntax for
+ // associating language codes with 2057 blobs, e.g., <filename>:<lang>
+ text_object->RFC5646TextLanguageCode = Options.language;
+ }
+ }
+ }
+
+ if ( KM_SUCCESS(result) )
+ {
+ result = Writer.Finalize();
+ }
+ }
+
+ return result;
+}
//
int
case ESS_JPEG_2000:
result = write_JP2K_file(Options);
break;
-
+ // PB
+ case ::ESS_AS02_ACES:
+ result = write_ACES_file(Options);
+ break;
case ESS_PCM_24b_48k:
case ESS_PCM_24b_96k:
result = write_PCM_file(Options);
result = write_timed_text_file(Options);
break;
+ case ESS_DCDATA_UNKNOWN:
+ if ( ! Options.isxd_document_namespace.empty() )
+ {
+ result = write_isxd_file(Options);
+ }
+ else
+ {
+ fprintf(stderr, "%s: Unknown synchronous data file type, not AS-02-compatible essence.\n",
+ Options.filenames.front().c_str());
+ return 5;
+ }
+ break;
+
default:
fprintf(stderr, "%s: Unknown file type, not AS-02-compatible essence.\n",
Options.filenames.front().c_str());