// PHZ // 2018-6-7 #if defined(WIN32) || defined(_WIN32) #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif #endif #include "H265Source.h" #include #include #if defined(__linux) || defined(__linux__) #include #endif using namespace xop; using namespace std; H265Source::H265Source(uint32_t framerate) : framerate_(framerate) { payload_ = 96; media_type_ = H265; clock_rate_ = 90000; } H265Source* H265Source::CreateNew(uint32_t framerate) { return new H265Source(framerate); } H265Source::~H265Source() { } string H265Source::GetMediaDescription(uint16_t port) { char buf[100] = {0}; sprintf(buf, "m=video %hu RTP/AVP 96", port); return string(buf); } string H265Source::GetAttribute() { return string("a=rtpmap:96 H265/90000"); } bool H265Source::HandleFrame(MediaChannelId channelId, AVFrame frame) { uint8_t *frame_buf = frame.buffer.get(); uint32_t frame_size = frame.size; if (frame.timestamp == 0) { frame.timestamp = GetTimestamp(); } if (frame_size <= MAX_RTP_PAYLOAD_SIZE) { RtpPacket rtp_pkt; rtp_pkt.type = frame.type; rtp_pkt.timestamp = frame.timestamp; rtp_pkt.size = frame_size + RTP_TCP_HEAD_SIZE + RTP_HEADER_SIZE; rtp_pkt.last = 1; memcpy(rtp_pkt.data.get()+RTP_TCP_HEAD_SIZE+RTP_HEADER_SIZE, frame_buf, frame_size); if (send_frame_callback_) { if (!send_frame_callback_(channelId, rtp_pkt)) { return false; } } } else { char FU[3] = {0}; char nalUnitType = (frame_buf[0] & 0x7E) >> 1; FU[0] = (frame_buf[0] & 0x81) | (49<<1); FU[1] = frame_buf[1]; FU[2] = (0x80 | nalUnitType); frame_buf += 2; frame_size -= 2; while (frame_size + 3 > MAX_RTP_PAYLOAD_SIZE) { RtpPacket rtp_pkt; rtp_pkt.type = frame.type; rtp_pkt.timestamp = frame.timestamp; rtp_pkt.size = RTP_TCP_HEAD_SIZE + RTP_HEADER_SIZE + MAX_RTP_PAYLOAD_SIZE; rtp_pkt.last = 0; rtp_pkt.data.get()[RTP_TCP_HEAD_SIZE + RTP_HEADER_SIZE + 0] = FU[0]; rtp_pkt.data.get()[RTP_TCP_HEAD_SIZE + RTP_HEADER_SIZE + 1] = FU[1]; rtp_pkt.data.get()[RTP_TCP_HEAD_SIZE + RTP_HEADER_SIZE + 2] = FU[2]; memcpy(rtp_pkt.data.get()+RTP_TCP_HEAD_SIZE+RTP_HEADER_SIZE+3, frame_buf, MAX_RTP_PAYLOAD_SIZE-3); if (send_frame_callback_) { if (!send_frame_callback_(channelId, rtp_pkt)) { return false; } } frame_buf += (MAX_RTP_PAYLOAD_SIZE - 3); frame_size -= (MAX_RTP_PAYLOAD_SIZE - 3); FU[2] &= ~0x80; } { RtpPacket rtp_pkt; rtp_pkt.type = frame.type; rtp_pkt.timestamp = frame.timestamp; rtp_pkt.size = RTP_TCP_HEAD_SIZE + RTP_HEADER_SIZE + 3 + frame_size; rtp_pkt.last = 1; FU[2] |= 0x40; rtp_pkt.data.get()[RTP_TCP_HEAD_SIZE + RTP_HEADER_SIZE + 0] = FU[0]; rtp_pkt.data.get()[RTP_TCP_HEAD_SIZE + RTP_HEADER_SIZE + 1] = FU[1]; rtp_pkt.data.get()[RTP_TCP_HEAD_SIZE + RTP_HEADER_SIZE + 2] = FU[2]; memcpy(rtp_pkt.data.get()+RTP_TCP_HEAD_SIZE+RTP_HEADER_SIZE+3, frame_buf, frame_size); if (send_frame_callback_) { if (!send_frame_callback_(channelId, rtp_pkt)) { return false; } } } } return true; } uint32_t H265Source::GetTimestamp() { /* #if defined(__linux) || defined(__linux__) struct timeval tv = {0}; gettimeofday(&tv, NULL); uint32_t ts = ((tv.tv_sec*1000)+((tv.tv_usec+500)/1000))*90; // 90: _clockRate/1000; return ts; #else */ //auto time_point = chrono::time_point_cast(chrono::system_clock::now()); //auto time_point = chrono::time_point_cast(chrono::steady_clock::now()); auto time_point = chrono::time_point_cast(chrono::steady_clock::now()); return (uint32_t)((time_point.time_since_epoch().count() + 500) / 1000 * 90); //#endif }