delta-mjpeg-hdr.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) STMicroelectronics SA 2013
  4. * Author: Hugues Fruchet <hugues.fruchet@st.com> for STMicroelectronics.
  5. */
  6. #include "delta.h"
  7. #include "delta-mjpeg.h"
  8. #define MJPEG_SOF_0 0xc0
  9. #define MJPEG_SOF_1 0xc1
  10. #define MJPEG_SOI 0xd8
  11. #define MJPEG_MARKER 0xff
  12. static char *header_str(struct mjpeg_header *header,
  13. char *str,
  14. unsigned int len)
  15. {
  16. char *cur = str;
  17. unsigned int left = len;
  18. if (!header)
  19. return "";
  20. snprintf(cur, left, "[MJPEG header]\n"
  21. "|- length = %d\n"
  22. "|- precision = %d\n"
  23. "|- width = %d\n"
  24. "|- height = %d\n"
  25. "|- components = %d\n",
  26. header->length,
  27. header->sample_precision,
  28. header->frame_width,
  29. header->frame_height,
  30. header->nb_of_components);
  31. return str;
  32. }
  33. static int delta_mjpeg_read_sof(struct delta_ctx *pctx,
  34. unsigned char *data, unsigned int size,
  35. struct mjpeg_header *header)
  36. {
  37. struct delta_dev *delta = pctx->dev;
  38. unsigned int offset = 0;
  39. if (size < 64)
  40. goto err_no_more;
  41. memset(header, 0, sizeof(*header));
  42. header->length = be16_to_cpu(*(__be16 *)(data + offset));
  43. offset += sizeof(u16);
  44. header->sample_precision = *(u8 *)(data + offset);
  45. offset += sizeof(u8);
  46. header->frame_height = be16_to_cpu(*(__be16 *)(data + offset));
  47. offset += sizeof(u16);
  48. header->frame_width = be16_to_cpu(*(__be16 *)(data + offset));
  49. offset += sizeof(u16);
  50. header->nb_of_components = *(u8 *)(data + offset);
  51. offset += sizeof(u8);
  52. if (header->nb_of_components >= MJPEG_MAX_COMPONENTS) {
  53. dev_err(delta->dev,
  54. "%s unsupported number of components (%d > %d)\n",
  55. pctx->name, header->nb_of_components,
  56. MJPEG_MAX_COMPONENTS);
  57. return -EINVAL;
  58. }
  59. if ((offset + header->nb_of_components *
  60. sizeof(header->components[0])) > size)
  61. goto err_no_more;
  62. return 0;
  63. err_no_more:
  64. dev_err(delta->dev,
  65. "%s sof: reached end of %d size input stream\n",
  66. pctx->name, size);
  67. return -ENODATA;
  68. }
  69. int delta_mjpeg_read_header(struct delta_ctx *pctx,
  70. unsigned char *data, unsigned int size,
  71. struct mjpeg_header *header,
  72. unsigned int *data_offset)
  73. {
  74. struct delta_dev *delta = pctx->dev;
  75. unsigned char str[200];
  76. unsigned int ret = 0;
  77. unsigned int offset = 0;
  78. unsigned int soi = 0;
  79. if (size < 2)
  80. goto err_no_more;
  81. offset = 0;
  82. while (1) {
  83. if (data[offset] == MJPEG_MARKER)
  84. switch (data[offset + 1]) {
  85. case MJPEG_SOI:
  86. soi = 1;
  87. *data_offset = offset;
  88. break;
  89. case MJPEG_SOF_0:
  90. case MJPEG_SOF_1:
  91. if (!soi) {
  92. dev_err(delta->dev,
  93. "%s wrong sequence, got SOF while SOI not seen\n",
  94. pctx->name);
  95. return -EINVAL;
  96. }
  97. ret = delta_mjpeg_read_sof(pctx,
  98. &data[offset + 2],
  99. size - (offset + 2),
  100. header);
  101. if (ret)
  102. goto err;
  103. goto done;
  104. default:
  105. break;
  106. }
  107. offset++;
  108. if ((offset + 2) >= size)
  109. goto err_no_more;
  110. }
  111. done:
  112. dev_dbg(delta->dev,
  113. "%s found header @ offset %d:\n%s", pctx->name,
  114. *data_offset,
  115. header_str(header, str, sizeof(str)));
  116. return 0;
  117. err_no_more:
  118. dev_err(delta->dev,
  119. "%s no header found within %d bytes input stream\n",
  120. pctx->name, size);
  121. return -ENODATA;
  122. err:
  123. return ret;
  124. }