Coverage Report

Created: 2026-06-10 06:56

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.0k
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.72M
static BRUNSLI_INLINE uint64_t HasZeroByte(uint64_t x) {
49
4.72M
  return (x - 0x0101010101010101ULL) & ~x & 0x8080808080808080ULL;
50
4.72M
}
51
52
9.52k
void BitWriterInit(BitWriter* bw, std::deque<OutputChunk>* output_queue) {
53
9.52k
  bw->output = output_queue;
54
9.52k
  bw->chunk = OutputChunk(kBitWriterChunkSize);
55
9.52k
  bw->pos = 0;
56
9.52k
  bw->put_buffer = 0;
57
9.52k
  bw->put_bits = 64;
58
9.52k
  bw->healthy = true;
59
9.52k
  bw->data = bw->chunk.buffer->data();
60
9.52k
}
61
62
1.69k
static BRUNSLI_NOINLINE void SwapBuffer(BitWriter* bw) {
63
1.69k
  bw->chunk.len = bw->pos;
64
1.69k
  bw->output->emplace_back(std::move(bw->chunk));
65
1.69k
  bw->chunk = OutputChunk(kBitWriterChunkSize);
66
1.69k
  bw->data = bw->chunk.buffer->data();
67
1.69k
  bw->pos = 0;
68
1.69k
}
69
70
5.70M
static BRUNSLI_INLINE void Reserve(BitWriter* bw, size_t n_bytes) {
71
5.70M
  if (BRUNSLI_PREDICT_FALSE((bw->pos + n_bytes) > kBitWriterChunkSize)) {
72
1.69k
    SwapBuffer(bw);
73
1.69k
  }
74
5.70M
}
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
10.9M
static BRUNSLI_INLINE void EmitByte(BitWriter* bw, int byte) {
83
10.9M
  bw->data[bw->pos++] = byte;
84
10.9M
  if (byte == 0xFF) bw->data[bw->pos++] = 0;
85
10.9M
}
86
87
4.72M
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.72M
  Reserve(bw, 12);
94
4.72M
  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.64M
    EmitByte(bw, (bw->put_buffer >> 56) & 0xFF);
98
1.64M
    EmitByte(bw, (bw->put_buffer >> 48) & 0xFF);
99
1.64M
    EmitByte(bw, (bw->put_buffer >> 40) & 0xFF);
100
1.64M
    EmitByte(bw, (bw->put_buffer >> 32) & 0xFF);
101
1.64M
    EmitByte(bw, (bw->put_buffer >> 24) & 0xFF);
102
1.64M
    EmitByte(bw, (bw->put_buffer >> 16) & 0xFF);
103
3.07M
  } else {
104
    // We don't have any 0xFF bytes, output all 6 bytes without checking.
105
3.07M
    bw->data[bw->pos] = (bw->put_buffer >> 56) & 0xFF;
106
3.07M
    bw->data[bw->pos + 1] = (bw->put_buffer >> 48) & 0xFF;
107
3.07M
    bw->data[bw->pos + 2] = (bw->put_buffer >> 40) & 0xFF;
108
3.07M
    bw->data[bw->pos + 3] = (bw->put_buffer >> 32) & 0xFF;
109
3.07M
    bw->data[bw->pos + 4] = (bw->put_buffer >> 24) & 0xFF;
110
3.07M
    bw->data[bw->pos + 5] = (bw->put_buffer >> 16) & 0xFF;
111
3.07M
    bw->pos += 6;
112
3.07M
  }
113
4.72M
  bw->put_buffer <<= 48;
114
4.72M
  bw->put_bits += 48;
115
4.72M
}
116
117
56.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
56.4M
  if (nbits == 0) {
123
7.13M
    bw->healthy = false;
124
7.13M
    return;
125
7.13M
  }
126
49.3M
  bw->put_bits -= nbits;
127
49.3M
  bw->put_buffer |= (bits << bw->put_bits);
128
49.3M
  if (bw->put_bits <= 16) DischargeBitBuffer(bw);
129
49.3M
}
130
131
485k
void EmitMarker(BitWriter* bw, int marker) {
132
485k
  Reserve(bw, 2);
133
485k
  BRUNSLI_DCHECK(marker != 0xFF);
134
485k
  bw->data[bw->pos++] = 0xFF;
135
485k
  bw->data[bw->pos++] = marker;
136
485k
}
137
138
bool JumpToByteBoundary(BitWriter* bw, const int** pad_bits,
139
494k
                        const int* pad_bits_end) {
140
494k
  size_t n_bits = bw->put_bits & 7u;
141
494k
  uint8_t pad_pattern;
142
494k
  if (*pad_bits == nullptr) {
143
487k
    pad_pattern = (1u << n_bits) - 1;
144
487k
  } else {
145
7.21k
    pad_pattern = 0;
146
7.21k
    const int* src = *pad_bits;
147
    // TODO(eustas): bitwise reading looks insanely ineffective...
148
14.1k
    while (n_bits--) {
149
7.04k
      pad_pattern <<= 1;
150
7.04k
      if (src >= pad_bits_end) return false;
151
      // TODO(eustas): DCHECK *src == {0, 1}
152
6.94k
      pad_pattern |= !!*(src++);
153
6.94k
    }
154
7.11k
    *pad_bits = src;
155
7.11k
  }
156
157
494k
  Reserve(bw, 16);
158
159
1.17M
  while (bw->put_bits <= 56) {
160
680k
    int c = (bw->put_buffer >> 56) & 0xFF;
161
680k
    EmitByte(bw, c);
162
680k
    bw->put_buffer <<= 8;
163
680k
    bw->put_bits += 8;
164
680k
  }
165
494k
  if (bw->put_bits < 64) {
166
388k
    int pad_mask = 0xFFu >> (64 - bw->put_bits);
167
388k
    int c = ((bw->put_buffer >> 56) & ~pad_mask) | pad_pattern;
168
388k
    EmitByte(bw, c);
169
388k
  }
170
494k
  bw->put_buffer = 0;
171
494k
  bw->put_bits = 64;
172
173
494k
  return true;
174
494k
}
175
176
9.42k
void BitWriterFinish(BitWriter* bw) {
177
9.42k
  if (bw->pos == 0) return;
178
9.03k
  bw->chunk.len = bw->pos;
179
9.03k
  bw->output->emplace_back(std::move(bw->chunk));
180
9.03k
  bw->chunk = OutputChunk(nullptr, 0);
181
9.03k
  bw->data = nullptr;
182
9.03k
  bw->pos = 0;
183
9.03k
}
184
185
9.52k
void DCTCodingStateInit(DCTCodingState* s) {
186
9.52k
  s->eob_run_ = 0;
187
9.52k
  s->cur_ac_huff_ = nullptr;
188
9.52k
  s->refinement_bits_.clear();
189
9.52k
  s->refinement_bits_.reserve(64);  // 1024 bits most often is more than enough.
190
9.52k
  s->refinement_bits_count_ = 0;
191
9.52k
}
192
193
// Emit all buffered data to the bit stream using the given Huffman code and
194
// bit writer.
195
15.6M
static BRUNSLI_INLINE void Flush(DCTCodingState* s, BitWriter* bw) {
196
15.6M
  if (s->eob_run_ > 0) {
197
15.0M
    int nbits = Log2FloorNonZero(s->eob_run_);
198
15.0M
    int symbol = nbits << 4u;
199
15.0M
    WriteBits(bw, s->cur_ac_huff_->depth[symbol],
200
15.0M
              s->cur_ac_huff_->code[symbol]);
201
15.0M
    if (nbits > 0) {
202
68.8k
      WriteBits(bw, nbits, s->eob_run_ & ((1 << nbits) - 1));
203
68.8k
    }
204
15.0M
    s->eob_run_ = 0;
205
15.0M
  }
206
15.6M
  size_t num_words = s->refinement_bits_count_ >> 4;
207
15.6M
  for (size_t i = 0; i < num_words; ++i) {
208
53.6k
    WriteBits(bw, 16, s->refinement_bits_[i]);
209
53.6k
  }
210
15.6M
  size_t tail = s->refinement_bits_count_ & 0xF;
211
15.6M
  if (tail) {
212
75.5k
    WriteBits(bw, tail, s->refinement_bits_.back());
213
75.5k
  }
214
15.6M
  s->refinement_bits_.clear();
215
15.6M
  s->refinement_bits_count_ = 0;
216
15.6M
}
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
70.3M
                                           BitWriter* bw) {
225
70.3M
  if (s->eob_run_ == 0) {
226
15.0M
    s->cur_ac_huff_ = ac_huff;
227
15.0M
  }
228
70.3M
  ++s->eob_run_;
229
70.3M
  if (new_bits_count) {
230
295k
    uint64_t new_bits = 0;
231
1.48M
    for (size_t i = 0; i < new_bits_count; ++i) {
232
1.19M
      new_bits = (new_bits << 1) | new_bits_array[i];
233
1.19M
    }
234
295k
    size_t tail = s->refinement_bits_count_ & 0xF;
235
295k
    if (tail) {  // First stuff the tail item
236
207k
      size_t stuff_bits_count = std::min(16 - tail, new_bits_count);
237
207k
      uint16_t stuff_bits = new_bits >> (new_bits_count - stuff_bits_count);
238
207k
      stuff_bits &= ((1u << stuff_bits_count) - 1);
239
207k
      s->refinement_bits_.back() =
240
207k
          (s->refinement_bits_.back() << stuff_bits_count) | stuff_bits;
241
207k
      new_bits_count -= stuff_bits_count;
242
207k
      s->refinement_bits_count_ += stuff_bits_count;
243
207k
    }
244
316k
    while (new_bits_count >= 16) {
245
21.7k
      s->refinement_bits_.push_back(new_bits >> (new_bits_count - 16));
246
21.7k
      new_bits_count -= 16;
247
21.7k
      s->refinement_bits_count_ += 16;
248
21.7k
    }
249
295k
    if (new_bits_count) {
250
107k
      s->refinement_bits_.push_back(new_bits & ((1u << new_bits_count) - 1));
251
107k
      s->refinement_bits_count_ += new_bits_count;
252
107k
    }
253
295k
  }
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
70.3M
  if (s->refinement_bits_count_ > 0x7FFF * (kDCTBlockSize - 1)) {
257
0
    return false;
258
0
  }
259
70.3M
  if (s->eob_run_ == 0x7FFF) {
260
1.38k
    Flush(s, bw);
261
1.38k
  }
262
70.3M
  return true;
263
70.3M
}
264
265
bool BuildHuffmanCodeTable(const JPEGHuffmanCode& huff,
266
23.5k
                           HuffmanCodeTable* table) {
267
23.5k
  int huff_code[kJpegHuffmanAlphabetSize];
268
  // +1 for a sentinel element.
269
23.5k
  uint32_t huff_size[kJpegHuffmanAlphabetSize + 1];
270
23.5k
  int p = 0;
271
400k
  for (size_t l = 1; l <= kJpegHuffmanMaxBitLength; ++l) {
272
377k
    int i = huff.counts[l];
273
377k
    if (p + i > kJpegHuffmanAlphabetSize + 1) {
274
0
      return false;
275
0
    }
276
2.15M
    while (i--) huff_size[p++] = static_cast<uint32_t>(l);
277
377k
  }
278
279
23.5k
  if (p == 0) {
280
0
    return true;
281
0
  }
282
283
  // Reuse sentinel element.
284
23.5k
  int last_p = p - 1;
285
23.5k
  huff_size[last_p] = 0;
286
287
23.5k
  int code = 0;
288
23.5k
  uint32_t si = huff_size[0];
289
23.5k
  p = 0;
290
244k
  while (huff_size[p]) {
291
1.97M
    while ((huff_size[p]) == si) {
292
1.75M
      huff_code[p++] = code;
293
1.75M
      code++;
294
1.75M
    }
295
220k
    code <<= 1;
296
220k
    si++;
297
220k
  }
298
1.77M
  for (p = 0; p < last_p; p++) {
299
1.75M
    int i = huff.values[p];
300
1.75M
    table->depth[i] = huff_size[p];
301
1.75M
    table->code[i] = huff_code[p];
302
1.75M
  }
303
23.5k
  return true;
304
23.5k
}
305
306
8.93k
bool EncodeSOI(SerializationState* state) {
307
8.93k
  state->output_queue.push_back(OutputChunk({0xFF, 0xD8}));
308
8.93k
  return true;
309
8.93k
}
310
311
650
bool EncodeEOI(const JPEGData& jpg, SerializationState* state) {
312
650
  state->output_queue.push_back(OutputChunk({0xFF, 0xD9}));
313
650
  state->output_queue.emplace_back(jpg.tail_data);
314
650
  return true;
315
650
}
316
317
23.0k
bool EncodeSOF(const JPEGData& jpg, uint8_t marker, SerializationState* state) {
318
23.0k
  if (marker <= 0xC2) state->is_progressive = (marker == 0xC2);
319
320
23.0k
  const size_t n_comps = jpg.components.size();
321
23.0k
  const size_t marker_len = 8 + 3 * n_comps;
322
23.0k
  state->output_queue.emplace_back(marker_len + 2);
323
23.0k
  uint8_t* data = state->output_queue.back().buffer->data();
324
23.0k
  size_t pos = 0;
325
23.0k
  data[pos++] = 0xFFu;
326
23.0k
  data[pos++] = marker;
327
23.0k
  data[pos++] = static_cast<uint8_t>(marker_len >> 8u);
328
23.0k
  data[pos++] = static_cast<uint8_t>(marker_len);
329
23.0k
  data[pos++] = kJpegPrecision;
330
23.0k
  data[pos++] = jpg.height >> 8u;
331
23.0k
  data[pos++] = jpg.height & 0xFFu;
332
23.0k
  data[pos++] = jpg.width >> 8u;
333
23.0k
  data[pos++] = jpg.width & 0xFFu;
334
23.0k
  data[pos++] = static_cast<uint8_t>(n_comps);
335
47.1k
  for (size_t i = 0; i < n_comps; ++i) {
336
24.1k
    data[pos++] = jpg.components[i].id;
337
24.1k
    data[pos++] = ((jpg.components[i].h_samp_factor << 4u) |
338
24.1k
                   (jpg.components[i].v_samp_factor));
339
24.1k
    const size_t quant_idx = jpg.components[i].quant_idx;
340
24.1k
    if (quant_idx >= jpg.quant.size()) return false;
341
24.1k
    data[pos++] = jpg.quant[quant_idx].index;
342
24.1k
  }
343
23.0k
  return true;
344
23.0k
}
345
346
bool EncodeSOS(const JPEGData& jpg, const JPEGScanInfo& scan_info,
347
9.78k
               SerializationState* state) {
348
9.78k
  const size_t n_scans = scan_info.num_components;
349
9.78k
  const size_t marker_len = 6 + 2 * n_scans;
350
9.78k
  state->output_queue.emplace_back(marker_len + 2);
351
9.78k
  uint8_t* data = state->output_queue.back().buffer->data();
352
9.78k
  size_t pos = 0;
353
9.78k
  data[pos++] = 0xFFu;
354
9.78k
  data[pos++] = 0xDAu;
355
9.78k
  data[pos++] = static_cast<uint8_t>(marker_len >> 8u);
356
9.78k
  data[pos++] = static_cast<uint8_t>(marker_len);
357
9.78k
  data[pos++] = static_cast<uint8_t>(n_scans);
358
35.1k
  for (size_t i = 0; i < n_scans; ++i) {
359
25.6k
    const JPEGComponentScanInfo& si = scan_info.components[i];
360
25.6k
    if (si.comp_idx >= jpg.components.size()) return false;
361
25.3k
    data[pos++] = jpg.components[si.comp_idx].id;
362
25.3k
    data[pos++] = (si.dc_tbl_idx << 4u) + si.ac_tbl_idx;
363
25.3k
  }
364
9.52k
  data[pos++] = scan_info.Ss;
365
9.52k
  data[pos++] = scan_info.Se;
366
9.52k
  data[pos++] = ((scan_info.Ah << 4u) | (scan_info.Al));
367
9.52k
  return true;
368
9.78k
}
369
370
9.23k
bool EncodeDHT(const JPEGData& jpg, SerializationState* state) {
371
9.23k
  const std::vector<JPEGHuffmanCode>& huffman_code = jpg.huffman_code;
372
373
9.23k
  size_t marker_len = 2;
374
23.5k
  for (size_t i = state->dht_index; i < huffman_code.size(); ++i) {
375
23.5k
    const JPEGHuffmanCode& huff = huffman_code[i];
376
23.5k
    marker_len += kJpegHuffmanMaxBitLength;
377
424k
    for (size_t j = 0; j < huff.counts.size(); ++j) {
378
400k
      marker_len += huff.counts[j];
379
400k
    }
380
23.5k
    if (huff.is_last) break;
381
23.5k
  }
382
9.23k
  state->output_queue.emplace_back(marker_len + 2);
383
9.23k
  uint8_t* data = state->output_queue.back().buffer->data();
384
9.23k
  size_t pos = 0;
385
9.23k
  data[pos++] = 0xFFu;
386
9.23k
  data[pos++] = 0xC4u;
387
9.23k
  data[pos++] = static_cast<uint8_t>(marker_len >> 8u);
388
9.23k
  data[pos++] = static_cast<uint8_t>(marker_len);
389
23.5k
  while (true) {
390
23.5k
    const size_t huffman_code_index = state->dht_index++;
391
23.5k
    if (huffman_code_index >= huffman_code.size()) {
392
0
      return false;
393
0
    }
394
23.5k
    const JPEGHuffmanCode& huff = huffman_code[huffman_code_index];
395
23.5k
    size_t index = huff.slot_id;
396
23.5k
    HuffmanCodeTable* huff_table;
397
23.5k
    if (index & 0x10) {
398
13.2k
      index -= 0x10;
399
13.2k
      huff_table = &state->ac_huff_table[index];
400
13.2k
    } else {
401
10.2k
      huff_table = &state->dc_huff_table[index];
402
10.2k
    }
403
    // TODO(eustas): cache
404
    // TODO(eustas): set up non-existing symbols
405
23.5k
    if (!BuildHuffmanCodeTable(huff, huff_table)) {
406
0
      return false;
407
0
    }
408
23.5k
    size_t total_count = 0;
409
23.5k
    size_t max_length = 0;
410
424k
    for (size_t i = 0; i < huff.counts.size(); ++i) {
411
400k
      if (huff.counts[i] != 0) {
412
203k
        max_length = i;
413
203k
      }
414
400k
      total_count += huff.counts[i];
415
400k
    }
416
23.5k
    --total_count;
417
23.5k
    data[pos++] = huff.slot_id;
418
400k
    for (size_t i = 1; i <= kJpegHuffmanMaxBitLength; ++i) {
419
377k
      data[pos++] = (i == max_length ? huff.counts[i] - 1 : huff.counts[i]);
420
377k
    }
421
1.77M
    for (size_t i = 0; i < total_count; ++i) {
422
1.75M
      data[pos++] = huff.values[i];
423
1.75M
    }
424
23.5k
    if (huff.is_last) break;
425
23.5k
  }
426
9.23k
  return true;
427
9.23k
}
428
429
720
bool EncodeDQT(const JPEGData& jpg, SerializationState* state) {
430
720
  int marker_len = 2;
431
720
  for (size_t i = state->dqt_index; i < jpg.quant.size(); ++i) {
432
698
    const JPEGQuantTable& table = jpg.quant[i];
433
698
    marker_len += 1 + (table.precision ? 2 : 1) * kDCTBlockSize;
434
698
    if (table.is_last) break;
435
698
  }
436
720
  state->output_queue.emplace_back(marker_len + 2);
437
720
  uint8_t* data = state->output_queue.back().buffer->data();
438
720
  size_t pos = 0;
439
720
  data[pos++] = 0xFF;
440
720
  data[pos++] = 0xDB;
441
720
  data[pos++] = marker_len >> 8u;
442
720
  data[pos++] = marker_len & 0xFFu;
443
720
  while (true) {
444
720
    const size_t idx = state->dqt_index++;
445
720
    if (idx >= jpg.quant.size()) {
446
22
      return false;  // corrupt input
447
22
    }
448
698
    const JPEGQuantTable& table = jpg.quant[idx];
449
698
    data[pos++] = (table.precision << 4u) + table.index;
450
45.3k
    for (size_t i = 0; i < kDCTBlockSize; ++i) {
451
44.6k
      int val_idx = kJPEGNaturalOrder[i];
452
44.6k
      int val = table.values[val_idx];
453
44.6k
      if (table.precision) {
454
12.1k
        data[pos++] = val >> 8u;
455
12.1k
      }
456
44.6k
      data[pos++] = val & 0xFFu;
457
44.6k
    }
458
698
    if (table.is_last) break;
459
698
  }
460
698
  return true;
461
720
}
462
463
3.75k
bool EncodeDRI(const JPEGData& jpg, SerializationState* state) {
464
3.75k
  state->seen_dri_marker = true;
465
3.75k
  OutputChunk dri_marker = {0xFF,
466
3.75k
                            0xDD,
467
3.75k
                            0,
468
3.75k
                            4,
469
3.75k
                            static_cast<uint8_t>(jpg.restart_interval >> 8),
470
3.75k
                            static_cast<uint8_t>(jpg.restart_interval & 0xFF)};
471
3.75k
  state->output_queue.push_back(std::move(dri_marker));
472
3.75k
  return true;
473
3.75k
}
474
475
17.9k
bool EncodeRestart(uint8_t marker, SerializationState* state) {
476
17.9k
  state->output_queue.push_back(OutputChunk({0xFF, marker}));
477
17.9k
  return true;
478
17.9k
}
479
480
375
bool EncodeAPP(const JPEGData& jpg, uint8_t marker, SerializationState* state) {
481
  // TODO(eustas): check that marker corresponds to payload?
482
375
  (void)marker;
483
484
375
  size_t app_index = state->app_index++;
485
375
  if (app_index >= jpg.app_data.size()) return false;
486
32
  state->output_queue.push_back(OutputChunk({0xFF}));
487
32
  state->output_queue.emplace_back(jpg.app_data[app_index]);
488
32
  return true;
489
375
}
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
44
bool EncodeInterMarkerData(const JPEGData& jpg, SerializationState* state) {
500
44
  size_t index = state->data_index++;
501
44
  if (index >= jpg.inter_marker_data.size()) return false;
502
44
  state->output_queue.emplace_back(jpg.inter_marker_data[index]);
503
44
  return true;
504
44
}
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
8.30M
                              BitWriter* bw) {
511
8.30M
  coeff_t temp2;
512
8.30M
  coeff_t temp;
513
8.30M
  temp2 = coeffs[0];
514
8.30M
  temp = temp2 - *last_dc_coeff;
515
8.30M
  *last_dc_coeff = temp2;
516
8.30M
  temp2 = temp;
517
8.30M
  if (temp < 0) {
518
2.19M
    temp = -temp;
519
2.19M
    temp2--;
520
2.19M
  }
521
8.30M
  int dc_nbits = (temp == 0) ? 0 : (Log2FloorNonZero(temp) + 1);
522
8.30M
  WriteBits(bw, dc_huff.depth[dc_nbits], dc_huff.code[dc_nbits]);
523
8.30M
  if (dc_nbits > 0) {
524
4.34M
    WriteBits(bw, dc_nbits, temp2 & ((1u << dc_nbits) - 1));
525
4.34M
  }
526
8.30M
  int r = 0;
527
531M
  for (int k = 1; k < 64; ++k) {
528
523M
    if ((temp = coeffs[kJPEGNaturalOrder[k]]) == 0) {
529
522M
      r++;
530
522M
      continue;
531
522M
    }
532
66.3k
    if (temp < 0) {
533
45.3k
      temp = -temp;
534
45.3k
      temp2 = ~temp;
535
45.3k
    } else {
536
20.9k
      temp2 = temp;
537
20.9k
    }
538
134k
    while (r > 15) {
539
67.8k
      WriteBits(bw, ac_huff.depth[0xf0], ac_huff.code[0xf0]);
540
67.8k
      r -= 16;
541
67.8k
    }
542
66.3k
    int ac_nbits = Log2FloorNonZero(temp) + 1;
543
66.3k
    int symbol = (r << 4u) + ac_nbits;
544
66.3k
    WriteBits(bw, ac_huff.depth[symbol], ac_huff.code[symbol]);
545
66.3k
    WriteBits(bw, ac_nbits, temp2 & ((1 << ac_nbits) - 1));
546
66.3k
    r = 0;
547
66.3k
  }
548
8.30M
  for (int i = 0; i < num_zero_runs; ++i) {
549
6.31k
    WriteBits(bw, ac_huff.depth[0xf0], ac_huff.code[0xf0]);
550
6.31k
    r -= 16;
551
6.31k
  }
552
8.30M
  if (r > 0) {
553
8.30M
    WriteBits(bw, ac_huff.depth[0], ac_huff.code[0]);
554
8.30M
  }
555
8.30M
  return true;
556
8.30M
}
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.8M
                               coeff_t* last_dc_coeff, BitWriter* bw) {
564
18.8M
  bool eob_run_allowed = Ss > 0;
565
18.8M
  coeff_t temp2;
566
18.8M
  coeff_t temp;
567
18.8M
  if (Ss == 0) {
568
7.20M
    temp2 = coeffs[0] >> Al;
569
7.20M
    temp = temp2 - *last_dc_coeff;
570
7.20M
    *last_dc_coeff = temp2;
571
7.20M
    temp2 = temp;
572
7.20M
    if (temp < 0) {
573
1.97M
      temp = -temp;
574
1.97M
      temp2--;
575
1.97M
    }
576
7.20M
    int nbits = (temp == 0) ? 0 : (Log2FloorNonZero(temp) + 1);
577
7.20M
    WriteBits(bw, dc_huff.depth[nbits], dc_huff.code[nbits]);
578
7.20M
    if (nbits > 0) {
579
3.93M
      WriteBits(bw, nbits, temp2 & ((1 << nbits) - 1));
580
3.93M
    }
581
7.20M
    ++Ss;
582
7.20M
  }
583
18.8M
  if (Ss > Se) {
584
698k
    return true;
585
698k
  }
586
18.1M
  int r = 0;
587
486M
  for (int k = Ss; k <= Se; ++k) {
588
468M
    if ((temp = coeffs[kJPEGNaturalOrder[k]]) == 0) {
589
467M
      r++;
590
467M
      continue;
591
467M
    }
592
115k
    if (temp < 0) {
593
81.5k
      temp = -temp;
594
81.5k
      temp >>= Al;
595
81.5k
      temp2 = ~temp;
596
81.5k
    } else {
597
34.0k
      temp >>= Al;
598
34.0k
      temp2 = temp;
599
34.0k
    }
600
115k
    if (temp == 0) {
601
4.82k
      r++;
602
4.82k
      continue;
603
4.82k
    }
604
110k
    Flush(coding_state, bw);
605
189k
    while (r > 15) {
606
78.5k
      WriteBits(bw, ac_huff.depth[0xf0], ac_huff.code[0xf0]);
607
78.5k
      r -= 16;
608
78.5k
    }
609
110k
    int nbits = Log2FloorNonZero(temp) + 1;
610
110k
    int symbol = (r << 4u) + nbits;
611
110k
    WriteBits(bw, ac_huff.depth[symbol], ac_huff.code[symbol]);
612
110k
    WriteBits(bw, nbits, temp2 & ((1 << nbits) - 1));
613
110k
    r = 0;
614
110k
  }
615
18.1M
  if (num_zero_runs > 0) {
616
8.97k
    Flush(coding_state, bw);
617
25.2k
    for (int i = 0; i < num_zero_runs; ++i) {
618
16.2k
      WriteBits(bw, ac_huff.depth[0xf0], ac_huff.code[0xf0]);
619
16.2k
      r -= 16;
620
16.2k
    }
621
8.97k
  }
622
18.1M
  if (r > 0) {
623
    // Ignore result: since we do not buffer bits - it can not fail.
624
18.1M
    BufferEndOfBand(coding_state, &ac_huff, nullptr, 0, bw);
625
18.1M
    if (!eob_run_allowed) {
626
6.92M
      Flush(coding_state, bw);
627
6.92M
    }
628
18.1M
  }
629
18.1M
  return true;
630
18.8M
}
631
632
bool EncodeRefinementBits(const coeff_t* coeffs,
633
                          const HuffmanCodeTable& ac_huff, int Ss, int Se,
634
52.8M
                          int Al, DCTCodingState* coding_state, BitWriter* bw) {
635
52.8M
  bool eob_run_allowed = Ss > 0;
636
52.8M
  if (Ss == 0) {
637
    // Emit next bit of DC component.
638
8.05M
    WriteBits(bw, 1, (coeffs[0] >> Al) & 1);
639
8.05M
    ++Ss;
640
8.05M
  }
641
52.8M
  if (Ss > Se) {
642
622k
    return true;
643
622k
  }
644
52.2M
  int abs_values[kDCTBlockSize];
645
52.2M
  int eob = 0;
646
1.26G
  for (int k = Ss; k <= Se; k++) {
647
1.21G
    const coeff_t abs_val = std::abs(coeffs[kJPEGNaturalOrder[k]]);
648
1.21G
    abs_values[k] = abs_val >> Al;
649
1.21G
    if (abs_values[k] == 1) {
650
205k
      eob = k;
651
205k
    }
652
1.21G
  }
653
52.2M
  int r = 0;
654
52.2M
  int refinement_bits[kDCTBlockSize];
655
52.2M
  size_t refinement_bits_count = 0;
656
1.26G
  for (int k = Ss; k <= Se; k++) {
657
1.21G
    if (abs_values[k] == 0) {
658
1.21G
      r++;
659
1.21G
      continue;
660
1.21G
    }
661
1.57M
    while (r > 15 && k <= eob) {
662
115k
      Flush(coding_state, bw);
663
115k
      WriteBits(bw, ac_huff.depth[0xf0], ac_huff.code[0xf0]);
664
115k
      r -= 16;
665
131k
      for (size_t i = 0; i < refinement_bits_count; ++i) {
666
16.1k
        WriteBits(bw, 1, refinement_bits[i]);
667
16.1k
      }
668
115k
      refinement_bits_count = 0;
669
115k
    }
670
1.45M
    if (abs_values[k] > 1) {
671
1.24M
      refinement_bits[refinement_bits_count++] = abs_values[k] & 1u;
672
1.24M
      continue;
673
1.24M
    }
674
205k
    Flush(coding_state, bw);
675
205k
    int symbol = (r << 4u) + 1;
676
205k
    int new_non_zero_bit = (coeffs[kJPEGNaturalOrder[k]] < 0) ? 0 : 1;
677
205k
    WriteBits(bw, ac_huff.depth[symbol], ac_huff.code[symbol]);
678
205k
    WriteBits(bw, 1, new_non_zero_bit);
679
244k
    for (size_t i = 0; i < refinement_bits_count; ++i) {
680
39.0k
      WriteBits(bw, 1, refinement_bits[i]);
681
39.0k
    }
682
205k
    refinement_bits_count = 0;
683
205k
    r = 0;
684
205k
  }
685
52.2M
  if (r > 0 || refinement_bits_count) {
686
52.2M
    if (!BufferEndOfBand(coding_state, &ac_huff, refinement_bits,
687
52.2M
                         refinement_bits_count, bw)) {
688
0
      return false;
689
0
    }
690
52.2M
    if (!eob_run_allowed) {
691
7.70M
      Flush(coding_state, bw);
692
7.70M
    }
693
52.2M
  }
694
52.2M
  return true;
695
52.2M
}
696
697
template <int kMode>
698
SerializationStatus BRUNSLI_NOINLINE DoEncodeScan(const JPEGData& jpg,
699
                                                  const State& parsing_state,
700
9.78k
                                                  SerializationState* state) {
701
9.78k
  const JPEGScanInfo& scan_info = jpg.scan_info[state->scan_index];
702
9.78k
  EncodeScanState& ss = state->scan_state;
703
704
9.78k
  const int restart_interval =
705
9.78k
      state->seen_dri_marker ? jpg.restart_interval : 0;
706
707
22.9k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
22.9k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
13.4k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
13.4k
    } else {
711
9.43k
      return -1;
712
9.43k
    }
713
22.9k
  };
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.66k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
3.66k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
2.22k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
2.22k
    } else {
711
1.44k
      return -1;
712
1.44k
    }
713
3.66k
  };
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
12.0k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
12.0k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
9.12k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
9.12k
    } else {
711
2.92k
      return -1;
712
2.92k
    }
713
12.0k
  };
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.21k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
7.21k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
2.15k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
5.06k
    } else {
711
5.06k
      return -1;
712
5.06k
    }
713
7.21k
  };
714
715
41.6k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
41.6k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
32.2k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
32.2k
    } else {
719
9.35k
      return -1;
720
9.35k
    }
721
41.6k
  };
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.92k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
2.92k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
1.47k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
1.47k
    } else {
719
1.44k
      return -1;
720
1.44k
    }
721
2.92k
  };
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
14.3k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
14.3k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
11.4k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
11.4k
    } else {
719
2.90k
      return -1;
720
2.90k
    }
721
14.3k
  };
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
24.3k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
24.3k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
19.3k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
19.3k
    } else {
719
5.00k
      return -1;
720
5.00k
    }
721
24.3k
  };
722
723
9.78k
  if (ss.stage == EncodeScanState::HEAD) {
724
9.78k
    if (!EncodeSOS(jpg, scan_info, state)) return SerializationStatus::ERROR;
725
9.52k
    BitWriterInit(&ss.bw, &state->output_queue);
726
9.52k
    DCTCodingStateInit(&ss.coding_state);
727
9.52k
    ss.restarts_to_go = restart_interval;
728
9.52k
    ss.next_restart_marker = 0;
729
9.52k
    ss.block_scan_index = 0;
730
9.52k
    ss.extra_zero_runs_pos = 0;
731
9.52k
    ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
732
9.52k
    ss.next_reset_point_pos = 0;
733
9.52k
    ss.next_reset_point = get_next_reset_point();
734
9.52k
    ss.mcu_y = 0;
735
9.52k
    memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
736
9.52k
    ss.stage = EncodeScanState::BODY;
737
9.52k
  }
738
9.52k
  BitWriter* bw = &ss.bw;
739
9.52k
  DCTCodingState* coding_state = &ss.coding_state;
740
741
9.52k
  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.52k
  const bool is_interleaved = (scan_info.num_components > 1);
746
9.52k
  const JPEGComponent& base_component =
747
9.52k
      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.52k
  const int h_group = is_interleaved ? 1 : base_component.h_samp_factor;
754
9.52k
  const int v_group = is_interleaved ? 1 : base_component.v_samp_factor;
755
9.52k
  const int MCUs_per_row =
756
9.52k
      DivCeil(jpg.width * h_group, 8 * jpg.max_h_samp_factor);
757
9.52k
  const int MCU_rows = DivCeil(jpg.height * v_group, 8 * jpg.max_v_samp_factor);
758
9.52k
  const bool is_progressive = state->is_progressive;
759
9.52k
  const int Al = is_progressive ? scan_info.Al : 0;
760
9.52k
  const int Ss = is_progressive ? scan_info.Ss : 0;
761
9.52k
  const int Se = is_progressive ? scan_info.Se : 63;
762
763
  // DC-only is defined by [0..0] spectral range.
764
9.52k
  const bool want_ac = ((Ss != 0) || (Se != 0));
765
9.52k
  const bool complete_ac = (parsing_state.stage == Stage::DONE);
766
9.52k
  const bool has_ac =
767
9.52k
      complete_ac || HasSection(&parsing_state, kBrunsliACDataTag);
768
9.52k
  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.52k
  const bool complete_dc = has_ac;
774
9.52k
  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.52k
  const int last_mcu_y =
778
9.52k
      complete ? MCU_rows : parsing_state.internal->ac_dc.next_mcu_y * v_group;
779
780
447k
  for (; ss.mcu_y < last_mcu_y; ++ss.mcu_y) {
781
3.60M
    for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
782
      // Possibly emit a restart marker.
783
3.16M
      if (restart_interval > 0 && ss.restarts_to_go == 0) {
784
485k
        Flush(coding_state, bw);
785
485k
        if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
786
52
          return SerializationStatus::ERROR;
787
52
        }
788
485k
        EmitMarker(bw, 0xD0 + ss.next_restart_marker);
789
485k
        ss.next_restart_marker += 1;
790
485k
        ss.next_restart_marker &= 0x7;
791
485k
        ss.restarts_to_go = restart_interval;
792
485k
        memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
793
485k
      }
794
      // Encode one MCU
795
10.1M
      for (size_t i = 0; i < scan_info.num_components; ++i) {
796
6.95M
        const JPEGComponentScanInfo& si = scan_info.components[i];
797
6.95M
        const JPEGComponent& c = jpg.components[si.comp_idx];
798
6.95M
        const HuffmanCodeTable& dc_huff = state->dc_huff_table[si.dc_tbl_idx];
799
6.95M
        const HuffmanCodeTable& ac_huff = state->ac_huff_table[si.ac_tbl_idx];
800
6.95M
        int n_blocks_y = is_interleaved ? c.v_samp_factor : 1;
801
6.95M
        int n_blocks_x = is_interleaved ? c.h_samp_factor : 1;
802
31.8M
        for (int iy = 0; iy < n_blocks_y; ++iy) {
803
104M
          for (int ix = 0; ix < n_blocks_x; ++ix) {
804
79.9M
            int block_y = ss.mcu_y * n_blocks_y + iy;
805
79.9M
            int block_x = mcu_x * n_blocks_x + ix;
806
79.9M
            int block_idx = block_y * c.width_in_blocks + block_x;
807
79.9M
            if (ss.block_scan_index == ss.next_reset_point) {
808
32.1k
              Flush(coding_state, bw);
809
32.1k
              ss.next_reset_point = get_next_reset_point();
810
32.1k
            }
811
79.9M
            int num_zero_runs = 0;
812
79.9M
            if (ss.block_scan_index == ss.next_extra_zero_run_index) {
813
13.4k
              num_zero_runs = scan_info.extra_zero_runs[ss.extra_zero_runs_pos]
814
13.4k
                                  .num_extra_zero_runs;
815
13.4k
              ++ss.extra_zero_runs_pos;
816
13.4k
              ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
817
13.4k
            }
818
79.9M
            const coeff_t* coeffs = &c.coeffs[block_idx << 6];
819
79.9M
            bool ok;
820
79.9M
            if (kMode == 0) {
821
8.30M
              ok = EncodeDCTBlockSequential(coeffs, dc_huff, ac_huff,
822
8.30M
                                            num_zero_runs,
823
8.30M
                                            ss.last_dc_coeff + si.comp_idx, bw);
824
71.6M
            } else if (kMode == 1) {
825
18.8M
              ok = EncodeDCTBlockProgressive(
826
18.8M
                  coeffs, dc_huff, ac_huff, Ss, Se, Al, num_zero_runs,
827
18.8M
                  coding_state, ss.last_dc_coeff + si.comp_idx, bw);
828
52.8M
            } else {
829
52.8M
              ok = EncodeRefinementBits(coeffs, ac_huff, Ss, Se, Al,
830
52.8M
                                        coding_state, bw);
831
52.8M
            }
832
79.9M
            if (!ok) return SerializationStatus::ERROR;
833
79.9M
            ++ss.block_scan_index;
834
79.9M
          }
835
24.9M
        }
836
6.95M
      }
837
3.16M
      --ss.restarts_to_go;
838
3.16M
    }
839
438k
  }
840
9.47k
  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.47k
  Flush(coding_state, bw);
845
9.47k
  if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
846
48
    return SerializationStatus::ERROR;
847
48
  }
848
9.42k
  BitWriterFinish(bw);
849
9.42k
  ss.stage = EncodeScanState::HEAD;
850
9.42k
  state->scan_index++;
851
9.42k
  if (!bw->healthy) return SerializationStatus::ERROR;
852
853
2.14k
  return SerializationStatus::DONE;
854
9.42k
}
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.52k
                                                  SerializationState* state) {
701
1.52k
  const JPEGScanInfo& scan_info = jpg.scan_info[state->scan_index];
702
1.52k
  EncodeScanState& ss = state->scan_state;
703
704
1.52k
  const int restart_interval =
705
1.52k
      state->seen_dri_marker ? jpg.restart_interval : 0;
706
707
1.52k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
1.52k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
1.52k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
1.52k
    } else {
711
1.52k
      return -1;
712
1.52k
    }
713
1.52k
  };
714
715
1.52k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
1.52k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
1.52k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
1.52k
    } else {
719
1.52k
      return -1;
720
1.52k
    }
721
1.52k
  };
722
723
1.52k
  if (ss.stage == EncodeScanState::HEAD) {
724
1.52k
    if (!EncodeSOS(jpg, scan_info, state)) return SerializationStatus::ERROR;
725
1.45k
    BitWriterInit(&ss.bw, &state->output_queue);
726
1.45k
    DCTCodingStateInit(&ss.coding_state);
727
1.45k
    ss.restarts_to_go = restart_interval;
728
1.45k
    ss.next_restart_marker = 0;
729
1.45k
    ss.block_scan_index = 0;
730
1.45k
    ss.extra_zero_runs_pos = 0;
731
1.45k
    ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
732
1.45k
    ss.next_reset_point_pos = 0;
733
1.45k
    ss.next_reset_point = get_next_reset_point();
734
1.45k
    ss.mcu_y = 0;
735
1.45k
    memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
736
1.45k
    ss.stage = EncodeScanState::BODY;
737
1.45k
  }
738
1.45k
  BitWriter* bw = &ss.bw;
739
1.45k
  DCTCodingState* coding_state = &ss.coding_state;
740
741
1.45k
  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.45k
  const bool is_interleaved = (scan_info.num_components > 1);
746
1.45k
  const JPEGComponent& base_component =
747
1.45k
      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.45k
  const int h_group = is_interleaved ? 1 : base_component.h_samp_factor;
754
1.45k
  const int v_group = is_interleaved ? 1 : base_component.v_samp_factor;
755
1.45k
  const int MCUs_per_row =
756
1.45k
      DivCeil(jpg.width * h_group, 8 * jpg.max_h_samp_factor);
757
1.45k
  const int MCU_rows = DivCeil(jpg.height * v_group, 8 * jpg.max_v_samp_factor);
758
1.45k
  const bool is_progressive = state->is_progressive;
759
1.45k
  const int Al = is_progressive ? scan_info.Al : 0;
760
1.45k
  const int Ss = is_progressive ? scan_info.Ss : 0;
761
1.45k
  const int Se = is_progressive ? scan_info.Se : 63;
762
763
  // DC-only is defined by [0..0] spectral range.
764
1.45k
  const bool want_ac = ((Ss != 0) || (Se != 0));
765
1.45k
  const bool complete_ac = (parsing_state.stage == Stage::DONE);
766
1.45k
  const bool has_ac =
767
1.45k
      complete_ac || HasSection(&parsing_state, kBrunsliACDataTag);
768
1.45k
  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.45k
  const bool complete_dc = has_ac;
774
1.45k
  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.45k
  const int last_mcu_y =
778
1.45k
      complete ? MCU_rows : parsing_state.internal->ac_dc.next_mcu_y * v_group;
779
780
133k
  for (; ss.mcu_y < last_mcu_y; ++ss.mcu_y) {
781
852k
    for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
782
      // Possibly emit a restart marker.
783
720k
      if (restart_interval > 0 && ss.restarts_to_go == 0) {
784
177k
        Flush(coding_state, bw);
785
177k
        if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
786
17
          return SerializationStatus::ERROR;
787
17
        }
788
177k
        EmitMarker(bw, 0xD0 + ss.next_restart_marker);
789
177k
        ss.next_restart_marker += 1;
790
177k
        ss.next_restart_marker &= 0x7;
791
177k
        ss.restarts_to_go = restart_interval;
792
177k
        memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
793
177k
      }
794
      // Encode one MCU
795
2.14M
      for (size_t i = 0; i < scan_info.num_components; ++i) {
796
1.42M
        const JPEGComponentScanInfo& si = scan_info.components[i];
797
1.42M
        const JPEGComponent& c = jpg.components[si.comp_idx];
798
1.42M
        const HuffmanCodeTable& dc_huff = state->dc_huff_table[si.dc_tbl_idx];
799
1.42M
        const HuffmanCodeTable& ac_huff = state->ac_huff_table[si.ac_tbl_idx];
800
1.42M
        int n_blocks_y = is_interleaved ? c.v_samp_factor : 1;
801
1.42M
        int n_blocks_x = is_interleaved ? c.h_samp_factor : 1;
802
4.53M
        for (int iy = 0; iy < n_blocks_y; ++iy) {
803
11.4M
          for (int ix = 0; ix < n_blocks_x; ++ix) {
804
8.30M
            int block_y = ss.mcu_y * n_blocks_y + iy;
805
8.30M
            int block_x = mcu_x * n_blocks_x + ix;
806
8.30M
            int block_idx = block_y * c.width_in_blocks + block_x;
807
8.30M
            if (ss.block_scan_index == ss.next_reset_point) {
808
1.46k
              Flush(coding_state, bw);
809
1.46k
              ss.next_reset_point = get_next_reset_point();
810
1.46k
            }
811
8.30M
            int num_zero_runs = 0;
812
8.30M
            if (ss.block_scan_index == ss.next_extra_zero_run_index) {
813
2.20k
              num_zero_runs = scan_info.extra_zero_runs[ss.extra_zero_runs_pos]
814
2.20k
                                  .num_extra_zero_runs;
815
2.20k
              ++ss.extra_zero_runs_pos;
816
2.20k
              ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
817
2.20k
            }
818
8.30M
            const coeff_t* coeffs = &c.coeffs[block_idx << 6];
819
8.30M
            bool ok;
820
8.30M
            if (kMode == 0) {
821
8.30M
              ok = EncodeDCTBlockSequential(coeffs, dc_huff, ac_huff,
822
8.30M
                                            num_zero_runs,
823
8.30M
                                            ss.last_dc_coeff + si.comp_idx, bw);
824
8.30M
            } 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
8.30M
            if (!ok) return SerializationStatus::ERROR;
833
8.30M
            ++ss.block_scan_index;
834
8.30M
          }
835
3.10M
        }
836
1.42M
      }
837
720k
      --ss.restarts_to_go;
838
720k
    }
839
132k
  }
840
1.43k
  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.43k
  Flush(coding_state, bw);
845
1.43k
  if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
846
18
    return SerializationStatus::ERROR;
847
18
  }
848
1.42k
  BitWriterFinish(bw);
849
1.42k
  ss.stage = EncodeScanState::HEAD;
850
1.42k
  state->scan_index++;
851
1.42k
  if (!bw->healthy) return SerializationStatus::ERROR;
852
853
307
  return SerializationStatus::DONE;
854
1.42k
}
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.02k
                                                  SerializationState* state) {
701
3.02k
  const JPEGScanInfo& scan_info = jpg.scan_info[state->scan_index];
702
3.02k
  EncodeScanState& ss = state->scan_state;
703
704
3.02k
  const int restart_interval =
705
3.02k
      state->seen_dri_marker ? jpg.restart_interval : 0;
706
707
3.02k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
3.02k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
3.02k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
3.02k
    } else {
711
3.02k
      return -1;
712
3.02k
    }
713
3.02k
  };
714
715
3.02k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
3.02k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
3.02k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
3.02k
    } else {
719
3.02k
      return -1;
720
3.02k
    }
721
3.02k
  };
722
723
3.02k
  if (ss.stage == EncodeScanState::HEAD) {
724
3.02k
    if (!EncodeSOS(jpg, scan_info, state)) return SerializationStatus::ERROR;
725
2.98k
    BitWriterInit(&ss.bw, &state->output_queue);
726
2.98k
    DCTCodingStateInit(&ss.coding_state);
727
2.98k
    ss.restarts_to_go = restart_interval;
728
2.98k
    ss.next_restart_marker = 0;
729
2.98k
    ss.block_scan_index = 0;
730
2.98k
    ss.extra_zero_runs_pos = 0;
731
2.98k
    ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
732
2.98k
    ss.next_reset_point_pos = 0;
733
2.98k
    ss.next_reset_point = get_next_reset_point();
734
2.98k
    ss.mcu_y = 0;
735
2.98k
    memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
736
2.98k
    ss.stage = EncodeScanState::BODY;
737
2.98k
  }
738
2.98k
  BitWriter* bw = &ss.bw;
739
2.98k
  DCTCodingState* coding_state = &ss.coding_state;
740
741
2.98k
  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
2.98k
  const bool is_interleaved = (scan_info.num_components > 1);
746
2.98k
  const JPEGComponent& base_component =
747
2.98k
      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
2.98k
  const int h_group = is_interleaved ? 1 : base_component.h_samp_factor;
754
2.98k
  const int v_group = is_interleaved ? 1 : base_component.v_samp_factor;
755
2.98k
  const int MCUs_per_row =
756
2.98k
      DivCeil(jpg.width * h_group, 8 * jpg.max_h_samp_factor);
757
2.98k
  const int MCU_rows = DivCeil(jpg.height * v_group, 8 * jpg.max_v_samp_factor);
758
2.98k
  const bool is_progressive = state->is_progressive;
759
2.98k
  const int Al = is_progressive ? scan_info.Al : 0;
760
2.98k
  const int Ss = is_progressive ? scan_info.Ss : 0;
761
2.98k
  const int Se = is_progressive ? scan_info.Se : 63;
762
763
  // DC-only is defined by [0..0] spectral range.
764
2.98k
  const bool want_ac = ((Ss != 0) || (Se != 0));
765
2.98k
  const bool complete_ac = (parsing_state.stage == Stage::DONE);
766
2.98k
  const bool has_ac =
767
2.98k
      complete_ac || HasSection(&parsing_state, kBrunsliACDataTag);
768
2.98k
  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
2.98k
  const bool complete_dc = has_ac;
774
2.98k
  const bool complete = want_ac ? complete_ac : complete_dc;
775
  // When "incomplete" |ac_dc| tracks information about current ("incomplete")
776
  // band parsing progress.
777
2.98k
  const int last_mcu_y =
778
2.98k
      complete ? MCU_rows : parsing_state.internal->ac_dc.next_mcu_y * v_group;
779
780
127k
  for (; ss.mcu_y < last_mcu_y; ++ss.mcu_y) {
781
840k
    for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
782
      // Possibly emit a restart marker.
783
715k
      if (restart_interval > 0 && ss.restarts_to_go == 0) {
784
134k
        Flush(coding_state, bw);
785
134k
        if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
786
23
          return SerializationStatus::ERROR;
787
23
        }
788
134k
        EmitMarker(bw, 0xD0 + ss.next_restart_marker);
789
134k
        ss.next_restart_marker += 1;
790
134k
        ss.next_restart_marker &= 0x7;
791
134k
        ss.restarts_to_go = restart_interval;
792
134k
        memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
793
134k
      }
794
      // Encode one MCU
795
2.58M
      for (size_t i = 0; i < scan_info.num_components; ++i) {
796
1.87M
        const JPEGComponentScanInfo& si = scan_info.components[i];
797
1.87M
        const JPEGComponent& c = jpg.components[si.comp_idx];
798
1.87M
        const HuffmanCodeTable& dc_huff = state->dc_huff_table[si.dc_tbl_idx];
799
1.87M
        const HuffmanCodeTable& ac_huff = state->ac_huff_table[si.ac_tbl_idx];
800
1.87M
        int n_blocks_y = is_interleaved ? c.v_samp_factor : 1;
801
1.87M
        int n_blocks_x = is_interleaved ? c.h_samp_factor : 1;
802
7.74M
        for (int iy = 0; iy < n_blocks_y; ++iy) {
803
24.6M
          for (int ix = 0; ix < n_blocks_x; ++ix) {
804
18.8M
            int block_y = ss.mcu_y * n_blocks_y + iy;
805
18.8M
            int block_x = mcu_x * n_blocks_x + ix;
806
18.8M
            int block_idx = block_y * c.width_in_blocks + block_x;
807
18.8M
            if (ss.block_scan_index == ss.next_reset_point) {
808
11.4k
              Flush(coding_state, bw);
809
11.4k
              ss.next_reset_point = get_next_reset_point();
810
11.4k
            }
811
18.8M
            int num_zero_runs = 0;
812
18.8M
            if (ss.block_scan_index == ss.next_extra_zero_run_index) {
813
9.07k
              num_zero_runs = scan_info.extra_zero_runs[ss.extra_zero_runs_pos]
814
9.07k
                                  .num_extra_zero_runs;
815
9.07k
              ++ss.extra_zero_runs_pos;
816
9.07k
              ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
817
9.07k
            }
818
18.8M
            const coeff_t* coeffs = &c.coeffs[block_idx << 6];
819
18.8M
            bool ok;
820
18.8M
            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.8M
            } else if (kMode == 1) {
825
18.8M
              ok = EncodeDCTBlockProgressive(
826
18.8M
                  coeffs, dc_huff, ac_huff, Ss, Se, Al, num_zero_runs,
827
18.8M
                  coding_state, ss.last_dc_coeff + si.comp_idx, bw);
828
18.8M
            } else {
829
0
              ok = EncodeRefinementBits(coeffs, ac_huff, Ss, Se, Al,
830
0
                                        coding_state, bw);
831
0
            }
832
18.8M
            if (!ok) return SerializationStatus::ERROR;
833
18.8M
            ++ss.block_scan_index;
834
18.8M
          }
835
5.87M
        }
836
1.87M
      }
837
715k
      --ss.restarts_to_go;
838
715k
    }
839
124k
  }
840
2.95k
  if (ss.mcu_y < MCU_rows) {
841
0
    if (!bw->healthy) return SerializationStatus::ERROR;
842
0
    return SerializationStatus::NEEDS_MORE_INPUT;
843
0
  }
844
2.95k
  Flush(coding_state, bw);
845
2.95k
  if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
846
9
    return SerializationStatus::ERROR;
847
9
  }
848
2.94k
  BitWriterFinish(bw);
849
2.94k
  ss.stage = EncodeScanState::HEAD;
850
2.94k
  state->scan_index++;
851
2.94k
  if (!bw->healthy) return SerializationStatus::ERROR;
852
853
749
  return SerializationStatus::DONE;
854
2.94k
}
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.24k
                                                  SerializationState* state) {
701
5.24k
  const JPEGScanInfo& scan_info = jpg.scan_info[state->scan_index];
702
5.24k
  EncodeScanState& ss = state->scan_state;
703
704
5.24k
  const int restart_interval =
705
5.24k
      state->seen_dri_marker ? jpg.restart_interval : 0;
706
707
5.24k
  const auto get_next_extra_zero_run_index = [&ss, &scan_info]() -> int {
708
5.24k
    if (ss.extra_zero_runs_pos < scan_info.extra_zero_runs.size()) {
709
5.24k
      return scan_info.extra_zero_runs[ss.extra_zero_runs_pos].block_idx;
710
5.24k
    } else {
711
5.24k
      return -1;
712
5.24k
    }
713
5.24k
  };
714
715
5.24k
  const auto get_next_reset_point = [&ss, &scan_info]() -> int {
716
5.24k
    if (ss.next_reset_point_pos < scan_info.reset_points.size()) {
717
5.24k
      return scan_info.reset_points[ss.next_reset_point_pos++];
718
5.24k
    } else {
719
5.24k
      return -1;
720
5.24k
    }
721
5.24k
  };
722
723
5.24k
  if (ss.stage == EncodeScanState::HEAD) {
724
5.24k
    if (!EncodeSOS(jpg, scan_info, state)) return SerializationStatus::ERROR;
725
5.09k
    BitWriterInit(&ss.bw, &state->output_queue);
726
5.09k
    DCTCodingStateInit(&ss.coding_state);
727
5.09k
    ss.restarts_to_go = restart_interval;
728
5.09k
    ss.next_restart_marker = 0;
729
5.09k
    ss.block_scan_index = 0;
730
5.09k
    ss.extra_zero_runs_pos = 0;
731
5.09k
    ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
732
5.09k
    ss.next_reset_point_pos = 0;
733
5.09k
    ss.next_reset_point = get_next_reset_point();
734
5.09k
    ss.mcu_y = 0;
735
5.09k
    memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
736
5.09k
    ss.stage = EncodeScanState::BODY;
737
5.09k
  }
738
5.09k
  BitWriter* bw = &ss.bw;
739
5.09k
  DCTCodingState* coding_state = &ss.coding_state;
740
741
5.09k
  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.09k
  const bool is_interleaved = (scan_info.num_components > 1);
746
5.09k
  const JPEGComponent& base_component =
747
5.09k
      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.09k
  const int h_group = is_interleaved ? 1 : base_component.h_samp_factor;
754
5.09k
  const int v_group = is_interleaved ? 1 : base_component.v_samp_factor;
755
5.09k
  const int MCUs_per_row =
756
5.09k
      DivCeil(jpg.width * h_group, 8 * jpg.max_h_samp_factor);
757
5.09k
  const int MCU_rows = DivCeil(jpg.height * v_group, 8 * jpg.max_v_samp_factor);
758
5.09k
  const bool is_progressive = state->is_progressive;
759
5.09k
  const int Al = is_progressive ? scan_info.Al : 0;
760
5.09k
  const int Ss = is_progressive ? scan_info.Ss : 0;
761
5.09k
  const int Se = is_progressive ? scan_info.Se : 63;
762
763
  // DC-only is defined by [0..0] spectral range.
764
5.09k
  const bool want_ac = ((Ss != 0) || (Se != 0));
765
5.09k
  const bool complete_ac = (parsing_state.stage == Stage::DONE);
766
5.09k
  const bool has_ac =
767
5.09k
      complete_ac || HasSection(&parsing_state, kBrunsliACDataTag);
768
5.09k
  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.09k
  const bool complete_dc = has_ac;
774
5.09k
  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.09k
  const int last_mcu_y =
778
5.09k
      complete ? MCU_rows : parsing_state.internal->ac_dc.next_mcu_y * v_group;
779
780
186k
  for (; ss.mcu_y < last_mcu_y; ++ss.mcu_y) {
781
1.91M
    for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
782
      // Possibly emit a restart marker.
783
1.73M
      if (restart_interval > 0 && ss.restarts_to_go == 0) {
784
173k
        Flush(coding_state, bw);
785
173k
        if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
786
12
          return SerializationStatus::ERROR;
787
12
        }
788
173k
        EmitMarker(bw, 0xD0 + ss.next_restart_marker);
789
173k
        ss.next_restart_marker += 1;
790
173k
        ss.next_restart_marker &= 0x7;
791
173k
        ss.restarts_to_go = restart_interval;
792
173k
        memset(ss.last_dc_coeff, 0, sizeof(ss.last_dc_coeff));
793
173k
      }
794
      // Encode one MCU
795
5.38M
      for (size_t i = 0; i < scan_info.num_components; ++i) {
796
3.65M
        const JPEGComponentScanInfo& si = scan_info.components[i];
797
3.65M
        const JPEGComponent& c = jpg.components[si.comp_idx];
798
3.65M
        const HuffmanCodeTable& dc_huff = state->dc_huff_table[si.dc_tbl_idx];
799
3.65M
        const HuffmanCodeTable& ac_huff = state->ac_huff_table[si.ac_tbl_idx];
800
3.65M
        int n_blocks_y = is_interleaved ? c.v_samp_factor : 1;
801
3.65M
        int n_blocks_x = is_interleaved ? c.h_samp_factor : 1;
802
19.6M
        for (int iy = 0; iy < n_blocks_y; ++iy) {
803
68.8M
          for (int ix = 0; ix < n_blocks_x; ++ix) {
804
52.8M
            int block_y = ss.mcu_y * n_blocks_y + iy;
805
52.8M
            int block_x = mcu_x * n_blocks_x + ix;
806
52.8M
            int block_idx = block_y * c.width_in_blocks + block_x;
807
52.8M
            if (ss.block_scan_index == ss.next_reset_point) {
808
19.2k
              Flush(coding_state, bw);
809
19.2k
              ss.next_reset_point = get_next_reset_point();
810
19.2k
            }
811
52.8M
            int num_zero_runs = 0;
812
52.8M
            if (ss.block_scan_index == ss.next_extra_zero_run_index) {
813
2.12k
              num_zero_runs = scan_info.extra_zero_runs[ss.extra_zero_runs_pos]
814
2.12k
                                  .num_extra_zero_runs;
815
2.12k
              ++ss.extra_zero_runs_pos;
816
2.12k
              ss.next_extra_zero_run_index = get_next_extra_zero_run_index();
817
2.12k
            }
818
52.8M
            const coeff_t* coeffs = &c.coeffs[block_idx << 6];
819
52.8M
            bool ok;
820
52.8M
            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.8M
            } 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.8M
            } else {
829
52.8M
              ok = EncodeRefinementBits(coeffs, ac_huff, Ss, Se, Al,
830
52.8M
                                        coding_state, bw);
831
52.8M
            }
832
52.8M
            if (!ok) return SerializationStatus::ERROR;
833
52.8M
            ++ss.block_scan_index;
834
52.8M
          }
835
15.9M
        }
836
3.65M
      }
837
1.73M
      --ss.restarts_to_go;
838
1.73M
    }
839
181k
  }
840
5.08k
  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.08k
  Flush(coding_state, bw);
845
5.08k
  if (!JumpToByteBoundary(bw, &state->pad_bits, state->pad_bits_end)) {
846
21
    return SerializationStatus::ERROR;
847
21
  }
848
5.05k
  BitWriterFinish(bw);
849
5.05k
  ss.stage = EncodeScanState::HEAD;
850
5.05k
  state->scan_index++;
851
5.05k
  if (!bw->healthy) return SerializationStatus::ERROR;
852
853
1.08k
  return SerializationStatus::DONE;
854
5.05k
}
855
856
static SerializationStatus BRUNSLI_INLINE
857
EncodeScan(const JPEGData& jpg, const State& parsing_state,
858
9.78k
           SerializationState* state) {
859
9.78k
  const JPEGScanInfo& scan_info = jpg.scan_info[state->scan_index];
860
9.78k
  const bool is_progressive = state->is_progressive;
861
9.78k
  const int Al = is_progressive ? scan_info.Al : 0;
862
9.78k
  const int Ah = is_progressive ? scan_info.Ah : 0;
863
9.78k
  const int Ss = is_progressive ? scan_info.Ss : 0;
864
9.78k
  const int Se = is_progressive ? scan_info.Se : 63;
865
9.78k
  const bool need_sequential =
866
9.78k
      !is_progressive || (Ah == 0 && Al == 0 && Ss == 0 && Se == 63);
867
9.78k
  if (need_sequential) {
868
1.52k
    return DoEncodeScan<0>(jpg, parsing_state, state);
869
8.26k
  } else if (Ah == 0) {
870
3.02k
    return DoEncodeScan<1>(jpg, parsing_state, state);
871
5.24k
  } else {
872
5.24k
    return DoEncodeScan<2>(jpg, parsing_state, state);
873
5.24k
  }
874
9.78k
}
875
876
SerializationStatus SerializeSection(uint8_t marker, const State& parsing_state,
877
                                     SerializationState* state,
878
65.8k
                                     const JPEGData& jpg) {
879
65.8k
  const auto to_status = [](bool result) {
880
55.7k
    return result ? SerializationStatus::DONE : SerializationStatus::ERROR;
881
55.7k
  };
882
  // TODO(eustas): add and use marker enum
883
65.8k
  switch (marker) {
884
6.92k
    case 0xC0:
885
8.87k
    case 0xC1:
886
18.0k
    case 0xC2:
887
20.7k
    case 0xC9:
888
23.0k
    case 0xCA:
889
23.0k
      return to_status(EncodeSOF(jpg, marker, state));
890
891
9.23k
    case 0xC4:
892
9.23k
      return to_status(EncodeDHT(jpg, state));
893
894
3.29k
    case 0xD0:
895
5.54k
    case 0xD1:
896
7.47k
    case 0xD2:
897
9.65k
    case 0xD3:
898
11.6k
    case 0xD4:
899
14.2k
    case 0xD5:
900
16.4k
    case 0xD6:
901
17.9k
    case 0xD7:
902
17.9k
      return to_status(EncodeRestart(marker, state));
903
904
650
    case 0xD9:
905
650
      return to_status(EncodeEOI(jpg, state));
906
907
9.78k
    case 0xDA:
908
9.78k
      return EncodeScan(jpg, parsing_state, state);
909
910
720
    case 0xDB:
911
720
      return to_status(EncodeDQT(jpg, state));
912
913
3.75k
    case 0xDD:
914
3.75k
      return to_status(EncodeDRI(jpg, state));
915
916
42
    case 0xE0:
917
55
    case 0xE1:
918
73
    case 0xE2:
919
82
    case 0xE3:
920
114
    case 0xE4:
921
130
    case 0xE5:
922
158
    case 0xE6:
923
190
    case 0xE7:
924
219
    case 0xE8:
925
238
    case 0xE9:
926
275
    case 0xEA:
927
295
    case 0xEB:
928
317
    case 0xEC:
929
339
    case 0xED:
930
356
    case 0xEE:
931
375
    case 0xEF:
932
375
      return to_status(EncodeAPP(jpg, marker, state));
933
934
13
    case 0xFE:
935
13
      return to_status(EncodeCOM(jpg, state));
936
937
44
    case 0xFF:
938
44
      return to_status(EncodeInterMarkerData(jpg, state));
939
940
259
    default:
941
259
      return SerializationStatus::ERROR;
942
65.8k
  }
943
65.8k
}
944
945
void PushOutput(std::deque<OutputChunk>* in, size_t* available_out,
946
75.7k
                uint8_t** next_out) {
947
145k
  while (*available_out > 0) {
948
    // No more data.
949
144k
    if (in->empty()) return;
950
69.3k
    OutputChunk& chunk = in->front();
951
69.3k
    size_t to_copy = std::min(*available_out, chunk.len);
952
69.3k
    if (to_copy > 0) {
953
68.6k
      memcpy(*next_out, chunk.next, to_copy);
954
68.6k
      *next_out += to_copy;
955
68.6k
      *available_out -= to_copy;
956
68.6k
      chunk.next += to_copy;
957
68.6k
      chunk.len -= to_copy;
958
68.6k
    }
959
69.3k
    if (chunk.len == 0) in->pop_front();
960
69.3k
  }
961
75.7k
}
962
963
}  // namespace
964
965
// Adaptor for old API users. Will be removed once new API will support proper
966
// streaming serialization.
967
8.95k
bool WriteJpeg(const JPEGData& jpg, JPEGOutput out) {
968
8.95k
  State state;
969
8.95k
  state.stage = Stage::DONE;
970
8.95k
  std::vector<uint8_t> buffer(16384);
971
9.33k
  while (true) {
972
9.33k
    uint8_t* next_out = buffer.data();
973
9.33k
    size_t available_out = buffer.size();
974
9.33k
    SerializationStatus status =
975
9.33k
        SerializeJpeg(&state, jpg, &available_out, &next_out);
976
9.33k
    if (status != SerializationStatus::DONE &&
977
8.67k
        status != SerializationStatus::NEEDS_MORE_OUTPUT) {
978
8.28k
      return false;
979
8.28k
    }
980
1.05k
    size_t to_write = buffer.size() - available_out;
981
1.05k
    if (!out.Write(buffer.data(), to_write)) return false;
982
1.05k
    if (status == SerializationStatus::DONE) return true;
983
1.05k
  }
984
8.95k
}
985
986
namespace internal {
987
namespace dec {
988
SerializationStatus SerializeJpeg(State* state, const JPEGData& jpg,
989
9.33k
                                  size_t* available_out, uint8_t** next_out) {
990
9.33k
  SerializationState& ss = state->internal->serialization;
991
992
75.7k
  const auto maybe_push_output = [&]() {
993
75.7k
    if (ss.stage != SerializationState::ERROR) {
994
75.7k
      PushOutput(&ss.output_queue, available_out, next_out);
995
75.7k
    }
996
75.7k
  };
997
998
  // Push remaining output from prevoius session.
999
9.33k
  maybe_push_output();
1000
1001
84.7k
  while (true) {
1002
84.7k
    switch (ss.stage) {
1003
8.95k
      case SerializationState::INIT: {
1004
        // If parsing is complete, serialization is possible.
1005
8.95k
        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
8.95k
        if (HasSection(state, kBrunsliDCDataTag) ||
1009
8.95k
            HasSection(state, kBrunsliACDataTag)) {
1010
0
          can_start_serialization = true;
1011
0
        }
1012
8.95k
        if (!can_start_serialization) {
1013
0
          return SerializationStatus::NEEDS_MORE_INPUT;
1014
0
        }
1015
        // JpegBypass is a very simple / special case.
1016
8.95k
        if (jpg.version == kFallbackVersion) {
1017
20
          if (jpg.original_jpg == nullptr) {
1018
2
            ss.stage = SerializationState::ERROR;
1019
2
            break;
1020
2
          }
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
18
          ss.output_queue.emplace_back(jpg.original_jpg, jpg.original_jpg_size);
1025
18
          ss.stage = SerializationState::DONE;
1026
18
          break;
1027
20
        }
1028
1029
        // Invalid mode - fallback + something else.
1030
8.93k
        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
8.93k
        if (jpg.marker_order.empty()) {
1039
0
          ss.stage = SerializationState::ERROR;
1040
0
          break;
1041
0
        }
1042
1043
8.93k
        ss.dc_huff_table.resize(kMaxHuffmanTables);
1044
8.93k
        ss.ac_huff_table.resize(kMaxHuffmanTables);
1045
8.93k
        if (jpg.has_zero_padding_bit) {
1046
456
          ss.pad_bits = jpg.padding_bits.data();
1047
456
          ss.pad_bits_end = ss.pad_bits + jpg.padding_bits.size();
1048
456
        }
1049
1050
8.93k
        EncodeSOI(&ss);
1051
8.93k
        maybe_push_output();
1052
8.93k
        ss.stage = SerializationState::SERIALIZE_SECTION;
1053
8.93k
        break;
1054
8.93k
      }
1055
1056
66.4k
      case SerializationState::SERIALIZE_SECTION: {
1057
66.4k
        if (ss.section_index >= jpg.marker_order.size()) {
1058
650
          ss.stage = SerializationState::DONE;
1059
650
          break;
1060
650
        }
1061
65.8k
        uint8_t marker = jpg.marker_order[ss.section_index];
1062
65.8k
        SerializationStatus status = SerializeSection(marker, *state, &ss, jpg);
1063
65.8k
        if (status == SerializationStatus::ERROR) {
1064
8.28k
          BRUNSLI_LOG_DEBUG() << "Failed to encode marker " << std::hex
1065
0
                              << marker << BRUNSLI_ENDL();
1066
8.28k
          ss.stage = SerializationState::ERROR;
1067
8.28k
          break;
1068
8.28k
        }
1069
57.5k
        maybe_push_output();
1070
57.5k
        if (status == SerializationStatus::NEEDS_MORE_INPUT) {
1071
0
          return SerializationStatus::NEEDS_MORE_INPUT;
1072
57.5k
        } else if (status != SerializationStatus::DONE) {
1073
0
          BRUNSLI_DCHECK(false);
1074
0
          ss.stage = SerializationState::ERROR;
1075
0
          break;
1076
0
        }
1077
57.5k
        ++ss.section_index;
1078
57.5k
        break;
1079
57.5k
      }
1080
1081
1.05k
      case SerializationState::DONE: {
1082
1.05k
        if (!ss.output_queue.empty()) {
1083
386
          return SerializationStatus::NEEDS_MORE_OUTPUT;
1084
668
        } else {
1085
668
          return SerializationStatus::DONE;
1086
668
        }
1087
1.05k
      }
1088
1089
8.28k
      default:
1090
8.28k
        return SerializationStatus::ERROR;
1091
84.7k
    }
1092
84.7k
  }
1093
9.33k
}
1094
}  // namespace dec
1095
}  // namespace internal
1096
1097
}  // namespace brunsli