media_audio_loaders.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "media/audio/media_audio_loaders.h"
  8. #include "media/audio/media_audio.h"
  9. #include "media/audio/media_audio_ffmpeg_loader.h"
  10. #include "media/audio/media_child_ffmpeg_loader.h"
  11. #include "media/media_common.h"
  12. namespace Media {
  13. namespace Player {
  14. Loaders::Loaders(QThread *thread)
  15. : _fromExternalNotify([=] { videoSoundAdded(); }) {
  16. moveToThread(thread);
  17. _fromExternalNotify.moveToThread(thread);
  18. connect(thread, SIGNAL(started()), this, SLOT(onInit()));
  19. connect(thread, SIGNAL(finished()), this, SLOT(deleteLater()));
  20. }
  21. void Loaders::feedFromExternal(ExternalSoundPart &&part) {
  22. auto invoke = false;
  23. {
  24. QMutexLocker lock(&_fromExternalMutex);
  25. invoke = _fromExternalQueues.empty()
  26. && _fromExternalForceToBuffer.empty();
  27. auto &queue = _fromExternalQueues[part.audio];
  28. queue.insert(
  29. end(queue),
  30. std::make_move_iterator(part.packets.begin()),
  31. std::make_move_iterator(part.packets.end()));
  32. }
  33. if (invoke) {
  34. _fromExternalNotify.call();
  35. }
  36. }
  37. void Loaders::forceToBufferExternal(const AudioMsgId &audioId) {
  38. auto invoke = false;
  39. {
  40. QMutexLocker lock(&_fromExternalMutex);
  41. invoke = _fromExternalQueues.empty()
  42. && _fromExternalForceToBuffer.empty();
  43. _fromExternalForceToBuffer.emplace(audioId);
  44. }
  45. if (invoke) {
  46. _fromExternalNotify.call();
  47. }
  48. }
  49. void Loaders::videoSoundAdded() {
  50. auto queues = decltype(_fromExternalQueues)();
  51. auto forces = decltype(_fromExternalForceToBuffer)();
  52. {
  53. QMutexLocker lock(&_fromExternalMutex);
  54. queues = base::take(_fromExternalQueues);
  55. forces = base::take(_fromExternalForceToBuffer);
  56. }
  57. for (const auto &audioId : forces) {
  58. const auto tryLoader = [&](const auto &id, auto &loader) {
  59. if (audioId == id && loader) {
  60. loader->setForceToBuffer(true);
  61. if (loader->holdsSavedDecodedSamples()
  62. && !queues.contains(audioId)) {
  63. loadData(audioId);
  64. }
  65. return true;
  66. }
  67. return false;
  68. };
  69. tryLoader(_audio, _audioLoader)
  70. || tryLoader(_song, _songLoader)
  71. || tryLoader(_video, _videoLoader);
  72. }
  73. for (auto &pair : queues) {
  74. const auto audioId = pair.first;
  75. auto &packets = pair.second;
  76. const auto tryLoader = [&](const auto &id, auto &loader) {
  77. if (id == audioId && loader) {
  78. loader->enqueuePackets(std::move(packets));
  79. if (loader->holdsSavedDecodedSamples()) {
  80. loadData(audioId);
  81. }
  82. return true;
  83. }
  84. return false;
  85. };
  86. tryLoader(_audio, _audioLoader)
  87. || tryLoader(_song, _songLoader)
  88. || tryLoader(_video, _videoLoader);
  89. }
  90. }
  91. void Loaders::onInit() {
  92. }
  93. void Loaders::onStart(const AudioMsgId &audio, qint64 positionMs) {
  94. auto type = audio.type();
  95. clear(type);
  96. {
  97. QMutexLocker lock(internal::audioPlayerMutex());
  98. if (!mixer()) return;
  99. auto track = mixer()->trackForType(type);
  100. if (!track) return;
  101. track->loading = true;
  102. }
  103. loadData(audio, positionMs);
  104. }
  105. AudioMsgId Loaders::clear(AudioMsgId::Type type) {
  106. AudioMsgId result;
  107. switch (type) {
  108. case AudioMsgId::Type::Voice:
  109. std::swap(result, _audio);
  110. _audioLoader = nullptr;
  111. break;
  112. case AudioMsgId::Type::Song:
  113. std::swap(result, _song);
  114. _songLoader = nullptr;
  115. break;
  116. case AudioMsgId::Type::Video:
  117. std::swap(result, _video);
  118. _videoLoader = nullptr;
  119. break;
  120. }
  121. return result;
  122. }
  123. void Loaders::setStoppedState(Mixer::Track *track, State state) {
  124. mixer()->setStoppedState(track, state);
  125. }
  126. void Loaders::emitError(AudioMsgId::Type type) {
  127. error(clear(type));
  128. }
  129. void Loaders::onLoad(const AudioMsgId &audio) {
  130. loadData(audio);
  131. }
  132. void Loaders::loadData(AudioMsgId audio, crl::time positionMs) {
  133. auto type = audio.type();
  134. auto setup = setupLoader(audio, positionMs);
  135. const auto l = setup.loader;
  136. if (!l) {
  137. if (setup.errorAtStart) {
  138. emitError(type);
  139. }
  140. return;
  141. }
  142. const auto sampleSize = l->sampleSize();
  143. const auto speedChanged = !EqualSpeeds(setup.newSpeed, setup.oldSpeed);
  144. auto updatedWithSpeed = speedChanged
  145. ? rebufferOnSpeedChange(setup)
  146. : std::optional<Mixer::Track::WithSpeed>();
  147. if (!speedChanged && setup.oldSpeed > 0.) {
  148. const auto normalPosition = Mixer::Track::SpeedIndependentPosition(
  149. setup.position,
  150. setup.oldSpeed);
  151. l->dropFramesTill(normalPosition);
  152. }
  153. const auto started = setup.justStarted;
  154. auto finished = false;
  155. auto waiting = false;
  156. auto errAtStart = started;
  157. auto accumulated = QByteArray();
  158. auto accumulatedCount = 0;
  159. if (l->holdsSavedDecodedSamples()) {
  160. l->takeSavedDecodedSamples(&accumulated);
  161. accumulatedCount = accumulated.size() / sampleSize;
  162. }
  163. const auto accumulateTill = l->bytesPerBuffer();
  164. while (accumulated.size() < accumulateTill) {
  165. using Error = AudioPlayerLoader::ReadError;
  166. const auto result = l->readMore();
  167. if (result == Error::Retry) {
  168. continue;
  169. }
  170. const auto sampleBytes = v::is<bytes::const_span>(result)
  171. ? v::get<bytes::const_span>(result)
  172. : bytes::const_span();
  173. if (!sampleBytes.empty()) {
  174. accumulated.append(
  175. reinterpret_cast<const char*>(sampleBytes.data()),
  176. sampleBytes.size());
  177. accumulatedCount += sampleBytes.size() / sampleSize;
  178. } else if (result == Error::Other) {
  179. if (errAtStart) {
  180. {
  181. QMutexLocker lock(internal::audioPlayerMutex());
  182. if (auto track = checkLoader(type)) {
  183. track->state.state = State::StoppedAtStart;
  184. }
  185. }
  186. emitError(type);
  187. return;
  188. }
  189. finished = true;
  190. break;
  191. } else if (result == Error::EndOfFile) {
  192. finished = true;
  193. break;
  194. } else if (result == Error::Wait) {
  195. waiting = (accumulated.size() < accumulateTill)
  196. && (accumulated.isEmpty() || !l->forceToBuffer());
  197. if (waiting) {
  198. l->saveDecodedSamples(&accumulated);
  199. }
  200. break;
  201. } else if (v::is<bytes::const_span>(result)) {
  202. errAtStart = false;
  203. }
  204. QMutexLocker lock(internal::audioPlayerMutex());
  205. if (!checkLoader(type)) {
  206. clear(type);
  207. return;
  208. }
  209. }
  210. QMutexLocker lock(internal::audioPlayerMutex());
  211. auto track = checkLoader(type);
  212. if (!track) {
  213. clear(type);
  214. return;
  215. }
  216. if (started || !accumulated.isEmpty() || updatedWithSpeed) {
  217. Audio::AttachToDevice();
  218. }
  219. if (started) {
  220. Assert(!updatedWithSpeed);
  221. track->started();
  222. if (!internal::audioCheckError()) {
  223. setStoppedState(track, State::StoppedAtStart);
  224. emitError(type);
  225. return;
  226. }
  227. track->format = l->format();
  228. track->state.frequency = l->samplesFrequency();
  229. track->state.position = (positionMs * track->state.frequency)
  230. / 1000LL;
  231. track->updateWithSpeedPosition();
  232. track->withSpeed.bufferedPosition = track->withSpeed.position;
  233. track->withSpeed.fadeStartPosition = track->withSpeed.position;
  234. } else if (updatedWithSpeed) {
  235. auto old = Mixer::Track();
  236. old.stream = base::take(track->stream);
  237. old.withSpeed = std::exchange(track->withSpeed, *updatedWithSpeed);
  238. track->speed = setup.newSpeed;
  239. track->reattach(type);
  240. old.detach();
  241. }
  242. if (!accumulated.isEmpty()) {
  243. track->ensureStreamCreated(type);
  244. auto bufferIndex = track->getNotQueuedBufferIndex();
  245. if (!internal::audioCheckError()) {
  246. setStoppedState(track, State::StoppedAtError);
  247. emitError(type);
  248. return;
  249. }
  250. if (bufferIndex < 0) { // No free buffers, wait.
  251. track->waitingForBuffer = true;
  252. l->saveDecodedSamples(&accumulated);
  253. return;
  254. } else if (l->forceToBuffer()) {
  255. l->setForceToBuffer(false);
  256. }
  257. track->waitingForBuffer = false;
  258. track->withSpeed.buffered[bufferIndex] = accumulated;
  259. track->withSpeed.samples[bufferIndex] = accumulatedCount;
  260. track->withSpeed.bufferedLength += accumulatedCount;
  261. alBufferData(
  262. track->stream.buffers[bufferIndex],
  263. track->format,
  264. accumulated.constData(),
  265. accumulated.size(),
  266. track->state.frequency);
  267. alSourceQueueBuffers(
  268. track->stream.source,
  269. 1,
  270. track->stream.buffers + bufferIndex);
  271. if (!internal::audioCheckError()) {
  272. setStoppedState(track, State::StoppedAtError);
  273. emitError(type);
  274. return;
  275. }
  276. } else {
  277. if (waiting) {
  278. return;
  279. }
  280. finished = true;
  281. }
  282. track->state.waitingForData = false;
  283. if (finished) {
  284. track->loaded = true;
  285. track->withSpeed.length = track->withSpeed.bufferedPosition
  286. + track->withSpeed.bufferedLength;
  287. track->state.length = Mixer::Track::SpeedIndependentPosition(
  288. track->withSpeed.length,
  289. track->speed);
  290. }
  291. track->loading = false;
  292. if (IsPausedOrPausing(track->state.state)
  293. || IsStoppedOrStopping(track->state.state)) {
  294. return;
  295. }
  296. ALint state = AL_INITIAL;
  297. alGetSourcei(track->stream.source, AL_SOURCE_STATE, &state);
  298. if (!internal::audioCheckError()) {
  299. setStoppedState(track, State::StoppedAtError);
  300. emitError(type);
  301. return;
  302. }
  303. if (state == AL_PLAYING) {
  304. return;
  305. } else if (state == AL_STOPPED && !internal::CheckAudioDeviceConnected()) {
  306. return;
  307. }
  308. alSourcef(track->stream.source, AL_GAIN, ComputeVolume(type));
  309. if (!internal::audioCheckError()) {
  310. setStoppedState(track, State::StoppedAtError);
  311. emitError(type);
  312. return;
  313. }
  314. if (state == AL_STOPPED) {
  315. alSourcei(
  316. track->stream.source,
  317. AL_SAMPLE_OFFSET,
  318. qMax(track->withSpeed.position - track->withSpeed.bufferedPosition, 0LL));
  319. if (!internal::audioCheckError()) {
  320. setStoppedState(track, State::StoppedAtError);
  321. emitError(type);
  322. return;
  323. }
  324. }
  325. alSourcePlay(track->stream.source);
  326. if (!internal::audioCheckError()) {
  327. setStoppedState(track, State::StoppedAtError);
  328. emitError(type);
  329. return;
  330. }
  331. needToCheck();
  332. }
  333. Loaders::SetupLoaderResult Loaders::setupLoader(
  334. const AudioMsgId &audio,
  335. crl::time positionMs) {
  336. QMutexLocker lock(internal::audioPlayerMutex());
  337. if (!mixer()) {
  338. return {};
  339. }
  340. auto track = mixer()->trackForType(audio.type());
  341. if (!track || track->state.id != audio || !track->loading) {
  342. error(audio);
  343. LOG(("Audio Error: trying to load part of audio, that is not current at the moment"));
  344. return {};
  345. }
  346. bool isGoodId = false;
  347. AudioPlayerLoader *l = nullptr;
  348. switch (audio.type()) {
  349. case AudioMsgId::Type::Voice: l = _audioLoader.get(); isGoodId = (_audio == audio); break;
  350. case AudioMsgId::Type::Song: l = _songLoader.get(); isGoodId = (_song == audio); break;
  351. case AudioMsgId::Type::Video: l = _videoLoader.get(); isGoodId = (_video == audio); break;
  352. }
  353. if (l && (!isGoodId || !l->check(track->file, track->data))) {
  354. clear(audio.type());
  355. l = nullptr;
  356. }
  357. auto SpeedDependentPosition = Mixer::Track::SpeedDependentPosition;
  358. if (!l) {
  359. std::unique_ptr<AudioPlayerLoader> *loader = nullptr;
  360. switch (audio.type()) {
  361. case AudioMsgId::Type::Voice: _audio = audio; loader = &_audioLoader; break;
  362. case AudioMsgId::Type::Song: _song = audio; loader = &_songLoader; break;
  363. case AudioMsgId::Type::Video: _video = audio; loader = &_videoLoader; break;
  364. }
  365. if (audio.externalPlayId()) {
  366. if (!track->externalData) {
  367. clear(audio.type());
  368. track->state.state = State::StoppedAtError;
  369. error(audio);
  370. LOG(("Audio Error: video sound data not ready"));
  371. return {};
  372. }
  373. *loader = std::make_unique<ChildFFMpegLoader>(
  374. std::move(track->externalData));
  375. } else {
  376. *loader = std::make_unique<FFMpegLoader>(
  377. track->file,
  378. track->data,
  379. bytes::vector());
  380. }
  381. l = loader->get();
  382. track->speed = track->nextSpeed;
  383. if (!l->open(positionMs, track->speed)) {
  384. track->state.state = State::StoppedAtStart;
  385. return { .errorAtStart = true };
  386. }
  387. const auto duration = l->duration();
  388. if (duration <= 0) {
  389. track->state.state = State::StoppedAtStart;
  390. return { .errorAtStart = true };
  391. }
  392. track->state.frequency = l->samplesFrequency();
  393. track->state.length = (duration * track->state.frequency) / 1000;
  394. track->withSpeed.length = SpeedDependentPosition(
  395. track->state.length,
  396. track->speed);
  397. return { .loader = l, .justStarted = true };
  398. } else if (!EqualSpeeds(track->nextSpeed, track->speed)) {
  399. return {
  400. .loader = l,
  401. .oldSpeed = track->speed,
  402. .newSpeed = track->nextSpeed,
  403. .fadeStartPosition = track->withSpeed.fadeStartPosition,
  404. .position = track->withSpeed.fineTunedPosition,
  405. .normalLength = track->state.length,
  406. .frequency = track->state.frequency,
  407. };
  408. } else if (track->loaded) {
  409. LOG(("Audio Error: trying to load part of audio, that is already loaded to the end"));
  410. return {};
  411. }
  412. return {
  413. .loader = l,
  414. .oldSpeed = track->speed,
  415. .newSpeed = track->nextSpeed,
  416. .position = track->withSpeed.fineTunedPosition,
  417. .frequency = track->state.frequency,
  418. };
  419. }
  420. Mixer::Track::WithSpeed Loaders::rebufferOnSpeedChange(
  421. const SetupLoaderResult &setup) {
  422. Expects(setup.oldSpeed > 0. && setup.newSpeed > 0.);
  423. Expects(setup.loader != nullptr);
  424. const auto speed = setup.newSpeed;
  425. const auto change = setup.oldSpeed / speed;
  426. const auto normalPosition = Mixer::Track::SpeedIndependentPosition(
  427. setup.position,
  428. setup.oldSpeed);
  429. const auto newPosition = int64(base::SafeRound(setup.position * change));
  430. auto result = Mixer::Track::WithSpeed{
  431. .fineTunedPosition = newPosition,
  432. .position = newPosition,
  433. .length = Mixer::Track::SpeedDependentPosition(
  434. setup.normalLength,
  435. speed),
  436. .fadeStartPosition = int64(
  437. base::SafeRound(setup.fadeStartPosition * change)),
  438. };
  439. const auto l = setup.loader;
  440. l->dropFramesTill(normalPosition);
  441. const auto normalFrom = l->startReadingQueuedFrames(speed);
  442. if (normalFrom < 0) {
  443. result.bufferedPosition = newPosition;
  444. return result;
  445. }
  446. result.bufferedPosition = Mixer::Track::SpeedDependentPosition(
  447. normalFrom,
  448. speed);
  449. for (auto i = 0; i != Mixer::Track::kBuffersCount; ++i) {
  450. auto finished = false;
  451. auto accumulated = QByteArray();
  452. auto accumulatedCount = int64();
  453. const auto sampleSize = l->sampleSize();
  454. const auto accumulateTill = l->bytesPerBuffer();
  455. while (accumulated.size() < accumulateTill) {
  456. const auto result = l->readMore();
  457. const auto sampleBytes = v::is<bytes::const_span>(result)
  458. ? v::get<bytes::const_span>(result)
  459. : bytes::const_span();
  460. if (!sampleBytes.empty()) {
  461. accumulated.append(
  462. reinterpret_cast<const char*>(sampleBytes.data()),
  463. sampleBytes.size());
  464. accumulatedCount += sampleBytes.size() / sampleSize;
  465. continue;
  466. } else if (result == AudioPlayerLoader::ReadError::Retry) {
  467. continue;
  468. }
  469. Assert(result == AudioPlayerLoader::ReadError::RetryNotQueued
  470. || result == AudioPlayerLoader::ReadError::EndOfFile);
  471. finished = true;
  472. break;
  473. }
  474. if (!accumulated.isEmpty()) {
  475. result.samples[i] = accumulatedCount;
  476. result.bufferedLength += accumulatedCount;
  477. result.buffered[i] = accumulated;
  478. }
  479. if (finished) {
  480. break;
  481. }
  482. }
  483. const auto limit = result.bufferedPosition + result.bufferedLength;
  484. if (newPosition > limit) {
  485. result.fineTunedPosition = limit;
  486. result.position = limit;
  487. }
  488. if (limit > result.length) {
  489. result.length = limit;
  490. }
  491. return result;
  492. }
  493. Mixer::Track *Loaders::checkLoader(AudioMsgId::Type type) {
  494. if (!mixer()) return nullptr;
  495. auto track = mixer()->trackForType(type);
  496. auto isGoodId = false;
  497. AudioPlayerLoader *l = nullptr;
  498. switch (type) {
  499. case AudioMsgId::Type::Voice: l = _audioLoader.get(); isGoodId = (track->state.id == _audio); break;
  500. case AudioMsgId::Type::Song: l = _songLoader.get(); isGoodId = (track->state.id == _song); break;
  501. case AudioMsgId::Type::Video: l = _videoLoader.get(); isGoodId = (track->state.id == _video); break;
  502. }
  503. if (!l || !track) return nullptr;
  504. if (!isGoodId || !track->loading || !l->check(track->file, track->data)) {
  505. LOG(("Audio Error: playing changed while loading"));
  506. return nullptr;
  507. }
  508. return track;
  509. }
  510. void Loaders::onCancel(const AudioMsgId &audio) {
  511. Expects(audio.type() != AudioMsgId::Type::Unknown);
  512. switch (audio.type()) {
  513. case AudioMsgId::Type::Voice: if (_audio == audio) clear(audio.type()); break;
  514. case AudioMsgId::Type::Song: if (_song == audio) clear(audio.type()); break;
  515. case AudioMsgId::Type::Video: if (_video == audio) clear(audio.type()); break;
  516. }
  517. QMutexLocker lock(internal::audioPlayerMutex());
  518. if (!mixer()) return;
  519. for (auto i = 0; i != kTogetherLimit; ++i) {
  520. auto track = mixer()->trackForType(audio.type(), i);
  521. if (track->state.id == audio) {
  522. track->loading = false;
  523. }
  524. }
  525. }
  526. Loaders::~Loaders() = default;
  527. } // namespace Player
  528. } // namespace Media