Vignesh Venkatasubramanianthird_party/libwebm: pull from upstreamc33787712 years agoHistory
8358 lines · 190.1 KB · C++
RawDownload
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.//// Use of this source code is governed by a BSD-style license// that can be found in the LICENSE file in the root of the source// tree. An additional intellectual property rights grant can be found// in the file PATENTS.  All contributing project authors may// be found in the AUTHORS file in the root of the source tree. #include "mkvparser.hpp"#include <cassert>#include <cstring>#include <new>#include <climits> #ifdef _MSC_VER// Disable MSVC warnings that suggest making code non-portable.#pragma warning(disable : 4996)#endif mkvparser::IMkvReader::~IMkvReader() {} void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision) {  major = 1;  minor = 0;  build = 0;  revision = 28;} long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len) {  assert(pReader);  assert(pos >= 0);   int status;   //#ifdef _DEBUG  //    long long total, available;  //    status = pReader->Length(&total, &available);  //    assert(status >= 0);  //    assert((total < 0) || (available <= total));  //    assert(pos < available);  //    assert((available - pos) >= 1);  //assume here max u-int len is 8  //#endif   len = 1;   unsigned char b;   status = pReader->Read(pos, 1, &b);   if (status < 0)  // error or underflow    return status;   if (status > 0)  // interpreted as "underflow"    return E_BUFFER_NOT_FULL;   if (b == 0)  // we can't handle u-int values larger than 8 bytes    return E_FILE_FORMAT_INVALID;   unsigned char m = 0x80;   while (!(b & m)) {    m >>= 1;    ++len;  }   //#ifdef _DEBUG  //    assert((available - pos) >= len);  //#endif   long long result = b & (~m);  ++pos;   for (int i = 1; i < len; ++i) {    status = pReader->Read(pos, 1, &b);     if (status < 0) {      len = 1;      return status;    }     if (status > 0) {      len = 1;      return E_BUFFER_NOT_FULL;    }     result <<= 8;    result |= b;     ++pos;  }   return result;} long long mkvparser::GetUIntLength(IMkvReader* pReader, long long pos,                                   long& len) {  assert(pReader);  assert(pos >= 0);   long long total, available;   int status = pReader->Length(&total, &available);  assert(status >= 0);  assert((total < 0) || (available <= total));   len = 1;   if (pos >= available)    return pos;  // too few bytes available   unsigned char b;   status = pReader->Read(pos, 1, &b);   if (status < 0)    return status;   assert(status == 0);   if (b == 0)  // we can't handle u-int values larger than 8 bytes    return E_FILE_FORMAT_INVALID;   unsigned char m = 0x80;   while (!(b & m)) {    m >>= 1;    ++len;  }   return 0;  // success} long long mkvparser::UnserializeUInt(IMkvReader* pReader, long long pos,                                     long long size) {  assert(pReader);  assert(pos >= 0);   if ((size <= 0) || (size > 8))    return E_FILE_FORMAT_INVALID;   long long result = 0;   for (long long i = 0; i < size; ++i) {    unsigned char b;     const long status = pReader->Read(pos, 1, &b);     if (status < 0)      return status;     result <<= 8;    result |= b;     ++pos;  }   return result;} long mkvparser::UnserializeFloat(IMkvReader* pReader, long long pos,                                 long long size_, double& result) {  assert(pReader);  assert(pos >= 0);   if ((size_ != 4) && (size_ != 8))    return E_FILE_FORMAT_INVALID;   const long size = static_cast<long>(size_);   unsigned char buf[8];   const int status = pReader->Read(pos, size, buf);   if (status < 0)  // error    return status;   if (size == 4) {    union {      float f;      unsigned long ff;    };     ff = 0;     for (int i = 0;;) {      ff |= buf[i];       if (++i >= 4)        break;       ff <<= 8;    }     result = f;  } else {    assert(size == 8);     union {      double d;      unsigned long long dd;    };     dd = 0;     for (int i = 0;;) {      dd |= buf[i];       if (++i >= 8)        break;       dd <<= 8;    }     result = d;  }   return 0;} long mkvparser::UnserializeInt(IMkvReader* pReader, long long pos, long size,                               long long& result) {  assert(pReader);  assert(pos >= 0);  assert(size > 0);  assert(size <= 8);   {    signed char b;     const long status = pReader->Read(pos, 1, (unsigned char*)&b);     if (status < 0)      return status;     result = b;     ++pos;  }   for (long i = 1; i < size; ++i) {    unsigned char b;     const long status = pReader->Read(pos, 1, &b);     if (status < 0)      return status;     result <<= 8;    result |= b;     ++pos;  }   return 0;  // success} long mkvparser::UnserializeString(IMkvReader* pReader, long long pos,                                  long long size_, char*& str) {  delete[] str;  str = NULL;   if (size_ >= LONG_MAX)  // we need (size+1) chars    return E_FILE_FORMAT_INVALID;   const long size = static_cast<long>(size_);   str = new (std::nothrow) char[size + 1];   if (str == NULL)    return -1;   unsigned char* const buf = reinterpret_cast<unsigned char*>(str);   const long status = pReader->Read(pos, size, buf);   if (status) {    delete[] str;    str = NULL;     return status;  }   str[size] = '\0';   return 0;  // success} long mkvparser::ParseElementHeader(IMkvReader* pReader, long long& pos,                                   long long stop, long long& id,                                   long long& size) {  if ((stop >= 0) && (pos >= stop))    return E_FILE_FORMAT_INVALID;   long len;   id = ReadUInt(pReader, pos, len);   if (id < 0)    return E_FILE_FORMAT_INVALID;   pos += len;  // consume id   if ((stop >= 0) && (pos >= stop))    return E_FILE_FORMAT_INVALID;   size = ReadUInt(pReader, pos, len);   if (size < 0)    return E_FILE_FORMAT_INVALID;   pos += len;  // consume length of size   // pos now designates payload   if ((stop >= 0) && ((pos + size) > stop))    return E_FILE_FORMAT_INVALID;   return 0;  // success} bool mkvparser::Match(IMkvReader* pReader, long long& pos, unsigned long id_,                      long long& val) {  assert(pReader);  assert(pos >= 0);   long long total, available;   const long status = pReader->Length(&total, &available);  assert(status >= 0);  assert((total < 0) || (available <= total));  if (status < 0)    return false;   long len;   const long long id = ReadUInt(pReader, pos, len);  assert(id >= 0);  assert(len > 0);  assert(len <= 8);  assert((pos + len) <= available);   if ((unsigned long)id != id_)    return false;   pos += len;  // consume id   const long long size = ReadUInt(pReader, pos, len);  assert(size >= 0);  assert(size <= 8);  assert(len > 0);  assert(len <= 8);  assert((pos + len) <= available);   pos += len;  // consume length of size of payload   val = UnserializeUInt(pReader, pos, size);  assert(val >= 0);   pos += size;  // consume size of payload   return true;} bool mkvparser::Match(IMkvReader* pReader, long long& pos, unsigned long id_,                      unsigned char*& buf, size_t& buflen) {  assert(pReader);  assert(pos >= 0);   long long total, available;   long status = pReader->Length(&total, &available);  assert(status >= 0);  assert((total < 0) || (available <= total));  if (status < 0)    return false;   long len;  const long long id = ReadUInt(pReader, pos, len);  assert(id >= 0);  assert(len > 0);  assert(len <= 8);  assert((pos + len) <= available);   if ((unsigned long)id != id_)    return false;   pos += len;  // consume id   const long long size_ = ReadUInt(pReader, pos, len);  assert(size_ >= 0);  assert(len > 0);  assert(len <= 8);  assert((pos + len) <= available);   pos += len;  // consume length of size of payload  assert((pos + size_) <= available);   const long buflen_ = static_cast<long>(size_);   buf = new (std::nothrow) unsigned char[buflen_];  assert(buf);  // TODO   status = pReader->Read(pos, buflen_, buf);  assert(status == 0);  // TODO   buflen = buflen_;   pos += size_;  // consume size of payload  return true;} namespace mkvparser { EBMLHeader::EBMLHeader() : m_docType(NULL) { Init(); } EBMLHeader::~EBMLHeader() { delete[] m_docType; } void EBMLHeader::Init() {  m_version = 1;  m_readVersion = 1;  m_maxIdLength = 4;  m_maxSizeLength = 8;   if (m_docType) {    delete[] m_docType;    m_docType = NULL;  }   m_docTypeVersion = 1;  m_docTypeReadVersion = 1;} long long EBMLHeader::Parse(IMkvReader* pReader, long long& pos) {  assert(pReader);   long long total, available;   long status = pReader->Length(&total, &available);   if (status < 0)  // error    return status;   pos = 0;  long long end = (available >= 1024) ? 1024 : available;   for (;;) {    unsigned char b = 0;     while (pos < end) {      status = pReader->Read(pos, 1, &b);       if (status < 0)  // error        return status;       if (b == 0x1A)        break;       ++pos;    }     if (b != 0x1A) {      if (pos >= 1024)        return E_FILE_FORMAT_INVALID;  // don't bother looking anymore       if ((total >= 0) && ((total - available) < 5))        return E_FILE_FORMAT_INVALID;       return available + 5;  // 5 = 4-byte ID + 1st byte of size    }     if ((total >= 0) && ((total - pos) < 5))      return E_FILE_FORMAT_INVALID;     if ((available - pos) < 5)      return pos + 5;  // try again later     long len;     const long long result = ReadUInt(pReader, pos, len);     if (result < 0)  // error      return result;     if (result == 0x0A45DFA3) {  // EBML Header ID      pos += len;  // consume ID      break;    }     ++pos;  // throw away just the 0x1A byte, and try again  }   // pos designates start of size field   // get length of size field   long len;  long long result = GetUIntLength(pReader, pos, len);   if (result < 0)  // error    return result;

Lines 1–500 of 8358.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t