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 assert (tmp_size <= 0xFFFFFFFFL);
92 m_ValueLength = (ui32_t) tmp_size;
93 m_KLLength = SMPTE_UL_LENGTH + Kumu::BER_length(buf + SMPTE_UL_LENGTH);
95 m_ValueStart = buf + m_KLLength;
101 ASDCP::KLVPacket::HasUL(const byte_t* ul)
103 if ( m_KeyStart == 0 )
106 return ( memcmp(ul, m_KeyStart, SMPTE_UL_LENGTH) == 0 ) ? true : false;
111 ASDCP::KLVPacket::WriteKLToBuffer(ASDCP::FrameBuffer& Buffer, const byte_t* label, ui32_t length)
113 if ( Buffer.Size() + kl_length > Buffer.Capacity() )
115 DefaultLogSink().Error("Small write buffer\n");
119 memcpy(Buffer.Data() + Buffer.Size(), label, SMPTE_UL_LENGTH);
121 if ( ! Kumu::write_BER(Buffer.Data() + Buffer.Size() + SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
124 Buffer.Size(Buffer.Size() + kl_length);
130 ASDCP::KLVPacket::Dump(FILE* stream, bool show_hex)
135 if ( m_KeyStart != 0 )
137 assert(m_ValueStart);
138 UL TmpUL(m_KeyStart);
140 fprintf(stream, "%s", TmpUL.EncodeString(buf, 64));
142 const MDDEntry* Entry = Dict::FindUL(m_KeyStart);
143 fprintf(stream, " len: %7u (%s)\n", m_ValueLength, (Entry ? Entry->name : "Unknown"));
145 if ( show_hex && m_ValueLength < 1000 )
146 Kumu::hexdump(m_ValueStart, Kumu::xmin(m_ValueLength, (ui32_t)64), stream);
150 fprintf(stream, "*** Malformed KLV packet ***\n");
156 ASDCP::KLVFilePacket::InitFromFile(const Kumu::FileReader& Reader, const byte_t* label)
158 Result_t result = KLVFilePacket::InitFromFile(Reader);
160 if ( ASDCP_SUCCESS(result) )
161 result = ( memcmp(m_KeyStart, label, SMPTE_UL_LENGTH) == 0 ) ?
162 RESULT_OK : RESULT_FAIL;
167 // TODO: refactor to use InitFromBuffer
169 ASDCP::KLVFilePacket::InitFromFile(const Kumu::FileReader& Reader)
172 byte_t tmp_data[tmp_read_size];
174 m_KeyStart = m_ValueStart = 0;
175 m_KLLength = m_ValueLength = 0;
178 Result_t result = Reader.Read(tmp_data, tmp_read_size, &read_count);
180 if ( ASDCP_FAILURE(result) )
183 if ( read_count < (SMPTE_UL_LENGTH + 1) )
185 DefaultLogSink().Error("Short read of Key and Length got %u\n", read_count);
186 return RESULT_READFAIL;
189 if ( memcmp(tmp_data, SMPTE_UL_START, 4) != 0 )
191 DefaultLogSink().Error("Unexpected UL preamble: %02x.%02x.%02x.%02x\n",
192 tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]);
196 if ( ! Kumu::read_BER(tmp_data + SMPTE_UL_LENGTH, &tmp_size) )
198 DefaultLogSink().Error("BER Length decoding error\n");
202 if ( tmp_size > MAX_KLV_PACKET_LENGTH )
204 Kumu::ui64Printer tmp_size_str(tmp_size);
205 DefaultLogSink().Error("Packet length %s exceeds internal limit\n", tmp_size_str.c_str());
209 ui32_t remainder = 0;
210 ui32_t ber_len = Kumu::BER_length(tmp_data + SMPTE_UL_LENGTH);
211 m_KLLength = SMPTE_UL_LENGTH + ber_len;
212 assert(tmp_size <= 0xFFFFFFFFL);
213 m_ValueLength = (ui32_t) tmp_size;
214 ui32_t packet_length = m_ValueLength + m_KLLength;
216 result = m_Buffer.Capacity(packet_length);
218 if ( ASDCP_FAILURE(result) )
221 m_KeyStart = m_Buffer.Data();
222 m_ValueStart = m_Buffer.Data() + m_KLLength;
223 m_Buffer.Size(packet_length);
225 // is the whole packet in the tmp buf?
226 if ( packet_length <= tmp_read_size )
228 assert(packet_length <= read_count);
229 memcpy(m_Buffer.Data(), tmp_data, packet_length);
231 if ( (remainder = read_count - packet_length) != 0 )
233 DefaultLogSink().Warn("Repositioning pointer for short packet\n");
234 Kumu::fpos_t pos = Reader.Tell();
235 assert(pos > remainder);
236 result = Reader.Seek(pos - remainder);
241 if ( read_count < tmp_read_size )
243 DefaultLogSink().Error("Short read of packet body, expecting %u, got %u\n",
244 m_Buffer.Size(), read_count);
245 return RESULT_READFAIL;
248 memcpy(m_Buffer.Data(), tmp_data, tmp_read_size);
249 remainder = m_Buffer.Size() - tmp_read_size;
253 result = Reader.Read(m_Buffer.Data() + tmp_read_size, remainder, &read_count);
255 if ( read_count != remainder )
257 DefaultLogSink().Error("Short read of packet body, expecting %u, got %u\n",
258 remainder+tmp_read_size, read_count+tmp_read_size);
259 result = RESULT_READFAIL;
269 ASDCP::KLVFilePacket::WriteKLToFile(Kumu::FileWriter& Writer, const byte_t* label, ui32_t length)
271 byte_t buffer[kl_length];
272 memcpy(buffer, label, SMPTE_UL_LENGTH);
274 if ( ! Kumu::write_BER(buffer+SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
278 Writer.Write(buffer, kl_length, &write_count);
279 assert(write_count == kl_length);