Coverage Report

Created: 2025-12-31 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brunsli/c/dec/jpeg_data_writer.cc
Line
Count
Source
1
// Copyright (c) Google LLC 2019
2
//
3
// Use of this source code is governed by an MIT-style
4
// license that can be found in the LICENSE file or at
5
// https://opensource.org/licenses/MIT.
6
7
#include <brunsli/jpeg_data_writer.h>
8
9
#include <cstddef>
10
#include <cstdlib>
11
#include <cstring> /* for memset, memcpy */
12
#include <deque>
13
#include <string>
14
#include <vector>
15
16
#include "../common/constants.h"
17
#include <brunsli/jpeg_data.h>
18
#include "../common/platform.h"
19
#include <brunsli/types.h>
20
#include "./serialization_state.h"
21
#include "./state.h"
22
#include "./state_internal.h"
23
24
namespace brunsli {
25
26
using ::brunsli::internal::dec::BitWriter;
27
using ::brunsli::internal::dec::DCTCodingState;
28
using ::brunsli::internal::dec::EncodeScanState;
29
using ::brunsli::internal::dec::OutputChunk;
30
using ::brunsli::internal::dec::SerializationState;
31
using ::brunsli::internal::dec::SerializationStatus;
32
using ::brunsli::internal::dec::SerializeJpeg;
33
using ::brunsli::internal::dec::Stage;
34
using ::brunsli::internal::dec::State;
35
36
namespace {
37
38
const int kJpegPrecision = 8;
39
40
// BitWriter: buffer size
41
const size_t kBitWriterChunkSize = 16384;
42
43
// Returns ceil(a/b).
44
19.5k
static BRUNSLI_INLINE int DivCeil(int a, int b) { return (a + b - 1) / b; }
45
46
// Returns non-zero if and only if x has a zero byte, i.e. one of
47
// x & 0xff, x & 0xff00, ..., x & 0xff00000000000000 is zero.
48
4.04M
static BRUNSLI_INLINE uint64_t HasZeroByte(uint64_t x) {
49
4.04M
  return (x - 0x0101010101010101ULL) & ~x & 0x8080808080808080ULL;
50
4.04M
}
51
52
9.77k
void BitWriterInit(BitWriter* bw, std::deque<OutputChunk>* output_queue) {
53
9.77k
  bw->output = output_queue;
54
9.77k
  bw->chunk = OutputChunk(kBitWriterChunkSize);
55
9.77k
  bw->pos = 0;
56
9.77k
  bw->put_buffer = 0;
57
9.77k
  bw->put_bits = 64;
58
9.77k
  bw->healthy = true;
59
9.77k
  bw->data = bw->chunk.buffer->data();
60
9.77k
}
61
62
1.47k
static BRUNSLI_NOINLINE void SwapBuffer(BitWriter* bw) {
63
1.47k
  bw->chunk.len = bw->pos;
64
1.47k
  bw->output->emplace_back(std::move(bw->chunk));
65
1.47k
  bw->chunk = OutputChunk(kBitWriterChunkSize);
66
1.47k
  bw->data = bw->chunk.buffer->data();
67
1.47k
  bw->pos = 0;
68
1.47k
}
69
70
5.07M
static BRUNSLI_INLINE void Reserve(BitWriter* bw, size_t n_bytes) {
71
5.07M
  if (BRUNSLI_PREDICT_FALSE((bw->pos + n_bytes) > kBitWriterChunkSize)) {
72
1.47k
    SwapBuffer(bw);
73
1.47k
  }
74
5.07M
}
75
76
/**
77
 * Writes the given byte to the output, writes an extra zero if byte is 0xFF.
78
 *
79
 * This method is "careless" - caller must make sure that there is enough
80
 * space in the output buffer. Emits up to 2 bytes to buffer.
81
 */
82
9.88M
static BRUNSLI_INLINE void EmitByte(BitWriter* bw, int byte) {
83
9.88M
  bw->data[bw->pos++] = byte;
84
9.88M
  if (byte == 0xFF) bw->data[bw->pos++] = 0;
85
9.88M
}
86
87
4.04M
static BRUNSLI_INLINE void DischargeBitBuffer(BitWriter* bw) {
88
  // At this point we are ready to emit the most significant 6 bytes of
89
  // put_buffer_ to the output.
90
  // The JPEG format requires that after every 0xff byte in the entropy
91
  // coded section, there is a zero byte, therefore we first check if any of
92
  // the 6 most significant bytes of put_buffer_ is 0xFF.
93
4.04M
  Reserve(bw, 12);
94
4.04M
  if (HasZeroByte(~bw->put_buffer | 0xFFFF)) {
95
    // We have a 0xFF byte somewhere, examine each byte and append a zero
96
    // byte if necessary.
97
1.45M
    EmitByte(bw, (bw->put_buffer >> 56) & 0xFF);
98
1.45M
    EmitByte(bw, (bw->put_buffer >> 48) & 0xFF);
99
1.45M
    EmitByte(bw, (bw->put_buffer >> 40) & 0xFF);
100
1.45M
    EmitByte(bw, (bw->put_buffer >> 32) & 0xFF);
101
1.45M
    EmitByte(bw, (bw->put_buffer >> 24) & 0xFF);
102
1.45M
    EmitByte(bw, (bw->put_buffer >> 16) & 0xFF);
103
2.58M
  } else {
104
    // We don't have any 0xFF bytes, output all 6 bytes without checking.
105
2.58M
    bw->data[bw->pos] = (bw->put_buffer >> 56) & 0xFF;
106
2.58M
    bw->data[bw->pos + 1] = (bw->put_buffer >> 48) & 0xFF;
107
2.58M
    bw->data[bw->pos + 2] = (bw->put_buffer >> 40) & 0xFF;
108
2.58M
    bw->data[bw->pos + 3] = (bw->put_buffer >> 32) & 0xFF;
109
2.58M
    bw->data[bw->pos + 4] = (bw->put_buffer >> 24) & 0xFF;
110
2.58M
    bw->data[bw->pos + 5] = (bw->put_buffer >> 16) & 0xFF;
111
2.58M
    bw->pos += 6;
112
2.58M
  }
113
4.04M
  bw->put_buffer <<= 48;
114
4.04M
  bw->put_bits += 48;
115
4.04M
}
116
117
50.4M
static BRUNSLI_INLINE void WriteBits(BitWriter* bw, int nbits, uint64_t bits) {
118
  // This is an optimization; if everything goes well,
119
  // then |nbits| is positive; if non-existing Huffman symbol is going to be
120
  // encoded, its length should be zero; later encoder could check the
121
  // "health" of BitWriter.
122
50.4M
  if (nbits == 0) {
123
7.87M
    bw->healthy = false;
124
7.87M
    return;
125
7.87M
  }
126
42.5M
  bw->put_bits -= nbits;
127
42.5M
  bw->put_buffer |= (bits << bw->put_bits);
128
42.5M
  if (bw->put_bits <= 16) DischargeBitBuffer(bw);
129
42.5M
}
130
131
512k
void EmitMarker(BitWriter* bw, int marker) {
132
512k
  Reserve(bw, 2);
133
512k
  BRUNSLI_DCHECK(marker != 0xFF);
134
512k
  bw->data[bw->pos++] = 0xFF;
135
512k
  bw->data[bw->pos++] = marker;
136
512k
}
137
138
bool JumpToByteBoundary(BitWriter* bw, const int** pad_bits,
139
522k
                        const int* pad_bits_end) {
140
522k
  size_t n_bits = bw->put_bits & 7u;
141
522k
  uint8_t pad_pattern;
142
522k
  if (*pad_bits == nullptr) {
143
518k
    pad_pattern = (1u << n_bits) - 1;
144
518k
  } else {
145
4.12k
    pad_pattern = 0;
146
4.12k
    const int* src = *pad_bits;
147
    // TODO(eustas): bitwise reading looks insanely ineffective...
148
10.8k
    while (n_bits--) {
149
6.88k
      pad_pattern <<= 1;
150
6.88k
      if (src >= pad_bits_end) return false;
151
      // TODO(eustas): DCHECK *src == {0, 1}
152
6.76k
      pad_pattern |= !!*(src++);
153
6.76k
    }
154
4.01k
    *pad_bits = src;
155
4.01k
  }
156
157
522k
  Reserve(bw, 16);
158
159
1.28M
  while (bw->put_bits <= 56) {
160
765k
    int c = (bw->put_buffer >> 56) & 0xFF;
161
765k
    EmitByte(bw, c);
162
765k
    bw->put_buffer <<= 8;
163
765k
    bw->put_bits += 8;
164
765k
  }
165
522k
  if (bw->put_bits < 64) {
166
387k
    int pad_mask = 0xFFu >> (64 - bw->put_bits);
167
387k
    int c = ((bw->put_buffer >> 56) & ~pad_mask) | pad_pattern;
168
387k
    EmitByte(bw, c);
169
387k
  }
170
522k
  bw->put_buffer = 0;
171
522k
  bw->put_bits = 64;
172
173
522k
  return true;
174
522k
}
175
176
9.65k
void BitWriterFinish(BitWriter* bw) {
177
9.65k
  if (bw->pos == 0) return;
178
9.20k
  bw->chunk.len = bw->pos;
179
9.20k
  bw->output->emplace_back(std::move(bw->chunk));
180
9.20k
  bw->chunk = OutputChunk(nullptr, 0);
181
9.20k
  bw->data = nullptr;
182
9.20k
  bw->pos = 0;
183
9.20k
}
184
185
9.77k
void DCTCodingStateInit(DCTCodingState* s) {
186
9.77k
  s->eob_run_ = 0;
187
9.77k
  s->cur_ac_huff_ = nullptr;
188
9.77k
  s->refinement_bits_.clear();
189
9.77k
  s->refinement_bits_.reserve(64);  // 1024 bits most often is more than enough.
190
9.77k
  s->refinement_bits_count_ = 0;
191
9.77k
}
192
193
// Emit all buffered data to the bit stream using the given Huffman code and
194
// bit writer.
195
13.9M
static BRUNSLI_INLINE void Flush(DCTCodingState* s, BitWriter* bw) {
196
13.9M
  if (s->eob_run_ > 0) {
197
13.3M
    int nbits = Log2FloorNonZero(s->eob_run_);
198
13.3M
    int symbol = nbits << 4u;
199
13.3M
    WriteBits(bw, s->cur_ac_huff_->depth[symbol],
200
13.3M
              s->cur_ac_huff_->code[symbol]);
201
13.3M
    if (nbits > 0) {
202
63.5k
      WriteBits(bw, nbits, s->eob_run_ & ((1 << nbits) - 1));
203
63.5k
    }
204
13.3M
    s->eob_run_ = 0;
205
13.3M
  }
206
13.9M
  size_t num_words = s->refinement_bits_count_ >> 4;
207
14.0M
  for (size_t i = 0; i < num_words; ++i) {
208
51.5k
    WriteBits(bw, 16, s->refinement_bits_[i]);
209
51.5k
  }
210
13.9M
  size_t tail = s->refinement_bits_count_ & 0xF;
211
13.9M
  if (tail) {
212
61.5k
    WriteBits(bw, tail, s->refinement_bits_.back());
213
61.5k
  }
214
13.9M
  s->refinement_bits_.clear();
215
13.9M
  s->refinement_bits_count_ = 0;
216
13.9M
}
217
218
// Buffer some more data at the end-of-band (the last non-zero or newly
219
// non-zero coefficient within the [Ss, Se] spectral band).
220
static BRUNSLI_INLINE bool BufferEndOfBand(DCTCodingState* s,
221
                                           const HuffmanCodeTable* ac_huff,
222
                                           const int* new_bits_array,
223
                                           size_t new_bits_count,
224
69.8M
                                           BitWriter* bw) {
225
69.8M
  if (s->eob_run_ == 0) {
226
13.3M
    s->cur_ac_huff_ = ac_huff;
227
13.3M
  }
228
69.8M
  ++s->eob_run_;
229
69.8M
  if (new_bits_count) {
230
260k
    uint64_t new_bits = 0;
231
1.37M
    for (size_t i = 0; i < new_bits_count; ++i) {
232
1.11M
      new_bits = (new_bits << 1) | new_bits_array[i];
233
1.11M
    }
234
260k
    size_t tail = s->refinement_bits_count_ & 0xF;
235
260k
    if (tail) {  // First stuff the tail item
236
188k
      size_t stuff_bits_count = std::min(16 - tail, new_bits_count);
237
188k
      uint16_t stuff_bits = new_bits >> (new_bits_count - stuff_bits_count);
238
188k
      stuff_bits &= ((1u << stuff_bits_count) - 1);
239
188k
      s->refinement_bits_.back() =
240
188k
          (s->refinement_bits_.back() << stuff_bits_count) | stuff_bits;
241
188k
      new_bits_count -= stuff_bits_count;
242
188k
      s->refinement_bits_count_ += stuff_bits_count;
243
188k
    }
244
281k
    while (new_bits_count >= 16) {
245
20.7k
      s->refinement_bits_.push_back(new_bits >> (new_bits_count - 16));
246
20.7k
      new_bits_count -= 16;
247
20.7k
      s->refinement_bits_count_ += 16;
248
20.7k
    }
249
260k
    if (new_bits_count) {
250
92.4k
      s->refinement_bits_.push_back(new_bits & ((1u << new_bits_count) - 1));
251
92.4k
      s->refinement_bits_count_ += new_bits_count;
252
92.4k
    }
253
260k
  }
254
  // At most we buffer at most ~258041 bytes; that is less than we have reserved
255
  // before; still, let's make sure we don't use more memory ever.
256
69.8M
  if (s->refinement_bits_count_ > 0x7FFF * (kDCTBlockSize - 1)) {
257
0
    return false;
258
0
  }
259
69.8M
  if (s->eob_run_ == 0x7FFF) {
260
1.41k
    Flush(s, bw);
261
1.41k
  }
262
69.8M
  return true;
263
69.8M
}
264
265
bool BuildHuffmanCodeTable(const JPEGHuffmanCode& huff,
266
24.4k
                           HuffmanCodeTable* table) {
267
24.4k
  int huff_code[kJpegHuffmanAlphabetSize];
268
  // +1 for a sentinel element.
269
24.4k
  uint32_t huff_size[kJpegHuffmanAlphabetSize + 1];
270
24.4k
  int p = 0;
271
415k
  for (size_t l = 1; l <= kJpegHuffmanMaxBitLength; ++l) {
272
390k
    int i = huff.counts[l];
273
390k
    if (p + i > kJpegHuffmanAlphabetSize + 1) {
274
0
      return false;
275
0
    }
276
2.19M
    while (i--) huff_size[p++] = static_cast<uint32_t>(l);
277
390k
  }
278
279
24.4k
  if (p == 0) {
280
0
    return true;
281
0
  }
282
283
  // Reuse sentinel element.
284
24.4k
  int last_p = p - 1;
285
24.4k
  huff_size[last_p] = 0;
286
287
24.4k
  int code = 0;
288
24.4k
  uint32_t si = huff_size[0];
289
24.4k
  p = 0;
290
244k
  while (huff_size[p]) {
291
1.99M
    while ((huff_size[p]) == si) {
292
1.77M
      huff_code[p++] = code;
293
1.77M
      code++;
294
1.77M
    }
295
220k
    code <<= 1;
296
220k
    si++;
297
220k
  }
298
1.80M
  for (p = 0; p < last_p; p++) {
299
1.77M
    int i = huff.values[p];
300
1.77M
    table->depth[i] = huff_size[p];
301
1.77M
    table->code[i] = huff_code[p];
302
1.77M
  }
303
24.4k
  return true;
304
24.4k
}
305
306
9.24k
bool EncodeSOI(SerializationState* state) {
307
9.24k
  state->output_queue.push_back(OutputChunk({0xFF, 0xD8}));
308
9.24k
  return true;
309
9.24k
}
310
311
754
bool EncodeEOI(const JPEGData& jpg, SerializationState* state) {
312
754
  state->output_queue.push_back(OutputChunk({0xFF, 0xD9}));
313
754
  state->output_queue.emplace_back(jpg.tail_data);
314
754
  return true;
315
754
}
316
317
25.3k
bool EncodeSOF(const JPEGData& jpg, uint8_t marker, SerializationState* state) {
318
25.3k
  if (marker <= 0xC2) state->is_progressive = (marker == 0xC2);
319
320
25.3k
  const size_t n_comps = jpg.components.size();
321
25.3k
  const size_t marker_len = 8 + 3 * n_comps;
322
25.3k
  state->output_queue.emplace_back(marker_len + 2);
323
25.3k
  uint8_t* data = state->output_queue.back().buffer->data();
324
25.3k
  size_t pos = 0;
325
25.3k
  data[pos++] = 0xFFu;
326
25.3k
  data[pos++] = marker;
327
25.3k
  data[pos++] = static_cast<uint8_t>(marker_len >> 8u);
328
25.3k
  data[pos++] = static_cast<uint8_t>(marker_len);
329
25.3k
  data[pos++] = kJpegPrecision;
330
25.3k
  data[pos++] = jpg.height >> 8u;
331
25.3k
  data[pos++] = jpg.height & 0xFFu;
332
25.3k
  data[pos++] = jpg.width >> 8u;
333
25.3k
  data[pos++] = jpg.width & 0xFFu;
334
25.3k
  data[pos++] = static_cast<uint8_t>(n_comps);
335
51.1k
  for (size_t i = 0; i < n_comps; ++i) {
336
25.7k
    data[pos++] = jpg.components[i].id;
337
25.7k
    data[pos++] = ((jpg.components[i].h_samp_factor << 4u) |
338
25.7k
                   (jpg.components[i].v_samp_factor));
339
25.7k
    const size_t quant_idx = jpg.components[i].quant_idx;
340
25.7k
    if (quant_idx >= jpg.quant.size()) return false;
341
25.7k
    data[pos++] = jpg.quant[quant_idx].index;
342
25.7k
  }
343
25.3k
  return true;
344
25.3k
}
345
346
bool EncodeSOS(const JPEGData& jpg, const JPEGScanInfo& scan_info,
347
10.0k
               SerializationState* state) {
348
10.0k
  const size_t n_scans = scan_info.num_components;
349
10.0k
  const size_t marker_len = 6 + 2 * n_scans;
350
10.0k
  state->output_queue.emplace_back(marker_len + 2);
351
10.0k
  uint8_t* data = state->output_queue.back().buffer->data();
352
10.0k
  size_t pos = 0;
353
10.0k
  data[pos++] = 0xFFu;
354
10.0k
  data[pos++] = 0xDAu;
355
10.0k
  data[pos++] = static_cast<uint8_t>(marker_len >> 8u);
356
10.0k
  data[pos++] = static_cast<uint8_t>(marker_len);
357
10.0k
  data[pos++] = static_cast<uint8_t>(n_scans);
358
35.1k
  for (size_t i = 0; i < n_scans; ++i) {
359
25.4k
    const JPEGComponentScanInfo& si = scan_info.components[i];
360
25.4k
    if (si.comp_idx >= jpg.components.size()) return false;
361
25.1k
    data[pos++] = jpg.components[si.comp_idx].id;
362
25.1k
    data[pos++] = (si.dc_tbl_idx << 4u) + si.ac_tbl_idx;
363
25.1k
  }
364
9.77k
  data[pos++] = scan_info.Ss;
365
9.77k
  data[pos++] = scan_info.Se;
366
9.77k
  data[pos++] = ((scan_info.Ah << 4u) | (scan_info.Al));
367
9.77k
  return true;
368
10.0k
}
369
370
9.47k
bool EncodeDHT(const JPEGData& jpg, SerializationState* state) {
371
9.47k
  const std::vector<JPEGHuffmanCode>& huffman_code = jpg.huffman_code;
372
373
9.47k
  size_t marker_len = 2;
374
24.4k
  for (size_t i = state->dht_index; i < huffman_code.size(); ++i) {
375
24.4k
    const JPEGHuffmanCode& huff = huffman_code[i];
376
24.4k
    marker_len += kJpegHuffmanMaxBitLength;
377
439k
    for (size_t j = 0; j < huff.counts.size(); ++j) {
378
415k
      marker_len += huff.counts[j];
379
415k
    }
380
24.4k
    if (huff.is_last) break;
381
24.4k
  }
382
9.47k
  state->output_queue.emplace_back(marker_len + 2);
383
9.47k
  uint8_t* data = state->output_queue.back().buffer->data();
384
9.47k
  size_t pos = 0;
385
9.47k
  data[pos++] = 0xFFu;
386
9.47k
  data[pos++] = 0xC4u;
387
9.47k
  data[pos++] = static_cast<uint8_t>(marker_len >> 8u);
388
9.47k
  data[pos++] = static_cast<uint8_t>(marker_len);
389
24.4k
  while (true) {
390
24.4k
    const size_t huffman_code_index = state->dht_index++;
391
24.4k
    if (huffman_code_index >= huffman_code.size()) {
392
0
      return false;
393
0
    }
394
24.4k
    const JPEGHuffmanCode& huff = huffman_code[huffman_code_index];
395
24.4k
    size_t index = huff.slot_id;
396
24.4k
    HuffmanCodeTable* huff_table;
397
24.4k
    if (index & 0x10) {
398
13.5k
      index -= 0x10;
399
13.5k
      huff_table = &state->ac_huff_table[index];
400
13.5k
    } else {
401
10.8k
      huff_table = &state->dc_huff_table[index];
402
10.8k
    }
403
    // TODO(eustas): cache
404
    // TODO(eustas): set up non-existing symbols
405
24.4k
    if (!BuildHuffmanCodeTable(huff, huff_table)) {
406
0
      return false;
407
0
    }
408
24.4k
    size_t total_count = 0;
409
24.4k
    size_t max_length = 0;
410
439k
    for (size_t i = 0; i < huff.counts.size(); ++i) {
411
415k
      if (huff.counts[i] != 0) {
412
203k
        max_length = i;
413
203k
      }
414
415k
      total_count += huff.counts[i];
415
415k
    }
416
24.4k
    --total_count;
417
24.4k
    data[pos++] = huff.slot_id;
418
415k
    for (size_t i = 1; i <= kJpegHuffmanMaxBitLength; ++i) {
419
390k
      data[pos++] = (i == max_length ? huff.counts[i] - 1 : huff.counts[i]);
420
390k
    }
421
1.80M
    for (size_t i = 0; i < total_count; ++i) {
422
1.77M
      data[pos++] = huff.values[i];
423
1.77M
    }
424
24.4k
    if (huff.is_last) break;
425
24.4k
  }
426
9.47k
  return true;
427
9.47k
}
428
429
745
bool EncodeDQT(const JPEGData& jpg, SerializationState* state) {
430
745
  int marker_len = 2;
431
745
  for (size_t i = state->dqt_index; i < jpg.quant.size(); ++i) {
432
723
    const JPEGQuantTable& table = jpg.quant[i];
433
723
    marker_len += 1 + (table.precision ? 2 : 1) * kDCTBlockSize;
434
723
    if (table.is_last) break;
435
723
  }
436
745
  state->output_queue.emplace_back(marker_len + 2);
437
745
  uint8_t* data = state->output_queue.back().buffer->data();
438
745
  size_t pos = 0;
439
745
  data[pos++] = 0xFF;
440
745
  data[pos++] = 0xDB;
441
745
  data[pos++] = marker_len >> 8u;
442
745
  data[pos++] = marker_len & 0xFFu;
443
745
  while (true) {
444
745
    const size_t idx = state->dqt_index++;
445
745
    if (idx >= jpg.quant.size()) {
446
22
      return false;  // corrupt input
447
22
    }
448
723
    const JPEGQuantTable& table = jpg.quant[idx];
449
723
    data[pos++] = (table.precision << 4u) + table.index;
450
46.9k
    for (size_t i = 0; i < kDCTBlockSize; ++i) {
451
46.2k
      int val_idx = kJPEGNaturalOrder[i];
452
46.2k
      int val = table.values[val_idx];
453
46.2k
      if (table.precision) {
454
12.3k
        data[pos++] = val >> 8u;
455
12.3k
      }
456
46.2k
      data[pos++] = val & 0xFFu;
457
46.2k
    }
458
723
    if (table.is_last) break;
459
723
  }
460
723
  return true;
461
745
}
462
463
3.67k
bool EncodeDRI(const JPEGData& jpg, SerializationState* state) {
464
3.67k
  state->seen_dri_marker = true;
465
3.67k
  OutputChunk dri_marker = {0xFF,
466
3.67k
                            0xDD,
467
3.67k
                            0,
468
3.67k
                            4,
469
3.67k
                            static_cast<uint8_t>(jpg.restart_interval >> 8),
470
3.67k
                            static_cast<uint8_t>(jpg.restart_interval & 0xFF)};
471
3.67k
  state->output_queue.push_back(std::move(dri_marker));
472
3.67k
  return true;
473
3.67k
}
474
475
17.7k
bool EncodeRestart(uint8_t marker, SerializationState* state) {
476
17.7k
  state->output_queue.push_back(OutputChunk({0xFF, marker}));
477
17.7k
  return true;
478
17.7k
}
479
480
453
bool EncodeAPP(const JPEGData& jpg, uint8_t marker, SerializationState* state) {
481
  // TODO(eustas): check that marker corresponds to payload?
482
453
  (void)marker;
483
484
453
  size_t app_index = state->app_index++;
485
453
  if (app_index >= jpg.app_data.size()) return false;
486
37
  state->output_queue.push_back(OutputChunk({0xFF}));
487
37
  state->output_queue.emplace_back(jpg.app_data[app_index]);
488
37
  return true;
489
453
}
490
491
13
bool EncodeCOM(const JPEGData& jpg, SerializationState* state) {
492
13
  size_t com_index = state->com_index++;
493
13
  if (com_index >= jpg.com_data.size()) return false;
494
0
  state->output_queue.push_back(OutputChunk({0xFF}));
495
0
  state->output_queue.emplace_back(jpg.com_data[com_index]);
496
0
  return true;
497
13
}
498
499
53
bool EncodeInterMarkerData(const JPEGData& jpg, SerializationState* state) {
500
53
  size_t index = state->data_index++;
501
53
  if (index >= jpg.inter_marker_data.size()) return false;
502
53
  state->output_queue.emplace_back(jpg.inter_marker_data[index]);
503
53
  return true;
504
53
}
505
506
bool EncodeDCTBlockSequential(const coeff_t* coeffs,
507
                              const HuffmanCodeTable& dc_huff,
508
                              const HuffmanCodeTable& ac_huff,
509
                              int num_zero_runs, coeff_t* last_dc_coeff,
510
7.55M
                              BitWriter* bw) {
511
7.55M
  coeff_t temp2;
512
7.55M
  coeff_t temp;
513
7.55M
  temp2 = coeffs[0];
514
7.55M
  temp = temp2 - *last_dc_coeff;
515
7.55M
  *last_dc_coeff = temp2;
516
7.55M
  temp2 = temp;
517
7.55M
  if (temp < 0) {
518
1.91M
    temp = -temp;
519
1.91M
    temp2--;
520
1.91M
  }
521
7.55M
  int dc_nbits = (temp == 0) ? 0 : (Log2FloorNonZero(temp) + 1);
522
7.55M
  WriteBits(bw, dc_huff.depth[dc_nbits], dc_huff.code[dc_nbits]);
523
7.55M
  if (dc_nbits > 0) {
524
3.75M
    WriteBits(bw, dc_nbits, temp2 & ((1u << dc_nbits) - 1));
525
3.75M
  }
526
7.55M
  int r = 0;
527
483M
  for (int k = 1; k < 64; ++k) {
528
476M
    if ((temp = coeffs[kJPEGNaturalOrder[k]]) == 0) {
529
476M
      r++;
530
476M
      continue;
531
476M
    }
532
71.5k
    if (temp < 0) {
533
45.7k
      temp = -temp;
534
45.7k
      temp2 = ~temp;
535
45.7k
    } else {
536
25.8k
      temp2 = temp;
537
25.8k
    }
538
123k
    while (r > 15) {
539
51.5k
      WriteBits(bw, ac_huff.depth[0xf0], ac_huff.code[0xf0]);
540
51.5k
      r -= 16;
541
51.5k
    }
542
71.5k
    int ac_nbits = Log2FloorNonZero(temp) + 1;
543
71.5k
    int symbol = (r << 4u) + ac_nbits;
544
71.5k
    WriteBits(bw, ac_huff.depth[symbol], ac_huff.code[symbol]);
545
71.5k
    WriteBits(bw, ac_nbits, temp2 & ((1 << ac_nbits) - 1));
546
71.5k
    r = 0;
547
71.5k
  }
548
7.56M
  for (int i = 0; i < num_zero_runs; ++i) {
549
6.57k
    WriteBits(bw, ac_huff.depth[0xf0], ac_huff.code[0xf0]);
550
6.57k
    r -= 16;
551
6.57k
  }
552
7.55M
  if (r > 0) {
553
7.55M
    WriteBits(bw, ac_huff.depth[0], ac_huff.code[0]);
554
7.55M
  }
555
7.55M
  return true;
556
7.55M
}
557
558
bool EncodeDCTBlockProgressive(const coeff_t* coeffs,
559
                               const HuffmanCodeTable& dc_huff,
560
                               const HuffmanCodeTable& ac_huff, int Ss, int Se,
561
                               int Al, int num_zero_runs,
562
                               DCTCodingState* coding_state,
563
18.9M
                               coeff_t* last_dc_coeff, BitWriter* bw) {
564
18.9M
  bool eob_run_allowed = Ss > 0;
565
18.9M
  coeff_t temp2;
566
18.9M
  coeff_t temp;
567
18.9M
  if (Ss == 0) {
568
6.63M
    temp2 = coeffs[0] >> Al;
569
6.63M
    temp = temp2 - *last_dc_coeff;
570
6.63M
    *last_dc_coeff = temp2;
571
6.63M
    temp2 = temp;
572
6.63M
    if (temp < 0) {
573
1.67M
      temp = -temp;
574
1.67M
      temp2--;
575
1.67M
    }
576
6.63M
    int nbits = (temp == 0) ? 0 : (Log2FloorNonZero(temp) + 1);
577
6.63M
    WriteBits(bw, dc_huff.depth[nbits], dc_huff.code[nbits]);
578
6.63M
    if (nbits > 0) {
579
3.37M
      WriteBits(bw, nbits, temp2 & ((1 << nbits) - 1));
580
3.37M
    }
581
6.63M
    ++Ss;
582
6.63M
  }
583
18.9M
  if (Ss > Se) {
584
844k
    return true;
585
844k
  }
586
18.0M
  int r = 0;
587
494M
  for (int k = Ss; k <= Se; ++k) {
588
476M
    if ((temp = coeffs[kJPEGNaturalOrder[k]]) == 0) {
589
476M
      r++;
590
476M
      continue;
591
476M
    }
592
107k
    if (temp < 0) {
593
77.0k
      temp = -temp;
594
77.0k
      temp >>= Al;
595
77.0k
      temp2 = ~temp;
596
77.0k
    } else {
597
30.0k
      temp >>= Al;
598
30.0k
      temp2 = temp;
599
30.0k
    }
600
107k
    if (temp == 0) {
601
4.03k
      r++;
602
4.03k
      continue;
603
4.03k
    }
604
103k
    Flush(coding_state, bw);
605
170k
    while (r > 15) {
606
67.7k
      WriteBits(bw, ac_huff.depth[0xf0], ac_huff.code[0xf0]);
607
67.7k
      r -= 16;
608
67.7k
    }
609
103k
    int nbits = Log2FloorNonZero(temp) + 1;
610
103k
    int symbol = (r << 4u) + nbits;
611
103k
    WriteBits(bw, ac_huff.depth[symbol], ac_huff.code[symbol]);
612
103k
    WriteBits(bw, nbits, temp2 & ((1 << nbits) - 1));
613
103k
    r = 0;
614
103k
  }
615
18.0M
  if (num_zero_runs > 0) {
616
8.73k
    Flush(coding_state, bw);
617
23.6k
    for (int i = 0; i < num_zero_runs; ++i) {
618
14.8k
      WriteBits(bw, ac_huff.depth[0xf0], ac_huff.code[0xf0]);
619
14.8k
      r -= 16;
620
14.8k
    }
621
8.73k
  }
622
18.0M
  if (r > 0) {
623
    // Ignore result: since we do not buffer bits - it can not fail.
624
18.0M
    BufferEndOfBand(coding_state, &ac_huff, nullptr, 0, bw);
625
18.0M
    if (!eob_run_allowed) {
626
6.18M
      Flush(coding_state, bw);
627
6.18M
    }
628
18.0M
  }
629
18.0M
  return true;
630
18.9M
}
631
632
bool EncodeRefinementBits(const coeff_t* coeffs,
633
                          const HuffmanCodeTable& ac_huff, int Ss, int Se,
634
52.1M
                          int Al, DCTCodingState* coding_state, BitWriter* bw) {
635
52.1M
  bool eob_run_allowed = Ss > 0;
636
52.1M
  if (Ss == 0) {
637
    // Emit next bit of DC component.
638
6.98M
    WriteBits(bw, 1, (coeffs[0] >> Al) & 1);
639
6.98M
    ++Ss;
640
6.98M
  }
641
52.1M
  if (Ss > Se) {
642
449k
    return true;
643
449k
  }
644
51.7M
  int abs_values[kDCTBlockSize];
645
51.7M
  int eob = 0;
646
1.33G
  for (int k = Ss; k <= Se; k++) {
647
1.28G
    const coeff_t abs_val = std::abs(coeffs[kJPEGNaturalOrder[k]]);
648
1.28G
    abs_values[k] = abs_val >> Al;
649
1.28G
    if (abs_values[k] == 1) {
650
186k
      eob = k;
651
186k
    }
652
1.28G
  }
653
51.7M
  int r = 0;
654
51.7M
  int refinement_bits[kDCTBlockSize];
655
51.7M
  size_t refinement_bits_count = 0;
656
1.33G
  for (int k = Ss; k <= Se; k++) {
657
1.28G
    if (abs_values[k] == 0) {
658
1.28G
      r++;
659
1.28G
      continue;
660
1.28G
    }
661
1.46M
    while (r > 15 && k <= eob) {
662
108k
      Flush(coding_state, bw);
663
108k
      WriteBits(bw, ac_huff.depth[0xf0], ac_huff.code[0xf0]);
664
108k
      r -= 16;
665
127k
      for (size_t i = 0; i < refinement_bits_count; ++i) {
666
18.7k
        WriteBits(bw, 1, refinement_bits[i]);
667
18.7k
      }
668
108k
      refinement_bits_count = 0;
669
108k
    }
670
1.35M
    if (abs_values[k] > 1) {
671
1.16M
      refinement_bits[refinement_bits_count++] = abs_values[k] & 1u;
672
1.16M
      continue;
673
1.16M
    }
674
186k
    Flush(coding_state, bw);
675
186k
    int symbol = (r << 4u) + 1;
676
186k
    int new_non_zero_bit = (coeffs[kJPEGNaturalOrder[k]] < 0) ? 0 : 1;
677
186k
    WriteBits(bw, ac_huff.depth[symbol], ac_huff.code[symbol]);
678
186k
    WriteBits(bw, 1, new_non_zero_bit);
679
225k
    for (size_t i = 0; i < refinement_bits_count; ++i) {
680
38.7k
      WriteBits(bw, 1, refinement_bits[i]);
681
38.7k
    }
682
186k
    refinement_bits_count = 0;
683
186k
    r = 0;
684
186k
  }
685
51.7M
  if (r > 0 || refinement_bits_count) {
686
51.7M
    if (!BufferEndOfBand(coding_state, &ac_huff, refinement_bits,
687
51.7M
                         refinement_bits_count, bw)) {
688
0
      return false;
689
0
    }
690
51.7M
    if (!eob_run_allowed) {
691
6.84M
      Flush(coding_state, bw);
692
6.84M
    }
693
51.7M
  }
694
51.7M
  return true;
695
51.7M
}
696
697
template <int kMode>
698
SerializationStatus BRUNSLI_NOINLINE DoEncodeScan(const JPEGData& jpg,
699
                                                  const State& parsing_state,
700
10.0k
                                                  SerializationState* state) {
701
10.0k
  const JPEGScanInfo& scan_info = jpg.scan_info[state->scan_index];
702
10.0k
  EncodeScanState& ss = state->scan_state;
703
704
10.0k
  const int restart_interval =
705
10.0k
      state->seen_dri_marker ? jpg.restart_interval : 0;
706
707
22.7k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
22.7k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
13.0k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
13.0k
    } else {
711
9.66k
      return -1;
712
9.66k
    }
713
22.7k
  };
jpeg_data_writer.cc:brunsli::(anonymous namespace)::DoEncodeScan<0>(brunsli::JPEGData const&, brunsli::internal::dec::State const&, brunsli::internal::dec::SerializationState*)::{lambda()#1}::operator()() const
Line
Count
Source
707
3.69k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
3.69k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
2.18k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
2.18k
    } else {
711
1.50k
      return -1;
712
1.50k
    }
713
3.69k
  };
jpeg_data_writer.cc:brunsli::(anonymous namespace)::DoEncodeScan<1>(brunsli::JPEGData const&, brunsli::internal::dec::State const&, brunsli::internal::dec::SerializationState*)::{lambda()#1}::operator()() const
Line
Count
Source
707
11.8k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
11.8k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
8.87k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
8.87k
    } else {
711
3.01k
      return -1;
712
3.01k
    }
713
11.8k
  };
jpeg_data_writer.cc:brunsli::(anonymous namespace)::DoEncodeScan<2>(brunsli::JPEGData const&, brunsli::internal::dec::State const&, brunsli::internal::dec::SerializationState*)::{lambda()#1}::operator()() const
Line
Count
Source
707
7.11k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
7.11k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
1.97k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
5.13k
    } else {
711
5.13k
      return -1;
712
5.13k
    }
713
7.11k
  };
714
715
38.3k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
38.3k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
28.7k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
28.7k
    } else {
719
9.59k
      return -1;
720
9.59k
    }
721
38.3k
  };
jpeg_data_writer.cc:brunsli::(anonymous namespace)::DoEncodeScan<0>(brunsli::JPEGData const&, brunsli::internal::dec::State const&, brunsli::internal::dec::SerializationState*)::{lambda()#2}::operator()() const
Line
Count
Source
715
2.87k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
2.87k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
1.36k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
1.50k
    } else {
719
1.50k
      return -1;
720
1.50k
    }
721
2.87k
  };
jpeg_data_writer.cc:brunsli::(anonymous namespace)::DoEncodeScan<1>(brunsli::JPEGData const&, brunsli::internal::dec::State const&, brunsli::internal::dec::SerializationState*)::{lambda()#2}::operator()() const
Line
Count
Source
715
12.6k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
12.6k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
9.68k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
9.68k
    } else {
719
3.01k
      return -1;
720
3.01k
    }
721
12.6k
  };
jpeg_data_writer.cc:brunsli::(anonymous namespace)::DoEncodeScan<2>(brunsli::JPEGData const&, brunsli::internal::dec::State const&, brunsli::internal::dec::SerializationState*)::{lambda()#2}::operator()() const
Line
Count
Source
715
22.7k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
22.7k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
17.6k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
17.6k
    } else {
719
5.08k
      return -1;
720
5.08k
    }
721
22.7k
  };
722
723
10.0k
  if (ss.stage == EncodeScanState::HEAD) {
724
10.0k
    if (!EncodeSOS(jpg, scan_info, state)) return SerializationStatus::ERROR;
725
9.77k
    BitWriterInit(&ss.bw, &state->output_queue);
726
9.77k
    DCTCodingStateInit(&ss.coding_state);
727
9.77k
    ss.restarts_to_go = restart_interval;
728
9.77k
    ss.next_restart_marker = 0;
729
9.77k
    ss.block_scan_index = 0;
730
9.77k
    ss.extra_zero_runs_pos = 0;
731
9.77k
    ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
732
9.77k
    ss.next_reset_point_pos = 0;
733
9.77k
    ss.next_reset_point = get_next_reset_point();
734
9.77k
    ss.mcu_y = 0;
735
9.77k
    memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
736
9.77k
    ss.stage = EncodeScanState::BODY;
737
9.77k
  }
738
9.77k
  BitWriter* bw = &ss.bw;
739
9.77k
  DCTCodingState* coding_state = &ss.coding_state;
740
741
9.77k
  BRUNSLI_DCHECK(ss.stage == EncodeScanState::BODY);
742
743
  // "Non-interleaved" means color data comes in separate scans, in other words
744
  // each scan can contain only one color component.
745
9.77k
  const bool is_interleaved = (scan_info.num_components > 1);
746
9.77k
  const JPEGComponent& base_component =
747
9.77k
      jpg.components[scan_info.components[0].comp_idx];
748
  // h_group / v_group act as numerators for converting number of blocks to
749
  // number of MCU. In interleaved mode it is 1, so MCU is represented with
750
  // max_*_samp_factor blocks. In non-interleaved mode we choose numerator to
751
  // be the samping factor, consequently MCU is always represented with single
752
  // block.
753
9.77k
  const int h_group = is_interleaved ? 1 : base_component.h_samp_factor;
754
9.77k
  const int v_group = is_interleaved ? 1 : base_component.v_samp_factor;
755
9.77k
  const int MCUs_per_row =
756
9.77k
      DivCeil(jpg.width * h_group, 8 * jpg.max_h_samp_factor);
757
9.77k
  const int MCU_rows = DivCeil(jpg.height * v_group, 8 * jpg.max_v_samp_factor);
758
9.77k
  const bool is_progressive = state->is_progressive;
759
9.77k
  const int Al = is_progressive ? scan_info.Al : 0;
760
9.77k
  const int Ss = is_progressive ? scan_info.Ss : 0;
761
9.77k
  const int Se = is_progressive ? scan_info.Se : 63;
762
763
  // DC-only is defined by [0..0] spectral range.
764
9.77k
  const bool want_ac = ((Ss != 0) || (Se != 0));
765
9.77k
  const bool complete_ac = (parsing_state.stage == Stage::DONE);
766
9.77k
  const bool has_ac =
767
9.77k
      complete_ac || HasSection(&parsing_state, kBrunsliACDataTag);
768
9.77k
  if (want_ac && !has_ac) return SerializationStatus::NEEDS_MORE_INPUT;
769
770
  // |has_ac| implies |complete_dc| but not vice versa; for the sake of
771
  // simplicity we pretend they are equal, because they are separated by just a
772
  // few bytes of input.
773
9.77k
  const bool complete_dc = has_ac;
774
9.77k
  const bool complete = want_ac ? complete_ac : complete_dc;
775
  // When "incomplete" |ac_dc| tracks information about current ("incomplete")
776
  // band parsing progress.
777
9.77k
  const int last_mcu_y =
778
9.77k
      complete ? MCU_rows : parsing_state.internal->ac_dc.next_mcu_y * v_group;
779
780
389k
  for (; ss.mcu_y < last_mcu_y; ++ss.mcu_y) {
781
3.40M
    for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
782
      // Possibly emit a restart marker.
783
3.02M
      if (restart_interval > 0 && ss.restarts_to_go == 0) {
784
512k
        Flush(coding_state, bw);
785
512k
        if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
786
51
          return SerializationStatus::ERROR;
787
51
        }
788
512k
        EmitMarker(bw, 0xD0 + ss.next_restart_marker);
789
512k
        ss.next_restart_marker += 1;
790
512k
        ss.next_restart_marker &= 0x7;
791
512k
        ss.restarts_to_go = restart_interval;
792
512k
        memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
793
512k
      }
794
      // Encode one MCU
795
9.44M
      for (size_t i = 0; i < scan_info.num_components; ++i) {
796
6.41M
        const JPEGComponentScanInfo& si = scan_info.components[i];
797
6.41M
        const JPEGComponent& c = jpg.components[si.comp_idx];
798
6.41M
        const HuffmanCodeTable& dc_huff = state->dc_huff_table[si.dc_tbl_idx];
799
6.41M
        const HuffmanCodeTable& ac_huff = state->ac_huff_table[si.ac_tbl_idx];
800
6.41M
        int n_blocks_y = is_interleaved ? c.v_samp_factor : 1;
801
6.41M
        int n_blocks_x = is_interleaved ? c.h_samp_factor : 1;
802
32.0M
        for (int iy = 0; iy < n_blocks_y; ++iy) {
803
104M
          for (int ix = 0; ix < n_blocks_x; ++ix) {
804
78.6M
            int block_y = ss.mcu_y * n_blocks_y + iy;
805
78.6M
            int block_x = mcu_x * n_blocks_x + ix;
806
78.6M
            int block_idx = block_y * c.width_in_blocks + block_x;
807
78.6M
            if (ss.block_scan_index == ss.next_reset_point) {
808
28.5k
              Flush(coding_state, bw);
809
28.5k
              ss.next_reset_point = get_next_reset_point();
810
28.5k
            }
811
78.6M
            int num_zero_runs = 0;
812
78.6M
            if (ss.block_scan_index == ss.next_extra_zero_run_index) {
813
12.9k
              num_zero_runs = scan_info.extra_zero_runs[ss.extra_zero_runs_pos]
814
12.9k
                                  .num_extra_zero_runs;
815
12.9k
              ++ss.extra_zero_runs_pos;
816
12.9k
              ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
817
12.9k
            }
818
78.6M
            const coeff_t* coeffs = &c.coeffs[block_idx << 6];
819
78.6M
            bool ok;
820
78.6M
            if (kMode == 0) {
821
7.55M
              ok = EncodeDCTBlockSequential(coeffs, dc_huff, ac_huff,
822
7.55M
                                            num_zero_runs,
823
7.55M
                                            ss.last_dc_coeff + si.comp_idx, bw);
824
71.1M
            } else if (kMode == 1) {
825
18.9M
              ok = EncodeDCTBlockProgressive(
826
18.9M
                  coeffs, dc_huff, ac_huff, Ss, Se, Al, num_zero_runs,
827
18.9M
                  coding_state, ss.last_dc_coeff + si.comp_idx, bw);
828
52.1M
            } else {
829
52.1M
              ok = EncodeRefinementBits(coeffs, ac_huff, Ss, Se, Al,
830
52.1M
                                        coding_state, bw);
831
52.1M
            }
832
78.6M
            if (!ok) return SerializationStatus::ERROR;
833
78.6M
            ++ss.block_scan_index;
834
78.6M
          }
835
25.6M
        }
836
6.41M
      }
837
3.02M
      --ss.restarts_to_go;
838
3.02M
    }
839
379k
  }
840
9.72k
  if (ss.mcu_y < MCU_rows) {
841
0
    if (!bw->healthy) return SerializationStatus::ERROR;
842
0
    return SerializationStatus::NEEDS_MORE_INPUT;
843
0
  }
844
9.72k
  Flush(coding_state, bw);
845
9.72k
  if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
846
64
    return SerializationStatus::ERROR;
847
64
  }
848
9.65k
  BitWriterFinish(bw);
849
9.65k
  ss.stage = EncodeScanState::HEAD;
850
9.65k
  state->scan_index++;
851
9.65k
  if (!bw->healthy) return SerializationStatus::ERROR;
852
853
2.24k
  return SerializationStatus::DONE;
854
9.65k
}
jpeg_data_writer.cc:brunsli::internal::dec::SerializationStatus brunsli::(anonymous namespace)::DoEncodeScan<0>(brunsli::JPEGData const&, brunsli::internal::dec::State const&, brunsli::internal::dec::SerializationState*)
Line
Count
Source
700
1.60k
                                                  SerializationState* state) {
701
1.60k
  const JPEGScanInfo& scan_info = jpg.scan_info[state->scan_index];
702
1.60k
  EncodeScanState& ss = state->scan_state;
703
704
1.60k
  const int restart_interval =
705
1.60k
      state->seen_dri_marker ? jpg.restart_interval : 0;
706
707
1.60k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
1.60k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
1.60k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
1.60k
    } else {
711
1.60k
      return -1;
712
1.60k
    }
713
1.60k
  };
714
715
1.60k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
1.60k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
1.60k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
1.60k
    } else {
719
1.60k
      return -1;
720
1.60k
    }
721
1.60k
  };
722
723
1.60k
  if (ss.stage == EncodeScanState::HEAD) {
724
1.60k
    if (!EncodeSOS(jpg, scan_info, state)) return SerializationStatus::ERROR;
725
1.51k
    BitWriterInit(&ss.bw, &state->output_queue);
726
1.51k
    DCTCodingStateInit(&ss.coding_state);
727
1.51k
    ss.restarts_to_go = restart_interval;
728
1.51k
    ss.next_restart_marker = 0;
729
1.51k
    ss.block_scan_index = 0;
730
1.51k
    ss.extra_zero_runs_pos = 0;
731
1.51k
    ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
732
1.51k
    ss.next_reset_point_pos = 0;
733
1.51k
    ss.next_reset_point = get_next_reset_point();
734
1.51k
    ss.mcu_y = 0;
735
1.51k
    memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
736
1.51k
    ss.stage = EncodeScanState::BODY;
737
1.51k
  }
738
1.51k
  BitWriter* bw = &ss.bw;
739
1.51k
  DCTCodingState* coding_state = &ss.coding_state;
740
741
1.51k
  BRUNSLI_DCHECK(ss.stage == EncodeScanState::BODY);
742
743
  // "Non-interleaved" means color data comes in separate scans, in other words
744
  // each scan can contain only one color component.
745
1.51k
  const bool is_interleaved = (scan_info.num_components > 1);
746
1.51k
  const JPEGComponent& base_component =
747
1.51k
      jpg.components[scan_info.components[0].comp_idx];
748
  // h_group / v_group act as numerators for converting number of blocks to
749
  // number of MCU. In interleaved mode it is 1, so MCU is represented with
750
  // max_*_samp_factor blocks. In non-interleaved mode we choose numerator to
751
  // be the samping factor, consequently MCU is always represented with single
752
  // block.
753
1.51k
  const int h_group = is_interleaved ? 1 : base_component.h_samp_factor;
754
1.51k
  const int v_group = is_interleaved ? 1 : base_component.v_samp_factor;
755
1.51k
  const int MCUs_per_row =
756
1.51k
      DivCeil(jpg.width * h_group, 8 * jpg.max_h_samp_factor);
757
1.51k
  const int MCU_rows = DivCeil(jpg.height * v_group, 8 * jpg.max_v_samp_factor);
758
1.51k
  const bool is_progressive = state->is_progressive;
759
1.51k
  const int Al = is_progressive ? scan_info.Al : 0;
760
1.51k
  const int Ss = is_progressive ? scan_info.Ss : 0;
761
1.51k
  const int Se = is_progressive ? scan_info.Se : 63;
762
763
  // DC-only is defined by [0..0] spectral range.
764
1.51k
  const bool want_ac = ((Ss != 0) || (Se != 0));
765
1.51k
  const bool complete_ac = (parsing_state.stage == Stage::DONE);
766
1.51k
  const bool has_ac =
767
1.51k
      complete_ac || HasSection(&parsing_state, kBrunsliACDataTag);
768
1.51k
  if (want_ac && !has_ac) return SerializationStatus::NEEDS_MORE_INPUT;
769
770
  // |has_ac| implies |complete_dc| but not vice versa; for the sake of
771
  // simplicity we pretend they are equal, because they are separated by just a
772
  // few bytes of input.
773
1.51k
  const bool complete_dc = has_ac;
774
1.51k
  const bool complete = want_ac ? complete_ac : complete_dc;
775
  // When "incomplete" |ac_dc| tracks information about current ("incomplete")
776
  // band parsing progress.
777
1.51k
  const int last_mcu_y =
778
1.51k
      complete ? MCU_rows : parsing_state.internal->ac_dc.next_mcu_y * v_group;
779
780
123k
  for (; ss.mcu_y < last_mcu_y; ++ss.mcu_y) {
781
796k
    for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
782
      // Possibly emit a restart marker.
783
674k
      if (restart_interval > 0 && ss.restarts_to_go == 0) {
784
190k
        Flush(coding_state, bw);
785
190k
        if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
786
22
          return SerializationStatus::ERROR;
787
22
        }
788
190k
        EmitMarker(bw, 0xD0 + ss.next_restart_marker);
789
190k
        ss.next_restart_marker += 1;
790
190k
        ss.next_restart_marker &= 0x7;
791
190k
        ss.restarts_to_go = restart_interval;
792
190k
        memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
793
190k
      }
794
      // Encode one MCU
795
2.06M
      for (size_t i = 0; i < scan_info.num_components; ++i) {
796
1.38M
        const JPEGComponentScanInfo& si = scan_info.components[i];
797
1.38M
        const JPEGComponent& c = jpg.components[si.comp_idx];
798
1.38M
        const HuffmanCodeTable& dc_huff = state->dc_huff_table[si.dc_tbl_idx];
799
1.38M
        const HuffmanCodeTable& ac_huff = state->ac_huff_table[si.ac_tbl_idx];
800
1.38M
        int n_blocks_y = is_interleaved ? c.v_samp_factor : 1;
801
1.38M
        int n_blocks_x = is_interleaved ? c.h_samp_factor : 1;
802
4.68M
        for (int iy = 0; iy < n_blocks_y; ++iy) {
803
10.8M
          for (int ix = 0; ix < n_blocks_x; ++ix) {
804
7.55M
            int block_y = ss.mcu_y * n_blocks_y + iy;
805
7.55M
            int block_x = mcu_x * n_blocks_x + ix;
806
7.55M
            int block_idx = block_y * c.width_in_blocks + block_x;
807
7.55M
            if (ss.block_scan_index == ss.next_reset_point) {
808
1.35k
              Flush(coding_state, bw);
809
1.35k
              ss.next_reset_point = get_next_reset_point();
810
1.35k
            }
811
7.55M
            int num_zero_runs = 0;
812
7.55M
            if (ss.block_scan_index == ss.next_extra_zero_run_index) {
813
2.17k
              num_zero_runs = scan_info.extra_zero_runs[ss.extra_zero_runs_pos]
814
2.17k
                                  .num_extra_zero_runs;
815
2.17k
              ++ss.extra_zero_runs_pos;
816
2.17k
              ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
817
2.17k
            }
818
7.55M
            const coeff_t* coeffs = &c.coeffs[block_idx << 6];
819
7.55M
            bool ok;
820
7.55M
            if (kMode == 0) {
821
7.55M
              ok = EncodeDCTBlockSequential(coeffs, dc_huff, ac_huff,
822
7.55M
                                            num_zero_runs,
823
7.55M
                                            ss.last_dc_coeff + si.comp_idx, bw);
824
7.55M
            } else if (kMode == 1) {
825
0
              ok = EncodeDCTBlockProgressive(
826
0
                  coeffs, dc_huff, ac_huff, Ss, Se, Al, num_zero_runs,
827
0
                  coding_state, ss.last_dc_coeff + si.comp_idx, bw);
828
0
            } else {
829
0
              ok = EncodeRefinementBits(coeffs, ac_huff, Ss, Se, Al,
830
0
                                        coding_state, bw);
831
0
            }
832
7.55M
            if (!ok) return SerializationStatus::ERROR;
833
7.55M
            ++ss.block_scan_index;
834
7.55M
          }
835
3.29M
        }
836
1.38M
      }
837
674k
      --ss.restarts_to_go;
838
674k
    }
839
121k
  }
840
1.49k
  if (ss.mcu_y < MCU_rows) {
841
0
    if (!bw->healthy) return SerializationStatus::ERROR;
842
0
    return SerializationStatus::NEEDS_MORE_INPUT;
843
0
  }
844
1.49k
  Flush(coding_state, bw);
845
1.49k
  if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
846
25
    return SerializationStatus::ERROR;
847
25
  }
848
1.47k
  BitWriterFinish(bw);
849
1.47k
  ss.stage = EncodeScanState::HEAD;
850
1.47k
  state->scan_index++;
851
1.47k
  if (!bw->healthy) return SerializationStatus::ERROR;
852
853
306
  return SerializationStatus::DONE;
854
1.47k
}
jpeg_data_writer.cc:brunsli::internal::dec::SerializationStatus brunsli::(anonymous namespace)::DoEncodeScan<1>(brunsli::JPEGData const&, brunsli::internal::dec::State const&, brunsli::internal::dec::SerializationState*)
Line
Count
Source
700
3.11k
                                                  SerializationState* state) {
701
3.11k
  const JPEGScanInfo& scan_info = jpg.scan_info[state->scan_index];
702
3.11k
  EncodeScanState& ss = state->scan_state;
703
704
3.11k
  const int restart_interval =
705
3.11k
      state->seen_dri_marker ? jpg.restart_interval : 0;
706
707
3.11k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
3.11k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
3.11k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
3.11k
    } else {
711
3.11k
      return -1;
712
3.11k
    }
713
3.11k
  };
714
715
3.11k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
3.11k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
3.11k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
3.11k
    } else {
719
3.11k
      return -1;
720
3.11k
    }
721
3.11k
  };
722
723
3.11k
  if (ss.stage == EncodeScanState::HEAD) {
724
3.11k
    if (!EncodeSOS(jpg, scan_info, state)) return SerializationStatus::ERROR;
725
3.08k
    BitWriterInit(&ss.bw, &state->output_queue);
726
3.08k
    DCTCodingStateInit(&ss.coding_state);
727
3.08k
    ss.restarts_to_go = restart_interval;
728
3.08k
    ss.next_restart_marker = 0;
729
3.08k
    ss.block_scan_index = 0;
730
3.08k
    ss.extra_zero_runs_pos = 0;
731
3.08k
    ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
732
3.08k
    ss.next_reset_point_pos = 0;
733
3.08k
    ss.next_reset_point = get_next_reset_point();
734
3.08k
    ss.mcu_y = 0;
735
3.08k
    memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
736
3.08k
    ss.stage = EncodeScanState::BODY;
737
3.08k
  }
738
3.08k
  BitWriter* bw = &ss.bw;
739
3.08k
  DCTCodingState* coding_state = &ss.coding_state;
740
741
3.08k
  BRUNSLI_DCHECK(ss.stage == EncodeScanState::BODY);
742
743
  // "Non-interleaved" means color data comes in separate scans, in other words
744
  // each scan can contain only one color component.
745
3.08k
  const bool is_interleaved = (scan_info.num_components > 1);
746
3.08k
  const JPEGComponent& base_component =
747
3.08k
      jpg.components[scan_info.components[0].comp_idx];
748
  // h_group / v_group act as numerators for converting number of blocks to
749
  // number of MCU. In interleaved mode it is 1, so MCU is represented with
750
  // max_*_samp_factor blocks. In non-interleaved mode we choose numerator to
751
  // be the samping factor, consequently MCU is always represented with single
752
  // block.
753
3.08k
  const int h_group = is_interleaved ? 1 : base_component.h_samp_factor;
754
3.08k
  const int v_group = is_interleaved ? 1 : base_component.v_samp_factor;
755
3.08k
  const int MCUs_per_row =
756
3.08k
      DivCeil(jpg.width * h_group, 8 * jpg.max_h_samp_factor);
757
3.08k
  const int MCU_rows = DivCeil(jpg.height * v_group, 8 * jpg.max_v_samp_factor);
758
3.08k
  const bool is_progressive = state->is_progressive;
759
3.08k
  const int Al = is_progressive ? scan_info.Al : 0;
760
3.08k
  const int Ss = is_progressive ? scan_info.Ss : 0;
761
3.08k
  const int Se = is_progressive ? scan_info.Se : 63;
762
763
  // DC-only is defined by [0..0] spectral range.
764
3.08k
  const bool want_ac = ((Ss != 0) || (Se != 0));
765
3.08k
  const bool complete_ac = (parsing_state.stage == Stage::DONE);
766
3.08k
  const bool has_ac =
767
3.08k
      complete_ac || HasSection(&parsing_state, kBrunsliACDataTag);
768
3.08k
  if (want_ac && !has_ac) return SerializationStatus::NEEDS_MORE_INPUT;
769
770
  // |has_ac| implies |complete_dc| but not vice versa; for the sake of
771
  // simplicity we pretend they are equal, because they are separated by just a
772
  // few bytes of input.
773
3.08k
  const bool complete_dc = has_ac;
774
3.08k
  const bool complete = want_ac ? complete_ac : complete_dc;
775
  // When "incomplete" |ac_dc| tracks information about current ("incomplete")
776
  // band parsing progress.
777
3.08k
  const int last_mcu_y =
778
3.08k
      complete ? MCU_rows : parsing_state.internal->ac_dc.next_mcu_y * v_group;
779
780
135k
  for (; ss.mcu_y < last_mcu_y; ++ss.mcu_y) {
781
1.02M
    for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
782
      // Possibly emit a restart marker.
783
889k
      if (restart_interval > 0 && ss.restarts_to_go == 0) {
784
160k
        Flush(coding_state, bw);
785
160k
        if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
786
14
          return SerializationStatus::ERROR;
787
14
        }
788
160k
        EmitMarker(bw, 0xD0 + ss.next_restart_marker);
789
160k
        ss.next_restart_marker += 1;
790
160k
        ss.next_restart_marker &= 0x7;
791
160k
        ss.restarts_to_go = restart_interval;
792
160k
        memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
793
160k
      }
794
      // Encode one MCU
795
2.83M
      for (size_t i = 0; i < scan_info.num_components; ++i) {
796
1.94M
        const JPEGComponentScanInfo& si = scan_info.components[i];
797
1.94M
        const JPEGComponent& c = jpg.components[si.comp_idx];
798
1.94M
        const HuffmanCodeTable& dc_huff = state->dc_huff_table[si.dc_tbl_idx];
799
1.94M
        const HuffmanCodeTable& ac_huff = state->ac_huff_table[si.ac_tbl_idx];
800
1.94M
        int n_blocks_y = is_interleaved ? c.v_samp_factor : 1;
801
1.94M
        int n_blocks_x = is_interleaved ? c.h_samp_factor : 1;
802
8.39M
        for (int iy = 0; iy < n_blocks_y; ++iy) {
803
25.3M
          for (int ix = 0; ix < n_blocks_x; ++ix) {
804
18.9M
            int block_y = ss.mcu_y * n_blocks_y + iy;
805
18.9M
            int block_x = mcu_x * n_blocks_x + ix;
806
18.9M
            int block_idx = block_y * c.width_in_blocks + block_x;
807
18.9M
            if (ss.block_scan_index == ss.next_reset_point) {
808
9.61k
              Flush(coding_state, bw);
809
9.61k
              ss.next_reset_point = get_next_reset_point();
810
9.61k
            }
811
18.9M
            int num_zero_runs = 0;
812
18.9M
            if (ss.block_scan_index == ss.next_extra_zero_run_index) {
813
8.81k
              num_zero_runs = scan_info.extra_zero_runs[ss.extra_zero_runs_pos]
814
8.81k
                                  .num_extra_zero_runs;
815
8.81k
              ++ss.extra_zero_runs_pos;
816
8.81k
              ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
817
8.81k
            }
818
18.9M
            const coeff_t* coeffs = &c.coeffs[block_idx << 6];
819
18.9M
            bool ok;
820
18.9M
            if (kMode == 0) {
821
0
              ok = EncodeDCTBlockSequential(coeffs, dc_huff, ac_huff,
822
0
                                            num_zero_runs,
823
0
                                            ss.last_dc_coeff + si.comp_idx, bw);
824
18.9M
            } else if (kMode == 1) {
825
18.9M
              ok = EncodeDCTBlockProgressive(
826
18.9M
                  coeffs, dc_huff, ac_huff, Ss, Se, Al, num_zero_runs,
827
18.9M
                  coding_state, ss.last_dc_coeff + si.comp_idx, bw);
828
18.9M
            } else {
829
0
              ok = EncodeRefinementBits(coeffs, ac_huff, Ss, Se, Al,
830
0
                                        coding_state, bw);
831
0
            }
832
18.9M
            if (!ok) return SerializationStatus::ERROR;
833
18.9M
            ++ss.block_scan_index;
834
18.9M
          }
835
6.44M
        }
836
1.94M
      }
837
889k
      --ss.restarts_to_go;
838
889k
    }
839
132k
  }
840
3.06k
  if (ss.mcu_y < MCU_rows) {
841
0
    if (!bw->healthy) return SerializationStatus::ERROR;
842
0
    return SerializationStatus::NEEDS_MORE_INPUT;
843
0
  }
844
3.06k
  Flush(coding_state, bw);
845
3.06k
  if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
846
12
    return SerializationStatus::ERROR;
847
12
  }
848
3.05k
  BitWriterFinish(bw);
849
3.05k
  ss.stage = EncodeScanState::HEAD;
850
3.05k
  state->scan_index++;
851
3.05k
  if (!bw->healthy) return SerializationStatus::ERROR;
852
853
792
  return SerializationStatus::DONE;
854
3.05k
}
jpeg_data_writer.cc:brunsli::internal::dec::SerializationStatus brunsli::(anonymous namespace)::DoEncodeScan<2>(brunsli::JPEGData const&, brunsli::internal::dec::State const&, brunsli::internal::dec::SerializationState*)
Line
Count
Source
700
5.31k
                                                  SerializationState* state) {
701
5.31k
  const JPEGScanInfo& scan_info = jpg.scan_info[state->scan_index];
702
5.31k
  EncodeScanState& ss = state->scan_state;
703
704
5.31k
  const int restart_interval =
705
5.31k
      state->seen_dri_marker ? jpg.restart_interval : 0;
706
707
5.31k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
5.31k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
5.31k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
5.31k
    } else {
711
5.31k
      return -1;
712
5.31k
    }
713
5.31k
  };
714
715
5.31k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
5.31k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
5.31k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
5.31k
    } else {
719
5.31k
      return -1;
720
5.31k
    }
721
5.31k
  };
722
723
5.31k
  if (ss.stage == EncodeScanState::HEAD) {
724
5.31k
    if (!EncodeSOS(jpg, scan_info, state)) return SerializationStatus::ERROR;
725
5.17k
    BitWriterInit(&ss.bw, &state->output_queue);
726
5.17k
    DCTCodingStateInit(&ss.coding_state);
727
5.17k
    ss.restarts_to_go = restart_interval;
728
5.17k
    ss.next_restart_marker = 0;
729
5.17k
    ss.block_scan_index = 0;
730
5.17k
    ss.extra_zero_runs_pos = 0;
731
5.17k
    ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
732
5.17k
    ss.next_reset_point_pos = 0;
733
5.17k
    ss.next_reset_point = get_next_reset_point();
734
5.17k
    ss.mcu_y = 0;
735
5.17k
    memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
736
5.17k
    ss.stage = EncodeScanState::BODY;
737
5.17k
  }
738
5.17k
  BitWriter* bw = &ss.bw;
739
5.17k
  DCTCodingState* coding_state = &ss.coding_state;
740
741
5.17k
  BRUNSLI_DCHECK(ss.stage == EncodeScanState::BODY);
742
743
  // "Non-interleaved" means color data comes in separate scans, in other words
744
  // each scan can contain only one color component.
745
5.17k
  const bool is_interleaved = (scan_info.num_components > 1);
746
5.17k
  const JPEGComponent& base_component =
747
5.17k
      jpg.components[scan_info.components[0].comp_idx];
748
  // h_group / v_group act as numerators for converting number of blocks to
749
  // number of MCU. In interleaved mode it is 1, so MCU is represented with
750
  // max_*_samp_factor blocks. In non-interleaved mode we choose numerator to
751
  // be the samping factor, consequently MCU is always represented with single
752
  // block.
753
5.17k
  const int h_group = is_interleaved ? 1 : base_component.h_samp_factor;
754
5.17k
  const int v_group = is_interleaved ? 1 : base_component.v_samp_factor;
755
5.17k
  const int MCUs_per_row =
756
5.17k
      DivCeil(jpg.width * h_group, 8 * jpg.max_h_samp_factor);
757
5.17k
  const int MCU_rows = DivCeil(jpg.height * v_group, 8 * jpg.max_v_samp_factor);
758
5.17k
  const bool is_progressive = state->is_progressive;
759
5.17k
  const int Al = is_progressive ? scan_info.Al : 0;
760
5.17k
  const int Ss = is_progressive ? scan_info.Ss : 0;
761
5.17k
  const int Se = is_progressive ? scan_info.Se : 63;
762
763
  // DC-only is defined by [0..0] spectral range.
764
5.17k
  const bool want_ac = ((Ss != 0) || (Se != 0));
765
5.17k
  const bool complete_ac = (parsing_state.stage == Stage::DONE);
766
5.17k
  const bool has_ac =
767
5.17k
      complete_ac || HasSection(&parsing_state, kBrunsliACDataTag);
768
5.17k
  if (want_ac && !has_ac) return SerializationStatus::NEEDS_MORE_INPUT;
769
770
  // |has_ac| implies |complete_dc| but not vice versa; for the sake of
771
  // simplicity we pretend they are equal, because they are separated by just a
772
  // few bytes of input.
773
5.17k
  const bool complete_dc = has_ac;
774
5.17k
  const bool complete = want_ac ? complete_ac : complete_dc;
775
  // When "incomplete" |ac_dc| tracks information about current ("incomplete")
776
  // band parsing progress.
777
5.17k
  const int last_mcu_y =
778
5.17k
      complete ? MCU_rows : parsing_state.internal->ac_dc.next_mcu_y * v_group;
779
780
130k
  for (; ss.mcu_y < last_mcu_y; ++ss.mcu_y) {
781
1.58M
    for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
782
      // Possibly emit a restart marker.
783
1.46M
      if (restart_interval > 0 && ss.restarts_to_go == 0) {
784
162k
        Flush(coding_state, bw);
785
162k
        if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
786
15
          return SerializationStatus::ERROR;
787
15
        }
788
162k
        EmitMarker(bw, 0xD0 + ss.next_restart_marker);
789
162k
        ss.next_restart_marker += 1;
790
162k
        ss.next_restart_marker &= 0x7;
791
162k
        ss.restarts_to_go = restart_interval;
792
162k
        memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
793
162k
      }
794
      // Encode one MCU
795
4.54M
      for (size_t i = 0; i < scan_info.num_components; ++i) {
796
3.08M
        const JPEGComponentScanInfo& si = scan_info.components[i];
797
3.08M
        const JPEGComponent& c = jpg.components[si.comp_idx];
798
3.08M
        const HuffmanCodeTable& dc_huff = state->dc_huff_table[si.dc_tbl_idx];
799
3.08M
        const HuffmanCodeTable& ac_huff = state->ac_huff_table[si.ac_tbl_idx];
800
3.08M
        int n_blocks_y = is_interleaved ? c.v_samp_factor : 1;
801
3.08M
        int n_blocks_x = is_interleaved ? c.h_samp_factor : 1;
802
18.9M
        for (int iy = 0; iy < n_blocks_y; ++iy) {
803
68.0M
          for (int ix = 0; ix < n_blocks_x; ++ix) {
804
52.1M
            int block_y = ss.mcu_y * n_blocks_y + iy;
805
52.1M
            int block_x = mcu_x * n_blocks_x + ix;
806
52.1M
            int block_idx = block_y * c.width_in_blocks + block_x;
807
52.1M
            if (ss.block_scan_index == ss.next_reset_point) {
808
17.5k
              Flush(coding_state, bw);
809
17.5k
              ss.next_reset_point = get_next_reset_point();
810
17.5k
            }
811
52.1M
            int num_zero_runs = 0;
812
52.1M
            if (ss.block_scan_index == ss.next_extra_zero_run_index) {
813
1.94k
              num_zero_runs = scan_info.extra_zero_runs[ss.extra_zero_runs_pos]
814
1.94k
                                  .num_extra_zero_runs;
815
1.94k
              ++ss.extra_zero_runs_pos;
816
1.94k
              ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
817
1.94k
            }
818
52.1M
            const coeff_t* coeffs = &c.coeffs[block_idx << 6];
819
52.1M
            bool ok;
820
52.1M
            if (kMode == 0) {
821
0
              ok = EncodeDCTBlockSequential(coeffs, dc_huff, ac_huff,
822
0
                                            num_zero_runs,
823
0
                                            ss.last_dc_coeff + si.comp_idx, bw);
824
52.1M
            } else if (kMode == 1) {
825
0
              ok = EncodeDCTBlockProgressive(
826
0
                  coeffs, dc_huff, ac_huff, Ss, Se, Al, num_zero_runs,
827
0
                  coding_state, ss.last_dc_coeff + si.comp_idx, bw);
828
52.1M
            } else {
829
52.1M
              ok = EncodeRefinementBits(coeffs, ac_huff, Ss, Se, Al,
830
52.1M
                                        coding_state, bw);
831
52.1M
            }
832
52.1M
            if (!ok) return SerializationStatus::ERROR;
833
52.1M
            ++ss.block_scan_index;
834
52.1M
          }
835
15.8M
        }
836
3.08M
      }
837
1.46M
      --ss.restarts_to_go;
838
1.46M
    }
839
125k
  }
840
5.15k
  if (ss.mcu_y < MCU_rows) {
841
0
    if (!bw->healthy) return SerializationStatus::ERROR;
842
0
    return SerializationStatus::NEEDS_MORE_INPUT;
843
0
  }
844
5.15k
  Flush(coding_state, bw);
845
5.15k
  if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
846
27
    return SerializationStatus::ERROR;
847
27
  }
848
5.12k
  BitWriterFinish(bw);
849
5.12k
  ss.stage = EncodeScanState::HEAD;
850
5.12k
  state->scan_index++;
851
5.12k
  if (!bw->healthy) return SerializationStatus::ERROR;
852
853
1.14k
  return SerializationStatus::DONE;
854
5.12k
}
855
856
static SerializationStatus BRUNSLI_INLINE
857
EncodeScan(const JPEGData& jpg, const State& parsing_state,
858
10.0k
           SerializationState* state) {
859
10.0k
  const JPEGScanInfo& scan_info = jpg.scan_info[state->scan_index];
860
10.0k
  const bool is_progressive = state->is_progressive;
861
10.0k
  const int Al = is_progressive ? scan_info.Al : 0;
862
10.0k
  const int Ah = is_progressive ? scan_info.Ah : 0;
863
10.0k
  const int Ss = is_progressive ? scan_info.Ss : 0;
864
10.0k
  const int Se = is_progressive ? scan_info.Se : 63;
865
10.0k
  const bool need_sequential =
866
10.0k
      !is_progressive || (Ah == 0 && Al == 0 && Ss == 0 && Se == 63);
867
10.0k
  if (need_sequential) {
868
1.60k
    return DoEncodeScan<0>(jpg, parsing_state, state);
869
8.43k
  } else if (Ah == 0) {
870
3.11k
    return DoEncodeScan<1>(jpg, parsing_state, state);
871
5.31k
  } else {
872
5.31k
    return DoEncodeScan<2>(jpg, parsing_state, state);
873
5.31k
  }
874
10.0k
}
875
876
SerializationStatus SerializeSection(uint8_t marker, const State& parsing_state,
877
                                     SerializationState* state,
878
68.5k
                                     const JPEGData& jpg) {
879
68.5k
  const auto to_status = [](bool result) {
880
58.2k
    return result ? SerializationStatus::DONE : SerializationStatus::ERROR;
881
58.2k
  };
882
  // TODO(eustas): add and use marker enum
883
68.5k
  switch (marker) {
884
7.95k
    case 0xC0:
885
10.2k
    case 0xC1:
886
19.5k
    case 0xC2:
887
22.7k
    case 0xC9:
888
25.3k
    case 0xCA:
889
25.3k
      return to_status(EncodeSOF(jpg, marker, state));
890
891
9.47k
    case 0xC4:
892
9.47k
      return to_status(EncodeDHT(jpg, state));
893
894
2.65k
    case 0xD0:
895
4.97k
    case 0xD1:
896
6.88k
    case 0xD2:
897
8.82k
    case 0xD3:
898
10.8k
    case 0xD4:
899
13.8k
    case 0xD5:
900
16.3k
    case 0xD6:
901
17.7k
    case 0xD7:
902
17.7k
      return to_status(EncodeRestart(marker, state));
903
904
754
    case 0xD9:
905
754
      return to_status(EncodeEOI(jpg, state));
906
907
10.0k
    case 0xDA:
908
10.0k
      return EncodeScan(jpg, parsing_state, state);
909
910
745
    case 0xDB:
911
745
      return to_status(EncodeDQT(jpg, state));
912
913
3.67k
    case 0xDD:
914
3.67k
      return to_status(EncodeDRI(jpg, state));
915
916
43
    case 0xE0:
917
84
    case 0xE1:
918
143
    case 0xE2:
919
155
    case 0xE3:
920
180
    case 0xE4:
921
210
    case 0xE5:
922
248
    case 0xE6:
923
285
    case 0xE7:
924
305
    case 0xE8:
925
323
    case 0xE9:
926
352
    case 0xEA:
927
377
    case 0xEB:
928
400
    case 0xEC:
929
415
    case 0xED:
930
434
    case 0xEE:
931
453
    case 0xEF:
932
453
      return to_status(EncodeAPP(jpg, marker, state));
933
934
13
    case 0xFE:
935
13
      return to_status(EncodeCOM(jpg, state));
936
937
53
    case 0xFF:
938
53
      return to_status(EncodeInterMarkerData(jpg, state));
939
940
251
    default:
941
251
      return SerializationStatus::ERROR;
942
68.5k
  }
943
68.5k
}
944
945
void PushOutput(std::deque<OutputChunk>* in, size_t* available_out,
946
78.9k
                uint8_t** next_out) {
947
151k
  while (*available_out > 0) {
948
    // No more data.
949
150k
    if (in->empty()) return;
950
72.2k
    OutputChunk& chunk = in->front();
951
72.2k
    size_t to_copy = std::min(*available_out, chunk.len);
952
72.2k
    if (to_copy > 0) {
953
71.5k
      memcpy(*next_out, chunk.next, to_copy);
954
71.5k
      *next_out += to_copy;
955
71.5k
      *available_out -= to_copy;
956
71.5k
      chunk.next += to_copy;
957
71.5k
      chunk.len -= to_copy;
958
71.5k
    }
959
72.2k
    if (chunk.len == 0) in->pop_front();
960
72.2k
  }
961
78.9k
}
962
963
}  // namespace
964
965
// Adaptor for old API users. Will be removed once new API will support proper
966
// streaming serialization.
967
9.27k
bool WriteJpeg(const JPEGData& jpg, JPEGOutput out) {
968
9.27k
  State state;
969
9.27k
  state.stage = Stage::DONE;
970
9.27k
  std::vector<uint8_t> buffer(16384);
971
9.61k
  while (true) {
972
9.61k
    uint8_t* next_out = buffer.data();
973
9.61k
    size_t available_out = buffer.size();
974
9.61k
    SerializationStatus status =
975
9.61k
        SerializeJpeg(&state, jpg, &available_out, &next_out);
976
9.61k
    if (status != SerializationStatus::DONE &&
977
8.84k
        status != SerializationStatus::NEEDS_MORE_OUTPUT) {
978
8.49k
      return false;
979
8.49k
    }
980
1.11k
    size_t to_write = buffer.size() - available_out;
981
1.11k
    if (!out.Write(buffer.data(), to_write)) return false;
982
1.11k
    if (status == SerializationStatus::DONE) return true;
983
1.11k
  }
984
9.27k
}
985
986
namespace internal {
987
namespace dec {
988
SerializationStatus SerializeJpeg(State* state, const JPEGData& jpg,
989
9.61k
                                  size_t* available_out, uint8_t** next_out) {
990
9.61k
  SerializationState& ss = state->internal->serialization;
991
992
78.9k
  const auto maybe_push_output = [&]() {
993
78.9k
    if (ss.stage != SerializationState::ERROR) {
994
78.9k
      PushOutput(&ss.output_queue, available_out, next_out);
995
78.9k
    }
996
78.9k
  };
997
998
  // Push remaining output from prevoius session.
999
9.61k
  maybe_push_output();
1000
1001
88.2k
  while (true) {
1002
88.2k
    switch (ss.stage) {
1003
9.27k
      case SerializationState::INIT: {
1004
        // If parsing is complete, serialization is possible.
1005
9.27k
        bool can_start_serialization = (state->stage == Stage::DONE);
1006
        // Parsing of AC/DC has started; i.e. quant/huffman/metadata is ready
1007
        // to be used.
1008
9.27k
        if (HasSection(state, kBrunsliDCDataTag) ||
1009
9.27k
            HasSection(state, kBrunsliACDataTag)) {
1010
0
          can_start_serialization = true;
1011
0
        }
1012
9.27k
        if (!can_start_serialization) {
1013
0
          return SerializationStatus::NEEDS_MORE_INPUT;
1014
0
        }
1015
        // JpegBypass is a very simple / special case.
1016
9.27k
        if (jpg.version == kFallbackVersion) {
1017
24
          if (jpg.original_jpg == nullptr) {
1018
3
            ss.stage = SerializationState::ERROR;
1019
3
            break;
1020
3
          }
1021
          // TODO(eustas): investigate if bad things can happen when complete
1022
          //               file is passed to parser, but it is impossible to
1023
          //               push complete output.
1024
21
          ss.output_queue.emplace_back(jpg.original_jpg, jpg.original_jpg_size);
1025
21
          ss.stage = SerializationState::DONE;
1026
21
          break;
1027
24
        }
1028
1029
        // Invalid mode - fallback + something else.
1030
9.24k
        if ((jpg.version & 1) == kFallbackVersion) {
1031
0
          ss.stage = SerializationState::ERROR;
1032
0
          break;
1033
0
        }
1034
1035
        // Valid Brunsli requires, at least, 0xD9 marker.
1036
        // This might happen on corrupted stream, or on unconditioned JPEGData.
1037
        // TODO(eustas): check D9 in the only one and is the last one.
1038
9.24k
        if (jpg.marker_order.empty()) {
1039
0
          ss.stage = SerializationState::ERROR;
1040
0
          break;
1041
0
        }
1042
1043
9.24k
        ss.dc_huff_table.resize(kMaxHuffmanTables);
1044
9.24k
        ss.ac_huff_table.resize(kMaxHuffmanTables);
1045
9.24k
        if (jpg.has_zero_padding_bit) {
1046
492
          ss.pad_bits = jpg.padding_bits.data();
1047
492
          ss.pad_bits_end = ss.pad_bits + jpg.padding_bits.size();
1048
492
        }
1049
1050
9.24k
        EncodeSOI(&ss);
1051
9.24k
        maybe_push_output();
1052
9.24k
        ss.stage = SerializationState::SERIALIZE_SECTION;
1053
9.24k
        break;
1054
9.24k
      }
1055
1056
69.3k
      case SerializationState::SERIALIZE_SECTION: {
1057
69.3k
        if (ss.section_index >= jpg.marker_order.size()) {
1058
754
          ss.stage = SerializationState::DONE;
1059
754
          break;
1060
754
        }
1061
68.5k
        uint8_t marker = jpg.marker_order[ss.section_index];
1062
68.5k
        SerializationStatus status = SerializeSection(marker, *state, &ss, jpg);
1063
68.5k
        if (status == SerializationStatus::ERROR) {
1064
8.49k
          BRUNSLI_LOG_DEBUG() << "Failed to encode marker " << std::hex
1065
0
                              << marker << BRUNSLI_ENDL();
1066
8.49k
          ss.stage = SerializationState::ERROR;
1067
8.49k
          break;
1068
8.49k
        }
1069
60.0k
        maybe_push_output();
1070
60.0k
        if (status == SerializationStatus::NEEDS_MORE_INPUT) {
1071
0
          return SerializationStatus::NEEDS_MORE_INPUT;
1072
60.0k
        } else if (status != SerializationStatus::DONE) {
1073
0
          BRUNSLI_DCHECK(false);
1074
0
          ss.stage = SerializationState::ERROR;
1075
0
          break;
1076
0
        }
1077
60.0k
        ++ss.section_index;
1078
60.0k
        break;
1079
60.0k
      }
1080
1081
1.11k
      case SerializationState::DONE: {
1082
1.11k
        if (!ss.output_queue.empty()) {
1083
344
          return SerializationStatus::NEEDS_MORE_OUTPUT;
1084
775
        } else {
1085
775
          return SerializationStatus::DONE;
1086
775
        }
1087
1.11k
      }
1088
1089
8.49k
      default:
1090
8.49k
        return SerializationStatus::ERROR;
1091
88.2k
    }
1092
88.2k
  }
1093
9.61k
}
1094
}  // namespace dec
1095
}  // namespace internal
1096
1097
}  // namespace brunsli