~medibuntu-maintainers/mplayer/medibuntu.quantal

« back to all changes in this revision

Viewing changes to libavcodec/msrledec.c

  • Committer: Gauvain Pocentek
  • Date: 2011-08-21 07:22:23 UTC
  • mfrom: (66.1.11 oneiric)
  • Revision ID: gauvain@pocentek.net-20110821072223-ummeossdz7okpb3d
* Merge from Ubuntu:
  - put back faac support
  - recommends apport-hooks-medibuntu
  - change Maintainer, Uploaders & Vcs-* fields.
* New upstream snapshot
  - update 23mplayer-debug-printf.patch
  - fixes miscompilation with gcc 4.6, Closes: #623304
  - improved internal mkv demuxer, Closes: #595452
  - Fixed segfault due to missing sanitation on playlist files,
    Closes: #591525
  - Fixed byteorder on 16-bit displays, Closes: #594093
  - tighten build depends on libav
  - --enable-largefile switch has been dropped
  - add build dependency on yasm
* Fix build dependency on libjpeg-dev, Closes: #634277
* rewrite debian/copyright in DEP5 format
* fix clean target
* don't remove snapshot_version file
* enable XVID, MP3 and X264 encoders
* simply architecture specific dependencies, Closes: #634773
* make buildlogs verbose
* unbreak building mplayer-doc package
* don't fail debian package build if not all shlibdeps information could be retrieved
* update configure flags for static libav* libraries
* fix spelling in mplayer-dbg description, Closes: #617826
* enable blueray support, Closes: #577761
* Select oss as default audio output module on kFreeBSD, Closes: #598431
* Update documentation with regard to our modifications to the upstream tarball.
* really no longer build mplayer-gui, Closes: #612473
* simplify/remove instruction to get upstream sources
* normalize debian/{control,copyright,mplayer.install} with wrap-and-sort
* bump standards version

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Microsoft RLE decoder
3
 
 * Copyright (C) 2008 Konstantin Shishkov
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 decoder based on decoder by Mike Melanson and my own for TSCC
25
 
 * For more information about the MS RLE format, visit:
26
 
 *   http://www.multimedia.cx/msrle.txt
27
 
 */
28
 
 
29
 
#include "libavutil/intreadwrite.h"
30
 
#include "avcodec.h"
31
 
#include "msrledec.h"
32
 
 
33
 
#define FETCH_NEXT_STREAM_BYTE() \
34
 
    if (stream_ptr >= data_size) \
35
 
    { \
36
 
      av_log(avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
37
 
      return -1; \
38
 
    } \
39
 
    stream_byte = data[stream_ptr++];
40
 
 
41
 
static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
42
 
                              const uint8_t *data, int data_size)
43
 
{
44
 
    int stream_ptr = 0;
45
 
    unsigned char rle_code;
46
 
    unsigned char extra_byte, odd_pixel;
47
 
    unsigned char stream_byte;
48
 
    int pixel_ptr = 0;
49
 
    int row_dec = pic->linesize[0];
50
 
    int row_ptr = (avctx->height - 1) * row_dec;
51
 
    int frame_size = row_dec * avctx->height;
52
 
    int i;
53
 
 
54
 
    while (row_ptr >= 0) {
55
 
        FETCH_NEXT_STREAM_BYTE();
56
 
        rle_code = stream_byte;
57
 
        if (rle_code == 0) {
58
 
            /* fetch the next byte to see how to handle escape code */
59
 
            FETCH_NEXT_STREAM_BYTE();
60
 
            if (stream_byte == 0) {
61
 
                /* line is done, goto the next one */
62
 
                row_ptr -= row_dec;
63
 
                pixel_ptr = 0;
64
 
            } else if (stream_byte == 1) {
65
 
                /* decode is done */
66
 
                return 0;
67
 
            } else if (stream_byte == 2) {
68
 
                /* reposition frame decode coordinates */
69
 
                FETCH_NEXT_STREAM_BYTE();
70
 
                pixel_ptr += stream_byte;
71
 
                FETCH_NEXT_STREAM_BYTE();
72
 
                row_ptr -= stream_byte * row_dec;
73
 
        } else {
74
 
            // copy pixels from encoded stream
75
 
            odd_pixel =  stream_byte & 1;
76
 
            rle_code = (stream_byte + 1) / 2;
77
 
            extra_byte = rle_code & 0x01;
78
 
            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
79
 
                (row_ptr < 0)) {
80
 
                av_log(avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
81
 
                return -1;
82
 
            }
83
 
 
84
 
            for (i = 0; i < rle_code; i++) {
85
 
                if (pixel_ptr >= avctx->width)
86
 
                    break;
87
 
                FETCH_NEXT_STREAM_BYTE();
88
 
                pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
89
 
                pixel_ptr++;
90
 
                if (i + 1 == rle_code && odd_pixel)
91
 
                    break;
92
 
                if (pixel_ptr >= avctx->width)
93
 
                    break;
94
 
                pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
95
 
                pixel_ptr++;
96
 
            }
97
 
 
98
 
            // if the RLE code is odd, skip a byte in the stream
99
 
            if (extra_byte)
100
 
              stream_ptr++;
101
 
            }
102
 
        } else {
103
 
            // decode a run of data
104
 
            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
105
 
                (row_ptr < 0)) {
106
 
                av_log(avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
107
 
                return -1;
108
 
            }
109
 
            FETCH_NEXT_STREAM_BYTE();
110
 
            for (i = 0; i < rle_code; i++) {
111
 
                if (pixel_ptr >= avctx->width)
112
 
                    break;
113
 
                if ((i & 1) == 0)
114
 
                    pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
115
 
                else
116
 
                    pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
117
 
                pixel_ptr++;
118
 
            }
119
 
        }
120
 
    }
121
 
 
122
 
    /* one last sanity check on the way out */
123
 
    if (stream_ptr < data_size) {
124
 
        av_log(avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
125
 
            stream_ptr, data_size);
126
 
        return -1;
127
 
    }
128
 
 
129
 
    return 0;
130
 
}
131
 
 
132
 
 
133
 
static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, int depth,
134
 
                                    const uint8_t *data, int srcsize)
135
 
{
136
 
    uint8_t *output, *output_end;
137
 
    const uint8_t* src = data;
138
 
    int p1, p2, line=avctx->height - 1, pos=0, i;
139
 
    uint16_t av_uninit(pix16);
140
 
    uint32_t av_uninit(pix32);
141
 
 
142
 
    output = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
143
 
    output_end = pic->data[0] + (avctx->height) * pic->linesize[0];
144
 
    while(src < data + srcsize) {
145
 
        p1 = *src++;
146
 
        if(p1 == 0) { //Escape code
147
 
            p2 = *src++;
148
 
            if(p2 == 0) { //End-of-line
149
 
                output = pic->data[0] + (--line) * pic->linesize[0];
150
 
                if (line < 0 && !(src+1 < data + srcsize && AV_RB16(src) == 1)) {
151
 
                    av_log(avctx, AV_LOG_ERROR, "Next line is beyond picture bounds\n");
152
 
                    return -1;
153
 
                }
154
 
                pos = 0;
155
 
                continue;
156
 
            } else if(p2 == 1) { //End-of-picture
157
 
                return 0;
158
 
            } else if(p2 == 2) { //Skip
159
 
                p1 = *src++;
160
 
                p2 = *src++;
161
 
                line -= p2;
162
 
                if (line < 0){
163
 
                    av_log(avctx, AV_LOG_ERROR, "Skip beyond picture bounds\n");
164
 
                    return -1;
165
 
                }
166
 
                pos += p1;
167
 
                output = pic->data[0] + line * pic->linesize[0] + pos * (depth >> 3);
168
 
                continue;
169
 
            }
170
 
            // Copy data
171
 
            if ((pic->linesize[0] > 0 && output + p2 * (depth >> 3) > output_end)
172
 
              ||(pic->linesize[0] < 0 && output + p2 * (depth >> 3) < output_end)) {
173
 
                src += p2 * (depth >> 3);
174
 
                continue;
175
 
            }
176
 
            if ((depth == 8) || (depth == 24)) {
177
 
                for(i = 0; i < p2 * (depth >> 3); i++) {
178
 
                    *output++ = *src++;
179
 
                }
180
 
                // RLE8 copy is actually padded - and runs are not!
181
 
                if(depth == 8 && (p2 & 1)) {
182
 
                    src++;
183
 
                }
184
 
            } else if (depth == 16) {
185
 
                for(i = 0; i < p2; i++) {
186
 
                    pix16 = AV_RL16(src);
187
 
                    src += 2;
188
 
                    *(uint16_t*)output = pix16;
189
 
                    output += 2;
190
 
                }
191
 
            } else if (depth == 32) {
192
 
                for(i = 0; i < p2; i++) {
193
 
                    pix32 = AV_RL32(src);
194
 
                    src += 4;
195
 
                    *(uint32_t*)output = pix32;
196
 
                    output += 4;
197
 
                }
198
 
            }
199
 
            pos += p2;
200
 
        } else { //run of pixels
201
 
            uint8_t pix[3]; //original pixel
202
 
            switch(depth){
203
 
            case  8: pix[0] = *src++;
204
 
                     break;
205
 
            case 16: pix16 = AV_RL16(src);
206
 
                     src += 2;
207
 
                     break;
208
 
            case 24: pix[0] = *src++;
209
 
                     pix[1] = *src++;
210
 
                     pix[2] = *src++;
211
 
                     break;
212
 
            case 32: pix32 = AV_RL32(src);
213
 
                     src += 4;
214
 
                     break;
215
 
            }
216
 
            if ((pic->linesize[0] > 0 && output + p1 * (depth >> 3) > output_end)
217
 
              ||(pic->linesize[0] < 0 && output + p1 * (depth >> 3) < output_end))
218
 
                continue;
219
 
            for(i = 0; i < p1; i++) {
220
 
                switch(depth){
221
 
                case  8: *output++ = pix[0];
222
 
                         break;
223
 
                case 16: *(uint16_t*)output = pix16;
224
 
                         output += 2;
225
 
                         break;
226
 
                case 24: *output++ = pix[0];
227
 
                         *output++ = pix[1];
228
 
                         *output++ = pix[2];
229
 
                         break;
230
 
                case 32: *(uint32_t*)output = pix32;
231
 
                         output += 4;
232
 
                         break;
233
 
                }
234
 
            }
235
 
            pos += p1;
236
 
        }
237
 
    }
238
 
 
239
 
    av_log(avctx, AV_LOG_WARNING, "MS RLE warning: no end-of-picture code\n");
240
 
    return 0;
241
 
}
242
 
 
243
 
 
244
 
int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, int depth,
245
 
                    const uint8_t* data, int data_size)
246
 
{
247
 
    switch(depth){
248
 
    case  4:
249
 
        return msrle_decode_pal4(avctx, pic, data, data_size);
250
 
    case  8:
251
 
    case 16:
252
 
    case 24:
253
 
    case 32:
254
 
        return msrle_decode_8_16_24_32(avctx, pic, depth, data, data_size);
255
 
    default:
256
 
        av_log(avctx, AV_LOG_ERROR, "Unknown depth %d\n", depth);
257
 
        return -1;
258
 
    }
259
 
}
260