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
;
50 if (!ppc
->pc
.frame_start_found
) {
51 uint64_t state64
= ppc
->pc
.state64
;
52 for (; i
< buf_size
; i
++) {
53 state64
= (state64
<< 8) | buf
[i
];
54 if (state64
== PNGSIG
|| state64
== MNGSIG
) {
56 ppc
->pc
.frame_start_found
= 1;
60 ppc
->pc
.state64
= state64
;
61 } else if (ppc
->remaining_size
) {
62 i
= FFMIN(ppc
->remaining_size
, buf_size
);
63 ppc
->remaining_size
-= i
;
64 if (ppc
->remaining_size
)
66 if (ppc
->chunk_pos
== -1) {
72 for (; ppc
->pc
.frame_start_found
&& i
< buf_size
; i
++) {
73 ppc
->pc
.state
= (ppc
->pc
.state
<< 8) | buf
[i
];
74 if (ppc
->chunk_pos
== 3) {
75 ppc
->chunk_length
= ppc
->pc
.state
;
76 if (ppc
->chunk_length
> 0x7fffffff) {
77 ppc
->chunk_pos
= ppc
->pc
.frame_start_found
= 0;
80 ppc
->chunk_length
+= 4;
81 } else if (ppc
->chunk_pos
== 7) {
82 if (ppc
->chunk_length
>= buf_size
- i
)
83 ppc
->remaining_size
= ppc
->chunk_length
- buf_size
+ i
+ 1;
84 if (ppc
->pc
.state
== MKBETAG('I', 'E', 'N', 'D')) {
85 if (ppc
->remaining_size
)
88 next
= ppc
->chunk_length
+ i
+ 1;
92 if (ppc
->remaining_size
)
95 i
+= ppc
->chunk_length
;
103 if (ff_combine_frame(&ppc
->pc
, next
, &buf
, &buf_size
) < 0)
106 ppc
->chunk_pos
= ppc
->pc
.frame_start_found
= 0;
109 *poutbuf_size
= buf_size
;
113 const AVCodecParser ff_png_parser
= {
114 .codec_ids
= { AV_CODEC_ID_PNG
},
115 .priv_data_size
= sizeof(PNGParseContext
),
116 .parser_parse
= png_parse
,
117 .parser_close
= ff_parse_close
,