~ubuntu-branches/ubuntu/raring/libav/raring-security

« back to all changes in this revision

Viewing changes to .pc/post-0.7.1/0022-Fix-incorrect-max_lowres-values.patch/libavcodec/kgv1dec.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2011-09-28 09:18:34 UTC
  • mfrom: (1.3.7 sid)
  • Revision ID: package-import@ubuntu.com-20110928091834-w415mnuh06h4zpvc
Tags: 4:0.7.1-7ubuntu2
Revert "Convert package to include multiarch support."

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Kega Game Video (KGV1) decoder
 
3
 * Copyright (c) 2010 Daniel Verkamp
 
4
 *
 
5
 * This file is part of Libav.
 
6
 *
 
7
 * Libav is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * Libav is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with Libav; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
20
 */
 
21
 
 
22
/**
 
23
 * @file
 
24
 * Kega Game Video decoder
 
25
 */
 
26
 
 
27
#include "libavutil/intreadwrite.h"
 
28
#include "libavutil/imgutils.h"
 
29
#include "avcodec.h"
 
30
 
 
31
typedef struct {
 
32
    AVCodecContext *avctx;
 
33
    AVFrame pic;
 
34
    uint16_t *prev, *cur;
 
35
} KgvContext;
 
36
 
 
37
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
 
38
{
 
39
    const uint8_t *buf = avpkt->data;
 
40
    const uint8_t *buf_end = buf + avpkt->size;
 
41
    KgvContext * const c = avctx->priv_data;
 
42
    int offsets[7];
 
43
    uint16_t *out, *prev;
 
44
    int outcnt = 0, maxcnt;
 
45
    int w, h, i;
 
46
 
 
47
    if (avpkt->size < 2)
 
48
        return -1;
 
49
 
 
50
    w = (buf[0] + 1) * 8;
 
51
    h = (buf[1] + 1) * 8;
 
52
    buf += 2;
 
53
 
 
54
    if (av_image_check_size(w, h, 0, avctx))
 
55
        return -1;
 
56
 
 
57
    if (w != avctx->width || h != avctx->height)
 
58
        avcodec_set_dimensions(avctx, w, h);
 
59
 
 
60
    maxcnt = w * h;
 
61
 
 
62
    out = av_realloc(c->cur, w * h * 2);
 
63
    if (!out)
 
64
        return -1;
 
65
    c->cur = out;
 
66
 
 
67
    prev = av_realloc(c->prev, w * h * 2);
 
68
    if (!prev)
 
69
        return -1;
 
70
    c->prev = prev;
 
71
 
 
72
    for (i = 0; i < 7; i++)
 
73
        offsets[i] = -1;
 
74
 
 
75
    while (outcnt < maxcnt && buf_end - 2 > buf) {
 
76
        int code = AV_RL16(buf);
 
77
        buf += 2;
 
78
 
 
79
        if (!(code & 0x8000)) {
 
80
            out[outcnt++] = code; // rgb555 pixel coded directly
 
81
        } else {
 
82
            int count;
 
83
            uint16_t *inp;
 
84
 
 
85
            if ((code & 0x6000) == 0x6000) {
 
86
                // copy from previous frame
 
87
                int oidx = (code >> 10) & 7;
 
88
                int start;
 
89
 
 
90
                count = (code & 0x3FF) + 3;
 
91
 
 
92
                if (offsets[oidx] < 0) {
 
93
                    if (buf_end - 3 < buf)
 
94
                        break;
 
95
                    offsets[oidx] = AV_RL24(buf);
 
96
                    buf += 3;
 
97
                }
 
98
 
 
99
                start = (outcnt + offsets[oidx]) % maxcnt;
 
100
 
 
101
                if (maxcnt - start < count)
 
102
                    break;
 
103
 
 
104
                inp = prev + start;
 
105
            } else {
 
106
                // copy from earlier in this frame
 
107
                int offset = (code & 0x1FFF) + 1;
 
108
 
 
109
                if (!(code & 0x6000)) {
 
110
                    count = 2;
 
111
                } else if ((code & 0x6000) == 0x2000) {
 
112
                    count = 3;
 
113
                } else {
 
114
                    if (buf_end - 1 < buf)
 
115
                        break;
 
116
                    count = 4 + *buf++;
 
117
                }
 
118
 
 
119
                if (outcnt < offset)
 
120
                    break;
 
121
 
 
122
                inp = out + outcnt - offset;
 
123
            }
 
124
 
 
125
            if (maxcnt - outcnt < count)
 
126
                break;
 
127
 
 
128
            for (i = 0; i < count; i++)
 
129
                out[outcnt++] = inp[i];
 
130
        }
 
131
    }
 
132
 
 
133
    if (outcnt - maxcnt)
 
134
        av_log(avctx, AV_LOG_DEBUG, "frame finished with %d diff\n", outcnt - maxcnt);
 
135
 
 
136
    c->pic.data[0]     = (uint8_t *)c->cur;
 
137
    c->pic.linesize[0] = w * 2;
 
138
 
 
139
    *data_size = sizeof(AVFrame);
 
140
    *(AVFrame*)data = c->pic;
 
141
 
 
142
    FFSWAP(uint16_t *, c->cur, c->prev);
 
143
 
 
144
    return avpkt->size;
 
145
}
 
146
 
 
147
static av_cold int decode_init(AVCodecContext *avctx)
 
148
{
 
149
    KgvContext * const c = avctx->priv_data;
 
150
 
 
151
    c->avctx = avctx;
 
152
    avctx->pix_fmt = PIX_FMT_RGB555;
 
153
 
 
154
    return 0;
 
155
}
 
156
 
 
157
static av_cold int decode_end(AVCodecContext *avctx)
 
158
{
 
159
    KgvContext * const c = avctx->priv_data;
 
160
 
 
161
    av_freep(&c->cur);
 
162
    av_freep(&c->prev);
 
163
 
 
164
    return 0;
 
165
}
 
166
 
 
167
AVCodec ff_kgv1_decoder = {
 
168
    "kgv1",
 
169
    AVMEDIA_TYPE_VIDEO,
 
170
    CODEC_ID_KGV1,
 
171
    sizeof(KgvContext),
 
172
    decode_init,
 
173
    NULL,
 
174
    decode_end,
 
175
    decode_frame,
 
176
    .max_lowres = 1,
 
177
    .long_name = NULL_IF_CONFIG_SMALL("Kega Game Video"),
 
178
};