/**************************************** * 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"); }
int FLVEncoder::StartEncoding() { Log(">Start encoding FLV [id:%d]\n",id); //Si estabamos mandando tenemos que parar if (encodingAudio || encodingVideo) //paramos StopEncoding(); //Set init time getUpdDifTime(&first); //Check if got old meta if (meta) //Delete delete(meta); //Create metadata object meta = new RTMPMetaData(0); //Set name meta->AddParam(new AMFString(L"@setDataFrame")); //Set name meta->AddParam(new AMFString(L"onMetaData")); //Create properties string AMFEcmaArray *prop = new AMFEcmaArray(); //Set audio properties switch(audioCodec) { case AudioCodec::SPEEX16: prop->AddProperty(L"audiocodecid" ,(float)RTMPAudioFrame::SPEEX ); //Number Audio codec ID used in the file (see E.4.2.1 for available SoundFormat values) prop->AddProperty(L"audiosamplerate" ,(float)16000.0 ); // Number Frequency at which the audio stream is replayed break; case AudioCodec::NELLY11: prop->AddProperty(L"audiocodecid" ,(float)RTMPAudioFrame::NELLY ); //Number Audio codec ID used in the file (see E.4.2.1 for available SoundFormat values) prop->AddProperty(L"audiosamplerate" ,(float)11025.0 ); // Number Frequency at which the audio stream is replayed break; case AudioCodec::NELLY8: prop->AddProperty(L"audiocodecid" ,(float)RTMPAudioFrame::NELLY8khz ); //Number Audio codec ID used in the file (see E.4.2.1 for available SoundFormat values) prop->AddProperty(L"audiosamplerate" ,(float)8000.0 ); // Number Frequency at which the audio stream is replayed break; } prop->AddProperty(L"stereo" ,new AMFBoolean(false) ); // Boolean Indicating stereo audio prop->AddProperty(L"audiodelay" ,0.0 ); // Number Delay introduced by the audio codec in seconds //Set video codecs if (videoCodec==VideoCodec::SORENSON) //Set number prop->AddProperty(L"videocodecid" ,(float)RTMPVideoFrame::FLV1 ); // Number Video codec ID used in the file (see E.4.3.1 for available CodecID values) else if (videoCodec==VideoCodec::H264) //AVC prop->AddProperty(L"videocodecid" ,new AMFString(L"avc1") ); // Number Video codec ID used in the file (see E.4.3.1 for available CodecID values) prop->AddProperty(L"framerate" ,(float)fps ); // Number Number of frames per second prop->AddProperty(L"height" ,(float)height ); // Number Height of the video in pixels prop->AddProperty(L"videodatarate" ,(float)bitrate ); // Number Video bit rate in kilobits per second prop->AddProperty(L"width" ,(float)width ); // Number Width of the video in pixels prop->AddProperty(L"canSeekToEnd" ,new AMFBoolean(false) ); // Boolean Indicating the last video frame is a key frame //Add param meta->AddParam(prop); //Send metadata SendMetaData(meta); //If got audio if (audioInput) { //We are enconding encodingAudio = 1; //Start thread createPriorityThread(&encodingAudioThread,startEncodingAudio,this,1); } //If got video if (videoInput) { //We are enconding encodingVideo = 1; //Start thread createPriorityThread(&encodingVideoThread,startEncodingVideo,this,1); } Log("<Stop encoding FLV [%d]\n",encodingAudio); return 1; }