forked from ShuriZma/suyu
1
0
Fork 0

codec: Improve libav memory alloc and cleanup

This commit is contained in:
ameerj 2021-08-07 23:57:22 -04:00
parent bc3efb79cc
commit a832aa699f
2 changed files with 19 additions and 14 deletions

View File

@ -20,6 +20,12 @@ namespace {
constexpr AVPixelFormat PREFERRED_GPU_FMT = AV_PIX_FMT_NV12; constexpr AVPixelFormat PREFERRED_GPU_FMT = AV_PIX_FMT_NV12;
constexpr AVPixelFormat PREFERRED_CPU_FMT = AV_PIX_FMT_YUV420P; 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) { AVPixelFormat GetGpuFormat(AVCodecContext* av_codec_ctx, const AVPixelFormat* pix_fmts) {
for (const AVPixelFormat* p = pix_fmts; *p != AV_PIX_FMT_NONE; ++p) { for (const AVPixelFormat* p = pix_fmts; *p != AV_PIX_FMT_NONE; ++p) {
if (*p == av_codec_ctx->pix_fmt) { if (*p == av_codec_ctx->pix_fmt) {
@ -46,11 +52,7 @@ Codec::~Codec() {
return; return;
} }
// Free libav memory // Free libav memory
avcodec_send_packet(av_codec_ctx, nullptr); avcodec_free_context(&av_codec_ctx);
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);
av_buffer_unref(&av_gpu_decoder); av_buffer_unref(&av_gpu_decoder);
} }
@ -111,6 +113,11 @@ bool Codec::CreateGpuAvDevice() {
return false; 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() { void Codec::InitializeGpuDecoder() {
if (!CreateGpuAvDevice()) { if (!CreateGpuAvDevice()) {
av_buffer_unref(&av_gpu_decoder); av_buffer_unref(&av_gpu_decoder);
@ -135,13 +142,11 @@ void Codec::Initialize() {
} }
}(); }();
av_codec = avcodec_find_decoder(codec); av_codec = avcodec_find_decoder(codec);
av_codec_ctx = avcodec_alloc_context3(av_codec); InitializeAvCodecContext();
av_opt_set(av_codec_ctx->priv_data, "tune", "zerolatency", 0);
InitializeGpuDecoder(); InitializeGpuDecoder();
if (const int res = avcodec_open2(av_codec_ctx, av_codec, nullptr); res < 0) { if (const int res = avcodec_open2(av_codec_ctx, av_codec, nullptr); res < 0) {
LOG_ERROR(Service_NVDRV, "avcodec_open2() Failed with result {}", res); 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); av_buffer_unref(&av_gpu_decoder);
return; return;
} }
@ -174,17 +179,15 @@ void Codec::Decode() {
frame_data = vp9_decoder->ComposeFrameHeader(state); frame_data = vp9_decoder->ComposeFrameHeader(state);
vp9_hidden_frame = vp9_decoder->WasFrameHidden(); vp9_hidden_frame = vp9_decoder->WasFrameHidden();
} }
AVPacket* packet = av_packet_alloc(); AVPacketPtr packet{av_packet_alloc(), AVPacketDeleter};
if (!packet) { if (!packet) {
LOG_ERROR(Service_NVDRV, "av_packet_alloc failed"); LOG_ERROR(Service_NVDRV, "av_packet_alloc failed");
return; return;
} }
packet->data = frame_data.data(); packet->data = frame_data.data();
packet->size = static_cast<s32>(frame_data.size()); packet->size = static_cast<s32>(frame_data.size());
const int send_pkt_ret = avcodec_send_packet(av_codec_ctx, packet); if (const int res = avcodec_send_packet(av_codec_ctx, packet.get()); res != 0) {
av_packet_free(&packet); LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", res);
if (send_pkt_ret != 0) {
LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", send_pkt_ret);
return; return;
} }
// Only receive/store visible frames // Only receive/store visible frames

View File

@ -55,6 +55,8 @@ public:
[[nodiscard]] std::string_view GetCurrentCodecName() const; [[nodiscard]] std::string_view GetCurrentCodecName() const;
private: private:
void InitializeAvCodecContext();
void InitializeGpuDecoder(); void InitializeGpuDecoder();
bool CreateGpuAvDevice(); bool CreateGpuAvDevice();