Merge pull request #610 from vladmikhalin/avplayer-handle-init-errors
AvPlayer: Handle Initialization errors
This commit is contained in:
commit
62f165a7e4
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
struct AVIOContext;
|
struct AVIOContext;
|
||||||
|
|
||||||
namespace Libraries::AvPlayer {
|
namespace Libraries::AvPlayer {
|
||||||
|
@ -14,6 +16,7 @@ namespace Libraries::AvPlayer {
|
||||||
class IDataStreamer {
|
class IDataStreamer {
|
||||||
public:
|
public:
|
||||||
virtual ~IDataStreamer() = default;
|
virtual ~IDataStreamer() = default;
|
||||||
|
virtual bool Init(std::string_view path) = 0;
|
||||||
virtual AVIOContext* GetContext() = 0;
|
virtual AVIOContext* GetContext() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,19 +18,8 @@ extern "C" {
|
||||||
|
|
||||||
namespace Libraries::AvPlayer {
|
namespace Libraries::AvPlayer {
|
||||||
|
|
||||||
AvPlayerFileStreamer::AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement,
|
AvPlayerFileStreamer::AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement)
|
||||||
std::string_view path)
|
: m_file_replacement(file_replacement) {}
|
||||||
: m_file_replacement(file_replacement) {
|
|
||||||
const auto ptr = m_file_replacement.object_ptr;
|
|
||||||
m_fd = m_file_replacement.open(ptr, path.data());
|
|
||||||
ASSERT(m_fd >= 0);
|
|
||||||
m_file_size = m_file_replacement.size(ptr);
|
|
||||||
// avio_buffer is deallocated in `avio_context_free`
|
|
||||||
const auto avio_buffer = reinterpret_cast<u8*>(av_malloc(AVPLAYER_AVIO_BUFFER_SIZE));
|
|
||||||
m_avio_context =
|
|
||||||
avio_alloc_context(avio_buffer, AVPLAYER_AVIO_BUFFER_SIZE, 0, this,
|
|
||||||
&AvPlayerFileStreamer::ReadPacket, nullptr, &AvPlayerFileStreamer::Seek);
|
|
||||||
}
|
|
||||||
|
|
||||||
AvPlayerFileStreamer::~AvPlayerFileStreamer() {
|
AvPlayerFileStreamer::~AvPlayerFileStreamer() {
|
||||||
if (m_avio_context != nullptr) {
|
if (m_avio_context != nullptr) {
|
||||||
|
@ -43,6 +32,21 @@ AvPlayerFileStreamer::~AvPlayerFileStreamer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AvPlayerFileStreamer::Init(std::string_view path) {
|
||||||
|
const auto ptr = m_file_replacement.object_ptr;
|
||||||
|
m_fd = m_file_replacement.open(ptr, path.data());
|
||||||
|
if (m_fd < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_file_size = m_file_replacement.size(ptr);
|
||||||
|
// avio_buffer is deallocated in `avio_context_free`
|
||||||
|
const auto avio_buffer = reinterpret_cast<u8*>(av_malloc(AVPLAYER_AVIO_BUFFER_SIZE));
|
||||||
|
m_avio_context =
|
||||||
|
avio_alloc_context(avio_buffer, AVPLAYER_AVIO_BUFFER_SIZE, 0, this,
|
||||||
|
&AvPlayerFileStreamer::ReadPacket, nullptr, &AvPlayerFileStreamer::Seek);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
s32 AvPlayerFileStreamer::ReadPacket(void* opaque, u8* buffer, s32 size) {
|
s32 AvPlayerFileStreamer::ReadPacket(void* opaque, u8* buffer, s32 size) {
|
||||||
const auto self = reinterpret_cast<AvPlayerFileStreamer*>(opaque);
|
const auto self = reinterpret_cast<AvPlayerFileStreamer*>(opaque);
|
||||||
if (self->m_position >= self->m_file_size) {
|
if (self->m_position >= self->m_file_size) {
|
||||||
|
|
|
@ -15,9 +15,11 @@ namespace Libraries::AvPlayer {
|
||||||
|
|
||||||
class AvPlayerFileStreamer : public IDataStreamer {
|
class AvPlayerFileStreamer : public IDataStreamer {
|
||||||
public:
|
public:
|
||||||
AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement, std::string_view path);
|
AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement);
|
||||||
~AvPlayerFileStreamer();
|
~AvPlayerFileStreamer();
|
||||||
|
|
||||||
|
bool Init(std::string_view path) override;
|
||||||
|
|
||||||
AVIOContext* GetContext() override {
|
AVIOContext* GetContext() override {
|
||||||
return m_avio_context;
|
return m_avio_context;
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ s32 AvPlayer::AddSource(std::string_view path) {
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
if (AVPLAYER_IS_ERROR(m_state->AddSource(path, GetSourceType(path)))) {
|
if (!m_state->AddSource(path, GetSourceType(path))) {
|
||||||
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
|
@ -128,7 +128,7 @@ s32 AvPlayer::GetStreamCount() {
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 AvPlayer::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
|
s32 AvPlayer::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
|
||||||
if (AVPLAYER_IS_ERROR(m_state->GetStreamInfo(stream_index, info))) {
|
if (!m_state->GetStreamInfo(stream_index, info)) {
|
||||||
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
|
@ -145,7 +145,10 @@ s32 AvPlayer::EnableStream(u32 stream_index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 AvPlayer::Start() {
|
s32 AvPlayer::Start() {
|
||||||
return m_state->Start();
|
if (!m_state->Start()) {
|
||||||
|
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AvPlayer::GetVideoData(SceAvPlayerFrameInfo& video_info) {
|
bool AvPlayer::GetVideoData(SceAvPlayerFrameInfo& video_info) {
|
||||||
|
|
|
@ -24,31 +24,39 @@ namespace Libraries::AvPlayer {
|
||||||
|
|
||||||
using namespace Kernel;
|
using namespace Kernel;
|
||||||
|
|
||||||
AvPlayerSource::AvPlayerSource(AvPlayerStateCallback& state, std::string_view path,
|
AvPlayerSource::AvPlayerSource(AvPlayerStateCallback& state) : m_state(state) {}
|
||||||
const SceAvPlayerInitData& init_data,
|
|
||||||
SceAvPlayerSourceType source_type)
|
|
||||||
: m_state(state), m_memory_replacement(init_data.memory_replacement),
|
|
||||||
m_num_output_video_framebuffers(
|
|
||||||
std::min(std::max(2, init_data.num_output_video_framebuffers), 16)) {
|
|
||||||
AVFormatContext* context = avformat_alloc_context();
|
|
||||||
if (init_data.file_replacement.open != nullptr) {
|
|
||||||
m_up_data_streamer =
|
|
||||||
std::make_unique<AvPlayerFileStreamer>(init_data.file_replacement, path);
|
|
||||||
context->pb = m_up_data_streamer->GetContext();
|
|
||||||
ASSERT(!AVPLAYER_IS_ERROR(avformat_open_input(&context, nullptr, nullptr, nullptr)));
|
|
||||||
} else {
|
|
||||||
const auto mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
|
||||||
const auto filepath = mnt->GetHostPath(path);
|
|
||||||
ASSERT(!AVPLAYER_IS_ERROR(
|
|
||||||
avformat_open_input(&context, filepath.string().c_str(), nullptr, nullptr)));
|
|
||||||
}
|
|
||||||
m_avformat_context = AVFormatContextPtr(context, &ReleaseAVFormatContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
AvPlayerSource::~AvPlayerSource() {
|
AvPlayerSource::~AvPlayerSource() {
|
||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AvPlayerSource::Init(const SceAvPlayerInitData& init_data, std::string_view path) {
|
||||||
|
m_memory_replacement = init_data.memory_replacement,
|
||||||
|
m_num_output_video_framebuffers =
|
||||||
|
std::min(std::max(2, init_data.num_output_video_framebuffers), 16);
|
||||||
|
|
||||||
|
AVFormatContext* context = avformat_alloc_context();
|
||||||
|
if (init_data.file_replacement.open != nullptr) {
|
||||||
|
m_up_data_streamer = std::make_unique<AvPlayerFileStreamer>(init_data.file_replacement);
|
||||||
|
if (!m_up_data_streamer->Init(path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
context->pb = m_up_data_streamer->GetContext();
|
||||||
|
if (AVPLAYER_IS_ERROR(avformat_open_input(&context, nullptr, nullptr, nullptr))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const auto mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
||||||
|
const auto filepath = mnt->GetHostPath(path);
|
||||||
|
if (AVPLAYER_IS_ERROR(
|
||||||
|
avformat_open_input(&context, filepath.string().c_str(), nullptr, nullptr))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_avformat_context = AVFormatContextPtr(context, &ReleaseAVFormatContext);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool AvPlayerSource::FindStreamInfo() {
|
bool AvPlayerSource::FindStreamInfo() {
|
||||||
if (m_avformat_context == nullptr) {
|
if (m_avformat_context == nullptr) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "Could not find stream info. NULL context.");
|
LOG_ERROR(Lib_AvPlayer, "Could not find stream info. NULL context.");
|
||||||
|
@ -87,16 +95,16 @@ static f32 AVRationalToF32(const AVRational rational) {
|
||||||
return f32(rational.num) / rational.den;
|
return f32(rational.num) / rational.den;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
|
bool AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
|
||||||
info = {};
|
info = {};
|
||||||
if (m_avformat_context == nullptr || stream_index >= m_avformat_context->nb_streams) {
|
if (m_avformat_context == nullptr || stream_index >= m_avformat_context->nb_streams) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info.", stream_index);
|
LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info.", stream_index);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
const auto p_stream = m_avformat_context->streams[stream_index];
|
const auto p_stream = m_avformat_context->streams[stream_index];
|
||||||
if (p_stream == nullptr || p_stream->codecpar == nullptr) {
|
if (p_stream == nullptr || p_stream->codecpar == nullptr) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info. NULL stream.", stream_index);
|
LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info. NULL stream.", stream_index);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
info.type = CodecTypeToStreamType(p_stream->codecpar->codec_type);
|
info.type = CodecTypeToStreamType(p_stream->codecpar->codec_type);
|
||||||
info.start_time = p_stream->start_time;
|
info.start_time = p_stream->start_time;
|
||||||
|
@ -140,9 +148,9 @@ s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info)
|
||||||
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 -1;
|
return false;
|
||||||
}
|
}
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AvPlayerSource::EnableStream(u32 stream_index) {
|
bool AvPlayerSource::EnableStream(u32 stream_index) {
|
||||||
|
@ -215,12 +223,12 @@ std::optional<bool> AvPlayerSource::HasFrames(u32 num_frames) {
|
||||||
return m_video_packets.Size() > num_frames || m_is_eof;
|
return m_video_packets.Size() > num_frames || m_is_eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 AvPlayerSource::Start() {
|
bool AvPlayerSource::Start() {
|
||||||
std::unique_lock lock(m_state_mutex);
|
std::unique_lock lock(m_state_mutex);
|
||||||
|
|
||||||
if (m_audio_codec_context == nullptr && m_video_codec_context == nullptr) {
|
if (m_audio_codec_context == nullptr && m_video_codec_context == nullptr) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "Could not start playback. NULL context.");
|
LOG_ERROR(Lib_AvPlayer, "Could not start playback. NULL context.");
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
m_demuxer_thread = std::jthread([this](std::stop_token stop) { this->DemuxerThread(stop); });
|
m_demuxer_thread = std::jthread([this](std::stop_token stop) { this->DemuxerThread(stop); });
|
||||||
m_video_decoder_thread =
|
m_video_decoder_thread =
|
||||||
|
@ -228,7 +236,7 @@ s32 AvPlayerSource::Start() {
|
||||||
m_audio_decoder_thread =
|
m_audio_decoder_thread =
|
||||||
std::jthread([this](std::stop_token stop) { this->AudioDecoderThread(stop); });
|
std::jthread([this](std::stop_token stop) { this->AudioDecoderThread(stop); });
|
||||||
m_start_time = std::chrono::high_resolution_clock::now();
|
m_start_time = std::chrono::high_resolution_clock::now();
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AvPlayerSource::Stop() {
|
bool AvPlayerSource::Stop() {
|
||||||
|
|
|
@ -120,17 +120,17 @@ private:
|
||||||
|
|
||||||
class AvPlayerSource {
|
class AvPlayerSource {
|
||||||
public:
|
public:
|
||||||
AvPlayerSource(AvPlayerStateCallback& state, std::string_view path,
|
AvPlayerSource(AvPlayerStateCallback& state);
|
||||||
const SceAvPlayerInitData& init_data, SceAvPlayerSourceType source_type);
|
|
||||||
~AvPlayerSource();
|
~AvPlayerSource();
|
||||||
|
|
||||||
|
bool Init(const SceAvPlayerInitData& init_data, std::string_view path);
|
||||||
bool FindStreamInfo();
|
bool FindStreamInfo();
|
||||||
s32 GetStreamCount();
|
s32 GetStreamCount();
|
||||||
s32 GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info);
|
bool GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info);
|
||||||
bool EnableStream(u32 stream_index);
|
bool EnableStream(u32 stream_index);
|
||||||
void SetLooping(bool is_looping);
|
void SetLooping(bool is_looping);
|
||||||
std::optional<bool> HasFrames(u32 num_frames);
|
std::optional<bool> HasFrames(u32 num_frames);
|
||||||
s32 Start();
|
bool Start();
|
||||||
bool Stop();
|
bool Stop();
|
||||||
bool GetAudioData(SceAvPlayerFrameInfo& audio_info);
|
bool GetAudioData(SceAvPlayerFrameInfo& audio_info);
|
||||||
bool GetVideoData(SceAvPlayerFrameInfo& video_info);
|
bool GetVideoData(SceAvPlayerFrameInfo& video_info);
|
||||||
|
|
|
@ -24,6 +24,7 @@ void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_i
|
||||||
s32 timedtext_stream_index = -1;
|
s32 timedtext_stream_index = -1;
|
||||||
const s32 stream_count = self->GetStreamCount();
|
const s32 stream_count = self->GetStreamCount();
|
||||||
if (AVPLAYER_IS_ERROR(stream_count)) {
|
if (AVPLAYER_IS_ERROR(stream_count)) {
|
||||||
|
self->Stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (stream_count == 0) {
|
if (stream_count == 0) {
|
||||||
|
@ -32,7 +33,10 @@ void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_i
|
||||||
}
|
}
|
||||||
for (u32 stream_index = 0; stream_index < stream_count; ++stream_index) {
|
for (u32 stream_index = 0; stream_index < stream_count; ++stream_index) {
|
||||||
SceAvPlayerStreamInfo info{};
|
SceAvPlayerStreamInfo info{};
|
||||||
self->GetStreamInfo(stream_index, info);
|
if (!self->GetStreamInfo(stream_index, info)) {
|
||||||
|
self->Stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string_view default_language(
|
const std::string_view default_language(
|
||||||
reinterpret_cast<char*>(self->m_default_language));
|
reinterpret_cast<char*>(self->m_default_language));
|
||||||
|
@ -116,23 +120,28 @@ AvPlayerState::~AvPlayerState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called inside GAME thread
|
// Called inside GAME thread
|
||||||
s32 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()) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "File path is empty.");
|
LOG_ERROR(Lib_AvPlayer, "File path is empty.");
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::unique_lock lock(m_source_mutex);
|
std::unique_lock lock(m_source_mutex);
|
||||||
if (m_up_source != nullptr) {
|
if (m_up_source != nullptr) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "Only one source is supported.");
|
LOG_ERROR(Lib_AvPlayer, "Only one source is supported.");
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_up_source = std::make_unique<AvPlayerSource>(*this, path, m_init_data, source_type);
|
m_up_source = std::make_unique<AvPlayerSource>(*this);
|
||||||
|
if (!m_up_source->Init(m_init_data, path)) {
|
||||||
|
SetState(AvState::Error);
|
||||||
|
m_up_source.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AddSourceEvent();
|
AddSourceEvent();
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called inside GAME thread
|
// Called inside GAME thread
|
||||||
|
@ -146,25 +155,25 @@ s32 AvPlayerState::GetStreamCount() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called inside GAME thread
|
// Called inside GAME thread
|
||||||
s32 AvPlayerState::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
|
bool AvPlayerState::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
|
||||||
std::shared_lock lock(m_source_mutex);
|
std::shared_lock lock(m_source_mutex);
|
||||||
if (m_up_source == nullptr) {
|
if (m_up_source == nullptr) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info. No source.", stream_index);
|
LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info. No source.", stream_index);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
return m_up_source->GetStreamInfo(stream_index, info);
|
return m_up_source->GetStreamInfo(stream_index, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called inside GAME thread
|
// Called inside GAME thread
|
||||||
s32 AvPlayerState::Start() {
|
bool AvPlayerState::Start() {
|
||||||
std::shared_lock lock(m_source_mutex);
|
std::shared_lock lock(m_source_mutex);
|
||||||
if (m_up_source == nullptr || m_up_source->Start() < 0) {
|
if (m_up_source == nullptr || !m_up_source->Start()) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "Could not start playback.");
|
LOG_ERROR(Lib_AvPlayer, "Could not start playback.");
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
SetState(AvState::Play);
|
SetState(AvState::Play);
|
||||||
OnPlaybackStateChanged(AvState::Play);
|
OnPlaybackStateChanged(AvState::Play);
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvPlayerState::AvControllerThread(std::stop_token stop) {
|
void AvPlayerState::AvControllerThread(std::stop_token stop) {
|
||||||
|
@ -219,10 +228,10 @@ bool AvPlayerState::Stop() {
|
||||||
if (m_up_source == nullptr || m_current_state == AvState::Stop) {
|
if (m_up_source == nullptr || m_current_state == AvState::Stop) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!SetState(AvState::Stop)) {
|
if (!m_up_source->Stop()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!m_up_source->Stop()) {
|
if (!SetState(AvState::Stop)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
OnPlaybackStateChanged(AvState::Stop);
|
OnPlaybackStateChanged(AvState::Stop);
|
||||||
|
|
|
@ -24,11 +24,11 @@ public:
|
||||||
AvPlayerState(const SceAvPlayerInitData& init_data);
|
AvPlayerState(const SceAvPlayerInitData& init_data);
|
||||||
~AvPlayerState();
|
~AvPlayerState();
|
||||||
|
|
||||||
s32 AddSource(std::string_view filename, SceAvPlayerSourceType source_type);
|
bool AddSource(std::string_view filename, SceAvPlayerSourceType source_type);
|
||||||
s32 GetStreamCount();
|
s32 GetStreamCount();
|
||||||
s32 GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info);
|
bool GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info);
|
||||||
bool EnableStream(u32 stream_index);
|
bool EnableStream(u32 stream_index);
|
||||||
s32 Start();
|
bool Start();
|
||||||
bool Stop();
|
bool Stop();
|
||||||
bool GetAudioData(SceAvPlayerFrameInfo& audio_info);
|
bool GetAudioData(SceAvPlayerFrameInfo& audio_info);
|
||||||
bool GetVideoData(SceAvPlayerFrameInfo& video_info);
|
bool GetVideoData(SceAvPlayerFrameInfo& video_info);
|
||||||
|
|
Loading…
Reference in New Issue