FFmpeg
Loading...
Searching...
No Matches
jpeg2000_parser.c
Go to the documentation of this file.
1/*
2 * JPEG2000 parser
3 * Copyright (c) 2020 Gautam Ramakrishnan
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22/**
23 * @file
24 * JPEG2000 parser.
25 */
26
27#include "parser.h"
28#include "parser_internal.h"
29
30/* Whether frame is jp2 file or codestream
31*/
36
37typedef struct JPEG2000ParserContext {
39 uint64_t bytes_read;
40 uint64_t fheader_state;
41 uint32_t skip_bytes; // skip bytes inside codestream data
42 enum frame_type ft; // 1 if file, 2 if codestream
43 uint8_t fheader_read; // are we reading
46 uint8_t read_tp;
48 uint8_t skip_to_eoc;
50
52{
53 ParseContext *pc = &m->pc;
54
55 pc->frame_start_found= 0;
56 pc->state64 = 0;
57 m->bytes_read = 0;
58 m->ft = 0;
59 m->skipped_codestream = 0;
60 m->fheader_read = 0;
61 m->skip_bytes = 0;
62 m->read_tp = 0;
63 m->in_codestream = 0;
64 m->skip_to_eoc = 0;
65}
66
67/* Returns 1 if marker has any data which can be skipped
68*/
69static uint8_t info_marker(uint16_t marker)
70{
71 static const uint8_t lut[256] = {
72 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
73 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
74 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
75 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
76 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 0xFF4F
77 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
78 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
79 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
80 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
81 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xFF90 0xFF92 0xFF93
82 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
83 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
84 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
85 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, // 0xFFD9
86 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
87 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
88 };
89 return marker < 0xFF00 ? 0 : lut[marker & 0xFF];
90}
91
92/**
93 * Find the end of the current frame in the bitstream.
94 * @return the position of the first byte of the next frame, or -1
95 */
96static int find_frame_end(JPEG2000ParserContext *m, const uint8_t *buf, int buf_size)
97{
98 ParseContext *pc= &m->pc;
99 int i;
100 uint64_t state64 = pc->state64;
101 uint64_t bytes_read = m->bytes_read;
102
103 if (buf_size == 0) {
104 return 0;
105 }
106
107 for (i = 0; i < buf_size; i++) {
108 state64 = state64 << 8 | buf[i];
109 bytes_read++;
110 if (m->skip_bytes) {
111 // handle long skips
112 if (m->skip_bytes > 8) {
113 // need -9 else buf_size - i == 8 ==> i == buf_size after this,
114 // and thus i == buf_size + 1 after the loop
115 int skip = FFMIN(FFMIN((int64_t)m->skip_bytes - 8, buf_size - i - 9), INT_MAX);
116 if (skip > 0) {
117 m->skip_bytes -= skip;
118 i += skip;
119 bytes_read += skip;
120 }
121 }
122 m->skip_bytes--;
123 continue;
124 }
125 if (m->read_tp) { // Find out how many bytes inside Tile part codestream to skip.
126 if (m->read_tp == 1) {
127 m->skip_bytes = (state64 & 0xFFFFFFFF) > 9 ?
128 (state64 & 0xFFFFFFFF) - 9 : 0;
129 }
130 m->read_tp--;
131 continue;
132 }
133 if (m->skip_to_eoc) {
134 if ((state64 & 0xFFFF) == 0xFF91)
135 m->skip_bytes = 5;
136 if ((state64 & 0xFFFF) != 0xFFD9)
137 continue;
138 }
139 if (m->fheader_read) {
140 if (m->fheader_read == 1) {
141 if (state64 == 0x6A5020200D0A870A) { // JP2 signature box value.
142 if (pc->frame_start_found) {
143 pc->frame_start_found = 0;
144 reset_context(m);
145 return i - 11;
146 } else {
147 pc->frame_start_found = 1;
148 m->ft = jp2_file;
149 }
150 }
151 }
152 m->fheader_read--;
153 }
154 if ((state64 & 0xFFFFFFFF) == 0x0000000C && bytes_read >= 3) { // Indicates start of JP2 file. Check signature next.
155 m->fheader_read = 8;
156 } else if ((state64 & 0xFFFF) == 0xFF4F) {
157 m->in_codestream = 1;
158 if (!pc->frame_start_found) {
159 pc->frame_start_found = 1;
160 m->ft = j2k_cstream;
161 } else if (pc->frame_start_found && m->ft == jp2_file && m->skipped_codestream) {
162 reset_context(m);
163 return i - 1;
164 }
165 } else if ((state64 & 0xFFFF) == 0xFFD9) {
166 if (pc->frame_start_found && m->ft == jp2_file) {
167 m->skipped_codestream = 1;
168 } else if (pc->frame_start_found && m->ft == j2k_cstream) {
169 reset_context(m);
170 return i + 1; // End of frame detected, return frame size.
171 }
172 m->in_codestream = 0;
173 m->skip_to_eoc = 0;
174 } else if (m->in_codestream) {
175 if ((state64 & 0xFFFF) == 0xFF90) { // Are we in tile part header?
176 m->read_tp = 8;
177 } else if ((state64 & 0xFFFF) == 0xFF93) {
178 m->skip_to_eoc = 1;
179 } else if (info_marker((state64 & 0xFFFF0000)>>16) && pc->frame_start_found && (state64 & 0xFFFF)) {
180 // Calculate number of bytes to skip to get to end of the next marker.
181 m->skip_bytes = (state64 & 0xFFFF)-1;
182
183 // If the next marker is an info marker, skip to the end of of the marker length.
184 if (i + m->skip_bytes + 1 < buf_size) {
185 uint32_t next_state = (buf[i + m->skip_bytes] << 8) | buf[i + m->skip_bytes + 1];
186 if (info_marker(next_state)) {
187 // Skip an additional 2 bytes to get to the end of the marker length.
188 m->skip_bytes += 2;
189 }
190 }
191 }
192 }
193 }
194
195 pc->state64 = state64;
196 m->bytes_read = bytes_read;
197 return END_NOT_FOUND;
198}
199
201 AVCodecContext *avctx,
202 const uint8_t **poutbuf, int *poutbuf_size,
203 const uint8_t *buf, int buf_size)
204{
205 JPEG2000ParserContext *m = s->priv_data;
206 ParseContext *pc = &m->pc;
207 int next;
208
209 if(s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
210 next= buf_size;
211 } else {
212 next= find_frame_end(m, buf, buf_size);
213
214 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
215 *poutbuf = NULL;
216 *poutbuf_size = 0;
217 return buf_size;
218 }
219 }
220
221 *poutbuf = buf;
222 *poutbuf_size = buf_size;
223 return next;
224}
225
static int parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size)
Definition apv_parser.c:92
#define PARSER_FLAG_COMPLETE_FRAMES
Definition avcodec.h:2672
static void BS_FUNC skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
@ AV_CODEC_ID_JPEG2000
Definition codec_id.h:138
frame_type
@ j2k_cstream
@ jp2_file
static uint8_t info_marker(uint16_t marker)
static void reset_context(JPEG2000ParserContext *m)
const FFCodecParser ff_jpeg2000_parser
static int jpeg2000_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size)
static int find_frame_end(JPEG2000ParserContext *m, const uint8_t *buf, int buf_size)
Find the end of the current frame in the bitstream.
av_cold void CBS_FUNC close(CodedBitstreamContext **ctx_ptr)
Close a context and free all internal state.
Definition cbs.c:118
#define FFMIN(a, b)
Definition macros.h:49
av_cold void ff_parse_close(AVCodecParserContext *s)
Definition parser.c:300
int ff_combine_frame(ParseContext *pc, int next, const uint8_t **buf, int *buf_size)
Combine the (truncated) bitstream to a complete frame.
Definition parser.c:213
#define END_NOT_FOUND
Definition parser.h:40
#define PARSER_CODEC_LIST(...)
main external API structure.
Definition avcodec.h:443
uint64_t state64
contains the last 8 bytes in MSB order
Definition parser.h:37
int frame_start_found
Definition parser.h:34