summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CMakeLists.txt1
-rw-r--r--externals/ffmpeg/CMakeLists.txt5
-rw-r--r--src/video_core/host1x/codecs/codec.cpp93
-rw-r--r--src/video_core/host1x/codecs/codec.h8
4 files changed, 103 insertions, 4 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 561eaafb2..7276ac9dd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -453,6 +453,7 @@ endif()
453# List of all FFmpeg components required 453# List of all FFmpeg components required
454set(FFmpeg_COMPONENTS 454set(FFmpeg_COMPONENTS
455 avcodec 455 avcodec
456 avfilter
456 avutil 457 avutil
457 swscale) 458 swscale)
458 459
diff --git a/externals/ffmpeg/CMakeLists.txt b/externals/ffmpeg/CMakeLists.txt
index 0baac8e17..03fad0778 100644
--- a/externals/ffmpeg/CMakeLists.txt
+++ b/externals/ffmpeg/CMakeLists.txt
@@ -131,7 +131,6 @@ if (NOT WIN32)
131 COMMAND 131 COMMAND
132 /bin/bash ${FFmpeg_PREFIX}/configure 132 /bin/bash ${FFmpeg_PREFIX}/configure
133 --disable-avdevice 133 --disable-avdevice
134 --disable-avfilter
135 --disable-avformat 134 --disable-avformat
136 --disable-doc 135 --disable-doc
137 --disable-everything 136 --disable-everything
@@ -143,6 +142,7 @@ if (NOT WIN32)
143 --enable-decoder=h264 142 --enable-decoder=h264
144 --enable-decoder=vp8 143 --enable-decoder=vp8
145 --enable-decoder=vp9 144 --enable-decoder=vp9
145 --enable-filter=yadif
146 --cc="${FFmpeg_CC}" 146 --cc="${FFmpeg_CC}"
147 --cxx="${FFmpeg_CXX}" 147 --cxx="${FFmpeg_CXX}"
148 ${FFmpeg_HWACCEL_FLAGS} 148 ${FFmpeg_HWACCEL_FLAGS}
@@ -199,7 +199,7 @@ if (NOT WIN32)
199 endif() 199 endif()
200else(WIN32) 200else(WIN32)
201 # Use yuzu FFmpeg binaries 201 # Use yuzu FFmpeg binaries
202 set(FFmpeg_EXT_NAME "ffmpeg-4.4") 202 set(FFmpeg_EXT_NAME "ffmpeg-5.1.3")
203 set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}") 203 set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
204 download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "") 204 download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")
205 set(FFmpeg_FOUND YES) 205 set(FFmpeg_FOUND YES)
@@ -210,6 +210,7 @@ else(WIN32)
210 set(FFmpeg_LIBRARIES 210 set(FFmpeg_LIBRARIES
211 ${FFmpeg_LIBRARY_DIR}/swscale.lib 211 ${FFmpeg_LIBRARY_DIR}/swscale.lib
212 ${FFmpeg_LIBRARY_DIR}/avcodec.lib 212 ${FFmpeg_LIBRARY_DIR}/avcodec.lib
213 ${FFmpeg_LIBRARY_DIR}/avfilter.lib
213 ${FFmpeg_LIBRARY_DIR}/avutil.lib 214 ${FFmpeg_LIBRARY_DIR}/avutil.lib
214 CACHE PATH "Paths to FFmpeg libraries" FORCE) 215 CACHE PATH "Paths to FFmpeg libraries" FORCE)
215 # exported variables 216 # exported variables
diff --git a/src/video_core/host1x/codecs/codec.cpp b/src/video_core/host1x/codecs/codec.cpp
index 3e9022dce..cd6a3a9b8 100644
--- a/src/video_core/host1x/codecs/codec.cpp
+++ b/src/video_core/host1x/codecs/codec.cpp
@@ -5,6 +5,7 @@
5#include <fstream> 5#include <fstream>
6#include <vector> 6#include <vector>
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/scope_exit.h"
8#include "common/settings.h" 9#include "common/settings.h"
9#include "video_core/host1x/codecs/codec.h" 10#include "video_core/host1x/codecs/codec.h"
10#include "video_core/host1x/codecs/h264.h" 11#include "video_core/host1x/codecs/h264.h"
@@ -14,6 +15,8 @@
14#include "video_core/memory_manager.h" 15#include "video_core/memory_manager.h"
15 16
16extern "C" { 17extern "C" {
18#include <libavfilter/buffersink.h>
19#include <libavfilter/buffersrc.h>
17#include <libavutil/opt.h> 20#include <libavutil/opt.h>
18#ifdef LIBVA_FOUND 21#ifdef LIBVA_FOUND
19// for querying VAAPI driver information 22// for querying VAAPI driver information
@@ -85,6 +88,10 @@ Codec::~Codec() {
85 // Free libav memory 88 // Free libav memory
86 avcodec_free_context(&av_codec_ctx); 89 avcodec_free_context(&av_codec_ctx);
87 av_buffer_unref(&av_gpu_decoder); 90 av_buffer_unref(&av_gpu_decoder);
91
92 if (filters_initialized) {
93 avfilter_graph_free(&av_filter_graph);
94 }
88} 95}
89 96
90bool Codec::CreateGpuAvDevice() { 97bool Codec::CreateGpuAvDevice() {
@@ -167,6 +174,62 @@ void Codec::InitializeGpuDecoder() {
167 av_codec_ctx->get_format = GetGpuFormat; 174 av_codec_ctx->get_format = GetGpuFormat;
168} 175}
169 176
177void Codec::InitializeAvFilters(AVFrame* frame) {
178 const AVFilter* buffer_src = avfilter_get_by_name("buffer");
179 const AVFilter* buffer_sink = avfilter_get_by_name("buffersink");
180 AVFilterInOut* inputs = avfilter_inout_alloc();
181 AVFilterInOut* outputs = avfilter_inout_alloc();
182 SCOPE_EXIT({
183 avfilter_inout_free(&inputs);
184 avfilter_inout_free(&outputs);
185 });
186
187 // Don't know how to get the accurate time_base but it doesn't matter for yadif filter
188 // so just use 1/1 to make buffer filter happy
189 std::string args = fmt::format("video_size={}x{}:pix_fmt={}:time_base=1/1", frame->width,
190 frame->height, frame->format);
191
192 av_filter_graph = avfilter_graph_alloc();
193 int ret = avfilter_graph_create_filter(&av_filter_src_ctx, buffer_src, "in", args.c_str(),
194 nullptr, av_filter_graph);
195 if (ret < 0) {
196 LOG_ERROR(Service_NVDRV, "avfilter_graph_create_filter source error: {}", ret);
197 return;
198 }
199
200 ret = avfilter_graph_create_filter(&av_filter_sink_ctx, buffer_sink, "out", nullptr, nullptr,
201 av_filter_graph);
202 if (ret < 0) {
203 LOG_ERROR(Service_NVDRV, "avfilter_graph_create_filter sink error: {}", ret);
204 return;
205 }
206
207 inputs->name = av_strdup("out");
208 inputs->filter_ctx = av_filter_sink_ctx;
209 inputs->pad_idx = 0;
210 inputs->next = nullptr;
211
212 outputs->name = av_strdup("in");
213 outputs->filter_ctx = av_filter_src_ctx;
214 outputs->pad_idx = 0;
215 outputs->next = nullptr;
216
217 const char* description = "yadif=1:-1:0";
218 ret = avfilter_graph_parse_ptr(av_filter_graph, description, &inputs, &outputs, nullptr);
219 if (ret < 0) {
220 LOG_ERROR(Service_NVDRV, "avfilter_graph_parse_ptr error: {}", ret);
221 return;
222 }
223
224 ret = avfilter_graph_config(av_filter_graph, nullptr);
225 if (ret < 0) {
226 LOG_ERROR(Service_NVDRV, "avfilter_graph_config error: {}", ret);
227 return;
228 }
229
230 filters_initialized = true;
231}
232
170void Codec::Initialize() { 233void Codec::Initialize() {
171 const AVCodecID codec = [&] { 234 const AVCodecID codec = [&] {
172 switch (current_codec) { 235 switch (current_codec) {
@@ -271,8 +334,34 @@ void Codec::Decode() {
271 UNIMPLEMENTED_MSG("Unexpected video format: {}", final_frame->format); 334 UNIMPLEMENTED_MSG("Unexpected video format: {}", final_frame->format);
272 return; 335 return;
273 } 336 }
274 av_frames.push(std::move(final_frame)); 337 if (!final_frame->interlaced_frame) {
275 if (av_frames.size() > 10) { 338 av_frames.push(std::move(final_frame));
339 } else {
340 if (!filters_initialized) {
341 InitializeAvFilters(final_frame.get());
342 }
343 if (const int ret = av_buffersrc_add_frame_flags(av_filter_src_ctx, final_frame.get(),
344 AV_BUFFERSRC_FLAG_KEEP_REF);
345 ret) {
346 LOG_DEBUG(Service_NVDRV, "av_buffersrc_add_frame_flags error {}", ret);
347 return;
348 }
349 while (true) {
350 auto filter_frame = AVFramePtr{av_frame_alloc(), AVFrameDeleter};
351
352 int ret = av_buffersink_get_frame(av_filter_sink_ctx, filter_frame.get());
353
354 if (ret == AVERROR(EAGAIN) || ret == AVERROR(AVERROR_EOF))
355 break;
356 if (ret < 0) {
357 LOG_DEBUG(Service_NVDRV, "av_buffersink_get_frame error {}", ret);
358 return;
359 }
360
361 av_frames.push(std::move(filter_frame));
362 }
363 }
364 while (av_frames.size() > 10) {
276 LOG_TRACE(Service_NVDRV, "av_frames.push overflow dropped frame"); 365 LOG_TRACE(Service_NVDRV, "av_frames.push overflow dropped frame");
277 av_frames.pop(); 366 av_frames.pop();
278 } 367 }
diff --git a/src/video_core/host1x/codecs/codec.h b/src/video_core/host1x/codecs/codec.h
index 0d45fb7fe..06fe00a4b 100644
--- a/src/video_core/host1x/codecs/codec.h
+++ b/src/video_core/host1x/codecs/codec.h
@@ -15,6 +15,7 @@ extern "C" {
15#pragma GCC diagnostic ignored "-Wconversion" 15#pragma GCC diagnostic ignored "-Wconversion"
16#endif 16#endif
17#include <libavcodec/avcodec.h> 17#include <libavcodec/avcodec.h>
18#include <libavfilter/avfilter.h>
18#if defined(__GNUC__) || defined(__clang__) 19#if defined(__GNUC__) || defined(__clang__)
19#pragma GCC diagnostic pop 20#pragma GCC diagnostic pop
20#endif 21#endif
@@ -61,17 +62,24 @@ public:
61private: 62private:
62 void InitializeAvCodecContext(); 63 void InitializeAvCodecContext();
63 64
65 void InitializeAvFilters(AVFrame* frame);
66
64 void InitializeGpuDecoder(); 67 void InitializeGpuDecoder();
65 68
66 bool CreateGpuAvDevice(); 69 bool CreateGpuAvDevice();
67 70
68 bool initialized{}; 71 bool initialized{};
72 bool filters_initialized{};
69 Host1x::NvdecCommon::VideoCodec current_codec{Host1x::NvdecCommon::VideoCodec::None}; 73 Host1x::NvdecCommon::VideoCodec current_codec{Host1x::NvdecCommon::VideoCodec::None};
70 74
71 const AVCodec* av_codec{nullptr}; 75 const AVCodec* av_codec{nullptr};
72 AVCodecContext* av_codec_ctx{nullptr}; 76 AVCodecContext* av_codec_ctx{nullptr};
73 AVBufferRef* av_gpu_decoder{nullptr}; 77 AVBufferRef* av_gpu_decoder{nullptr};
74 78
79 AVFilterContext* av_filter_src_ctx{nullptr};
80 AVFilterContext* av_filter_sink_ctx{nullptr};
81 AVFilterGraph* av_filter_graph{nullptr};
82
75 Host1x::Host1x& host1x; 83 Host1x::Host1x& host1x;
76 const Host1x::NvdecCommon::NvdecRegisters& state; 84 const Host1x::NvdecCommon::NvdecRegisters& state;
77 std::unique_ptr<Decoder::H264> h264_decoder; 85 std::unique_ptr<Decoder::H264> h264_decoder;