123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) STMicroelectronics SA 2013
- * Author: Hugues Fruchet <hugues.fruchet@st.com> for STMicroelectronics.
- */
- #include "delta.h"
- #include "delta-mjpeg.h"
- #define MJPEG_SOF_0 0xc0
- #define MJPEG_SOF_1 0xc1
- #define MJPEG_SOI 0xd8
- #define MJPEG_MARKER 0xff
- static char *header_str(struct mjpeg_header *header,
- char *str,
- unsigned int len)
- {
- char *cur = str;
- unsigned int left = len;
- if (!header)
- return "";
- snprintf(cur, left, "[MJPEG header]\n"
- "|- length = %d\n"
- "|- precision = %d\n"
- "|- width = %d\n"
- "|- height = %d\n"
- "|- components = %d\n",
- header->length,
- header->sample_precision,
- header->frame_width,
- header->frame_height,
- header->nb_of_components);
- return str;
- }
- static int delta_mjpeg_read_sof(struct delta_ctx *pctx,
- unsigned char *data, unsigned int size,
- struct mjpeg_header *header)
- {
- struct delta_dev *delta = pctx->dev;
- unsigned int offset = 0;
- if (size < 64)
- goto err_no_more;
- memset(header, 0, sizeof(*header));
- header->length = be16_to_cpu(*(__be16 *)(data + offset));
- offset += sizeof(u16);
- header->sample_precision = *(u8 *)(data + offset);
- offset += sizeof(u8);
- header->frame_height = be16_to_cpu(*(__be16 *)(data + offset));
- offset += sizeof(u16);
- header->frame_width = be16_to_cpu(*(__be16 *)(data + offset));
- offset += sizeof(u16);
- header->nb_of_components = *(u8 *)(data + offset);
- offset += sizeof(u8);
- if (header->nb_of_components >= MJPEG_MAX_COMPONENTS) {
- dev_err(delta->dev,
- "%s unsupported number of components (%d > %d)\n",
- pctx->name, header->nb_of_components,
- MJPEG_MAX_COMPONENTS);
- return -EINVAL;
- }
- if ((offset + header->nb_of_components *
- sizeof(header->components[0])) > size)
- goto err_no_more;
- return 0;
- err_no_more:
- dev_err(delta->dev,
- "%s sof: reached end of %d size input stream\n",
- pctx->name, size);
- return -ENODATA;
- }
- int delta_mjpeg_read_header(struct delta_ctx *pctx,
- unsigned char *data, unsigned int size,
- struct mjpeg_header *header,
- unsigned int *data_offset)
- {
- struct delta_dev *delta = pctx->dev;
- unsigned char str[200];
- unsigned int ret = 0;
- unsigned int offset = 0;
- unsigned int soi = 0;
- if (size < 2)
- goto err_no_more;
- offset = 0;
- while (1) {
- if (data[offset] == MJPEG_MARKER)
- switch (data[offset + 1]) {
- case MJPEG_SOI:
- soi = 1;
- *data_offset = offset;
- break;
- case MJPEG_SOF_0:
- case MJPEG_SOF_1:
- if (!soi) {
- dev_err(delta->dev,
- "%s wrong sequence, got SOF while SOI not seen\n",
- pctx->name);
- return -EINVAL;
- }
- ret = delta_mjpeg_read_sof(pctx,
- &data[offset + 2],
- size - (offset + 2),
- header);
- if (ret)
- goto err;
- goto done;
- default:
- break;
- }
- offset++;
- if ((offset + 2) >= size)
- goto err_no_more;
- }
- done:
- dev_dbg(delta->dev,
- "%s found header @ offset %d:\n%s", pctx->name,
- *data_offset,
- header_str(header, str, sizeof(str)));
- return 0;
- err_no_more:
- dev_err(delta->dev,
- "%s no header found within %d bytes input stream\n",
- pctx->name, size);
- return -ENODATA;
- err:
- return ret;
- }
|