summaryrefslogtreecommitdiffstats
path: root/third_party/libwebp/enc/syntax.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebp/enc/syntax.c')
-rw-r--r--third_party/libwebp/enc/syntax.c103
1 files changed, 85 insertions, 18 deletions
diff --git a/third_party/libwebp/enc/syntax.c b/third_party/libwebp/enc/syntax.c
index a788f3c..f119018 100644
--- a/third_party/libwebp/enc/syntax.c
+++ b/third_party/libwebp/enc/syntax.c
@@ -26,7 +26,7 @@ extern "C" {
#define MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition
#define MAX_PARTITION_SIZE (1 << 24) // max size for token partition
-//-----------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// Writers for header's various pieces (in order of appearance)
// Main keyframe header
@@ -39,26 +39,31 @@ static void PutLE32(uint8_t* const data, uint32_t val) {
}
static int PutHeader(int profile, size_t size0, size_t total_size,
- const WebPPicture* const pic) {
+ WebPPicture* const pic) {
uint8_t buf[KHEADER_SIZE];
uint8_t RIFF[KRIFF_SIZE] = {
'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P', 'V', 'P', '8', ' '
};
uint32_t bits;
- if (size0 >= MAX_PARTITION0_SIZE) {
- return 0; // partition #0 is too big to fit
+ if (size0 >= MAX_PARTITION0_SIZE) { // partition #0 is too big to fit
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_PARTITION0_OVERFLOW);
}
- PutLE32(RIFF + 4, total_size + KSIZE_OFFSET);
- PutLE32(RIFF + 16, total_size);
- if (!pic->writer(RIFF, sizeof(RIFF), pic))
- return 0;
+ if (total_size > 0xfffffffeU - KRIFF_SIZE) {
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_FILE_TOO_BIG);
+ }
+
+ PutLE32(RIFF + 4, (uint32_t)(total_size + KSIZE_OFFSET));
+ PutLE32(RIFF + 16, (uint32_t)total_size);
+ if (!pic->writer(RIFF, sizeof(RIFF), pic)) {
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE);
+ }
- bits = 0 // keyframe (1b)
- | (profile << 1) // profile (3b)
- | (1 << 4) // visible (1b)
- | (size0 << 5); // partition length (19b)
+ bits = 0 // keyframe (1b)
+ | (profile << 1) // profile (3b)
+ | (1 << 4) // visible (1b)
+ | ((uint32_t)size0 << 5); // partition length (19b)
buf[0] = bits & 0xff;
buf[1] = (bits >> 8) & 0xff;
buf[2] = (bits >> 16) & 0xff;
@@ -138,13 +143,13 @@ static void PutQuant(VP8BitWriter* const bw,
// Partition sizes
static int EmitPartitionsSize(const VP8Encoder* const enc,
- const WebPPicture* const pic) {
+ WebPPicture* const pic) {
uint8_t buf[3 * (MAX_NUM_PARTITIONS - 1)];
int p;
for (p = 0; p < enc->num_parts_ - 1; ++p) {
const size_t part_size = VP8BitWriterSize(enc->parts_ + p);
if (part_size >= MAX_PARTITION_SIZE) {
- return 0; // partition is too big to fit
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_PARTITION_OVERFLOW);
}
buf[3 * p + 0] = (part_size >> 0) & 0xff;
buf[3 * p + 1] = (part_size >> 8) & 0xff;
@@ -153,16 +158,69 @@ static int EmitPartitionsSize(const VP8Encoder* const enc,
return p ? pic->writer(buf, 3 * p, pic) : 1;
}
-//-----------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+
+#define KTRAILER_SIZE 8
+
+static void PutLE24(uint8_t* buf, size_t value) {
+ buf[0] = (value >> 0) & 0xff;
+ buf[1] = (value >> 8) & 0xff;
+ buf[2] = (value >> 16) & 0xff;
+}
+
+static int WriteExtensions(VP8Encoder* const enc) {
+ uint8_t buffer[KTRAILER_SIZE];
+ VP8BitWriter* const bw = &enc->bw_;
+ WebPPicture* const pic = enc->pic_;
+
+ // Layer (bytes 0..3)
+ PutLE24(buffer + 0, enc->layer_data_size_);
+ buffer[3] = enc->pic_->colorspace & WEBP_CSP_UV_MASK;
+ if (enc->layer_data_size_ > 0) {
+ assert(enc->use_layer_);
+ // append layer data to last partition
+ if (!VP8BitWriterAppend(&enc->parts_[enc->num_parts_ - 1],
+ enc->layer_data_, enc->layer_data_size_)) {
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY);
+ }
+ }
+ // Alpha (bytes 4..6)
+ PutLE24(buffer + 4, enc->alpha_data_size_);
+ if (enc->alpha_data_size_ > 0) {
+ assert(enc->has_alpha_);
+ if (!VP8BitWriterAppend(bw, enc->alpha_data_, enc->alpha_data_size_)) {
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY);
+ }
+ }
+
+ buffer[KTRAILER_SIZE - 1] = 0x01; // marker
+ if (!VP8BitWriterAppend(bw, buffer, KTRAILER_SIZE)) {
+ return WebPEncodingSetError(pic, VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY);
+ }
+ return 1;
+}
+
+#endif /* WEBP_EXPERIMENTAL_FEATURES */
+
+//------------------------------------------------------------------------------
static size_t GeneratePartition0(VP8Encoder* const enc) {
VP8BitWriter* const bw = &enc->bw_;
const int mb_size = enc->mb_w_ * enc->mb_h_;
uint64_t pos1, pos2, pos3;
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ const int need_extensions = enc->has_alpha_ || enc->use_layer_;
+#endif
pos1 = VP8BitWriterPos(bw);
VP8BitWriterInit(bw, mb_size * 7 / 8); // ~7 bits per macroblock
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ VP8PutBitUniform(bw, need_extensions); // extensions
+#else
VP8PutBitUniform(bw, 0); // colorspace
+#endif
VP8PutBitUniform(bw, 0); // clamp type
PutSegmentHeader(bw, enc);
@@ -174,11 +232,20 @@ static size_t GeneratePartition0(VP8Encoder* const enc) {
pos2 = VP8BitWriterPos(bw);
VP8CodeIntraModes(enc);
VP8BitWriterFinish(bw);
+
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ if (need_extensions && !WriteExtensions(enc)) {
+ return 0;
+ }
+#endif
+
pos3 = VP8BitWriterPos(bw);
if (enc->pic_->stats) {
enc->pic_->stats->header_bytes[0] = (int)((pos2 - pos1 + 7) >> 3);
enc->pic_->stats->header_bytes[1] = (int)((pos3 - pos2 + 7) >> 3);
+ enc->pic_->stats->alpha_data_size = (int)enc->alpha_data_size_;
+ enc->pic_->stats->layer_data_size = (int)enc->layer_data_size_;
}
return !bw->error_;
}
@@ -191,7 +258,7 @@ int VP8EncWrite(VP8Encoder* const enc) {
int p;
// Partition #0 with header and partition sizes
- ok = GeneratePartition0(enc);
+ ok = !!GeneratePartition0(enc);
// Compute total size (for the RIFF header)
coded_size = KHEADER_SIZE + VP8BitWriterSize(bw) + 3 * (enc->num_parts_ - 1);
@@ -226,11 +293,11 @@ int VP8EncWrite(VP8Encoder* const enc) {
ok = pic->writer(pad_byte, 1, pic);
}
- enc->coded_size_ = coded_size + KRIFF_SIZE;
+ enc->coded_size_ = (int)coded_size + KRIFF_SIZE;
return ok;
}
-//-----------------------------------------------------------------------------
+//------------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"