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; }
/**************************************** * RecText * Obtiene los packetes y los muestra *****************************************/ int MediaBridgeSession::RecText() { DWORD timeStamp=0; DWORD lastSeq = RTPPacket::MaxExtSeqNum; Log(">RecText\n"); //Mientras tengamos que capturar while(receivingText) { //Get packet RTPPacket *packet = rtpText.GetPacket(); //Check packet if (!packet) continue; //Get data BYTE* data = packet->GetMediaData(); //And length DWORD size = packet->GetMediaLength(); //Get extended sequence number DWORD seq = packet->GetExtSeqNum(); //Lost packets since last one DWORD lost = 0; //If not first if (lastSeq!=RTPPacket::MaxExtSeqNum) //Calculate losts lost = seq-lastSeq-1; //Update last sequence number lastSeq = seq; //Get type TextCodec::Type type = (TextCodec::Type)packet->GetCodec(); //Check the type of data if (type==TextCodec::T140RED) { //Get redundant packet RTPRedundantPacket* red = (RTPRedundantPacket*)packet; //Check lost packets count if (lost == 0) { //Create text frame TextFrame frame(timeStamp ,red->GetPrimaryPayloadData(),red->GetPrimaryPayloadSize()); //Create new timestamp associated to latest media time RTMPMetaData meta(getDifTime(&first)/1000); //Add text name meta.AddParam(new AMFString(L"onText")); //Set data meta.AddParam(new AMFString(frame.GetWChar())); //Send data SendMetaData(&meta); } else { //Timestamp of first packet (either receovered or not) DWORD ts = timeStamp; //Check if we have any red pacekt if (red->GetRedundantCount()>0) //Get the timestamp of first redundant packet ts = red->GetRedundantTimestamp(0); //If we have lost too many if (lost>red->GetRedundantCount()) //Get what we have available only lost = red->GetRedundantCount(); //For each lonot recoveredt packet send a mark for (int i=red->GetRedundantCount();i<lost;i++) { //Create frame of lost replacement TextFrame frame(ts,LOSTREPLACEMENT,sizeof(LOSTREPLACEMENT)); //Create new timestamp associated to latest media time RTMPMetaData meta(getDifTime(&first)/1000); //Add text name meta.AddParam(new AMFString(L"onText")); //Set data meta.AddParam(new AMFString(frame.GetWChar())); //Send data SendMetaData(&meta); } //Fore each recovered packet for (int i=red->GetRedundantCount()-lost;i<red->GetRedundantCount();i++) { //Create frame from recovered data TextFrame frame(red->GetRedundantTimestamp(i),red->GetRedundantPayloadData(i),red->GetRedundantPayloadSize(i)); //Create new timestamp associated to latest media time RTMPMetaData meta(getDifTime(&first)/1000); //Add text name meta.AddParam(new AMFString(L"onText")); //Set data meta.AddParam(new AMFString(frame.GetWChar())); //Send data SendMetaData(&meta); } } } else { //Create frame TextFrame frame(timeStamp,data,size); //Create new timestamp associated to latest media time RTMPMetaData meta(getDifTime(&first)/1000); //Add text name meta.AddParam(new AMFString(L"onText")); //Set data meta.AddParam(new AMFString(frame.GetWChar())); //Send data SendMetaData(&meta); } } Log("<RecText\n"); }
/**************************************** * 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"); }