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 <UL> - ISXD (RDD47) essence coding label\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 NOTES: o There is no option grouping, all options must be distinct arguments.\n\
188 o All option arguments must be separated from the option by whitespace.\n\n");
191 const float chromaticity_scale = 50000.0;
194 set_primary_from_token(const std::string& token, ui16_t& primary)
196 float raw_value = strtod(token.c_str(),0);
198 if ( raw_value == 0.0 || raw_value > 1.0 )
200 fprintf(stderr, "Invalid coordinate value \"%s\".\n", token.c_str());
204 primary = floor(0.5 + ( raw_value * chromaticity_scale ));
208 const float luminance_scale = 10000.0;
211 set_luminance_from_token(const std::string& token, ui32_t& luminance)
213 float raw_value = strtod(token.c_str(),0);
215 if ( raw_value == 0.0 || raw_value > 400000.0 )
217 fprintf(stderr, "Invalid luminance value \"%s\".\n", token.c_str());
221 luminance = floor(0.5 + ( raw_value * luminance_scale ));
225 #define SET_LUMINANCE(p,t) \
226 if ( ! set_luminance_from_token(t, p) ) { \
236 bool error_flag; // true if the given options are in error or not complete
237 bool key_flag; // true if an encryption key was given
238 bool asset_id_flag; // true if an asset ID was given
239 bool encrypt_header_flag; // true if j2c headers are to be encrypted
240 bool write_hmac; // true if HMAC values are to be generated and written
241 bool verbose_flag; // true if the verbose option was selected
242 ui32_t fb_dump_size; // number of bytes of frame buffer to dump
243 bool no_write_flag; // true if no output files are to be written
244 bool version_flag; // true if the version display option was selected
245 bool help_flag; // true if the help display option was selected
246 ui32_t duration; // number of frames to be processed
247 bool j2c_pedantic; // passed to JP2K::SequenceParser::OpenRead
248 bool use_cdci_descriptor; //
249 Rational edit_rate; // edit rate of JP2K sequence
250 ui32_t fb_size; // size of picture frame buffer
251 byte_t key_value[KeyLen]; // value of given encryption key (when key_flag is true)
252 bool key_id_flag; // true if a key ID was given
253 byte_t key_id_value[UUIDlen];// value of given key ID (when key_id_flag is true)
254 byte_t asset_id_value[UUIDlen];// value of asset ID (when asset_id_flag is true)
255 bool show_ul_values_flag; /// if true, dump the UL table before going tp work.
256 Kumu::PathList_t filenames; // list of filenames to be processed
258 UL channel_assignment, picture_coding, transfer_characteristic, color_primaries, coding_equations;
259 ASDCP::MXF::AS02_MCAConfigParser mca_config;
260 std::string language;
265 ui32_t horizontal_subsampling;
266 ui32_t vertical_subsampling;
267 ui32_t component_depth;
269 ASDCP::Rational aspect_ratio;
270 ui8_t field_dominance;
271 ui32_t mxf_header_size;
272 ui32_t cdci_BlackRefLevel;
273 ui32_t cdci_WhiteRefLevel;
274 ui32_t cdci_ColorRange;
276 ui32_t md_min_luminance, md_max_luminance;
277 ASDCP::MXF::ThreeColorPrimaries md_primaries;
278 ASDCP::MXF::ColorPrimary md_white_point;
280 //new attributes for AS-02 support
281 AS_02::IndexStrategy_t index_strategy; //Shim parameter index_strategy_frame/clip
282 ui32_t partition_space; //Shim parameter partition_spacing
285 std::string isxd_document_namespace;
286 std::list<std::string> global_isxd_metadata;
289 MXF::LineMapPair line_map;
290 std::string out_file, profile_name; //
293 bool set_video_line_map(const std::string& arg)
295 const char* sep_str = strrchr(arg.c_str(), ',');
299 fprintf(stderr, "Expecting <first>,<second>\n");
303 line_map.First = Kumu::xabs(strtol(arg.c_str(), 0, 10));
304 line_map.Second = Kumu::xabs(strtol(sep_str+1, 0, 10));
309 bool set_video_ref(const std::string& arg)
311 std::list<std::string> ref_tokens = Kumu::km_token_split(arg, ",");
313 switch ( ref_tokens.size() )
316 cdci_ColorRange = Kumu::xabs(strtol(ref_tokens.back().c_str(), 0, 10));
317 ref_tokens.pop_back();
319 cdci_BlackRefLevel = Kumu::xabs(strtol(ref_tokens.back().c_str(), 0, 10));
320 ref_tokens.pop_back();
322 cdci_WhiteRefLevel = Kumu::xabs(strtol(ref_tokens.back().c_str(), 0, 10));
326 fprintf(stderr, "Expecting <white-ref>[,<black-ref>[,<color-range>]]\n");
330 if ( cdci_WhiteRefLevel > 65535 || cdci_BlackRefLevel > 65535 || cdci_ColorRange > 65535 )
332 fprintf(stderr, "Unexpected CDCI video referece levels.\n");
340 bool set_display_primaries(const std::string& arg)
342 std::list<std::string> coordinate_tokens = Kumu::km_token_split(arg, ",");
343 if ( coordinate_tokens.size() != 8 )
345 fprintf(stderr, "Expecting four coordinate pairs.\n");
349 std::list<std::string>::const_iterator i = coordinate_tokens.begin();
350 if ( ! set_primary_from_token(*(i++), md_primaries.First.X) ) return false;
351 if ( ! set_primary_from_token(*(i++), md_primaries.First.Y) ) return false;
352 if ( ! set_primary_from_token(*(i++), md_primaries.Second.X) ) return false;
353 if ( ! set_primary_from_token(*(i++), md_primaries.Second.Y) ) return false;
354 if ( ! set_primary_from_token(*(i++), md_primaries.Third.X) ) return false;
355 if ( ! set_primary_from_token(*(i++), md_primaries.Third.Y) ) return false;
356 if ( ! set_primary_from_token(*(i++), md_white_point.X) ) return false;
357 if ( ! set_primary_from_token(*i, md_white_point.Y) ) return false;
363 bool set_display_luminance(const std::string& arg)
365 std::list<std::string> luminance_tokens = Kumu::km_token_split(arg, ",");
366 if ( luminance_tokens.size() != 2 )
368 fprintf(stderr, "Expecting a luminance pair.\n");
372 if ( ! set_luminance_from_token(luminance_tokens.front(), md_min_luminance) ) return false;
373 if ( ! set_luminance_from_token(luminance_tokens.back(), md_max_luminance) ) return false;
379 bool set_color_system_from_arg(const char* arg)
385 // Application 2 (ST 2067-20)
387 coding_equations = g_dict->ul(MDD_CodingEquations_601);
388 transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_709);
389 color_primaries = g_dict->ul(MDD_ColorPrimaries_ITU470_PAL);
390 use_cdci_descriptor = true;
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_SMPTE170M);
397 use_cdci_descriptor = true;
401 coding_equations = g_dict->ul(MDD_CodingEquations_709);
402 transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_709);
403 color_primaries = g_dict->ul(MDD_ColorPrimaries_BT709);
404 use_cdci_descriptor = true;
407 // Application 2e (ST 2067-21)
409 coding_equations = g_dict->ul(MDD_CodingEquations_709);
410 transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_xvYCC);
411 color_primaries = g_dict->ul(MDD_ColorPrimaries_BT709);
412 use_cdci_descriptor = true;
416 coding_equations = g_dict->ul(MDD_CodingEquations_709);
417 transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_2020);
418 color_primaries = g_dict->ul(MDD_ColorPrimaries_BT2020);
419 use_cdci_descriptor = true;
423 fprintf(stderr, "Unrecognized color system number, expecting one of 1-5.\n");
430 CommandOptions(int argc, const char** argv) :
431 error_flag(true), key_flag(false), key_id_flag(false), asset_id_flag(false),
432 encrypt_header_flag(true), write_hmac(true), verbose_flag(false), fb_dump_size(0),
433 no_write_flag(false), version_flag(false), help_flag(false),
434 duration(0xffffffff), j2c_pedantic(true), use_cdci_descriptor(false),
435 edit_rate(24,1), fb_size(FRAME_BUFFER_SIZE),
436 show_ul_values_flag(false), index_strategy(AS_02::IS_FOLLOW), partition_space(60),
437 mca_config(g_dict), rgba_MaxRef(1023), rgba_MinRef(0),
438 horizontal_subsampling(2), vertical_subsampling(2), component_depth(10),
439 frame_layout(0), aspect_ratio(ASDCP::Rational(4,3)), field_dominance(0),
440 mxf_header_size(16384), cdci_WhiteRefLevel(940), cdci_BlackRefLevel(64), cdci_ColorRange(897),
441 md_min_luminance(0), md_max_luminance(0), line_map(0,0)
443 memset(key_value, 0, KeyLen);
444 memset(key_id_value, 0, UUIDlen);
446 coding_equations = g_dict->ul(MDD_CodingEquations_709);
447 color_primaries = g_dict->ul(MDD_ColorPrimaries_BT709);
448 transfer_characteristic = g_dict->ul(MDD_TransferCharacteristics_709);
449 std::string mca_config_str;
451 for ( int i = 1; i < argc; i++ )
454 if ( (strcmp( argv[i], "-help") == 0) )
460 if ( argv[i][0] == '-'
461 && ( isalpha(argv[i][1]) || isdigit(argv[i][1]) )
464 switch ( argv[i][1] )
467 TEST_EXTRA_ARG(i, 'A');
468 if ( ! DecodeRational(argv[i], aspect_ratio) )
470 fprintf(stderr, "Error decoding aspect ratio value: %s\n", argv[i]);
476 asset_id_flag = true;
477 TEST_EXTRA_ARG(i, 'a');
480 Kumu::hex2bin(argv[i], asset_id_value, UUIDlen, &length);
482 if ( length != UUIDlen )
484 fprintf(stderr, "Unexpected asset ID length: %u, expecting %u characters.\n", length, UUIDlen);
491 TEST_EXTRA_ARG(i, 'b');
492 fb_size = Kumu::xabs(strtol(argv[i], 0, 10));
495 fprintf(stderr, "Frame Buffer size: %u bytes.\n", fb_size);
500 TEST_EXTRA_ARG(i, 'c');
501 if ( ! set_color_system_from_arg(argv[i]) )
508 TEST_EXTRA_ARG(i, 'C');
509 if ( ! channel_assignment.DecodeHex(argv[i]) )
511 fprintf(stderr, "Error decoding ChannelAssignment UL value: %s\n", argv[i]);
517 TEST_EXTRA_ARG(i, 'D');
518 component_depth = Kumu::xabs(strtol(argv[i], 0, 10));
522 TEST_EXTRA_ARG(i, 'd');
523 duration = Kumu::xabs(strtol(argv[i], 0, 10));
526 case 'E': encrypt_header_flag = false; break;
527 case 'e': encrypt_header_flag = true; break;
530 TEST_EXTRA_ARG(i, 'F');
531 field_dominance = Kumu::xabs(strtol(argv[i], 0, 10));
532 if ( field_dominance > 1 )
534 fprintf(stderr, "Field dominance value must be \"0\" or \"1\"\n");
540 TEST_EXTRA_ARG(i, 'g');
545 TEST_EXTRA_ARG(i, 'G');
546 global_isxd_metadata.push_back(argv[i]);
549 case 'h': help_flag = true; break;
553 use_cdci_descriptor = true;
558 TEST_EXTRA_ARG(i, 'j');
561 Kumu::hex2bin(argv[i], key_id_value, UUIDlen, &length);
563 if ( length != UUIDlen )
565 fprintf(stderr, "Unexpected key ID length: %u, expecting %u characters.\n", length, UUIDlen);
571 case 'k': key_flag = true;
572 TEST_EXTRA_ARG(i, 'k');
575 Kumu::hex2bin(argv[i], key_value, KeyLen, &length);
577 if ( length != KeyLen )
579 fprintf(stderr, "Unexpected key length: %u, expecting %u characters.\n", length, KeyLen);
586 TEST_EXTRA_ARG(i, 'y');
587 if ( ! set_video_line_map(argv[i]) )
593 case 'M': write_hmac = false; break;
596 TEST_EXTRA_ARG(i, 'm');
597 mca_config_str = argv[i];
601 TEST_EXTRA_ARG(i, 'n');
602 if ( ! transfer_characteristic.DecodeHex(argv[i]) )
604 fprintf(stderr, "Error decoding TransferCharacteristic UL value: %s\n", argv[i]);
610 TEST_EXTRA_ARG(i, 'O');
611 if ( ! set_display_primaries(argv[i]) )
618 TEST_EXTRA_ARG(i, 'o');
619 if ( ! set_display_luminance(argv[i]) )
626 TEST_EXTRA_ARG(i, 'P');
627 profile_name = argv[i];
631 TEST_EXTRA_ARG(i, 'p');
632 if ( ! picture_coding.DecodeHex(argv[i]) )
634 fprintf(stderr, "Error decoding PictureEssenceCoding UL value: %s\n", argv[i]);
640 TEST_EXTRA_ARG(i, 'q');
641 if ( ! coding_equations.DecodeHex(argv[i]) )
643 fprintf(stderr, "Error decoding CodingEquations UL value: %s\n", argv[i]);
649 TEST_EXTRA_ARG(i, 'r');
650 if ( ! DecodeRational(argv[i], edit_rate) )
652 fprintf(stderr, "Error decoding edit rate value: %s\n", argv[i]);
659 use_cdci_descriptor = false;
663 TEST_EXTRA_ARG(i, 's');
664 partition_space = Kumu::xabs(strtol(argv[i], 0, 10));
668 TEST_EXTRA_ARG(i, 't');
669 rgba_MinRef = Kumu::xabs(strtol(argv[i], 0, 10));
673 TEST_EXTRA_ARG(i, 'T');
674 rgba_MaxRef = Kumu::xabs(strtol(argv[i], 0, 10));
677 case 'u': show_ul_values_flag = true; break;
680 TEST_EXTRA_ARG(i, 'U');
681 isxd_document_namespace = argv[i];
684 case 'V': version_flag = true; break;
685 case 'v': verbose_flag = true; break;
686 case 'W': no_write_flag = true; break;
689 TEST_EXTRA_ARG(i, 'x');
690 horizontal_subsampling = Kumu::xabs(strtol(argv[i], 0, 10));
694 TEST_EXTRA_ARG(i, 'X');
695 vertical_subsampling = Kumu::xabs(strtol(argv[i], 0, 10));
699 use_cdci_descriptor = true;
700 // default 10 bit video range YUV, ref levels already set
704 // Use values provided as argument, sharp tool, be careful
705 use_cdci_descriptor = true;
706 TEST_EXTRA_ARG(i, 'y');
707 if ( ! set_video_ref(argv[i]) )
713 case 'Z': j2c_pedantic = false; break;
714 case 'z': j2c_pedantic = true; break;
717 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
724 if ( argv[i][0] != '-' )
726 filenames.push_back(argv[i]);
730 fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
736 if ( ! mca_config_str.empty() )
738 if ( language.empty() )
740 if ( ! mca_config.DecodeString(mca_config_str) )
747 if ( ! mca_config.DecodeString(mca_config_str, language) )
754 if ( help_flag || version_flag || show_ul_values_flag )
759 if ( filenames.size() < 2 )
761 fputs("Option requires at least two filename arguments: <input-file> <output-file>\n", stderr);
765 out_file = filenames.back();
766 filenames.pop_back();
768 if ( ! picture_coding.HasValue() )
770 picture_coding = UL(g_dict->ul(MDD_JP2KEssenceCompression_BroadcastProfile_1));
778 //------------------------------------------------------------------------------------------
782 Result_t JP2K_PDesc_to_MD(const ASDCP::JP2K::PictureDescriptor& PDesc,
783 const ASDCP::Dictionary& dict,
784 ASDCP::MXF::GenericPictureEssenceDescriptor& GenericPictureEssenceDescriptor,
785 ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor);
787 Result_t PCM_ADesc_to_MD(ASDCP::PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj);
790 // Write one or more plaintext JPEG 2000 codestreams to a plaintext AS-02 file
791 // Write one or more plaintext JPEG 2000 codestreams to a ciphertext AS-02 file
794 write_JP2K_file(CommandOptions& Options)
796 AESEncContext* Context = 0;
797 HMACContext* HMAC = 0;
798 AS_02::JP2K::MXFWriter Writer;
799 JP2K::FrameBuffer FrameBuffer(Options.fb_size);
800 JP2K::SequenceParser Parser;
801 byte_t IV_buf[CBC_BLOCK_SIZE];
802 Kumu::FortunaRNG RNG;
803 ASDCP::MXF::FileDescriptor *essence_descriptor = 0;
804 ASDCP::MXF::InterchangeObject_list_t essence_sub_descriptors;
806 // set up essence parser
807 Result_t result = Parser.OpenRead(Options.filenames.front().c_str(), Options.j2c_pedantic);
810 if ( ASDCP_SUCCESS(result) )
812 ASDCP::JP2K::PictureDescriptor PDesc;
813 Parser.FillPictureDescriptor(PDesc);
814 PDesc.EditRate = Options.edit_rate;
816 if ( Options.verbose_flag )
818 fprintf(stderr, "JPEG 2000 pictures\n");
819 fputs("PictureDescriptor:\n", stderr);
820 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
821 JP2K::PictureDescriptorDump(PDesc);
824 if ( Options.use_cdci_descriptor )
826 ASDCP::MXF::CDCIEssenceDescriptor* tmp_dscr = new ASDCP::MXF::CDCIEssenceDescriptor(g_dict);
827 essence_sub_descriptors.push_back(new ASDCP::MXF::JPEG2000PictureSubDescriptor(g_dict));
829 result = ASDCP::JP2K_PDesc_to_MD(PDesc, *g_dict,
830 *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr),
831 *static_cast<ASDCP::MXF::JPEG2000PictureSubDescriptor*>(essence_sub_descriptors.back()));
833 if ( ASDCP_SUCCESS(result) )
835 tmp_dscr->CodingEquations = Options.coding_equations;
836 tmp_dscr->TransferCharacteristic = Options.transfer_characteristic;
837 tmp_dscr->ColorPrimaries = Options.color_primaries;
838 tmp_dscr->PictureEssenceCoding = Options.picture_coding;
839 tmp_dscr->HorizontalSubsampling = Options.horizontal_subsampling;
840 tmp_dscr->VerticalSubsampling = Options.vertical_subsampling;
841 tmp_dscr->ComponentDepth = Options.component_depth;
842 tmp_dscr->FrameLayout = Options.frame_layout;
843 tmp_dscr->AspectRatio = Options.aspect_ratio;
844 tmp_dscr->FieldDominance = Options.field_dominance;
845 tmp_dscr->WhiteReflevel = Options.cdci_WhiteRefLevel;
846 tmp_dscr->BlackRefLevel = Options.cdci_BlackRefLevel;
847 tmp_dscr->ColorRange = Options.cdci_ColorRange;
848 tmp_dscr->VideoLineMap = Options.line_map;
850 if ( Options.md_min_luminance || Options.md_max_luminance )
852 tmp_dscr->MasteringDisplayMinimumLuminance = Options.md_min_luminance;
853 tmp_dscr->MasteringDisplayMaximumLuminance = Options.md_max_luminance;
856 if ( Options.md_primaries.HasValue() )
858 tmp_dscr->MasteringDisplayPrimaries = Options.md_primaries;
859 tmp_dscr->MasteringDisplayWhitePointChromaticity = Options.md_white_point;
862 essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr);
867 ASDCP::MXF::RGBAEssenceDescriptor* tmp_dscr = new ASDCP::MXF::RGBAEssenceDescriptor(g_dict);
868 essence_sub_descriptors.push_back(new ASDCP::MXF::JPEG2000PictureSubDescriptor(g_dict));
870 result = ASDCP::JP2K_PDesc_to_MD(PDesc, *g_dict,
871 *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr),
872 *static_cast<ASDCP::MXF::JPEG2000PictureSubDescriptor*>(essence_sub_descriptors.back()));
874 if ( ASDCP_SUCCESS(result) )
876 tmp_dscr->CodingEquations = Options.coding_equations;
877 tmp_dscr->TransferCharacteristic = Options.transfer_characteristic;
878 tmp_dscr->ColorPrimaries = Options.color_primaries;
879 tmp_dscr->ScanningDirection = 0;
880 tmp_dscr->PictureEssenceCoding = Options.picture_coding;
881 tmp_dscr->ComponentMaxRef = Options.rgba_MaxRef;
882 tmp_dscr->ComponentMinRef = Options.rgba_MinRef;
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 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
903 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
904 Info.LabelSetType = LS_MXF_SMPTE;
906 if ( Options.asset_id_flag )
907 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
909 Kumu::GenRandomUUID(Info.AssetUUID);
911 // configure encryption
912 if( Options.key_flag )
914 Kumu::GenRandomUUID(Info.ContextID);
915 Info.EncryptedEssence = true;
917 if ( Options.key_id_flag )
919 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
923 create_random_uuid(Info.CryptographicKeyID);
926 Context = new AESEncContext;
927 result = Context->InitKey(Options.key_value);
929 if ( ASDCP_SUCCESS(result) )
930 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
932 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
934 Info.UsesHMAC = true;
935 HMAC = new HMACContext;
936 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
940 if ( ASDCP_SUCCESS(result) )
942 result = Writer.OpenWrite(Options.out_file, Info, essence_descriptor, essence_sub_descriptors,
943 Options.edit_rate, Options.mxf_header_size, Options.index_strategy, Options.partition_space);
947 if ( ASDCP_SUCCESS(result) )
950 result = Parser.Reset();
952 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
954 result = Parser.ReadFrame(FrameBuffer);
956 if ( ASDCP_SUCCESS(result) )
958 if ( Options.verbose_flag )
959 FrameBuffer.Dump(stderr, Options.fb_dump_size);
961 if ( Options.encrypt_header_flag )
962 FrameBuffer.PlaintextOffset(0);
965 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
967 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);
969 // The Writer class will forward the last block of ciphertext
970 // to the encryption context for use as the IV for the next
971 // frame. If you want to use non-sequitur IV values, un-comment
972 // the following line of code.
973 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
974 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
978 if ( result == RESULT_ENDOFFILE )
982 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
983 result = Writer.Finalize();
988 //------------------------------------------------------------------------------------------
992 // Write one or more plaintext PCM audio streams to a plaintext AS-02 file
993 // Write one or more plaintext PCM audio streams to a ciphertext AS-02 file
996 write_PCM_file(CommandOptions& Options)
998 AESEncContext* Context = 0;
999 HMACContext* HMAC = 0;
1000 PCMParserList Parser;
1001 AS_02::PCM::MXFWriter Writer;
1002 PCM::FrameBuffer FrameBuffer;
1003 byte_t IV_buf[CBC_BLOCK_SIZE];
1004 Kumu::FortunaRNG RNG;
1005 ASDCP::MXF::WaveAudioDescriptor *essence_descriptor = 0;
1007 // set up essence parser
1008 Result_t result = Parser.OpenRead(Options.filenames, Options.edit_rate);
1010 // set up MXF writer
1011 if ( ASDCP_SUCCESS(result) )
1013 ASDCP::PCM::AudioDescriptor ADesc;
1014 Parser.FillAudioDescriptor(ADesc);
1016 ADesc.EditRate = Options.edit_rate;
1017 FrameBuffer.Capacity(PCM::CalcFrameBufferSize(ADesc));
1019 if ( Options.verbose_flag )
1022 fprintf(stderr, "%.1fkHz PCM Audio, %s fps (%u spf)\n",
1023 ADesc.AudioSamplingRate.Quotient() / 1000.0,
1024 RationalToString(Options.edit_rate, buf, 64),
1025 PCM::CalcSamplesPerFrame(ADesc));
1026 fputs("AudioDescriptor:\n", stderr);
1027 PCM::AudioDescriptorDump(ADesc);
1030 essence_descriptor = new ASDCP::MXF::WaveAudioDescriptor(g_dict);
1032 result = ASDCP::PCM_ADesc_to_MD(ADesc, essence_descriptor);
1034 if ( Options.mca_config.empty() )
1036 essence_descriptor->ChannelAssignment = Options.channel_assignment;
1040 if ( Options.mca_config.ChannelCount() != essence_descriptor->ChannelCount )
1042 fprintf(stderr, "MCA label count (%d) differs from essence stream channel count (%d).\n",
1043 Options.mca_config.ChannelCount(), essence_descriptor->ChannelCount);
1047 // this is the d-cinema MCA label, what is the one for IMF?
1048 essence_descriptor->ChannelAssignment = g_dict->ul(MDD_IMFAudioChannelCfg_MCA);
1052 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1054 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
1055 Info.LabelSetType = LS_MXF_SMPTE;
1057 if ( Options.asset_id_flag )
1058 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
1060 Kumu::GenRandomUUID(Info.AssetUUID);
1062 // configure encryption
1063 if( Options.key_flag )
1065 Kumu::GenRandomUUID(Info.ContextID);
1066 Info.EncryptedEssence = true;
1068 if ( Options.key_id_flag )
1070 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
1074 create_random_uuid(Info.CryptographicKeyID);
1077 Context = new AESEncContext;
1078 result = Context->InitKey(Options.key_value);
1080 if ( ASDCP_SUCCESS(result) )
1081 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1083 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
1085 Info.UsesHMAC = true;
1086 HMAC = new HMACContext;
1087 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
1091 if ( ASDCP_SUCCESS(result) )
1093 result = Writer.OpenWrite(Options.out_file.c_str(), Info, essence_descriptor,
1094 Options.mca_config, Options.edit_rate);
1098 if ( ASDCP_SUCCESS(result) )
1100 result = Parser.Reset();
1101 ui32_t duration = 0;
1103 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
1105 result = Parser.ReadFrame(FrameBuffer);
1107 if ( ASDCP_SUCCESS(result) )
1109 if ( Options.verbose_flag )
1110 FrameBuffer.Dump(stderr, Options.fb_dump_size);
1112 if ( ! Options.no_write_flag )
1114 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);
1116 // The Writer class will forward the last block of ciphertext
1117 // to the encryption context for use as the IV for the next
1118 // frame. If you want to use non-sequitur IV values, un-comment
1119 // the following line of code.
1120 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
1121 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1126 if ( result == RESULT_ENDOFFILE )
1130 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1131 result = Writer.Finalize();
1139 //------------------------------------------------------------------------------------------
1140 // TimedText essence
1143 // Write one or more plaintext timed text streams to a plaintext AS-02 file
1144 // Write one or more plaintext timed text streams to a ciphertext AS-02 file
1147 write_timed_text_file(CommandOptions& Options)
1149 AESEncContext* Context = 0;
1150 HMACContext* HMAC = 0;
1151 AS_02::TimedText::ST2052_TextParser Parser;
1152 AS_02::TimedText::MXFWriter Writer;
1153 TimedText::FrameBuffer FrameBuffer;
1154 TimedText::TimedTextDescriptor TDesc;
1155 byte_t IV_buf[CBC_BLOCK_SIZE];
1156 Kumu::FortunaRNG RNG;
1158 // set up essence parser
1159 Result_t result = Parser.OpenRead(Options.filenames.front());
1161 // set up MXF writer
1162 if ( ASDCP_SUCCESS(result) )
1164 Parser.FillTimedTextDescriptor(TDesc);
1165 TDesc.EditRate = Options.edit_rate;
1166 TDesc.ContainerDuration = Options.duration;
1167 FrameBuffer.Capacity(Options.fb_size);
1169 if ( ! Options.profile_name.empty() )
1171 TDesc.NamespaceName = Options.profile_name;
1174 if ( Options.verbose_flag )
1176 fputs("IMF Timed-Text Descriptor:\n", stderr);
1177 TimedText::DescriptorDump(TDesc);
1181 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1183 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
1184 Info.LabelSetType = LS_MXF_SMPTE;
1186 if ( Options.asset_id_flag )
1187 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
1189 Kumu::GenRandomUUID(Info.AssetUUID);
1191 // configure encryption
1192 if( Options.key_flag )
1194 Kumu::GenRandomUUID(Info.ContextID);
1195 Info.EncryptedEssence = true;
1197 if ( Options.key_id_flag )
1199 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
1203 create_random_uuid(Info.CryptographicKeyID);
1206 Context = new AESEncContext;
1207 result = Context->InitKey(Options.key_value);
1209 if ( ASDCP_SUCCESS(result) )
1210 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1212 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
1214 Info.UsesHMAC = true;
1215 HMAC = new HMACContext;
1216 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
1220 if ( ASDCP_SUCCESS(result) )
1221 result = Writer.OpenWrite(Options.out_file.c_str(), Info, TDesc);
1224 if ( ASDCP_FAILURE(result) )
1228 TimedText::ResourceList_t::const_iterator ri;
1230 result = Parser.ReadTimedTextResource(XMLDoc);
1232 if ( ASDCP_SUCCESS(result) )
1233 result = Writer.WriteTimedTextResource(XMLDoc, Context, HMAC);
1235 for ( ri = TDesc.ResourceList.begin() ; ri != TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ )
1237 result = Parser.ReadAncillaryResource((*ri).ResourceID, FrameBuffer);
1239 if ( ASDCP_SUCCESS(result) )
1241 if ( Options.verbose_flag )
1242 FrameBuffer.Dump(stderr, Options.fb_dump_size);
1244 if ( ! Options.no_write_flag )
1246 result = Writer.WriteAncillaryResource(FrameBuffer, Context, HMAC);
1248 // The Writer class will forward the last block of ciphertext
1249 // to the encryption context for use as the IV for the next
1250 // frame. If you want to use non-sequitur IV values, un-comment
1251 // the following line of code.
1252 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
1253 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1257 if ( result == RESULT_ENDOFFILE )
1261 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1262 result = Writer.Finalize();
1269 get_current_dms_text_descriptor(AS_02::ISXD::MXFWriter& writer, ASDCP::MXF::GenericStreamTextBasedSet *&text_object)
1271 std::list<MXF::InterchangeObject*> object_list;
1272 writer.OP1aHeader().GetMDObjectsByType(DefaultSMPTEDict().ul(MDD_GenericStreamTextBasedSet), object_list);
1274 if ( object_list.empty() )
1279 text_object = dynamic_cast<MXF::GenericStreamTextBasedSet*>(object_list.back());
1280 assert(text_object != 0);
1285 // Write one or more plaintext Aux Data bytestreams to a plaintext AS-02 file
1286 // Write one or more plaintext Aux Data bytestreams to a ciphertext AS-02 file
1289 write_isxd_file(CommandOptions& Options)
1291 AESEncContext* Context = 0;
1292 HMACContext* HMAC = 0;
1293 AS_02::ISXD::MXFWriter Writer;
1294 DCData::FrameBuffer FrameBuffer(Options.fb_size);
1295 DCData::SequenceParser Parser;
1296 byte_t IV_buf[CBC_BLOCK_SIZE];
1297 Kumu::FortunaRNG RNG;
1299 // set up essence parser
1300 Result_t result = Parser.OpenRead(Options.filenames.front());
1302 // set up MXF writer
1303 if ( ASDCP_SUCCESS(result) )
1306 if ( Options.verbose_flag )
1308 fprintf(stderr, "Aux Data\n");
1309 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
1313 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1315 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
1316 if ( Options.asset_id_flag )
1317 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
1319 Kumu::GenRandomUUID(Info.AssetUUID);
1321 Info.LabelSetType = LS_MXF_SMPTE;
1323 // configure encryption
1324 if( Options.key_flag )
1326 Kumu::GenRandomUUID(Info.ContextID);
1327 Info.EncryptedEssence = true;
1329 if ( Options.key_id_flag )
1331 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
1335 create_random_uuid(Info.CryptographicKeyID);
1338 Context = new AESEncContext;
1339 result = Context->InitKey(Options.key_value);
1341 if ( ASDCP_SUCCESS(result) )
1342 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1344 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
1346 Info.UsesHMAC = true;
1347 HMAC = new HMACContext;
1348 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
1352 if ( ASDCP_SUCCESS(result) )
1354 if ( Options.isxd_document_namespace == "auto" )
1356 // get ns of first item
1357 std::string ns_prefix, type_name, namespace_name;
1358 result = Parser.ReadFrame(FrameBuffer);
1360 if ( ASDCP_SUCCESS(result) )
1362 Kumu::AttributeList doc_attr_list;
1363 result = GetXMLDocType(FrameBuffer.RoData(), FrameBuffer.Size(), ns_prefix, type_name,
1364 namespace_name, doc_attr_list) ? RESULT_OK : RESULT_FAIL;
1367 if ( ASDCP_SUCCESS(result) && ! namespace_name.empty() )
1369 Options.isxd_document_namespace = namespace_name;
1373 fprintf(stderr, "Unable to parse an XML namespace name from the input document.\n");
1378 result = Writer.OpenWrite(Options.out_file, Info, Options.isxd_document_namespace, Options.edit_rate);
1382 if ( ASDCP_SUCCESS(result) )
1384 ui32_t duration = 0;
1385 result = Parser.Reset();
1387 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
1389 result = Parser.ReadFrame(FrameBuffer);
1391 if ( ASDCP_SUCCESS(result) )
1393 if ( Options.verbose_flag )
1394 FrameBuffer.Dump(stderr, Options.fb_dump_size);
1396 if ( Options.encrypt_header_flag )
1397 FrameBuffer.PlaintextOffset(0);
1400 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
1402 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);
1404 // The Writer class will forward the last block of ciphertext
1405 // to the encryption context for use as the IV for the next
1406 // frame. If you want to use non-sequitur IV values, un-comment
1407 // the following line of code.
1408 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
1409 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
1413 if ( result == RESULT_ENDOFFILE )
1419 if ( KM_SUCCESS(result) && ! Options.no_write_flag )
1421 ASDCP::FrameBuffer global_metadata;
1422 std::list<std::string>::iterator i;
1424 for ( i = Options.global_isxd_metadata.begin(); i != Options.global_isxd_metadata.end(); ++i )
1426 ui32_t file_size = Kumu::FileSize(*i);
1427 result = global_metadata.Capacity(file_size);
1429 if ( KM_SUCCESS(result) )
1431 ui32_t read_count = 0;
1432 Kumu::FileReader Reader;
1433 std::string namespace_name;
1435 result = Reader.OpenRead(*i);
1437 if ( KM_SUCCESS(result) )
1439 result = Reader.Read(global_metadata.Data(), file_size, &read_count);
1442 if ( KM_SUCCESS(result) )
1444 if ( file_size != read_count)
1445 return RESULT_READFAIL;
1447 global_metadata.Size(read_count);
1449 std::string ns_prefix, type_name;
1450 Kumu::AttributeList doc_attr_list;
1451 result = GetXMLDocType(global_metadata.RoData(), global_metadata.Size(), ns_prefix, type_name,
1452 namespace_name, doc_attr_list) ? RESULT_OK : RESULT_FAIL;
1455 if ( KM_SUCCESS(result) )
1457 result = Writer.AddDmsGenericPartUtf8Text(global_metadata, Context, HMAC);
1460 if ( KM_SUCCESS(result) )
1462 ASDCP::MXF::GenericStreamTextBasedSet *text_object = 0;
1463 get_current_dms_text_descriptor(Writer, text_object);
1464 assert(text_object);
1465 text_object->TextMIMEMediaType = "text/xml";
1466 text_object->TextDataDescription = namespace_name;
1468 // this is not really useful when inserting multiple objects because
1469 // it cannot be set per object without some other CLI syntax for
1470 // associating language codes with 2057 blobs, e.g., <filename>:<lang>
1471 text_object->RFC5646TextLanguageCode = Options.language;
1476 if ( KM_SUCCESS(result) )
1478 result = Writer.Finalize();
1487 main(int argc, const char** argv)
1489 Result_t result = RESULT_OK;
1491 g_dict = &ASDCP::DefaultSMPTEDict();
1494 CommandOptions Options(argc, argv);
1496 if ( Options.version_flag )
1499 if ( Options.help_flag )
1502 if ( Options.show_ul_values_flag )
1504 g_dict->Dump(stdout);
1507 if ( Options.version_flag || Options.help_flag || Options.show_ul_values_flag )
1510 if ( Options.error_flag )
1512 fprintf(stderr, "There was a problem. Type %s -h for help.\n", PROGRAM_NAME);
1516 EssenceType_t EssenceType;
1517 result = ASDCP::RawEssenceType(Options.filenames.front().c_str(), EssenceType);
1519 if ( ASDCP_SUCCESS(result) )
1521 switch ( EssenceType )
1524 result = write_JP2K_file(Options);
1527 case ESS_PCM_24b_48k:
1528 case ESS_PCM_24b_96k:
1529 result = write_PCM_file(Options);
1532 case ESS_TIMED_TEXT:
1533 result = write_timed_text_file(Options);
1536 case ESS_DCDATA_UNKNOWN:
1537 if ( ! Options.isxd_document_namespace.empty() )
1539 result = write_isxd_file(Options);
1543 fprintf(stderr, "%s: Unknown synchronous data file type, not AS-02-compatible essence.\n",
1544 Options.filenames.front().c_str());
1550 fprintf(stderr, "%s: Unknown file type, not AS-02-compatible essence.\n",
1551 Options.filenames.front().c_str());
1556 if ( ASDCP_FAILURE(result) )
1558 fputs("Program stopped on error.\n", stderr);
1560 if ( result != RESULT_FAIL )
1562 fputs(result, stderr);
1563 fputc('\n', stderr);
1574 // end as-02-wrap.cpp