🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2188 lines
71 KiB

  1. /*
  2. * An example showing how to play a stream sync'd to video, using ffmpeg.
  3. *
  4. * Requires C++14.
  5. */
  6. #include <condition_variable>
  7. #include <functional>
  8. #include <algorithm>
  9. #include <iostream>
  10. #include <utility>
  11. #include <iomanip>
  12. #include <cstdint>
  13. #include <cstring>
  14. #include <cstdlib>
  15. #include <atomic>
  16. #include <cerrno>
  17. #include <chrono>
  18. #include <cstdio>
  19. #include <future>
  20. #include <memory>
  21. #include <string>
  22. #include <thread>
  23. #include <vector>
  24. #include <array>
  25. #include <cmath>
  26. #include <deque>
  27. #include <mutex>
  28. #include <ratio>
  29. extern "C" {
  30. #ifdef __GNUC__
  31. _Pragma("GCC diagnostic push")
  32. _Pragma("GCC diagnostic ignored \"-Wconversion\"")
  33. _Pragma("GCC diagnostic ignored \"-Wold-style-cast\"")
  34. #endif
  35. #include "libavcodec/avcodec.h"
  36. #include "libavformat/avformat.h"
  37. #include "libavformat/avio.h"
  38. #include "libavformat/version.h"
  39. #include "libavutil/avutil.h"
  40. #include "libavutil/error.h"
  41. #include "libavutil/frame.h"
  42. #include "libavutil/mem.h"
  43. #include "libavutil/pixfmt.h"
  44. #include "libavutil/rational.h"
  45. #include "libavutil/samplefmt.h"
  46. #include "libavutil/time.h"
  47. #include "libavutil/version.h"
  48. #include "libavutil/channel_layout.h"
  49. #include "libswscale/swscale.h"
  50. #include "libswresample/swresample.h"
  51. constexpr auto AVNoPtsValue = AV_NOPTS_VALUE;
  52. constexpr auto AVErrorEOF = AVERROR_EOF;
  53. struct SwsContext;
  54. #ifdef __GNUC__
  55. _Pragma("GCC diagnostic pop")
  56. #endif
  57. }
  58. #include "SDL.h"
  59. #include "AL/alc.h"
  60. #include "AL/al.h"
  61. #include "AL/alext.h"
  62. #include "common/alhelpers.h"
  63. namespace {
  64. inline constexpr int64_t operator "" _i64(unsigned long long int n) noexcept { return static_cast<int64_t>(n); }
  65. #ifndef M_PI
  66. #define M_PI (3.14159265358979323846)
  67. #endif
  68. using fixed32 = std::chrono::duration<int64_t,std::ratio<1,(1_i64<<32)>>;
  69. using nanoseconds = std::chrono::nanoseconds;
  70. using microseconds = std::chrono::microseconds;
  71. using milliseconds = std::chrono::milliseconds;
  72. using seconds = std::chrono::seconds;
  73. using seconds_d64 = std::chrono::duration<double>;
  74. using std::chrono::duration_cast;
  75. const std::string AppName{"alffplay"};
  76. ALenum DirectOutMode{AL_FALSE};
  77. bool EnableWideStereo{false};
  78. bool EnableSuperStereo{false};
  79. bool DisableVideo{false};
  80. LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT;
  81. LPALCGETINTEGER64VSOFT alcGetInteger64vSOFT;
  82. LPALEVENTCONTROLSOFT alEventControlSOFT;
  83. LPALEVENTCALLBACKSOFT alEventCallbackSOFT;
  84. LPALBUFFERCALLBACKSOFT alBufferCallbackSOFT;
  85. ALenum FormatStereo8{AL_FORMAT_STEREO8};
  86. ALenum FormatStereo16{AL_FORMAT_STEREO16};
  87. ALenum FormatStereo32F{AL_FORMAT_STEREO_FLOAT32};
  88. const seconds AVNoSyncThreshold{10};
  89. #define VIDEO_PICTURE_QUEUE_SIZE 24
  90. const seconds_d64 AudioSyncThreshold{0.03};
  91. const milliseconds AudioSampleCorrectionMax{50};
  92. /* Averaging filter coefficient for audio sync. */
  93. #define AUDIO_DIFF_AVG_NB 20
  94. const double AudioAvgFilterCoeff{std::pow(0.01, 1.0/AUDIO_DIFF_AVG_NB)};
  95. /* Per-buffer size, in time */
  96. constexpr milliseconds AudioBufferTime{20};
  97. /* Buffer total size, in time (should be divisible by the buffer time) */
  98. constexpr milliseconds AudioBufferTotalTime{800};
  99. constexpr auto AudioBufferCount = AudioBufferTotalTime / AudioBufferTime;
  100. enum {
  101. FF_MOVIE_DONE_EVENT = SDL_USEREVENT
  102. };
  103. enum class SyncMaster {
  104. Audio,
  105. Video,
  106. External,
  107. Default = Audio
  108. };
  109. inline microseconds get_avtime()
  110. { return microseconds{av_gettime()}; }
  111. /* Define unique_ptrs to auto-cleanup associated ffmpeg objects. */
  112. struct AVIOContextDeleter {
  113. void operator()(AVIOContext *ptr) { avio_closep(&ptr); }
  114. };
  115. using AVIOContextPtr = std::unique_ptr<AVIOContext,AVIOContextDeleter>;
  116. struct AVFormatCtxDeleter {
  117. void operator()(AVFormatContext *ptr) { avformat_close_input(&ptr); }
  118. };
  119. using AVFormatCtxPtr = std::unique_ptr<AVFormatContext,AVFormatCtxDeleter>;
  120. struct AVCodecCtxDeleter {
  121. void operator()(AVCodecContext *ptr) { avcodec_free_context(&ptr); }
  122. };
  123. using AVCodecCtxPtr = std::unique_ptr<AVCodecContext,AVCodecCtxDeleter>;
  124. struct AVPacketDeleter {
  125. void operator()(AVPacket *pkt) { av_packet_free(&pkt); }
  126. };
  127. using AVPacketPtr = std::unique_ptr<AVPacket,AVPacketDeleter>;
  128. struct AVFrameDeleter {
  129. void operator()(AVFrame *ptr) { av_frame_free(&ptr); }
  130. };
  131. using AVFramePtr = std::unique_ptr<AVFrame,AVFrameDeleter>;
  132. struct SwrContextDeleter {
  133. void operator()(SwrContext *ptr) { swr_free(&ptr); }
  134. };
  135. using SwrContextPtr = std::unique_ptr<SwrContext,SwrContextDeleter>;
  136. struct SwsContextDeleter {
  137. void operator()(SwsContext *ptr) { sws_freeContext(ptr); }
  138. };
  139. using SwsContextPtr = std::unique_ptr<SwsContext,SwsContextDeleter>;
  140. template<size_t SizeLimit>
  141. class DataQueue {
  142. std::mutex mPacketMutex, mFrameMutex;
  143. std::condition_variable mPacketCond;
  144. std::condition_variable mInFrameCond, mOutFrameCond;
  145. std::deque<AVPacketPtr> mPackets;
  146. size_t mTotalSize{0};
  147. bool mFinished{false};
  148. AVPacketPtr getPacket()
  149. {
  150. std::unique_lock<std::mutex> plock{mPacketMutex};
  151. while(mPackets.empty() && !mFinished)
  152. mPacketCond.wait(plock);
  153. if(mPackets.empty())
  154. return nullptr;
  155. auto ret = std::move(mPackets.front());
  156. mPackets.pop_front();
  157. mTotalSize -= static_cast<unsigned int>(ret->size);
  158. return ret;
  159. }
  160. public:
  161. int sendPacket(AVCodecContext *codecctx)
  162. {
  163. AVPacketPtr packet{getPacket()};
  164. int ret{};
  165. {
  166. std::unique_lock<std::mutex> flock{mFrameMutex};
  167. while((ret=avcodec_send_packet(codecctx, packet.get())) == AVERROR(EAGAIN))
  168. mInFrameCond.wait_for(flock, milliseconds{50});
  169. }
  170. mOutFrameCond.notify_one();
  171. if(!packet)
  172. {
  173. if(!ret) return AVErrorEOF;
  174. std::cerr<< "Failed to send flush packet: "<<ret <<std::endl;
  175. return ret;
  176. }
  177. if(ret < 0)
  178. std::cerr<< "Failed to send packet: "<<ret <<std::endl;
  179. return ret;
  180. }
  181. int receiveFrame(AVCodecContext *codecctx, AVFrame *frame)
  182. {
  183. int ret{};
  184. {
  185. std::unique_lock<std::mutex> flock{mFrameMutex};
  186. while((ret=avcodec_receive_frame(codecctx, frame)) == AVERROR(EAGAIN))
  187. mOutFrameCond.wait_for(flock, milliseconds{50});
  188. }
  189. mInFrameCond.notify_one();
  190. return ret;
  191. }
  192. void setFinished()
  193. {
  194. {
  195. std::lock_guard<std::mutex> _{mPacketMutex};
  196. mFinished = true;
  197. }
  198. mPacketCond.notify_one();
  199. }
  200. void flush()
  201. {
  202. {
  203. std::lock_guard<std::mutex> _{mPacketMutex};
  204. mFinished = true;
  205. mPackets.clear();
  206. mTotalSize = 0;
  207. }
  208. mPacketCond.notify_one();
  209. }
  210. bool put(const AVPacket *pkt)
  211. {
  212. {
  213. std::unique_lock<std::mutex> lock{mPacketMutex};
  214. if(mTotalSize >= SizeLimit || mFinished)
  215. return false;
  216. mPackets.push_back(AVPacketPtr{av_packet_alloc()});
  217. if(av_packet_ref(mPackets.back().get(), pkt) != 0)
  218. {
  219. mPackets.pop_back();
  220. return true;
  221. }
  222. mTotalSize += static_cast<unsigned int>(mPackets.back()->size);
  223. }
  224. mPacketCond.notify_one();
  225. return true;
  226. }
  227. };
  228. struct MovieState;
  229. struct AudioState {
  230. MovieState &mMovie;
  231. AVStream *mStream{nullptr};
  232. AVCodecCtxPtr mCodecCtx;
  233. DataQueue<2*1024*1024> mQueue;
  234. /* Used for clock difference average computation */
  235. seconds_d64 mClockDiffAvg{0};
  236. /* Time of the next sample to be buffered */
  237. nanoseconds mCurrentPts{0};
  238. /* Device clock time that the stream started at. */
  239. nanoseconds mDeviceStartTime{nanoseconds::min()};
  240. /* Decompressed sample frame, and swresample context for conversion */
  241. AVFramePtr mDecodedFrame;
  242. SwrContextPtr mSwresCtx;
  243. /* Conversion format, for what gets fed to OpenAL */
  244. uint64_t mDstChanLayout{0};
  245. AVSampleFormat mDstSampleFmt{AV_SAMPLE_FMT_NONE};
  246. /* Storage of converted samples */
  247. uint8_t *mSamples{nullptr};
  248. int mSamplesLen{0}; /* In samples */
  249. int mSamplesPos{0};
  250. int mSamplesMax{0};
  251. std::unique_ptr<uint8_t[]> mBufferData;
  252. size_t mBufferDataSize{0};
  253. std::atomic<size_t> mReadPos{0};
  254. std::atomic<size_t> mWritePos{0};
  255. /* OpenAL format */
  256. ALenum mFormat{AL_NONE};
  257. ALuint mFrameSize{0};
  258. std::mutex mSrcMutex;
  259. std::condition_variable mSrcCond;
  260. std::atomic_flag mConnected;
  261. ALuint mSource{0};
  262. std::array<ALuint,AudioBufferCount> mBuffers{};
  263. ALuint mBufferIdx{0};
  264. AudioState(MovieState &movie) : mMovie(movie)
  265. { mConnected.test_and_set(std::memory_order_relaxed); }
  266. ~AudioState()
  267. {
  268. if(mSource)
  269. alDeleteSources(1, &mSource);
  270. if(mBuffers[0])
  271. alDeleteBuffers(static_cast<ALsizei>(mBuffers.size()), mBuffers.data());
  272. av_freep(&mSamples);
  273. }
  274. static void AL_APIENTRY eventCallbackC(ALenum eventType, ALuint object, ALuint param,
  275. ALsizei length, const ALchar *message, void *userParam)
  276. { static_cast<AudioState*>(userParam)->eventCallback(eventType, object, param, length, message); }
  277. void eventCallback(ALenum eventType, ALuint object, ALuint param, ALsizei length,
  278. const ALchar *message);
  279. static ALsizei AL_APIENTRY bufferCallbackC(void *userptr, void *data, ALsizei size)
  280. { return static_cast<AudioState*>(userptr)->bufferCallback(data, size); }
  281. ALsizei bufferCallback(void *data, ALsizei size);
  282. nanoseconds getClockNoLock();
  283. nanoseconds getClock()
  284. {
  285. std::lock_guard<std::mutex> lock{mSrcMutex};
  286. return getClockNoLock();
  287. }
  288. bool startPlayback();
  289. int getSync();
  290. int decodeFrame();
  291. bool readAudio(uint8_t *samples, unsigned int length, int &sample_skip);
  292. bool readAudio(int sample_skip);
  293. int handler();
  294. };
  295. struct VideoState {
  296. MovieState &mMovie;
  297. AVStream *mStream{nullptr};
  298. AVCodecCtxPtr mCodecCtx;
  299. DataQueue<14*1024*1024> mQueue;
  300. /* The pts of the currently displayed frame, and the time (av_gettime) it
  301. * was last updated - used to have running video pts
  302. */
  303. nanoseconds mDisplayPts{0};
  304. microseconds mDisplayPtsTime{microseconds::min()};
  305. std::mutex mDispPtsMutex;
  306. /* Swscale context for format conversion */
  307. SwsContextPtr mSwscaleCtx;
  308. struct Picture {
  309. AVFramePtr mFrame{};
  310. nanoseconds mPts{nanoseconds::min()};
  311. };
  312. std::array<Picture,VIDEO_PICTURE_QUEUE_SIZE> mPictQ;
  313. std::atomic<size_t> mPictQRead{0u}, mPictQWrite{1u};
  314. std::mutex mPictQMutex;
  315. std::condition_variable mPictQCond;
  316. SDL_Texture *mImage{nullptr};
  317. int mWidth{0}, mHeight{0}; /* Full texture size */
  318. bool mFirstUpdate{true};
  319. std::atomic<bool> mEOS{false};
  320. std::atomic<bool> mFinalUpdate{false};
  321. VideoState(MovieState &movie) : mMovie(movie) { }
  322. ~VideoState()
  323. {
  324. if(mImage)
  325. SDL_DestroyTexture(mImage);
  326. mImage = nullptr;
  327. }
  328. nanoseconds getClock();
  329. void display(SDL_Window *screen, SDL_Renderer *renderer, AVFrame *frame);
  330. void updateVideo(SDL_Window *screen, SDL_Renderer *renderer, bool redraw);
  331. int handler();
  332. };
  333. struct MovieState {
  334. AVIOContextPtr mIOContext;
  335. AVFormatCtxPtr mFormatCtx;
  336. SyncMaster mAVSyncType{SyncMaster::Default};
  337. microseconds mClockBase{microseconds::min()};
  338. std::atomic<bool> mQuit{false};
  339. AudioState mAudio;
  340. VideoState mVideo;
  341. std::mutex mStartupMutex;
  342. std::condition_variable mStartupCond;
  343. bool mStartupDone{false};
  344. std::thread mParseThread;
  345. std::thread mAudioThread;
  346. std::thread mVideoThread;
  347. std::string mFilename;
  348. MovieState(std::string fname)
  349. : mAudio(*this), mVideo(*this), mFilename(std::move(fname))
  350. { }
  351. ~MovieState()
  352. {
  353. stop();
  354. if(mParseThread.joinable())
  355. mParseThread.join();
  356. }
  357. static int decode_interrupt_cb(void *ctx);
  358. bool prepare();
  359. void setTitle(SDL_Window *window);
  360. void stop();
  361. nanoseconds getClock();
  362. nanoseconds getMasterClock();
  363. nanoseconds getDuration();
  364. int streamComponentOpen(unsigned int stream_index);
  365. int parse_handler();
  366. };
  367. nanoseconds AudioState::getClockNoLock()
  368. {
  369. // The audio clock is the timestamp of the sample currently being heard.
  370. if(alcGetInteger64vSOFT)
  371. {
  372. // If device start time = min, we aren't playing yet.
  373. if(mDeviceStartTime == nanoseconds::min())
  374. return nanoseconds::zero();
  375. // Get the current device clock time and latency.
  376. auto device = alcGetContextsDevice(alcGetCurrentContext());
  377. ALCint64SOFT devtimes[2]{0,0};
  378. alcGetInteger64vSOFT(device, ALC_DEVICE_CLOCK_LATENCY_SOFT, 2, devtimes);
  379. auto latency = nanoseconds{devtimes[1]};
  380. auto device_time = nanoseconds{devtimes[0]};
  381. // The clock is simply the current device time relative to the recorded
  382. // start time. We can also subtract the latency to get more a accurate
  383. // position of where the audio device actually is in the output stream.
  384. return device_time - mDeviceStartTime - latency;
  385. }
  386. if(mBufferDataSize > 0)
  387. {
  388. if(mDeviceStartTime == nanoseconds::min())
  389. return nanoseconds::zero();
  390. /* With a callback buffer and no device clock, mDeviceStartTime is
  391. * actually the timestamp of the first sample frame played. The audio
  392. * clock, then, is that plus the current source offset.
  393. */
  394. ALint64SOFT offset[2];
  395. if(alGetSourcei64vSOFT)
  396. alGetSourcei64vSOFT(mSource, AL_SAMPLE_OFFSET_LATENCY_SOFT, offset);
  397. else
  398. {
  399. ALint ioffset;
  400. alGetSourcei(mSource, AL_SAMPLE_OFFSET, &ioffset);
  401. offset[0] = ALint64SOFT{ioffset} << 32;
  402. offset[1] = 0;
  403. }
  404. /* NOTE: The source state must be checked last, in case an underrun
  405. * occurs and the source stops between getting the state and retrieving
  406. * the offset+latency.
  407. */
  408. ALint status;
  409. alGetSourcei(mSource, AL_SOURCE_STATE, &status);
  410. nanoseconds pts{};
  411. if(status == AL_PLAYING || status == AL_PAUSED)
  412. pts = mDeviceStartTime - nanoseconds{offset[1]} +
  413. duration_cast<nanoseconds>(fixed32{offset[0] / mCodecCtx->sample_rate});
  414. else
  415. {
  416. /* If the source is stopped, the pts of the next sample to be heard
  417. * is the pts of the next sample to be buffered, minus the amount
  418. * already in the buffer ready to play.
  419. */
  420. const size_t woffset{mWritePos.load(std::memory_order_acquire)};
  421. const size_t roffset{mReadPos.load(std::memory_order_relaxed)};
  422. const size_t readable{((woffset >= roffset) ? woffset : (mBufferDataSize+woffset)) -
  423. roffset};
  424. pts = mCurrentPts - nanoseconds{seconds{readable/mFrameSize}}/mCodecCtx->sample_rate;
  425. }
  426. return pts;
  427. }
  428. /* The source-based clock is based on 4 components:
  429. * 1 - The timestamp of the next sample to buffer (mCurrentPts)
  430. * 2 - The length of the source's buffer queue
  431. * (AudioBufferTime*AL_BUFFERS_QUEUED)
  432. * 3 - The offset OpenAL is currently at in the source (the first value
  433. * from AL_SAMPLE_OFFSET_LATENCY_SOFT)
  434. * 4 - The latency between OpenAL and the DAC (the second value from
  435. * AL_SAMPLE_OFFSET_LATENCY_SOFT)
  436. *
  437. * Subtracting the length of the source queue from the next sample's
  438. * timestamp gives the timestamp of the sample at the start of the source
  439. * queue. Adding the source offset to that results in the timestamp for the
  440. * sample at OpenAL's current position, and subtracting the source latency
  441. * from that gives the timestamp of the sample currently at the DAC.
  442. */
  443. nanoseconds pts{mCurrentPts};
  444. if(mSource)
  445. {
  446. ALint64SOFT offset[2];
  447. if(alGetSourcei64vSOFT)
  448. alGetSourcei64vSOFT(mSource, AL_SAMPLE_OFFSET_LATENCY_SOFT, offset);
  449. else
  450. {
  451. ALint ioffset;
  452. alGetSourcei(mSource, AL_SAMPLE_OFFSET, &ioffset);
  453. offset[0] = ALint64SOFT{ioffset} << 32;
  454. offset[1] = 0;
  455. }
  456. ALint queued, status;
  457. alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued);
  458. alGetSourcei(mSource, AL_SOURCE_STATE, &status);
  459. /* If the source is AL_STOPPED, then there was an underrun and all
  460. * buffers are processed, so ignore the source queue. The audio thread
  461. * will put the source into an AL_INITIAL state and clear the queue
  462. * when it starts recovery.
  463. */
  464. if(status != AL_STOPPED)
  465. {
  466. pts -= AudioBufferTime*queued;
  467. pts += duration_cast<nanoseconds>(fixed32{offset[0] / mCodecCtx->sample_rate});
  468. }
  469. /* Don't offset by the latency if the source isn't playing. */
  470. if(status == AL_PLAYING)
  471. pts -= nanoseconds{offset[1]};
  472. }
  473. return std::max(pts, nanoseconds::zero());
  474. }
  475. bool AudioState::startPlayback()
  476. {
  477. const size_t woffset{mWritePos.load(std::memory_order_acquire)};
  478. const size_t roffset{mReadPos.load(std::memory_order_relaxed)};
  479. const size_t readable{((woffset >= roffset) ? woffset : (mBufferDataSize+woffset)) -
  480. roffset};
  481. if(mBufferDataSize > 0)
  482. {
  483. if(readable == 0)
  484. return false;
  485. if(!alcGetInteger64vSOFT)
  486. mDeviceStartTime = mCurrentPts -
  487. nanoseconds{seconds{readable/mFrameSize}}/mCodecCtx->sample_rate;
  488. }
  489. else
  490. {
  491. ALint queued{};
  492. alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued);
  493. if(queued == 0) return false;
  494. }
  495. alSourcePlay(mSource);
  496. if(alcGetInteger64vSOFT)
  497. {
  498. /* Subtract the total buffer queue time from the current pts to get the
  499. * pts of the start of the queue.
  500. */
  501. int64_t srctimes[2]{0,0};
  502. alGetSourcei64vSOFT(mSource, AL_SAMPLE_OFFSET_CLOCK_SOFT, srctimes);
  503. auto device_time = nanoseconds{srctimes[1]};
  504. auto src_offset = duration_cast<nanoseconds>(fixed32{srctimes[0]}) /
  505. mCodecCtx->sample_rate;
  506. /* The mixer may have ticked and incremented the device time and sample
  507. * offset, so subtract the source offset from the device time to get
  508. * the device time the source started at. Also subtract startpts to get
  509. * the device time the stream would have started at to reach where it
  510. * is now.
  511. */
  512. if(mBufferDataSize > 0)
  513. {
  514. nanoseconds startpts{mCurrentPts -
  515. nanoseconds{seconds{readable/mFrameSize}}/mCodecCtx->sample_rate};
  516. mDeviceStartTime = device_time - src_offset - startpts;
  517. }
  518. else
  519. {
  520. nanoseconds startpts{mCurrentPts - AudioBufferTotalTime};
  521. mDeviceStartTime = device_time - src_offset - startpts;
  522. }
  523. }
  524. return true;
  525. }
  526. int AudioState::getSync()
  527. {
  528. if(mMovie.mAVSyncType == SyncMaster::Audio)
  529. return 0;
  530. auto ref_clock = mMovie.getMasterClock();
  531. auto diff = ref_clock - getClockNoLock();
  532. if(!(diff < AVNoSyncThreshold && diff > -AVNoSyncThreshold))
  533. {
  534. /* Difference is TOO big; reset accumulated average */
  535. mClockDiffAvg = seconds_d64::zero();
  536. return 0;
  537. }
  538. /* Accumulate the diffs */
  539. mClockDiffAvg = mClockDiffAvg*AudioAvgFilterCoeff + diff;
  540. auto avg_diff = mClockDiffAvg*(1.0 - AudioAvgFilterCoeff);
  541. if(avg_diff < AudioSyncThreshold/2.0 && avg_diff > -AudioSyncThreshold)
  542. return 0;
  543. /* Constrain the per-update difference to avoid exceedingly large skips */
  544. diff = std::min<nanoseconds>(diff, AudioSampleCorrectionMax);
  545. return static_cast<int>(duration_cast<seconds>(diff*mCodecCtx->sample_rate).count());
  546. }
  547. int AudioState::decodeFrame()
  548. {
  549. do {
  550. while(int ret{mQueue.receiveFrame(mCodecCtx.get(), mDecodedFrame.get())})
  551. {
  552. if(ret == AVErrorEOF) return 0;
  553. std::cerr<< "Failed to receive frame: "<<ret <<std::endl;
  554. }
  555. } while(mDecodedFrame->nb_samples <= 0);
  556. /* If provided, update w/ pts */
  557. if(mDecodedFrame->best_effort_timestamp != AVNoPtsValue)
  558. mCurrentPts = duration_cast<nanoseconds>(seconds_d64{av_q2d(mStream->time_base) *
  559. static_cast<double>(mDecodedFrame->best_effort_timestamp)});
  560. if(mDecodedFrame->nb_samples > mSamplesMax)
  561. {
  562. av_freep(&mSamples);
  563. av_samples_alloc(&mSamples, nullptr, mCodecCtx->channels, mDecodedFrame->nb_samples,
  564. mDstSampleFmt, 0);
  565. mSamplesMax = mDecodedFrame->nb_samples;
  566. }
  567. /* Return the amount of sample frames converted */
  568. int data_size{swr_convert(mSwresCtx.get(), &mSamples, mDecodedFrame->nb_samples,
  569. const_cast<const uint8_t**>(mDecodedFrame->data), mDecodedFrame->nb_samples)};
  570. av_frame_unref(mDecodedFrame.get());
  571. return data_size;
  572. }
  573. /* Duplicates the sample at in to out, count times. The frame size is a
  574. * multiple of the template type size.
  575. */
  576. template<typename T>
  577. static void sample_dup(uint8_t *out, const uint8_t *in, size_t count, size_t frame_size)
  578. {
  579. auto *sample = reinterpret_cast<const T*>(in);
  580. auto *dst = reinterpret_cast<T*>(out);
  581. if(frame_size == sizeof(T))
  582. std::fill_n(dst, count, *sample);
  583. else
  584. {
  585. /* NOTE: frame_size is a multiple of sizeof(T). */
  586. size_t type_mult{frame_size / sizeof(T)};
  587. size_t i{0};
  588. std::generate_n(dst, count*type_mult,
  589. [sample,type_mult,&i]() -> T
  590. {
  591. T ret = sample[i];
  592. i = (i+1)%type_mult;
  593. return ret;
  594. }
  595. );
  596. }
  597. }
  598. bool AudioState::readAudio(uint8_t *samples, unsigned int length, int &sample_skip)
  599. {
  600. unsigned int audio_size{0};
  601. /* Read the next chunk of data, refill the buffer, and queue it
  602. * on the source */
  603. length /= mFrameSize;
  604. while(mSamplesLen > 0 && audio_size < length)
  605. {
  606. unsigned int rem{length - audio_size};
  607. if(mSamplesPos >= 0)
  608. {
  609. const auto len = static_cast<unsigned int>(mSamplesLen - mSamplesPos);
  610. if(rem > len) rem = len;
  611. std::copy_n(mSamples + static_cast<unsigned int>(mSamplesPos)*mFrameSize,
  612. rem*mFrameSize, samples);
  613. }
  614. else
  615. {
  616. rem = std::min(rem, static_cast<unsigned int>(-mSamplesPos));
  617. /* Add samples by copying the first sample */
  618. if((mFrameSize&7) == 0)
  619. sample_dup<uint64_t>(samples, mSamples, rem, mFrameSize);
  620. else if((mFrameSize&3) == 0)
  621. sample_dup<uint32_t>(samples, mSamples, rem, mFrameSize);
  622. else if((mFrameSize&1) == 0)
  623. sample_dup<uint16_t>(samples, mSamples, rem, mFrameSize);
  624. else
  625. sample_dup<uint8_t>(samples, mSamples, rem, mFrameSize);
  626. }
  627. mSamplesPos += rem;
  628. mCurrentPts += nanoseconds{seconds{rem}} / mCodecCtx->sample_rate;
  629. samples += rem*mFrameSize;
  630. audio_size += rem;
  631. while(mSamplesPos >= mSamplesLen)
  632. {
  633. mSamplesLen = decodeFrame();
  634. mSamplesPos = std::min(mSamplesLen, sample_skip);
  635. if(mSamplesLen <= 0) break;
  636. sample_skip -= mSamplesPos;
  637. // Adjust the device start time and current pts by the amount we're
  638. // skipping/duplicating, so that the clock remains correct for the
  639. // current stream position.
  640. auto skip = nanoseconds{seconds{mSamplesPos}} / mCodecCtx->sample_rate;
  641. mDeviceStartTime -= skip;
  642. mCurrentPts += skip;
  643. continue;
  644. }
  645. }
  646. if(audio_size <= 0)
  647. return false;
  648. if(audio_size < length)
  649. {
  650. const unsigned int rem{length - audio_size};
  651. std::fill_n(samples, rem*mFrameSize,
  652. (mDstSampleFmt == AV_SAMPLE_FMT_U8) ? 0x80 : 0x00);
  653. mCurrentPts += nanoseconds{seconds{rem}} / mCodecCtx->sample_rate;
  654. }
  655. return true;
  656. }
  657. bool AudioState::readAudio(int sample_skip)
  658. {
  659. size_t woffset{mWritePos.load(std::memory_order_acquire)};
  660. while(mSamplesLen > 0)
  661. {
  662. const size_t roffset{mReadPos.load(std::memory_order_relaxed)};
  663. if(mSamplesPos < 0)
  664. {
  665. size_t rem{(((roffset > woffset) ? roffset-1
  666. : ((roffset == 0) ? mBufferDataSize-1
  667. : mBufferDataSize)) - woffset) / mFrameSize};
  668. rem = std::min<size_t>(rem, static_cast<ALuint>(-mSamplesPos));
  669. if(rem == 0) break;
  670. auto *splout{&mBufferData[woffset]};
  671. if((mFrameSize&7) == 0)
  672. sample_dup<uint64_t>(splout, mSamples, rem, mFrameSize);
  673. else if((mFrameSize&3) == 0)
  674. sample_dup<uint32_t>(splout, mSamples, rem, mFrameSize);
  675. else if((mFrameSize&1) == 0)
  676. sample_dup<uint16_t>(splout, mSamples, rem, mFrameSize);
  677. else
  678. sample_dup<uint8_t>(splout, mSamples, rem, mFrameSize);
  679. woffset += rem * mFrameSize;
  680. if(woffset == mBufferDataSize)
  681. woffset = 0;
  682. mWritePos.store(woffset, std::memory_order_release);
  683. mSamplesPos += static_cast<int>(rem);
  684. mCurrentPts += nanoseconds{seconds{rem}} / mCodecCtx->sample_rate;
  685. continue;
  686. }
  687. const size_t boffset{static_cast<ALuint>(mSamplesPos) * size_t{mFrameSize}};
  688. const size_t nbytes{static_cast<ALuint>(mSamplesLen)*size_t{mFrameSize} -
  689. boffset};
  690. if(roffset > woffset)
  691. {
  692. const size_t writable{roffset-woffset-1};
  693. if(writable < nbytes) break;
  694. memcpy(&mBufferData[woffset], mSamples+boffset, nbytes);
  695. woffset += nbytes;
  696. }
  697. else
  698. {
  699. const size_t writable{mBufferDataSize+roffset-woffset-1};
  700. if(writable < nbytes) break;
  701. const size_t todo1{std::min<size_t>(nbytes, mBufferDataSize-woffset)};
  702. const size_t todo2{nbytes - todo1};
  703. memcpy(&mBufferData[woffset], mSamples+boffset, todo1);
  704. woffset += todo1;
  705. if(woffset == mBufferDataSize)
  706. {
  707. woffset = 0;
  708. if(todo2 > 0)
  709. {
  710. memcpy(&mBufferData[woffset], mSamples+boffset+todo1, todo2);
  711. woffset += todo2;
  712. }
  713. }
  714. }
  715. mWritePos.store(woffset, std::memory_order_release);
  716. mCurrentPts += nanoseconds{seconds{mSamplesLen-mSamplesPos}} / mCodecCtx->sample_rate;
  717. do {
  718. mSamplesLen = decodeFrame();
  719. mSamplesPos = std::min(mSamplesLen, sample_skip);
  720. if(mSamplesLen <= 0) return false;
  721. sample_skip -= mSamplesPos;
  722. auto skip = nanoseconds{seconds{mSamplesPos}} / mCodecCtx->sample_rate;
  723. mDeviceStartTime -= skip;
  724. mCurrentPts += skip;
  725. } while(mSamplesPos >= mSamplesLen);
  726. }
  727. return true;
  728. }
  729. void AL_APIENTRY AudioState::eventCallback(ALenum eventType, ALuint object, ALuint param,
  730. ALsizei length, const ALchar *message)
  731. {
  732. if(eventType == AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT)
  733. {
  734. /* Temporarily lock the source mutex to ensure it's not between
  735. * checking the processed count and going to sleep.
  736. */
  737. std::unique_lock<std::mutex>{mSrcMutex}.unlock();
  738. mSrcCond.notify_one();
  739. return;
  740. }
  741. std::cout<< "\n---- AL Event on AudioState "<<this<<" ----\nEvent: ";
  742. switch(eventType)
  743. {
  744. case AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT: std::cout<< "Buffer completed"; break;
  745. case AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT: std::cout<< "Source state changed"; break;
  746. case AL_EVENT_TYPE_DISCONNECTED_SOFT: std::cout<< "Disconnected"; break;
  747. default:
  748. std::cout<< "0x"<<std::hex<<std::setw(4)<<std::setfill('0')<<eventType<<std::dec<<
  749. std::setw(0)<<std::setfill(' '); break;
  750. }
  751. std::cout<< "\n"
  752. "Object ID: "<<object<<"\n"
  753. "Parameter: "<<param<<"\n"
  754. "Message: "<<std::string{message, static_cast<ALuint>(length)}<<"\n----"<<
  755. std::endl;
  756. if(eventType == AL_EVENT_TYPE_DISCONNECTED_SOFT)
  757. {
  758. {
  759. std::lock_guard<std::mutex> lock{mSrcMutex};
  760. mConnected.clear(std::memory_order_release);
  761. }
  762. mSrcCond.notify_one();
  763. }
  764. }
  765. ALsizei AudioState::bufferCallback(void *data, ALsizei size)
  766. {
  767. ALsizei got{0};
  768. size_t roffset{mReadPos.load(std::memory_order_acquire)};
  769. while(got < size)
  770. {
  771. const size_t woffset{mWritePos.load(std::memory_order_relaxed)};
  772. if(woffset == roffset) break;
  773. size_t todo{((woffset < roffset) ? mBufferDataSize : woffset) - roffset};
  774. todo = std::min<size_t>(todo, static_cast<ALuint>(size-got));
  775. memcpy(data, &mBufferData[roffset], todo);
  776. data = static_cast<ALbyte*>(data) + todo;
  777. got += static_cast<ALsizei>(todo);
  778. roffset += todo;
  779. if(roffset == mBufferDataSize)
  780. roffset = 0;
  781. }
  782. mReadPos.store(roffset, std::memory_order_release);
  783. return got;
  784. }
  785. int AudioState::handler()
  786. {
  787. std::unique_lock<std::mutex> srclock{mSrcMutex, std::defer_lock};
  788. milliseconds sleep_time{AudioBufferTime / 3};
  789. struct EventControlManager {
  790. const std::array<ALenum,3> evt_types{{
  791. AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT, AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT,
  792. AL_EVENT_TYPE_DISCONNECTED_SOFT}};
  793. EventControlManager(milliseconds &sleep_time)
  794. {
  795. if(alEventControlSOFT)
  796. {
  797. alEventControlSOFT(static_cast<ALsizei>(evt_types.size()), evt_types.data(),
  798. AL_TRUE);
  799. alEventCallbackSOFT(&AudioState::eventCallbackC, this);
  800. sleep_time = AudioBufferTotalTime;
  801. }
  802. }
  803. ~EventControlManager()
  804. {
  805. if(alEventControlSOFT)
  806. {
  807. alEventControlSOFT(static_cast<ALsizei>(evt_types.size()), evt_types.data(),
  808. AL_FALSE);
  809. alEventCallbackSOFT(nullptr, nullptr);
  810. }
  811. }
  812. };
  813. EventControlManager event_controller{sleep_time};
  814. const bool has_bfmt_ex{alIsExtensionPresent("AL_SOFT_bformat_ex") != AL_FALSE};
  815. ALenum ambi_layout{AL_FUMA_SOFT};
  816. ALenum ambi_scale{AL_FUMA_SOFT};
  817. std::unique_ptr<uint8_t[]> samples;
  818. ALsizei buffer_len{0};
  819. /* Find a suitable format for OpenAL. */
  820. mDstChanLayout = 0;
  821. mFormat = AL_NONE;
  822. if((mCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLTP
  823. || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_DBL
  824. || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_DBLP
  825. || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_S32
  826. || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_S32P
  827. || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_S64
  828. || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_S64P)
  829. && alIsExtensionPresent("AL_EXT_FLOAT32"))
  830. {
  831. mDstSampleFmt = AV_SAMPLE_FMT_FLT;
  832. mFrameSize = 4;
  833. if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
  834. {
  835. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1)
  836. {
  837. mDstChanLayout = mCodecCtx->channel_layout;
  838. mFrameSize *= 8;
  839. mFormat = alGetEnumValue("AL_FORMAT_71CHN32");
  840. }
  841. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1
  842. || mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK)
  843. {
  844. mDstChanLayout = mCodecCtx->channel_layout;
  845. mFrameSize *= 6;
  846. mFormat = alGetEnumValue("AL_FORMAT_51CHN32");
  847. }
  848. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_QUAD)
  849. {
  850. mDstChanLayout = mCodecCtx->channel_layout;
  851. mFrameSize *= 4;
  852. mFormat = alGetEnumValue("AL_FORMAT_QUAD32");
  853. }
  854. }
  855. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
  856. {
  857. mDstChanLayout = mCodecCtx->channel_layout;
  858. mFrameSize *= 1;
  859. mFormat = AL_FORMAT_MONO_FLOAT32;
  860. }
  861. /* Assume 3D B-Format (ambisonics) if the channel layout is blank and
  862. * there's 4 or more channels. FFmpeg/libavcodec otherwise seems to
  863. * have no way to specify if the source is actually B-Format (let alone
  864. * if it's 2D or 3D).
  865. */
  866. if(mCodecCtx->channel_layout == 0 && mCodecCtx->channels >= 4
  867. && alIsExtensionPresent("AL_EXT_BFORMAT"))
  868. {
  869. /* Calculate what should be the ambisonic order from the number of
  870. * channels, and confirm that's the number of channels. Opus allows
  871. * an optional non-diegetic stereo stream with the B-Format stream,
  872. * which we can ignore, so check for that too.
  873. */
  874. auto order = static_cast<int>(std::sqrt(mCodecCtx->channels)) - 1;
  875. int channels{(order+1) * (order+1)};
  876. if(channels == mCodecCtx->channels || channels+2 == mCodecCtx->channels)
  877. {
  878. /* OpenAL only supports first-order with AL_EXT_BFORMAT, which
  879. * is 4 channels for 3D buffers.
  880. */
  881. mFrameSize *= 4;
  882. mFormat = alGetEnumValue("AL_FORMAT_BFORMAT3D_FLOAT32");
  883. }
  884. }
  885. if(!mFormat || mFormat == -1)
  886. {
  887. mDstChanLayout = AV_CH_LAYOUT_STEREO;
  888. mFrameSize *= 2;
  889. mFormat = FormatStereo32F;
  890. }
  891. }
  892. if(mCodecCtx->sample_fmt == AV_SAMPLE_FMT_U8 || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_U8P)
  893. {
  894. mDstSampleFmt = AV_SAMPLE_FMT_U8;
  895. mFrameSize = 1;
  896. if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
  897. {
  898. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1)
  899. {
  900. mDstChanLayout = mCodecCtx->channel_layout;
  901. mFrameSize *= 8;
  902. mFormat = alGetEnumValue("AL_FORMAT_71CHN8");
  903. }
  904. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1
  905. || mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK)
  906. {
  907. mDstChanLayout = mCodecCtx->channel_layout;
  908. mFrameSize *= 6;
  909. mFormat = alGetEnumValue("AL_FORMAT_51CHN8");
  910. }
  911. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_QUAD)
  912. {
  913. mDstChanLayout = mCodecCtx->channel_layout;
  914. mFrameSize *= 4;
  915. mFormat = alGetEnumValue("AL_FORMAT_QUAD8");
  916. }
  917. }
  918. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
  919. {
  920. mDstChanLayout = mCodecCtx->channel_layout;
  921. mFrameSize *= 1;
  922. mFormat = AL_FORMAT_MONO8;
  923. }
  924. if(mCodecCtx->channel_layout == 0 && mCodecCtx->channels >= 4
  925. && alIsExtensionPresent("AL_EXT_BFORMAT"))
  926. {
  927. auto order = static_cast<int>(std::sqrt(mCodecCtx->channels)) - 1;
  928. int channels{(order+1) * (order+1)};
  929. if(channels == mCodecCtx->channels || channels+2 == mCodecCtx->channels)
  930. {
  931. mFrameSize *= 4;
  932. mFormat = alGetEnumValue("AL_FORMAT_BFORMAT3D_8");
  933. }
  934. }
  935. if(!mFormat || mFormat == -1)
  936. {
  937. mDstChanLayout = AV_CH_LAYOUT_STEREO;
  938. mFrameSize *= 2;
  939. mFormat = FormatStereo8;
  940. }
  941. }
  942. if(!mFormat || mFormat == -1)
  943. {
  944. mDstSampleFmt = AV_SAMPLE_FMT_S16;
  945. mFrameSize = 2;
  946. if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
  947. {
  948. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1)
  949. {
  950. mDstChanLayout = mCodecCtx->channel_layout;
  951. mFrameSize *= 8;
  952. mFormat = alGetEnumValue("AL_FORMAT_71CHN16");
  953. }
  954. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1
  955. || mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK)
  956. {
  957. mDstChanLayout = mCodecCtx->channel_layout;
  958. mFrameSize *= 6;
  959. mFormat = alGetEnumValue("AL_FORMAT_51CHN16");
  960. }
  961. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_QUAD)
  962. {
  963. mDstChanLayout = mCodecCtx->channel_layout;
  964. mFrameSize *= 4;
  965. mFormat = alGetEnumValue("AL_FORMAT_QUAD16");
  966. }
  967. }
  968. if(mCodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
  969. {
  970. mDstChanLayout = mCodecCtx->channel_layout;
  971. mFrameSize *= 1;
  972. mFormat = AL_FORMAT_MONO16;
  973. }
  974. if(mCodecCtx->channel_layout == 0 && mCodecCtx->channels >= 4
  975. && alIsExtensionPresent("AL_EXT_BFORMAT"))
  976. {
  977. auto order = static_cast<int>(std::sqrt(mCodecCtx->channels)) - 1;
  978. int channels{(order+1) * (order+1)};
  979. if(channels == mCodecCtx->channels || channels+2 == mCodecCtx->channels)
  980. {
  981. mFrameSize *= 4;
  982. mFormat = alGetEnumValue("AL_FORMAT_BFORMAT3D_16");
  983. }
  984. }
  985. if(!mFormat || mFormat == -1)
  986. {
  987. mDstChanLayout = AV_CH_LAYOUT_STEREO;
  988. mFrameSize *= 2;
  989. mFormat = FormatStereo16;
  990. }
  991. }
  992. mSamples = nullptr;
  993. mSamplesMax = 0;
  994. mSamplesPos = 0;
  995. mSamplesLen = 0;
  996. mDecodedFrame.reset(av_frame_alloc());
  997. if(!mDecodedFrame)
  998. {
  999. std::cerr<< "Failed to allocate audio frame" <<std::endl;
  1000. return 0;
  1001. }
  1002. if(!mDstChanLayout)
  1003. {
  1004. /* OpenAL only supports first-order ambisonics with AL_EXT_BFORMAT, so
  1005. * we have to drop any extra channels.
  1006. */
  1007. mSwresCtx.reset(swr_alloc_set_opts(nullptr,
  1008. (1_i64<<4)-1, mDstSampleFmt, mCodecCtx->sample_rate,
  1009. (1_i64<<mCodecCtx->channels)-1, mCodecCtx->sample_fmt, mCodecCtx->sample_rate,
  1010. 0, nullptr));
  1011. /* Note that ffmpeg/libavcodec has no method to check the ambisonic
  1012. * channel order and normalization, so we can only assume AmbiX as the
  1013. * defacto-standard. This is not true for .amb files, which use FuMa.
  1014. */
  1015. std::vector<double> mtx(64*64, 0.0);
  1016. ambi_layout = AL_ACN_SOFT;
  1017. ambi_scale = AL_SN3D_SOFT;
  1018. if(has_bfmt_ex)
  1019. {
  1020. /* An identity matrix that doesn't remix any channels. */
  1021. std::cout<< "Found AL_SOFT_bformat_ex" <<std::endl;
  1022. mtx[0 + 0*64] = 1.0;
  1023. mtx[1 + 1*64] = 1.0;
  1024. mtx[2 + 2*64] = 1.0;
  1025. mtx[3 + 3*64] = 1.0;
  1026. }
  1027. else
  1028. {
  1029. std::cout<< "Found AL_EXT_BFORMAT" <<std::endl;
  1030. /* Without AL_SOFT_bformat_ex, OpenAL only supports FuMa channel
  1031. * ordering and normalization, so a custom matrix is needed to
  1032. * scale and reorder the source from AmbiX.
  1033. */
  1034. mtx[0 + 0*64] = std::sqrt(0.5);
  1035. mtx[3 + 1*64] = 1.0;
  1036. mtx[1 + 2*64] = 1.0;
  1037. mtx[2 + 3*64] = 1.0;
  1038. }
  1039. swr_set_matrix(mSwresCtx.get(), mtx.data(), 64);
  1040. }
  1041. else
  1042. mSwresCtx.reset(swr_alloc_set_opts(nullptr,
  1043. static_cast<int64_t>(mDstChanLayout), mDstSampleFmt, mCodecCtx->sample_rate,
  1044. mCodecCtx->channel_layout ? static_cast<int64_t>(mCodecCtx->channel_layout)
  1045. : av_get_default_channel_layout(mCodecCtx->channels),
  1046. mCodecCtx->sample_fmt, mCodecCtx->sample_rate,
  1047. 0, nullptr));
  1048. if(!mSwresCtx || swr_init(mSwresCtx.get()) != 0)
  1049. {
  1050. std::cerr<< "Failed to initialize audio converter" <<std::endl;
  1051. return 0;
  1052. }
  1053. alGenBuffers(static_cast<ALsizei>(mBuffers.size()), mBuffers.data());
  1054. alGenSources(1, &mSource);
  1055. if(DirectOutMode)
  1056. alSourcei(mSource, AL_DIRECT_CHANNELS_SOFT, DirectOutMode);
  1057. if(EnableWideStereo)
  1058. {
  1059. const float angles[2]{static_cast<float>(M_PI / 3.0), static_cast<float>(-M_PI / 3.0)};
  1060. alSourcefv(mSource, AL_STEREO_ANGLES, angles);
  1061. }
  1062. if(has_bfmt_ex)
  1063. {
  1064. for(ALuint bufid : mBuffers)
  1065. {
  1066. alBufferi(bufid, AL_AMBISONIC_LAYOUT_SOFT, ambi_layout);
  1067. alBufferi(bufid, AL_AMBISONIC_SCALING_SOFT, ambi_scale);
  1068. }
  1069. }
  1070. #ifdef AL_SOFT_UHJ
  1071. if(EnableSuperStereo)
  1072. alSourcei(mSource, AL_STEREO_MODE_SOFT, AL_SUPER_STEREO_SOFT);
  1073. #endif
  1074. if(alGetError() != AL_NO_ERROR)
  1075. return 0;
  1076. bool callback_ok{false};
  1077. if(alBufferCallbackSOFT)
  1078. {
  1079. alBufferCallbackSOFT(mBuffers[0], mFormat, mCodecCtx->sample_rate, bufferCallbackC, this);
  1080. alSourcei(mSource, AL_BUFFER, static_cast<ALint>(mBuffers[0]));
  1081. if(alGetError() != AL_NO_ERROR)
  1082. {
  1083. fprintf(stderr, "Failed to set buffer callback\n");
  1084. alSourcei(mSource, AL_BUFFER, 0);
  1085. }
  1086. else
  1087. {
  1088. mBufferDataSize = static_cast<size_t>(duration_cast<seconds>(mCodecCtx->sample_rate *
  1089. AudioBufferTotalTime).count()) * mFrameSize;
  1090. mBufferData = std::make_unique<uint8_t[]>(mBufferDataSize);
  1091. std::fill_n(mBufferData.get(), mBufferDataSize, uint8_t{});
  1092. mReadPos.store(0, std::memory_order_relaxed);
  1093. mWritePos.store(mBufferDataSize/mFrameSize/2*mFrameSize, std::memory_order_relaxed);
  1094. ALCint refresh{};
  1095. alcGetIntegerv(alcGetContextsDevice(alcGetCurrentContext()), ALC_REFRESH, 1, &refresh);
  1096. sleep_time = milliseconds{seconds{1}} / refresh;
  1097. callback_ok = true;
  1098. }
  1099. }
  1100. if(!callback_ok)
  1101. buffer_len = static_cast<int>(duration_cast<seconds>(mCodecCtx->sample_rate *
  1102. AudioBufferTime).count() * mFrameSize);
  1103. if(buffer_len > 0)
  1104. samples = std::make_unique<uint8_t[]>(static_cast<ALuint>(buffer_len));
  1105. /* Prefill the codec buffer. */
  1106. auto packet_sender = [this]()
  1107. {
  1108. while(1)
  1109. {
  1110. const int ret{mQueue.sendPacket(mCodecCtx.get())};
  1111. if(ret == AVErrorEOF) break;
  1112. }
  1113. };
  1114. auto sender = std::async(std::launch::async, packet_sender);
  1115. srclock.lock();
  1116. if(alcGetInteger64vSOFT)
  1117. {
  1118. int64_t devtime{};
  1119. alcGetInteger64vSOFT(alcGetContextsDevice(alcGetCurrentContext()), ALC_DEVICE_CLOCK_SOFT,
  1120. 1, &devtime);
  1121. mDeviceStartTime = nanoseconds{devtime} - mCurrentPts;
  1122. }
  1123. mSamplesLen = decodeFrame();
  1124. if(mSamplesLen > 0)
  1125. {
  1126. mSamplesPos = std::min(mSamplesLen, getSync());
  1127. auto skip = nanoseconds{seconds{mSamplesPos}} / mCodecCtx->sample_rate;
  1128. mDeviceStartTime -= skip;
  1129. mCurrentPts += skip;
  1130. }
  1131. while(1)
  1132. {
  1133. ALenum state;
  1134. if(mBufferDataSize > 0)
  1135. {
  1136. alGetSourcei(mSource, AL_SOURCE_STATE, &state);
  1137. /* If mQuit is set, don't actually quit until we can't get more
  1138. * audio, indicating we've reached the flush packet and the packet
  1139. * sender will also quit.
  1140. *
  1141. * If mQuit is not set, don't quit even if there's no more audio,
  1142. * so what's buffered has a chance to play to the real end.
  1143. */
  1144. if(!readAudio(getSync()) && mMovie.mQuit.load(std::memory_order_relaxed))
  1145. goto finish;
  1146. }
  1147. else
  1148. {
  1149. ALint processed, queued;
  1150. /* First remove any processed buffers. */
  1151. alGetSourcei(mSource, AL_BUFFERS_PROCESSED, &processed);
  1152. while(processed > 0)
  1153. {
  1154. ALuint bid;
  1155. alSourceUnqueueBuffers(mSource, 1, &bid);
  1156. --processed;
  1157. }
  1158. /* Refill the buffer queue. */
  1159. int sync_skip{getSync()};
  1160. alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued);
  1161. while(static_cast<ALuint>(queued) < mBuffers.size())
  1162. {
  1163. /* Read the next chunk of data, filling the buffer, and queue
  1164. * it on the source.
  1165. */
  1166. const bool got_audio{readAudio(samples.get(), static_cast<ALuint>(buffer_len),
  1167. sync_skip)};
  1168. if(!got_audio)
  1169. {
  1170. if(mMovie.mQuit.load(std::memory_order_relaxed))
  1171. goto finish;
  1172. break;
  1173. }
  1174. const ALuint bufid{mBuffers[mBufferIdx]};
  1175. mBufferIdx = static_cast<ALuint>((mBufferIdx+1) % mBuffers.size());
  1176. alBufferData(bufid, mFormat, samples.get(), buffer_len, mCodecCtx->sample_rate);
  1177. alSourceQueueBuffers(mSource, 1, &bufid);
  1178. ++queued;
  1179. }
  1180. /* Check that the source is playing. */
  1181. alGetSourcei(mSource, AL_SOURCE_STATE, &state);
  1182. if(state == AL_STOPPED)
  1183. {
  1184. /* AL_STOPPED means there was an underrun. Clear the buffer
  1185. * queue since this likely means we're late, and rewind the
  1186. * source to get it back into an AL_INITIAL state.
  1187. */
  1188. alSourceRewind(mSource);
  1189. alSourcei(mSource, AL_BUFFER, 0);
  1190. if(alcGetInteger64vSOFT)
  1191. {
  1192. /* Also update the device start time with the current
  1193. * device clock, so the decoder knows we're running behind.
  1194. */
  1195. int64_t devtime{};
  1196. alcGetInteger64vSOFT(alcGetContextsDevice(alcGetCurrentContext()),
  1197. ALC_DEVICE_CLOCK_SOFT, 1, &devtime);
  1198. mDeviceStartTime = nanoseconds{devtime} - mCurrentPts;
  1199. }
  1200. continue;
  1201. }
  1202. }
  1203. /* (re)start the source if needed, and wait for a buffer to finish */
  1204. if(state != AL_PLAYING && state != AL_PAUSED)
  1205. {
  1206. if(!startPlayback())
  1207. break;
  1208. }
  1209. if(ALenum err{alGetError()})
  1210. std::cerr<< "Got AL error: 0x"<<std::hex<<err<<std::dec
  1211. << " ("<<alGetString(err)<<")" <<std::endl;
  1212. mSrcCond.wait_for(srclock, sleep_time);
  1213. }
  1214. finish:
  1215. alSourceRewind(mSource);
  1216. alSourcei(mSource, AL_BUFFER, 0);
  1217. srclock.unlock();
  1218. return 0;
  1219. }
  1220. nanoseconds VideoState::getClock()
  1221. {
  1222. /* NOTE: This returns incorrect times while not playing. */
  1223. std::lock_guard<std::mutex> _{mDispPtsMutex};
  1224. if(mDisplayPtsTime == microseconds::min())
  1225. return nanoseconds::zero();
  1226. auto delta = get_avtime() - mDisplayPtsTime;
  1227. return mDisplayPts + delta;
  1228. }
  1229. /* Called by VideoState::updateVideo to display the next video frame. */
  1230. void VideoState::display(SDL_Window *screen, SDL_Renderer *renderer, AVFrame *frame)
  1231. {
  1232. if(!mImage)
  1233. return;
  1234. double aspect_ratio;
  1235. int win_w, win_h;
  1236. int w, h, x, y;
  1237. int frame_width{frame->width - static_cast<int>(frame->crop_left + frame->crop_right)};
  1238. int frame_height{frame->height - static_cast<int>(frame->crop_top + frame->crop_bottom)};
  1239. if(frame->sample_aspect_ratio.num == 0)
  1240. aspect_ratio = 0.0;
  1241. else
  1242. {
  1243. aspect_ratio = av_q2d(frame->sample_aspect_ratio) * frame_width /
  1244. frame_height;
  1245. }
  1246. if(aspect_ratio <= 0.0)
  1247. aspect_ratio = static_cast<double>(frame_width) / frame_height;
  1248. SDL_GetWindowSize(screen, &win_w, &win_h);
  1249. h = win_h;
  1250. w = (static_cast<int>(std::rint(h * aspect_ratio)) + 3) & ~3;
  1251. if(w > win_w)
  1252. {
  1253. w = win_w;
  1254. h = (static_cast<int>(std::rint(w / aspect_ratio)) + 3) & ~3;
  1255. }
  1256. x = (win_w - w) / 2;
  1257. y = (win_h - h) / 2;
  1258. SDL_Rect src_rect{ static_cast<int>(frame->crop_left), static_cast<int>(frame->crop_top),
  1259. frame_width, frame_height };
  1260. SDL_Rect dst_rect{ x, y, w, h };
  1261. SDL_RenderCopy(renderer, mImage, &src_rect, &dst_rect);
  1262. SDL_RenderPresent(renderer);
  1263. }
  1264. /* Called regularly on the main thread where the SDL_Renderer was created. It
  1265. * handles updating the textures of decoded frames and displaying the latest
  1266. * frame.
  1267. */
  1268. void VideoState::updateVideo(SDL_Window *screen, SDL_Renderer *renderer, bool redraw)
  1269. {
  1270. size_t read_idx{mPictQRead.load(std::memory_order_relaxed)};
  1271. Picture *vp{&mPictQ[read_idx]};
  1272. auto clocktime = mMovie.getMasterClock();
  1273. bool updated{false};
  1274. while(1)
  1275. {
  1276. size_t next_idx{(read_idx+1)%mPictQ.size()};
  1277. if(next_idx == mPictQWrite.load(std::memory_order_acquire))
  1278. break;
  1279. Picture *nextvp{&mPictQ[next_idx]};
  1280. if(clocktime < nextvp->mPts && !mMovie.mQuit.load(std::memory_order_relaxed))
  1281. {
  1282. /* For the first update, ensure the first frame gets shown. */
  1283. if(!mFirstUpdate || updated)
  1284. break;
  1285. }
  1286. vp = nextvp;
  1287. updated = true;
  1288. read_idx = next_idx;
  1289. }
  1290. if(mMovie.mQuit.load(std::memory_order_relaxed))
  1291. {
  1292. if(mEOS)
  1293. mFinalUpdate = true;
  1294. mPictQRead.store(read_idx, std::memory_order_release);
  1295. std::unique_lock<std::mutex>{mPictQMutex}.unlock();
  1296. mPictQCond.notify_one();
  1297. return;
  1298. }
  1299. AVFrame *frame{vp->mFrame.get()};
  1300. if(updated)
  1301. {
  1302. mPictQRead.store(read_idx, std::memory_order_release);
  1303. std::unique_lock<std::mutex>{mPictQMutex}.unlock();
  1304. mPictQCond.notify_one();
  1305. /* allocate or resize the buffer! */
  1306. bool fmt_updated{false};
  1307. if(!mImage || mWidth != frame->width || mHeight != frame->height)
  1308. {
  1309. fmt_updated = true;
  1310. if(mImage)
  1311. SDL_DestroyTexture(mImage);
  1312. mImage = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING,
  1313. frame->width, frame->height);
  1314. if(!mImage)
  1315. std::cerr<< "Failed to create YV12 texture!" <<std::endl;
  1316. mWidth = frame->width;
  1317. mHeight = frame->height;
  1318. }
  1319. int frame_width{frame->width - static_cast<int>(frame->crop_left + frame->crop_right)};
  1320. int frame_height{frame->height - static_cast<int>(frame->crop_top + frame->crop_bottom)};
  1321. if(mFirstUpdate && frame_width > 0 && frame_height > 0)
  1322. {
  1323. /* For the first update, set the window size to the video size. */
  1324. mFirstUpdate = false;
  1325. if(frame->sample_aspect_ratio.den != 0)
  1326. {
  1327. double aspect_ratio = av_q2d(frame->sample_aspect_ratio);
  1328. if(aspect_ratio >= 1.0)
  1329. frame_width = static_cast<int>(frame_width*aspect_ratio + 0.5);
  1330. else if(aspect_ratio > 0.0)
  1331. frame_height = static_cast<int>(frame_height/aspect_ratio + 0.5);
  1332. }
  1333. SDL_SetWindowSize(screen, frame_width, frame_height);
  1334. }
  1335. if(mImage)
  1336. {
  1337. void *pixels{nullptr};
  1338. int pitch{0};
  1339. if(mCodecCtx->pix_fmt == AV_PIX_FMT_YUV420P)
  1340. SDL_UpdateYUVTexture(mImage, nullptr,
  1341. frame->data[0], frame->linesize[0],
  1342. frame->data[1], frame->linesize[1],
  1343. frame->data[2], frame->linesize[2]
  1344. );
  1345. else if(SDL_LockTexture(mImage, nullptr, &pixels, &pitch) != 0)
  1346. std::cerr<< "Failed to lock texture" <<std::endl;
  1347. else
  1348. {
  1349. // Convert the image into YUV format that SDL uses
  1350. int w{frame->width};
  1351. int h{frame->height};
  1352. if(!mSwscaleCtx || fmt_updated)
  1353. {
  1354. mSwscaleCtx.reset(sws_getContext(
  1355. w, h, mCodecCtx->pix_fmt,
  1356. w, h, AV_PIX_FMT_YUV420P, 0,
  1357. nullptr, nullptr, nullptr
  1358. ));
  1359. }
  1360. /* point pict at the queue */
  1361. uint8_t *pict_data[3];
  1362. pict_data[0] = static_cast<uint8_t*>(pixels);
  1363. pict_data[1] = pict_data[0] + w*h;
  1364. pict_data[2] = pict_data[1] + w*h/4;
  1365. int pict_linesize[3];
  1366. pict_linesize[0] = pitch;
  1367. pict_linesize[1] = pitch / 2;
  1368. pict_linesize[2] = pitch / 2;
  1369. sws_scale(mSwscaleCtx.get(), reinterpret_cast<uint8_t**>(frame->data), frame->linesize,
  1370. 0, h, pict_data, pict_linesize);
  1371. SDL_UnlockTexture(mImage);
  1372. }
  1373. redraw = true;
  1374. }
  1375. }
  1376. if(redraw)
  1377. {
  1378. /* Show the picture! */
  1379. display(screen, renderer, frame);
  1380. }
  1381. if(updated)
  1382. {
  1383. auto disp_time = get_avtime();
  1384. std::lock_guard<std::mutex> _{mDispPtsMutex};
  1385. mDisplayPts = vp->mPts;
  1386. mDisplayPtsTime = disp_time;
  1387. }
  1388. if(mEOS.load(std::memory_order_acquire))
  1389. {
  1390. if((read_idx+1)%mPictQ.size() == mPictQWrite.load(std::memory_order_acquire))
  1391. {
  1392. mFinalUpdate = true;
  1393. std::unique_lock<std::mutex>{mPictQMutex}.unlock();
  1394. mPictQCond.notify_one();
  1395. }
  1396. }
  1397. }
  1398. int VideoState::handler()
  1399. {
  1400. std::for_each(mPictQ.begin(), mPictQ.end(),
  1401. [](Picture &pict) -> void
  1402. { pict.mFrame = AVFramePtr{av_frame_alloc()}; });
  1403. /* Prefill the codec buffer. */
  1404. auto packet_sender = [this]()
  1405. {
  1406. while(1)
  1407. {
  1408. const int ret{mQueue.sendPacket(mCodecCtx.get())};
  1409. if(ret == AVErrorEOF) break;
  1410. }
  1411. };
  1412. auto sender = std::async(std::launch::async, packet_sender);
  1413. {
  1414. std::lock_guard<std::mutex> _{mDispPtsMutex};
  1415. mDisplayPtsTime = get_avtime();
  1416. }
  1417. auto current_pts = nanoseconds::zero();
  1418. while(1)
  1419. {
  1420. size_t write_idx{mPictQWrite.load(std::memory_order_relaxed)};
  1421. Picture *vp{&mPictQ[write_idx]};
  1422. /* Retrieve video frame. */
  1423. AVFrame *decoded_frame{vp->mFrame.get()};
  1424. while(int ret{mQueue.receiveFrame(mCodecCtx.get(), decoded_frame)})
  1425. {
  1426. if(ret == AVErrorEOF) goto finish;
  1427. std::cerr<< "Failed to receive frame: "<<ret <<std::endl;
  1428. }
  1429. /* Get the PTS for this frame. */
  1430. if(decoded_frame->best_effort_timestamp != AVNoPtsValue)
  1431. current_pts = duration_cast<nanoseconds>(seconds_d64{av_q2d(mStream->time_base) *
  1432. static_cast<double>(decoded_frame->best_effort_timestamp)});
  1433. vp->mPts = current_pts;
  1434. /* Update the video clock to the next expected PTS. */
  1435. auto frame_delay = av_q2d(mCodecCtx->time_base);
  1436. frame_delay += decoded_frame->repeat_pict * (frame_delay * 0.5);
  1437. current_pts += duration_cast<nanoseconds>(seconds_d64{frame_delay});
  1438. /* Put the frame in the queue to be loaded into a texture and displayed
  1439. * by the rendering thread.
  1440. */
  1441. write_idx = (write_idx+1)%mPictQ.size();
  1442. mPictQWrite.store(write_idx, std::memory_order_release);
  1443. if(write_idx == mPictQRead.load(std::memory_order_acquire))
  1444. {
  1445. /* Wait until we have space for a new pic */
  1446. std::unique_lock<std::mutex> lock{mPictQMutex};
  1447. while(write_idx == mPictQRead.load(std::memory_order_acquire))
  1448. mPictQCond.wait(lock);
  1449. }
  1450. }
  1451. finish:
  1452. mEOS = true;
  1453. std::unique_lock<std::mutex> lock{mPictQMutex};
  1454. while(!mFinalUpdate) mPictQCond.wait(lock);
  1455. return 0;
  1456. }
  1457. int MovieState::decode_interrupt_cb(void *ctx)
  1458. {
  1459. return static_cast<MovieState*>(ctx)->mQuit.load(std::memory_order_relaxed);
  1460. }
  1461. bool MovieState::prepare()
  1462. {
  1463. AVIOContext *avioctx{nullptr};
  1464. AVIOInterruptCB intcb{decode_interrupt_cb, this};
  1465. if(avio_open2(&avioctx, mFilename.c_str(), AVIO_FLAG_READ, &intcb, nullptr))
  1466. {
  1467. std::cerr<< "Failed to open "<<mFilename <<std::endl;
  1468. return false;
  1469. }
  1470. mIOContext.reset(avioctx);
  1471. /* Open movie file. If avformat_open_input fails it will automatically free
  1472. * this context, so don't set it onto a smart pointer yet.
  1473. */
  1474. AVFormatContext *fmtctx{avformat_alloc_context()};
  1475. fmtctx->pb = mIOContext.get();
  1476. fmtctx->interrupt_callback = intcb;
  1477. if(avformat_open_input(&fmtctx, mFilename.c_str(), nullptr, nullptr) != 0)
  1478. {
  1479. std::cerr<< "Failed to open "<<mFilename <<std::endl;
  1480. return false;
  1481. }
  1482. mFormatCtx.reset(fmtctx);
  1483. /* Retrieve stream information */
  1484. if(avformat_find_stream_info(mFormatCtx.get(), nullptr) < 0)
  1485. {
  1486. std::cerr<< mFilename<<": failed to find stream info" <<std::endl;
  1487. return false;
  1488. }
  1489. /* Dump information about file onto standard error */
  1490. av_dump_format(mFormatCtx.get(), 0, mFilename.c_str(), 0);
  1491. mParseThread = std::thread{std::mem_fn(&MovieState::parse_handler), this};
  1492. std::unique_lock<std::mutex> slock{mStartupMutex};
  1493. while(!mStartupDone) mStartupCond.wait(slock);
  1494. return true;
  1495. }
  1496. void MovieState::setTitle(SDL_Window *window)
  1497. {
  1498. auto pos1 = mFilename.rfind('/');
  1499. auto pos2 = mFilename.rfind('\\');
  1500. auto fpos = ((pos1 == std::string::npos) ? pos2 :
  1501. (pos2 == std::string::npos) ? pos1 :
  1502. std::max(pos1, pos2)) + 1;
  1503. SDL_SetWindowTitle(window, (mFilename.substr(fpos)+" - "+AppName).c_str());
  1504. }
  1505. nanoseconds MovieState::getClock()
  1506. {
  1507. if(mClockBase == microseconds::min())
  1508. return nanoseconds::zero();
  1509. return get_avtime() - mClockBase;
  1510. }
  1511. nanoseconds MovieState::getMasterClock()
  1512. {
  1513. if(mAVSyncType == SyncMaster::Video && mVideo.mStream)
  1514. return mVideo.getClock();
  1515. if(mAVSyncType == SyncMaster::Audio && mAudio.mStream)
  1516. return mAudio.getClock();
  1517. return getClock();
  1518. }
  1519. nanoseconds MovieState::getDuration()
  1520. { return std::chrono::duration<int64_t,std::ratio<1,AV_TIME_BASE>>(mFormatCtx->duration); }
  1521. int MovieState::streamComponentOpen(unsigned int stream_index)
  1522. {
  1523. if(stream_index >= mFormatCtx->nb_streams)
  1524. return -1;
  1525. /* Get a pointer to the codec context for the stream, and open the
  1526. * associated codec.
  1527. */
  1528. AVCodecCtxPtr avctx{avcodec_alloc_context3(nullptr)};
  1529. if(!avctx) return -1;
  1530. if(avcodec_parameters_to_context(avctx.get(), mFormatCtx->streams[stream_index]->codecpar))
  1531. return -1;
  1532. const AVCodec *codec{avcodec_find_decoder(avctx->codec_id)};
  1533. if(!codec || avcodec_open2(avctx.get(), codec, nullptr) < 0)
  1534. {
  1535. std::cerr<< "Unsupported codec: "<<avcodec_get_name(avctx->codec_id)
  1536. << " (0x"<<std::hex<<avctx->codec_id<<std::dec<<")" <<std::endl;
  1537. return -1;
  1538. }
  1539. /* Initialize and start the media type handler */
  1540. switch(avctx->codec_type)
  1541. {
  1542. case AVMEDIA_TYPE_AUDIO:
  1543. mAudio.mStream = mFormatCtx->streams[stream_index];
  1544. mAudio.mCodecCtx = std::move(avctx);
  1545. break;
  1546. case AVMEDIA_TYPE_VIDEO:
  1547. mVideo.mStream = mFormatCtx->streams[stream_index];
  1548. mVideo.mCodecCtx = std::move(avctx);
  1549. break;
  1550. default:
  1551. return -1;
  1552. }
  1553. return static_cast<int>(stream_index);
  1554. }
  1555. int MovieState::parse_handler()
  1556. {
  1557. auto &audio_queue = mAudio.mQueue;
  1558. auto &video_queue = mVideo.mQueue;
  1559. int video_index{-1};
  1560. int audio_index{-1};
  1561. /* Find the first video and audio streams */
  1562. for(unsigned int i{0u};i < mFormatCtx->nb_streams;i++)
  1563. {
  1564. auto codecpar = mFormatCtx->streams[i]->codecpar;
  1565. if(codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !DisableVideo && video_index < 0)
  1566. video_index = streamComponentOpen(i);
  1567. else if(codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_index < 0)
  1568. audio_index = streamComponentOpen(i);
  1569. }
  1570. {
  1571. std::unique_lock<std::mutex> slock{mStartupMutex};
  1572. mStartupDone = true;
  1573. }
  1574. mStartupCond.notify_all();
  1575. if(video_index < 0 && audio_index < 0)
  1576. {
  1577. std::cerr<< mFilename<<": could not open codecs" <<std::endl;
  1578. mQuit = true;
  1579. }
  1580. /* Set the base time 750ms ahead of the current av time. */
  1581. mClockBase = get_avtime() + milliseconds{750};
  1582. if(audio_index >= 0)
  1583. mAudioThread = std::thread{std::mem_fn(&AudioState::handler), &mAudio};
  1584. if(video_index >= 0)
  1585. mVideoThread = std::thread{std::mem_fn(&VideoState::handler), &mVideo};
  1586. /* Main packet reading/dispatching loop */
  1587. AVPacketPtr packet{av_packet_alloc()};
  1588. while(!mQuit.load(std::memory_order_relaxed))
  1589. {
  1590. if(av_read_frame(mFormatCtx.get(), packet.get()) < 0)
  1591. break;
  1592. /* Copy the packet into the queue it's meant for. */
  1593. if(packet->stream_index == video_index)
  1594. {
  1595. while(!mQuit.load(std::memory_order_acquire) && !video_queue.put(packet.get()))
  1596. std::this_thread::sleep_for(milliseconds{100});
  1597. }
  1598. else if(packet->stream_index == audio_index)
  1599. {
  1600. while(!mQuit.load(std::memory_order_acquire) && !audio_queue.put(packet.get()))
  1601. std::this_thread::sleep_for(milliseconds{100});
  1602. }
  1603. av_packet_unref(packet.get());
  1604. }
  1605. /* Finish the queues so the receivers know nothing more is coming. */
  1606. video_queue.setFinished();
  1607. audio_queue.setFinished();
  1608. /* all done - wait for it */
  1609. if(mVideoThread.joinable())
  1610. mVideoThread.join();
  1611. if(mAudioThread.joinable())
  1612. mAudioThread.join();
  1613. mVideo.mEOS = true;
  1614. std::unique_lock<std::mutex> lock{mVideo.mPictQMutex};
  1615. while(!mVideo.mFinalUpdate)
  1616. mVideo.mPictQCond.wait(lock);
  1617. lock.unlock();
  1618. SDL_Event evt{};
  1619. evt.user.type = FF_MOVIE_DONE_EVENT;
  1620. SDL_PushEvent(&evt);
  1621. return 0;
  1622. }
  1623. void MovieState::stop()
  1624. {
  1625. mQuit = true;
  1626. mAudio.mQueue.flush();
  1627. mVideo.mQueue.flush();
  1628. }
  1629. // Helper class+method to print the time with human-readable formatting.
  1630. struct PrettyTime {
  1631. seconds mTime;
  1632. };
  1633. std::ostream &operator<<(std::ostream &os, const PrettyTime &rhs)
  1634. {
  1635. using hours = std::chrono::hours;
  1636. using minutes = std::chrono::minutes;
  1637. seconds t{rhs.mTime};
  1638. if(t.count() < 0)
  1639. {
  1640. os << '-';
  1641. t *= -1;
  1642. }
  1643. // Only handle up to hour formatting
  1644. if(t >= hours{1})
  1645. os << duration_cast<hours>(t).count() << 'h' << std::setfill('0') << std::setw(2)
  1646. << (duration_cast<minutes>(t).count() % 60) << 'm';
  1647. else
  1648. os << duration_cast<minutes>(t).count() << 'm' << std::setfill('0');
  1649. os << std::setw(2) << (duration_cast<seconds>(t).count() % 60) << 's' << std::setw(0)
  1650. << std::setfill(' ');
  1651. return os;
  1652. }
  1653. } // namespace
  1654. int main(int argc, char *argv[])
  1655. {
  1656. std::unique_ptr<MovieState> movState;
  1657. if(argc < 2)
  1658. {
  1659. std::cerr<< "Usage: "<<argv[0]<<" [-device <device name>] [-direct] <files...>" <<std::endl;
  1660. return 1;
  1661. }
  1662. /* Register all formats and codecs */
  1663. #if !(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 9, 100))
  1664. av_register_all();
  1665. #endif
  1666. /* Initialize networking protocols */
  1667. avformat_network_init();
  1668. if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS))
  1669. {
  1670. std::cerr<< "Could not initialize SDL - <<"<<SDL_GetError() <<std::endl;
  1671. return 1;
  1672. }
  1673. /* Make a window to put our video */
  1674. SDL_Window *screen{SDL_CreateWindow(AppName.c_str(), 0, 0, 640, 480, SDL_WINDOW_RESIZABLE)};
  1675. if(!screen)
  1676. {
  1677. std::cerr<< "SDL: could not set video mode - exiting" <<std::endl;
  1678. return 1;
  1679. }
  1680. /* Make a renderer to handle the texture image surface and rendering. */
  1681. Uint32 render_flags{SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC};
  1682. SDL_Renderer *renderer{SDL_CreateRenderer(screen, -1, render_flags)};
  1683. if(renderer)
  1684. {
  1685. SDL_RendererInfo rinf{};
  1686. bool ok{false};
  1687. /* Make sure the renderer supports IYUV textures. If not, fallback to a
  1688. * software renderer. */
  1689. if(SDL_GetRendererInfo(renderer, &rinf) == 0)
  1690. {
  1691. for(Uint32 i{0u};!ok && i < rinf.num_texture_formats;i++)
  1692. ok = (rinf.texture_formats[i] == SDL_PIXELFORMAT_IYUV);
  1693. }
  1694. if(!ok)
  1695. {
  1696. std::cerr<< "IYUV pixelformat textures not supported on renderer "<<rinf.name <<std::endl;
  1697. SDL_DestroyRenderer(renderer);
  1698. renderer = nullptr;
  1699. }
  1700. }
  1701. if(!renderer)
  1702. {
  1703. render_flags = SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC;
  1704. renderer = SDL_CreateRenderer(screen, -1, render_flags);
  1705. }
  1706. if(!renderer)
  1707. {
  1708. std::cerr<< "SDL: could not create renderer - exiting" <<std::endl;
  1709. return 1;
  1710. }
  1711. SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
  1712. SDL_RenderFillRect(renderer, nullptr);
  1713. SDL_RenderPresent(renderer);
  1714. /* Open an audio device */
  1715. ++argv; --argc;
  1716. if(InitAL(&argv, &argc))
  1717. {
  1718. std::cerr<< "Failed to set up audio device" <<std::endl;
  1719. return 1;
  1720. }
  1721. {
  1722. auto device = alcGetContextsDevice(alcGetCurrentContext());
  1723. if(alcIsExtensionPresent(device, "ALC_SOFT_device_clock"))
  1724. {
  1725. std::cout<< "Found ALC_SOFT_device_clock" <<std::endl;
  1726. alcGetInteger64vSOFT = reinterpret_cast<LPALCGETINTEGER64VSOFT>(
  1727. alcGetProcAddress(device, "alcGetInteger64vSOFT")
  1728. );
  1729. }
  1730. }
  1731. if(alIsExtensionPresent("AL_SOFT_source_latency"))
  1732. {
  1733. std::cout<< "Found AL_SOFT_source_latency" <<std::endl;
  1734. alGetSourcei64vSOFT = reinterpret_cast<LPALGETSOURCEI64VSOFT>(
  1735. alGetProcAddress("alGetSourcei64vSOFT")
  1736. );
  1737. }
  1738. if(alIsExtensionPresent("AL_SOFT_events"))
  1739. {
  1740. std::cout<< "Found AL_SOFT_events" <<std::endl;
  1741. alEventControlSOFT = reinterpret_cast<LPALEVENTCONTROLSOFT>(
  1742. alGetProcAddress("alEventControlSOFT"));
  1743. alEventCallbackSOFT = reinterpret_cast<LPALEVENTCALLBACKSOFT>(
  1744. alGetProcAddress("alEventCallbackSOFT"));
  1745. }
  1746. if(alIsExtensionPresent("AL_SOFT_callback_buffer"))
  1747. {
  1748. std::cout<< "Found AL_SOFT_callback_buffer" <<std::endl;
  1749. alBufferCallbackSOFT = reinterpret_cast<LPALBUFFERCALLBACKSOFT>(
  1750. alGetProcAddress("alBufferCallbackSOFT"));
  1751. }
  1752. int fileidx{0};
  1753. for(;fileidx < argc;++fileidx)
  1754. {
  1755. if(strcmp(argv[fileidx], "-direct") == 0)
  1756. {
  1757. if(alIsExtensionPresent("AL_SOFT_direct_channels_remix"))
  1758. {
  1759. std::cout<< "Found AL_SOFT_direct_channels_remix" <<std::endl;
  1760. DirectOutMode = AL_REMIX_UNMATCHED_SOFT;
  1761. }
  1762. else if(alIsExtensionPresent("AL_SOFT_direct_channels"))
  1763. {
  1764. std::cout<< "Found AL_SOFT_direct_channels" <<std::endl;
  1765. DirectOutMode = AL_DROP_UNMATCHED_SOFT;
  1766. }
  1767. else
  1768. std::cerr<< "AL_SOFT_direct_channels not supported for direct output" <<std::endl;
  1769. }
  1770. else if(strcmp(argv[fileidx], "-wide") == 0)
  1771. {
  1772. if(!alIsExtensionPresent("AL_EXT_STEREO_ANGLES"))
  1773. std::cerr<< "AL_EXT_STEREO_ANGLES not supported for wide stereo" <<std::endl;
  1774. else
  1775. {
  1776. std::cout<< "Found AL_EXT_STEREO_ANGLES" <<std::endl;
  1777. EnableWideStereo = true;
  1778. }
  1779. }
  1780. else if(strcmp(argv[fileidx], "-uhj") == 0)
  1781. {
  1782. if(!alIsExtensionPresent("AL_SOFT_UHJ"))
  1783. std::cerr<< "AL_SOFT_UHJ not supported for UHJ decoding" <<std::endl;
  1784. else
  1785. {
  1786. std::cout<< "Found AL_SOFT_UHJ" <<std::endl;
  1787. FormatStereo8 = AL_FORMAT_UHJ2CHN8_SOFT;
  1788. FormatStereo16 = AL_FORMAT_UHJ2CHN16_SOFT;
  1789. FormatStereo32F = AL_FORMAT_UHJ2CHN_FLOAT32_SOFT;
  1790. }
  1791. }
  1792. else if(strcmp(argv[fileidx], "-superstereo") == 0)
  1793. {
  1794. if(!alIsExtensionPresent("AL_SOFT_UHJ"))
  1795. std::cerr<< "AL_SOFT_UHJ not supported for Super Stereo decoding" <<std::endl;
  1796. else
  1797. {
  1798. std::cout<< "Found AL_SOFT_UHJ (Super Stereo)" <<std::endl;
  1799. EnableSuperStereo = true;
  1800. }
  1801. }
  1802. else if(strcmp(argv[fileidx], "-novideo") == 0)
  1803. DisableVideo = true;
  1804. else
  1805. break;
  1806. }
  1807. while(fileidx < argc && !movState)
  1808. {
  1809. movState = std::unique_ptr<MovieState>{new MovieState{argv[fileidx++]}};
  1810. if(!movState->prepare()) movState = nullptr;
  1811. }
  1812. if(!movState)
  1813. {
  1814. std::cerr<< "Could not start a video" <<std::endl;
  1815. return 1;
  1816. }
  1817. movState->setTitle(screen);
  1818. /* Default to going to the next movie at the end of one. */
  1819. enum class EomAction {
  1820. Next, Quit
  1821. } eom_action{EomAction::Next};
  1822. seconds last_time{seconds::min()};
  1823. while(1)
  1824. {
  1825. /* SDL_WaitEventTimeout is broken, just force a 10ms sleep. */
  1826. std::this_thread::sleep_for(milliseconds{10});
  1827. auto cur_time = std::chrono::duration_cast<seconds>(movState->getMasterClock());
  1828. if(cur_time != last_time)
  1829. {
  1830. auto end_time = std::chrono::duration_cast<seconds>(movState->getDuration());
  1831. std::cout<< " \r "<<PrettyTime{cur_time}<<" / "<<PrettyTime{end_time} <<std::flush;
  1832. last_time = cur_time;
  1833. }
  1834. bool force_redraw{false};
  1835. SDL_Event event{};
  1836. while(SDL_PollEvent(&event) != 0)
  1837. {
  1838. switch(event.type)
  1839. {
  1840. case SDL_KEYDOWN:
  1841. switch(event.key.keysym.sym)
  1842. {
  1843. case SDLK_ESCAPE:
  1844. movState->stop();
  1845. eom_action = EomAction::Quit;
  1846. break;
  1847. case SDLK_n:
  1848. movState->stop();
  1849. eom_action = EomAction::Next;
  1850. break;
  1851. default:
  1852. break;
  1853. }
  1854. break;
  1855. case SDL_WINDOWEVENT:
  1856. switch(event.window.event)
  1857. {
  1858. case SDL_WINDOWEVENT_RESIZED:
  1859. SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
  1860. SDL_RenderFillRect(renderer, nullptr);
  1861. force_redraw = true;
  1862. break;
  1863. case SDL_WINDOWEVENT_EXPOSED:
  1864. force_redraw = true;
  1865. break;
  1866. default:
  1867. break;
  1868. }
  1869. break;
  1870. case SDL_QUIT:
  1871. movState->stop();
  1872. eom_action = EomAction::Quit;
  1873. break;
  1874. case FF_MOVIE_DONE_EVENT:
  1875. std::cout<<'\n';
  1876. last_time = seconds::min();
  1877. if(eom_action != EomAction::Quit)
  1878. {
  1879. movState = nullptr;
  1880. while(fileidx < argc && !movState)
  1881. {
  1882. movState = std::unique_ptr<MovieState>{new MovieState{argv[fileidx++]}};
  1883. if(!movState->prepare()) movState = nullptr;
  1884. }
  1885. if(movState)
  1886. {
  1887. movState->setTitle(screen);
  1888. break;
  1889. }
  1890. }
  1891. /* Nothing more to play. Shut everything down and quit. */
  1892. movState = nullptr;
  1893. CloseAL();
  1894. SDL_DestroyRenderer(renderer);
  1895. renderer = nullptr;
  1896. SDL_DestroyWindow(screen);
  1897. screen = nullptr;
  1898. SDL_Quit();
  1899. exit(0);
  1900. default:
  1901. break;
  1902. }
  1903. }
  1904. movState->mVideo.updateVideo(screen, renderer, force_redraw);
  1905. }
  1906. std::cerr<< "SDL_WaitEvent error - "<<SDL_GetError() <<std::endl;
  1907. return 1;
  1908. }