Skip to content
Snippets Groups Projects
Commit cffd2587 authored by Philippe Gorley's avatar Philippe Gorley Committed by Sébastien Blin
Browse files

encoder: correctly set frame timestamp


Timestamp has to consider frame/sample rate and stream time base.

Fixes recording synchronization issues.

Change-Id: Ib270f9482b757eed65e7daa8ad7acf46db7f6450
Reviewed-by: default avatarSebastien Blin <sebastien.blin@savoirfairelinux.com>
parent 68286730
No related branches found
No related tags found
No related merge requests found
...@@ -341,6 +341,15 @@ MediaEncoder::startIO() ...@@ -341,6 +341,15 @@ MediaEncoder::startIO()
#endif #endif
} }
// seq: frame number for video, sent samples audio
// sampleFreq: fps for video, sample rate for audio
// clock: stream time base (packetization interval times)
int64_t
getNextTimestamp(int64_t seq, rational<int64_t> sampleFreq, rational<int64_t> clock)
{
return (seq / (sampleFreq * clock)).real<int64_t>();
}
#ifdef RING_VIDEO #ifdef RING_VIDEO
int int
MediaEncoder::encode(VideoFrame& input, bool is_keyframe, MediaEncoder::encode(VideoFrame& input, bool is_keyframe,
...@@ -354,7 +363,8 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe, ...@@ -354,7 +363,8 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe,
scaler_.scale_with_aspect(input, scaledFrame_); scaler_.scale_with_aspect(input, scaledFrame_);
auto frame = scaledFrame_.pointer(); auto frame = scaledFrame_.pointer();
frame->pts = frame_number; AVStream* st = outputCtx_->streams[currentStreamIdx_];
frame->pts = getNextTimestamp(frame_number, st->avg_frame_rate, st->time_base);
if (is_keyframe) { if (is_keyframe) {
frame->pict_type = AV_PICTURE_TYPE_I; frame->pict_type = AV_PICTURE_TYPE_I;
...@@ -412,7 +422,8 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer) ...@@ -412,7 +422,8 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
frame->channels = buffer.channels(); frame->channels = buffer.channels();
frame->sample_rate = sample_rate; frame->sample_rate = sample_rate;
frame->pts = sent_samples; AVStream* st = outputCtx_->streams[currentStreamIdx_];
frame->pts = getNextTimestamp(sent_samples, st->codecpar->sample_rate, st->time_base);
sent_samples += frame->nb_samples; sent_samples += frame->nb_samples;
const auto buffer_size = \ const auto buffer_size = \
......
...@@ -182,12 +182,6 @@ MediaRecorder::recordData(AVFrame* frame, bool isVideo, bool fromPeer) ...@@ -182,12 +182,6 @@ MediaRecorder::recordData(AVFrame* frame, bool isVideo, bool fromPeer)
const MediaStream& ms = streams_[isVideo][fromPeer]; const MediaStream& ms = streams_[isVideo][fromPeer];
// stream has to start at 0 // stream has to start at 0
input->pts = input->pts - ms.firstTimestamp; input->pts = input->pts - ms.firstTimestamp;
// convert streams to rtp timestamps if not already done by FFmpeg
if (isVideo && !fromPeer) {
input->pts = input->pts / (ms.frameRate * ms.timeBase).real();
} else if (!isVideo) {
input->pts = input->pts / (ms.timeBase * ms.sampleRate).real();
}
if (inputName.empty()) // #nofilters if (inputName.empty()) // #nofilters
return sendToEncoder(input, streamIdx); return sendToEncoder(input, streamIdx);
...@@ -228,7 +222,7 @@ MediaRecorder::initRecord() ...@@ -228,7 +222,7 @@ MediaRecorder::initRecord()
videoFilter_.reset(); videoFilter_.reset();
if (nbReceivedVideoStreams_ > 0) { if (nbReceivedVideoStreams_ > 0) {
auto videoStream = setupVideoOutput(); const MediaStream& videoStream = setupVideoOutput();
if (videoStream.format < 0) { if (videoStream.format < 0) {
RING_ERR() << "Could not retrieve video recorder stream properties"; RING_ERR() << "Could not retrieve video recorder stream properties";
return -1; return -1;
...@@ -242,7 +236,7 @@ MediaRecorder::initRecord() ...@@ -242,7 +236,7 @@ MediaRecorder::initRecord()
audioFilter_.reset(); audioFilter_.reset();
if (nbReceivedAudioStreams_ > 0) { if (nbReceivedAudioStreams_ > 0) {
auto audioStream = setupAudioOutput(); const MediaStream& audioStream = setupAudioOutput();
if (audioStream.format < 0) { if (audioStream.format < 0) {
RING_ERR() << "Could not retrieve audio recorder stream properties"; RING_ERR() << "Could not retrieve audio recorder stream properties";
return -1; return -1;
...@@ -338,8 +332,8 @@ MediaRecorder::buildVideoFilter() ...@@ -338,8 +332,8 @@ MediaRecorder::buildVideoFilter()
{ {
std::stringstream v; std::stringstream v;
const auto p = streams_[true][true]; const MediaStream& p = streams_[true][true];
const auto l = streams_[true][false]; const MediaStream& l = streams_[true][false];
const constexpr int minHeight = 720; const constexpr int minHeight = 720;
const auto newFps = std::max(p.frameRate, l.frameRate); const auto newFps = std::max(p.frameRate, l.frameRate);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment