~siretart/libav/trusty

« back to all changes in this revision

Viewing changes to libavcodec/qpeg.c

  • Committer: Reinhard Tartler
  • Date: 2013-10-23 03:04:17 UTC
  • mfrom: (1.3.36 sid)
  • Revision ID: siretart@tauware.de-20131023030417-1o6mpkl1l0raifjt
mergeĀ fromĀ debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 */
26
26
 
27
27
#include "avcodec.h"
 
28
#include "bytestream.h"
28
29
 
29
30
typedef struct QpegContext{
30
31
    AVCodecContext *avctx;
31
32
    AVFrame pic;
32
33
    uint8_t *refdata;
33
34
    uint32_t pal[256];
 
35
    GetByteContext buffer;
34
36
} QpegContext;
35
37
 
36
 
static void qpeg_decode_intra(const uint8_t *src, uint8_t *dst, int size,
37
 
                            int stride, int width, int height)
 
38
static void qpeg_decode_intra(QpegContext *qctx, uint8_t *dst,
 
39
                              int stride, int width, int height)
38
40
{
39
41
    int i;
40
42
    int code;
47
49
    height--;
48
50
    dst = dst + height * stride;
49
51
 
50
 
    while((size > 0) && (rows_to_go > 0)) {
51
 
        code = *src++;
52
 
        size--;
 
52
    while ((bytestream2_get_bytes_left(&qctx->buffer) > 0) && (rows_to_go > 0)) {
 
53
        code = bytestream2_get_byte(&qctx->buffer);
53
54
        run = copy = 0;
54
55
        if(code == 0xFC) /* end-of-picture code */
55
56
            break;
56
57
        if(code >= 0xF8) { /* very long run */
57
 
            c0 = *src++;
58
 
            c1 = *src++;
59
 
            size -= 2;
 
58
            c0 = bytestream2_get_byte(&qctx->buffer);
 
59
            c1 = bytestream2_get_byte(&qctx->buffer);
60
60
            run = ((code & 0x7) << 16) + (c0 << 8) + c1 + 2;
61
61
        } else if (code >= 0xF0) { /* long run */
62
 
            c0 = *src++;
63
 
            size--;
 
62
            c0 = bytestream2_get_byte(&qctx->buffer);
64
63
            run = ((code & 0xF) << 8) + c0 + 2;
65
64
        } else if (code >= 0xE0) { /* short run */
66
65
            run = (code & 0x1F) + 2;
67
66
        } else if (code >= 0xC0) { /* very long copy */
68
 
            c0 = *src++;
69
 
            c1 = *src++;
70
 
            size -= 2;
 
67
            c0 = bytestream2_get_byte(&qctx->buffer);
 
68
            c1 = bytestream2_get_byte(&qctx->buffer);
71
69
            copy = ((code & 0x3F) << 16) + (c0 << 8) + c1 + 1;
72
70
        } else if (code >= 0x80) { /* long copy */
73
 
            c0 = *src++;
74
 
            size--;
 
71
            c0 = bytestream2_get_byte(&qctx->buffer);
75
72
            copy = ((code & 0x7F) << 8) + c0 + 1;
76
73
        } else { /* short copy */
77
74
            copy = code + 1;
81
78
        if(run) {
82
79
            int p;
83
80
 
84
 
            p = *src++;
85
 
            size--;
 
81
            p = bytestream2_get_byte(&qctx->buffer);
86
82
            for(i = 0; i < run; i++) {
87
83
                dst[filled++] = p;
88
84
                if (filled >= width) {
94
90
                }
95
91
            }
96
92
        } else {
97
 
            size -= copy;
98
93
            for(i = 0; i < copy; i++) {
99
 
                dst[filled++] = *src++;
 
94
                dst[filled++] = bytestream2_get_byte(&qctx->buffer);
100
95
                if (filled >= width) {
101
96
                    filled = 0;
102
97
                    dst -= stride;
115
110
 { 0x00, 0x20, 0x18, 0x08, 0x18, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x20, 0x08, 0x10, 0x18, 0x04};
116
111
 
117
112
/* Decodes delta frames */
118
 
static void qpeg_decode_inter(const uint8_t *src, uint8_t *dst, int size,
119
 
                            int stride, int width, int height,
120
 
                            int delta, const uint8_t *ctable, uint8_t *refdata)
 
113
static void qpeg_decode_inter(QpegContext *qctx, uint8_t *dst,
 
114
                              int stride, int width, int height,
 
115
                              int delta, const uint8_t *ctable,
 
116
                              uint8_t *refdata)
121
117
{
122
118
    int i, j;
123
119
    int code;
132
128
    height--;
133
129
    dst = dst + height * stride;
134
130
 
135
 
    while((size > 0) && (height >= 0)) {
136
 
        code = *src++;
137
 
        size--;
 
131
    while ((bytestream2_get_bytes_left(&qctx->buffer) > 0) && (height >= 0)) {
 
132
        code = bytestream2_get_byte(&qctx->buffer);
138
133
 
139
134
        if(delta) {
140
135
            /* motion compensation */
151
146
                    me_h = qpeg_table_h[me_idx];
152
147
 
153
148
                    /* extract motion vector */
154
 
                    corr = *src++;
155
 
                    size--;
 
149
                    corr = bytestream2_get_byte(&qctx->buffer);
156
150
 
157
151
                    val = corr >> 4;
158
152
                    if(val > 7)
179
173
                        }
180
174
                    }
181
175
                }
182
 
                code = *src++;
183
 
                size--;
 
176
                code = bytestream2_get_byte(&qctx->buffer);
184
177
            }
185
178
        }
186
179
 
190
183
            int p;
191
184
 
192
185
            code &= 0x1F;
193
 
            p = *src++;
194
 
            size--;
 
186
            p = bytestream2_get_byte(&qctx->buffer);
195
187
            for(i = 0; i <= code; i++) {
196
188
                dst[filled++] = p;
197
189
                if(filled >= width) {
198
190
                    filled = 0;
199
191
                    dst -= stride;
200
192
                    height--;
 
193
                    if (height < 0)
 
194
                        break;
201
195
                }
202
196
            }
203
197
        } else if(code >= 0xC0) { /* copy code: 0xC0..0xDF */
204
198
            code &= 0x1F;
205
199
 
206
200
            for(i = 0; i <= code; i++) {
207
 
                dst[filled++] = *src++;
 
201
                dst[filled++] = bytestream2_get_byte(&qctx->buffer);
208
202
                if(filled >= width) {
209
203
                    filled = 0;
210
204
                    dst -= stride;
211
205
                    height--;
 
206
                    if (height < 0)
 
207
                        break;
212
208
                }
213
209
            }
214
 
            size -= code + 1;
215
210
        } else if(code >= 0x80) { /* skip code: 0x80..0xBF */
216
211
            int skip;
217
212
 
219
214
            /* codes 0x80 and 0x81 are actually escape codes,
220
215
               skip value minus constant is in the next byte */
221
216
            if(!code)
222
 
                skip = (*src++) + 64;
 
217
                skip = bytestream2_get_byte(&qctx->buffer) +  64;
223
218
            else if(code == 1)
224
 
                skip = (*src++) + 320;
 
219
                skip = bytestream2_get_byte(&qctx->buffer) + 320;
225
220
            else
226
221
                skip = code;
227
222
            filled += skip;
234
229
            }
235
230
        } else {
236
231
            /* zero code treated as one-pixel skip */
237
 
            if(code)
 
232
            if(code) {
238
233
                dst[filled++] = ctable[code & 0x7F];
 
234
            }
239
235
            else
240
236
                filled++;
241
237
            if(filled >= width) {
248
244
}
249
245
 
250
246
static int decode_frame(AVCodecContext *avctx,
251
 
                        void *data, int *data_size,
 
247
                        void *data, int *got_frame,
252
248
                        AVPacket *avpkt)
253
249
{
254
 
    const uint8_t *buf = avpkt->data;
255
 
    int buf_size = avpkt->size;
 
250
    uint8_t ctable[128];
256
251
    QpegContext * const a = avctx->priv_data;
257
 
    AVFrame * const p= (AVFrame*)&a->pic;
 
252
    AVFrame * const p = &a->pic;
258
253
    uint8_t* outdata;
259
254
    int delta;
260
255
    const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
261
256
 
 
257
    if (avpkt->size < 0x86) {
 
258
        av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
 
259
        return AVERROR_INVALIDDATA;
 
260
    }
 
261
 
 
262
    bytestream2_init(&a->buffer, avpkt->data, avpkt->size);
262
263
    p->reference = 3;
263
264
    if (avctx->reget_buffer(avctx, p) < 0) {
264
265
        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
265
266
        return -1;
266
267
    }
267
268
    outdata = a->pic.data[0];
268
 
    if(buf[0x85] == 0x10) {
269
 
        qpeg_decode_intra(buf+0x86, outdata, buf_size - 0x86, a->pic.linesize[0], avctx->width, avctx->height);
 
269
    bytestream2_skip(&a->buffer, 4);
 
270
    bytestream2_get_buffer(&a->buffer, ctable, 128);
 
271
    bytestream2_skip(&a->buffer, 1);
 
272
 
 
273
    delta = bytestream2_get_byte(&a->buffer);
 
274
    if(delta == 0x10) {
 
275
        qpeg_decode_intra(a, outdata, a->pic.linesize[0], avctx->width, avctx->height);
270
276
    } else {
271
 
        delta = buf[0x85];
272
 
        qpeg_decode_inter(buf+0x86, outdata, buf_size - 0x86, a->pic.linesize[0], avctx->width, avctx->height, delta, buf + 4, a->refdata);
 
277
        qpeg_decode_inter(a, outdata, a->pic.linesize[0], avctx->width, avctx->height, delta, ctable, a->refdata);
273
278
    }
274
279
 
275
280
    /* make the palette available on the way out */
279
284
    }
280
285
    memcpy(a->pic.data[1], a->pal, AVPALETTE_SIZE);
281
286
 
282
 
    *data_size = sizeof(AVFrame);
 
287
    *got_frame      = 1;
283
288
    *(AVFrame*)data = a->pic;
284
289
 
285
 
    return buf_size;
 
290
    return avpkt->size;
286
291
}
287
292
 
288
293
static av_cold int decode_init(AVCodecContext *avctx){
289
294
    QpegContext * const a = avctx->priv_data;
290
295
 
291
296
    a->avctx = avctx;
292
 
    avctx->pix_fmt= PIX_FMT_PAL8;
 
297
    avctx->pix_fmt= AV_PIX_FMT_PAL8;
293
298
    a->refdata = av_malloc(avctx->width * avctx->height);
294
299
 
295
300
    return 0;
297
302
 
298
303
static av_cold int decode_end(AVCodecContext *avctx){
299
304
    QpegContext * const a = avctx->priv_data;
300
 
    AVFrame * const p= (AVFrame*)&a->pic;
 
305
    AVFrame * const p = &a->pic;
301
306
 
302
307
    if(p->data[0])
303
308
        avctx->release_buffer(avctx, p);
309
314
AVCodec ff_qpeg_decoder = {
310
315
    .name           = "qpeg",
311
316
    .type           = AVMEDIA_TYPE_VIDEO,
312
 
    .id             = CODEC_ID_QPEG,
 
317
    .id             = AV_CODEC_ID_QPEG,
313
318
    .priv_data_size = sizeof(QpegContext),
314
319
    .init           = decode_init,
315
320
    .close          = decode_end,
316
321
    .decode         = decode_frame,
317
322
    .capabilities   = CODEC_CAP_DR1,
318
 
    .long_name = NULL_IF_CONFIG_SMALL("Q-team QPEG"),
 
323
    .long_name      = NULL_IF_CONFIG_SMALL("Q-team QPEG"),
319
324
};