av_player.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #ifndef AV_PLAYER_H
  2. #define AV_PLAYER_H
  3. #include <QObject>
  4. #include <QSharedPointer>
  5. #include <QSize>
  6. #include <atomic>
  7. #include "av_clock.h"
  8. #include "av_decoder.h"
  9. #include "sonic.h"
  10. extern "C" {
  11. #include <SDL.h>
  12. }
  13. #include "ffmpeg_compat.h"
  14. using AVTool::Decoder;
  15. class VideoFrame;
  16. typedef Decoder::MyFrame MyFrame;
  17. class AVPlayer : public QObject
  18. {
  19. Q_OBJECT
  20. friend void fillAStreamCallback(void* userdata, uint8_t* stream, int len);
  21. public:
  22. enum PlayState { AV_STOPPED, AV_PLAYING, AV_PAUSED };
  23. // 新增:同步主时钟类型
  24. enum SyncType { SYNC_AUDIO, SYNC_VIDEO, SYNC_EXTERNAL };
  25. AVPlayer();
  26. ~AVPlayer();
  27. int play(const QString& url);
  28. void pause(bool isPause);
  29. void clearPlayer();
  30. AVTool::MediaInfo* detectMediaInfo(const QString& url);
  31. AVPlayer::PlayState playState();
  32. void setVFrameSize(const QSize& size)
  33. {
  34. m_imageWidth = size.width();
  35. m_imageHeight = size.height();
  36. }
  37. inline void setVolume(int volumePer)
  38. {
  39. m_volume = (volumePer * SDL_MIX_MAXVOLUME / 100) % (SDL_MIX_MAXVOLUME + 1);
  40. }
  41. // 新增:设置同步主时钟类型(默认外部时钟,适合直播/RTSP)
  42. inline void setSyncType(SyncType type) { m_syncType = type; }
  43. // 修改:根据选定主时钟进行seek,使用微秒时间戳
  44. inline void seekBy(int32_t time_s)
  45. {
  46. int64_t baseUs = masterClockUs();
  47. int32_t baseSeconds = static_cast<int32_t>(baseUs / 1000000);
  48. seekTo(baseSeconds + time_s);
  49. }
  50. inline void seekTo(int32_t time_s)
  51. {
  52. if (playState() == AV_STOPPED)
  53. return;
  54. if (time_s < 0)
  55. time_s = 0;
  56. int64_t baseUs = masterClockUs();
  57. int32_t baseSeconds = static_cast<int32_t>(baseUs / 1000000);
  58. m_decoder->seekTo(time_s, time_s - baseSeconds);
  59. }
  60. inline uint32_t avDuration() { return m_duration; }
  61. inline void setSpeed(float speed) { m_playSpeed = speed; }
  62. signals:
  63. void frameChanged(QSharedPointer<VideoFrame> frame);
  64. void AVTerminate();
  65. void AVPtsChanged(unsigned int pts);
  66. void AVDurationChanged(unsigned int duration);
  67. private:
  68. int initSDL();
  69. int initVideo();
  70. void videoCallback(std::shared_ptr<void> par);
  71. double computeTargetDelay(double delay);
  72. double vpDuration(MyFrame* lastFrame, MyFrame* curFrame);
  73. void displayImage(AVFrame* frame);
  74. void initAVClock();
  75. // 新增:获取当前主时钟(微秒)
  76. inline int64_t masterClockUs()
  77. {
  78. switch (m_syncType) {
  79. case SYNC_AUDIO:
  80. return m_audioClock.getClock();
  81. case SYNC_VIDEO:
  82. return m_videoClock.getClock();
  83. case SYNC_EXTERNAL:
  84. default:
  85. return m_extClock.getClock();
  86. }
  87. }
  88. private:
  89. //解码器实例
  90. Decoder* m_decoder;
  91. AVFormatContext* m_fmtCtx;
  92. AVCodecParameters* m_audioCodecPar;
  93. SwrContext* m_swrCtx;
  94. uint8_t* m_audioBuf;
  95. sonicStream m_sonicStream;
  96. uint32_t m_audioBufSize;
  97. uint32_t m_audioBufIndex;
  98. uint32_t m_duration;
  99. uint32_t m_lastAudPts;
  100. enum AVSampleFormat m_targetSampleFmt;
  101. //记录音视频帧最新播放帧的时间戳,用于同步
  102. // double m_audioPts;
  103. // double m_videoPts;
  104. std::atomic<float> m_playSpeed;
  105. //延时时间
  106. double m_delay;
  107. //音频播放时钟
  108. AVClock m_audioClock;
  109. //视频播放时钟
  110. AVClock m_videoClock;
  111. // 新增:外部时钟(以系统时钟为基准)
  112. AVClock m_extClock;
  113. // 新增:PTS基线(微秒),用于将首帧归零,避免绝对PTS导致的巨幅偏差
  114. int64_t m_audioStartPtsUs = -1;
  115. int64_t m_videoStartPtsUs = -1;
  116. int m_targetChannels;
  117. int m_targetFreq;
  118. int m_targetChannelLayout;
  119. int m_targetNbSamples;
  120. int m_volume;
  121. //同步时钟初始化标志,音视频异步线程
  122. //谁先读到初始标志位就由谁初始化时钟
  123. int m_clockInitFlag;
  124. int m_audioIndex;
  125. int m_videoIndex;
  126. int m_imageWidth;
  127. int m_imageHeight;
  128. //终止标志
  129. std::atomic<int> m_exit;
  130. //记录暂停前的时间(微秒)
  131. int64_t m_pauseTimeUs;
  132. //暂停时钟快照(微秒)
  133. int64_t m_pauseAudClockUs = 0;
  134. int64_t m_pauseVidClockUs = 0;
  135. int64_t m_pauseExtClockUs = 0;
  136. //暂停标志
  137. std::atomic<int> m_pause;
  138. AVFrame* m_audioFrame;
  139. AVCodecParameters* m_videoCodecPar;
  140. enum AVPixelFormat m_dstPixFmt;
  141. int m_swsFlags;
  142. SwsContext* m_swsCtx;
  143. uint8_t* m_buffer;
  144. uint8_t* m_pixels[4];
  145. int m_pitch[4];
  146. // 新增:是否存在音频/视频流
  147. bool m_hasAudio = false;
  148. bool m_hasVideo = false;
  149. // 性能优化:添加高精度时间基准(微秒)
  150. int64_t m_baseTimeUs = 0; // 高精度时间基准(微秒)
  151. int64_t m_frameTimerUs = 0; // 高精度帧定时器(微秒)
  152. int m_performanceFrameCount = 0; // 性能监控帧计数
  153. double m_lastDelayValue = 0.0; // 上次延迟值,用于延迟累积检测
  154. // 新增:同步主时钟类型(默认外部时钟,同步策略更接近ffplay -sync ext)
  155. SyncType m_syncType = SYNC_EXTERNAL;
  156. };
  157. #endif