<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <blockquote type="cite"
      cite="mid:239F8F92-3099-40DF-9DB2-D51B4F388506@live555.com">
      <pre wrap="" class="moz-quote-pre">

</pre>
      <blockquote type="cite">
        <pre wrap="" class="moz-quote-pre">On Sep 11, 2025, at 5:43 AM, <a class="moz-txt-link-abbreviated" href="mailto:d.gordenin@ngslab.ru">d.gordenin@ngslab.ru</a> wrote:

Hello.
I have an RTSP server, it is fully our code, but it is based on Live555.
</pre>
      </blockquote>
      <pre wrap="" class="moz-quote-pre">
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)</pre>
    </blockquote>
    <p>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:</p>
    <pre>void <a class="moz-txt-link-freetext" href="VideoSource::doGetNextFrame()">VideoSource::doGetNextFrame()</a>
{
  fFrameSize = 0;
  <a class="moz-txt-link-freetext" href="ingest::MediaFrame">ingest::MediaFrame</a> audio_frame_dummy;
  StorageResult result = <a class="moz-txt-link-freetext" href="StorageResult::OK">StorageResult::OK</a>;
  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_ == <a class="moz-txt-link-freetext" href="chunk::StreamInfo::StreamSubtype::UNKNOWN">chunk::StreamInfo::StreamSubtype::UNKNOWN</a>)
        {
          //detect type of the stream
          if (<a class="moz-txt-link-freetext" href="videoreceiver::demuxer::Demuxer::GetH264NaluType((const">videoreceiver::demuxer::Demuxer::GetH264NaluType((const</a> unsigned char*)&frame_.raw_data[0], frame_.raw_data.size()))
            stream_type_ = <a class="moz-txt-link-freetext" href="chunk::StreamInfo::StreamSubtype::H264">chunk::StreamInfo::StreamSubtype::H264</a>;
          else if (<a class="moz-txt-link-freetext" href="videoreceiver::demuxer::Demuxer::GetH265NaluType((const">videoreceiver::demuxer::Demuxer::GetH265NaluType((const</a> unsigned char*)&frame_.raw_data[0], frame_.raw_data.size()))
            stream_type_ = <a class="moz-txt-link-freetext" href="chunk::StreamInfo::StreamSubtype::H265">chunk::StreamInfo::StreamSubtype::H265</a>;
        }
      }
      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 == <a class="moz-txt-link-freetext" href="StorageResult::OK">StorageResult::OK</a> && !frame_.is_key);

              frame_.duration = summ_duration;
            }
            else
            {
              do
              {
                result = storage_manager_->GetPrevVideoFrame(frame_);
                summ_duration += frame_.duration;
              }
              while (result == <a class="moz-txt-link-freetext" href="StorageResult::OK">StorageResult::OK</a> && !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_ != <a class="moz-txt-link-freetext" href="chunk::StreamInfo::StreamSubtype::UNKNOWN">chunk::StreamInfo::StreamSubtype::UNKNOWN</a>)
    {
      //send SEI
      <a class="moz-txt-link-freetext" href="ingest::MediaFrame">ingest::MediaFrame</a> 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 == <a class="moz-txt-link-freetext" href="StorageResult::OK">StorageResult::OK</a>)
      {
        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 == <a class="moz-txt-link-freetext" href="StorageResult::EMPTY_CHUNKS_QUEUE">StorageResult::EMPTY_CHUNKS_QUEUE</a>)
      {
        log_->Info(<a class="moz-txt-link-rfc2396E" href="VideoSource::doGetNextFrame()endofchunksqueue">"VideoSource::doGetNextFrame() end of chunks queue"</a>);
        handleClosure();
        return;
      }

      log_->Info("result={}", (int)result);

      send_frame = false;

      if (stream_type_ == <a class="moz-txt-link-freetext" href="chunk::StreamInfo::StreamSubtype::UNKNOWN">chunk::StreamInfo::StreamSubtype::UNKNOWN</a>)
      {
        //detect type of the stream
        if (<a class="moz-txt-link-freetext" href="videoreceiver::demuxer::Demuxer::GetH264NaluType((const">videoreceiver::demuxer::Demuxer::GetH264NaluType((const</a> unsigned char*)&frame_.raw_data[0], frame_.raw_data.size()))
          stream_type_ = <a class="moz-txt-link-freetext" href="chunk::StreamInfo::StreamSubtype::H264">chunk::StreamInfo::StreamSubtype::H264</a>;
        else if (<a class="moz-txt-link-freetext" href="videoreceiver::demuxer::Demuxer::GetH265NaluType((const">videoreceiver::demuxer::Demuxer::GetH265NaluType((const</a> unsigned char*)&frame_.raw_data[0], frame_.raw_data.size()))
          stream_type_ = <a class="moz-txt-link-freetext" href="chunk::StreamInfo::StreamSubtype::H265">chunk::StreamInfo::StreamSubtype::H265</a>;
      }

      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*)<a class="moz-txt-link-freetext" href="FramedSource::afterGetting">FramedSource::afterGetting</a>, this);
}

</pre>
    <p></p>
    <p><br>
    </p>
    <blockquote type="cite"
      cite="mid:239F8F92-3099-40DF-9DB2-D51B4F388506@live555.com">
      <pre wrap="" class="moz-quote-pre">


Ross Finlayson
Live Networks, Inc.
<a class="moz-txt-link-freetext" href="http://www.live555.com/">http://www.live555.com/</a>


_______________________________________________
live-devel mailing list
<a class="moz-txt-link-abbreviated" href="mailto:live-devel@lists.live555.com">live-devel@lists.live555.com</a>
<a class="moz-txt-link-freetext" href="http://lists.live555.com/mailman/listinfo/live-devel">http://lists.live555.com/mailman/listinfo/live-devel</a>
</pre>
    </blockquote>
    <p><br>
    </p>
  </body>
</html>