GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/bintext.c Lines: 0 113 0.0 %
Date: 2019-11-18 18:00:01 Branches: 0 70 0.0 %

Line Branch Exec Source
1
/*
2
 * Binary text decoder
3
 * eXtended BINary text (XBIN) decoder
4
 * iCEDraw File decoder
5
 * Copyright (c) 2010 Peter Ross (pross@xvid.org)
6
 *
7
 * This file is part of FFmpeg.
8
 *
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.
13
 *
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.
18
 *
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
22
 */
23
24
/**
25
 * @file
26
 * Binary text decoder
27
 * eXtended BINary text (XBIN) decoder
28
 * iCEDraw File decoder
29
 */
30
31
#include "libavutil/intreadwrite.h"
32
#include "libavutil/xga_font_data.h"
33
#include "avcodec.h"
34
#include "cga_data.h"
35
#include "bintext.h"
36
#include "internal.h"
37
38
#define FONT_WIDTH 8
39
40
typedef struct XbinContext {
41
    AVFrame *frame;
42
    int palette[16];
43
    int flags;
44
    int font_height;
45
    const uint8_t *font;
46
    int x, y;
47
} XbinContext;
48
49
static av_cold int decode_init(AVCodecContext *avctx)
50
{
51
    XbinContext *s = avctx->priv_data;
52
    uint8_t *p;
53
    int i;
54
55
    avctx->pix_fmt = AV_PIX_FMT_PAL8;
56
    p = avctx->extradata;
57
    if (p) {
58
        s->font_height = p[0];
59
        s->flags = p[1];
60
        p += 2;
61
        if(avctx->extradata_size < 2 + (!!(s->flags & BINTEXT_PALETTE))*3*16
62
                                     + (!!(s->flags & BINTEXT_FONT))*s->font_height*256) {
63
            av_log(avctx, AV_LOG_ERROR, "not enough extradata\n");
64
            return AVERROR_INVALIDDATA;
65
        }
66
        if (!s->font_height) {
67
            av_log(avctx, AV_LOG_ERROR, "invalid font height\n");
68
            return AVERROR_INVALIDDATA;
69
        }
70
    } else {
71
        s->font_height = 8;
72
        s->flags = 0;
73
    }
74
75
    if ((s->flags & BINTEXT_PALETTE)) {
76
        for (i = 0; i < 16; i++) {
77
            s->palette[i] = 0xFF000000 | (AV_RB24(p) << 2) | ((AV_RB24(p) >> 4) & 0x30303);
78
            p += 3;
79
        }
80
    } else {
81
        for (i = 0; i < 16; i++)
82
            s->palette[i] = 0xFF000000 | ff_cga_palette[i];
83
    }
84
85
    if ((s->flags & BINTEXT_FONT)) {
86
        s->font = p;
87
    } else {
88
        switch(s->font_height) {
89
        default:
90
            av_log(avctx, AV_LOG_WARNING, "font height %i not supported\n", s->font_height);
91
            s->font_height = 8;
92
        case 8:
93
            s->font = avpriv_cga_font;
94
            break;
95
        case 16:
96
            s->font = avpriv_vga16_font;
97
            break;
98
        }
99
    }
100
    if (avctx->width < FONT_WIDTH || avctx->height < s->font_height) {
101
        av_log(avctx, AV_LOG_ERROR, "Resolution too small for font.\n");
102
        return AVERROR_INVALIDDATA;
103
    }
104
105
    return 0;
106
}
107
108
#define DEFAULT_BG_COLOR 0
109
av_unused static void hscroll(AVCodecContext *avctx)
110
{
111
    XbinContext *s = avctx->priv_data;
112
    if (s->y < avctx->height - s->font_height) {
113
        s->y += s->font_height;
114
    } else {
115
        memmove(s->frame->data[0], s->frame->data[0] + s->font_height*s->frame->linesize[0],
116
            (avctx->height - s->font_height)*s->frame->linesize[0]);
117
        memset(s->frame->data[0] + (avctx->height - s->font_height)*s->frame->linesize[0],
118
            DEFAULT_BG_COLOR, s->font_height * s->frame->linesize[0]);
119
    }
120
}
121
122
/**
123
 * Draw character to screen
124
 */
125
static void draw_char(AVCodecContext *avctx, int c, int a)
126
{
127
    XbinContext *s = avctx->priv_data;
128
    if (s->y > avctx->height - s->font_height)
129
        return;
130
    ff_draw_pc_font(s->frame->data[0] + s->y * s->frame->linesize[0] + s->x,
131
                    s->frame->linesize[0], s->font, s->font_height, c,
132
                    a & 0x0F, a >> 4);
133
    s->x += FONT_WIDTH;
134
    if (s->x > avctx->width - FONT_WIDTH) {
135
        s->x = 0;
136
        s->y += s->font_height;
137
    }
138
}
139
140
static int decode_frame(AVCodecContext *avctx,
141
                            void *data, int *got_frame,
142
                            AVPacket *avpkt)
143
{
144
    XbinContext *s = avctx->priv_data;
145
    const uint8_t *buf = avpkt->data;
146
    int buf_size = avpkt->size;
147
    const uint8_t *buf_end = buf+buf_size;
148
    int ret;
149
150
    if ((avctx->width / FONT_WIDTH) * (avctx->height / s->font_height) / 256 > buf_size)
151
        return AVERROR_INVALIDDATA;
152
153
    s->frame = data;
154
    s->x = s->y = 0;
155
    if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0)
156
        return ret;
157
    s->frame->pict_type           = AV_PICTURE_TYPE_I;
158
    s->frame->palette_has_changed = 1;
159
    memcpy(s->frame->data[1], s->palette, 16 * 4);
160
161
    if (avctx->codec_id == AV_CODEC_ID_XBIN) {
162
        while (buf + 2 < buf_end) {
163
            int i,c,a;
164
            int type  = *buf >> 6;
165
            int count = (*buf & 0x3F) + 1;
166
            buf++;
167
            switch (type) {
168
            case 0: //no compression
169
                for (i = 0; i < count && buf + 1 < buf_end; i++) {
170
                    draw_char(avctx, buf[0], buf[1]);
171
                    buf += 2;
172
                }
173
                break;
174
            case 1: //character compression
175
                c = *buf++;
176
                for (i = 0; i < count && buf < buf_end; i++)
177
                    draw_char(avctx, c, *buf++);
178
                break;
179
            case 2: //attribute compression
180
                a = *buf++;
181
                for (i = 0; i < count && buf < buf_end; i++)
182
                    draw_char(avctx, *buf++, a);
183
                break;
184
            case 3: //character/attribute compression
185
                c = *buf++;
186
                a = *buf++;
187
                for (i = 0; i < count && buf < buf_end; i++)
188
                    draw_char(avctx, c, a);
189
                break;
190
            }
191
        }
192
    } else if (avctx->codec_id == AV_CODEC_ID_IDF) {
193
        while (buf + 2 < buf_end) {
194
            if (AV_RL16(buf) == 1) {
195
               int i;
196
               if (buf + 6 > buf_end)
197
                   break;
198
               for (i = 0; i < buf[2]; i++)
199
                   draw_char(avctx, buf[4], buf[5]);
200
               buf += 6;
201
            } else {
202
               draw_char(avctx, buf[0], buf[1]);
203
               buf += 2;
204
            }
205
        }
206
    } else {
207
        while (buf + 1 < buf_end) {
208
            draw_char(avctx, buf[0], buf[1]);
209
            buf += 2;
210
        }
211
    }
212
213
    *got_frame      = 1;
214
    return buf_size;
215
}
216
217
#if CONFIG_BINTEXT_DECODER
218
AVCodec ff_bintext_decoder = {
219
    .name           = "bintext",
220
    .long_name      = NULL_IF_CONFIG_SMALL("Binary text"),
221
    .type           = AVMEDIA_TYPE_VIDEO,
222
    .id             = AV_CODEC_ID_BINTEXT,
223
    .priv_data_size = sizeof(XbinContext),
224
    .init           = decode_init,
225
    .decode         = decode_frame,
226
    .capabilities   = AV_CODEC_CAP_DR1,
227
};
228
#endif
229
#if CONFIG_XBIN_DECODER
230
AVCodec ff_xbin_decoder = {
231
    .name           = "xbin",
232
    .long_name      = NULL_IF_CONFIG_SMALL("eXtended BINary text"),
233
    .type           = AVMEDIA_TYPE_VIDEO,
234
    .id             = AV_CODEC_ID_XBIN,
235
    .priv_data_size = sizeof(XbinContext),
236
    .init           = decode_init,
237
    .decode         = decode_frame,
238
    .capabilities   = AV_CODEC_CAP_DR1,
239
};
240
#endif
241
#if CONFIG_IDF_DECODER
242
AVCodec ff_idf_decoder = {
243
    .name           = "idf",
244
    .long_name      = NULL_IF_CONFIG_SMALL("iCEDraw text"),
245
    .type           = AVMEDIA_TYPE_VIDEO,
246
    .id             = AV_CODEC_ID_IDF,
247
    .priv_data_size = sizeof(XbinContext),
248
    .init           = decode_init,
249
    .decode         = decode_frame,
250
    .capabilities   = AV_CODEC_CAP_DR1,
251
};
252
#endif