diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/command_classes/codecs/codec.cpp | 31 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/codec.h | 2 |
2 files changed, 19 insertions, 14 deletions
diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp index 400834129..18aa40ca3 100644 --- a/src/video_core/command_classes/codecs/codec.cpp +++ b/src/video_core/command_classes/codecs/codec.cpp | |||
| @@ -20,6 +20,12 @@ namespace { | |||
| 20 | constexpr AVPixelFormat PREFERRED_GPU_FMT = AV_PIX_FMT_NV12; | 20 | constexpr AVPixelFormat PREFERRED_GPU_FMT = AV_PIX_FMT_NV12; |
| 21 | constexpr AVPixelFormat PREFERRED_CPU_FMT = AV_PIX_FMT_YUV420P; | 21 | constexpr AVPixelFormat PREFERRED_CPU_FMT = AV_PIX_FMT_YUV420P; |
| 22 | 22 | ||
| 23 | void AVPacketDeleter(AVPacket* ptr) { | ||
| 24 | av_packet_free(&ptr); | ||
| 25 | } | ||
| 26 | |||
| 27 | using AVPacketPtr = std::unique_ptr<AVPacket, decltype(&AVPacketDeleter)>; | ||
| 28 | |||
| 23 | AVPixelFormat GetGpuFormat(AVCodecContext* av_codec_ctx, const AVPixelFormat* pix_fmts) { | 29 | AVPixelFormat GetGpuFormat(AVCodecContext* av_codec_ctx, const AVPixelFormat* pix_fmts) { |
| 24 | for (const AVPixelFormat* p = pix_fmts; *p != AV_PIX_FMT_NONE; ++p) { | 30 | for (const AVPixelFormat* p = pix_fmts; *p != AV_PIX_FMT_NONE; ++p) { |
| 25 | if (*p == av_codec_ctx->pix_fmt) { | 31 | if (*p == av_codec_ctx->pix_fmt) { |
| @@ -46,11 +52,7 @@ Codec::~Codec() { | |||
| 46 | return; | 52 | return; |
| 47 | } | 53 | } |
| 48 | // Free libav memory | 54 | // Free libav memory |
| 49 | avcodec_send_packet(av_codec_ctx, nullptr); | 55 | avcodec_free_context(&av_codec_ctx); |
| 50 | AVFramePtr av_frame{av_frame_alloc(), AVFrameDeleter}; | ||
| 51 | avcodec_receive_frame(av_codec_ctx, av_frame.get()); | ||
| 52 | avcodec_flush_buffers(av_codec_ctx); | ||
| 53 | avcodec_close(av_codec_ctx); | ||
| 54 | av_buffer_unref(&av_gpu_decoder); | 56 | av_buffer_unref(&av_gpu_decoder); |
| 55 | } | 57 | } |
| 56 | 58 | ||
| @@ -111,6 +113,11 @@ bool Codec::CreateGpuAvDevice() { | |||
| 111 | return false; | 113 | return false; |
| 112 | } | 114 | } |
| 113 | 115 | ||
| 116 | void Codec::InitializeAvCodecContext() { | ||
| 117 | av_codec_ctx = avcodec_alloc_context3(av_codec); | ||
| 118 | av_opt_set(av_codec_ctx->priv_data, "tune", "zerolatency", 0); | ||
| 119 | } | ||
| 120 | |||
| 114 | void Codec::InitializeGpuDecoder() { | 121 | void Codec::InitializeGpuDecoder() { |
| 115 | if (!CreateGpuAvDevice()) { | 122 | if (!CreateGpuAvDevice()) { |
| 116 | av_buffer_unref(&av_gpu_decoder); | 123 | av_buffer_unref(&av_gpu_decoder); |
| @@ -135,13 +142,11 @@ void Codec::Initialize() { | |||
| 135 | } | 142 | } |
| 136 | }(); | 143 | }(); |
| 137 | av_codec = avcodec_find_decoder(codec); | 144 | av_codec = avcodec_find_decoder(codec); |
| 138 | av_codec_ctx = avcodec_alloc_context3(av_codec); | 145 | InitializeAvCodecContext(); |
| 139 | av_opt_set(av_codec_ctx->priv_data, "tune", "zerolatency", 0); | ||
| 140 | |||
| 141 | InitializeGpuDecoder(); | 146 | InitializeGpuDecoder(); |
| 142 | if (const int res = avcodec_open2(av_codec_ctx, av_codec, nullptr); res < 0) { | 147 | if (const int res = avcodec_open2(av_codec_ctx, av_codec, nullptr); res < 0) { |
| 143 | LOG_ERROR(Service_NVDRV, "avcodec_open2() Failed with result {}", res); | 148 | LOG_ERROR(Service_NVDRV, "avcodec_open2() Failed with result {}", res); |
| 144 | avcodec_close(av_codec_ctx); | 149 | avcodec_free_context(&av_codec_ctx); |
| 145 | av_buffer_unref(&av_gpu_decoder); | 150 | av_buffer_unref(&av_gpu_decoder); |
| 146 | return; | 151 | return; |
| 147 | } | 152 | } |
| @@ -174,17 +179,15 @@ void Codec::Decode() { | |||
| 174 | frame_data = vp9_decoder->ComposeFrameHeader(state); | 179 | frame_data = vp9_decoder->ComposeFrameHeader(state); |
| 175 | vp9_hidden_frame = vp9_decoder->WasFrameHidden(); | 180 | vp9_hidden_frame = vp9_decoder->WasFrameHidden(); |
| 176 | } | 181 | } |
| 177 | AVPacket* packet = av_packet_alloc(); | 182 | AVPacketPtr packet{av_packet_alloc(), AVPacketDeleter}; |
| 178 | if (!packet) { | 183 | if (!packet) { |
| 179 | LOG_ERROR(Service_NVDRV, "av_packet_alloc failed"); | 184 | LOG_ERROR(Service_NVDRV, "av_packet_alloc failed"); |
| 180 | return; | 185 | return; |
| 181 | } | 186 | } |
| 182 | packet->data = frame_data.data(); | 187 | packet->data = frame_data.data(); |
| 183 | packet->size = static_cast<s32>(frame_data.size()); | 188 | packet->size = static_cast<s32>(frame_data.size()); |
| 184 | const int send_pkt_ret = avcodec_send_packet(av_codec_ctx, packet); | 189 | if (const int res = avcodec_send_packet(av_codec_ctx, packet.get()); res != 0) { |
| 185 | av_packet_free(&packet); | 190 | LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", res); |
| 186 | if (send_pkt_ret != 0) { | ||
| 187 | LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", send_pkt_ret); | ||
| 188 | return; | 191 | return; |
| 189 | } | 192 | } |
| 190 | // Only receive/store visible frames | 193 | // Only receive/store visible frames |
diff --git a/src/video_core/command_classes/codecs/codec.h b/src/video_core/command_classes/codecs/codec.h index f51ab9df0..1508d36c2 100644 --- a/src/video_core/command_classes/codecs/codec.h +++ b/src/video_core/command_classes/codecs/codec.h | |||
| @@ -55,6 +55,8 @@ public: | |||
| 55 | [[nodiscard]] std::string_view GetCurrentCodecName() const; | 55 | [[nodiscard]] std::string_view GetCurrentCodecName() const; |
| 56 | 56 | ||
| 57 | private: | 57 | private: |
| 58 | void InitializeAvCodecContext(); | ||
| 59 | |||
| 58 | void InitializeGpuDecoder(); | 60 | void InitializeGpuDecoder(); |
| 59 | 61 | ||
| 60 | bool CreateGpuAvDevice(); | 62 | bool CreateGpuAvDevice(); |