Counter Strike : Global Offensive Source Code
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.

325 lines
9.3 KiB

  1. //========== Copyright � Valve Corporation, All rights reserved. ========
  2. #ifndef VJOBS_MP3DEC_SHARED_HDR
  3. #define VJOBS_MP3DEC_SHARED_HDR
  4. #include "ps3/spu_job_shared.h"
  5. #ifdef SPU
  6. #include "Mp3DecSpuLib.h"
  7. #else
  8. #include "mp3declib.h"
  9. #endif
  10. extern uint8 s_mp3_bitrate_8000[2][16];
  11. extern uint16 s_mp3_samplingrate_div50[2][4];
  12. struct Mp3FrameHeader
  13. {
  14. // http://www.mars.org/pipermail/mad-dev/2002-January/000425.html
  15. // The absolute theoretical maximum frame size is 2881 bytes: MPEG 2.5 Layer II,
  16. // 8000 Hz @ 160 kbps, with a padding slot
  17. enum ConstEnum_t{
  18. MAX_FRAME_LENGTH = 2881,
  19. // Theoretical frame sizes for Layer III range from 24 to 1441 bytes, but there
  20. // is a "soft" limit imposed by the standard of 960 bytes
  21. MAX_MP3_FRAME_LENGTH = 1441
  22. };
  23. // http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm is a good reference as to what the following bitfields mean
  24. // WARNING
  25. // this struct works in debugger perfectly, but if you use it in the SPU code, it'll sometimes be wrong
  26. // don't use it for anything other than debugging
  27. /*union
  28. {
  29. struct
  30. {
  31. uint m_nFrameSync :11; // all bits must be set at all times , or it's not really a frame header
  32. uint m_nAudioVersion : 2;
  33. uint m_nLayerDesc : 2;
  34. uint m_nProtection : 1;
  35. uint m_nBitrate : 4;
  36. uint m_nSamplingRate : 2;
  37. uint m_nPadding : 1;
  38. uint m_nPrivateBit : 1;
  39. uint m_nChannelMode : 2; // 01 (joint) isn't supported in mp3dec from Sony
  40. uint m_nModeExtension : 2;
  41. uint m_nCopyright : 1;
  42. uint m_nOriginal : 1;
  43. uint m_nEmphasis : 2;
  44. };
  45. */
  46. uint8 m_bits[4];
  47. //};
  48. //AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
  49. uint CheckSync()const{ return IsCorrectHeader( m_bits ); }
  50. uint GetAudioVersionId()const
  51. {
  52. return ( m_bits[1] >> 3 ) & 3;
  53. }
  54. uint GetLayerDescId()const
  55. {
  56. return ( m_bits[1] >> 1 ) & 3;
  57. }
  58. uint GetProtection()const
  59. {
  60. return m_bits[1] & 1;
  61. }
  62. uint GetBitrateId()const
  63. {
  64. return m_bits[2] >> 4;
  65. }
  66. uint GetSamplingRateId()const
  67. {
  68. return ( m_bits[2] >> 2 ) & 3;
  69. }
  70. uint GetPadding()const
  71. {
  72. return ( m_bits[2] >> 1 ) & 1;
  73. }
  74. uint GetPrivateBit()const
  75. {
  76. return ( m_bits[2] ) & 1;
  77. }
  78. uint GetChannelModeId()const
  79. {
  80. return ( m_bits[3] >> 6 ) & 3;
  81. }
  82. uint GetModeExtensionId()const
  83. {
  84. return ( m_bits[3] >> 4 ) & 3;
  85. }
  86. uint GetCopyright()const
  87. {
  88. return ( m_bits[3] >> 3 ) & 1;
  89. }
  90. uint GetOriginal()const
  91. {
  92. return ( m_bits[3] >> 2 ) & 1;
  93. }
  94. uint GetEmphasisId()const
  95. {
  96. return ( m_bits[3] ) & 3;
  97. }
  98. inline uint GetFrameLengthIncludingHeader( bool bUsePadding = true )const
  99. {
  100. COMPILE_TIME_ASSERT( sizeof( *this ) == 4 );
  101. Assert( CheckSync() && GetAudioVersionId() >= 2 && GetLayerDescId() == 1 ); // version2 , layer 3
  102. // 1 kbps = 1024 bits per second = 128 bytes per second
  103. uint nAudioVersion = GetAudioVersionId() & 1, nBitrate = GetBitrateId(), nSamplingRateId = GetSamplingRateId();
  104. uint bitrate_8000 = s_mp3_bitrate_8000[ nAudioVersion ][ nBitrate ];
  105. uint samplingrate_50 = s_mp3_samplingrate_div50[ nAudioVersion ][ nSamplingRateId ];
  106. uint a;
  107. // TODO: Change the table so we don't have to do this test
  108. if ( nAudioVersion == 1 )
  109. {
  110. a = ( 144 * 8 * 20 ) * bitrate_8000;
  111. }
  112. else
  113. {
  114. a = ( 72 * 8 * 20 ) * bitrate_8000;
  115. }
  116. Assert( a > 0 && samplingrate_50 > 0 );
  117. uint nLength = a / samplingrate_50;
  118. if ( bUsePadding )
  119. {
  120. nLength += GetPadding();
  121. }
  122. return nLength;
  123. }
  124. inline uint GetFrameSamplingRate() const
  125. {
  126. return s_mp3_samplingrate_div50[ GetAudioVersionId()& 1][ GetSamplingRateId() ] * 50;
  127. }
  128. inline uint GetBitrateKbps()const
  129. {
  130. uint nAudioVersion = GetAudioVersionId() & 1, nBitrateId = GetBitrateId();
  131. return s_mp3_bitrate_8000[ nAudioVersion ][ nBitrateId ] * 8;
  132. }
  133. // Checks that the header is similar. Padding differences are ignored.
  134. // This will not work with VBR encoding.
  135. inline bool IsSimilar(const Mp3FrameHeader & otherHeader) const
  136. {
  137. // TODO: Could be optimized. Although I doubt this is actually necessary.
  138. bool b0 = m_bits[0] == otherHeader.m_bits[0];
  139. bool b1 = m_bits[1] == otherHeader.m_bits[1];
  140. bool b2 = (m_bits[2] & 0xFD) == (otherHeader.m_bits[2] & 0xFD);
  141. bool b3 = m_bits[3] == otherHeader.m_bits[3];
  142. return b0 & b1 & b2 & b3;
  143. }
  144. static bool IsCorrectHeader( const uint8 * h )
  145. {
  146. uint8 h0 = h[0], h1 = h[1];
  147. // must be 11111111 1111x01x for V1 or V2, Layer 3 header
  148. return ( h0 == 0xFF && ( h1 & 0xF6 ) == 0xF2 );
  149. }
  150. inline uint CorrectFrameLength( uint nLength, const uint8 * pStreamEnd )const
  151. {
  152. const uint8 * pFrameEnd = ( ( const uint8 * ) this ) + nLength;
  153. if( pStreamEnd >= pFrameEnd + 1 + 2 )
  154. {
  155. if( IsCorrectHeader( pFrameEnd ) )
  156. return nLength;
  157. for( uint d = 1; d < 2; ++d )
  158. {
  159. if( IsCorrectHeader( pFrameEnd - d ) )
  160. return nLength - d;
  161. if( IsCorrectHeader( pFrameEnd + d ) )
  162. return nLength + d;
  163. }
  164. }
  165. return nLength;
  166. }
  167. // scan the byte stream to find the next header
  168. inline uint CorrectFrameLength( const uint8 * pStreamEnd)const
  169. {
  170. uint nLength = GetFrameLengthIncludingHeader();
  171. return CorrectFrameLength( nLength, pStreamEnd );
  172. }
  173. };
  174. namespace job_mp3dec
  175. {
  176. enum ConstEnum_t
  177. {
  178. MP3_FRAME_SAMPLE_COUNT = 0x480,
  179. // we need space for stereo mp3 frame, 16 bits per sample,
  180. // and then 127 bytes on each side of it for misalignment,
  181. // and then 127 bytes more for misalignment of this whole buffer size
  182. // for smoother output with less pointless copying, specify more local store when initializing the job descriptor
  183. IOBUFFER_SIZE = ( MP3_FRAME_SAMPLE_COUNT * 2 * sizeof( int16 ) + 3 * 127 ) & -128
  184. };
  185. struct ALIGN16 Context_t
  186. {
  187. CellMP3Context m_context[2];
  188. int32 m_nInternalMp3Count;
  189. int32 m_nLastBytesRead;
  190. int32 m_nLastBytesWritten;
  191. uint32 m_nTotalBytesRead;
  192. uint32 m_nTotalBytesWritten;
  193. void Init();
  194. }ALIGN16_POST;
  195. // a joblet may not be "allocated"; if it's "not complete" AND "allocated", only then will it be processed
  196. // it may be deallocated any time after it's complete; it may be appended any time after it's complete; it may not suddenly become incomplete
  197. struct ALIGN16 Joblet_t
  198. {
  199. enum FlagEnum_t
  200. {
  201. FLAG_DEBUG_STOP = 0x1000,
  202. FLAG_DEBUG_SPIN = 0x2000,
  203. FLAG_DECODE_INVALID_FRAME = 0x4000,
  204. FLAG_DECODE_INCOMPLETE_FRAME = 0x8000,
  205. FLAG_DECODE_WAV_SCATTER = 0x400,
  206. FLAG_DECODE_MP3_GATHER = 0x200,
  207. FLAG_DECODE_INIT_CONTEXT = 0x100, // don't take the context from main memory, init it in local to zeroes and then DMA it out
  208. FLAG_DECODE_ERROR = 0x80, // an error happened during decode; COMPLETE bits is still set, you may read the buffer ends
  209. FLAG_DECODE_EMPTY = 0x40, // empty input or output stream
  210. FLAG_DECODE_COMPLETE = 0x20, // decoding complete; you may read the buffer ends
  211. FLAG_ALLOCATED = 0x10,
  212. FLAG_LITTLE_ENDIAN = 0x08,
  213. FLAG_FULL_MP3_FRAMES_ONLY = 4,
  214. // input: means m_eaWav will accept mono
  215. // output: means m_eaWav points to mono samples
  216. FLAG_MONO = 1,
  217. // input: means m_eaWav will accept stereo
  218. // output: means m_eaWav points to pairs of samples "left, right"
  219. FLAG_STEREO = 2,
  220. FLAGS_MONO_OR_STEREO = FLAG_MONO | FLAG_STEREO
  221. };
  222. uint32 m_nFlags;
  223. uint32 m_nSkipSamples;
  224. // input: max number of mp3 frames to decode;
  225. // output: number of frames decoded
  226. //uint32 m_nMp3Frames;
  227. // input buffer
  228. uint8 * m_eaMp3;
  229. // output: the last decoded frame, for warming up
  230. uint8 * m_eaMp3Last;
  231. // output: the end of the buffer that has been read
  232. uint8 *m_eaMp3Get;
  233. // input: the end of the buffer allowed to read
  234. uint8 * m_eaMp3End;
  235. // output buffer
  236. int16 * m_eaWave;
  237. // output: the end of the buffer written to
  238. int16 *m_eaWavePut;
  239. // intput: the end of the buffer allocated for writing
  240. int16 * m_eaWaveEnd;
  241. // In/Out - 2 contexts
  242. Context_t *m_eaContext;
  243. bool NeedDecode()const { return ( m_nFlags & ( FLAG_DECODE_ERROR | FLAG_DECODE_COMPLETE | FLAG_ALLOCATED ) ) == FLAG_ALLOCATED; }
  244. bool IsAllocated()const{ return (m_nFlags & FLAG_ALLOCATED) != 0; }
  245. bool IsComplete()const { return (m_nFlags & FLAG_DECODE_COMPLETE) != 0; }
  246. bool HasDecodingError()const { return (m_nFlags & FLAG_DECODE_ERROR) != 0; }
  247. } ALIGN16_POST;
  248. typedef CellSpursJob128 JobDescriptor_t;
  249. struct ALIGN16 JobParams_t
  250. {
  251. void *m_eaDecoder;
  252. Joblet_t *m_eaJoblets;
  253. // joblet get index;
  254. // SPU: volatile makes no sense because it's only operated on in LS; it's changed by multiple SPUs, though
  255. // PPU: m_nGet can change at any time by SPU
  256. PPU_ONLY( volatile ) uint32 m_nGet;
  257. // how many jobs are started and didn't decide to quit yet.
  258. // when this is down to 0 AFTER we advanced our m_nPut (don't forget the barrier!), we have to spawn more jobs
  259. PPU_ONLY( volatile ) uint32 m_nWorkers;
  260. // joblet put index ;
  261. // SPU: volatile makes no sense because it's only operated on in LS
  262. // PPU: volatile makes no sense because PPU uses atomics to access it, and SPU never changes this value
  263. uint32 m_nPut;
  264. //uint32 m_nJobletIndexMask;
  265. enum ConstEnum_t {JOBLET_COUNT = 64 * 4 }; // Each sound uses 4 joblets at a time. Can decode 64 sounds in a row.
  266. uint32 m_nDebuggerBreak;
  267. uint32 m_nWorkerTotal; // total workers that ever existed (not including m_nWorkers, which are the currently started up workers)
  268. uint32 m_nJobletsAcquired;
  269. uint32 m_nWorkerLock; // min workers to hold on to
  270. }ALIGN16_POST;
  271. inline JobParams_t * GetJobParams( void *pJob )
  272. {
  273. return VjobGetJobParams< JobParams_t, JobDescriptor_t >( pJob );
  274. }
  275. }
  276. #endif