[Live-devel] Stopping playing after changing resolution
d.gordenin at ngslab.ru
d.gordenin at ngslab.ru
Thu Sep 11 07:26:04 PDT 2025
>
>> On Sep 11, 2025, at 5:43 AM,d.gordenin at ngslab.ru wrote:
>>
>> Hello.
>> I have an RTSP server, it is fully our code, but it is based on Live555.
> Sorry, but if this “fully your code”, then you can’t expect help on this mailing list. (But, a reminder that if it’s “based on LIVE555”, you are subject to the terms of the LGPL)
Code is not a problem, but there is a lot of them, I don't know which
one you are interested on... This is the doGetNextFrame() function, here
the frames fly to the client via live555:
voidVideoSource::doGetNextFrame()
{
fFrameSize = 0;
ingest::MediaFrame audio_frame_dummy;
StorageResult result =StorageResult::OK;
uint64_t summ_duration = 0;
unsigned int start_delay = config_->GetStartStreamerDelay();
unsigned int start_fps = config_->GetStartStreamerFps();
while (fFrameSize == 0)
{
bool res = false;
log_->Info("Next frame");
if (!send_sei && !send_frame)
{
frame_.raw_data.resize(0);
if (start_source_)
{
if (first_frame_ && storage_manager_->seek_position != 0)
{
result = storage_manager_->GetNextVideoFrame(frame_);
first_frames_.push_back(frame_);
log_->Info("Prepare frame: {} {} {} {}", frame_.frame_time, frame_.is_key, frame_.duration, frame_.raw_data.size());
while (frame_.frame_time <= (uint64_t)storage_manager_->seek_position)
{
result = storage_manager_->GetNextVideoFrame(frame_);
//log_->Info("Prepare frame: {} {} {} {}", frame_.frame_time, frame_.is_key, frame_.duration, frame_.raw_data.size());
first_frames_.push_back(frame_);
}
send_sei = true;
}
if (!first_frames_.empty())
{
if (start_fps > 0)
frame_.frame_time = storage_manager_->seek_position - first_frames_.size() * start_fps;
else
frame_.frame_time = first_frames_[0].frame_time;
}
first_frame_ = false;
//send VPS, SPS, PPS before the first frame
frame_.is_key = false;
frame_.duration = 0;
if (!vps_.empty())
{
frame_.raw_data.assign(vps_.begin(), vps_.end());
vps_.clear();
log_->Info("Prepare VPS: {} {}", frame_.frame_time, frame_.raw_data.size());
}
else if (!sps_.empty())
{
frame_.raw_data.assign(sps_.begin(), sps_.end());
sps_.clear();
log_->Info("Prepare SPS: {} {}", frame_.frame_time, frame_.raw_data.size());
}
else if (!pps_.empty())
{
frame_.raw_data.assign(pps_.begin(), pps_.end());
pps_.clear();
log_->Info("Prepare PPS: {} {}", frame_.frame_time, frame_.raw_data.size());
}
else
{
send_sei = false;
start_source_ = false;
}
if (stream_type_ ==chunk::StreamInfo::StreamSubtype::UNKNOWN)
{
//detect type of the stream
if (videoreceiver::demuxer::Demuxer::GetH264NaluType((const unsigned char*)&frame_.raw_data[0], frame_.raw_data.size()))
stream_type_ =chunk::StreamInfo::StreamSubtype::H264;
else if (videoreceiver::demuxer::Demuxer::GetH265NaluType((const unsigned char*)&frame_.raw_data[0], frame_.raw_data.size()))
stream_type_ =chunk::StreamInfo::StreamSubtype::H265;
}
}
else
{
if (!first_frames_.empty())
{
frame_ = first_frames_[0];
if (start_delay > 0)
frame_.duration = start_delay;
if (start_fps > 0)
frame_.frame_time = storage_manager_->seek_position - first_frames_.size() * start_fps;
first_frames_.erase(first_frames_.begin());
}
else
{
if (decimator_.OnlyKeyFrames())
{
if (!reverse_)
{
do
{
result = storage_manager_->GetNextVideoFrame(frame_);
summ_duration += frame_.duration;
}
while (result ==StorageResult::OK && !frame_.is_key);
frame_.duration = summ_duration;
}
else
{
do
{
result = storage_manager_->GetPrevVideoFrame(frame_);
summ_duration += frame_.duration;
}
while (result ==StorageResult::OK && !frame_.is_key);
frame_.duration = summ_duration;
}
}
else
{
if (!reverse_)
result = storage_manager_->GetNextVideoFrame(frame_);
}
}
send_sei = true;
}
}
if (send_sei && frame_.frame_time != 0 && stream_type_ !=chunk::StreamInfo::StreamSubtype::UNKNOWN)
{
//send SEI
ingest::MediaFrame sei_frame;
makeSeiFrame(frame_.frame_time, sei_frame);
//log_->Info("Send SEI: {} {} {} {}", sei_frame.frame_time, sei_frame.is_key, sei_frame.duration, sei_frame.raw_data.size());
memcpy(fTo, sei_frame.raw_data.data(), sei_frame.raw_data.size());
fFrameSize = sei_frame.raw_data.size();
send_sei = false;
send_frame = true;
fDurationInMicroseconds = 0;
}
else
{
//send the frame
if (result ==StorageResult::OK)
{
if (decimator_.ApproveFrame(frame_.is_key))
{
log_->Info("Send frame: {} {} {} {}", frame_.frame_time, frame_.is_key, frame_.duration, frame_.raw_data.size());
memcpy(fTo, frame_.raw_data.data(), frame_.raw_data.size());
fFrameSize = frame_.raw_data.size();
}
}
else if (result ==StorageResult::EMPTY_CHUNKS_QUEUE)
{
log_->Info("VideoSource::doGetNextFrame() end of chunks queue");
handleClosure();
return;
}
log_->Info("result={}", (int)result);
send_frame = false;
if (stream_type_ ==chunk::StreamInfo::StreamSubtype::UNKNOWN)
{
//detect type of the stream
if (videoreceiver::demuxer::Demuxer::GetH264NaluType((const unsigned char*)&frame_.raw_data[0], frame_.raw_data.size()))
stream_type_ =chunk::StreamInfo::StreamSubtype::H264;
else if (videoreceiver::demuxer::Demuxer::GetH265NaluType((const unsigned char*)&frame_.raw_data[0], frame_.raw_data.size()))
stream_type_ =chunk::StreamInfo::StreamSubtype::H265;
}
if (!first_frames_.empty() && start_delay > 0)
fDurationInMicroseconds = start_delay * 1000;
else
fDurationInMicroseconds = static_cast<unsigned>(decimator_.CalcDuration(frame_.duration));
}
}
//calculate RTP timestamp
if (start_time_ == 0)
{
timeval s;
gettimeofday(&s, NULL);
start_time_ = ((long long)s.tv_sec * 1000000UL + s.tv_usec);
first_frame_time_ = frame_.frame_time;
//log_->Info("gettimeofday={},{} start_time_={} first_frame_time_={}", s.tv_sec, s.tv_usec, start_time_, first_frame_time_);
}
uint64_t t = uint64_t((double)frame_.frame_time * double(start_time_) / first_frame_time_);
if (decimator_.rate_ == 1)
{
fPresentationTime.tv_sec = t / 1000000UL;
fPresentationTime.tv_usec = t % 1000000UL;
}
else
gettimeofday(&fPresentationTime, NULL);
rtp_timestamp_ = t;
//log_->Info("fDurationInMicroseconds={} fPresentationTime={},{} rtp_timestamp_={}", fDurationInMicroseconds, fPresentationTime.tv_sec,
// fPresentationTime.tv_usec, rtp_timestamp_);
log_->Info("nextTask");
nextTask() = envir().taskScheduler().scheduleDelayedTask(0, (TaskFunc*)FramedSource::afterGetting, this);
}
>
>
> Ross Finlayson
> Live Networks, Inc.
> http://www.live555.com/
>
>
> _______________________________________________
> live-devel mailing list
> live-devel at lists.live555.com
> http://lists.live555.com/mailman/listinfo/live-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20250911/18ac2f72/attachment-0001.htm>
More information about the live-devel
mailing list