2 Copyright (c) 2003-2012, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 /*! \file asdcp-unwrap.cpp
29 \brief AS-DCP file manipulation utility
31 This program extracts picture, sound and text essence from AS-DCP files.
33 For more information about asdcplib, please refer to the header file AS_DCP.h
36 #include <KM_fileio.h>
37 #include <WavFileWriter.h>
39 using namespace ASDCP;
41 const ui32_t FRAME_BUFFER_SIZE = 4 * Kumu::Megabyte;
43 //------------------------------------------------------------------------------------------
45 // command line option parser class
47 static const char* PROGRAM_NAME = "asdcp-unwrap"; // program name for messages
49 // Increment the iterator, test for an additional non-option command line argument.
50 // Causes the caller to return if there are no remaining arguments or if the next
51 // argument begins with '-'.
52 #define TEST_EXTRA_ARG(i,c) \
53 if ( ++i >= argc || argv[(i)][0] == '-' ) { \
54 fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
60 banner(FILE* stream = stdout)
64 Copyright (c) 2003-2012 John Hurst\n\n\
65 asdcplib may be copied only under the terms of the license found at\n\
66 the top of every file in the asdcplib distribution kit.\n\n\
67 Specify the -h (help) option for further information about %s\n\n",
68 PROGRAM_NAME, ASDCP::Version(), PROGRAM_NAME);
73 usage(FILE* stream = stdout)
76 USAGE: %s [-h|-help] [-V]\n\
78 %s -G [-v] <input-file>\n\
80 %s [-1|-2] [-3] [-b <buffer-size>] [-d <duration>]\n\
81 [-f <starting-frame>] [-m] [-p <frame-rate>] [-R] [-s <size>] [-v] [-W]\n\
82 [-w] <input-file> [<file-prefix>]\n\n",
83 PROGRAM_NAME, PROGRAM_NAME, PROGRAM_NAME);
87 -1 - Split Wave essence to mono WAV files during extract.\n\
88 Default is multichannel WAV\n\
89 -2 - Split Wave essence to stereo WAV files during extract.\n\
90 Default is multichannel WAV\n\
91 -3 - Force stereoscopic interpretation of a JP2K file.\n\
92 -b <buffer-size> - Specify size in bytes of picture frame buffer\n\
93 Defaults to 4,194,304 (4MB)\n\
94 -d <duration> - Number of frames to process, default all\n\
95 -f <start-frame> - Starting frame number, default 0\n\
96 -G - Perform GOP start lookup test on MXF+Interop MPEG file\n\
97 -h | -help - Show help\n\
98 -k <key-string> - Use key for ciphertext operations\n\
99 -m - verify HMAC values when reading\n\
100 -p <rate> - fps of picture when wrapping PCM or JP2K:\n\
101 Use one of [23|24|25|30|48|50|60], 24 is default\n\
102 -s <size> - Number of bytes to dump to output when -v is given\n\
103 -V - Show version information\n\
104 -v - Verbose, prints informative messages to stderr\n\
105 -W - Read input file only, do not write destination file\n\
106 -w <width> - Width of numeric element in a series of frame file names\n\
108 -z - Fail if j2c inputs have unequal parameters (default)\n\
109 -Z - Ignore unequal parameters in j2c inputs\n\
111 NOTES: o There is no option grouping, all options must be distinct arguments.\n\
112 o All option arguments must be separated from the option by whitespace.\n\
113 o An argument of \"23\" to the -p option will be interpreted\n\
114 as 24000/1001 fps.\n\n");
132 bool error_flag; // true if the given options are in error or not complete
133 bool key_flag; // true if an encryption key was given
134 bool read_hmac; // true if HMAC values are to be validated
135 bool split_wav; // true if PCM is to be extracted to stereo WAV files
136 bool mono_wav; // true if PCM is to be extracted to mono WAV files
137 bool verbose_flag; // true if the verbose option was selected
138 ui32_t fb_dump_size; // number of bytes of frame buffer to dump
139 bool no_write_flag; // true if no output files are to be written
140 bool version_flag; // true if the version display option was selected
141 bool help_flag; // true if the help display option was selected
142 bool stereo_image_flag; // if true, expect stereoscopic JP2K input (left eye first)
143 ui32_t number_width; // number of digits in a serialized filename (for JPEG extract)
144 ui32_t start_frame; // frame number to begin processing
145 ui32_t duration; // number of frames to be processed
146 bool duration_flag; // true if duration argument given
147 bool j2c_pedantic; // passed to JP2K::SequenceParser::OpenRead
148 ui32_t picture_rate; // fps of picture when wrapping PCM
149 ui32_t fb_size; // size of picture frame buffer
150 const char* file_prefix; // filename pre for files written by the extract mode
151 byte_t key_value[KeyLen]; // value of given encryption key (when key_flag is true)
152 byte_t key_id_value[UUIDlen];// value of given key ID (when key_id_flag is true)
153 PCM::ChannelFormat_t channel_fmt; // audio channel arrangement
154 const char* input_filename;
155 std::string prefix_buffer;
158 Rational PictureRate()
160 if ( picture_rate == 23 ) return EditRate_23_98;
161 if ( picture_rate == 24 ) return EditRate_24;
162 if ( picture_rate == 25 ) return EditRate_25;
163 if ( picture_rate == 30 ) return EditRate_30;
164 if ( picture_rate == 48 ) return EditRate_48;
165 if ( picture_rate == 50 ) return EditRate_50;
166 if ( picture_rate == 60 ) return EditRate_60;
167 if ( picture_rate == 96 ) return EditRate_96;
168 if ( picture_rate == 100 ) return EditRate_100;
169 if ( picture_rate == 120 ) return EditRate_120;
174 CommandOptions(int argc, const char** argv) :
175 mode(MMT_EXTRACT), error_flag(true), key_flag(false), read_hmac(false), split_wav(false),
176 mono_wav(false), verbose_flag(false), fb_dump_size(0), no_write_flag(false),
177 version_flag(false), help_flag(false), stereo_image_flag(false), number_width(6),
178 start_frame(0), duration(0xffffffff), duration_flag(false), j2c_pedantic(true),
179 picture_rate(24), fb_size(FRAME_BUFFER_SIZE), file_prefix(0),
180 channel_fmt(PCM::CF_NONE), input_filename(0)
182 memset(key_value, 0, KeyLen);
183 memset(key_id_value, 0, UUIDlen);
185 for ( int i = 1; i < argc; ++i )
188 if ( (strcmp( argv[i], "-help") == 0) )
194 if ( argv[i][0] == '-'
195 && ( isalpha(argv[i][1]) || isdigit(argv[i][1]) )
198 switch ( argv[i][1] )
200 case '1': mono_wav = true; break;
201 case '2': split_wav = true; break;
202 case '3': stereo_image_flag = true; break;
205 TEST_EXTRA_ARG(i, 'b');
206 fb_size = abs(atoi(argv[i]));
209 fprintf(stderr, "Frame Buffer size: %u bytes.\n", fb_size);
214 TEST_EXTRA_ARG(i, 'd');
215 duration_flag = true;
216 duration = abs(atoi(argv[i]));
220 TEST_EXTRA_ARG(i, 'f');
221 start_frame = abs(atoi(argv[i]));
224 case 'G': mode = MMT_GOP_START; break;
225 case 'h': help_flag = true; break;
227 case 'm': read_hmac = true; break;
230 TEST_EXTRA_ARG(i, 'p');
231 picture_rate = abs(atoi(argv[i]));
235 TEST_EXTRA_ARG(i, 's');
236 fb_dump_size = abs(atoi(argv[i]));
239 case 'V': version_flag = true; break;
240 case 'v': verbose_flag = true; break;
241 case 'W': no_write_flag = true; break;
244 TEST_EXTRA_ARG(i, 'w');
245 number_width = abs(atoi(argv[i]));
248 case 'Z': j2c_pedantic = false; break;
249 case 'z': j2c_pedantic = true; break;
252 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
258 if ( argv[i][0] != '-' )
260 if ( input_filename == 0 )
262 input_filename = argv[i];
264 else if ( file_prefix == 0 )
266 file_prefix = argv[i];
271 fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
277 if ( help_flag || version_flag )
280 if ( ( mode == MMT_EXTRACT || mode == MMT_GOP_START ) && input_filename == 0 )
282 fputs("Option requires at least one filename argument.\n", stderr);
286 if ( mode == MMT_EXTRACT && file_prefix == 0 )
288 prefix_buffer = Kumu::PathSetExtension(input_filename, "") + "_";
289 file_prefix = prefix_buffer.c_str();
296 //------------------------------------------------------------------------------------------
299 // Read a plaintext MPEG2 Video Elementary Stream from a plaintext ASDCP file
300 // Read a plaintext MPEG2 Video Elementary Stream from a ciphertext ASDCP file
301 // Read a ciphertext MPEG2 Video Elementary Stream from a ciphertext ASDCP file
304 read_MPEG2_file(CommandOptions& Options)
306 AESDecContext* Context = 0;
307 HMACContext* HMAC = 0;
308 MPEG2::MXFReader Reader;
309 MPEG2::FrameBuffer FrameBuffer(Options.fb_size);
310 Kumu::FileWriter OutFile;
311 ui32_t frame_count = 0;
313 Result_t result = Reader.OpenRead(Options.input_filename);
315 if ( ASDCP_SUCCESS(result) )
317 MPEG2::VideoDescriptor VDesc;
318 Reader.FillVideoDescriptor(VDesc);
319 frame_count = VDesc.ContainerDuration;
321 if ( Options.verbose_flag )
323 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
324 MPEG2::VideoDescriptorDump(VDesc);
328 if ( ASDCP_SUCCESS(result) )
331 snprintf(filename, 256, "%s.ves", Options.file_prefix);
332 result = OutFile.OpenWrite(filename);
335 if ( ASDCP_SUCCESS(result) && Options.key_flag )
337 Context = new AESDecContext;
338 result = Context->InitKey(Options.key_value);
340 if ( ASDCP_SUCCESS(result) && Options.read_hmac )
343 Reader.FillWriterInfo(Info);
347 HMAC = new HMACContext;
348 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
352 fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
357 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);
358 if ( last_frame > frame_count )
359 last_frame = frame_count;
361 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )
363 result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);
365 if ( ASDCP_SUCCESS(result) )
367 if ( Options.verbose_flag )
368 FrameBuffer.Dump(stderr, Options.fb_dump_size);
370 ui32_t write_count = 0;
371 result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);
381 gop_start_test(CommandOptions& Options)
383 using namespace ASDCP::MPEG2;
386 MPEG2::FrameBuffer FrameBuffer(Options.fb_size);
387 ui32_t frame_count = 0;
389 Result_t result = Reader.OpenRead(Options.input_filename);
391 if ( ASDCP_SUCCESS(result) )
393 MPEG2::VideoDescriptor VDesc;
394 Reader.FillVideoDescriptor(VDesc);
395 frame_count = VDesc.ContainerDuration;
397 if ( Options.verbose_flag )
399 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
400 MPEG2::VideoDescriptorDump(VDesc);
404 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);
405 if ( last_frame > frame_count )
406 last_frame = frame_count;
408 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )
410 result = Reader.ReadFrameGOPStart(i, FrameBuffer);
412 if ( ASDCP_SUCCESS(result) )
414 if ( Options.verbose_flag )
415 FrameBuffer.Dump(stderr, Options.fb_dump_size);
417 if ( FrameBuffer.FrameType() != FRAME_I )
418 fprintf(stderr, "Expecting an I frame, got %c\n", FrameTypeChar(FrameBuffer.FrameType()));
420 fprintf(stderr, "Requested frame %u, got %u\n", i, FrameBuffer.FrameNumber());
427 //------------------------------------------------------------------------------------------
431 // Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a plaintext ASDCP file
432 // Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file
433 // Read one or more ciphertext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file
435 read_JP2K_S_file(CommandOptions& Options)
437 AESDecContext* Context = 0;
438 HMACContext* HMAC = 0;
439 JP2K::MXFSReader Reader;
440 JP2K::FrameBuffer FrameBuffer(Options.fb_size);
441 ui32_t frame_count = 0;
443 Result_t result = Reader.OpenRead(Options.input_filename);
445 if ( ASDCP_SUCCESS(result) )
447 JP2K::PictureDescriptor PDesc;
448 Reader.FillPictureDescriptor(PDesc);
450 frame_count = PDesc.ContainerDuration;
452 if ( Options.verbose_flag )
454 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
455 JP2K::PictureDescriptorDump(PDesc);
459 if ( ASDCP_SUCCESS(result) && Options.key_flag )
461 Context = new AESDecContext;
462 result = Context->InitKey(Options.key_value);
464 if ( ASDCP_SUCCESS(result) && Options.read_hmac )
467 Reader.FillWriterInfo(Info);
471 HMAC = new HMACContext;
472 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
476 fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
481 const int filename_max = 1024;
482 char filename[filename_max];
483 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);
484 if ( last_frame > frame_count )
485 last_frame = frame_count;
487 char left_format[64]; char right_format[64];
488 snprintf(left_format, 64, "%%s%%0%duL.j2c", Options.number_width);
489 snprintf(right_format, 64, "%%s%%0%duR.j2c", Options.number_width);
491 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )
493 result = Reader.ReadFrame(i, JP2K::SP_LEFT, FrameBuffer, Context, HMAC);
495 if ( ASDCP_SUCCESS(result) )
497 Kumu::FileWriter OutFile;
499 snprintf(filename, filename_max, left_format, Options.file_prefix, i);
500 result = OutFile.OpenWrite(filename);
502 if ( ASDCP_SUCCESS(result) )
503 result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);
505 if ( Options.verbose_flag )
506 FrameBuffer.Dump(stderr, Options.fb_dump_size);
509 if ( ASDCP_SUCCESS(result) )
510 result = Reader.ReadFrame(i, JP2K::SP_RIGHT, FrameBuffer, Context, HMAC);
512 if ( ASDCP_SUCCESS(result) )
514 Kumu::FileWriter OutFile;
516 snprintf(filename, filename_max, right_format, Options.file_prefix, i);
517 result = OutFile.OpenWrite(filename);
519 if ( ASDCP_SUCCESS(result) )
520 result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);
527 // Read one or more plaintext JPEG 2000 codestreams from a plaintext ASDCP file
528 // Read one or more plaintext JPEG 2000 codestreams from a ciphertext ASDCP file
529 // Read one or more ciphertext JPEG 2000 codestreams from a ciphertext ASDCP file
532 read_JP2K_file(CommandOptions& Options)
534 AESDecContext* Context = 0;
535 HMACContext* HMAC = 0;
536 JP2K::MXFReader Reader;
537 JP2K::FrameBuffer FrameBuffer(Options.fb_size);
538 ui32_t frame_count = 0;
540 Result_t result = Reader.OpenRead(Options.input_filename);
542 if ( ASDCP_SUCCESS(result) )
544 JP2K::PictureDescriptor PDesc;
545 Reader.FillPictureDescriptor(PDesc);
547 frame_count = PDesc.ContainerDuration;
549 if ( Options.verbose_flag )
551 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
552 JP2K::PictureDescriptorDump(PDesc);
556 if ( ASDCP_SUCCESS(result) && Options.key_flag )
558 Context = new AESDecContext;
559 result = Context->InitKey(Options.key_value);
561 if ( ASDCP_SUCCESS(result) && Options.read_hmac )
564 Reader.FillWriterInfo(Info);
568 HMAC = new HMACContext;
569 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
573 fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
578 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);
579 if ( last_frame > frame_count )
580 last_frame = frame_count;
582 char name_format[64];
583 snprintf(name_format, 64, "%%s%%0%du.j2c", Options.number_width);
585 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )
587 result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);
589 if ( ASDCP_SUCCESS(result) )
591 Kumu::FileWriter OutFile;
594 snprintf(filename, 256, name_format, Options.file_prefix, i);
595 result = OutFile.OpenWrite(filename);
597 if ( ASDCP_SUCCESS(result) )
598 result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);
600 if ( Options.verbose_flag )
601 FrameBuffer.Dump(stderr, Options.fb_dump_size);
608 //------------------------------------------------------------------------------------------
611 // Read one or more plaintext PCM audio streams from a plaintext ASDCP file
612 // Read one or more plaintext PCM audio streams from a ciphertext ASDCP file
613 // Read one or more ciphertext PCM audio streams from a ciphertext ASDCP file
616 read_PCM_file(CommandOptions& Options)
618 AESDecContext* Context = 0;
619 HMACContext* HMAC = 0;
620 PCM::MXFReader Reader;
621 PCM::FrameBuffer FrameBuffer;
622 WavFileWriter OutWave;
623 PCM::AudioDescriptor ADesc;
624 ui32_t last_frame = 0;
626 Result_t result = Reader.OpenRead(Options.input_filename);
628 if ( ASDCP_SUCCESS(result) )
630 Reader.FillAudioDescriptor(ADesc);
632 if ( ADesc.EditRate != EditRate_23_98
633 && ADesc.EditRate != EditRate_24
634 && ADesc.EditRate != EditRate_25
635 && ADesc.EditRate != EditRate_30
636 && ADesc.EditRate != EditRate_48
637 && ADesc.EditRate != EditRate_50
638 && ADesc.EditRate != EditRate_60 )
639 ADesc.EditRate = Options.PictureRate();
641 FrameBuffer.Capacity(PCM::CalcFrameBufferSize(ADesc));
643 if ( Options.verbose_flag )
644 PCM::AudioDescriptorDump(ADesc);
647 if ( ASDCP_SUCCESS(result) )
649 last_frame = ADesc.ContainerDuration;
651 if ( Options.duration > 0 && Options.duration < last_frame )
652 last_frame = Options.duration;
654 if ( Options.start_frame > 0 )
656 if ( Options.start_frame > ADesc.ContainerDuration )
658 fprintf(stderr, "Start value greater than file duration.\n");
662 last_frame = Kumu::xmin(Options.start_frame + last_frame, ADesc.ContainerDuration);
665 ADesc.ContainerDuration = last_frame - Options.start_frame;
666 OutWave.OpenWrite(ADesc, Options.file_prefix,
667 ( Options.split_wav ? WavFileWriter::ST_STEREO :
668 ( Options.mono_wav ? WavFileWriter::ST_MONO : WavFileWriter::ST_NONE ) ));
671 if ( ASDCP_SUCCESS(result) && Options.key_flag )
673 Context = new AESDecContext;
674 result = Context->InitKey(Options.key_value);
676 if ( ASDCP_SUCCESS(result) && Options.read_hmac )
679 Reader.FillWriterInfo(Info);
683 HMAC = new HMACContext;
684 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
688 fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
693 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )
695 result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);
697 if ( ASDCP_SUCCESS(result) )
699 if ( Options.verbose_flag )
700 FrameBuffer.Dump(stderr, Options.fb_dump_size);
702 result = OutWave.WriteFrame(FrameBuffer);
710 //------------------------------------------------------------------------------------------
713 // Read one or more timed text streams from a plaintext ASDCP file
714 // Read one or more timed text streams from a ciphertext ASDCP file
715 // Read one or more timed text streams from a ciphertext ASDCP file
718 read_timed_text_file(CommandOptions& Options)
720 AESDecContext* Context = 0;
721 HMACContext* HMAC = 0;
722 TimedText::MXFReader Reader;
723 TimedText::FrameBuffer FrameBuffer;
724 TimedText::TimedTextDescriptor TDesc;
726 Result_t result = Reader.OpenRead(Options.input_filename);
728 if ( ASDCP_SUCCESS(result) )
730 Reader.FillTimedTextDescriptor(TDesc);
731 FrameBuffer.Capacity(Options.fb_size);
733 if ( Options.verbose_flag )
734 TimedText::DescriptorDump(TDesc);
737 if ( ASDCP_SUCCESS(result) && Options.key_flag )
739 Context = new AESDecContext;
740 result = Context->InitKey(Options.key_value);
742 if ( ASDCP_SUCCESS(result) && Options.read_hmac )
745 Reader.FillWriterInfo(Info);
749 HMAC = new HMACContext;
750 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
754 fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
759 if ( ASDCP_FAILURE(result) )
763 std::string out_path = Kumu::PathDirname(Options.file_prefix);
766 TimedText::ResourceList_t::const_iterator ri;
768 result = Reader.ReadTimedTextResource(XMLDoc, Context, HMAC);
770 if ( ASDCP_SUCCESS(result) )
772 Kumu::FileWriter Writer;
773 result = Writer.OpenWrite(Options.file_prefix);
775 if ( ASDCP_SUCCESS(result) )
776 result = Writer.Write(reinterpret_cast<const byte_t*>(XMLDoc.c_str()), XMLDoc.size(), &write_count);
779 for ( ri = TDesc.ResourceList.begin() ; ri != TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ )
781 result = Reader.ReadAncillaryResource(ri->ResourceID, FrameBuffer, Context, HMAC);
783 if ( ASDCP_SUCCESS(result) )
785 Kumu::FileWriter Writer;
786 result = Writer.OpenWrite(Kumu::PathJoin(out_path, Kumu::UUID(ri->ResourceID).EncodeHex(buf, 64)).c_str());
788 if ( ASDCP_SUCCESS(result) )
790 if ( Options.verbose_flag )
791 FrameBuffer.Dump(stderr, Options.fb_dump_size);
793 result = Writer.Write(FrameBuffer.RoData(), FrameBuffer.Size(), &write_count);
803 main(int argc, const char** argv)
805 Result_t result = RESULT_OK;
807 CommandOptions Options(argc, argv);
809 if ( Options.version_flag )
812 if ( Options.help_flag )
815 if ( Options.version_flag || Options.help_flag )
818 if ( Options.error_flag )
820 fprintf(stderr, "There was a problem. Type %s -h for help.\n", PROGRAM_NAME);
824 if ( Options.mode == MMT_GOP_START )
826 result = gop_start_test(Options);
828 else if ( Options.mode == MMT_EXTRACT )
830 EssenceType_t EssenceType;
831 result = ASDCP::EssenceType(Options.input_filename, EssenceType);
833 if ( ASDCP_SUCCESS(result) )
835 switch ( EssenceType )
838 result = read_MPEG2_file(Options);
842 if ( Options.stereo_image_flag )
843 result = read_JP2K_S_file(Options);
845 result = read_JP2K_file(Options);
848 case ESS_JPEG_2000_S:
849 result = read_JP2K_S_file(Options);
852 case ESS_PCM_24b_48k:
853 case ESS_PCM_24b_96k:
854 result = read_PCM_file(Options);
858 result = read_timed_text_file(Options);
862 fprintf(stderr, "%s: Unknown file type, not ASDCP essence.\n", Options.input_filename);
869 fprintf(stderr, "Unhandled mode: %d.\n", Options.mode);
873 if ( ASDCP_FAILURE(result) )
875 fputs("Program stopped on error.\n", stderr);
877 if ( result == RESULT_SFORMAT )
879 fputs("Use option '-3' to force stereoscopic mode.\n", stderr);
881 else if ( result != RESULT_FAIL )
883 fputs(result, stderr);
895 // end asdcp-unwrap.cpp