early-access version 3615
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
@@ -9,6 +10,7 @@
|
||||
#include "core/file_sys/nca_metadata.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/hle/service/time/time_zone_manager.h"
|
||||
#include "core/hle/service/time/time_zone_types.h"
|
||||
|
||||
namespace Service::Time::TimeZone {
|
||||
|
||||
@@ -632,11 +634,47 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
}
|
||||
|
||||
const auto typesequiv = [](TimeZoneRule& rule, int a, int b) -> bool {
|
||||
if (a < 0 || a >= rule.type_count || b < 0 || b >= rule.type_count) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const struct TimeTypeInfo* ap = &rule.ttis[a];
|
||||
const struct TimeTypeInfo* bp = &rule.ttis[b];
|
||||
|
||||
return (ap->gmt_offset == bp->gmt_offset && ap->is_dst == bp->is_dst &&
|
||||
(std::strcmp(&rule.chars[ap->abbreviation_list_index],
|
||||
&rule.chars[bp->abbreviation_list_index]) == 0));
|
||||
};
|
||||
|
||||
if (time_zone_rule.type_count == 0) {
|
||||
return {};
|
||||
}
|
||||
if (time_zone_rule.time_count > 1) {
|
||||
UNIMPLEMENTED();
|
||||
if (time_zone_rule.ats[0] <= std::numeric_limits<s64>::max() - seconds_per_repeat) {
|
||||
s64 repeatat = time_zone_rule.ats[0] + seconds_per_repeat;
|
||||
int repeatattype = time_zone_rule.types[0];
|
||||
for (int i = 1; i < time_zone_rule.time_count; ++i) {
|
||||
if (time_zone_rule.ats[i] == repeatat &&
|
||||
typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) {
|
||||
time_zone_rule.go_back = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (std::numeric_limits<s64>::min() + seconds_per_repeat <=
|
||||
time_zone_rule.ats[time_zone_rule.time_count - 1]) {
|
||||
s64 repeatat = time_zone_rule.ats[time_zone_rule.time_count - 1] - seconds_per_repeat;
|
||||
int repeatattype = time_zone_rule.types[time_zone_rule.time_count - 1];
|
||||
for (int i = time_zone_rule.time_count; i >= 0; --i) {
|
||||
if (time_zone_rule.ats[i] == repeatat &&
|
||||
typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) {
|
||||
time_zone_rule.go_ahead = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 default_type{};
|
||||
|
@@ -1276,8 +1276,6 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu
|
||||
has_stream_leap = true;
|
||||
if (expands_right) {
|
||||
begin -= CACHING_PAGESIZE * 256;
|
||||
// We're about to increment cpu_addr by YUZU_PAGESIZE, but have not yet checked for
|
||||
// a buffer at the new begin.
|
||||
cpu_addr = begin - CACHING_PAGESIZE;
|
||||
}
|
||||
if (expands_left) {
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include "common/assert.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/settings.h"
|
||||
#include "video_core/host1x/codecs/codec.h"
|
||||
#include "video_core/host1x/codecs/h264.h"
|
||||
@@ -14,6 +15,8 @@
|
||||
#include "video_core/memory_manager.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavfilter/buffersink.h>
|
||||
#include <libavfilter/buffersrc.h>
|
||||
#include <libavutil/opt.h>
|
||||
#ifdef LIBVA_FOUND
|
||||
// for querying VAAPI driver information
|
||||
@@ -85,6 +88,10 @@ Codec::~Codec() {
|
||||
// Free libav memory
|
||||
avcodec_free_context(&av_codec_ctx);
|
||||
av_buffer_unref(&av_gpu_decoder);
|
||||
|
||||
if (filters_initialized) {
|
||||
avfilter_graph_free(&av_filter_graph);
|
||||
}
|
||||
}
|
||||
|
||||
bool Codec::CreateGpuAvDevice() {
|
||||
@@ -167,6 +174,62 @@ void Codec::InitializeGpuDecoder() {
|
||||
av_codec_ctx->get_format = GetGpuFormat;
|
||||
}
|
||||
|
||||
void Codec::InitializeAvFilters(AVFrame* frame) {
|
||||
const AVFilter* buffer_src = avfilter_get_by_name("buffer");
|
||||
const AVFilter* buffer_sink = avfilter_get_by_name("buffersink");
|
||||
AVFilterInOut* inputs = avfilter_inout_alloc();
|
||||
AVFilterInOut* outputs = avfilter_inout_alloc();
|
||||
SCOPE_EXIT({
|
||||
avfilter_inout_free(&inputs);
|
||||
avfilter_inout_free(&outputs);
|
||||
});
|
||||
|
||||
// Don't know how to get the accurate time_base but it doesn't matter for yadif filter
|
||||
// so just use 1/1 to make buffer filter happy
|
||||
std::string args = fmt::format("video_size={}x{}:pix_fmt={}:time_base=1/1", frame->width,
|
||||
frame->height, frame->format);
|
||||
|
||||
av_filter_graph = avfilter_graph_alloc();
|
||||
int ret = avfilter_graph_create_filter(&av_filter_src_ctx, buffer_src, "in", args.c_str(),
|
||||
nullptr, av_filter_graph);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(Service_NVDRV, "avfilter_graph_create_filter source error: {}", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = avfilter_graph_create_filter(&av_filter_sink_ctx, buffer_sink, "out", nullptr, nullptr,
|
||||
av_filter_graph);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(Service_NVDRV, "avfilter_graph_create_filter sink error: {}", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
inputs->name = av_strdup("out");
|
||||
inputs->filter_ctx = av_filter_sink_ctx;
|
||||
inputs->pad_idx = 0;
|
||||
inputs->next = nullptr;
|
||||
|
||||
outputs->name = av_strdup("in");
|
||||
outputs->filter_ctx = av_filter_src_ctx;
|
||||
outputs->pad_idx = 0;
|
||||
outputs->next = nullptr;
|
||||
|
||||
const char* description = "yadif=1:-1:0";
|
||||
ret = avfilter_graph_parse_ptr(av_filter_graph, description, &inputs, &outputs, nullptr);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(Service_NVDRV, "avfilter_graph_parse_ptr error: {}", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = avfilter_graph_config(av_filter_graph, nullptr);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(Service_NVDRV, "avfilter_graph_config error: {}", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
filters_initialized = true;
|
||||
}
|
||||
|
||||
void Codec::Initialize() {
|
||||
const AVCodecID codec = [&] {
|
||||
switch (current_codec) {
|
||||
@@ -271,8 +334,34 @@ void Codec::Decode() {
|
||||
UNIMPLEMENTED_MSG("Unexpected video format: {}", final_frame->format);
|
||||
return;
|
||||
}
|
||||
av_frames.push(std::move(final_frame));
|
||||
if (av_frames.size() > 10) {
|
||||
if (!final_frame->interlaced_frame) {
|
||||
av_frames.push(std::move(final_frame));
|
||||
} else {
|
||||
if (!filters_initialized) {
|
||||
InitializeAvFilters(final_frame.get());
|
||||
}
|
||||
if (const int ret = av_buffersrc_add_frame_flags(av_filter_src_ctx, final_frame.get(),
|
||||
AV_BUFFERSRC_FLAG_KEEP_REF);
|
||||
ret) {
|
||||
LOG_DEBUG(Service_NVDRV, "av_buffersrc_add_frame_flags error {}", ret);
|
||||
return;
|
||||
}
|
||||
while (true) {
|
||||
auto filter_frame = AVFramePtr{av_frame_alloc(), AVFrameDeleter};
|
||||
|
||||
int ret = av_buffersink_get_frame(av_filter_sink_ctx, filter_frame.get());
|
||||
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR(AVERROR_EOF))
|
||||
break;
|
||||
if (ret < 0) {
|
||||
LOG_DEBUG(Service_NVDRV, "av_buffersink_get_frame error {}", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
av_frames.push(std::move(filter_frame));
|
||||
}
|
||||
}
|
||||
while (av_frames.size() > 10) {
|
||||
LOG_TRACE(Service_NVDRV, "av_frames.push overflow dropped frame");
|
||||
av_frames.pop();
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ extern "C" {
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#endif
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavfilter/avfilter.h>
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
@@ -61,17 +62,24 @@ public:
|
||||
private:
|
||||
void InitializeAvCodecContext();
|
||||
|
||||
void InitializeAvFilters(AVFrame* frame);
|
||||
|
||||
void InitializeGpuDecoder();
|
||||
|
||||
bool CreateGpuAvDevice();
|
||||
|
||||
bool initialized{};
|
||||
bool filters_initialized{};
|
||||
Host1x::NvdecCommon::VideoCodec current_codec{Host1x::NvdecCommon::VideoCodec::None};
|
||||
|
||||
const AVCodec* av_codec{nullptr};
|
||||
AVCodecContext* av_codec_ctx{nullptr};
|
||||
AVBufferRef* av_gpu_decoder{nullptr};
|
||||
|
||||
AVFilterContext* av_filter_src_ctx{nullptr};
|
||||
AVFilterContext* av_filter_sink_ctx{nullptr};
|
||||
AVFilterGraph* av_filter_graph{nullptr};
|
||||
|
||||
Host1x::Host1x& host1x;
|
||||
const Host1x::NvdecCommon::NvdecRegisters& state;
|
||||
std::unique_ptr<Decoder::H264> h264_decoder;
|
||||
|
@@ -378,11 +378,7 @@ if(UNIX AND NOT APPLE)
|
||||
endif()
|
||||
|
||||
if (WIN32 AND QT_VERSION VERSION_GREATER_EQUAL 6)
|
||||
if (MSVC AND NOT ${CMAKE_GENERATOR} STREQUAL "Ninja")
|
||||
set(YUZU_EXE_DIR "${CMAKE_BINARY_DIR}/bin/$<CONFIG>")
|
||||
else()
|
||||
set(YUZU_EXE_DIR "${CMAKE_BINARY_DIR}/bin")
|
||||
endif()
|
||||
set(YUZU_EXE_DIR "$<TARGET_FILE_DIR:yuzu>")
|
||||
add_custom_command(TARGET yuzu POST_BUILD COMMAND ${WINDEPLOYQT_EXECUTABLE} "${YUZU_EXE_DIR}/yuzu.exe" --dir "${YUZU_EXE_DIR}" --libdir "${YUZU_EXE_DIR}" --plugindir "${YUZU_EXE_DIR}/plugins" --no-compiler-runtime --no-opengl-sw --no-system-d3d-compiler --no-translations --verbose 0)
|
||||
endif()
|
||||
|
||||
|
Reference in New Issue
Block a user