Switch thumbnail to bytebuf instead of byte pointer and length

This commit is contained in:
baldurk
2020-08-26 12:41:40 +01:00
parent 51b228b042
commit 9fd7f447d2
7 changed files with 74 additions and 135 deletions
+1 -1
View File
@@ -812,7 +812,7 @@ public:
if(empty())
return;
#define IS_WHITESPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
#define IS_WHITESPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n' || (c) == '\0')
const char *str = c_str();
size_t sz = size();
+6 -13
View File
@@ -1039,11 +1039,10 @@ void RenderDoc::ResamplePixels(const FramePixels &in, RDCThumb &out)
out.width = (uint16_t)RDCMIN(in.max_width, in.width);
out.width &= ~(in.pitch_requirement - 1); // align down to multiple of in.
out.height = uint16_t(out.width * in.height / in.width);
out.len = 3 * out.width * out.height;
out.pixels = new byte[out.len];
out.pixels.resize(3 * out.width * out.height);
out.format = FileType::Raw;
byte *dst = (byte *)out.pixels;
byte *dst = (byte *)out.pixels.data();
byte *source = (byte *)in.data;
for(uint32_t y = 0; y < out.height; y++)
@@ -1113,7 +1112,7 @@ void RenderDoc::ResamplePixels(const FramePixels &in, RDCThumb &out)
uint16_t flipY = (out.height - 1 - y);
for(uint16_t x = 0; x < out.width; x++)
{
byte *src = (byte *)out.pixels;
byte *src = (byte *)out.pixels.data();
byte save[3];
save[0] = src[(y * out.width + x) * 3 + 0];
save[1] = src[(y * out.width + x) * 3 + 1];
@@ -1152,12 +1151,10 @@ void RenderDoc::EncodePixelsPNG(const RDCThumb &in, RDCThumb &out)
WriteCallbackData callbackData;
stbi_write_png_to_func(&WriteCallbackData::writeData, &callbackData, in.width, in.height, 3,
in.pixels, 0);
in.pixels.data(), 0);
out.width = in.width;
out.height = in.height;
out.pixels = new byte[callbackData.buffer.size()];
memcpy((void *)out.pixels, callbackData.buffer.data(), callbackData.buffer.size());
out.len = (uint32_t)callbackData.buffer.size();
out.pixels.swap(callbackData.buffer);
out.format = FileType::PNG;
}
@@ -1206,9 +1203,6 @@ RDCFile *RenderDoc::CreateRDC(RDCDriver driver, uint32_t frameNum, const FramePi
SAFE_DELETE(ret);
}
SAFE_DELETE_ARRAY(outRaw.pixels);
SAFE_DELETE_ARRAY(outPng.pixels);
return ret;
}
@@ -1675,10 +1669,9 @@ void RenderDoc::FinishCaptureWriting(RDCFile *rdc, uint32_t frameNumber)
ExtThumbnailHeader header;
header.width = thumb.width;
header.height = thumb.height;
header.len = thumb.len;
header.format = thumb.format;
w->Write(header);
w->Write(thumb.pixels, thumb.len);
w->Write(thumb.pixels.data(), thumb.pixels.size());
w->Finish();
+12 -30
View File
@@ -56,11 +56,7 @@ struct RDCThumbnailProvider : public IThumbnailProvider, IInitializeWithStream
dds_data m_ddsData;
RDCThumbnailProvider() : m_iRefcount(1), m_Inited(false) { InterlockedIncrement(&numProviders); }
virtual ~RDCThumbnailProvider()
{
delete[] m_Thumb.pixels;
InterlockedDecrement(&numProviders);
}
virtual ~RDCThumbnailProvider() { InterlockedDecrement(&numProviders); }
ULONG STDMETHODCALLTYPE AddRef()
{
InterlockedIncrement(&m_iRefcount);
@@ -152,10 +148,9 @@ struct RDCThumbnailProvider : public IThumbnailProvider, IInitializeWithStream
// bitmap.
m_Thumb.height = (uint16_t)m_ddsData.height;
m_Thumb.width = (uint16_t)m_ddsData.width;
m_Thumb.len = m_ddsData.subsizes[0]; // size of slice 0
buf = new byte[m_Thumb.len];
m_Thumb.pixels = buf;
memcpy(buf, m_ddsData.subdata[0], m_Thumb.len); // slice 0
size_t len = m_ddsData.subsizes[0]; // size of slice 0
m_Thumb.pixels.resize(len);
memcpy(m_Thumb.pixels.data(), m_ddsData.subdata[0], len); // slice 0
m_Thumb.format = FileType::DDS;
// We don't need any other data
@@ -175,14 +170,7 @@ struct RDCThumbnailProvider : public IThumbnailProvider, IInitializeWithStream
// we don't care about the error code (which would come from the truncated file), we just care
// if we got the thumbnail
if(m_Thumb.len > 0 && m_Thumb.width > 0 && m_Thumb.height > 0 && m_Thumb.pixels)
{
buf = new byte[m_Thumb.len];
memcpy(buf, m_Thumb.pixels, m_Thumb.len);
m_Thumb.pixels = buf;
m_Thumb.format = FileType::JPG;
}
else
if(m_Thumb.pixels.empty() || m_Thumb.width == 0 || m_Thumb.height == 0)
{
ReadLegacyCaptureThumb(captureHeader);
}
@@ -378,13 +366,11 @@ struct RDCThumbnailProvider : public IThumbnailProvider, IInitializeWithStream
{
RDCDEBUG("Got %ux%u thumbnail, %u pixels", thumbWidth, thumbHeight, thumbLen);
byte *pixels = new byte[thumbLen];
memcpy(pixels, readPtr, thumbLen);
m_Thumb.pixels.resize(thumbLen);
memcpy(m_Thumb.pixels.data(), readPtr, thumbLen);
m_Thumb.width = (uint16_t)thumbWidth;
m_Thumb.height = (uint16_t)thumbHeight;
m_Thumb.len = thumbLen;
m_Thumb.pixels = pixels;
}
else
{
@@ -403,26 +389,22 @@ struct RDCThumbnailProvider : public IThumbnailProvider, IInitializeWithStream
return E_NOTIMPL;
}
if(m_Thumb.len == 0)
if(m_Thumb.pixels.empty())
{
RDCERR("Problem opening file");
return E_NOTIMPL;
}
size_t thumblen = m_Thumb.len;
uint32_t thumbwidth = m_Thumb.width, thumbheight = m_Thumb.height;
byte *thumbpixels = NULL;
if(m_Thumb.format == FileType::JPG)
{
const byte *jpgbuf = m_Thumb.pixels;
if(jpgbuf == NULL)
return E_NOTIMPL;
int w = thumbwidth;
int h = thumbheight;
int comp = 3;
thumbpixels = jpgd::decompress_jpeg_image_from_memory(jpgbuf, (int)thumblen, &w, &h, &comp, 3);
thumbpixels = jpgd::decompress_jpeg_image_from_memory(
m_Thumb.pixels.data(), (int)m_Thumb.pixels.size(), &w, &h, &comp, 3);
}
else
{
@@ -472,7 +454,7 @@ struct RDCThumbnailProvider : public IThumbnailProvider, IInitializeWithStream
unsigned char decompressedBlock[decompressedBlockMaxSize];
unsigned char greenBlock[16];
uint16_t decompressedBC6[48];
const byte *compBlockStart = m_Thumb.pixels;
const byte *compBlockStart = m_Thumb.pixels.data();
for(uint32_t blockY = 0; blockY < AlignUp4(thumbheight) / 4; blockY++)
{
@@ -589,7 +571,7 @@ struct RDCThumbnailProvider : public IThumbnailProvider, IInitializeWithStream
else
{
// read data as non-compressed
const byte *src = m_Thumb.pixels;
const byte *src = m_Thumb.pixels.data();
byte *dst = thumbpixels;
uint32_t texelSize = m_ddsData.format.ElementSize();
+23 -36
View File
@@ -32,7 +32,7 @@
#include "stb/stb_image_resize.h"
#include "stb/stb_image_write.h"
static void writeToByteVector(void *context, void *data, int size)
static void writeToBytebuf(void *context, void *data, int size)
{
bytebuf *buf = (bytebuf *)context;
buf->append((byte *)data, size);
@@ -64,12 +64,7 @@ static RDCThumb convertThumb(FileType thumbType, uint32_t thumbWidth, uint32_t t
if(thumbType == FileType::JPG)
{
// just need to copy
byte *pixels = (byte *)malloc(thumbData.size());
memcpy(pixels, thumbData.data(), thumbData.size());
ret.pixels = pixels;
ret.len = (uint32_t)thumbData.size();
ret.pixels = thumbData;
}
else
{
@@ -87,15 +82,14 @@ static RDCThumb convertThumb(FileType thumbType, uint32_t thumbWidth, uint32_t t
if(decoded)
{
int len = ret.width * ret.height * 3;
byte *pixels = (byte *)malloc(len);
ret.pixels.resize(len);
jpge::params p;
p.m_quality = 90;
jpge::compress_image_to_jpeg_file_in_memory(pixels, len, (int)ret.width, (int)ret.height, 3,
decoded, p);
jpge::compress_image_to_jpeg_file_in_memory(ret.pixels.data(), len, (int)ret.width,
(int)ret.height, 3, decoded, p);
ret.pixels = pixels;
ret.len = (uint32_t)len;
ret.pixels.resize(len);
free(decoded);
}
@@ -402,8 +396,6 @@ void CaptureFile::SetMetadata(const char *driverName, uint64_t machineIdent, Fil
m_RDC = new RDCFile;
m_RDC->SetData(driver, driverName, machineIdent, thumb);
free((void *)th.pixels);
}
ReplayStatus CaptureFile::Convert(const char *filename, const char *filetype, const SDFile *file,
@@ -551,11 +543,9 @@ Thumbnail CaptureFile::GetThumbnail(FileType type, uint32_t maxsize)
const RDCThumb &thumb = m_RDC->GetThumbnail();
const byte *thumbbuf = thumb.pixels;
size_t thumblen = thumb.len;
uint32_t thumbwidth = thumb.width, thumbheight = thumb.height;
if(thumbbuf == NULL)
if(thumb.pixels.empty())
return ret;
bytebuf buf;
@@ -564,7 +554,7 @@ Thumbnail CaptureFile::GetThumbnail(FileType type, uint32_t maxsize)
// already satisfied, return the data directly
if(type == thumb.format && (maxsize == 0 || (maxsize > thumbwidth && maxsize > thumbheight)))
{
buf.assign(thumbbuf, thumblen);
buf = thumb.pixels;
}
else
{
@@ -578,15 +568,16 @@ Thumbnail CaptureFile::GetThumbnail(FileType type, uint32_t maxsize)
switch(thumb.format)
{
case FileType::JPG:
allocatedBuffer =
jpgd::decompress_jpeg_image_from_memory(thumbbuf, (int)thumblen, &w, &h, &comp, 3);
allocatedBuffer = jpgd::decompress_jpeg_image_from_memory(
thumb.pixels.data(), (int)thumb.pixels.size(), &w, &h, &comp, 3);
thumbpixels = allocatedBuffer;
break;
case FileType::Raw: thumbpixels = thumbbuf; break;
case FileType::Raw: thumbpixels = thumb.pixels.data(); break;
default:
allocatedBuffer = stbi_load_from_memory(thumbbuf, (int)thumblen, &w, &h, &comp, 3);
allocatedBuffer =
stbi_load_from_memory(thumb.pixels.data(), (int)thumb.pixels.size(), &w, &h, &comp, 3);
if(allocatedBuffer == NULL)
{
RDCERR("Couldn't decode provided thumbnail");
@@ -626,42 +617,40 @@ Thumbnail CaptureFile::GetThumbnail(FileType type, uint32_t maxsize)
}
}
bytebuf encodedBytes;
switch(type)
{
case FileType::Raw:
{
encodedBytes.assign(thumbpixels, thumbwidth * thumbheight * 3);
buf.assign(thumbpixels, thumbwidth * thumbheight * 3);
break;
}
case FileType::JPG:
{
int len = thumbwidth * thumbheight * 3;
encodedBytes.resize(len);
buf.resize(len);
jpge::params p;
p.m_quality = 90;
jpge::compress_image_to_jpeg_file_in_memory(&encodedBytes[0], len, (int)thumbwidth,
jpge::compress_image_to_jpeg_file_in_memory(buf.data(), len, (int)thumbwidth,
(int)thumbheight, 3, thumbpixels, p);
encodedBytes.resize(len);
buf.resize(len);
break;
}
case FileType::PNG:
{
stbi_write_png_to_func(&writeToByteVector, &encodedBytes, (int)thumbwidth, (int)thumbheight,
3, thumbpixels, 0);
stbi_write_png_to_func(&writeToBytebuf, &buf, (int)thumbwidth, (int)thumbheight, 3,
thumbpixels, 0);
break;
}
case FileType::TGA:
{
stbi_write_tga_to_func(&writeToByteVector, &encodedBytes, (int)thumbwidth, (int)thumbheight,
3, thumbpixels);
stbi_write_tga_to_func(&writeToBytebuf, &buf, (int)thumbwidth, (int)thumbheight, 3,
thumbpixels);
break;
}
case FileType::BMP:
{
stbi_write_bmp_to_func(&writeToByteVector, &encodedBytes, (int)thumbwidth, (int)thumbheight,
3, thumbpixels);
stbi_write_bmp_to_func(&writeToBytebuf, &buf, (int)thumbwidth, (int)thumbheight, 3,
thumbpixels);
break;
}
default:
@@ -674,8 +663,6 @@ Thumbnail CaptureFile::GetThumbnail(FileType type, uint32_t maxsize)
}
}
buf = encodedBytes;
free(allocatedBuffer);
}
+9 -7
View File
@@ -296,7 +296,7 @@ static ReplayStatus Structured2XML(const char *filename, const RDCFile &file, ui
pugi::xml_node xThumbnail = xHeader.append_child("thumbnail");
const RDCThumb &th = file.GetThumbnail();
if(th.pixels && th.len > 0 && th.width > 0 && th.height > 0)
if(!th.pixels.empty() && th.width > 0 && th.height > 0)
{
xThumbnail.append_attribute("width") = th.width;
xThumbnail.append_attribute("height") = th.height;
@@ -604,8 +604,7 @@ static ReplayStatus XML2Structured(const char *xml, const ThumbTypeAndData &thum
if(th.width > 0 && th.height > 0 && !thumb.data.empty())
{
th.pixels = thumb.data.data();
th.len = (uint32_t)thumb.data.size();
th.pixels = thumb.data;
rdcthumb = &th;
}
@@ -814,14 +813,17 @@ static ReplayStatus Buffers2ZIP(const rdcstr &filename, const RDCFile &file,
}
const RDCThumb &th = file.GetThumbnail();
if(th.pixels && th.len > 0 && th.width > 0 && th.height > 0)
if(!th.pixels.empty() && th.width > 0 && th.height > 0)
{
if(th.format == FileType::JPG)
mz_zip_writer_add_mem(&zip, "thumb.jpg", th.pixels, th.len, MZ_BEST_COMPRESSION);
mz_zip_writer_add_mem(&zip, "thumb.jpg", th.pixels.data(), th.pixels.size(),
MZ_BEST_COMPRESSION);
else if(th.format == FileType::PNG)
mz_zip_writer_add_mem(&zip, "thumb.png", th.pixels, th.len, MZ_BEST_COMPRESSION);
mz_zip_writer_add_mem(&zip, "thumb.png", th.pixels.data(), th.pixels.size(),
MZ_BEST_COMPRESSION);
else if(th.format == FileType::Raw)
mz_zip_writer_add_mem(&zip, "thumb.raw", th.pixels, th.len, MZ_BEST_COMPRESSION);
mz_zip_writer_add_mem(&zip, "thumb.raw", th.pixels.data(), th.pixels.size(),
MZ_BEST_COMPRESSION);
else
RDCERR("Unexpected thumbnail format %s", ToStr(th.format).c_str());
}
+22 -46
View File
@@ -227,9 +227,6 @@ RDCFile::~RDCFile()
{
if(m_File)
FileIO::fclose(m_File);
if(m_Thumb.pixels)
delete[] m_Thumb.pixels;
}
void RDCFile::Open(const char *path)
@@ -352,12 +349,12 @@ void RDCFile::Init(StreamReader &reader)
RETURNERROR(ContainerError::Corrupt, "Thumbnail byte length invalid: %u", thumb.length);
}
byte *thumbData = new byte[thumb.length];
reader.Read(thumbData, thumb.length);
bytebuf thumbData;
thumbData.resize(thumb.length);
reader.Read(thumbData.data(), thumb.length);
if(reader.IsErrored())
{
delete[] thumbData;
RETURNERROR(ContainerError::FileIO, "I/O error reading thumbnail data");
}
@@ -366,45 +363,35 @@ void RDCFile::Init(StreamReader &reader)
if(reader.IsErrored())
{
delete[] thumbData;
RETURNERROR(ContainerError::FileIO, "I/O error reading capture metadata");
}
if(meta.driverNameLength == 0)
{
delete[] thumbData;
RETURNERROR(ContainerError::Corrupt,
"Driver name length is invalid, must be at least 1 to contain NULL terminator");
}
char *driverName = new char[meta.driverNameLength];
reader.Read(driverName, meta.driverNameLength);
rdcstr driverName;
driverName.resize(meta.driverNameLength);
reader.Read(driverName.data(), meta.driverNameLength);
driverName.trim();
if(reader.IsErrored())
{
delete[] thumbData;
delete[] driverName;
RETURNERROR(ContainerError::FileIO, "I/O error reading driver name");
}
driverName[meta.driverNameLength - 1] = '\0';
m_Driver = meta.driverID;
m_DriverName = driverName;
m_MachineIdent = meta.machineIdent;
m_Thumb.width = thumb.width;
m_Thumb.height = thumb.height;
m_Thumb.len = thumb.length;
m_Thumb.format = FileType::JPG;
if(m_Thumb.len > 0 && m_Thumb.width > 0 && m_Thumb.height > 0)
{
m_Thumb.pixels = thumbData;
thumbData = NULL;
}
delete[] thumbData;
delete[] driverName;
if(m_Thumb.width > 0 && m_Thumb.height > 0)
m_Thumb.pixels.swap(thumbData);
if(reader.GetOffset() > header.headerLength)
{
@@ -597,22 +584,16 @@ void RDCFile::Init(StreamReader &reader)
ExtThumbnailHeader thumbHeader;
if(thumbReader->Read(thumbHeader))
{
thumbData = new byte[thumbHeader.len];
bool succeeded = thumbReader->Read(thumbData, thumbHeader.len) && !thumbReader->IsErrored();
thumbData.resize(thumbHeader.len);
bool succeeded =
thumbReader->Read(thumbData.data(), thumbHeader.len) && !thumbReader->IsErrored();
if(succeeded && (uint32_t)thumbHeader.format < (uint32_t)FileType::Count)
{
m_Thumb.width = thumbHeader.width;
m_Thumb.height = thumbHeader.height;
m_Thumb.len = thumbHeader.len;
m_Thumb.format = thumbHeader.format;
delete[] m_Thumb.pixels;
m_Thumb.pixels = thumbData;
m_Thumb.pixels.swap(thumbData);
}
else
{
delete[] thumbData;
}
thumbData = NULL;
}
delete thumbReader;
}
@@ -651,11 +632,6 @@ void RDCFile::SetData(RDCDriver driver, const char *driverName, uint64_t machine
if(thumb)
{
m_Thumb = *thumb;
byte *pixels = new byte[m_Thumb.len];
memcpy(pixels, thumb->pixels, m_Thumb.len);
m_Thumb.pixels = pixels;
}
}
@@ -680,10 +656,10 @@ void RDCFile::Create(const char *filename)
thumbHeader.width = m_Thumb.width;
thumbHeader.height = m_Thumb.height;
const byte *jpgPixels = m_Thumb.pixels;
thumbHeader.length = m_Thumb.len;
const byte *jpgPixels = m_Thumb.pixels.data();
thumbHeader.length = (uint32_t)m_Thumb.pixels.size();
byte *jpgBuffer = NULL;
bytebuf jpgBuffer;
if(m_Thumb.format != FileType::JPG && m_Thumb.width > 0 && m_Thumb.height > 0)
{
// the primary thumbnail must be in JPG format, must perform conversion
@@ -695,23 +671,24 @@ void RDCFile::Create(const char *filename)
if(m_Thumb.format == FileType::Raw)
{
rawPixels = m_Thumb.pixels;
rawPixels = m_Thumb.pixels.data();
}
else
{
rawBuffer = stbi_load_from_memory(m_Thumb.pixels, (int)m_Thumb.len, &w, &h, &comp, 3);
rawBuffer =
stbi_load_from_memory(m_Thumb.pixels.data(), (int)m_Thumb.pixels.size(), &w, &h, &comp, 3);
rawPixels = rawBuffer;
}
if(rawPixels)
{
int len = w * h * comp;
jpgBuffer = new byte[len];
jpgBuffer.resize(len);
jpge::params p;
p.m_quality = 90;
jpge::compress_image_to_jpeg_file_in_memory(jpgBuffer, len, w, h, comp, rawPixels, p);
jpge::compress_image_to_jpeg_file_in_memory(jpgBuffer.data(), len, w, h, comp, rawPixels, p);
thumbHeader.length = (uint32_t)len;
jpgPixels = jpgBuffer;
jpgPixels = jpgBuffer.data();
}
else
{
@@ -745,7 +722,6 @@ void RDCFile::Create(const char *filename)
writer.Write(m_DriverName.c_str(), meta.driverNameLength);
delete[] jpgBuffer;
if(writer.IsErrored())
{
RETURNERROR(ContainerError::FileIO, "Error writing file header");
+1 -2
View File
@@ -40,8 +40,7 @@ extern const char *SectionTypeNames[];
struct RDCThumb
{
const byte *pixels = NULL;
uint32_t len = 0;
bytebuf pixels;
uint16_t width = 0;
uint16_t height = 0;
FileType format = FileType::JPG;