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
00029 #define PNGSIG 0x89504e470d0a1a0a
00030 #define MNGSIG 0x8a4d4e470d0a1a0a
00031
00032 typedef struct PNGParseContext
00033 {
00034 ParseContext pc;
00035 uint32_t index;
00036 uint32_t chunk_length;
00037 uint32_t remaining_size;
00038 } PNGParseContext;
00039
00040 static int png_parse(AVCodecParserContext *s, AVCodecContext *avctx,
00041 const uint8_t **poutbuf, int *poutbuf_size,
00042 const uint8_t *buf, int buf_size)
00043 {
00044 PNGParseContext *ppc = s->priv_data;
00045 int next = END_NOT_FOUND;
00046 int i = 0;
00047
00048 s->pict_type = AV_PICTURE_TYPE_NONE;
00049
00050 *poutbuf_size = 0;
00051 if (buf_size == 0)
00052 return 0;
00053
00054 if (!ppc->pc.frame_start_found) {
00055 uint64_t state64 = ppc->pc.state64;
00056 for (; i < buf_size; i++) {
00057 state64 = (state64 << 8) | buf[i];
00058 if (state64 == PNGSIG || state64 == MNGSIG) {
00059 i++;
00060 ppc->pc.frame_start_found = 1;
00061 break;
00062 }
00063 }
00064 ppc->pc.state64 = state64;
00065 } else
00066 if (ppc->remaining_size) {
00067 i = FFMIN(ppc->remaining_size, buf_size);
00068 ppc->remaining_size -= i;
00069 if (ppc->remaining_size)
00070 goto flush;
00071 if (ppc->index == -1) {
00072 next = i;
00073 goto flush;
00074 }
00075 }
00076
00077 for (;ppc->pc.frame_start_found && i < buf_size; i++) {
00078 ppc->pc.state = (ppc->pc.state<<8) | buf[i];
00079 if (ppc->index == 3) {
00080 ppc->chunk_length = ppc->pc.state;
00081 if (ppc->chunk_length > 0x7fffffff) {
00082 ppc->index = ppc->pc.frame_start_found = 0;
00083 goto flush;
00084 }
00085 ppc->chunk_length += 4;
00086 } else if (ppc->index == 7) {
00087 if (ppc->chunk_length >= buf_size - i)
00088 ppc->remaining_size = ppc->chunk_length - buf_size + i + 1;
00089 if (ppc->pc.state == MKBETAG('I', 'E', 'N', 'D')) {
00090 if (ppc->remaining_size)
00091 ppc->index = -1;
00092 else
00093 next = ppc->chunk_length + i + 1;
00094 break;
00095 } else {
00096 ppc->index = 0;
00097 if (ppc->remaining_size)
00098 break;
00099 else
00100 i += ppc->chunk_length;
00101 continue;
00102 }
00103 }
00104 ppc->index++;
00105 }
00106 flush:
00107 if (ff_combine_frame(&ppc->pc, next, &buf, &buf_size) < 0)
00108 return buf_size;
00109
00110 ppc->index = ppc->pc.frame_start_found = 0;
00111
00112 *poutbuf = buf;
00113 *poutbuf_size = buf_size;
00114 return next;
00115 }
00116
00117 AVCodecParser ff_png_parser = {
00118 { CODEC_ID_PNG },
00119 sizeof(PNGParseContext),
00120 NULL,
00121 png_parse,
00122 ff_parse_close,
00123 };