我們在研發live555用於集成在NVR時,實時流可通過回調URL讓上層應用去拉流再轉發就可以了,是否可以讓其也支持回放流呢? 答案是肯定的。
我們發現,在live555官方代碼中就已支持回放控制,只是控制部分需要改成我們自己實現的部分,將控制消息通過回調函數回調出來。
解決方案
參考代碼如下:
#include "LiveServerMediaSubsession.h"
LiveServerMediaSubsession::LiveServerMediaSubsession(UsageEnvironment& env, LiveSource *LiveSource, char *streamName, char *mediaTypeName, unsigned estimatedBitrate, RTSP_MEDIA_INFO_T *mediainfo, Boolean reuseFirstSource, unsigned int mediaType, portNumBits defaultPort)
: OnDemandServerMediaSubsession(env, reuseFirstSource /*reuse the first source*/, streamName, mediaTypeName, defaultPort, false),
fLiveSource(LiveSource), mMediaInfo(mediainfo), mMediaType(mediaType)
{
//fEstimatedKbps = (estimatedBitrate + 500)/1000;
fEstimatedKbps = estimatedBitrate;
}
LiveServerMediaSubsession::~LiveServerMediaSubsession() {
}
void LiveServerMediaSubsession::getAbsoluteTimeRange(char*& absStartTime, char*& absEndTime)// const
{
absStartTime = absEndTime = NULL;
//20100929T095038.00Z-20100929T102038.00Z
RTSPSvrCallBack pCallback = (RTSPSvrCallBack )fLiveSource->mCallbackPtr;
if (NULL == pCallback) return;
RTSP_PLAY_CONTROL_INFO_T durationCtlInfo;
memset(&durationCtlInfo, 0x00, sizeof(RTSP_PLAY_CONTROL_INFO_T));
durationCtlInfo.ctrlCommand = RTSP_PLAY_CTRL_CMD_GET_DURATION;
durationCtlInfo.mediaType = mMediaType;
if (fLiveSource->GetFlag() != LIVE_FLAG) return;
pCallback(RTSP_CHANNEL_PLAY_CONTROL, fLiveSource->channelName, &fLiveSource->mChannelHandle, fLiveSource->mMediaInfoPtr, &durationCtlInfo, fLiveSource->mUserPtr, (void *)fLiveSource->mChannelUserPtr);
if ( (int)strlen((char *)durationCtlInfo.startTime) > 0 )
{
absStartTime = (char *)durationCtlInfo.startTime;
}
if ( (int)strlen((char *)durationCtlInfo.endTime) > 0 )
{
absEndTime = (char *)durationCtlInfo.endTime;
}
}
//pause play
void LiveServerMediaSubsession::pauseStreamSource()
{
RTSPSvrCallBack pCallback = (RTSPSvrCallBack )fLiveSource->mCallbackPtr;
if (NULL == pCallback) return;
RTSP_PLAY_CONTROL_INFO_T playCtrlInfo;
memset(&playCtrlInfo, 0x00, sizeof(RTSP_PLAY_CONTROL_INFO_T));
playCtrlInfo.ctrlCommand = RTSP_PLAY_CTRL_CMD_PAUSE;
playCtrlInfo.mediaType = mMediaType;
pCallback(RTSP_CHANNEL_PLAY_CONTROL, fLiveSource->channelName, &fLiveSource->mChannelHandle, fLiveSource->mMediaInfoPtr, &playCtrlInfo, fLiveSource->mUserPtr, (void *)fLiveSource->mChannelUserPtr);
}
//Resume play
void LiveServerMediaSubsession::resumeStreamSource()
{
RTSPSvrCallBack pCallback = (RTSPSvrCallBack )fLiveSource->mCallbackPtr;
if (NULL == pCallback) return;
RTSP_PLAY_CONTROL_INFO_T playCtrlInfo;
memset(&playCtrlInfo, 0x00, sizeof(RTSP_PLAY_CONTROL_INFO_T));
playCtrlInfo.ctrlCommand = RTSP_PLAY_CTRL_CMD_RESUME;
playCtrlInfo.mediaType = mMediaType;
pCallback(RTSP_CHANNEL_PLAY_CONTROL, fLiveSource->channelName, &fLiveSource->mChannelHandle, fLiveSource->mMediaInfoPtr, &playCtrlInfo, fLiveSource->mUserPtr, (void *)fLiveSource->mChannelUserPtr);
}
void LiveServerMediaSubsession::testScaleFactor(float& scale)
{
if ( (scale >= 1.0000000f && scale <= 32.00000000f) ||
(scale >= 0.0312500f && scale<=0.500000000f) ||
(scale >= -32.00000000f && scale <= 0.00000000f) )
{
return;
}
else
{
scale = 1.0f;
}
}
void LiveServerMediaSubsession::setStreamSourceScale(FramedSource* inputSource, float scale)
{
RTSPSvrCallBack pCallback = (RTSPSvrCallBack )fLiveSource->mCallbackPtr;
if (NULL == pCallback) return;
RTSP_PLAY_CONTROL_INFO_T playCtrlInfo;
memset(&playCtrlInfo, 0x00, sizeof(RTSP_PLAY_CONTROL_INFO_T));
playCtrlInfo.ctrlCommand = RTSP_PLAY_CTRL_CMD_SCALE;
playCtrlInfo.mediaType = mMediaType;
playCtrlInfo.scale = scale;
pCallback(RTSP_CHANNEL_PLAY_CONTROL, fLiveSource->channelName, &fLiveSource->mChannelHandle, fLiveSource->mMediaInfoPtr, &playCtrlInfo, fLiveSource->mUserPtr, (void *)fLiveSource->mChannelUserPtr);
}
void LiveServerMediaSubsession::seekStreamSource(FramedSource* inputSource, char*& absStart, char*& absEnd)
{
RTSPSvrCallBack pCallback = (RTSPSvrCallBack )fLiveSource->mCallbackPtr;
if (NULL == pCallback) return;
RTSP_PLAY_CONTROL_INFO_T playCtrlInfo;
memset(&playCtrlInfo, 0x00, sizeof(RTSP_PLAY_CONTROL_INFO_T));
playCtrlInfo.ctrlCommand = RTSP_PLAY_CTRL_CMD_SEEK_STREAM;
playCtrlInfo.mediaType = mMediaType;
if (NULL!=absStart && ((int)strlen(absStart)>0)) strcpy((char*)playCtrlInfo.startTime, absStart);
if (NULL!=absEnd && ((int)strlen(absEnd)>0)) strcpy((char*)playCtrlInfo.endTime, absStart);
pCallback(RTSP_CHANNEL_PLAY_CONTROL, fLiveSource->channelName, &fLiveSource->mChannelHandle, fLiveSource->mMediaInfoPtr, &playCtrlInfo, fLiveSource->mUserPtr, (void *)fLiveSource->mChannelUserPtr);
}
#if 0
void LiveServerMediaSubsession::seekStreamSource(FramedSource* inputSource, double& seekNPT, double streamDuration, u_int64_t& numBytes)
{
printf("LiveServerMediaSubsession::seekStreamSource seekNPT[%s] absEnd[%.2f]\n", seekNPT, streamDuration);
}
void LiveServerMediaSubsession::seekStreamSource(FramedSource* inputSource, char*& absStart, char*& absEnd)
{
printf("LiveServerMediaSubsession::seekStreamSource absStart[%s] absEnd[%s]\n", absStart, absEnd);
}
void LiveServerMediaSubsession::setStreamSourceDuration(FramedSource* inputSource, double streamDuration, u_int64_t& numBytes)
{
printf("LiveServerMediaSubsession::setStreamSourceDuration streamDuration: %.2f\n", streamDuration);
}
void LiveServerMediaSubsession::closeStreamSource(FramedSource* inputSource)
{
printf("LiveServerMediaSubsession::closeStreamSource\n");
}
#endif