videogen.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * Generate a synthetic YUV video sequence suitable for codec testing.
  3. * NOTE: No floats are used to guarantee bitexact output.
  4. *
  5. * Copyright (c) 2002 Fabrice Bellard
  6. *
  7. * This file is part of FFmpeg.
  8. *
  9. * FFmpeg is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2.1 of the License, or (at your option) any later version.
  13. *
  14. * FFmpeg is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with FFmpeg; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. #include <stdlib.h>
  24. #include <stdint.h>
  25. #include <stdio.h>
  26. #define SCALEBITS 8
  27. #define ONE_HALF (1 << (SCALEBITS - 1))
  28. #define FIX(x) ((int) ((x) * (1L << SCALEBITS) + 0.5))
  29. static void rgb24_to_yuv420p(uint8_t *lum, uint8_t *cb, uint8_t *cr,
  30. uint8_t *src, int width, int height)
  31. {
  32. int wrap, wrap3, x, y;
  33. int r, g, b, r1, g1, b1;
  34. uint8_t *p;
  35. wrap = width;
  36. wrap3 = width * 3;
  37. p = src;
  38. for (y = 0; y < height; y += 2) {
  39. for (x = 0; x < width; x += 2) {
  40. r = p[0];
  41. g = p[1];
  42. b = p[2];
  43. r1 = r;
  44. g1 = g;
  45. b1 = b;
  46. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  47. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  48. r = p[3];
  49. g = p[4];
  50. b = p[5];
  51. r1 += r;
  52. g1 += g;
  53. b1 += b;
  54. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  55. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  56. p += wrap3;
  57. lum += wrap;
  58. r = p[0];
  59. g = p[1];
  60. b = p[2];
  61. r1 += r;
  62. g1 += g;
  63. b1 += b;
  64. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  65. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  66. r = p[3];
  67. g = p[4];
  68. b = p[5];
  69. r1 += r;
  70. g1 += g;
  71. b1 += b;
  72. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  73. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  74. cb[0] = 128 + ((- FIX(0.16874) * r1 -
  75. FIX(0.33126) * g1 +
  76. FIX(0.50000) * b1 +
  77. 4 * ONE_HALF - 1)
  78. >> (SCALEBITS + 2));
  79. cr[0] = 128 + ((FIX(0.50000) * r1 -
  80. FIX(0.41869) * g1 -
  81. FIX(0.08131) * b1 +
  82. 4 * ONE_HALF - 1)
  83. >> (SCALEBITS + 2));
  84. cb++;
  85. cr++;
  86. p += -wrap3 + 2 * 3;
  87. lum += -wrap + 2;
  88. }
  89. p += wrap3;
  90. lum += wrap;
  91. }
  92. }
  93. /* cif format */
  94. #define DEFAULT_WIDTH 352
  95. #define DEFAULT_HEIGHT 288
  96. #define DEFAULT_NB_PICT 50 /* 2 seconds */
  97. static void pgmyuv_save(const char *filename, int w, int h,
  98. unsigned char *rgb_tab)
  99. {
  100. FILE *f;
  101. int i, h2, w2;
  102. unsigned char *cb, *cr;
  103. unsigned char *lum_tab, *cb_tab, *cr_tab;
  104. lum_tab = malloc(w * h);
  105. cb_tab = malloc((w * h) / 4);
  106. cr_tab = malloc((w * h) / 4);
  107. rgb24_to_yuv420p(lum_tab, cb_tab, cr_tab, rgb_tab, w, h);
  108. f = fopen(filename, "wb");
  109. fprintf(f, "P5\n%d %d\n%d\n", w, (h * 3) / 2, 255);
  110. fwrite(lum_tab, 1, w * h, f);
  111. h2 = h / 2;
  112. w2 = w / 2;
  113. cb = cb_tab;
  114. cr = cr_tab;
  115. for (i = 0; i < h2; i++) {
  116. fwrite(cb, 1, w2, f);
  117. fwrite(cr, 1, w2, f);
  118. cb += w2;
  119. cr += w2;
  120. }
  121. fclose(f);
  122. free(lum_tab);
  123. free(cb_tab);
  124. free(cr_tab);
  125. }
  126. unsigned char *rgb_tab;
  127. int width, height, wrap;
  128. static void put_pixel(int x, int y, int r, int g, int b)
  129. {
  130. unsigned char *p;
  131. if (x < 0 || x >= width ||
  132. y < 0 || y >= height)
  133. return;
  134. p = rgb_tab + y * wrap + x * 3;
  135. p[0] = r;
  136. p[1] = g;
  137. p[2] = b;
  138. }
  139. static unsigned int myrnd(unsigned int *seed_ptr, int n)
  140. {
  141. unsigned int seed, val;
  142. seed = *seed_ptr;
  143. seed = (seed * 314159) + 1;
  144. if (n == 256) {
  145. val = seed >> 24;
  146. } else {
  147. val = seed % n;
  148. }
  149. *seed_ptr = seed;
  150. return val;
  151. }
  152. #define NOISE_X 10
  153. #define NOISE_Y 30
  154. #define NOISE_W 26
  155. #define FRAC_BITS 8
  156. #define FRAC_ONE (1 << FRAC_BITS)
  157. /* cosine approximate with 1-x^2 */
  158. static int int_cos(int a)
  159. {
  160. int v, neg;
  161. a = a & (FRAC_ONE - 1);
  162. if (a >= (FRAC_ONE / 2))
  163. a = FRAC_ONE - a;
  164. neg = 0;
  165. if (a > (FRAC_ONE / 4)) {
  166. neg = -1;
  167. a = (FRAC_ONE / 2) - a;
  168. }
  169. v = FRAC_ONE - ((a * a) >> 4);
  170. v = (v ^ neg) - neg;
  171. return v;
  172. }
  173. #define NB_OBJS 10
  174. typedef struct VObj {
  175. int x, y, w, h;
  176. int r, g, b;
  177. } VObj;
  178. VObj objs[NB_OBJS];
  179. unsigned int seed = 1;
  180. static void gen_image(int num, int w, int h)
  181. {
  182. int r, g, b, x, y, i, dx, dy, x1, y1;
  183. unsigned int seed1;
  184. if (num == 0) {
  185. for (i = 0; i < NB_OBJS; i++) {
  186. objs[i].x = myrnd(&seed, w);
  187. objs[i].y = myrnd(&seed, h);
  188. objs[i].w = myrnd(&seed, w / 4) + 10;
  189. objs[i].h = myrnd(&seed, h / 4) + 10;
  190. objs[i].r = myrnd(&seed, 256);
  191. objs[i].g = myrnd(&seed, 256);
  192. objs[i].b = myrnd(&seed, 256);
  193. }
  194. }
  195. /* first a moving background with gradients */
  196. /* test motion estimation */
  197. dx = int_cos(num * FRAC_ONE / 50) * 35;
  198. dy = int_cos(num * FRAC_ONE / 50 + FRAC_ONE / 10) * 30;
  199. for (y = 0; y < h; y++) {
  200. for (x = 0; x < w; x++) {
  201. x1 = (x << FRAC_BITS) + dx;
  202. y1 = (y << FRAC_BITS) + dy;
  203. r = ((y1 * 7) >> FRAC_BITS) & 0xff;
  204. g = (((x1 + y1) * 9) >> FRAC_BITS) & 0xff;
  205. b = ((x1 * 5) >> FRAC_BITS) & 0xff;
  206. put_pixel(x, y, r, g, b);
  207. }
  208. }
  209. /* then some noise with very high intensity to test saturation */
  210. seed1 = num;
  211. for (y = 0; y < NOISE_W; y++) {
  212. for (x = 0; x < NOISE_W; x++) {
  213. r = myrnd(&seed1, 256);
  214. g = myrnd(&seed1, 256);
  215. b = myrnd(&seed1, 256);
  216. put_pixel(x + NOISE_X, y + NOISE_Y, r, g, b);
  217. }
  218. }
  219. /* then moving objects */
  220. for (i = 0; i < NB_OBJS; i++) {
  221. VObj *p = &objs[i];
  222. seed1 = i;
  223. for (y = 0; y < p->h; y++) {
  224. for (x = 0; x < p->w; x++) {
  225. r = p->r;
  226. g = p->g;
  227. b = p->b;
  228. /* add a per object noise */
  229. r += myrnd(&seed1, 50);
  230. g += myrnd(&seed1, 50);
  231. b += myrnd(&seed1, 50);
  232. put_pixel(x + p->x, y + p->y, r, g, b);
  233. }
  234. }
  235. p->x += myrnd(&seed, 21) - 10;
  236. p->y += myrnd(&seed, 21) - 10;
  237. }
  238. }
  239. int main(int argc, char **argv)
  240. {
  241. int w, h, i;
  242. char buf[1024];
  243. if (argc != 2) {
  244. printf("usage: %s file\n"
  245. "generate a test video stream\n", argv[0]);
  246. exit(1);
  247. }
  248. w = DEFAULT_WIDTH;
  249. h = DEFAULT_HEIGHT;
  250. rgb_tab = malloc(w * h * 3);
  251. wrap = w * 3;
  252. width = w;
  253. height = h;
  254. for (i = 0; i < DEFAULT_NB_PICT; i++) {
  255. snprintf(buf, sizeof(buf), "%s%02d.pgm", argv[1], i);
  256. gen_image(i, w, h);
  257. pgmyuv_save(buf, w, h, rgb_tab);
  258. }
  259. free(rgb_tab);
  260. return 0;
  261. }