1
0

video-frame.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /******************************************************************************
  2. Copyright (C) 2013 by Hugh Bailey <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. #include "video-frame.h"
  15. #define ALIGN_SIZE(size, align) size = (((size) + (align - 1)) & (~(align - 1)))
  16. /* messy code alarm */
  17. void video_frame_init(struct video_frame *frame, enum video_format format,
  18. uint32_t width, uint32_t height)
  19. {
  20. size_t size;
  21. size_t offsets[MAX_AV_PLANES];
  22. int alignment = base_get_alignment();
  23. if (!frame)
  24. return;
  25. memset(frame, 0, sizeof(struct video_frame));
  26. memset(offsets, 0, sizeof(offsets));
  27. switch (format) {
  28. case VIDEO_FORMAT_NONE:
  29. return;
  30. case VIDEO_FORMAT_I420: {
  31. size = width * height;
  32. ALIGN_SIZE(size, alignment);
  33. offsets[0] = size;
  34. const uint32_t half_width = (width + 1) / 2;
  35. const uint32_t half_height = (height + 1) / 2;
  36. const uint32_t quarter_area = half_width * half_height;
  37. size += quarter_area;
  38. ALIGN_SIZE(size, alignment);
  39. offsets[1] = size;
  40. size += quarter_area;
  41. ALIGN_SIZE(size, alignment);
  42. frame->data[0] = bmalloc(size);
  43. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  44. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  45. frame->linesize[0] = width;
  46. frame->linesize[1] = half_width;
  47. frame->linesize[2] = half_width;
  48. break;
  49. }
  50. case VIDEO_FORMAT_NV12: {
  51. size = width * height;
  52. ALIGN_SIZE(size, alignment);
  53. offsets[0] = size;
  54. const uint32_t cbcr_width = (width + 1) & (UINT32_MAX - 1);
  55. size += cbcr_width * ((height + 1) / 2);
  56. ALIGN_SIZE(size, alignment);
  57. frame->data[0] = bmalloc(size);
  58. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  59. frame->linesize[0] = width;
  60. frame->linesize[1] = cbcr_width;
  61. break;
  62. }
  63. case VIDEO_FORMAT_Y800:
  64. size = width * height;
  65. ALIGN_SIZE(size, alignment);
  66. frame->data[0] = bmalloc(size);
  67. frame->linesize[0] = width;
  68. break;
  69. case VIDEO_FORMAT_YVYU:
  70. case VIDEO_FORMAT_YUY2:
  71. case VIDEO_FORMAT_UYVY: {
  72. const uint32_t double_width =
  73. ((width + 1) & (UINT32_MAX - 1)) * 2;
  74. size = double_width * height;
  75. ALIGN_SIZE(size, alignment);
  76. frame->data[0] = bmalloc(size);
  77. frame->linesize[0] = double_width;
  78. break;
  79. }
  80. case VIDEO_FORMAT_RGBA:
  81. case VIDEO_FORMAT_BGRA:
  82. case VIDEO_FORMAT_BGRX:
  83. case VIDEO_FORMAT_AYUV:
  84. size = width * height * 4;
  85. ALIGN_SIZE(size, alignment);
  86. frame->data[0] = bmalloc(size);
  87. frame->linesize[0] = width * 4;
  88. break;
  89. case VIDEO_FORMAT_I444:
  90. size = width * height;
  91. ALIGN_SIZE(size, alignment);
  92. frame->data[0] = bmalloc(size * 3);
  93. frame->data[1] = (uint8_t *)frame->data[0] + size;
  94. frame->data[2] = (uint8_t *)frame->data[1] + size;
  95. frame->linesize[0] = width;
  96. frame->linesize[1] = width;
  97. frame->linesize[2] = width;
  98. break;
  99. case VIDEO_FORMAT_BGR3:
  100. size = width * height * 3;
  101. ALIGN_SIZE(size, alignment);
  102. frame->data[0] = bmalloc(size);
  103. frame->linesize[0] = width * 3;
  104. break;
  105. case VIDEO_FORMAT_I422: {
  106. size = width * height;
  107. ALIGN_SIZE(size, alignment);
  108. offsets[0] = size;
  109. const uint32_t half_width = (width + 1) / 2;
  110. const uint32_t half_area = half_width * height;
  111. size += half_area;
  112. ALIGN_SIZE(size, alignment);
  113. offsets[1] = size;
  114. size += half_area;
  115. ALIGN_SIZE(size, alignment);
  116. frame->data[0] = bmalloc(size);
  117. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  118. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  119. frame->linesize[0] = width;
  120. frame->linesize[1] = half_width;
  121. frame->linesize[2] = half_width;
  122. break;
  123. }
  124. case VIDEO_FORMAT_I40A: {
  125. size = width * height;
  126. ALIGN_SIZE(size, alignment);
  127. offsets[0] = size;
  128. const uint32_t half_width = (width + 1) / 2;
  129. const uint32_t half_height = (height + 1) / 2;
  130. const uint32_t quarter_area = half_width * half_height;
  131. size += quarter_area;
  132. ALIGN_SIZE(size, alignment);
  133. offsets[1] = size;
  134. size += quarter_area;
  135. ALIGN_SIZE(size, alignment);
  136. offsets[2] = size;
  137. size += width * height;
  138. ALIGN_SIZE(size, alignment);
  139. frame->data[0] = bmalloc(size);
  140. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  141. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  142. frame->data[3] = (uint8_t *)frame->data[0] + offsets[2];
  143. frame->linesize[0] = width;
  144. frame->linesize[1] = half_width;
  145. frame->linesize[2] = half_width;
  146. frame->linesize[3] = width;
  147. break;
  148. }
  149. case VIDEO_FORMAT_I42A: {
  150. size = width * height;
  151. ALIGN_SIZE(size, alignment);
  152. offsets[0] = size;
  153. const uint32_t half_width = (width + 1) / 2;
  154. const uint32_t half_area = half_width * height;
  155. size += half_area;
  156. ALIGN_SIZE(size, alignment);
  157. offsets[1] = size;
  158. size += half_area;
  159. ALIGN_SIZE(size, alignment);
  160. offsets[2] = size;
  161. size += width * height;
  162. ALIGN_SIZE(size, alignment);
  163. frame->data[0] = bmalloc(size);
  164. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  165. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  166. frame->data[3] = (uint8_t *)frame->data[0] + offsets[2];
  167. frame->linesize[0] = width;
  168. frame->linesize[1] = half_width;
  169. frame->linesize[2] = half_width;
  170. frame->linesize[3] = width;
  171. break;
  172. }
  173. case VIDEO_FORMAT_YUVA:
  174. size = width * height;
  175. ALIGN_SIZE(size, alignment);
  176. offsets[0] = size;
  177. size += width * height;
  178. ALIGN_SIZE(size, alignment);
  179. offsets[1] = size;
  180. size += width * height;
  181. ALIGN_SIZE(size, alignment);
  182. offsets[2] = size;
  183. size += width * height;
  184. ALIGN_SIZE(size, alignment);
  185. frame->data[0] = bmalloc(size);
  186. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  187. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  188. frame->data[3] = (uint8_t *)frame->data[0] + offsets[2];
  189. frame->linesize[0] = width;
  190. frame->linesize[1] = width;
  191. frame->linesize[2] = width;
  192. frame->linesize[3] = width;
  193. break;
  194. }
  195. }
  196. void video_frame_copy(struct video_frame *dst, const struct video_frame *src,
  197. enum video_format format, uint32_t cy)
  198. {
  199. switch (format) {
  200. case VIDEO_FORMAT_NONE:
  201. return;
  202. case VIDEO_FORMAT_I420:
  203. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  204. memcpy(dst->data[1], src->data[1], src->linesize[1] * cy / 2);
  205. memcpy(dst->data[2], src->data[2], src->linesize[2] * cy / 2);
  206. break;
  207. case VIDEO_FORMAT_NV12:
  208. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  209. memcpy(dst->data[1], src->data[1], src->linesize[1] * cy / 2);
  210. break;
  211. case VIDEO_FORMAT_Y800:
  212. case VIDEO_FORMAT_YVYU:
  213. case VIDEO_FORMAT_YUY2:
  214. case VIDEO_FORMAT_UYVY:
  215. case VIDEO_FORMAT_RGBA:
  216. case VIDEO_FORMAT_BGRA:
  217. case VIDEO_FORMAT_BGRX:
  218. case VIDEO_FORMAT_BGR3:
  219. case VIDEO_FORMAT_AYUV:
  220. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  221. break;
  222. case VIDEO_FORMAT_I444:
  223. case VIDEO_FORMAT_I422:
  224. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  225. memcpy(dst->data[1], src->data[1], src->linesize[1] * cy);
  226. memcpy(dst->data[2], src->data[2], src->linesize[2] * cy);
  227. break;
  228. case VIDEO_FORMAT_I40A:
  229. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  230. memcpy(dst->data[1], src->data[1], src->linesize[1] * cy / 2);
  231. memcpy(dst->data[2], src->data[2], src->linesize[2] * cy / 2);
  232. memcpy(dst->data[3], src->data[3], src->linesize[3] * cy);
  233. break;
  234. case VIDEO_FORMAT_I42A:
  235. case VIDEO_FORMAT_YUVA:
  236. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  237. memcpy(dst->data[1], src->data[1], src->linesize[1] * cy);
  238. memcpy(dst->data[2], src->data[2], src->linesize[2] * cy);
  239. memcpy(dst->data[3], src->data[3], src->linesize[3] * cy);
  240. break;
  241. }
  242. }