3 * Copyright (c) 2009 Peter Holik
5 * This file is part of FFmpeg.
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.
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.
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
30 typedef struct PNGParseContext
{
32 uint32_t chunk_pos
; ///< position inside current chunk
33 uint32_t chunk_length
; ///< length of the current chunk
34 uint32_t remaining_size
; ///< remaining size of the current chunk
37 static int png_parse(AVCodecParserContext
*s
, AVCodecContext
*avctx
,
38 const uint8_t **poutbuf
, int *poutbuf_size
,
39 const uint8_t *buf
, int buf_size
)
41 PNGParseContext
*ppc
= s
->priv_data
;
42 int next
= END_NOT_FOUND
;
45 s
->pict_type
= AV_PICTURE_TYPE_NONE
;
49 if (!ppc
->pc
.frame_start_found
) {
50 uint64_t state64
= ppc
->pc
.state64
;
51 for (; i
< buf_size
; i
++) {
52 state64
= (state64
<< 8) | buf
[i
];
53 if (state64
== PNGSIG
|| state64
== MNGSIG
) {
55 ppc
->pc
.frame_start_found
= 1;
59 ppc
->pc
.state64
= state64
;
60 } else if (ppc
->remaining_size
) {
61 i
= FFMIN(ppc
->remaining_size
, buf_size
);
62 ppc
->remaining_size
-= i
;
63 if (ppc
->remaining_size
)
65 if (ppc
->chunk_pos
== -1) {
71 for (; ppc
->pc
.frame_start_found
&& i
< buf_size
; i
++) {
72 ppc
->pc
.state
= (ppc
->pc
.state
<< 8) | buf
[i
];
73 if (ppc
->chunk_pos
== 3) {
74 ppc
->chunk_length
= ppc
->pc
.state
;
75 if (ppc
->chunk_length
> 0x7fffffff) {
76 ppc
->chunk_pos
= ppc
->pc
.frame_start_found
= 0;
79 ppc
->chunk_length
+= 4;
80 } else if (ppc
->chunk_pos
== 7) {
81 if (ppc
->chunk_length
>= buf_size
- i
)
82 ppc
->remaining_size
= ppc
->chunk_length
- buf_size
+ i
+ 1;
83 if (ppc
->pc
.state
== MKBETAG('I', 'E', 'N', 'D')) {
84 if (ppc
->remaining_size
)
87 next
= ppc
->chunk_length
+ i
+ 1;
91 if (ppc
->remaining_size
)
94 i
+= ppc
->chunk_length
;
102 if (ff_combine_frame(&ppc
->pc
, next
, &buf
, &buf_size
) < 0)
105 ppc
->chunk_pos
= ppc
->pc
.frame_start_found
= 0;
108 *poutbuf_size
= buf_size
;
112 AVCodecParser ff_png_parser
= {
113 .codec_ids
= { AV_CODEC_ID_PNG
},
114 .priv_data_size
= sizeof(PNGParseContext
),
115 .parser_parse
= png_parse
,
116 .parser_close
= ff_parse_close
,