summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjhurst <jhurst@cinecert.com>2009-02-13 05:00:31 +0000
committerjhurst <>2009-02-13 05:00:31 +0000
commiteba0b92c6ce46a626f46c0843a88ab33d6b281af (patch)
tree6a3fe4fdcfa5efa6a556e402c3563de0f389fd84
parent899b377902acf3fb31fe8a2c027e204809067ecb (diff)
channel assignment
-rwxr-xr-xsrc/AS_DCP.h18
-rwxr-xr-xsrc/AS_DCP_PCM.cpp44
-rwxr-xr-xsrc/KM_error.h3
-rw-r--r--src/KM_tai.cpp2
-rwxr-xr-xsrc/KM_util.cpp45
-rw-r--r--src/MDD.cpp5
-rwxr-xr-xsrc/MDD.h3
-rwxr-xr-xsrc/Metadata.cpp5
-rwxr-xr-xsrc/Metadata.h3
-rwxr-xr-xsrc/PCM_Parser.cpp4
-rwxr-xr-xsrc/Wav.cpp4
-rwxr-xr-xsrc/asdcp-test.cpp40
12 files changed, 160 insertions, 16 deletions
diff --git a/src/AS_DCP.h b/src/AS_DCP.h
index e1cc261..70367ce 100755
--- a/src/AS_DCP.h
+++ b/src/AS_DCP.h
@@ -1,5 +1,5 @@
/*
-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
@@ -749,9 +749,22 @@ namespace ASDCP {
};
} // 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
@@ -763,6 +776,7 @@ namespace ASDCP {
ui32_t AvgBps; //
ui32_t LinkedTrackID; //
ui32_t ContainerDuration; // number of frames
+ ChannelFormat_t ChannelFormat; // audio channel arrangement
};
// Print AudioDescriptor to std::ostream
@@ -901,6 +915,7 @@ namespace ASDCP {
};
} // namespace PCM
+ //---------------------------------------------------------------------------------
//
namespace JP2K
{
@@ -1229,6 +1244,7 @@ namespace ASDCP {
};
} // namespace JP2K
+ //---------------------------------------------------------------------------------
//
namespace TimedText
{
diff --git a/src/AS_DCP_PCM.cpp b/src/AS_DCP_PCM.cpp
index a50f24b..6cf907e 100755
--- a/src/AS_DCP_PCM.cpp
+++ b/src/AS_DCP_PCM.cpp
@@ -1,5 +1,5 @@
/*
-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
@@ -39,6 +39,15 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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)
@@ -53,6 +62,24 @@ 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;
}
@@ -71,6 +98,21 @@ MD_to_PCM_ADesc(MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc)
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;
}
diff --git a/src/KM_error.h b/src/KM_error.h
index f8b7bde..c17fe76 100755
--- a/src/KM_error.h
+++ b/src/KM_error.h
@@ -1,5 +1,5 @@
/*
-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
@@ -87,6 +87,7 @@ namespace Kumu
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
//--------------------------------------------------------------------------------
diff --git a/src/KM_tai.cpp b/src/KM_tai.cpp
index dca8471..f6cbea5 100644
--- a/src/KM_tai.cpp
+++ b/src/KM_tai.cpp
@@ -193,6 +193,7 @@ const Kumu::TAI::tai&
Kumu::TAI::tai::operator=(const Kumu::TAI::caltime& rhs)
{
caltime_tai(&rhs, this);
+ return *this;
}
//
@@ -200,6 +201,7 @@ const Kumu::TAI::caltime&
Kumu::TAI::caltime::operator=(const Kumu::TAI::tai& rhs)
{
caltime_utc(this, &rhs);
+ return *this;
}
diff --git a/src/KM_util.cpp b/src/KM_util.cpp
index 46dbfa6..43b00a4 100755
--- a/src/KM_util.cpp
+++ b/src/KM_util.cpp
@@ -1,5 +1,5 @@
/*
-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
@@ -40,6 +40,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map>
#include <string>
+#define CONFIG_RANDOM_UUID
+
const char*
Kumu::Version()
{
@@ -75,8 +77,7 @@ Kumu::Result_t::Find(int v)
return *s_ResultMap[i].result;
}
- DefaultLogSink().Error("Unknown result code: %ld\n", v);
- return RESULT_FAIL;
+ return RESULT_UNKNOWN;
}
//
@@ -373,6 +374,38 @@ Kumu::hex2bin(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* conv_size)
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
//
@@ -384,6 +417,12 @@ Kumu::bin2hex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_l
|| ((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++ )
diff --git a/src/MDD.cpp b/src/MDD.cpp
index 73f22c7..da0163f 100644
--- a/src/MDD.cpp
+++ b/src/MDD.cpp
@@ -1,5 +1,5 @@
/*
-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
@@ -845,6 +845,9 @@ static const ASDCP::MDDEntry s_MDD_Table[] = {
{ { 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 }
};
diff --git a/src/MDD.h b/src/MDD.h
index e3145f5..5ec2b23 100755
--- a/src/MDD.h
+++ b/src/MDD.h
@@ -1,5 +1,5 @@
/*
-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
@@ -305,6 +305,7 @@ namespace ASDCP {
MDD_DMSegment_Duration, // 267
MDD_DMSegment_TrackIDList, // 268
MDD_StereoscopicPictureSubDescriptor, // 269
+ MDD_WaveAudioDescriptor_ChannelAssignment, // 270
MDD_Max,
}; // enum MDD_t
} // namespaceASDCP
diff --git a/src/Metadata.cpp b/src/Metadata.cpp
index 838fc53..f509aaa 100755
--- a/src/Metadata.cpp
+++ b/src/Metadata.cpp
@@ -1,5 +1,5 @@
/*
-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
@@ -977,6 +977,7 @@ WaveAudioDescriptor::InitFromTLVSet(TLVReader& TLVSet)
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;
}
@@ -988,6 +989,7 @@ WaveAudioDescriptor::WriteToTLVSet(TLVWriter& TLVSet)
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;
}
@@ -1005,6 +1007,7 @@ WaveAudioDescriptor::Dump(FILE* stream)
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));
}
//
diff --git a/src/Metadata.h b/src/Metadata.h
index 207e031..5117425 100755
--- a/src/Metadata.h
+++ b/src/Metadata.h
@@ -1,5 +1,5 @@
/*
-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
@@ -363,6 +363,7 @@ namespace ASDCP
ui16_t BlockAlign;
ui8_t SequenceOffset;
ui32_t AvgBps;
+ UL ChannelAssignment;
WaveAudioDescriptor() : BlockAlign(0), SequenceOffset(0), AvgBps(0) {}
virtual ~WaveAudioDescriptor() {}
diff --git a/src/PCM_Parser.cpp b/src/PCM_Parser.cpp
index f0caef2..2f96d23 100755
--- a/src/PCM_Parser.cpp
+++ b/src/PCM_Parser.cpp
@@ -1,5 +1,5 @@
/*
-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
@@ -110,6 +110,7 @@ ASDCP::PCM::WAVParser::h__WAVParser::OpenRead(const char* filename, const Ration
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
@@ -125,6 +126,7 @@ ASDCP::PCM::WAVParser::h__WAVParser::OpenRead(const char* filename, const Ration
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();
}
}
diff --git a/src/Wav.cpp b/src/Wav.cpp
index ff063fb..886a183 100755
--- a/src/Wav.cpp
+++ b/src/Wav.cpp
@@ -1,5 +1,5 @@
/*
-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
@@ -65,6 +65,7 @@ ASDCP::Wav::SimpleWaveHeader::FillADesc(ASDCP::PCM::AudioDescriptor& ADesc, ASDC
ADesc.QuantizationBits = bitspersample;
ui32_t FrameBufferSize = ASDCP::PCM::CalcFrameBufferSize(ADesc);
ADesc.ContainerDuration = data_len / FrameBufferSize;
+ ADesc.ChannelFormat = PCM::CF_NONE;
}
@@ -268,6 +269,7 @@ ASDCP::AIFF::SimpleAIFFHeader::FillADesc(ASDCP::PCM::AudioDescriptor& ADesc, ASD
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;
}
//
diff --git a/src/asdcp-test.cpp b/src/asdcp-test.cpp
index 7889974..d957407 100755
--- a/src/asdcp-test.cpp
+++ b/src/asdcp-test.cpp
@@ -1,5 +1,5 @@
/*
-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
@@ -116,8 +116,8 @@ usage(FILE* stream = stdout)
{
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\
@@ -170,6 +170,9 @@ Read/Write Options:\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\
@@ -215,6 +218,23 @@ enum MajorMode_t
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;
+}
//
//
@@ -254,6 +274,7 @@ public:
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()
@@ -279,7 +300,8 @@ public:
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);
@@ -366,6 +388,10 @@ public:
}
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;
@@ -1158,6 +1184,12 @@ write_PCM_file(CommandOptions& Options)
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 )
{