AudioChunkManager.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include "AudioChunkManager.h"
  2. #include "BellUtils.h"
  3. #include "Logger.h"
  4. AudioChunkManager::AudioChunkManager()
  5. : bell::Task("AudioChunkManager", 4 * 1024, +0, 0) {
  6. this->chunks = std::vector<std::shared_ptr<AudioChunk>>();
  7. startTask();
  8. }
  9. std::shared_ptr<AudioChunk>
  10. AudioChunkManager::registerNewChunk(uint16_t seqId,
  11. std::vector<uint8_t> &audioKey,
  12. uint32_t startPos, uint32_t endPos) {
  13. auto chunk =
  14. std::make_shared<AudioChunk>(seqId, audioKey, startPos * 4, endPos * 4);
  15. this->chunks.push_back(chunk);
  16. CSPOT_LOG(debug, "Chunk requested %d", seqId);
  17. return chunk;
  18. }
  19. void AudioChunkManager::handleChunkData(std::vector<uint8_t> &data,
  20. bool failed) {
  21. auto audioPair = std::pair(data, failed);
  22. audioChunkDataQueue.push(audioPair);
  23. }
  24. void AudioChunkManager::failAllChunks() {
  25. // Enumerate all the chunks and mark em all failed
  26. for (auto const &chunk : this->chunks) {
  27. if (!chunk->isLoaded) {
  28. chunk->isLoaded = true;
  29. chunk->isFailed = true;
  30. chunk->isHeaderFileSizeLoadedSemaphore->give();
  31. chunk->isLoadedSemaphore->give();
  32. }
  33. }
  34. }
  35. void AudioChunkManager::close() {
  36. this->isRunning = false;
  37. this->failAllChunks();
  38. this->audioChunkDataQueue.clear();
  39. std::scoped_lock lock(this->runningMutex);
  40. }
  41. void AudioChunkManager::runTask() {
  42. std::scoped_lock lock(this->runningMutex);
  43. this->isRunning = true;
  44. while (isRunning) {
  45. std::pair<std::vector<uint8_t>, bool> audioPair;
  46. if (this->audioChunkDataQueue.wtpop(audioPair, 100)) {
  47. auto data = audioPair.first;
  48. auto failed = audioPair.second;
  49. uint16_t seqId = ntohs(extract<uint16_t>(data, 0));
  50. // Erase all chunks that are not referenced elsewhere anymore
  51. chunks.erase(
  52. std::remove_if(chunks.begin(), chunks.end(),
  53. [](const std::shared_ptr<AudioChunk> &chunk) {
  54. return chunk.use_count() == 1;
  55. }),
  56. chunks.end());
  57. try {
  58. for (auto const &chunk : this->chunks) {
  59. // Found the right chunk
  60. if (chunk != nullptr && chunk->seqId == seqId) {
  61. if (failed) {
  62. // chunk->isFailed = true;
  63. chunk->startPosition = 0;
  64. chunk->endPosition = 0;
  65. chunk->isHeaderFileSizeLoadedSemaphore->give();
  66. chunk->isLoadedSemaphore->give();
  67. break;
  68. }
  69. switch (data.size()) {
  70. case DATA_SIZE_HEADER: {
  71. CSPOT_LOG(debug, "ID: %d: header decrypt!", seqId);
  72. auto headerSize = ntohs(extract<uint16_t>(data, 2));
  73. // Got file size!
  74. chunk->headerFileSize =
  75. ntohl(extract<uint32_t>(data, 5)) * 4;
  76. chunk->isHeaderFileSizeLoadedSemaphore->give();
  77. break;
  78. }
  79. case DATA_SIZE_FOOTER:
  80. if (chunk->endPosition > chunk->headerFileSize) {
  81. chunk->endPosition = chunk->headerFileSize;
  82. }
  83. CSPOT_LOG(debug, "ID: %d: Starting decrypt!",
  84. seqId);
  85. chunk->decrypt();
  86. chunk->isLoadedSemaphore->give();
  87. break;
  88. default:
  89. // printf("ID: %d: Got data chunk!\n", seqId);
  90. // 2 first bytes are size so we skip it
  91. // printf("(_)--- Free memory %d\n",
  92. // esp_get_free_heap_size());
  93. if (chunk == nullptr) {
  94. return;
  95. }
  96. auto actualData = std::vector<uint8_t>(
  97. data.begin() + 2, data.end());
  98. chunk->appendData(actualData);
  99. break;
  100. }
  101. }
  102. }
  103. } catch (...) {
  104. }
  105. } else {
  106. // usleep(100*1000);
  107. }
  108. }
  109. // Playback finished
  110. }