4 * Copyright (c) 2012 Paul B Mahol
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "libavutil/avstring.h"
29 static int convert(uint8_t x
)
40 static int parse_str_int(const uint8_t *p
, int len
, const uint8_t *key
)
42 const uint8_t *end
= p
+ len
;
44 for(; p
<end
- strlen(key
); p
++) {
45 if (!memcmp(p
, key
, strlen(key
)))
54 int64_t ret
= strtol(p
, &eptr
, 10);
55 if ((const uint8_t *)eptr
!= p
)
61 static int xbm_decode_frame(AVCodecContext
*avctx
, void *data
,
62 int *got_frame
, AVPacket
*avpkt
)
65 int ret
, linesize
, i
, j
;
68 const uint8_t *end
, *ptr
= avpkt
->data
;
72 avctx
->pix_fmt
= AV_PIX_FMT_MONOWHITE
;
73 end
= avpkt
->data
+ avpkt
->size
;
75 width
= parse_str_int(avpkt
->data
, avpkt
->size
, "_width");
76 height
= parse_str_int(avpkt
->data
, avpkt
->size
, "_height");
78 if ((ret
= ff_set_dimensions(avctx
, width
, height
)) < 0)
81 if ((ret
= ff_get_buffer(avctx
, p
, 0)) < 0)
84 // goto start of image data
85 next
= memchr(ptr
, '{', avpkt
->size
);
87 next
= memchr(ptr
, '(', avpkt
->size
);
89 return AVERROR_INVALIDDATA
;
92 linesize
= (avctx
->width
+ 7) / 8;
93 for (i
= 0; i
< avctx
->height
; i
++) {
94 dst
= p
->data
[0] + i
* p
->linesize
[0];
95 for (j
= 0; j
< linesize
; j
++) {
98 while (ptr
< end
&& *ptr
!= 'x' && *ptr
!= '$')
102 if (ptr
< end
&& av_isxdigit(*ptr
)) {
103 val
= convert(*ptr
++);
104 if (av_isxdigit(*ptr
))
105 val
= (val
<< 4) + convert(*ptr
++);
106 *dst
++ = ff_reverse
[val
];
107 if (av_isxdigit(*ptr
) && j
+1 < linesize
) {
109 val
= convert(*ptr
++);
110 if (av_isxdigit(*ptr
))
111 val
= (val
<< 4) + convert(*ptr
++);
112 *dst
++ = ff_reverse
[val
];
115 av_log(avctx
, AV_LOG_ERROR
,
116 "Unexpected data at %.8s.\n", ptr
);
117 return AVERROR_INVALIDDATA
;
123 p
->pict_type
= AV_PICTURE_TYPE_I
;
130 AVCodec ff_xbm_decoder
= {
132 .long_name
= NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"),
133 .type
= AVMEDIA_TYPE_VIDEO
,
134 .id
= AV_CODEC_ID_XBM
,
135 .decode
= xbm_decode_frame
,
136 .capabilities
= CODEC_CAP_DR1
,