AudioStream.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #pragma once
  2. #include <string>
  3. extern "C" {
  4. #include <libavcodec/avcodec.h>
  5. #include <libavformat/avformat.h>
  6. #include <libavutil/fifo.h>
  7. #include <libavutil/opt.h>
  8. #include <libswresample/swresample.h>
  9. #include <libswscale/swscale.h>
  10. }
  11. #include <SDL.h>
  12. #include <SDL_thread.h>
  13. #include "WallpaperEngine/Audio/AudioContext.h"
  14. // TODO: FIND A BETTER PLACE TO DO THIS? OLD_API MIGHT EXIST BUT THIS DEFINE MIGHT NOT BE DEFINED...
  15. #ifndef FF_API_FIFO_OLD_API
  16. #define FF_API_FIFO_OLD_API (LIBAVUTIL_VERSION_MAJOR < 59)
  17. #endif
  18. #ifndef FF_API_OLD_CHANNEL_LAYOUT
  19. #define FF_API_OLD_CHANNEL_LAYOUT (LIBAVUTIL_VERSION_MAJOR < 59)
  20. #endif
  21. #define MAX_QUEUE_SIZE (5 * 1024 * 1024)
  22. #define MIN_FRAMES (25)
  23. #define NO_AUDIO_STREAM (-1)
  24. namespace WallpaperEngine::Audio {
  25. class AudioContext;
  26. using namespace WallpaperEngine::FileSystem;
  27. /**
  28. * Represents a playable audio stream for the audio driver
  29. */
  30. class AudioStream {
  31. public:
  32. AudioStream (AudioContext& context, const std::string& filename);
  33. AudioStream (AudioContext& context, const ReadStreamSharedPtr& buffer);
  34. AudioStream (AudioContext& audioContext, AVCodecContext* context);
  35. ~AudioStream ();
  36. void queuePacket (AVPacket* pkt);
  37. /**
  38. * Gets the next packet in the queue
  39. *
  40. * WARNING: BLOCKS UNTIL SOME DATA IS READ FROM IT
  41. *
  42. * @return
  43. */
  44. void dequeuePacket ();
  45. /**
  46. * @return The audio context in use for this audio stream
  47. */
  48. [[nodiscard]] AudioContext& getAudioContext () const;
  49. /**
  50. * @return to the codec context, which provides information on the audio stream's format
  51. */
  52. [[nodiscard]] AVCodecContext* getContext () const;
  53. /**
  54. * @returns the format context, which controls how data is read off the audio stream
  55. */
  56. [[nodiscard]] AVFormatContext* getFormatContext () const;
  57. /**
  58. * @return The audio stream index of the given file
  59. */
  60. [[nodiscard]] int getAudioStream () const;
  61. /**
  62. * @return If the audio stream can be played or not
  63. */
  64. [[nodiscard]] bool isInitialized () const;
  65. /**
  66. * @param newRepeat true = repeat, false = no repeat
  67. */
  68. void setRepeat (bool newRepeat = true);
  69. /**
  70. * @return If the stream is to be repeated at the end or not
  71. */
  72. [[nodiscard]] bool isRepeat () const;
  73. /**
  74. * Stops decoding and playbak of the stream
  75. */
  76. void stop ();
  77. /**
  78. * @return The file data buffer
  79. */
  80. [[nodiscard]] ReadStreamSharedPtr& getBuffer ();
  81. /**
  82. * @return The SDL_cond used to signal waiting for data
  83. */
  84. [[nodiscard]] SDL_cond* getWaitCondition () const;
  85. /**
  86. * @return The data queue size
  87. */
  88. [[nodiscard]] size_t getQueueSize () const;
  89. /**
  90. * @return The amount of packets ready to be converted and played
  91. */
  92. [[nodiscard]] int getQueuePacketCount () const;
  93. /**
  94. * @return The duration (in seconds) of the queued data to be played
  95. */
  96. [[nodiscard]] int64_t getQueueDuration () const;
  97. /**
  98. * @return Time unit used for packet playback
  99. */
  100. [[nodiscard]] AVRational getTimeBase () const;
  101. /**
  102. * @return If the data queue is empty or not
  103. */
  104. [[nodiscard]] bool isQueueEmpty () const;
  105. /**
  106. * @return The SDL_mutex used for thread synchronization
  107. */
  108. [[nodiscard]] SDL_mutex* getMutex () const;
  109. /**
  110. * Reads a frame from the audio stream, resamples it to the driver's settings
  111. * and returns the data ready to be played
  112. *
  113. * @param audioBuffer
  114. * @param bufferSize
  115. *
  116. * @return The amount of bytes available or < 0 for error
  117. */
  118. int decodeFrame (uint8_t* audioBuffer, int bufferSize);
  119. private:
  120. /**
  121. * Initializes ffmpeg to read the given file
  122. *
  123. * @param filename
  124. */
  125. void loadCustomContent (const char* filename = nullptr);
  126. /**
  127. * Converts the audio frame from the original format to one supported by the audio driver
  128. *
  129. * @param out_buf
  130. * @return
  131. */
  132. int resampleAudio (uint8_t* out_buf, const int out_size);
  133. /**
  134. * Queues a packet into the play queue
  135. *
  136. * @param pkt
  137. * @return
  138. */
  139. bool doQueue (AVPacket* pkt);
  140. /**
  141. * Initializes queues and ffmpeg resampling
  142. */
  143. void initialize ();
  144. /** The SwrContext that handles resampling */
  145. SwrContext* m_swrctx = nullptr;
  146. /** The audio context this stream will be played under */
  147. AudioContext& m_audioContext;
  148. /** If this stream was properly initialized or not */
  149. bool m_initialized = false;
  150. /** Repeat enabled? */
  151. bool m_repeat = false;
  152. /** The codec context that contains the original audio format information */
  153. AVCodecContext* m_context = nullptr;
  154. /** The format context that controls how data is read off the file */
  155. AVFormatContext* m_formatContext = nullptr;
  156. /** The stream index for the audio being played */
  157. int m_audioStream = NO_AUDIO_STREAM;
  158. /** File data pointer */
  159. ReadStreamSharedPtr m_buffer = nullptr;
  160. /** The length of the file data pointer */
  161. uint32_t m_length = 0;
  162. struct MyAVPacketList {
  163. AVPacket* packet;
  164. };
  165. /** The packet used while decoding this stream */
  166. AVPacket* m_decodePacket = nullptr;
  167. /** The AV frame used while decoding this stream */
  168. AVFrame* m_decodeFrame = nullptr;
  169. /**
  170. * Packet queue information
  171. */
  172. struct PacketQueue {
  173. #if FF_API_FIFO_OLD_API
  174. AVFifoBuffer* packetList = nullptr;
  175. #else
  176. AVFifo* packetList = nullptr;
  177. #endif
  178. int nb_packets = 0;
  179. size_t size = 0;
  180. int64_t duration = 0;
  181. SDL_mutex* mutex = nullptr;
  182. SDL_cond* wait = nullptr;
  183. SDL_cond* cond = nullptr;
  184. }* m_queue {};
  185. };
  186. } // namespace WallpaperEngine::Audio