rtp發送h264 vlc進行播放

//在網上找到的demo都是linux的,我將他改爲vc的工程,推流成功

#include "stdio.h"
#include "string.h"
#include "rtp.h"
#include <windows.h>

//Windows套接字所需的頭文件
#include <WINSOCK.H>
//Windows套接字接口的庫文件
#pragma comment(lib, "WSOCK32.LIB")
//程序使用的WinSock主版本
#define SOCK_VER 2

 

#define FramePreSec    25
int main(int argc, char* argv[])
{
    SOCKET sock;
    char *sendbuf;
    RTP_FIXED_HEADER *pRtpHeader;
    int ret, addr, time_cnt = 0x00000000, seq_num = 0, sendcnt = 0;
    S_NULU nalu;
    FILE *fp;
    sock = InitUDP();
    if (sock==0)
    {
        printf("socket err");
        return 1;
    }
    nalu.buf = new char[MAX_NALU_SIZE];
    sendbuf = new char[sizeof(RTP_FIXED_HEADER) +2+ MAX_RTP_PKT_LENGTH];        //1 is 用於分包時候計算的數據
    pRtpHeader = (RTP_FIXED_HEADER *)sendbuf;
    nalu.max_size = MAX_NALU_SIZE;
    fp = fopen("test.h264", "rb");
    pRtpHeader = (RTP_FIXED_HEADER*)&sendbuf[0];
    //設置RTP HEADER,  
    
    //4 位。表示跟在 RTP 固定包頭後面CSRC 的數目,對於本文所要實現的基本的流媒體服務器來說,沒有用到混合器,該位也設爲 0x0
    pRtpHeader->csrc_len = 0;
    //rtp_hdr->extension=0;
    //rtp_hdr->padding=0;
    pRtpHeader->payload = H264;                      //負載類型號, h264
    pRtpHeader->version = 2;                          //版本號,此版本固定爲2  
    pRtpHeader->marker = 0;                           //標誌位,由具體協議規定其值。  
    pRtpHeader->ssrc = htonl(0xA53D8F5D);             //隨機指定爲10,並且在本RTP會話中全局唯一  bytes 8-11
    do{
        //if (feof(fp))    fseek(fp, 0, SEEK_SET);
        //addr = ftell(fp);
        //printf("file addr:%06X ", addr);
        ret = GetAnnexbNALU(&nalu, fp);
        if (ret == 0)
        {
            printf("nalutype:%02X,len:%d\r\n", nalu.buf[0], nalu.len);
        }
        //獲取幀成功
        //設定 rtp header
        if (nalu.len <= MAX_RTP_PKT_LENGTH)
        {
            //設置rtp M 位,1 位。如果當前 NALU爲一個接入單元最後的那個NALU,那麼將M位置 1;或者當前RTP 數據包爲一個NALU 的最後的那個分片時(NALU 的分片在後面講述),M位置 1。其餘情況下M 位保持爲 0
            pRtpHeader->marker = 1;                        
            if (nalu.nal_unit_type < 6 || nalu.nal_unit_type>8)
            {
                time_cnt += 90000 / FramePreSec;    //6-8不是顯示數據幀
            }
            pRtpHeader->timestamp = htonl(time_cnt);
            pRtpHeader->seq_no = htons(seq_num++);                                        //序列號,每發送一個RTP包增1
            //sendbuf[12]和nalu.buf[0] 是 NALU_HEADER ,數據一樣
            memcpy(sendbuf + sizeof(RTP_FIXED_HEADER), nalu.buf, nalu.len);
            sendcnt+=UdpSendData(sendbuf, nalu.len + sizeof(RTP_FIXED_HEADER), sock);
        }
        else
        {

            int cnt= nalu.len-1,len;
            char *pGetBuf=nalu.buf+1;
            //設置rtp M 位,1 位。如果當前 NALU爲一個接入單元最後的那個NALU,那麼將M位置 1;或者當前RTP 數據包爲一個NALU 的最後的那個分片時(NALU 的分片在後面講述),M位置 1。其餘情況下M 位保持爲 0
            pRtpHeader->marker = 0;
            time_cnt += 90000 / FramePreSec; pRtpHeader->timestamp = htonl(time_cnt);
            sendbuf[12] = (nalu.buf[0] & 0xE0) | 0x1C;    //將sendbuf[12]的地址賦給fu_ind,之後對fu_ind的寫入就將寫入sendbuf中;      
            sendbuf[13] = 0x80 | (nalu.buf[0]&0x1F);    //0x80 組包開始標識begin flag
            do{
                if (cnt >= 1400)    len = 1400;
                else                len = cnt;
                memcpy(sendbuf + 14, pGetBuf, len);
                pGetBuf += len;
                cnt -= len;
                if (cnt <= 0)
                {
                    pRtpHeader->marker = 1;
                    sendbuf[13] |= 0x40;                //組包結束標誌
                }
                pRtpHeader->seq_no = htons(seq_num++);                        //序列號,每發送一個RTP包增1
                sendcnt += UdpSendData(sendbuf, len + sizeof(RTP_FIXED_HEADER) + 2, sock);
                sendbuf[13] &= 0x1F;
                //printf(".");
            } while (cnt);
            printf("wait:%d\r\n", seq_num); //getchar();
        }
        if (nalu.nal_unit_type < 6 || nalu.nal_unit_type>8)    Sleep(1000 / FramePreSec);
    } while (ret == 0);
    printf("send:%d\r\n", sendcnt);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章