/*
-Copyright (c) 2011-2012, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst
+Copyright (c) 2011-2015, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
+John Hurst
+
All rights reserved.
Redistribution and use in source and binary forms, with or without
#include <AS_02.h>
#include <WavFileWriter.h>
+namespace ASDCP {
+ Result_t MD_to_PCM_ADesc(ASDCP::MXF::WaveAudioDescriptor* ADescObj, ASDCP::PCM::AudioDescriptor& ADesc);
+}
+
using namespace ASDCP;
const ui32_t FRAME_BUFFER_SIZE = 4 * Kumu::Megabyte;
{
fprintf(stream, "\n\
%s (asdcplib %s)\n\n\
-Copyright (c) 2011-2012, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst\n\n\
+Copyright (c) 2011-2015, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst\n\n\
asdcplib may be copied only under the terms of the license found at\n\
the top of every file in the asdcplib distribution kit.\n\n\
Specify the -h (help) option for further information about %s\n\n",
%s [-1|-2] [-b <buffer-size>] [-d <duration>]\n\
[-f <starting-frame>] [-m] [-p <frame-rate>] [-R] [-s <size>] [-v] [-W]\n\
[-w] <input-file> [<file-prefix>]\n\n",
- PROGRAM_NAME, PROGRAM_NAME, PROGRAM_NAME);
+ PROGRAM_NAME, PROGRAM_NAME);
fprintf(stream, "\
Options:\n\
bool j2c_pedantic; // passed to JP2K::SequenceParser::OpenRead
ui32_t picture_rate; // fps of picture when wrapping PCM
ui32_t fb_size; // size of picture frame buffer
+ Rational edit_rate; // frame buffer size for reading clip-wrapped PCM
const char* file_prefix; // filename pre for files written by the extract mode
byte_t key_value[KeyLen]; // value of given encryption key (when key_flag is true)
byte_t key_id_value[UUIDlen];// value of given key ID (when key_id_flag is true)
case 'b':
TEST_EXTRA_ARG(i, 'b');
- fb_size = abs(atoi(argv[i]));
+ fb_size = Kumu::xabs(strtol(argv[i], 0, 10));
if ( verbose_flag )
fprintf(stderr, "Frame Buffer size: %u bytes.\n", fb_size);
case 'd':
TEST_EXTRA_ARG(i, 'd');
duration_flag = true;
- duration = abs(atoi(argv[i]));
+ duration = Kumu::xabs(strtol(argv[i], 0, 10));
break;
case 'f':
TEST_EXTRA_ARG(i, 'f');
- start_frame = abs(atoi(argv[i]));
+ start_frame = Kumu::xabs(strtol(argv[i], 0, 10));
break;
case 'h': help_flag = true; break;
case 'p':
TEST_EXTRA_ARG(i, 'p');
- picture_rate = abs(atoi(argv[i]));
+ picture_rate = Kumu::xabs(strtol(argv[i], 0, 10));
break;
case 's':
TEST_EXTRA_ARG(i, 's');
- fb_dump_size = abs(atoi(argv[i]));
+ fb_dump_size = Kumu::xabs(strtol(argv[i], 0, 10));
break;
case 'V': version_flag = true; break;
case 'w':
TEST_EXTRA_ARG(i, 'w');
- number_width = abs(atoi(argv[i]));
+ number_width = Kumu::xabs(strtol(argv[i], 0, 10));
break;
case 'Z': j2c_pedantic = false; break;
{
AESDecContext* Context = 0;
HMACContext* HMAC = 0;
- JP2K::MXFReader Reader;
+ AS_02::JP2K::MXFReader Reader;
JP2K::FrameBuffer FrameBuffer(Options.fb_size);
ui32_t frame_count = 0;
if ( ASDCP_SUCCESS(result) )
{
- JP2K::PictureDescriptor PDesc;
- Reader.FillPictureDescriptor(PDesc);
-
- frame_count = PDesc.ContainerDuration;
-
if ( Options.verbose_flag )
{
fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
- JP2K::PictureDescriptorDump(PDesc);
+ }
+
+ ASDCP::MXF::RGBAEssenceDescriptor *rgba_descriptor = 0;
+ ASDCP::MXF::CDCIEssenceDescriptor *cdci_descriptor = 0;
+
+ result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_RGBAEssenceDescriptor),
+ reinterpret_cast<MXF::InterchangeObject**>(&rgba_descriptor));
+
+ if ( KM_SUCCESS(result) )
+ {
+ assert(rgba_descriptor);
+ frame_count = rgba_descriptor->ContainerDuration;
+
+ if ( Options.verbose_flag )
+ {
+ rgba_descriptor->Dump();
+ }
+ }
+ else
+ {
+ result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_CDCIEssenceDescriptor),
+ reinterpret_cast<MXF::InterchangeObject**>(&cdci_descriptor));
+
+ if ( KM_SUCCESS(result) )
+ {
+ assert(cdci_descriptor);
+ frame_count = cdci_descriptor->ContainerDuration;
+
+ if ( Options.verbose_flag )
+ {
+ cdci_descriptor->Dump();
+ }
+ }
+ else
+ {
+ fprintf(stderr, "File does not contain an essence descriptor.\n");
+ frame_count = Reader.AS02IndexReader().GetDuration();
+ }
+ }
+
+ if ( frame_count == 0 )
+ {
+ frame_count = Reader.AS02IndexReader().GetDuration();
+ }
+
+ if ( frame_count == 0 )
+ {
+ fprintf(stderr, "Unable to determine file duration.\n");
+ return RESULT_FAIL;
}
}
{
result = Reader.ReadFrame(i, FrameBuffer, Context, HMAC);
- if ( ASDCP_SUCCESS(result) )
+ char filename[1024];
+ snprintf(filename, 1024, name_format, Options.file_prefix, i);
+
+ if ( ASDCP_SUCCESS(result) && Options.verbose_flag )
+ {
+ printf("Frame %d, %d bytes", i, FrameBuffer.Size());
+
+ if ( ! Options.no_write_flag )
+ {
+ printf(" -> %s", filename);
+ }
+
+ printf("\n");
+ }
+
+ if ( ASDCP_SUCCESS(result) && ( ! Options.no_write_flag ) )
{
Kumu::FileWriter OutFile;
- char filename[256];
ui32_t write_count;
- snprintf(filename, 256, name_format, Options.file_prefix, i);
result = OutFile.OpenWrite(filename);
if ( ASDCP_SUCCESS(result) )
result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);
- if ( Options.verbose_flag )
- FrameBuffer.Dump(stderr, Options.fb_dump_size);
+ if ( ASDCP_SUCCESS(result) && Options.verbose_flag )
+ {
+ FrameBuffer.Dump(stderr, Options.fb_dump_size);
+ }
}
}
{
AESDecContext* Context = 0;
HMACContext* HMAC = 0;
- PCM::MXFReader Reader;
+ AS_02::PCM::MXFReader Reader;
PCM::FrameBuffer FrameBuffer;
WavFileWriter OutWave;
- PCM::AudioDescriptor ADesc;
ui32_t last_frame = 0;
+ ASDCP::MXF::WaveAudioDescriptor *wave_descriptor = 0;
- Result_t result = Reader.OpenRead(Options.input_filename);
-
- if ( ASDCP_SUCCESS(result) )
+ if ( Options.edit_rate == Rational(0,0) ) // todo, make this available to the CLI
{
- Reader.FillAudioDescriptor(ADesc);
- ADesc.EditRate = Rational(1, 1);
- FrameBuffer.Capacity(PCM::CalcFrameBufferSize(ADesc));
+ Options.edit_rate = EditRate_24;
+ }
+ Result_t result = Reader.OpenRead(Options.input_filename, Options.edit_rate);
+
+ if ( KM_SUCCESS(result) )
+ {
if ( Options.verbose_flag )
- PCM::AudioDescriptorDump(ADesc);
+ {
+ fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size);
+ }
+
+ ASDCP::MXF::InterchangeObject* tmp_obj = 0;
+
+ result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_WaveAudioDescriptor), &tmp_obj);
+
+ if ( KM_SUCCESS(result) )
+ {
+ wave_descriptor = dynamic_cast<ASDCP::MXF::WaveAudioDescriptor*>(tmp_obj);
+
+ if ( wave_descriptor == 0 )
+ {
+ fprintf(stderr, "File does not contain an essence descriptor.\n");
+ return RESULT_FAIL;
+ }
+
+ if ( Options.verbose_flag )
+ {
+ wave_descriptor->Dump();
+ }
+
+ if ( wave_descriptor->ContainerDuration.get() == 0 )
+ {
+ fprintf(stderr, "ContainerDuration not set in file descriptor, attempting to use index duration.\n");
+ last_frame = Reader.AS02IndexReader().GetDuration();
+ }
+ else
+ {
+ last_frame = wave_descriptor->ContainerDuration;
+ }
+
+ if ( last_frame == 0 )
+ {
+ fprintf(stderr, "ContainerDuration not set in index, attempting to use Duration from SourceClip.\n");
+ result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_SourceClip), &tmp_obj);
+ if ( KM_SUCCESS(result))
+ {
+ ASDCP::MXF::SourceClip *sourceClip = dynamic_cast<ASDCP::MXF::SourceClip*>(tmp_obj);
+ if ( ! sourceClip->Duration.empty() )
+ {
+ last_frame = sourceClip->Duration;
+ }
+ }
+ }
+
+ if ( last_frame == 0 )
+ {
+ fprintf(stderr, "Unable to determine file duration.\n");
+ return RESULT_FAIL;
+ }
+
+ assert(wave_descriptor);
+ FrameBuffer.Capacity(AS_02::MXF::CalcFrameBufferSize(*wave_descriptor, Options.edit_rate));
+ last_frame = AS_02::MXF::CalcFramesFromDurationInSamples(last_frame, *wave_descriptor, Options.edit_rate);
+ }
}
if ( ASDCP_SUCCESS(result) )
{
- last_frame = ADesc.ContainerDuration;
-
if ( Options.duration > 0 && Options.duration < last_frame )
last_frame = Options.duration;
if ( Options.start_frame > 0 )
{
- if ( Options.start_frame > ADesc.ContainerDuration )
+ if ( Options.start_frame > last_frame )
{
fprintf(stderr, "Start value greater than file duration.\n");
return RESULT_FAIL;
}
- last_frame = Kumu::xmin(Options.start_frame + last_frame, ADesc.ContainerDuration);
+ last_frame = Kumu::xmin(Options.start_frame + last_frame, last_frame);
}
- ADesc.ContainerDuration = last_frame - Options.start_frame;
- OutWave.OpenWrite(ADesc, Options.file_prefix,
- ( Options.split_wav ? WavFileWriter::ST_STEREO :
- ( Options.mono_wav ? WavFileWriter::ST_MONO : WavFileWriter::ST_NONE ) ));
+ last_frame = last_frame - Options.start_frame;
+
+ PCM::AudioDescriptor ADesc;
+
+ result = MD_to_PCM_ADesc(wave_descriptor, ADesc);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ADesc.ContainerDuration = last_frame;
+ ADesc.EditRate = Options.edit_rate;
+
+ result = OutWave.OpenWrite(ADesc, Options.file_prefix,
+ ( Options.split_wav ? WavFileWriter::ST_STEREO :
+ ( Options.mono_wav ? WavFileWriter::ST_MONO : WavFileWriter::ST_NONE ) ));
+ }
}
if ( ASDCP_SUCCESS(result) && Options.key_flag )
if ( ASDCP_SUCCESS(result) )
{
if ( Options.verbose_flag )
- FrameBuffer.Dump(stderr, Options.fb_dump_size);
+ {
+ FrameBuffer.FrameNumber(i);
+ FrameBuffer.Dump(stderr, Options.fb_dump_size);
+ }
+
+ if ( FrameBuffer.Size() != FrameBuffer.Capacity() )
+ {
+ fprintf(stderr, "Last frame is incomplete, padding with zeros.\n");
+ // actually, it has already been zeroed for us, we just need to recognize the appropriate size
+ FrameBuffer.Size(FrameBuffer.Capacity());
+ }
result = OutWave.WriteFrame(FrameBuffer);
}
{
switch ( EssenceType )
{
- case ESS_JPEG_2000:
+ case ESS_AS02_JPEG_2000:
result = read_JP2K_file(Options);
break;
- case ESS_PCM_24b_48k:
- case ESS_PCM_24b_96k:
+ case ESS_AS02_PCM_24b_48k:
+ case ESS_AS02_PCM_24b_96k:
result = read_PCM_file(Options);
break;
default:
- fprintf(stderr, "%s: Unknown file type, not ASDCP essence.\n", Options.input_filename);
+ fprintf(stderr, "%s: Unknown file type, not AS-02 essence.\n", Options.input_filename);
return 5;
}
}
{
fputs("Program stopped on error.\n", stderr);
- if ( result == RESULT_SFORMAT )
- {
- fputs("Use option '-3' to force stereoscopic mode.\n", stderr);
- }
- else if ( result != RESULT_FAIL )
+ if ( result != RESULT_FAIL )
{
fputs(result, stderr);
fputc('\n', stderr);