void M2VParser::StampFrame(MPEGFrame* frame){ MediaTime timeunit; timeunit = (MediaTime)(1000000000/(m_seqHdr.frameOrFieldRate*2)); if (m_timecodes.empty()) frame->timecode = previousTimecode + previousDuration; else { frame->timecode = m_timecodes.front(); m_timecodes.pop_front(); } previousTimecode = frame->timecode; frame->duration = (MediaTime)(frame->duration * timeunit); previousDuration = frame->duration; if(frame->frameType == 'P'){ frame->firstRef = firstRef; ShoveRef(previousTimecode); }else if(frame->frameType == 'B'){ frame->firstRef = firstRef; frame->secondRef = secondRef; } else{ ShoveRef(previousTimecode); } frame->stamped = true; }
//Reads frames until it can timestamp them, usually reads until it has //an I, P, B+, P...this way it can stamp them all and set references. //NOTE: references aren't yet used by our system but they are kept up //with in this plugin. int32_t M2VParser::FillQueues(){ if(chunks.empty()){ return -1; } bool done = false; while(!done){ MediaTime myTime = currentStampingTime; MPEGChunk* chunk = chunks.front(); while (chunk->GetType() != MPEG_VIDEO_PICTURE_START_CODE) { if (chunk->GetType() == MPEG_VIDEO_GOP_START_CODE) { if (gopChunk) delete gopChunk; gopChunk = chunk; } else if (chunk->GetType() == MPEG_VIDEO_SEQUENCE_START_CODE) { if (seqHdrChunk) delete seqHdrChunk; ParseSequenceHeader(chunk, m_seqHdr); seqHdrChunk = chunk; } chunks.erase(chunks.begin()); if (chunks.empty()) return -1; chunk = chunks.front(); } MPEG2PictureHeader picHdr; ParsePictureHeader(chunk, picHdr); MediaTime bcount; if(myTime == nextSkip){ myTime+=nextSkipDuration; currentStampingTime=myTime; } switch(picHdr.frameType){ case MPEG2_I_FRAME: bcount = CountBFrames(); if(bcount > 0){ //..BBIBB.. myTime += bcount; nextSkip = myTime; nextSkipDuration = GetFrameDuration(picHdr); }else{ //IPBB.. if(bcount == -1 && !m_eos) return -1; currentStampingTime += GetFrameDuration(picHdr);; } ShoveRef(myTime); QueueFrame(chunk, myTime, picHdr); notReachedFirstGOP = false; break; case MPEG2_P_FRAME: bcount = CountBFrames(); if(firstRef == -1) break; if(bcount > 0){ //..PBB.. myTime += bcount; nextSkip = myTime; nextSkipDuration = GetFrameDuration(picHdr); }else{ //..PPBB.. if(bcount == -1 && !m_eos) return -1; currentStampingTime+=GetFrameDuration(picHdr); } ShoveRef(myTime); QueueFrame(chunk, myTime, picHdr); break; default: //B-frames if(firstRef == -1 || secondRef == -1) break; QueueFrame(chunk, myTime, picHdr); currentStampingTime+=GetFrameDuration(picHdr); } chunks.erase(chunks.begin()); delete chunk; if (chunks.empty()) return -1; } return 0; }