2 Copyright (c) 2011-2016, John Hurst
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 3. The name of the author may not be used to endorse or promote products
15 derived from this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 /*! \file phdr-wrap.cpp
30 \brief prototype wrapping for HDR images in AS-02
32 This program wraps IMF essence (P-HDR picture) in to an AS-02 MXF file.
35 #include <KM_fileio.h>
37 #include <AS_02_PHDR.h>
39 using namespace ASDCP;
41 const ui32_t FRAME_BUFFER_SIZE = 4 * Kumu::Megabyte;
42 const ASDCP::Dictionary *g_dict = 0;
46 RationalToString(const ASDCP::Rational& r, char* buf, const ui32_t& len)
48 snprintf(buf, len, "%d/%d", r.Numerator, r.Denominator);
54 //------------------------------------------------------------------------------------------
56 // command line option parser class
58 static const char* PROGRAM_NAME = "as-02-wrap"; // program name for messages
60 // local program identification info written to file headers
61 class MyInfo : public WriterInfo
66 static byte_t default_ProductUUID_Data[UUIDlen] =
67 { 0xef, 0xe4, 0x59, 0xab, 0xbe, 0x0f, 0x4c, 0x7d,
68 0xb3, 0xa2, 0xb8, 0x96, 0x79, 0xe2, 0x3e, 0x8e };
70 memcpy(ProductUUID, default_ProductUUID_Data, UUIDlen);
71 CompanyName = "WidgetCo";
72 ProductName = "phdr-wrap";
73 ProductVersion = ASDCP::Version();
79 // Increment the iterator, test for an additional non-option command line argument.
80 // Causes the caller to return if there are no remaining arguments or if the next
81 // argument begins with '-'.
82 #define TEST_EXTRA_ARG(i,c) \
83 if ( ++i >= argc || argv[(i)][0] == '-' ) { \
84 fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
90 create_random_uuid(byte_t* uuidbuf)
93 GenRandomValue(tmp_id);
94 memcpy(uuidbuf, tmp_id.Value(), tmp_id.Size());
99 banner(FILE* stream = stdout)
102 %s (asdcplib %s)\n\n\
103 Copyright (c) 2011-2015, John Hurst\n\n\
104 asdcplib may be copied only under the terms of the license found at\n\
105 the top of every file in the asdcplib distribution kit.\n\n\
106 Specify the -h (help) option for further information about %s\n\n",
107 PROGRAM_NAME, ASDCP::Version(), PROGRAM_NAME);
112 usage(FILE* stream = stdout)
115 USAGE: %s [-h|-help] [-V]\n\
117 %s [-a <uuid>] [-A <w>/<h>] [-b <buffer-size>] [-C <UL>] [-d <duration>]\n\
118 [-D <depth>] [-e|-E] [-i] [-j <key-id-string>] [-k <key-string>]\n\
119 [-M] [-m <expr>] [-p <ul>] [-r <n>/<d>] [-R] [-s <seconds>]\n\
120 [-t <min>] [-T <max>] [-u] [-v] [-W] [-x <int>] [-X <int>] [-Y]\n\
121 [-z|-Z] <input-file>+ <output-file>\n\n",
122 PROGRAM_NAME, PROGRAM_NAME);
126 -h | -help - Show help\n\
127 -V - Show version information\n\
128 -a <uuid> - Specify the Asset ID of the file\n\
129 -A <w>/<h> - Set aspect ratio for image (default 4/3)\n\
130 -b <buffer-size> - Specify size in bytes of picture frame buffer\n\
131 Defaults to 4,194,304 (4MB)\n\
132 -C <ul> - Set ChannelAssignment UL value\n\
133 -d <duration> - Number of frames to process, default all\n\
134 -D <depth> - Component depth for YCbCr images (default: 10)\n\
135 -e - Encrypt JP2K headers (default)\n\
136 -E - Do not encrypt JP2K headers\n\
137 -F (0|1) - Set field dominance for interlaced image (default: 0)\n\
138 -g <filename> - Write global metadata from the named PIDM file.\n\
139 -i - Indicates input essence is interlaced fields (forces -Y)\n\
140 -j <key-id-str> - Write key ID instead of creating a random value\n\
141 -k <key-string> - Use key for ciphertext operations\n\
142 -M - Do not create HMAC values when writing\n\
143 -m <filename> - Filename of master metadata instance (the contents of\n\
144 which will be placed in the MXF wrapper)\n\
145 -p <ul> - Set broadcast profile\n\
146 -r <n>/<d> - Edit Rate of the output file. 24/1 is the default\n\
147 -R - Indicates RGB image essence (default)\n\
148 -s <seconds> - Duration of a frame-wrapped partition (default 60)\n\
149 -t <min> - Set RGB component minimum code value (default: 0)\n\
150 -T <max> - Set RGB component maximum code value (default: 1023)\n\
151 -u - Print UL catalog to stderr\n\
152 -U <UL> - Set DataEssenceCoding UL value in an Aux Data file\n\
153 -v - Verbose, prints informative messages to stderr\n\
154 -W - Read input file only, do not write source file\n\
155 -x <int> - Horizontal subsampling degree (default: 2)\n\
156 -X <int> - Vertical subsampling degree (default: 2)\n\
157 -Y - Indicates YCbCr image essence (default: RGB)\n\
158 -z - Fail if j2c inputs have unequal parameters (default)\n\
159 -Z - Ignore unequal parameters in j2c inputs\n\
161 NOTES: o There is no option grouping, all options must be distinct arguments.\n\
162 o All option arguments must be separated from the option by whitespace.\n\n");
172 bool error_flag; // true if the given options are in error or not complete
173 bool key_flag; // true if an encryption key was given
174 bool asset_id_flag; // true if an asset ID was given
175 bool encrypt_header_flag; // true if j2c headers are to be encrypted
176 bool write_hmac; // true if HMAC values are to be generated and written
177 bool verbose_flag; // true if the verbose option was selected
178 ui32_t fb_dump_size; // number of bytes of frame buffer to dump
179 bool no_write_flag; // true if no output files are to be written
180 bool version_flag; // true if the version display option was selected
181 bool help_flag; // true if the help display option was selected
182 ui32_t duration; // number of frames to be processed
183 bool j2c_pedantic; // passed to JP2K::SequenceParser::OpenRead
184 bool use_cdci_descriptor; //
185 Rational edit_rate; // edit rate of JP2K sequence
186 ui32_t fb_size; // size of picture frame buffer
187 byte_t key_value[KeyLen]; // value of given encryption key (when key_flag is true)
188 bool key_id_flag; // true if a key ID was given
189 byte_t key_id_value[UUIDlen];// value of given key ID (when key_id_flag is true)
190 byte_t asset_id_value[UUIDlen];// value of asset ID (when asset_id_flag is true)
191 std::string out_file; //
192 bool show_ul_values_flag; /// if true, dump the UL table before going tp work.
193 Kumu::PathList_t filenames; // list of filenames to be processed
199 ui32_t horizontal_subsampling;
200 ui32_t vertical_subsampling;
201 ui32_t component_depth;
203 ASDCP::Rational aspect_ratio;
204 ui8_t field_dominance;
205 ui32_t mxf_header_size;
207 //new attributes for AS-02 support
208 AS_02::IndexStrategy_t index_strategy; //Shim parameter index_strategy_frame/clip
209 ui32_t partition_space; //Shim parameter partition_spacing
211 std::string PHDR_master_metadata;
213 std::string global_metadata_filename;
216 CommandOptions(int argc, const char** argv) :
217 error_flag(true), key_flag(false), key_id_flag(false), asset_id_flag(false),
218 encrypt_header_flag(true), write_hmac(true), verbose_flag(false), fb_dump_size(0),
219 no_write_flag(false), version_flag(false), help_flag(false),
220 duration(0xffffffff), j2c_pedantic(true), use_cdci_descriptor(false), edit_rate(24,1), fb_size(FRAME_BUFFER_SIZE),
221 show_ul_values_flag(false), index_strategy(AS_02::IS_FOLLOW), partition_space(60),
222 rgba_MaxRef(1023), rgba_MinRef(0),
223 horizontal_subsampling(2), vertical_subsampling(2), component_depth(10),
224 frame_layout(0), aspect_ratio(ASDCP::Rational(4,3)), field_dominance(0),
225 mxf_header_size(16384)
227 memset(key_value, 0, KeyLen);
228 memset(key_id_value, 0, UUIDlen);
230 for ( int i = 1; i < argc; i++ )
233 if ( (strcmp( argv[i], "-help") == 0) )
239 if ( argv[i][0] == '-'
240 && ( isalpha(argv[i][1]) || isdigit(argv[i][1]) )
243 switch ( argv[i][1] )
246 TEST_EXTRA_ARG(i, 'A');
247 if ( ! DecodeRational(argv[i], aspect_ratio) )
249 fprintf(stderr, "Error decoding aspect ratio value: %s\n", argv[i]);
255 asset_id_flag = true;
256 TEST_EXTRA_ARG(i, 'a');
259 Kumu::hex2bin(argv[i], asset_id_value, UUIDlen, &length);
261 if ( length != UUIDlen )
263 fprintf(stderr, "Unexpected asset ID length: %u, expecting %u characters.\n", length, UUIDlen);
270 TEST_EXTRA_ARG(i, 'b');
271 fb_size = Kumu::xabs(strtol(argv[i], 0, 10));
274 fprintf(stderr, "Frame Buffer size: %u bytes.\n", fb_size);
279 TEST_EXTRA_ARG(i, 'D');
280 component_depth = Kumu::xabs(strtol(argv[i], 0, 10));
284 TEST_EXTRA_ARG(i, 'd');
285 duration = Kumu::xabs(strtol(argv[i], 0, 10));
288 case 'E': encrypt_header_flag = false; break;
289 case 'e': encrypt_header_flag = true; break;
292 TEST_EXTRA_ARG(i, 'F');
293 field_dominance = Kumu::xabs(strtol(argv[i], 0, 10));
294 if ( field_dominance > 1 )
296 fprintf(stderr, "Field dominance value must be \"0\" or \"1\"\n");
302 TEST_EXTRA_ARG(i, 'g');
303 global_metadata_filename = argv[i];
306 case 'h': help_flag = true; break;
310 use_cdci_descriptor = true;
315 TEST_EXTRA_ARG(i, 'j');
318 Kumu::hex2bin(argv[i], key_id_value, UUIDlen, &length);
320 if ( length != UUIDlen )
322 fprintf(stderr, "Unexpected key ID length: %u, expecting %u characters.\n", length, UUIDlen);
328 case 'k': key_flag = true;
329 TEST_EXTRA_ARG(i, 'k');
332 Kumu::hex2bin(argv[i], key_value, KeyLen, &length);
334 if ( length != KeyLen )
336 fprintf(stderr, "Unexpected key length: %u, expecting %u characters.\n", length, KeyLen);
342 case 'M': write_hmac = false; break;
345 TEST_EXTRA_ARG(i, 'm');
346 if ( KM_FAILURE(Kumu::ReadFileIntoString(argv[i], PHDR_master_metadata) ) )
348 fprintf(stderr, "Unable to read metadata file %s\n", argv[i]);
354 TEST_EXTRA_ARG(i, 'p');
355 if ( ! picture_coding.DecodeHex(argv[i]) )
357 fprintf(stderr, "Error decoding PictureEssenceCoding UL value: %s\n", argv[i]);
363 TEST_EXTRA_ARG(i, 'r');
364 if ( ! DecodeRational(argv[i], edit_rate) )
366 fprintf(stderr, "Error decoding edit rate value: %s\n", argv[i]);
373 use_cdci_descriptor = false;
377 TEST_EXTRA_ARG(i, 's');
378 partition_space = Kumu::xabs(strtol(argv[i], 0, 10));
382 TEST_EXTRA_ARG(i, 't');
383 rgba_MinRef = Kumu::xabs(strtol(argv[i], 0, 10));
387 TEST_EXTRA_ARG(i, 'T');
388 rgba_MaxRef = Kumu::xabs(strtol(argv[i], 0, 10));
391 case 'u': show_ul_values_flag = true; break;
394 TEST_EXTRA_ARG(i, 'U');
395 if ( ! aux_data_coding.DecodeHex(argv[i]) )
397 fprintf(stderr, "Error decoding UL value: %s\n", argv[i]);
402 case 'V': version_flag = true; break;
403 case 'v': verbose_flag = true; break;
404 case 'W': no_write_flag = true; break;
407 TEST_EXTRA_ARG(i, 'x');
408 horizontal_subsampling = Kumu::xabs(strtol(argv[i], 0, 10));
412 TEST_EXTRA_ARG(i, 'X');
413 vertical_subsampling = Kumu::xabs(strtol(argv[i], 0, 10));
417 use_cdci_descriptor = true;
420 case 'Z': j2c_pedantic = false; break;
421 case 'z': j2c_pedantic = true; break;
424 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
431 if ( argv[i][0] != '-' )
433 filenames.push_back(argv[i]);
437 fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
443 if ( help_flag || version_flag )
446 if ( filenames.size() < 2 )
448 fputs("Option requires at least two filename arguments: <input-file> <output-file>\n", stderr);
452 out_file = filenames.back();
453 filenames.pop_back();
455 if ( ! picture_coding.HasValue() )
457 picture_coding = UL(g_dict->ul(MDD_JP2KEssenceCompression_BroadcastProfile_1));
465 //------------------------------------------------------------------------------------------
469 Result_t JP2K_PDesc_to_MD(const ASDCP::JP2K::PictureDescriptor& PDesc,
470 const ASDCP::Dictionary& dict,
471 ASDCP::MXF::GenericPictureEssenceDescriptor& GenericPictureEssenceDescriptor,
472 ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor);
475 // Write one or more plaintext JPEG 2000 codestreams to a plaintext AS-02 file
476 // Write one or more plaintext JPEG 2000 codestreams to a ciphertext AS-02 file
479 write_JP2K_file(CommandOptions& Options)
481 AS_02::PHDR::MXFWriter Writer;
482 AS_02::PHDR::FrameBuffer FrameBuffer(Options.fb_size);
483 AS_02::PHDR::SequenceParser Parser;
485 AESEncContext* Context = 0;
486 HMACContext* HMAC = 0;
487 byte_t IV_buf[CBC_BLOCK_SIZE];
488 Kumu::FortunaRNG RNG;
490 ASDCP::MXF::FileDescriptor *essence_descriptor = 0;
491 ASDCP::MXF::InterchangeObject_list_t essence_sub_descriptors;
493 // set up essence parser
494 Result_t result = Parser.OpenRead(Options.filenames.front().c_str(), Options.j2c_pedantic);
497 if ( ASDCP_SUCCESS(result) )
499 ASDCP::JP2K::PictureDescriptor PDesc;
500 Parser.FillPictureDescriptor(PDesc);
501 PDesc.EditRate = Options.edit_rate;
503 if ( Options.verbose_flag )
505 fprintf(stderr, "JPEG 2000 P-HDR pictures\n");
506 fputs("PictureDescriptor:\n", stderr);
507 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
508 JP2K::PictureDescriptorDump(PDesc);
511 if ( Options.use_cdci_descriptor )
513 ASDCP::MXF::CDCIEssenceDescriptor* tmp_dscr = new ASDCP::MXF::CDCIEssenceDescriptor(g_dict);
514 essence_sub_descriptors.push_back(new ASDCP::MXF::JPEG2000PictureSubDescriptor(g_dict));
516 result = ASDCP::JP2K_PDesc_to_MD(PDesc, *g_dict,
517 *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr),
518 *static_cast<ASDCP::MXF::JPEG2000PictureSubDescriptor*>(essence_sub_descriptors.back()));
520 if ( ASDCP_SUCCESS(result) )
522 tmp_dscr->PictureEssenceCoding = Options.picture_coding;
523 tmp_dscr->HorizontalSubsampling = Options.horizontal_subsampling;
524 tmp_dscr->VerticalSubsampling = Options.vertical_subsampling;
525 tmp_dscr->ComponentDepth = Options.component_depth;
526 tmp_dscr->FrameLayout = Options.frame_layout;
527 tmp_dscr->AspectRatio = Options.aspect_ratio;
528 tmp_dscr->FieldDominance = Options.field_dominance;
529 essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr);
534 ASDCP::MXF::RGBAEssenceDescriptor* tmp_dscr = new ASDCP::MXF::RGBAEssenceDescriptor(g_dict);
535 essence_sub_descriptors.push_back(new ASDCP::MXF::JPEG2000PictureSubDescriptor(g_dict));
537 result = ASDCP::JP2K_PDesc_to_MD(PDesc, *g_dict,
538 *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(tmp_dscr),
539 *static_cast<ASDCP::MXF::JPEG2000PictureSubDescriptor*>(essence_sub_descriptors.back()));
541 if ( ASDCP_SUCCESS(result) )
543 tmp_dscr->PictureEssenceCoding = UL(g_dict->ul(MDD_JP2KEssenceCompression_BroadcastProfile_1));
544 tmp_dscr->ComponentMaxRef = Options.rgba_MaxRef;
545 tmp_dscr->ComponentMinRef = Options.rgba_MinRef;
546 essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr);
551 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
553 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
554 Info.LabelSetType = LS_MXF_SMPTE;
556 if ( Options.asset_id_flag )
557 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
559 Kumu::GenRandomUUID(Info.AssetUUID);
561 // configure encryption
562 if( Options.key_flag )
564 Kumu::GenRandomUUID(Info.ContextID);
565 Info.EncryptedEssence = true;
567 if ( Options.key_id_flag )
568 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
570 RNG.FillRandom(Info.CryptographicKeyID, UUIDlen);
572 Context = new AESEncContext;
573 result = Context->InitKey(Options.key_value);
575 if ( ASDCP_SUCCESS(result) )
576 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
578 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
580 Info.UsesHMAC = true;
581 HMAC = new HMACContext;
582 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
586 if ( ASDCP_SUCCESS(result) )
588 result = Writer.OpenWrite(Options.out_file, Info, essence_descriptor, essence_sub_descriptors,
589 Options.edit_rate, Options.mxf_header_size, Options.index_strategy, Options.partition_space);
593 if ( ASDCP_SUCCESS(result) )
596 result = Parser.Reset();
598 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
600 result = Parser.ReadFrame(FrameBuffer);
602 if ( ASDCP_SUCCESS(result) )
604 if ( Options.verbose_flag )
605 FrameBuffer.Dump(stderr, Options.fb_dump_size);
607 if ( Options.encrypt_header_flag )
608 FrameBuffer.PlaintextOffset(0);
611 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
613 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);
615 // The Writer class will forward the last block of ciphertext
616 // to the encryption context for use as the IV for the next
617 // frame. If you want to use non-sequitur IV values, un-comment
618 // the following line of code.
619 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
620 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
624 if ( result == RESULT_ENDOFFILE )
628 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
629 result = Writer.Finalize(Options.PHDR_master_metadata);
636 // Write one or more plaintext Aux Data bytestreams to a plaintext AS-02 file
637 // Write one or more plaintext Aux Data bytestreams to a ciphertext AS-02 file
640 write_aux_data_file(CommandOptions& Options)
642 AESEncContext* Context = 0;
643 HMACContext* HMAC = 0;
644 AS_02::PIDM::MXFWriter Writer;
645 DCData::FrameBuffer FrameBuffer(Options.fb_size);
646 DCData::SequenceParser Parser;
647 byte_t IV_buf[CBC_BLOCK_SIZE];
648 Kumu::FortunaRNG RNG;
650 if ( ! Options.global_metadata_filename.empty() )
652 if ( ! Kumu::PathIsFile(Options.global_metadata_filename) )
654 fprintf(stderr, "No such file or filename: \"%s\".\n", Options.global_metadata_filename.c_str());
659 // set up essence parser
660 Result_t result = Parser.OpenRead(Options.filenames.front());
663 if ( ASDCP_SUCCESS(result) )
666 if ( Options.verbose_flag )
668 fprintf(stderr, "Aux Data\n");
669 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
673 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
675 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
676 if ( Options.asset_id_flag )
677 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);
679 Kumu::GenRandomUUID(Info.AssetUUID);
681 Info.LabelSetType = LS_MXF_SMPTE;
683 // configure encryption
684 if( Options.key_flag )
686 Kumu::GenRandomUUID(Info.ContextID);
687 Info.EncryptedEssence = true;
689 if ( Options.key_id_flag )
691 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);
695 create_random_uuid(Info.CryptographicKeyID);
698 Context = new AESEncContext;
699 result = Context->InitKey(Options.key_value);
701 if ( ASDCP_SUCCESS(result) )
702 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
704 if ( ASDCP_SUCCESS(result) && Options.write_hmac )
706 Info.UsesHMAC = true;
707 HMAC = new HMACContext;
708 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
712 if ( ASDCP_SUCCESS(result) )
714 result = Writer.OpenWrite(Options.out_file, Info, Options.aux_data_coding, Options.edit_rate);
718 if ( ASDCP_SUCCESS(result) )
721 result = Parser.Reset();
723 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )
725 result = Parser.ReadFrame(FrameBuffer);
727 if ( ASDCP_SUCCESS(result) )
729 if ( Options.verbose_flag )
730 FrameBuffer.Dump(stderr, Options.fb_dump_size);
732 if ( Options.encrypt_header_flag )
733 FrameBuffer.PlaintextOffset(0);
736 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
738 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);
740 // The Writer class will forward the last block of ciphertext
741 // to the encryption context for use as the IV for the next
742 // frame. If you want to use non-sequitur IV values, un-comment
743 // the following line of code.
744 // if ( ASDCP_SUCCESS(result) && Options.key_flag )
745 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));
749 if ( result == RESULT_ENDOFFILE )
753 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
755 if ( Options.global_metadata_filename.empty() )
757 result = Writer.Finalize();
761 ASDCP::FrameBuffer global_metadata;
762 ui32_t file_size = Kumu::FileSize(Options.global_metadata_filename);
763 result = global_metadata.Capacity(file_size);
765 if ( ASDCP_SUCCESS(result) )
767 ui32_t read_count = 0;
768 Kumu::FileReader Reader;
770 result = Reader.OpenRead(Options.global_metadata_filename);
772 if ( ASDCP_SUCCESS(result) )
773 result = Reader.Read(global_metadata.Data(), file_size, &read_count);
775 if ( ASDCP_SUCCESS(result) )
777 if ( file_size != read_count)
778 return RESULT_READFAIL;
780 global_metadata.Size(read_count);
784 result = Writer.Finalize(global_metadata);
793 main(int argc, const char** argv)
795 Result_t result = RESULT_OK;
797 g_dict = &ASDCP::DefaultSMPTEDict();
800 CommandOptions Options(argc, argv);
802 if ( Options.version_flag )
805 if ( Options.help_flag )
808 if ( Options.show_ul_values_flag )
810 g_dict->Dump(stdout);
813 if ( Options.version_flag || Options.help_flag || Options.show_ul_values_flag )
816 if ( Options.error_flag )
818 fprintf(stderr, "There was a problem. Type %s -h for help.\n", PROGRAM_NAME);
822 EssenceType_t EssenceType;
823 result = ASDCP::RawEssenceType(Options.filenames.front().c_str(), EssenceType);
825 if ( ASDCP_SUCCESS(result) )
827 switch ( EssenceType )
830 result = write_JP2K_file(Options);
833 case ESS_DCDATA_UNKNOWN:
834 if ( ! Options.aux_data_coding.HasValue() )
836 fprintf(stderr, "Option \"-U <UL>\" is required for Aux Data essence.\n");
841 result = write_aux_data_file(Options);
846 fprintf(stderr, "%s: Unknown file type, not P-HDR-compatible essence.\n",
847 Options.filenames.front().c_str());
852 if ( ASDCP_FAILURE(result) )
854 fputs("Program stopped on error.\n", stderr);
856 if ( result != RESULT_FAIL )
858 fputs(result, stderr);