RTSP拉流 简易版代码

TCP方式拉流 RTSP

主要是 对TCP传输方式 的RTSP 提取出视频数据包  


#define RECVBUF_SIZE 10 * 8192
#define RTP_PACKET_SIZE 4096#define RTP_VERSION 2 // RTP version field must equal 2 (p66)typedef struct _rtp_header_t
{uint32_t v:2;		/* protocol version */uint32_t p:1;		/* padding flag */uint32_t x:1;		/* header extension flag */uint32_t cc:4;		/* CSRC count */uint32_t m:1;		/* marker bit */uint32_t pt:7;		/* payload type */uint32_t seq:16;	/* sequence number */uint32_t timestamp; /* timestamp */uint32_t ssrc;		/* synchronization source */
} rtp_header_t;#define RTP_V(v)	((v >> 30) & 0x03) /* protocol version */
#define RTP_P(v)	((v >> 29) & 0x01) /* padding flag */
#define RTP_X(v)	((v >> 28) & 0x01) /* header extension flag */
#define RTP_CC(v)	((v >> 24) & 0x0F) /* CSRC count */
#define RTP_M(v)	((v >> 23) & 0x01) /* marker bit */
#define RTP_PT(v)	((v >> 16) & 0x7F) /* payload type */
#define RTP_SEQ(v)	((v >> 00) & 0xFFFF) /* sequence number *//// RTP packet lost(miss packet before this frame)
#define RTP_PAYLOAD_FLAG_PACKET_LOST	0x0100 // some packets lost before the packet
#define RTP_PAYLOAD_FLAG_PACKET_CORRUPT 0x0200 // the packet data is corrupt#define RTP_PAYLOAD_MAX_SIZE			(10 * 1024 * 1024)#define RTP_FIXED_HEADER 12struct rtp_payload_t
{void* (*alloc)(void* param, int bytes);void (*free)(void* param, void *packet);/// @return 0-ok, other-errorint (*packet)(void* param, const void *packet, int bytes, uint32_t timestamp, int flags);
};struct rtp_packet_t
{rtp_header_t rtp;uint32_t csrc[16];const void* extension; // extension(valid only if rtp.x = 1)uint16_t extlen; // extension length in bytesuint16_t extprofile; // extension reservedconst void* payload; // payloadint payloadlen; // payload length in bytes
};struct rtp_decode_h264_t
{struct rtp_payload_t handler;void* cbparam;uint16_t seq; // rtp sequint32_t timestamp;uint8_t* ptr;int size, capacity;int flags;//For H265int using_donl_field;};static inline uint16_t rtp_read_uint16(const uint8_t* ptr)
{return (((uint16_t)ptr[0]) << 8) | ptr[1];
}static inline uint32_t rtp_read_uint32(const uint8_t* ptr)
{return (((uint32_t)ptr[0]) << 24) | (((uint32_t)ptr[1]) << 16) | (((uint32_t)ptr[2]) << 8) | ptr[3];
}#define H264_NAL(v)	((v) & 0x1F)
#define FU_START(v) ((v) & 0x80)
#define FU_END(v)	((v) & 0x40)
#define FU_NAL(v)	((v) & 0x1F)#define FU_NAL_H265(v)	((v) & 0x3F)#define H265_TYPE(v) (((v) >> 1) & 0x3f)FILE *g_file = nullptr;// RFC3550 RTP: A Transport Protocol for Real-Time Applications
// 5.1 RTP Fixed Header Fields (p12)
/*0               1               2               30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X|   CC  |M|     PT      |      sequence number          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           timestamp                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                synchronization source (SSRC) identifier       |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|                 contributing source (CSRC) identifiers        |
|                               ....                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/int rtp_packet_deserialize(struct rtp_packet_t *pkt, const void* data, int bytes)
{uint32_t i, v;int hdrlen;const uint8_t *ptr;if (bytes < RTP_FIXED_HEADER) // RFC3550 5.1 RTP Fixed Header Fields(p12)return -1;ptr = (const unsigned char *)data;memset(pkt, 0, sizeof(struct rtp_packet_t));// pkt headerv = rtp_read_uint32(ptr);pkt->rtp.v = RTP_V(v);pkt->rtp.p = RTP_P(v);pkt->rtp.x = RTP_X(v);pkt->rtp.cc = RTP_CC(v);pkt->rtp.m = RTP_M(v);pkt->rtp.pt = RTP_PT(v);pkt->rtp.seq = RTP_SEQ(v);pkt->rtp.timestamp = rtp_read_uint32(ptr + 4);pkt->rtp.ssrc = rtp_read_uint32(ptr + 8);assert(RTP_VERSION == pkt->rtp.v);hdrlen = RTP_FIXED_HEADER + pkt->rtp.cc * 4;if (RTP_VERSION != pkt->rtp.v || bytes < hdrlen + (pkt->rtp.x ? 4 : 0) + (pkt->rtp.p ? 1 : 0))return -1;// pkt contributing sourcefor (i = 0; i < pkt->rtp.cc; i++){pkt->csrc[i] = rtp_read_uint32(ptr + 12 + i * 4);}assert(bytes >= hdrlen);pkt->payload = (uint8_t*)ptr + hdrlen;pkt->payloadlen = bytes - hdrlen;// pkt header extensionif (1 == pkt->rtp.x){const uint8_t *rtpext = ptr + hdrlen;assert(pkt->payloadlen >= 4);pkt->extension = rtpext + 4;pkt->extprofile = rtp_read_uint16(rtpext);pkt->extlen = rtp_read_uint16(rtpext + 2) * 4;if (pkt->extlen + 4 > pkt->payloadlen){assert(0);return -1;}else{pkt->payload = rtpext + pkt->extlen + 4;pkt->payloadlen -= pkt->extlen + 4;}}// paddingif (1 == pkt->rtp.p){uint8_t padding = ptr[bytes - 1];if (pkt->payloadlen < padding){assert(0);return -1;}else{pkt->payloadlen -= padding;}}return 0;
}// 5.7.1. Single-Time Aggregation Packet (STAP) (p23)
/*0               1               2               30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           RTP Header                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|STAP-B NAL HDR |            DON                |  NALU 1 Size  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NALU 1 Size   | NALU 1 HDR    |         NALU 1 Data           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
:                                                               :
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|               | NALU 2 Size                   |   NALU 2 HDR  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            NALU 2 Data                        |
:                                                               :
|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               :    ...OPTIONAL RTP padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static int rtp_h264_unpack_stap(struct rtp_decode_h264_t *unpacker, const uint8_t* ptr, int bytes, uint32_t timestamp, int stap_b)
{int r, n;uint16_t len;uint16_t don;r = 0;n = stap_b ? 3 : 1;if (bytes < n){assert(0);return -EINVAL; // error}don = stap_b ? rtp_read_uint16(ptr + 1) : 0;ptr += n; // STAP-A / STAP-B HDR + DONfor(bytes -= n; 0 == r && bytes > 2; bytes -= len + 2){len = rtp_read_uint16(ptr);if(len + 2 > bytes || len < 2){assert(0);unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;unpacker->size = 0;return -EINVAL; // error}assert(H264_NAL(ptr[2]) > 0 && H264_NAL(ptr[2]) < 24);//printf("len = %d ptr+2=%02X bytes = %d r = %d\n",len,*(ptr+2),bytes,r);//PrintHex((unsigned char *) (ptr + 2), len);unpacker->handler.packet(unpacker->cbparam, ptr + 2, len, timestamp, unpacker->flags);//printf("After  len = %d ptr+2=%02X bytes = %d r = %d\n",len,*(ptr+2),bytes,r);unpacker->flags = 0;unpacker->size = 0;ptr += len + 2; // next NALUdon = (don + 1) % 65536;}return 0 == r ? 1 : r; // packet handled
}// 5.8. Fragmentation Units (FUs) (p29)
/*0               1               2               30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  FU indicator |   FU header   |              DON              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
|                                                               |
|                          FU payload                           |
|                                                               |
|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               :   ...OPTIONAL RTP padding     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static int rtp_h264_unpack_fu(struct rtp_decode_h264_t *unpacker, const uint8_t* ptr, int bytes, uint32_t timestamp, int fu_b)
{int r, n;uint8_t fuheader;//uint16_t don;r = 0;n = fu_b ? 4 : 2;if (bytes < n || unpacker->size + bytes - n > RTP_PAYLOAD_MAX_SIZE){assert(0);return -EINVAL; // error}if (unpacker->size + bytes - n + 1 /*NALU*/ > unpacker->capacity){void* p = NULL;int size = unpacker->size + bytes + 1;size += size / 4 > 128000 ? size / 4 : 128000;//printf("realloc  packer size = %d  fuheader = %02X capacity = %d \n",unpacker->size,fuheader,unpacker->capacity);p = realloc(unpacker->ptr, size);if (!p){//printf("FU_END case ENOMEM RTP_PAYLOAD_FLAG_PACKET_LOST %d\n",unpacker->size);	assert(0);// set packet lost flagunpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;unpacker->size = 0;return -ENOMEM; // error}unpacker->ptr = (uint8_t*)p;unpacker->capacity = size;}//PrintHex((unsigned char *) ptr,16);fuheader = ptr[1];//don = nbo_r16(ptr + 2);if (FU_START(fuheader)){
#if 0if (unpacker->size > 0){unpacker->flags |= RTP_PAYLOAD_FLAG_PACKET_CORRUPT;unpacker->handler.packet(unpacker->cbparam, unpacker->ptr, unpacker->size, unpacker->timestamp, unpacker->flags);unpacker->flags = 0;unpacker->size = 0; // reset}
#endifunpacker->size = 1; // NAL unit type byteunpacker->ptr[0] = (ptr[0]/*indicator*/ & 0xE0) | (fuheader & 0x1F);assert(H264_NAL(unpacker->ptr[0]) > 0 && H264_NAL(unpacker->ptr[0]) < 24);}else{if (0 == unpacker->size){unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;printf("FU_END case --------------->>>>>>>>>>>>>>>>>>>>>>>>RTP_PAYLOAD_FLAG_PACKET_LOST %d  fuheader = %02X \n",unpacker->size,fuheader);return 0; // packet discard}assert(unpacker->size > 0);}unpacker->timestamp = timestamp;if (bytes > n){assert(unpacker->capacity >= unpacker->size + bytes - n);memmove(unpacker->ptr + unpacker->size, ptr + n, bytes - n);unpacker->size += bytes - n;}if(FU_END(fuheader)){if(unpacker->size > 0){//printf("FU_END case %d\n",unpacker->size);r = unpacker->handler.packet(unpacker->cbparam, unpacker->ptr, unpacker->size, timestamp, unpacker->flags);}unpacker->flags = 0;unpacker->size = 0; // reset}return 0 == r ? 1 : r; // packet handled
}// 4.4.2. Aggregation Packets (APs) (p25)
/*0               1               2               30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          RTP Header                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      PayloadHdr (Type=48)     |           NALU 1 DONL         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           NALU 1 Size         |            NALU 1 HDR         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                         NALU 1 Data . . .                     |
|                                                               |
+     . . .     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|               |  NALU 2 DOND  |            NALU 2 Size        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          NALU 2 HDR           |                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+            NALU 2 Data        |
|                                                               |
|         . . .                 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               :    ...OPTIONAL RTP padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static int rtp_h265_unpack_ap(struct rtp_decode_h264_t *unpacker, const uint8_t* ptr, int bytes, uint32_t timestamp)
{int r;int n;int len;//uint16_t donl;//uint16_t dond;//donl = unpacker->using_donl_field ? nbo_r16(ptr + 2) : 0;ptr += 2; // PayloadHdrn = 2 /*LEN*/ + (unpacker->using_donl_field ? 2 : 0);r = 0;for (bytes -= 2 /*PayloadHdr*/; 0 == r && bytes > n; bytes -= len + 2){bytes -= n - 2; // skip DONptr += n - 2; // skip DONlen = rtp_read_uint16(ptr);if (len + 2 > bytes || len < 3){assert(0);unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;unpacker->size = 0;return -EINVAL; // error}//PrintHex((unsigned char *) (ptr + 2), len);assert(H265_TYPE(ptr[2]) >= 0 && H265_TYPE(ptr[2]) < 48);unpacker->handler.packet(unpacker->cbparam, ptr + 2, len, timestamp, unpacker->flags);unpacker->flags = 0;unpacker->size = 0;ptr += len + 2; // next NALUn = 2 /*LEN*/ + (unpacker->using_donl_field ? 1 : 0);}return 0 == r ? 1 : r; // packet handled
}// 4.4.3. Fragmentation Units (p29)
/*0               1               2               30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     PayloadHdr (Type=49)      |    FU header  |  DONL (cond)  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
|  DONL (cond)  |                                               |
|-+-+-+-+-+-+-+-+                                               |
|                           FU payload                          |
|                                                               |
|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               :    ...OPTIONAL RTP padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|   FuType  |
+---------------+
*/
static int rtp_h265_unpack_fu(struct rtp_decode_h264_t *unpacker, const uint8_t* ptr, int bytes, uint32_t timestamp)
{int r, n;uint8_t fuheader;r = 0;n = 1 /*FU header*/ + (unpacker->using_donl_field ? 4 : 2);if (bytes < n || unpacker->size + bytes - n > RTP_PAYLOAD_MAX_SIZE){assert(0);return -EINVAL;}if (unpacker->size + bytes - n + 2 /*NALU*/ > unpacker->capacity){void* p = NULL;int size = unpacker->size + bytes + 2;size += size / 4 > 128000 ? size / 4 : 128000;p = realloc(unpacker->ptr, size);if (!p){// set packet lost flagunpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;unpacker->size = 0;return -ENOMEM;}unpacker->ptr = (uint8_t*)p;unpacker->capacity = size;}fuheader = ptr[2];if (FU_START(fuheader)){
#if 0if (unpacker->size > 0){unpacker->flags |= RTP_PAYLOAD_FLAG_PACKET_CORRUPT;unpacker->handler.packet(unpacker->cbparam, unpacker->ptr, unpacker->size, unpacker->timestamp, unpacker->flags);unpacker->flags = 0;unpacker->size = 0; // reset}
#endifassert(unpacker->capacity > 2);unpacker->size = 2; // NAL unit type byteunpacker->ptr[0] = (FU_NAL_H265(fuheader) << 1) | (ptr[0] & 0x81); // replace NAL Unit Type Bitsunpacker->ptr[1] = ptr[1];assert(H265_TYPE(unpacker->ptr[0]) >= 0 && H265_TYPE(unpacker->ptr[0]) <= 63);}else{if (0 == unpacker->size){unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;return 0; // packet discard}assert(unpacker->size > 0);}unpacker->timestamp = timestamp;if (bytes > n){assert(unpacker->capacity >= unpacker->size + bytes - n);memmove(unpacker->ptr + unpacker->size, ptr + n, bytes - n);unpacker->size += bytes - n;}if (FU_END(fuheader)){r = unpacker->handler.packet(unpacker->cbparam, unpacker->ptr, unpacker->size, timestamp, unpacker->flags);unpacker->flags = 0;unpacker->size = 0;}return 0 == r ? 1 : r; // packet handled
}static int OnPacket(void* param, const void *packet, int bytes, uint32_t timestamp, int flags)
{static const uint8_t start_code[4] = { 0, 0, 0, 1 };//struct rtp_payload_test_t* ctx = (struct rtp_payload_test_t*)param;int res = 0;AVPacket pkt;const char *encoder = "H264";static uint8_t buffer[2 * 1024 * 1024];RTSP_ITEM * rtsp = (RTSP_ITEM*)param;//assert(bytes + 4 < sizeof(buffer));//assert(0 == flags);size_t size = 0;if (0 == strcmp("H264", encoder) || 0 == strcmp("H265", encoder)){#if 1if ((res = av_new_packet(&pkt,bytes+4)) < 0)return res;/* A/V packet: copy start sequence *///memcpy(&packet->data, start_code, sizeof(start_code));/* A/V packet: copy NAL unit data */memcpy(pkt.data ,start_code, sizeof(start_code));size += sizeof(start_code);pkt.dts=	pkt.pts = timestamp;#elsememcpy(buffer, start_code, sizeof(start_code));size += sizeof(start_code);#endif}else if (0 == strcmp("AV1", encoder) || 0 == strcmp("AV1X", encoder)){static const uint8_t av1_temporal_delimiter[] = { 0x12, 0x00 };//memcpy(buffer, av1_temporal_delimiter, sizeof(av1_temporal_delimiter));//size += sizeof(av1_temporal_delimiter);}else if (0 == strcmp("PS", encoder)){#if 0if(!ctx->ps)ctx->ps = ps_demuxer_create(mpeg_ps_demuxer_onpacket, ctx);ps_demuxer_input(ctx->ps, (const uint8_t*)packet, bytes);#endif}#if 1memcpy(pkt.data + size, packet, bytes);size += bytes;pkt.size = size;//PrintHex((unsigned char *)pkt.data,16);#elsememcpy(buffer + size, packet, bytes);size += bytes;PrintHex((unsigned char *)buffer,16);
#endif// TODO:// check media file//fwrite(buffer, 1, size, ctx->fsource2);for(auto &x:rtsp->rtmp_items){if(x.is_valid && x.rtmp_queue){AVPacket *new_packet = av_packet_clone(&pkt);auto ret = x.rtmp_queue->PushData(new_packet);if(ret == false){printf("PushData failed size \n",new_packet->size);av_packet_free(&new_packet);}}}av_packet_unref(&pkt);return size;
}int HandleRtpVideoPacket(char *buf,int size,bool is_h264,rtp_decode_h264_t *unpacker)
{rtp_packet_t rtp_packet;uint8_t nalt;int ret;if( 0 != rtp_packet_deserialize(&rtp_packet, buf,size) || rtp_packet.payloadlen < 1){printf("rtp_packet_deserialize failed\n");return -1;}if (-1 == unpacker->flags){unpacker->flags = 0;unpacker->seq = (uint16_t)(rtp_packet.rtp.seq - 1); // disable packet lost}if ((uint16_t)rtp_packet.rtp.seq != (uint16_t)(unpacker->seq + 1)){unpacker->flags = RTP_PAYLOAD_FLAG_PACKET_LOST;unpacker->size = 0; // discard previous packets}unpacker->seq = (uint16_t)rtp_packet.rtp.seq;//printf("nalt = %02X nalt & 0x1F = %d pkt->rtp.pt = %d\n",nalt,nalt&0x1F,rtp_packet.rtp.pt);if(is_h264){nalt = ((unsigned char *)rtp_packet.payload)[0];if(rtp_packet.rtp.pt!= 96) return -1;//PrintHexRTP((unsigned char *) buf,16);//printf("End of packet bit set =%d !!!!!!!!!!!!!!! unpacker->seq = %d	packersize = %d nalt & 0x1F = %d\n",//rtp_packet.rtp.m,unpacker->seq,unpacker->size,nalt & 0x1F);switch(nalt & 0x1F){case 0: // reservedcase 31: // reservedassert(0);return -1; // packet discardcase 24: // STAP-APrintHex((unsigned char *) buf-4,size+4);return rtp_h264_unpack_stap(unpacker, (const uint8_t*)rtp_packet.payload, rtp_packet.payloadlen, rtp_packet.rtp.timestamp, 0);
#if 0case 25: // STAP-Breturn rtp_h264_unpack_stap(unpacker, (const uint8_t*)rtp_packet.payload, rtp_packet.payloadlen, rtp_packet.rtp.timestamp, 1);case 26: // MTAP16return rtp_h264_unpack_mtap(unpacker, (const uint8_t*)rtp_packet.payload, rtp_packet.payloadlen, rtp_packet.rtp.timestamp, 2);case 27: // MTAP24return rtp_h264_unpack_mtap(unpacker, (const uint8_t*)rtp_packet.payload, rtp_packet.payloadlen, rtp_packet.rtp.timestamp, 3);
#endifcase 28: // FU-Areturn rtp_h264_unpack_fu(unpacker, (const uint8_t*)rtp_packet.payload, rtp_packet.payloadlen, rtp_packet.rtp.timestamp, 0);case 29: // FU-Breturn rtp_h264_unpack_fu(unpacker, (const uint8_t*)rtp_packet.payload, rtp_packet.payloadlen, rtp_packet.rtp.timestamp, 1);default: // 1-23 NAL unit//printf("defaulh handler case %d rtp_packet.payloadlen = %d\n",nalt & 0x1F,rtp_packet.payloadlen);//PrintHex((unsigned char *) rtp_packet.payload,rtp_packet.payloadlen);ret = unpacker->handler.packet(unpacker->cbparam, (const uint8_t*)rtp_packet.payload, rtp_packet.payloadlen, rtp_packet.rtp.timestamp, unpacker->flags);unpacker->flags = 0;unpacker->size = 0;return 0 == ret ? 1 : ret; // packet handled}}else{const uint8_t* ptr = (const uint8_t*)rtp_packet.payload;nalt = H265_TYPE(ptr[0]);if (nalt > 50)return 0; // packet discard, Unsupported (HEVC) NAL typeswitch (nalt){case 48: // aggregated packet (AP) - with two or more NAL unitsreturn rtp_h265_unpack_ap(unpacker, (const uint8_t*)rtp_packet.payload, rtp_packet.payloadlen, rtp_packet.rtp.timestamp);case 49: // fragmentation unit (FU)return rtp_h265_unpack_fu(unpacker, (const uint8_t*)rtp_packet.payload, rtp_packet.payloadlen, rtp_packet.rtp.timestamp);case 50: // TODO: 4.4.4. PACI Packets (p32)assert(0);return 0; // packet discardcase 32: // video parameter set (VPS)case 33: // sequence parameter set (SPS)case 34: // picture parameter set (PPS)case 39: // supplemental enhancement information (SEI)default: // 4.4.1. Single NAL Unit Packets (p24)ret = unpacker->handler.packet(unpacker->cbparam, (const uint8_t*)rtp_packet.payload, rtp_packet.payloadlen, rtp_packet.rtp.timestamp, unpacker->flags);unpacker->flags = 0;unpacker->size = 0;return 0 == ret ? 1 : ret; // packet handled}}return 0;	
}int HandleRtcpPacket(char *buf,int size,bool is_h264,rtp_decode_h264_t *unpacker)
{return 0;
}int HandleRtpPacket(char *buf,int size,bool is_h264,rtp_decode_h264_t *unpacker)
{//RTP_PACKET* rtp_packet;uint16_t sn = 0;uint32_t ts = 0;uint8_t *payload = nullptr;rtp_packet_t rtp_packet;uint8_t nalt;static uint16_t last_sn = 0;int ret;//sn = (uint16_t)(buf[2] *256 + (buf[3] &0xFF));//ts = (uint32_t)(buf[4] *256*256*256 + buf[5] *256*256+buf[7] *256 +(buf[7] &0xFF));//payload = (uint8_t*)(buf+12);if(buf[1] ==0){//HandleRtpVideoPacket(buf+4,size-4,is_h264,unpacker);return 0;}else if(buf[1] == 1){PrintHex((unsigned char *) buf,size);HandleRtcpPacket(buf+4,size-4,is_h264,unpacker);}else if(buf[1] ==2){}else if( buf[1] ==3){PrintHex((unsigned char *) buf,size);HandleRtcpPacket(buf+4,size-4,is_h264,unpacker);}return 0;}void HandleRtspProc(RTSP_ITEM *rtsp,std::shared_ptr<Socket>& sp_socket)
{int counter = 0;char send_buf[1024] = {0};int cseq = 1;int len = 0;int need_size = 0,left_size = 0;RTSPMessageHeader reply;int saved_size = 0;char * video_buf = (char*)malloc(RTP_PACKET_SIZE);char *start = nullptr;int reset_flag = 0;rtp_decode_h264_t  h264_unpacker = {0};h264_unpacker.flags = -1;h264_unpacker.handler.alloc = nullptr;h264_unpacker.handler.free = nullptr;h264_unpacker.handler.packet = OnPacket;h264_unpacker.cbparam =(void*) rtsp;const char * rtsp_url = "rtsp://192.168.131.132:554/live/qmcy";g_file = fopen("test.h264","wb");auto ret = SendRTSPCMD("OPTIONS",rtsp_url,cseq++,"QMCY",nullptr,nullptr,nullptr,nullptr,sp_socket);if(!ret ) return;auto recv_buf = sp_socket->ReadData(len);printf("recv_buf:%s\n",recv_buf+4);if(!len) return;ParseResponse(recv_buf+4,reply);if(reply.status_code != 200) return;ret = SendRTSPCMD("DESCRIBE",rtsp_url,cseq++,"QMCY",nullptr,nullptr,nullptr,nullptr,sp_socket);if(!ret ) return;recv_buf = sp_socket->ReadData(len);printf("recv_buf:%s\n",recv_buf+4);if(!len) return;ParseResponse(recv_buf+4,reply);if(reply.status_code != 200) return;if(reply.is_h264){printf("H264!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");}else{printf("H265!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");}ret = SendRTSPCMD("SETUP","rtsp://192.168.131.132:554/live/qmcy/streamid=0",cseq++,"QMCY",reply.session_id,nullptr,nullptr,"interleaved=0-1",sp_socket);if(!ret ) return;recv_buf = sp_socket->ReadData(len);printf("recv_buf:%s\n",recv_buf+4);if(!len) return;ParseResponse(recv_buf+4,reply);if(reply.status_code != 200) return;#if 1ret = SendRTSPCMD("SETUP","rtsp://192.168.131.132:554/live/qmcy/streamid=1",cseq++,"QMCY",reply.session_id,nullptr,nullptr,"interleaved=2-3",sp_socket);if(!ret ) return;recv_buf = sp_socket->ReadData(len);printf("recv_buf:%s\n",recv_buf);if(!len) return;ParseResponse(recv_buf+4,reply);if(reply.status_code != 200) return;#endifret = SendRTSPCMD("PLAY","rtsp://192.168.131.132:554/live/qmcy/streamid=0",cseq++,"QMCY",reply.session_id,nullptr,nullptr,nullptr,sp_socket);if(!ret ) return;recv_buf = sp_socket->ReadData(len);if(!len) return;printf("len = %d\n",len);PrintHex((unsigned char *) recv_buf,len);ParseResponse(recv_buf+4,reply);if(reply.status_code != 200) return;auto rtp_magic = strstr(recv_buf+4,"\r\n\r\n");rtp_magic+=4;int rtp_size = 0;auto play_len = rtp_magic-recv_buf-4;if(len > play_len){left_size = len-play_len;start = (char*)rtp_magic;while(left_size>0 && g_app.m_run_flag){counter++;if((*start)!=0x24){printf("22222 NOT rtp start magic  start = %02X left size = %d\n",*start,left_size);}else{//PrintHex((unsigned char *) start,left_size);rtp_size = start[2]*256; rtp_size+=(start[3] & 0xFF)+4;printf("rtpsize:%d left size = %d start2 = %02X start 3 = %02X \n",rtp_size,left_size,start[2],start[3]);if(left_size>=rtp_size){		memcpy(video_buf,start,rtp_size);left_size-=rtp_size;	saved_size= rtp_size;start+=rtp_size;	}else{memcpy(video_buf,start,left_size);saved_size+= left_size;start+=left_size;need_size = rtp_size-left_size;left_size = 0;	}printf("3333 RTP start magic  start = %02X left size = %d rtp_size = %d need size = %d\n",*start,left_size,rtp_size,need_size);if(saved_size== rtp_size){HandleRtpPacket(video_buf, saved_size,reply.is_h264, &h264_unpacker);//PrintHex((unsigned char *) video_buf,saved_size);}}}}else  {goto LOOP;}LOOP:while(g_app.m_run_flag){recv_buf = sp_socket->ReadData(len);start = (char*)recv_buf+4-reset_flag;left_size = len+reset_flag;//printf("recv_buf rtp_size:len = %d saved_size = %d left size = %d\n",rtp_size,saved_size,left_size);if(left_size>0 && left_size >=need_size){if(need_size>0){memcpy(video_buf+saved_size,start,need_size);left_size -= need_size;start+=need_size;	saved_size+=need_size;need_size = 0;if(saved_size== rtp_size){HandleRtpPacket(video_buf,saved_size,reply.is_h264, &h264_unpacker);saved_size = 0;}}while(left_size>0){counter++;if((*start)!=0x24){printf("111111 NOT rtp start magic  start = %02X left size = %d\n",*start,left_size);free(video_buf);return;}else if(left_size>=4){rtp_size = start[2]*256; rtp_size+=(start[3] & 0xFF)+4;if(reset_flag){memset((char*)recv_buf,0,4);}//printf("22222 RTP start magic	start = %02X left size = %d rtp_size = %d need size = %d saved_size = %d\n",//	*start,left_size,rtp_size,need_size,saved_size);if(left_size>=rtp_size){		memcpy(video_buf,start,rtp_size);left_size-=rtp_size; saved_size= rtp_size;start+=rtp_size;	}else{memcpy(video_buf,start,left_size);saved_size+= left_size;start+=left_size;need_size = rtp_size-left_size;left_size = 0;}//printf("3333 RTP start magic	start = %02X left size = %d rtp_size = %d need size = %d saved_size = %d\n",//	*start,left_size,rtp_size,need_size,saved_size);if(saved_size== rtp_size){HandleRtpPacket(video_buf,saved_size,reply.is_h264,&h264_unpacker);saved_size = 0;}reset_flag = 0;}else{printf("444444444444444444444444444444444444444444 left size =%d\n",left_size);memcpy((char*)recv_buf+4-left_size,start,left_size);reset_flag = left_size;left_size = 0;}}}else if(left_size>0 && left_size < need_size){memcpy(video_buf+saved_size,start,left_size);need_size-=left_size;saved_size+= left_size;left_size = 0;}}free(video_buf);fclose(g_file);}void* RTSPThread(void *args)
{std::string ip;int port = 554;RTSP_ITEM *rtsp  = (RTSP_ITEM*)args;//printf("CreateRTSPThread [%s] [%s]\n",rtmp->rtsp.c_str(),rtmp->rtmp.c_str());if(GetRtspInfo(ip,port,rtsp->rtsp) == false) return nullptr;//return nullptr;auto rtsp_socket = std::make_shared<Socket>(true,5);auto ret = rtsp_socket->CreateSocketAndConnect(true,5,ip.c_str(),port);if(ret){printf("Connect to [%s:%d] success \n",ip.c_str(),port);}else{printf("Connect to [%s:%d] failed\n",ip.c_str(),port);return nullptr;}HandleRtspProc(rtsp,rtsp_socket);return nullptr;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/149639.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Unity 设计模式 之 行为型模式 -【状态模式】【观察者模式】【备忘录模式】

Unity 设计模式 之 行为型模式 -【状态模式】【观察者模式】【备忘录模式】 目录 Unity 设计模式 之 行为型模式 -【状态模式】【观察者模式】【备忘录模式】 一、简单介绍 二、状态模式&#xff08;State Pattern&#xff09; 1、什么时候使用状态模式 2、使用状态模式的…

力扣516-最长回文子序列(Java详细题解)

题目链接&#xff1a;力扣516-最长回文子序列 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 dp五部曲。 1.确定dp数组和i下标的含义。 2.确定递推公式。 3.dp初始化。 4.确定dp的遍历顺序。 5.如果没有ac打印dp数组 利于debug。 每…

接口测试Postman关联,断言,前置,参数化用法

一、Postman下载 我们直接搜索Postman官网下载即可 Postman API Platformhttps://www.postman.com/ 二、使用 下载安装完成后我们需要登录注册&#xff0c;按照Postman的指示进行注册登录&#xff0c;不登陆可能有些功能无法使用 登陆完成我们就可以开始对接口进行测试了 …

C++速通LeetCode中等第27题-二叉树展开为链表(两种迭代法)

迭代法一&#xff1a;额外容器&#xff0c;前序遍历暴力求解&#xff08;空间O(n)) /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* …

Tableau|一入门

一 什么是BI工具 BI 工具即商业智能&#xff08;Business Intelligence&#xff09;工具&#xff0c;是一种用于收集、整理、分析和展示企业数据的软件系统&#xff0c;其主要目的是帮助企业用户更好地理解和利用数据&#xff0c;以支持决策制定。 主要功能&#xff1a; 1.数据…

springboot在线教学平台

基于springbootvue实现的在线教学平台 &#xff08;源码L文ppt&#xff09;4-069 4.1系统结构设计 这些功能可以充分满足在线教学平台的需求。此系统功能较为全面如下图系统功能结构如图4-1所示。 图4-1功能结构图 4.2系统功能模块设计 在线教学平台的使用者主要有二类…

技术速递|宣布 Azure Container Apps 上的 Java 体验正式推出

作者&#xff1a;Sean Li 排版&#xff1a;Alan Wang Azure Container Apps 是一个完全托管的、无服务器容器平台&#xff0c;使您能够构建、部署和运行容器化应用程序。使用 Azure Container Apps 您可以弹性扩缩容。您可以使用统一的网络设计弹性微服务&#xff0c;并利用启用…

频率增强通道注意力机制(FECAM)学习总结

本文提出了一种新的频率增强通道注意力机制&#xff08;FECAM&#xff09;&#xff0c;旨在解决时间序列预测中傅里叶变换因吉布斯现象导致的高频噪声问题。FECAM基于离散余弦变换&#xff0c;能自适应地模拟信道间的频率依赖性&#xff0c;有效避免预测误差。实验显示&#xf…

赛意SMOM和金蝶云星空接口打通对接实战

赛意SMOM和金蝶云星空接口打通对接实战 对接源平台:赛意SMOM 赛意信息已经发展成为国内企业数字化服务领域最具发展潜力的领军企业之一&#xff0c;聚焦于工业互联网、智能制造、新一代信息技术、数字化转型等领域的技术与商业模式应用&#xff0c;为企业提供高端软件咨询、实施…

成为谷歌开发者专家(GDE)的经历

大家好&#xff0c;我是张海龙(Jason)。经过一年多的准备&#xff0c;GDE申请 终于正式成功通过面试&#xff0c;成为了国内第一位Firebase GDE。下面对整个过程做个总结&#xff0c;希望对大家有所帮助。 1.什么是 GDE&#xff1f; Google Developers上面有详细的说明&#x…

Craft:年度 Mac 应用,卡片式笔记新星

今年的年度 Mac 应用大奖颁给了Craft&#xff0c;这是一款集笔记、文档和个人管理于一体的独特工具。Craft 最大的亮点在于其卡片式的交互设计&#xff0c;这种设计让信息组织变得更加直观且高效。 尽管它仅上线了一年时间&#xff0c;但已经展现出了不输于许多老牌笔记应用的…

前端开发迎来新机会,全栈转型就靠这个!

在如今的开发世界&#xff0c;全栈开发者已成为许多前端开发者的新目标。随着技术的不断演进&#xff0c;前端不再局限于写页面和样式&#xff0c;而是逐渐向后端延伸&#xff0c;甚至触及数据库和云服务。如果你想在职业道路上更进一步&#xff0c;向全栈开发者靠拢&#xff0…

【JavaEE】——多重锁,死锁问题和解决思路

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯&#xff0c;你们的点赞收藏是我前进最大的动力&#xff01;&#xff01;希望本文内容能够帮助到你&#xff01; 目录 一&#xff1a;加锁的“可重入性” 1&#xff1a;问题引入 2&#xff1a;问题分析 3&#xff1a;可重…

springboot快速开发平台使用达梦数据库

1.首先来到DM管理工具 大致流程是&#xff1a;创建表空间&#xff08;用于给新建的用户使用&#xff09;-》创建用户&#xff08;绑定表空间&#xff09; 文件位置 2.创建用户 来到所属角色页面&#xff0c;第一个权限管理员一定要勾上&#xff0c;其他的看情况 3.来到DM数…

Java项目实战II基于SSM的国外摇滚乐队交流和周边售卖系统的设计与实现(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者 一、前言 随着互联网技术的飞速发展&#xff0c;信息传播的广度和深度不断拓展&#xff0c;为各行业的创新发展…

GPIO与MIO控制LED——ZYNQ学习笔记2

一、GPIO简介 ZYNQ 分为 PS 和 PL 两部分&#xff0c;那么器件的引脚&#xff08; Pin&#xff09;资源同样也分成了两部分。 ZYNQ PS 中的外设可以通过 MIO&#xff08; multiplexed I/O&#xff0c;多路复用 I/O&#xff09;模块连接到 PS 端的引脚上&#xff0c;也可以通过 …

Python近红外光谱数据分析

ChatGPT4.0在近红外光谱数据分析、定性/定量分析模型代码自动生成等方面的强大功能&#xff0c;同时更加系统地学习人工智能&#xff08;包括传统机器学习、深度学习等&#xff09;的基础理论&#xff0c;以及具体的代码实现方法掌握ChatGPT4.0在科研工作中的各种使用方法与技巧…

C++学习笔记----8、掌握类与对象(一)---- 对象中的动态内存分配(1)

1、FRIENDS c允许类声明为其它类&#xff0c;其它类的成员函数&#xff0c;或者非成员函数为friend。可以访问protected与private数据成员与成员函数。例如&#xff0c;假设你有两个类Foo与Bar。你可以指定Bar类是Foo类的一个friend&#xff1a; class Foo {friend class Bar;…

C++之哈希 --- 哈希的应用(位图布隆过滤器)

一、位图 1.1 位图的基本概念 在如今网络交通高度发达的时代&#xff0c;网购已经成为我们日常生活中的一部分。没当双11到来&#xff0c;各大平台都会迎来一次网购的高潮。这就会让服务器短时间内获得高达几十亿上百亿的数据&#xff0c;那我们该如何去处理这海量的数据呢&am…

FortiGate 防火墙 DNS 地址转换(DNS Translation)

简介 本例介绍 FortiGate 防火墙 DNS 地址转换&#xff08;DNS Translation&#xff09;配置方法。 一、 网络结构 网络结构如下图&#xff0c;PC1 连接在 FG60B 的 Internal 接口&#xff0c;FG60B 的 Wan1 接口连接 FG80CM 的 DMZ 接口&#xff0c;Wan1 接口开启 DNS 服务…