AvPlayer: Do not align w/h to 16 with vdec2 (#1388)

This commit is contained in:
Vladislav Mikhalin 2024-10-15 22:31:11 +03:00 committed by GitHub
parent 6fc7b3993d
commit 437ebc1e02
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 54 additions and 23 deletions

View file

@ -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;
} }

View file

@ -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{};

View file

@ -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)),

View file

@ -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{};

View file

@ -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();

View file

@ -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]{};