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 when creating\n\
155 interlaced YCbCr files\n\
156 -m <expr> - Write MCA labels using <expr>. Example:\n\
157 51(L,R,C,LFE,Ls,Rs,),HI,VIN\n\
158 -M - Do not create HMAC values when writing\n\
159 -n <UL> - Set the TransferCharacteristic UL\n\
160 -o <min>,<max> - Mastering Display luminance, cd*m*m, e.g., \".05,100\"\n\
161 -O <rx>,<ry>,<gx>,<gy>,<bx>,<by>,<wx>,<wy>\n\
162 - Mastering Display Color Primaries and white point\n\
163 e.g., \".64,.33,.3,.6,.15,.06,.3457,.3585\"\n\
164 -p <ul> - Set broadcast profile\n\
165 -P <string> - Set NamespaceURI property when creating timed text MXF\n\
166 -q <UL> - Set the CodingEquations UL\n\
167 -r <n>/<d> - Edit Rate of the output file. 24/1 is the default\n\
168 -R - Indicates RGB image essence (default except with -c)\n\
169 -s <seconds> - Duration of a frame-wrapped partition (default 60)\n\
170 -t <min> - Set RGB component minimum code value (default: 0)\n\
171 -T <max> - Set RGB component maximum code value (default: 1023)\n\
172 -u - Print UL catalog to stdout\n\
173 -u <URI> - ISXD (RDD47) document URI (use 'auto' to read the\n\
174 namespace name from the first edit unit\n\
175 -v - Verbose, prints informative messages to stderr\n\
176 -W - Read input file only, do not write source file\n\
177 -x <int> - Horizontal subsampling degree (default: 2)\n\
178 -X <int> - Vertical subsampling degree (default: 2)\n\
179 -y <white-ref>[,<black-ref>[,<color-range>]]\n\
180 - Same as -Y but White Ref, Black Ref and Color Range are\n\
181 set from the given argument\n\
182 -Y - Indicates YCbCr image essence (default with -c), uses\n\
183 default values for White Ref, Black Ref and Color Range,\n\
184 940,64,897, indicating 10 bit standard Video Range\n\
185 -z - Fail if j2c inputs have unequal parameters (default)\n\
186 -Z - Ignore unequal parameters in j2c inputs\n\
188 --mca-audio-content-kind <string>\n\
189 - UL value for MCA descriptor MCAAudioContentKind property\n\
190 --mca-audio-element-kind <string>\n\
191 - UL value for MCA descriptor MCAAudioElementKind property\n\
193 NOTES: o There is no option grouping, all options must be distinct arguments.\n\
194 o All option arguments must be separated from the option by whitespace.\n\n");
197 const float chromaticity_scale = 50000.0;
200 set_primary_from_token(const std::string& token, ui16_t& primary)
202 float raw_value = strtod(token.c_str(),0);
204 if ( raw_value == 0.0 || raw_value > 1.0 )
206 fprintf(stderr, "Invalid coordinate value \"%s\".\n", token.c_str());
210 primary = floor(0.5 + ( raw_value * chromaticity_scale ));
214 const float luminance_scale = 10000.0;
217 set_luminance_from_token(const std::string& token, ui32_t& luminance)
219 float raw_value = strtod(token.c_str(),0);
221 if ( raw_value == 0.0 || raw_value > 400000.0 )
223 fprintf(stderr, "Invalid luminance value \"%s\".\n", token.c_str());
227 luminance = floor(0.5 + ( raw_value * luminance_scale ));
231 #define SET_LUMINANCE(p,t) \
232 if ( ! set_luminance_from_token(t, p) ) { \
242 bool error_flag; // true if the given options are in error or not complete
243 bool key_flag; // true if an encryption key was given
244 bool asset_id_flag; // true if an asset ID was given
245 bool encrypt_header_flag; // true if j2c headers are to be encrypted
246 bool write_hmac; // true if HMAC values are to be generated and written
247 bool verbose_flag; // true if the verbose option was selected
248 ui32_t fb_dump_size; // number of bytes of frame buffer to dump
249 bool no_write_flag; // true if no output files are to be written
250 bool version_flag; // true if the version display option was selected
251 bool help_flag; // true if the help display option was selected
252 ui32_t duration; // number of frames to be processed
253 bool j2c_pedantic; // passed to JP2K::SequenceParser::OpenRead
254 bool use_cdci_descriptor; //
255 Rational edit_rate; // edit rate of JP2K sequence
256 ui32_t fb_size; // size of picture frame buffer
257 byte_t key_value[KeyLen]; // value of given encryption key (when key_flag is true)
258 bool key_id_flag; // true if a key ID was given
259 byte_t key_id_value[UUIDlen];// value of given key ID (when key_id_flag is true)
260 byte_t asset_id_value[UUIDlen];// value of asset ID (when asset_id_flag is true)
261 bool show_ul_values_flag; // if true, dump the UL table before going tp work.
262 Kumu::PathList_t filenames; // list of filenames to be processed
264 UL channel_assignment, picture_coding, transfer_characteristic, color_primaries, coding_equations;
265 ASDCP::MXF::AS02_MCAConfigParser mca_config;
266 std::string language;
271 ui32_t horizontal_subsampling;
272 ui32_t vertical_subsampling;
273 ui32_t component_depth;
275 ASDCP::Rational aspect_ratio;
276 ui8_t field_dominance;
277 ui32_t mxf_header_size;
278 ui32_t cdci_BlackRefLevel;
279 ui32_t cdci_WhiteRefLevel;
280 ui32_t cdci_ColorRange;
282 ui32_t md_min_luminance, md_max_luminance;
283 ASDCP::MXF::ThreeColorPrimaries md_primaries;
284 ASDCP::MXF::ColorPrimary md_white_point;
286 //new attributes for AS-02 support
287 AS_02::IndexStrategy_t index_strategy; //Shim parameter index_strategy_frame/clip
288 ui32_t partition_space; //Shim parameter partition_spacing
291 std::string isxd_document_namespace;
292 std::list<std::string> global_isxd_metadata;
295 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)
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]) )
600 case 'M': write_hmac = false; break;
603 TEST_EXTRA_ARG(i, 'm');
604 mca_config_str = argv[i];
608 TEST_EXTRA_ARG(i, 'n');
609 if ( ! transfer_characteristic.DecodeHex(argv[i]) )
611 fprintf(stderr, "Error decoding TransferCharacteristic UL value: %s\n", argv[i]);
617 TEST_EXTRA_ARG(i, 'O');
618 if ( ! set_display_primaries(argv[i]) )
625 TEST_EXTRA_ARG(i, 'o');
626 if ( ! set_display_luminance(argv[i]) )
633 TEST_EXTRA_ARG(i, 'P');
634 profile_name = argv[i];
638 TEST_EXTRA_ARG(i, 'p');
639 if ( ! picture_coding.DecodeHex(argv[i]) )
641 fprintf(stderr, "Error decoding PictureEssenceCoding UL value: %s\n", argv[i]);
647 TEST_EXTRA_ARG(i, 'q');
648 if ( ! coding_equations.DecodeHex(argv[i]) )
650 fprintf(stderr, "Error decoding CodingEquations UL value: %s\n", argv[i]);
656 TEST_EXTRA_ARG(i, 'r');
657 if ( ! DecodeRational(argv[i], edit_rate) )
659 fprintf(stderr, "Error decoding edit rate value: %s\n", argv[i]);
666 use_cdci_descriptor = false;
670 TEST_EXTRA_ARG(i, 's');
671 partition_space = Kumu::xabs(strtol(argv[i], 0, 10));
675 TEST_EXTRA_ARG(i, 't');
676 rgba_MinRef = Kumu::xabs(strtol(argv[i], 0, 10));
680 TEST_EXTRA_ARG(i, 'T');
681 rgba_MaxRef = Kumu::xabs(strtol(argv[i], 0, 10));
684 case 'u': show_ul_values_flag = true; break;
687 TEST_EXTRA_ARG(i, 'U');
688 isxd_document_namespace = argv[i];
691 case 'V': version_flag = true; break;
692 case 'v': verbose_flag = true; break;
693 case 'W': no_write_flag = true; break;
696 TEST_EXTRA_ARG(i, 'x');
697 horizontal_subsampling = Kumu::xabs(strtol(argv[i], 0, 10));
701 TEST_EXTRA_ARG(i, 'X');
702 vertical_subsampling = Kumu::xabs(strtol(argv[i], 0, 10));
706 use_cdci_descriptor = true;
707 // default 10 bit video range YUV, ref levels already set
711 // Use values provided as argument, sharp tool, be careful
712 use_cdci_descriptor = true;
713 TEST_EXTRA_ARG(i, 'y');
714 if ( ! set_video_ref(argv[i]) )
720 case 'Z': j2c_pedantic = false; break;
721 case 'z': j2c_pedantic = true; break;
724 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
728 else if ( argv[i][0] == '-' && argv[i][1] == '-' && isalpha(argv[i][2]) )
730 if ( strcmp(argv[i]+2, "mca-audio-content-kind") == 0 )
732 if ( ++i >= argc || argv[(i)][0] == '-' )
734 fprintf(stderr, "Argument not found for option -mca-audio-content-kind.\n");
738 mca_audio_content_kind = argv[i];
740 else if ( strcmp(argv[i]+2, "mca-audio-element-kind") == 0 )
742 if ( ++i >= argc || argv[(i)][0] == '-' )
744 fprintf(stderr, "Argument not found for option -mca-audio-element-kind.\n");
748 mca_audio_element_kind = argv[i];
752 fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
758 if ( argv[i][0] != '-' )
760 filenames.push_back(argv[i]);
764 fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
770 if ( ! mca_config_str.empty() )
772 if ( language.empty() )
774 if ( ! mca_config.DecodeString(mca_config_str) )
781 if ( ! mca_config.DecodeString(mca_config_str, language) )
788 if ( help_flag || version_flag || show_ul_values_flag )
793 if ( filenames.size() < 2 )
795 fputs("Option requires at least two filename arguments: <input-file> <output-file>\n", stderr);
799 out_file = filenames.back();
800 filenames.pop_back();
802 if ( ! picture_coding.HasValue() )
804 picture_coding = UL(g_dict->ul(MDD_JP2KEssenceCompression_BroadcastProfile_1));
812 //------------------------------------------------------------------------------------------
816 Result_t JP2K_PDesc_to_MD(const ASDCP::JP2K::PictureDescriptor& PDesc,
817 const ASDCP::Dictionary& dict,
818 ASDCP::MXF::GenericPictureEssenceDescriptor& GenericPictureEssenceDescriptor,
819 ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor);
821 Result_t PCM_ADesc_to_MD(ASDCP::PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj);
824 // Write one or more plaintext JPEG 2000 codestreams to a plaintext AS-02 file
825 // Write one or more plaintext JPEG 2000 codestreams to a ciphertext AS-02 file
828 write_JP2K_file(CommandOptions& Options)
830 AESEncContext* Context = 0;
831 HMACContext* HMAC = 0;
832 AS_02::JP2K::MXFWriter Writer;
833 JP2K::FrameBuffer FrameBuffer(Options.fb_size);
834 JP2K::SequenceParser Parser;
835 byte_t IV_buf[CBC_BLOCK_SIZE];
836 Kumu::FortunaRNG RNG;
837 ASDCP::MXF::FileDescriptor *essence_descriptor = 0;
838 ASDCP::MXF::InterchangeObject_list_t essence_sub_descriptors;
840 // set up essence parser
841 Result_t result = Parser.OpenRead(Options.filenames.front().c_str(), Options.j2c_pedantic);
844 if ( ASDCP_SUCCESS(result) )
846 ASDCP::JP2K::PictureDescriptor PDesc;
847 Parser.FillPictureDescriptor(PDesc);
848 PDesc.EditRate = Options.edit_rate;
850 if ( Options.verbose_flag )
852 fprintf(stderr, "JPEG 2000 pictures\n");
853 fputs("PictureDescriptor:\n", stderr);
854 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
855 JP2K::PictureDescriptorDump(PDesc);
858 if ( Options.use_cdci_descriptor )
860 ASDCP::MXF::CDCIEssenceDescriptor* tmp_dscr = new ASDCP::MXF::CDCIEssenceDescriptor(g_dict);
861 essence_sub_descriptors.push_back(new ASDCP::MXF::JPEG2000PictureSubDescriptor(g_dict));
863 result = ASDCP::JP2K_PDesc_to_MD(PDesc, *g_dict,
864 *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr),
865 *static_cast<ASDCP::MXF::JPEG2000PictureSubDescriptor*>(essence_sub_descriptors.back()));
867 if ( ASDCP_SUCCESS(result) )
869 tmp_dscr->CodingEquations = Options.coding_equations;
870 tmp_dscr->TransferCharacteristic = Options.transfer_characteristic;
871 tmp_dscr->ColorPrimaries = Options.color_primaries;
872 tmp_dscr->PictureEssenceCoding = Options.picture_coding;
873 tmp_dscr->HorizontalSubsampling = Options.horizontal_subsampling;
874 tmp_dscr->VerticalSubsampling = Options.vertical_subsampling;
875 tmp_dscr->ComponentDepth = Options.component_depth;
876 tmp_dscr->FrameLayout = Options.frame_layout;
877 tmp_dscr->AspectRatio = Options.aspect_ratio;
878 tmp_dscr->FieldDominance = Options.field_dominance;
879 tmp_dscr->WhiteReflevel = Options.cdci_WhiteRefLevel;
880 tmp_dscr->BlackRefLevel = Options.cdci_BlackRefLevel;
881 tmp_dscr->ColorRange = Options.cdci_ColorRange;
882 tmp_dscr->VideoLineMap = Options.line_map;
884 if ( Options.md_min_luminance || Options.md_max_luminance )
886 tmp_dscr->MasteringDisplayMinimumLuminance = Options.md_min_luminance;
887 tmp_dscr->MasteringDisplayMaximumLuminance = Options.md_max_luminance;
890 if ( Options.md_primaries.HasValue() )
892 tmp_dscr->MasteringDisplayPrimaries = Options.md_primaries;
893 tmp_dscr->MasteringDisplayWhitePointChromaticity = Options.md_white_point;
896 essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr);
901 ASDCP::MXF::RGBAEssenceDescriptor* tmp_dscr = new ASDCP::MXF::RGBAEssenceDescriptor(g_dict);
902 essence_sub_descriptors.push_back(new ASDCP::MXF::JPEG2000PictureSubDescriptor(g_dict));
904 result = ASDCP::JP2K_PDesc_to_MD(PDesc, *g_dict,
905 *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr),
906 *static_cast<ASDCP::MXF::JPEG2000PictureSubDescriptor*>(essence_sub_descriptors.back()));
908 if ( ASDCP_SUCCESS(result) )
910 tmp_dscr->CodingEquations = Options.coding_equations;
911 tmp_dscr->TransferCharacteristic = Options.transfer_characteristic;
912 tmp_dscr->ColorPrimaries = Options.color_primaries;
913 tmp_dscr->ScanningDirection = 0;
914 tmp_dscr->PictureEssenceCoding = Options.picture_coding;
915 tmp_dscr->ComponentMaxRef = Options.rgba_MaxRef;
916 tmp_dscr->ComponentMinRef = Options.rgba_MinRef;
918 if ( Options.md_min_luminance || Options.md_max_luminance )
920 tmp_dscr->MasteringDisplayMinimumLuminance = Options.md_min_luminance;
921 tmp_dscr->MasteringDisplayMaximumLuminance = Options.md_max_luminance;
924 if ( Options.md_primaries.HasValue() )
926 tmp_dscr->MasteringDisplayPrimaries = Options.md_primaries;
927 tmp_dscr->MasteringDisplayWhitePointChromaticity = Options.md_white_point;
930 essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr);
935 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
937 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
938 Info.LabelSetType = LS_MXF_SMPTE;
940 if ( Options.asset_id_flag )
941 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
943 Kumu::GenRandomUUID(Info.AssetUUID);
945 // configure encryption
946 if( Options.key_flag )
948 Kumu::GenRandomUUID(Info.ContextID);
949 Info.EncryptedEssence = true;
951 if ( Options.key_id_flag )
953 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
957 create_random_uuid(Info.CryptographicKeyID);
960 Context = new AESEncContext;
961 result = Context->InitKey(Options.key_value);
963 if ( ASDCP_SUCCESS(result) )
964 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
966 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
968 Info.UsesHMAC = true;
969 HMAC = new HMACContext;
970 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
974 if ( ASDCP_SUCCESS(result) )
976 result = Writer.OpenWrite(Options.out_file, Info, essence_descriptor, essence_sub_descriptors,
977 Options.edit_rate, Options.mxf_header_size, Options.index_strategy, Options.partition_space);
981 if ( ASDCP_SUCCESS(result) )
984 result = Parser.Reset();
986 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
988 result = Parser.ReadFrame(FrameBuffer);
990 if ( ASDCP_SUCCESS(result) )
992 if ( Options.verbose_flag )
993 FrameBuffer.Dump(stderr, Options.fb_dump_size);
995 if ( Options.encrypt_header_flag )
996 FrameBuffer.PlaintextOffset(0);
999 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1001 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);
1003 // The Writer class will forward the last block of ciphertext
1004 // to the encryption context for use as the IV for the next
1005 // frame. If you want to use non-sequitur IV values, un-comment
1006 // the following line of code.
1007 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
1008 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1012 if ( result == RESULT_ENDOFFILE )
1016 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1017 result = Writer.Finalize();
1022 //------------------------------------------------------------------------------------------
1024 // Write one or more plaintext PCM audio streams to a plaintext AS-02 file
1025 // Write one or more plaintext PCM audio streams to a ciphertext AS-02 file
1028 write_PCM_file(CommandOptions& Options)
1030 AESEncContext* Context = 0;
1031 HMACContext* HMAC = 0;
1032 PCMParserList Parser;
1033 AS_02::PCM::MXFWriter Writer;
1034 PCM::FrameBuffer FrameBuffer;
1035 byte_t IV_buf[CBC_BLOCK_SIZE];
1036 Kumu::FortunaRNG RNG;
1037 ASDCP::MXF::WaveAudioDescriptor *essence_descriptor = 0;
1039 // set up essence parser
1040 Result_t result = Parser.OpenRead(Options.filenames, Options.edit_rate);
1042 // set up MXF writer
1043 if ( ASDCP_SUCCESS(result) )
1045 ASDCP::PCM::AudioDescriptor ADesc;
1046 Parser.FillAudioDescriptor(ADesc);
1048 ADesc.EditRate = Options.edit_rate;
1049 FrameBuffer.Capacity(PCM::CalcFrameBufferSize(ADesc));
1051 if ( Options.verbose_flag )
1054 fprintf(stderr, "%.1fkHz PCM Audio, %s fps (%u spf)\n",
1055 ADesc.AudioSamplingRate.Quotient() / 1000.0,
1056 RationalToString(Options.edit_rate, buf, 64),
1057 PCM::CalcSamplesPerFrame(ADesc));
1058 fputs("AudioDescriptor:\n", stderr);
1059 PCM::AudioDescriptorDump(ADesc);
1062 essence_descriptor = new ASDCP::MXF::WaveAudioDescriptor(g_dict);
1064 result = ASDCP::PCM_ADesc_to_MD(ADesc, essence_descriptor);
1066 if ( Options.mca_config.empty() )
1068 essence_descriptor->ChannelAssignment = Options.channel_assignment;
1072 if ( Options.mca_config.ChannelCount() != essence_descriptor->ChannelCount )
1074 fprintf(stderr, "MCA label count (%d) differs from essence stream channel count (%d).\n",
1075 Options.mca_config.ChannelCount(), essence_descriptor->ChannelCount);
1079 // This marks all soundfield groups using the same MCA property values
1080 MXF::InterchangeObject_list_t::iterator i;
1081 for ( i = Options.mca_config.begin(); i != Options.mca_config.end(); ++i )
1083 MXF::SoundfieldGroupLabelSubDescriptor * desc = dynamic_cast<MXF::SoundfieldGroupLabelSubDescriptor*>(*i);
1086 if ( ! Options.mca_audio_content_kind.empty() )
1088 desc->MCAAudioContentKind = Options.mca_audio_content_kind;
1090 if ( ! Options.mca_audio_element_kind.empty() )
1092 desc->MCAAudioElementKind = Options.mca_audio_element_kind;
1097 essence_descriptor->ChannelAssignment = g_dict->ul(MDD_IMFAudioChannelCfg_MCA);
1101 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1103 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
1104 Info.LabelSetType = LS_MXF_SMPTE;
1106 if ( Options.asset_id_flag )
1107 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
1109 Kumu::GenRandomUUID(Info.AssetUUID);
1111 // configure encryption
1112 if( Options.key_flag )
1114 Kumu::GenRandomUUID(Info.ContextID);
1115 Info.EncryptedEssence = true;
1117 if ( Options.key_id_flag )
1119 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
1123 create_random_uuid(Info.CryptographicKeyID);
1126 Context = new AESEncContext;
1127 result = Context->InitKey(Options.key_value);
1129 if ( ASDCP_SUCCESS(result) )
1130 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1132 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
1134 Info.UsesHMAC = true;
1135 HMAC = new HMACContext;
1136 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
1140 if ( ASDCP_SUCCESS(result) )
1142 result = Writer.OpenWrite(Options.out_file.c_str(), Info, essence_descriptor,
1143 Options.mca_config, Options.edit_rate);
1147 if ( ASDCP_SUCCESS(result) )
1149 result = Parser.Reset();
1150 ui32_t duration = 0;
1152 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
1154 result = Parser.ReadFrame(FrameBuffer);
1156 if ( ASDCP_SUCCESS(result) )
1158 if ( Options.verbose_flag )
1159 FrameBuffer.Dump(stderr, Options.fb_dump_size);
1161 if ( ! Options.no_write_flag )
1163 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);
1165 // The Writer class will forward the last block of ciphertext
1166 // to the encryption context for use as the IV for the next
1167 // frame. If you want to use non-sequitur IV values, un-comment
1168 // the following line of code.
1169 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
1170 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1175 if ( result == RESULT_ENDOFFILE )
1179 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1180 result = Writer.Finalize();
1188 //------------------------------------------------------------------------------------------
1189 // TimedText essence
1192 // Write one or more plaintext timed text streams to a plaintext AS-02 file
1193 // Write one or more plaintext timed text streams to a ciphertext AS-02 file
1196 write_timed_text_file(CommandOptions& Options)
1198 AESEncContext* Context = 0;
1199 HMACContext* HMAC = 0;
1200 AS_02::TimedText::ST2052_TextParser Parser;
1201 AS_02::TimedText::MXFWriter Writer;
1202 TimedText::FrameBuffer FrameBuffer;
1203 TimedText::TimedTextDescriptor TDesc;
1204 byte_t IV_buf[CBC_BLOCK_SIZE];
1205 Kumu::FortunaRNG RNG;
1207 // set up essence parser
1208 Result_t result = Parser.OpenRead(Options.filenames.front());
1210 // set up MXF writer
1211 if ( ASDCP_SUCCESS(result) )
1213 Parser.FillTimedTextDescriptor(TDesc);
1214 TDesc.EditRate = Options.edit_rate;
1215 TDesc.ContainerDuration = Options.duration;
1216 FrameBuffer.Capacity(Options.fb_size);
1218 if ( ! Options.profile_name.empty() )
1220 TDesc.NamespaceName = Options.profile_name;
1223 if ( Options.verbose_flag )
1225 fputs("IMF Timed-Text Descriptor:\n", stderr);
1226 TimedText::DescriptorDump(TDesc);
1230 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1232 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
1233 Info.LabelSetType = LS_MXF_SMPTE;
1235 if ( Options.asset_id_flag )
1236 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
1238 Kumu::GenRandomUUID(Info.AssetUUID);
1240 // configure encryption
1241 if( Options.key_flag )
1243 Kumu::GenRandomUUID(Info.ContextID);
1244 Info.EncryptedEssence = true;
1246 if ( Options.key_id_flag )
1248 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
1252 create_random_uuid(Info.CryptographicKeyID);
1255 Context = new AESEncContext;
1256 result = Context->InitKey(Options.key_value);
1258 if ( ASDCP_SUCCESS(result) )
1259 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1261 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
1263 Info.UsesHMAC = true;
1264 HMAC = new HMACContext;
1265 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
1269 if ( ASDCP_SUCCESS(result) )
1270 result = Writer.OpenWrite(Options.out_file.c_str(), Info, TDesc);
1273 if ( ASDCP_FAILURE(result) )
1277 TimedText::ResourceList_t::const_iterator ri;
1279 result = Parser.ReadTimedTextResource(XMLDoc);
1281 if ( ASDCP_SUCCESS(result) )
1282 result = Writer.WriteTimedTextResource(XMLDoc, Context, HMAC);
1284 for ( ri = TDesc.ResourceList.begin() ; ri != TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ )
1286 result = Parser.ReadAncillaryResource((*ri).ResourceID, FrameBuffer);
1288 if ( ASDCP_SUCCESS(result) )
1290 if ( Options.verbose_flag )
1291 FrameBuffer.Dump(stderr, Options.fb_dump_size);
1293 if ( ! Options.no_write_flag )
1295 result = Writer.WriteAncillaryResource(FrameBuffer, Context, HMAC);
1297 // The Writer class will forward the last block of ciphertext
1298 // to the encryption context for use as the IV for the next
1299 // frame. If you want to use non-sequitur IV values, un-comment
1300 // the following line of code.
1301 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
1302 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1306 if ( result == RESULT_ENDOFFILE )
1310 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1311 result = Writer.Finalize();
1318 get_current_dms_text_descriptor(AS_02::ISXD::MXFWriter& writer, ASDCP::MXF::GenericStreamTextBasedSet *&text_object)
1320 std::list<MXF::InterchangeObject*> object_list;
1321 writer.OP1aHeader().GetMDObjectsByType(DefaultSMPTEDict().ul(MDD_GenericStreamTextBasedSet), object_list);
1323 if ( object_list.empty() )
1328 text_object = dynamic_cast<MXF::GenericStreamTextBasedSet*>(object_list.back());
1329 assert(text_object != 0);
1334 // Write one or more plaintext Aux Data bytestreams to a plaintext AS-02 file
1335 // Write one or more plaintext Aux Data bytestreams to a ciphertext AS-02 file
1338 write_isxd_file(CommandOptions& Options)
1340 AESEncContext* Context = 0;
1341 HMACContext* HMAC = 0;
1342 AS_02::ISXD::MXFWriter Writer;
1343 DCData::FrameBuffer FrameBuffer(Options.fb_size);
1344 DCData::SequenceParser Parser;
1345 byte_t IV_buf[CBC_BLOCK_SIZE];
1346 Kumu::FortunaRNG RNG;
1348 // set up essence parser
1349 Result_t result = Parser.OpenRead(Options.filenames.front());
1351 // set up MXF writer
1352 if ( ASDCP_SUCCESS(result) )
1355 if ( Options.verbose_flag )
1357 fprintf(stderr, "ISXD Data\n");
1358 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
1362 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1364 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
1365 if ( Options.asset_id_flag )
1366 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
1368 Kumu::GenRandomUUID(Info.AssetUUID);
1370 Info.LabelSetType = LS_MXF_SMPTE;
1372 // configure encryption
1373 if( Options.key_flag )
1375 Kumu::GenRandomUUID(Info.ContextID);
1376 Info.EncryptedEssence = true;
1378 if ( Options.key_id_flag )
1380 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
1384 create_random_uuid(Info.CryptographicKeyID);
1387 Context = new AESEncContext;
1388 result = Context->InitKey(Options.key_value);
1390 if ( ASDCP_SUCCESS(result) )
1391 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1393 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
1395 Info.UsesHMAC = true;
1396 HMAC = new HMACContext;
1397 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
1401 if ( ASDCP_SUCCESS(result) )
1403 if ( Options.isxd_document_namespace == "auto" )
1405 // get ns of first item
1406 std::string ns_prefix, type_name, namespace_name;
1407 result = Parser.ReadFrame(FrameBuffer);
1409 if ( ASDCP_SUCCESS(result) )
1411 Kumu::AttributeList doc_attr_list;
1412 result = GetXMLDocType(FrameBuffer.RoData(), FrameBuffer.Size(), ns_prefix, type_name,
1413 namespace_name, doc_attr_list) ? RESULT_OK : RESULT_FAIL;
1416 if ( ASDCP_SUCCESS(result) && ! namespace_name.empty() )
1418 Options.isxd_document_namespace = namespace_name;
1422 fprintf(stderr, "Unable to parse an XML namespace name from the input document.\n");
1427 result = Writer.OpenWrite(Options.out_file, Info, Options.isxd_document_namespace, Options.edit_rate);
1431 if ( ASDCP_SUCCESS(result) )
1433 ui32_t duration = 0;
1434 result = Parser.Reset();
1436 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
1438 result = Parser.ReadFrame(FrameBuffer);
1440 if ( ASDCP_SUCCESS(result) )
1442 if ( Options.verbose_flag )
1443 FrameBuffer.Dump(stderr, Options.fb_dump_size);
1445 if ( Options.encrypt_header_flag )
1446 FrameBuffer.PlaintextOffset(0);
1449 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1451 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);
1453 // The Writer class will forward the last block of ciphertext
1454 // to the encryption context for use as the IV for the next
1455 // frame. If you want to use non-sequitur IV values, un-comment
1456 // the following line of code.
1457 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
1458 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1462 if ( result == RESULT_ENDOFFILE )
1468 if ( KM_SUCCESS(result) && ! Options.no_write_flag )
1470 ASDCP::FrameBuffer global_metadata;
1471 std::list<std::string>::iterator i;
1473 for ( i = Options.global_isxd_metadata.begin(); i != Options.global_isxd_metadata.end(); ++i )
1475 ui32_t file_size = Kumu::FileSize(*i);
1476 result = global_metadata.Capacity(file_size);
1478 if ( KM_SUCCESS(result) )
1480 ui32_t read_count = 0;
1481 Kumu::FileReader Reader;
1482 std::string namespace_name;
1484 result = Reader.OpenRead(*i);
1486 if ( KM_SUCCESS(result) )
1488 result = Reader.Read(global_metadata.Data(), file_size, &read_count);
1491 if ( KM_SUCCESS(result) )
1493 if ( file_size != read_count)
1494 return RESULT_READFAIL;
1496 global_metadata.Size(read_count);
1498 std::string ns_prefix, type_name;
1499 Kumu::AttributeList doc_attr_list;
1500 result = GetXMLDocType(global_metadata.RoData(), global_metadata.Size(), ns_prefix, type_name,
1501 namespace_name, doc_attr_list) ? RESULT_OK : RESULT_FAIL;
1504 if ( KM_SUCCESS(result) )
1506 result = Writer.AddDmsGenericPartUtf8Text(global_metadata, Context, HMAC);
1509 if ( KM_SUCCESS(result) )
1511 ASDCP::MXF::GenericStreamTextBasedSet *text_object = 0;
1512 get_current_dms_text_descriptor(Writer, text_object);
1513 assert(text_object);
1514 text_object->TextMIMEMediaType = "text/xml";
1515 text_object->TextDataDescription = namespace_name;
1517 // this is not really useful when inserting multiple objects because
1518 // it cannot be set per object without some other CLI syntax for
1519 // associating language codes with 2057 blobs, e.g., <filename>:<lang>
1520 text_object->RFC5646TextLanguageCode = Options.language;
1525 if ( KM_SUCCESS(result) )
1527 result = Writer.Finalize();
1536 main(int argc, const char** argv)
1538 Result_t result = RESULT_OK;
1540 g_dict = &ASDCP::DefaultSMPTEDict();
1543 CommandOptions Options(argc, argv);
1545 if ( Options.version_flag )
1548 if ( Options.help_flag )
1551 if ( Options.show_ul_values_flag )
1553 g_dict->Dump(stdout);
1556 if ( Options.version_flag || Options.help_flag || Options.show_ul_values_flag )
1559 if ( Options.error_flag )
1561 fprintf(stderr, "There was a problem. Type %s -h for help.\n", PROGRAM_NAME);
1565 EssenceType_t EssenceType;
1566 result = ASDCP::RawEssenceType(Options.filenames.front().c_str(), EssenceType);
1568 if ( ASDCP_SUCCESS(result) )
1570 switch ( EssenceType )
1573 result = write_JP2K_file(Options);
1576 case ESS_PCM_24b_48k:
1577 case ESS_PCM_24b_96k:
1578 result = write_PCM_file(Options);
1581 case ESS_TIMED_TEXT:
1582 result = write_timed_text_file(Options);
1585 case ESS_DCDATA_UNKNOWN:
1586 if ( ! Options.isxd_document_namespace.empty() )
1588 result = write_isxd_file(Options);
1592 fprintf(stderr, "%s: Unknown synchronous data file type, not AS-02-compatible essence.\n",
1593 Options.filenames.front().c_str());
1599 fprintf(stderr, "%s: Unknown file type, not AS-02-compatible essence.\n",
1600 Options.filenames.front().c_str());
1605 if ( ASDCP_FAILURE(result) )
1607 fputs("Program stopped on error.\n", stderr);
1609 if ( result != RESULT_FAIL )
1611 fputs(result, stderr);
1612 fputc('\n', stderr);
1623 // end as-02-wrap.cpp