FFmpeg
pnm_parser.c
Go to the documentation of this file.
1 /*
2  * PNM image parser
3  * Copyright (c) 2002, 2003 Fabrice Bellard
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 #include "libavutil/avassert.h"
23 #include "libavutil/imgutils.h"
24 
25 #include "parser.h" //for ParseContext
26 #include "pnm.h"
27 
28 typedef struct PNMParseContext {
33 
35  const uint8_t **poutbuf, int *poutbuf_size,
36  const uint8_t *buf, int buf_size)
37 {
38  PNMParseContext *pnmpc = s->priv_data;
39  ParseContext *pc = &pnmpc->pc;
40  PNMContext pnmctx;
41  int next = END_NOT_FOUND;
42  int skip = 0;
43 
44  if (pc->overread > 0) {
45  memmove(pc->buffer + pc->index, pc->buffer + pc->overread_index, pc->overread);
46  pc->index += pc->overread;
47  pc->overread_index += pc->overread;
48  pc->overread = 0;
49  }
50 
51  if (pnmpc->remaining_bytes) {
52  int inc = FFMIN(pnmpc->remaining_bytes, buf_size);
53  skip += inc;
54  pnmpc->remaining_bytes -= inc;
55 
56  if (!pnmpc->remaining_bytes)
57  next = skip;
58  goto end;
59  }
60 
61 retry:
62  if (pc->index) {
63  pnmctx.bytestream_start =
64  pnmctx.bytestream = pc->buffer;
65  pnmctx.bytestream_end = pc->buffer + pc->index;
66  } else {
67  pnmctx.bytestream_start =
68  pnmctx.bytestream = (uint8_t *) buf + skip; /* casts avoid warnings */
69  pnmctx.bytestream_end = (uint8_t *) buf + buf_size - skip;
70  }
71  if (ff_pnm_decode_header(avctx, &pnmctx) < 0) {
72  if (pnmctx.bytestream < pnmctx.bytestream_end) {
73  if (pc->index) {
74  pc->index = 0;
75  pnmpc->ascii_scan = 0;
76  } else {
77  unsigned step = FFMAX(1, pnmctx.bytestream - pnmctx.bytestream_start);
78 
79  skip += step;
80  }
81  goto retry;
82  }
83  } else if (pnmctx.type < 4) {
84  uint8_t *bs = pnmctx.bytestream;
85  const uint8_t *end = pnmctx.bytestream_end;
86  uint8_t *sync = bs;
87 
88  if (pc->index) {
89  av_assert0(pnmpc->ascii_scan <= end - bs);
90  bs += pnmpc->ascii_scan;
91  }
92 
93  while (bs < end) {
94  int c;
95  sync = bs;
96  c = *bs++;
97  if (c == '#') {
98  uint8_t *match = memchr(bs, '\n', end-bs);
99  if (match)
100  bs = match + 1;
101  else
102  break;
103  } else if (c == 'P') {
104  next = bs - pnmctx.bytestream_start + skip - 1;
105  pnmpc->ascii_scan = 0;
106  break;
107  }
108  }
109  if (next == END_NOT_FOUND)
110  pnmpc->ascii_scan = sync - pnmctx.bytestream + skip;
111  } else {
112  int ret = av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1);
113  next = pnmctx.bytestream - pnmctx.bytestream_start + skip;
114  if (ret >= 0 && next + (uint64_t)ret <= INT_MAX)
115  next += ret;
116  }
117  if (next != END_NOT_FOUND && pnmctx.bytestream_start != buf + skip)
118  next -= pc->index;
119  if (next > buf_size) {
120  pnmpc->remaining_bytes = next - buf_size;
121  next = END_NOT_FOUND;
122  }
123 end:
124  if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
125  *poutbuf = NULL;
126  *poutbuf_size = 0;
127  return buf_size;
128  }
129  *poutbuf = buf;
130  *poutbuf_size = buf_size;
131  return next;
132 }
133 
137  .priv_data_size = sizeof(PNMParseContext),
138  .parser_parse = pnm_parse,
139  .parser_close = ff_parse_close,
140 };
AV_CODEC_ID_PBM
@ AV_CODEC_ID_PBM
Definition: codec_id.h:113
ParseContext::overread_index
int overread_index
the index into ParseContext.buffer of the overread bytes
Definition: parser.h:36
PNMParseContext::ascii_scan
int ascii_scan
Definition: pnm_parser.c:31
step
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
Definition: rate_distortion.txt:58
ff_parse_close
void ff_parse_close(AVCodecParserContext *s)
Definition: parser.c:282
AV_CODEC_ID_PPM
@ AV_CODEC_ID_PPM
Definition: codec_id.h:112
AV_CODEC_ID_PGM
@ AV_CODEC_ID_PGM
Definition: codec_id.h:114
PNMContext::bytestream_end
uint8_t * bytestream_end
Definition: pnm.h:30
ParseContext
Definition: parser.h:28
ParseContext::buffer
uint8_t * buffer
Definition: parser.h:29
avassert.h
ParseContext::index
int index
Definition: parser.h:30
s
#define s(width, name)
Definition: cbs_vp9.c:257
pnm_parse
static int pnm_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size)
Definition: pnm_parser.c:34
PNMContext::bytestream_start
uint8_t * bytestream_start
Definition: pnm.h:29
PNMParseContext::pc
ParseContext pc
Definition: pnm_parser.c:29
ParseContext::overread
int overread
the number of bytes which where irreversibly read from the next frame
Definition: parser.h:35
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
NULL
#define NULL
Definition: coverity.c:32
AVCodecParser::codec_ids
int codec_ids[5]
Definition: avcodec.h:2922
AV_CODEC_ID_PGMYUV
@ AV_CODEC_ID_PGMYUV
Definition: codec_id.h:115
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
pnm.h
AV_CODEC_ID_PAM
@ AV_CODEC_ID_PAM
Definition: codec_id.h:116
FFMAX
#define FFMAX(a, b)
Definition: common.h:103
PNMContext
Definition: pnm.h:27
av_image_get_buffer_size
int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align)
Return the size in bytes of the amount of data required to store an image with the given parameters.
Definition: imgutils.c:466
FFMIN
#define FFMIN(a, b)
Definition: common.h:105
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:197
parser.h
AVCodecContext::height
int height
Definition: avcodec.h:557
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:594
AVCodecParserContext
Definition: avcodec.h:2762
ff_pnm_parser
const AVCodecParser ff_pnm_parser
Definition: pnm_parser.c:134
ret
ret
Definition: filter_design.txt:187
PNMContext::bytestream
uint8_t * bytestream
Definition: pnm.h:28
PNMParseContext
Definition: pnm_parser.c:28
PNMContext::type
int type
Definition: pnm.h:32
AVCodecContext
main external API structure.
Definition: avcodec.h:384
ff_pnm_decode_header
int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext *const s)
Definition: pnm.c:65
END_NOT_FOUND
#define END_NOT_FOUND
Definition: parser.h:40
AVCodecParser
Definition: avcodec.h:2921
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:557
imgutils.h
PNMParseContext::remaining_bytes
int remaining_bytes
Definition: pnm_parser.c:30