GSaha567/seq_level_training_data
052
1text,length,is_long_context,metric_val,label_metric2"/*3Copyright (c) 2003-2014, John Hurst4All rights reserved.5 6Redistribution and use in source and binary forms, with or without7modification, are permitted provided that the following conditions8are met:91. Redistributions of source code must retain the above copyright10 notice, this list of conditions and the following disclaimer.112. Redistributions in binary form must reproduce the above copyright12 notice, this list of conditions and the following disclaimer in the13 documentation and/or other materials provided with the distribution.143. The name of the author may not be used to endorse or promote products15 derived from this software without specific prior written permission.16 17THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR18IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES19OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.20IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,21INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT22NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF26THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.27*/28/*! \\file asdcp-test.cpp29 \\version $Id: asdcp-test.cpp,v 1.53 2015/10/07 16:41:23 jhurst Exp $ 30 \\brief AS-DCP file manipulation utility31 32 This program provides command line access to the major features of the asdcplib33 library, and serves as a library unit test which provides the functionality of34 the supported use cases.35 36 For more information about asdcplib, please refer to the header file AS_DCP.h37 38 WARNING: While the asdcplib library attempts to provide a complete and secure39 implementation of the cryptographic features of the AS-DCP file formats, this40 unit test program is NOT secure and is therefore NOT SUITABLE FOR USE in a41 production environment without some modification.42 43 In particular, this program uses weak IV generation and externally generated44 plaintext keys. These shortcomings exist because cryptographic-quality45 random number generation and key management are outside the scope of the46 asdcplib library. Developers using asdcplib for commercial implementations47 claiming SMPTE conformance are expected to provide proper implementations of48 these features.49*/50 51#include <KM_fileio.h>52#include <KM_prng.h>53#include <PCMParserList.h>54#include <WavFileWriter.h>55#include <MXF.h>56#include <Metadata.h>57#include <openssl/sha.h>58 59#include <iostream>60#include <assert.h>61 62using namespace ASDCP;63 64const ui32_t FRAME_BUFFER_SIZE = 4 * Kumu::Megabyte;65 66//------------------------------------------------------------------------------------------67//68// command line option parser class69 70static const char* PROGRAM_NAME = ""asdcp-test""; // program name for messages71const ui32_t MAX_IN_FILES = 16; // maximum number of input files handled by72 // the command option parser73 74// local program identification info written to file headers75class MyInfo : public WriterInfo76{77public:78 MyInfo()79 {80 static byte_t default_ProductUUID_Data[UUIDlen] =81 { 0x7d, 0x83, 0x6e, 0x16, 0x37, 0xc7, 0x4c, 0x22,82 0xb2, 0xe0, 0x46, 0xa7, 0x17, 0xe8, 0x4f, 0x42 };83 84 memcpy(ProductUUID, default_ProductUUID_Data, UUIDlen);85 CompanyName = ""WidgetCo"";86 ProductName = ""asdcp-test"";87 ProductVersion = ASDCP::Version();88 }89} s_MyInfo;90 91 92 93// Increment the iterator, test for an additional non-option command line argument.94// Causes the caller to return if there are no remaining arguments or if the next95// argument begins with '-'.96#define TEST_EXTRA_ARG(i,c) if ( ++i >= argc || argv[(i)][0] == '-' ) \\97 { \\98 fprintf(stderr, ""Argument not found for option -%c.\\n"", (c)); \\99 return; \\100 }101//102void103banner(FILE* stream = stdout)104{105 fprintf(stream, ""\\n\\106%s (asdcplib %s)\\n\\n\\107Copyright (c) 2003-2015 John Hurst\\n\\n\\108asdcplib may be copied only under the terms of the license found at\\n\\109the top of every file in the asdcplib distribution kit.\\n\\n\\110Specify the -h (help) option for further information about %s\\n\\n"",111 PROGRAM_NAME, ASDCP::Version(), PROGRAM_NAME);112}113 114//115void116usage(FILE* stream = stdout)117{118 fprintf(stream, ""\\119USAGE: %s -c <output-file> [-3] [-a <uuid>] [-b <buffer-size>]\\n\\120 [-d <duration>] [-e|-E] [-f <start-frame>] [-j <key-id-string>]\\n\\121 [-k <key-string>] [-l <label>] [-L] [-M] [-p <frame-rate>] [-R]\\n\\122 [-s <num>] [-v] [-W] [-z|-Z] <input-file> [<input-file-2> ...]\\n\\123\\n\\124 %s [-h|-help] [-V]\\n\\125\\n\\126 %s -i [-H] [-n] [-v] <input-file>\\n\\127\\n\\128 %s -g | -u\\n\\129\\n\\130 %s -G [-v] <input-file>\\n\\131\\n\\132 %s -t <input-file>\\n\\133\\n\\134 %s -x <file-prefix> [-3] [-b <buffer-size>] [-d <duration>]\\n\\135 [-f <starting-frame>] [-m] [-p <frame-rate>] [-R] [-s <num>] [-S|-1]\\n\\136 [-v] [-W] [-w] <input-file>\\n\\n"",137 PROGRAM_NAME, PROGRAM_NAME, PROGRAM_NAME, PROGRAM_NAME,138 PROGRAM_NAME, PROGRAM_NAME, PROGRAM_NAME);139 140 fprintf(stream, ""\\141Major modes:\\n\\142 -3 - With -c, create a stereoscopic image file. Expects two\\n\\143 directories of JP2K codestreams (directories must have\\n\\144 an equal number of frames; left eye is first).\\n\\145 - With -x, force stereoscopic interpretation of a JP2K\\n\\146 track file.\\n\\147 -c <output-file> - Create an AS-DCP track file from input(s)\\n\\148 -g - Generate a random 16 byte value to stdout\\n\\149 -G - Perform GOP start lookup test on MXF+Interop MPEG file\\n\\150 -h | -help - Show help\\n\\151 -i - Show file info\\n\\152 -t - Calculate message digest of input file\\n\\153 -U - Dump UL catalog to stdout\\n\\154 -u - Generate a random UUID value to stdout\\n\\155 -V - Show version information\\n\\156 -x <root-name> - Extract essence from AS-DCP file to named file(s)\\n\\157\\n"");158 159 fprintf(stream, ""\\160Security Options:\\n\\161 -e - Encrypt MPEG or JP2K headers (default)\\n\\162 -E - Do not encrypt MPEG or JP2K headers\\n\\163 -j <key-id-str> - Write key ID instead of creating a random value\\n\\164 -k <key-string> - Use key for ciphertext operations\\n\\165 -m - verify HMAC values when reading\\n\\166 -M - Do not create HMAC values when writing\\n\\167\\n"");168 169 fprintf(stream, ""\\170Read/Write Options:\\n\\171 -a <UUID> - Specify the Asset ID of a file (with -c)\\n\\172 -b <buffer-size> - Specify size in bytes of picture frame buffer.\\n\\173 Defaults to 4,194,304 (4MB)\\n\\174 -d <duration> - Number of frames to process, default all\\n\\175 -f <start-frame> - Starting frame number, default 0\\n\\176 -l <label> - Use given channel format label when writing MXF sound\\n\\177 files. SMPTE 429-2 labels: '5.1', '6.1', '7.1', '7.1DS', 'WTF'.\\n\\178 Default is no label (valid for Interop only).\\n\\179 -L - Write SMPTE UL values instead of MXF Interop\\n\\180 -p <rate> - fps of picture when wrapping PCM or JP2K:\\n\\181 Use one of [23|24|25|30|48|50|60], 24 is default\\n\\182 -R - Repeat the first frame over the entire file (picture\\n\\183 essence only, requires -c, -d)\\n\\184 -S - Split Wave essence to stereo WAV files during extract.\\n\\185 Default is multichannel WAV\\n\\186 -1 - Split Wave essence to mono WAV files during extract.\\n\\187 Default is multichannel WAV\\n\\188 -W - Read input file only, do not write source file\\n\\189 -w <width> - Width of numeric element in a series of frame file names\\n\\190 (use with -x, default 6).\\n\\191 -z - Fail if j2c inputs have unequal parameters (default)\\n\\192 -Z - Ignore unequal parameters in j2c inputs\\n\\193\\n"");194 195 fprintf(stream, ""\\196Info Options:\\n\\197 -H - Show MXF header metadata, used with option -i\\n\\198 -n - Show index, used with option -i\\n\\199\\n\\200Other Options:\\n\\201 -s <num> - Number of bytes of frame buffer to be dumped as hex to\\n\\202 stderr, used with option -v\\n\\203 -v - Verbose, prints informative messages to stderr\\n\\204\\n\\205 NOTES: o There is no option grouping, all options must be distinct arguments.\\n\\206 o All option arguments must be separated from the option by whitespace.\\n\\207 o An argument of \\""23\\"" to the -p option will be interpreted\\n\\208 as 24000/1001 fps.\\n\\209\\n"");210}211 212//213enum MajorMode_t214{215 MMT_NONE,216 MMT_INFO,217 MMT_CREATE,218 MMT_EXTRACT,219 MMT_GEN_ID,220 MMT_GEN_KEY,221 MMT_GOP_START,222 MMT_DIGEST,223 MMT_UL_LIST,224};225 226//227PCM::ChannelFormat_t228decode_channel_fmt(const std::string& label_name)229{230 if ( label_name == ""5.1"" )231 return PCM::CF_CFG_1;232 233 else if ( label_name == ""6.1"" )234 return PCM::CF_CFG_2;235 236 else if ( label_name == ""7.1"" )237 return PCM::CF_CFG_3;238 239 else if ( label_name == ""WTF"" )240 return PCM::CF_CFG_4;241 242 else if ( label_name == ""7.1DS"" )243 return PCM::CF_CFG_5;244 245 fprintf(stderr, ""Error decoding channel format string: %s\\n"", label_name.c_str());246 fprintf(stderr, ""Expecting '5.1', '6.1', '7.1', '7.1DS' or 'WTF'\\n"");247 return PCM::CF_NONE;248}249 250//251//252class CommandOptions253{254 CommandOptions();255 256public:257 MajorMode_t mode;258 bool error_flag; // true if the given options are in error or not complete259 bool key_flag; // true if an encryption key was given260 bool key_id_flag; // true if a key ID was given261 bool asset_id_flag; // true if an asset ID was given262 bool encrypt_header_flag; // true if mpeg headers are to be encrypted263 bool write_hmac; // true if HMAC values are to be generated and written264 bool read_hmac; // true if HMAC values are to be validated265 bool split_wav; // true if PCM is to be extracted to stereo WAV files266 bool mono_wav; // true if PCM is to be extracted to mono WAV files267 bool verbose_flag; // true if the verbose option was selected268 ui32_t fb_dump_size; // number of bytes of frame buffer to dump269 bool showindex_flag; // true if index is to be displayed270 bool showheader_flag; // true if MXF file header is to be displayed271 bool no_write_flag; // true if no output files are to be written272 bool version_flag; // true if the version display option was selected273 bool help_flag; // true if the help display option was selected274 bool stereo_image_flag; // if true, expect stereoscopic JP2K input (left eye first)275 ui32_t number_width; // number of digits in a serialized filename (for JPEG extract)276 ui32_t start_frame; // frame number to begin processing277 ui32_t duration; // number of frames to be processed278 bool duration_flag; // true if duration argument given279 bool do_repeat; // if true and -c -d, repeat first input frame280 bool use_smpte_labels; // if true, SMPTE UL values will be written instead of MXF Interop values281 bool j2c_pedantic; // passed to JP2K::SequenceParser::OpenRead282 ui32_t picture_rate; // fps of picture when wrapping PCM283 ui32_t fb_size; // size of picture frame buffer284 ui32_t file_count; // number of elements in filenames[]285 const char* file_root; // filename pre for files written by the extract mode286 const char* out_file; // name of mxf file created by create mode287 byte_t key_value[KeyLen]; // value of given encryption key (when key_flag is true)288 byte_t key_id_value[UUIDlen];// value of given key ID (when key_id_flag is true)289 byte_t asset_id_value[UUIDlen];// value of asset ID (when asset_id_flag is true)290 const char* filenames[MAX_IN_FILES]; // list of filenames to be processed291 PCM::ChannelFormat_t channel_fmt; // audio channel arrangement292 293 //294 Rational PictureRate()295 {296 if ( picture_rate == 16 ) return EditRate_16;297 if ( picture_rate == 18 ) return EditRate_18;298 if ( picture_rate == 20 ) return EditRate_20;299 if ( picture_rate == 22 ) return EditRate_22;300 if ( picture_rate == 23 ) return EditRate_23_98;301 if ( picture_rate == 24 ) return EditRate_24;302 if ( picture_rate == 25 ) return EditRate_25;303 if ( picture_rate == 30 ) return EditRate_30;304 if ( picture_rate == 48 ) return EditRate_48;305 if ( picture_rate == 50 ) return EditRate_50;306 if ( picture_rate == 60 ) return EditRate_60;307 if ( picture_rate == 96 ) return EditRate_96;308 if ( picture_rate == 100 ) return EditRate_100;309 if ( picture_rate == 120 ) return EditRate_120;310 return EditRate_24;311 }312 313 //314 const char* szPictureRate()315 {316 if ( picture_rate == 16 ) return ""16"";317 if ( picture_rate == 18 ) return ""18.182"";318 if ( picture_rate == 20 ) return ""20"";319 if ( picture_rate == 22 ) return ""21.818"";320 if ( picture_rate == 23 ) return ""23.976"";321 if ( picture_rate == 24 ) return ""24"";322 if ( picture_rate == 25 ) return ""25"";323 if ( picture_rate == 30 ) return ""30"";324 if ( picture_rate == 48 ) return ""48"";325 if ( picture_rate == 50 ) return ""50"";326 if ( picture_rate == 60 ) return ""60"";327 if ( picture_rate == 96 ) return ""96"";328 if ( picture_rate == 100 ) return ""100"";329 if ( picture_rate == 120 ) return ""120"";330 return ""24"";331 }332 333 //334 CommandOptions(int argc, const char** argv) :335 mode(MMT_NONE), error_flag(true), key_flag(false), key_id_flag(false), asset_id_flag(false),336 encrypt_header_flag(true), write_hmac(true), read_hmac(false), split_wav(false), mono_wav(false),337 verbose_flag(false), fb_dump_size(0), showindex_flag(false), showheader_flag(false),338 no_write_flag(false), version_flag(false), help_flag(false), stereo_image_flag(false),339 number_width(6), start_frame(0),340 duration(0xffffffff), duration_flag(false), do_repeat(false), use_smpte_labels(false), j2c_pedantic(true),341 picture_rate(24), fb_size(FRAME_BUFFER_SIZE), file_count(0), file_root(0), out_file(0),342 channel_fmt(PCM::CF_NONE)343 {344 memset(key_value, 0, KeyLen);345 memset(key_id_value, 0, UUIDlen);346 347 for ( int i = 1; i < argc; i++ )348 {349 350 if ( (strcmp( argv[i], ""-help"") == 0) )351 {352 help_flag = true;353 continue;354 }355 356 if ( argv[i][0] == '-'357 && ( isalpha(argv[i][1]) || isdigit(argv[i][1]) )358 && argv[i][2] == 0 )359 {360 switch ( argv[i][1] )361 {362 case '1': mono_wav = true; break;363 case '2': split_wav = true; break;364 case '3': stereo_image_flag = true; break;365 366 case 'a':367 asset_id_flag = true;368 TEST_EXTRA_ARG(i, 'a');369 {370 ui32_t length;371 Kumu::hex2bin(argv[i], asset_id_value, UUIDlen, &length);372 373 if ( length != UUIDlen )374 {375 fprintf(stderr, ""Unexpected asset ID length: %u, expecting %u characters.\\n"", length, UUIDlen);376 return;377 }378 }379 break;380 381 case 'b':382 TEST_EXTRA_ARG(i, 'b');383 fb_size = Kumu::xabs(strtol(argv[i], 0, 10));384 385 if ( verbose_flag )386 fprintf(stderr, ""Frame Buffer size: %u bytes.\\n"", fb_size);387 388 break;389 390 case 'c':391 TEST_EXTRA_ARG(i, 'c');392 mode = MMT_CREATE;393 out_file = argv[i];394 break;395 396 case 'd':397 TEST_EXTRA_ARG(i, 'd');398 duration_flag = true;399 duration = Kumu::xabs(strtol(argv[i], 0, 10));400 break;401 402 case 'E': encrypt_header_flag = false; break;403 case 'e': encrypt_header_flag = true; break;404 405 case 'f':406 TEST_EXTRA_ARG(i, 'f');407 start_frame = Kumu::xabs(strtol(argv[i], 0, 10));408 break;409 410 case 'G': mode = MMT_GOP_START; break;411 case 'g': mode = MMT_GEN_KEY; break;412 case 'H': showheader_flag = true; break;413 case 'h': help_flag = true; break;414 case 'i': mode = MMT_INFO; break;415 416 case 'j': key_id_flag = true;417 TEST_EXTRA_ARG(i, 'j');418 {419 ui32_t length;420 Kumu::hex2bin(argv[i], key_id_value, UUIDlen, &length);421 422 if ( length != UUIDlen )423 {424 fprintf(stderr, ""Unexpected key ID length: %u, expecting %u characters.\\n"", length, UUIDlen);425 return;426 }427 }428 break;429 430 case 'k': key_flag = true;431 TEST_EXTRA_ARG(i, 'k');432 {433 ui32_t length;434 Kumu::hex2bin(argv[i], key_value, KeyLen, &length);435 436 if ( length != KeyLen )437 {438 fprintf(stderr, ""Unexpected key length: %u, expecting %u characters.\\n"", length, KeyLen);439 return;440 }441 }442 break;443 444 case 'l':445 TEST_EXTRA_ARG(i, 'l');446 channel_fmt = decode_channel_fmt(argv[i]);447 break;448 449 case 'L': use_smpte_labels = true; break;450 case 'M': write_hmac = false; break;451 case 'm': read_hmac = true; break;452 case 'n': showindex_flag = true; break;453 454 case 'p':455 TEST_EXTRA_ARG(i, 'p');456 picture_rate = Kumu::xabs(strtol(argv[i], 0, 10));457 break;458 459 case 'R': do_repeat = true; break;460 case 'S': split_wav = true; break;461 462 case 's':463 TEST_EXTRA_ARG(i, 's');464 fb_dump_size = Kumu::xabs(strtol(argv[i], 0, 10));465 break;466 467 case 't': mode = MMT_DIGEST; break;468 case 'U': mode = MMT_UL_LIST; break;469 case 'u': mode = MMT_GEN_ID; break;470 case 'V': version_flag = true; break;471 case 'v': verbose_flag = true; break;472 case 'W': no_write_flag = true; break;473 474 case 'w':475 TEST_EXTRA_ARG(i, 'w');476 number_width = Kumu::xabs(strtol(argv[i], 0, 10));477 break;478 479 case 'x':480 TEST_EXTRA_ARG(i, 'x');481 mode = MMT_EXTRACT;482 file_root = argv[i];483 break;484 485 case 'Z': j2c_pedantic = false; break;486 case 'z': j2c_pedantic = true; break;487 488 default:489 fprintf(stderr, ""Unrecognized option: %s\\n"", argv[i]);490 return;491 }492 }493 else494 {495 496 if ( argv[i][0] != '-' )497 {498 filenames[file_count++] = argv[i];499 }500 else501 {502 fprintf(stderr, ""Unrecognized argument: %s\\n"", argv[i]);503 return;504 }505 506 if ( file_count >= MAX_IN_FILES )507 {508 fprintf(stderr, ""Filename lists exceeds maximum list size: %u\\n"", MAX_IN_FILES);509 return;510 }511 }512 }513 514 if ( help_flag || version_flag )515 return;516 517 if ( ( mode == MMT_INFO518 || mode == MMT_CREATE519 || mode == MMT_EXTRACT520 || mode == MMT_GOP_START521 || mode == MMT_DIGEST ) && file_count == 0 )522 {523 fputs(""Option requires at least one filename argument.\\n"", stderr);524 return;525 }526 527 if ( mode == MMT_NONE && ! help_flag && ! version_flag )528 {529 fputs(""No operation selected (use one of -[gGcitux] or -h for help).\\n"", stderr);530 return;531 }532 533 error_flag = false;534 }535};536 537//------------------------------------------------------------------------------------------538// MPEG2 essence539 540// Write a plaintext MPEG2 Video Elementary Stream to a plaintext ASDCP file541// Write a plaintext MPEG2 Video Elementary Stream to a ciphertext ASDCP file542//543Result_t544write_MPEG2_file(CommandOptions& Options)545{546 AESEncContext* Context = 0;547 HMACContext* HMAC = 0;548 MPEG2::FrameBuffer FrameBuffer(Options.fb_size);549 MPEG2::Parser Parser;550 MPEG2::MXFWriter Writer;551 MPEG2::VideoDescriptor VDesc;552 byte_t IV_buf[CBC_BLOCK_SIZE];553 Kumu::FortunaRNG RNG;554 555 // set up essence parser556 Result_t result = Parser.OpenRead(Options.filenames[0]);557 558 // set up MXF writer559 if ( ASDCP_SUCCESS(result) )560 {561 Parser.FillVideoDescriptor(VDesc);562 563 if ( Options.verbose_flag )564 {565 fputs(""MPEG-2 Pictures\\n"", stderr);566 fputs(""VideoDescriptor:\\n"", stderr);567 fprintf(stderr, ""Frame Buffer size: %u\\n"", Options.fb_size);568 MPEG2::VideoDescriptorDump(VDesc);569 }570 }571 572 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )573 {574 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here575 if ( Options.asset_id_flag )576 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);577 else578 Kumu::GenRandomUUID(Info.AssetUUID);579 580 if ( Options.use_smpte_labels )581 {582 Info.LabelSetType = LS_MXF_SMPTE;583 fprintf(stderr, ""ATTENTION! Writing SMPTE Universal Labels\\n"");584 }585 586 // configure encryption587 if( Options.key_flag )588 {589 Kumu::GenRandomUUID(Info.ContextID);590 Info.EncryptedEssence = true;591 592 if ( Options.key_id_flag )593 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);594 else595 RNG.FillRandom(Info.CryptographicKeyID, UUIDlen);596 597 Context = new AESEncContext;598 result = Context->InitKey(Options.key_value);599 600 if ( ASDCP_SUCCESS(result) )601 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));602 603 if ( ASDCP_SUCCESS(result) && Options.write_hmac )604 {605 Info.UsesHMAC = true;606 HMAC = new HMACContext;607 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);608 }609 }610 611 if ( ASDCP_SUCCESS(result) )612 result = Writer.OpenWrite(Options.out_file, Info, VDesc);613 }614 615 if ( ASDCP_SUCCESS(result) )616 // loop through the frames617 {618 result = Parser.Reset();619 ui32_t duration = 0;620 621 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )622 {623 if ( ! Options.do_repeat || duration == 1 )624 {625 result = Parser.ReadFrame(FrameBuffer);626 627 if ( ASDCP_SUCCESS(result) )628 {629 if ( Options.verbose_flag )630 FrameBuffer.Dump(stderr, Options.fb_dump_size);631 632 if ( Options.encrypt_header_flag )633 FrameBuffer.PlaintextOffset(0);634 }635 }636 637 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )638 {639 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);640 641 // The Writer class will forward the last block of ciphertext642 // to the encryption context for use as the IV for the next643 // frame. If you want to use non-sequitur IV values, un-comment644 // the following line of code.645 // if ( ASDCP_SUCCESS(result) && Options.key_flag )646 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));647 }648 }649 650 if ( result == RESULT_ENDOFFILE )651 result = RESULT_OK;652 }653 654 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )655 result = Writer.Finalize();656 657 return result;658}659 660// Read a plaintext MPEG2 Video Elementary Stream from a plaintext ASDCP file661// Read a plaintext MPEG2 Video Elementary Stream from a ciphertext ASDCP file662// Read a ciphertext MPEG2 Video Elementary Stream from a ciphertext ASDCP file663//664Result_t665read_MPEG2_file(CommandOptions& Options)666{667 AESDecContext* Context = 0;668 HMACContext* HMAC = 0;669 MPEG2::MXFReader Reader;670 MPEG2::FrameBuffer FrameBuffer(Options.fb_size);671 Kumu::FileWriter OutFile;672 ui32_t frame_count = 0;673 674 Result_t result = Reader.OpenRead(Options.filenames[0]);675 676 if ( ASDCP_SUCCESS(result) )677 {678 MPEG2::VideoDescriptor VDesc;679 Reader.FillVideoDescriptor(VDesc);680 frame_count = VDesc.ContainerDuration;681 682 if ( Options.verbose_flag )683 {684 fprintf(stderr, ""Frame Buffer size: %u\\n"", Options.fb_size);685 MPEG2::VideoDescriptorDump(VDesc);686 }687 }688 689 if ( ASDCP_SUCCESS(result) )690 {691 char filename[256];692 snprintf(filename, 256, ""%s.ves"", Options.file_root);693 result = OutFile.OpenWrite(filename);694 }695 696 if ( ASDCP_SUCCESS(result) && Options.key_flag )697 {698 Context = new AESDecContext;699 result = Context->InitKey(Options.key_value);700 701 if ( ASDCP_SUCCESS(result) && Options.read_hmac )702 {703 WriterInfo Info;704 Reader.FillWriterInfo(Info);705 706 if ( Info.UsesHMAC )707 {708 HMAC = new HMACContext;709 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);710 }711 else712 {713 fputs(""File does not contain HMAC values, ignoring -m option.\\n"", stderr);714 }715 }716 }717 718 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);719 if ( last_frame > frame_count )720 last_frame = frame_count;721 722 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )723 {724 result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);725 726 if ( ASDCP_SUCCESS(result) )727 {728 if ( Options.verbose_flag )729 FrameBuffer.Dump(stderr, Options.fb_dump_size);730 731 ui32_t write_count = 0;732 result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);733 }734 }735 736 return result;737}738 739 740//741Result_t742gop_start_test(CommandOptions& Options)743{744 using namespace ASDCP::MPEG2;745 746 MXFReader Reader;747 MPEG2::FrameBuffer FrameBuffer(Options.fb_size);748 ui32_t frame_count = 0;749 750 Result_t result = Reader.OpenRead(Options.filenames[0]);751 752 if ( ASDCP_SUCCESS(result) )753 {754 MPEG2::VideoDescriptor VDesc;755 Reader.FillVideoDescriptor(VDesc);756 frame_count = VDesc.ContainerDuration;757 758 if ( Options.verbose_flag )759 {760 fprintf(stderr, ""Frame Buffer size: %u\\n"", Options.fb_size);761 MPEG2::VideoDescriptorDump(VDesc);762 }763 }764 765 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);766 if ( last_frame > frame_count )767 last_frame = frame_count;768 769 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )770 {771 result = Reader.ReadFrameGOPStart(i, FrameBuffer);772 773 if ( ASDCP_SUCCESS(result) )774 {775 if ( Options.verbose_flag )776 FrameBuffer.Dump(stderr, Options.fb_dump_size);777 778 if ( FrameBuffer.FrameType() != FRAME_I )779 fprintf(stderr, ""Expecting an I frame, got %c\\n"", FrameTypeChar(FrameBuffer.FrameType()));780 781 fprintf(stderr, ""Requested frame %u, got %u\\n"", i, FrameBuffer.FrameNumber());782 }783 }784 785 return result;786}787 788//------------------------------------------------------------------------------------------789// JPEG 2000 essence790 791// Write one or more plaintext JPEG 2000 stereoscopic codestream pairs to a plaintext ASDCP file792// Write one or more plaintext JPEG 2000 stereoscopic codestream pairs to a ciphertext ASDCP file793//794Result_t795write_JP2K_S_file(CommandOptions& Options)796{797 AESEncContext* Context = 0;798 HMACContext* HMAC = 0;799 JP2K::MXFSWriter Writer;800 JP2K::FrameBuffer FrameBuffer(Options.fb_size);801 JP2K::PictureDescriptor PDesc;802 JP2K::SequenceParser ParserLeft, ParserRight;803 byte_t IV_buf[CBC_BLOCK_SIZE];804 Kumu::FortunaRNG RNG;805 806 if ( Options.file_count != 2 )807 {808 fprintf(stderr, ""Two inputs are required for stereoscopic option.\\n"");809 return RESULT_FAIL;810 }811 812 // set up essence parser813 Result_t result = ParserLeft.OpenRead(Options.filenames[0], Options.j2c_pedantic);814 815 if ( ASDCP_SUCCESS(result) )816 result = ParserRight.OpenRead(Options.filenames[1], Options.j2c_pedantic);817 818 // set up MXF writer819 if ( ASDCP_SUCCESS(result) )820 {821 ParserLeft.FillPictureDescriptor(PDesc);822 PDesc.EditRate = Options.PictureRate();823 824 if ( Options.verbose_flag )825 {826 fputs(""JPEG 2000 stereoscopic pictures\\nPictureDescriptor:\\n"", stderr);827 fprintf(stderr, ""Frame Buffer size: %u\\n"", Options.fb_size);828 JP2K::PictureDescriptorDump(PDesc);829 }830 }831 832 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )833 {834 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here835 if ( Options.asset_id_flag )836 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);837 else838 Kumu::GenRandomUUID(Info.AssetUUID);839 840 if ( Options.use_smpte_labels )841 {842 Info.LabelSetType = LS_MXF_SMPTE;843 fprintf(stderr, ""ATTENTION! Writing SMPTE Universal Labels\\n"");844 }845 846 // configure encryption847 if( Options.key_flag )848 {849 Kumu::GenRandomUUID(Info.ContextID);850 Info.EncryptedEssence = true;851 852 if ( Options.key_id_flag )853 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);854 else855 RNG.FillRandom(Info.CryptographicKeyID, UUIDlen);856 857 Context = new AESEncContext;858 result = Context->InitKey(Options.key_value);859 860 if ( ASDCP_SUCCESS(result) )861 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));862 863 if ( ASDCP_SUCCESS(result) && Options.write_hmac )864 {865 Info.UsesHMAC = true;866 HMAC = new HMACContext;867 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);868 }869 }870 871 if ( ASDCP_SUCCESS(result) )872 result = Writer.OpenWrite(Options.out_file, Info, PDesc);873 }874 875 if ( ASDCP_SUCCESS(result) )876 {877 ui32_t duration = 0;878 result = ParserLeft.Reset();879 if ( ASDCP_SUCCESS(result) ) result = ParserRight.Reset();880 881 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )882 {883 result = ParserLeft.ReadFrame(FrameBuffer);884 885 if ( ASDCP_SUCCESS(result) )886 {887 if ( Options.verbose_flag )888 FrameBuffer.Dump(stderr, Options.fb_dump_size);889 890 if ( Options.encrypt_header_flag )891 FrameBuffer.PlaintextOffset(0);892 }893 894 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )895 result = Writer.WriteFrame(FrameBuffer, JP2K::SP_LEFT, Context, HMAC);896 897 if ( ASDCP_SUCCESS(result) )898 result = ParserRight.ReadFrame(FrameBuffer);899 900 if ( ASDCP_SUCCESS(result) )901 {902 if ( Options.verbose_flag )903 FrameBuffer.Dump(stderr, Options.fb_dump_size);904 905 if ( Options.encrypt_header_flag )906 FrameBuffer.PlaintextOffset(0);907 }908 909 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )910 result = Writer.WriteFrame(FrameBuffer, JP2K::SP_RIGHT, Context, HMAC);911 }912 913 if ( result == RESULT_ENDOFFILE )914 result = RESULT_OK;915 }916 917 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )918 result = Writer.Finalize();919 920 return result;921}922 923// Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a plaintext ASDCP file924// Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file925// Read one or more ciphertext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file926Result_t927read_JP2K_S_file(CommandOptions& Options)928{929 AESDecContext* Context = 0;930 HMACContext* HMAC = 0;931 JP2K::MXFSReader Reader;932 JP2K::FrameBuffer FrameBuffer(Options.fb_size);933 ui32_t frame_count = 0;934 935 Result_t result = Reader.OpenRead(Options.filenames[0]);936 937 if ( ASDCP_SUCCESS(result) )938 {939 JP2K::PictureDescriptor PDesc;940 Reader.FillPictureDescriptor(PDesc);941 942 frame_count = PDesc.ContainerDuration;943 944 if ( Options.verbose_flag )945 {946 fprintf(stderr, ""Frame Buffer size: %u\\n"", Options.fb_size);947 JP2K::PictureDescriptorDump(PDesc);948 }949 }950 951 if ( ASDCP_SUCCESS(result) && Options.key_flag )952 {953 Context = new AESDecContext;954 result = Context->InitKey(Options.key_value);955 956 if ( ASDCP_SUCCESS(result) && Options.read_hmac )957 {958 WriterInfo Info;959 Reader.FillWriterInfo(Info);960 961 if ( Info.UsesHMAC )962 {963 HMAC = new HMACContext;964 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);965 }966 else967 {968 fputs(""File does not contain HMAC values, ignoring -m option.\\n"", stderr);969 }970 }971 }972 973 const int filename_max = 1024;974 char filename[filename_max];975 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);976 if ( last_frame > frame_count )977 last_frame = frame_count;978 979 char left_format[64]; char right_format[64];980 snprintf(left_format, 64, ""%%s%%0%duL.j2c"", Options.number_width);981 snprintf(right_format, 64, ""%%s%%0%duR.j2c"", Options.number_width);982 983 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )984 {985 result = Reader.ReadFrame(i, JP2K::SP_LEFT, FrameBuffer, Context, HMAC);986 987 if ( ASDCP_SUCCESS(result) )988 {989 Kumu::FileWriter OutFile;990 ui32_t write_count;991 snprintf(filename, filename_max, left_format, Options.file_root, i);992 result = OutFile.OpenWrite(filename);993 994 if ( ASDCP_SUCCESS(result) )995 result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);996 997 if ( Options.verbose_flag )998 FrameBuffer.Dump(stderr, Options.fb_dump_size);999 }1000 1001 if ( ASDCP_SUCCESS(result) )1002 result = Reader.ReadFrame(i, JP2K::SP_RIGHT, FrameBuffer, Context, HMAC);1003 1004 if ( ASDCP_SUCCESS(result) )1005 {1006 Kumu::FileWriter OutFile;1007 ui32_t write_count;1008 snprintf(filename, filename_max, right_format, Options.file_root, i);1009 result = OutFile.OpenWrite(filename);1010 1011 if ( ASDCP_SUCCESS(result) )1012 result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);1013 }1014 }1015 1016 return result;1017}1018 1019 1020 1021// Write one or more plaintext JPEG 2000 codestreams to a plaintext ASDCP file1022// Write one or more plaintext JPEG 2000 codestreams to a ciphertext ASDCP file1023//1024Result_t1025write_JP2K_file(CommandOptions& Options)1026{1027 AESEncContext* Context = 0;1028 HMACContext* HMAC = 0;1029 JP2K::MXFWriter Writer;1030 JP2K::FrameBuffer FrameBuffer(Options.fb_size);1031 JP2K::PictureDescriptor PDesc;1032 JP2K::SequenceParser Parser;1033 byte_t IV_buf[CBC_BLOCK_SIZE];1034 Kumu::FortunaRNG RNG;1035 1036 // set up essence parser1037 Result_t result = Parser.OpenRead(Options.filenames[0], Options.j2c_pedantic);1038 1039 // set up MXF writer1040 if ( ASDCP_SUCCESS(result) )1041 {1042 Parser.FillPictureDescriptor(PDesc);1043 PDesc.EditRate = Options.PictureRate();1044 1045 if ( Options.verbose_flag )1046 {1047 fprintf(stderr, ""JPEG 2000 pictures\\n"");1048 fputs(""PictureDescriptor:\\n"", stderr);1049 fprintf(stderr, ""Frame Buffer size: %u\\n"", Options.fb_size);1050 JP2K::PictureDescriptorDump(PDesc);1051 }1052 }1053 1054 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )1055 {1056 WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here1057 if ( Options.asset_id_flag )1058 memcpy(Info.AssetUUID, Options.asset_id_value, UUIDlen);1059 else1060 Kumu::GenRandomUUID(Info.AssetUUID);1061 1062 if ( Options.use_smpte_labels )1063 {1064 Info.LabelSetType = LS_MXF_SMPTE;1065 fprintf(stderr, ""ATTENTION! Writing SMPTE Universal Labels\\n"");1066 }1067 1068 // configure encryption1069 if( Options.key_flag )1070 {1071 Kumu::GenRandomUUID(Info.ContextID);1072 Info.EncryptedEssence = true;1073 1074 if ( Options.key_id_flag )1075 memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen);1076 else1077 RNG.FillRandom(Info.CryptographicKeyID, UUIDlen);1078 1079 Context = new AESEncContext;1080 result = Context->InitKey(Options.key_value);1081 1082 if ( ASDCP_SUCCESS(result) )1083 result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));1084 1085 if ( ASDCP_SUCCESS(result) && Options.write_hmac )1086 {1087 Info.UsesHMAC = true;1088 HMAC = new HMACContext;1089 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);1090 }1091 }1092 1093 if ( ASDCP_SUCCESS(result) )1094 result = Writer.OpenWrite(Options.out_file, Info, PDesc);1095 }1096 1097 if ( ASDCP_SUCCESS(result) )1098 {1099 ui32_t duration = 0;1100 result = Parser.Reset();1101 1102 while ( ASDCP_SUCCESS(result) && duration++ < Options.duration )1103 {1104 if ( ! Options.do_repeat || duration == 1 )1105 {1106 result = Parser.ReadFrame(FrameBuffer);1107 1108 if ( ASDCP_SUCCESS(result) )1109 {1110 if ( Options.verbose_flag )1111 FrameBuffer.Dump(stderr, Options.fb_dump_size);1112 1113 if ( Options.encrypt_header_flag )1114 FrameBuffer.PlaintextOffset(0);1115 }1116 }1117 1118 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )1119 {1120 result = Writer.WriteFrame(FrameBuffer, Context, HMAC);1121 1122 // The Writer class will forward the last block of ciphertext1123 // to the encryption context for use as the IV for the next1124 // frame. If you want to use non-sequitur IV values, un-comment1125 // the following line of code.1126 // if ( ASDCP_SUCCESS(result) && Options.key_flag )1127 // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE));1128 }1129 }1130 1131 if ( result == RESULT_ENDOFFILE )1132 result = RESULT_OK;1133 }1134 1135 if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )1136 result = Writer.Finalize();1137 1138 return result;1139}1140 1141// Read one or more plaintext JPEG 2000 codestreams from a plaintext ASDCP file1142// Read one or more plaintext JPEG 2000 codestreams from a ciphertext ASDCP file1143// Read one or more ciphertext JPEG 2000 codestreams from a ciphertext ASDCP file1144//1145Result_t1146read_JP2K_file(CommandOptions& Options)1147{1148 AESDecContext* Context = 0;1149 HMACContext* HMAC = 0;1150 JP2K::MXFReader Reader;1151 JP2K::FrameBuffer FrameBuffer(Options.fb_size);1152 ui32_t frame_count = 0;1153 1154 Result_t result = Reader.OpenRead(Options.filenames[0]);1155 1156 if ( ASDCP_SUCCESS(result) )1157 {1158 JP2K::PictureDescriptor PDesc;1159 Reader.FillPictureDescriptor(PDesc);1160 1161 frame_count = PDesc.ContainerDuration;1162 1163 if ( Options.verbose_flag )1164 {1165 fprintf(stderr, ""Frame Buffer size: %u\\n"", Options.fb_size);1166 JP2K::PictureDescriptorDump(PDesc);1167 }1168 }1169 1170 if ( ASDCP_SUCCESS(result) && Options.key_flag )1171 {1172 Context = new AESDecContext;1173 result = Context->InitKey(Options.key_value);1174 1175 if ( ASDCP_SUCCESS(result) && Options.read_hmac )1176 {1177 WriterInfo Info;1178 Reader.FillWriterInfo(Info);1179 1180 if ( Info.UsesHMAC )1181 {1182 HMAC = new HMACContext;1183 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);1184 }1185 else1186 {1187 fputs(""File does not contain HMAC values, ignoring -m option.\\n"", stderr);1188 }1189 }1190 }1191 1192 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);1193 if ( last_frame > frame_count )1194 last_frame = frame_count;1195 1196 char name_format[64];1197 snprintf(name_format, 64, ""%%s%%0%du.j2c"", Options.number_width);1198 1199 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )1200 {