RTMP 两种方式推流:推H.264、ACC和推FLV封装格式

一、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);
}

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(&timestamp, 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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值