Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Unified Diff: src/codec/SkRawCodec.cpp

Issue 1645963002: Optimize the SkRawStream when the input is an asset stream (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Handle the case when getBaseMemory() == nullptr Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codec/SkRawCodec.cpp
diff --git a/src/codec/SkRawCodec.cpp b/src/codec/SkRawCodec.cpp
index da3c28c549ff617cc74df0effb9ff18177eca023..6f6fa050ac01cb5b564fc0b3d080940a9e15b29d 100644
--- a/src/codec/SkRawCodec.cpp
+++ b/src/codec/SkRawCodec.cpp
@@ -159,21 +159,64 @@ public:
} // namespace
-// Note: this class could throw exception if it is used as dng_stream.
-class SkRawStream : public ::piex::StreamInterface {
+class SkRawStream {
public:
- // Note that this call will take the ownership of stream.
- explicit SkRawStream(SkStream* stream)
- : fStream(stream), fWholeStreamRead(false) {}
+ virtual ~SkRawStream() {}
+
+ /*
+ * Gets the length of the stream. Denpending on the type of stream, this may require read to the
scroggo 2016/02/02 19:23:06 depending* reading*
yujieqin 2016/02/04 14:50:32 Done.
+ * end of stream.
scroggo 2016/02/02 19:23:06 the* stream
yujieqin 2016/02/04 14:50:31 Done.
+ */
+ virtual uint64 getLength() = 0;
- ~SkRawStream() override {}
+ virtual bool read(size_t offset, size_t length, void* data) = 0;
scroggo 2016/02/02 19:23:06 nit: We typically put our output parameters first.
yujieqin 2016/02/04 14:50:31 Done.
/*
* Creates an SkMemoryStream from the offset with size.
* Note: for performance reason, this function is destructive to the SkRawStream. One should
* abandon current object after the function call.
*/
- SkMemoryStream* transferBuffer(size_t offset, size_t size) {
+ virtual SkMemoryStream* transferBuffer(size_t offset, size_t size) = 0;
+};
+
+class SkRawBufferedStream : public SkRawStream {
+public:
+ static SkRawStream* NewFromStream(SkStream* stream) {
+ return new SkRawBufferedStream(stream);
+ }
+
+ // Will take the ownership of the stream.
+ explicit SkRawBufferedStream(SkStream* stream)
+ : fStream(stream)
+ , fWholeStreamRead(false)
+ {
+ // Only use SkRawBufferedStream when the stream is not seekable.
+ SkASSERT(!fStream->hasPosition());
+ }
+
+ ~SkRawBufferedStream() override {}
+
+ uint64 getLength() override {
+ if (!this->bufferMoreData(kReadToEnd)) { // read whole stream
+ ThrowReadFile();
+ }
+ return fStreamBuffer.bytesWritten();
+ }
+
+ bool read(size_t offset, size_t length, void* data) {
+ if (offset == 0 && length == 0) {
scroggo 2016/02/02 19:23:06 Why is there a special case here? I can see why a
yujieqin 2016/02/04 14:50:31 I think you are right. This should be a bug. :)
+ return true;
+ }
+
+ size_t sum;
+ if (!safe_add_to_size_t(offset, length, &sum)) {
+ return false;
+ }
+
+ return this->bufferMoreData(sum) && fStreamBuffer.read(data, offset, length);
+ }
+
+ SkMemoryStream* transferBuffer(size_t offset, size_t size) override {
SkAutoTUnref<SkData> data(SkData::NewUninitialized(size));
if (offset > fStreamBuffer.bytesWritten()) {
// If the offset is not buffered, read from fStream directly and skip the buffering.
@@ -208,46 +251,6 @@ public:
return new SkMemoryStream(data);
}
- // For PIEX
- ::piex::Error GetData(const size_t offset, const size_t length,
- uint8* data) override {
- if (offset == 0 && length == 0) {
- return ::piex::Error::kOk;
- }
- size_t sum;
- if (!safe_add_to_size_t(offset, length, &sum) || !this->bufferMoreData(sum)) {
- return ::piex::Error::kFail;
- }
- if (!fStreamBuffer.read(data, offset, length)) {
- return ::piex::Error::kFail;
- }
- return ::piex::Error::kOk;
- }
-
- // For dng_stream
- uint64 getLength() {
- if (!this->bufferMoreData(kReadToEnd)) { // read whole stream
- ThrowReadFile();
- }
- return fStreamBuffer.bytesWritten();
- }
-
- // For dng_stream
- void read(void* data, uint32 count, uint64 offset) {
- if (count == 0 && offset == 0) {
- return;
- }
- size_t sum;
- if (!safe_add_to_size_t(static_cast<uint64>(count), offset, &sum) ||
- !this->bufferMoreData(sum)) {
- ThrowReadFile();
- }
-
- if (!fStreamBuffer.read(data, static_cast<size_t>(offset), count)) {
- ThrowReadFile();
- }
- }
-
private:
// Note: if the newSize == kReadToEnd (0), this function will read to the end of stream.
bool bufferMoreData(size_t newSize) {
@@ -284,18 +287,110 @@ private:
const size_t kReadToEnd = 0;
};
+class SkRawSeekableStream : public SkRawStream {
+public:
+ static SkRawStream* NewFromStream(SkStream* stream) {
+ return new SkRawSeekableStream(stream);
+ }
+
+ // Will take the ownership of the stream.
+ explicit SkRawSeekableStream(SkStream* stream)
+ : fStream(stream)
+ {
+ // Only use SkRawSeekableStream when the stream is seekable.
+ SkASSERT(fStream->hasPosition());
+ }
+
+ ~SkRawSeekableStream() override {}
+
+ uint64 getLength() {
+ return fStream->getLength();
scroggo 2016/02/02 19:23:06 Maybe we should also check hasLength() to determin
yujieqin 2016/02/04 14:50:31 Done.
+ }
+
+
+ bool read(size_t offset, size_t length, void* data) {
+ if (offset == 0 && length == 0) {
+ return true;
+ }
+
+ size_t sum;
+ if (!safe_add_to_size_t(offset, length, &sum)) {
+ return false;
+ }
+
+ if (sum > fStream->getLength()) {
scroggo 2016/02/02 19:23:06 I don't think this check is necessary - the below
yujieqin 2016/02/04 14:50:31 Done.
+ return false;
scroggo 2016/02/02 19:23:06 four space indent.
yujieqin 2016/02/04 14:50:31 Done.
+ }
+ return fStream->seek(offset) && (fStream->read(data, length) == length);
+ }
+
+ SkMemoryStream* transferBuffer(size_t offset, size_t size) {
+ size_t sum;
+ if (!safe_add_to_size_t(offset, size, &sum)) {
+ return nullptr;
+ }
+
+ if (fStream->getMemoryBase()) {
+ SkAutoTUnref<SkData> data(SkData::NewWithCopy(
+ static_cast<const uint8_t*>(fStream->getMemoryBase()) + offset, size));
scroggo 2016/02/02 19:23:06 This case should also support a partial jpeg file.
yujieqin 2016/02/04 14:50:31 Done.
+ fStream.free();
+ return new SkMemoryStream(data);
+ } else {
+ SkAutoTUnref<SkData> data(SkData::NewUninitialized(size));
+ if (!fStream->seek(offset)) {
+ return nullptr;
+ }
+ // Don't check the returned size, because the following JPEG codec may be able to
scroggo 2016/02/02 19:23:06 We do need to know the returned size, though, beca
yujieqin 2016/02/04 14:50:31 Done.
+ // process an incomplete file.
+ fStream->read(data->writable_data(), size);
+ return new SkMemoryStream(data);
+ }
+ }
+private:
+ SkAutoTDelete<SkStream> fStream;
+};
+
+class SkPiexStream : public ::piex::StreamInterface {
+public:
+ // Note that this call will take the ownership of stream.
+ explicit SkPiexStream(SkRawStream* stream) : fStream(stream) {}
+
+ ~SkPiexStream() override {}
+
+ ::piex::Error GetData(const size_t offset, const size_t length,
+ uint8* data) override {
+ return fStream->read(offset, length, static_cast<void*>(data)) ?
+ ::piex::Error::kOk : ::piex::Error::kFail;
+ }
+
+ // Release the fStream. One should abandon current object after this call.
+ SkRawStream* releaseRawStream() {
+ return fStream.release();
+ }
+
+private:
+ SkAutoTDelete<SkRawStream> fStream;
+};
+
class SkDngStream : public dng_stream {
public:
- SkDngStream(SkRawStream* rawStream) : fRawStream(rawStream) {}
+ // Will NOT take the ownership of the stream, because the stream needs to be able to reuse.
+ SkDngStream(SkRawStream* stream) : fStream(stream) {}
+
+ ~SkDngStream() override {}
- uint64 DoGetLength() override { return fRawStream->getLength(); }
+ uint64 DoGetLength() override { return fStream->getLength(); }
void DoRead(void* data, uint32 count, uint64 offset) override {
- fRawStream->read(data, count, offset);
+ size_t sum;
+ if (!safe_add_to_size_t(static_cast<uint64>(count), offset, &sum) ||
scroggo 2016/02/02 19:23:06 Won't the implementation of fStream->read also mak
yujieqin 2016/02/04 14:50:31 as explained for last patch set, this check is for
+ !fStream->read(static_cast<size_t>(offset), static_cast<size_t>(count), data)) {
+ ThrowReadFile();
+ }
}
private:
- SkRawStream* fRawStream;
+ SkRawStream* fStream;
};
class SkDngImage {
@@ -436,13 +531,15 @@ private:
* fallback to create SkRawCodec for DNG images.
*/
SkCodec* SkRawCodec::NewFromStream(SkStream* stream) {
- SkAutoTDelete<SkRawStream> rawStream(new SkRawStream(stream));
+ SkAutoTDelete<SkPiexStream> piexStream(new SkPiexStream(
+ stream->hasPosition() ?
+ SkRawSeekableStream::NewFromStream(stream) : SkRawBufferedStream::NewFromStream(stream)));
scroggo 2016/02/02 19:23:06 I don't think these factory functions are necessar
yujieqin 2016/02/04 14:50:31 Done.
::piex::PreviewImageData imageData;
// FIXME: ::piex::GetPreviewImageData() calls GetData() frequently with small amounts,
// resulting in many calls to bufferMoreData(). Could we make this more efficient by grouping
// smaller requests together?
- if (::piex::IsRaw(rawStream.get())) {
- ::piex::Error error = ::piex::GetPreviewImageData(rawStream.get(), &imageData);
+ if (::piex::IsRaw(piexStream.get())) {
+ ::piex::Error error = ::piex::GetPreviewImageData(piexStream.get(), &imageData);
if (error == ::piex::Error::kOk && imageData.preview_length > 0) {
#if !defined(GOOGLE3)
@@ -450,7 +547,8 @@ SkCodec* SkRawCodec::NewFromStream(SkStream* stream) {
// function call.
// FIXME: one may avoid the copy of memoryStream and use the buffered rawStream.
SkMemoryStream* memoryStream =
- rawStream->transferBuffer(imageData.preview_offset, imageData.preview_length);
+ piexStream->releaseRawStream()->transferBuffer(imageData.preview_offset,
scroggo 2016/02/02 19:23:06 This is going to leak the raw stream. I think it m
yujieqin 2016/02/04 14:50:31 Done.
+ imageData.preview_length);
return memoryStream ? SkJpegCodec::NewFromStream(memoryStream) : nullptr;
#else
return nullptr;
@@ -460,7 +558,7 @@ SkCodec* SkRawCodec::NewFromStream(SkStream* stream) {
}
}
- SkAutoTDelete<SkDngImage> dngImage(SkDngImage::NewFromStream(rawStream.release()));
+ SkAutoTDelete<SkDngImage> dngImage(SkDngImage::NewFromStream(piexStream->releaseRawStream()));
if (!dngImage) {
return nullptr;
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698