Files
ANSCORE/MediaClient/media/rtmp_player.cpp

408 lines
9.8 KiB
C++
Raw Normal View History

2026-03-28 16:54:11 +11:00
/***************************************************************************************
*
* 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 "rtmp_player.h"
#include "utils.h"
/***************************************************************************************/
int rtmp_notify_callback(int evt, void * puser)
{
CRtmpPlayer * pPlayer = (CRtmpPlayer *) puser;
pPlayer->onNotify(evt);
return 0;
}
int rtmp_audio_callback(uint8 * pdata, int len, uint32 ts, void *puser)
{
CRtmpPlayer * pPlayer = (CRtmpPlayer *) puser;
pPlayer->onAudio(pdata, len, ts);
return 0;
}
int rtmp_video_callback(uint8 * pdata, int len, uint32 ts, void *puser)
{
CRtmpPlayer * pPlayer = (CRtmpPlayer *) puser;
pPlayer->onVideo(pdata, len, ts);
return 0;
}
/***************************************************************************************/
CRtmpPlayer::CRtmpPlayer()
: CVideoPlayer()
{
memset(m_ip, 0, sizeof(m_ip));
}
CRtmpPlayer::~CRtmpPlayer()
{
close();
}
std::string CRtmpPlayer::createNewRTMPUrl(const std::string& username,
const std::string& password,
const std::string& url) {
// Copy the original strings to avoid modifying the originals
std::string modUsername = username;
std::string modPassword = password;
// Replace '@' with '_' in username and password
std::replace(modUsername.begin(), modUsername.end(), '@', '_');
std::replace(modPassword.begin(), modPassword.end(), '@', '_');
// Extract the protocol and rest of the URL
size_t protocolEndPos = url.find("://") + 3; // Find the position right after "://"
std::string protocol = url.substr(0, protocolEndPos); // Include "://"
// Construct the new URL with modified credentials
std::string newUrl = protocol;
newUrl += modUsername + ":" + modPassword + "@";
newUrl += url.substr(protocolEndPos);
return newUrl;
}
BOOL CRtmpPlayer::open(std::string fileName)
{
close();
CVideoPlayer::open(fileName);
char host[100];
url_split(fileName.c_str(), NULL, 0, NULL, 0, NULL, 0, host, sizeof(host), NULL, NULL, 0);
if (host[0] == '\0')
{
return FALSE;
}
strncpy(m_ip, host, sizeof(m_ip) - 1);
m_rtmp.set_notify_cb(rtmp_notify_callback, this);
m_rtmp.set_audio_cb(rtmp_audio_callback);
m_rtmp.set_video_cb(rtmp_video_callback);
return TRUE;
}
BOOL CRtmpPlayer::open(std::string _username, std::string _password, std::string _url)
{
close();
CVideoPlayer::open(_username, _password, _url);
int port;
char proto[32], username[100], password[100], host[100], path[200];
std::string fileName = createNewRTMPUrl(_username, _password, _url);
url_split(fileName.c_str(),
proto, sizeof(proto),
username, sizeof(username),
password, sizeof(password),
host, sizeof(host),
&port,
path, sizeof(path));
if (host[0] == '\0')
{
return FALSE;
}
strncpy(m_ip, host, sizeof(m_ip) - 1);
m_rtmp.set_notify_cb(rtmp_notify_callback, this);
m_rtmp.set_audio_cb(rtmp_audio_callback);
m_rtmp.set_video_cb(rtmp_video_callback);
return TRUE;
}
void CRtmpPlayer::close()
{
// stop rtmp connection
m_rtmp.rtmp_stop();
m_rtmp.rtmp_close();
m_bPlaying = FALSE;
m_bPaused = FALSE;
CVideoPlayer::StopVideoDecoder();
CVideoPlayer::close();
}
BOOL CRtmpPlayer::play()
{
if (m_rtmp.rtmp_start(m_sFileName.c_str(), m_acct.c_str(), m_pass.c_str()))
{
m_bPlaying = TRUE;
m_bPaused = FALSE;
}
CVideoPlayer::StartVideoDecoder();// Start the video decoder
return m_bPlaying;
}
void CRtmpPlayer::stop()
{
if (m_bPlaying || m_bPaused)
{
m_rtmp.rtmp_stop();
}
// Set flags BEFORE stopping decoder so rx thread stops calling decode()
m_bPlaying = FALSE;
m_bPaused = FALSE;
CVideoPlayer::StopVideoDecoder(); // Stop the video decoder
}
BOOL CRtmpPlayer::pause()
{
if (m_bPlaying)
{
if (m_rtmp.rtmp_pause())
{
m_bPaused = TRUE;
m_bPlaying = FALSE;
}
}
else if (m_bPaused)
{
if (m_rtmp.rtmp_play())
{
m_bPaused = FALSE;
m_bPlaying = TRUE;
}
}
CVideoPlayer::StopVideoDecoder(); // Stop the video decoder
return m_bPaused;
}
BOOL CRtmpPlayer::seek(int pos)
{
return FALSE;
}
int64 CRtmpPlayer::getElapse()
{
uint32 cur_ts;
uint32 init_ts;
int frequency;
if (m_videoClock.SyncTime.tv_sec > m_audioClock.SyncTime.tv_sec)
{
cur_ts = m_videoClock.SyncTimestamp;
init_ts = m_rtmp.get_video_init_ts();
frequency = getVideoClock();
}
else if (m_videoClock.SyncTime.tv_sec == m_audioClock.SyncTime.tv_sec &&
m_videoClock.SyncTime.tv_usec > m_audioClock.SyncTime.tv_usec)
{
cur_ts = m_videoClock.SyncTimestamp;
init_ts = m_rtmp.get_video_init_ts();
frequency = getVideoClock();
}
else
{
cur_ts = m_audioClock.SyncTimestamp;
init_ts = m_rtmp.get_audio_init_ts();
frequency = getAudioClock();
}
if (init_ts == 0)
{
return 0;
}
int64 elapse;
int timestampDiff = cur_ts - init_ts;
// Divide this by the timestamp frequency to get real time:
double timeDiff = timestampDiff / (double)frequency;
if (timeDiff >= 0.0)
{
elapse = timeDiff * 1000;
}
else
{
timeDiff = -timeDiff;
elapse = timeDiff * 1000;
}
return elapse;
}
int64 CRtmpPlayer::getDuration()
{
return 0;
}
int CRtmpPlayer::getVideoCodec()
{
return m_rtmp.video_codec();
}
int CRtmpPlayer::getAudioCodec()
{
return m_rtmp.audio_codec();
}
void CRtmpPlayer::setBbox(cv::Rect bbox) {
CVideoPlayer::setBbox(bbox);
}
void CRtmpPlayer::setCrop(bool crop) {
CVideoPlayer::setCrop(crop);
}
void CRtmpPlayer::onNotify(int evt)
{
if (evt == RTMP_EVE_VIDEOREADY)
{
int videoCodec = m_rtmp.video_codec();
if (VIDEO_CODEC_NONE != videoCodec)
{
openVideo(videoCodec);
}
}
else if (evt == RTMP_EVE_AUDIOREADY)
{
int audioCodec = m_rtmp.audio_codec();
if (AUDIO_CODEC_NONE != audioCodec)
{
openAudio(audioCodec, m_rtmp.get_audio_samplerate(), m_rtmp.get_audio_channels());
}
}
//emit notify(evt);
}
void CRtmpPlayer::onAudio(uint8 * pdata, int len, uint32 ts)
{
playAudio(pdata, len, ts, 0);
}
void CRtmpPlayer::onVideo(uint8 * pdata, int len, uint32 ts)
{
playVideo(pdata, len, ts, 0);
}
BOOL CRtmpPlayer::onRecord()
{
CRtmpClient * p_rtmp = &m_rtmp;
AVICTX * p_avictx = m_pAviCtx;
int vcodec = p_rtmp->video_codec();
int fps = p_rtmp->get_video_framerate();
int v_extra_len = 0;
uint8 v_extra[1024];
if (VIDEO_CODEC_H264 == vcodec)
{
avi_set_video_info(p_avictx, fps, 0, 0, "H264");
uint8 sps[512], pps[512];
int sps_len = 0, pps_len = 0;
if (p_rtmp->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, fps, 0, 0, "H265");
uint8 vps[512], sps[512], pps[512];
int vps_len = 0, sps_len = 0, pps_len = 0;
if (p_rtmp->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, fps, 0, 0, "JPEG");
}
else if (VIDEO_CODEC_MP4 == vcodec)
{
avi_set_video_info(p_avictx, fps, 0, 0, "MP4V");
}
int acodec = p_rtmp->audio_codec();
int sr = p_rtmp->get_audio_samplerate();
int ch = p_rtmp->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_rtmp->get_audio_config(), p_rtmp->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;
}