diff options
Diffstat (limited to 'src/video_core/host1x/codecs/codec.cpp')
| -rw-r--r-- | src/video_core/host1x/codecs/codec.cpp | 165 |
1 files changed, 87 insertions, 78 deletions
diff --git a/src/video_core/host1x/codecs/codec.cpp b/src/video_core/host1x/codecs/codec.cpp index 1030db681..be7e6c6b1 100644 --- a/src/video_core/host1x/codecs/codec.cpp +++ b/src/video_core/host1x/codecs/codec.cpp @@ -12,102 +12,111 @@ namespace Tegra { -Codec::Codec(Host1x::Host1x& host1x_, const Host1x::NvdecCommon::NvdecRegisters& regs) + Codec::Codec(Host1x::Host1x& host1x_, const Host1x::NvdecCommon::NvdecRegisters& regs) : host1x(host1x_), state{regs}, h264_decoder(std::make_unique<Decoder::H264>(host1x)), - vp8_decoder(std::make_unique<Decoder::VP8>(host1x)), - vp9_decoder(std::make_unique<Decoder::VP9>(host1x)) {} + vp8_decoder(std::make_unique<Decoder::VP8>(host1x)), + vp9_decoder(std::make_unique<Decoder::VP9>(host1x)) {} -Codec::~Codec() = default; + Codec::~Codec() = default; -void Codec::Initialize() { - initialized = decode_api.Initialize(current_codec); -} - -void Codec::SetTargetCodec(Host1x::NvdecCommon::VideoCodec codec) { - if (current_codec != codec) { - current_codec = codec; - LOG_INFO(Service_NVDRV, "NVDEC video codec initialized to {}", GetCurrentCodecName()); + void Codec::Initialize() { + initialized = decode_api.Initialize(current_codec); } -} -void Codec::Decode() { - const bool is_first_frame = !initialized; - if (is_first_frame) { - Initialize(); + void Codec::SetTargetCodec(Host1x::NvdecCommon::VideoCodec codec) { + if (current_codec != codec) { + current_codec = codec; + LOG_INFO(Service_NVDRV, "NVDEC video codec initialized to {}", GetCurrentCodecName()); + } } - if (!initialized) { - return; - } + void Codec::Decode() { + const bool is_first_frame = !initialized; + if (is_first_frame) { + Initialize(); + } - // Assemble bitstream. - bool vp9_hidden_frame = false; - size_t configuration_size = 0; - const auto packet_data = [&]() { - switch (current_codec) { - case Tegra::Host1x::NvdecCommon::VideoCodec::H264: - return h264_decoder->ComposeFrame(state, &configuration_size, is_first_frame); - case Tegra::Host1x::NvdecCommon::VideoCodec::VP8: - return vp8_decoder->ComposeFrame(state); - case Tegra::Host1x::NvdecCommon::VideoCodec::VP9: - vp9_decoder->ComposeFrame(state); - vp9_hidden_frame = vp9_decoder->WasFrameHidden(); - return vp9_decoder->GetFrameBytes(); - default: - ASSERT(false); - return std::span<const u8>{}; + if (!initialized) { + return; } - }(); - // Send assembled bitstream to decoder. - if (!decode_api.SendPacket(packet_data, configuration_size)) { - return; - } + // Assemble bitstream. + bool vp9_hidden_frame = false; + size_t configuration_size = 0; + const auto packet_data = [&]() { + switch (current_codec) { + case Tegra::Host1x::NvdecCommon::VideoCodec::H264: + return h264_decoder->ComposeFrame(state, &configuration_size, is_first_frame); + case Tegra::Host1x::NvdecCommon::VideoCodec::VP8: + return vp8_decoder->ComposeFrame(state); + case Tegra::Host1x::NvdecCommon::VideoCodec::VP9: + vp9_decoder->ComposeFrame(state); + vp9_hidden_frame = vp9_decoder->WasFrameHidden(); + return vp9_decoder->GetFrameBytes(); + default: + ASSERT(false); + return std::span<const u8>{}; + } + }(); + + // Send assembled bitstream to decoder. + if (!decode_api.SendPacket(packet_data, configuration_size)) { + return; + } - // Only receive/store visible frames. - if (vp9_hidden_frame) { - return; + // Only receive/store visible frames. + if (vp9_hidden_frame) { + return; + } + + // Receive output frames from decoder. + // The previous code called decode_api.ReceiveFrames(frames); which would queue multiple frames. + // Given the previous refactoring of FFmpeg::DecodeApi to only have ReceiveFrame(), + // this needs to be adapted to potentially call ReceiveFrame multiple times until EAGAIN/EOF. + // For now, I'll adapt it to receive one frame and push it. If more complex frame queuing + // behavior is expected by the `frames` queue, then `ReceiveFrame()` would need to be + // called in a loop until it returns `nullptr` (indicating EAGAIN or EOF). + auto frame = decode_api.ReceiveFrame(); + if (frame) { + frames.push(std::move(frame)); + } + + while (frames.size() > 10) { + LOG_DEBUG(HW_GPU, "ReceiveFrames overflow, dropped frame"); + frames.pop(); + } } - // Receive output frames from decoder. - decode_api.ReceiveFrames(frames); + std::unique_ptr<FFmpeg::Frame> Codec::GetCurrentFrame() { + // Sometimes VIC will request more frames than have been decoded. + // in this case, return a blank frame and don't overwrite previous data. + if (frames.empty()) { + return {}; + } - while (frames.size() > 10) { - LOG_DEBUG(HW_GPU, "ReceiveFrames overflow, dropped frame"); + auto frame = std::move(frames.front()); frames.pop(); + return frame; } -} -std::unique_ptr<FFmpeg::Frame> Codec::GetCurrentFrame() { - // Sometimes VIC will request more frames than have been decoded. - // in this case, return a blank frame and don't overwrite previous data. - if (frames.empty()) { - return {}; + Host1x::NvdecCommon::VideoCodec Codec::GetCurrentCodec() const { + return current_codec; } - auto frame = std::move(frames.front()); - frames.pop(); - return frame; -} - -Host1x::NvdecCommon::VideoCodec Codec::GetCurrentCodec() const { - return current_codec; -} - -std::string_view Codec::GetCurrentCodecName() const { - switch (current_codec) { - case Host1x::NvdecCommon::VideoCodec::None: - return "None"; - case Host1x::NvdecCommon::VideoCodec::H264: - return "H264"; - case Host1x::NvdecCommon::VideoCodec::VP8: - return "VP8"; - case Host1x::NvdecCommon::VideoCodec::H265: - return "H265"; - case Host1x::NvdecCommon::VideoCodec::VP9: - return "VP9"; - default: - return "Unknown"; + std::string_view Codec::GetCurrentCodecName() const { + switch (current_codec) { + case Host1x::NvdecCommon::VideoCodec::None: + return "None"; + case Host1x::NvdecCommon::VideoCodec::H264: + return "H264"; + case Host1x::NvdecCommon::VideoCodec::VP8: + return "VP8"; + case Host1x::NvdecCommon::VideoCodec::H265: + return "H265"; + case Host1x::NvdecCommon::VideoCodec::VP9: + return "VP9"; + default: + return "Unknown"; + } } -} } // namespace Tegra |
