# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
+ */
#include "libv4lconvert-priv.h"
#include <string.h>
/* CPIA YUYV (sometimes sort of compressed) */
int v4lconvert_cpia1_to_yuv420(struct v4lconvert_data *data,
- const unsigned char *src, int src_size,
- unsigned char *dest, int width, int height, int yvu)
+ const unsigned char *src, int src_size,
+ unsigned char *dest, int width, int height, int yvu)
{
- int x, y, ll, compressed;
- unsigned char *udest, *vdest;
-
- if (width > 352 || height > 288) {
- fprintf(stderr, "FATAL ERROR CPIA1 size > 352x288, please report!\n");
- return -1;
- }
-
- if (data->previous_frame == NULL) {
- data->previous_frame = malloc(352 * 288 * 3 / 2);
- if (data->previous_frame == NULL) {
- fprintf(stderr, "cpia1 decode error: could not allocate buffer!\n");
- return -1;
- }
- }
-
- if (yvu) {
- vdest = dest + width * height;
- udest = vdest + width * height / 4;
- } else {
- udest = dest + width * height;
- vdest = udest + width * height / 4;
- }
-
- /* Verify header */
- if (src_size < FRAME_HEADER_SIZE ||
- src[0] != MAGIC_0 || src[1] != MAGIC_1 ||
- src[17] != SUBSAMPLE_420 ||
- src[18] != YUVORDER_YUYV ||
- (src[25] - src[24]) * 8 != width ||
- (src[27] - src[26]) * 4 != height ||
- (src[28] != NOT_COMPRESSED && src[28] != COMPRESSED) ||
- (src[29] != NO_DECIMATION && src[29] != DECIMATION_ENAB)) {
- fprintf(stderr, "cpia1 decode error: invalid header\n");
- return -1;
- }
-
- if (src[29] == DECIMATION_ENAB) {
- fprintf(stderr, "cpia1 decode error: decimation is not supported\n");
- return -1;
- }
-
- compressed = src[28] == COMPRESSED;
-
- src += FRAME_HEADER_SIZE;
- src_size -= FRAME_HEADER_SIZE;
-
- if (!compressed) {
- for (y = 0; y < height && src_size > 2; y++) {
- ll = src[0] | (src[1] << 8);
- src += 2;
- src_size -= 2;
- if (src_size < ll) {
- fprintf(stderr, "cpia1 decode error: short frame\n");
- return -1;
- }
- if (src[ll - 1] != EOL) {
- fprintf(stderr, "cpia1 decode error: invalid terminated line\n");
- return -1;
- }
-
- if (!(y & 1)) { /* Even line Y + UV in the form of YUYV */
- if (ll != 2 * width + 1) {
- fprintf(stderr, "cpia1 decode error: invalid uncompressed even ll\n");
- return -1;
+ int x, y, ll, compressed;
+ unsigned char *udest, *vdest;
+
+ if (width > 352 || height > 288) {
+ fprintf(stderr, "FATAL ERROR CPIA1 size > 352x288, please report!\n");
+ return -1;
+ }
+
+ if (data->previous_frame == NULL) {
+ data->previous_frame = malloc(352 * 288 * 3 / 2);
+ if (data->previous_frame == NULL) {
+ fprintf(stderr, "cpia1 decode error: could not allocate buffer!\n");
+ return -1;
+ }
}
- /* copy the Y values */
- for (x = 0; x < width; x += 2) {
- *dest++ = src[0];
- *dest++ = src[2];
- src += 4;
+ if (yvu) {
+ vdest = dest + width * height;
+ udest = vdest + width * height / 4;
+ } else {
+ udest = dest + width * height;
+ vdest = udest + width * height / 4;
}
- /* copy the UV values */
- src -= 2 * width;
- for (x = 0; x < width; x += 2) {
- *udest++ = src[1];
- *vdest++ = src[3];
- src += 4;
+ /* Verify header */
+ if (src_size < FRAME_HEADER_SIZE ||
+ src[0] != MAGIC_0 || src[1] != MAGIC_1 ||
+ src[17] != SUBSAMPLE_420 ||
+ src[18] != YUVORDER_YUYV ||
+ (src[25] - src[24]) * 8 != width ||
+ (src[27] - src[26]) * 4 != height ||
+ (src[28] != NOT_COMPRESSED && src[28] != COMPRESSED) ||
+ (src[29] != NO_DECIMATION && src[29] != DECIMATION_ENAB)) {
+ fprintf(stderr, "cpia1 decode error: invalid header\n");
+ return -1;
}
- } else { /* Odd line only Y values */
- if (ll != width + 1) {
- fprintf(stderr, "cpia1 decode error: invalid uncompressed odd ll\n");
- return -1;
+
+ if (src[29] == DECIMATION_ENAB) {
+ fprintf(stderr, "cpia1 decode error: decimation is not supported\n");
+ return -1;
}
- memcpy(dest, src, width);
- dest += width;
- src += width;
- }
- src++; /* Skip EOL */
- src_size -= ll;
- }
- } else { /* compressed */
- int ydest_index, uvdest_index;
-
- /* Pre-fill dest with previous frame, as the cpia1 "compression" consists
- of simply ommitting certain pixels */
- memcpy(dest, data->previous_frame, width * height * 3 / 2);
-
- for (y = 0; y < height && src_size > 2; y++) {
- ll = src[0] | (src[1] << 8);
- src += 2;
- src_size -= 2;
- if (src_size < ll) {
- fprintf(stderr, "cpia1 decode error: short frame\n");
- return -1;
- }
- if (src[ll - 1] != EOL) {
- fprintf(stderr, "cpia1 decode error: invalid terminated line\n");
- return -1;
- }
-
- /* Do this now as we use ll as loop variable below */
- src_size -= ll;
- for (x = 0; x < width && ll > 1; ) {
- if (*src & 1) { /* skip N pixels */
- int skip = *src >> 1;
-
- if (skip & 1) {
- fprintf(stderr,
- "cpia1 decode error: odd number of pixels to skip");
- return -1;
- }
-
- if (!(y & 1)) { /* Even line Y + UV in the form of YUYV */
- dest += skip;
- udest += skip / 2;
- vdest += skip / 2;
- } else { /* Odd line only Y values */
- dest += skip;
- }
- x += skip;
- src++;
- ll--;
- } else {
- if (!(y & 1)) { /* Even line Y + UV in the form of YUYV */
- *dest++ = *src++;
- *udest++ = *src++;
- *dest++ = *src++;
- *vdest++ = *src++;
- ll -= 4;
- } else { /* Odd line only Y values */
- *dest++ = *src++;
- *dest++ = *src++;
- ll -= 2;
- }
- x += 2;
+ compressed = src[28] == COMPRESSED;
+
+ src += FRAME_HEADER_SIZE;
+ src_size -= FRAME_HEADER_SIZE;
+
+ if (!compressed) {
+ for (y = 0; y < height && src_size > 2; y++) {
+ ll = src[0] | (src[1] << 8);
+ src += 2;
+ src_size -= 2;
+ if (src_size < ll) {
+ fprintf(stderr, "cpia1 decode error: short frame\n");
+ return -1;
+ }
+ if (src[ll - 1] != EOL) {
+ fprintf(stderr, "cpia1 decode error: invalid terminated line\n");
+ return -1;
+ }
+
+ if (!(y & 1)) { /* Even line Y + UV in the form of YUYV */
+ if (ll != 2 * width + 1) {
+ fprintf(stderr, "cpia1 decode error: invalid uncompressed even ll\n");
+ return -1;
+ }
+
+ /* copy the Y values */
+ for (x = 0; x < width; x += 2) {
+ *dest++ = src[0];
+ *dest++ = src[2];
+ src += 4;
+ }
+
+ /* copy the UV values */
+ src -= 2 * width;
+ for (x = 0; x < width; x += 2) {
+ *udest++ = src[1];
+ *vdest++ = src[3];
+ src += 4;
+ }
+ } else { /* Odd line only Y values */
+ if (ll != width + 1) {
+ fprintf(stderr, "cpia1 decode error: invalid uncompressed odd ll\n");
+ return -1;
+ }
+
+ memcpy(dest, src, width);
+ dest += width;
+ src += width;
+ }
+ src++; /* Skip EOL */
+ src_size -= ll;
+ }
+ } else { /* compressed */
+ /* Pre-fill dest with previous frame, as the cpia1 "compression" consists
+ of simply ommitting certain pixels */
+ memcpy(dest, data->previous_frame, width * height * 3 / 2);
+
+ for (y = 0; y < height && src_size > 2; y++) {
+ ll = src[0] | (src[1] << 8);
+ src += 2;
+ src_size -= 2;
+ if (src_size < ll) {
+ fprintf(stderr, "cpia1 decode error: short frame\n");
+ return -1;
+ }
+ if (src[ll - 1] != EOL) {
+ fprintf(stderr, "cpia1 decode error: invalid terminated line\n");
+ return -1;
+ }
+
+ /* Do this now as we use ll as loop variable below */
+ src_size -= ll;
+ for (x = 0; x < width && ll > 1; ) {
+ if (*src & 1) { /* skip N pixels */
+ int skip = *src >> 1;
+
+ if (skip & 1) {
+ fprintf(stderr, "cpia1 decode error: odd number of pixels to skip");
+ return -1;
+ }
+
+ if (!(y & 1)) { /* Even line Y + UV in the form of YUYV */
+ dest += skip;
+ udest += skip / 2;
+ vdest += skip / 2;
+ } else { /* Odd line only Y values */
+ dest += skip;
+ }
+ x += skip;
+ src++;
+ ll--;
+ } else {
+ if (!(y & 1)) { /* Even line Y + UV in the form of YUYV */
+ *dest++ = *src++;
+ *udest++ = *src++;
+ *dest++ = *src++;
+ *vdest++ = *src++;
+ ll -= 4;
+ } else { /* Odd line only Y values */
+ *dest++ = *src++;
+ *dest++ = *src++;
+ ll -= 2;
+ }
+ x += 2;
+ }
+ }
+ if (ll != 1 || x != width) {
+ fprintf(stderr, "cpia1 decode error: line length mismatch\n");
+ return -1;
+ }
+ src++; /* Skip EOL */
+ }
}
- }
- if (ll != 1 || x != width) {
- fprintf(stderr, "cpia1 decode error: line length mismatch\n");
- return -1;
- }
- src++; /* Skip EOL */
- }
- }
-
- if (y != height) {
- fprintf(stderr, "cpia1 decode error: frame height mismatch\n");
- return -1;
- }
-
- if (src_size < 4 ||
- src[src_size - 4] != EOI || src[src_size - 3] != EOI ||
- src[src_size - 2] != EOI || src[src_size - 1] != EOI) {
- fprintf(stderr, "cpia1 decode error: invaled EOI marker\n");
- return -1;
- }
-
- /* Safe frame for decompression of the next frame */
- dest -= width * height;
- memcpy(data->previous_frame, dest, width * height * 3 / 2);
-
- return 0;
+
+ if (y != height) {
+ fprintf(stderr, "cpia1 decode error: frame height mismatch\n");
+ return -1;
+ }
+
+ if (src_size < 4 || src[src_size - 4] != EOI || src[src_size - 3] != EOI ||
+ src[src_size - 2] != EOI || src[src_size - 1] != EOI) {
+ fprintf(stderr, "cpia1 decode error: invaled EOI marker\n");
+ return -1;
+ }
+
+ /* Safe frame for decompression of the next frame */
+ dest -= width * height;
+ memcpy(data->previous_frame, dest, width * height * 3 / 2);
+
+ return 0;
}