~ubuntu-branches/ubuntu/precise/v4l-utils/precise

« back to all changes in this revision

Viewing changes to lib/libv4lconvert/mr97310a.c

  • Committer: Bazaar Package Importer
  • Author(s): Gregor Jasny
  • Date: 2010-02-28 19:44:15 UTC
  • Revision ID: james.westby@ubuntu.com-20100228194415-067hdj8rvawj91zw
Tags: upstream-0.7.90
ImportĀ upstreamĀ versionĀ 0.7.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * MR97310A decoder
 
3
 *
 
4
 * Copyright (C) 2004-2009 Theodore Kilgore <kilgota@auburn.edu>
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Lesser General Public
 
8
 * License as published by the Free Software Foundation; either
 
9
 * version 2 of the License, or (at your option) any later version.
 
10
 *
 
11
 * This library is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * Lesser General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General Public
 
17
 * License along with this library; if not, write to the
 
18
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
19
 * Boston, MA 02111-1307, USA.
 
20
 */
 
21
 
 
22
#include <unistd.h>
 
23
#include "libv4lconvert-priv.h"
 
24
#include "libv4lsyscall-priv.h"
 
25
 
 
26
#define CLIP(x) ((x)<0?0:((x)>0xff)?0xff:(x))
 
27
 
 
28
#define MIN_CLOCKDIV_CID V4L2_CID_PRIVATE_BASE
 
29
 
 
30
/* FIXME not threadsafe */
 
31
static int decoder_initialized = 0;
 
32
 
 
33
static struct {
 
34
        unsigned char is_abs;
 
35
        unsigned char len;
 
36
        signed char val;
 
37
} table[256];
 
38
 
 
39
static void init_mr97310a_decoder(void)
 
40
{
 
41
        int i;
 
42
        int is_abs, val, len;
 
43
 
 
44
        for (i = 0; i < 256; ++i) {
 
45
                is_abs = 0;
 
46
                val = 0;
 
47
                len = 0;
 
48
                if ((i & 0x80) == 0) {
 
49
                        /* code 0 */
 
50
                        val = 0;
 
51
                        len = 1;
 
52
                } else if ((i & 0xe0) == 0xc0) {
 
53
                        /* code 110 */
 
54
                        val = -3;
 
55
                        len = 3;
 
56
                } else if ((i & 0xe0) == 0xa0) {
 
57
                        /* code 101 */
 
58
                        val = +3;
 
59
                        len = 3;
 
60
                } else if ((i & 0xf0) == 0x80) {
 
61
                        /* code 1000 */
 
62
                        val = +8;
 
63
                        len = 4;
 
64
                } else if ((i & 0xf0) == 0x90) {
 
65
                        /* code 1001 */
 
66
                        val = -8;
 
67
                        len = 4;
 
68
                } else if ((i & 0xf0) == 0xf0) {
 
69
                        /* code 1111 */
 
70
                        val = -20;
 
71
                        len = 4;
 
72
                } else if ((i & 0xf8) == 0xe0) {
 
73
                        /* code 11100 */
 
74
                        val = +20;
 
75
                        len = 5;
 
76
                } else if ((i & 0xf8) == 0xe8) {
 
77
                        /* code 11101xxxxx */
 
78
                        is_abs = 1;
 
79
                        val = 0;  /* value is calculated later */
 
80
                        len = 5;
 
81
                }
 
82
                table[i].is_abs = is_abs;
 
83
                table[i].val = val;
 
84
                table[i].len = len;
 
85
        }
 
86
        decoder_initialized = 1;
 
87
}
 
88
 
 
89
static inline unsigned char get_byte(const unsigned char *inp,
 
90
                                     unsigned int bitpos)
 
91
{
 
92
        const unsigned char *addr;
 
93
        addr = inp + (bitpos >> 3);
 
94
        return (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
 
95
}
 
96
 
 
97
int v4lconvert_decode_mr97310a(struct v4lconvert_data *data,
 
98
                               const unsigned char *inp, int src_size,
 
99
                               unsigned char *outp, int width, int height)
 
100
{
 
101
        int row, col;
 
102
        int val;
 
103
        int bitpos;
 
104
        unsigned char code;
 
105
        unsigned char lp, tp, tlp, trp;
 
106
        struct v4l2_control min_clockdiv = { .id = MIN_CLOCKDIV_CID };
 
107
 
 
108
        if (!decoder_initialized)
 
109
                init_mr97310a_decoder();
 
110
 
 
111
        /* remove the header */
 
112
        inp += 12;
 
113
 
 
114
        bitpos = 0;
 
115
 
 
116
        /* main decoding loop */
 
117
        for (row = 0; row < height; ++row) {
 
118
                col = 0;
 
119
 
 
120
                /* first two pixels in first two rows are stored as raw 8-bit */
 
121
                if (row < 2) {
 
122
                        code = get_byte(inp, bitpos);
 
123
                        bitpos += 8;
 
124
                        *outp++ = code;
 
125
 
 
126
                        code = get_byte(inp, bitpos);
 
127
                        bitpos += 8;
 
128
                        *outp++ = code;
 
129
 
 
130
                        col += 2;
 
131
                }
 
132
 
 
133
                while (col < width) {
 
134
                        /* get bitcode */
 
135
                        code = get_byte(inp, bitpos);
 
136
                        /* update bit position */
 
137
                        bitpos += table[code].len;
 
138
 
 
139
                        /* calculate pixel value */
 
140
                        if (table[code].is_abs) {
 
141
                                /* get 5 more bits and use them as absolute value */
 
142
                                code = get_byte(inp, bitpos);
 
143
                                val = (code & 0xf8);
 
144
                                bitpos += 5;
 
145
 
 
146
                        } else {
 
147
                                /* value is relative to top or left pixel */
 
148
                                val = table[code].val;
 
149
                                lp = outp[-2];
 
150
                                if (row > 1) {
 
151
                                        tlp = outp[-2*width-2];
 
152
                                        tp  = outp[-2*width];
 
153
                                        trp = outp[-2*width+2];
 
154
                                }
 
155
                                if (row < 2) {
 
156
                                        /* top row: relative to left pixel */
 
157
                                        val += lp;
 
158
                                } else if (col < 2) {
 
159
                                        /* left column: relative to top pixel */
 
160
                                        /* initial estimate */
 
161
                                        val += (tp + trp)/2;
 
162
                                } else if (col > width - 3) {
 
163
                                        /* left column: relative to top pixel */
 
164
                                        val += (tp + lp + tlp + 1)/3;
 
165
                                /* main area: weighted average of tlp, trp,
 
166
                                 * lp, and tp */
 
167
                                } else {
 
168
                                        tlp>>=1;
 
169
                                        trp>>=1;
 
170
                                        /* initial estimate for predictor */
 
171
                                        val += (lp + tp + tlp + trp + 1)/3;
 
172
                                }
 
173
                        }
 
174
                        /* store pixel */
 
175
                        *outp++ = CLIP(val);
 
176
                        ++col;
 
177
                }
 
178
 
 
179
                /* src_size - 12 because of 12 byte footer */
 
180
                if (((bitpos - 1) / 8) >= (src_size - 12)) {
 
181
                        data->frames_dropped++;
 
182
                        if (data->frames_dropped == 3) {
 
183
                                /* Tell the driver to go slower as
 
184
                                   the compression engine is not able to
 
185
                                   compress the image enough, we may
 
186
                                   fail to do this because older
 
187
                                   drivers don't support this */
 
188
                                SYS_IOCTL(data->fd, VIDIOC_G_CTRL,
 
189
                                          &min_clockdiv);
 
190
                                min_clockdiv.value++;
 
191
                                SYS_IOCTL(data->fd, VIDIOC_S_CTRL,
 
192
                                          &min_clockdiv);
 
193
                                /* We return success here, because if we
 
194
                                   return failure for too many frames in a row
 
195
                                   libv4l2 will return an error to the
 
196
                                   application and some applications abort
 
197
                                   on the first error received. */
 
198
                                data->frames_dropped = 0;
 
199
                                return 0;
 
200
                        }
 
201
                        V4LCONVERT_ERR("incomplete mr97310a frame\n");
 
202
                        return -1;
 
203
                }
 
204
        }
 
205
 
 
206
        data->frames_dropped = 0;
 
207
        return 0;
 
208
}