mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2024-12-28 18:46:06 +00:00
AvPlayer: Do not align w/h to 16 with vdec2 (#1388)
This commit is contained in:
parent
6fc7b3993d
commit
437ebc1e02
|
@ -112,7 +112,7 @@ AvPlayer::AvPlayer(const SceAvPlayerInitData& data)
|
||||||
m_state(std::make_unique<AvPlayerState>(m_init_data)) {}
|
m_state(std::make_unique<AvPlayerState>(m_init_data)) {}
|
||||||
|
|
||||||
s32 AvPlayer::PostInit(const SceAvPlayerPostInitData& data) {
|
s32 AvPlayer::PostInit(const SceAvPlayerPostInitData& data) {
|
||||||
m_post_init_data = data;
|
m_state->PostInit(data);
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,6 @@ private:
|
||||||
|
|
||||||
SceAvPlayerInitData m_init_data{};
|
SceAvPlayerInitData m_init_data{};
|
||||||
SceAvPlayerInitData m_init_data_original{};
|
SceAvPlayerInitData m_init_data_original{};
|
||||||
SceAvPlayerPostInitData m_post_init_data{};
|
|
||||||
std::mutex m_file_io_mutex{};
|
std::mutex m_file_io_mutex{};
|
||||||
|
|
||||||
std::atomic_bool m_has_source{};
|
std::atomic_bool m_has_source{};
|
||||||
|
|
|
@ -37,7 +37,8 @@ namespace Libraries::AvPlayer {
|
||||||
|
|
||||||
using namespace Kernel;
|
using namespace Kernel;
|
||||||
|
|
||||||
AvPlayerSource::AvPlayerSource(AvPlayerStateCallback& state) : m_state(state) {}
|
AvPlayerSource::AvPlayerSource(AvPlayerStateCallback& state, bool use_vdec2)
|
||||||
|
: m_state(state), m_use_vdec2(use_vdec2) {}
|
||||||
|
|
||||||
AvPlayerSource::~AvPlayerSource() {
|
AvPlayerSource::~AvPlayerSource() {
|
||||||
Stop();
|
Stop();
|
||||||
|
@ -129,18 +130,25 @@ bool AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info
|
||||||
LOG_WARNING(Lib_AvPlayer, "Stream {} language is unknown", stream_index);
|
LOG_WARNING(Lib_AvPlayer, "Stream {} language is unknown", stream_index);
|
||||||
}
|
}
|
||||||
switch (info.type) {
|
switch (info.type) {
|
||||||
case SCE_AVPLAYER_VIDEO:
|
case SCE_AVPLAYER_VIDEO: {
|
||||||
LOG_INFO(Lib_AvPlayer, "Stream {} is a video stream.", stream_index);
|
LOG_INFO(Lib_AvPlayer, "Stream {} is a video stream.", stream_index);
|
||||||
info.details.video.aspect_ratio =
|
info.details.video.aspect_ratio =
|
||||||
f32(p_stream->codecpar->width) / p_stream->codecpar->height;
|
f32(p_stream->codecpar->width) / p_stream->codecpar->height;
|
||||||
info.details.video.width = Common::AlignUp(u32(p_stream->codecpar->width), 16);
|
auto width = u32(p_stream->codecpar->width);
|
||||||
info.details.video.height = Common::AlignUp(u32(p_stream->codecpar->height), 16);
|
auto height = u32(p_stream->codecpar->height);
|
||||||
|
if (!m_use_vdec2) {
|
||||||
|
width = Common::AlignUp(width, 16);
|
||||||
|
height = Common::AlignUp(height, 16);
|
||||||
|
}
|
||||||
|
info.details.video.width = width;
|
||||||
|
info.details.video.height = height;
|
||||||
if (p_lang_node != nullptr) {
|
if (p_lang_node != nullptr) {
|
||||||
std::memcpy(info.details.video.language_code, p_lang_node->value,
|
std::memcpy(info.details.video.language_code, p_lang_node->value,
|
||||||
std::min(strlen(p_lang_node->value), size_t(3)));
|
std::min(strlen(p_lang_node->value), size_t(3)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SCE_AVPLAYER_AUDIO:
|
}
|
||||||
|
case SCE_AVPLAYER_AUDIO: {
|
||||||
LOG_INFO(Lib_AvPlayer, "Stream {} is an audio stream.", stream_index);
|
LOG_INFO(Lib_AvPlayer, "Stream {} is an audio stream.", stream_index);
|
||||||
info.details.audio.channel_count = p_stream->codecpar->ch_layout.nb_channels;
|
info.details.audio.channel_count = p_stream->codecpar->ch_layout.nb_channels;
|
||||||
info.details.audio.sample_rate = p_stream->codecpar->sample_rate;
|
info.details.audio.sample_rate = p_stream->codecpar->sample_rate;
|
||||||
|
@ -150,7 +158,8 @@ bool AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info
|
||||||
std::min(strlen(p_lang_node->value), size_t(3)));
|
std::min(strlen(p_lang_node->value), size_t(3)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SCE_AVPLAYER_TIMEDTEXT:
|
}
|
||||||
|
case SCE_AVPLAYER_TIMEDTEXT: {
|
||||||
LOG_WARNING(Lib_AvPlayer, "Stream {} is a timedtext stream.", stream_index);
|
LOG_WARNING(Lib_AvPlayer, "Stream {} is a timedtext stream.", stream_index);
|
||||||
info.details.subs.font_size = 12;
|
info.details.subs.font_size = 12;
|
||||||
info.details.subs.text_size = 12;
|
info.details.subs.text_size = 12;
|
||||||
|
@ -159,10 +168,12 @@ bool AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info
|
||||||
std::min(strlen(p_lang_node->value), size_t(3)));
|
std::min(strlen(p_lang_node->value), size_t(3)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
|
default: {
|
||||||
LOG_ERROR(Lib_AvPlayer, "Stream {} type is unknown: {}.", stream_index, info.type);
|
LOG_ERROR(Lib_AvPlayer, "Stream {} type is unknown: {}.", stream_index, info.type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,8 +200,12 @@ bool AvPlayerSource::EnableStream(u32 stream_index) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "Could not open avcodec for video stream {}.", stream_index);
|
LOG_ERROR(Lib_AvPlayer, "Could not open avcodec for video stream {}.", stream_index);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto width = Common::AlignUp(u32(m_video_codec_context->width), 16);
|
auto width = u32(m_video_codec_context->width);
|
||||||
const auto height = Common::AlignUp(u32(m_video_codec_context->height), 16);
|
auto height = u32(m_video_codec_context->height);
|
||||||
|
if (!m_use_vdec2) {
|
||||||
|
width = Common::AlignUp(width, 16);
|
||||||
|
height = Common::AlignUp(height, 16);
|
||||||
|
}
|
||||||
const auto size = (width * height * 3) / 2;
|
const auto size = (width * height * 3) / 2;
|
||||||
for (u64 index = 0; index < m_num_output_video_framebuffers; ++index) {
|
for (u64 index = 0; index < m_num_output_video_framebuffers; ++index) {
|
||||||
m_video_buffers.Push(FrameBuffer(m_memory_replacement, 0x100, size));
|
m_video_buffers.Push(FrameBuffer(m_memory_replacement, 0x100, size));
|
||||||
|
@ -316,7 +331,7 @@ bool AvPlayerSource::GetVideoData(SceAvPlayerFrameInfoEx& video_info) {
|
||||||
|
|
||||||
auto frame = m_video_frames.Pop();
|
auto frame = m_video_frames.Pop();
|
||||||
if (!frame.has_value()) {
|
if (!frame.has_value()) {
|
||||||
LOG_WARNING(Lib_AvPlayer, "Could get video frame. EOF reached.");
|
LOG_TRACE(Lib_AvPlayer, "Could get video frame. EOF reached.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,7 +366,7 @@ bool AvPlayerSource::GetAudioData(SceAvPlayerFrameInfo& audio_info) {
|
||||||
|
|
||||||
auto frame = m_audio_frames.Pop();
|
auto frame = m_audio_frames.Pop();
|
||||||
if (!frame.has_value()) {
|
if (!frame.has_value()) {
|
||||||
LOG_WARNING(Lib_AvPlayer, "Could get audio frame. EOF reached.");
|
LOG_TRACE(Lib_AvPlayer, "Could get audio frame. EOF reached.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,9 +552,13 @@ AvPlayerSource::AVFramePtr AvPlayerSource::ConvertVideoFrame(const AVFrame& fram
|
||||||
return nv12_frame;
|
return nv12_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CopyNV12Data(u8* dst, const AVFrame& src) {
|
static void CopyNV12Data(u8* dst, const AVFrame& src, bool use_vdec2) {
|
||||||
const auto width = Common::AlignUp(u32(src.width), 16);
|
auto width = u32(src.width);
|
||||||
const auto height = Common::AlignUp(u32(src.height), 16);
|
auto height = u32(src.height);
|
||||||
|
if (!use_vdec2) {
|
||||||
|
width = Common::AlignUp(width, 16);
|
||||||
|
height = Common::AlignUp(height, 16);
|
||||||
|
}
|
||||||
|
|
||||||
if (src.width == width) {
|
if (src.width == width) {
|
||||||
std::memcpy(dst, src.data[0], src.width * src.height);
|
std::memcpy(dst, src.data[0], src.width * src.height);
|
||||||
|
@ -561,7 +580,7 @@ Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame
|
||||||
ASSERT(frame.format == AV_PIX_FMT_NV12);
|
ASSERT(frame.format == AV_PIX_FMT_NV12);
|
||||||
|
|
||||||
auto p_buffer = buffer.GetBuffer();
|
auto p_buffer = buffer.GetBuffer();
|
||||||
CopyNV12Data(p_buffer, frame);
|
CopyNV12Data(p_buffer, frame, m_use_vdec2);
|
||||||
|
|
||||||
const auto pkt_dts = u64(frame.pkt_dts) * 1000;
|
const auto pkt_dts = u64(frame.pkt_dts) * 1000;
|
||||||
const auto stream = m_avformat_context->streams[m_video_stream_index.value()];
|
const auto stream = m_avformat_context->streams[m_video_stream_index.value()];
|
||||||
|
@ -570,8 +589,12 @@ Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame
|
||||||
const auto num = time_base.num;
|
const auto num = time_base.num;
|
||||||
const auto timestamp = (num != 0 && den > 1) ? (pkt_dts * num) / den : pkt_dts;
|
const auto timestamp = (num != 0 && den > 1) ? (pkt_dts * num) / den : pkt_dts;
|
||||||
|
|
||||||
const auto width = Common::AlignUp(u32(frame.width), 16);
|
auto width = u32(frame.width);
|
||||||
const auto height = Common::AlignUp(u32(frame.height), 16);
|
auto height = u32(frame.height);
|
||||||
|
if (!m_use_vdec2) {
|
||||||
|
width = Common::AlignUp(width, 16);
|
||||||
|
height = Common::AlignUp(height, 16);
|
||||||
|
}
|
||||||
|
|
||||||
return Frame{
|
return Frame{
|
||||||
.buffer = std::move(buffer),
|
.buffer = std::move(buffer),
|
||||||
|
@ -583,8 +606,8 @@ Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame
|
||||||
{
|
{
|
||||||
.video =
|
.video =
|
||||||
{
|
{
|
||||||
.width = u32(width),
|
.width = width,
|
||||||
.height = u32(height),
|
.height = height,
|
||||||
.aspect_ratio = AVRationalToF32(frame.sample_aspect_ratio),
|
.aspect_ratio = AVRationalToF32(frame.sample_aspect_ratio),
|
||||||
.crop_left_offset = u32(frame.crop_left),
|
.crop_left_offset = u32(frame.crop_left),
|
||||||
.crop_right_offset = u32(frame.crop_right + (width - frame.width)),
|
.crop_right_offset = u32(frame.crop_right + (width - frame.width)),
|
||||||
|
|
|
@ -120,7 +120,7 @@ private:
|
||||||
|
|
||||||
class AvPlayerSource {
|
class AvPlayerSource {
|
||||||
public:
|
public:
|
||||||
AvPlayerSource(AvPlayerStateCallback& state);
|
AvPlayerSource(AvPlayerStateCallback& state, bool use_vdec2);
|
||||||
~AvPlayerSource();
|
~AvPlayerSource();
|
||||||
|
|
||||||
bool Init(const SceAvPlayerInitData& init_data, std::string_view path);
|
bool Init(const SceAvPlayerInitData& init_data, std::string_view path);
|
||||||
|
@ -168,6 +168,7 @@ private:
|
||||||
Frame PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame);
|
Frame PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame);
|
||||||
|
|
||||||
AvPlayerStateCallback& m_state;
|
AvPlayerStateCallback& m_state;
|
||||||
|
bool m_use_vdec2 = false;
|
||||||
|
|
||||||
SceAvPlayerMemAllocator m_memory_replacement{};
|
SceAvPlayerMemAllocator m_memory_replacement{};
|
||||||
u32 m_num_output_video_framebuffers{};
|
u32 m_num_output_video_framebuffers{};
|
||||||
|
|
|
@ -130,6 +130,10 @@ AvPlayerState::~AvPlayerState() {
|
||||||
m_event_queue.Clear();
|
m_event_queue.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvPlayerState::PostInit(const SceAvPlayerPostInitData& post_init_data) {
|
||||||
|
m_post_init_data = post_init_data;
|
||||||
|
}
|
||||||
|
|
||||||
// Called inside GAME thread
|
// Called inside GAME thread
|
||||||
bool AvPlayerState::AddSource(std::string_view path, SceAvPlayerSourceType source_type) {
|
bool AvPlayerState::AddSource(std::string_view path, SceAvPlayerSourceType source_type) {
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
|
@ -144,7 +148,9 @@ bool AvPlayerState::AddSource(std::string_view path, SceAvPlayerSourceType sourc
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_up_source = std::make_unique<AvPlayerSource>(*this);
|
m_up_source = std::make_unique<AvPlayerSource>(
|
||||||
|
*this, m_post_init_data.video_decoder_init.decoderType.video_type ==
|
||||||
|
SCE_AVPLAYER_VIDEO_DECODER_TYPE_SOFTWARE2);
|
||||||
if (!m_up_source->Init(m_init_data, path)) {
|
if (!m_up_source->Init(m_init_data, path)) {
|
||||||
SetState(AvState::Error);
|
SetState(AvState::Error);
|
||||||
m_up_source.reset();
|
m_up_source.reset();
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
AvPlayerState(const SceAvPlayerInitData& init_data);
|
AvPlayerState(const SceAvPlayerInitData& init_data);
|
||||||
~AvPlayerState();
|
~AvPlayerState();
|
||||||
|
|
||||||
|
void PostInit(const SceAvPlayerPostInitData& post_init_data);
|
||||||
bool AddSource(std::string_view filename, SceAvPlayerSourceType source_type);
|
bool AddSource(std::string_view filename, SceAvPlayerSourceType source_type);
|
||||||
s32 GetStreamCount();
|
s32 GetStreamCount();
|
||||||
bool GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info);
|
bool GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info);
|
||||||
|
@ -68,6 +69,7 @@ private:
|
||||||
std::unique_ptr<AvPlayerSource> m_up_source;
|
std::unique_ptr<AvPlayerSource> m_up_source;
|
||||||
|
|
||||||
SceAvPlayerInitData m_init_data{};
|
SceAvPlayerInitData m_init_data{};
|
||||||
|
SceAvPlayerPostInitData m_post_init_data{};
|
||||||
SceAvPlayerEventReplacement m_event_replacement{};
|
SceAvPlayerEventReplacement m_event_replacement{};
|
||||||
bool m_auto_start{};
|
bool m_auto_start{};
|
||||||
u8 m_default_language[4]{};
|
u8 m_default_language[4]{};
|
||||||
|
|
Loading…
Reference in a new issue