audio_output.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. #include "audio_output.h"
  2. #include "../base/logger.h"
  3. #include <QAudioDeviceInfo>
  4. #include <QDebug>
  5. #include <algorithm>
  6. #include <cstring>
  7. extern "C" {
  8. #include <libavutil/channel_layout.h>
  9. #include <libavutil/avutil.h>
  10. #include <libavutil/time.h>
  11. #include <libswresample/swresample.h>
  12. }
  13. namespace av {
  14. namespace player {
  15. AudioOutput::AudioOutput(QObject* parent)
  16. : QObject(parent)
  17. , m_audioOutput(nullptr)
  18. , m_audioDevice(nullptr)
  19. , m_sampleRate(44100)
  20. , m_channels(2)
  21. , m_inputFormat(AV_SAMPLE_FMT_S16)
  22. , m_swrContext(nullptr)
  23. , m_needResampling(false)
  24. , m_volume(1.0)
  25. , m_playbackSpeed(1.0)
  26. , m_lastAudioPts(0.0)
  27. , m_initialized(false)
  28. , m_playing(false)
  29. {
  30. }
  31. AudioOutput::~AudioOutput()
  32. {
  33. stop();
  34. cleanupResampler();
  35. if (m_audioOutput) {
  36. delete m_audioOutput;
  37. m_audioOutput = nullptr;
  38. }
  39. }
  40. bool AudioOutput::initialize(int sampleRate, int channels, AVSampleFormat sampleFormat)
  41. {
  42. QMutexLocker locker(&m_mutex);
  43. if (m_initialized) {
  44. av::Logger::instance().warning("Audio output already initialized");
  45. return true;
  46. }
  47. m_sampleRate = sampleRate;
  48. m_channels = channels;
  49. m_inputFormat = sampleFormat;
  50. // 设置Qt音频格式
  51. m_audioFormat.setSampleRate(sampleRate);
  52. m_audioFormat.setChannelCount(channels);
  53. m_audioFormat.setSampleSize(16); // 输出16位
  54. m_audioFormat.setCodec("audio/pcm");
  55. m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);
  56. m_audioFormat.setSampleType(QAudioFormat::SignedInt);
  57. // 检查设备是否支持该格式
  58. QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
  59. if (!deviceInfo.isFormatSupported(m_audioFormat)) {
  60. av::Logger::instance().warning("Audio format not supported, using nearest format");
  61. m_audioFormat = deviceInfo.nearestFormat(m_audioFormat);
  62. // 记录实际使用的格式
  63. av::Logger::instance().info("Using audio format: " +
  64. std::to_string(m_audioFormat.sampleRate()) + "Hz, " +
  65. std::to_string(m_audioFormat.channelCount()) + "ch, " +
  66. std::to_string(m_audioFormat.sampleSize()) + "bit");
  67. }
  68. // 创建音频输出设备
  69. m_audioOutput = new QAudioOutput(m_audioFormat, this);
  70. if (!m_audioOutput) {
  71. av::Logger::instance().error("Failed to create audio output device");
  72. return false;
  73. }
  74. // 设置缓冲区大小
  75. m_audioOutput->setBufferSize(32768); // 32KB缓冲区
  76. // 连接状态变化信号
  77. connect(m_audioOutput, &QAudioOutput::stateChanged,
  78. this, &AudioOutput::onStateChanged);
  79. // 记录音频格式信息
  80. av::Logger::instance().info("Audio format: " +
  81. std::to_string(m_audioFormat.sampleRate()) + "Hz, " +
  82. std::to_string(m_audioFormat.channelCount()) + "ch, " +
  83. std::to_string(m_audioFormat.sampleSize()) + "bit, " +
  84. m_audioFormat.codec().toStdString());
  85. // 初始化重采样器(如果需要)
  86. if (!initResampler()) {
  87. av::Logger::instance().error("Failed to initialize audio resampler");
  88. return false;
  89. }
  90. m_initialized = true;
  91. av::Logger::instance().info("Audio output initialized successfully");
  92. return true;
  93. }
  94. void AudioOutput::start()
  95. {
  96. QMutexLocker locker(&m_mutex);
  97. if (!m_initialized || !m_audioOutput) {
  98. av::Logger::instance().error("Audio output not initialized");
  99. return;
  100. }
  101. if (m_playing) {
  102. return;
  103. }
  104. av::Logger::instance().debug("Starting audio output device...");
  105. av::Logger::instance().debug("Audio output state before start: " + std::to_string(m_audioOutput->state()));
  106. // 检查音频格式
  107. QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
  108. av::Logger::instance().debug("Default audio device: " + deviceInfo.deviceName().toStdString());
  109. av::Logger::instance().debug("Audio format supported: " + std::to_string(deviceInfo.isFormatSupported(m_audioFormat)));
  110. // 确保音频输出设备处于正确状态
  111. if (m_audioOutput->state() == QAudio::StoppedState) {
  112. av::Logger::instance().debug("Resetting audio output device");
  113. m_audioOutput->reset();
  114. // 给设备一点时间重置
  115. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  116. }
  117. // 如果设备不支持当前格式,尝试使用最接近的格式
  118. if (!deviceInfo.isFormatSupported(m_audioFormat)) {
  119. av::Logger::instance().warning("Audio format not supported, using nearest format");
  120. QAudioFormat nearestFormat = deviceInfo.nearestFormat(m_audioFormat);
  121. // m_audioOutput->setFormat(nearestFormat);
  122. av::Logger::instance().info("Using nearest format: " +
  123. std::to_string(nearestFormat.sampleRate()) + "Hz, " +
  124. std::to_string(nearestFormat.channelCount()) + "ch, " +
  125. std::to_string(nearestFormat.sampleSize()) + "bit");
  126. }
  127. m_audioDevice = m_audioOutput->start();
  128. if (!m_audioDevice) {
  129. av::Logger::instance().error("Failed to start audio output device");
  130. return;
  131. }
  132. av::Logger::instance().debug("Audio device started, waiting for active state...");
  133. // 等待音频设备进入活动状态
  134. int maxWaitMs = 2000; // 最多等待2秒
  135. int waitMs = 0;
  136. while (m_audioOutput->state() != QAudio::ActiveState && waitMs < maxWaitMs) {
  137. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  138. waitMs += 10;
  139. if (waitMs % 100 == 0) {
  140. av::Logger::instance().debug("Audio output state: " + std::to_string(m_audioOutput->state()) +
  141. " (waited " + std::to_string(waitMs) + "ms)");
  142. }
  143. }
  144. if (m_audioOutput->state() != QAudio::ActiveState) {
  145. av::Logger::instance().error("Audio device failed to enter active state: " + std::to_string(m_audioOutput->state()));
  146. m_audioDevice = nullptr;
  147. return;
  148. }
  149. av::Logger::instance().debug("Audio device entered active state");
  150. // 初始化并启动Synchronizer
  151. if (!m_synchronizer) {
  152. av::utils::SyncConfig syncConfig;
  153. syncConfig.strategy = av::utils::SyncStrategy::AUDIO_MASTER;
  154. syncConfig.syncThreshold = 0.04; // 40ms,与AVPlayer2一致
  155. syncConfig.maxAudioDelay = 0.1; // 100ms
  156. m_synchronizer = std::make_shared<av::utils::Synchronizer>(syncConfig);
  157. m_synchronizer->initialize();
  158. m_synchronizer->start();
  159. }
  160. m_playing = true;
  161. av::Logger::instance().info("Audio output started successfully");
  162. }
  163. void AudioOutput::stop()
  164. {
  165. QMutexLocker locker(&m_mutex);
  166. if (!m_playing || !m_audioOutput) {
  167. return;
  168. }
  169. m_audioOutput->stop();
  170. m_audioDevice = nullptr;
  171. m_playing = false;
  172. // 停止Synchronizer
  173. if (m_synchronizer) {
  174. m_synchronizer->stop();
  175. }
  176. av::Logger::instance().info("Audio output stopped");
  177. }
  178. void AudioOutput::pause()
  179. {
  180. QMutexLocker locker(&m_mutex);
  181. if (!m_playing || !m_audioOutput) {
  182. return;
  183. }
  184. m_audioOutput->suspend();
  185. av::Logger::instance().info("Audio output paused");
  186. }
  187. void AudioOutput::resume()
  188. {
  189. QMutexLocker locker(&m_mutex);
  190. if (!m_playing || !m_audioOutput) {
  191. return;
  192. }
  193. m_audioOutput->resume();
  194. av::Logger::instance().info("Audio output resumed");
  195. }
  196. bool AudioOutput::writeFrame(const AVFramePtr& frame)
  197. {
  198. if (!frame || !m_playing || !m_audioDevice) {
  199. av::Logger::instance().debug("Audio write failed: frame=" + std::to_string(frame != nullptr) +
  200. ", playing=" + std::to_string(m_playing) + ", device=" + std::to_string(m_audioDevice != nullptr));
  201. return false;
  202. }
  203. // 检查音频设备状态
  204. if (m_audioOutput && m_audioOutput->state() != QAudio::ActiveState) {
  205. av::Logger::instance().warning("Audio device not in active state: " + std::to_string(m_audioOutput->state()));
  206. return false;
  207. }
  208. // 使用Synchronizer进行时间同步
  209. if (frame->pts != AV_NOPTS_VALUE && m_synchronizer) {
  210. // 计算音频PTS(转换为秒)
  211. double audioPts = (double)frame->pts / AV_TIME_BASE;
  212. // 更新音频时钟
  213. m_synchronizer->setAudioClock(audioPts);
  214. // 计算同步延迟
  215. double delay = 0.0;
  216. ErrorCode result = m_synchronizer->synchronizeAudio(audioPts, delay);
  217. if (result == ErrorCode::SUCCESS && delay > 0) {
  218. // 应用播放速度控制
  219. delay = delay / m_playbackSpeed;
  220. // 限制最大延迟时间,避免异常情况
  221. const double MAX_DELAY = 0.1; // 100ms
  222. if (delay > 0 && delay < MAX_DELAY) {
  223. int delayUs = static_cast<int>(delay * 1000000);
  224. av_usleep(delayUs);
  225. }
  226. }
  227. m_lastAudioPts = audioPts;
  228. }
  229. // 转换音频帧格式
  230. QByteArray audioData = convertFrame(frame);
  231. if (audioData.isEmpty()) {
  232. av::Logger::instance().warning("Audio frame conversion failed");
  233. return false;
  234. }
  235. // 应用音量控制
  236. applyVolume(audioData);
  237. // 写入音频设备 - 添加异常处理
  238. try {
  239. qint64 bytesWritten = m_audioDevice->write(audioData);
  240. if (bytesWritten != audioData.size()) {
  241. av::Logger::instance().warning("Audio write incomplete: " +
  242. std::to_string(bytesWritten) + "/" + std::to_string(audioData.size()));
  243. return false;
  244. }
  245. av::Logger::instance().debug("Audio frame written successfully: " +
  246. std::to_string(audioData.size()) + " bytes");
  247. return true;
  248. } catch (const std::exception& e) {
  249. av::Logger::instance().error("Exception during audio write: " + std::string(e.what()));
  250. return false;
  251. } catch (...) {
  252. av::Logger::instance().error("Unknown exception during audio write");
  253. return false;
  254. }
  255. }
  256. void AudioOutput::setVolume(double volume)
  257. {
  258. m_volume = std::clamp(volume, 0.0, 1.0);
  259. if (m_audioOutput) {
  260. m_audioOutput->setVolume(m_volume);
  261. }
  262. }
  263. double AudioOutput::getVolume() const
  264. {
  265. return m_volume;
  266. }
  267. void AudioOutput::setPlaybackSpeed(double speed)
  268. {
  269. speed = std::max(0.1, std::min(4.0, speed));
  270. m_playbackSpeed = speed;
  271. // 同时更新Synchronizer的播放速度
  272. if (m_synchronizer) {
  273. m_synchronizer->setPlaybackSpeed(speed);
  274. }
  275. av::Logger::instance().debug("Audio playback speed set to: " + std::to_string(speed));
  276. }
  277. double AudioOutput::getPlaybackSpeed() const
  278. {
  279. return m_playbackSpeed;
  280. }
  281. void AudioOutput::flush()
  282. {
  283. QMutexLocker locker(&m_mutex);
  284. if (m_audioOutput) {
  285. m_audioOutput->reset();
  286. }
  287. }
  288. int AudioOutput::getBufferSize() const
  289. {
  290. if (m_audioOutput) {
  291. return m_audioOutput->bufferSize() * 1000 /
  292. (m_audioFormat.sampleRate() * m_audioFormat.channelCount() *
  293. m_audioFormat.sampleSize() / 8);
  294. }
  295. return 0;
  296. }
  297. bool AudioOutput::isPlaying() const
  298. {
  299. return m_playing;
  300. }
  301. void AudioOutput::onStateChanged(QAudio::State state)
  302. {
  303. switch (state) {
  304. case QAudio::ActiveState:
  305. av::Logger::instance().debug("Audio output state: Active");
  306. break;
  307. case QAudio::SuspendedState:
  308. av::Logger::instance().debug("Audio output state: Suspended");
  309. break;
  310. case QAudio::StoppedState:
  311. av::Logger::instance().debug("Audio output state: Stopped");
  312. break;
  313. case QAudio::IdleState:
  314. av::Logger::instance().debug("Audio output state: Idle");
  315. break;
  316. }
  317. }
  318. bool AudioOutput::initResampler()
  319. {
  320. // 检查是否需要重采样
  321. bool needSampleRateConversion = (m_audioFormat.sampleRate() != m_sampleRate);
  322. bool needChannelConversion = (m_audioFormat.channelCount() != m_channels);
  323. bool needFormatConversion = (m_inputFormat != AV_SAMPLE_FMT_S16);
  324. m_needResampling = needSampleRateConversion || needChannelConversion || needFormatConversion;
  325. if (!m_needResampling) {
  326. av::Logger::instance().info("No audio resampling needed");
  327. return true;
  328. }
  329. // 创建重采样上下文
  330. m_swrContext = swr_alloc();
  331. if (!m_swrContext) {
  332. av::Logger::instance().error("Failed to allocate resampler context");
  333. return false;
  334. }
  335. // 设置输入参数
  336. AVChannelLayout inputLayout;
  337. av_channel_layout_default(&inputLayout, m_channels);
  338. // 设置输出参数
  339. AVChannelLayout outputLayout;
  340. av_channel_layout_default(&outputLayout, m_audioFormat.channelCount());
  341. // 配置重采样器
  342. int ret = swr_alloc_set_opts2(&m_swrContext,
  343. &outputLayout, AV_SAMPLE_FMT_S16, m_audioFormat.sampleRate(),
  344. &inputLayout, m_inputFormat, m_sampleRate,
  345. 0, nullptr);
  346. if (ret < 0) {
  347. av::Logger::instance().error("Failed to set resampler options");
  348. swr_free(&m_swrContext);
  349. return false;
  350. }
  351. // 初始化重采样器
  352. ret = swr_init(m_swrContext);
  353. if (ret < 0) {
  354. av::Logger::instance().error("Failed to initialize resampler");
  355. swr_free(&m_swrContext);
  356. return false;
  357. }
  358. av::Logger::instance().info("Audio resampler initialized successfully");
  359. return true;
  360. }
  361. void AudioOutput::cleanupResampler()
  362. {
  363. if (m_swrContext) {
  364. swr_free(&m_swrContext);
  365. m_swrContext = nullptr;
  366. }
  367. }
  368. QByteArray AudioOutput::convertFrame(const AVFramePtr& frame)
  369. {
  370. if (!frame) {
  371. return QByteArray();
  372. }
  373. if (!m_needResampling) {
  374. // 直接复制数据
  375. int dataSize = frame->nb_samples * m_channels * sizeof(int16_t);
  376. return QByteArray(reinterpret_cast<const char*>(frame->data[0]), dataSize);
  377. }
  378. if (!m_swrContext) {
  379. av::Logger::instance().error("Resampler not initialized");
  380. return QByteArray();
  381. }
  382. // 计算输出采样数
  383. int outputSamples = swr_get_out_samples(m_swrContext, frame->nb_samples);
  384. if (outputSamples <= 0) {
  385. return QByteArray();
  386. }
  387. // 分配输出缓冲区
  388. int outputChannels = m_audioFormat.channelCount();
  389. int outputDataSize = outputSamples * outputChannels * sizeof(int16_t);
  390. QByteArray outputData(outputDataSize, 0);
  391. uint8_t* outputBuffer = reinterpret_cast<uint8_t*>(outputData.data());
  392. // 执行重采样
  393. int convertedSamples = swr_convert(m_swrContext,
  394. &outputBuffer, outputSamples,
  395. const_cast<const uint8_t**>(frame->data), frame->nb_samples);
  396. if (convertedSamples < 0) {
  397. av::Logger::instance().error("Audio resampling failed");
  398. return QByteArray();
  399. }
  400. // 调整输出数据大小
  401. int actualDataSize = convertedSamples * outputChannels * sizeof(int16_t);
  402. outputData.resize(actualDataSize);
  403. return outputData;
  404. }
  405. void AudioOutput::applyVolume(QByteArray& data)
  406. {
  407. if (std::abs(m_volume - 1.0) < 0.001) {
  408. return; // 音量为1.0,无需调整
  409. }
  410. int16_t* samples = reinterpret_cast<int16_t*>(data.data());
  411. int sampleCount = data.size() / sizeof(int16_t);
  412. for (int i = 0; i < sampleCount; ++i) {
  413. samples[i] = static_cast<int16_t>(samples[i] * m_volume);
  414. }
  415. }
  416. } // namespace player
  417. } // namespace av