[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