StreamInfo::FrameType ParserMpeg2Video::parsePicture(unsigned char* data, int length) {
    int frametype = GetFrameType(data, length);

    // get I,P frames distance
    if(frametype < 3 && m_curDts != DVD_NOPTS_VALUE && m_curPts != DVD_NOPTS_VALUE) {
        m_frameDifference = m_curPts - m_curDts;
        m_lastDts = m_curDts;
        return ConvertFrameType(frametype);
    }

    // extrapolate DTS
    if(m_curDts == DVD_NOPTS_VALUE && m_duration != 0) {
        m_curDts = PtsAdd(m_lastDts, m_duration);
        m_lastDts = m_curDts;
    }

    // B frames have DTS = PTS
    if(frametype == 3 && m_curPts == DVD_NOPTS_VALUE) {
        m_curPts = m_curDts;
    }

    // extrapolate PTS of I/P frame
    if(frametype < 3 && m_curPts == DVD_NOPTS_VALUE) {
        m_curPts = PtsAdd(m_curDts, m_frameDifference);
    }

    return ConvertFrameType(frametype);
}
Exemple #2
0
void cParser::Parse(unsigned char *data, int datasize, bool pusi)
{
  // get available data
  int length = 0;
  uint8_t* buffer = Get(length);

  // do we have a sync ?
  int framesize = 0;
  if(length > m_headersize && buffer != NULL && CheckAlignmentHeader(buffer, framesize))
  {
    if(framesize > 0 && length >= framesize)
    {
      ParsePayload(buffer, framesize);
      SendPayload(buffer, framesize);

      m_curPTS = PtsAdd(m_curPTS, m_duration);
      m_curDTS = PtsAdd(m_curDTS, m_duration);

      Del(framesize);
    }

    PutData(data, datasize, pusi);
    return;
  }

  // try to find sync
  int offset = FindAlignmentOffset(buffer, length, 0, framesize);
  if(offset != -1)
  {
    INFOLOG("sync found at offset %i (streamtype: %s / %i bytes in buffer / framesize: %i bytes)", offset, m_demuxer->TypeName(), Available(), framesize);
    Del(offset);
  }

  PutData(data, datasize, pusi);
}
int ParserMpeg2Video::parsePayload(unsigned char* data, int length) {
    // lookup sequence start code
    int o = findStartCode(data, length, 0, MPEG2_SEQUENCE_START);

    if(o >= 0) {
        // skip sequence start code
        o += 4;

        // parse picture sequence (width, height, aspect, duration)
        parseSequenceStart(data + o, length - 4);
    }

    // just to be sure, exit if there's isn't any duration
    if(m_duration == 0) {
        return length;
    }

    // check for picture start codes
    int s = findStartCode(data, length, 0, MPEG2_PICTURE_START);

    // abort if there isn't any picture information
    if(s == -1) {
        return length;
    }

    int e = findStartCode(data, length, s + 4, MPEG2_PICTURE_START);
    o = s;
    s = 0;

    // divide this packet into frames
    while(e != -1) {

        // parse and send payload data
        m_frameType = parsePicture(data + o, e - o);
        Parser::sendPayload(data + s, e - s);

        // get next picture offsets
        s = e;
        o = s;
        e = findStartCode(data, length, s + 4, MPEG2_PICTURE_START);

        // increment timestamps
        m_curPts = DVD_NOPTS_VALUE;
        m_curDts = PtsAdd(m_curDts, m_duration);
    }

    // append last part
    m_frameType = parsePicture(data + o, length - o);
    Parser::sendPayload(data + s, length - s);

    return length;
}