一、RTMP推流方式一:推H.264、ACC
1、创建一个线程来初始化RTMP。
void RtmpPush::init() {
LOGE("init()");
mCallJava->onConnectint(THREAD_MAIN);
pthread_create(&push_thread, NULL, callBackPush, this);
}
void *callBackPush(void *data)
{
RtmpPush *rtmpPush = static_cast<RtmpPush *>(data);
rtmpPush->startPushing = false;
LOGE("callBackPush()");
//RTMP 申请堆内存
rtmpPush->rtmp = RTMP_Alloc();
//RTMP 初始化
RTMP_Init(rtmpPush->rtmp);
rtmpPush->rtmp->Link.timeout = 10;
rtmpPush->rtmp->Link.lFlags |= RTMP_LF_LIVE;
//设置推流地址
RTMP_SetupURL(rtmpPush->rtmp, rtmpPush->url);
//打开输出模式,这里推流的时候.(拉流的时候可以不用开启)
RTMP_EnableWrite(rtmpPush->rtmp);
//连接服务器
if(!RTMP_Connect(rtmpPush->rtmp, NULL))
{
//LOGE("can not connect the url");
rtmpPush->mCallJava->onConnectFail("RTMPConnectsFaile");
goto end;
}
if(!RTMP_ConnectStream(rtmpPush->rtmp, 0))
{
//LOGE("can not connect the stream of service");
rtmpPush->mCallJava->onConnectFail("RTMPConnectStreamFaile");
goto end;
}
rtmpPush->mCallJava->onConnectsuccess();
LOGE("链接成功, 开始推流");
rtmpPush->startPushing = true;
rtmpPush->startTime = RTMP_GetTime();
while(true)
{
if(!rtmpPush->startPushing)
{
break;
}
RTMPPacket *packet = NULL;
packet = rtmpPush->queue->getRtmpPacket();
if(packet != NULL)
{
//发送数据包
int result = RTMP_SendPacket(rtmpPush->rtmp, packet, 1);
//LOGE("RTMP_SendPacket result is %d", result);
if(!result){
rtmpPush->mCallJava->onConnectFail("rtmpSocketDisconnect");
goto end;
}
RTMPPacket_Free(packet);
free(packet);
packet = NULL;
}
}
end:
RTMP_Close(rtmpPush->rtmp);
RTMP_Free(rtmpPush->rtmp);
rtmpPush->rtmp = NULL;
pthread_exit(&rtmpPush->push_thread);
}
本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓
2、RTMP发送SPS、PPS
void RtmpPush::pushSPSPPS(char *sps, int sps_len, char *pps, int pps_len) {
int bodysize = sps_len + pps_len + 16;
RTMPPacket *packet = static_cast<RTMPPacket *>(malloc(sizeof(RTMPPacket)));
RTMPPacket_Alloc(packet, bodysize);
RTMPPacket_Reset(packet);
char *body = packet->m_body;
int i = 0;
body[i++] = 0x17;
body[i++] = 0x00;
body[i++] = 0x00;
body[i++] = 0x00;
body[i++] = 0x00;
body[i++] = 0x01;
body[i++] = sps[1];
body[i++] = sps[2];
body[i++] = sps[3];
body[i++] = 0xFF;
body[i++] = 0xE1;
body[i++] = (sps_len >> 8) & 0xff;
body[i++] = sps_len & 0xff;
memcpy(&body[i], sps, sps_len);
i += sps_len;
body[i++] = 0x01;
body[i++] = (pps_len >> 8) & 0xff;
body[i++] = pps_len & 0xff;
memcpy(&body[i], pps, pps_len);
packet->m_packetType = RTMP_PACKET_TYPE_VIDEO;
packet->m_nBodySize = bodysize;
packet->m_nTimeStamp = 0;
packet->m_hasAbsTimestamp = 0;
packet->m_nChannel = 0x04;
packet->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
packet->m_nInfoField2 = rtmp->m_stream_id;
queue->putRtmpPacket(packet);
}
3、发送视频数据
void RtmpPush::pushVideoData(char *data, int data_len, bool keyframe) {
int bodysize = data_len + 9;
RTMPPacket *packet = static_cast<RTMPPacket *>(malloc(sizeof(RTMPPacket)));
RTMPPacket_Alloc(packet, bodysize);
RTMPPacket_Reset(packet);
char *body = packet->m_body;
int i = 0;
if(keyframe)
{
body[i++] = 0x17;
} else{
body[i++] = 0x27;
}
body[i++] = 0x01;
body[i++] = 0x00;
body[i++] = 0x00;
body[i++] = 0x00;
body[i++] = (data_len >> 24) & 0xff;
body[i++] = (data_len >> 16) & 0xff;
body[i++] = (data_len >> 8) & 0xff;
body[i++] = data_len & 0xff;
memcpy(&body[i], data, data_len);
packet->m_packetType = RTMP_PACKET_TYPE_VIDEO;
packet->m_nBodySize = bodysize;
packet->m_nTimeStamp = RTMP_GetTime() - startTime;
packet->m_hasAbsTimestamp = 0;
packet->m_nChannel = 0x04;
packet->m_headerType = RTMP_PACKET_SIZE_LARGE;
packet->m_nInfoField2 = rtmp->m_stream_id;
queue->putRtmpPacket(packet);
}
4、发送音频数据
void RtmpPush::pushAudioData(char *data, int data_len) {
int bodysize = data_len + 2;
RTMPPacket *packet = static_cast<RTMPPacket *>(malloc(sizeof(RTMPPacket)));
RTMPPacket_Alloc(packet, bodysize);
RTMPPacket_Reset(packet);
char *body = packet->m_body;
body[0] = 0xAF;
body[1] = 0x01;
memcpy(&body[2], data, data_len);
packet->m_packetType = RTMP_PACKET_TYPE_AUDIO;
packet->m_nBodySize = bodysize;
packet->m_nTimeStamp = RTMP_GetTime() - startTime;
packet->m_hasAbsTimestamp = 0;
packet->m_nChannel = 0x04;
packet->m_headerType = RTMP_PACKET_SIZE_LARGE;
packet->m_nInfoField2 = rtmp->m_stream_id;
queue->putRtmpPacket(packet);
}
二、RTMP推流方式二:推FLV封装格式
int RtmpPush::pushFlvData(char *data, int data_len) {
if (data_len < 15) {
return -1;
}
//packet attributes
uint32_t type = 0;
uint32_t datalength = 0;
uint32_t timestamp = 0;
uint32_t streamid = 0;
memcpy(&type, data, 1);
data++;
memcpy(&datalength, data, 3);
datalength = HTON24(datalength);
data += 3;
memcpy(×tamp, data, 4);
timestamp = HTONTIME(timestamp);
data += 4;
memcpy(&streamid, data, 3);
streamid = HTON24(streamid);
data += 3;
//LOGE("解析包数据:%u,%u,%u,%u,%d",type, datalength, timestamp, streamid, data_len);
if (type != 0x08 && type != 0x09) {
return -2;
}
if (datalength != (data_len - 11 - 4)) {
return -3;
}
RTMPPacket *packet = static_cast<RTMPPacket *>(malloc(sizeof(RTMPPacket)));
RTMPPacket_Alloc(packet, 1024 * 64);
RTMPPacket_Reset(packet);
memcpy(packet->m_body, data, data_len - 11 - 4);
packet->m_headerType = RTMP_PACKET_SIZE_LARGE;
packet->m_nTimeStamp = timestamp;
packet->m_packetType = type;
packet->m_nBodySize = datalength;
if(type == RTMP_PACKET_TYPE_AUDIO){
packet->m_nChannel = 0x05;//audio
}else if(type == RTMP_PACKET_TYPE_VIDEO){
packet->m_nChannel = 0x04;//video
}else if(type == RTMP_PACKET_TYPE_INFO){
packet->m_nChannel = 0x03;//metaData
}
packet->m_nInfoField2 = rtmp->m_stream_id;
queue->putRtmpPacket(packet);
return 0;
}
本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓