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); }
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; }