Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6148 serge 1
/*
2
 * Microsoft RLE video decoder
3
 * Copyright (C) 2003 the ffmpeg project
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg 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
 * FFmpeg 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 FFmpeg; 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
 * MS RLE video decoder by Mike Melanson (melanson@pcisys.net)
25
 * For more information about the MS RLE format, visit:
26
 *   http://www.pcisys.net/~melanson/codecs/
27
 *
28
 * The MS RLE decoder outputs PAL8 colorspace data.
29
 */
30
 
31
#include 
32
#include 
33
#include 
34
 
35
#include "avcodec.h"
36
#include "internal.h"
37
#include "msrledec.h"
38
 
39
typedef struct MsrleContext {
40
    AVCodecContext *avctx;
41
    AVFrame frame;
42
 
43
    GetByteContext gb;
44
    const unsigned char *buf;
45
    int size;
46
 
47
    uint32_t pal[256];
48
} MsrleContext;
49
 
50
static av_cold int msrle_decode_init(AVCodecContext *avctx)
51
{
52
    MsrleContext *s = avctx->priv_data;
53
    int i;
54
 
55
    s->avctx = avctx;
56
 
57
    switch (avctx->bits_per_coded_sample) {
58
    case 1:
59
        avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
60
        break;
61
    case 4:
62
    case 8:
63
        avctx->pix_fmt = AV_PIX_FMT_PAL8;
64
        break;
65
    case 24:
66
        avctx->pix_fmt = AV_PIX_FMT_BGR24;
67
        break;
68
    default:
69
        av_log(avctx, AV_LOG_ERROR, "unsupported bits per sample\n");
70
        return AVERROR_INVALIDDATA;
71
    }
72
 
73
    avcodec_get_frame_defaults(&s->frame);
74
 
75
    if (avctx->extradata_size >= 4)
76
        for (i = 0; i < FFMIN(avctx->extradata_size, AVPALETTE_SIZE)/4; i++)
77
            s->pal[i] = 0xFFU<<24 | AV_RL32(avctx->extradata+4*i);
78
 
79
    return 0;
80
}
81
 
82
static int msrle_decode_frame(AVCodecContext *avctx,
83
                              void *data, int *got_frame,
84
                              AVPacket *avpkt)
85
{
86
    const uint8_t *buf = avpkt->data;
87
    int buf_size = avpkt->size;
88
    MsrleContext *s = avctx->priv_data;
89
    int istride = FFALIGN(avctx->width*avctx->bits_per_coded_sample, 32) / 8;
90
    int ret;
91
 
92
    s->buf = buf;
93
    s->size = buf_size;
94
 
95
    if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0)
96
        return ret;
97
 
98
    if (avctx->bits_per_coded_sample > 1 && avctx->bits_per_coded_sample <= 8) {
99
        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
100
 
101
        if (pal) {
102
            s->frame.palette_has_changed = 1;
103
            memcpy(s->pal, pal, AVPALETTE_SIZE);
104
        }
105
        /* make the palette available */
106
        memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE);
107
    }
108
 
109
    /* FIXME how to correctly detect RLE ??? */
110
    if (avctx->height * istride == avpkt->size) { /* assume uncompressed */
111
        int linesize = (avctx->width * avctx->bits_per_coded_sample + 7) / 8;
112
        uint8_t *ptr = s->frame.data[0];
113
        uint8_t *buf = avpkt->data + (avctx->height-1)*istride;
114
        int i, j;
115
 
116
        for (i = 0; i < avctx->height; i++) {
117
            if (avctx->bits_per_coded_sample == 4) {
118
                for (j = 0; j < avctx->width - 1; j += 2) {
119
                    ptr[j+0] = buf[j>>1] >> 4;
120
                    ptr[j+1] = buf[j>>1] & 0xF;
121
                }
122
                if (avctx->width & 1)
123
                    ptr[j+0] = buf[j>>1] >> 4;
124
            } else {
125
                memcpy(ptr, buf, linesize);
126
            }
127
            buf -= istride;
128
            ptr += s->frame.linesize[0];
129
        }
130
    } else {
131
        bytestream2_init(&s->gb, buf, buf_size);
132
        ff_msrle_decode(avctx, (AVPicture*)&s->frame, avctx->bits_per_coded_sample, &s->gb);
133
    }
134
 
135
    if ((ret = av_frame_ref(data, &s->frame)) < 0)
136
        return ret;
137
 
138
    *got_frame      = 1;
139
 
140
    /* report that the buffer was completely consumed */
141
    return buf_size;
142
}
143
 
144
static av_cold int msrle_decode_end(AVCodecContext *avctx)
145
{
146
    MsrleContext *s = avctx->priv_data;
147
 
148
    /* release the last frame */
149
    av_frame_unref(&s->frame);
150
 
151
    return 0;
152
}
153
 
154
AVCodec ff_msrle_decoder = {
155
    .name           = "msrle",
156
    .long_name      = NULL_IF_CONFIG_SMALL("Microsoft RLE"),
157
    .type           = AVMEDIA_TYPE_VIDEO,
158
    .id             = AV_CODEC_ID_MSRLE,
159
    .priv_data_size = sizeof(MsrleContext),
160
    .init           = msrle_decode_init,
161
    .close          = msrle_decode_end,
162
    .decode         = msrle_decode_frame,
163
    .capabilities   = CODEC_CAP_DR1,
164
};