bool FECDecoder::AddPacket(RTPPacket* packet) { //Check if it is a redundant packet if (packet->GetCodec()==VideoCodec::RED) { //Get the redundant packet RTPRedundantPacket *red = (RTPRedundantPacket *)packet; //Check primary redundant type if (red->GetPrimaryCodec()==VideoCodec::ULPFEC) { //Create new FEC data FECData *fec = new FECData(red->GetPrimaryPayloadData(),red->GetPrimaryPayloadSize()); //Log Debug("-fec primary red data at %d\n",fec->GetBaseExtSeq()); //Append it codes.insert(std::pair<DWORD,FECData*>(fec->GetBaseExtSeq(),fec)); //Packet contained no media return false; } //Ensure we don't have it already if (medias.find(packet->GetExtSeqNum())==medias.end()) //Add media packet medias[packet->GetExtSeqNum()] = red->CreatePrimaryPacket(); //For each redundant data for (int i=0;i<red->GetRedundantCount();++i) { //Check if it is a FEC pacekt if (red->GetRedundantCodec(i)==VideoCodec::ULPFEC) { //Create new FEC data FECData *fec = new FECData(red->GetRedundantPayloadData(i),red->GetRedundantPayloadSize(i)); //Log Debug("-fec red data at %d\n",fec->GetBaseExtSeq()); //Append it codes.insert(std::pair<DWORD,FECData*>(fec->GetBaseExtSeq(),fec)); } } } else if (packet->GetCodec()==VideoCodec::ULPFEC ) { //Create new FEC data FECData *fec = new FECData(packet->GetMediaData(),packet->GetMediaLength()); //Log Debug("-fec data at %d\n",fec->GetBaseExtSeq()); //Append it codes.insert(std::pair<DWORD,FECData*>(fec->GetBaseExtSeq(),fec)); //Packet contained no media return false; } else if (packet->GetCodec()==VideoCodec::FLEXFEC) { //TODO return false; } else { //Check if we have it already if (medias.find(packet->GetExtSeqNum())!=medias.end()) //Do nothing return false; //Add media packet medias[packet->GetExtSeqNum()] = packet->Clone(); } //Get last seq number DWORD seq = medias.rbegin()->first; //Remove unused packets RTPOrderedPackets::iterator it = medias.begin(); //Delete everything until seq-63 while (it->first<seq-63 && it!=medias.end()) { //Delete rtp packet delete (it->second); //Erase it medias.erase(it++); } //Now clean recovery codes FECOrderedData::iterator it2 = codes.begin(); //Check base sequence while (it2->first<seq-63 && it2!=codes.end()) { //Delete object delete(it2->second); //Erase and move to next codes.erase(it2++); } //Packet had media return true; }
/**************************************** * RecVideo * Obtiene los packetes y los muestra *****************************************/ int VideoStream::RecVideo() { VideoDecoder* videoDecoder = NULL; VideoCodec::Type type; timeval before; timeval lastFPURequest; DWORD lostCount=0; DWORD frameTime = (DWORD)-1; DWORD lastSeq = RTPPacket::MaxExtSeqNum; bool waitIntra = false; Log(">RecVideo\n"); //Get now gettimeofday(&before,NULL); //Not sent FPU yet setZeroTime(&lastFPURequest); //Mientras tengamos que capturar while(receivingVideo) { //Get RTP packet RTPPacket* packet = rtp.GetPacket(); //Check if (!packet) //Next continue; //Get extended sequence number and timestamp DWORD seq = packet->GetExtSeqNum(); DWORD ts = packet->GetTimestamp(); //Get packet data BYTE* buffer = packet->GetMediaData(); DWORD size = packet->GetMediaLength(); //Get type type = (VideoCodec::Type)packet->GetCodec(); //Lost packets since last DWORD lost = 0; //If not first if (lastSeq!=RTPPacket::MaxExtSeqNum) //Calculate losts lost = seq-lastSeq-1; //Increase total lost count lostCount += lost; //Update last sequence number lastSeq = seq; //If lost some packets or still have not got an iframe if(lostCount || waitIntra) { //Check if we got listener and more than 1/2 second have elapsed from last request if (listener && getDifTime(&lastFPURequest)>minFPUPeriod) { //Debug Debug("-Requesting FPU lost %d\n",lostCount); //Reset count lostCount = 0; //Request it listener->onRequestFPU(); //Request also over rtp rtp.RequestFPU(); //Update time getUpdDifTime(&lastFPURequest); //Waiting for refresh waitIntra = true; } } //Check if it is a redundant packet if (type==VideoCodec::RED) { //Get redundant packet RTPRedundantPacket* red = (RTPRedundantPacket*)packet; //Get primary codec type = (VideoCodec::Type)red->GetPrimaryCodec(); //Check it is not ULPFEC redundant packet if (type==VideoCodec::ULPFEC) { //Delete packet delete(packet); //Skip continue; } //Update primary redundant payload buffer = red->GetPrimaryPayloadData(); size = red->GetPrimaryPayloadSize(); } //Check codecs if ((videoDecoder==NULL) || (type!=videoDecoder->type)) { //If we already got one if (videoDecoder!=NULL) //Delete it delete videoDecoder; //Create video decorder for codec videoDecoder = VideoCodecFactory::CreateDecoder(type); //Check if (videoDecoder==NULL) { Error("Error creando nuevo decodificador de video [%d]\n",type); //Delete packet delete(packet); //Next continue; } } //Check if we have lost the last packet from the previous frame by comparing both timestamps if (ts>frameTime) { Debug("-lost mark packet ts:%u frameTime:%u\n",ts,frameTime); //Try to decode what is in the buffer videoDecoder->DecodePacket(NULL,0,1,1); //Get picture BYTE *frame = videoDecoder->GetFrame(); DWORD width = videoDecoder->GetWidth(); DWORD height = videoDecoder->GetHeight(); //Check values if (frame && width && height) { //Set frame size videoOutput->SetVideoSize(width,height); //Check if muted if (!muted) //Send it videoOutput->NextFrame(frame); } } //Update frame time frameTime = ts; //Decode packet if(!videoDecoder->DecodePacket(buffer,size,lost,packet->GetMark())) { //Check if we got listener and more than 1/2 seconds have elapsed from last request if (listener && getDifTime(&lastFPURequest)>minFPUPeriod) { //Debug Log("-Requesting FPU decoder error\n"); //Reset count lostCount = 0; //Request it listener->onRequestFPU(); //Request also over rtp rtp.RequestFPU(); //Update time getUpdDifTime(&lastFPURequest); //Waiting for refresh waitIntra = true; } } //Check if it is the last packet of a frame if(packet->GetMark()) { if (videoDecoder->IsKeyFrame()) Debug("-Got Intra\n"); //No frame time yet for next frame frameTime = (DWORD)-1; //Get picture BYTE *frame = videoDecoder->GetFrame(); DWORD width = videoDecoder->GetWidth(); DWORD height = videoDecoder->GetHeight(); //Check values if (frame && width && height) { //Set frame size videoOutput->SetVideoSize(width,height); //Check if muted if (!muted) //Send it videoOutput->NextFrame(frame); } //Check if we got the waiting refresh if (waitIntra && videoDecoder->IsKeyFrame()) //Do not wait anymore waitIntra = false; } //Delete packet delete(packet); } //Delete encoder delete videoDecoder; Log("<RecVideo\n"); }