2 Copyright (c) 2011-2018, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /*! \file as-02-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-2018, 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 -f <start-frame> - Starting frame number, default 0\n\
101 -g <SID> - Extract the Generic Stream Partition payload\n\
102 -h | -help - Show help\n\
103 -k <key-string> - Use key for ciphertext operations\n\
104 -m - verify HMAC values when reading\n\
105 -s <size> - Number of bytes to dump to output when -v is given\n\
106 -V - Show version information\n\
107 -v - Verbose, prints informative messages to stderr\n\
108 -W - Read input file only, do not write destination file\n\
109 -w <width> - Width of numeric element in a series of frame file names\n\
111 -z - Fail if j2c inputs have unequal parameters (default)\n\
112 -Z - Ignore unequal parameters in j2c inputs\n\
114 NOTES: o There is no option grouping, all options must be distinct arguments.\n\
115 o All option arguments must be separated from the option by whitespace.\n\n");
124 bool error_flag; // true if the given options are in error or not complete
125 bool key_flag; // true if an encryption key was given
126 bool read_hmac; // true if HMAC values are to be validated
127 bool split_wav; // true if PCM is to be extracted to stereo WAV files
128 bool mono_wav; // true if PCM is to be extracted to mono WAV files
129 bool verbose_flag; // true if the verbose option was selected
130 ui32_t fb_dump_size; // number of bytes of frame buffer to dump
131 bool no_write_flag; // true if no output files are to be written
132 bool version_flag; // true if the version display option was selected
133 bool help_flag; // true if the help display option was selected
134 bool stereo_image_flag; // if true, expect stereoscopic JP2K input (left eye first)
135 ui32_t number_width; // number of digits in a serialized filename (for JPEG extract)
136 ui32_t start_frame; // frame number to begin processing
137 ui32_t duration; // number of frames to be processed
138 bool duration_flag; // true if duration argument given
139 bool j2c_pedantic; // passed to JP2K::SequenceParser::OpenRead
140 ui32_t picture_rate; // fps of picture when wrapping PCM
141 ui32_t fb_size; // size of picture frame buffer
142 Rational edit_rate; // frame buffer size for reading clip-wrapped PCM
143 const char* file_prefix; // filename pre for files written by the extract mode
144 byte_t key_value[KeyLen]; // value of given encryption key (when key_flag is true)
145 byte_t key_id_value[UUIDlen];// value of given key ID (when key_id_flag is true)
146 const char* input_filename;
147 const char* extension;
148 i32_t g_stream_sid; // Stream ID of a generic stream partition payload to be extracted
149 std::string prefix_buffer;
152 CommandOptions(int argc, const char** argv) :
153 error_flag(true), key_flag(false), read_hmac(false), split_wav(false),
154 mono_wav(false), verbose_flag(false), fb_dump_size(0), no_write_flag(false),
155 version_flag(false), help_flag(false), number_width(6),
156 start_frame(0), duration(0xffffffff), duration_flag(false), j2c_pedantic(true),
157 picture_rate(24), fb_size(FRAME_BUFFER_SIZE), file_prefix(0),
158 input_filename(0), extension(0), g_stream_sid(0)
160 memset(key_value, 0, KeyLen);
161 memset(key_id_value, 0, UUIDlen);
163 for ( int i = 1; i < argc; ++i )
166 if ( (strcmp( argv[i], "-help") == 0) )
172 if ( argv[i][0] == '-'
173 && ( isalpha(argv[i][1]) || isdigit(argv[i][1]) )
176 switch ( argv[i][1] )
178 case '1': mono_wav = true; break;
179 case '2': split_wav = true; break;
182 TEST_EXTRA_ARG(i, 'b');
183 fb_size = Kumu::xabs(strtol(argv[i], 0, 10));
186 fprintf(stderr, "Frame Buffer size: %u bytes.\n", fb_size);
191 TEST_EXTRA_ARG(i, 'd');
192 duration_flag = true;
193 duration = Kumu::xabs(strtol(argv[i], 0, 10));
197 TEST_EXTRA_ARG(i, 'e');
202 TEST_EXTRA_ARG(i, 'f');
203 start_frame = Kumu::xabs(strtol(argv[i], 0, 10));
207 TEST_EXTRA_ARG(i, 'g');
208 g_stream_sid = strtol(argv[i], 0, 10);
211 case 'h': help_flag = true; break;
212 case 'm': read_hmac = true; break;
215 TEST_EXTRA_ARG(i, 'p');
216 picture_rate = Kumu::xabs(strtol(argv[i], 0, 10));
220 TEST_EXTRA_ARG(i, 's');
221 fb_dump_size = Kumu::xabs(strtol(argv[i], 0, 10));
224 case 'V': version_flag = true; break;
225 case 'v': verbose_flag = true; break;
226 case 'W': no_write_flag = true; break;
229 TEST_EXTRA_ARG(i, 'w');
230 number_width = Kumu::xabs(strtol(argv[i], 0, 10));
233 case 'Z': j2c_pedantic = false; break;
234 case 'z': j2c_pedantic = true; break;
237 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
243 if ( argv[i][0] != '-' )
245 if ( input_filename == 0 )
247 input_filename = argv[i];
249 else if ( file_prefix == 0 )
251 file_prefix = argv[i];
256 fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
262 if ( help_flag || version_flag )
265 if ( input_filename == 0 )
267 fputs("At least one filename argument is required.\n", stderr);
271 if ( file_prefix == 0 )
273 prefix_buffer = Kumu::PathSetExtension(input_filename, "") + "_";
274 file_prefix = prefix_buffer.c_str();
282 //------------------------------------------------------------------------------------------
286 // Read one or more plaintext JPEG 2000 codestreams from a plaintext ASDCP file
287 // Read one or more plaintext JPEG 2000 codestreams from a ciphertext ASDCP file
288 // Read one or more ciphertext JPEG 2000 codestreams from a ciphertext ASDCP file
291 read_JP2K_file(CommandOptions& Options)
293 AESDecContext* Context = 0;
294 HMACContext* HMAC = 0;
295 AS_02::JP2K::MXFReader Reader;
296 JP2K::FrameBuffer FrameBuffer(Options.fb_size);
297 ui32_t frame_count = 0;
299 Result_t result = Reader.OpenRead(Options.input_filename);
301 if ( ASDCP_SUCCESS(result) )
303 if ( Options.verbose_flag )
305 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
308 ASDCP::MXF::RGBAEssenceDescriptor *rgba_descriptor = 0;
309 ASDCP::MXF::CDCIEssenceDescriptor *cdci_descriptor = 0;
311 result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_RGBAEssenceDescriptor),
312 reinterpret_cast<MXF::InterchangeObject**>(&rgba_descriptor));
314 if ( KM_SUCCESS(result) )
316 assert(rgba_descriptor);
317 frame_count = (ui32_t)rgba_descriptor->ContainerDuration;
319 if ( Options.verbose_flag )
321 rgba_descriptor->Dump();
326 result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_CDCIEssenceDescriptor),
327 reinterpret_cast<MXF::InterchangeObject**>(&cdci_descriptor));
329 if ( KM_SUCCESS(result) )
331 assert(cdci_descriptor);
332 frame_count = (ui32_t)cdci_descriptor->ContainerDuration;
334 if ( Options.verbose_flag )
336 cdci_descriptor->Dump();
341 fprintf(stderr, "File does not contain an essence descriptor.\n");
342 frame_count = Reader.AS02IndexReader().GetDuration();
346 if ( frame_count == 0 )
348 frame_count = Reader.AS02IndexReader().GetDuration();
351 if ( frame_count == 0 )
353 fprintf(stderr, "Unable to determine file duration.\n");
358 if ( ASDCP_SUCCESS(result) && Options.key_flag )
360 Context = new AESDecContext;
361 result = Context->InitKey(Options.key_value);
363 if ( ASDCP_SUCCESS(result) && Options.read_hmac )
366 Reader.FillWriterInfo(Info);
370 HMAC = new HMACContext;
371 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
375 fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
380 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);
381 if ( last_frame > frame_count )
382 last_frame = frame_count;
384 char name_format[64];
385 snprintf(name_format, 64, "%%s%%0%du.j2c", Options.number_width);
387 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )
389 result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);
392 snprintf(filename, 1024, name_format, Options.file_prefix, i);
394 if ( ASDCP_SUCCESS(result) && Options.verbose_flag )
396 printf("Frame %d, %d bytes", i, FrameBuffer.Size());
398 if ( ! Options.no_write_flag )
400 printf(" -> %s", filename);
406 if ( ASDCP_SUCCESS(result) && ( ! Options.no_write_flag ) )
408 Kumu::FileWriter OutFile;
410 result = OutFile.OpenWrite(filename);
412 if ( ASDCP_SUCCESS(result) )
413 result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);
415 if ( ASDCP_SUCCESS(result) && Options.verbose_flag )
417 FrameBuffer.Dump(stderr, Options.fb_dump_size);
425 //------------------------------------------------------------------------------------------
428 // Read one or more plaintext PCM audio streams from a plaintext ASDCP file
429 // Read one or more plaintext PCM audio streams from a ciphertext ASDCP file
430 // Read one or more ciphertext PCM audio streams from a ciphertext ASDCP file
433 read_PCM_file(CommandOptions& Options)
435 AESDecContext* Context = 0;
436 HMACContext* HMAC = 0;
437 AS_02::PCM::MXFReader Reader;
438 PCM::FrameBuffer FrameBuffer;
439 WavFileWriter OutWave;
440 ui32_t last_frame = 0;
441 ASDCP::MXF::WaveAudioDescriptor *wave_descriptor = 0;
443 if ( Options.edit_rate == Rational(0,0) ) // todo, make this available to the CLI
445 Options.edit_rate = EditRate_24;
448 Result_t result = Reader.OpenRead(Options.input_filename, Options.edit_rate);
450 if ( KM_SUCCESS(result) )
452 if ( Options.verbose_flag )
454 fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
457 ASDCP::MXF::InterchangeObject* tmp_obj = 0;
459 result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_WaveAudioDescriptor), &tmp_obj);
461 if ( KM_SUCCESS(result) )
463 wave_descriptor = dynamic_cast<ASDCP::MXF::WaveAudioDescriptor*>(tmp_obj);
465 if ( wave_descriptor == 0 )
467 fprintf(stderr, "File does not contain an essence descriptor.\n");
471 if ( Options.verbose_flag )
473 wave_descriptor->Dump();
476 if ( wave_descriptor->ContainerDuration.get() == 0 )
478 fprintf(stderr, "ContainerDuration not set in file descriptor, attempting to use index duration.\n");
479 last_frame = Reader.AS02IndexReader().GetDuration();
483 last_frame = (ui32_t)wave_descriptor->ContainerDuration;
486 if ( last_frame == 0 )
488 fprintf(stderr, "ContainerDuration not set in index, attempting to use Duration from SourceClip.\n");
489 result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_SourceClip), &tmp_obj);
490 if ( KM_SUCCESS(result))
492 ASDCP::MXF::SourceClip *sourceClip = dynamic_cast<ASDCP::MXF::SourceClip*>(tmp_obj);
493 if ( ! sourceClip->Duration.empty() )
495 last_frame = (ui32_t)sourceClip->Duration;
500 if ( last_frame == 0 )
502 fprintf(stderr, "Unable to determine file duration.\n");
506 assert(wave_descriptor);
507 FrameBuffer.Capacity(AS_02::MXF::CalcFrameBufferSize(*wave_descriptor, Options.edit_rate));
508 last_frame = AS_02::MXF::CalcFramesFromDurationInSamples(last_frame, *wave_descriptor, Options.edit_rate);
512 if ( ASDCP_SUCCESS(result) )
514 if ( Options.duration > 0 && Options.duration < last_frame )
515 last_frame = Options.duration;
517 if ( Options.start_frame > 0 )
519 if ( Options.start_frame > last_frame )
521 fprintf(stderr, "Start value greater than file duration.\n");
525 last_frame = Kumu::xmin(Options.start_frame + last_frame, last_frame);
528 last_frame = last_frame - Options.start_frame;
530 PCM::AudioDescriptor ADesc;
532 result = MD_to_PCM_ADesc(wave_descriptor, ADesc);
534 if ( ASDCP_SUCCESS(result) )
536 ADesc.ContainerDuration = last_frame;
537 ADesc.EditRate = Options.edit_rate;
539 result = OutWave.OpenWrite(ADesc, Options.file_prefix,
540 ( Options.split_wav ? WavFileWriter::ST_STEREO :
541 ( Options.mono_wav ? WavFileWriter::ST_MONO : WavFileWriter::ST_NONE ) ));
545 if ( ASDCP_SUCCESS(result) && Options.key_flag )
547 Context = new AESDecContext;
548 result = Context->InitKey(Options.key_value);
550 if ( ASDCP_SUCCESS(result) && Options.read_hmac )
553 Reader.FillWriterInfo(Info);
557 HMAC = new HMACContext;
558 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
562 fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
567 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )
569 result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);
571 if ( ASDCP_SUCCESS(result) )
573 if ( Options.verbose_flag )
575 FrameBuffer.FrameNumber(i);
576 FrameBuffer.Dump(stderr, Options.fb_dump_size);
579 if ( FrameBuffer.Size() != FrameBuffer.Capacity() )
581 fprintf(stderr, "Last frame is incomplete, padding with zeros.\n");
582 // actually, it has already been zeroed for us, we just need to recognize the appropriate size
583 FrameBuffer.Size(FrameBuffer.Capacity());
586 result = OutWave.WriteFrame(FrameBuffer);
594 //------------------------------------------------------------------------------------------
597 // Read one or more timed text streams from a plaintext AS-02 file
600 read_timed_text_file(CommandOptions& Options)
602 AESDecContext* Context = 0;
603 HMACContext* HMAC = 0;
604 AS_02::TimedText::MXFReader Reader;
605 TimedText::FrameBuffer FrameBuffer(Options.fb_size);
606 //ASDCP::TimedText::FrameBuffer FrameBuffer(Options.fb_size);
607 AS_02::TimedText::TimedTextDescriptor TDesc;
608 ASDCP::MXF::TimedTextDescriptor *tt_descriptor = 0;
610 Result_t result = Reader.OpenRead(Options.input_filename);
612 if ( ASDCP_SUCCESS(result) )
614 result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_TimedTextDescriptor),
615 reinterpret_cast<MXF::InterchangeObject**>(&tt_descriptor));
616 if ( Options.verbose_flag ) {
617 tt_descriptor->Dump();
621 if ( ASDCP_FAILURE(result) )
625 std::string out_path = Kumu::PathDirname(Options.file_prefix);
628 TimedText::ResourceList_t::const_iterator ri;
630 result = Reader.ReadTimedTextResource(XMLDoc);
632 if ( ASDCP_SUCCESS(result) )
634 Reader.FillTimedTextDescriptor(TDesc);
635 FrameBuffer.Capacity(Options.fb_size);
637 if ( Options.verbose_flag )
638 TimedText::DescriptorDump(TDesc);
641 if ( ASDCP_SUCCESS(result) && ( ! Options.no_write_flag ) )
643 Kumu::FileWriter Writer;
644 result = Writer.OpenWrite(Options.file_prefix);
646 if ( ASDCP_SUCCESS(result) )
647 result = Writer.Write(reinterpret_cast<const byte_t*>(XMLDoc.c_str()), XMLDoc.size(), &write_count);
650 for ( ri = TDesc.ResourceList.begin() ; ri != TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ )
652 result = Reader.ReadAncillaryResource(ri->ResourceID, FrameBuffer, Context, HMAC);
654 if ( ASDCP_SUCCESS(result) && ( ! Options.no_write_flag ) )
656 Kumu::FileWriter Writer;
657 if (out_path != "") {
658 result = Writer.OpenWrite(Kumu::PathJoin(out_path, Kumu::UUID(ri->ResourceID).EncodeHex(buf, 64)).c_str());
660 // Workaround for a bug in Kumu::PathJoin
661 result = Writer.OpenWrite(Kumu::UUID(ri->ResourceID).EncodeHex(buf, 64));
664 if ( ASDCP_SUCCESS(result) )
665 result = Writer.Write(FrameBuffer.RoData(), FrameBuffer.Size(), &write_count);
667 if ( Options.verbose_flag )
668 FrameBuffer.Dump(stderr, Options.fb_dump_size);
677 read_isxd_file(CommandOptions& Options)
679 AESDecContext* Context = 0;
680 HMACContext* HMAC = 0;
681 AS_02::ISXD::MXFReader Reader;
682 ASDCP::FrameBuffer FrameBuffer;
683 ui32_t frame_count = 0;
685 Result_t result = Reader.OpenRead(Options.input_filename);
687 if ( ASDCP_SUCCESS(result) )
689 result = FrameBuffer.Capacity(Options.fb_size);
692 if ( ASDCP_SUCCESS(result) )
694 std::list<MXF::InterchangeObject*> object_list;
695 Reader.OP1aHeader().GetMDObjectsByType(DefaultSMPTEDict().ul(MDD_GenericStreamTextBasedSet), object_list);
697 std::list<MXF::InterchangeObject*>::iterator i;
698 for ( i = object_list.begin(); i != object_list.end(); ++i )
700 MXF::GenericStreamTextBasedSet *text_object = dynamic_cast<MXF::GenericStreamTextBasedSet*>(*i);
702 text_object->Dump(stderr);
706 if ( ASDCP_SUCCESS(result) && Options.key_flag )
708 Context = new AESDecContext;
709 result = Context->InitKey(Options.key_value);
711 if ( ASDCP_SUCCESS(result) && Options.read_hmac )
714 Reader.FillWriterInfo(Info);
718 HMAC = new HMACContext;
719 result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
723 fputs("File does not contain HMAC values, ignoring -m option.\n", stderr);
728 ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count);
729 if ( last_frame > frame_count )
730 last_frame = frame_count;
732 char name_format[64];
733 snprintf(name_format, 64, "%%s%%0%du.%s", Options.number_width, Options.extension);
735 for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ )
737 result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);
739 if ( ASDCP_SUCCESS(result) )
741 if ( ! Options.no_write_flag )
743 Kumu::FileWriter OutFile;
746 snprintf(filename, 256, name_format, Options.file_prefix, i);
747 result = OutFile.OpenWrite(filename);
749 if ( ASDCP_SUCCESS(result) )
750 result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);
759 extract_generic_stream_partition_payload(const std::string& in_filename, const ui32_t sid, const std::string& out_filename)
761 ASDCP::FrameBuffer payload;
762 AS_02::ISXD::MXFReader reader;
764 Result_t result = reader.OpenRead(in_filename);
766 if ( KM_SUCCESS(result) )
768 result = reader.ReadGenericStreamPartitionPayload(sid, payload);
771 if ( KM_SUCCESS(result) )
773 Kumu::FileWriter writer;
774 ui32_t write_count = 0;
775 result = writer.OpenWrite(out_filename);
777 if ( KM_SUCCESS(result) )
779 result = writer.Write(payload.RoData(), payload.Size(), &write_count);
789 main(int argc, const char** argv)
791 CommandOptions Options(argc, argv);
793 if ( Options.version_flag )
796 if ( Options.help_flag )
799 if ( Options.version_flag || Options.help_flag )
802 if ( Options.error_flag )
804 fprintf(stderr, "There was a problem. Type %s -h for help.\n", PROGRAM_NAME);
808 EssenceType_t EssenceType;
809 Result_t result = ASDCP::EssenceType(Options.input_filename, EssenceType);
811 if ( ASDCP_SUCCESS(result) )
813 switch ( EssenceType )
815 case ESS_AS02_JPEG_2000:
816 result = read_JP2K_file(Options);
819 case ESS_AS02_PCM_24b_48k:
820 case ESS_AS02_PCM_24b_96k:
821 result = read_PCM_file(Options);
824 case ESS_AS02_TIMED_TEXT:
825 result = read_timed_text_file(Options);
829 if ( Options.g_stream_sid == 0 )
831 result = read_isxd_file(Options);
835 result = extract_generic_stream_partition_payload(Options.input_filename,
836 Options.g_stream_sid,
837 Options.file_prefix);
842 fprintf(stderr, "%s: Unknown file type (%d), not AS-02 essence.\n", Options.input_filename, EssenceType);
847 if ( ASDCP_FAILURE(result) )
849 fputs("Program stopped on error.\n", stderr);
851 if ( result != RESULT_FAIL )
853 fputs(result, stderr);
865 // end as-02-unwrap.cpp