Add a tool menu item that will recompress a capture file

This commit is contained in:
baldurk
2017-11-17 16:33:05 +00:00
parent 13de20612b
commit 016bc29609
16 changed files with 289 additions and 64 deletions
+181 -33
View File
@@ -567,6 +567,148 @@ void CaptureContext::AddFakeProfileMarkers()
m_Drawcalls = ret;
}
void CaptureContext::RecompressCapture()
{
QString destFilename = GetCaptureFilename();
QString tempFilename;
ICaptureFile *cap = NULL;
ICaptureFile *tempCap = NULL;
bool inplace = false;
if(IsCaptureTemporary() || !IsCaptureLocal())
{
QMessageBox::StandardButton res =
RDDialog::question(m_MainWindow, tr("Unsaved capture"),
tr("To recompress a capture you must save it first. Save this capture?"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if(res == QMessageBox::Cancel || res == QMessageBox::No)
return;
destFilename = m_MainWindow->GetSavePath();
// if it's already local, we'll do the save as part of the recompression convert. If it's
// remote, we need to copy it first, but we copy it to a temporary so we can do the conversion
// to the target location
if(IsCaptureLocal())
{
tempFilename = GetCaptureFilename();
}
else
{
tempFilename = TempCaptureFilename(lit("recompress"));
Replay().CopyCaptureFromRemote(GetCaptureFilename(), tempFilename, m_MainWindow);
if(!QFile::exists(tempFilename))
{
RDDialog::critical(m_MainWindow, tr("Failed to save capture"),
tr("Capture couldn't be saved from remote."));
return;
}
}
}
else
{
// if we're doing this inplace on an already saved capture, then we need to recompress to a
// temporary and close/move it afterwards.
inplace = true;
destFilename = TempCaptureFilename(lit("recompress"));
}
if(IsCaptureLocal())
{
// for local files we already have a handle. We'll reuse it, then re-open
cap = Replay().GetCaptureFile();
}
else
{
// for remote files we open a new short-lived handle on the temporary file
tempCap = cap = RENDERDOC_OpenCaptureFile();
cap->OpenFile(tempFilename.toUtf8().data(), "rdc");
}
if(!cap)
{
RDDialog::critical(m_MainWindow, tr("Unexpected missing handle"),
tr("Couldn't get open handle to file for recompression."));
return;
}
int index = cap->FindSectionByType(SectionType::FrameCapture);
SectionProperties props = cap->GetSectionProperties(index);
if(props.flags & SectionFlags::ZstdCompressed)
{
RDDialog::information(m_MainWindow, tr("Capture already compressed"),
tr("This capture is already compressed as much as is possible."));
if(tempCap)
tempCap->Shutdown();
if(!tempFilename.isEmpty())
QFile::remove(tempFilename);
return;
}
// convert from the currently open cap to the destination
float progress = 0.0f;
LambdaThread *th = new LambdaThread([this, cap, destFilename, &progress]() {
cap->Convert(destFilename.toUtf8().data(), "rdc", &progress);
});
th->start();
// wait a few ms before popping up a progress bar
th->wait(500);
if(th->isRunning())
{
ShowProgressDialog(m_MainWindow, tr("Recompressing file."), [th]() { return !th->isRunning(); },
[&progress]() { return progress; });
}
th->deleteLater();
if(inplace)
{
// if we're recompressing "in place", we need to close our capture, move the temporary over
// the original, then re-open.
// this releases the hold over the real desired location.
cap->OpenFile("", "");
// now remove the old capture
QFile::remove(GetCaptureFilename());
// move the recompressed one over
QFile::rename(destFilename, GetCaptureFilename());
// and re-open
cap->OpenFile(GetCaptureFilename().toUtf8().data(), "rdc");
}
else
{
// we've converted into the desired location. We don't have to do anything else but mark our
// new locally saved non-temporary status.
m_CaptureFile = destFilename;
m_CaptureLocal = true;
m_CaptureTemporary = false;
// open the saved capture file. This will let us remove the old file too
Replay().ReopenCaptureFile(m_CaptureFile);
m_CaptureMods = CaptureModifications::All;
SaveChanges();
}
// close any temporary resources
if(tempCap)
tempCap->Shutdown();
if(!tempFilename.isEmpty())
QFile::remove(tempFilename);
}
bool CaptureContext::SaveCaptureTo(const QString &captureFile)
{
bool success = false;
@@ -633,33 +775,7 @@ bool CaptureContext::SaveCaptureTo(const QString &captureFile)
m_CaptureTemporary = false;
Replay().ReopenCaptureFile(captureFile);
if(m_CaptureMods & CaptureModifications::Renames)
{
SectionProperties props;
props.type = SectionType::ResourceRenames;
props.version = 1;
Replay().GetCaptureAccess()->WriteSection(props, SaveRenames().toUtf8());
}
if(m_CaptureMods & CaptureModifications::Bookmarks)
{
SectionProperties props;
props.type = SectionType::Bookmarks;
props.version = 1;
Replay().GetCaptureAccess()->WriteSection(props, SaveBookmarks().toUtf8());
}
if(m_CaptureMods & CaptureModifications::Notes)
{
SectionProperties props;
props.type = SectionType::Notes;
props.version = 1;
Replay().GetCaptureAccess()->WriteSection(props, SaveNotes().toUtf8());
}
m_CaptureMods = CaptureModifications::NoModifications;
SaveChanges();
return true;
}
@@ -810,7 +926,21 @@ void CaptureContext::RemoveBookmark(uint32_t EID)
RefreshUIStatus({}, true, true);
}
QString CaptureContext::SaveRenames()
void CaptureContext::SaveChanges()
{
if(m_CaptureMods & CaptureModifications::Renames)
SaveRenames();
if(m_CaptureMods & CaptureModifications::Bookmarks)
SaveBookmarks();
if(m_CaptureMods & CaptureModifications::Notes)
SaveNotes();
m_CaptureMods = CaptureModifications::NoModifications;
}
void CaptureContext::SaveRenames()
{
QVariantMap resources;
for(ResourceId id : m_CustomNames.keys())
@@ -821,7 +951,13 @@ QString CaptureContext::SaveRenames()
QVariantMap root;
root[lit("CustomResourceNames")] = resources;
return VariantToJSON(root);
QString json = VariantToJSON(root);
SectionProperties props;
props.type = SectionType::ResourceRenames;
props.version = 1;
Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8());
}
void CaptureContext::LoadRenames(const QString &data)
@@ -852,7 +988,7 @@ void CaptureContext::LoadRenames(const QString &data)
}
}
QString CaptureContext::SaveBookmarks()
void CaptureContext::SaveBookmarks()
{
QVariantList bookmarks;
for(const EventBookmark &mark : m_Bookmarks)
@@ -867,7 +1003,13 @@ QString CaptureContext::SaveBookmarks()
QVariantMap root;
root[lit("Bookmarks")] = bookmarks;
return VariantToJSON(root);
QString json = VariantToJSON(root);
SectionProperties props;
props.type = SectionType::Bookmarks;
props.version = 1;
Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8());
}
void CaptureContext::LoadBookmarks(const QString &data)
@@ -892,13 +1034,19 @@ void CaptureContext::LoadBookmarks(const QString &data)
}
}
QString CaptureContext::SaveNotes()
void CaptureContext::SaveNotes()
{
QVariantMap root;
for(const QString &key : m_Notes.keys())
root[key] = m_Notes[key];
return VariantToJSON(root);
QString json = VariantToJSON(root);
SectionProperties props;
props.type = SectionType::Notes;
props.version = 1;
Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8());
}
void CaptureContext::LoadNotes(const QString &data)
+6 -4
View File
@@ -74,6 +74,7 @@ public:
void LoadCapture(const QString &captureFile, const QString &origFilename, bool temporary,
bool local) override;
bool SaveCaptureTo(const QString &captureFile) override;
void RecompressCapture() override;
void CloseCapture() override;
void SetEventID(const QVector<ICaptureViewer *> &exclude, uint32_t selectedEventID,
@@ -253,13 +254,15 @@ private:
bool ContainsMarker(const rdcarray<DrawcallDescription> &m_Drawcalls);
void AddFakeProfileMarkers();
QString SaveRenames();
void SaveChanges();
void SaveRenames();
void LoadRenames(const QString &data);
QString SaveBookmarks();
void SaveBookmarks();
void LoadBookmarks(const QString &data);
QString SaveNotes();
void SaveNotes();
void LoadNotes(const QString &data);
float m_LoadProgress = 0.0f;
@@ -291,7 +294,6 @@ private:
}
void setupDockWindow(QWidget *shad);
rdcarray<DrawcallDescription> m_Drawcalls;
APIProperties m_APIProps;
+4
View File
@@ -917,6 +917,7 @@ enum class CaptureModifications : uint32_t
Renames = 0x0001,
Bookmarks = 0x0002,
Notes = 0x0004,
All = 0xffffffff,
};
BITMASK_OPERATORS(CaptureModifications);
@@ -984,6 +985,9 @@ time.
)");
virtual bool SaveCaptureTo(const QString &captureFile) = 0;
DOCUMENT("Recompress the current capture as much as possible.");
virtual void RecompressCapture() = 0;
DOCUMENT("Close the currently open capture file.");
virtual void CloseCapture() = 0;
+11
View File
@@ -183,6 +183,8 @@ MainWindow::MainWindow(ICaptureContext &ctx) : QMainWindow(NULL), ui(new Ui::Mai
ui->action_Resolve_Symbols->setEnabled(false);
ui->action_Resolve_Symbols->setText(tr("Resolve Symbols"));
ui->action_Recompress_Capture->setEnabled(false);
LambdaThread *th = new LambdaThread([this]() {
m_Ctx.Config().AddAndroidHosts();
for(RemoteHost *host : m_Ctx.Config().RemoteHosts)
@@ -1295,6 +1297,8 @@ void MainWindow::OnCaptureLoaded()
statusProgress->setVisible(false);
ui->action_Recompress_Capture->setEnabled(true);
ui->action_Start_Replay_Loop->setEnabled(true);
setCaptureHasErrors(!m_Ctx.DebugMessages().empty());
@@ -1335,6 +1339,8 @@ void MainWindow::OnCaptureClosed()
ui->action_Resolve_Symbols->setEnabled(false);
ui->action_Resolve_Symbols->setText(tr("Resolve Symbols"));
ui->action_Recompress_Capture->setEnabled(false);
SetTitle();
// if the remote sever disconnected during capture replay, resort back to a 'disconnected' state
@@ -1628,6 +1634,11 @@ void MainWindow::on_action_Resolve_Symbols_triggered()
m_Ctx.GetAPIInspector()->Refresh();
}
void MainWindow::on_action_Recompress_Capture_triggered()
{
m_Ctx.RecompressCapture();
}
void MainWindow::on_action_Start_Replay_Loop_triggered()
{
if(!m_Ctx.IsCaptureLoaded())
+1
View File
@@ -119,6 +119,7 @@ private slots:
void on_action_Python_Shell_triggered();
void on_action_Inject_into_Process_triggered();
void on_action_Resolve_Symbols_triggered();
void on_action_Recompress_Capture_triggered();
void on_action_Start_Replay_Loop_triggered();
void on_action_Attach_to_Running_Instance_triggered();
void on_action_Manage_Remote_Servers_triggered();
+6
View File
@@ -50,6 +50,7 @@
<string>&amp;Tools</string>
</property>
<addaction name="action_Resolve_Symbols"/>
<addaction name="action_Recompress_Capture"/>
<addaction name="action_Start_Replay_Loop"/>
<addaction name="separator"/>
<addaction name="action_Settings"/>
@@ -424,6 +425,11 @@
<string>Capture C&amp;omments</string>
</property>
</action>
<action name="action_Recompress_Capture">
<property name="text">
<string>Re&amp;compress Capture</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
+4
View File
@@ -169,6 +169,10 @@ struct CaptureContextInvoker : ICaptureContext
{
return InvokeRetFunction<bool>(&ICaptureContext::SaveCaptureTo, capture);
}
virtual void RecompressCapture() override
{
InvokeVoidFunction(&ICaptureContext::RecompressCapture);
}
virtual void CloseCapture() override { InvokeVoidFunction(&ICaptureContext::CloseCapture); }
virtual void SetEventID(const QVector<ICaptureViewer *> &exclude, uint32_t selectedEventID,
uint32_t eventID, bool force = false) override