FFmpeg
jpegxs_parser.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "libavutil/mem.h"
20 
21 #include "bytestream.h"
22 #include "get_bits.h"
23 #include "jpegxs.h"
24 #include "parser.h"
25 #include "parser_internal.h"
26 
27 typedef struct JPEGXSParseContext {
29 
30  int eoc_found;
32 
33 /**
34  * Find the end of the current frame in the bitstream.
35  * @return the position of the first byte of the next frame, or -1
36  */
37 static int jpegxs_find_frame_end(JPEGXSParseContext *jpegxs, const uint8_t *buf,
38  int buf_size)
39 {
40  ParseContext *pc = &jpegxs->pc;
41  int pic_found, i = 0;
42  uint32_t state;
43 
44  pic_found = pc->frame_start_found;
45  state = pc->state;
46 
47  if (!pic_found) {
48  for (i = 0; i < buf_size; i++) {
49  state = (state << 8) | buf[i];
50  if ((uint16_t)state == JPEGXS_MARKER_SOC) {
51  i++;
52  pic_found = 1;
53  break;
54  }
55  }
56  }
57 
58  if (buf_size == 0) {
59  if (jpegxs->eoc_found) {
60  pc->frame_start_found = jpegxs->eoc_found = 0;
61  pc->state = -1;
62  }
63  return 0;
64  }
65 
66  while (pic_found && i < buf_size) {
67  if (jpegxs->eoc_found) {
68  for(; i < buf_size; i++) {
69  state = (state << 8) | buf[i];
70  if ((state >> 16) == JPEGXS_MARKER_EOC) {
71  if ((uint16_t)state == JPEGXS_MARKER_SOC) {
72  // New image
73  pc->frame_start_found = jpegxs->eoc_found = 0;
74  pc->state = -1;
75  return i - 1;
76  } else {
77  // False positive
78  i++;
79  jpegxs->eoc_found = 0;
80  break;
81  }
82  }
83  }
84  }
85 
86  for(; i < buf_size; i++) {
87  state = (state << 8) | buf[i];
88  if ((uint16_t)state == JPEGXS_MARKER_EOC) {
89  // EOC candidate
90  i++;
91  jpegxs->eoc_found = 1;
92  break;
93  }
94  }
95  }
96 
97  pc->frame_start_found = pic_found;
98  pc->state = state;
99  return END_NOT_FOUND;
100 }
101 
103  const uint8_t *buf, int buf_size)
104 {
105  GetByteContext gbc;
106  GetBitContext gb;
107  int8_t bpc[3], log2_chroma_w[3], log2_chroma_h[3];
108  int size, marker, components;
109 
110  s->key_frame = 1;
111  s->pict_type = AV_PICTURE_TYPE_I;
112 
113  if (buf_size < 4)
114  return 0;
115 
116  bytestream2_init(&gbc, buf, buf_size);
117  marker = bytestream2_get_be16(&gbc);
118  if (marker != JPEGXS_MARKER_SOC)
119  return 0;
120 
121  marker = bytestream2_get_be16(&gbc);
122  if (marker != JPEGXS_MARKER_CAP)
123  return 0;
124  size = bytestream2_get_be16(&gbc);
125  bytestream2_skip(&gbc, FFMAX(size - 2, 0));
126 
127  marker = bytestream2_get_be16(&gbc);
128  if (marker != JPEGXS_MARKER_PIH)
129  return 0;
130  size = bytestream2_get_be16(&gbc);
131  bytestream2_skip(&gbc, 4); // Lcod
132  bytestream2_skip(&gbc, 2); // Ppih
133  bytestream2_skip(&gbc, 2); // Plev
134  size -= 8;
135 
136  s->width = bytestream2_get_be16(&gbc);
137  s->height = bytestream2_get_be16(&gbc);
138  size -= 4;
139 
140  bytestream2_skip(&gbc, 2); // Cw
141  bytestream2_skip(&gbc, 2); // Hsl
142  size -= 4;
143 
144  components = bytestream2_get_byte(&gbc);
145  if (components != 1 && components != 3)
146  return 0;
147  size--;
148 
149  bytestream2_skip(&gbc, FFMAX(size - 2, 0));
150 
151  while (bytestream2_get_bytes_left(&gbc) > 0) {
152  marker = bytestream2_get_be16(&gbc);
153 
154  switch(marker) {
155  case JPEGXS_MARKER_CDT:
156  size = bytestream2_get_be16(&gbc);
157  init_get_bits8(&gb, gbc.buffer, FFMIN(FFMAX(size - 2, 0), bytestream2_get_bytes_left(&gbc)));
158 
159  for (int i = 0; i < components; i++) {
160  bpc[i] = get_bits(&gb, 8);
161  if (i && bpc[i] != bpc[i-1])
162  return 0;
163 
164  log2_chroma_w[i] = get_bits(&gb, 4);
165  log2_chroma_h[i] = get_bits(&gb, 4);
166 
167  if (log2_chroma_h[i] > log2_chroma_w[i])
168  return 0;
169  if (i == 2 && (log2_chroma_h[2] != log2_chroma_h[1] ||
170  log2_chroma_w[2] != log2_chroma_w[1]))
171  return 0;
172  }
173 
174  switch (bpc[0]) {
175  case 8:
176  if (components == 1) s->format = AV_PIX_FMT_GRAY8;
177  else if (log2_chroma_w[1] == 1 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV444P;
178  else if (log2_chroma_w[1] == 2 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV422P;
179  else s->format = AV_PIX_FMT_YUV420P;
180  break;
181  case 10:
182  if (components == 1) s->format = AV_PIX_FMT_GRAY10;
183  else if (log2_chroma_w[1] == 1 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV444P10;
184  else if (log2_chroma_w[1] == 2 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV422P10;
185  else s->format = AV_PIX_FMT_YUV420P10;
186  break;
187  case 12:
188  if (components == 1) s->format = AV_PIX_FMT_GRAY12;
189  else if (log2_chroma_w[1] == 1 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV444P12;
190  else if (log2_chroma_w[1] == 2 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV422P12;
191  else s->format = AV_PIX_FMT_YUV420P12;
192  break;
193  case 14:
194  if (components == 1) s->format = AV_PIX_FMT_GRAY14;
195  else if (log2_chroma_w[1] == 1 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV444P14;
196  else if (log2_chroma_w[1] == 2 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV422P14;
197  else s->format = AV_PIX_FMT_YUV420P14;
198  break;
199  default:
200  s->format = AV_PIX_FMT_NONE;
201  break;
202  }
203  return 0;
204  default:
205  size = bytestream2_get_be16(&gbc);
206  bytestream2_skip(&gbc, FFMAX(size - 2, 0));
207  break;
208  }
209  }
210 
211  return 0;
212 }
213 
215  AVCodecContext *avctx,
216  const uint8_t **poutbuf, int *poutbuf_size,
217  const uint8_t *buf, int buf_size)
218 {
219  JPEGXSParseContext *jpegxs = s->priv_data;
220  ParseContext *pc = &jpegxs->pc;
221  int next;
222 
223  next = jpegxs_find_frame_end(jpegxs, buf, buf_size);
224 
225  if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
226  *poutbuf = NULL;
227  *poutbuf_size = 0;
228  return buf_size;
229  }
230 
231  jpegxs_parse_frame(s, avctx, buf, buf_size);
232 
233  *poutbuf = buf;
234  *poutbuf_size = buf_size;
235  return next;
236 }
237 
239 {
240  JPEGXSParseContext *jpegxs = s->priv_data;
241  ParseContext *pc = &jpegxs->pc;
242 
243  av_freep(&pc->buffer);
244 }
245 
248  .priv_data_size = sizeof(JPEGXSParseContext),
251 };
JPEGXSParseContext::pc
ParseContext pc
Definition: jpegxs_parser.c:28
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition: bytestream.h:158
GetByteContext
Definition: bytestream.h:33
JPEGXSParseContext::eoc_found
int eoc_found
Definition: jpegxs_parser.c:30
parser_internal.h
JPEGXS_MARKER_CAP
@ JPEGXS_MARKER_CAP
Definition: jpegxs.h:34
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:539
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
ParseContext::state
uint32_t state
contains the last few bytes in MSB order
Definition: parser.h:33
close
static av_cold void close(AVCodecParserContext *s)
Definition: apv_parser.c:136
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
get_bits
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:337
ParseContext
Definition: parser.h:28
JPEGXS_MARKER_SOC
@ JPEGXS_MARKER_SOC
Definition: jpegxs.h:23
GetBitContext
Definition: get_bits.h:109
AV_PIX_FMT_YUV444P10
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:542
ParseContext::buffer
uint8_t * buffer
Definition: parser.h:29
av_cold
#define av_cold
Definition: attributes.h:106
init_get_bits8
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:544
s
#define s(width, name)
Definition: cbs_vp9.c:198
GetByteContext::buffer
const uint8_t * buffer
Definition: bytestream.h:34
JPEGXS_MARKER_EOC
@ JPEGXS_MARKER_EOC
Definition: jpegxs.h:24
get_bits.h
AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:521
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:519
NULL
#define NULL
Definition: coverity.c:32
jpegxsparse_close
static av_cold void jpegxsparse_close(AVCodecParserContext *s)
Definition: jpegxs_parser.c:238
JPEGXS_MARKER_CDT
@ JPEGXS_MARKER_CDT
Definition: jpegxs.h:26
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:278
ParseContext::frame_start_found
int frame_start_found
Definition: parser.h:34
AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:540
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
parse
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:46
jpegxs_find_frame_end
static int jpegxs_find_frame_end(JPEGXSParseContext *jpegxs, const uint8_t *buf, int buf_size)
Find the end of the current frame in the bitstream.
Definition: jpegxs_parser.c:37
AV_PIX_FMT_YUV422P12
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:544
size
int size
Definition: twinvq_data.h:10344
AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:546
ff_jpegxs_parser
const FFCodecParser ff_jpegxs_parser
Definition: jpegxs_parser.c:246
state
static struct @547 state
jpegxs_parse_frame
static int jpegxs_parse_frame(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t *buf, int buf_size)
Definition: jpegxs_parser.c:102
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:211
FFCodecParser
Definition: parser_internal.h:29
AV_CODEC_ID_JPEGXS
@ AV_CODEC_ID_JPEGXS
Definition: codec_id.h:334
jpegxs.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
parser.h
PARSER_CODEC_LIST
#define PARSER_CODEC_LIST(...)
Definition: parser_internal.h:76
AVCodecParserContext
Definition: avcodec.h:2589
AV_PIX_FMT_YUV420P12
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:543
AV_PIX_FMT_YUV422P14
#define AV_PIX_FMT_YUV422P14
Definition: pixfmt.h:548
AVCodecContext
main external API structure.
Definition: avcodec.h:439
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:78
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:77
mem.h
jpegxsvideo_parse
static int jpegxsvideo_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size)
Definition: jpegxs_parser.c:214
END_NOT_FOUND
#define END_NOT_FOUND
Definition: parser.h:40
JPEGXS_MARKER_PIH
@ JPEGXS_MARKER_PIH
Definition: jpegxs.h:25
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
bytestream.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
JPEGXSParseContext
Definition: jpegxs_parser.c:27
AV_PIX_FMT_YUV444P14
#define AV_PIX_FMT_YUV444P14
Definition: pixfmt.h:549
AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:520
AV_PIX_FMT_YUV420P14
#define AV_PIX_FMT_YUV420P14
Definition: pixfmt.h:547