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()
#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
int
MediaEncoder::encode(VideoFrame& input, bool is_keyframe,
......@@ -354,7 +363,8 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe,
scaler_.scale_with_aspect(input, scaledFrame_);
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) {
frame->pict_type = AV_PICTURE_TYPE_I;
......@@ -412,7 +422,8 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
frame->channels = buffer.channels();
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;
const auto buffer_size = \
......
......@@ -182,12 +182,6 @@ MediaRecorder::recordData(AVFrame* frame, bool isVideo, bool fromPeer)
const MediaStream& ms = streams_[isVideo][fromPeer];
// stream has to start at 0
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
return sendToEncoder(input, streamIdx);
......@@ -228,7 +222,7 @@ MediaRecorder::initRecord()
videoFilter_.reset();
if (nbReceivedVideoStreams_ > 0) {
auto videoStream = setupVideoOutput();
const MediaStream& videoStream = setupVideoOutput();
if (videoStream.format < 0) {
RING_ERR() << "Could not retrieve video recorder stream properties";
return -1;
......@@ -242,7 +236,7 @@ MediaRecorder::initRecord()
audioFilter_.reset();
if (nbReceivedAudioStreams_ > 0) {
auto audioStream = setupAudioOutput();
const MediaStream& audioStream = setupAudioOutput();
if (audioStream.format < 0) {
RING_ERR() << "Could not retrieve audio recorder stream properties";
return -1;
......@@ -338,8 +332,8 @@ MediaRecorder::buildVideoFilter()
{
std::stringstream v;
const auto p = streams_[true][true];
const auto l = streams_[true][false];
const MediaStream& p = streams_[true][true];
const MediaStream& l = streams_[true][false];
const constexpr int minHeight = 720;
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