Initial setup for CLion
This commit is contained in:
687
MediaClient/srt/srt_cln.cpp
Normal file
687
MediaClient/srt/srt_cln.cpp
Normal file
@@ -0,0 +1,687 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
*
|
||||
* By downloading, copying, installing or using the software you agree to this license.
|
||||
* If you do not agree to this license, do not download, install,
|
||||
* copy or use the software.
|
||||
*
|
||||
* Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved.
|
||||
*
|
||||
* Redistribution and use in binary forms, with or without modification, are permitted.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the License.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#include "sys_inc.h"
|
||||
#include "srt_cln.h"
|
||||
#include "h264.h"
|
||||
#include "h265.h"
|
||||
#include "media_format.h"
|
||||
#include "bs.h"
|
||||
#include "media_util.h"
|
||||
|
||||
|
||||
void * srt_rx_thread(void * argv)
|
||||
{
|
||||
CSrtClient * pSrtClient = (CSrtClient *) argv;
|
||||
|
||||
pSrtClient->rx_thread();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ts_payload_cb(uint8 * data, uint32 size, uint32 type, uint64 pts, void * userdata)
|
||||
{
|
||||
CSrtClient * pSrtClient = (CSrtClient *) userdata;
|
||||
|
||||
pSrtClient->srt_payload_cb(data, size, type, pts);
|
||||
}
|
||||
|
||||
CSrtClient::CSrtClient()
|
||||
: m_nport(0)
|
||||
, m_fd(0)
|
||||
, m_eid(0)
|
||||
, m_bRunning(FALSE)
|
||||
, m_bVideoReady(FALSE)
|
||||
, m_bAudioReady(FALSE)
|
||||
, m_tidRx(0)
|
||||
, m_nVpsLen(0)
|
||||
, m_nSpsLen(0)
|
||||
, m_nPpsLen(0)
|
||||
, m_nAudioConfigLen(0)
|
||||
, m_nVideoCodec(VIDEO_CODEC_NONE)
|
||||
, m_nWidth(0)
|
||||
, m_nHeight(0)
|
||||
, m_nFrameRate(0)
|
||||
, m_nAudioCodec(AUDIO_CODEC_NONE)
|
||||
, m_nSamplerate(44100)
|
||||
, m_nChannels(2)
|
||||
, m_nVideoInitTS(0)
|
||||
, m_nAudioInitTS(0)
|
||||
, m_pNotify(NULL)
|
||||
, m_pUserdata(NULL)
|
||||
, m_pVideoCB(NULL)
|
||||
, m_pAudioCB(NULL)
|
||||
{
|
||||
memset(m_url, 0, sizeof(m_url));
|
||||
memset(m_user, 0, sizeof(m_user));
|
||||
memset(m_pass, 0, sizeof(m_pass));
|
||||
memset(m_ip, 0, sizeof(m_ip));
|
||||
memset(m_streamid, 0, sizeof(m_streamid));
|
||||
|
||||
memset(&m_pVps, 0, sizeof(m_pVps));
|
||||
memset(&m_pSps, 0, sizeof(m_pVps));
|
||||
memset(&m_pPps, 0, sizeof(m_pVps));
|
||||
memset(&m_pAudioConfig, 0, sizeof(m_pAudioConfig));
|
||||
|
||||
m_pMutex = sys_os_create_mutex();
|
||||
|
||||
m_nRxTimeout = 10; // default 10s timeout
|
||||
|
||||
ts_parser_init(&m_tsParser);
|
||||
|
||||
ts_parser_set_cb(&m_tsParser, ts_payload_cb, this);
|
||||
}
|
||||
|
||||
CSrtClient::~CSrtClient()
|
||||
{
|
||||
srt_close();
|
||||
|
||||
if (m_pMutex)
|
||||
{
|
||||
sys_os_destroy_sig_mutex(m_pMutex);
|
||||
m_pMutex = NULL;
|
||||
}
|
||||
|
||||
ts_parser_free(&m_tsParser);
|
||||
}
|
||||
|
||||
BOOL CSrtClient::srt_start(const char * url, const char * user, const char * pass)
|
||||
{
|
||||
int port = 0;
|
||||
char proto[32], username[64], password[64], host[100], path[200];
|
||||
|
||||
url_split(url, proto, sizeof(proto), username, sizeof(username),
|
||||
password, sizeof(password), host, sizeof(host), &port, path, sizeof(path));
|
||||
|
||||
if (strcasecmp(proto, "srt") != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (port <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (host[0] == '\0')
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_nport = port;
|
||||
|
||||
strncpy(m_ip, host, sizeof(m_ip) - 1);
|
||||
|
||||
char * p = strstr(path, "streamid");
|
||||
if (p)
|
||||
{
|
||||
p += strlen("streamid=");
|
||||
strncpy(m_streamid, p, sizeof(m_streamid)-1);
|
||||
}
|
||||
|
||||
if (url && url[0] != '\0')
|
||||
{
|
||||
strncpy(m_url, url, sizeof(m_url)-1);
|
||||
}
|
||||
|
||||
if (user && user[0] != '\0')
|
||||
{
|
||||
strncpy(m_user, user, sizeof(m_user)-1);
|
||||
}
|
||||
|
||||
if (pass && pass[0] != '\0')
|
||||
{
|
||||
strncpy(m_pass, pass, sizeof(m_pass)-1);
|
||||
}
|
||||
|
||||
log_print(HT_LOG_INFO, "%s, url=%s, ip=%s, port=%d, streamid=%s\r\n",
|
||||
__FUNCTION__, m_url, m_ip, m_nport, m_streamid);
|
||||
|
||||
m_bRunning = TRUE;
|
||||
m_tidRx = sys_os_create_thread((void *)srt_rx_thread, this);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CSrtClient::srt_play()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CSrtClient::srt_stop()
|
||||
{
|
||||
return srt_close();
|
||||
}
|
||||
|
||||
BOOL CSrtClient::srt_pause()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CSrtClient::srt_close()
|
||||
{
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
m_pAudioCB = NULL;
|
||||
m_pVideoCB = NULL;
|
||||
m_pNotify = NULL;
|
||||
m_pUserdata = NULL;
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
|
||||
m_bRunning = FALSE;
|
||||
|
||||
while (m_tidRx)
|
||||
{
|
||||
usleep(10*1000);
|
||||
}
|
||||
|
||||
if (m_fd)
|
||||
{
|
||||
::srt_close(m_fd);
|
||||
m_fd = 0;
|
||||
}
|
||||
|
||||
if (m_eid)
|
||||
{
|
||||
srt_epoll_release(m_eid);
|
||||
m_eid = 0;
|
||||
}
|
||||
|
||||
m_bVideoReady = FALSE;
|
||||
m_bAudioReady = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CSrtClient::srt_connect()
|
||||
{
|
||||
srt_send_notify(SRT_EVE_CONNECTING);
|
||||
|
||||
SRTSOCKET fd = srt_create_socket();
|
||||
|
||||
if (srt_setsockopt(fd, 0, SRTO_STREAMID, m_streamid, strlen(m_streamid)) < 0)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, srt_setsockopt SRTO_STREAMID failure. err=%s\r\n",
|
||||
__FUNCTION__, srt_getlasterror_str());
|
||||
::srt_close(fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
struct sockaddr_in sa;
|
||||
memset(&sa, 0, sizeof sa);
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(m_nport);
|
||||
sa.sin_addr.s_addr = get_address_by_name(m_ip);
|
||||
|
||||
struct sockaddr *psa = (struct sockaddr *) &sa;
|
||||
|
||||
int status = ::srt_connect(fd, psa, sizeof sa);
|
||||
if (status == SRT_ERROR)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, srt_connect failure. ip=%s, port=%d\r\n",
|
||||
__FUNCTION__, m_ip, m_nport);
|
||||
::srt_close(fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_eid = srt_epoll_create();
|
||||
|
||||
int modes = SRT_EPOLL_IN | SRT_EPOLL_ERR;
|
||||
|
||||
int ret = srt_epoll_add_usock(m_eid, fd, &modes);
|
||||
if (ret < 0)
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, srt_epoll_add_usock failed, epoll=%d, fd=%d, modes=%d, %s\r\n",
|
||||
__FUNCTION__, m_eid, fd, modes, srt_getlasterror_str());
|
||||
::srt_close(fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_fd = fd;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CSrtClient::rx_thread()
|
||||
{
|
||||
if (!srt_connect())
|
||||
{
|
||||
m_tidRx = 0;
|
||||
srt_send_notify(SRT_EVE_CONNFAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
#define TS_UDP_LEN 1316 //7*188
|
||||
|
||||
int tm_count = 0;
|
||||
BOOL nodata_notify = FALSE;
|
||||
char buff[TS_UDP_LEN];
|
||||
|
||||
while (m_bRunning)
|
||||
{
|
||||
SRTSOCKET read_socks[1];
|
||||
int read_len = 1;
|
||||
|
||||
int ret = srt_epoll_wait(m_eid, read_socks, &read_len, NULL, NULL, 1000, 0, 0, 0, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = srt_getlasterror(NULL);
|
||||
if (ret == SRT_ETIMEOUT)
|
||||
{
|
||||
tm_count++;
|
||||
if (tm_count >= m_nRxTimeout && !nodata_notify) // in 10s without data
|
||||
{
|
||||
nodata_notify = TRUE;
|
||||
srt_send_notify(SRT_EVE_NODATA);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_print(HT_LOG_ERR, "%s, srt_epoll_wait failed. err=%d\r\n", __FUNCTION__, ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (read_len <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
SRT_SOCKSTATUS status = srt_getsockstate(m_fd);
|
||||
if (status == SRTS_BROKEN ||
|
||||
status == SRTS_NONEXIST ||
|
||||
status == SRTS_CLOSED)
|
||||
{
|
||||
srt_epoll_remove_usock(m_eid, m_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = srt_recvmsg(m_fd, buff, TS_UDP_LEN);
|
||||
if (ret < 0)
|
||||
{
|
||||
log_print(HT_LOG_WARN, "%s, srt_recvmsg failed, sock=%d, ret=%d, err=%s\r\n",
|
||||
__FUNCTION__, m_fd, ret, srt_getlasterror_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nodata_notify)
|
||||
{
|
||||
nodata_notify = FALSE;
|
||||
srt_send_notify(SRT_EVE_RESUME);
|
||||
}
|
||||
|
||||
tm_count = 0;
|
||||
|
||||
ts_parser_parse(&m_tsParser, (uint8*)buff, ret);
|
||||
}
|
||||
|
||||
m_tidRx = 0;
|
||||
|
||||
srt_send_notify(SRT_EVE_STOPPED);
|
||||
}
|
||||
|
||||
void CSrtClient::srt_send_notify(int event)
|
||||
{
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
|
||||
if (m_pNotify)
|
||||
{
|
||||
m_pNotify(event, m_pUserdata);
|
||||
}
|
||||
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
}
|
||||
|
||||
void CSrtClient::srt_h264_rx(uint8 * p_data, uint32 len, uint64 pts)
|
||||
{
|
||||
int s_len = 0, n_len = 0, parse_len = len;
|
||||
uint8 nalu_t;
|
||||
uint8 * p_cur = p_data;
|
||||
uint8 * p_end = p_data + len;
|
||||
|
||||
while (p_cur && p_cur < p_end && parse_len > 0)
|
||||
{
|
||||
uint8 * p_next = avc_split_nalu(p_cur, parse_len, &s_len, &n_len);
|
||||
|
||||
nalu_t = (p_cur[s_len] & 0x1F);
|
||||
|
||||
if (nalu_t == H264_NAL_SPS && m_nSpsLen == 0)
|
||||
{
|
||||
if (n_len <= (int)sizeof(m_pSps))
|
||||
{
|
||||
memcpy(m_pSps, p_cur, n_len);
|
||||
m_nSpsLen = n_len;
|
||||
}
|
||||
|
||||
video_data_cb(p_cur, n_len, pts);
|
||||
}
|
||||
else if (nalu_t == H264_NAL_PPS && m_nPpsLen == 0)
|
||||
{
|
||||
if (n_len <= (int)sizeof(m_pPps))
|
||||
{
|
||||
memcpy(m_pPps, p_cur, n_len);
|
||||
m_nPpsLen = n_len;
|
||||
}
|
||||
|
||||
video_data_cb(p_cur, n_len, pts);
|
||||
}
|
||||
else if (nalu_t == H264_NAL_AUD || nalu_t == H264_NAL_SEI)
|
||||
{
|
||||
// skip
|
||||
}
|
||||
else
|
||||
{
|
||||
video_data_cb(p_cur, n_len, pts);
|
||||
}
|
||||
|
||||
parse_len -= n_len;
|
||||
p_cur = p_next;
|
||||
}
|
||||
}
|
||||
|
||||
void CSrtClient::srt_h265_rx(uint8 * p_data, uint32 len, uint64 pts)
|
||||
{
|
||||
int s_len = 0, n_len = 0, parse_len = len;
|
||||
uint8 nalu_t;
|
||||
uint8 * p_cur = p_data;
|
||||
uint8 * p_end = p_data + len;
|
||||
|
||||
while (p_cur && p_cur < p_end && parse_len > 0)
|
||||
{
|
||||
uint8 * p_next = avc_split_nalu(p_cur, parse_len, &s_len, &n_len);
|
||||
|
||||
nalu_t = (p_cur[s_len] >> 1) & 0x3F;
|
||||
|
||||
if (nalu_t == HEVC_NAL_VPS && m_nVpsLen == 0)
|
||||
{
|
||||
if (n_len <= (int)sizeof(m_pVps))
|
||||
{
|
||||
memcpy(m_pVps, p_cur, n_len);
|
||||
m_nVpsLen = n_len;
|
||||
}
|
||||
|
||||
video_data_cb(p_cur, n_len, pts);
|
||||
}
|
||||
else if (nalu_t == HEVC_NAL_SPS && m_nSpsLen == 0)
|
||||
{
|
||||
if (n_len <= (int)sizeof(m_pSps))
|
||||
{
|
||||
memcpy(m_pSps, p_cur, n_len);
|
||||
m_nSpsLen = n_len;
|
||||
}
|
||||
|
||||
video_data_cb(p_cur, n_len, pts);
|
||||
}
|
||||
else if (nalu_t == HEVC_NAL_PPS && m_nPpsLen == 0)
|
||||
{
|
||||
if (n_len <= (int)sizeof(m_pPps))
|
||||
{
|
||||
memcpy(m_pPps, p_cur, n_len);
|
||||
m_nPpsLen = n_len;
|
||||
}
|
||||
|
||||
video_data_cb(p_cur, n_len, pts);
|
||||
}
|
||||
else if (nalu_t == HEVC_NAL_AUD ||
|
||||
nalu_t == HEVC_NAL_SEI_PREFIX ||
|
||||
nalu_t == HEVC_NAL_SEI_SUFFIX)
|
||||
{
|
||||
// skip
|
||||
}
|
||||
else
|
||||
{
|
||||
video_data_cb(p_cur, n_len, pts);
|
||||
}
|
||||
|
||||
parse_len -= n_len;
|
||||
p_cur = p_next;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CSrtClient::srt_parse_adts(uint8 * p_data, uint32 len)
|
||||
{
|
||||
bs_t bs;
|
||||
bs_init(&bs, p_data, len);
|
||||
|
||||
if (bs_read(&bs, 12) != 0xfff)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const int audio_sample_rates[16] = {
|
||||
96000, 88200, 64000, 48000, 44100, 32000,
|
||||
24000, 22050, 16000, 12000, 11025, 8000, 7350
|
||||
};
|
||||
|
||||
int sr, ch, size;
|
||||
|
||||
bs_skip(&bs, 1); /* id */
|
||||
bs_skip(&bs, 2); /* layer */
|
||||
bs_skip(&bs, 1); /* protection_absent */
|
||||
bs_skip(&bs, 2); /* profile_objecttype */
|
||||
sr = bs_read(&bs, 4); /* sample_frequency_index */
|
||||
if (!audio_sample_rates[sr])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bs_skip(&bs, 1); /* private_bit */
|
||||
ch = bs_read(&bs, 3); /* channel_configuration */
|
||||
|
||||
bs_skip(&bs, 1); /* original/copy */
|
||||
bs_skip(&bs, 1); /* home */
|
||||
|
||||
/* adts_variable_header */
|
||||
bs_skip(&bs, 1); /* copyright_identification_bit */
|
||||
bs_skip(&bs, 1); /* copyright_identification_start */
|
||||
size = bs_read(&bs, 13); /* aac_frame_length */
|
||||
if (size < 7)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bs_skip(&bs, 11); /* adts_buffer_fullness */
|
||||
bs_skip(&bs, 2); /* number_of_raw_data_blocks_in_frame */
|
||||
|
||||
m_nSamplerate = audio_sample_rates[sr];
|
||||
m_nChannels = ch;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CSrtClient::srt_payload_cb(uint8 * p_data, uint32 len, uint32 type, uint64 pts)
|
||||
{
|
||||
if (type == TS_VIDEO_H264)
|
||||
{
|
||||
if (!m_bVideoReady)
|
||||
{
|
||||
m_nVideoCodec = VIDEO_CODEC_H264;
|
||||
m_bVideoReady = TRUE;
|
||||
srt_send_notify(SRT_EVE_VIDEOREADY);
|
||||
}
|
||||
|
||||
srt_h264_rx(p_data, len, pts);
|
||||
}
|
||||
else if (type == TS_VIDEO_HEVC)
|
||||
{
|
||||
if (!m_bVideoReady)
|
||||
{
|
||||
m_nVideoCodec = VIDEO_CODEC_H265;
|
||||
m_bVideoReady = TRUE;
|
||||
srt_send_notify(SRT_EVE_VIDEOREADY);
|
||||
}
|
||||
|
||||
srt_h265_rx(p_data, len, pts);
|
||||
}
|
||||
else if (type == TS_VIDEO_MPEG4)
|
||||
{
|
||||
if (!m_bVideoReady)
|
||||
{
|
||||
m_nVideoCodec = VIDEO_CODEC_MP4;
|
||||
m_bVideoReady = TRUE;
|
||||
srt_send_notify(SRT_EVE_VIDEOREADY);
|
||||
}
|
||||
|
||||
video_data_cb(p_data, len, pts);
|
||||
}
|
||||
else if (type == TS_AUDIO_AAC)
|
||||
{
|
||||
if (!m_bAudioReady)
|
||||
{
|
||||
srt_parse_adts(p_data, len);
|
||||
|
||||
m_nAudioCodec = AUDIO_CODEC_AAC;
|
||||
m_bAudioReady = TRUE;
|
||||
srt_send_notify(SRT_EVE_AUDIOREADY);
|
||||
}
|
||||
|
||||
audio_data_cb(p_data, len, pts);
|
||||
}
|
||||
}
|
||||
|
||||
void CSrtClient::video_data_cb(uint8 * p_data, int len, uint32 ts)
|
||||
{
|
||||
if (m_nVideoInitTS == 0 && ts != 0)
|
||||
{
|
||||
m_nVideoInitTS = ts;
|
||||
}
|
||||
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
if (m_pVideoCB)
|
||||
{
|
||||
m_pVideoCB(p_data, len, ts, m_pUserdata);
|
||||
}
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
}
|
||||
|
||||
void CSrtClient::audio_data_cb(uint8 * p_data, int len, uint32 ts)
|
||||
{
|
||||
if (m_nAudioInitTS == 0 && ts != 0)
|
||||
{
|
||||
m_nAudioInitTS = ts;
|
||||
}
|
||||
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
if (m_pAudioCB)
|
||||
{
|
||||
m_pAudioCB(p_data, len, ts, m_pUserdata);
|
||||
}
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
}
|
||||
|
||||
void CSrtClient::get_h264_params()
|
||||
{
|
||||
if (m_nSpsLen > 0)
|
||||
{
|
||||
video_data_cb(m_pSps, m_nSpsLen, 0);
|
||||
}
|
||||
|
||||
if (m_nPpsLen > 0)
|
||||
{
|
||||
video_data_cb(m_pPps, m_nPpsLen, 0);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CSrtClient::get_h264_params(uint8 * p_sps, int * sps_len, uint8 * p_pps, int * pps_len)
|
||||
{
|
||||
if (m_nSpsLen > 0)
|
||||
{
|
||||
*sps_len = m_nSpsLen;
|
||||
memcpy(p_sps, m_pSps, m_nSpsLen);
|
||||
}
|
||||
|
||||
if (m_nPpsLen > 0)
|
||||
{
|
||||
*pps_len = m_nPpsLen;
|
||||
memcpy(p_pps, m_pPps, m_nPpsLen);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CSrtClient::get_h265_params()
|
||||
{
|
||||
if (m_nVpsLen > 0)
|
||||
{
|
||||
video_data_cb(m_pVps, m_nVpsLen, 0);
|
||||
}
|
||||
|
||||
if (m_nSpsLen > 0)
|
||||
{
|
||||
video_data_cb(m_pSps, m_nSpsLen, 0);
|
||||
}
|
||||
|
||||
if (m_nPpsLen > 0)
|
||||
{
|
||||
video_data_cb(m_pPps, m_nPpsLen, 0);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CSrtClient::get_h265_params(uint8 * p_sps, int * sps_len, uint8 * p_pps, int * pps_len, uint8 * p_vps, int * vps_len)
|
||||
{
|
||||
if (m_nVpsLen > 0)
|
||||
{
|
||||
*vps_len = m_nVpsLen;
|
||||
memcpy(p_vps, m_pVps, m_nVpsLen);
|
||||
}
|
||||
|
||||
if (m_nSpsLen > 0)
|
||||
{
|
||||
*sps_len = m_nSpsLen;
|
||||
memcpy(p_sps, m_pSps, m_nSpsLen);
|
||||
}
|
||||
|
||||
if (m_nPpsLen > 0)
|
||||
{
|
||||
*pps_len = m_nPpsLen;
|
||||
memcpy(p_pps, m_pPps, m_nPpsLen);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CSrtClient::set_notify_cb(srt_notify_cb notify, void * userdata)
|
||||
{
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
m_pNotify = notify;
|
||||
m_pUserdata = userdata;
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
}
|
||||
|
||||
void CSrtClient::set_video_cb(srt_video_cb cb)
|
||||
{
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
m_pVideoCB = cb;
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
}
|
||||
|
||||
void CSrtClient::set_audio_cb(srt_audio_cb cb)
|
||||
{
|
||||
sys_os_mutex_enter(m_pMutex);
|
||||
m_pAudioCB = cb;
|
||||
sys_os_mutex_leave(m_pMutex);
|
||||
}
|
||||
|
||||
void CSrtClient::set_rx_timeout(int timeout)
|
||||
{
|
||||
m_nRxTimeout = timeout;
|
||||
}
|
||||
|
||||
|
||||
146
MediaClient/srt/srt_cln.h
Normal file
146
MediaClient/srt/srt_cln.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
*
|
||||
* By downloading, copying, installing or using the software you agree to this license.
|
||||
* If you do not agree to this license, do not download, install,
|
||||
* copy or use the software.
|
||||
*
|
||||
* Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved.
|
||||
*
|
||||
* Redistribution and use in binary forms, with or without modification, are permitted.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the License.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef SRT_CLN_H
|
||||
#define SRT_CLN_H
|
||||
|
||||
#include "srt/srt.h"
|
||||
#include "h264.h"
|
||||
#include "ts_parser.h"
|
||||
|
||||
|
||||
#define SRT_EVE_STOPPED 60
|
||||
#define SRT_EVE_CONNECTING 61
|
||||
#define SRT_EVE_CONNFAIL 62
|
||||
#define SRT_EVE_NOSIGNAL 63
|
||||
#define SRT_EVE_RESUME 64
|
||||
#define SRT_EVE_AUTHFAILED 65
|
||||
#define SRT_EVE_NODATA 66
|
||||
#define SRT_EVE_VIDEOREADY 67
|
||||
#define SRT_EVE_AUDIOREADY 68
|
||||
|
||||
|
||||
#define DEF_BUFTIME (10 * 60 * 60 * 1000) /* 10 hours default */
|
||||
|
||||
typedef int (*srt_notify_cb)(int, void *);
|
||||
typedef int (*srt_video_cb)(uint8 *, int, uint32, void *);
|
||||
typedef int (*srt_audio_cb)(uint8 *, int, uint32, void *);
|
||||
|
||||
|
||||
class CSrtClient
|
||||
{
|
||||
public:
|
||||
CSrtClient(void);
|
||||
~CSrtClient(void);
|
||||
|
||||
public:
|
||||
BOOL srt_start(const char * url, const char * user, const char * pass);
|
||||
BOOL srt_play();
|
||||
BOOL srt_stop();
|
||||
BOOL srt_pause();
|
||||
BOOL srt_close();
|
||||
|
||||
char * get_url() {return m_url;}
|
||||
char * get_user() {return m_user;}
|
||||
char * get_pass() {return m_pass;}
|
||||
int audio_codec() {return m_nAudioCodec;}
|
||||
int video_codec() {return m_nVideoCodec;}
|
||||
void get_h264_params();
|
||||
BOOL get_h264_params(uint8 * p_sps, int * sps_len, uint8 * p_pps, int * pps_len);
|
||||
void get_h265_params();
|
||||
BOOL get_h265_params(uint8 * p_sps, int * sps_len, uint8 * p_pps, int * pps_len, uint8 * p_vps, int * vps_len);
|
||||
int get_video_width() {return m_nWidth;}
|
||||
int get_video_height() {return m_nHeight;}
|
||||
double get_video_framerate() {return m_nFrameRate;}
|
||||
int get_audio_samplerate() {return m_nSamplerate;}
|
||||
int get_audio_channels() {return m_nChannels;}
|
||||
uint8 * get_audio_config() {return m_pAudioConfig;}
|
||||
int get_audio_config_len() {return m_nAudioConfigLen;}
|
||||
uint32 get_video_init_ts() {return m_nVideoInitTS;}
|
||||
uint32 get_audio_init_ts() {return m_nAudioInitTS;}
|
||||
|
||||
void set_notify_cb(srt_notify_cb notify, void * userdata);
|
||||
void set_video_cb(srt_video_cb cb);
|
||||
void set_audio_cb(srt_audio_cb cb);
|
||||
void set_rx_timeout(int timeout);
|
||||
|
||||
void rx_thread();
|
||||
void srt_payload_cb(uint8 * p_data, uint32 len, uint32 type, uint64 pts);
|
||||
void video_data_cb(uint8 * p_data, int len, uint32 ts);
|
||||
void audio_data_cb(uint8 * p_data, int len, uint32 ts);
|
||||
|
||||
private:
|
||||
BOOL srt_connect();
|
||||
void srt_send_notify(int event);
|
||||
void srt_h264_rx(uint8 * p_data, uint32 len, uint64 pts);
|
||||
void srt_h265_rx(uint8 * p_data, uint32 len, uint64 pts);
|
||||
BOOL srt_parse_adts(uint8 * p_data, uint32 len);
|
||||
|
||||
private:
|
||||
char m_url[512];
|
||||
char m_user[64];
|
||||
char m_pass[64];
|
||||
char m_ip[128];
|
||||
char m_streamid[256];
|
||||
int m_nport;
|
||||
|
||||
int m_fd;
|
||||
int m_eid;
|
||||
|
||||
BOOL m_bRunning;
|
||||
BOOL m_bVideoReady;
|
||||
BOOL m_bAudioReady;
|
||||
pthread_t m_tidRx;
|
||||
|
||||
uint8 m_pVps[256];
|
||||
int m_nVpsLen;
|
||||
uint8 m_pSps[256];
|
||||
int m_nSpsLen;
|
||||
uint8 m_pPps[256];
|
||||
int m_nPpsLen;
|
||||
|
||||
TSParser m_tsParser;
|
||||
|
||||
uint8 m_pAudioConfig[32];
|
||||
uint32 m_nAudioConfigLen;
|
||||
|
||||
int m_nVideoCodec;
|
||||
int m_nWidth;
|
||||
int m_nHeight;
|
||||
double m_nFrameRate;
|
||||
int m_nAudioCodec;
|
||||
int m_nSamplerate;
|
||||
int m_nChannels;
|
||||
|
||||
uint32 m_nVideoInitTS;
|
||||
uint32 m_nAudioInitTS;
|
||||
|
||||
srt_notify_cb m_pNotify;
|
||||
void * m_pUserdata;
|
||||
srt_video_cb m_pVideoCB;
|
||||
srt_audio_cb m_pAudioCB;
|
||||
void * m_pMutex;
|
||||
int m_nRxTimeout;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user