comparison pnm.c @ 4978:95934eef9589 libavcodec

move pnm parser in its own file
author aurel
date Thu, 10 May 2007 23:03:14 +0000
parents 0d1cc37d9430
children
comparison
equal deleted inserted replaced
4977:9d7c1fbd3359 4978:95934eef9589
17 * You should have received a copy of the GNU Lesser General Public 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 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 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */ 20 */
21 #include "avcodec.h" 21 #include "avcodec.h"
22 #include "parser.h" //for ParseContext 22 #include "pnm.h"
23 23
24 typedef struct PNMContext {
25 uint8_t *bytestream;
26 uint8_t *bytestream_start;
27 uint8_t *bytestream_end;
28 AVFrame picture;
29 int maxval; ///< maximum value of a pixel
30 } PNMContext;
31
32 static inline int pnm_space(int c)
33 {
34 return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
35 }
36
37 static void pnm_get(PNMContext *sc, char *str, int buf_size)
38 {
39 char *s;
40 int c;
41
42 /* skip spaces and comments */
43 for(;;) {
44 c = *sc->bytestream++;
45 if (c == '#') {
46 do {
47 c = *sc->bytestream++;
48 } while (c != '\n' && sc->bytestream < sc->bytestream_end);
49 } else if (!pnm_space(c)) {
50 break;
51 }
52 }
53
54 s = str;
55 while (sc->bytestream < sc->bytestream_end && !pnm_space(c)) {
56 if ((s - str) < buf_size - 1)
57 *s++ = c;
58 c = *sc->bytestream++;
59 }
60 *s = '\0';
61 }
62 24
63 static int common_init(AVCodecContext *avctx){ 25 static int common_init(AVCodecContext *avctx){
64 PNMContext *s = avctx->priv_data; 26 PNMContext *s = avctx->priv_data;
65 27
66 avcodec_get_frame_defaults((AVFrame*)&s->picture); 28 avcodec_get_frame_defaults((AVFrame*)&s->picture);
67 avctx->coded_frame= (AVFrame*)&s->picture; 29 avctx->coded_frame= (AVFrame*)&s->picture;
68 30
69 return 0;
70 }
71
72 static int pnm_decode_header(AVCodecContext *avctx, PNMContext * const s){
73 char buf1[32], tuple_type[32];
74 int h, w, depth, maxval;
75
76 pnm_get(s, buf1, sizeof(buf1));
77 if (!strcmp(buf1, "P4")) {
78 avctx->pix_fmt = PIX_FMT_MONOWHITE;
79 } else if (!strcmp(buf1, "P5")) {
80 if (avctx->codec_id == CODEC_ID_PGMYUV)
81 avctx->pix_fmt = PIX_FMT_YUV420P;
82 else
83 avctx->pix_fmt = PIX_FMT_GRAY8;
84 } else if (!strcmp(buf1, "P6")) {
85 avctx->pix_fmt = PIX_FMT_RGB24;
86 } else if (!strcmp(buf1, "P7")) {
87 w = -1;
88 h = -1;
89 maxval = -1;
90 depth = -1;
91 tuple_type[0] = '\0';
92 for(;;) {
93 pnm_get(s, buf1, sizeof(buf1));
94 if (!strcmp(buf1, "WIDTH")) {
95 pnm_get(s, buf1, sizeof(buf1));
96 w = strtol(buf1, NULL, 10);
97 } else if (!strcmp(buf1, "HEIGHT")) {
98 pnm_get(s, buf1, sizeof(buf1));
99 h = strtol(buf1, NULL, 10);
100 } else if (!strcmp(buf1, "DEPTH")) {
101 pnm_get(s, buf1, sizeof(buf1));
102 depth = strtol(buf1, NULL, 10);
103 } else if (!strcmp(buf1, "MAXVAL")) {
104 pnm_get(s, buf1, sizeof(buf1));
105 maxval = strtol(buf1, NULL, 10);
106 } else if (!strcmp(buf1, "TUPLETYPE")) {
107 pnm_get(s, tuple_type, sizeof(tuple_type));
108 } else if (!strcmp(buf1, "ENDHDR")) {
109 break;
110 } else {
111 return -1;
112 }
113 }
114 /* check that all tags are present */
115 if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0' || avcodec_check_dimensions(avctx, w, h))
116 return -1;
117
118 avctx->width = w;
119 avctx->height = h;
120 if (depth == 1) {
121 if (maxval == 1)
122 avctx->pix_fmt = PIX_FMT_MONOWHITE;
123 else
124 avctx->pix_fmt = PIX_FMT_GRAY8;
125 } else if (depth == 3) {
126 avctx->pix_fmt = PIX_FMT_RGB24;
127 } else if (depth == 4) {
128 avctx->pix_fmt = PIX_FMT_RGB32;
129 } else {
130 return -1;
131 }
132 return 0;
133 } else {
134 return -1;
135 }
136 pnm_get(s, buf1, sizeof(buf1));
137 avctx->width = atoi(buf1);
138 if (avctx->width <= 0)
139 return -1;
140 pnm_get(s, buf1, sizeof(buf1));
141 avctx->height = atoi(buf1);
142 if(avcodec_check_dimensions(avctx, avctx->width, avctx->height))
143 return -1;
144 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
145 pnm_get(s, buf1, sizeof(buf1));
146 s->maxval = atoi(buf1);
147 if(s->maxval >= 256 && avctx->pix_fmt == PIX_FMT_GRAY8) {
148 avctx->pix_fmt = PIX_FMT_GRAY16BE;
149 if (s->maxval != 65535)
150 avctx->pix_fmt = PIX_FMT_GRAY16;
151 }
152 }
153 /* more check if YUV420 */
154 if (avctx->pix_fmt == PIX_FMT_YUV420P) {
155 if ((avctx->width & 1) != 0)
156 return -1;
157 h = (avctx->height * 2);
158 if ((h % 3) != 0)
159 return -1;
160 h /= 3;
161 avctx->height = h;
162 }
163 return 0; 31 return 0;
164 } 32 }
165 33
166 static int pnm_decode_frame(AVCodecContext *avctx, 34 static int pnm_decode_frame(AVCodecContext *avctx,
167 void *data, int *data_size, 35 void *data, int *data_size,
175 43
176 s->bytestream_start= 44 s->bytestream_start=
177 s->bytestream= buf; 45 s->bytestream= buf;
178 s->bytestream_end= buf + buf_size; 46 s->bytestream_end= buf + buf_size;
179 47
180 if(pnm_decode_header(avctx, s) < 0) 48 if(ff_pnm_decode_header(avctx, s) < 0)
181 return -1; 49 return -1;
182 50
183 if(p->data[0]) 51 if(p->data[0])
184 avctx->release_buffer(avctx, p); 52 avctx->release_buffer(avctx, p);
185 53
484 else 352 else
485 return 0; 353 return 0;
486 } 354 }
487 #endif 355 #endif
488 356
489 #ifdef CONFIG_PNM_PARSER
490 static int pnm_parse(AVCodecParserContext *s,
491 AVCodecContext *avctx,
492 const uint8_t **poutbuf, int *poutbuf_size,
493 const uint8_t *buf, int buf_size)
494 {
495 ParseContext *pc = s->priv_data;
496 PNMContext pnmctx;
497 int next;
498
499 for(; pc->overread>0; pc->overread--){
500 pc->buffer[pc->index++]= pc->buffer[pc->overread_index++];
501 }
502 retry:
503 if(pc->index){
504 pnmctx.bytestream_start=
505 pnmctx.bytestream= pc->buffer;
506 pnmctx.bytestream_end= pc->buffer + pc->index;
507 }else{
508 pnmctx.bytestream_start=
509 pnmctx.bytestream= (uint8_t *) buf; /* casts avoid warnings */
510 pnmctx.bytestream_end= (uint8_t *) buf + buf_size;
511 }
512 if(pnm_decode_header(avctx, &pnmctx) < 0){
513 if(pnmctx.bytestream < pnmctx.bytestream_end){
514 if(pc->index){
515 pc->index=0;
516 }else{
517 buf++;
518 buf_size--;
519 }
520 goto retry;
521 }
522 #if 0
523 if(pc->index && pc->index*2 + FF_INPUT_BUFFER_PADDING_SIZE < pc->buffer_size && buf_size > pc->index){
524 memcpy(pc->buffer + pc->index, buf, pc->index);
525 pc->index += pc->index;
526 buf += pc->index;
527 buf_size -= pc->index;
528 goto retry;
529 }
530 #endif
531 next= END_NOT_FOUND;
532 }else{
533 next= pnmctx.bytestream - pnmctx.bytestream_start
534 + avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
535 if(pnmctx.bytestream_start!=buf)
536 next-= pc->index;
537 if(next > buf_size)
538 next= END_NOT_FOUND;
539 }
540
541 if(ff_combine_frame(pc, next, &buf, &buf_size)<0){
542 *poutbuf = NULL;
543 *poutbuf_size = 0;
544 return buf_size;
545 }
546 *poutbuf = buf;
547 *poutbuf_size = buf_size;
548 return next;
549 }
550
551 AVCodecParser pnm_parser = {
552 { CODEC_ID_PGM, CODEC_ID_PGMYUV, CODEC_ID_PPM, CODEC_ID_PBM, CODEC_ID_PAM},
553 sizeof(ParseContext),
554 NULL,
555 pnm_parse,
556 ff_parse_close,
557 };
558 #endif /* CONFIG_PNM_PARSER */
559 357
560 #ifdef CONFIG_PGM_ENCODER 358 #ifdef CONFIG_PGM_ENCODER
561 AVCodec pgm_encoder = { 359 AVCodec pgm_encoder = {
562 "pgm", 360 "pgm",
563 CODEC_TYPE_VIDEO, 361 CODEC_TYPE_VIDEO,