void RtmpAudio::bufferPacket(const RTMPPacket& p) { RTMPPacket np = p; if(!RTMPPacket_Alloc(&np,np.m_nBodySize)){ ERROR("could not allocate packet.\n"); return; } memcpy(np.m_body,p.m_body,p.m_nBodySize); m_q_recv.lock(); q_recv.push(np); m_q_recv.unlock(); }
void LibRtmp::SendSetChunkSize(unsigned int chunkSize) { RTMPPacket rtmp_pakt; RTMPPacket_Reset(&rtmp_pakt); RTMPPacket_Alloc(&rtmp_pakt, 4); rtmp_pakt.m_packetType = 0x01; rtmp_pakt.m_nChannel = 0x02; // control channel rtmp_pakt.m_headerType = RTMP_PACKET_SIZE_LARGE; rtmp_pakt.m_nInfoField2 = 0; rtmp_pakt.m_nBodySize = 4; UI32ToBytes(rtmp_pakt.m_body, chunkSize); RTMP_SendPacket(rtmp_, &rtmp_pakt, 0); RTMPPacket_Free(&rtmp_pakt); }
bool LibRtmp::Send(const char* buf, int bufLen, int type, unsigned int timestamp) { RTMPPacket rtmp_pakt; RTMPPacket_Reset(&rtmp_pakt); RTMPPacket_Alloc(&rtmp_pakt, bufLen); rtmp_pakt.m_packetType = type; rtmp_pakt.m_nBodySize = bufLen; rtmp_pakt.m_nTimeStamp = timestamp; rtmp_pakt.m_nChannel = 4; rtmp_pakt.m_headerType = RTMP_PACKET_SIZE_LARGE; rtmp_pakt.m_nInfoField2 = rtmp_->m_stream_id; memcpy(rtmp_pakt.m_body, buf, bufLen); int retval = RTMP_SendPacket(rtmp_, &rtmp_pakt, 0); RTMPPacket_Free(&rtmp_pakt); return !!retval; }
int RtmpAudio::send(unsigned int user_ts, unsigned int size) { m_sender.lock(); if(!sender || !play_stream_id) { //DBG("!sender || !play_stream_id"); m_sender.unlock(); return 0; } // - generate a new RTMP audio packet // - send packet RTMPPacket packet; RTMPPacket_Reset(&packet); packet.m_headerType = send_offset_i ? RTMP_PACKET_SIZE_MEDIUM : RTMP_PACKET_SIZE_LARGE; packet.m_packetType = RTMP_PACKET_TYPE_AUDIO; packet.m_nChannel = 4;//TODO packet.m_nInfoField2 = play_stream_id; if(!send_offset_i){ send_rtmp_offset = user_ts; send_offset_i = true; } unsigned int rtmp_ts = (user_ts - send_rtmp_offset) / (SPEEX_WB_SAMPLE_RATE/1000); packet.m_nTimeStamp = rtmp_ts; RTMPPacket_Alloc(&packet,size+1); packet.m_nBodySize = size+1; // soundType (byte & 0x01) » 0 // 0: mono, 1: stereo // soundSize (byte & 0x02) » 1 // 0: 8-bit, 1: 16-bit // soundRate (byte & 0x0C) » 2 // 0: 5.5 kHz, 1: 11 kHz, 2: 22 kHz, 3: 44 kHz // soundFormat (byte & 0xf0) » 4 // 0: Uncompressed, 1: ADPCM, 2: MP3, 5: Nellymoser 8kHz mono, 6: Nellymoser, 11: Speex // 0xB2: speex, 16kHz packet.m_body[0] = 0xB2; memcpy(packet.m_body+1,(unsigned char*)samples,size); //DBG("sending audio packet: size=%u rtmp_ts=%u StreamID=%u (rtp_ts=%u)\n", // size+1,rtmp_ts,play_stream_id,user_ts); sender->push_back(packet); m_sender.unlock(); //dump_audio(&packet); RTMPPacket_Free(&packet); return size; }
//Publish using RTMP_SendPacket() int publish_using_packet(){ RTMP *rtmp=NULL; RTMPPacket *packet=NULL; uint32_t start_time=0; uint32_t now_time=0; //the timestamp of the previous frame long pre_frame_time=0; long lasttime=0; int bNextIsKey=1; uint32_t preTagsize=0; //packet attributes uint32_t type=0; uint32_t datalength=0; uint32_t timestamp=0; uint32_t streamid=0; FILE*fp=NULL; fp=fopen("../live.flv","rb"); if (!fp){ RTMP_LogPrintf("Open File Error.\n"); // CleanupSockets(); return -1; } /* set log level */ //RTMP_LogLevel loglvl=RTMP_LOGDEBUG; //RTMP_LogSetLevel(loglvl); // if (!InitSockets()){ // RTMP_LogPrintf("Init Socket Err\n"); // return -1; // } rtmp=RTMP_Alloc(); RTMP_Init(rtmp); //set connection timeout,default 30s rtmp->Link.timeout=5; if(!RTMP_SetupURL(rtmp,"rtmp://101.251.251.93:1935/myapp/mystream")) { RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n"); RTMP_Free(rtmp); // CleanupSockets(); return -1; } //if unable,the AMF command would be 'play' instead of 'publish' RTMP_EnableWrite(rtmp); if (!RTMP_Connect(rtmp,NULL)){ RTMP_Log(RTMP_LOGERROR,"Connect Err\n"); RTMP_Free(rtmp); // CleanupSockets(); return -1; } if (!RTMP_ConnectStream(rtmp,0)){ RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n"); RTMP_Close(rtmp); RTMP_Free(rtmp); // CleanupSockets(); return -1; } packet=(RTMPPacket*)malloc(sizeof(RTMPPacket)); RTMPPacket_Alloc(packet,1024*64); RTMPPacket_Reset(packet); packet->m_hasAbsTimestamp = 0; packet->m_nChannel = 0x04; packet->m_nInfoField2 = rtmp->m_stream_id; RTMP_LogPrintf("Start to send data ...\n"); //jump over FLV Header fseek(fp,9,SEEK_SET); //jump over previousTagSizen fseek(fp,4,SEEK_CUR); start_time=RTMP_GetTime(); while(1) { if((((now_time=RTMP_GetTime())-start_time) <(pre_frame_time)) && bNextIsKey){ //wait for 1 sec if the send process is too fast //this mechanism is not very good,need some improvement if(pre_frame_time>lasttime){ RTMP_LogPrintf("TimeStamp:%8lu ms\n",pre_frame_time); lasttime=pre_frame_time; } sleep(1); continue; } //not quite the same as FLV spec if(!ReadU8(&type,fp)) break; if(!ReadU24(&datalength,fp)) break; if(!ReadTime(×tamp,fp)) break; if(!ReadU24(&streamid,fp)) break; if (type!=0x08&&type!=0x09){ //jump over non_audio and non_video frame, //jump over next previousTagSizen at the same time fseek(fp,datalength+4,SEEK_CUR); continue; } if(fread(packet->m_body,1,datalength,fp)!=datalength) break; packet->m_headerType = RTMP_PACKET_SIZE_LARGE; packet->m_nTimeStamp = timestamp; packet->m_packetType = type; packet->m_nBodySize = datalength; pre_frame_time=timestamp; if (!RTMP_IsConnected(rtmp)){ RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n"); break; } if (!RTMP_SendPacket(rtmp,packet,0)){ RTMP_Log(RTMP_LOGERROR,"Send Error\n"); break; } if(!ReadU32(&preTagsize,fp)) break; if(!PeekU8(&type,fp)) break; if(type==0x09){ if(fseek(fp,11,SEEK_CUR)!=0) break; if(!PeekU8(&type,fp)){ break; } if(type==0x17) bNextIsKey=1; else bNextIsKey=0; fseek(fp,-11,SEEK_CUR); } } RTMP_LogPrintf("\nSend Data Over\n"); if(fp) fclose(fp); if (rtmp!=NULL){ RTMP_Close(rtmp); RTMP_Free(rtmp); rtmp=NULL; } if (packet!=NULL){ RTMPPacket_Free(packet); free(packet); packet=NULL; } // CleanupSockets(); return 0; }