cellVdec: minor fix

This commit is contained in:
Nekotekina 2017-01-27 00:34:54 +03:00
parent b644d5b2ae
commit 8693031b06
1 changed files with 64 additions and 67 deletions

View File

@ -16,6 +16,7 @@ extern "C"
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include <queue> #include <queue>
#include <cmath>
std::mutex g_mutex_avcodec_open2; std::mutex g_mutex_avcodec_open2;
@ -71,8 +72,8 @@ struct vdec_thread : ppu_thread
u32 mem_bias{}; u32 mem_bias{};
u32 frc_set{}; // Frame Rate Override u32 frc_set{}; // Frame Rate Override
u64 last_pts{}; u64 next_pts{};
u64 last_dts{}; u64 next_dts{};
std::queue<vdec_frame> out; std::queue<vdec_frame> out;
std::queue<u64> user_data; // TODO std::queue<u64> user_data; // TODO
@ -160,8 +161,8 @@ struct vdec_thread : ppu_thread
avcodec_flush_buffers(ctx); avcodec_flush_buffers(ctx);
frc_set = 0; // TODO: ??? frc_set = 0; // TODO: ???
last_pts = 0; next_pts = 0;
last_dts = 0; next_dts = 0;
cellVdec.trace("Start sequence..."); cellVdec.trace("Start sequence...");
break; break;
} }
@ -172,29 +173,38 @@ struct vdec_thread : ppu_thread
AVPacket packet{}; AVPacket packet{};
packet.pos = -1; packet.pos = -1;
u32 au_mode{};
u32 au_addr{};
u32 au_size{};
u64 au_pts{};
u64 au_dts{};
u64 au_usrd{}; u64 au_usrd{};
u64 au_spec{};
if (vcmd == vdec_cmd::decode) if (vcmd == vdec_cmd::decode)
{ {
au_mode = cmd.arg2<u32>(); // TODO const u32 au_mode = cmd.arg2<u32>(); // TODO
au_addr = cmd_get(1).arg1<u32>(); const u32 au_addr = cmd_get(1).arg1<u32>();
au_size = cmd_get(1).arg2<u32>(); const u32 au_size = cmd_get(1).arg2<u32>();
au_pts = cmd_get(2).as<u64>(); const u64 au_pts = cmd_get(2).as<u64>();
au_dts = cmd_get(3).as<u64>(); const u64 au_dts = cmd_get(3).as<u64>();
au_usrd = cmd_get(4).as<u64>(); // TODO au_usrd = cmd_get(4).as<u64>(); // TODO
au_spec = cmd_get(5).as<u64>(); // TODO const u64 au_spec = cmd_get(5).as<u64>(); // Unused
cmd_pop(5); cmd_pop(5);
packet.data = vm::_ptr<u8>(au_addr); packet.data = vm::_ptr<u8>(au_addr);
packet.size = au_size; packet.size = au_size;
packet.pts = au_pts != -1 ? au_pts : AV_NOPTS_VALUE; packet.pts = au_pts != -1 ? au_pts : AV_NOPTS_VALUE;
packet.dts = au_dts != -1 ? au_dts : AV_NOPTS_VALUE; packet.dts = au_dts != -1 ? au_dts : AV_NOPTS_VALUE;
if (next_pts == 0 && au_pts != -1)
{
next_pts = au_pts;
}
if (next_dts == 0 && au_dts != -1)
{
next_dts = au_dts;
}
ctx->skip_frame =
au_mode == CELL_VDEC_DEC_MODE_NORMAL ? AVDISCARD_DEFAULT :
au_mode == CELL_VDEC_DEC_MODE_B_SKIP ? AVDISCARD_NONREF : AVDISCARD_NONINTRA;
cellVdec.trace("AU decoding: size=0x%x, pts=0x%llx, dts=0x%llx, userdata=0x%llx", au_size, au_pts, au_dts, au_usrd); cellVdec.trace("AU decoding: size=0x%x, pts=0x%llx, dts=0x%llx, userdata=0x%llx", au_size, au_pts, au_dts, au_usrd);
} }
else else
@ -208,10 +218,6 @@ struct vdec_thread : ppu_thread
while (true) while (true)
{ {
ctx->skip_frame =
au_mode == CELL_VDEC_DEC_MODE_NORMAL ? AVDISCARD_DEFAULT :
au_mode == CELL_VDEC_DEC_MODE_B_SKIP ? AVDISCARD_NONREF : AVDISCARD_NONINTRA;
vdec_frame frame; vdec_frame frame;
frame.avf.reset(av_frame_alloc()); frame.avf.reset(av_frame_alloc());
@ -251,6 +257,20 @@ struct vdec_thread : ppu_thread
fmt::throw_exception("Repeated frames not supported (0x%x)", frame->repeat_pict); fmt::throw_exception("Repeated frames not supported (0x%x)", frame->repeat_pict);
} }
if (frame->pkt_pts != AV_NOPTS_VALUE)
{
next_pts = frame->pkt_pts;
}
if (frame->pkt_dts != AV_NOPTS_VALUE)
{
next_dts = frame->pkt_dts;
}
frame.pts = next_pts;
frame.dts = next_dts;
frame.userdata = au_usrd;
if (frc_set) if (frc_set)
{ {
u64 amend = 0; u64 amend = 0;
@ -271,62 +291,39 @@ struct vdec_thread : ppu_thread
} }
} }
last_pts += amend; next_pts += amend;
last_dts += amend; next_dts += amend;
frame.frc = frc_set; frame.frc = frc_set;
} }
else else
{ {
const u64 amend = ctx->time_base.num * 90000 * ctx->ticks_per_frame / ctx->time_base.den; const u64 amend = u64{90000} * ctx->time_base.num * ctx->ticks_per_frame / ctx->time_base.den;
last_pts += amend; next_pts += amend;
last_dts += amend; next_dts += amend;
if (ctx->time_base.num == 1) const auto freq = 1. * ctx->time_base.den / ctx->time_base.num / ctx->ticks_per_frame;
{
switch ((u64)ctx->time_base.den + (u64)(ctx->ticks_per_frame - 1) * 0x100000000ull) if (std::abs(freq - 23.976) < 0.002)
{ frame.frc = CELL_VDEC_FRC_24000DIV1001;
case 24: case 0x100000000ull + 48: frame.frc = CELL_VDEC_FRC_24; break; else if (std::abs(freq - 24.000) < 0.001)
case 25: case 0x100000000ull + 50: frame.frc = CELL_VDEC_FRC_25; break; frame.frc = CELL_VDEC_FRC_24;
case 30: case 0x100000000ull + 60: frame.frc = CELL_VDEC_FRC_30; break; else if (std::abs(freq - 25.000) < 0.001)
case 50: case 0x100000000ull + 100: frame.frc = CELL_VDEC_FRC_50; break; frame.frc = CELL_VDEC_FRC_25;
case 60: case 0x100000000ull + 120: frame.frc = CELL_VDEC_FRC_60; break; else if (std::abs(freq - 29.970) < 0.002)
default: frame.frc = CELL_VDEC_FRC_30000DIV1001;
fmt::throw_exception("Unsupported time_base.den (%d/1, tpf=%d)" HERE, ctx->time_base.den, ctx->ticks_per_frame); else if (std::abs(freq - 30.000) < 0.001)
} frame.frc = CELL_VDEC_FRC_30;
} else if (std::abs(freq - 50.000) < 0.001)
else if (ctx->time_base.num == 1001) frame.frc = CELL_VDEC_FRC_50;
{ else if (std::abs(freq - 59.940) < 0.002)
switch (ctx->time_base.den / ctx->ticks_per_frame) frame.frc = CELL_VDEC_FRC_60000DIV1001;
{ else if (std::abs(freq - 60.000) < 0.001)
case 24000: frame.frc = CELL_VDEC_FRC_24000DIV1001; break; frame.frc = CELL_VDEC_FRC_60;
case 30000: frame.frc = CELL_VDEC_FRC_30000DIV1001; break;
case 60000: frame.frc = CELL_VDEC_FRC_60000DIV1001; break;
default:
fmt::throw_exception("Unsupported time_base.den (%d/1001, tpf=%d)" HERE, ctx->time_base.den, ctx->ticks_per_frame);
}
}
else if (ctx->time_base.num == 50)
{
switch (ctx->time_base.den / ctx->ticks_per_frame)
{
case 1199: frame.frc = CELL_VDEC_FRC_24000DIV1001; break;
case 1498: frame.frc = CELL_VDEC_FRC_30000DIV1001; break;
case 2997: frame.frc = CELL_VDEC_FRC_60000DIV1001; break;
default:
fmt::throw_exception("Unsupported time_base.den(%d/50, tpf=%d)" HERE, ctx->time_base.den, ctx->ticks_per_frame);
}
}
else else
{
fmt::throw_exception("Unsupported time_base.num (%d/%d, tpf=%d)" HERE, ctx->time_base.den, ctx->time_base.num, ctx->ticks_per_frame); fmt::throw_exception("Unsupported time_base.num (%d/%d, tpf=%d)" HERE, ctx->time_base.den, ctx->time_base.num, ctx->ticks_per_frame);
} }
}
frame.pts = last_pts = frame->pkt_pts != AV_NOPTS_VALUE ? frame->pkt_pts : last_pts; cellVdec.trace("Got picture (pts=0x%llx[0x%llx], dts=0x%llx[0x%llx])", frame.pts, frame->pkt_pts, frame.dts, frame->pkt_dts);
frame.dts = last_dts = frame->pkt_dts != AV_NOPTS_VALUE ? frame->pkt_dts : last_dts;
frame.userdata = au_usrd;
cellVdec.trace("Got picture (pts=0x%llx, dts=0x%llx)", frame.pts, frame.dts);
thread_lock{*this}, out.push(std::move(frame)); thread_lock{*this}, out.push(std::move(frame));