~ubuntu-branches/debian/sid/v4l-utils/sid

« back to all changes in this revision

Viewing changes to lib/libv4lconvert/libv4lconvert.c

  • Committer: Bazaar Package Importer
  • Author(s): Gregor Jasny
  • Date: 2010-05-07 20:48:34 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100507204834-ga01cxhz3fekk47r
Tags: 0.8.0-1
* New upstream version
* Switch to 3.0 (quilt) source format
* Re-enable pristine-tar
* Split utils package into command line and the Qt based qv4l2
  (Closes: #576422)
* Update upstream URL

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# You should have received a copy of the GNU Lesser General Public License
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
*/
 
17
 */
18
18
 
19
19
#include <errno.h>
20
20
#include <string.h>
26
26
#include "libv4lconvert-priv.h"
27
27
#include "libv4lsyscall-priv.h"
28
28
 
29
 
#define MIN(a,b) (((a)<(b))?(a):(b))
 
29
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
30
30
 
31
31
/* Note for proper functioning of v4lconvert_enum_fmt the first entries in
32
 
  supported_src_pixfmts must match with the entries in supported_dst_pixfmts */
 
32
   supported_src_pixfmts must match with the entries in supported_dst_pixfmts */
33
33
#define SUPPORTED_DST_PIXFMTS \
34
 
  { V4L2_PIX_FMT_RGB24,  0 }, \
35
 
  { V4L2_PIX_FMT_BGR24,  0 }, \
36
 
  { V4L2_PIX_FMT_YUV420, 0 }, \
37
 
  { V4L2_PIX_FMT_YVU420, 0 }
 
34
{ V4L2_PIX_FMT_RGB24,  0 }, \
 
35
{ V4L2_PIX_FMT_BGR24,  0 }, \
 
36
{ V4L2_PIX_FMT_YUV420, 0 }, \
 
37
{ V4L2_PIX_FMT_YVU420, 0 }
38
38
 
39
39
static void v4lconvert_get_framesizes(struct v4lconvert_data *data,
40
 
  unsigned int pixelformat, int index);
 
40
                unsigned int pixelformat, int index);
41
41
 
42
42
/* Note uncompressed formats must go first so that they are prefered by
43
43
   v4lconvert_try_format for low resolutions */
44
44
static const struct v4lconvert_pixfmt supported_src_pixfmts[] = {
45
 
  SUPPORTED_DST_PIXFMTS,
46
 
  { V4L2_PIX_FMT_YUYV,         0 },
47
 
  { V4L2_PIX_FMT_YVYU,         0 },
48
 
  { V4L2_PIX_FMT_UYVY,         0 },
49
 
  { V4L2_PIX_FMT_RGB565,       0 },
50
 
  { V4L2_PIX_FMT_SN9C20X_I420, V4LCONVERT_NEEDS_CONVERSION },
51
 
  { V4L2_PIX_FMT_SBGGR8,       V4LCONVERT_NEEDS_CONVERSION },
52
 
  { V4L2_PIX_FMT_SGBRG8,       V4LCONVERT_NEEDS_CONVERSION },
53
 
  { V4L2_PIX_FMT_SGRBG8,       V4LCONVERT_NEEDS_CONVERSION },
54
 
  { V4L2_PIX_FMT_SRGGB8,       V4LCONVERT_NEEDS_CONVERSION },
55
 
  { V4L2_PIX_FMT_STV0680,      V4LCONVERT_NEEDS_CONVERSION },
56
 
  { V4L2_PIX_FMT_SPCA501,      V4LCONVERT_NEEDS_CONVERSION },
57
 
  { V4L2_PIX_FMT_SPCA505,      V4LCONVERT_NEEDS_CONVERSION },
58
 
  { V4L2_PIX_FMT_SPCA508,      V4LCONVERT_NEEDS_CONVERSION },
59
 
  { V4L2_PIX_FMT_CPIA1,        V4LCONVERT_NEEDS_CONVERSION },
60
 
  { V4L2_PIX_FMT_HM12,         V4LCONVERT_NEEDS_CONVERSION },
61
 
  { V4L2_PIX_FMT_MJPEG,        V4LCONVERT_COMPRESSED },
62
 
  { V4L2_PIX_FMT_JPEG,         V4LCONVERT_COMPRESSED },
63
 
  { V4L2_PIX_FMT_SPCA561,      V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
64
 
  { V4L2_PIX_FMT_SN9C10X,      V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
65
 
  { V4L2_PIX_FMT_SN9C2028,     V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
66
 
  { V4L2_PIX_FMT_PAC207,       V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
67
 
  { V4L2_PIX_FMT_MR97310A,     V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
68
 
  { V4L2_PIX_FMT_SQ905C,       V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
69
 
  { V4L2_PIX_FMT_PJPG,         V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
70
 
  { V4L2_PIX_FMT_OV511,        V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
71
 
  { V4L2_PIX_FMT_OV518,        V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
 
45
        SUPPORTED_DST_PIXFMTS,
 
46
        { V4L2_PIX_FMT_YUYV,         0 },
 
47
        { V4L2_PIX_FMT_YVYU,         0 },
 
48
        { V4L2_PIX_FMT_UYVY,         0 },
 
49
        { V4L2_PIX_FMT_RGB565,       0 },
 
50
        { V4L2_PIX_FMT_SN9C20X_I420, V4LCONVERT_NEEDS_CONVERSION },
 
51
        { V4L2_PIX_FMT_SBGGR8,       V4LCONVERT_NEEDS_CONVERSION },
 
52
        { V4L2_PIX_FMT_SGBRG8,       V4LCONVERT_NEEDS_CONVERSION },
 
53
        { V4L2_PIX_FMT_SGRBG8,       V4LCONVERT_NEEDS_CONVERSION },
 
54
        { V4L2_PIX_FMT_SRGGB8,       V4LCONVERT_NEEDS_CONVERSION },
 
55
        { V4L2_PIX_FMT_STV0680,      V4LCONVERT_NEEDS_CONVERSION },
 
56
        { V4L2_PIX_FMT_SPCA501,      V4LCONVERT_NEEDS_CONVERSION },
 
57
        { V4L2_PIX_FMT_SPCA505,      V4LCONVERT_NEEDS_CONVERSION },
 
58
        { V4L2_PIX_FMT_SPCA508,      V4LCONVERT_NEEDS_CONVERSION },
 
59
        { V4L2_PIX_FMT_CPIA1,        V4LCONVERT_NEEDS_CONVERSION },
 
60
        { V4L2_PIX_FMT_HM12,         V4LCONVERT_NEEDS_CONVERSION },
 
61
        { V4L2_PIX_FMT_MJPEG,        V4LCONVERT_COMPRESSED },
 
62
        { V4L2_PIX_FMT_JPEG,         V4LCONVERT_COMPRESSED },
 
63
        { V4L2_PIX_FMT_SPCA561,      V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
 
64
        { V4L2_PIX_FMT_SN9C10X,      V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
 
65
        { V4L2_PIX_FMT_SN9C2028,     V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
 
66
        { V4L2_PIX_FMT_PAC207,       V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
 
67
        { V4L2_PIX_FMT_MR97310A,     V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
 
68
        { V4L2_PIX_FMT_SQ905C,       V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
 
69
        { V4L2_PIX_FMT_PJPG,         V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
 
70
        { V4L2_PIX_FMT_OV511,        V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
 
71
        { V4L2_PIX_FMT_OV518,        V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION },
72
72
};
73
73
 
74
74
static const struct v4lconvert_pixfmt supported_dst_pixfmts[] = {
75
 
  SUPPORTED_DST_PIXFMTS
 
75
        SUPPORTED_DST_PIXFMTS
76
76
};
77
77
 
78
78
/* List of well known resolutions which we can get by cropping somewhat larger
79
79
   resolutions */
80
80
static const int v4lconvert_crop_res[][2] = {
81
 
  /* low res VGA resolutions, can be made by software cropping SIF resolutions
82
 
     for cam/drivers which do not support this in hardware */
83
 
  { 320, 240 },
84
 
  { 160, 120 },
85
 
  /* Some CIF cams (with vv6410 sensor) have slightly larger then usual CIF
86
 
     resolutions, make regular CIF resolutions available on these by sw crop */
87
 
  { 352, 288 },
88
 
  { 176, 144 },
 
81
        /* low res VGA resolutions, can be made by software cropping SIF resolutions
 
82
           for cam/drivers which do not support this in hardware */
 
83
        { 320, 240 },
 
84
        { 160, 120 },
 
85
        /* Some CIF cams (with vv6410 sensor) have slightly larger then usual CIF
 
86
           resolutions, make regular CIF resolutions available on these by sw crop */
 
87
        { 352, 288 },
 
88
        { 176, 144 },
89
89
};
90
90
 
91
91
struct v4lconvert_data *v4lconvert_create(int fd)
92
92
{
93
 
  int i, j;
94
 
  struct v4lconvert_data *data = calloc(1, sizeof(struct v4lconvert_data));
95
 
  struct v4l2_capability cap;
96
 
  /* This keeps tracks of devices which have only formats for which apps
97
 
     most likely will need conversion and we can thus safely add software
98
 
     processing controls without a performance impact. */
99
 
  int always_needs_conversion = 1;
100
 
 
101
 
  if (!data) {
102
 
    fprintf(stderr, "libv4lconvert: error: out of memory!\n");
103
 
    return NULL;
104
 
  }
105
 
 
106
 
  data->fd = fd;
107
 
  data->decompress_pid = -1;
108
 
 
109
 
  /* Check supported formats */
110
 
  for (i = 0; ; i++) {
111
 
    struct v4l2_fmtdesc fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
112
 
 
113
 
    fmt.index = i;
114
 
 
115
 
    if (SYS_IOCTL(data->fd, VIDIOC_ENUM_FMT, &fmt))
116
 
      break;
117
 
 
118
 
    for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++)
119
 
      if (fmt.pixelformat == supported_src_pixfmts[j].fmt) {
120
 
        data->supported_src_formats |= 1 << j;
121
 
        v4lconvert_get_framesizes(data, fmt.pixelformat, j);
122
 
        if (!(supported_src_pixfmts[j].flags & V4LCONVERT_NEEDS_CONVERSION))
123
 
          always_needs_conversion = 0;
124
 
        break;
125
 
      }
126
 
 
127
 
    if (j == ARRAY_SIZE(supported_src_pixfmts))
128
 
      always_needs_conversion = 0;
129
 
  }
130
 
 
131
 
  data->no_formats = i;
132
 
 
133
 
  /* Check if this cam has any special flags */
134
 
  if (SYS_IOCTL(data->fd, VIDIOC_QUERYCAP, &cap) == 0) {
135
 
    if (!strcmp((char *)cap.driver, "uvcvideo"))
136
 
      data->flags |= V4LCONVERT_IS_UVC;
137
 
    else if (!strcmp((char *)cap.driver, "sn9c20x"))
138
 
      data->flags |= V4LCONVERT_IS_SN9C20X;
139
 
 
140
 
    if ((cap.capabilities & 0xff) & ~V4L2_CAP_VIDEO_CAPTURE)
141
 
      always_needs_conversion = 0;
142
 
  }
143
 
 
144
 
  data->control = v4lcontrol_create(fd, always_needs_conversion);
145
 
  if (!data->control) {
146
 
    free(data);
147
 
    return NULL;
148
 
  }
149
 
  data->control_flags = v4lcontrol_get_flags(data->control);
150
 
 
151
 
  data->processing = v4lprocessing_create(fd, data->control);
152
 
  if (!data->processing) {
153
 
    v4lcontrol_destroy(data->control);
154
 
    free(data);
155
 
    return NULL;
156
 
  }
157
 
 
158
 
  return data;
 
93
        int i, j;
 
94
        struct v4lconvert_data *data = calloc(1, sizeof(struct v4lconvert_data));
 
95
        struct v4l2_capability cap;
 
96
        /* This keeps tracks of devices which have only formats for which apps
 
97
           most likely will need conversion and we can thus safely add software
 
98
           processing controls without a performance impact. */
 
99
        int always_needs_conversion = 1;
 
100
 
 
101
        if (!data) {
 
102
                fprintf(stderr, "libv4lconvert: error: out of memory!\n");
 
103
                return NULL;
 
104
        }
 
105
 
 
106
        data->fd = fd;
 
107
        data->decompress_pid = -1;
 
108
 
 
109
        /* Check supported formats */
 
110
        for (i = 0; ; i++) {
 
111
                struct v4l2_fmtdesc fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
 
112
 
 
113
                fmt.index = i;
 
114
 
 
115
                if (SYS_IOCTL(data->fd, VIDIOC_ENUM_FMT, &fmt))
 
116
                        break;
 
117
 
 
118
                for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++)
 
119
                        if (fmt.pixelformat == supported_src_pixfmts[j].fmt) {
 
120
                                data->supported_src_formats |= 1 << j;
 
121
                                v4lconvert_get_framesizes(data, fmt.pixelformat, j);
 
122
                                if (!(supported_src_pixfmts[j].flags & V4LCONVERT_NEEDS_CONVERSION))
 
123
                                        always_needs_conversion = 0;
 
124
                                break;
 
125
                        }
 
126
 
 
127
                if (j == ARRAY_SIZE(supported_src_pixfmts))
 
128
                        always_needs_conversion = 0;
 
129
        }
 
130
 
 
131
        data->no_formats = i;
 
132
 
 
133
        /* Check if this cam has any special flags */
 
134
        if (SYS_IOCTL(data->fd, VIDIOC_QUERYCAP, &cap) == 0) {
 
135
                if (!strcmp((char *)cap.driver, "uvcvideo"))
 
136
                        data->flags |= V4LCONVERT_IS_UVC;
 
137
                else if (!strcmp((char *)cap.driver, "sn9c20x"))
 
138
                        data->flags |= V4LCONVERT_IS_SN9C20X;
 
139
 
 
140
                if ((cap.capabilities & 0xff) & ~V4L2_CAP_VIDEO_CAPTURE)
 
141
                        always_needs_conversion = 0;
 
142
        }
 
143
 
 
144
        data->control = v4lcontrol_create(fd, always_needs_conversion);
 
145
        if (!data->control) {
 
146
                free(data);
 
147
                return NULL;
 
148
        }
 
149
        data->control_flags = v4lcontrol_get_flags(data->control);
 
150
 
 
151
        data->processing = v4lprocessing_create(fd, data->control);
 
152
        if (!data->processing) {
 
153
                v4lcontrol_destroy(data->control);
 
154
                free(data);
 
155
                return NULL;
 
156
        }
 
157
 
 
158
        return data;
159
159
}
160
160
 
161
161
void v4lconvert_destroy(struct v4lconvert_data *data)
162
162
{
163
 
  v4lprocessing_destroy(data->processing);
164
 
  v4lcontrol_destroy(data->control);
165
 
  if (data->jdec) {
166
 
    unsigned char *comps[3] = { NULL, NULL, NULL };
167
 
    tinyjpeg_set_components(data->jdec, comps, 3);
168
 
    tinyjpeg_free(data->jdec);
169
 
  }
170
 
  v4lconvert_helper_cleanup(data);
171
 
  free(data->convert1_buf);
172
 
  free(data->convert2_buf);
173
 
  free(data->rotate90_buf);
174
 
  free(data->flip_buf);
175
 
  free(data->convert_pixfmt_buf);
176
 
  free(data->previous_frame);
177
 
  free(data);
 
163
        v4lprocessing_destroy(data->processing);
 
164
        v4lcontrol_destroy(data->control);
 
165
        if (data->jdec) {
 
166
                unsigned char *comps[3] = { NULL, NULL, NULL };
 
167
 
 
168
                tinyjpeg_set_components(data->jdec, comps, 3);
 
169
                tinyjpeg_free(data->jdec);
 
170
        }
 
171
        v4lconvert_helper_cleanup(data);
 
172
        free(data->convert1_buf);
 
173
        free(data->convert2_buf);
 
174
        free(data->rotate90_buf);
 
175
        free(data->flip_buf);
 
176
        free(data->convert_pixfmt_buf);
 
177
        free(data->previous_frame);
 
178
        free(data);
178
179
}
179
180
 
180
181
int v4lconvert_supported_dst_format(unsigned int pixelformat)
181
182
{
182
 
  int i;
183
 
 
184
 
  for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
185
 
    if (supported_dst_pixfmts[i].fmt == pixelformat)
186
 
      break;
187
 
 
188
 
  return i != ARRAY_SIZE(supported_dst_pixfmts);
 
183
        int i;
 
184
 
 
185
        for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
 
186
                if (supported_dst_pixfmts[i].fmt == pixelformat)
 
187
                        break;
 
188
 
 
189
        return i != ARRAY_SIZE(supported_dst_pixfmts);
189
190
}
190
191
 
191
192
int v4lconvert_supported_dst_fmt_only(struct v4lconvert_data *data)
192
193
{
193
 
  return v4lcontrol_needs_conversion(data->control) &&
194
 
         data->supported_src_formats;
 
194
        return v4lcontrol_needs_conversion(data->control) &&
 
195
                data->supported_src_formats;
195
196
}
196
197
 
197
198
/* See libv4lconvert.h for description of in / out parameters */
198
199
int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt)
199
200
{
200
 
  int i, no_faked_fmts = 0;
201
 
  unsigned int faked_fmts[ARRAY_SIZE(supported_dst_pixfmts)];
202
 
 
203
 
  if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
204
 
      (!v4lconvert_supported_dst_fmt_only(data) &&
205
 
       fmt->index < data->no_formats))
206
 
    return SYS_IOCTL(data->fd, VIDIOC_ENUM_FMT, fmt);
207
 
 
208
 
  for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
209
 
    if (v4lconvert_supported_dst_fmt_only(data) ||
210
 
        !(data->supported_src_formats & (1 << i))) {
211
 
      faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt;
212
 
      no_faked_fmts++;
213
 
    }
214
 
 
215
 
  if (!v4lconvert_supported_dst_fmt_only(data))
216
 
    i = fmt->index - data->no_formats;
217
 
  else
218
 
    i = fmt->index;
219
 
 
220
 
  if (i >= no_faked_fmts) {
221
 
    errno = EINVAL;
222
 
    return -1;
223
 
  }
224
 
 
225
 
  fmt->flags = V4L2_FMT_FLAG_EMULATED;
226
 
  fmt->pixelformat = faked_fmts[i];
227
 
  fmt->description[0] = faked_fmts[i] & 0xff;
228
 
  fmt->description[1] = (faked_fmts[i] >> 8) & 0xff;
229
 
  fmt->description[2] = (faked_fmts[i] >> 16) & 0xff;
230
 
  fmt->description[3] = faked_fmts[i] >> 24;
231
 
  fmt->description[4] = '\0';
232
 
  memset(fmt->reserved, 0, 4);
233
 
 
234
 
  return 0;
 
201
        int i, no_faked_fmts = 0;
 
202
        unsigned int faked_fmts[ARRAY_SIZE(supported_dst_pixfmts)];
 
203
 
 
204
        if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
 
205
                        (!v4lconvert_supported_dst_fmt_only(data) &&
 
206
                         fmt->index < data->no_formats))
 
207
                return SYS_IOCTL(data->fd, VIDIOC_ENUM_FMT, fmt);
 
208
 
 
209
        for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
 
210
                if (v4lconvert_supported_dst_fmt_only(data) ||
 
211
                                !(data->supported_src_formats & (1 << i))) {
 
212
                        faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt;
 
213
                        no_faked_fmts++;
 
214
                }
 
215
 
 
216
        if (!v4lconvert_supported_dst_fmt_only(data))
 
217
                i = fmt->index - data->no_formats;
 
218
        else
 
219
                i = fmt->index;
 
220
 
 
221
        if (i >= no_faked_fmts) {
 
222
                errno = EINVAL;
 
223
                return -1;
 
224
        }
 
225
 
 
226
        fmt->flags = V4L2_FMT_FLAG_EMULATED;
 
227
        fmt->pixelformat = faked_fmts[i];
 
228
        fmt->description[0] = faked_fmts[i] & 0xff;
 
229
        fmt->description[1] = (faked_fmts[i] >> 8) & 0xff;
 
230
        fmt->description[2] = (faked_fmts[i] >> 16) & 0xff;
 
231
        fmt->description[3] = faked_fmts[i] >> 24;
 
232
        fmt->description[4] = '\0';
 
233
        memset(fmt->reserved, 0, 4);
 
234
 
 
235
        return 0;
235
236
}
236
237
 
237
238
/* Find out what format to use based on the (cached) results of enum
239
240
   currently is intended for use with UVC cams only. This is esp.
240
241
   important for UVC based cams as doing try_fmt there actually causes I/O */
241
242
static int v4lconvert_do_try_format_uvc(struct v4lconvert_data *data,
242
 
  struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt)
 
243
                struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt)
243
244
{
244
 
  int i;
245
 
  unsigned int closest_fmt_size_diff = -1;
246
 
  int best_framesize = 0;/* Just use the first format if no small enough one */
247
 
  int best_format = 0;
248
 
 
249
 
  for (i = 0; i < data->no_framesizes; i++) {
250
 
    if (data->framesizes[i].discrete.width <= dest_fmt->fmt.pix.width &&
251
 
        data->framesizes[i].discrete.height <= dest_fmt->fmt.pix.height) {
252
 
      int size_x_diff = dest_fmt->fmt.pix.width -
253
 
                        data->framesizes[i].discrete.width;
254
 
      int size_y_diff = dest_fmt->fmt.pix.height -
255
 
                        data->framesizes[i].discrete.height;
256
 
      unsigned int size_diff = size_x_diff * size_x_diff +
257
 
                               size_y_diff * size_y_diff;
258
 
 
259
 
      if (size_diff < closest_fmt_size_diff) {
260
 
        closest_fmt_size_diff = size_diff;
261
 
        best_framesize = i;
262
 
      }
263
 
    }
264
 
  }
265
 
 
266
 
  for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) {
267
 
    /* is this format supported? */
268
 
    if (!(data->framesizes[best_framesize].pixel_format & (1 << i)))
269
 
      continue;
270
 
 
271
 
    if (!best_format ||
272
 
        supported_src_pixfmts[i].fmt == dest_fmt->fmt.pix.pixelformat ||
273
 
        ((data->framesizes[best_framesize].discrete.width > 180 ||
274
 
          data->framesizes[best_framesize].discrete.height > 148) &&
275
 
         (supported_src_pixfmts[i].flags & V4LCONVERT_COMPRESSED)))
276
 
      best_format = supported_src_pixfmts[i].fmt;
277
 
  }
278
 
 
279
 
  dest_fmt->fmt.pix.width = data->framesizes[best_framesize].discrete.width;
280
 
  dest_fmt->fmt.pix.height = data->framesizes[best_framesize].discrete.height;
281
 
  dest_fmt->fmt.pix.field = V4L2_FIELD_NONE; /* UVC has no fields */
282
 
  /* Not pretty, the pwc driver doesn't fill these in try_fmt either though,
283
 
     so we should be able to get away with this. */
284
 
  dest_fmt->fmt.pix.bytesperline = 0;
285
 
  dest_fmt->fmt.pix.sizeimage = 0;
286
 
  dest_fmt->fmt.pix.colorspace = 0;
287
 
  dest_fmt->fmt.pix.priv = 0;
288
 
 
289
 
  *src_fmt = *dest_fmt;
290
 
  src_fmt->fmt.pix.pixelformat = best_format;
291
 
 
292
 
  return 0;
 
245
        int i;
 
246
        unsigned int closest_fmt_size_diff = -1;
 
247
        int best_framesize = 0;/* Just use the first format if no small enough one */
 
248
        int best_format = 0;
 
249
 
 
250
        for (i = 0; i < data->no_framesizes; i++) {
 
251
                if (data->framesizes[i].discrete.width <= dest_fmt->fmt.pix.width &&
 
252
                                data->framesizes[i].discrete.height <= dest_fmt->fmt.pix.height) {
 
253
                        int size_x_diff = dest_fmt->fmt.pix.width -
 
254
                                data->framesizes[i].discrete.width;
 
255
                        int size_y_diff = dest_fmt->fmt.pix.height -
 
256
                                data->framesizes[i].discrete.height;
 
257
                        unsigned int size_diff = size_x_diff * size_x_diff +
 
258
                                size_y_diff * size_y_diff;
 
259
 
 
260
                        if (size_diff < closest_fmt_size_diff) {
 
261
                                closest_fmt_size_diff = size_diff;
 
262
                                best_framesize = i;
 
263
                        }
 
264
                }
 
265
        }
 
266
 
 
267
        for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) {
 
268
                /* is this format supported? */
 
269
                if (!(data->framesizes[best_framesize].pixel_format & (1 << i)))
 
270
                        continue;
 
271
 
 
272
                if (!best_format ||
 
273
                                supported_src_pixfmts[i].fmt == dest_fmt->fmt.pix.pixelformat ||
 
274
                                ((data->framesizes[best_framesize].discrete.width > 180 ||
 
275
                                  data->framesizes[best_framesize].discrete.height > 148) &&
 
276
                                 (supported_src_pixfmts[i].flags & V4LCONVERT_COMPRESSED)))
 
277
                        best_format = supported_src_pixfmts[i].fmt;
 
278
        }
 
279
 
 
280
        dest_fmt->fmt.pix.width = data->framesizes[best_framesize].discrete.width;
 
281
        dest_fmt->fmt.pix.height = data->framesizes[best_framesize].discrete.height;
 
282
        dest_fmt->fmt.pix.field = V4L2_FIELD_NONE; /* UVC has no fields */
 
283
        /* Not pretty, the pwc driver doesn't fill these in try_fmt either though,
 
284
           so we should be able to get away with this. */
 
285
        dest_fmt->fmt.pix.bytesperline = 0;
 
286
        dest_fmt->fmt.pix.sizeimage = 0;
 
287
        dest_fmt->fmt.pix.colorspace = 0;
 
288
        dest_fmt->fmt.pix.priv = 0;
 
289
 
 
290
        *src_fmt = *dest_fmt;
 
291
        src_fmt->fmt.pix.pixelformat = best_format;
 
292
 
 
293
        return 0;
293
294
}
294
295
 
295
296
static int v4lconvert_do_try_format(struct v4lconvert_data *data,
296
 
  struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt)
 
297
                struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt)
297
298
{
298
 
  int i;
299
 
  unsigned int closest_fmt_size_diff = -1;
300
 
  unsigned int desired_pixfmt = dest_fmt->fmt.pix.pixelformat;
301
 
  struct v4l2_format try_fmt, closest_fmt = { .type = 0 };
302
 
 
303
 
  if (data->flags & V4LCONVERT_IS_UVC)
304
 
    return v4lconvert_do_try_format_uvc(data, dest_fmt, src_fmt);
305
 
 
306
 
  for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) {
307
 
    /* is this format supported? */
308
 
    if (!(data->supported_src_formats & (1 << i)))
309
 
      continue;
310
 
 
311
 
    try_fmt = *dest_fmt;
312
 
    try_fmt.fmt.pix.pixelformat = supported_src_pixfmts[i].fmt;
313
 
 
314
 
    if (!SYS_IOCTL(data->fd, VIDIOC_TRY_FMT, &try_fmt))
315
 
    {
316
 
      if (try_fmt.fmt.pix.pixelformat == supported_src_pixfmts[i].fmt) {
317
 
        int size_x_diff = abs((int)try_fmt.fmt.pix.width -
318
 
                              (int)dest_fmt->fmt.pix.width);
319
 
        int size_y_diff = abs((int)try_fmt.fmt.pix.height -
320
 
                              (int)dest_fmt->fmt.pix.height);
321
 
        unsigned int size_diff = size_x_diff * size_x_diff +
322
 
                                 size_y_diff * size_y_diff;
323
 
        if (size_diff < closest_fmt_size_diff ||
324
 
            (size_diff == closest_fmt_size_diff &&
325
 
             (supported_src_pixfmts[i].fmt == desired_pixfmt ||
326
 
              ((try_fmt.fmt.pix.width > 180 || try_fmt.fmt.pix.height > 148) &&
327
 
               (supported_src_pixfmts[i].flags & V4LCONVERT_COMPRESSED))))) {
328
 
          closest_fmt_size_diff = size_diff;
329
 
          closest_fmt = try_fmt;
 
299
        int i;
 
300
        unsigned int closest_fmt_size_diff = -1;
 
301
        unsigned int desired_pixfmt = dest_fmt->fmt.pix.pixelformat;
 
302
        struct v4l2_format try_fmt, closest_fmt = { .type = 0 };
 
303
 
 
304
        if (data->flags & V4LCONVERT_IS_UVC)
 
305
                return v4lconvert_do_try_format_uvc(data, dest_fmt, src_fmt);
 
306
 
 
307
        for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) {
 
308
                /* is this format supported? */
 
309
                if (!(data->supported_src_formats & (1 << i)))
 
310
                        continue;
 
311
 
 
312
                try_fmt = *dest_fmt;
 
313
                try_fmt.fmt.pix.pixelformat = supported_src_pixfmts[i].fmt;
 
314
 
 
315
                if (!SYS_IOCTL(data->fd, VIDIOC_TRY_FMT, &try_fmt)) {
 
316
                        if (try_fmt.fmt.pix.pixelformat == supported_src_pixfmts[i].fmt) {
 
317
                                int size_x_diff = abs((int)try_fmt.fmt.pix.width -
 
318
                                                (int)dest_fmt->fmt.pix.width);
 
319
                                int size_y_diff = abs((int)try_fmt.fmt.pix.height -
 
320
                                                (int)dest_fmt->fmt.pix.height);
 
321
                                unsigned int size_diff = size_x_diff * size_x_diff +
 
322
                                        size_y_diff * size_y_diff;
 
323
 
 
324
                                if (size_diff < closest_fmt_size_diff ||
 
325
                                                (size_diff == closest_fmt_size_diff &&
 
326
                                                 (supported_src_pixfmts[i].fmt == desired_pixfmt ||
 
327
                                                  ((try_fmt.fmt.pix.width > 180 || try_fmt.fmt.pix.height > 148) &&
 
328
                                                   (supported_src_pixfmts[i].flags & V4LCONVERT_COMPRESSED))))) {
 
329
                                        closest_fmt_size_diff = size_diff;
 
330
                                        closest_fmt = try_fmt;
 
331
                                }
 
332
                        }
 
333
                }
330
334
        }
331
 
      }
332
 
    }
333
 
  }
334
 
 
335
 
  if (closest_fmt.type == 0)
336
 
    return -1;
337
 
 
338
 
  *dest_fmt = closest_fmt;
339
 
  if (closest_fmt.fmt.pix.pixelformat != desired_pixfmt)
340
 
    dest_fmt->fmt.pix.pixelformat = desired_pixfmt;
341
 
  *src_fmt = closest_fmt;
342
 
 
343
 
  return 0;
 
335
 
 
336
        if (closest_fmt.type == 0)
 
337
                return -1;
 
338
 
 
339
        *dest_fmt = closest_fmt;
 
340
        if (closest_fmt.fmt.pix.pixelformat != desired_pixfmt)
 
341
                dest_fmt->fmt.pix.pixelformat = desired_pixfmt;
 
342
        *src_fmt = closest_fmt;
 
343
 
 
344
        return 0;
344
345
}
345
346
 
346
347
void v4lconvert_fixup_fmt(struct v4l2_format *fmt)
347
348
{
348
 
  switch (fmt->fmt.pix.pixelformat) {
349
 
  case V4L2_PIX_FMT_RGB24:
350
 
  case V4L2_PIX_FMT_BGR24:
351
 
    fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * 3;
352
 
    fmt->fmt.pix.sizeimage = fmt->fmt.pix.width * fmt->fmt.pix.height * 3;
353
 
    break;
354
 
  case V4L2_PIX_FMT_YUV420:
355
 
  case V4L2_PIX_FMT_YVU420:
356
 
    fmt->fmt.pix.bytesperline = fmt->fmt.pix.width;
357
 
    fmt->fmt.pix.sizeimage = fmt->fmt.pix.width * fmt->fmt.pix.height * 3 / 2;
358
 
    break;
359
 
  }
 
349
        switch (fmt->fmt.pix.pixelformat) {
 
350
        case V4L2_PIX_FMT_RGB24:
 
351
        case V4L2_PIX_FMT_BGR24:
 
352
                fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * 3;
 
353
                fmt->fmt.pix.sizeimage = fmt->fmt.pix.width * fmt->fmt.pix.height * 3;
 
354
                break;
 
355
        case V4L2_PIX_FMT_YUV420:
 
356
        case V4L2_PIX_FMT_YVU420:
 
357
                fmt->fmt.pix.bytesperline = fmt->fmt.pix.width;
 
358
                fmt->fmt.pix.sizeimage = fmt->fmt.pix.width * fmt->fmt.pix.height * 3 / 2;
 
359
                break;
 
360
        }
360
361
}
361
362
 
362
363
/* See libv4lconvert.h for description of in / out parameters */
363
364
int v4lconvert_try_format(struct v4lconvert_data *data,
364
 
  struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt)
 
365
                struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt)
365
366
{
366
 
  int i, result;
367
 
  unsigned int desired_width = dest_fmt->fmt.pix.width;
368
 
  unsigned int desired_height = dest_fmt->fmt.pix.height;
369
 
  struct v4l2_format try_src, try_dest, try2_src, try2_dest;
370
 
 
371
 
  if (dest_fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
372
 
      v4lconvert_supported_dst_fmt_only(data) &&
373
 
      !v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat))
374
 
    dest_fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
375
 
 
376
 
  try_dest = *dest_fmt;
377
 
 
378
 
  /* Can we do conversion to the requested format & type? */
379
 
  if (!v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat) ||
380
 
      dest_fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
381
 
      v4lconvert_do_try_format(data, &try_dest, &try_src)) {
382
 
    result = SYS_IOCTL(data->fd, VIDIOC_TRY_FMT, dest_fmt);
383
 
    if (src_fmt)
384
 
      *src_fmt = *dest_fmt;
385
 
    return result;
386
 
  }
387
 
 
388
 
  /* In case of a non exact resolution match, try again with a slightly larger
389
 
     resolution as some weird devices are not able to crop of the number of
390
 
     extra (border) pixels most sensors have compared to standard resolutions,
391
 
     which we will then just crop of in software */
392
 
  if (try_dest.fmt.pix.width != desired_width ||
393
 
      try_dest.fmt.pix.height != desired_height) {
394
 
    try2_dest = *dest_fmt;
395
 
    try2_dest.fmt.pix.width  = desired_width + 7;
396
 
    try2_dest.fmt.pix.height = desired_height + 1;
397
 
    result = v4lconvert_do_try_format(data, &try2_dest, &try2_src);
398
 
    if (result == 0 &&
399
 
        try2_dest.fmt.pix.width >= desired_width &&
400
 
        try2_dest.fmt.pix.width <= desired_width + 7 &&
401
 
        try2_dest.fmt.pix.height >= desired_height &&
402
 
        try2_dest.fmt.pix.height <= desired_height + 1) {
403
 
      /* Success! */
404
 
      try2_dest.fmt.pix.width = desired_width;
405
 
      try2_dest.fmt.pix.height = desired_height;
406
 
      try_dest = try2_dest;
407
 
      try_src = try2_src;
408
 
    }
409
 
  }
410
 
 
411
 
  /* In case of a non exact resolution match, see if this is a well known
412
 
     resolution some apps are hardcoded too and try to give the app what it
413
 
     asked for by cropping a slightly larger resolution or adding a small
414
 
     black border to a slightly smaller resolution */
415
 
  if (try_dest.fmt.pix.width != desired_width ||
416
 
      try_dest.fmt.pix.height != desired_height) {
417
 
    for (i = 0; i < ARRAY_SIZE(v4lconvert_crop_res); i++) {
418
 
      if (v4lconvert_crop_res[i][0] == desired_width &&
419
 
          v4lconvert_crop_res[i][1] == desired_height) {
420
 
        try2_dest = *dest_fmt;
421
 
 
422
 
        /* Note these are chosen so that cropping to vga res just works for
423
 
           vv6410 sensor cams, which have 356x292 and 180x148 */
424
 
        try2_dest.fmt.pix.width = desired_width * 113 / 100;
425
 
        try2_dest.fmt.pix.height = desired_height * 124 / 100;
426
 
        result = v4lconvert_do_try_format(data, &try2_dest, &try2_src);
427
 
        if (result == 0 &&
428
 
            (/* Add a small black border of max 16 pixels */
429
 
             (try2_dest.fmt.pix.width >= desired_width - 16 &&
430
 
              try2_dest.fmt.pix.width <= desired_width &&
431
 
              try2_dest.fmt.pix.height >= desired_height - 16 &&
432
 
              try2_dest.fmt.pix.height <= desired_height) ||
433
 
             /* Standard cropping to max 80% of actual width / height */
434
 
             (try2_dest.fmt.pix.width >= desired_width &&
435
 
              try2_dest.fmt.pix.width <= desired_width * 5 / 4 &&
436
 
              try2_dest.fmt.pix.height >= desired_height &&
437
 
              try2_dest.fmt.pix.height <= desired_height * 5 / 4) ||
438
 
             /* Downscale 2x + cropping to max 80% of actual width / height */
439
 
             (try2_dest.fmt.pix.width >= desired_width * 2 &&
440
 
              try2_dest.fmt.pix.width <= desired_width * 5 / 2 &&
441
 
              try2_dest.fmt.pix.height >= desired_height * 2 &&
442
 
              try2_dest.fmt.pix.height <= desired_height * 5 / 2))) {
443
 
          /* Success! */
444
 
          try2_dest.fmt.pix.width = desired_width;
445
 
          try2_dest.fmt.pix.height = desired_height;
446
 
          try_dest = try2_dest;
447
 
          try_src = try2_src;
448
 
        }
449
 
        break;
450
 
      }
451
 
    }
452
 
  }
453
 
 
454
 
  /* Some applications / libs (*cough* gstreamer *cough*) will not work
455
 
     correctly with planar YUV formats when the width is not a multiple of 8
456
 
     or the height is not a multiple of 2. With RGB formats these apps require
457
 
     the width to be a multiple of 4. We apply the same rounding to all
458
 
     formats to not end up with 2 close but different resolutions. */
459
 
  try_dest.fmt.pix.width &= ~7;
460
 
  try_dest.fmt.pix.height &= ~1;
461
 
 
462
 
  /* Are we converting / cropping ? */
463
 
  if(try_src.fmt.pix.width != try_dest.fmt.pix.width ||
464
 
     try_src.fmt.pix.height != try_dest.fmt.pix.height ||
465
 
     try_src.fmt.pix.pixelformat != try_dest.fmt.pix.pixelformat)
466
 
    v4lconvert_fixup_fmt(&try_dest);
467
 
 
468
 
  *dest_fmt = try_dest;
469
 
  if (src_fmt)
470
 
    *src_fmt = try_src;
471
 
 
472
 
  return 0;
 
367
        int i, result;
 
368
        unsigned int desired_width = dest_fmt->fmt.pix.width;
 
369
        unsigned int desired_height = dest_fmt->fmt.pix.height;
 
370
        struct v4l2_format try_src, try_dest, try2_src, try2_dest;
 
371
 
 
372
        if (dest_fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
 
373
                        v4lconvert_supported_dst_fmt_only(data) &&
 
374
                        !v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat))
 
375
                dest_fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
 
376
 
 
377
        try_dest = *dest_fmt;
 
378
 
 
379
        /* Can we do conversion to the requested format & type? */
 
380
        if (!v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat) ||
 
381
                        dest_fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
 
382
                        v4lconvert_do_try_format(data, &try_dest, &try_src)) {
 
383
                result = SYS_IOCTL(data->fd, VIDIOC_TRY_FMT, dest_fmt);
 
384
                if (src_fmt)
 
385
                        *src_fmt = *dest_fmt;
 
386
                return result;
 
387
        }
 
388
 
 
389
        /* In case of a non exact resolution match, try again with a slightly larger
 
390
           resolution as some weird devices are not able to crop of the number of
 
391
           extra (border) pixels most sensors have compared to standard resolutions,
 
392
           which we will then just crop of in software */
 
393
        if (try_dest.fmt.pix.width != desired_width ||
 
394
                        try_dest.fmt.pix.height != desired_height) {
 
395
                try2_dest = *dest_fmt;
 
396
                try2_dest.fmt.pix.width  = desired_width + 7;
 
397
                try2_dest.fmt.pix.height = desired_height + 1;
 
398
                result = v4lconvert_do_try_format(data, &try2_dest, &try2_src);
 
399
                if (result == 0 &&
 
400
                                try2_dest.fmt.pix.width >= desired_width &&
 
401
                                try2_dest.fmt.pix.width <= desired_width + 7 &&
 
402
                                try2_dest.fmt.pix.height >= desired_height &&
 
403
                                try2_dest.fmt.pix.height <= desired_height + 1) {
 
404
                        /* Success! */
 
405
                        try2_dest.fmt.pix.width = desired_width;
 
406
                        try2_dest.fmt.pix.height = desired_height;
 
407
                        try_dest = try2_dest;
 
408
                        try_src = try2_src;
 
409
                }
 
410
        }
 
411
 
 
412
        /* In case of a non exact resolution match, see if this is a well known
 
413
           resolution some apps are hardcoded too and try to give the app what it
 
414
           asked for by cropping a slightly larger resolution or adding a small
 
415
           black border to a slightly smaller resolution */
 
416
        if (try_dest.fmt.pix.width != desired_width ||
 
417
                        try_dest.fmt.pix.height != desired_height) {
 
418
                for (i = 0; i < ARRAY_SIZE(v4lconvert_crop_res); i++) {
 
419
                        if (v4lconvert_crop_res[i][0] == desired_width &&
 
420
                                        v4lconvert_crop_res[i][1] == desired_height) {
 
421
                                try2_dest = *dest_fmt;
 
422
 
 
423
                                /* Note these are chosen so that cropping to vga res just works for
 
424
                                   vv6410 sensor cams, which have 356x292 and 180x148 */
 
425
                                try2_dest.fmt.pix.width = desired_width * 113 / 100;
 
426
                                try2_dest.fmt.pix.height = desired_height * 124 / 100;
 
427
                                result = v4lconvert_do_try_format(data, &try2_dest, &try2_src);
 
428
                                if (result == 0 &&
 
429
                                                (/* Add a small black border of max 16 pixels */
 
430
                                                 (try2_dest.fmt.pix.width >= desired_width - 16 &&
 
431
                                                  try2_dest.fmt.pix.width <= desired_width &&
 
432
                                                  try2_dest.fmt.pix.height >= desired_height - 16 &&
 
433
                                                  try2_dest.fmt.pix.height <= desired_height) ||
 
434
                                                 /* Standard cropping to max 80% of actual width / height */
 
435
                                                 (try2_dest.fmt.pix.width >= desired_width &&
 
436
                                                  try2_dest.fmt.pix.width <= desired_width * 5 / 4 &&
 
437
                                                  try2_dest.fmt.pix.height >= desired_height &&
 
438
                                                  try2_dest.fmt.pix.height <= desired_height * 5 / 4) ||
 
439
                                                 /* Downscale 2x + cropping to max 80% of actual width / height */
 
440
                                                 (try2_dest.fmt.pix.width >= desired_width * 2 &&
 
441
                                                  try2_dest.fmt.pix.width <= desired_width * 5 / 2 &&
 
442
                                                  try2_dest.fmt.pix.height >= desired_height * 2 &&
 
443
                                                  try2_dest.fmt.pix.height <= desired_height * 5 / 2))) {
 
444
                                        /* Success! */
 
445
                                        try2_dest.fmt.pix.width = desired_width;
 
446
                                        try2_dest.fmt.pix.height = desired_height;
 
447
                                        try_dest = try2_dest;
 
448
                                        try_src = try2_src;
 
449
                                }
 
450
                                break;
 
451
                        }
 
452
                }
 
453
        }
 
454
 
 
455
        /* Some applications / libs (*cough* gstreamer *cough*) will not work
 
456
           correctly with planar YUV formats when the width is not a multiple of 8
 
457
           or the height is not a multiple of 2. With RGB formats these apps require
 
458
           the width to be a multiple of 4. We apply the same rounding to all
 
459
           formats to not end up with 2 close but different resolutions. */
 
460
        try_dest.fmt.pix.width &= ~7;
 
461
        try_dest.fmt.pix.height &= ~1;
 
462
 
 
463
        /* Are we converting / cropping ? */
 
464
        if (try_src.fmt.pix.width != try_dest.fmt.pix.width ||
 
465
                        try_src.fmt.pix.height != try_dest.fmt.pix.height ||
 
466
                        try_src.fmt.pix.pixelformat != try_dest.fmt.pix.pixelformat)
 
467
                v4lconvert_fixup_fmt(&try_dest);
 
468
 
 
469
        *dest_fmt = try_dest;
 
470
        if (src_fmt)
 
471
                *src_fmt = try_src;
 
472
 
 
473
        return 0;
473
474
}
474
475
 
475
476
/* Is conversion necessary ? */
476
477
int v4lconvert_needs_conversion(struct v4lconvert_data *data,
477
 
  const struct v4l2_format *src_fmt,  /* in */
478
 
  const struct v4l2_format *dest_fmt) /* in */
 
478
                const struct v4l2_format *src_fmt,  /* in */
 
479
                const struct v4l2_format *dest_fmt) /* in */
479
480
{
480
 
  if (src_fmt->fmt.pix.width != dest_fmt->fmt.pix.width ||
481
 
      src_fmt->fmt.pix.height != dest_fmt->fmt.pix.height ||
482
 
      src_fmt->fmt.pix.pixelformat != dest_fmt->fmt.pix.pixelformat ||
483
 
      (v4lcontrol_needs_conversion(data->control) &&
484
 
       v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)))
485
 
    return 1;
 
481
        if (src_fmt->fmt.pix.width != dest_fmt->fmt.pix.width ||
 
482
                        src_fmt->fmt.pix.height != dest_fmt->fmt.pix.height ||
 
483
                        src_fmt->fmt.pix.pixelformat != dest_fmt->fmt.pix.pixelformat ||
 
484
                        (v4lcontrol_needs_conversion(data->control) &&
 
485
                         v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)))
 
486
                return 1;
486
487
 
487
 
  return 0;
 
488
        return 0;
488
489
}
489
490
 
490
491
static int v4lconvert_processing_needs_double_conversion(
491
 
  unsigned int src_pix_fmt, unsigned int dest_pix_fmt)
 
492
                unsigned int src_pix_fmt, unsigned int dest_pix_fmt)
492
493
{
493
 
  switch (src_pix_fmt) {
494
 
    case V4L2_PIX_FMT_RGB24:
495
 
    case V4L2_PIX_FMT_BGR24:
496
 
    case V4L2_PIX_FMT_SPCA561:
497
 
    case V4L2_PIX_FMT_SN9C10X:
498
 
    case V4L2_PIX_FMT_PAC207:
499
 
    case V4L2_PIX_FMT_MR97310A:
500
 
    case V4L2_PIX_FMT_SN9C2028:
501
 
    case V4L2_PIX_FMT_SQ905C:
502
 
    case V4L2_PIX_FMT_SBGGR8:
503
 
    case V4L2_PIX_FMT_SGBRG8:
504
 
    case V4L2_PIX_FMT_SGRBG8:
505
 
    case V4L2_PIX_FMT_SRGGB8:
506
 
    case V4L2_PIX_FMT_STV0680:
507
 
      return 0;
508
 
  }
509
 
  switch (dest_pix_fmt) {
510
 
    case V4L2_PIX_FMT_RGB24:
511
 
    case V4L2_PIX_FMT_BGR24:
512
 
      return 0;
513
 
  }
 
494
        switch (src_pix_fmt) {
 
495
        case V4L2_PIX_FMT_RGB24:
 
496
        case V4L2_PIX_FMT_BGR24:
 
497
        case V4L2_PIX_FMT_SPCA561:
 
498
        case V4L2_PIX_FMT_SN9C10X:
 
499
        case V4L2_PIX_FMT_PAC207:
 
500
        case V4L2_PIX_FMT_MR97310A:
 
501
        case V4L2_PIX_FMT_SN9C2028:
 
502
        case V4L2_PIX_FMT_SQ905C:
 
503
        case V4L2_PIX_FMT_SBGGR8:
 
504
        case V4L2_PIX_FMT_SGBRG8:
 
505
        case V4L2_PIX_FMT_SGRBG8:
 
506
        case V4L2_PIX_FMT_SRGGB8:
 
507
        case V4L2_PIX_FMT_STV0680:
 
508
                return 0;
 
509
        }
 
510
        switch (dest_pix_fmt) {
 
511
        case V4L2_PIX_FMT_RGB24:
 
512
        case V4L2_PIX_FMT_BGR24:
 
513
                return 0;
 
514
        }
514
515
 
515
 
  return 1;
 
516
        return 1;
516
517
}
517
518
 
518
519
unsigned char *v4lconvert_alloc_buffer(int needed,
519
 
                                       unsigned char **buf, int *buf_size)
 
520
                unsigned char **buf, int *buf_size)
520
521
{
521
 
  if (*buf_size < needed) {
522
 
    free(*buf);
523
 
    *buf = malloc(needed);
524
 
    if (*buf == NULL) {
525
 
      *buf_size = 0;
526
 
      return NULL;
527
 
    }
528
 
    *buf_size = needed;
529
 
  }
530
 
  return *buf;
 
522
        if (*buf_size < needed) {
 
523
                free(*buf);
 
524
                *buf = malloc(needed);
 
525
                if (*buf == NULL) {
 
526
                        *buf_size = 0;
 
527
                        return NULL;
 
528
                }
 
529
                *buf_size = needed;
 
530
        }
 
531
        return *buf;
531
532
}
532
533
 
533
534
static int v4lconvert_oom_error(struct v4lconvert_data *data)
534
535
{
535
 
  V4LCONVERT_ERR("could not allocate memory\n");
536
 
  errno = ENOMEM;
537
 
  return -1;
 
536
        V4LCONVERT_ERR("could not allocate memory\n");
 
537
        errno = ENOMEM;
 
538
        return -1;
538
539
}
539
540
 
540
541
static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
541
 
  unsigned char *src, int src_size, unsigned char *dest, int dest_size,
542
 
  struct v4l2_format *fmt, unsigned int dest_pix_fmt)
 
542
                unsigned char *src, int src_size, unsigned char *dest, int dest_size,
 
543
                struct v4l2_format *fmt, unsigned int dest_pix_fmt)
543
544
{
544
 
  unsigned int header_width, header_height;
545
 
  int result = 0, jpeg_flags = TINYJPEG_FLAGS_MJPEG_TABLE;
546
 
  unsigned char *components[3];
547
 
  unsigned int src_pix_fmt = fmt->fmt.pix.pixelformat;
548
 
  unsigned int width  = fmt->fmt.pix.width;
549
 
  unsigned int height = fmt->fmt.pix.height;
550
 
 
551
 
  switch (src_pix_fmt) {
552
 
    case V4L2_PIX_FMT_PJPG:
553
 
      jpeg_flags |= TINYJPEG_FLAGS_PIXART_JPEG;
554
 
      /* Fall through */
555
 
    case V4L2_PIX_FMT_MJPEG:
556
 
    case V4L2_PIX_FMT_JPEG:
557
 
      if (!data->jdec) {
558
 
        data->jdec = tinyjpeg_init();
559
 
        if (!data->jdec)
560
 
          return v4lconvert_oom_error(data);
561
 
      }
562
 
      tinyjpeg_set_flags(data->jdec, jpeg_flags);
563
 
      if (tinyjpeg_parse_header(data->jdec, src, src_size)) {
564
 
        V4LCONVERT_ERR("parsing JPEG header: %s",
565
 
          tinyjpeg_get_errorstring(data->jdec));
566
 
        errno = EIO;
567
 
        return -1;
568
 
      }
569
 
      tinyjpeg_get_size(data->jdec, &header_width, &header_height);
570
 
 
571
 
      if (header_width != width || header_height != height) {
572
 
        /* Check for (pixart) rotated JPEG */
573
 
        if (header_width == height && header_height == width) {
574
 
          if (!(data->control_flags & V4LCONTROL_ROTATED_90_JPEG)) {
575
 
            V4LCONVERT_ERR("JPEG needs 90° rotation, please report "
576
 
                           "this to <hdegoede@redhat.com>\n");
577
 
            errno = EIO;
578
 
            return -1;
579
 
          }
580
 
          fmt->fmt.pix.width = header_width;
581
 
          fmt->fmt.pix.height = header_height;
582
 
        } else {
583
 
          V4LCONVERT_ERR("unexpected width / height in JPEG header"
584
 
                         "expected: %ux%u, header: %ux%u\n", width, height,
585
 
                         header_width, header_height);
586
 
          errno = EIO;
587
 
          return -1;
588
 
        }
589
 
      } else if ((data->control_flags & V4LCONTROL_ROTATED_90_JPEG)) {
590
 
        fprintf(stderr, "libv4lconvert: expected 90° rotated JPEG, but got "
591
 
                "normal JPEG, please report this to <hdegoede@redhat.com>\n");
592
 
        V4LCONVERT_ERR("expected 90° rotated JPEG, but got normal JPEG\n");
593
 
        errno = EAGAIN;
594
 
        data->control_flags &= ~V4LCONTROL_ROTATED_90_JPEG;
595
 
        return -1;
596
 
      }
597
 
 
598
 
      components[0] = dest;
599
 
 
600
 
      switch (dest_pix_fmt) {
601
 
      case V4L2_PIX_FMT_RGB24:
602
 
        tinyjpeg_set_components(data->jdec, components, 1);
603
 
        result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_RGB24);
604
 
        break;
605
 
      case V4L2_PIX_FMT_BGR24:
606
 
        tinyjpeg_set_components(data->jdec, components, 1);
607
 
        result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_BGR24);
608
 
        break;
609
 
      case V4L2_PIX_FMT_YUV420:
610
 
        components[1] = components[0] + width * height;
611
 
        components[2] = components[1] + width * height / 4;
612
 
        tinyjpeg_set_components(data->jdec, components, 3);
613
 
        result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_YUV420P);
614
 
        break;
615
 
      case V4L2_PIX_FMT_YVU420:
616
 
        components[2] = components[0] + width * height;
617
 
        components[1] = components[2] + width * height / 4;
618
 
        tinyjpeg_set_components(data->jdec, components, 3);
619
 
        result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_YUV420P);
620
 
        break;
621
 
      }
622
 
 
623
 
      if (result) {
624
 
        /* Pixart webcam's seem to regulary generate corrupt frames, which
625
 
           are best thrown away to avoid flashes in the video stream. Tell
626
 
           the upper layer this is an intermediate fault and it should try
627
 
           again with a new buffer by setting errno to EAGAIN */
628
 
        if (src_pix_fmt == V4L2_PIX_FMT_PJPG ||
629
 
            data->flags & V4LCONVERT_IS_SN9C20X) {
630
 
          V4LCONVERT_ERR("decompressing JPEG: %s",
631
 
            tinyjpeg_get_errorstring(data->jdec));
632
 
          errno = EAGAIN;
633
 
          return -1;
634
 
        } else {
635
 
        /* If the JPEG header checked out ok and we get an error during actual
636
 
           decompression, log the error, but don't return an errorcode to the
637
 
           application, so that the user gets what we managed to decompress */
638
 
          fprintf(stderr, "libv4lconvert: Error decompressing JPEG: %s",
639
 
            tinyjpeg_get_errorstring(data->jdec));
640
 
        }
641
 
      }
642
 
      break;
643
 
 
644
 
    /* Custom cam specific YUV formats */
645
 
    case V4L2_PIX_FMT_SPCA501:
646
 
    case V4L2_PIX_FMT_SPCA505:
647
 
    case V4L2_PIX_FMT_SPCA508:
648
 
    case V4L2_PIX_FMT_SN9C20X_I420:
649
 
    case V4L2_PIX_FMT_CPIA1:
650
 
    case V4L2_PIX_FMT_OV511:
651
 
    case V4L2_PIX_FMT_OV518:
652
 
    {
653
 
      unsigned char *d;
654
 
      int d_size;
655
 
      int yvu = 0;
656
 
 
657
 
      if (dest_pix_fmt != V4L2_PIX_FMT_YUV420 &&
658
 
          dest_pix_fmt != V4L2_PIX_FMT_YVU420) {
659
 
        d = v4lconvert_alloc_buffer(width * height * 3 / 2,
660
 
              &data->convert_pixfmt_buf, &data->convert_pixfmt_buf_size);
661
 
        if (!d)
662
 
          return v4lconvert_oom_error(data);
663
 
        d_size = width * height * 3 / 2;
664
 
      } else {
665
 
        d = dest;
666
 
        d_size = dest_size;
667
 
      }
668
 
 
669
 
      if (dest_pix_fmt == V4L2_PIX_FMT_YVU420)
670
 
        yvu = 1;
671
 
 
672
 
      switch (src_pix_fmt) {
 
545
        unsigned int header_width, header_height;
 
546
        int result = 0, jpeg_flags = TINYJPEG_FLAGS_MJPEG_TABLE;
 
547
        unsigned char *components[3];
 
548
        unsigned int src_pix_fmt = fmt->fmt.pix.pixelformat;
 
549
        unsigned int width  = fmt->fmt.pix.width;
 
550
        unsigned int height = fmt->fmt.pix.height;
 
551
 
 
552
        switch (src_pix_fmt) {
 
553
        case V4L2_PIX_FMT_PJPG:
 
554
                jpeg_flags |= TINYJPEG_FLAGS_PIXART_JPEG;
 
555
                /* Fall through */
 
556
        case V4L2_PIX_FMT_MJPEG:
 
557
        case V4L2_PIX_FMT_JPEG:
 
558
                if (!data->jdec) {
 
559
                        data->jdec = tinyjpeg_init();
 
560
                        if (!data->jdec)
 
561
                                return v4lconvert_oom_error(data);
 
562
                }
 
563
                tinyjpeg_set_flags(data->jdec, jpeg_flags);
 
564
                if (tinyjpeg_parse_header(data->jdec, src, src_size)) {
 
565
                        V4LCONVERT_ERR("parsing JPEG header: %s",
 
566
                                        tinyjpeg_get_errorstring(data->jdec));
 
567
                        errno = EIO;
 
568
                        return -1;
 
569
                }
 
570
                tinyjpeg_get_size(data->jdec, &header_width, &header_height);
 
571
 
 
572
                if (header_width != width || header_height != height) {
 
573
                        /* Check for (pixart) rotated JPEG */
 
574
                        if (header_width == height && header_height == width) {
 
575
                                if (!(data->control_flags & V4LCONTROL_ROTATED_90_JPEG)) {
 
576
                                        V4LCONVERT_ERR("JPEG needs 90° rotation, please report "
 
577
                                                        "this to <hdegoede@redhat.com>\n");
 
578
                                        errno = EIO;
 
579
                                        return -1;
 
580
                                }
 
581
                                fmt->fmt.pix.width = header_width;
 
582
                                fmt->fmt.pix.height = header_height;
 
583
                        } else {
 
584
                                V4LCONVERT_ERR("unexpected width / height in JPEG header"
 
585
                                                "expected: %ux%u, header: %ux%u\n", width, height,
 
586
                                                header_width, header_height);
 
587
                                errno = EIO;
 
588
                                return -1;
 
589
                        }
 
590
                } else if ((data->control_flags & V4LCONTROL_ROTATED_90_JPEG)) {
 
591
                        fprintf(stderr, "libv4lconvert: expected 90° rotated JPEG, but got "
 
592
                                        "normal JPEG, please report this to <hdegoede@redhat.com>\n");
 
593
                        V4LCONVERT_ERR("expected 90° rotated JPEG, but got normal JPEG\n");
 
594
                        errno = EAGAIN;
 
595
                        data->control_flags &= ~V4LCONTROL_ROTATED_90_JPEG;
 
596
                        return -1;
 
597
                }
 
598
 
 
599
                components[0] = dest;
 
600
 
 
601
                switch (dest_pix_fmt) {
 
602
                case V4L2_PIX_FMT_RGB24:
 
603
                        tinyjpeg_set_components(data->jdec, components, 1);
 
604
                        result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_RGB24);
 
605
                        break;
 
606
                case V4L2_PIX_FMT_BGR24:
 
607
                        tinyjpeg_set_components(data->jdec, components, 1);
 
608
                        result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_BGR24);
 
609
                        break;
 
610
                case V4L2_PIX_FMT_YUV420:
 
611
                        components[1] = components[0] + width * height;
 
612
                        components[2] = components[1] + width * height / 4;
 
613
                        tinyjpeg_set_components(data->jdec, components, 3);
 
614
                        result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_YUV420P);
 
615
                        break;
 
616
                case V4L2_PIX_FMT_YVU420:
 
617
                        components[2] = components[0] + width * height;
 
618
                        components[1] = components[2] + width * height / 4;
 
619
                        tinyjpeg_set_components(data->jdec, components, 3);
 
620
                        result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_YUV420P);
 
621
                        break;
 
622
                }
 
623
 
 
624
                if (result) {
 
625
                        /* Pixart webcam's seem to regulary generate corrupt frames, which
 
626
                           are best thrown away to avoid flashes in the video stream. Tell
 
627
                           the upper layer this is an intermediate fault and it should try
 
628
                           again with a new buffer by setting errno to EAGAIN */
 
629
                        if (src_pix_fmt == V4L2_PIX_FMT_PJPG ||
 
630
                                        data->flags & V4LCONVERT_IS_SN9C20X) {
 
631
                                V4LCONVERT_ERR("decompressing JPEG: %s",
 
632
                                                tinyjpeg_get_errorstring(data->jdec));
 
633
                                errno = EAGAIN;
 
634
                                return -1;
 
635
                        } else {
 
636
                                /* If the JPEG header checked out ok and we get an error during actual
 
637
                                   decompression, log the error, but don't return an errorcode to the
 
638
                                   application, so that the user gets what we managed to decompress */
 
639
                                fprintf(stderr, "libv4lconvert: Error decompressing JPEG: %s",
 
640
                                                tinyjpeg_get_errorstring(data->jdec));
 
641
                        }
 
642
                }
 
643
                break;
 
644
 
 
645
                /* Custom cam specific YUV formats */
673
646
        case V4L2_PIX_FMT_SPCA501:
674
 
          v4lconvert_spca501_to_yuv420(src, d, width, height, yvu);
675
 
          break;
676
647
        case V4L2_PIX_FMT_SPCA505:
677
 
          v4lconvert_spca505_to_yuv420(src, d, width, height, yvu);
678
 
          break;
679
648
        case V4L2_PIX_FMT_SPCA508:
680
 
          v4lconvert_spca508_to_yuv420(src, d, width, height, yvu);
681
 
          break;
682
649
        case V4L2_PIX_FMT_SN9C20X_I420:
683
 
          v4lconvert_sn9c20x_to_yuv420(src, d, width, height, yvu);
684
 
          break;
685
650
        case V4L2_PIX_FMT_CPIA1:
686
 
          if (v4lconvert_cpia1_to_yuv420(data, src, src_size, d,
687
 
                                         width, height, yvu)) {
688
 
            /* Corrupt frame, better get another one */
689
 
            errno = EAGAIN;
690
 
            return -1;
691
 
          }
692
 
          break;
693
651
        case V4L2_PIX_FMT_OV511:
694
 
          if (v4lconvert_helper_decompress(data, LIBDIR "/" LIBSUBDIR "/ov511-decomp",
695
 
                     src, src_size, d, d_size, width, height, yvu)) {
696
 
            /* Corrupt frame, better get another one */
697
 
            errno = EAGAIN;
698
 
            return -1;
699
 
          }
700
 
          break;
701
 
        case V4L2_PIX_FMT_OV518:
702
 
          if (v4lconvert_helper_decompress(data, LIBDIR "/" LIBSUBDIR "/ov518-decomp",
703
 
                     src, src_size, d, d_size, width, height, yvu)) {
704
 
            /* Corrupt frame, better get another one */
705
 
            errno = EAGAIN;
706
 
            return -1;
707
 
          }
708
 
          break;
709
 
      }
710
 
 
711
 
      switch (dest_pix_fmt) {
712
 
      case V4L2_PIX_FMT_RGB24:
713
 
        v4lconvert_yuv420_to_rgb24(data->convert_pixfmt_buf, dest, width,
714
 
                                   height, yvu);
715
 
        break;
716
 
      case V4L2_PIX_FMT_BGR24:
717
 
        v4lconvert_yuv420_to_bgr24(data->convert_pixfmt_buf, dest, width,
718
 
                                   height, yvu);
719
 
        break;
720
 
      }
721
 
      break;
722
 
    }
723
 
 
724
 
    /* Conexant cx2341x raw video macroblock format */
725
 
    case V4L2_PIX_FMT_HM12:
726
 
      switch (dest_pix_fmt) {
727
 
      case V4L2_PIX_FMT_RGB24:
728
 
        v4lconvert_hm12_to_rgb24(src, dest, width, height);
729
 
        break;
730
 
      case V4L2_PIX_FMT_BGR24:
731
 
        v4lconvert_hm12_to_bgr24(src, dest, width, height);
732
 
        break;
733
 
      case V4L2_PIX_FMT_YUV420:
734
 
        v4lconvert_hm12_to_yuv420(src, dest, width, height, 0);
735
 
        break;
736
 
      case V4L2_PIX_FMT_YVU420:
737
 
        v4lconvert_hm12_to_yuv420(src, dest, width, height, 1);
738
 
        break;
739
 
      }
740
 
      break;
741
 
 
742
 
    /* compressed bayer formats */
743
 
    case V4L2_PIX_FMT_SPCA561:
744
 
    case V4L2_PIX_FMT_SN9C10X:
745
 
    case V4L2_PIX_FMT_PAC207:
746
 
    case V4L2_PIX_FMT_MR97310A:
747
 
    case V4L2_PIX_FMT_SN9C2028:
748
 
    case V4L2_PIX_FMT_SQ905C:
749
 
    case V4L2_PIX_FMT_STV0680: /* Not compressed but needs some shuffling */
750
 
    {
751
 
      unsigned char *tmpbuf;
752
 
      struct v4l2_format tmpfmt = *fmt;
753
 
 
754
 
      tmpbuf = v4lconvert_alloc_buffer(width * height,
755
 
            &data->convert_pixfmt_buf, &data->convert_pixfmt_buf_size);
756
 
      if (!tmpbuf)
757
 
        return v4lconvert_oom_error(data);
758
 
 
759
 
      switch (src_pix_fmt) {
 
652
        case V4L2_PIX_FMT_OV518: {
 
653
                unsigned char *d;
 
654
                int d_size;
 
655
                int yvu = 0;
 
656
 
 
657
                if (dest_pix_fmt != V4L2_PIX_FMT_YUV420 &&
 
658
                                dest_pix_fmt != V4L2_PIX_FMT_YVU420) {
 
659
                        d = v4lconvert_alloc_buffer(width * height * 3 / 2,
 
660
                                        &data->convert_pixfmt_buf, &data->convert_pixfmt_buf_size);
 
661
                        if (!d)
 
662
                                return v4lconvert_oom_error(data);
 
663
                        d_size = width * height * 3 / 2;
 
664
                } else {
 
665
                        d = dest;
 
666
                        d_size = dest_size;
 
667
                }
 
668
 
 
669
                if (dest_pix_fmt == V4L2_PIX_FMT_YVU420)
 
670
                        yvu = 1;
 
671
 
 
672
                switch (src_pix_fmt) {
 
673
                case V4L2_PIX_FMT_SPCA501:
 
674
                        v4lconvert_spca501_to_yuv420(src, d, width, height, yvu);
 
675
                        break;
 
676
                case V4L2_PIX_FMT_SPCA505:
 
677
                        v4lconvert_spca505_to_yuv420(src, d, width, height, yvu);
 
678
                        break;
 
679
                case V4L2_PIX_FMT_SPCA508:
 
680
                        v4lconvert_spca508_to_yuv420(src, d, width, height, yvu);
 
681
                        break;
 
682
                case V4L2_PIX_FMT_SN9C20X_I420:
 
683
                        v4lconvert_sn9c20x_to_yuv420(src, d, width, height, yvu);
 
684
                        break;
 
685
                case V4L2_PIX_FMT_CPIA1:
 
686
                        if (v4lconvert_cpia1_to_yuv420(data, src, src_size, d,
 
687
                                                width, height, yvu)) {
 
688
                                /* Corrupt frame, better get another one */
 
689
                                errno = EAGAIN;
 
690
                                return -1;
 
691
                        }
 
692
                        break;
 
693
                case V4L2_PIX_FMT_OV511:
 
694
                        if (v4lconvert_helper_decompress(data, LIBDIR "/" LIBSUBDIR "/ov511-decomp",
 
695
                                                src, src_size, d, d_size, width, height, yvu)) {
 
696
                                /* Corrupt frame, better get another one */
 
697
                                errno = EAGAIN;
 
698
                                return -1;
 
699
                        }
 
700
                        break;
 
701
                case V4L2_PIX_FMT_OV518:
 
702
                        if (v4lconvert_helper_decompress(data, LIBDIR "/" LIBSUBDIR "/ov518-decomp",
 
703
                                                src, src_size, d, d_size, width, height, yvu)) {
 
704
                                /* Corrupt frame, better get another one */
 
705
                                errno = EAGAIN;
 
706
                                return -1;
 
707
                        }
 
708
                        break;
 
709
                }
 
710
 
 
711
                switch (dest_pix_fmt) {
 
712
                case V4L2_PIX_FMT_RGB24:
 
713
                        v4lconvert_yuv420_to_rgb24(data->convert_pixfmt_buf, dest, width,
 
714
                                        height, yvu);
 
715
                        break;
 
716
                case V4L2_PIX_FMT_BGR24:
 
717
                        v4lconvert_yuv420_to_bgr24(data->convert_pixfmt_buf, dest, width,
 
718
                                        height, yvu);
 
719
                        break;
 
720
                }
 
721
                break;
 
722
        }
 
723
 
 
724
                /* Conexant cx2341x raw video macroblock format */
 
725
        case V4L2_PIX_FMT_HM12:
 
726
                switch (dest_pix_fmt) {
 
727
                case V4L2_PIX_FMT_RGB24:
 
728
                        v4lconvert_hm12_to_rgb24(src, dest, width, height);
 
729
                        break;
 
730
                case V4L2_PIX_FMT_BGR24:
 
731
                        v4lconvert_hm12_to_bgr24(src, dest, width, height);
 
732
                        break;
 
733
                case V4L2_PIX_FMT_YUV420:
 
734
                        v4lconvert_hm12_to_yuv420(src, dest, width, height, 0);
 
735
                        break;
 
736
                case V4L2_PIX_FMT_YVU420:
 
737
                        v4lconvert_hm12_to_yuv420(src, dest, width, height, 1);
 
738
                        break;
 
739
                }
 
740
                break;
 
741
 
 
742
                /* compressed bayer formats */
760
743
        case V4L2_PIX_FMT_SPCA561:
761
 
          v4lconvert_decode_spca561(src, tmpbuf, width, height);
762
 
          tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SGBRG8;
763
 
          break;
764
744
        case V4L2_PIX_FMT_SN9C10X:
765
 
          v4lconvert_decode_sn9c10x(src, tmpbuf, width, height);
766
 
          tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
767
 
          break;
768
745
        case V4L2_PIX_FMT_PAC207:
769
 
          if (v4lconvert_decode_pac207(data, src, src_size, tmpbuf,
770
 
                                       width, height)) {
771
 
            /* Corrupt frame, better get another one */
772
 
            errno = EAGAIN;
773
 
            return -1;
774
 
          }
775
 
          tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
776
 
          break;
777
746
        case V4L2_PIX_FMT_MR97310A:
778
 
          if (v4lconvert_decode_mr97310a(data, src, src_size, tmpbuf,
779
 
                                         width, height)) {
780
 
            /* Corrupt frame, better get another one */
781
 
            errno = EAGAIN;
782
 
            return -1;
783
 
          }
784
 
          tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
785
 
          break;
786
747
        case V4L2_PIX_FMT_SN9C2028:
787
 
          v4lconvert_decode_sn9c2028(src, tmpbuf, width, height);
788
 
          tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
789
 
          break;
790
748
        case V4L2_PIX_FMT_SQ905C:
791
 
          v4lconvert_decode_sq905c(src, tmpbuf, width, height);
792
 
          tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8;
793
 
          break;
794
 
        case V4L2_PIX_FMT_STV0680:
795
 
          v4lconvert_decode_stv0680(src, tmpbuf, width, height);
796
 
          tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8;
797
 
          break;
798
 
      }
799
 
      /* Do processing on the tmp buffer, because doing it on bayer data is
800
 
         cheaper, and bayer == rgb and our dest_fmt may be yuv */
801
 
      tmpfmt.fmt.pix.bytesperline = width;
802
 
      tmpfmt.fmt.pix.sizeimage = width * height;
803
 
      v4lprocessing_processing(data->processing, tmpbuf, &tmpfmt);
804
 
      /* Deliberate fall through to raw bayer fmt code! */
805
 
      src_pix_fmt = tmpfmt.fmt.pix.pixelformat;
806
 
      src = tmpbuf;
807
 
    }
808
 
 
809
 
    /* Raw bayer formats */
810
 
    case V4L2_PIX_FMT_SBGGR8:
811
 
    case V4L2_PIX_FMT_SGBRG8:
812
 
    case V4L2_PIX_FMT_SGRBG8:
813
 
    case V4L2_PIX_FMT_SRGGB8:
814
 
      switch (dest_pix_fmt) {
815
 
      case V4L2_PIX_FMT_RGB24:
816
 
        v4lconvert_bayer_to_rgb24(src, dest, width, height, src_pix_fmt);
817
 
        break;
818
 
      case V4L2_PIX_FMT_BGR24:
819
 
        v4lconvert_bayer_to_bgr24(src, dest, width, height, src_pix_fmt);
820
 
        break;
821
 
      case V4L2_PIX_FMT_YUV420:
822
 
        v4lconvert_bayer_to_yuv420(src, dest, width, height, src_pix_fmt, 0);
823
 
        break;
824
 
      case V4L2_PIX_FMT_YVU420:
825
 
        v4lconvert_bayer_to_yuv420(src, dest, width, height, src_pix_fmt, 1);
826
 
        break;
827
 
      }
828
 
      break;
829
 
 
830
 
    case V4L2_PIX_FMT_RGB565:
831
 
      switch (dest_pix_fmt) {
832
 
      case V4L2_PIX_FMT_RGB24:
833
 
        v4lconvert_rgb565_to_rgb24(src, dest, width, height);
834
 
        break;
835
 
      case V4L2_PIX_FMT_BGR24:
836
 
        v4lconvert_rgb565_to_bgr24(src, dest, width, height);
837
 
        break;
838
 
      case V4L2_PIX_FMT_YUV420:
839
 
        v4lconvert_rgb565_to_yuv420(src, dest, fmt, 0);
840
 
        break;
841
 
      case V4L2_PIX_FMT_YVU420:
842
 
        v4lconvert_rgb565_to_yuv420(src, dest, fmt, 1);
843
 
        break;
844
 
      }
845
 
      break;
846
 
 
847
 
    case V4L2_PIX_FMT_RGB24:
848
 
      switch (dest_pix_fmt) {
849
 
      case V4L2_PIX_FMT_BGR24:
850
 
        v4lconvert_swap_rgb(src, dest, width, height);
851
 
        break;
852
 
      case V4L2_PIX_FMT_YUV420:
853
 
        v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 0);
854
 
        break;
855
 
      case V4L2_PIX_FMT_YVU420:
856
 
        v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 1);
857
 
        break;
858
 
      }
859
 
      break;
860
 
 
861
 
    case V4L2_PIX_FMT_BGR24:
862
 
      switch (dest_pix_fmt) {
863
 
      case V4L2_PIX_FMT_RGB24:
864
 
        v4lconvert_swap_rgb(src, dest, width, height);
865
 
        break;
866
 
      case V4L2_PIX_FMT_YUV420:
867
 
        v4lconvert_rgb24_to_yuv420(src, dest, fmt, 1, 0);
868
 
        break;
869
 
      case V4L2_PIX_FMT_YVU420:
870
 
        v4lconvert_rgb24_to_yuv420(src, dest, fmt, 1, 1);
871
 
        break;
872
 
      }
873
 
      break;
874
 
 
875
 
    case V4L2_PIX_FMT_YUV420:
876
 
      switch (dest_pix_fmt) {
877
 
      case V4L2_PIX_FMT_RGB24:
878
 
        v4lconvert_yuv420_to_rgb24(src, dest, width,
879
 
                                   height, 0);
880
 
        break;
881
 
      case V4L2_PIX_FMT_BGR24:
882
 
        v4lconvert_yuv420_to_bgr24(src, dest, width,
883
 
                                   height, 0);
884
 
        break;
885
 
      case V4L2_PIX_FMT_YVU420:
886
 
        v4lconvert_swap_uv(src, dest, fmt);
887
 
        break;
888
 
      }
889
 
      break;
890
 
 
891
 
    case V4L2_PIX_FMT_YVU420:
892
 
      switch (dest_pix_fmt) {
893
 
      case V4L2_PIX_FMT_RGB24:
894
 
        v4lconvert_yuv420_to_rgb24(src, dest, width,
895
 
                                   height, 1);
896
 
        break;
897
 
      case V4L2_PIX_FMT_BGR24:
898
 
        v4lconvert_yuv420_to_bgr24(src, dest, width,
899
 
                                   height, 1);
900
 
        break;
901
 
      case V4L2_PIX_FMT_YUV420:
902
 
        v4lconvert_swap_uv(src, dest, fmt);
903
 
        break;
904
 
      }
905
 
      break;
906
 
 
907
 
    case V4L2_PIX_FMT_YUYV:
908
 
      switch (dest_pix_fmt) {
909
 
      case V4L2_PIX_FMT_RGB24:
910
 
        v4lconvert_yuyv_to_rgb24(src, dest, width, height);
911
 
        break;
912
 
      case V4L2_PIX_FMT_BGR24:
913
 
        v4lconvert_yuyv_to_bgr24(src, dest, width, height);
914
 
        break;
915
 
      case V4L2_PIX_FMT_YUV420:
916
 
        v4lconvert_yuyv_to_yuv420(src, dest, width, height, 0);
917
 
        break;
918
 
      case V4L2_PIX_FMT_YVU420:
919
 
        v4lconvert_yuyv_to_yuv420(src, dest, width, height, 1);
920
 
        break;
921
 
      }
922
 
      break;
923
 
 
924
 
    case V4L2_PIX_FMT_YVYU:
925
 
      switch (dest_pix_fmt) {
926
 
      case V4L2_PIX_FMT_RGB24:
927
 
        v4lconvert_yvyu_to_rgb24(src, dest, width, height);
928
 
        break;
929
 
      case V4L2_PIX_FMT_BGR24:
930
 
        v4lconvert_yvyu_to_bgr24(src, dest, width, height);
931
 
        break;
932
 
      case V4L2_PIX_FMT_YUV420:
933
 
        /* Note we use yuyv_to_yuv420 not v4lconvert_yvyu_to_yuv420,
934
 
           with the last argument reversed to make it have as we want */
935
 
        v4lconvert_yuyv_to_yuv420(src, dest, width, height, 1);
936
 
        break;
937
 
      case V4L2_PIX_FMT_YVU420:
938
 
        v4lconvert_yuyv_to_yuv420(src, dest, width, height, 0);
939
 
        break;
940
 
      }
941
 
      break;
942
 
 
943
 
    case V4L2_PIX_FMT_UYVY:
944
 
      switch (dest_pix_fmt) {
945
 
      case V4L2_PIX_FMT_RGB24:
946
 
        v4lconvert_uyvy_to_rgb24(src, dest, width, height);
947
 
        break;
948
 
      case V4L2_PIX_FMT_BGR24:
949
 
        v4lconvert_uyvy_to_bgr24(src, dest, width, height);
950
 
        break;
951
 
      case V4L2_PIX_FMT_YUV420:
952
 
        v4lconvert_uyvy_to_yuv420(src, dest, width, height, 0);
953
 
        break;
954
 
      case V4L2_PIX_FMT_YVU420:
955
 
        v4lconvert_uyvy_to_yuv420(src, dest, width, height, 1);
956
 
        break;
957
 
      }
958
 
      break;
959
 
 
960
 
    default:
961
 
      V4LCONVERT_ERR("Unknown src format in conversion\n");
962
 
      errno = EINVAL;
963
 
      return -1;
964
 
  }
965
 
 
966
 
  fmt->fmt.pix.pixelformat = dest_pix_fmt;
967
 
  v4lconvert_fixup_fmt(fmt);
968
 
 
969
 
  return 0;
 
749
        case V4L2_PIX_FMT_STV0680: { /* Not compressed but needs some shuffling */
 
750
                unsigned char *tmpbuf;
 
751
                struct v4l2_format tmpfmt = *fmt;
 
752
 
 
753
                tmpbuf = v4lconvert_alloc_buffer(width * height,
 
754
                                &data->convert_pixfmt_buf, &data->convert_pixfmt_buf_size);
 
755
                if (!tmpbuf)
 
756
                        return v4lconvert_oom_error(data);
 
757
 
 
758
                switch (src_pix_fmt) {
 
759
                case V4L2_PIX_FMT_SPCA561:
 
760
                        v4lconvert_decode_spca561(src, tmpbuf, width, height);
 
761
                        tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SGBRG8;
 
762
                        break;
 
763
                case V4L2_PIX_FMT_SN9C10X:
 
764
                        v4lconvert_decode_sn9c10x(src, tmpbuf, width, height);
 
765
                        tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
 
766
                        break;
 
767
                case V4L2_PIX_FMT_PAC207:
 
768
                        if (v4lconvert_decode_pac207(data, src, src_size, tmpbuf,
 
769
                                                width, height)) {
 
770
                                /* Corrupt frame, better get another one */
 
771
                                errno = EAGAIN;
 
772
                                return -1;
 
773
                        }
 
774
                        tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
 
775
                        break;
 
776
                case V4L2_PIX_FMT_MR97310A:
 
777
                        if (v4lconvert_decode_mr97310a(data, src, src_size, tmpbuf,
 
778
                                                width, height)) {
 
779
                                /* Corrupt frame, better get another one */
 
780
                                errno = EAGAIN;
 
781
                                return -1;
 
782
                        }
 
783
                        tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
 
784
                        break;
 
785
                case V4L2_PIX_FMT_SN9C2028:
 
786
                        v4lconvert_decode_sn9c2028(src, tmpbuf, width, height);
 
787
                        tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
 
788
                        break;
 
789
                case V4L2_PIX_FMT_SQ905C:
 
790
                        v4lconvert_decode_sq905c(src, tmpbuf, width, height);
 
791
                        tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8;
 
792
                        break;
 
793
                case V4L2_PIX_FMT_STV0680:
 
794
                        v4lconvert_decode_stv0680(src, tmpbuf, width, height);
 
795
                        tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8;
 
796
                        break;
 
797
                }
 
798
                /* Do processing on the tmp buffer, because doing it on bayer data is
 
799
                   cheaper, and bayer == rgb and our dest_fmt may be yuv */
 
800
                tmpfmt.fmt.pix.bytesperline = width;
 
801
                tmpfmt.fmt.pix.sizeimage = width * height;
 
802
                v4lprocessing_processing(data->processing, tmpbuf, &tmpfmt);
 
803
                /* Deliberate fall through to raw bayer fmt code! */
 
804
                src_pix_fmt = tmpfmt.fmt.pix.pixelformat;
 
805
                src = tmpbuf;
 
806
                /* fall through */
 
807
        }
 
808
 
 
809
                /* Raw bayer formats */
 
810
        case V4L2_PIX_FMT_SBGGR8:
 
811
        case V4L2_PIX_FMT_SGBRG8:
 
812
        case V4L2_PIX_FMT_SGRBG8:
 
813
        case V4L2_PIX_FMT_SRGGB8:
 
814
                switch (dest_pix_fmt) {
 
815
                case V4L2_PIX_FMT_RGB24:
 
816
                        v4lconvert_bayer_to_rgb24(src, dest, width, height, src_pix_fmt);
 
817
                        break;
 
818
                case V4L2_PIX_FMT_BGR24:
 
819
                        v4lconvert_bayer_to_bgr24(src, dest, width, height, src_pix_fmt);
 
820
                        break;
 
821
                case V4L2_PIX_FMT_YUV420:
 
822
                        v4lconvert_bayer_to_yuv420(src, dest, width, height, src_pix_fmt, 0);
 
823
                        break;
 
824
                case V4L2_PIX_FMT_YVU420:
 
825
                        v4lconvert_bayer_to_yuv420(src, dest, width, height, src_pix_fmt, 1);
 
826
                        break;
 
827
                }
 
828
                break;
 
829
 
 
830
        case V4L2_PIX_FMT_RGB565:
 
831
                switch (dest_pix_fmt) {
 
832
                case V4L2_PIX_FMT_RGB24:
 
833
                        v4lconvert_rgb565_to_rgb24(src, dest, width, height);
 
834
                        break;
 
835
                case V4L2_PIX_FMT_BGR24:
 
836
                        v4lconvert_rgb565_to_bgr24(src, dest, width, height);
 
837
                        break;
 
838
                case V4L2_PIX_FMT_YUV420:
 
839
                        v4lconvert_rgb565_to_yuv420(src, dest, fmt, 0);
 
840
                        break;
 
841
                case V4L2_PIX_FMT_YVU420:
 
842
                        v4lconvert_rgb565_to_yuv420(src, dest, fmt, 1);
 
843
                        break;
 
844
                }
 
845
                break;
 
846
 
 
847
        case V4L2_PIX_FMT_RGB24:
 
848
                switch (dest_pix_fmt) {
 
849
                case V4L2_PIX_FMT_BGR24:
 
850
                        v4lconvert_swap_rgb(src, dest, width, height);
 
851
                        break;
 
852
                case V4L2_PIX_FMT_YUV420:
 
853
                        v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 0);
 
854
                        break;
 
855
                case V4L2_PIX_FMT_YVU420:
 
856
                        v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 1);
 
857
                        break;
 
858
                }
 
859
                break;
 
860
 
 
861
        case V4L2_PIX_FMT_BGR24:
 
862
                switch (dest_pix_fmt) {
 
863
                case V4L2_PIX_FMT_RGB24:
 
864
                        v4lconvert_swap_rgb(src, dest, width, height);
 
865
                        break;
 
866
                case V4L2_PIX_FMT_YUV420:
 
867
                        v4lconvert_rgb24_to_yuv420(src, dest, fmt, 1, 0);
 
868
                        break;
 
869
                case V4L2_PIX_FMT_YVU420:
 
870
                        v4lconvert_rgb24_to_yuv420(src, dest, fmt, 1, 1);
 
871
                        break;
 
872
                }
 
873
                break;
 
874
 
 
875
        case V4L2_PIX_FMT_YUV420:
 
876
                switch (dest_pix_fmt) {
 
877
                case V4L2_PIX_FMT_RGB24:
 
878
                        v4lconvert_yuv420_to_rgb24(src, dest, width,
 
879
                                        height, 0);
 
880
                        break;
 
881
                case V4L2_PIX_FMT_BGR24:
 
882
                        v4lconvert_yuv420_to_bgr24(src, dest, width,
 
883
                                        height, 0);
 
884
                        break;
 
885
                case V4L2_PIX_FMT_YVU420:
 
886
                        v4lconvert_swap_uv(src, dest, fmt);
 
887
                        break;
 
888
                }
 
889
                break;
 
890
 
 
891
        case V4L2_PIX_FMT_YVU420:
 
892
                switch (dest_pix_fmt) {
 
893
                case V4L2_PIX_FMT_RGB24:
 
894
                        v4lconvert_yuv420_to_rgb24(src, dest, width,
 
895
                                        height, 1);
 
896
                        break;
 
897
                case V4L2_PIX_FMT_BGR24:
 
898
                        v4lconvert_yuv420_to_bgr24(src, dest, width,
 
899
                                        height, 1);
 
900
                        break;
 
901
                case V4L2_PIX_FMT_YUV420:
 
902
                        v4lconvert_swap_uv(src, dest, fmt);
 
903
                        break;
 
904
                }
 
905
                break;
 
906
 
 
907
        case V4L2_PIX_FMT_YUYV:
 
908
                switch (dest_pix_fmt) {
 
909
                case V4L2_PIX_FMT_RGB24:
 
910
                        v4lconvert_yuyv_to_rgb24(src, dest, width, height);
 
911
                        break;
 
912
                case V4L2_PIX_FMT_BGR24:
 
913
                        v4lconvert_yuyv_to_bgr24(src, dest, width, height);
 
914
                        break;
 
915
                case V4L2_PIX_FMT_YUV420:
 
916
                        v4lconvert_yuyv_to_yuv420(src, dest, width, height, 0);
 
917
                        break;
 
918
                case V4L2_PIX_FMT_YVU420:
 
919
                        v4lconvert_yuyv_to_yuv420(src, dest, width, height, 1);
 
920
                        break;
 
921
                }
 
922
                break;
 
923
 
 
924
        case V4L2_PIX_FMT_YVYU:
 
925
                switch (dest_pix_fmt) {
 
926
                case V4L2_PIX_FMT_RGB24:
 
927
                        v4lconvert_yvyu_to_rgb24(src, dest, width, height);
 
928
                        break;
 
929
                case V4L2_PIX_FMT_BGR24:
 
930
                        v4lconvert_yvyu_to_bgr24(src, dest, width, height);
 
931
                        break;
 
932
                case V4L2_PIX_FMT_YUV420:
 
933
                        /* Note we use yuyv_to_yuv420 not v4lconvert_yvyu_to_yuv420,
 
934
                           with the last argument reversed to make it have as we want */
 
935
                        v4lconvert_yuyv_to_yuv420(src, dest, width, height, 1);
 
936
                        break;
 
937
                case V4L2_PIX_FMT_YVU420:
 
938
                        v4lconvert_yuyv_to_yuv420(src, dest, width, height, 0);
 
939
                        break;
 
940
                }
 
941
                break;
 
942
 
 
943
        case V4L2_PIX_FMT_UYVY:
 
944
                switch (dest_pix_fmt) {
 
945
                case V4L2_PIX_FMT_RGB24:
 
946
                        v4lconvert_uyvy_to_rgb24(src, dest, width, height);
 
947
                        break;
 
948
                case V4L2_PIX_FMT_BGR24:
 
949
                        v4lconvert_uyvy_to_bgr24(src, dest, width, height);
 
950
                        break;
 
951
                case V4L2_PIX_FMT_YUV420:
 
952
                        v4lconvert_uyvy_to_yuv420(src, dest, width, height, 0);
 
953
                        break;
 
954
                case V4L2_PIX_FMT_YVU420:
 
955
                        v4lconvert_uyvy_to_yuv420(src, dest, width, height, 1);
 
956
                        break;
 
957
                }
 
958
                break;
 
959
 
 
960
        default:
 
961
                V4LCONVERT_ERR("Unknown src format in conversion\n");
 
962
                errno = EINVAL;
 
963
                return -1;
 
964
        }
 
965
 
 
966
        fmt->fmt.pix.pixelformat = dest_pix_fmt;
 
967
        v4lconvert_fixup_fmt(fmt);
 
968
 
 
969
        return 0;
970
970
}
971
971
 
972
972
int v4lconvert_convert(struct v4lconvert_data *data,
973
 
  const struct v4l2_format *src_fmt,  /* in */
974
 
  const struct v4l2_format *dest_fmt, /* in */
975
 
  unsigned char *src, int src_size, unsigned char *dest, int dest_size)
 
973
                const struct v4l2_format *src_fmt,  /* in */
 
974
                const struct v4l2_format *dest_fmt, /* in */
 
975
                unsigned char *src, int src_size, unsigned char *dest, int dest_size)
976
976
{
977
 
  int res, dest_needed, temp_needed, processing, convert = 0;
978
 
  int rotate90, vflip, hflip, crop;
979
 
  unsigned char *convert1_dest = dest;
980
 
  int convert1_dest_size = dest_size;
981
 
  unsigned char *convert2_src = src, *convert2_dest = dest;
982
 
  int convert2_dest_size = dest_size;
983
 
  unsigned char *rotate90_src = src, *rotate90_dest = dest;
984
 
  unsigned char *flip_src = src, *flip_dest = dest;
985
 
  unsigned char *crop_src = src;
986
 
  struct v4l2_format my_src_fmt = *src_fmt;
987
 
  struct v4l2_format my_dest_fmt = *dest_fmt;
988
 
 
989
 
  processing = v4lprocessing_pre_processing(data->processing);
990
 
  rotate90 = data->control_flags & V4LCONTROL_ROTATED_90_JPEG;
991
 
  hflip = v4lcontrol_get_ctrl(data->control, V4LCONTROL_HFLIP);
992
 
  vflip = v4lcontrol_get_ctrl(data->control, V4LCONTROL_VFLIP);
993
 
  crop = my_dest_fmt.fmt.pix.width != my_src_fmt.fmt.pix.width ||
994
 
         my_dest_fmt.fmt.pix.height != my_src_fmt.fmt.pix.height;
995
 
 
996
 
  if (/* If no conversion/processing is needed */
997
 
      (src_fmt->fmt.pix.pixelformat == dest_fmt->fmt.pix.pixelformat &&
998
 
       !processing && !rotate90 && !hflip && !vflip && !crop) ||
999
 
      /* or if we should do processing/rotating/flipping but the app tries to
1000
 
         use the native cam format, we just return an unprocessed frame copy */
1001
 
      !v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)) {
1002
 
    int to_copy = MIN(dest_size, src_size);
1003
 
    memcpy(dest, src, to_copy);
1004
 
    return to_copy;
1005
 
  }
1006
 
 
1007
 
  /* When field is V4L2_FIELD_ALTERNATE, each buffer only contains half the
1008
 
     lines */
1009
 
  if (my_src_fmt.fmt.pix.field == V4L2_FIELD_ALTERNATE) {
1010
 
    my_src_fmt.fmt.pix.height /= 2;
1011
 
    my_dest_fmt.fmt.pix.height /= 2;
1012
 
  }
1013
 
 
1014
 
  /* sanity check, is the dest buffer large enough? */
1015
 
  switch (my_dest_fmt.fmt.pix.pixelformat) {
1016
 
    case V4L2_PIX_FMT_RGB24:
1017
 
    case V4L2_PIX_FMT_BGR24:
1018
 
      dest_needed = my_dest_fmt.fmt.pix.width * my_dest_fmt.fmt.pix.height * 3;
1019
 
      temp_needed = my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3;
1020
 
      break;
1021
 
    case V4L2_PIX_FMT_YUV420:
1022
 
    case V4L2_PIX_FMT_YVU420:
1023
 
      dest_needed =
1024
 
        my_dest_fmt.fmt.pix.width * my_dest_fmt.fmt.pix.height * 3 / 2;
1025
 
      temp_needed =
1026
 
        my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3 / 2;
1027
 
      break;
1028
 
    default:
1029
 
      V4LCONVERT_ERR("Unknown dest format in conversion\n");
1030
 
      errno = EINVAL;
1031
 
      return -1;
1032
 
  }
1033
 
 
1034
 
  if (dest_size < dest_needed) {
1035
 
    V4LCONVERT_ERR("destination buffer too small (%d < %d)\n",
1036
 
                   dest_size, dest_needed);
1037
 
    errno = EFAULT;
1038
 
    return -1;
1039
 
  }
1040
 
 
1041
 
 
1042
 
  /* Sometimes we need foo -> rgb -> bar as video processing (whitebalance,
1043
 
     etc.) can only be done on rgb data */
1044
 
  if (processing && v4lconvert_processing_needs_double_conversion(
1045
 
                                             my_src_fmt.fmt.pix.pixelformat,
1046
 
                                             my_dest_fmt.fmt.pix.pixelformat))
1047
 
    convert = 2;
1048
 
  else if (my_dest_fmt.fmt.pix.pixelformat != my_src_fmt.fmt.pix.pixelformat)
1049
 
    convert = 1;
1050
 
 
1051
 
  /* convert_pixfmt (only if convert == 2) -> processing -> convert_pixfmt ->
1052
 
     rotate -> flip -> crop, all steps are optional */
1053
 
  if (convert == 2) {
1054
 
    convert1_dest = v4lconvert_alloc_buffer(
1055
 
                     my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3,
1056
 
                     &data->convert1_buf, &data->convert1_buf_size);
1057
 
    if (!convert1_dest)
1058
 
      return v4lconvert_oom_error(data);
1059
 
 
1060
 
    convert1_dest_size =
1061
 
      my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3;
1062
 
    convert2_src = convert1_dest;
1063
 
  }
1064
 
 
1065
 
  if (convert && (rotate90 || hflip || vflip || crop)) {
1066
 
    convert2_dest = v4lconvert_alloc_buffer(temp_needed,
1067
 
                     &data->convert2_buf, &data->convert2_buf_size);
1068
 
    if (!convert2_dest)
1069
 
      return v4lconvert_oom_error(data);
1070
 
 
1071
 
    convert2_dest_size = temp_needed;
1072
 
    rotate90_src = flip_src = crop_src = convert2_dest;
1073
 
  }
1074
 
 
1075
 
  if (rotate90 && (hflip || vflip || crop)) {
1076
 
    rotate90_dest = v4lconvert_alloc_buffer(temp_needed,
1077
 
                    &data->rotate90_buf, &data->rotate90_buf_size);
1078
 
    if (!rotate90_dest)
1079
 
      return v4lconvert_oom_error(data);
1080
 
 
1081
 
    flip_src = crop_src = rotate90_dest;
1082
 
  }
1083
 
 
1084
 
  if ((vflip || hflip) && crop) {
1085
 
    flip_dest = v4lconvert_alloc_buffer(temp_needed, &data->flip_buf,
1086
 
                                        &data->flip_buf_size);
1087
 
    if (!flip_dest)
1088
 
      return v4lconvert_oom_error(data);
1089
 
 
1090
 
    crop_src = flip_dest;
1091
 
  }
1092
 
 
1093
 
  /* Done setting sources / dest and allocating intermediate buffers,
1094
 
     real conversion / processing / ... starts here. */
1095
 
  if (convert == 2) {
1096
 
    res = v4lconvert_convert_pixfmt(data, src, src_size,
1097
 
                                    convert1_dest, convert1_dest_size,
1098
 
                                    &my_src_fmt,
1099
 
                                    V4L2_PIX_FMT_RGB24);
1100
 
    if (res)
1101
 
      return res;
1102
 
 
1103
 
    src_size = my_src_fmt.fmt.pix.sizeimage;
1104
 
  }
1105
 
 
1106
 
  if (processing)
1107
 
    v4lprocessing_processing(data->processing, convert2_src, &my_src_fmt);
1108
 
 
1109
 
  if (convert) {
1110
 
    res = v4lconvert_convert_pixfmt(data, convert2_src, src_size,
1111
 
                                    convert2_dest, convert2_dest_size,
1112
 
                                    &my_src_fmt,
1113
 
                                    my_dest_fmt.fmt.pix.pixelformat);
1114
 
    if (res)
1115
 
      return res;
1116
 
 
1117
 
    src_size = my_src_fmt.fmt.pix.sizeimage;
1118
 
 
1119
 
    /* We call processing here again in case the source format was not
1120
 
       rgb, but the dest is. v4lprocessing checks it self it only actually
1121
 
       does the processing once per frame. */
1122
 
    if (processing)
1123
 
      v4lprocessing_processing(data->processing, convert2_dest, &my_src_fmt);
1124
 
  }
1125
 
 
1126
 
  if (rotate90)
1127
 
    v4lconvert_rotate90(rotate90_src, rotate90_dest, &my_src_fmt);
1128
 
 
1129
 
  if (hflip || vflip)
1130
 
    v4lconvert_flip(flip_src, flip_dest, &my_src_fmt, hflip, vflip);
1131
 
 
1132
 
  if (crop)
1133
 
    v4lconvert_crop(crop_src, dest, &my_src_fmt, &my_dest_fmt);
1134
 
 
1135
 
  return dest_needed;
 
977
        int res, dest_needed, temp_needed, processing, convert = 0;
 
978
        int rotate90, vflip, hflip, crop;
 
979
        unsigned char *convert1_dest = dest;
 
980
        int convert1_dest_size = dest_size;
 
981
        unsigned char *convert2_src = src, *convert2_dest = dest;
 
982
        int convert2_dest_size = dest_size;
 
983
        unsigned char *rotate90_src = src, *rotate90_dest = dest;
 
984
        unsigned char *flip_src = src, *flip_dest = dest;
 
985
        unsigned char *crop_src = src;
 
986
        struct v4l2_format my_src_fmt = *src_fmt;
 
987
        struct v4l2_format my_dest_fmt = *dest_fmt;
 
988
 
 
989
        processing = v4lprocessing_pre_processing(data->processing);
 
990
        rotate90 = data->control_flags & V4LCONTROL_ROTATED_90_JPEG;
 
991
        hflip = v4lcontrol_get_ctrl(data->control, V4LCONTROL_HFLIP);
 
992
        vflip = v4lcontrol_get_ctrl(data->control, V4LCONTROL_VFLIP);
 
993
        crop = my_dest_fmt.fmt.pix.width != my_src_fmt.fmt.pix.width ||
 
994
                my_dest_fmt.fmt.pix.height != my_src_fmt.fmt.pix.height;
 
995
 
 
996
        if (/* If no conversion/processing is needed */
 
997
                        (src_fmt->fmt.pix.pixelformat == dest_fmt->fmt.pix.pixelformat &&
 
998
                         !processing && !rotate90 && !hflip && !vflip && !crop) ||
 
999
                        /* or if we should do processing/rotating/flipping but the app tries to
 
1000
                           use the native cam format, we just return an unprocessed frame copy */
 
1001
                        !v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)) {
 
1002
                int to_copy = MIN(dest_size, src_size);
 
1003
                memcpy(dest, src, to_copy);
 
1004
                return to_copy;
 
1005
        }
 
1006
 
 
1007
        /* When field is V4L2_FIELD_ALTERNATE, each buffer only contains half the
 
1008
           lines */
 
1009
        if (my_src_fmt.fmt.pix.field == V4L2_FIELD_ALTERNATE) {
 
1010
                my_src_fmt.fmt.pix.height /= 2;
 
1011
                my_dest_fmt.fmt.pix.height /= 2;
 
1012
        }
 
1013
 
 
1014
        /* sanity check, is the dest buffer large enough? */
 
1015
        switch (my_dest_fmt.fmt.pix.pixelformat) {
 
1016
        case V4L2_PIX_FMT_RGB24:
 
1017
        case V4L2_PIX_FMT_BGR24:
 
1018
                dest_needed = my_dest_fmt.fmt.pix.width * my_dest_fmt.fmt.pix.height * 3;
 
1019
                temp_needed = my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3;
 
1020
                break;
 
1021
        case V4L2_PIX_FMT_YUV420:
 
1022
        case V4L2_PIX_FMT_YVU420:
 
1023
                dest_needed =
 
1024
                        my_dest_fmt.fmt.pix.width * my_dest_fmt.fmt.pix.height * 3 / 2;
 
1025
                temp_needed =
 
1026
                        my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3 / 2;
 
1027
                break;
 
1028
        default:
 
1029
                V4LCONVERT_ERR("Unknown dest format in conversion\n");
 
1030
                errno = EINVAL;
 
1031
                return -1;
 
1032
        }
 
1033
 
 
1034
        if (dest_size < dest_needed) {
 
1035
                V4LCONVERT_ERR("destination buffer too small (%d < %d)\n",
 
1036
                                dest_size, dest_needed);
 
1037
                errno = EFAULT;
 
1038
                return -1;
 
1039
        }
 
1040
 
 
1041
 
 
1042
        /* Sometimes we need foo -> rgb -> bar as video processing (whitebalance,
 
1043
           etc.) can only be done on rgb data */
 
1044
        if (processing && v4lconvert_processing_needs_double_conversion(
 
1045
                                my_src_fmt.fmt.pix.pixelformat,
 
1046
                                my_dest_fmt.fmt.pix.pixelformat))
 
1047
                convert = 2;
 
1048
        else if (my_dest_fmt.fmt.pix.pixelformat != my_src_fmt.fmt.pix.pixelformat)
 
1049
                convert = 1;
 
1050
 
 
1051
        /* convert_pixfmt (only if convert == 2) -> processing -> convert_pixfmt ->
 
1052
           rotate -> flip -> crop, all steps are optional */
 
1053
        if (convert == 2) {
 
1054
                convert1_dest = v4lconvert_alloc_buffer(
 
1055
                                my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3,
 
1056
                                &data->convert1_buf, &data->convert1_buf_size);
 
1057
                if (!convert1_dest)
 
1058
                        return v4lconvert_oom_error(data);
 
1059
 
 
1060
                convert1_dest_size =
 
1061
                        my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3;
 
1062
                convert2_src = convert1_dest;
 
1063
        }
 
1064
 
 
1065
        if (convert && (rotate90 || hflip || vflip || crop)) {
 
1066
                convert2_dest = v4lconvert_alloc_buffer(temp_needed,
 
1067
                                &data->convert2_buf, &data->convert2_buf_size);
 
1068
                if (!convert2_dest)
 
1069
                        return v4lconvert_oom_error(data);
 
1070
 
 
1071
                convert2_dest_size = temp_needed;
 
1072
                rotate90_src = flip_src = crop_src = convert2_dest;
 
1073
        }
 
1074
 
 
1075
        if (rotate90 && (hflip || vflip || crop)) {
 
1076
                rotate90_dest = v4lconvert_alloc_buffer(temp_needed,
 
1077
                                &data->rotate90_buf, &data->rotate90_buf_size);
 
1078
                if (!rotate90_dest)
 
1079
                        return v4lconvert_oom_error(data);
 
1080
 
 
1081
                flip_src = crop_src = rotate90_dest;
 
1082
        }
 
1083
 
 
1084
        if ((vflip || hflip) && crop) {
 
1085
                flip_dest = v4lconvert_alloc_buffer(temp_needed, &data->flip_buf,
 
1086
                                &data->flip_buf_size);
 
1087
                if (!flip_dest)
 
1088
                        return v4lconvert_oom_error(data);
 
1089
 
 
1090
                crop_src = flip_dest;
 
1091
        }
 
1092
 
 
1093
        /* Done setting sources / dest and allocating intermediate buffers,
 
1094
           real conversion / processing / ... starts here. */
 
1095
        if (convert == 2) {
 
1096
                res = v4lconvert_convert_pixfmt(data, src, src_size,
 
1097
                                convert1_dest, convert1_dest_size,
 
1098
                                &my_src_fmt,
 
1099
                                V4L2_PIX_FMT_RGB24);
 
1100
                if (res)
 
1101
                        return res;
 
1102
 
 
1103
                src_size = my_src_fmt.fmt.pix.sizeimage;
 
1104
        }
 
1105
 
 
1106
        if (processing)
 
1107
                v4lprocessing_processing(data->processing, convert2_src, &my_src_fmt);
 
1108
 
 
1109
        if (convert) {
 
1110
                res = v4lconvert_convert_pixfmt(data, convert2_src, src_size,
 
1111
                                convert2_dest, convert2_dest_size,
 
1112
                                &my_src_fmt,
 
1113
                                my_dest_fmt.fmt.pix.pixelformat);
 
1114
                if (res)
 
1115
                        return res;
 
1116
 
 
1117
                src_size = my_src_fmt.fmt.pix.sizeimage;
 
1118
 
 
1119
                /* We call processing here again in case the source format was not
 
1120
                   rgb, but the dest is. v4lprocessing checks it self it only actually
 
1121
                   does the processing once per frame. */
 
1122
                if (processing)
 
1123
                        v4lprocessing_processing(data->processing, convert2_dest, &my_src_fmt);
 
1124
        }
 
1125
 
 
1126
        if (rotate90)
 
1127
                v4lconvert_rotate90(rotate90_src, rotate90_dest, &my_src_fmt);
 
1128
 
 
1129
        if (hflip || vflip)
 
1130
                v4lconvert_flip(flip_src, flip_dest, &my_src_fmt, hflip, vflip);
 
1131
 
 
1132
        if (crop)
 
1133
                v4lconvert_crop(crop_src, dest, &my_src_fmt, &my_dest_fmt);
 
1134
 
 
1135
        return dest_needed;
1136
1136
}
1137
1137
 
1138
1138
const char *v4lconvert_get_error_message(struct v4lconvert_data *data)
1139
1139
{
1140
 
  return data->error_msg;
 
1140
        return data->error_msg;
1141
1141
}
1142
1142
 
1143
1143
static void v4lconvert_get_framesizes(struct v4lconvert_data *data,
1144
 
  unsigned int pixelformat, int index)
 
1144
                unsigned int pixelformat, int index)
1145
1145
{
1146
 
  int i, j, match;
1147
 
  struct v4l2_frmsizeenum frmsize = { .pixel_format = pixelformat };
1148
 
 
1149
 
  for (i = 0; ; i++) {
1150
 
    frmsize.index = i;
1151
 
    if (SYS_IOCTL(data->fd, VIDIOC_ENUM_FRAMESIZES, &frmsize))
1152
 
      break;
1153
 
 
1154
 
    /* We got a framesize, check we don't have the same one already */
1155
 
    match = 0;
1156
 
    for (j = 0; j < data->no_framesizes; j++) {
1157
 
      if (frmsize.type != data->framesizes[j].type)
1158
 
        continue;
1159
 
 
1160
 
      switch(frmsize.type) {
1161
 
        case V4L2_FRMSIZE_TYPE_DISCRETE:
1162
 
          if(!memcmp(&frmsize.discrete, &data->framesizes[j].discrete,
1163
 
                     sizeof(frmsize.discrete)))
1164
 
            match = 1;
1165
 
          break;
1166
 
        case V4L2_FRMSIZE_TYPE_CONTINUOUS:
1167
 
        case V4L2_FRMSIZE_TYPE_STEPWISE:
1168
 
          if(!memcmp(&frmsize.stepwise, &data->framesizes[j].stepwise,
1169
 
                     sizeof(frmsize.stepwise)))
1170
 
            match = 1;
1171
 
          break;
1172
 
      }
1173
 
      if (match)
1174
 
        break;
1175
 
    }
1176
 
    /* Add this framesize if it is not already in our list */
1177
 
    if (!match) {
1178
 
      if (data->no_framesizes == V4LCONVERT_MAX_FRAMESIZES) {
1179
 
        fprintf(stderr,
1180
 
          "libv4lconvert: warning more framesizes then I can handle!\n");
1181
 
        return;
1182
 
      }
1183
 
      data->framesizes[data->no_framesizes].type = frmsize.type;
1184
 
      /* We use the pixel_format member to store a bitmask of all
1185
 
         supported src_formats which can do this size */
1186
 
      data->framesizes[data->no_framesizes].pixel_format = 1 << index;
1187
 
      switch(frmsize.type) {
1188
 
        case V4L2_FRMSIZE_TYPE_DISCRETE:
1189
 
          data->framesizes[data->no_framesizes].discrete = frmsize.discrete;
1190
 
          break;
1191
 
        case V4L2_FRMSIZE_TYPE_CONTINUOUS:
1192
 
        case V4L2_FRMSIZE_TYPE_STEPWISE:
1193
 
          data->framesizes[data->no_framesizes].stepwise = frmsize.stepwise;
1194
 
          break;
1195
 
      }
1196
 
      data->no_framesizes++;
1197
 
    }
1198
 
    else
1199
 
      data->framesizes[j].pixel_format |= 1 << index;
1200
 
  }
 
1146
        int i, j, match;
 
1147
        struct v4l2_frmsizeenum frmsize = { .pixel_format = pixelformat };
 
1148
 
 
1149
        for (i = 0; ; i++) {
 
1150
                frmsize.index = i;
 
1151
                if (SYS_IOCTL(data->fd, VIDIOC_ENUM_FRAMESIZES, &frmsize))
 
1152
                        break;
 
1153
 
 
1154
                /* We got a framesize, check we don't have the same one already */
 
1155
                match = 0;
 
1156
                for (j = 0; j < data->no_framesizes; j++) {
 
1157
                        if (frmsize.type != data->framesizes[j].type)
 
1158
                                continue;
 
1159
 
 
1160
                        switch (frmsize.type) {
 
1161
                        case V4L2_FRMSIZE_TYPE_DISCRETE:
 
1162
                                if (!memcmp(&frmsize.discrete, &data->framesizes[j].discrete,
 
1163
                                                        sizeof(frmsize.discrete)))
 
1164
                                        match = 1;
 
1165
                                break;
 
1166
                        case V4L2_FRMSIZE_TYPE_CONTINUOUS:
 
1167
                        case V4L2_FRMSIZE_TYPE_STEPWISE:
 
1168
                                if (!memcmp(&frmsize.stepwise, &data->framesizes[j].stepwise,
 
1169
                                                        sizeof(frmsize.stepwise)))
 
1170
                                        match = 1;
 
1171
                                break;
 
1172
                        }
 
1173
                        if (match)
 
1174
                                break;
 
1175
                }
 
1176
                /* Add this framesize if it is not already in our list */
 
1177
                if (!match) {
 
1178
                        if (data->no_framesizes == V4LCONVERT_MAX_FRAMESIZES) {
 
1179
                                fprintf(stderr, "libv4lconvert: warning more framesizes then I can handle!\n");
 
1180
                                return;
 
1181
                        }
 
1182
                        data->framesizes[data->no_framesizes].type = frmsize.type;
 
1183
                        /* We use the pixel_format member to store a bitmask of all
 
1184
                           supported src_formats which can do this size */
 
1185
                        data->framesizes[data->no_framesizes].pixel_format = 1 << index;
 
1186
 
 
1187
                        switch (frmsize.type) {
 
1188
                        case V4L2_FRMSIZE_TYPE_DISCRETE:
 
1189
                                data->framesizes[data->no_framesizes].discrete = frmsize.discrete;
 
1190
                                break;
 
1191
                        case V4L2_FRMSIZE_TYPE_CONTINUOUS:
 
1192
                        case V4L2_FRMSIZE_TYPE_STEPWISE:
 
1193
                                data->framesizes[data->no_framesizes].stepwise = frmsize.stepwise;
 
1194
                                break;
 
1195
                        }
 
1196
                        data->no_framesizes++;
 
1197
                } else {
 
1198
                        data->framesizes[j].pixel_format |= 1 << index;
 
1199
                }
 
1200
        }
1201
1201
}
1202
1202
 
1203
1203
int v4lconvert_enum_framesizes(struct v4lconvert_data *data,
1204
 
  struct v4l2_frmsizeenum *frmsize)
 
1204
                struct v4l2_frmsizeenum *frmsize)
1205
1205
{
1206
 
  if (!v4lconvert_supported_dst_format(frmsize->pixel_format)) {
1207
 
    if (v4lconvert_supported_dst_fmt_only(data)) {
1208
 
      errno = EINVAL;
1209
 
      return -1;
1210
 
    }
1211
 
    return SYS_IOCTL(data->fd, VIDIOC_ENUM_FRAMESIZES, frmsize);
1212
 
  }
1213
 
 
1214
 
  if (frmsize->index >= data->no_framesizes) {
1215
 
    errno = EINVAL;
1216
 
    return -1;
1217
 
  }
1218
 
 
1219
 
  frmsize->type = data->framesizes[frmsize->index].type;
1220
 
  switch(frmsize->type) {
1221
 
    case V4L2_FRMSIZE_TYPE_DISCRETE:
1222
 
      frmsize->discrete = data->framesizes[frmsize->index].discrete;
1223
 
      /* Apply the same rounding algorithm as v4lconvert_try_format */
1224
 
      frmsize->discrete.width &= ~7;
1225
 
      frmsize->discrete.height &= ~1;
1226
 
      break;
1227
 
    case V4L2_FRMSIZE_TYPE_CONTINUOUS:
1228
 
    case V4L2_FRMSIZE_TYPE_STEPWISE:
1229
 
      frmsize->stepwise = data->framesizes[frmsize->index].stepwise;
1230
 
      break;
1231
 
  }
1232
 
 
1233
 
  return 0;
 
1206
        if (!v4lconvert_supported_dst_format(frmsize->pixel_format)) {
 
1207
                if (v4lconvert_supported_dst_fmt_only(data)) {
 
1208
                        errno = EINVAL;
 
1209
                        return -1;
 
1210
                }
 
1211
                return SYS_IOCTL(data->fd, VIDIOC_ENUM_FRAMESIZES, frmsize);
 
1212
        }
 
1213
 
 
1214
        if (frmsize->index >= data->no_framesizes) {
 
1215
                errno = EINVAL;
 
1216
                return -1;
 
1217
        }
 
1218
 
 
1219
        frmsize->type = data->framesizes[frmsize->index].type;
 
1220
        switch (frmsize->type) {
 
1221
        case V4L2_FRMSIZE_TYPE_DISCRETE:
 
1222
                frmsize->discrete = data->framesizes[frmsize->index].discrete;
 
1223
                /* Apply the same rounding algorithm as v4lconvert_try_format */
 
1224
                frmsize->discrete.width &= ~7;
 
1225
                frmsize->discrete.height &= ~1;
 
1226
                break;
 
1227
        case V4L2_FRMSIZE_TYPE_CONTINUOUS:
 
1228
        case V4L2_FRMSIZE_TYPE_STEPWISE:
 
1229
                frmsize->stepwise = data->framesizes[frmsize->index].stepwise;
 
1230
                break;
 
1231
        }
 
1232
 
 
1233
        return 0;
1234
1234
}
1235
1235
 
1236
1236
int v4lconvert_enum_frameintervals(struct v4lconvert_data *data,
1237
 
  struct v4l2_frmivalenum *frmival)
1238
 
{
1239
 
  int res;
1240
 
  struct v4l2_format src_fmt, dest_fmt;
1241
 
 
1242
 
  if (!v4lconvert_supported_dst_format(frmival->pixel_format)) {
1243
 
    if (v4lconvert_supported_dst_fmt_only(data)) {
1244
 
      errno = EINVAL;
1245
 
      return -1;
1246
 
    }
1247
 
    res = SYS_IOCTL(data->fd, VIDIOC_ENUM_FRAMEINTERVALS, frmival);
1248
 
    if (res)
1249
 
      V4LCONVERT_ERR("%s\n", strerror(errno));
1250
 
    return res;
1251
 
  }
1252
 
 
1253
 
  /* Check which format we will be using to convert to frmival->pixel_format */
1254
 
  memset(&dest_fmt, 0, sizeof(dest_fmt));
1255
 
  dest_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1256
 
  dest_fmt.fmt.pix.pixelformat = frmival->pixel_format;
1257
 
  dest_fmt.fmt.pix.width = frmival->width;
1258
 
  dest_fmt.fmt.pix.height = frmival->height;
1259
 
  if ((res = v4lconvert_try_format(data, &dest_fmt, &src_fmt))) {
1260
 
    if (res)
1261
 
      V4LCONVERT_ERR("trying format: %s\n", strerror(errno));
1262
 
    return res;
1263
 
  }
1264
 
 
1265
 
  /* Check the requested format is supported exactly as requested */
1266
 
  if (dest_fmt.fmt.pix.pixelformat != frmival->pixel_format ||
1267
 
      dest_fmt.fmt.pix.width  != frmival->width ||
1268
 
      dest_fmt.fmt.pix.height != frmival->height) {
1269
 
    int frmival_pixformat = frmival->pixel_format;
1270
 
    int dest_pixformat = dest_fmt.fmt.pix.pixelformat;
1271
 
    V4LCONVERT_ERR("Could not find matching framesize for: %c%c%c%c %dx%d "
1272
 
            "closest match: %c%c%c%c %dx%d\n",
1273
 
            frmival_pixformat & 0xff,
1274
 
            (frmival_pixformat >> 8) & 0xff,
1275
 
            (frmival_pixformat >> 16) & 0xff,
1276
 
            frmival_pixformat >> 24,
1277
 
            frmival->width, frmival->height,
1278
 
            dest_pixformat & 0xff,
1279
 
            (dest_pixformat >> 8) & 0xff,
1280
 
            (dest_pixformat >> 16) & 0xff,
1281
 
            dest_pixformat >> 24,
1282
 
            dest_fmt.fmt.pix.width , dest_fmt.fmt.pix.height);
1283
 
    errno = EINVAL;
1284
 
    return -1;
1285
 
  }
1286
 
 
1287
 
  /* Enumerate the frameintervals of the source format we will be using */
1288
 
  frmival->pixel_format = src_fmt.fmt.pix.pixelformat;
1289
 
  frmival->width = src_fmt.fmt.pix.width;
1290
 
  frmival->height = src_fmt.fmt.pix.height;
1291
 
  res = SYS_IOCTL(data->fd, VIDIOC_ENUM_FRAMEINTERVALS, frmival);
1292
 
  if (res) {
1293
 
    int dest_pixfmt = dest_fmt.fmt.pix.pixelformat;
1294
 
    int src_pixfmt  = src_fmt.fmt.pix.pixelformat;
1295
 
    V4LCONVERT_ERR("Could not enum frameival index: %d for: %c%c%c%c %dx%d "
1296
 
            "using src: %c%c%c%c %dx%d, error: %s\n",
1297
 
            frmival->index,
1298
 
            dest_pixfmt & 0xff,
1299
 
            (dest_pixfmt >> 8) & 0xff,
1300
 
            (dest_pixfmt >> 16) & 0xff,
1301
 
            dest_pixfmt >> 24,
1302
 
            dest_fmt.fmt.pix.width , dest_fmt.fmt.pix.height,
1303
 
            src_pixfmt & 0xff,
1304
 
            (src_pixfmt >> 8) & 0xff,
1305
 
            (src_pixfmt >> 16) & 0xff,
1306
 
            src_pixfmt >> 24,
1307
 
            src_fmt.fmt.pix.width, src_fmt.fmt.pix.height, strerror(errno));
1308
 
  }
1309
 
 
1310
 
  /* Restore the requested format in the frmival struct */
1311
 
  frmival->pixel_format = dest_fmt.fmt.pix.pixelformat;
1312
 
  frmival->width = dest_fmt.fmt.pix.width;
1313
 
  frmival->height = dest_fmt.fmt.pix.height;
1314
 
 
1315
 
  return res;
1316
 
}
1317
 
 
1318
 
int v4lconvert_vidioc_queryctrl(struct v4lconvert_data *data, void *arg) {
1319
 
  return v4lcontrol_vidioc_queryctrl(data->control, arg);
1320
 
}
1321
 
 
1322
 
int v4lconvert_vidioc_g_ctrl(struct v4lconvert_data *data, void *arg) {
1323
 
  return v4lcontrol_vidioc_g_ctrl(data->control, arg);
1324
 
}
1325
 
 
1326
 
int v4lconvert_vidioc_s_ctrl(struct v4lconvert_data *data, void *arg){
1327
 
  return v4lcontrol_vidioc_s_ctrl(data->control, arg);
 
1237
                struct v4l2_frmivalenum *frmival)
 
1238
{
 
1239
        int res;
 
1240
        struct v4l2_format src_fmt, dest_fmt;
 
1241
 
 
1242
        if (!v4lconvert_supported_dst_format(frmival->pixel_format)) {
 
1243
                if (v4lconvert_supported_dst_fmt_only(data)) {
 
1244
                        errno = EINVAL;
 
1245
                        return -1;
 
1246
                }
 
1247
                res = SYS_IOCTL(data->fd, VIDIOC_ENUM_FRAMEINTERVALS, frmival);
 
1248
                if (res)
 
1249
                        V4LCONVERT_ERR("%s\n", strerror(errno));
 
1250
                return res;
 
1251
        }
 
1252
 
 
1253
        /* Check which format we will be using to convert to frmival->pixel_format */
 
1254
        memset(&dest_fmt, 0, sizeof(dest_fmt));
 
1255
        dest_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
1256
        dest_fmt.fmt.pix.pixelformat = frmival->pixel_format;
 
1257
        dest_fmt.fmt.pix.width = frmival->width;
 
1258
        dest_fmt.fmt.pix.height = frmival->height;
 
1259
        res = v4lconvert_try_format(data, &dest_fmt, &src_fmt);
 
1260
        if (res) {
 
1261
                V4LCONVERT_ERR("trying format: %s\n", strerror(errno));
 
1262
                return res;
 
1263
        }
 
1264
 
 
1265
        /* Check the requested format is supported exactly as requested */
 
1266
        if (dest_fmt.fmt.pix.pixelformat != frmival->pixel_format ||
 
1267
                        dest_fmt.fmt.pix.width  != frmival->width ||
 
1268
                        dest_fmt.fmt.pix.height != frmival->height) {
 
1269
                int frmival_pixformat = frmival->pixel_format;
 
1270
                int dest_pixformat = dest_fmt.fmt.pix.pixelformat;
 
1271
 
 
1272
                V4LCONVERT_ERR("Could not find matching framesize for: %c%c%c%c %dx%d "
 
1273
                                "closest match: %c%c%c%c %dx%d\n",
 
1274
                                frmival_pixformat & 0xff,
 
1275
                                (frmival_pixformat >> 8) & 0xff,
 
1276
                                (frmival_pixformat >> 16) & 0xff,
 
1277
                                frmival_pixformat >> 24,
 
1278
                                frmival->width, frmival->height,
 
1279
                                dest_pixformat & 0xff,
 
1280
                                (dest_pixformat >> 8) & 0xff,
 
1281
                                (dest_pixformat >> 16) & 0xff,
 
1282
                                dest_pixformat >> 24,
 
1283
                                dest_fmt.fmt.pix.width , dest_fmt.fmt.pix.height);
 
1284
                errno = EINVAL;
 
1285
                return -1;
 
1286
        }
 
1287
 
 
1288
        /* Enumerate the frameintervals of the source format we will be using */
 
1289
        frmival->pixel_format = src_fmt.fmt.pix.pixelformat;
 
1290
        frmival->width = src_fmt.fmt.pix.width;
 
1291
        frmival->height = src_fmt.fmt.pix.height;
 
1292
        res = SYS_IOCTL(data->fd, VIDIOC_ENUM_FRAMEINTERVALS, frmival);
 
1293
        if (res) {
 
1294
                int dest_pixfmt = dest_fmt.fmt.pix.pixelformat;
 
1295
                int src_pixfmt  = src_fmt.fmt.pix.pixelformat;
 
1296
 
 
1297
                V4LCONVERT_ERR("Could not enum frameival index: %d for: %c%c%c%c %dx%d "
 
1298
                                "using src: %c%c%c%c %dx%d, error: %s\n",
 
1299
                                frmival->index,
 
1300
                                dest_pixfmt & 0xff,
 
1301
                                (dest_pixfmt >> 8) & 0xff,
 
1302
                                (dest_pixfmt >> 16) & 0xff,
 
1303
                                dest_pixfmt >> 24,
 
1304
                                dest_fmt.fmt.pix.width , dest_fmt.fmt.pix.height,
 
1305
                                src_pixfmt & 0xff,
 
1306
                                (src_pixfmt >> 8) & 0xff,
 
1307
                                (src_pixfmt >> 16) & 0xff,
 
1308
                                src_pixfmt >> 24,
 
1309
                                src_fmt.fmt.pix.width, src_fmt.fmt.pix.height, strerror(errno));
 
1310
        }
 
1311
 
 
1312
        /* Restore the requested format in the frmival struct */
 
1313
        frmival->pixel_format = dest_fmt.fmt.pix.pixelformat;
 
1314
        frmival->width = dest_fmt.fmt.pix.width;
 
1315
        frmival->height = dest_fmt.fmt.pix.height;
 
1316
 
 
1317
        return res;
 
1318
}
 
1319
 
 
1320
int v4lconvert_vidioc_queryctrl(struct v4lconvert_data *data, void *arg)
 
1321
{
 
1322
        return v4lcontrol_vidioc_queryctrl(data->control, arg);
 
1323
}
 
1324
 
 
1325
int v4lconvert_vidioc_g_ctrl(struct v4lconvert_data *data, void *arg)
 
1326
{
 
1327
        return v4lcontrol_vidioc_g_ctrl(data->control, arg);
 
1328
}
 
1329
 
 
1330
int v4lconvert_vidioc_s_ctrl(struct v4lconvert_data *data, void *arg)
 
1331
{
 
1332
        return v4lcontrol_vidioc_s_ctrl(data->control, arg);
1328
1333
}