Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkJpegSegmentScan.h
Go to the documentation of this file.
1/*
2 * Copyright 2023 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkJpegSegmentScan_codec_DEFINED
9#define SkJpegSegmentScan_codec_DEFINED
10
13
14#include <cstddef>
15#include <cstdint>
16#include <memory>
17#include <vector>
18
19class SkData;
20class SkStream;
21
22/*
23 * A JPEG segment.
24 */
26 // The offset in bytes from the initial position to where this segment starts.
27 size_t offset = 0;
28 // The second byte of the marker code, which determines the segment type.
29 uint8_t marker = 0;
30 // The length of the parameters for this segment (including the two bytes used to specify
31 // the length).
32 uint16_t parameterLength = 0;
33};
34
35/*
36 * Class for scanning JPEG data. The JPEG format consists of a sequence of segments that begin with
37 * a marker, with entropy-coded data in between.
38 */
40public:
41 SkJpegSegmentScanner(uint8_t stopMarker = kJpegMarkerEndOfImage);
42
43 bool isDone() const { return fState == State::kDone; }
44 bool hadError() const { return fState == State::kError; }
45
46 // Provide more bytes of data to the state machine.
47 void onBytes(const void* data, size_t size);
48
49 // Return the segments that have been retrieved so far. If an error was encountered, this will
50 // include all segments up to the error.
51 const std::vector<SkJpegSegment>& getSegments() const;
52
53 // Helper function to retrieve the parameters for a segment. ScannedData must be the data that
54 // was scanned to produce segment, starting at StartOfImage.
55 static sk_sp<SkData> GetParameters(const SkData* scannedData, const SkJpegSegment& segment);
56
57private:
58 // The scanner is a state machine. State transitions happen when a byte is read.
59 enum class State {
60 // The initial state, before we read the 0xFF,0xD8,0xFF JPEG signature.
61 kStartOfImageByte0,
62 // We have read the 0xFF of the JPEG signature.
63 kStartOfImageByte1,
64 // We have read the 0xFF,0xD8 of the JPEG signature. The next byte should be the 0xFF that
65 // completes the JPEG signature and starts the second marker (the one after StartOfImage).
66 kSecondMarkerByte0,
67 // We have read the full JPEG signature. The next byte should be the the second byte of the
68 // second marker.
69 kSecondMarkerByte1,
70 // We have read a marker that does not stand alone. The next byte is the first byte of the
71 // length of the parameters,
72 kSegmentParamLengthByte0,
73 // We have read the first byte of the length of the parameters (and it is stored in
74 // |fSegmentParamLengthByte0|). The next byte we read is the second byte of the length of
75 // the parameters.
76 kSegmentParamLengthByte1,
77 // We have read the full length of the parameters. The next |fSegmentParamBytesRemaining|
78 // bytes are the parameters.
79 kSegmentParam,
80 // We have read a marker and (optionally) its parameters, and we are now reading entropy-
81 // coded data. All subsequent bytes until we reach 0xFF are entropy-coded data.
82 kEntropyCodedData,
83 // We reached an 0xFF in entropy-coded data. If the next byte is 0x00 then we continue
84 // reading entropy-coded data. If the next byte is 0xFF then we are reading fill data.
85 // If the next byte is anything else then it is the second byte of a marker.
86 kEntropyCodedDataSentinel,
87 // We are reading fill data. If the next byte is 0xFF then we are still reading fill data,
88 // otherwise the next byte is the second byte of a marker.
89 kPostEntropyCodedDataFill,
90 // We reached |fStopMarker| and have stopped tracking our state.
91 kDone,
92 // We hit an error somewhere and have given up.
93 kError,
94 };
95 State fState = State::kStartOfImageByte0;
96
97 // Update state transition when a single byte is read.
98 void onByte(uint8_t byte);
99
100 // Perform the appropriate state transition for when a marker is read. This will set
101 // |fCurrentSegmentMarker| and |fCurrentSegmentOffset|, and potentially call saveCurrentSegment.
102 void onMarkerSecondByte(uint8_t byte);
103
104 // Add a new entry in |segments| for |fCurrentSegmentMarker| and offset |fCurrentSegmentOffset|
105 // and the specified length.
106 void saveCurrentSegment(uint16_t length);
107
108 static bool MarkerStandsAlone(uint8_t marker) {
109 // These markers are TEM (0x01), RSTm (0xD0 through 0xD7), SOI (0xD8), and
110 // EOI (0xD9). See section B.1.1.3, Marker assignments.
111 return marker == 0x01 || (marker >= 0xD0 && marker <= 0xD9);
112 }
113
114 // Stop tracking state when we hit this marker. If this is 0x00, then never stop.
115 const uint8_t fStopMarker;
116
117 // The number of bytes that have been processed so far.
118 size_t fOffset = 0;
119
120 // If |fState| is kSegmentParamLengthByte1, then this is the value of the the previous byte.
121 uint8_t fSegmentParamLengthByte0 = 0;
122
123 // If |fState| is kSegmentParam, then this is the number of bytes reamining in the current
124 // segment.
125 size_t fSegmentParamBytesRemaining = 0;
126
127 // The offset and marker for the segment started by the previous call to OnMarkerSecondByte.
128 // These are re-set when SaveCurrentSegment is called.
129 size_t fCurrentSegmentOffset = 0;
130 uint8_t fCurrentSegmentMarker = 0;
131
132 std::vector<SkJpegSegment> fSegments;
133};
134
135#endif
static const char marker[]
static constexpr uint8_t kJpegMarkerEndOfImage
const std::vector< SkJpegSegment > & getSegments() const
static sk_sp< SkData > GetParameters(const SkData *scannedData, const SkJpegSegment &segment)
void onBytes(const void *data, size_t size)
size_t length
uint16_t parameterLength