2 Copyright (c) 2011-2016, 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-unwrap.cpp
31 \brief AS-02 file manipulation utility
33 This program extracts picture and sound from AS-02 files.
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>
41 #include <WavFileWriter.h>
44 Result_t MD_to_PCM_ADesc(ASDCP::MXF::WaveAudioDescriptor* ADescObj, ASDCP::PCM::AudioDescriptor& ADesc);
47 using namespace ASDCP;
49 const ui32_t FRAME_BUFFER_SIZE = 4 * Kumu::Megabyte;
51 //------------------------------------------------------------------------------------------
53 // command line option parser class
55 static const char* PROGRAM_NAME = "as-02-unwrap"; // program name for messages
57 // Increment the iterator, test for an additional non-option command line argument.
58 // Causes the caller to return if there are no remaining arguments or if the next
59 // argument begins with '-'.
60 #define TEST_EXTRA_ARG(i,c) \
61 if ( ++i >= argc || argv[(i)][0] == '-' ) { \
62 fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
68 banner(FILE* stream = stdout)
72 Copyright (c) 2011-2015, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst\n\n\
73 asdcplib may be copied only under the terms of the license found at\n\
74 the top of every file in the asdcplib distribution kit.\n\n\
75 Specify the -h (help) option for further information about %s\n\n",
76 PROGRAM_NAME, ASDCP::Version(), PROGRAM_NAME);
81 usage(FILE* stream = stdout)
84 USAGE: %s [-h|-help] [-V]\n\
86 %s [-1|-2] [-b <buffer-size>] [-d <duration>]\n\
87 [-f <starting-frame>] [-m] [-p <frame-rate>] [-R] [-s <size>] [-v] [-W]\n\
88 [-w] <input-file> [<file-prefix>]\n\n",
89 PROGRAM_NAME, PROGRAM_NAME);
93 -1 - Split Wave essence to mono WAV files during extract.\n\
94 Default is multichannel WAV\n\
95 -2 - Split Wave essence to stereo WAV files during extract.\n\
96 Default is multichannel WAV\n\
97 -b <buffer-size> - Specify size in bytes of picture frame buffer\n\
98 Defaults to 4,194,304 (4MB)\n\
99 -d <duration> - Number of frames to process, default all\n\
100 -e <extension> - Extension to use for aux data files. default \"bin\"\n\
101 -f <start-frame> - Starting frame number, default 0\n\
102 -g <filename> - Extract global metadata to the named file.\n\
103 -h | -help - Show help\n\
104 -k <key-string> - Use key for ciphertext operations\n\
105 -m - verify HMAC values when reading\n\
106 -s <size> - Number of bytes to dump to output when -v is given\n\
107 -V - Show version information\n\
108 -v - Verbose, prints informative messages to stderr\n\
109 -W - Read input file only, do not write destination file\n\
110 -w <width> - Width of numeric element in a series of frame file names\n\
112 -z - Fail if j2c inputs have unequal parameters (default)\n\
113 -Z - Ignore unequal parameters in j2c inputs\n\
115 NOTES: o There is no option grouping, all options must be distinct arguments.\n\
116 o All option arguments must be separated from the option by whitespace.\n\n");
125 bool error_flag; // true if the given options are in error or not complete
126 bool key_flag; // true if an encryption key was given
127 bool read_hmac; // true if HMAC values are to be validated
128 bool split_wav; // true if PCM is to be extracted to stereo WAV files
129 bool mono_wav; // true if PCM is to be extracted to mono WAV files
130 bool verbose_flag; // true if the verbose option was selected
131 ui32_t fb_dump_size; // number of bytes of frame buffer to dump
132 bool no_write_flag; // true if no output files are to be written
133 bool version_flag; // true if the version display option was selected
134 bool help_flag; // true if the help display option was selected
135 bool stereo_image_flag; // if true, expect stereoscopic JP2K input (left eye first)
136 ui32_t number_width; // number of digits in a serialized filename (for JPEG extract)
137 ui32_t start_frame; // frame number to begin processing
138 ui32_t duration; // number of frames to be processed
139 bool duration_flag; // true if duration argument given
140 bool j2c_pedantic; // passed to JP2K::SequenceParser::OpenRead
141 ui32_t picture_rate; // fps of picture when wrapping PCM
142 ui32_t fb_size; // size of picture frame buffer
143 Rational edit_rate; // frame buffer size for reading clip-wrapped PCM
144 const char* file_prefix; // filename pre for files written by the extract mode
145 byte_t key_value[KeyLen]; // value of given encryption key (when key_flag is true)
146 byte_t key_id_value[UUIDlen];// value of given key ID (when key_id_flag is true)
147 PCM::ChannelFormat_t channel_fmt; // audio channel arrangement
148 const char* input_filename;
149 const char* extension;
150 std::string global_metadata_filename, prefix_buffer;
153 CommandOptions(int argc, const char** argv) :
154 error_flag(true), key_flag(false), read_hmac(false), split_wav(false),
155 mono_wav(false), verbose_flag(false), fb_dump_size(0), no_write_flag(false),
156 version_flag(false), help_flag(false), number_width(6),
157 start_frame(0), duration(0xffffffff), duration_flag(false), j2c_pedantic(true),
158 picture_rate(24), fb_size(FRAME_BUFFER_SIZE), file_prefix(0),
159 input_filename(0), extension("bin")
161 memset(key_value, 0, KeyLen);
162 memset(key_id_value, 0, UUIDlen);
164 for ( int i = 1; i < argc; ++i )
167 if ( (strcmp( argv[i], "-help") == 0) )
173 if ( argv[i][0] == '-'
174 && ( isalpha(argv[i][1]) || isdigit(argv[i][1]) )
177 switch ( argv[i][1] )
179 case '1': mono_wav = true; break;
180 case '2': split_wav = true; break;
183 TEST_EXTRA_ARG(i, 'b');
184 fb_size = Kumu::xabs(strtol(argv[i], 0, 10));
187 fprintf(stderr, "Frame Buffer size: %u bytes.\n", fb_size);
192 TEST_EXTRA_ARG(i, 'd');
193 duration_flag = true;
194 duration = Kumu::xabs(strtol(argv[i], 0, 10));
198 TEST_EXTRA_ARG(i, 'e');
203 TEST_EXTRA_ARG(i, 'f');
204 start_frame = Kumu::xabs(strtol(argv[i], 0, 10));
208 TEST_EXTRA_ARG(i, 'g');
209 global_metadata_filename = argv[i];
212 case 'h': help_flag = true; break;
213 case 'm': read_hmac = true; break;
216 TEST_EXTRA_ARG(i, 'p');
217 picture_rate = Kumu::xabs(strtol(argv[i], 0, 10));
221 TEST_EXTRA_ARG(i, 's');
222 fb_dump_size = Kumu::xabs(strtol(argv[i], 0, 10));
225 case 'V': version_flag = true; break;
226 case 'v': verbose_flag = true; break;
227 case 'W': no_write_flag = true; break;
230 TEST_EXTRA_ARG(i, 'w');
231 number_width = Kumu::xabs(strtol(argv[i], 0, 10));
234 case 'Z': j2c_pedantic = false; break;
235 case 'z': j2c_pedantic = true; break;
238 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
244 if ( argv[i][0] != '-' )
246 if ( input_filename == 0 )
248 input_filename = argv[i];
250 else if ( file_prefix == 0 )
252 file_prefix = argv[i];
257 fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
263 if ( help_flag || version_flag )
266 if ( input_filename == 0 )
268 fputs("At least one filename argument is required.\n", stderr);
272 if ( file_prefix == 0 )
274 prefix_buffer = Kumu::PathSetExtension(input_filename, "") + "_";
275 file_prefix = prefix_buffer.c_str();
283 //------------------------------------------------------------------------------------------
287 // Read one or more plaintext JPEG 2000 codestreams from a plaintext ASDCP file
288 // Read one or more plaintext JPEG 2000 codestreams from a ciphertext ASDCP file
289 // Read one or more ciphertext JPEG 2000 codestreams from a ciphertext ASDCP file
292 read_JP2K_file(CommandOptions& Options)
294 AESDecContext* Context = 0;
295 HMACContext* HMAC = 0;
296 AS_02::JP2K::MXFReader Reader;
297 JP2K::FrameBuffer FrameBuffer(Options.fb_size);
298 ui32_t frame_count = 0;
300 Result_t result = Reader.OpenRead(Options.input_filename);
302 if ( ASDCP_SUCCESS(result) )
304 if ( Options.verbose_flag )
306 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
309 ASDCP::MXF::RGBAEssenceDescriptor *rgba_descriptor = 0;
310 ASDCP::MXF::CDCIEssenceDescriptor *cdci_descriptor = 0;
312 result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_RGBAEssenceDescriptor),
313 reinterpret_cast<MXF::InterchangeObject**>(&rgba_descriptor));
315 if ( KM_SUCCESS(result) )
317 assert(rgba_descriptor);
318 frame_count = rgba_descriptor->ContainerDuration;
320 if ( Options.verbose_flag )
322 rgba_descriptor->Dump();
327 result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_CDCIEssenceDescriptor),
328 reinterpret_cast<MXF::InterchangeObject**>(&cdci_descriptor));
330 if ( KM_SUCCESS(result) )
332 assert(cdci_descriptor);
333 frame_count = cdci_descriptor->ContainerDuration;
335 if ( Options.verbose_flag )
337 cdci_descriptor->Dump();
342 fprintf(stderr, "File does not contain an essence descriptor.\n");
343 frame_count = Reader.AS02IndexReader().GetDuration();
347 if ( frame_count == 0 )
349 frame_count = Reader.AS02IndexReader().GetDuration();
352 if ( frame_count == 0 )
354 fprintf(stderr, "Unable to determine file duration.\n");
359 if ( ASDCP_SUCCESS(result) && Options.key_flag )
361 Context = new AESDecContext;
362 result = Context->InitKey(Options.key_value);
364 if ( ASDCP_SUCCESS(result) && Options.read_hmac )
367 Reader.FillWriterInfo(Info);
371 HMAC = new HMACContext;
372 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
376 fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
381 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);
382 if ( last_frame > frame_count )
383 last_frame = frame_count;
385 char name_format[64];
386 snprintf(name_format, 64, "%%s%%0%du.j2c", Options.number_width);
388 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )
390 result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);
393 snprintf(filename, 1024, name_format, Options.file_prefix, i);
395 if ( ASDCP_SUCCESS(result) && Options.verbose_flag )
397 printf("Frame %d, %d bytes", i, FrameBuffer.Size());
399 if ( ! Options.no_write_flag )
401 printf(" -> %s", filename);
407 if ( ASDCP_SUCCESS(result) && ( ! Options.no_write_flag ) )
409 Kumu::FileWriter OutFile;
411 result = OutFile.OpenWrite(filename);
413 if ( ASDCP_SUCCESS(result) )
414 result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);
416 if ( ASDCP_SUCCESS(result) && Options.verbose_flag )
418 FrameBuffer.Dump(stderr, Options.fb_dump_size);
426 //------------------------------------------------------------------------------------------
429 // Read one or more plaintext PCM audio streams from a plaintext ASDCP file
430 // Read one or more plaintext PCM audio streams from a ciphertext ASDCP file
431 // Read one or more ciphertext PCM audio streams from a ciphertext ASDCP file
434 read_PCM_file(CommandOptions& Options)
436 AESDecContext* Context = 0;
437 HMACContext* HMAC = 0;
438 AS_02::PCM::MXFReader Reader;
439 PCM::FrameBuffer FrameBuffer;
440 WavFileWriter OutWave;
441 ui32_t last_frame = 0;
442 ASDCP::MXF::WaveAudioDescriptor *wave_descriptor = 0;
444 if ( Options.edit_rate == Rational(0,0) ) // todo, make this available to the CLI
446 Options.edit_rate = EditRate_24;
449 Result_t result = Reader.OpenRead(Options.input_filename, Options.edit_rate);
451 if ( KM_SUCCESS(result) )
453 if ( Options.verbose_flag )
455 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
458 ASDCP::MXF::InterchangeObject* tmp_obj = 0;
460 result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_WaveAudioDescriptor), &tmp_obj);
462 if ( KM_SUCCESS(result) )
464 wave_descriptor = dynamic_cast<ASDCP::MXF::WaveAudioDescriptor*>(tmp_obj);
466 if ( wave_descriptor == 0 )
468 fprintf(stderr, "File does not contain an essence descriptor.\n");
472 if ( Options.verbose_flag )
474 wave_descriptor->Dump();
477 if ( wave_descriptor->ContainerDuration.get() == 0 )
479 fprintf(stderr, "ContainerDuration not set in file descriptor, attempting to use index duration.\n");
480 last_frame = Reader.AS02IndexReader().GetDuration();
484 last_frame = wave_descriptor->ContainerDuration;
487 if ( last_frame == 0 )
489 fprintf(stderr, "ContainerDuration not set in index, attempting to use Duration from SourceClip.\n");
490 result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_SourceClip), &tmp_obj);
491 if ( KM_SUCCESS(result))
493 ASDCP::MXF::SourceClip *sourceClip = dynamic_cast<ASDCP::MXF::SourceClip*>(tmp_obj);
494 if ( ! sourceClip->Duration.empty() )
496 last_frame = sourceClip->Duration;
501 if ( last_frame == 0 )
503 fprintf(stderr, "Unable to determine file duration.\n");
507 assert(wave_descriptor);
508 FrameBuffer.Capacity(AS_02::MXF::CalcFrameBufferSize(*wave_descriptor, Options.edit_rate));
509 last_frame = AS_02::MXF::CalcFramesFromDurationInSamples(last_frame, *wave_descriptor, Options.edit_rate);
513 if ( ASDCP_SUCCESS(result) )
515 if ( Options.duration > 0 && Options.duration < last_frame )
516 last_frame = Options.duration;
518 if ( Options.start_frame > 0 )
520 if ( Options.start_frame > last_frame )
522 fprintf(stderr, "Start value greater than file duration.\n");
526 last_frame = Kumu::xmin(Options.start_frame + last_frame, last_frame);
529 last_frame = last_frame - Options.start_frame;
531 PCM::AudioDescriptor ADesc;
533 result = MD_to_PCM_ADesc(wave_descriptor, ADesc);
535 if ( ASDCP_SUCCESS(result) )
537 ADesc.ContainerDuration = last_frame;
538 ADesc.EditRate = Options.edit_rate;
540 result = OutWave.OpenWrite(ADesc, Options.file_prefix,
541 ( Options.split_wav ? WavFileWriter::ST_STEREO :
542 ( Options.mono_wav ? WavFileWriter::ST_MONO : WavFileWriter::ST_NONE ) ));
546 if ( ASDCP_SUCCESS(result) && Options.key_flag )
548 Context = new AESDecContext;
549 result = Context->InitKey(Options.key_value);
551 if ( ASDCP_SUCCESS(result) && Options.read_hmac )
554 Reader.FillWriterInfo(Info);
558 HMAC = new HMACContext;
559 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
563 fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
568 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )
570 result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);
572 if ( ASDCP_SUCCESS(result) )
574 if ( Options.verbose_flag )
576 FrameBuffer.FrameNumber(i);
577 FrameBuffer.Dump(stderr, Options.fb_dump_size);
580 if ( FrameBuffer.Size() != FrameBuffer.Capacity() )
582 fprintf(stderr, "Last frame is incomplete, padding with zeros.\n");
583 // actually, it has already been zeroed for us, we just need to recognize the appropriate size
584 FrameBuffer.Size(FrameBuffer.Capacity());
587 result = OutWave.WriteFrame(FrameBuffer);
595 //------------------------------------------------------------------------------------------
598 // Read one or more timed text streams from a plaintext AS-02 file
601 read_timed_text_file(CommandOptions& Options)
603 AESDecContext* Context = 0;
604 HMACContext* HMAC = 0;
605 AS_02::TimedText::MXFReader Reader;
606 TimedText::FrameBuffer FrameBuffer(Options.fb_size);
607 //ASDCP::TimedText::FrameBuffer FrameBuffer(Options.fb_size);
608 AS_02::TimedText::TimedTextDescriptor TDesc;
609 ASDCP::MXF::TimedTextDescriptor *tt_descriptor = 0;
611 Result_t result = Reader.OpenRead(Options.input_filename);
613 if ( ASDCP_SUCCESS(result) )
615 result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_TimedTextDescriptor),
616 reinterpret_cast<MXF::InterchangeObject**>(&tt_descriptor));
617 if ( Options.verbose_flag ) {
618 tt_descriptor->Dump();
622 if ( ASDCP_FAILURE(result) )
626 std::string out_path = Kumu::PathDirname(Options.file_prefix);
629 TimedText::ResourceList_t::const_iterator ri;
631 result = Reader.ReadTimedTextResource(XMLDoc);
633 if ( ASDCP_SUCCESS(result) )
635 Reader.FillTimedTextDescriptor(TDesc);
636 FrameBuffer.Capacity(Options.fb_size);
638 if ( Options.verbose_flag )
639 TimedText::DescriptorDump(TDesc);
642 if ( ASDCP_SUCCESS(result) && ( ! Options.no_write_flag ) )
644 Kumu::FileWriter Writer;
645 result = Writer.OpenWrite(Options.file_prefix);
647 if ( ASDCP_SUCCESS(result) )
648 result = Writer.Write(reinterpret_cast<const byte_t*>(XMLDoc.c_str()), XMLDoc.size(), &write_count);
651 for ( ri = TDesc.ResourceList.begin() ; ri != TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ )
653 result = Reader.ReadAncillaryResource(ri->ResourceID, FrameBuffer, Context, HMAC);
655 if ( ASDCP_SUCCESS(result) && ( ! Options.no_write_flag ) )
657 Kumu::FileWriter Writer;
658 if (out_path != "") {
659 result = Writer.OpenWrite(Kumu::PathJoin(out_path, Kumu::UUID(ri->ResourceID).EncodeHex(buf, 64)).c_str());
661 // Workaround for a bug in Kumu::PathJoin
662 result = Writer.OpenWrite(Kumu::UUID(ri->ResourceID).EncodeHex(buf, 64));
665 if ( ASDCP_SUCCESS(result) )
666 result = Writer.Write(FrameBuffer.RoData(), FrameBuffer.Size(), &write_count);
668 if ( Options.verbose_flag )
669 FrameBuffer.Dump(stderr, Options.fb_dump_size);
676 // Read one or more plaintext DCData bytestreams from a plaintext ASDCP file
677 // Read one or more plaintext DCData bytestreams from a ciphertext ASDCP file
678 // Read one or more ciphertext DCData byestreams from a ciphertext ASDCP file
681 read_aux_data_file(CommandOptions& Options)
683 AESDecContext* Context = 0;
684 HMACContext* HMAC = 0;
685 AS_02::AuxData::MXFReader Reader;
686 DCData::FrameBuffer FrameBuffer(Options.fb_size);
687 ui32_t frame_count = 0;
689 ASDCP::FrameBuffer global_metadata;
690 Result_t result = Reader.OpenRead(Options.input_filename, global_metadata);
692 if ( ASDCP_SUCCESS(result)
693 && global_metadata.Size()
694 && ! Options.global_metadata_filename.empty() )
696 ui32_t write_count = 0;
697 Kumu::FileWriter Writer;
699 result = Writer.OpenWrite(Options.global_metadata_filename);
701 if ( ASDCP_SUCCESS(result) )
703 result = Writer.Write(global_metadata.RoData(), global_metadata.Size(), &write_count);
706 if ( ASDCP_SUCCESS(result) && global_metadata.Size() != write_count)
708 return RESULT_WRITEFAIL;
712 if ( ASDCP_SUCCESS(result) )
714 frame_count = Reader.AS02IndexReader().GetDuration();
716 if ( Options.verbose_flag )
718 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
722 if ( ASDCP_SUCCESS(result) && Options.key_flag )
724 Context = new AESDecContext;
725 result = Context->InitKey(Options.key_value);
727 if ( ASDCP_SUCCESS(result) && Options.read_hmac )
730 Reader.FillWriterInfo(Info);
734 HMAC = new HMACContext;
735 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
739 fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
744 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);
745 if ( last_frame > frame_count )
746 last_frame = frame_count;
748 char name_format[64];
749 snprintf(name_format, 64, "%%s%%0%du.%s", Options.number_width, Options.extension);
751 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )
753 result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);
755 if ( ASDCP_SUCCESS(result) )
757 if ( ! Options.no_write_flag )
759 Kumu::FileWriter OutFile;
762 snprintf(filename, 256, name_format, Options.file_prefix, i);
763 result = OutFile.OpenWrite(filename);
765 if ( ASDCP_SUCCESS(result) )
766 result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);
769 if ( Options.verbose_flag )
770 FrameBuffer.Dump(stderr, Options.fb_dump_size);
780 main(int argc, const char** argv)
783 CommandOptions Options(argc, argv);
785 if ( Options.version_flag )
788 if ( Options.help_flag )
791 if ( Options.version_flag || Options.help_flag )
794 if ( Options.error_flag )
796 fprintf(stderr, "There was a problem. Type %s -h for help.\n", PROGRAM_NAME);
800 EssenceType_t EssenceType;
801 Result_t result = ASDCP::EssenceType(Options.input_filename, EssenceType);
803 if ( ASDCP_SUCCESS(result) )
805 switch ( EssenceType )
807 case ESS_AS02_JPEG_2000:
808 result = read_JP2K_file(Options);
811 case ESS_AS02_PCM_24b_48k:
812 case ESS_AS02_PCM_24b_96k:
813 result = read_PCM_file(Options);
816 case ESS_AS02_TIMED_TEXT:
817 result = read_timed_text_file(Options);
820 case ESS_DCDATA_UNKNOWN:
821 result = read_aux_data_file(Options);
825 fprintf(stderr, "%s: Unknown file type, not AS-02 essence.\n", Options.input_filename);
830 if ( ASDCP_FAILURE(result) )
832 fputs("Program stopped on error.\n", stderr);
834 if ( result != RESULT_FAIL )
836 fputs(result, stderr);
848 // end as-02-unwrap.cpp