~ubuntu-branches/ubuntu/saucy/gst-libav1.0/saucy-proposed

« back to all changes in this revision

Viewing changes to gst-libs/ext/libav/libavcodec/qpeg.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2013-07-30 09:00:15 UTC
  • mfrom: (1.1.16) (7.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20130730090015-sc1ou2yssu7q5w4e
Tags: 1.1.3-1
* New upstream development snapshot:
  + debian/control:
    - Build depend on GStreamer and gst-plugins-base >= 1.1.3.

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) {
204
196
            code &= 0x1F;
205
197
 
206
198
            for(i = 0; i <= code; i++) {
207
 
                dst[filled++] = *src++;
 
199
                dst[filled++] = bytestream2_get_byte(&qctx->buffer);
208
200
                if(filled >= width) {
209
201
                    filled = 0;
210
202
                    dst -= stride;
211
203
                    height--;
212
204
                }
213
205
            }
214
 
            size -= code + 1;
215
206
        } else if(code >= 0x80) { /* skip code: 0x80..0xBF */
216
207
            int skip;
217
208
 
219
210
            /* codes 0x80 and 0x81 are actually escape codes,
220
211
               skip value minus constant is in the next byte */
221
212
            if(!code)
222
 
                skip = (*src++) + 64;
 
213
                skip = bytestream2_get_byte(&qctx->buffer) +  64;
223
214
            else if(code == 1)
224
 
                skip = (*src++) + 320;
 
215
                skip = bytestream2_get_byte(&qctx->buffer) + 320;
225
216
            else
226
217
                skip = code;
227
218
            filled += skip;
234
225
            }
235
226
        } else {
236
227
            /* zero code treated as one-pixel skip */
237
 
            if(code)
 
228
            if(code) {
238
229
                dst[filled++] = ctable[code & 0x7F];
 
230
            }
239
231
            else
240
232
                filled++;
241
233
            if(filled >= width) {
248
240
}
249
241
 
250
242
static int decode_frame(AVCodecContext *avctx,
251
 
                        void *data, int *data_size,
 
243
                        void *data, int *got_frame,
252
244
                        AVPacket *avpkt)
253
245
{
254
 
    const uint8_t *buf = avpkt->data;
255
 
    int buf_size = avpkt->size;
 
246
    uint8_t ctable[128];
256
247
    QpegContext * const a = avctx->priv_data;
257
 
    AVFrame * const p= (AVFrame*)&a->pic;
 
248
    AVFrame * const p = &a->pic;
258
249
    uint8_t* outdata;
259
250
    int delta;
260
251
    const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
261
252
 
 
253
    if (avpkt->size < 0x86) {
 
254
        av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
 
255
        return AVERROR_INVALIDDATA;
 
256
    }
 
257
 
 
258
    bytestream2_init(&a->buffer, avpkt->data, avpkt->size);
262
259
    p->reference = 3;
263
260
    if (avctx->reget_buffer(avctx, p) < 0) {
264
261
        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
265
262
        return -1;
266
263
    }
267
264
    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);
 
265
    bytestream2_skip(&a->buffer, 4);
 
266
    bytestream2_get_buffer(&a->buffer, ctable, 128);
 
267
    bytestream2_skip(&a->buffer, 1);
 
268
 
 
269
    delta = bytestream2_get_byte(&a->buffer);
 
270
    if(delta == 0x10) {
 
271
        qpeg_decode_intra(a, outdata, a->pic.linesize[0], avctx->width, avctx->height);
270
272
    } 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);
 
273
        qpeg_decode_inter(a, outdata, a->pic.linesize[0], avctx->width, avctx->height, delta, ctable, a->refdata);
273
274
    }
274
275
 
275
276
    /* make the palette available on the way out */
279
280
    }
280
281
    memcpy(a->pic.data[1], a->pal, AVPALETTE_SIZE);
281
282
 
282
 
    *data_size = sizeof(AVFrame);
 
283
    *got_frame      = 1;
283
284
    *(AVFrame*)data = a->pic;
284
285
 
285
 
    return buf_size;
 
286
    return avpkt->size;
286
287
}
287
288
 
288
289
static av_cold int decode_init(AVCodecContext *avctx){
289
290
    QpegContext * const a = avctx->priv_data;
290
291
 
291
292
    a->avctx = avctx;
292
 
    avctx->pix_fmt= PIX_FMT_PAL8;
 
293
    avctx->pix_fmt= AV_PIX_FMT_PAL8;
293
294
    a->refdata = av_malloc(avctx->width * avctx->height);
294
295
 
295
296
    return 0;
297
298
 
298
299
static av_cold int decode_end(AVCodecContext *avctx){
299
300
    QpegContext * const a = avctx->priv_data;
300
 
    AVFrame * const p= (AVFrame*)&a->pic;
 
301
    AVFrame * const p = &a->pic;
301
302
 
302
303
    if(p->data[0])
303
304
        avctx->release_buffer(avctx, p);
309
310
AVCodec ff_qpeg_decoder = {
310
311
    .name           = "qpeg",
311
312
    .type           = AVMEDIA_TYPE_VIDEO,
312
 
    .id             = CODEC_ID_QPEG,
 
313
    .id             = AV_CODEC_ID_QPEG,
313
314
    .priv_data_size = sizeof(QpegContext),
314
315
    .init           = decode_init,
315
316
    .close          = decode_end,
316
317
    .decode         = decode_frame,
317
318
    .capabilities   = CODEC_CAP_DR1,
318
 
    .long_name = NULL_IF_CONFIG_SMALL("Q-team QPEG"),
 
319
    .long_name      = NULL_IF_CONFIG_SMALL("Q-team QPEG"),
319
320
};