Files
2026-03-28 11:39:04 +11:00

437 lines
10 KiB
C++

/***************************************************************************************
*
* 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 "srt_player.h"
#include "utils.h"
/***************************************************************************************/
int srt_notify_callback(int evt, void * puser)
{
CSrtPlayer * pPlayer = (CSrtPlayer *) puser;
pPlayer->onNotify(evt);
return 0;
}
int srt_audio_callback(uint8 * pdata, int len, uint32 ts, void *puser)
{
CSrtPlayer * pPlayer = (CSrtPlayer *) puser;
pPlayer->onAudio(pdata, len, ts);
return 0;
}
int srt_video_callback(uint8 * pdata, int len, uint32 ts, void *puser)
{
CSrtPlayer * pPlayer = (CSrtPlayer *) puser;
pPlayer->onVideo(pdata, len, ts);
return 0;
}
/***************************************************************************************/
CSrtPlayer::CSrtPlayer(QObject * parent)
: CVideoPlayer(parent)
, m_port(-1)
{
memset(m_ip, 0, sizeof(m_ip));
}
CSrtPlayer::~CSrtPlayer()
{
close();
}
BOOL CSrtPlayer::open(QString fileName, WId hWnd)
{
close();
CVideoPlayer::open(fileName, hWnd);
int port;
char proto[32], username[100], password[100], host[100], path[200];
url_split(fileName.toStdString().c_str(), proto, sizeof(proto), username, sizeof(username),
password, sizeof(password), host, sizeof(host), &port, path, sizeof(path));
if (host[0] == '\0')
{
return FALSE;
}
if (port <= 0)
{
return FALSE;
}
if (username[0] != '\0')
{
m_acct = username;
}
if (password[0] != '\0')
{
m_pass = password;
}
strncpy(m_ip, host, sizeof(m_ip) - 1);
m_port = port;
m_srt.set_notify_cb(srt_notify_callback, this);
m_srt.set_audio_cb(srt_audio_callback);
m_srt.set_video_cb(srt_video_callback);
return TRUE;
}
void CSrtPlayer::close()
{
// stop connection
m_srt.srt_stop();
m_srt.srt_close();
m_bPlaying = FALSE;
m_bPaused = FALSE;
m_port = -1;
memset(m_ip, 0, sizeof(m_ip));
CVideoPlayer::close();
}
BOOL CSrtPlayer::play()
{
if (m_srt.srt_start(m_sFileName.toStdString().c_str(), m_acct.toStdString().c_str(), m_pass.toStdString().c_str()))
{
m_bPlaying = TRUE;
}
return m_bPlaying;
}
void CSrtPlayer::stop()
{
if (m_bPlaying || m_bPaused)
{
m_srt.srt_stop();
}
m_bPlaying = FALSE;
m_bPaused = FALSE;
}
BOOL CSrtPlayer::pause()
{
if (m_bPlaying)
{
if (m_srt.srt_pause())
{
m_bPaused = TRUE;
m_bPlaying = FALSE;
}
}
else if (m_bPaused)
{
if (m_srt.srt_play())
{
m_bPaused = FALSE;
m_bPlaying = TRUE;
}
}
return m_bPaused;
}
BOOL CSrtPlayer::seek(int pos)
{
if (pos < 0 || pos > 100)
{
return FALSE;
}
int64 duration = getDuration();
if (duration <= 0)
{
return FALSE;
}
int ntp_pos = duration / 100 * pos;
// m_srt.srt_play();
return TRUE;
}
int64 CSrtPlayer::getElapse()
{
return 0;
}
int64 CSrtPlayer::getDuration()
{
return 0;
}
int CSrtPlayer::getVideoClock()
{
return 90000;
}
int CSrtPlayer::getAudioClock()
{
return 90000;
}
int CSrtPlayer::getVideoCodec()
{
return m_srt.video_codec();
}
int CSrtPlayer::getAudioCodec()
{
return m_srt.audio_codec();
}
void CSrtPlayer::onNotify(int evt)
{
if (evt == SRT_EVE_VIDEOREADY)
{
int videoCodec = m_srt.video_codec();
if (VIDEO_CODEC_NONE != videoCodec)
{
BOOL ret;
uint8 extradata[1024];
int extradata_size = 0;
if (VIDEO_CODEC_H264 == videoCodec)
{
ret = m_srt.get_h264_params(m_h26XParamSets.sps, &m_h26XParamSets.sps_size,
m_h26XParamSets.pps, &m_h26XParamSets.pps_size);
if (ret)
{
memcpy(extradata, m_h26XParamSets.sps, m_h26XParamSets.sps_size);
extradata_size += m_h26XParamSets.sps_size;
memcpy(extradata+extradata_size, m_h26XParamSets.pps, m_h26XParamSets.pps_size);
extradata_size += m_h26XParamSets.pps_size;
// init video decoder
openVideo(videoCodec, extradata, extradata_size);
}
}
else if (VIDEO_CODEC_H265 == videoCodec)
{
ret = m_srt.get_h265_params(m_h26XParamSets.sps, &m_h26XParamSets.sps_size,
m_h26XParamSets.pps, &m_h26XParamSets.pps_size,
m_h26XParamSets.vps, &m_h26XParamSets.vps_size);
if (ret)
{
memcpy(extradata, m_h26XParamSets.vps, m_h26XParamSets.vps_size);
extradata_size += m_h26XParamSets.vps_size;
memcpy(extradata+extradata_size, m_h26XParamSets.sps, m_h26XParamSets.sps_size);
extradata_size += m_h26XParamSets.sps_size;
memcpy(extradata+extradata_size, m_h26XParamSets.pps, m_h26XParamSets.pps_size);
extradata_size += m_h26XParamSets.pps_size;
// init video decoder
openVideo(videoCodec, extradata, extradata_size);
}
}
else
{
openVideo(videoCodec);
}
}
}
else if (evt == SRT_EVE_AUDIOREADY)
{
int audioCodec = m_srt.audio_codec();
if (AUDIO_CODEC_NONE != audioCodec)
{
openAudio(audioCodec, m_srt.get_audio_samplerate(), m_srt.get_audio_channels());
}
}
emit notify(evt);
}
void CSrtPlayer::onAudio(uint8 * pdata, int len, uint32 ts)
{
playAudio(pdata, len, ts, 0);
}
void CSrtPlayer::onVideo(uint8 * pdata, int len, uint32 ts)
{
playVideo(pdata, len, ts, 0);
}
BOOL CSrtPlayer::onRecord()
{
CSrtClient * p_srt = &m_srt;
AVICTX * p_avictx = m_pAviCtx;
int vcodec = p_srt->video_codec();
int v_extra_len = 0;
uint8 v_extra[1024];
if (VIDEO_CODEC_H264 == vcodec)
{
avi_set_video_info(p_avictx, 0, 0, 0, "H264");
uint8 sps[512], pps[512];
int sps_len = 0, pps_len = 0;
if (p_srt->get_h264_params(sps, &sps_len, pps, &pps_len))
{
memcpy(v_extra, sps, sps_len);
memcpy(v_extra + sps_len, pps, pps_len);
v_extra_len = sps_len + pps_len;
}
if (v_extra_len > 0)
{
avi_set_video_extra_info(p_avictx, v_extra, v_extra_len);
}
}
else if (VIDEO_CODEC_H265 == vcodec)
{
avi_set_video_info(p_avictx, 0, 0, 0, "H265");
uint8 vps[512], sps[512], pps[512];
int vps_len = 0, sps_len = 0, pps_len = 0;
if (p_srt->get_h265_params(sps, &sps_len, pps, &pps_len, vps, &vps_len))
{
memcpy(v_extra, vps, vps_len);
memcpy(v_extra + vps_len, sps, sps_len);
memcpy(v_extra + vps_len + sps_len, pps, pps_len);
v_extra_len = vps_len + sps_len + pps_len;
}
if (v_extra_len > 0)
{
avi_set_video_extra_info(p_avictx, v_extra, v_extra_len);
}
}
else if (VIDEO_CODEC_JPEG == vcodec)
{
avi_set_video_info(p_avictx, 0, 0, 0, "JPEG");
}
else if (VIDEO_CODEC_MP4 == vcodec)
{
avi_set_video_info(p_avictx, 0, 0, 0, "MP4V");
}
int acodec = p_srt->audio_codec();
int sr = p_srt->get_audio_samplerate();
int ch = p_srt->get_audio_channels();
if (AUDIO_CODEC_G711A == acodec)
{
avi_set_audio_info(p_avictx, ch, sr, AUDIO_FORMAT_ALAW);
}
else if (AUDIO_CODEC_G711U == acodec)
{
avi_set_audio_info(p_avictx, ch, sr, AUDIO_FORMAT_MULAW);
}
else if (AUDIO_CODEC_G726 == acodec)
{
avi_set_audio_info(p_avictx, ch, sr, AUDIO_FORMAT_G726);
}
else if (AUDIO_CODEC_G722 == acodec)
{
avi_set_audio_info(p_avictx, ch, sr, AUDIO_FORMAT_G722);
}
else if (AUDIO_CODEC_AAC == acodec)
{
avi_set_audio_info(p_avictx, ch, sr, AUDIO_FORMAT_AAC);
avi_set_audio_extra_info(p_avictx, p_srt->get_audio_config(), p_srt->get_audio_config_len());
}
avi_update_header(p_avictx);
if (p_avictx->ctxf_video)
{
if (v_extra_len > 0)
{
recordVideo(v_extra, v_extra_len, 0, 0);
}
}
return TRUE;
}
void CSrtPlayer::onRecordFileSwitch()
{
AVICTX * p_ctx;
AVICTX * p_oldctx = m_pAviCtx;
QString path = getRecordPath();
QString file = path + "/" + getTempFile(m_ip, ".avi");
p_ctx = avi_write_open(file.toLocal8Bit().toStdString().c_str());
if (NULL == p_ctx)
{
return;
}
p_ctx->ctxf_video = p_oldctx->ctxf_video;
p_ctx->ctxf_audio = p_oldctx->ctxf_audio;
if (p_ctx->ctxf_video)
{
avi_calc_fps(p_oldctx);
avi_set_video_info(p_ctx, p_oldctx->v_fps, p_oldctx->v_width, p_oldctx->v_height, p_oldctx->v_fcc);
avi_set_video_extra_info(p_ctx, p_oldctx->v_extra, p_oldctx->v_extra_len);
}
if (p_ctx->ctxf_audio)
{
avi_set_audio_info(p_ctx, p_oldctx->a_chns, p_oldctx->a_rate, p_oldctx->a_fmt);
avi_set_audio_extra_info(p_ctx, p_oldctx->a_extra, p_oldctx->a_extra_len);
}
avi_write_close(p_oldctx);
avi_update_header(p_ctx);
m_pAviCtx = p_ctx;
if (m_h26XParamSets.vps_size > 0 ||
m_h26XParamSets.sps_size > 0 ||
m_h26XParamSets.pps_size > 0)
{
avi_write_nalu(m_pAviCtx,
m_h26XParamSets.vps, m_h26XParamSets.vps_size,
m_h26XParamSets.sps, m_h26XParamSets.sps_size,
m_h26XParamSets.pps, m_h26XParamSets.pps_size);
}
}