audio_output.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. #include "audio_output.h"
  2. #include "../base/logger.h"
  3. #include "../utils/utils_synchronizer_v2.h"
  4. #include <QAudioDeviceInfo>
  5. #include <QDebug>
  6. #include <algorithm>
  7. #include <cstring>
  8. #include <thread>
  9. #include <chrono>
  10. extern "C" {
  11. #include <libavutil/channel_layout.h>
  12. #include <libavutil/avutil.h>
  13. #include <libavutil/time.h>
  14. #include <libswresample/swresample.h>
  15. }
  16. namespace av {
  17. namespace player {
  18. AudioOutput::AudioOutput(QObject* parent)
  19. : QObject(parent)
  20. , m_audioOutput(nullptr)
  21. , m_audioDevice(nullptr)
  22. , m_sampleRate(44100)
  23. , m_channels(2)
  24. , m_inputFormat(AV_SAMPLE_FMT_S16)
  25. , m_swrContext(nullptr)
  26. , m_needResampling(false)
  27. , m_volume(1.0)
  28. , m_playbackSpeed(1.0)
  29. , m_lastAudioPts(0.0)
  30. , m_initialized(false)
  31. , m_playing(false)
  32. {
  33. }
  34. AudioOutput::~AudioOutput()
  35. {
  36. stop();
  37. cleanupResampler();
  38. if (m_audioOutput) {
  39. delete m_audioOutput;
  40. m_audioOutput = nullptr;
  41. }
  42. }
  43. bool AudioOutput::initialize(int sampleRate, int channels, AVSampleFormat sampleFormat)
  44. {
  45. QMutexLocker locker(&m_mutex);
  46. if (m_initialized) {
  47. av::Logger::instance().warning("Audio output already initialized");
  48. return true;
  49. }
  50. m_sampleRate = sampleRate;
  51. m_channels = channels;
  52. m_inputFormat = sampleFormat;
  53. // 设置Qt音频格式
  54. m_audioFormat.setSampleRate(sampleRate);
  55. m_audioFormat.setChannelCount(channels);
  56. m_audioFormat.setSampleSize(16); // 输出16位
  57. m_audioFormat.setCodec("audio/pcm");
  58. m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);
  59. m_audioFormat.setSampleType(QAudioFormat::SignedInt);
  60. // 检查设备是否支持该格式
  61. QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
  62. if (!deviceInfo.isFormatSupported(m_audioFormat)) {
  63. av::Logger::instance().warning("Audio format not supported, using nearest format");
  64. m_audioFormat = deviceInfo.nearestFormat(m_audioFormat);
  65. // 记录实际使用的格式
  66. av::Logger::instance().info("Using audio format: " +
  67. std::to_string(m_audioFormat.sampleRate()) + "Hz, " +
  68. std::to_string(m_audioFormat.channelCount()) + "ch, " +
  69. std::to_string(m_audioFormat.sampleSize()) + "bit");
  70. }
  71. // 创建音频输出设备
  72. m_audioOutput = new QAudioOutput(m_audioFormat, this);
  73. if (!m_audioOutput) {
  74. av::Logger::instance().error("Failed to create audio output device");
  75. return false;
  76. }
  77. // 设置缓冲区大小
  78. m_audioOutput->setBufferSize(32768); // 32KB缓冲区
  79. // 连接状态变化信号
  80. connect(m_audioOutput, &QAudioOutput::stateChanged,
  81. this, &AudioOutput::onStateChanged);
  82. // 记录音频格式信息
  83. av::Logger::instance().info("Audio format: " +
  84. std::to_string(m_audioFormat.sampleRate()) + "Hz, " +
  85. std::to_string(m_audioFormat.channelCount()) + "ch, " +
  86. std::to_string(m_audioFormat.sampleSize()) + "bit, " +
  87. m_audioFormat.codec().toStdString());
  88. // 初始化重采样器(如果需要)
  89. if (!initResampler()) {
  90. av::Logger::instance().error("Failed to initialize audio resampler");
  91. return false;
  92. }
  93. m_initialized = true;
  94. av::Logger::instance().info("Audio output initialized successfully");
  95. return true;
  96. }
  97. void AudioOutput::start()
  98. {
  99. QMutexLocker locker(&m_mutex);
  100. if (!m_initialized || !m_audioOutput) {
  101. av::Logger::instance().error("Audio output not initialized");
  102. return;
  103. }
  104. if (m_playing) {
  105. return;
  106. }
  107. av::Logger::instance().debug("Starting audio output device...");
  108. av::Logger::instance().debug("Audio output state before start: " + std::to_string(m_audioOutput->state()));
  109. // 检查音频格式
  110. QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
  111. av::Logger::instance().debug("Default audio device: " + deviceInfo.deviceName().toStdString());
  112. av::Logger::instance().debug("Audio format supported: " + std::to_string(deviceInfo.isFormatSupported(m_audioFormat)));
  113. // 确保音频输出设备处于正确状态
  114. if (m_audioOutput->state() == QAudio::StoppedState) {
  115. av::Logger::instance().debug("Resetting audio output device");
  116. m_audioOutput->reset();
  117. // 给设备一点时间重置
  118. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  119. }
  120. // 如果设备不支持当前格式,尝试使用最接近的格式
  121. if (!deviceInfo.isFormatSupported(m_audioFormat)) {
  122. av::Logger::instance().warning("Audio format not supported, using nearest format");
  123. QAudioFormat nearestFormat = deviceInfo.nearestFormat(m_audioFormat);
  124. // m_audioOutput->setFormat(nearestFormat);
  125. av::Logger::instance().info("Using nearest format: " +
  126. std::to_string(nearestFormat.sampleRate()) + "Hz, " +
  127. std::to_string(nearestFormat.channelCount()) + "ch, " +
  128. std::to_string(nearestFormat.sampleSize()) + "bit");
  129. }
  130. // 尝试多次启动音频设备
  131. int retryCount = 0;
  132. const int maxRetries = 5; // 增加重试次数
  133. bool deviceStarted = false;
  134. while (retryCount < maxRetries && !deviceStarted) {
  135. if (retryCount > 0) {
  136. av::Logger::instance().info("Retrying audio device start (attempt " + std::to_string(retryCount + 1) + "/" + std::to_string(maxRetries) + ")");
  137. // 重新创建音频输出设备
  138. if (m_audioOutput) {
  139. m_audioOutput->stop();
  140. delete m_audioOutput;
  141. m_audioOutput = nullptr;
  142. }
  143. // 等待更长时间让系统释放音频资源
  144. std::this_thread::sleep_for(std::chrono::milliseconds(500));
  145. m_audioOutput = new QAudioOutput(m_audioFormat, this);
  146. if (!m_audioOutput) {
  147. av::Logger::instance().error("Failed to recreate audio output device");
  148. return;
  149. }
  150. m_audioOutput->setBufferSize(32768);
  151. connect(m_audioOutput, &QAudioOutput::stateChanged, this, &AudioOutput::onStateChanged);
  152. }
  153. // 检查音频设备可用性
  154. QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
  155. if (deviceInfo.isNull()) {
  156. av::Logger::instance().error("No audio output device available");
  157. return;
  158. }
  159. av::Logger::instance().debug("Starting audio device (attempt " + std::to_string(retryCount + 1) + ")");
  160. m_audioDevice = m_audioOutput->start();
  161. if (!m_audioDevice) {
  162. av::Logger::instance().warning("Failed to start audio output device (attempt " + std::to_string(retryCount + 1) + ")");
  163. retryCount++;
  164. continue;
  165. }
  166. av::Logger::instance().debug("Audio device started, waiting for active state...");
  167. // 写入一些静音数据来激活设备
  168. QByteArray silentData(2048, 0); // 增加静音数据大小
  169. qint64 written = m_audioDevice->write(silentData);
  170. av::Logger::instance().debug("Written silent data: " + std::to_string(written) + " bytes");
  171. // 等待音频设备进入活动状态
  172. int maxWaitMs = 2000; // 增加等待时间到2秒
  173. int waitMs = 0;
  174. while (m_audioOutput->state() != QAudio::ActiveState && waitMs < maxWaitMs) {
  175. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  176. waitMs += 100;
  177. if (waitMs % 500 == 0) {
  178. av::Logger::instance().debug("Audio output state: " + std::to_string(m_audioOutput->state()) +
  179. " (waited " + std::to_string(waitMs) + "ms)");
  180. // 尝试再次写入数据激活设备
  181. if (m_audioDevice && m_audioOutput->state() == QAudio::IdleState) {
  182. QByteArray moreData(1024, 0);
  183. m_audioDevice->write(moreData);
  184. }
  185. }
  186. }
  187. if (m_audioOutput->state() == QAudio::ActiveState) {
  188. deviceStarted = true;
  189. av::Logger::instance().info("Audio device successfully entered active state");
  190. } else if (m_audioOutput->state() == QAudio::IdleState) {
  191. // IdleState也可以接受,表示设备已准备好但暂时没有数据
  192. deviceStarted = true;
  193. av::Logger::instance().info("Audio device in idle state, ready for playback");
  194. } else {
  195. av::Logger::instance().warning("Audio device failed to enter active/idle state: " + std::to_string(m_audioOutput->state()) + " (attempt " + std::to_string(retryCount + 1) + ")");
  196. m_audioDevice = nullptr;
  197. retryCount++;
  198. }
  199. }
  200. if (!deviceStarted) {
  201. av::Logger::instance().error("Failed to start audio device after " + std::to_string(maxRetries) + " attempts");
  202. m_initialized = false;
  203. return;
  204. }
  205. av::Logger::instance().debug("Audio device entered active state");
  206. m_playing = true;
  207. av::Logger::instance().info("Audio output started successfully");
  208. }
  209. void AudioOutput::stop()
  210. {
  211. QMutexLocker locker(&m_mutex);
  212. if (!m_playing || !m_audioOutput) {
  213. return;
  214. }
  215. m_audioOutput->stop();
  216. m_audioDevice = nullptr;
  217. m_playing = false;
  218. av::Logger::instance().info("Audio output stopped");
  219. }
  220. void AudioOutput::pause()
  221. {
  222. QMutexLocker locker(&m_mutex);
  223. if (!m_playing || !m_audioOutput) {
  224. return;
  225. }
  226. m_audioOutput->suspend();
  227. av::Logger::instance().info("Audio output paused");
  228. }
  229. void AudioOutput::resume()
  230. {
  231. QMutexLocker locker(&m_mutex);
  232. if (!m_playing || !m_audioOutput) {
  233. return;
  234. }
  235. m_audioOutput->resume();
  236. av::Logger::instance().info("Audio output resumed");
  237. }
  238. bool AudioOutput::writeFrame(const AVFramePtr& frame)
  239. {
  240. if (!frame || !m_playing || !m_audioDevice) {
  241. av::Logger::instance().debug("Audio write failed: frame=" + std::to_string(frame != nullptr) +
  242. ", playing=" + std::to_string(m_playing) + ", device=" + std::to_string(m_audioDevice != nullptr));
  243. return false;
  244. }
  245. // 检查是否是EOF帧,EOF帧不需要处理,直接返回成功
  246. if (!frame->data[0] && frame->nb_samples == 0) {
  247. av::Logger::instance().debug("Received EOF frame in audio output, ignoring");
  248. return true;
  249. }
  250. // 检查音频设备状态 - 允许ActiveState和IdleState
  251. if (m_audioOutput) {
  252. QAudio::State currentState = m_audioOutput->state();
  253. if (currentState != QAudio::ActiveState && currentState != QAudio::IdleState) {
  254. av::Logger::instance().warning("Audio device not in playable state: " + std::to_string(currentState));
  255. // 尝试重新启动设备
  256. if (currentState == QAudio::StoppedState) {
  257. av::Logger::instance().info("Attempting to restart stopped audio device");
  258. m_audioDevice = m_audioOutput->start();
  259. if (!m_audioDevice) {
  260. av::Logger::instance().error("Failed to restart audio device");
  261. return false;
  262. }
  263. // 写入静音数据激活设备
  264. QByteArray silentData(1024, 0);
  265. m_audioDevice->write(silentData);
  266. // 短暂等待设备状态更新
  267. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  268. currentState = m_audioOutput->state();
  269. if (currentState != QAudio::ActiveState && currentState != QAudio::IdleState) {
  270. av::Logger::instance().error("Audio device restart failed, state: " + std::to_string(currentState));
  271. return false;
  272. }
  273. } else {
  274. return false;
  275. }
  276. }
  277. }
  278. // 使用Synchronizer进行时间同步
  279. if (frame->pts != AV_NOPTS_VALUE && m_synchronizer) {
  280. // 使用原始PTS值和时间基准
  281. int64_t audioPts = frame->pts;
  282. double timeBase = 1.0 / AV_TIME_BASE; // 假设使用AV_TIME_BASE作为时间基准
  283. // 更新音频时钟
  284. m_synchronizer->setAudioClock(audioPts, timeBase);
  285. // 计算同步延迟
  286. double delay = 0.0;
  287. auto decision = m_synchronizer->shouldPlayAudioFrame(audioPts, timeBase);
  288. ErrorCode result = decision.action == av::utils::FrameAction::DISPLAY ? ErrorCode::SUCCESS : ErrorCode::PROCESSING_ERROR;
  289. delay = decision.delay;
  290. if (result == ErrorCode::SUCCESS && delay > 0) {
  291. // 应用播放速度控制
  292. delay = delay / m_playbackSpeed;
  293. // 限制最大延迟时间,避免异常情况
  294. const double MAX_DELAY = 0.1; // 100ms
  295. if (delay > 0 && delay < MAX_DELAY) {
  296. int delayUs = static_cast<int>(delay * 1000000);
  297. av_usleep(delayUs);
  298. }
  299. }
  300. m_lastAudioPts = audioPts * timeBase; // 转换为秒用于记录
  301. }
  302. // 转换音频帧格式
  303. QByteArray audioData = convertFrame(frame);
  304. if (audioData.isEmpty()) {
  305. av::Logger::instance().warning("Audio frame conversion failed");
  306. return false;
  307. }
  308. // 应用音量控制
  309. applyVolume(audioData);
  310. // 写入音频设备 - 添加重试机制和异常处理
  311. const int maxRetries = 10;
  312. const int retryDelayMs = 5;
  313. for (int retry = 0; retry < maxRetries; ++retry) {
  314. try {
  315. qint64 bytesWritten = m_audioDevice->write(audioData);
  316. if (bytesWritten == audioData.size()) {
  317. av::Logger::instance().debug("Audio frame written successfully: " +
  318. std::to_string(audioData.size()) + " bytes");
  319. return true;
  320. }
  321. // 写入不完整,记录警告并重试
  322. av::Logger::instance().warning("Audio write incomplete (attempt " +
  323. std::to_string(retry + 1) + "/" + std::to_string(maxRetries) + "): " +
  324. std::to_string(bytesWritten) + "/" + std::to_string(audioData.size()));
  325. // 如果不是最后一次重试,等待一段时间再重试
  326. if (retry < maxRetries - 1) {
  327. std::this_thread::sleep_for(std::chrono::milliseconds(retryDelayMs));
  328. }
  329. } catch (const std::exception& e) {
  330. av::Logger::instance().error("Exception during audio write (attempt " +
  331. std::to_string(retry + 1) + "): " + std::string(e.what()));
  332. if (retry < maxRetries - 1) {
  333. std::this_thread::sleep_for(std::chrono::milliseconds(retryDelayMs));
  334. }
  335. } catch (...) {
  336. av::Logger::instance().error("Unknown exception during audio write (attempt " +
  337. std::to_string(retry + 1) + ")");
  338. if (retry < maxRetries - 1) {
  339. std::this_thread::sleep_for(std::chrono::milliseconds(retryDelayMs));
  340. }
  341. }
  342. }
  343. av::Logger::instance().error("Audio write failed after " + std::to_string(maxRetries) + " attempts");
  344. return false;
  345. }
  346. void AudioOutput::setVolume(double volume)
  347. {
  348. m_volume = std::clamp(volume, 0.0, 1.0);
  349. if (m_audioOutput) {
  350. m_audioOutput->setVolume(m_volume);
  351. }
  352. }
  353. double AudioOutput::getVolume() const
  354. {
  355. return m_volume;
  356. }
  357. void AudioOutput::setPlaybackSpeed(double speed)
  358. {
  359. speed = std::max(0.1, std::min(4.0, speed));
  360. m_playbackSpeed = speed;
  361. // 同时更新Synchronizer的播放速度
  362. if (m_synchronizer) {
  363. m_synchronizer->setPlaybackSpeed(speed);
  364. }
  365. av::Logger::instance().debug("Audio playback speed set to: " + std::to_string(speed));
  366. }
  367. double AudioOutput::getPlaybackSpeed() const
  368. {
  369. return m_playbackSpeed;
  370. }
  371. void AudioOutput::flush()
  372. {
  373. QMutexLocker locker(&m_mutex);
  374. if (m_audioOutput) {
  375. m_audioOutput->reset();
  376. }
  377. }
  378. int AudioOutput::getBufferSize() const
  379. {
  380. if (m_audioOutput) {
  381. return m_audioOutput->bufferSize() * 1000 /
  382. (m_audioFormat.sampleRate() * m_audioFormat.channelCount() *
  383. m_audioFormat.sampleSize() / 8);
  384. }
  385. return 0;
  386. }
  387. bool AudioOutput::isPlaying() const
  388. {
  389. return m_playing;
  390. }
  391. void AudioOutput::setSynchronizer(std::shared_ptr<av::utils::SynchronizerV2> synchronizer)
  392. {
  393. QMutexLocker locker(&m_mutex);
  394. m_synchronizer = synchronizer;
  395. av::Logger::instance().info("Audio output synchronizer set");
  396. }
  397. void AudioOutput::onStateChanged(QAudio::State state)
  398. {
  399. switch (state) {
  400. case QAudio::ActiveState:
  401. av::Logger::instance().debug("Audio output state: Active");
  402. break;
  403. case QAudio::SuspendedState:
  404. av::Logger::instance().debug("Audio output state: Suspended");
  405. break;
  406. case QAudio::StoppedState:
  407. av::Logger::instance().debug("Audio output state: Stopped");
  408. break;
  409. case QAudio::IdleState:
  410. av::Logger::instance().debug("Audio output state: Idle");
  411. break;
  412. }
  413. }
  414. bool AudioOutput::initResampler()
  415. {
  416. // 检查是否需要重采样
  417. bool needSampleRateConversion = (m_audioFormat.sampleRate() != m_sampleRate);
  418. bool needChannelConversion = (m_audioFormat.channelCount() != m_channels);
  419. bool needFormatConversion = (m_inputFormat != AV_SAMPLE_FMT_S16);
  420. m_needResampling = needSampleRateConversion || needChannelConversion || needFormatConversion;
  421. if (!m_needResampling) {
  422. av::Logger::instance().info("No audio resampling needed");
  423. return true;
  424. }
  425. // 创建重采样上下文
  426. m_swrContext = swr_alloc();
  427. if (!m_swrContext) {
  428. av::Logger::instance().error("Failed to allocate resampler context");
  429. return false;
  430. }
  431. // 设置输入参数
  432. AVChannelLayout inputLayout;
  433. av_channel_layout_default(&inputLayout, m_channels);
  434. // 设置输出参数
  435. AVChannelLayout outputLayout;
  436. av_channel_layout_default(&outputLayout, m_audioFormat.channelCount());
  437. // 配置重采样器
  438. int ret = swr_alloc_set_opts2(&m_swrContext,
  439. &outputLayout, AV_SAMPLE_FMT_S16, m_audioFormat.sampleRate(),
  440. &inputLayout, m_inputFormat, m_sampleRate,
  441. 0, nullptr);
  442. if (ret < 0) {
  443. av::Logger::instance().error("Failed to set resampler options");
  444. swr_free(&m_swrContext);
  445. return false;
  446. }
  447. // 初始化重采样器
  448. ret = swr_init(m_swrContext);
  449. if (ret < 0) {
  450. av::Logger::instance().error("Failed to initialize resampler");
  451. swr_free(&m_swrContext);
  452. return false;
  453. }
  454. av::Logger::instance().info("Audio resampler initialized successfully");
  455. return true;
  456. }
  457. void AudioOutput::cleanupResampler()
  458. {
  459. if (m_swrContext) {
  460. swr_free(&m_swrContext);
  461. m_swrContext = nullptr;
  462. }
  463. }
  464. QByteArray AudioOutput::convertFrame(const AVFramePtr& frame)
  465. {
  466. if (!frame) {
  467. av::Logger::instance().error("convertFrame: null frame pointer");
  468. return QByteArray();
  469. }
  470. // 检查帧数据有效性
  471. if (!frame->data[0] || frame->nb_samples <= 0) {
  472. av::Logger::instance().error("convertFrame: invalid frame data, nb_samples=" + std::to_string(frame->nb_samples));
  473. return QByteArray();
  474. }
  475. av::Logger::instance().debug("convertFrame: input samples=" + std::to_string(frame->nb_samples) +
  476. ", channels=" + std::to_string(m_channels) +
  477. ", format=" + std::to_string(m_inputFormat) +
  478. ", need_resampling=" + std::to_string(m_needResampling));
  479. if (!m_needResampling) {
  480. // 直接复制数据
  481. int dataSize = frame->nb_samples * m_channels * sizeof(int16_t);
  482. av::Logger::instance().debug("convertFrame: direct copy, size=" + std::to_string(dataSize));
  483. return QByteArray(reinterpret_cast<const char*>(frame->data[0]), dataSize);
  484. }
  485. if (!m_swrContext) {
  486. av::Logger::instance().error("convertFrame: resampler not initialized");
  487. return QByteArray();
  488. }
  489. // 计算输出采样数
  490. int outputSamples = swr_get_out_samples(m_swrContext, frame->nb_samples);
  491. if (outputSamples <= 0) {
  492. av::Logger::instance().error("convertFrame: invalid output samples=" + std::to_string(outputSamples));
  493. return QByteArray();
  494. }
  495. // 分配输出缓冲区
  496. int outputChannels = m_audioFormat.channelCount();
  497. int outputDataSize = outputSamples * outputChannels * sizeof(int16_t);
  498. QByteArray outputData(outputDataSize, 0);
  499. uint8_t* outputBuffer = reinterpret_cast<uint8_t*>(outputData.data());
  500. av::Logger::instance().debug("convertFrame: resampling " + std::to_string(frame->nb_samples) +
  501. " -> " + std::to_string(outputSamples) + " samples");
  502. // 执行重采样
  503. int convertedSamples = swr_convert(m_swrContext,
  504. &outputBuffer, outputSamples,
  505. const_cast<const uint8_t**>(frame->data), frame->nb_samples);
  506. if (convertedSamples < 0) {
  507. char errorBuf[256];
  508. av_strerror(convertedSamples, errorBuf, sizeof(errorBuf));
  509. av::Logger::instance().error("convertFrame: resampling failed with error " +
  510. std::to_string(convertedSamples) + ": " + std::string(errorBuf));
  511. return QByteArray();
  512. }
  513. // 调整输出数据大小
  514. int actualDataSize = convertedSamples * outputChannels * sizeof(int16_t);
  515. outputData.resize(actualDataSize);
  516. av::Logger::instance().debug("convertFrame: successfully converted " + std::to_string(convertedSamples) +
  517. " samples, output size=" + std::to_string(actualDataSize));
  518. return outputData;
  519. }
  520. void AudioOutput::applyVolume(QByteArray& data)
  521. {
  522. if (std::abs(m_volume - 1.0) < 0.001) {
  523. return; // 音量为1.0,无需调整
  524. }
  525. int16_t* samples = reinterpret_cast<int16_t*>(data.data());
  526. int sampleCount = data.size() / sizeof(int16_t);
  527. for (int i = 0; i < sampleCount; ++i) {
  528. samples[i] = static_cast<int16_t>(samples[i] * m_volume);
  529. }
  530. }
  531. } // namespace player
  532. } // namespace av