Lacing.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include "Lacing.h"
  2. #include "Cluster.h"
  3. #include "vint.h"
  4. bool nsmkv::Lacing::GetState(uint8_t flags, const uint8_t *data, size_t data_len, nsmkv::LacingState *state)
  5. {
  6. // TODO: error check by making sure data_len doesn't go below 0
  7. switch(flags & BlockBinary::LACE_MASK)
  8. {
  9. case BlockBinary::NO_LACING:
  10. state->laces = 1;
  11. state->positions[0] = 0;
  12. state->sizes[0] = data_len;
  13. #ifdef WA_VALIDATE
  14. printf(" Lacing = NO_LACING\n");
  15. #endif
  16. return true;
  17. case BlockBinary::EBML_LACING:
  18. {
  19. uint16_t number_of_frames = state->laces = *data++ + 1;
  20. uint64_t delta = vint_get_number_bytes(data[0]);
  21. state->sizes[0] = vint_read_ptr_len((uint8_t)delta, data);
  22. delta++;
  23. state->positions[0] = 1;
  24. state->positions[1] = 1+state->sizes[0];
  25. for (uint16_t i=1;i<number_of_frames-1;i++)
  26. {
  27. uint8_t this_len = vint_get_number_bytes(data[delta]);
  28. state->sizes[i] = vsint_read_ptr_len(this_len, data+delta);
  29. state->sizes[i] += state->sizes[i-1];
  30. state->positions[i+1] = state->positions[i] + state->sizes[i];
  31. delta+=this_len + 1;
  32. }
  33. state->sizes[number_of_frames-1] = data_len - state->positions[number_of_frames-1] - delta;
  34. for (uint16_t i=0;i<number_of_frames;i++)
  35. {
  36. state->positions[i] += delta;
  37. }
  38. #ifdef WA_VALIDATE
  39. printf(" Lacing = EBML_LACING\n");
  40. #endif
  41. }
  42. return true;
  43. case BlockBinary::XIPH_LACING:
  44. {
  45. const uint8_t *orig_data = data;
  46. uint16_t number_of_frames=state->laces = *data++ + 1;
  47. for (uint16_t i=0;i!=number_of_frames-1;i++)
  48. {
  49. size_t frame_len = 0;
  50. do
  51. {
  52. frame_len += *data;
  53. } while (data && *data++ == 255);
  54. state->sizes[i] = frame_len;
  55. }
  56. uint64_t delta = data - orig_data;
  57. uint64_t last_position = delta;
  58. uint64_t last_size = 0;
  59. for (uint16_t i=0;i!=number_of_frames;i++)
  60. {
  61. state->positions[i] = last_position + last_size;
  62. last_position = state->positions[i];
  63. last_size = state->sizes[i];
  64. }
  65. state->sizes[number_of_frames-1] = data_len - state->positions[number_of_frames-1];
  66. #ifdef WA_VALIDATE
  67. printf(" Lacing = XIPH LACING\n");
  68. #endif
  69. }
  70. return true;
  71. case BlockBinary::FIXED_LACING:
  72. {
  73. uint16_t number_of_frames=state->laces=data[0]+1;
  74. uint32_t size_per_frame = (uint32_t)(data_len-1) / number_of_frames;
  75. for (uint16_t i=0;i<number_of_frames;i++)
  76. {
  77. state->positions[i] = (uint64_t)(1 + size_per_frame*i);
  78. state->sizes[i] = size_per_frame;
  79. }
  80. #ifdef WA_VALIDATE
  81. printf(" Lacing = FIXED LACING\n");
  82. #endif
  83. }
  84. return true;
  85. default:
  86. return false;
  87. }
  88. }
  89. bool nsmkv::Lacing::GetFrame(uint16_t frame_number, const uint8_t *data, size_t data_len, const uint8_t **frame, size_t *frame_len, const LacingState *state)
  90. {
  91. if (frame_number >= state->laces)
  92. return false;
  93. const uint8_t *lace = data + state->positions[frame_number];
  94. size_t lace_len = (size_t)state->sizes[frame_number];
  95. if (lace < data // if the lace starts before our data
  96. || (state->positions[frame_number] + lace_len) > data_len) // or extends out past our data
  97. {
  98. return false;
  99. }
  100. *frame = lace;
  101. *frame_len = lace_len;
  102. return true;
  103. }