granulepos.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
  5. * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  6. * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  7. * *
  8. * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
  9. * by the Xiph.Org Foundation http://www.xiph.org/ *
  10. * *
  11. ********************************************************************
  12. function: routines for validating encoder granulepos generation
  13. last mod: $Id: granulepos.c 16503 2009-08-22 18:14:02Z giles $
  14. ********************************************************************/
  15. #include <stdlib.h>
  16. #include <theora/theoraenc.h>
  17. #include <math.h>
  18. #include "tests.h"
  19. static int ilog(unsigned int v){
  20. int ret=0;
  21. while(v){
  22. ret++;
  23. v>>=1;
  24. }
  25. return(ret);
  26. }
  27. static int
  28. granulepos_test_encode (int frequency)
  29. {
  30. th_info ti;
  31. th_enc_ctx *te;
  32. int result;
  33. int frame, tframe, keyframe, keydist;
  34. int shift;
  35. double rate, ttime;
  36. th_ycbcr_buffer yuv;
  37. unsigned char *framedata;
  38. ogg_packet op;
  39. long long int last_granule = -1;
  40. /* INFO ("+ Initializing th_info struct"); */
  41. th_info_init (&ti);
  42. ti.frame_width = 32;
  43. ti.frame_height = 32;
  44. ti.pic_width = ti.frame_width;
  45. ti.pic_height = ti.frame_height;
  46. ti.pic_x = 0;
  47. ti.pic_y = 0;
  48. ti.fps_numerator = 16;
  49. ti.fps_denominator = 1;
  50. ti.aspect_numerator = 1;
  51. ti.aspect_denominator = 1;
  52. ti.colorspace = TH_CS_UNSPECIFIED;
  53. ti.pixel_fmt = TH_PF_420;
  54. ti.quality = 16;
  55. ti.keyframe_granule_shift=ilog(frequency);
  56. /* INFO ("+ Allocating encoder context"); */
  57. te = th_encode_alloc(&ti);
  58. if (te == NULL) {
  59. INFO ("+ Clearing th_info");
  60. th_info_clear(&ti);
  61. FAIL ("negative return code initializing encoder");
  62. }
  63. /* INFO ("+ Setting up dummy 4:2:0 frame data"); */
  64. framedata = calloc(ti.frame_height, ti.frame_width);
  65. yuv[0].width = ti.frame_width;
  66. yuv[0].height = ti.frame_height;
  67. yuv[0].stride = ti.frame_width;
  68. yuv[0].data = framedata;
  69. yuv[1].width = ti.frame_width / 2;
  70. yuv[1].height = ti.frame_width / 2;
  71. yuv[1].stride = ti.frame_width;
  72. yuv[1].data = framedata;
  73. yuv[2].width = ti.frame_width / 2;
  74. yuv[2].height = ti.frame_width / 2;
  75. yuv[2].stride = ti.frame_width;
  76. yuv[2].data = framedata;
  77. INFO ("+ Checking granulepos generation");
  78. shift = ti.keyframe_granule_shift;
  79. rate = (double)ti.fps_denominator/ti.fps_numerator;
  80. for (frame = 0; frame < frequency * 2 + 1; frame++) {
  81. result = th_encode_ycbcr_in (te, yuv);
  82. if (result < 0) {
  83. printf("th_encode_ycbcr_in() returned %d\n", result);
  84. FAIL ("negative error code submitting frame for compression");
  85. }
  86. result = th_encode_packetout (te, frame >= frequency * 2, &op);
  87. if (result <= 0) {
  88. printf("th_encode_packetout() returned %d\n", result);
  89. FAIL("failed to retrieve compressed frame");
  90. }
  91. if ((long long int)op.granulepos < last_granule)
  92. FAIL ("encoder returned a decreasing granulepos value");
  93. last_granule = op.granulepos;
  94. keyframe = op.granulepos >> shift;
  95. keydist = op.granulepos - (keyframe << shift);
  96. tframe = th_granule_frame (te, op.granulepos);
  97. ttime = th_granule_time(te, op.granulepos);
  98. #if DEBUG
  99. printf("++ frame %d granulepos %lld %d:%d %d %.3lfs\n",
  100. frame, (long long int)op.granulepos, keyframe, keydist,
  101. tframe, th_granule_time (te, op.granulepos));
  102. #endif
  103. /* granulepos stores the frame count */
  104. if ((keyframe + keydist) != frame + 1)
  105. FAIL ("encoder granulepos does not map to the correct frame number");
  106. /* th_granule_frame() returns the frame index */
  107. if (tframe != frame)
  108. FAIL ("th_granule_frame() returned incorrect results");
  109. /* th_granule_time() returns the end time */
  110. if (fabs(rate*(frame+1) - ttime) > 1.0e-6)
  111. FAIL ("th_granule_time() returned incorrect results");
  112. }
  113. /* clean up */
  114. /* INFO ("+ Freeing dummy frame data"); */
  115. free(framedata);
  116. /* INFO ("+ Clearing th_info struct"); */
  117. th_info_clear(&ti);
  118. /* INFO ("+ Freeing encoder context"); */
  119. th_encode_free(te);
  120. return 0;
  121. }
  122. int main(int argc, char *argv[])
  123. {
  124. granulepos_test_encode (1);
  125. granulepos_test_encode (2);
  126. granulepos_test_encode (3);
  127. granulepos_test_encode (4);
  128. granulepos_test_encode (8);
  129. granulepos_test_encode (64);
  130. exit (0);
  131. }