1
0

video-frame.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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_I412:
  100. size = width * height * 2;
  101. ALIGN_SIZE(size, alignment);
  102. frame->data[0] = bmalloc(size * 3);
  103. frame->data[1] = (uint8_t *)frame->data[0] + size;
  104. frame->data[2] = (uint8_t *)frame->data[1] + size;
  105. frame->linesize[0] = width * 2;
  106. frame->linesize[1] = width * 2;
  107. frame->linesize[2] = width * 2;
  108. break;
  109. case VIDEO_FORMAT_BGR3:
  110. size = width * height * 3;
  111. ALIGN_SIZE(size, alignment);
  112. frame->data[0] = bmalloc(size);
  113. frame->linesize[0] = width * 3;
  114. break;
  115. case VIDEO_FORMAT_I422: {
  116. size = width * height;
  117. ALIGN_SIZE(size, alignment);
  118. offsets[0] = size;
  119. const uint32_t half_width = (width + 1) / 2;
  120. const uint32_t half_area = half_width * height;
  121. size += half_area;
  122. ALIGN_SIZE(size, alignment);
  123. offsets[1] = size;
  124. size += half_area;
  125. ALIGN_SIZE(size, alignment);
  126. frame->data[0] = bmalloc(size);
  127. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  128. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  129. frame->linesize[0] = width;
  130. frame->linesize[1] = half_width;
  131. frame->linesize[2] = half_width;
  132. break;
  133. }
  134. case VIDEO_FORMAT_I210: {
  135. size = width * height * 2;
  136. ALIGN_SIZE(size, alignment);
  137. offsets[0] = size;
  138. const uint32_t half_width = (width + 1) / 2;
  139. const uint32_t half_area = half_width * height;
  140. const uint32_t half_area_size = 2 * half_area;
  141. size += half_area_size;
  142. ALIGN_SIZE(size, alignment);
  143. offsets[1] = size;
  144. size += half_area_size;
  145. ALIGN_SIZE(size, alignment);
  146. frame->data[0] = bmalloc(size);
  147. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  148. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  149. frame->linesize[0] = width * 2;
  150. frame->linesize[1] = half_width * 2;
  151. frame->linesize[2] = half_width * 2;
  152. break;
  153. }
  154. case VIDEO_FORMAT_I40A: {
  155. size = width * height;
  156. ALIGN_SIZE(size, alignment);
  157. offsets[0] = size;
  158. const uint32_t half_width = (width + 1) / 2;
  159. const uint32_t half_height = (height + 1) / 2;
  160. const uint32_t quarter_area = half_width * half_height;
  161. size += quarter_area;
  162. ALIGN_SIZE(size, alignment);
  163. offsets[1] = size;
  164. size += quarter_area;
  165. ALIGN_SIZE(size, alignment);
  166. offsets[2] = size;
  167. size += width * height;
  168. ALIGN_SIZE(size, alignment);
  169. frame->data[0] = bmalloc(size);
  170. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  171. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  172. frame->data[3] = (uint8_t *)frame->data[0] + offsets[2];
  173. frame->linesize[0] = width;
  174. frame->linesize[1] = half_width;
  175. frame->linesize[2] = half_width;
  176. frame->linesize[3] = width;
  177. break;
  178. }
  179. case VIDEO_FORMAT_I42A: {
  180. size = width * height;
  181. ALIGN_SIZE(size, alignment);
  182. offsets[0] = size;
  183. const uint32_t half_width = (width + 1) / 2;
  184. const uint32_t half_area = half_width * height;
  185. size += half_area;
  186. ALIGN_SIZE(size, alignment);
  187. offsets[1] = size;
  188. size += half_area;
  189. ALIGN_SIZE(size, alignment);
  190. offsets[2] = size;
  191. size += width * height;
  192. ALIGN_SIZE(size, alignment);
  193. frame->data[0] = bmalloc(size);
  194. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  195. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  196. frame->data[3] = (uint8_t *)frame->data[0] + offsets[2];
  197. frame->linesize[0] = width;
  198. frame->linesize[1] = half_width;
  199. frame->linesize[2] = half_width;
  200. frame->linesize[3] = width;
  201. break;
  202. }
  203. case VIDEO_FORMAT_YUVA:
  204. size = width * height;
  205. ALIGN_SIZE(size, alignment);
  206. offsets[0] = size;
  207. size += width * height;
  208. ALIGN_SIZE(size, alignment);
  209. offsets[1] = size;
  210. size += width * height;
  211. ALIGN_SIZE(size, alignment);
  212. offsets[2] = size;
  213. size += width * height;
  214. ALIGN_SIZE(size, alignment);
  215. frame->data[0] = bmalloc(size);
  216. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  217. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  218. frame->data[3] = (uint8_t *)frame->data[0] + offsets[2];
  219. frame->linesize[0] = width;
  220. frame->linesize[1] = width;
  221. frame->linesize[2] = width;
  222. frame->linesize[3] = width;
  223. break;
  224. case VIDEO_FORMAT_YA2L: {
  225. const uint32_t linesize = width * 2;
  226. const uint32_t plane_size = linesize * height;
  227. size = plane_size;
  228. ALIGN_SIZE(size, alignment);
  229. offsets[0] = size;
  230. size += plane_size;
  231. ALIGN_SIZE(size, alignment);
  232. offsets[1] = size;
  233. size += plane_size;
  234. ALIGN_SIZE(size, alignment);
  235. offsets[2] = size;
  236. size += plane_size;
  237. ALIGN_SIZE(size, alignment);
  238. frame->data[0] = bmalloc(size);
  239. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  240. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  241. frame->data[3] = (uint8_t *)frame->data[0] + offsets[2];
  242. frame->linesize[0] = linesize;
  243. frame->linesize[1] = linesize;
  244. frame->linesize[2] = linesize;
  245. frame->linesize[3] = linesize;
  246. break;
  247. }
  248. case VIDEO_FORMAT_I010: {
  249. size = width * height * 2;
  250. ALIGN_SIZE(size, alignment);
  251. offsets[0] = size;
  252. const uint32_t half_width = (width + 1) / 2;
  253. const uint32_t half_height = (height + 1) / 2;
  254. const uint32_t quarter_area = half_width * half_height;
  255. size += quarter_area * 2;
  256. ALIGN_SIZE(size, alignment);
  257. offsets[1] = size;
  258. size += quarter_area * 2;
  259. ALIGN_SIZE(size, alignment);
  260. frame->data[0] = bmalloc(size);
  261. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  262. frame->data[2] = (uint8_t *)frame->data[0] + offsets[1];
  263. frame->linesize[0] = width * 2;
  264. frame->linesize[1] = half_width * 2;
  265. frame->linesize[2] = half_width * 2;
  266. break;
  267. }
  268. case VIDEO_FORMAT_P010: {
  269. size = width * height * 2;
  270. ALIGN_SIZE(size, alignment);
  271. offsets[0] = size;
  272. const uint32_t cbcr_width = (width + 1) & (UINT32_MAX - 1);
  273. size += cbcr_width * ((height + 1) / 2) * 2;
  274. ALIGN_SIZE(size, alignment);
  275. frame->data[0] = bmalloc(size);
  276. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  277. frame->linesize[0] = width * 2;
  278. frame->linesize[1] = cbcr_width * 2;
  279. break;
  280. }
  281. case VIDEO_FORMAT_P216: {
  282. size = width * height * 2;
  283. ALIGN_SIZE(size, alignment);
  284. offsets[0] = size;
  285. const uint32_t cbcr_width = (width + 1) & (UINT32_MAX - 1);
  286. size += cbcr_width * height * 2;
  287. ALIGN_SIZE(size, alignment);
  288. frame->data[0] = bmalloc(size);
  289. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  290. frame->linesize[0] = width * 2;
  291. frame->linesize[1] = cbcr_width * 2;
  292. break;
  293. }
  294. case VIDEO_FORMAT_P416: {
  295. size = width * height * 2;
  296. ALIGN_SIZE(size, alignment);
  297. offsets[0] = size;
  298. size += width * height * 4;
  299. ALIGN_SIZE(size, alignment);
  300. frame->data[0] = bmalloc(size);
  301. frame->data[1] = (uint8_t *)frame->data[0] + offsets[0];
  302. frame->linesize[0] = width * 2;
  303. frame->linesize[1] = width * 4;
  304. break;
  305. }
  306. case VIDEO_FORMAT_V210: {
  307. const uint32_t adjusted_width = ((width + 5) / 6) * 16;
  308. size = adjusted_width * height;
  309. ALIGN_SIZE(size, alignment);
  310. frame->data[0] = bmalloc(size);
  311. frame->linesize[0] = adjusted_width;
  312. break;
  313. }
  314. }
  315. }
  316. void video_frame_copy(struct video_frame *dst, const struct video_frame *src,
  317. enum video_format format, uint32_t cy)
  318. {
  319. switch (format) {
  320. case VIDEO_FORMAT_NONE:
  321. return;
  322. case VIDEO_FORMAT_I420:
  323. case VIDEO_FORMAT_I010:
  324. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  325. memcpy(dst->data[1], src->data[1], src->linesize[1] * cy / 2);
  326. memcpy(dst->data[2], src->data[2], src->linesize[2] * cy / 2);
  327. break;
  328. case VIDEO_FORMAT_NV12:
  329. case VIDEO_FORMAT_P010:
  330. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  331. memcpy(dst->data[1], src->data[1], src->linesize[1] * cy / 2);
  332. break;
  333. case VIDEO_FORMAT_Y800:
  334. case VIDEO_FORMAT_YVYU:
  335. case VIDEO_FORMAT_YUY2:
  336. case VIDEO_FORMAT_UYVY:
  337. case VIDEO_FORMAT_RGBA:
  338. case VIDEO_FORMAT_BGRA:
  339. case VIDEO_FORMAT_BGRX:
  340. case VIDEO_FORMAT_BGR3:
  341. case VIDEO_FORMAT_AYUV:
  342. case VIDEO_FORMAT_V210:
  343. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  344. break;
  345. case VIDEO_FORMAT_I444:
  346. case VIDEO_FORMAT_I422:
  347. case VIDEO_FORMAT_I210:
  348. case VIDEO_FORMAT_I412:
  349. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  350. memcpy(dst->data[1], src->data[1], src->linesize[1] * cy);
  351. memcpy(dst->data[2], src->data[2], src->linesize[2] * cy);
  352. break;
  353. case VIDEO_FORMAT_I40A:
  354. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  355. memcpy(dst->data[1], src->data[1], src->linesize[1] * cy / 2);
  356. memcpy(dst->data[2], src->data[2], src->linesize[2] * cy / 2);
  357. memcpy(dst->data[3], src->data[3], src->linesize[3] * cy);
  358. break;
  359. case VIDEO_FORMAT_I42A:
  360. case VIDEO_FORMAT_YUVA:
  361. case VIDEO_FORMAT_YA2L:
  362. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  363. memcpy(dst->data[1], src->data[1], src->linesize[1] * cy);
  364. memcpy(dst->data[2], src->data[2], src->linesize[2] * cy);
  365. memcpy(dst->data[3], src->data[3], src->linesize[3] * cy);
  366. break;
  367. case VIDEO_FORMAT_P216:
  368. case VIDEO_FORMAT_P416:
  369. memcpy(dst->data[0], src->data[0], src->linesize[0] * cy);
  370. memcpy(dst->data[1], src->data[1], src->linesize[1] * cy);
  371. break;
  372. }
  373. }