00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "parser.h"
00028 #include "png.h"
00029
00030 typedef struct PNGParseContext
00031 {
00032 ParseContext pc;
00033 uint32_t index;
00034 uint32_t chunk_length;
00035 uint32_t remaining_size;
00036 } PNGParseContext;
00037
00038 static int png_parse(AVCodecParserContext *s, AVCodecContext *avctx,
00039 const uint8_t **poutbuf, int *poutbuf_size,
00040 const uint8_t *buf, int buf_size)
00041 {
00042 PNGParseContext *ppc = s->priv_data;
00043 int next = END_NOT_FOUND;
00044 int i = 0;
00045
00046 s->pict_type = AV_PICTURE_TYPE_NONE;
00047
00048 *poutbuf_size = 0;
00049 if (buf_size == 0)
00050 return 0;
00051
00052 if (!ppc->pc.frame_start_found) {
00053 uint64_t state64 = ppc->pc.state64;
00054 for (; i < buf_size; i++) {
00055 state64 = (state64 << 8) | buf[i];
00056 if (state64 == PNGSIG || state64 == MNGSIG) {
00057 i++;
00058 ppc->pc.frame_start_found = 1;
00059 break;
00060 }
00061 }
00062 ppc->pc.state64 = state64;
00063 } else
00064 if (ppc->remaining_size) {
00065 i = FFMIN(ppc->remaining_size, buf_size);
00066 ppc->remaining_size -= i;
00067 if (ppc->remaining_size)
00068 goto flush;
00069 if (ppc->index == -1) {
00070 next = i;
00071 goto flush;
00072 }
00073 }
00074
00075 for (;ppc->pc.frame_start_found && i < buf_size; i++) {
00076 ppc->pc.state = (ppc->pc.state<<8) | buf[i];
00077 if (ppc->index == 3) {
00078 ppc->chunk_length = ppc->pc.state;
00079 if (ppc->chunk_length > 0x7fffffff) {
00080 ppc->index = ppc->pc.frame_start_found = 0;
00081 goto flush;
00082 }
00083 ppc->chunk_length += 4;
00084 } else if (ppc->index == 7) {
00085 if (ppc->chunk_length >= buf_size - i)
00086 ppc->remaining_size = ppc->chunk_length - buf_size + i + 1;
00087 if (ppc->pc.state == MKBETAG('I', 'E', 'N', 'D')) {
00088 if (ppc->remaining_size)
00089 ppc->index = -1;
00090 else
00091 next = ppc->chunk_length + i + 1;
00092 break;
00093 } else {
00094 ppc->index = 0;
00095 if (ppc->remaining_size)
00096 break;
00097 else
00098 i += ppc->chunk_length;
00099 continue;
00100 }
00101 }
00102 ppc->index++;
00103 }
00104 flush:
00105 if (ff_combine_frame(&ppc->pc, next, &buf, &buf_size) < 0)
00106 return buf_size;
00107
00108 ppc->index = ppc->pc.frame_start_found = 0;
00109
00110 *poutbuf = buf;
00111 *poutbuf_size = buf_size;
00112 return next;
00113 }
00114
00115 AVCodecParser ff_png_parser = {
00116 .codec_ids = { AV_CODEC_ID_PNG },
00117 .priv_data_size = sizeof(PNGParseContext),
00118 .parser_parse = png_parse,
00119 .parser_close = ff_parse_close,
00120 };