Coverage Report

Created: 2026-01-09 06:49

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