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); }
StringList::StringList(const ByteVectorList &bl, String::Type t) : List<String>() { ByteVectorList::ConstIterator i = bl.begin(); for(;i != bl.end(); i++) { append(String(*i, t)); } }
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); }
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); }
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)); } } }
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); } }
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; }
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; }