Avoid recreating SwsContext every frame

* Applies to video decoding(`libvdec`) and post-processing(`libvpost`).
This commit is contained in:
VelocityRa 2017-11-24 20:56:51 +02:00 committed by Ivan
parent 5f07f78c23
commit 754cdea435
3 changed files with 24 additions and 10 deletions

View File

@ -64,6 +64,7 @@ struct vdec_thread : ppu_thread
{ {
AVCodec* codec{}; AVCodec* codec{};
AVCodecContext* ctx{}; AVCodecContext* ctx{};
SwsContext* sws{};
const s32 type; const s32 type;
const u32 profile; const u32 profile;
@ -147,6 +148,7 @@ struct vdec_thread : ppu_thread
{ {
avcodec_close(ctx); avcodec_close(ctx);
avcodec_free_context(&ctx); avcodec_free_context(&ctx);
sws_freeContext(sws);
} }
virtual std::string dump() const override virtual std::string dump() const override
@ -361,7 +363,7 @@ struct vdec_thread : ppu_thread
{ {
au_count--; au_count--;
} }
while (std::lock_guard<std::mutex>{mutex}, max_frames && out.size() > max_frames) while (std::lock_guard<std::mutex>{mutex}, max_frames && out.size() > max_frames)
{ {
thread_ctrl::wait(); thread_ctrl::wait();
@ -483,7 +485,7 @@ s32 cellVdecClose(ppu_thread& ppu, u32 handle)
vdec->cmd_push({vdec_cmd::close, 0}); vdec->cmd_push({vdec_cmd::close, 0});
vdec->max_frames = 0; vdec->max_frames = 0;
} }
vdec->notify(); vdec->notify();
vdec->join(); vdec->join();
idm::remove<ppu_thread>(handle); idm::remove<ppu_thread>(handle);
@ -586,7 +588,7 @@ s32 cellVdecGetPicture(u32 handle, vm::cptr<CellVdecPicFormat> format, vm::ptr<u
} }
vdec->notify(); vdec->notify();
if (outBuff) if (outBuff)
{ {
const int w = frame->width; const int w = frame->width;
@ -632,7 +634,7 @@ s32 cellVdecGetPicture(u32 handle, vm::cptr<CellVdecPicFormat> format, vm::ptr<u
} }
} }
std::unique_ptr<SwsContext, void(*)(SwsContext*)> sws(sws_getContext(w, h, in_f, w, h, out_f, SWS_POINT, NULL, NULL, NULL), sws_freeContext); vdec->sws = sws_getCachedContext(vdec->sws, w, h, in_f, w, h, out_f, SWS_POINT, NULL, NULL, NULL);
u8* in_data[4] = { frame->data[0], frame->data[1], frame->data[2], alpha_plane.get() }; u8* in_data[4] = { frame->data[0], frame->data[1], frame->data[2], alpha_plane.get() };
int in_line[4] = { frame->linesize[0], frame->linesize[1], frame->linesize[2], w * 1 }; int in_line[4] = { frame->linesize[0], frame->linesize[1], frame->linesize[2], w * 1 };
@ -648,7 +650,7 @@ s32 cellVdecGetPicture(u32 handle, vm::cptr<CellVdecPicFormat> format, vm::ptr<u
out_line[2] = w / 2; out_line[2] = w / 2;
} }
sws_scale(sws.get(), in_data, in_line, 0, h, out_data, out_line); sws_scale(vdec->sws, in_data, in_line, 0, h, out_data, out_line);
//const u32 buf_size = align(av_image_get_buffer_size(vdec->ctx->pix_fmt, vdec->ctx->width, vdec->ctx->height, 1), 128); //const u32 buf_size = align(av_image_get_buffer_size(vdec->ctx->pix_fmt, vdec->ctx->width, vdec->ctx->height, 1), 128);
@ -771,7 +773,7 @@ s32 cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
avc->transfer_characteristics = CELL_VDEC_AVC_TC_ITU_R_BT_709_5; avc->transfer_characteristics = CELL_VDEC_AVC_TC_ITU_R_BT_709_5;
avc->matrix_coefficients = CELL_VDEC_AVC_MXC_ITU_R_BT_709_5; // important avc->matrix_coefficients = CELL_VDEC_AVC_MXC_ITU_R_BT_709_5; // important
avc->timing_info_present_flag = true; avc->timing_info_present_flag = true;
switch (frc) switch (frc)
{ {
case CELL_VDEC_FRC_24000DIV1001: avc->frameRateCode = CELL_VDEC_AVC_FRC_24000DIV1001; break; case CELL_VDEC_FRC_24000DIV1001: avc->frameRateCode = CELL_VDEC_AVC_FRC_24000DIV1001; break;
@ -838,7 +840,7 @@ s32 cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
mp2->horizontal_size = frame->width; mp2->horizontal_size = frame->width;
mp2->vertical_size = frame->height; mp2->vertical_size = frame->height;
mp2->aspect_ratio_information = CELL_VDEC_MPEG2_ARI_SAR_1_1; // ??? mp2->aspect_ratio_information = CELL_VDEC_MPEG2_ARI_SAR_1_1; // ???
switch (frc) switch (frc)
{ {
case CELL_VDEC_FRC_24000DIV1001: mp2->frame_rate_code = CELL_VDEC_MPEG2_FRC_24000DIV1001; break; case CELL_VDEC_FRC_24000DIV1001: mp2->frame_rate_code = CELL_VDEC_MPEG2_FRC_24000DIV1001; break;

View File

@ -55,7 +55,7 @@ s32 cellVpostClose(u32 handle)
return CELL_VPOST_ERROR_C_ARG_HDL_INVALID; return CELL_VPOST_ERROR_C_ARG_HDL_INVALID;
} }
idm::remove<VpostInstance>(handle); idm::remove<VpostInstance>(handle);
return CELL_OK; return CELL_OK;
} }
@ -120,7 +120,7 @@ s32 cellVpostExec(u32 handle, vm::cptr<u8> inPicBuff, vm::cptr<CellVpostCtrlPara
//u64 stamp1 = get_system_time(); //u64 stamp1 = get_system_time();
std::unique_ptr<SwsContext, void(*)(SwsContext*)> sws(sws_getContext(w, h, AV_PIX_FMT_YUVA420P, ow, oh, AV_PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL), sws_freeContext); vpost->sws = sws_getCachedContext(vpost->sws, w, h, AV_PIX_FMT_YUVA420P, ow, oh, AV_PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL);
//u64 stamp2 = get_system_time(); //u64 stamp2 = get_system_time();
@ -129,7 +129,7 @@ s32 cellVpostExec(u32 handle, vm::cptr<u8> inPicBuff, vm::cptr<CellVpostCtrlPara
u8* out_data[4] = { outPicBuff.get_ptr(), NULL, NULL, NULL }; u8* out_data[4] = { outPicBuff.get_ptr(), NULL, NULL, NULL };
int out_line[4] = { static_cast<int>(ow*4), 0, 0, 0 }; int out_line[4] = { static_cast<int>(ow*4), 0, 0, 0 };
sws_scale(sws.get(), in_data, in_line, 0, h, out_data, out_line); sws_scale(vpost->sws, in_data, in_line, 0, h, out_data, out_line);
//ConLog.Write("cellVpostExec() perf (access=%d, getContext=%d, scale=%d, finalize=%d)", //ConLog.Write("cellVpostExec() perf (access=%d, getContext=%d, scale=%d, finalize=%d)",
//stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3); //stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3);

View File

@ -1,5 +1,10 @@
#pragma once #pragma once
extern "C"
{
#include "libswscale/swscale.h"
}
namespace vm { using namespace ps3; } namespace vm { using namespace ps3; }
// Error Codes // Error Codes
@ -327,8 +332,15 @@ public:
const bool to_rgba; const bool to_rgba;
SwsContext* sws{};
VpostInstance(bool rgba) VpostInstance(bool rgba)
: to_rgba(rgba) : to_rgba(rgba)
{ {
} }
~VpostInstance()
{
sws_freeContext(sws);
}
}; };