3 * eXtended BINary text (XBIN) decoder
5 * Copyright (c) 2010 Peter Ross (pross@xvid.org)
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 * eXtended BINary text (XBIN) decoder
28 * iCEDraw File decoder
31 #include "libavutil/intreadwrite.h"
32 #include "libavutil/xga_font_data.h"
38 typedef struct XbinContext
{
47 static av_cold
int decode_init(AVCodecContext
*avctx
)
49 XbinContext
*s
= avctx
->priv_data
;
53 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
56 s
->font_height
= p
[0];
59 if(avctx
->extradata_size
< 2 + (!!(s
->flags
& BINTEXT_PALETTE
))*3*16
60 + (!!(s
->flags
& BINTEXT_FONT
))*s
->font_height
*256) {
61 av_log(avctx
, AV_LOG_ERROR
, "not enough extradata\n");
62 return AVERROR_INVALIDDATA
;
69 if ((s
->flags
& BINTEXT_PALETTE
)) {
70 for (i
= 0; i
< 16; i
++) {
71 s
->palette
[i
] = 0xFF000000 | (AV_RB24(p
) << 2) | ((AV_RB24(p
) >> 4) & 0x30303);
75 for (i
= 0; i
< 16; i
++)
76 s
->palette
[i
] = 0xFF000000 | ff_cga_palette
[i
];
79 if ((s
->flags
& BINTEXT_FONT
)) {
82 switch(s
->font_height
) {
84 av_log(avctx
, AV_LOG_WARNING
, "font height %i not supported\n", s
->font_height
);
87 s
->font
= avpriv_cga_font
;
90 s
->font
= avpriv_vga16_font
;
95 s
->frame
= av_frame_alloc();
97 return AVERROR(ENOMEM
);
102 #define DEFAULT_BG_COLOR 0
103 av_unused
static void hscroll(AVCodecContext
*avctx
)
105 XbinContext
*s
= avctx
->priv_data
;
106 if (s
->y
< avctx
->height
- s
->font_height
) {
107 s
->y
+= s
->font_height
;
109 memmove(s
->frame
->data
[0], s
->frame
->data
[0] + s
->font_height
*s
->frame
->linesize
[0],
110 (avctx
->height
- s
->font_height
)*s
->frame
->linesize
[0]);
111 memset(s
->frame
->data
[0] + (avctx
->height
- s
->font_height
)*s
->frame
->linesize
[0],
112 DEFAULT_BG_COLOR
, s
->font_height
* s
->frame
->linesize
[0]);
119 * Draw character to screen
121 static void draw_char(AVCodecContext
*avctx
, int c
, int a
)
123 XbinContext
*s
= avctx
->priv_data
;
124 if (s
->y
> avctx
->height
- s
->font_height
)
126 ff_draw_pc_font(s
->frame
->data
[0] + s
->y
* s
->frame
->linesize
[0] + s
->x
,
127 s
->frame
->linesize
[0], s
->font
, s
->font_height
, c
,
130 if (s
->x
> avctx
->width
- FONT_WIDTH
) {
132 s
->y
+= s
->font_height
;
136 static int decode_frame(AVCodecContext
*avctx
,
137 void *data
, int *got_frame
,
140 XbinContext
*s
= avctx
->priv_data
;
141 const uint8_t *buf
= avpkt
->data
;
142 int buf_size
= avpkt
->size
;
143 const uint8_t *buf_end
= buf
+buf_size
;
147 if ((ret
= ff_reget_buffer(avctx
, s
->frame
)) < 0)
149 s
->frame
->pict_type
= AV_PICTURE_TYPE_I
;
150 s
->frame
->palette_has_changed
= 1;
151 memcpy(s
->frame
->data
[1], s
->palette
, 16 * 4);
153 if (avctx
->codec_id
== AV_CODEC_ID_XBIN
) {
154 while (buf
+ 2 < buf_end
) {
156 int type
= *buf
>> 6;
157 int count
= (*buf
& 0x3F) + 1;
160 case 0: //no compression
161 for (i
= 0; i
< count
&& buf
+ 1 < buf_end
; i
++) {
162 draw_char(avctx
, buf
[0], buf
[1]);
166 case 1: //character compression
168 for (i
= 0; i
< count
&& buf
< buf_end
; i
++)
169 draw_char(avctx
, c
, *buf
++);
171 case 2: //attribute compression
173 for (i
= 0; i
< count
&& buf
< buf_end
; i
++)
174 draw_char(avctx
, *buf
++, a
);
176 case 3: //character/attribute compression
179 for (i
= 0; i
< count
&& buf
< buf_end
; i
++)
180 draw_char(avctx
, c
, a
);
184 } else if (avctx
->codec_id
== AV_CODEC_ID_IDF
) {
185 while (buf
+ 2 < buf_end
) {
186 if (AV_RL16(buf
) == 1) {
188 if (buf
+ 6 > buf_end
)
190 for (i
= 0; i
< buf
[2]; i
++)
191 draw_char(avctx
, buf
[4], buf
[5]);
194 draw_char(avctx
, buf
[0], buf
[1]);
199 while (buf
+ 1 < buf_end
) {
200 draw_char(avctx
, buf
[0], buf
[1]);
205 if ((ret
= av_frame_ref(data
, s
->frame
)) < 0)
211 static av_cold
int decode_end(AVCodecContext
*avctx
)
213 XbinContext
*s
= avctx
->priv_data
;
215 av_frame_free(&s
->frame
);
220 #if CONFIG_BINTEXT_DECODER
221 AVCodec ff_bintext_decoder
= {
223 .long_name
= NULL_IF_CONFIG_SMALL("Binary text"),
224 .type
= AVMEDIA_TYPE_VIDEO
,
225 .id
= AV_CODEC_ID_BINTEXT
,
226 .priv_data_size
= sizeof(XbinContext
),
229 .decode
= decode_frame
,
230 .capabilities
= CODEC_CAP_DR1
,
233 #if CONFIG_XBIN_DECODER
234 AVCodec ff_xbin_decoder
= {
236 .long_name
= NULL_IF_CONFIG_SMALL("eXtended BINary text"),
237 .type
= AVMEDIA_TYPE_VIDEO
,
238 .id
= AV_CODEC_ID_XBIN
,
239 .priv_data_size
= sizeof(XbinContext
),
242 .decode
= decode_frame
,
243 .capabilities
= CODEC_CAP_DR1
,
246 #if CONFIG_IDF_DECODER
247 AVCodec ff_idf_decoder
= {
249 .long_name
= NULL_IF_CONFIG_SMALL("iCEDraw text"),
250 .type
= AVMEDIA_TYPE_VIDEO
,
251 .id
= AV_CODEC_ID_IDF
,
252 .priv_data_size
= sizeof(XbinContext
),
255 .decode
= decode_frame
,
256 .capabilities
= CODEC_CAP_DR1
,