2 Copyright (c) 2005-2006, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 using Kumu::DefaultLogSink;
37 // This is how much we read when we're reading from a file and we don't know
38 // how long the packet is. This gives us the K (16 bytes) and L (4-9 bytes)
39 // and the remaining bytes for an even read (tmp_read_size % 16 == 0)
40 const ui32_t kl_length = ASDCP::SMPTE_UL_LENGTH + ASDCP::MXF_BER_LENGTH;
41 const ui32_t tmp_read_size = 32;
43 //------------------------------------------------------------------------------------------
48 ASDCP::KLVPacket::InitFromBuffer(const byte_t* buf, ui32_t buf_len, const byte_t* label)
50 Result_t result = KLVPacket::InitFromBuffer(buf, buf_len);
52 if ( ASDCP_SUCCESS(result) )
53 result = ( memcmp(m_KeyStart, label, SMPTE_UL_LENGTH) == 0 ) ?
54 RESULT_OK : RESULT_FAIL;
61 ASDCP::KLVPacket::InitFromBuffer(const byte_t* buf, ui32_t buf_len)
63 m_KeyStart = m_ValueStart = 0;
64 m_KLLength = m_ValueLength = 0;
66 if ( memcmp(buf, SMPTE_UL_START, 4) != 0 )
68 DefaultLogSink().Error("Unexpected UL preamble: %02x.%02x.%02x.%02x\n",
69 buf[0], buf[1], buf[2], buf[3]);
73 ui32_t ber_len = Kumu::BER_length(buf + SMPTE_UL_LENGTH);
75 if ( ber_len > ( buf_len - SMPTE_UL_LENGTH ) )
77 DefaultLogSink().Error("BER encoding length exceeds buffer size\n");
83 DefaultLogSink().Error("KLV format error, zero BER length not allowed\n");
88 if ( ! Kumu::read_BER(buf + SMPTE_UL_LENGTH, &tmp_size) )
91 m_ValueLength = tmp_size;
92 m_KLLength = SMPTE_UL_LENGTH + Kumu::BER_length(buf + SMPTE_UL_LENGTH);
94 m_ValueStart = buf + m_KLLength;
100 ASDCP::KLVPacket::HasUL(const byte_t* ul)
102 if ( m_KeyStart == 0 )
105 return ( memcmp(ul, m_KeyStart, SMPTE_UL_LENGTH) == 0 ) ? true : false;
110 ASDCP::KLVPacket::WriteKLToBuffer(ASDCP::FrameBuffer& Buffer, const byte_t* label, ui32_t length)
112 if ( Buffer.Size() + kl_length > Buffer.Capacity() )
114 DefaultLogSink().Error("Small write buffer\n");
118 memcpy(Buffer.Data() + Buffer.Size(), label, SMPTE_UL_LENGTH);
120 if ( ! Kumu::write_BER(Buffer.Data() + Buffer.Size() + SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
123 Buffer.Size(Buffer.Size() + kl_length);
129 ASDCP::KLVPacket::Dump(FILE* stream, bool show_hex)
134 if ( m_KeyStart != 0 )
136 assert(m_ValueStart);
137 UL TmpUL(m_KeyStart);
139 fprintf(stream, "%s", TmpUL.EncodeString(buf, 64));
141 const MDDEntry* Entry = Dict::FindUL(m_KeyStart);
142 fprintf(stream, " len: %7u (%s)\n", m_ValueLength, (Entry ? Entry->name : "Unknown"));
144 if ( show_hex && m_ValueLength < 1000 )
145 Kumu::hexdump(m_ValueStart, Kumu::xmin(m_ValueLength, (ui32_t)64), stream);
149 fprintf(stream, "*** Malformed KLV packet ***\n");
155 ASDCP::KLVFilePacket::InitFromFile(const Kumu::FileReader& Reader, const byte_t* label)
157 Result_t result = KLVFilePacket::InitFromFile(Reader);
159 if ( ASDCP_SUCCESS(result) )
160 result = ( memcmp(m_KeyStart, label, SMPTE_UL_LENGTH) == 0 ) ?
161 RESULT_OK : RESULT_FAIL;
166 // TODO: refactor to use InitFromBuffer
168 ASDCP::KLVFilePacket::InitFromFile(const Kumu::FileReader& Reader)
171 byte_t tmp_data[tmp_read_size];
173 m_KeyStart = m_ValueStart = 0;
174 m_KLLength = m_ValueLength = 0;
177 Result_t result = Reader.Read(tmp_data, tmp_read_size, &read_count);
179 if ( ASDCP_FAILURE(result) )
182 if ( read_count < (SMPTE_UL_LENGTH + 1) )
184 DefaultLogSink().Error("Short read of Key and Length got %u\n", read_count);
185 return RESULT_READFAIL;
188 if ( memcmp(tmp_data, SMPTE_UL_START, 4) != 0 )
190 DefaultLogSink().Error("Unexpected UL preamble: %02x.%02x.%02x.%02x\n",
191 tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]);
195 if ( ! Kumu::read_BER(tmp_data + SMPTE_UL_LENGTH, &tmp_size) )
197 DefaultLogSink().Error("BER Length decoding error\n");
201 if ( tmp_size > MAX_KLV_PACKET_LENGTH )
203 Kumu::ui64Printer tmp_size_str(tmp_size);
204 DefaultLogSink().Error("Packet length %s exceeds internal limit\n", tmp_size_str.c_str());
208 ui32_t remainder = 0;
209 ui32_t ber_len = Kumu::BER_length(tmp_data + SMPTE_UL_LENGTH);
210 m_KLLength = SMPTE_UL_LENGTH + ber_len;
211 m_ValueLength = tmp_size;
212 ui32_t packet_length = m_ValueLength + m_KLLength;
214 result = m_Buffer.Capacity(packet_length);
216 if ( ASDCP_FAILURE(result) )
219 m_KeyStart = m_Buffer.Data();
220 m_ValueStart = m_Buffer.Data() + m_KLLength;
221 m_Buffer.Size(packet_length);
223 // is the whole packet in the tmp buf?
224 if ( packet_length <= tmp_read_size )
226 assert(packet_length <= read_count);
227 memcpy(m_Buffer.Data(), tmp_data, packet_length);
229 if ( (remainder = read_count - packet_length) != 0 )
231 DefaultLogSink().Warn("Repositioning pointer for short packet\n");
232 Kumu::fpos_t pos = Reader.Tell();
233 assert(pos > remainder);
234 result = Reader.Seek(pos - remainder);
239 if ( read_count < tmp_read_size )
241 DefaultLogSink().Error("Short read of packet body, expecting %u, got %u\n",
242 m_Buffer.Size(), read_count);
243 return RESULT_READFAIL;
246 memcpy(m_Buffer.Data(), tmp_data, tmp_read_size);
247 remainder = m_Buffer.Size() - tmp_read_size;
251 result = Reader.Read(m_Buffer.Data() + tmp_read_size, remainder, &read_count);
253 if ( read_count != remainder )
255 DefaultLogSink().Error("Short read of packet body, expecting %u, got %u\n",
256 remainder+tmp_read_size, read_count+tmp_read_size);
257 result = RESULT_READFAIL;
267 ASDCP::KLVFilePacket::WriteKLToFile(Kumu::FileWriter& Writer, const byte_t* label, ui32_t length)
269 byte_t buffer[kl_length];
270 memcpy(buffer, label, SMPTE_UL_LENGTH);
272 if ( ! Kumu::write_BER(buffer+SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
276 Writer.Write(buffer, kl_length, &write_count);
277 assert(write_count == kl_length);