2 Copyright (c) 2005-2009, 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 UL& label)
50 Result_t result = KLVPacket::InitFromBuffer(buf, buf_len);
52 if ( ASDCP_SUCCESS(result) )
53 result = ( UL(m_KeyStart) == label ) ? RESULT_OK : RESULT_FAIL;
60 ASDCP::KLVPacket::GetUL() {
61 return UL(m_KeyStart);
66 ASDCP::KLVPacket::InitFromBuffer(const byte_t* buf, ui32_t buf_len)
68 m_KeyStart = m_ValueStart = 0;
69 m_KLLength = m_ValueLength = 0;
71 if ( memcmp(buf, SMPTE_UL_START, 4) != 0 )
73 DefaultLogSink().Error("Unexpected UL preamble: %02x.%02x.%02x.%02x\n",
74 buf[0], buf[1], buf[2], buf[3]);
78 ui32_t ber_len = Kumu::BER_length(buf + SMPTE_UL_LENGTH);
80 if ( ber_len > ( buf_len - SMPTE_UL_LENGTH ) )
82 DefaultLogSink().Error("BER encoding length exceeds buffer size\n");
88 DefaultLogSink().Error("KLV format error, zero BER length not allowed\n");
93 if ( ! Kumu::read_BER(buf + SMPTE_UL_LENGTH, &tmp_size) )
96 assert (tmp_size <= 0xFFFFFFFFL);
97 m_ValueLength = (ui32_t) tmp_size;
98 m_KLLength = SMPTE_UL_LENGTH + Kumu::BER_length(buf + SMPTE_UL_LENGTH);
100 m_ValueStart = buf + m_KLLength;
106 ASDCP::KLVPacket::HasUL(const byte_t* ul)
108 if ( m_KeyStart == 0 )
111 return ( memcmp(ul, m_KeyStart, SMPTE_UL_LENGTH) == 0 ) ? true : false;
116 ASDCP::KLVPacket::WriteKLToBuffer(ASDCP::FrameBuffer& Buffer, const UL& label, ui32_t length)
118 if ( Buffer.Size() + kl_length > Buffer.Capacity() )
120 DefaultLogSink().Error("Small write buffer\n");
124 memcpy(Buffer.Data() + Buffer.Size(), label.Value(), label.Size());
126 if ( ! Kumu::write_BER(Buffer.Data() + Buffer.Size() + SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
129 Buffer.Size(Buffer.Size() + kl_length);
135 ASDCP::KLVPacket::Dump(FILE* stream, const Dictionary& Dict, bool show_value)
140 if ( m_KeyStart != 0 )
142 assert(m_ValueStart);
143 UL TmpUL(m_KeyStart);
145 fprintf(stream, "%s", TmpUL.EncodeString(buf, 64));
147 const MDDEntry* Entry = Dict.FindUL(m_KeyStart);
148 fprintf(stream, " len: %7u (%s)\n", m_ValueLength, (Entry ? Entry->name : "Unknown"));
150 if ( show_value && m_ValueLength < 1000 )
151 Kumu::hexdump(m_ValueStart, Kumu::xmin(m_ValueLength, (ui32_t)128), stream);
155 fprintf(stream, "*** Malformed KLV packet ***\n");
161 ASDCP::KLVFilePacket::InitFromFile(const Kumu::FileReader& Reader, const UL& label)
163 Result_t result = KLVFilePacket::InitFromFile(Reader);
165 if ( ASDCP_SUCCESS(result) )
166 result = ( UL(m_KeyStart) == label ) ? RESULT_OK : RESULT_FAIL;
171 // TODO: refactor to use InitFromBuffer
173 ASDCP::KLVFilePacket::InitFromFile(const Kumu::FileReader& Reader)
176 byte_t tmp_data[tmp_read_size];
178 m_KeyStart = m_ValueStart = 0;
179 m_KLLength = m_ValueLength = 0;
182 Result_t result = Reader.Read(tmp_data, tmp_read_size, &read_count);
184 if ( ASDCP_FAILURE(result) )
187 if ( read_count < (SMPTE_UL_LENGTH + 1) )
189 DefaultLogSink().Error("Short read of Key and Length got %u\n", read_count);
190 return RESULT_READFAIL;
193 if ( memcmp(tmp_data, SMPTE_UL_START, 4) != 0 )
195 DefaultLogSink().Error("Unexpected UL preamble: %02x.%02x.%02x.%02x\n",
196 tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]);
200 if ( ! Kumu::read_BER(tmp_data + SMPTE_UL_LENGTH, &tmp_size) )
202 DefaultLogSink().Error("BER Length decoding error\n");
206 if ( tmp_size > MAX_KLV_PACKET_LENGTH )
208 Kumu::ui64Printer tmp_size_str(tmp_size);
209 DefaultLogSink().Error("Packet length %s exceeds internal limit\n", tmp_size_str.c_str());
213 ui32_t remainder = 0;
214 ui32_t ber_len = Kumu::BER_length(tmp_data + SMPTE_UL_LENGTH);
215 m_KLLength = SMPTE_UL_LENGTH + ber_len;
216 assert(tmp_size <= 0xFFFFFFFFL);
217 m_ValueLength = (ui32_t) tmp_size;
218 ui32_t packet_length = m_ValueLength + m_KLLength;
220 result = m_Buffer.Capacity(packet_length);
222 if ( ASDCP_FAILURE(result) )
225 m_KeyStart = m_Buffer.Data();
226 m_ValueStart = m_Buffer.Data() + m_KLLength;
227 m_Buffer.Size(packet_length);
229 // is the whole packet in the tmp buf?
230 if ( packet_length <= tmp_read_size )
232 assert(packet_length <= read_count);
233 memcpy(m_Buffer.Data(), tmp_data, packet_length);
235 if ( (remainder = read_count - packet_length) != 0 )
237 DefaultLogSink().Warn("Repositioning pointer for short packet\n");
238 Kumu::fpos_t pos = Reader.Tell();
239 assert(pos > remainder);
240 result = Reader.Seek(pos - remainder);
245 if ( read_count < tmp_read_size )
247 DefaultLogSink().Error("Short read of packet body, expecting %u, got %u\n",
248 m_Buffer.Size(), read_count);
249 return RESULT_READFAIL;
252 memcpy(m_Buffer.Data(), tmp_data, tmp_read_size);
253 remainder = m_Buffer.Size() - tmp_read_size;
257 result = Reader.Read(m_Buffer.Data() + tmp_read_size, remainder, &read_count);
259 if ( read_count != remainder )
261 DefaultLogSink().Error("Short read of packet body, expecting %u, got %u\n",
262 remainder+tmp_read_size, read_count+tmp_read_size);
263 result = RESULT_READFAIL;
273 ASDCP::KLVFilePacket::WriteKLToFile(Kumu::FileWriter& Writer, const UL& label, ui32_t length)
275 byte_t buffer[kl_length];
276 memcpy(buffer, label.Value(), label.Size());
278 if ( ! Kumu::write_BER(buffer+SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
282 Writer.Write(buffer, kl_length, &write_count);
283 assert(write_count == kl_length);