librtmp发送AVC,AAC数据包

来源:互联网 发布:天刀神威捏脸数据 编辑:程序博客网 时间:2024/05/29 13:53


http://blog.csdn.net/huibailingyu/article/details/50554315


1. libRTMP的包结构

[cpp] view plain copy
  1. typedef struct RTMPPacket  
  2. {  
  3.   uint8_t  m_headerType;     
  4.   uint8_t  m_packetType;  
  5.   uint8_t  m_hasAbsTimestamp;     
  6.   int      m_nChannel;  
  7.   uint32_t m_nTimeStamp;      
  8.   int32_t  m_nInfoField2;     
  9.   uint32_t m_nBodySize;  
  10.   uint32_t m_nBytesRead;  
  11.   RTMPChunk *m_chunk;  
  12.   char    *m_body;  
  13. } RTMPPacket;  

packet->m_headerType: 可以定义如下:
[cpp] view plain copy
  1. #define RTMP_PACKET_SIZE_LARGE    0  
  2. #define RTMP_PACKET_SIZE_MEDIUM   1  
  3. #define RTMP_PACKET_SIZE_SMALL    2  
  4. #define RTMP_PACKET_SIZE_MINIMUM  3  
一般定位为 RTMP_PACKET_SIZE_MEDIUM

packet->m_packetType: 音频、视频包类型
[cpp] view plain copy
  1. #define RTMP_PACKET_TYPE_AUDIO    0x08  
  2. #define RTMP_PACKET_TYPE_VIDEO    0x09  
  3. #define RTMP_PACKET_TYPE_INFO     0x12   
还有其他更多类型,但一般都是 音频或视频

packet->m_hasAbsTimestamp: 是否使用绝对时间戳,一般定义为0。

packet->m_nChannel:音视频通道号码,音视频不要写错,
[cpp] view plain copy
  1. #define STREAM_CHANNEL_METADATA  0x03  
  2. #define STREAM_CHANNEL_VIDEO     0x04  
  3. #define STREAM_CHANNEL_AUDIO     0x05  

packet->m_nTimeStamp:时间戳
一般视频时间戳可以从0开始计算,每帧时间戳 + 1000/fps (25fps每帧递增25;30fps递增33)
音频时间戳也可以从0开始计算,48K采样每帧递增21;44.1K采样每帧递增23。

packet->m_nInfoField2 = rtmp->m_stream_id

packet->m_nBodySize:数据包长度 = NALU包长度 + 包头长度

packet->m_nBytesRead:不用管
packet->m_chunk: 不用管
packet->m_body:包头数据 + NALU数据,其长度为packet->m_nBodySize。


2. 发送视频SPS,PPS包

[cpp] view plain copy
  1. int rtmp_write_video_header(RTMP *rtmp) {  
  2.     int size = 10 + 3 + sps_pps.sps_length + 3 + sps_pps.pps_length;  
  3.   
  4.     RTMPPacket packet;  
  5.     RTMPPacket_Reset(&packet);  
  6.     RTMPPacket_Alloc(&packet, size);  
  7.     unsigned char *body = packet.m_body;  
  8.   
  9.     int i = 0;  
  10.     body[i++] = 0x17;  
  11.     body[i++] = 0x00;  
  12.   
  13.     body[i++] = 0x00;  
  14.     body[i++] = 0x00;  
  15.     body[i++] = 0x00;  
  16.   
  17.     //AVCDecoderConfigurationRecord  
  18.     body[i++] = 0x01;  
  19.     body[i++] = sps_pps.sps_data[1];  
  20.     body[i++] = sps_pps.sps_data[2];  
  21.     body[i++] = sps_pps.sps_data[3];  
  22.     body[i++] = 0xFF;  
  23.   
  24.     //sps  
  25.     body[i++] = 0xE1;  
  26.     body[i++] = (sps_pps.sps_length >> 8) & 0xFF;  
  27.     body[i++] =  sps_pps.sps_length       & 0xFF;  
  28.     memcpy(&body[i], sps_pps.sps_data, sps_pps.sps_length);  // 复制sps数据  
  29.     i +=  sps_pps.sps_length;  
  30.   
  31.     // pps  
  32.     body[i++] = 0x01;  
  33.     body[i++] = (sps_pps.pps_length >> 8) & 0xFF;  
  34.     body[i++] =  sps_pps.pps_length       & 0xFF;  
  35.     memcpy(&body[i], sps_pps.pps_data, sps_pps.pps_length);  // 复制pps数据  
  36.     i +=  sps_pps.pps_length;  
  37.   
  38.     packet->m_headerType  = RTMP_PACKET_SIZE_MEDIUM;  
  39.     packet->m_packetType = RTMP_PACKET_TYPE_VIDEO;  
  40.     packet->m_hasAbsTimestamp = 0;  
  41.     packet->m_nChannel   = STREAM_CHANNEL_VIDEO;  
  42.     packet->m_nTimeStamp = 0;  
  43.     packet->m_nInfoField2 = rtmp->m_stream_id;  
  44.     packet->m_nBodySize  = size;  
  45.   
  46.     //调用发送接口  
  47.     int nRet = RTMP_SendPacket(rtmp, packet, TRUE);  
  48.     RTMPPacket_Free(&packet);  
  49.     return nRet;  
  50. }  

在最开始发送一次即可。

3. 发送视频数据包

[cpp] view plain copy
  1. <pre name="code" class="cpp">int rtmp_write_video_frame(RTMP *rtmp, const BYTE *nalu_data, int slice_count, int nTimestamp){  
  2.     int n;  
  3.     int nRet =0;  
  4.     int size = 0;  
  5.     for(n=0; n<slice_count; n++)  
  6.         size += (slice[n].slice_length + 4);  // 每个slice数据前要加4字节的slice长度  
  7.   
  8.     size += 5;                                // 5字节头  
  9.     RTMPPacket packet;  
  10.     RTMPPacket_Reset(&packet);  
  11.     RTMPPacket_Alloc(&packet, size);  
  12.     unsigned char *body = packet.m_body;  
  13.   
  14.     // NALU size  
  15.     int i=0;  
  16.     body[0] = ((slice[0].slice_type&0x1F) == 0x5) ? 0x17 : 0x27;  
  17.     body[1] = 0x01;  // AVC NALU  
  18.     body[2] = 0x00;  
  19.     body[3] = 0x00;  
  20.     body[4] = 0x00;  
  21.     i=5;  
  22.   
  23.     //包体内存  
  24.     packet.m_headerType  = RTMP_PACKET_SIZE_LARGE;  
  25.     packet.m_packetType = RTMP_PACKET_TYPE_VIDEO;  
  26.     packet.m_hasAbsTimestamp = 0;  
  27.     packet.m_nChannel   = STREAM_CHANNEL_VIDEO;  
  28.     packet.m_nTimeStamp = nTimestamp;  
  29.     packet.m_nInfoField2 = rtmp->m_stream_id;  
  30.     packet.m_nBodySize  = size;  
  31.   
  32.     for(n=0; n<slice_count; n++) {  
  33.         int len = slice[n].slice_length;  
  34.         int_to_bytes(len, &body[i], 4);  
  35.         i+=4;  
  36.         memcpy(&body[i], nalu_data + slice[n].start_address, len);  
  37.         i += len;  
  38.     }  
  39.   
  40.     //发送  
  41.     if (RTMP_IsConnected(rtmp)){  
  42.         nRet = RTMP_SendPacket(rtmp, &packet, TRUE); //TRUE为放进发送队列,FALSE是不放进发送队列,直接发送  
  43.         if(nRet <= 0) {  
  44.             printf("RTMP_SendPacket Error\n");  
  45.         }  
  46.     }  
  47.   
  48.     //释放内存  
  49.     RTMPPacket_Free(&packet);  
  50.     return nRet;  
  51. }  


4. 发送音频头包

[cpp] view plain copy
  1. int rtmp_write_audio_header(RTMP *rtmp){  
  2.     RTMPPacket packet;  
  3.     RTMPPacket_Reset(&packet);  
  4.     RTMPPacket_Alloc(&packet, 4);  
  5.   
  6.     packet.m_body[0] = 0xAF;  // MP3 AAC format 48000Hz  
  7.     packet.m_body[1] = 0x00;  
  8.     packet.m_body[2] = 0x11;  
  9.     packet.m_body[3] = 0x90;//0x10修改为0x90,2016-1-19  
  10.   
  11.     packet.m_headerType  = RTMP_PACKET_SIZE_MEDIUM;  
  12.     packet.m_packetType = RTMP_PACKET_TYPE_AUDIO;  
  13.     packet.m_hasAbsTimestamp = 0;  
  14.     packet.m_nChannel   = STREAM_CHANNEL_AUDIO;  
  15.     packet.m_nTimeStamp = 0;  
  16.     packet.m_nInfoField2 = rtmp->m_stream_id;  
  17.     packet.m_nBodySize  = 4;  
  18.   
  19.     //调用发送接口  
  20.     int nRet = RTMP_SendPacket(rtmp, &packet, TRUE);  
  21.     RTMPPacket_Free(&packet);//释放内存  
  22.     return nRet;  
  23. }  
在最开始发送一次即可。


5. 发送音频包

[cpp] view plain copy
  1. int rtmp_write_audio_data(RTMP *rtmp, const BYTE *nalu_data, int nalu_size, int audio_TimeStamp){  
  2.     //rtmp包结构  
  3.     int size = nalu_size + 2;  
  4.     RTMPPacket packet;  
  5.     RTMPPacket_Reset(&packet);  
  6.     RTMPPacket_Alloc(&packet, size);  
  7.   
  8.     int i=0;  
  9.     // MP3 AAC format 48000Hz  
  10.     packet.m_body[i++] = 0xAF;  
  11.     packet.m_body[i++] = 0x01;  
  12.     memcpy(&packet.m_body[i], nalu_data, nalu_size);  
  13.   
  14.     packet.m_headerType  = RTMP_PACKET_SIZE_MEDIUM;  
  15.     packet.m_packetType = RTMP_PACKET_TYPE_AUDIO;  
  16.     packet.m_hasAbsTimestamp = 0;  
  17.     packet.m_nChannel   = STREAM_CHANNEL_AUDIO;  
  18.     packet.m_nTimeStamp = audio_TimeStamp;  
  19.     packet.m_nInfoField2 = rtmp->m_stream_id;  
  20.     packet.m_nBodySize  = size;  
  21.   
  22.     //调用发送接口  
  23.     int nRet = RTMP_SendPacket(rtmp, &packet, TRUE);  
  24.     RTMPPacket_Free(&packet);//释放内存  
  25.     return nRet;  
  26. }  

6. 本地存储packet

[cpp] view plain copy
  1. int RTMP_SendPacket_wrap(RTMP_ *rtmp, RTMPPacket *packet, int queue){  
  2. #if OUTPUT_FLV  
  3.     uint8_t data[] = {0x09,  
  4.         0x00, 0x00, 0x00,  
  5.         0x00, 0x00, 0x00, 0x00,  
  6.         0x00, 0x00, 0x00 };  
  7.     if(packet->m_packetType == RTMP_PACKET_TYPE_VIDEO){  
  8.         data[0] = 0x09;  
  9.     } else if(packet->m_packetType == RTMP_PACKET_TYPE_AUDIO){  
  10.         data[0] = 0x08;  
  11.     }  
  12.     int len = 0;  
  13.     int_to_bytes(packet->m_nBodySize,  &data[1], 3);  // 3字节 包内容长度  
  14.     int_to_bytes(packet->m_nTimeStamp, &data[4], 3);  // 3字节 时间戳,没用第4字节,太长的文件会溢出  
  15.     len += fwrite(data, 1, 11, flv_fp);               // 写入包头11字节  
  16.     len += fwrite(packet->m_body, 1, packet->m_nBodySize, flv_fp); // 写入数据包体  
  17.     int_to_bytes(len, &data[0], 4);                   // 写入的总字节长度  
  18.     fwrite(data, 1, 4, flv_fp);                       // 等于前Tag总长度  
  19. #endif  
  20.     return RTMP_SendPacket(rtmp, packet, queue);  
  21. }  


0
 
0
 

原创粉丝点击