Fix the gemini-written video player to actually work

This commit is contained in:
Henrik Rydgård committed 2026-02-26 09:33:26 +01:00
1 parent 250c52d1d7
commit e50199ad0a
18 files changed
+415 -132

No files matched your search

+110 -3
View File
@@ -42,6 +42,7 @@
#include "Core/Util/GameDB.h"
#include "Core/Util/RecentFiles.h"
#include "Core/Util/PathUtil.h"
#include "Core/Util/VideoPlayer.h"
#include "UI/OnScreenDisplay.h"
#include "UI/Background.h"
#include "UI/CwCheatScreen.h"
@@ -56,7 +57,95 @@
#include "UI/SavedataScreen.h"
#include "UI/MiscViews.h"
constexpr GameInfoFlags g_desiredFlags = GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::PIC0 | GameInfoFlags::PIC1 | GameInfoFlags::UNCOMPRESSED_SIZE | GameInfoFlags::SIZE | GameInfoFlags::SAVEDATA_SIZE;
constexpr GameInfoFlags g_desiredFlags = GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::PIC0 | GameInfoFlags::PIC1 | GameInfoFlags::ICON1_PMF | GameInfoFlags::UNCOMPRESSED_SIZE | GameInfoFlags::SIZE | GameInfoFlags::SAVEDATA_SIZE;
class PMFView : public UI::InertView {
public:
PMFView(std::string data, UI::LayoutParams *params) : UI::InertView(params), data_(data) {
startTime_ = Instant::Now();
player_ = pmf_create();
if (0 == pmf_init(player_, (const uint8_t *)data_.data(), data_.size(), &width_, &height_)) {
} else {
ERROR_LOG(Log::G3D, "Couldn't load pmf");
pmf_destroy(player_);
player_ = nullptr;
}
}
~PMFView() {
if (curFrame_) {
curFrame_->Release();
curFrame_ = nullptr;
}
if (player_) {
pmf_destroy(player_);
player_ = nullptr;
}
}
void DeviceLost() override {
if (curFrame_) {
curFrame_->Release();
curFrame_ = nullptr;
}
}
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override {
// Just use the video size.
w = width_;
h = height_;
}
void Draw(UIContext &dc) override {
if (!player_) {
return;
}
Draw::DrawContext *draw = dc.GetDrawContext();
std::vector<u8> frame(width_ * height_ * 4);
if (pmf_update(player_, startTime_.ElapsedSeconds(), frame.data())) {
if (curFrame_) {
curFrame_->Release();
curFrame_ = nullptr;
}
Draw::TextureDesc desc{};
desc.width = width_;
desc.height = height_;
desc.depth = 1;
desc.format = Draw::DataFormat::R8G8B8A8_UNORM;
desc.generateMips = false;
desc.tag = "pmf_frame";
desc.type = Draw::TextureType::LINEAR2D;
desc.mipLevels = 1;
desc.initData.push_back(frame.data());
curFrame_ = draw->CreateTexture(desc);
}
if (curFrame_) {
int dropsize = 5;
dc.Draw()->DrawImage4Grid(dc.GetTheme().dropShadow4Grid, bounds_.x - dropsize * 1.5f, bounds_.y - dropsize * 1.5f, bounds_.x2() + dropsize * 1.5f, bounds_.y2() + dropsize * 1.5f, 0xFF000000, 1.0f);
dc.Flush();
draw->BindTexture(0, curFrame_);
dc.Draw()->DrawTexRect(bounds_, 0, 0, 1.0f, 1.0f, 0xFFFFFFFF);
dc.Flush();
}
dc.RebindTexture();
}
private:
std::string data_;
Draw::Texture *curFrame_ = nullptr;
PMFPlayer *player_ = nullptr;
Instant startTime_;
int width_ = 0;
int height_ = 0;
};
GameScreen::GameScreen(const Path &gamePath, bool inGame) : UITwoPaneBaseDialogScreen(gamePath, TwoPaneFlags::SettingsToTheRight | TwoPaneFlags::CustomContextMenu), inGame_(inGame) {
g_BackgroundAudio.SetGame(gamePath);
@@ -92,8 +181,13 @@ void GameScreen::update() {
bool recreate = false;
if (knownFlags_ != hasFlags) {
bool justAudio = ((u32)knownFlags_ ^ (u32)hasFlags) == (u32)GameInfoFlags::SND;
knownFlags_ = hasFlags;
recreate = true;
// don't need to recreate if the audio loaded.
if (!justAudio) {
recreate = true;
}
}
// Has the user requested a CRC32?
@@ -130,6 +224,7 @@ static bool FileTypeHasIcon(IdentifiedFileType fileType) {
case IdentifiedFileType::PSP_ISO_NP:
case IdentifiedFileType::PSP_ISO:
case IdentifiedFileType::PSP_UMD_VIDEO_ISO:
case IdentifiedFileType::PSP_DISC_DIRECTORY:
return true;
default:
return false;
@@ -191,7 +286,7 @@ void GameScreen::CreateContentViews(UI::ViewGroup *parent) {
mainGameInfo = new LinearLayout(ORIENT_VERTICAL);
leftColumn->Add(new Spacer(8.0f));
if (fileTypeHasIcon && !(info_->icon.dataLoaded && info_->icon.data.empty())) {
leftColumn->Add(new GameImageView(gamePath_, GameInfoFlags::ICON, 2.0f, new LinearLayoutParams(UI::Margins(0))));
leftColumn->Add(new GameImageView(gamePath_, GameInfoFlags::ICON, 2.0f, new LinearLayoutParams(144 * 2, 80 * 2, UI::Margins(0))));
}
leftColumn->Add(mainGameInfo);
} else {
@@ -205,6 +300,18 @@ void GameScreen::CreateContentViews(UI::ViewGroup *parent) {
}
mainGameInfo->SetSpacing(3.0f);
if (pmf_player_available() && fileTypeHasIcon && (knownFlags_ & GameInfoFlags::ICON1_PMF) && !info_->icon1pmf.empty()) {
std::string pmfData;
{
std::lock_guard<std::mutex> guard(info_->lock);
pmfData = info_->icon1pmf;
}
if (!pmfData.empty()) {
leftColumn->Add(new PMFView(pmfData, new LinearLayoutParams(144 * 2, 80 * 2, UI::Margins(0, 10))));
}
}
std::vector<GameDBInfo> dbInfos;
const bool inGameDB = g_gameDB.GetGameInfos(info_->id_version, &dbInfos);