FFmpeg
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 
29 /* Whether frame is jp2 file or codestream
30 */
31 enum frame_type {
32  jp2_file = 1,
34 };
35 
36 typedef struct JPEG2000ParserContext {
38  uint64_t bytes_read;
39  uint64_t fheader_state;
40  uint32_t skip_bytes; // skip bytes inside codestream data
41  enum frame_type ft; // 1 if file, 2 if codestream
42  uint8_t fheader_read; // are we reading
45  uint8_t read_tp;
46  uint8_t in_codestream;
48 
49 static inline void reset_context(JPEG2000ParserContext *m)
50 {
51  ParseContext *pc = &m->pc;
52 
53  pc->frame_start_found= 0;
54  pc->state64 = 0;
55  m->bytes_read = 0;
56  m->ft = 0;
57  m->skipped_codestream = 0;
58  m->fheader_read = 0;
59  m->skip_bytes = 0;
60  m->read_tp = 0;
61  m->in_codestream = 0;
62 }
63 
64 /* Returns 1 if marker has any data which can be skipped
65 */
66 static uint8_t info_marker(uint16_t marker)
67 {
68  static const uint8_t lut[256] = {
69  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
70  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
71  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
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, 0, // 0xFF4F
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, 1,
77  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
78  0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xFF90 0xFF92 0xFF93
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  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
82  1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, // 0xFFD9
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  };
86  return marker < 0xFF00 ? 0 : lut[marker & 0xFF];
87 }
88 
89 /**
90  * Find the end of the current frame in the bitstream.
91  * @return the position of the first byte of the next frame, or -1
92  */
93 static int find_frame_end(JPEG2000ParserContext *m, const uint8_t *buf, int buf_size)
94 {
95  ParseContext *pc= &m->pc;
96  int i;
97  uint64_t state64 = pc->state64;
98  uint64_t bytes_read = m->bytes_read;
99 
100  if (buf_size == 0) {
101  return 0;
102  }
103 
104  for (i = 0; i < buf_size; i++) {
105  state64 = state64 << 8 | buf[i];
106  bytes_read++;
107  if (m->skip_bytes) {
108  // handle long skips
109  if (m->skip_bytes > 8) {
110  // need -9 else buf_size - i == 8 ==> i == buf_size after this,
111  // and thus i == buf_size + 1 after the loop
112  int skip = FFMIN(FFMIN((int64_t)m->skip_bytes - 8, buf_size - i - 9), INT_MAX);
113  if (skip > 0) {
114  m->skip_bytes -= skip;
115  i += skip;
116  bytes_read += skip;
117  }
118  }
119  m->skip_bytes--;
120  continue;
121  }
122  if (m->read_tp) { // Find out how many bytes inside Tile part codestream to skip.
123  if (m->read_tp == 1) {
124  m->skip_bytes = (state64 & 0xFFFFFFFF) - 9 > 0?
125  (state64 & 0xFFFFFFFF) - 9 : 0;
126  }
127  m->read_tp--;
128  continue;
129  }
130  if (m->fheader_read) {
131  if (m->fheader_read == 1) {
132  if (state64 == 0x6A5020200D0A870A) { // JP2 signature box value.
133  if (pc->frame_start_found) {
134  pc->frame_start_found = 0;
135  reset_context(m);
136  return i - 11;
137  } else {
138  pc->frame_start_found = 1;
139  m->ft = jp2_file;
140  }
141  }
142  }
143  m->fheader_read--;
144  }
145  if ((state64 & 0xFFFFFFFF) == 0x0000000C && bytes_read >= 3) { // Indicates start of JP2 file. Check signature next.
146  m->fheader_read = 8;
147  } else if ((state64 & 0xFFFF) == 0xFF4F) {
148  m->in_codestream = 1;
149  if (!pc->frame_start_found) {
150  pc->frame_start_found = 1;
151  m->ft = j2k_cstream;
152  } else if (pc->frame_start_found && m->ft == jp2_file && m->skipped_codestream) {
153  reset_context(m);
154  return i - 1;
155  }
156  } else if ((state64 & 0xFFFF) == 0xFFD9) {
157  if (pc->frame_start_found && m->ft == jp2_file) {
158  m->skipped_codestream = 1;
159  } else if (pc->frame_start_found && m->ft == j2k_cstream) {
160  reset_context(m);
161  return i + 1; // End of frame detected, return frame size.
162  }
163  m->in_codestream = 0;
164  } else if (m->in_codestream) {
165  if ((state64 & 0xFFFF) == 0xFF90) { // Are we in tile part header?
166  m->read_tp = 8;
167  } else if (info_marker((state64 & 0xFFFF0000)>>16) && pc->frame_start_found && (state64 & 0xFFFF)) {
168  // Calculate number of bytes to skip to get to end of the next marker.
169  m->skip_bytes = (state64 & 0xFFFF)-1;
170 
171  // If the next marker is an info marker, skip to the end of of the marker length.
172  if (i + m->skip_bytes + 1 < buf_size) {
173  uint32_t next_state = (buf[i + m->skip_bytes] << 8) | buf[i + m->skip_bytes + 1];
174  if (info_marker(next_state)) {
175  // Skip an additional 2 bytes to get to the end of the marker length.
176  m->skip_bytes += 2;
177  }
178  }
179  }
180  }
181  }
182 
183  pc->state64 = state64;
184  m->bytes_read = bytes_read;
185  return END_NOT_FOUND;
186 }
187 
189  AVCodecContext *avctx,
190  const uint8_t **poutbuf, int *poutbuf_size,
191  const uint8_t *buf, int buf_size)
192 {
193  JPEG2000ParserContext *m = s->priv_data;
194  ParseContext *pc = &m->pc;
195  int next;
196 
197  if(s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
198  next= buf_size;
199  } else {
200  next= find_frame_end(m, buf, buf_size);
201 
202  if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
203  *poutbuf = NULL;
204  *poutbuf_size = 0;
205  return buf_size;
206  }
207  }
208 
209  *poutbuf = buf;
210  *poutbuf_size = buf_size;
211  return next;
212 }
213 
216  .priv_data_size = sizeof(JPEG2000ParserContext),
217  .parser_parse = jpeg2000_parse,
218  .parser_close = ff_parse_close,
219 };
j2k_cstream
@ j2k_cstream
Definition: jpeg2000_parser.c:33
int64_t
long long int64_t
Definition: coverity.c:34
ff_parse_close
void ff_parse_close(AVCodecParserContext *s)
Definition: parser.c:290
JPEG2000ParserContext::in_codestream
uint8_t in_codestream
Definition: jpeg2000_parser.c:46
ParseContext
Definition: parser.h:28
jpeg2000_parse
static int jpeg2000_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size)
Definition: jpeg2000_parser.c:188
s
#define s(width, name)
Definition: cbs_vp9.c:198
JPEG2000ParserContext::reading_file_header
uint8_t reading_file_header
Definition: jpeg2000_parser.c:43
JPEG2000ParserContext::pc
ParseContext pc
Definition: jpeg2000_parser.c:37
if
if(ret)
Definition: filter_design.txt:179
NULL
#define NULL
Definition: coverity.c:32
JPEG2000ParserContext::read_tp
uint8_t read_tp
Definition: jpeg2000_parser.c:45
ParseContext::frame_start_found
int frame_start_found
Definition: parser.h:34
find_frame_end
static int find_frame_end(JPEG2000ParserContext *m, const uint8_t *buf, int buf_size)
Find the end of the current frame in the bitstream.
Definition: jpeg2000_parser.c:93
JPEG2000ParserContext::fheader_read
uint8_t fheader_read
Definition: jpeg2000_parser.c:42
AVCodecParser::codec_ids
int codec_ids[7]
Definition: avcodec.h:2908
jp2_file
@ jp2_file
Definition: jpeg2000_parser.c:32
ff_combine_frame
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:203
reset_context
static void reset_context(JPEG2000ParserContext *m)
Definition: jpeg2000_parser.c:49
ff_jpeg2000_parser
const AVCodecParser ff_jpeg2000_parser
Definition: jpeg2000_parser.c:214
PARSER_FLAG_COMPLETE_FRAMES
#define PARSER_FLAG_COMPLETE_FRAMES
Definition: avcodec.h:2782
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
frame_type
frame_type
Definition: jpeg2000_parser.c:31
JPEG2000ParserContext
Definition: jpeg2000_parser.c:36
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
parser.h
AV_CODEC_ID_JPEG2000
@ AV_CODEC_ID_JPEG2000
Definition: codec_id.h:140
AVCodecParserContext
Definition: avcodec.h:2748
JPEG2000ParserContext::skip_bytes
uint32_t skip_bytes
Definition: jpeg2000_parser.c:40
JPEG2000ParserContext::skipped_codestream
uint8_t skipped_codestream
Definition: jpeg2000_parser.c:44
AVCodecContext
main external API structure.
Definition: avcodec.h:451
info_marker
static uint8_t info_marker(uint16_t marker)
Definition: jpeg2000_parser.c:66
JPEG2000ParserContext::fheader_state
uint64_t fheader_state
Definition: jpeg2000_parser.c:39
ParseContext::state64
uint64_t state64
contains the last 8 bytes in MSB order
Definition: parser.h:37
JPEG2000ParserContext::ft
enum frame_type ft
Definition: jpeg2000_parser.c:41
END_NOT_FOUND
#define END_NOT_FOUND
Definition: parser.h:40
AVCodecParser
Definition: avcodec.h:2907
JPEG2000ParserContext::bytes_read
uint64_t bytes_read
Definition: jpeg2000_parser.c:38
skip
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
Definition: bitstream_template.h:375