codec: Improve libav memory alloc and cleanup
This commit is contained in:
		| @@ -20,6 +20,12 @@ namespace { | ||||
| constexpr AVPixelFormat PREFERRED_GPU_FMT = AV_PIX_FMT_NV12; | ||||
| constexpr AVPixelFormat PREFERRED_CPU_FMT = AV_PIX_FMT_YUV420P; | ||||
|  | ||||
| void AVPacketDeleter(AVPacket* ptr) { | ||||
|     av_packet_free(&ptr); | ||||
| } | ||||
|  | ||||
| using AVPacketPtr = std::unique_ptr<AVPacket, decltype(&AVPacketDeleter)>; | ||||
|  | ||||
| AVPixelFormat GetGpuFormat(AVCodecContext* av_codec_ctx, const AVPixelFormat* pix_fmts) { | ||||
|     for (const AVPixelFormat* p = pix_fmts; *p != AV_PIX_FMT_NONE; ++p) { | ||||
|         if (*p == av_codec_ctx->pix_fmt) { | ||||
| @@ -46,11 +52,7 @@ Codec::~Codec() { | ||||
|         return; | ||||
|     } | ||||
|     // Free libav memory | ||||
|     avcodec_send_packet(av_codec_ctx, nullptr); | ||||
|     AVFramePtr av_frame{av_frame_alloc(), AVFrameDeleter}; | ||||
|     avcodec_receive_frame(av_codec_ctx, av_frame.get()); | ||||
|     avcodec_flush_buffers(av_codec_ctx); | ||||
|     avcodec_close(av_codec_ctx); | ||||
|     avcodec_free_context(&av_codec_ctx); | ||||
|     av_buffer_unref(&av_gpu_decoder); | ||||
| } | ||||
|  | ||||
| @@ -111,6 +113,11 @@ bool Codec::CreateGpuAvDevice() { | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| void Codec::InitializeAvCodecContext() { | ||||
|     av_codec_ctx = avcodec_alloc_context3(av_codec); | ||||
|     av_opt_set(av_codec_ctx->priv_data, "tune", "zerolatency", 0); | ||||
| } | ||||
|  | ||||
| void Codec::InitializeGpuDecoder() { | ||||
|     if (!CreateGpuAvDevice()) { | ||||
|         av_buffer_unref(&av_gpu_decoder); | ||||
| @@ -135,13 +142,11 @@ void Codec::Initialize() { | ||||
|         } | ||||
|     }(); | ||||
|     av_codec = avcodec_find_decoder(codec); | ||||
|     av_codec_ctx = avcodec_alloc_context3(av_codec); | ||||
|     av_opt_set(av_codec_ctx->priv_data, "tune", "zerolatency", 0); | ||||
|  | ||||
|     InitializeAvCodecContext(); | ||||
|     InitializeGpuDecoder(); | ||||
|     if (const int res = avcodec_open2(av_codec_ctx, av_codec, nullptr); res < 0) { | ||||
|         LOG_ERROR(Service_NVDRV, "avcodec_open2() Failed with result {}", res); | ||||
|         avcodec_close(av_codec_ctx); | ||||
|         avcodec_free_context(&av_codec_ctx); | ||||
|         av_buffer_unref(&av_gpu_decoder); | ||||
|         return; | ||||
|     } | ||||
| @@ -174,17 +179,15 @@ void Codec::Decode() { | ||||
|         frame_data = vp9_decoder->ComposeFrameHeader(state); | ||||
|         vp9_hidden_frame = vp9_decoder->WasFrameHidden(); | ||||
|     } | ||||
|     AVPacket* packet = av_packet_alloc(); | ||||
|     AVPacketPtr packet{av_packet_alloc(), AVPacketDeleter}; | ||||
|     if (!packet) { | ||||
|         LOG_ERROR(Service_NVDRV, "av_packet_alloc failed"); | ||||
|         return; | ||||
|     } | ||||
|     packet->data = frame_data.data(); | ||||
|     packet->size = static_cast<s32>(frame_data.size()); | ||||
|     const int send_pkt_ret = avcodec_send_packet(av_codec_ctx, packet); | ||||
|     av_packet_free(&packet); | ||||
|     if (send_pkt_ret != 0) { | ||||
|         LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", send_pkt_ret); | ||||
|     if (const int res = avcodec_send_packet(av_codec_ctx, packet.get()); res != 0) { | ||||
|         LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", res); | ||||
|         return; | ||||
|     } | ||||
|     // Only receive/store visible frames | ||||
|   | ||||
| @@ -55,6 +55,8 @@ public: | ||||
|     [[nodiscard]] std::string_view GetCurrentCodecName() const; | ||||
|  | ||||
| private: | ||||
|     void InitializeAvCodecContext(); | ||||
|  | ||||
|     void InitializeGpuDecoder(); | ||||
|  | ||||
|     bool CreateGpuAvDevice(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user