diff --git a/src/core/libraries/avplayer/avplayer_data_streamer.h b/src/core/libraries/avplayer/avplayer_data_streamer.h index 319c88a91..34c2167ca 100644 --- a/src/core/libraries/avplayer/avplayer_data_streamer.h +++ b/src/core/libraries/avplayer/avplayer_data_streamer.h @@ -17,6 +17,7 @@ class IDataStreamer { public: virtual ~IDataStreamer() = default; virtual bool Init(std::string_view path) = 0; + virtual void Reset() = 0; virtual AVIOContext* GetContext() = 0; }; diff --git a/src/core/libraries/avplayer/avplayer_file_streamer.cpp b/src/core/libraries/avplayer/avplayer_file_streamer.cpp index c610012a5..0b44ee75c 100644 --- a/src/core/libraries/avplayer/avplayer_file_streamer.cpp +++ b/src/core/libraries/avplayer/avplayer_file_streamer.cpp @@ -43,6 +43,10 @@ bool AvPlayerFileStreamer::Init(std::string_view path) { return true; } +void AvPlayerFileStreamer::Reset() { + m_position = 0; +} + s32 AvPlayerFileStreamer::ReadPacket(void* opaque, u8* buffer, s32 size) { const auto self = reinterpret_cast(opaque); if (self->m_position >= self->m_file_size) { diff --git a/src/core/libraries/avplayer/avplayer_file_streamer.h b/src/core/libraries/avplayer/avplayer_file_streamer.h index c0cdb4a07..8e9b6bf43 100644 --- a/src/core/libraries/avplayer/avplayer_file_streamer.h +++ b/src/core/libraries/avplayer/avplayer_file_streamer.h @@ -17,6 +17,7 @@ public: ~AvPlayerFileStreamer(); bool Init(std::string_view path) override; + void Reset() override; AVIOContext* GetContext() override { return m_avio_context; diff --git a/src/core/libraries/avplayer/avplayer_source.cpp b/src/core/libraries/avplayer/avplayer_source.cpp index ed2dc9ab0..fae08e48d 100644 --- a/src/core/libraries/avplayer/avplayer_source.cpp +++ b/src/core/libraries/avplayer/avplayer_source.cpp @@ -31,7 +31,7 @@ AvPlayerSource::~AvPlayerSource() { } bool AvPlayerSource::Init(const AvPlayerInitData& init_data, std::string_view path) { - m_memory_replacement = init_data.memory_replacement, + m_memory_replacement = init_data.memory_replacement; m_max_num_video_framebuffers = std::min(std::max(2, init_data.num_output_video_framebuffers), 16); @@ -165,40 +165,14 @@ bool AvPlayerSource::EnableStream(u32 stream_index) { return false; } const auto stream = m_avformat_context->streams[stream_index]; - const auto decoder = avcodec_find_decoder(stream->codecpar->codec_id); - if (decoder == nullptr) { - return false; - } switch (stream->codecpar->codec_type) { case AVMediaType::AVMEDIA_TYPE_VIDEO: { m_video_stream_index = stream_index; - m_video_codec_context = - AVCodecContextPtr(avcodec_alloc_context3(decoder), &ReleaseAVCodecContext); - if (avcodec_parameters_to_context(m_video_codec_context.get(), stream->codecpar) < 0) { - LOG_ERROR(Lib_AvPlayer, "Could not copy stream {} avcodec parameters to context.", - stream_index); - return false; - } - if (avcodec_open2(m_video_codec_context.get(), decoder, nullptr) < 0) { - LOG_ERROR(Lib_AvPlayer, "Could not open avcodec for video stream {}.", stream_index); - return false; - } LOG_INFO(Lib_AvPlayer, "Video stream {} enabled", stream_index); break; } case AVMediaType::AVMEDIA_TYPE_AUDIO: { m_audio_stream_index = stream_index; - m_audio_codec_context = - AVCodecContextPtr(avcodec_alloc_context3(decoder), &ReleaseAVCodecContext); - if (avcodec_parameters_to_context(m_audio_codec_context.get(), stream->codecpar) < 0) { - LOG_ERROR(Lib_AvPlayer, "Could not copy stream {} avcodec parameters to context.", - stream_index); - return false; - } - if (avcodec_open2(m_audio_codec_context.get(), decoder, nullptr) < 0) { - LOG_ERROR(Lib_AvPlayer, "Could not open avcodec for audio stream {}.", stream_index); - return false; - } LOG_INFO(Lib_AvPlayer, "Audio stream {} enabled", stream_index); break; } @@ -221,11 +195,30 @@ std::optional AvPlayerSource::HasFrames(u32 num_frames) { bool AvPlayerSource::Start() { std::unique_lock lock(m_state_mutex); - if (m_audio_codec_context == nullptr && m_video_codec_context == nullptr) { - LOG_ERROR(Lib_AvPlayer, "Could not start playback. NULL context."); + if (!m_video_stream_index && !m_audio_stream_index) { + LOG_ERROR(Lib_AvPlayer, "Could not start playback. No streams."); return false; } - if (m_video_codec_context) { + if (m_video_stream_index) { + const auto stream = m_avformat_context->streams[m_video_stream_index.value()]; + avformat_seek_file(m_avformat_context.get(), m_video_stream_index.value(), 0, 0, + stream->duration, 0); + const auto decoder = avcodec_find_decoder(stream->codecpar->codec_id); + if (decoder == nullptr) { + return false; + } + m_video_codec_context = + AVCodecContextPtr(avcodec_alloc_context3(decoder), &ReleaseAVCodecContext); + if (avcodec_parameters_to_context(m_video_codec_context.get(), stream->codecpar) < 0) { + LOG_ERROR(Lib_AvPlayer, "Could not copy stream {} avcodec parameters to context.", + m_video_stream_index.value()); + return false; + } + if (avcodec_open2(m_video_codec_context.get(), decoder, nullptr) < 0) { + LOG_ERROR(Lib_AvPlayer, "Could not open avcodec for video stream {}.", + m_video_stream_index.value()); + return false; + } auto width = u32(m_video_codec_context->width); auto height = u32(m_video_codec_context->height); if (!m_use_vdec2) { @@ -237,7 +230,26 @@ bool AvPlayerSource::Start() { m_video_buffers.Push(GuestBuffer(m_memory_replacement, 0x100, size, true)); } } - if (m_audio_codec_context) { + if (m_audio_stream_index) { + const auto stream = m_avformat_context->streams[m_audio_stream_index.value()]; + avformat_seek_file(m_avformat_context.get(), m_audio_stream_index.value(), 0, 0, + stream->duration, 0); + const auto decoder = avcodec_find_decoder(stream->codecpar->codec_id); + if (decoder == nullptr) { + return false; + } + m_audio_codec_context = + AVCodecContextPtr(avcodec_alloc_context3(decoder), &ReleaseAVCodecContext); + if (avcodec_parameters_to_context(m_audio_codec_context.get(), stream->codecpar) < 0) { + LOG_ERROR(Lib_AvPlayer, "Could not copy stream {} avcodec parameters to context.", + m_audio_stream_index.value()); + return false; + } + if (avcodec_open2(m_audio_codec_context.get(), decoder, nullptr) < 0) { + LOG_ERROR(Lib_AvPlayer, "Could not open avcodec for audio stream {}.", + m_audio_stream_index.value()); + return false; + } const auto num_channels = m_audio_codec_context->ch_layout.nb_channels; const auto align = num_channels * sizeof(u16); const auto size = num_channels * sizeof(u16) * 1024; @@ -260,6 +272,10 @@ bool AvPlayerSource::Stop() { return false; } + if (m_up_data_streamer) { + m_up_data_streamer->Reset(); + } + m_video_decoder_thread.Stop(); m_audio_decoder_thread.Stop(); m_demuxer_thread.Stop(); @@ -274,6 +290,14 @@ bool AvPlayerSource::Stop() { m_audio_frames.Clear(); m_video_frames.Clear(); + m_last_audio_ts.reset(); + m_start_time.reset(); + m_pause_time = {}; + m_pause_duration = {}; + + m_is_paused = false; + m_is_eof = false; + return true; } diff --git a/src/core/libraries/avplayer/avplayer_state.cpp b/src/core/libraries/avplayer/avplayer_state.cpp index f2912d89d..e1b11840e 100644 --- a/src/core/libraries/avplayer/avplayer_state.cpp +++ b/src/core/libraries/avplayer/avplayer_state.cpp @@ -177,8 +177,10 @@ bool AvPlayerState::GetStreamInfo(u32 stream_index, AvPlayerStreamInfo& info) { bool AvPlayerState::Start() { std::shared_lock lock(m_source_mutex); if (m_current_state == AvState::Ready || m_current_state == AvState::Stop || Stop()) { + SetState(AvState::Starting); if (!m_up_source->Start()) { LOG_ERROR(Lib_AvPlayer, "Could not start playback."); + SetState(AvState::Error); return false; } SetState(AvState::Play);