Merge branch 'olive-editor:master' into av1

This commit is contained in:
jazztickets
2022-10-12 09:11:27 -06:00
committed by GitHub
34 changed files with 527 additions and 230 deletions
+4 -16
View File
@@ -45,7 +45,6 @@ Decoder::Decoder() :
void Decoder::IncrementAccessTime(qint64 t)
{
QMutexLocker locker(&mutex_);
last_accessed_ += t;
}
@@ -156,7 +155,6 @@ Decoder::RetrieveAudioStatus Decoder::RetrieveAudio(SampleBuffer &dest, const Ti
qint64 Decoder::GetLastAccessedTime()
{
QMutexLocker locker(&mutex_);
return last_accessed_;
}
@@ -215,19 +213,6 @@ DecoderPtr Decoder::CreateFromID(const QString &id)
return nullptr;
}
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;
}
rational Decoder::GetTimestampInTimeUnits(int64_t time, const rational &timebase, int64_t start_time)
{
time -= start_time;
return Timecode::timestamp_to_time(time, timebase);
}
void Decoder::SignalProcessingProgress(int64_t ts, int64_t duration)
{
if (duration != AV_NOPTS_VALUE && duration != 0) {
@@ -294,10 +279,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 -4
View File
@@ -294,8 +294,7 @@ protected:
return stream_;
}
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:
/**
@@ -307,13 +306,13 @@ 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_;
QMutex mutex_;
qint64 last_accessed_;
std::atomic_int64_t last_accessed_;
TexturePtr cached_texture_;
rational cached_time_;
+16
View File
@@ -214,6 +214,7 @@ void EncodingParams::Save(QXmlStreamWriter *writer) const
writer->writeTextElement(QStringLiteral("width"), QString::number(video_params_.width()));
writer->writeTextElement(QStringLiteral("height"), QString::number(video_params_.height()));
writer->writeTextElement(QStringLiteral("format"), QString::number(video_params_.format()));
writer->writeTextElement(QStringLiteral("pixelaspect"), video_params_.pixel_aspect_ratio().toString());
writer->writeTextElement(QStringLiteral("timebase"), video_params_.time_base().toString());
writer->writeTextElement(QStringLiteral("divider"), QString::number(video_params_.divider()));
writer->writeTextElement(QStringLiteral("bitrate"), QString::number(video_bit_rate_));
@@ -258,6 +259,7 @@ void EncodingParams::Save(QXmlStreamWriter *writer) const
writer->writeTextElement(QStringLiteral("samplerate"), QString::number(audio_params_.sample_rate()));
writer->writeTextElement(QStringLiteral("channellayout"), QString::number(audio_params_.channel_layout()));
writer->writeTextElement(QStringLiteral("format"), QString::number(audio_params_.format()));
writer->writeTextElement(QStringLiteral("bitrate"), QString::number(audio_bit_rate_));
}
writer->writeStartElement(QStringLiteral("subtitles"));
@@ -398,6 +400,8 @@ bool EncodingParams::LoadV1(QXmlStreamReader *reader)
video_params_.set_height(reader->readElementText().toInt());
} else if (reader->name() == QStringLiteral("format")) {
video_params_.set_format(static_cast<VideoParams::Format>(reader->readElementText().toInt()));
} else if (reader->name() == QStringLiteral("pixelaspect")) {
video_params_.set_pixel_aspect_ratio(rational::fromString(reader->readElementText()));
} else if (reader->name() == QStringLiteral("timebase")) {
video_params_.set_time_base(rational::fromString(reader->readElementText()));
} else if (reader->name() == QStringLiteral("divider")) {
@@ -448,6 +452,11 @@ bool EncodingParams::LoadV1(QXmlStreamReader *reader)
reader->skipCurrentElement();
}
}
// HACK: Resolve bug where I forgot to serialize pixel aspect ratio
if (video_params_.pixel_aspect_ratio().isNull()) {
video_params_.set_pixel_aspect_ratio(1);
}
} else if (reader->name() == QStringLiteral("audio")) {
XMLAttributeLoop(reader, attr) {
if (attr.name() == QStringLiteral("enabled")) {
@@ -464,10 +473,17 @@ bool EncodingParams::LoadV1(QXmlStreamReader *reader)
audio_params_.set_channel_layout(reader->readElementText().toULongLong());
} else if (reader->name() == QStringLiteral("format")) {
audio_params_.set_format(static_cast<AudioParams::Format>(reader->readElementText().toInt()));
} else if (reader->name() == QStringLiteral("bitrate")) {
audio_bit_rate_ = reader->readElementText().toLongLong();
} else {
reader->skipCurrentElement();
}
}
// HACK: Resolve bug where I forgot to serialize the audio bit rate
if (!audio_bit_rate_) {
audio_bit_rate_ = 320000;
}
} else if (reader->name() == QStringLiteral("subtitles")) {
XMLAttributeLoop(reader, attr) {
if (attr.name() == QStringLiteral("enabled")) {
+37 -18
View File
@@ -40,12 +40,9 @@ extern "C" {
#include <QtConcurrent/QtConcurrent>
#include "codec/planarfiledevice.h"
#include "common/define.h"
#include "common/ffmpegutils.h"
#include "common/filefunctions.h"
#include "common/timecodefunctions.h"
#include "render/framehashcache.h"
#include "render/diskmanager.h"
#include "render/renderer.h"
#include "render/subtitleparams.h"
@@ -143,7 +140,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;
}
@@ -235,9 +232,9 @@ TexturePtr FFmpegDecoder::RetrieveVideoInternal(const RetrieveVideoParams &p)
job.Insert(QStringLiteral("u_channel"), NodeValue(NodeValue::kTexture, QVariant::fromValue(u_plane)));
job.Insert(QStringLiteral("v_channel"), NodeValue(NodeValue::kTexture, QVariant::fromValue(v_plane)));
job.Insert(QStringLiteral("bits_per_pixel"), NodeValue(NodeValue::kInt, bits_per_pixel));
job.Insert(QStringLiteral("full_range"), NodeValue(NodeValue::kBoolean, f->color_range == AVCOL_RANGE_JPEG));
job.Insert(QStringLiteral("full_range"), NodeValue(NodeValue::kBoolean, hw_in->color_range == AVCOL_RANGE_JPEG));
const int *yuv_coeffs = sws_getCoefficients(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(f.get()->colorspace));
const int *yuv_coeffs = sws_getCoefficients(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(hw_in->colorspace));
job.Insert(QStringLiteral("yuv_crv"), NodeValue(NodeValue::kInt, yuv_coeffs[0]));
job.Insert(QStringLiteral("yuv_cgu"), NodeValue(NodeValue::kInt, yuv_coeffs[2]));
job.Insert(QStringLiteral("yuv_cgv"), NodeValue(NodeValue::kInt, yuv_coeffs[3]));
@@ -246,7 +243,7 @@ TexturePtr FFmpegDecoder::RetrieveVideoInternal(const RetrieveVideoParams &p)
int interlacing = 0;
if (p.src_interlacing != VideoParams::kInterlaceNone) {
if (frame_rate_tb_.isNull()) {
frame_rate_tb_ = av_guess_frame_rate(instance_.fmt_ctx(), instance_.avstream(), f.get());
frame_rate_tb_ = av_guess_frame_rate(instance_.fmt_ctx(), instance_.avstream(), hw_in);
// Double frame rate for interlaced fields
frame_rate_tb_ *= 2;
@@ -256,7 +253,7 @@ TexturePtr FFmpegDecoder::RetrieveVideoInternal(const RetrieveVideoParams &p)
}
int64_t req = Timecode::time_to_timestamp(p.time, frame_rate_tb_);
int64_t frm = Timecode::rescale_timestamp(f->pts - instance_.avstream()->start_time, instance_.avstream()->time_base, frame_rate_tb_);
int64_t frm = Timecode::rescale_timestamp(hw_in->pts - instance_.avstream()->start_time, instance_.avstream()->time_base, frame_rate_tb_);
bool first = (req == frm);
bool top_first = (p.src_interlacing == VideoParams::kInterlacedTopFirst);
@@ -268,6 +265,8 @@ TexturePtr FFmpegDecoder::RetrieveVideoInternal(const RetrieveVideoParams &p)
tex = p.renderer->CreateTexture(vp);
p.renderer->BlitToTexture(Yuv2RgbShader, job, tex.get(), false);
av_frame_unref(working_frame_);
}
}
@@ -311,6 +310,18 @@ void FFmpegDecoder::CloseInternal()
native_output_pix_fmt_ = VideoParams::kFormatInvalid;
}
rational FFmpegDecoder::GetAudioStartOffset() const
{
auto f = instance_.fmt_ctx();
if (f) {
rational fmt_start = rational(instance_.fmt_ctx()->start_time, AV_TIME_BASE);
rational str_start = rational(instance_.avstream()->time_base) * instance_.avstream()->start_time;
return str_start - fmt_start;
} else {
return 0;
}
}
QString FFmpegDecoder::id() const
{
return QStringLiteral("ffmpeg");
@@ -787,11 +798,19 @@ 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);
int64_t target_ts = Timecode::time_to_timestamp(time, instance_.avstream()->time_base);
const int64_t min_seek = -instance_.avstream()->start_time;
if (interlacing != VideoParams::kInterlaceNone && !IsPixelFormatGLSLCompatible(static_cast<AVPixelFormat>(instance_.avstream()->codecpar->format))) {
target_ts *= 2;
}
if (instance_.fmt_ctx()->start_time != AV_NOPTS_VALUE) {
target_ts += av_rescale_q(instance_.fmt_ctx()->start_time, {1, AV_TIME_BASE}, instance_.avstream()->time_base);
}
const int64_t min_seek = 0;
int64_t seek_ts = std::max(min_seek, target_ts - MaximumQueueSize());
bool still_seeking = false;
@@ -991,8 +1010,10 @@ bool FFmpegDecoder::InitScaler(AVFrame *input, const RetrieveVideoParams& params
// Link filters as necessary
AVFilterContext *last_filter = buffersrc_ctx_;
bool glsl_available = IsPixelFormatGLSLCompatible(static_cast<AVPixelFormat>(input->format));
// Add deinterlace filter if necessary
if (filter_params_.src_interlacing != VideoParams::kInterlaceNone) {
if (filter_params_.src_interlacing != VideoParams::kInterlaceNone && !glsl_available) {
AVFilterContext* deint_filter;
snprintf(filter_args, kFilterArgSz, "mode=1:parity=%s",
@@ -1006,14 +1027,14 @@ bool FFmpegDecoder::InitScaler(AVFrame *input, const RetrieveVideoParams& params
}
// Add scale filter if necessary
int dst_width, dst_height;
if (filter_params_.divider > 1) {
AVFilterContext* scale_filter;
int dst_width, dst_height;
dst_width = VideoParams::GetScaledDimension(src_width, filter_params_.divider);
dst_height = VideoParams::GetScaledDimension(src_height, filter_params_.divider);
snprintf(filter_args, kFilterArgSz, "w=%d:h=%d:flags=fast_bilinear:interl=-1",
snprintf(filter_args, kFilterArgSz, "w=%d:h=%d:flags=fast_bilinear:interl=0",
dst_width,
dst_height);
@@ -1021,13 +1042,10 @@ bool FFmpegDecoder::InitScaler(AVFrame *input, const RetrieveVideoParams& params
avfilter_link(last_filter, 0, scale_filter, 0);
last_filter = scale_filter;
} else {
dst_width = src_width;
dst_height = src_height;
}
// Add format filter if necessary
if (ideal_pix_fmt != input->format && !IsPixelFormatGLSLCompatible(static_cast<AVPixelFormat>(input->format))) {
if (ideal_pix_fmt != input->format && !glsl_available) {
AVFilterContext* format_filter;
snprintf(filter_args, kFilterArgSz, "pix_fmts=%u", ideal_pix_fmt);
@@ -1129,6 +1147,7 @@ int FFmpegDecoder::MaximumQueueSize()
FFmpegDecoder::Instance::Instance() :
fmt_ctx_(nullptr),
codec_ctx_(nullptr),
avstream_(nullptr),
opts_(nullptr)
{
}
+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();