diff options
Diffstat (limited to 'debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4file_io.cpp')
-rw-r--r-- | debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4file_io.cpp | 581 |
1 files changed, 581 insertions, 0 deletions
diff --git a/debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4file_io.cpp b/debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4file_io.cpp new file mode 100644 index 00000000..5de29104 --- /dev/null +++ b/debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4file_io.cpp @@ -0,0 +1,581 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "src/impl.h" + +namespace mp4v2 { +namespace impl { + +/////////////////////////////////////////////////////////////////////////////// + +// MP4File low level IO support + +uint64_t MP4File::GetPosition( File* file ) +{ + if( m_memoryBuffer ) + return m_memoryBufferPosition; + + if( !file ) + file = m_file; + + ASSERT( file ); + return file->position; +} + +void MP4File::SetPosition( uint64_t pos, File* file ) +{ + if( m_memoryBuffer ) { + if( pos >= m_memoryBufferSize ) + throw new Exception( "position out of range", __FILE__, __LINE__, __FUNCTION__ ); + m_memoryBufferPosition = pos; + return; + } + + if( !file ) + file = m_file; + + ASSERT( file ); + if( file->seek( pos )) + throw new PlatformException( "seek failed", sys::getLastError(), __FILE__, __LINE__, __FUNCTION__ ); +} + +uint64_t MP4File::GetSize( File* file ) +{ + if( m_memoryBuffer ) + return m_memoryBufferSize; + + if( !file ) + file = m_file; + + ASSERT( file ); + return file->size; +} + +void MP4File::ReadBytes( uint8_t* buf, uint32_t bufsiz, File* file ) +{ + if( bufsiz == 0 ) + return; + + ASSERT( buf ); + WARNING( m_numReadBits > 0 ); + + if( m_memoryBuffer ) { + if( m_memoryBufferPosition + bufsiz > m_memoryBufferSize ) + throw new Exception( "not enough bytes, reached end-of-memory", __FILE__, __LINE__, __FUNCTION__ ); + memcpy( buf, &m_memoryBuffer[m_memoryBufferPosition], bufsiz ); + m_memoryBufferPosition += bufsiz; + return; + } + + if( !file ) + file = m_file; + + ASSERT( file ); + File::Size nin; + if( file->read( buf, bufsiz, nin )) + throw new PlatformException( "read failed", sys::getLastError(), __FILE__, __LINE__, __FUNCTION__ ); + if( nin != bufsiz ) + throw new Exception( "not enough bytes, reached end-of-file", __FILE__, __LINE__, __FUNCTION__ ); +} + +void MP4File::PeekBytes( uint8_t* buf, uint32_t bufsiz, File* file ) +{ + const uint64_t pos = GetPosition( file ); + ReadBytes( buf, bufsiz, file ); + SetPosition( pos, file ); +} + +void MP4File::EnableMemoryBuffer( uint8_t* pBytes, uint64_t numBytes ) +{ + ASSERT( !m_memoryBuffer ); + + if (pBytes) { + m_memoryBuffer = pBytes; + m_memoryBufferSize = numBytes; + } else { + if (numBytes) { + m_memoryBufferSize = numBytes; + } else { + m_memoryBufferSize = 4096; + } + m_memoryBuffer = (uint8_t*)MP4Malloc(m_memoryBufferSize); + } + m_memoryBufferPosition = 0; +} + +void MP4File::DisableMemoryBuffer( uint8_t** ppBytes, uint64_t* pNumBytes ) +{ + ASSERT(m_memoryBuffer != NULL); + + if (ppBytes) { + *ppBytes = m_memoryBuffer; + } + if (pNumBytes) { + *pNumBytes = m_memoryBufferPosition; + } + + m_memoryBuffer = NULL; + m_memoryBufferSize = 0; + m_memoryBufferPosition = 0; +} + +void MP4File::WriteBytes( uint8_t* buf, uint32_t bufsiz, File* file ) +{ + ASSERT( m_numWriteBits == 0 || m_numWriteBits >= 8 ); + + if( !buf || bufsiz == 0 ) + return; + + if( m_memoryBuffer ) { + if( m_memoryBufferPosition + bufsiz > m_memoryBufferSize ) { + m_memoryBufferSize = 2 * (m_memoryBufferSize + bufsiz); + m_memoryBuffer = (uint8_t*)MP4Realloc( m_memoryBuffer, m_memoryBufferSize ); + } + memcpy( &m_memoryBuffer[m_memoryBufferPosition], buf, bufsiz ); + m_memoryBufferPosition += bufsiz; + return; + } + + if( !file ) + file = m_file; + + ASSERT( file ); + File::Size nout; + if( file->write( buf, bufsiz, nout )) + throw new PlatformException( "write failed", sys::getLastError(), __FILE__, __LINE__, __FUNCTION__ ); + if( nout != bufsiz ) + throw new Exception( "not all bytes written", __FILE__, __LINE__, __FUNCTION__ ); +} + +uint64_t MP4File::ReadUInt(uint8_t size) +{ + switch (size) { + case 1: + return ReadUInt8(); + case 2: + return ReadUInt16(); + case 3: + return ReadUInt24(); + case 4: + return ReadUInt32(); + case 8: + return ReadUInt64(); + default: + ASSERT(false); + return 0; + } +} + +uint8_t MP4File::ReadUInt8() +{ + uint8_t data; + ReadBytes(&data, 1); + return data; +} + +void MP4File::WriteUInt8(uint8_t value) +{ + WriteBytes(&value, 1); +} + +uint16_t MP4File::ReadUInt16() +{ + uint8_t data[2]; + ReadBytes(&data[0], 2); + return ((data[0] << 8) | data[1]); +} + +void MP4File::WriteUInt16(uint16_t value) +{ + uint8_t data[2]; + data[0] = (value >> 8) & 0xFF; + data[1] = value & 0xFF; + WriteBytes(data, 2); +} + +uint32_t MP4File::ReadUInt24() +{ + uint8_t data[3]; + ReadBytes(&data[0], 3); + return ((data[0] << 16) | (data[1] << 8) | data[2]); +} + +void MP4File::WriteUInt24(uint32_t value) +{ + uint8_t data[3]; + data[0] = (value >> 16) & 0xFF; + data[1] = (value >> 8) & 0xFF; + data[2] = value & 0xFF; + WriteBytes(data, 3); +} + +uint32_t MP4File::ReadUInt32() +{ + uint8_t data[4]; + ReadBytes(&data[0], 4); + return ((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]); +} + +void MP4File::WriteUInt32(uint32_t value) +{ + uint8_t data[4]; + data[0] = (value >> 24) & 0xFF; + data[1] = (value >> 16) & 0xFF; + data[2] = (value >> 8) & 0xFF; + data[3] = value & 0xFF; + WriteBytes(data, 4); +} + +uint64_t MP4File::ReadUInt64() +{ + uint8_t data[8]; + uint64_t result = 0; + uint64_t temp; + + ReadBytes(&data[0], 8); + + for (int i = 0; i < 8; i++) { + temp = data[i]; + result |= temp << ((7 - i) * 8); + } + return result; +} + +void MP4File::WriteUInt64(uint64_t value) +{ + uint8_t data[8]; + + for (int i = 7; i >= 0; i--) { + data[i] = value & 0xFF; + value >>= 8; + } + WriteBytes(data, 8); +} + +float MP4File::ReadFixed16() +{ + uint8_t iPart = ReadUInt8(); + uint8_t fPart = ReadUInt8(); + + return iPart + (((float)fPart) / 0x100); +} + +void MP4File::WriteFixed16(float value) +{ + if (value >= 0x100) { + ostringstream msg; + msg << value << " out of range"; + throw new PlatformException(msg.str().c_str(), ERANGE, __FILE__, __LINE__, __FUNCTION__); + } + + uint8_t iPart = (uint8_t)value; + uint8_t fPart = (uint8_t)((value - iPart) * 0x100); + + WriteUInt8(iPart); + WriteUInt8(fPart); +} + +float MP4File::ReadFixed32() +{ + uint16_t iPart = ReadUInt16(); + uint16_t fPart = ReadUInt16(); + + return iPart + (((float)fPart) / 0x10000); +} + +void MP4File::WriteFixed32(float value) +{ + if (value >= 0x10000) { + ostringstream msg; + msg << value << " out of range"; + throw new PlatformException(msg.str().c_str(), ERANGE, __FILE__, __LINE__, __FUNCTION__); + } + + uint16_t iPart = (uint16_t)value; + uint16_t fPart = (uint16_t)((value - iPart) * 0x10000); + + WriteUInt16(iPart); + WriteUInt16(fPart); +} + +float MP4File::ReadFloat() +{ + union { + float f; + uint32_t i; + } u; + + u.i = ReadUInt32(); + return u.f; +} + +void MP4File::WriteFloat(float value) +{ + union { + float f; + uint32_t i; + } u; + + u.f = value; + WriteUInt32(u.i); +} + +char* MP4File::ReadString() +{ + uint32_t length = 0; + uint32_t alloced = 64; + char* data = (char*)MP4Malloc(alloced); + + do { + if (length == alloced) { + data = (char*)MP4Realloc(data, alloced * 2); + if (data == NULL) return NULL; + alloced *= 2; + } + ReadBytes((uint8_t*)&data[length], 1); + length++; + } while (data[length - 1] != 0); + + data = (char*)MP4Realloc(data, length); + return data; +} + +void MP4File::WriteString(char* string) +{ + if (string == NULL) { + uint8_t zero = 0; + WriteBytes(&zero, 1); + } else { + WriteBytes((uint8_t*)string, (uint32_t)strlen(string) + 1); + } +} + +char* MP4File::ReadCountedString(uint8_t charSize, bool allowExpandedCount, uint8_t fixedLength) +{ + uint32_t charLength; + if (allowExpandedCount) { + uint8_t b; + uint32_t ix = 0; + charLength = 0; + do { + b = ReadUInt8(); + charLength += b; + ix++; + if (ix > 25) + throw new PlatformException("Counted string too long 25 * 255",ERANGE, + __FILE__, __LINE__, __FUNCTION__); + } while (b == 255); + } else { + charLength = ReadUInt8(); + } + + if (fixedLength && (charLength > fixedLength)) { + /* + * The counted length of this string is greater than the + * maxiumum fixed length, so truncate the string to the + * maximum fixed length amount (take 1 byte away from the + * fixedlength since we've already sacrificed one byte for + * reading the counted length, and there has been a bug where + * a non counted string has been used in the place of a + * counted string). + */ + WARNING(charLength > fixedLength); + charLength = fixedLength - 1U; + } + + uint32_t byteLength = charLength * charSize; + char* data = (char*)MP4Malloc(byteLength + 1); + if (byteLength > 0) { + ReadBytes((uint8_t*)data, byteLength); + } + data[byteLength] = '\0'; + + // read padding + if (fixedLength) { + const uint8_t padsize = fixedLength - byteLength -1U; + if( padsize ) { + uint8_t* padbuf = (uint8_t*)malloc( padsize ); + ReadBytes( padbuf, padsize ); + free( padbuf ); + } + } + + return data; +} + +void MP4File::WriteCountedString(char* string, + uint8_t charSize, bool allowExpandedCount, + uint32_t fixedLength) +{ + uint32_t byteLength; + uint8_t zero[1]; + + if (string) { + byteLength = (uint32_t)strlen(string); + if (fixedLength && (byteLength >= fixedLength)) { + byteLength = fixedLength-1; + } + } + else { + byteLength = 0; + } + uint32_t charLength = byteLength / charSize; + + if (allowExpandedCount) { + while (charLength >= 0xFF) { + WriteUInt8(0xFF); + charLength -= 0xFF; + } + // Write the count + WriteUInt8(charLength); + } else { + if (charLength > 255) { + ostringstream msg; + msg << "Length is " << charLength; + throw new PlatformException(msg.str().c_str(), ERANGE, __FILE__, __LINE__, __FUNCTION__); + } + // Write the count + WriteUInt8(charLength); + } + + if (byteLength > 0) { + // Write the string (or the portion that we want to write) + WriteBytes((uint8_t*)string, byteLength); + } + + // Write any padding if this is a fixed length counted string + if (fixedLength) { + zero[0] = 0; + while (byteLength < fixedLength-1U) { + WriteBytes(zero, 1); + byteLength++; + } + } +} + +uint64_t MP4File::ReadBits(uint8_t numBits) +{ + ASSERT(numBits > 0); + ASSERT(numBits <= 64); + + uint64_t bits = 0; + + for (uint8_t i = numBits; i > 0; i--) { + if (m_numReadBits == 0) { + ReadBytes(&m_bufReadBits, 1); + m_numReadBits = 8; + } + bits = (bits << 1) | ((m_bufReadBits >> (--m_numReadBits)) & 1); + } + + return bits; +} + +void MP4File::FlushReadBits() +{ + // eat any remaining bits in the read buffer + m_numReadBits = 0; +} + +void MP4File::WriteBits(uint64_t bits, uint8_t numBits) +{ + ASSERT(numBits <= 64); + + for (uint8_t i = numBits; i > 0; i--) { + m_bufWriteBits |= + (((bits >> (i - 1)) & 1) << (8 - ++m_numWriteBits)); + + if (m_numWriteBits == 8) { + FlushWriteBits(); + } + } +} + +void MP4File::PadWriteBits(uint8_t pad) +{ + if (m_numWriteBits) { + WriteBits(pad ? 0xFF : 0x00, 8 - m_numWriteBits); + } +} + +void MP4File::FlushWriteBits() +{ + if (m_numWriteBits > 0) { + WriteBytes(&m_bufWriteBits, 1); + m_numWriteBits = 0; + m_bufWriteBits = 0; + } +} + +uint32_t MP4File::ReadMpegLength() +{ + uint32_t length = 0; + uint8_t numBytes = 0; + uint8_t b; + + do { + b = ReadUInt8(); + length = (length << 7) | (b & 0x7F); + numBytes++; + } while ((b & 0x80) && numBytes < 4); + + return length; +} + +void MP4File::WriteMpegLength(uint32_t value, bool compact) +{ + if (value > 0x0FFFFFFF) { + ostringstream msg; + msg << "out of range: " << value; + throw new PlatformException(msg.str().c_str(), ERANGE, __FILE__, __LINE__, __FUNCTION__ ); + } + + int8_t numBytes; + + if (compact) { + if (value <= 0x7F) { + numBytes = 1; + } else if (value <= 0x3FFF) { + numBytes = 2; + } else if (value <= 0x1FFFFF) { + numBytes = 3; + } else { + numBytes = 4; + } + } else { + numBytes = 4; + } + + int8_t i = numBytes; + do { + i--; + uint8_t b = (value >> (i * 7)) & 0x7F; + if (i > 0) { + b |= 0x80; + } + WriteUInt8(b); + } while (i > 0); +} + +/////////////////////////////////////////////////////////////////////////////// + +} +} // namespace mp4v2::impl |