| | 1 | /* |
| | 2 | * PNG parser |
| | 3 | * Copyright (c) 2009 Peter Holik |
| | 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 libavcodec/png_parser.c |
| | 24 | * PNG parser |
| | 25 | */ |
| | 26 | |
| | 27 | #include "libavutil/intreadwrite.h" |
| | 28 | #include "parser.h" |
| | 29 | |
| | 30 | #define PNGSIG 0x89504e470d0a1a0a |
| | 31 | #define MNGSIG 0x8a4d4e470d0a1a0a |
| | 32 | |
| | 33 | typedef struct PNGParseContext |
| | 34 | { |
| | 35 | ParseContext pc; |
| | 36 | uint32_t index; |
| | 37 | uint32_t chunk_length; |
| | 38 | uint32_t remaining_size; |
| | 39 | } PNGParseContext; |
| | 40 | |
| | 41 | static int png_parse(AVCodecParserContext *s, AVCodecContext *avctx, |
| | 42 | const uint8_t **poutbuf, int *poutbuf_size, |
| | 43 | const uint8_t *buf, int buf_size) |
| | 44 | { |
| | 45 | PNGParseContext *ppc = s->priv_data; |
| | 46 | int next = END_NOT_FOUND; |
| | 47 | int i = 0; |
| | 48 | |
| | 49 | *poutbuf_size = 0; |
| | 50 | if (buf_size == 0) |
| | 51 | return 0; |
| | 52 | |
| | 53 | if (!ppc->pc.frame_start_found) { |
| | 54 | uint64_t state64 = ppc->pc.state64; |
| | 55 | for (; i < buf_size; i++) { |
| | 56 | state64 = (state64 << 8) | buf[i]; |
| | 57 | if (state64 == PNGSIG || state64 == MNGSIG) { |
| | 58 | i++; |
| | 59 | ppc->pc.frame_start_found = 1; |
| | 60 | break; |
| | 61 | } |
| | 62 | } |
| | 63 | ppc->pc.state64 = state64; |
| | 64 | } else |
| | 65 | if (ppc->remaining_size) { |
| | 66 | i = FFMIN(ppc->remaining_size, buf_size); |
| | 67 | ppc->remaining_size -= i; |
| | 68 | if (ppc->remaining_size) |
| | 69 | goto flush; |
| | 70 | if (ppc->index == -1) { |
| | 71 | next = i; |
| | 72 | goto flush; |
| | 73 | } |
| | 74 | } |
| | 75 | |
| | 76 | for (;ppc->pc.frame_start_found && i < buf_size; i++) { |
| | 77 | ppc->pc.state = (ppc->pc.state<<8) | buf[i]; |
| | 78 | if (ppc->index == 3) { |
| | 79 | ppc->chunk_length = AV_RL32(&ppc->pc.state); |
| | 80 | if (ppc->chunk_length > 0x7fffffff) { |
| | 81 | ppc->index = ppc->pc.frame_start_found = 0; |
| | 82 | goto flush; |
| | 83 | } |
| | 84 | ppc->chunk_length += 4; |
| | 85 | } else if (ppc->index == 7) { |
| | 86 | if (ppc->chunk_length >= buf_size - i) |
| | 87 | ppc->remaining_size = ppc->chunk_length - buf_size + i + 1; |
| | 88 | if (AV_RB32(&ppc->pc.state) == MKTAG('I', 'E', 'N', 'D')) { |
| | 89 | if (ppc->remaining_size) |
| | 90 | ppc->index = -1; |
| | 91 | else |
| | 92 | next = ppc->chunk_length + i + 1; |
| | 93 | break; |
| | 94 | } else { |
| | 95 | ppc->index = 0; |
| | 96 | if (ppc->remaining_size) |
| | 97 | break; |
| | 98 | else |
| | 99 | i += ppc->chunk_length; |
| | 100 | continue; |
| | 101 | } |
| | 102 | } |
| | 103 | ppc->index++; |
| | 104 | } |
| | 105 | flush: |
| | 106 | if (ff_combine_frame(&ppc->pc, next, &buf, &buf_size) < 0) |
| | 107 | return buf_size; |
| | 108 | |
| | 109 | ppc->index = ppc->pc.frame_start_found = 0; |
| | 110 | |
| | 111 | *poutbuf = buf; |
| | 112 | *poutbuf_size = buf_size; |
| | 113 | return next; |
| | 114 | } |
| | 115 | |
| | 116 | AVCodecParser ff_png_parser = { |
| | 117 | { CODEC_ID_PNG }, |
| | 118 | sizeof(PNGParseContext), |
| | 119 | NULL, |
| | 120 | png_parse, |
| | 121 | ff_parse_close, |
| | 122 | }; |