videogen.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*
  2. * Generates a synthetic YUV video sequence suitable for codec testing.
  3. * NOTE: No floats are used to guarantee a bit exact 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] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
  75. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  76. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
  77. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  78. cb++;
  79. cr++;
  80. p += -wrap3 + 2 * 3;
  81. lum += -wrap + 2;
  82. }
  83. p += wrap3;
  84. lum += wrap;
  85. }
  86. }
  87. /* cif format */
  88. #define DEFAULT_WIDTH 352
  89. #define DEFAULT_HEIGHT 288
  90. #define DEFAULT_NB_PICT 50 /* 2 seconds */
  91. static void pgmyuv_save(const char *filename, int w, int h,
  92. unsigned char *rgb_tab)
  93. {
  94. FILE *f;
  95. int i, h2, w2;
  96. unsigned char *cb, *cr;
  97. unsigned char *lum_tab, *cb_tab, *cr_tab;
  98. lum_tab = malloc(w * h);
  99. cb_tab = malloc((w * h) / 4);
  100. cr_tab = malloc((w * h) / 4);
  101. rgb24_to_yuv420p(lum_tab, cb_tab, cr_tab, rgb_tab, w, h);
  102. f = fopen(filename,"wb");
  103. fprintf(f, "P5\n%d %d\n%d\n", w, (h * 3) / 2, 255);
  104. fwrite(lum_tab, 1, w * h, f);
  105. h2 = h / 2;
  106. w2 = w / 2;
  107. cb = cb_tab;
  108. cr = cr_tab;
  109. for(i=0;i<h2;i++) {
  110. fwrite(cb, 1, w2, f);
  111. fwrite(cr, 1, w2, f);
  112. cb += w2;
  113. cr += w2;
  114. }
  115. fclose(f);
  116. free(lum_tab);
  117. free(cb_tab);
  118. free(cr_tab);
  119. }
  120. unsigned char *rgb_tab;
  121. int width, height, wrap;
  122. static void put_pixel(int x, int y, int r, int g, int b)
  123. {
  124. unsigned char *p;
  125. if (x < 0 || x >= width ||
  126. y < 0 || y >= height)
  127. return;
  128. p = rgb_tab + y * wrap + x * 3;
  129. p[0] = r;
  130. p[1] = g;
  131. p[2] = b;
  132. }
  133. static unsigned int myrnd(unsigned int *seed_ptr, int n)
  134. {
  135. unsigned int seed, val;
  136. seed = *seed_ptr;
  137. seed = (seed * 314159) + 1;
  138. if (n == 256) {
  139. val = seed >> 24;
  140. } else {
  141. val = seed % n;
  142. }
  143. *seed_ptr = seed;
  144. return val;
  145. }
  146. #define NOISE_X 10
  147. #define NOISE_Y 30
  148. #define NOISE_W 26
  149. #define FRAC_BITS 8
  150. #define FRAC_ONE (1 << FRAC_BITS)
  151. /* cosine approximate with 1-x^2 */
  152. static int int_cos(int a)
  153. {
  154. int v, neg;
  155. a = a & (FRAC_ONE - 1);
  156. if (a >= (FRAC_ONE / 2))
  157. a = FRAC_ONE - a;
  158. neg = 0;
  159. if (a > (FRAC_ONE / 4)) {
  160. neg = -1;
  161. a = (FRAC_ONE / 2) - a;
  162. }
  163. v = FRAC_ONE - ((a * a) >> 4);
  164. v = (v ^ neg) - neg;
  165. return v;
  166. }
  167. #define NB_OBJS 10
  168. typedef struct VObj {
  169. int x, y, w, h;
  170. int r, g, b;
  171. } VObj;
  172. VObj objs[NB_OBJS];
  173. unsigned int seed = 1;
  174. static void gen_image(int num, int w, int h)
  175. {
  176. int r, g, b, x, y, i, dx, dy, x1, y1;
  177. unsigned int seed1;
  178. if (num == 0) {
  179. for(i=0;i<NB_OBJS;i++) {
  180. objs[i].x = myrnd(&seed, w);
  181. objs[i].y = myrnd(&seed, h);
  182. objs[i].w = myrnd(&seed, w / 4) + 10;
  183. objs[i].h = myrnd(&seed, h / 4) + 10;
  184. objs[i].r = myrnd(&seed, 256);
  185. objs[i].g = myrnd(&seed, 256);
  186. objs[i].b = myrnd(&seed, 256);
  187. }
  188. }
  189. /* first a moving background with gradients */
  190. /* test motion estimation */
  191. dx = int_cos(num * FRAC_ONE / 50) * 35;
  192. dy = int_cos(num * FRAC_ONE / 50 + FRAC_ONE / 10) * 30;
  193. for(y=0;y<h;y++) {
  194. for(x=0;x<w;x++) {
  195. x1 = (x << FRAC_BITS) + dx;
  196. y1 = (y << FRAC_BITS) + dy;
  197. r = ((y1 * 7) >> FRAC_BITS) & 0xff;
  198. g = (((x1 + y1) * 9) >> FRAC_BITS) & 0xff;
  199. b = ((x1 * 5) >> FRAC_BITS) & 0xff;
  200. put_pixel(x, y, r, g, b);
  201. }
  202. }
  203. /* then some noise with very high intensity to test saturation */
  204. seed1 = num;
  205. for(y=0;y<NOISE_W;y++) {
  206. for(x=0;x<NOISE_W;x++) {
  207. r = myrnd(&seed1, 256);
  208. g = myrnd(&seed1, 256);
  209. b = myrnd(&seed1, 256);
  210. put_pixel(x + NOISE_X, y + NOISE_Y, r, g, b);
  211. }
  212. }
  213. /* then moving objects */
  214. for(i=0;i<NB_OBJS;i++) {
  215. VObj *p = &objs[i];
  216. seed1 = i;
  217. for(y=0;y<p->h;y++) {
  218. for(x=0;x<p->w;x++) {
  219. r = p->r;
  220. g = p->g;
  221. b = p->b;
  222. /* add a per object noise */
  223. r += myrnd(&seed1, 50);
  224. g += myrnd(&seed1, 50);
  225. b += myrnd(&seed1, 50);
  226. put_pixel(x + p->x, y + p->y, r, g, b);
  227. }
  228. }
  229. p->x += myrnd(&seed, 21) - 10;
  230. p->y += myrnd(&seed, 21) - 10;
  231. }
  232. }
  233. int main(int argc, char **argv)
  234. {
  235. int w, h, i;
  236. char buf[1024];
  237. if (argc != 2) {
  238. printf("usage: %s file\n"
  239. "generate a test video stream\n", argv[0]);
  240. exit(1);
  241. }
  242. w = DEFAULT_WIDTH;
  243. h = DEFAULT_HEIGHT;
  244. rgb_tab = malloc(w * h * 3);
  245. wrap = w * 3;
  246. width = w;
  247. height = h;
  248. for(i=0;i<DEFAULT_NB_PICT;i++) {
  249. snprintf(buf, sizeof(buf), "%s%02d.pgm", argv[1], i);
  250. gen_image(i, w, h);
  251. pgmyuv_save(buf, w, h, rgb_tab);
  252. }
  253. free(rgb_tab);
  254. return 0;
  255. }