PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/seek/seek-read-error.c

https://bitbucket.org/achurch_/libnogg
C | 177 lines | 143 code | 20 blank | 14 comment | 31 complexity | 46aa7a934849fc07c9ea55bf0022c4f0 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*
  2. * libnogg: a decoder library for Ogg Vorbis streams
  3. * Copyright (c) 2014-2015 Andrew Church <achurch@achurch.org>
  4. *
  5. * This software may be copied and redistributed under certain conditions;
  6. * see the file "COPYING" in the source code distribution for details.
  7. * NO WARRANTY is provided with this software.
  8. */
  9. #include "include/nogg.h"
  10. #include "src/common.h" // For lenof().
  11. #include "tests/common.h"
  12. #include "tests/data/noise-6ch_float.h" // Defines expected_pcm[].
  13. static int64_t length(void *opaque)
  14. {
  15. FILE *f = (FILE *)opaque;
  16. const long saved_offset = ftell(f);
  17. if (fseek(f, 0, SEEK_END) != 0) {
  18. return -1;
  19. }
  20. const int64_t len = ftell(f);
  21. if (fseek(f, saved_offset, SEEK_SET) != 0) {
  22. return -1;
  23. }
  24. return len;
  25. }
  26. static int64_t tell(void *opaque)
  27. {
  28. return ftell((FILE *)opaque);
  29. }
  30. static void seek(void *opaque, int64_t offset)
  31. {
  32. fseek((FILE *)opaque, offset, SEEK_SET);
  33. }
  34. static int read_count;
  35. static int32_t read(void *opaque, void *buf, int32_t len)
  36. {
  37. if (read_count > 0) {
  38. read_count--;
  39. return fread(buf, 1, len, (FILE *)opaque);
  40. } else {
  41. return 0;
  42. }
  43. }
  44. static void close(void *opaque)
  45. {
  46. fclose((FILE *)opaque);
  47. }
  48. int main(void)
  49. {
  50. FILE *f;
  51. vorbis_t *vorbis;
  52. read_count = 10000;
  53. EXPECT_TRUE(f = fopen("tests/data/6ch-all-page-types.ogg", "rb"));
  54. EXPECT_TRUE(vorbis = vorbis_open_callbacks(((const vorbis_callbacks_t){
  55. .length = length,
  56. .tell = tell,
  57. .seek = seek,
  58. .read = read,
  59. .close = close}),
  60. f, 0, NULL));
  61. /* Make sure the first and last page data is cached before we start
  62. * failing read operations, or seeks won't work at all. */
  63. EXPECT_TRUE(vorbis_seek(vorbis, 0));
  64. static const int seek_offsets[] = {0, 2000, 8499};
  65. for (int i = 0; i < lenof(seek_offsets); i++) {
  66. const int offset = seek_offsets[i];
  67. int32_t j;
  68. for (j = 0; j < 10000; j++) {
  69. read_count = j;
  70. if (vorbis_seek(vorbis, offset)) {
  71. break;
  72. }
  73. }
  74. if (j == 10000) {
  75. printf("%s:%d: Seek to %d failed\n", __FILE__, __LINE__, offset);
  76. return EXIT_FAILURE;
  77. }
  78. read_count = 10000;
  79. float pcm[6];
  80. vorbis_error_t error = (vorbis_error_t)-1;
  81. const int num_read = vorbis_read_float(vorbis, pcm, 1, &error);
  82. if (num_read == 0 && error == VORBIS_ERROR_STREAM_END) {
  83. /* The decode_frame() call in vorbis_seek() hit a read error
  84. * at a page boundary, which gets interpreted as end-of-stream.
  85. * There's not much we can do about this case, so just let it
  86. * slide. */
  87. continue;
  88. }
  89. if (num_read != 1) {
  90. fprintf(stderr, "%s:%d: Failed to read sample %d (error %d)\n",
  91. __FILE__, __LINE__, offset, error);
  92. return EXIT_FAILURE;
  93. }
  94. if (error != VORBIS_NO_ERROR) {
  95. fprintf(stderr, "%s:%d: error was %d but should have been %d"
  96. " for sample %d\n", __FILE__, __LINE__, error,
  97. VORBIS_NO_ERROR, offset);
  98. return EXIT_FAILURE;
  99. }
  100. for (j = 0; j < 6; j++) {
  101. if (fabsf(pcm[j] - expected_pcm[offset*6+j]) > 1.0e-6f) {
  102. fprintf(stderr, "%s:%d: Sample %d+%d was %.8g but should have"
  103. " been near %.8g\n", __FILE__, __LINE__, offset, j,
  104. pcm[j], expected_pcm[offset*6+j]);
  105. return EXIT_FAILURE;
  106. }
  107. }
  108. }
  109. vorbis_close(vorbis);
  110. read_count = 10000;
  111. EXPECT_TRUE(f = fopen("tests/data/6ch-long-first-packet.ogg", "rb"));
  112. EXPECT_TRUE(vorbis = vorbis_open_callbacks(((const vorbis_callbacks_t){
  113. .length = length,
  114. .tell = tell,
  115. .seek = seek,
  116. .read = read,
  117. .close = close}),
  118. f, 0, NULL));
  119. EXPECT_TRUE(vorbis_seek(vorbis, 0));
  120. const int offset = 500;
  121. int32_t j;
  122. for (j = 0; j < 10000; j++) {
  123. read_count = j;
  124. if (vorbis_seek(vorbis, offset)) {
  125. break;
  126. }
  127. }
  128. if (j == 10000) {
  129. printf("%s:%d: Seek to %d failed\n", __FILE__, __LINE__, offset);
  130. return EXIT_FAILURE;
  131. }
  132. read_count = 10000;
  133. float pcm[6];
  134. vorbis_error_t error = (vorbis_error_t)-1;
  135. const int num_read = vorbis_read_float(vorbis, pcm, 1, &error);
  136. if (num_read != 1) {
  137. fprintf(stderr, "%s:%d: Failed to read sample %d (error %d)\n",
  138. __FILE__, __LINE__, offset, error);
  139. return EXIT_FAILURE;
  140. }
  141. if (error != VORBIS_NO_ERROR) {
  142. fprintf(stderr, "%s:%d: error was %d but should have been %d"
  143. " for sample %d\n", __FILE__, __LINE__, error,
  144. VORBIS_NO_ERROR, offset);
  145. return EXIT_FAILURE;
  146. }
  147. for (j = 0; j < 6; j++) {
  148. if (fabsf(pcm[j] - expected_pcm[offset*6+j]) > 1.0e-6f) {
  149. fprintf(stderr, "%s:%d: Sample %d+%d was %.8g but should have"
  150. " been near %.8g\n", __FILE__, __LINE__, offset, j,
  151. pcm[j], expected_pcm[offset*6+j]);
  152. return EXIT_FAILURE;
  153. }
  154. }
  155. vorbis_close(vorbis);
  156. return EXIT_SUCCESS;
  157. }