Example #1
0
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;
}
Example #2
0
/****************************************
* 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");
}
Example #3
0
/****************************************
* 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");
}