Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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