void Opus::Properties::read(File *file)
{
  // Get the identification header from the Ogg implementation.

  // http://tools.ietf.org/html/draft-terriberry-oggopus-01#section-5.1

  const ByteVector data = file->packet(0);

  // *Magic Signature*
  uint pos = 8;

  // *Version* (8 bits, unsigned)
  d->opusVersion = uchar(data.at(pos));
  pos += 1;

  // *Output Channel Count* 'C' (8 bits, unsigned)
  d->channels = uchar(data.at(pos));
  pos += 1;

  // *Pre-skip* (16 bits, unsigned, little endian)
  const ushort preSkip = data.toUShort(pos, false);
  pos += 2;

  // *Input Sample Rate* (32 bits, unsigned, little endian)
  d->inputSampleRate = data.toUInt(pos, false);
  pos += 4;

  // *Output Gain* (16 bits, signed, little endian)
  pos += 2;

  // *Channel Mapping Family* (8 bits, unsigned)
  pos += 1;

  const Ogg::PageHeader *first = file->firstPageHeader();
  const Ogg::PageHeader *last  = file->lastPageHeader();

  if(first && last) {
    const long long start = first->absoluteGranularPosition();
    const long long end   = last->absoluteGranularPosition();

    if(start >= 0 && end >= 0) {
      const long long frameCount = (end - start - preSkip);

      if(frameCount > 0) {
        const double length = frameCount * 1000.0 / 48000.0;
        d->length  = static_cast<int>(length + 0.5);
        d->bitrate = static_cast<int>(file->length() * 8.0 / length + 0.5);
      }
    }
    else {
      debug("Opus::Properties::read() -- The PCM values for the start or "
            "end of this file was incorrect.");
    }
  }
  else
    debug("Opus::Properties::read() -- Could not find valid first and last Ogg pages.");
}
Exemple #2
0
void ID3v2::Tag::parse(const ByteVector &data)
{
  uint frameDataPosition = 0;
  uint frameDataLength = data.size();

  // check for extended header

  if(d->header.extendedHeader()) {
    if(!d->extendedHeader)
      d->extendedHeader = new ExtendedHeader;
    d->extendedHeader->setData(data);
    if(d->extendedHeader->size() <= data.size()) {
      frameDataPosition += d->extendedHeader->size();
      frameDataLength -= d->extendedHeader->size();
    }
  }

  // check for footer -- we don't actually need to parse it, as it *must*
  // contain the same data as the header, but we do need to account for its
  // size.

  if(d->header.footerPresent() && Footer::size() <= frameDataLength)
    frameDataLength -= Footer::size();

  // parse frames

  // Make sure that there is at least enough room in the remaining frame data for
  // a frame header.

  while(frameDataPosition < frameDataLength - Frame::headerSize(d->header.majorVersion())) {

    // If the next data is position is 0, assume that we've hit the padding
    // portion of the frame data.

    if(data.at(frameDataPosition) == 0) {
      if(d->header.footerPresent())
        debug("Padding *and* a footer found.  This is not allowed by the spec.");

      d->paddingSize = frameDataLength - frameDataPosition;
      return;
    }

    Frame *frame = d->factory->createFrame(data.mid(frameDataPosition),
                                           d->header.majorVersion());

    if(!frame)
      return;

    // Checks to make sure that frame parsed correctly.

    if(frame->size() <= 0) {
      delete frame;
      return;
    }

    frameDataPosition += frame->size() + Frame::headerSize(d->header.majorVersion());
    addFrame(frame);
  }
}
void TableOfContentsFrame::parseFields(const ByteVector &data)
{
  TagLib::uint size = data.size();
  if(size < 6) {
    debug("A CTOC frame must contain at least 6 bytes (1 byte element ID terminated by "
          "null, 1 byte flags, 1 byte entry count and 1 byte child element ID terminated "
          "by null.");
    return;
  }

  int pos = 0;
  TagLib::uint embPos = 0;
  d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
  d->isTopLevel = (data.at(pos) & 2) > 0;
  d->isOrdered = (data.at(pos++) & 1) > 0;
  TagLib::uint entryCount = data.at(pos++);
  for(TagLib::uint i = 0; i < entryCount; i++) {
    ByteVector childElementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
    d->childElements.append(childElementID);
  }

  size -= pos;

  if(size < header()->size())
    return;

  while(embPos < size - header()->size()) {
    Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);

    if(!frame)
      return;

    // Checks to make sure that frame parsed correctly.
    if(frame->size() <= 0) {
      delete frame;
      return;
    }

    embPos += frame->size() + header()->size();
    addEmbeddedFrame(frame);
  }
}
/*----------------------------------------------------------------------------*/
bool DDAProtocol :: txPacket()
{
  ByteVector txData;
  if(m_txData.size())
    txData = m_txData[0];
  if(txData.empty())
    return false;

  unsigned size = txData.size();
  serial_write(m_serial, &txData.at(0), size);
  return true;
}
MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style)
  : AudioProperties(style)
{
  d = new PropertiesPrivate;

  MP4::Atom *moov = atoms->find("moov");
  if(!moov) {
    debug("MP4: Atom 'moov' not found");
    return;
  }

  MP4::Atom *trak = 0;
  ByteVector data;

  MP4::AtomList trakList = moov->findall("trak");
  for (unsigned int i = 0; i < trakList.size(); i++) {
    trak = trakList[i];
    MP4::Atom *hdlr = trak->find("mdia", "hdlr");
    if(!hdlr) {
      debug("MP4: Atom 'trak.mdia.hdlr' not found");
      return;
    }
    file->seek(hdlr->offset);
    data = file->readBlock(hdlr->length);
    if(data.mid(16, 4) == "soun") {
      break;
    }
    trak = 0;
  }
  if (!trak) {
    debug("MP4: No audio tracks");
    return;
  }

  MP4::Atom *mdhd = trak->find("mdia", "mdhd");
  if(!mdhd) {
    debug("MP4: Atom 'trak.mdia.mdhd' not found");
    return;
  }

  file->seek(mdhd->offset);
  data = file->readBlock(mdhd->length);
  uint version = data[8];
  if(version == 1) {
    if (data.size() < 36 + 8) {
      debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
      return;
    }
    const long long unit   = data.toLongLong(28U);
    const long long length = data.toLongLong(36U);
    d->length = unit ? int(length / unit) : 0;
  }
  else {
    if (data.size() < 24 + 4) {
      debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
      return;
    }
    const unsigned int unit   = data.toUInt(20U);
    const unsigned int length = data.toUInt(24U);
    d->length = unit ? length / unit : 0;
  }

  MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd");
  if(!atom) {
    return;
  }

  file->seek(atom->offset);
  data = file->readBlock(atom->length);
  if(data.mid(20, 4) == "mp4a") {
    d->channels      = data.toShort(40U);
    d->bitsPerSample = data.toShort(42U);
    d->sampleRate    = data.toUInt(46U);
    if(data.mid(56, 4) == "esds" && data[64] == 0x03) {
      uint pos = 65;
      if(data.mid(pos, 3) == "\x80\x80\x80") {
        pos += 3;
      }
      pos += 4;
      if(data[pos] == 0x04) {
        pos += 1;
        if(data.mid(pos, 3) == "\x80\x80\x80") {
          pos += 3;
        }
        pos += 10;
        d->bitrate = (data.toUInt(pos) + 500) / 1000;
      }
    }
  }
  else if (data.mid(20, 4) == "alac") {
    if (atom->length == 88 && data.mid(56, 4) == "alac") {
      d->bitsPerSample = data.at(69);
      d->channels   = data.at(73);
      d->bitrate    = data.toUInt(80U) / 1000;
      d->sampleRate = data.toUInt(84U);
    }
  }

  MP4::Atom *drms = atom->find("drms");
  if(drms) {
    d->encrypted = true;
  }
}
Exemple #6
0
void ChapterFrame::setElementID(const ByteVector &eID)
{
  d->elementID = eID;
  if(eID.at(eID.size() - 1) != char(0))
    d->elementID.append(char(0));
}
Exemple #7
0
void ID3v2::Tag::parse(const ByteVector &origData)
{
    ByteVector data = origData;

    if(d->header.unsynchronisation() && d->header.majorVersion() <= 3)
        data = SynchData::decode(data);

    uint frameDataPosition = 0;
    uint frameDataLength = data.size();

    // check for extended header

    if(d->header.extendedHeader()) {
        if(!d->extendedHeader)
            d->extendedHeader = new ExtendedHeader;
        d->extendedHeader->setData(data);
        if(d->extendedHeader->size() <= data.size()) {
            frameDataPosition += d->extendedHeader->size();
            frameDataLength -= d->extendedHeader->size();
        }
    }

    // check for footer -- we don't actually need to parse it, as it *must*
    // contain the same data as the header, but we do need to account for its
    // size.

    if(d->header.footerPresent() && Footer::size() <= frameDataLength)
        frameDataLength -= Footer::size();

    // parse frames

    // Make sure that there is at least enough room in the remaining frame data for
    // a frame header.

    while(frameDataPosition < frameDataLength - Frame::headerSize(d->header.majorVersion())) {

        // If the next data is position is 0, assume that we've hit the padding
        // portion of the frame data.

        if(data.at(frameDataPosition) == 0) {
            if(d->header.footerPresent()) {
                debug("Padding *and* a footer found.  This is not allowed by the spec.");
            }

            d->paddingSize = frameDataLength - frameDataPosition;
            return;
        }

        Frame *frame = d->factory->createFrame(data.mid(frameDataPosition),
                                               &d->header);

        if(!frame)
            return;

        frameDataPosition += frame->size() + Frame::headerSize(d->header.majorVersion());

        // Checks to make sure that frame parsed correctly.
        // (windows media player tends to write null byte frames
        // even though the spec forbids it
        // We delete those frames because they are mostly broken
        // (e.g. no null termination)
        if(frame->size() <= 0) {
            delete frame;
        } else {
            addFrame(frame);
        }
    }
}
void TableOfContentsFrame::setElementID(const ByteVector &eID)
{
  d->elementID = eID;
  if(eID.at(eID.size() - 1) != char(0))
    d->elementID.append(char(0));
}
Exemple #9
0
void
MP4::Properties::read(File *file, Atoms *atoms)
{
  MP4::Atom *moov = atoms->find("moov");
  if(!moov) {
    debug("MP4: Atom 'moov' not found");
    return;
  }

  MP4::Atom *trak = 0;
  ByteVector data;

  const MP4::AtomList trakList = moov->findall("trak");
  for(MP4::AtomList::ConstIterator it = trakList.begin(); it != trakList.end(); ++it) {
    trak = *it;
    MP4::Atom *hdlr = trak->find("mdia", "hdlr");
    if(!hdlr) {
      debug("MP4: Atom 'trak.mdia.hdlr' not found");
      return;
    }
    file->seek(hdlr->offset);
    data = file->readBlock(hdlr->length);
    if(data.containsAt("soun", 16)) {
      break;
    }
    trak = 0;
  }
  if(!trak) {
    debug("MP4: No audio tracks");
    return;
  }

  MP4::Atom *mdhd = trak->find("mdia", "mdhd");
  if(!mdhd) {
    debug("MP4: Atom 'trak.mdia.mdhd' not found");
    return;
  }

  file->seek(mdhd->offset);
  data = file->readBlock(mdhd->length);

  const unsigned int version = data[8];
  long long unit;
  long long length;
  if(version == 1) {
    if(data.size() < 36 + 8) {
      debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
      return;
    }
    unit   = data.toUInt(28U);
    length = data.toLongLong(32U);
  }
  else {
    if(data.size() < 24 + 8) {
      debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
      return;
    }
    unit   = data.toUInt(20U);
    length = data.toUInt(24U);
  }
  if(unit > 0 && length > 0)
    d->length = static_cast<int>(length * 1000.0 / unit + 0.5);

  MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd");
  if(!atom) {
    return;
  }

  file->seek(atom->offset);
  data = file->readBlock(atom->length);
  if(data.containsAt("mp4a", 20)) {
    d->codec         = AAC;
    d->channels      = data.toShort(40U);
    d->bitsPerSample = data.toShort(42U);
    d->sampleRate    = data.toUInt(46U);
    if(data.containsAt("esds", 56) && data[64] == 0x03) {
      unsigned int pos = 65;
      if(data.containsAt("\x80\x80\x80", pos)) {
        pos += 3;
      }
      pos += 4;
      if(data[pos] == 0x04) {
        pos += 1;
        if(data.containsAt("\x80\x80\x80", pos)) {
          pos += 3;
        }
        pos += 10;
        d->bitrate = static_cast<int>((data.toUInt(pos) + 500) / 1000.0 + 0.5);
      }
    }
  }
  else if(data.containsAt("alac", 20)) {
    if(atom->length == 88 && data.containsAt("alac", 56)) {
      d->codec         = ALAC;
      d->bitsPerSample = data.at(69);
      d->channels      = data.at(73);
      d->bitrate       = static_cast<int>(data.toUInt(80U) / 1000.0 + 0.5);
      d->sampleRate    = data.toUInt(84U);
    }
  }

  MP4::Atom *drms = atom->find("drms");
  if(drms) {
    d->encrypted = true;
  }
}