2 Copyright (c) 2011-2018, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /*! \file as-02-wrap.cpp
31 \brief AS-02 file manipulation utility
33 This program wraps IMF essence (picture or sound) in to an AS-02 MXF file.
35 For more information about AS-02, please refer to the header file AS_02.h
36 For more information about asdcplib, please refer to the header file AS_DCP.h
39 #include <KM_fileio.h>
43 #include <PCMParserList.h>
46 using namespace ASDCP;
48 const ui32_t FRAME_BUFFER_SIZE = 4 * Kumu::Megabyte;
49 const ASDCP::Dictionary *g_dict = 0;
52 RationalToString(const ASDCP::Rational& r, char* buf, const ui32_t& len)
54 snprintf(buf, len, "%d/%d", r.Numerator, r.Denominator);
59 //------------------------------------------------------------------------------------------
61 // command line option parser class
63 static const char* PROGRAM_NAME = "as-02-wrap"; // program name for messages
65 // local program identification info written to file headers
66 class MyInfo : public WriterInfo
71 static byte_t default_ProductUUID_Data[UUIDlen] =
72 { 0x7d, 0x83, 0x6e, 0x16, 0x37, 0xc7, 0x4c, 0x22,
73 0xb2, 0xe0, 0x46, 0xa7, 0x17, 0xe8, 0x4f, 0x42 };
75 memcpy(ProductUUID, default_ProductUUID_Data, UUIDlen);
76 CompanyName = "WidgetCo";
77 ProductName = "as-02-wrap";
78 ProductVersion = ASDCP::Version();
84 // Increment the iterator, test for an additional non-option command line argument.
85 // Causes the caller to return if there are no remaining arguments or if the next
86 // argument begins with '-'.
87 #define TEST_EXTRA_ARG(i,c) \
88 if ( ++i >= argc || argv[(i)][0] == '-' ) { \
89 fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
96 create_random_uuid(byte_t* uuidbuf)
99 GenRandomValue(tmp_id);
100 memcpy(uuidbuf, tmp_id.Value(), tmp_id.Size());
105 banner(FILE* stream = stdout)
108 %s (asdcplib %s)\n\n\
109 Copyright (c) 2011-2018, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst\n\n\
110 asdcplib may be copied only under the terms of the license found at\n\
111 the top of every file in the asdcplib distribution kit.\n\n\
112 Specify the -h (help) option for further information about %s\n\n",
113 PROGRAM_NAME, ASDCP::Version(), PROGRAM_NAME);
118 usage(FILE* stream = stdout)
121 USAGE: %s [-h|-help] [-V]\n\
123 %s [options] <input-file>+ <output-file>\n\n",
124 PROGRAM_NAME, PROGRAM_NAME);
128 -h | -help - Show help\n\
129 -V - Show version information\n\
130 -a <uuid> - Specify the Asset ID of the file\n\
131 -A <w>/<h> - Set aspect ratio for image (default 4/3)\n\
132 -b <buffer-size> - Specify size in bytes of picture frame buffer\n\
133 Defaults to 4,194,304 (4MB)\n\
134 -c <num> - Select the IMF color system to be signaled:\n\
135 Application 2 (2067-20): 1, 2, or 3\n\
136 Application 2e (2067-21): 4 or 5\n\
137 All color system values assume YCbCr; also use -R for RGB\n\
138 -C <ul> - Set ChannelAssignment UL value\n\
139 -d <duration> - Number of frames to process, default all\n\
140 -D <depth> - Component depth for YCbCr images (default: 10)\n\
141 -e - Encrypt JP2K headers (default)\n\
142 -E - Do not encrypt JP2K headers\n\
143 -F (0|1) - Set field dominance for interlaced image (default: 0)\n\
144 -g <rfc-5646-code>\n\
145 - Create MCA labels having the given RFC 5646 language code\n\
146 (requires option \"-m\") -- Also used with -G to set the\n\
147 value of the TextMIMEMediaType property\n\
148 -G <filename> - Filename of XML resource to be carried per RP 2057 Generic\n\
149 Stream. May be issued multiple times.\n\
150 -i - Indicates input essence is interlaced fields (forces -Y)\n\
151 -j <key-id-str> - Write key ID instead of creating a random value\n\
152 -k <key-string> - Use key for ciphertext operations\n\
153 -l <first>,<second>\n\
154 - Integer values that set the VideoLineMap\n\
155 -m <expr> - Write MCA labels using <expr>. Example:\n\
156 51(L,R,C,LFE,Ls,Rs,),HI,VIN\n\
157 -M - Do not create HMAC values when writing\n\
158 -n <UL> - Set the TransferCharacteristic UL\n\
159 -o <min>,<max> - Mastering Display luminance, cd*m*m, e.g., \".05,100\"\n\
160 -O <rx>,<ry>,<gx>,<gy>,<bx>,<by>,<wx>,<wy>\n\
161 - Mastering Display Color Primaries and white point\n\
162 e.g., \".64,.33,.3,.6,.15,.06,.3457,.3585\"\n\
163 -p <ul> - Set broadcast profile\n\
164 -P <string> - Set NamespaceURI property when creating timed text MXF\n\
165 -q <UL> - Set the CodingEquations UL\n\
166 -r <n>/<d> - Edit Rate of the output file. 24/1 is the default\n\
167 -R - Indicates RGB image essence (default except with -c)\n\
168 -s <seconds> - Duration of a frame-wrapped partition (default 60)\n\
169 -t <min> - Set RGB component minimum code value (default: 0)\n\
170 -T <max> - Set RGB component maximum code value (default: 1023)\n\
171 -u - Print UL catalog to stdout\n\
172 -u <URI> - ISXD (RDD47) document URI (use 'auto' to read the\n\
173 namespace name from the first edit unit\n\
174 -v - Verbose, prints informative messages to stderr\n\
175 -W - Read input file only, do not write source file\n\
176 -x <int> - Horizontal subsampling degree (default: 2)\n\
177 -X <int> - Vertical subsampling degree (default: 2)\n\
178 -y <white-ref>[,<black-ref>[,<color-range>]]\n\
179 - Same as -Y but White Ref, Black Ref and Color Range are\n\
180 set from the given argument\n\
181 -Y - Indicates YCbCr image essence (default with -c), uses\n\
182 default values for White Ref, Black Ref and Color Range,\n\
183 940,64,897, indicating 10 bit standard Video Range\n\
184 -z - Fail if j2c inputs have unequal parameters (default)\n\
185 -Z - Ignore unequal parameters in j2c inputs\n\
187 --mca-audio-content-kind <string>\n\
188 - UL value for MCA descriptor MCAAudioContentKind property\n\
189 --mca-audio-element-kind <string>\n\
190 - UL value for MCA descriptor MCAAudioElementKind property\n\
192 NOTES: o There is no option grouping, all options must be distinct arguments.\n\
193 o All option arguments must be separated from the option by whitespace.\n\n");
196 const float chromaticity_scale = 50000.0;
199 set_primary_from_token(const std::string& token, ui16_t& primary)
201 float raw_value = strtod(token.c_str(),0);
203 if ( raw_value == 0.0 || raw_value > 1.0 )
205 fprintf(stderr, "Invalid coordinate value \"%s\".\n", token.c_str());
209 primary = floor(0.5 + ( raw_value * chromaticity_scale ));
213 const float luminance_scale = 10000.0;
216 set_luminance_from_token(const std::string& token, ui32_t& luminance)
218 float raw_value = strtod(token.c_str(),0);
220 if ( raw_value == 0.0 || raw_value > 400000.0 )
222 fprintf(stderr, "Invalid luminance value \"%s\".\n", token.c_str());
226 luminance = floor(0.5 + ( raw_value * luminance_scale ));
230 #define SET_LUMINANCE(p,t) \
231 if ( ! set_luminance_from_token(t, p) ) { \
241 bool error_flag; // true if the given options are in error or not complete
242 bool key_flag; // true if an encryption key was given
243 bool asset_id_flag; // true if an asset ID was given
244 bool encrypt_header_flag; // true if j2c headers are to be encrypted
245 bool write_hmac; // true if HMAC values are to be generated and written
246 bool verbose_flag; // true if the verbose option was selected
247 ui32_t fb_dump_size; // number of bytes of frame buffer to dump
248 bool no_write_flag; // true if no output files are to be written
249 bool version_flag; // true if the version display option was selected
250 bool help_flag; // true if the help display option was selected
251 ui32_t duration; // number of frames to be processed
252 bool j2c_pedantic; // passed to JP2K::SequenceParser::OpenRead
253 bool use_cdci_descriptor; //
254 Rational edit_rate; // edit rate of JP2K sequence
255 ui32_t fb_size; // size of picture frame buffer
256 byte_t key_value[KeyLen]; // value of given encryption key (when key_flag is true)
257 bool key_id_flag; // true if a key ID was given
258 byte_t key_id_value[UUIDlen];// value of given key ID (when key_id_flag is true)
259 byte_t asset_id_value[UUIDlen];// value of asset ID (when asset_id_flag is true)
260 bool show_ul_values_flag; // if true, dump the UL table before going tp work.
261 Kumu::PathList_t filenames; // list of filenames to be processed
263 UL channel_assignment, picture_coding, transfer_characteristic, color_primaries, coding_equations;
264 ASDCP::MXF::AS02_MCAConfigParser mca_config;
265 std::string language;
270 ui32_t horizontal_subsampling;
271 ui32_t vertical_subsampling;
272 ui32_t component_depth;
274 ASDCP::Rational aspect_ratio;
275 ui8_t field_dominance;
276 ui32_t mxf_header_size;
277 ui32_t cdci_BlackRefLevel;
278 ui32_t cdci_WhiteRefLevel;
279 ui32_t cdci_ColorRange;
281 ui32_t md_min_luminance, md_max_luminance;
282 ASDCP::MXF::ThreeColorPrimaries md_primaries;
283 ASDCP::MXF::ColorPrimary md_white_point;
285 //new attributes for AS-02 support
286 AS_02::IndexStrategy_t index_strategy; //Shim parameter index_strategy_frame/clip
287 ui32_t partition_space; //Shim parameter partition_spacing
290 std::string isxd_document_namespace;
291 std::list<std::string> global_isxd_metadata;
294 MXF::LineMapPair line_map;
296 std::string out_file, profile_name; //
297 std::string mca_audio_element_kind, mca_audio_content_kind;
300 bool set_video_line_map(const std::string& arg)
302 const char* sep_str = strrchr(arg.c_str(), ',');
306 fprintf(stderr, "Expecting <first>,<second>\n");
310 line_map.First = Kumu::xabs(strtol(arg.c_str(), 0, 10));
311 line_map.Second = Kumu::xabs(strtol(sep_str+1, 0, 10));
316 bool set_video_ref(const std::string& arg)
318 std::list<std::string> ref_tokens = Kumu::km_token_split(arg, ",");
320 switch ( ref_tokens.size() )
323 cdci_ColorRange = Kumu::xabs(strtol(ref_tokens.back().c_str(), 0, 10));
324 ref_tokens.pop_back();
326 cdci_BlackRefLevel = Kumu::xabs(strtol(ref_tokens.back().c_str(), 0, 10));
327 ref_tokens.pop_back();
329 cdci_WhiteRefLevel = Kumu::xabs(strtol(ref_tokens.back().c_str(), 0, 10));
333 fprintf(stderr, "Expecting <white-ref>[,<black-ref>[,<color-range>]]\n");
337 if ( cdci_WhiteRefLevel > 65535 || cdci_BlackRefLevel > 65535 || cdci_ColorRange > 65535 )
339 fprintf(stderr, "Unexpected CDCI video referece levels.\n");
347 bool set_display_primaries(const std::string& arg)
349 std::list<std::string> coordinate_tokens = Kumu::km_token_split(arg, ",");
350 if ( coordinate_tokens.size() != 8 )
352 fprintf(stderr, "Expecting four coordinate pairs.\n");
356 std::list<std::string>::const_iterator i = coordinate_tokens.begin();
357 if ( ! set_primary_from_token(*(i++), md_primaries.First.X) ) return false;
358 if ( ! set_primary_from_token(*(i++), md_primaries.First.Y) ) return false;
359 if ( ! set_primary_from_token(*(i++), md_primaries.Second.X) ) return false;
360 if ( ! set_primary_from_token(*(i++), md_primaries.Second.Y) ) return false;
361 if ( ! set_primary_from_token(*(i++), md_primaries.Third.X) ) return false;
362 if ( ! set_primary_from_token(*(i++), md_primaries.Third.Y) ) return false;
363 if ( ! set_primary_from_token(*(i++), md_white_point.X) ) return false;
364 if ( ! set_primary_from_token(*i, md_white_point.Y) ) return false;
370 bool set_display_luminance(const std::string& arg)
372 std::list<std::string> luminance_tokens = Kumu::km_token_split(arg, ",");
373 if ( luminance_tokens.size() != 2 )
375 fprintf(stderr, "Expecting a luminance pair.\n");
379 if ( ! set_luminance_from_token(luminance_tokens.front(), md_min_luminance) ) return false;
380 if ( ! set_luminance_from_token(luminance_tokens.back(), md_max_luminance) ) return false;
386 bool set_color_system_from_arg(const char* arg)
392 // Application 2 (ST 2067-20)
394 coding_equations = g_dict->ul(MDD_CodingEquations_601);
395 transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_709);
396 color_primaries = g_dict->ul(MDD_ColorPrimaries_ITU470_PAL);
397 use_cdci_descriptor = true;
401 coding_equations = g_dict->ul(MDD_CodingEquations_601);
402 transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_709);
403 color_primaries = g_dict->ul(MDD_ColorPrimaries_SMPTE170M);
404 use_cdci_descriptor = true;
408 coding_equations = g_dict->ul(MDD_CodingEquations_709);
409 transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_709);
410 color_primaries = g_dict->ul(MDD_ColorPrimaries_BT709);
411 use_cdci_descriptor = true;
414 // Application 2e (ST 2067-21)
416 coding_equations = g_dict->ul(MDD_CodingEquations_709);
417 transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_xvYCC);
418 color_primaries = g_dict->ul(MDD_ColorPrimaries_BT709);
419 use_cdci_descriptor = true;
423 coding_equations = g_dict->ul(MDD_CodingEquations_709);
424 transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_2020);
425 color_primaries = g_dict->ul(MDD_ColorPrimaries_BT2020);
426 use_cdci_descriptor = true;
430 fprintf(stderr, "Unrecognized color system number, expecting one of 1-5.\n");
437 CommandOptions(int argc, const char** argv) :
438 error_flag(true), key_flag(false), key_id_flag(false), asset_id_flag(false),
439 encrypt_header_flag(true), write_hmac(true), verbose_flag(false), fb_dump_size(0),
440 no_write_flag(false), version_flag(false), help_flag(false),
441 duration(0xffffffff), j2c_pedantic(true), use_cdci_descriptor(false),
442 edit_rate(24,1), fb_size(FRAME_BUFFER_SIZE),
443 show_ul_values_flag(false), index_strategy(AS_02::IS_FOLLOW), partition_space(60),
444 mca_config(g_dict), rgba_MaxRef(1023), rgba_MinRef(0),
445 horizontal_subsampling(2), vertical_subsampling(2), component_depth(10),
446 frame_layout(0), aspect_ratio(ASDCP::Rational(4,3)), field_dominance(0),
447 mxf_header_size(16384), cdci_WhiteRefLevel(940), cdci_BlackRefLevel(64), cdci_ColorRange(897),
448 md_min_luminance(0), md_max_luminance(0), line_map(0,0), line_map_flag(false)
450 memset(key_value, 0, KeyLen);
451 memset(key_id_value, 0, UUIDlen);
453 coding_equations = g_dict->ul(MDD_CodingEquations_709);
454 color_primaries = g_dict->ul(MDD_ColorPrimaries_BT709);
455 transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_709);
456 std::string mca_config_str;
458 for ( int i = 1; i < argc; i++ )
461 if ( (strcmp( argv[i], "-help") == 0) )
467 if ( argv[i][0] == '-'
468 && ( isalpha(argv[i][1]) || isdigit(argv[i][1]) )
471 switch ( argv[i][1] )
474 TEST_EXTRA_ARG(i, 'A');
475 if ( ! DecodeRational(argv[i], aspect_ratio) )
477 fprintf(stderr, "Error decoding aspect ratio value: %s\n", argv[i]);
483 asset_id_flag = true;
484 TEST_EXTRA_ARG(i, 'a');
487 Kumu::hex2bin(argv[i], asset_id_value, UUIDlen, &length);
489 if ( length != UUIDlen )
491 fprintf(stderr, "Unexpected asset ID length: %u, expecting %u characters.\n", length, UUIDlen);
498 TEST_EXTRA_ARG(i, 'b');
499 fb_size = Kumu::xabs(strtol(argv[i], 0, 10));
502 fprintf(stderr, "Frame Buffer size: %u bytes.\n", fb_size);
507 TEST_EXTRA_ARG(i, 'c');
508 if ( ! set_color_system_from_arg(argv[i]) )
515 TEST_EXTRA_ARG(i, 'C');
516 if ( ! channel_assignment.DecodeHex(argv[i]) )
518 fprintf(stderr, "Error decoding ChannelAssignment UL value: %s\n", argv[i]);
524 TEST_EXTRA_ARG(i, 'D');
525 component_depth = Kumu::xabs(strtol(argv[i], 0, 10));
529 TEST_EXTRA_ARG(i, 'd');
530 duration = Kumu::xabs(strtol(argv[i], 0, 10));
533 case 'E': encrypt_header_flag = false; break;
534 case 'e': encrypt_header_flag = true; break;
537 TEST_EXTRA_ARG(i, 'F');
538 field_dominance = Kumu::xabs(strtol(argv[i], 0, 10));
539 if ( field_dominance > 1 )
541 fprintf(stderr, "Field dominance value must be \"0\" or \"1\"\n");
547 TEST_EXTRA_ARG(i, 'g');
552 TEST_EXTRA_ARG(i, 'G');
553 global_isxd_metadata.push_back(argv[i]);
556 case 'h': help_flag = true; break;
560 use_cdci_descriptor = true;
565 TEST_EXTRA_ARG(i, 'j');
568 Kumu::hex2bin(argv[i], key_id_value, UUIDlen, &length);
570 if ( length != UUIDlen )
572 fprintf(stderr, "Unexpected key ID length: %u, expecting %u characters.\n", length, UUIDlen);
578 case 'k': key_flag = true;
579 TEST_EXTRA_ARG(i, 'k');
582 Kumu::hex2bin(argv[i], key_value, KeyLen, &length);
584 if ( length != KeyLen )
586 fprintf(stderr, "Unexpected key length: %u, expecting %u characters.\n", length, KeyLen);
593 TEST_EXTRA_ARG(i, 'y');
594 if ( ! set_video_line_map(argv[i]) )
598 line_map_flag = true;
602 case 'M': write_hmac = false; break;
605 TEST_EXTRA_ARG(i, 'm');
606 mca_config_str = argv[i];
610 TEST_EXTRA_ARG(i, 'n');
611 if ( ! transfer_characteristic.DecodeHex(argv[i]) )
613 fprintf(stderr, "Error decoding TransferCharacteristic UL value: %s\n", argv[i]);
619 TEST_EXTRA_ARG(i, 'O');
620 if ( ! set_display_primaries(argv[i]) )
627 TEST_EXTRA_ARG(i, 'o');
628 if ( ! set_display_luminance(argv[i]) )
635 TEST_EXTRA_ARG(i, 'P');
636 profile_name = argv[i];
640 TEST_EXTRA_ARG(i, 'p');
641 if ( ! picture_coding.DecodeHex(argv[i]) )
643 fprintf(stderr, "Error decoding PictureEssenceCoding UL value: %s\n", argv[i]);
649 TEST_EXTRA_ARG(i, 'q');
650 if ( ! coding_equations.DecodeHex(argv[i]) )
652 fprintf(stderr, "Error decoding CodingEquations UL value: %s\n", argv[i]);
658 TEST_EXTRA_ARG(i, 'r');
659 if ( ! DecodeRational(argv[i], edit_rate) )
661 fprintf(stderr, "Error decoding edit rate value: %s\n", argv[i]);
668 use_cdci_descriptor = false;
672 TEST_EXTRA_ARG(i, 's');
673 partition_space = Kumu::xabs(strtol(argv[i], 0, 10));
677 TEST_EXTRA_ARG(i, 't');
678 rgba_MinRef = Kumu::xabs(strtol(argv[i], 0, 10));
682 TEST_EXTRA_ARG(i, 'T');
683 rgba_MaxRef = Kumu::xabs(strtol(argv[i], 0, 10));
686 case 'u': show_ul_values_flag = true; break;
689 TEST_EXTRA_ARG(i, 'U');
690 isxd_document_namespace = argv[i];
693 case 'V': version_flag = true; break;
694 case 'v': verbose_flag = true; break;
695 case 'W': no_write_flag = true; break;
698 TEST_EXTRA_ARG(i, 'x');
699 horizontal_subsampling = Kumu::xabs(strtol(argv[i], 0, 10));
703 TEST_EXTRA_ARG(i, 'X');
704 vertical_subsampling = Kumu::xabs(strtol(argv[i], 0, 10));
708 use_cdci_descriptor = true;
709 // default 10 bit video range YUV, ref levels already set
713 // Use values provided as argument, sharp tool, be careful
714 use_cdci_descriptor = true;
715 TEST_EXTRA_ARG(i, 'y');
716 if ( ! set_video_ref(argv[i]) )
722 case 'Z': j2c_pedantic = false; break;
723 case 'z': j2c_pedantic = true; break;
726 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
730 else if ( argv[i][0] == '-' && argv[i][1] == '-' && isalpha(argv[i][2]) )
732 if ( strcmp(argv[i]+2, "mca-audio-content-kind") == 0 )
734 if ( ++i >= argc || argv[(i)][0] == '-' )
736 fprintf(stderr, "Argument not found for option -mca-audio-content-kind.\n");
740 mca_audio_content_kind = argv[i];
742 else if ( strcmp(argv[i]+2, "mca-audio-element-kind") == 0 )
744 if ( ++i >= argc || argv[(i)][0] == '-' )
746 fprintf(stderr, "Argument not found for option -mca-audio-element-kind.\n");
750 mca_audio_element_kind = argv[i];
754 fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
760 if ( argv[i][0] != '-' )
762 filenames.push_back(argv[i]);
766 fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
772 if ( ! mca_config_str.empty() )
774 if ( language.empty() )
776 if ( ! mca_config.DecodeString(mca_config_str) )
783 if ( ! mca_config.DecodeString(mca_config_str, language) )
790 if ( help_flag || version_flag || show_ul_values_flag )
795 if ( filenames.size() < 2 )
797 fputs("Option requires at least two filename arguments: <input-file> <output-file>\n", stderr);
801 out_file = filenames.back();
802 filenames.pop_back();
804 if ( ! picture_coding.HasValue() )
806 picture_coding = UL(g_dict->ul(MDD_JP2KEssenceCompression_BroadcastProfile_1));
814 //------------------------------------------------------------------------------------------
818 Result_t JP2K_PDesc_to_MD(const ASDCP::JP2K::PictureDescriptor& PDesc,
819 const ASDCP::Dictionary& dict,
820 ASDCP::MXF::GenericPictureEssenceDescriptor& GenericPictureEssenceDescriptor,
821 ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor);
823 Result_t PCM_ADesc_to_MD(ASDCP::PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj);
826 // Write one or more plaintext JPEG 2000 codestreams to a plaintext AS-02 file
827 // Write one or more plaintext JPEG 2000 codestreams to a ciphertext AS-02 file
830 write_JP2K_file(CommandOptions& Options)
832 AESEncContext* Context = 0;
833 HMACContext* HMAC = 0;
834 AS_02::JP2K::MXFWriter Writer;
835 JP2K::FrameBuffer FrameBuffer(Options.fb_size);
836 JP2K::SequenceParser Parser;
837 byte_t IV_buf[CBC_BLOCK_SIZE];
838 Kumu::FortunaRNG RNG;
839 ASDCP::MXF::FileDescriptor *essence_descriptor = 0;
840 ASDCP::MXF::InterchangeObject_list_t essence_sub_descriptors;
842 // set up essence parser
843 Result_t result = Parser.OpenRead(Options.filenames.front().c_str(), Options.j2c_pedantic);
846 if ( ASDCP_SUCCESS(result) )
848 ASDCP::JP2K::PictureDescriptor PDesc;
849 Parser.FillPictureDescriptor(PDesc);
850 PDesc.EditRate = Options.edit_rate;
852 if ( Options.verbose_flag )
854 fprintf(stderr, "JPEG 2000 pictures\n");
855 fputs("PictureDescriptor:\n", stderr);
856 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
857 JP2K::PictureDescriptorDump(PDesc);
860 if ( Options.use_cdci_descriptor )
862 ASDCP::MXF::CDCIEssenceDescriptor* tmp_dscr = new ASDCP::MXF::CDCIEssenceDescriptor(g_dict);
863 essence_sub_descriptors.push_back(new ASDCP::MXF::JPEG2000PictureSubDescriptor(g_dict));
865 result = ASDCP::JP2K_PDesc_to_MD(PDesc, *g_dict,
866 *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr),
867 *static_cast<ASDCP::MXF::JPEG2000PictureSubDescriptor*>(essence_sub_descriptors.back()));
869 if ( ASDCP_SUCCESS(result) )
871 tmp_dscr->CodingEquations = Options.coding_equations;
872 tmp_dscr->TransferCharacteristic = Options.transfer_characteristic;
873 tmp_dscr->ColorPrimaries = Options.color_primaries;
874 tmp_dscr->PictureEssenceCoding = Options.picture_coding;
875 tmp_dscr->HorizontalSubsampling = Options.horizontal_subsampling;
876 tmp_dscr->VerticalSubsampling = Options.vertical_subsampling;
877 tmp_dscr->ComponentDepth = Options.component_depth;
878 tmp_dscr->FrameLayout = Options.frame_layout;
879 tmp_dscr->AspectRatio = Options.aspect_ratio;
880 tmp_dscr->FieldDominance = Options.field_dominance;
881 tmp_dscr->WhiteReflevel = Options.cdci_WhiteRefLevel;
882 tmp_dscr->BlackRefLevel = Options.cdci_BlackRefLevel;
883 tmp_dscr->ColorRange = Options.cdci_ColorRange;
884 if (Options.line_map_flag) tmp_dscr->VideoLineMap = Options.line_map;
886 if ( Options.md_min_luminance || Options.md_max_luminance )
888 tmp_dscr->MasteringDisplayMinimumLuminance = Options.md_min_luminance;
889 tmp_dscr->MasteringDisplayMaximumLuminance = Options.md_max_luminance;
892 if ( Options.md_primaries.HasValue() )
894 tmp_dscr->MasteringDisplayPrimaries = Options.md_primaries;
895 tmp_dscr->MasteringDisplayWhitePointChromaticity = Options.md_white_point;
898 essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr);
903 ASDCP::MXF::RGBAEssenceDescriptor* tmp_dscr = new ASDCP::MXF::RGBAEssenceDescriptor(g_dict);
904 essence_sub_descriptors.push_back(new ASDCP::MXF::JPEG2000PictureSubDescriptor(g_dict));
906 result = ASDCP::JP2K_PDesc_to_MD(PDesc, *g_dict,
907 *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr),
908 *static_cast<ASDCP::MXF::JPEG2000PictureSubDescriptor*>(essence_sub_descriptors.back()));
910 if ( ASDCP_SUCCESS(result) )
912 tmp_dscr->CodingEquations = Options.coding_equations;
913 tmp_dscr->TransferCharacteristic = Options.transfer_characteristic;
914 tmp_dscr->ColorPrimaries = Options.color_primaries;
915 tmp_dscr->ScanningDirection = 0;
916 tmp_dscr->PictureEssenceCoding = Options.picture_coding;
917 tmp_dscr->ComponentMaxRef = Options.rgba_MaxRef;
918 tmp_dscr->ComponentMinRef = Options.rgba_MinRef;
919 if (Options.line_map_flag) tmp_dscr->VideoLineMap = Options.line_map;
921 if ( Options.md_min_luminance || Options.md_max_luminance )
923 tmp_dscr->MasteringDisplayMinimumLuminance = Options.md_min_luminance;
924 tmp_dscr->MasteringDisplayMaximumLuminance = Options.md_max_luminance;
927 if ( Options.md_primaries.HasValue() )
929 tmp_dscr->MasteringDisplayPrimaries = Options.md_primaries;
930 tmp_dscr->MasteringDisplayWhitePointChromaticity = Options.md_white_point;
933 essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr);
938 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
940 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
941 Info.LabelSetType = LS_MXF_SMPTE;
943 if ( Options.asset_id_flag )
944 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
946 Kumu::GenRandomUUID(Info.AssetUUID);
948 // configure encryption
949 if( Options.key_flag )
951 Kumu::GenRandomUUID(Info.ContextID);
952 Info.EncryptedEssence = true;
954 if ( Options.key_id_flag )
956 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
960 create_random_uuid(Info.CryptographicKeyID);
963 Context = new AESEncContext;
964 result = Context->InitKey(Options.key_value);
966 if ( ASDCP_SUCCESS(result) )
967 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
969 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
971 Info.UsesHMAC = true;
972 HMAC = new HMACContext;
973 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
977 if ( ASDCP_SUCCESS(result) )
979 result = Writer.OpenWrite(Options.out_file, Info, essence_descriptor, essence_sub_descriptors,
980 Options.edit_rate, Options.mxf_header_size, Options.index_strategy, Options.partition_space);
984 if ( ASDCP_SUCCESS(result) )
987 result = Parser.Reset();
989 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
991 result = Parser.ReadFrame(FrameBuffer);
993 if ( ASDCP_SUCCESS(result) )
995 if ( Options.verbose_flag )
996 FrameBuffer.Dump(stderr, Options.fb_dump_size);
998 if ( Options.encrypt_header_flag )
999 FrameBuffer.PlaintextOffset(0);
1002 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1004 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);
1006 // The Writer class will forward the last block of ciphertext
1007 // to the encryption context for use as the IV for the next
1008 // frame. If you want to use non-sequitur IV values, un-comment
1009 // the following line of code.
1010 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
1011 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1015 if ( result == RESULT_ENDOFFILE )
1019 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1020 result = Writer.Finalize();
1025 //------------------------------------------------------------------------------------------
1027 // Write one or more plaintext PCM audio streams to a plaintext AS-02 file
1028 // Write one or more plaintext PCM audio streams to a ciphertext AS-02 file
1031 write_PCM_file(CommandOptions& Options)
1033 AESEncContext* Context = 0;
1034 HMACContext* HMAC = 0;
1035 PCMParserList Parser;
1036 AS_02::PCM::MXFWriter Writer;
1037 PCM::FrameBuffer FrameBuffer;
1038 byte_t IV_buf[CBC_BLOCK_SIZE];
1039 Kumu::FortunaRNG RNG;
1040 ASDCP::MXF::WaveAudioDescriptor *essence_descriptor = 0;
1042 // set up essence parser
1043 Result_t result = Parser.OpenRead(Options.filenames, Options.edit_rate);
1045 // set up MXF writer
1046 if ( ASDCP_SUCCESS(result) )
1048 ASDCP::PCM::AudioDescriptor ADesc;
1049 Parser.FillAudioDescriptor(ADesc);
1051 ADesc.EditRate = Options.edit_rate;
1052 FrameBuffer.Capacity(PCM::CalcFrameBufferSize(ADesc));
1054 if ( Options.verbose_flag )
1057 fprintf(stderr, "%.1fkHz PCM Audio, %s fps (%u spf)\n",
1058 ADesc.AudioSamplingRate.Quotient() / 1000.0,
1059 RationalToString(Options.edit_rate, buf, 64),
1060 PCM::CalcSamplesPerFrame(ADesc));
1061 fputs("AudioDescriptor:\n", stderr);
1062 PCM::AudioDescriptorDump(ADesc);
1065 essence_descriptor = new ASDCP::MXF::WaveAudioDescriptor(g_dict);
1067 result = ASDCP::PCM_ADesc_to_MD(ADesc, essence_descriptor);
1069 if ( Options.mca_config.empty() )
1071 essence_descriptor->ChannelAssignment = Options.channel_assignment;
1075 if ( Options.mca_config.ChannelCount() != essence_descriptor->ChannelCount )
1077 fprintf(stderr, "MCA label count (%d) differs from essence stream channel count (%d).\n",
1078 Options.mca_config.ChannelCount(), essence_descriptor->ChannelCount);
1082 // This marks all soundfield groups using the same MCA property values
1083 MXF::InterchangeObject_list_t::iterator i;
1084 for ( i = Options.mca_config.begin(); i != Options.mca_config.end(); ++i )
1086 MXF::SoundfieldGroupLabelSubDescriptor * desc = dynamic_cast<MXF::SoundfieldGroupLabelSubDescriptor*>(*i);
1089 if ( ! Options.mca_audio_content_kind.empty() )
1091 desc->MCAAudioContentKind = Options.mca_audio_content_kind;
1093 if ( ! Options.mca_audio_element_kind.empty() )
1095 desc->MCAAudioElementKind = Options.mca_audio_element_kind;
1100 essence_descriptor->ChannelAssignment = g_dict->ul(MDD_IMFAudioChannelCfg_MCA);
1104 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1106 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
1107 Info.LabelSetType = LS_MXF_SMPTE;
1109 if ( Options.asset_id_flag )
1110 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
1112 Kumu::GenRandomUUID(Info.AssetUUID);
1114 // configure encryption
1115 if( Options.key_flag )
1117 Kumu::GenRandomUUID(Info.ContextID);
1118 Info.EncryptedEssence = true;
1120 if ( Options.key_id_flag )
1122 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
1126 create_random_uuid(Info.CryptographicKeyID);
1129 Context = new AESEncContext;
1130 result = Context->InitKey(Options.key_value);
1132 if ( ASDCP_SUCCESS(result) )
1133 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1135 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
1137 Info.UsesHMAC = true;
1138 HMAC = new HMACContext;
1139 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
1143 if ( ASDCP_SUCCESS(result) )
1145 result = Writer.OpenWrite(Options.out_file.c_str(), Info, essence_descriptor,
1146 Options.mca_config, Options.edit_rate);
1150 if ( ASDCP_SUCCESS(result) )
1152 result = Parser.Reset();
1153 ui32_t duration = 0;
1155 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
1157 result = Parser.ReadFrame(FrameBuffer);
1159 if ( ASDCP_SUCCESS(result) )
1161 if ( Options.verbose_flag )
1162 FrameBuffer.Dump(stderr, Options.fb_dump_size);
1164 if ( ! Options.no_write_flag )
1166 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);
1168 // The Writer class will forward the last block of ciphertext
1169 // to the encryption context for use as the IV for the next
1170 // frame. If you want to use non-sequitur IV values, un-comment
1171 // the following line of code.
1172 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
1173 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1178 if ( result == RESULT_ENDOFFILE )
1182 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1183 result = Writer.Finalize();
1191 //------------------------------------------------------------------------------------------
1192 // TimedText essence
1195 // Write one or more plaintext timed text streams to a plaintext AS-02 file
1196 // Write one or more plaintext timed text streams to a ciphertext AS-02 file
1199 write_timed_text_file(CommandOptions& Options)
1201 AESEncContext* Context = 0;
1202 HMACContext* HMAC = 0;
1203 AS_02::TimedText::ST2052_TextParser Parser;
1204 AS_02::TimedText::MXFWriter Writer;
1205 TimedText::FrameBuffer FrameBuffer;
1206 TimedText::TimedTextDescriptor TDesc;
1207 byte_t IV_buf[CBC_BLOCK_SIZE];
1208 Kumu::FortunaRNG RNG;
1210 // set up essence parser
1211 Result_t result = Parser.OpenRead(Options.filenames.front());
1213 // set up MXF writer
1214 if ( ASDCP_SUCCESS(result) )
1216 Parser.FillTimedTextDescriptor(TDesc);
1217 TDesc.EditRate = Options.edit_rate;
1218 TDesc.ContainerDuration = Options.duration;
1219 FrameBuffer.Capacity(Options.fb_size);
1221 if ( ! Options.profile_name.empty() )
1223 TDesc.NamespaceName = Options.profile_name;
1226 if ( Options.verbose_flag )
1228 fputs("IMF Timed-Text Descriptor:\n", stderr);
1229 TimedText::DescriptorDump(TDesc);
1233 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1235 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
1236 Info.LabelSetType = LS_MXF_SMPTE;
1238 if ( Options.asset_id_flag )
1239 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
1241 Kumu::GenRandomUUID(Info.AssetUUID);
1243 // configure encryption
1244 if( Options.key_flag )
1246 Kumu::GenRandomUUID(Info.ContextID);
1247 Info.EncryptedEssence = true;
1249 if ( Options.key_id_flag )
1251 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
1255 create_random_uuid(Info.CryptographicKeyID);
1258 Context = new AESEncContext;
1259 result = Context->InitKey(Options.key_value);
1261 if ( ASDCP_SUCCESS(result) )
1262 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1264 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
1266 Info.UsesHMAC = true;
1267 HMAC = new HMACContext;
1268 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
1272 if ( ASDCP_SUCCESS(result) )
1273 result = Writer.OpenWrite(Options.out_file.c_str(), Info, TDesc);
1276 if ( ASDCP_FAILURE(result) )
1280 TimedText::ResourceList_t::const_iterator ri;
1282 result = Parser.ReadTimedTextResource(XMLDoc);
1284 if ( ASDCP_SUCCESS(result) )
1285 result = Writer.WriteTimedTextResource(XMLDoc, Context, HMAC);
1287 for ( ri = TDesc.ResourceList.begin() ; ri != TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ )
1289 result = Parser.ReadAncillaryResource((*ri).ResourceID, FrameBuffer);
1291 if ( ASDCP_SUCCESS(result) )
1293 if ( Options.verbose_flag )
1294 FrameBuffer.Dump(stderr, Options.fb_dump_size);
1296 if ( ! Options.no_write_flag )
1298 result = Writer.WriteAncillaryResource(FrameBuffer, Context, HMAC);
1300 // The Writer class will forward the last block of ciphertext
1301 // to the encryption context for use as the IV for the next
1302 // frame. If you want to use non-sequitur IV values, un-comment
1303 // the following line of code.
1304 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
1305 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1309 if ( result == RESULT_ENDOFFILE )
1313 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1314 result = Writer.Finalize();
1321 get_current_dms_text_descriptor(AS_02::ISXD::MXFWriter& writer, ASDCP::MXF::GenericStreamTextBasedSet *&text_object)
1323 std::list<MXF::InterchangeObject*> object_list;
1324 writer.OP1aHeader().GetMDObjectsByType(DefaultSMPTEDict().ul(MDD_GenericStreamTextBasedSet), object_list);
1326 if ( object_list.empty() )
1331 text_object = dynamic_cast<MXF::GenericStreamTextBasedSet*>(object_list.back());
1332 assert(text_object != 0);
1337 // Write one or more plaintext Aux Data bytestreams to a plaintext AS-02 file
1338 // Write one or more plaintext Aux Data bytestreams to a ciphertext AS-02 file
1341 write_isxd_file(CommandOptions& Options)
1343 AESEncContext* Context = 0;
1344 HMACContext* HMAC = 0;
1345 AS_02::ISXD::MXFWriter Writer;
1346 DCData::FrameBuffer FrameBuffer(Options.fb_size);
1347 DCData::SequenceParser Parser;
1348 byte_t IV_buf[CBC_BLOCK_SIZE];
1349 Kumu::FortunaRNG RNG;
1351 // set up essence parser
1352 Result_t result = Parser.OpenRead(Options.filenames.front());
1354 // set up MXF writer
1355 if ( ASDCP_SUCCESS(result) )
1358 if ( Options.verbose_flag )
1360 fprintf(stderr, "ISXD Data\n");
1361 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
1365 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1367 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
1368 if ( Options.asset_id_flag )
1369 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
1371 Kumu::GenRandomUUID(Info.AssetUUID);
1373 Info.LabelSetType = LS_MXF_SMPTE;
1375 // configure encryption
1376 if( Options.key_flag )
1378 Kumu::GenRandomUUID(Info.ContextID);
1379 Info.EncryptedEssence = true;
1381 if ( Options.key_id_flag )
1383 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
1387 create_random_uuid(Info.CryptographicKeyID);
1390 Context = new AESEncContext;
1391 result = Context->InitKey(Options.key_value);
1393 if ( ASDCP_SUCCESS(result) )
1394 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1396 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
1398 Info.UsesHMAC = true;
1399 HMAC = new HMACContext;
1400 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
1404 if ( ASDCP_SUCCESS(result) )
1406 if ( Options.isxd_document_namespace == "auto" )
1408 // get ns of first item
1409 std::string ns_prefix, type_name, namespace_name;
1410 result = Parser.ReadFrame(FrameBuffer);
1412 if ( ASDCP_SUCCESS(result) )
1414 Kumu::AttributeList doc_attr_list;
1415 result = GetXMLDocType(FrameBuffer.RoData(), FrameBuffer.Size(), ns_prefix, type_name,
1416 namespace_name, doc_attr_list) ? RESULT_OK : RESULT_FAIL;
1419 if ( ASDCP_SUCCESS(result) && ! namespace_name.empty() )
1421 Options.isxd_document_namespace = namespace_name;
1425 fprintf(stderr, "Unable to parse an XML namespace name from the input document.\n");
1430 result = Writer.OpenWrite(Options.out_file, Info, Options.isxd_document_namespace, Options.edit_rate);
1434 if ( ASDCP_SUCCESS(result) )
1436 ui32_t duration = 0;
1437 result = Parser.Reset();
1439 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
1441 result = Parser.ReadFrame(FrameBuffer);
1443 if ( ASDCP_SUCCESS(result) )
1445 if ( Options.verbose_flag )
1446 FrameBuffer.Dump(stderr, Options.fb_dump_size);
1448 if ( Options.encrypt_header_flag )
1449 FrameBuffer.PlaintextOffset(0);
1452 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1454 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);
1456 // The Writer class will forward the last block of ciphertext
1457 // to the encryption context for use as the IV for the next
1458 // frame. If you want to use non-sequitur IV values, un-comment
1459 // the following line of code.
1460 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
1461 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1465 if ( result == RESULT_ENDOFFILE )
1471 if ( KM_SUCCESS(result) && ! Options.no_write_flag )
1473 ASDCP::FrameBuffer global_metadata;
1474 std::list<std::string>::iterator i;
1476 for ( i = Options.global_isxd_metadata.begin(); i != Options.global_isxd_metadata.end(); ++i )
1478 ui32_t file_size = Kumu::FileSize(*i);
1479 result = global_metadata.Capacity(file_size);
1481 if ( KM_SUCCESS(result) )
1483 ui32_t read_count = 0;
1484 Kumu::FileReader Reader;
1485 std::string namespace_name;
1487 result = Reader.OpenRead(*i);
1489 if ( KM_SUCCESS(result) )
1491 result = Reader.Read(global_metadata.Data(), file_size, &read_count);
1494 if ( KM_SUCCESS(result) )
1496 if ( file_size != read_count)
1497 return RESULT_READFAIL;
1499 global_metadata.Size(read_count);
1501 std::string ns_prefix, type_name;
1502 Kumu::AttributeList doc_attr_list;
1503 result = GetXMLDocType(global_metadata.RoData(), global_metadata.Size(), ns_prefix, type_name,
1504 namespace_name, doc_attr_list) ? RESULT_OK : RESULT_FAIL;
1507 if ( KM_SUCCESS(result) )
1509 result = Writer.AddDmsGenericPartUtf8Text(global_metadata, Context, HMAC);
1512 if ( KM_SUCCESS(result) )
1514 ASDCP::MXF::GenericStreamTextBasedSet *text_object = 0;
1515 get_current_dms_text_descriptor(Writer, text_object);
1516 assert(text_object);
1517 text_object->TextMIMEMediaType = "text/xml";
1518 text_object->TextDataDescription = namespace_name;
1520 // this is not really useful when inserting multiple objects because
1521 // it cannot be set per object without some other CLI syntax for
1522 // associating language codes with 2057 blobs, e.g., <filename>:<lang>
1523 text_object->RFC5646TextLanguageCode = Options.language;
1528 if ( KM_SUCCESS(result) )
1530 result = Writer.Finalize();
1539 main(int argc, const char** argv)
1541 Result_t result = RESULT_OK;
1543 g_dict = &ASDCP::DefaultSMPTEDict();
1546 CommandOptions Options(argc, argv);
1548 if ( Options.version_flag )
1551 if ( Options.help_flag )
1554 if ( Options.show_ul_values_flag )
1556 g_dict->Dump(stdout);
1559 if ( Options.version_flag || Options.help_flag || Options.show_ul_values_flag )
1562 if ( Options.error_flag )
1564 fprintf(stderr, "There was a problem. Type %s -h for help.\n", PROGRAM_NAME);
1568 EssenceType_t EssenceType;
1569 result = ASDCP::RawEssenceType(Options.filenames.front().c_str(), EssenceType);
1571 if ( ASDCP_SUCCESS(result) )
1573 switch ( EssenceType )
1576 result = write_JP2K_file(Options);
1579 case ESS_PCM_24b_48k:
1580 case ESS_PCM_24b_96k:
1581 result = write_PCM_file(Options);
1584 case ESS_TIMED_TEXT:
1585 result = write_timed_text_file(Options);
1588 case ESS_DCDATA_UNKNOWN:
1589 if ( ! Options.isxd_document_namespace.empty() )
1591 result = write_isxd_file(Options);
1595 fprintf(stderr, "%s: Unknown synchronous data file type, not AS-02-compatible essence.\n",
1596 Options.filenames.front().c_str());
1602 fprintf(stderr, "%s: Unknown file type, not AS-02-compatible essence.\n",
1603 Options.filenames.front().c_str());
1608 if ( ASDCP_FAILURE(result) )
1610 fputs("Program stopped on error.\n", stderr);
1612 if ( result != RESULT_FAIL )
1614 fputs(result, stderr);
1615 fputc('\n', stderr);
1626 // end as-02-wrap.cpp