1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * PNM image parser 3cabdff1aSopenharmony_ci * Copyright (c) 2002, 2003 Fabrice Bellard 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 23cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "parser.h" //for ParseContext 26cabdff1aSopenharmony_ci#include "pnm.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_citypedef struct PNMParseContext { 29cabdff1aSopenharmony_ci ParseContext pc; 30cabdff1aSopenharmony_ci int remaining_bytes; 31cabdff1aSopenharmony_ci int ascii_scan; 32cabdff1aSopenharmony_ci}PNMParseContext; 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_cistatic int pnm_parse(AVCodecParserContext *s, AVCodecContext *avctx, 35cabdff1aSopenharmony_ci const uint8_t **poutbuf, int *poutbuf_size, 36cabdff1aSopenharmony_ci const uint8_t *buf, int buf_size) 37cabdff1aSopenharmony_ci{ 38cabdff1aSopenharmony_ci PNMParseContext *pnmpc = s->priv_data; 39cabdff1aSopenharmony_ci ParseContext *pc = &pnmpc->pc; 40cabdff1aSopenharmony_ci PNMContext pnmctx; 41cabdff1aSopenharmony_ci int next = END_NOT_FOUND; 42cabdff1aSopenharmony_ci int skip = 0; 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_ci if (pc->overread > 0) { 45cabdff1aSopenharmony_ci memmove(pc->buffer + pc->index, pc->buffer + pc->overread_index, pc->overread); 46cabdff1aSopenharmony_ci pc->index += pc->overread; 47cabdff1aSopenharmony_ci pc->overread_index += pc->overread; 48cabdff1aSopenharmony_ci pc->overread = 0; 49cabdff1aSopenharmony_ci } 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_ci if (pnmpc->remaining_bytes) { 52cabdff1aSopenharmony_ci int inc = FFMIN(pnmpc->remaining_bytes, buf_size); 53cabdff1aSopenharmony_ci skip += inc; 54cabdff1aSopenharmony_ci pnmpc->remaining_bytes -= inc; 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_ci if (!pnmpc->remaining_bytes) 57cabdff1aSopenharmony_ci next = skip; 58cabdff1aSopenharmony_ci goto end; 59cabdff1aSopenharmony_ci } 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ciretry: 62cabdff1aSopenharmony_ci if (pc->index) { 63cabdff1aSopenharmony_ci pnmctx.bytestream_start = 64cabdff1aSopenharmony_ci pnmctx.bytestream = pc->buffer; 65cabdff1aSopenharmony_ci pnmctx.bytestream_end = pc->buffer + pc->index; 66cabdff1aSopenharmony_ci } else { 67cabdff1aSopenharmony_ci pnmctx.bytestream_start = 68cabdff1aSopenharmony_ci pnmctx.bytestream = (uint8_t *) buf + skip; /* casts avoid warnings */ 69cabdff1aSopenharmony_ci pnmctx.bytestream_end = (uint8_t *) buf + buf_size - skip; 70cabdff1aSopenharmony_ci } 71cabdff1aSopenharmony_ci if (ff_pnm_decode_header(avctx, &pnmctx) < 0) { 72cabdff1aSopenharmony_ci if (pnmctx.bytestream < pnmctx.bytestream_end) { 73cabdff1aSopenharmony_ci if (pc->index) { 74cabdff1aSopenharmony_ci pc->index = 0; 75cabdff1aSopenharmony_ci pnmpc->ascii_scan = 0; 76cabdff1aSopenharmony_ci } else { 77cabdff1aSopenharmony_ci unsigned step = FFMAX(1, pnmctx.bytestream - pnmctx.bytestream_start); 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci skip += step; 80cabdff1aSopenharmony_ci } 81cabdff1aSopenharmony_ci goto retry; 82cabdff1aSopenharmony_ci } 83cabdff1aSopenharmony_ci } else if (pnmctx.type < 4) { 84cabdff1aSopenharmony_ci uint8_t *bs = pnmctx.bytestream; 85cabdff1aSopenharmony_ci const uint8_t *end = pnmctx.bytestream_end; 86cabdff1aSopenharmony_ci uint8_t *sync = bs; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci if (pc->index) { 89cabdff1aSopenharmony_ci av_assert0(pnmpc->ascii_scan <= end - bs); 90cabdff1aSopenharmony_ci bs += pnmpc->ascii_scan; 91cabdff1aSopenharmony_ci } 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_ci while (bs < end) { 94cabdff1aSopenharmony_ci int c; 95cabdff1aSopenharmony_ci sync = bs; 96cabdff1aSopenharmony_ci c = *bs++; 97cabdff1aSopenharmony_ci if (c == '#') { 98cabdff1aSopenharmony_ci uint8_t *match = memchr(bs, '\n', end-bs); 99cabdff1aSopenharmony_ci if (match) 100cabdff1aSopenharmony_ci bs = match + 1; 101cabdff1aSopenharmony_ci else 102cabdff1aSopenharmony_ci break; 103cabdff1aSopenharmony_ci } else if (c == 'P') { 104cabdff1aSopenharmony_ci next = bs - pnmctx.bytestream_start + skip - 1; 105cabdff1aSopenharmony_ci pnmpc->ascii_scan = 0; 106cabdff1aSopenharmony_ci break; 107cabdff1aSopenharmony_ci } 108cabdff1aSopenharmony_ci } 109cabdff1aSopenharmony_ci if (next == END_NOT_FOUND) 110cabdff1aSopenharmony_ci pnmpc->ascii_scan = sync - pnmctx.bytestream + skip; 111cabdff1aSopenharmony_ci } else { 112cabdff1aSopenharmony_ci int ret = av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1); 113cabdff1aSopenharmony_ci next = pnmctx.bytestream - pnmctx.bytestream_start + skip; 114cabdff1aSopenharmony_ci if (ret > 0 && pnmctx.half) 115cabdff1aSopenharmony_ci ret >>= 1; 116cabdff1aSopenharmony_ci if (ret >= 0 && next + (uint64_t)ret <= INT_MAX) 117cabdff1aSopenharmony_ci next += ret; 118cabdff1aSopenharmony_ci } 119cabdff1aSopenharmony_ci if (next != END_NOT_FOUND && pnmctx.bytestream_start != buf + skip) 120cabdff1aSopenharmony_ci next -= pc->index; 121cabdff1aSopenharmony_ci if (next > buf_size) { 122cabdff1aSopenharmony_ci pnmpc->remaining_bytes = next - buf_size; 123cabdff1aSopenharmony_ci next = END_NOT_FOUND; 124cabdff1aSopenharmony_ci } 125cabdff1aSopenharmony_ciend: 126cabdff1aSopenharmony_ci if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { 127cabdff1aSopenharmony_ci *poutbuf = NULL; 128cabdff1aSopenharmony_ci *poutbuf_size = 0; 129cabdff1aSopenharmony_ci return buf_size; 130cabdff1aSopenharmony_ci } 131cabdff1aSopenharmony_ci *poutbuf = buf; 132cabdff1aSopenharmony_ci *poutbuf_size = buf_size; 133cabdff1aSopenharmony_ci return next; 134cabdff1aSopenharmony_ci} 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ciconst AVCodecParser ff_pnm_parser = { 137cabdff1aSopenharmony_ci .codec_ids = { AV_CODEC_ID_PGM, AV_CODEC_ID_PGMYUV, AV_CODEC_ID_PPM, 138cabdff1aSopenharmony_ci AV_CODEC_ID_PBM, AV_CODEC_ID_PAM, AV_CODEC_ID_PFM, 139cabdff1aSopenharmony_ci AV_CODEC_ID_PHM }, 140cabdff1aSopenharmony_ci .priv_data_size = sizeof(PNMParseContext), 141cabdff1aSopenharmony_ci .parser_parse = pnm_parse, 142cabdff1aSopenharmony_ci .parser_close = ff_parse_close, 143cabdff1aSopenharmony_ci}; 144