/*
-Copyright (c) 2003-2008, John Hurst
+Copyright (c) 2003-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
};
} // namespace MPEG2
+ //---------------------------------------------------------------------------------
//
namespace PCM
{
+ // The channel format will normally be CF_NONE. Unless you have read and understand
+ // SMPTE 429-2-2009 Annex A you should leave it as-is. If you want to label your channel
+ // format and it is one of the fomats given in 429-2, select the appropriate value
+ // from this enum and use it in the ChannelFormat element of the AudioDescriptor struct.
+ //
+ enum ChannelFormat_t {
+ CF_NONE,
+ CF_CFG_1, // 5.1 with optional HI/VI
+ CF_CFG_2, // 6.1 (5.1 + center surround) with optional HI/VI
+ CF_CFG_3, // 7.1 with optional HI/VI
+ };
+
struct AudioDescriptor
{
Rational SampleRate; // rate of frame wrapping
ui32_t AvgBps; //
ui32_t LinkedTrackID; //
ui32_t ContainerDuration; // number of frames
+ ChannelFormat_t ChannelFormat; // audio channel arrangement
};
// Print AudioDescriptor to std::ostream
};
} // namespace PCM
+ //---------------------------------------------------------------------------------
//
namespace JP2K
{
};
} // namespace JP2K
+ //---------------------------------------------------------------------------------
//
namespace TimedText
{
/*
-Copyright (c) 2004-2008, John Hurst
+Copyright (c) 2004-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
static std::string PCM_PACKAGE_LABEL = "File Package: SMPTE 382M frame wrapping of wave audio";
static std::string SOUND_DEF_LABEL = "Sound Track";
+static byte_t SNDFMT_CFG_1_UL[16] = { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0b,
+ 0x04, 0x02, 0x02, 0x10, 0x03, 0x01, 0x01, 0x00 };
+
+static byte_t SNDFMT_CFG_2_UL[16] = { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0b,
+ 0x04, 0x02, 0x02, 0x10, 0x03, 0x01, 0x02, 0x00 };
+
+static byte_t SNDFMT_CFG_3_UL[16] = { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0b,
+ 0x04, 0x02, 0x02, 0x10, 0x03, 0x01, 0x03, 0x00 };
+
//
Result_t
PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, MXF::WaveAudioDescriptor* ADescObj)
ADescObj->AvgBps = ADesc.AvgBps;
ADescObj->LinkedTrackID = ADesc.LinkedTrackID;
ADescObj->ContainerDuration = ADesc.ContainerDuration;
+
+ ADescObj->ChannelAssignment.Reset();
+
+ switch ( ADesc.ChannelFormat )
+ {
+ case PCM::CF_CFG_1:
+ ADescObj->ChannelAssignment = UL(SNDFMT_CFG_1_UL);
+ break;
+
+ case PCM::CF_CFG_2:
+ ADescObj->ChannelAssignment = UL(SNDFMT_CFG_2_UL);
+ break;
+
+ case PCM::CF_CFG_3:
+ ADescObj->ChannelAssignment = UL(SNDFMT_CFG_3_UL);
+ break;
+ }
+
return RESULT_OK;
}
ADesc.LinkedTrackID = ADescObj->LinkedTrackID;
assert(ADescObj->ContainerDuration <= 0xFFFFFFFFL);
ADesc.ContainerDuration = (ui32_t) ADescObj->ContainerDuration;
+
+ ADesc.ChannelFormat = PCM::CF_NONE;
+
+ if ( ADescObj->ChannelAssignment.HasValue() )
+ {
+ if ( ADescObj->ChannelAssignment == UL(SNDFMT_CFG_1_UL) )
+ ADesc.ChannelFormat = PCM::CF_CFG_1;
+
+ else if ( ADescObj->ChannelAssignment == UL(SNDFMT_CFG_2_UL) )
+ ADesc.ChannelFormat = PCM::CF_CFG_2;
+
+ else if ( ADescObj->ChannelAssignment == UL(SNDFMT_CFG_3_UL) )
+ ADesc.ChannelFormat = PCM::CF_CFG_3;
+ }
+
return RESULT_OK;
}
/*
-Copyright (c) 2004-2008, John Hurst
+Copyright (c) 2004-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
const Result_t RESULT_ENDOFFILE (-17, "Attempt to read past end of file.");
const Result_t RESULT_FILEEXISTS (-18, "Filename already exists.");
const Result_t RESULT_NOTAFILE (-19, "Filename not found.");
+ const Result_t RESULT_UNKNOWN (-20, "Unknown result code.");
} // namespace Kumu
//--------------------------------------------------------------------------------
Kumu::TAI::tai::operator=(const Kumu::TAI::caltime& rhs)
{
caltime_tai(&rhs, this);
+ return *this;
}
//
Kumu::TAI::caltime::operator=(const Kumu::TAI::tai& rhs)
{
caltime_utc(this, &rhs);
+ return *this;
}
/*
-Copyright (c) 2005-2006, John Hurst
+Copyright (c) 2005-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
#include <map>
#include <string>
+#define CONFIG_RANDOM_UUID
+
const char*
Kumu::Version()
{
return *s_ResultMap[i].result;
}
- DefaultLogSink().Error("Unknown result code: %ld\n", v);
- return RESULT_FAIL;
+ return RESULT_UNKNOWN;
}
//
return 0;
}
+#ifdef CONFIG_RANDOM_UUID
+
+// convert a memory region to a NULL-terminated hexadecimal string
+//
+static const char*
+bin2hex_rand(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len)
+{
+ if ( bin_buf == 0
+ || str_buf == 0
+ || ((bin_len * 2) + 1) > str_len )
+ return 0;
+
+ char* p = str_buf;
+ Kumu::mem_ptr<byte_t> rand_buf = new byte_t[bin_len];
+ Kumu::FortunaRNG RNG;
+ RNG.FillRandom(rand_buf, bin_len);
+
+ for ( ui32_t i = 0; i < bin_len; i++ )
+ {
+ *p = (bin_buf[i] >> 4) & 0x0f;
+ *p += *p < 10 ? 0x30 : (( ((rand_buf[i] & 0x01) == 0) ? 0x61 : 0x41 ) - 10);
+ p++;
+
+ *p = bin_buf[i] & 0x0f;
+ *p += *p < 10 ? 0x30 : (( (((rand_buf[i] >> 1) & 0x01) == 0) ? 0x61 : 0x41 ) - 10);
+ p++;
+ }
+
+ *p = '\0';
+ return str_buf;
+}
+#endif
// convert a memory region to a NULL-terminated hexadecimal string
//
|| ((bin_len * 2) + 1) > str_len )
return 0;
+#ifdef CONFIG_RANDOM_UUID
+ const char* use_random_uuid = getenv("KM_USE_RANDOM_UUID");
+ if ( use_random_uuid != 0 && use_random_uuid[0] != 0 && use_random_uuid[0] != '0' )
+ return bin2hex_rand(bin_buf, bin_len, str_buf, str_len);
+#endif
+
char* p = str_buf;
for ( ui32_t i = 0; i < bin_len; i++ )
/*
-Copyright (c) 2006, John Hurst
+Copyright (c) 2006-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
{ { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x0c, // 269
0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x63, 0x00 },
{0}, false, "StereoscopicPictureSubDescriptor" },
+ { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x07, // 270
+ 0x04, 0x02, 0x01, 0x01, 0x05, 0x00, 0x00, 0x00 },
+ {0x3d, 0x32}, true, "WaveAudioDescriptor_ChannelAssignment" },
{ {0}, {0}, false, 0 }
};
/*
-Copyright (c) 2006, John Hurst
+Copyright (c) 2006-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
MDD_DMSegment_Duration, // 267
MDD_DMSegment_TrackIDList, // 268
MDD_StereoscopicPictureSubDescriptor, // 269
+ MDD_WaveAudioDescriptor_ChannelAssignment, // 270
MDD_Max,
}; // enum MDD_t
} // namespaceASDCP
/*
-Copyright (c) 2005-2007, John Hurst
+Copyright (c) 2005-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi16(OBJ_READ_ARGS(WaveAudioDescriptor, BlockAlign));
if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi8(OBJ_READ_ARGS(WaveAudioDescriptor, SequenceOffset));
if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(WaveAudioDescriptor, AvgBps));
+ if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(WaveAudioDescriptor, ChannelAssignment));
return result;
}
if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi16(OBJ_WRITE_ARGS(WaveAudioDescriptor, BlockAlign));
if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi8(OBJ_WRITE_ARGS(WaveAudioDescriptor, SequenceOffset));
if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(WaveAudioDescriptor, AvgBps));
+ if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(WaveAudioDescriptor, ChannelAssignment));
return result;
}
fprintf(stream, " %22s = %d\n", "BlockAlign", BlockAlign);
fprintf(stream, " %22s = %d\n", "SequenceOffset", SequenceOffset);
fprintf(stream, " %22s = %d\n", "AvgBps", AvgBps);
+ fprintf(stream, " %22s = %s\n", "ChannelAssignment", ChannelAssignment.EncodeString(identbuf, IdentBufferLen));
}
//
/*
-Copyright (c) 2005-2007, John Hurst
+Copyright (c) 2005-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
ui16_t BlockAlign;
ui8_t SequenceOffset;
ui32_t AvgBps;
+ UL ChannelAssignment;
WaveAudioDescriptor() : BlockAlign(0), SequenceOffset(0), AvgBps(0) {}
virtual ~WaveAudioDescriptor() {}
/*
-Copyright (c) 2004-2006, John Hurst
+Copyright (c) 2004-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
m_FrameBufferSize = ASDCP::PCM::CalcFrameBufferSize(m_ADesc);
m_DataLength = WavHeader.data_len;
m_ADesc.ContainerDuration = m_DataLength / m_FrameBufferSize;
+ m_ADesc.ChannelFormat = PCM::CF_NONE;
Reset();
}
else
m_FrameBufferSize = ASDCP::PCM::CalcFrameBufferSize(m_ADesc);
m_DataLength = AIFFHeader.data_len;
m_ADesc.ContainerDuration = m_DataLength / m_FrameBufferSize;
+ m_ADesc.ChannelFormat = PCM::CF_NONE;
Reset();
}
}
/*
-Copyright (c) 2005-2006, John Hurst
+Copyright (c) 2005-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
ADesc.QuantizationBits = bitspersample;
ui32_t FrameBufferSize = ASDCP::PCM::CalcFrameBufferSize(ADesc);
ADesc.ContainerDuration = data_len / FrameBufferSize;
+ ADesc.ChannelFormat = PCM::CF_NONE;
}
ADesc.AvgBps = (ui32_t) (ADesc.BlockAlign * ADesc.AudioSamplingRate.Quotient());
ui32_t FrameBufferSize = ASDCP::PCM::CalcFrameBufferSize(ADesc);
ADesc.ContainerDuration = data_len / FrameBufferSize;
+ ADesc.ChannelFormat = PCM::CF_NONE;
}
//
/*
-Copyright (c) 2003-2008, John Hurst
+Copyright (c) 2003-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
{
fprintf(stream, "\
USAGE: %s -c <output-file> [-3] [-b <buffer-size>] [-d <duration>] [-e|-E]\n\
- [-f <start-frame>] [-j <key-id-string>] [-k <key-string>] [-L] [-M]\n\
- [-p <frame-rate>] [-R] [-s <num>] [-v] [-W]\n\
+ [-f <start-frame>] [-j <key-id-string>] [-k <key-string>] [-l <label>]\n\
+ [-L] [-M] [-p <frame-rate>] [-R] [-s <num>] [-v] [-W]\n\
<input-file> [<input-file-2> ...]\n\
\n\
%s [-h|-help] [-V]\n\
Defaults to 4,194,304 (4MB)\n\
-d <duration> - Number of frames to process, default all\n\
-f <start-frame> - Starting frame number, default 0\n\
+ -l <label> - Use given channel format label when writing MXF sound\n\
+ files. SMPTE 429-2 labels: '5.1', '6.1', '7.1'. Default\n\
+ is no label (valid for Interop only).\n\
-L - Write SMPTE UL values instead of MXF Interop\n\
-p <rate> - fps of picture when wrapping PCM or JP2K:\n\
Use one of [23|24|48], 24 is default\n\
MMT_UL_LIST,
};
+//
+PCM::ChannelFormat_t
+decode_channel_fmt(const std::string& label_name)
+{
+ if ( label_name == "5.1" )
+ return PCM::CF_CFG_1;
+
+ else if ( label_name == "6.1" )
+ return PCM::CF_CFG_2;
+
+ else if ( label_name == "7.1" )
+ return PCM::CF_CFG_3;
+
+ fprintf(stderr, "Error decoding channel format string: %s\n", label_name.c_str());
+ fprintf(stderr, "Expecting '5.1', '6.1', or '7.1'\n");
+ return PCM::CF_NONE;
+}
//
//
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)
const char* filenames[MAX_IN_FILES]; // list of filenames to be processed
+ PCM::ChannelFormat_t channel_fmt; // audio channel arrangement
//
Rational PictureRate()
no_write_flag(false), version_flag(false), help_flag(false), stereo_image_flag(false),
number_width(6), start_frame(0),
duration(0xffffffff), duration_flag(false), do_repeat(false), use_smpte_labels(false),
- picture_rate(24), fb_size(FRAME_BUFFER_SIZE), file_count(0), file_root(0), out_file(0)
+ picture_rate(24), fb_size(FRAME_BUFFER_SIZE), file_count(0), file_root(0), out_file(0),
+ channel_fmt(PCM::CF_NONE)
{
memset(key_value, 0, KeyLen);
memset(key_id_value, 0, UUIDlen);
}
break;
+ case 'l':
+ TEST_EXTRA_ARG(i, 'l');
+ channel_fmt = decode_channel_fmt(argv[i]);
+ break;
case 'L': use_smpte_labels = true; break;
case 'M': write_hmac = false; break;
ADesc.SampleRate = PictureRate;
FrameBuffer.Capacity(PCM::CalcFrameBufferSize(ADesc));
+ ADesc.ChannelFormat = Options.channel_fmt;
+
+ if ( Options.use_smpte_labels && ADesc.ChannelFormat == PCM::CF_NONE)
+ {
+ fprintf(stderr, "ATTENTION! Writing SMPTE audio without ChannelAssignment property (see option -l)\n");
+ }
if ( Options.verbose_flag )
{