diff options
| author | jhurst <jhurst@cinecert.com> | 2009-02-13 05:00:31 +0000 |
|---|---|---|
| committer | jhurst <> | 2009-02-13 05:00:31 +0000 |
| commit | eba0b92c6ce46a626f46c0843a88ab33d6b281af (patch) | |
| tree | 6a3fe4fdcfa5efa6a556e402c3563de0f389fd84 | |
| parent | 899b377902acf3fb31fe8a2c027e204809067ecb (diff) | |
channel assignment
| -rwxr-xr-x | src/AS_DCP.h | 18 | ||||
| -rwxr-xr-x | src/AS_DCP_PCM.cpp | 44 | ||||
| -rwxr-xr-x | src/KM_error.h | 3 | ||||
| -rw-r--r-- | src/KM_tai.cpp | 2 | ||||
| -rwxr-xr-x | src/KM_util.cpp | 45 | ||||
| -rw-r--r-- | src/MDD.cpp | 5 | ||||
| -rwxr-xr-x | src/MDD.h | 3 | ||||
| -rwxr-xr-x | src/Metadata.cpp | 5 | ||||
| -rwxr-xr-x | src/Metadata.h | 3 | ||||
| -rwxr-xr-x | src/PCM_Parser.cpp | 4 | ||||
| -rwxr-xr-x | src/Wav.cpp | 4 | ||||
| -rwxr-xr-x | src/asdcp-test.cpp | 40 |
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 } }; @@ -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 ) { |
