Example #1
0
Ogg::Page::Page(const ByteVectorList &packets,
                uint streamSerialNumber,
                int pageNumber,
                bool firstPacketContinued,
                bool lastPacketCompleted,
                bool containsLastPacket)
{
  d = new PagePrivate;

  ByteVector data;
  List<int> packetSizes;

  d->header.setFirstPageOfStream(pageNumber == 0 && !firstPacketContinued);
  d->header.setLastPageOfStream(containsLastPacket);
  d->header.setFirstPacketContinued(firstPacketContinued);
  d->header.setLastPacketCompleted(lastPacketCompleted);
  d->header.setStreamSerialNumber(streamSerialNumber);
  d->header.setPageSequenceNumber(pageNumber);

  // Build a page from the list of packets.

  for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) {
    packetSizes.append((*it).size());
    data.append(*it);
  }
  d->packets = packets;
  d->header.setPacketSizes(packetSizes);
}
Example #2
0
StringList::StringList(const ByteVectorList &bl, String::Type t) : List<String>()
{
  ByteVectorList::ConstIterator i = bl.begin();
  for(;i != bl.end(); i++) {
    append(String(*i, t));
  }
}
Example #3
0
ByteVector
MP4::Tag::renderFreeForm(const String &name, const MP4::Item &item) const
{
  StringList header = StringList::split(name, ":");
  if(header.size() != 3) {
    debug("MP4: Invalid free-form item name \"" + name + "\"");
    return ByteVector();
  }
  ByteVector data;
  data.append(renderAtom("mean", ByteVector::fromUInt(0) + header[1].data(String::UTF8)));
  data.append(renderAtom("name", ByteVector::fromUInt(0) + header[2].data(String::UTF8)));
  AtomDataType type = item.atomDataType();
  if(type == TypeUndefined) {
    if(!item.toStringList().isEmpty()) {
      type = TypeUTF8;
    }
    else {
      type = TypeImplicit;
    }
  }
  if(type == TypeUTF8) {
    StringList value = item.toStringList();
    for(StringList::ConstIterator it = value.begin(); it != value.end(); ++it) {
      data.append(renderAtom("data", ByteVector::fromUInt(type) + ByteVector(4, '\0') + it->data(String::UTF8)));
    }
  }
  else {
    ByteVectorList value = item.toByteVectorList();
    for(ByteVectorList::ConstIterator it = value.begin(); it != value.end(); ++it) {
      data.append(renderAtom("data", ByteVector::fromUInt(type) + ByteVector(4, '\0') + *it));
    }
  }
  return renderAtom("----", data);
}
Example #4
0
ByteVector
MP4::Tag::renderData(const ByteVector &name, int flags, const ByteVectorList &data) const
{
  ByteVector result;
  for(ByteVectorList::ConstIterator it = data.begin(); it != data.end(); ++it) {
    result.append(renderAtom("data", ByteVector::fromUInt(flags) + ByteVector(4, '\0') + *it));
  }
  return renderAtom(name, result);
}
Example #5
0
void
MP4::Tag::parseText(const MP4::Atom *atom, int expectedFlags)
{
  ByteVectorList data = parseData(atom, expectedFlags);
  if(!data.isEmpty()) {
    StringList value;
    for(ByteVectorList::ConstIterator it = data.begin(); it != data.end(); ++it) {
      value.append(String(*it, String::UTF8));
    }
    addItem(atom->name, value);
  }
}
void TextIdentificationFrame::parseFields(const ByteVector &data)
{
  // Don't try to parse invalid frames

  if(data.size() < 2)
    return;

  // read the string data type (the first byte of the field data)

  d->textEncoding = String::Type(data[0]);

  // split the byte array into chunks based on the string type (two byte delimiter
  // for unicode encodings)

  int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2;

  // build a small counter to strip nulls off the end of the field

  int dataLength = data.size() - 1;

  while(dataLength > 0 && data[dataLength] == 0)
    dataLength--;

  while(dataLength % byteAlign != 0)
    dataLength++;

  ByteVectorList l = ByteVectorList::split(data.mid(1, dataLength), textDelimiter(d->textEncoding), byteAlign);

  d->fieldList.clear();

  // append those split values to the list and make sure that the new string's
  // type is the same specified for this frame

  for(ByteVectorList::ConstIterator it = l.begin(); it != l.end(); it++) {
    if(!(*it).isEmpty()) {
      if(d->textEncoding == String::Latin1)
        d->fieldList.append(Tag::latin1StringHandler()->parse(*it));
      else
        d->fieldList.append(String(*it, d->textEncoding));
    }
  }
}
Example #7
0
void TextIdentificationFrame::parseFields(const ByteVector &data)
{
  // read the string data type (the first byte of the field data)

  d->textEncoding = String::Type(data[0]);

  // split the byte array into chunks based on the string type (two byte delimiter
  // for unicode encodings)

  int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2;

  ByteVectorList l = ByteVectorList::split(data.mid(1), textDelimiter(d->textEncoding), byteAlign);

  d->fieldList.clear();

  // append those split values to the list and make sure that the new string's
  // type is the same specified for this frame

  for(ByteVectorList::Iterator it = l.begin(); it != l.end(); it++) {
    String s(*it, d->textEncoding);
    d->fieldList.append(s);
  }
}
Example #8
0
List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
                                      PaginationStrategy strategy,
                                      uint streamSerialNumber,
                                      int firstPage,
                                      bool firstPacketContinued,
                                      bool lastPacketCompleted,
                                      bool containsLastPacket)
{
  List<Page *> l;

  int totalSize = 0;

  for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it)
    totalSize += (*it).size();

  // Handle creation of multiple pages with appropriate pagination.
  if(strategy == Repaginate || totalSize + packets.size() > 255 * 255) {

    // SPLITSIZE must be a multiple of 255 in order to get the lacing values right
    // create pages of about 8KB each
#define SPLITSIZE (32*255)

    int pageIndex = 0;

    for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) {
      bool continued = false;

      // mark very first packet?
      if(firstPacketContinued && it==packets.begin()) {
        continued = true;
      }

      // append to buf
      ByteVector packetBuf;
      packetBuf.append(*it);

      while(packetBuf.size() > SPLITSIZE) {
        // output a Page
        ByteVector packetForOnePage;
        packetForOnePage.resize(SPLITSIZE);
        std::copy(packetBuf.begin(), packetBuf.begin() + SPLITSIZE, packetForOnePage.begin());

        ByteVectorList packetList;
        packetList.append(packetForOnePage);
        Page *p = new Page(packetList, streamSerialNumber, firstPage+pageIndex, continued, false, false);
        l.append(p);

        pageIndex++;
        continued = true;
        packetBuf = packetBuf.mid(SPLITSIZE);
      }

      ByteVectorList::ConstIterator jt = it;
      ++jt;
      bool lastPacketInList = (jt == packets.end());

      // output a page for the rest (we output one packet per page, so this one should be completed)
      ByteVectorList packetList;
      packetList.append(packetBuf);

      bool isVeryLastPacket = false;
      if(containsLastPacket) {
        // mark the very last output page as last of stream
        ByteVectorList::ConstIterator jt = it;
        ++jt;
        if(jt == packets.end()) {
          isVeryLastPacket = true;
        }
      }

      Page *p = new Page(packetList, streamSerialNumber, firstPage+pageIndex, continued,
                         lastPacketInList ? lastPacketCompleted : true,
                         isVeryLastPacket);
      pageIndex++;

      l.append(p);
    }
  }
  else {
    Page *p = new Page(packets, streamSerialNumber, firstPage, firstPacketContinued,
                       lastPacketCompleted, containsLastPacket);
    l.append(p);
  }

  return l;
}
Example #9
0
List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
                                      PaginationStrategy strategy,
                                      unsigned int streamSerialNumber,
                                      int firstPage,
                                      bool firstPacketContinued,
                                      bool lastPacketCompleted,
                                      bool containsLastPacket)
{
  // SplitSize must be a multiple of 255 in order to get the lacing values right
  // create pages of about 8KB each

  static const unsigned int SplitSize = 32 * 255;

  // Force repagination if the segment table will exceed the size limit.

  if(strategy != Repaginate) {

    size_t tableSize = 0;
    for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it)
      tableSize += it->size() / 255 + 1;

    if(tableSize > 255)
      strategy = Repaginate;
  }

  List<Page *> l;

  // Handle creation of multiple pages with appropriate pagination.

  if(strategy == Repaginate) {

    int pageIndex = firstPage;

    for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) {

      const bool lastPacketInList = (it == --packets.end());

      // mark very first packet?

      bool continued = (firstPacketContinued && it == packets.begin());
      unsigned int pos = 0;

      while(pos < it->size()) {

        const bool lastSplit = (pos + SplitSize >= it->size());

        ByteVectorList packetList;
        packetList.append(it->mid(pos, SplitSize));

        l.append(new Page(packetList,
                          streamSerialNumber,
                          pageIndex,
                          continued,
                          lastSplit && (lastPacketInList ? lastPacketCompleted : true),
                          lastSplit && (containsLastPacket && lastPacketInList)));
        pageIndex++;
        continued = true;

        pos += SplitSize;
      }
    }
  }
  else {
    l.append(new Page(packets,
                      streamSerialNumber,
                      firstPage,
                      firstPacketContinued,
                      lastPacketCompleted,
                      containsLastPacket));
  }

  return l;
}