decoder: fixed longstanding audio sync issue

Wow this has probably been a bug for 3 years straight
This commit is contained in:
itsmattkc
2022-10-03 15:30:52 -07:00
parent 9d2a9a632c
commit 3275dac50f
4 changed files with 27 additions and 9 deletions
+5 -5
View File
@@ -217,14 +217,11 @@ DecoderPtr Decoder::CreateFromID(const QString &id)
int64_t Decoder::GetTimeInTimebaseUnits(const rational &time, const rational &timebase, int64_t start_time)
{
int64_t t = Timecode::time_to_timestamp(time, timebase);
t += start_time;
return t;
return Timecode::time_to_timestamp(time, timebase);
}
rational Decoder::GetTimestampInTimeUnits(int64_t time, const rational &timebase, int64_t start_time)
{
time -= start_time;
return Timecode::timestamp_to_time(time, timebase);
}
@@ -294,10 +291,13 @@ bool Decoder::ConformAudioInternal(const QVector<QString> &filenames, const Audi
return false;
}
bool Decoder::RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector<QString> &conform_filenames, const TimeRange& range, LoopMode loop_mode, const AudioParams &input_params)
bool Decoder::RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector<QString> &conform_filenames, TimeRange range, LoopMode loop_mode, const AudioParams &input_params)
{
PlanarFileDevice input;
if (input.open(conform_filenames, QFile::ReadOnly)) {
// Offset range by audio start offset
range -= GetAudioStartOffset();
qint64 read_index = input_params.time_to_bytes(range.in()) / input_params.channel_count();
qint64 write_index = 0;
+3 -1
View File
@@ -297,6 +297,8 @@ protected:
static int64_t GetTimeInTimebaseUnits(const rational& time, const rational& timebase, int64_t start_time);
static rational GetTimestampInTimeUnits(int64_t time, const rational& timebase, int64_t start_time);
virtual rational GetAudioStartOffset() const { return 0; }
signals:
/**
* @brief While indexing, this signal will provide progress as a percentage (0-100 inclusive) if
@@ -307,7 +309,7 @@ signals:
private:
void UpdateLastAccessed();
bool RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector<QString> &conform_filenames, const TimeRange &range, LoopMode loop_mode, const AudioParams &params);
bool RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector<QString> &conform_filenames, TimeRange range, LoopMode loop_mode, const AudioParams &params);
CodecStream stream_;
+16 -2
View File
@@ -143,7 +143,7 @@ bool FFmpegDecoder::OpenInternal()
TexturePtr FFmpegDecoder::RetrieveVideoInternal(const RetrieveVideoParams &p)
{
if (AVFramePtr f = RetrieveFrame(p.time, p.cancelled)) {
if (AVFramePtr f = RetrieveFrame(p.time, p.src_interlacing, p.cancelled)) {
if (p.cancelled && p.cancelled->IsCancelled()) {
return nullptr;
}
@@ -311,6 +311,16 @@ void FFmpegDecoder::CloseInternal()
native_output_pix_fmt_ = VideoParams::kFormatInvalid;
}
rational FFmpegDecoder::GetAudioStartOffset() const
{
AVStream *s = this->instance_.avstream();
if (s) {
return rational(s->start_time * s->time_base.num, s->time_base.den);
} else {
return 0;
}
}
QString FFmpegDecoder::id() const
{
return QStringLiteral("ffmpeg");
@@ -787,10 +797,14 @@ void FFmpegDecoder::ClearFrameCache()
}
}
AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, CancelAtom *cancelled)
AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, VideoParams::Interlacing interlacing, CancelAtom *cancelled)
{
int64_t target_ts = GetTimeInTimebaseUnits(time, instance_.avstream()->time_base, instance_.avstream()->start_time);
if (interlacing != VideoParams::kInterlaceNone) {
target_ts *= 2;
}
const int64_t min_seek = -instance_.avstream()->start_time;
int64_t seek_ts = std::max(min_seek, target_ts - MaximumQueueSize());
bool still_seeking = false;
+3 -1
View File
@@ -67,6 +67,8 @@ protected:
virtual bool ConformAudioInternal(const QVector<QString>& filenames, const AudioParams &params, CancelAtom *cancelled) override;
virtual void CloseInternal() override;
virtual rational GetAudioStartOffset() const override;
private:
class Instance
{
@@ -148,7 +150,7 @@ private:
void ClearFrameCache();
AVFramePtr RetrieveFrame(const rational &time, CancelAtom *cancelled);
AVFramePtr RetrieveFrame(const rational &time, VideoParams::Interlacing interlacing, CancelAtom *cancelled);
void RemoveFirstFrame();