/**************************************** * RecAudio * Obtiene los packetes y los muestra *****************************************/ int MediaBridgeSession::RecAudio() { DWORD firstAudio = 0; DWORD timeStamp=0; DWORD firstTS = 0; SWORD raw[512]; DWORD rawSize = 512; DWORD rawLen; //Create new audio frame RTMPAudioFrame *audio = new RTMPAudioFrame(0,RTPPAYLOADSIZE); Log(">RecAudio\n"); //Mientras tengamos que capturar while(receivingAudio) { //Obtenemos el paquete RTPPacket *packet = rtpAudio.GetPacket(); //Check if (!packet) //Next continue; //Get type AudioCodec::Type codec = (AudioCodec::Type)packet->GetCodec(); //Check rtp type if (codec==AudioCodec::SPEEX16) { //TODO!!!! } //Check if we have a decoder if (!rtpAudioDecoder || rtpAudioDecoder->type!=codec) { //Check if (rtpAudioDecoder) //Delete old one delete(rtpAudioDecoder); //Create new one rtpAudioDecoder = AudioCodecFactory::CreateDecoder(codec); } //Decode it rawLen = rtpAudioDecoder->Decode(packet->GetMediaData(),packet->GetMediaLength(),raw,rawSize); //Delete packet delete(packet); //Rencode it DWORD len; while((len=rtmpAudioEncoder->Encode(raw,rawLen,audio->GetMediaData(),audio->GetMaxMediaSize()))>0) { //REset rawLen = 0; //Set length audio->SetMediaSize(len); switch(rtmpAudioEncoder->type) { case AudioCodec::SPEEX16: //Set RTMP data audio->SetAudioCodec(RTMPAudioFrame::SPEEX); audio->SetSoundRate(RTMPAudioFrame::RATE11khz); audio->SetSamples16Bits(1); audio->SetStereo(0); break; case AudioCodec::NELLY8: //Set RTMP data audio->SetAudioCodec(RTMPAudioFrame::NELLY8khz); audio->SetSoundRate(RTMPAudioFrame::RATE11khz); audio->SetSamples16Bits(1); audio->SetStereo(0); break; case AudioCodec::NELLY11: //Set RTMP data audio->SetAudioCodec(RTMPAudioFrame::NELLY); audio->SetSoundRate(RTMPAudioFrame::RATE11khz); audio->SetSamples16Bits(1); audio->SetStereo(0); break; } //If it is first if (!firstTS) { //Get first audio time firstAudio = getDifTime(&first)/1000; //It is first firstTS = timeStamp; } DWORD ts = firstAudio +(timeStamp-firstTS)/8; //Set timestamp audio->SetTimestamp(ts); //Send packet SendMediaFrame(audio); } } //Check if (audio) //Delete it delete(audio); Log("<RecAudio\n"); }
RTPPacket* FECDecoder::Recover() { BYTE aux[8]; QWORD lostMask = 0; //Check we have media pacekts if (!medias.size()) //Exit return NULL; //Get First packet RTPPacket* first = medias.begin()->second; //Get the SSRC DWORD ssrc = first->GetSSRC(); //Get first media packet DWORD minSeq = first->GetExtSeqNum(); //Iterator on seq DWORD lastSeq = minSeq; //Set to 0 memset(aux,0,8); //Create writter BitWritter w(aux,8); //vector of lost pacekt seq std::vector<DWORD> losts; //For each media packet for (RTPOrderedPackets::iterator it=medias.begin();it!=medias.end();++it) { //Get seq DWORD cur = it->first; //Insert lost for (DWORD i=lastSeq+1;i<cur;++i) { //set mask bit to not present w.Put(1,0); //Add to the vecotr losts.push_back(i); } //Set last seq lastSeq = cur; //set mask bit to present w.Put(1,1); } //End it w.Flush(); //Get mask lostMask = get8(aux,0); //Check we have lost pacekts if (!losts.size()) //Exit return NULL; //For each lost packet for(std::vector<DWORD>::iterator it=losts.begin();it!=losts.end();++it) { //Get lost packet sequence DWORD seq = *it; //Search FEC packets associated this media packet for (FECOrderedData::iterator it2 = codes.begin();it2!=codes.end();++it2) { //Get FEC packet FECData *fec = it2->second; //Check if it is associated with this media pacekt in level 0 if (!fec->IsProtectedAtLevel0(seq)) //Next continue; //Get the seq difference between fec data and the media // fec seq has to be <= media seq it fec data protect media data) DWORD diff = seq-fec->GetBaseExtSeq(); //Shit mask of the lost packets to check the present ones from the base seq QWORD mediaMask = lostMask << (fec->GetBaseExtSeq()-minSeq); //Remove lost packet bit from the fec mask QWORD fecMask = fec->GetLevel0Mask() & ~(((QWORD)1)<<(64-diff-1)); //Compare needed pacekts with actual pacekts, to check if we have all of them except the missing if ((fecMask & mediaMask) == fecMask) { //Rocovered media data BYTE recovered[MTU+SRTP_MAX_TRAILER_LEN] ZEROALIGNEDTO32; //Get attributes bool p = fec->GetRecoveryP(); bool x = fec->GetRecoveryX(); BYTE cc = fec->GetRecoveryCC(); bool m = fec->GetRecoveryM(); BYTE pt = fec->GetRecoveryType(); DWORD ts = fec->GetRecoveryTimestamp(); WORD l = fec->GetRecoveryLength(); //Get protection length DWORD level0Size = fec->GetLevel0Size(); //Ensure there is enought size if (level0Size>MTU) { //Error Error("-FEC level 0 data size too big [%d]\n",level0Size); //Skip this one continue; } //Copy data memcpy(recovered,fec->GetLevel0Data(),level0Size); //Set value in temp buffer set8(aux,0,fecMask); //Get bit reader BitReader r(aux,8); //Read all media packet while(r.Left()) { //If the media packet is used to reconstrud the packet if (r.Get(1)) { //Get media packet RTPPacket* media = medias[fec->GetBaseExtSeq()+r.GetPos()-1]; //Calculate receovered attributes p ^= media->GetP(); x ^= media->GetX(); cc ^= media->GetCC(); m ^= media->GetMark(); pt ^= media->GetType(); ts ^= media->GetTimestamp(); l ^= media->GetMediaLength(); //Get data BYTE *payload = media->GetMediaData(); //Calculate the xor for (int i=0;i<fmin(media->GetMediaLength(),level0Size);++i) //XOR recovered[i] ^= payload[i]; } } //Create new video packet RTPPacket* packet = new RTPPacket(MediaFrame::Video,pt); //Set values packet->SetP(p); packet->SetX(x); packet->SetMark(m); packet->SetTimestamp(ts); //Set sequence number packet->SetSeqNum(seq); //Set seq cycles packet->SetSeqCycles(fec->GetBaseSeqCylcles()); //Set ssrc packet->SetSSRC(ssrc); //Set payload and recovered length if (!packet->SetPayloadWithExtensionData(recovered,l)) { //Delete packet delete(packet); //Error Error("-FEC payload of recovered packet to big [%u]\n",(unsigned int)l); //Skip continue; } Debug("-recovered packet len:%u ts:%u pts:%u seq:%d\n",l,ts,packet->GetTimestamp() ,packet->GetSeqNum()); //Append the packet to the media packet list if (AddPacket(packet)) //Return it if contained media return packet; else //Discard and continue delete(packet); } } } //Nothing found return NULL; }
/**************************************** * RecVideo * Obtiene los packetes y los muestra *****************************************/ int MediaBridgeSession::RecVideo() { //Coders VideoDecoder* decoder = NULL; VideoEncoder* encoder = VideoCodecFactory::CreateEncoder(VideoCodec::SORENSON); //Create new video frame RTMPVideoFrame frame(0,262143); //Set codec frame.SetVideoCodec(RTMPVideoFrame::FLV1); int width=0; int height=0; DWORD numpixels=0; Log(">RecVideo\n"); //Mientras tengamos que capturar while(receivingVideo) { ///Obtenemos el paquete RTPPacket* packet = rtpVideo.GetPacket(); //Check if (!packet) //Next continue; //Get type VideoCodec::Type type = (VideoCodec::Type)packet->GetCodec(); if ((decoder==NULL) || (type!=decoder->type)) { //Si habia uno nos lo cargamos if (decoder!=NULL) delete decoder; //Creamos uno dependiendo del tipo decoder = VideoCodecFactory::CreateDecoder(type); //Check if (!decoder) { delete(packet); continue; } } //Lo decodificamos if(!decoder->DecodePacket(packet->GetMediaData(),packet->GetMediaLength(),0,packet->GetMark())) { delete(packet); continue; } //Get mark bool mark = packet->GetMark(); //Delete packet delete(packet); //Check if it is last one if(!mark) continue; //Check size if (decoder->GetWidth()!=width || decoder->GetHeight()!=height) { //Get dimension width = decoder->GetWidth(); height = decoder->GetHeight(); //Set size numpixels = width*height*3/2; //Set also frame rate and bps encoder->SetFrameRate(25,300,500); //Set them in the encoder encoder->SetSize(width,height); } //Encode next frame VideoFrame *encoded = encoder->EncodeFrame(decoder->GetFrame(),numpixels); //Check if (!encoded) break; //Check size if (frame.GetMaxMediaSize()<encoded->GetLength()) //Not enougth space return Error("Not enought space to copy FLV encodec frame [frame:%d,encoded:%d",frame.GetMaxMediaSize(),encoded->GetLength()); //Get full frame frame.SetVideoFrame(encoded->GetData(),encoded->GetLength()); //Set buffer size frame.SetMediaSize(encoded->GetLength()); //Check type if (encoded->IsIntra()) //Set type frame.SetFrameType(RTMPVideoFrame::INTRA); else //Set type frame.SetFrameType(RTMPVideoFrame::INTER); //Let the connection set the timestamp frame.SetTimestamp(getDifTime(&first)/1000); //Send it SendMediaFrame(&frame); } //Check if (decoder) //Delete delete(decoder); //Check if (encoder) //Delete delete(encoder); Log("<RecVideo\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"); }