1
0

DecodeThread.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. #include "DecodeThread.h"
  2. #include "giofile.h"
  3. #include "main.h"
  4. #include "pdtimer.h"
  5. #include "mpegutil.h"
  6. #include "../Winamp/wa_ipc.h"
  7. #include "config.h"
  8. #include <shlwapi.h>
  9. #include "adts.h"
  10. #include "adts_vlb.h"
  11. #include <foundation/error.h>
  12. // {19450308-90D7-4E45-8A9D-DC71E67123E2}
  13. static const GUID adts_aac_guid =
  14. { 0x19450308, 0x90d7, 0x4e45, { 0x8a, 0x9d, 0xdc, 0x71, 0xe6, 0x71, 0x23, 0xe2 } };
  15. // {4192FE3F-E843-445c-8D62-51BE5EE5E68C}
  16. static const GUID adts_mp2_guid =
  17. { 0x4192fe3f, 0xe843, 0x445c, { 0x8d, 0x62, 0x51, 0xbe, 0x5e, 0xe5, 0xe6, 0x8c } };
  18. extern int m_is_stream;
  19. extern bool m_is_stream_seekable;
  20. // post this to the main window at end of file (after playback as stopped)
  21. #define WM_WA_MPEG_EOF WM_USER+2
  22. /* public data */
  23. int last_decode_pos_ms;
  24. int decode_pos_ms; // current decoding position, in milliseconds.
  25. volatile int seek_needed; // if != -1, it is the point that the decode
  26. // thread should seek to, in ms.
  27. int g_ds;
  28. size_t g_bits;
  29. int g_sndopened;
  30. int g_bufferstat;
  31. int g_length = -1000;
  32. int g_vis_enabled;
  33. volatile int g_closeaudio = 0;
  34. CGioFile *g_playing_file=0;
  35. /* private data */
  36. static size_t g_samplebuf_used;
  37. static int need_prebuffer;
  38. static int g_srate, g_nch, g_br_add, g_br_div, g_avg_vbr_br;
  39. int g_br;
  40. class EndCutter
  41. {
  42. public:
  43. EndCutter() : buffer(0), cutSize(0), filledSize(0), preCutSize(0), preCut(0), decoderDelay(0)
  44. {}
  45. ~EndCutter()
  46. {
  47. free(buffer);
  48. }
  49. void SetEndSize(int postSize)
  50. {
  51. postSize -= decoderDelay;
  52. if (postSize < 0)
  53. postSize = 0;
  54. else if (postSize)
  55. {
  56. free(buffer);
  57. buffer = (char *)calloc(postSize, sizeof(char));
  58. cutSize = postSize;
  59. }
  60. }
  61. void SetSize(int decoderDelaySize, int preSize, int postSize)
  62. {
  63. decoderDelay = decoderDelaySize;
  64. SetEndSize(postSize);
  65. preCutSize = preSize;
  66. preCut = preCutSize + decoderDelay;
  67. }
  68. void Flush(int time_in_ms)
  69. {
  70. if (time_in_ms == 0) // TODO: calculate actual delay if we seek within the encoder delay area
  71. preCut = preCutSize; // reset precut size if we seek to the start
  72. filledSize = 0;
  73. mod.outMod->Flush(time_in_ms);
  74. }
  75. void Write(char *out, int outSize)
  76. {
  77. if (!out && (!outSize))
  78. {
  79. mod.outMod->Write(0, 0);
  80. return ;
  81. }
  82. // cut pre samples, if necessary
  83. int pre = min(preCut, outSize);
  84. out += pre;
  85. outSize -= pre;
  86. preCut -= pre;
  87. if (!outSize)
  88. return ;
  89. int remainingFill = cutSize - filledSize;
  90. int fillWrite = min(outSize - remainingFill, filledSize); // only write fill buffer if we've got enough left to fill it up
  91. if (fillWrite > 0)
  92. {
  93. mod.outMod->Write((char *)buffer, fillWrite);
  94. if (cutSize - fillWrite)
  95. memmove(buffer, buffer + fillWrite, cutSize - fillWrite);
  96. filledSize -= fillWrite;
  97. }
  98. remainingFill = cutSize - filledSize;
  99. int outWrite = max(0, outSize - remainingFill);
  100. if (outWrite)
  101. mod.outMod->Write((char *)out, outWrite);
  102. out += outWrite;
  103. outSize -= outWrite;
  104. if (outSize)
  105. {
  106. memcpy(buffer + filledSize, out, outSize);
  107. filledSize += outSize;
  108. }
  109. }
  110. char *buffer;
  111. int cutSize;
  112. int filledSize;
  113. int preCut, preCutSize, decoderDelay;
  114. };
  115. class DecodeLoop
  116. {
  117. public:
  118. DecodeLoop() : decoder(0)
  119. {
  120. isAac = 0;
  121. isEAAC = 0;
  122. last_bpos = -1;
  123. need_synclight = true;
  124. done = 0;
  125. br = 0;
  126. g_framesize = 0;
  127. maxlatency = 0;
  128. sampleFrameSize = 0;
  129. memset(&g_samplebuf, 0, sizeof(g_samplebuf));
  130. }
  131. ~DecodeLoop()
  132. {
  133. if (decoder)
  134. {
  135. decoder->Close();
  136. decoder->Release();
  137. }
  138. decoder=0;
  139. }
  140. DWORD Loop();
  141. DWORD OpenDecoder();
  142. void Seek(int seekPosition);
  143. void PreBuffer();
  144. void Decode();
  145. void Viz();
  146. void CalculateCodecDelay();
  147. DWORD OpenOutput(int numChannels, int sampleRate, int bitsPerSample);
  148. void SetupStream();
  149. BYTE g_samplebuf[6*3*2*2*1152];
  150. int g_framesize;
  151. int isAac;
  152. int isEAAC;
  153. CGioFile file;
  154. int maxlatency;
  155. int last_bpos;
  156. bool need_synclight;
  157. int done; // set to TRUE if decoding has finished, 2 if all has been written
  158. size_t br;
  159. EndCutter endCutter;
  160. int sampleFrameSize;
  161. adts *decoder;
  162. };
  163. static int CalcPreBuffer(int buffer_setting, int bitrate)
  164. {
  165. if (bitrate < 8)
  166. bitrate = 8;
  167. else if (bitrate > 320)
  168. bitrate = 320;
  169. int prebuffer = (buffer_setting * bitrate) / 128;
  170. if (prebuffer > 100)
  171. prebuffer=100;
  172. return prebuffer;
  173. }
  174. void DecodeLoop::SetupStream()
  175. {
  176. char buf[1024] = {0};
  177. int len;
  178. m_is_stream = file.IsStream();
  179. //Wait until we have data...
  180. while (!killDecodeThread && file.Peek(buf, 1024, &len) == NErr_Success && !len)
  181. Sleep(50);
  182. m_is_stream_seekable = file.IsStreamSeekable();
  183. char *content_type = file.m_content_type;
  184. if (content_type)
  185. {
  186. if (!_strnicmp(content_type, "misc/ultravox", 13))
  187. {
  188. switch (file.uvox_last_message)
  189. {
  190. case 0x8001:
  191. case 0x8003:
  192. isEAAC = 1;
  193. isAac = 1;
  194. break;
  195. case 0x8000:
  196. isAac = 1;
  197. break;
  198. }
  199. }
  200. else if (!_strnicmp(content_type, "audio/aac", 9))
  201. {
  202. isEAAC = 1;
  203. isAac = 1;
  204. }
  205. else if (!_strnicmp(content_type, "audio/aacp", 10))
  206. {
  207. isEAAC = 1;
  208. isAac = 1;
  209. }
  210. else if (!_strnicmp(content_type, "audio/apl", 10))
  211. {
  212. isEAAC = 1;
  213. isAac = 1;
  214. }
  215. }
  216. // todo: poll until connected to see if we get aac uvox frames or a content-type:aac header
  217. }
  218. DWORD DecodeLoop::OpenOutput(int numChannels, int sampleRate, int bitsPerSample)
  219. {
  220. maxlatency = mod.outMod->Open(sampleRate, numChannels, bitsPerSample, -1, -1);
  221. // maxlatency is the maxium latency between a outMod->Write() call and
  222. // when you hear those samples. In ms. Used primarily by the visualization
  223. // system.
  224. if (maxlatency < 0) // error opening device
  225. {
  226. PostMessage(mod.hMainWindow, WM_COMMAND, 40047, 0);
  227. return 0;
  228. }
  229. g_sndopened = 1;
  230. if (maxlatency == 0 && file.IsStream() == 2) // can't use with disk writer
  231. {
  232. if (!killDecodeThread)
  233. {
  234. EnterCriticalSection(&g_lfnscs);
  235. WASABI_API_LNGSTRING_BUF(IDS_CANNOT_WRITE_STREAMS_TO_DISK,lastfn_status,256);
  236. LeaveCriticalSection(&g_lfnscs);
  237. PostMessage(mod.hMainWindow, WM_USER, 0, IPC_UPDTITLE);
  238. }
  239. if (!killDecodeThread) Sleep(200);
  240. if (!killDecodeThread) PostMessage(mod.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
  241. g_bufferstat = 0;
  242. g_closeaudio = 1;
  243. return 0;
  244. }
  245. if (paused) mod.outMod->Pause(1);
  246. // set the output plug-ins default volume.
  247. // volume is 0-255, -666 is a token for
  248. // current volume.
  249. mod.outMod->SetVolume(-666);
  250. return 1;
  251. }
  252. void DecodeLoop::CalculateCodecDelay()
  253. {
  254. int decoderDelaySamples = (int)decoder->GetDecoderDelay();
  255. endCutter.SetSize(decoderDelaySamples*sampleFrameSize,
  256. file.prepad*sampleFrameSize,
  257. file.postpad*sampleFrameSize);
  258. }
  259. void DecodeLoop::Viz()
  260. {
  261. if (!config_fastvis || (decoder->GetLayer() != 3 || g_ds))
  262. {
  263. int vis_waveNch;
  264. int vis_specNch;
  265. int csa = mod.SAGetMode();
  266. int is_vis_running = mod.VSAGetMode(&vis_specNch, &vis_waveNch);
  267. if (csa || is_vis_running)
  268. {
  269. int l = 576 * sampleFrameSize;
  270. int ti = decode_pos_ms;
  271. {
  272. if (g_ds == 2)
  273. {
  274. memcpy(g_samplebuf + g_samplebuf_used, g_samplebuf, g_samplebuf_used);
  275. }
  276. size_t pos = 0;
  277. while (pos < g_samplebuf_used)
  278. {
  279. int a, b;
  280. if (mod.SAGetMode()) mod.SAAddPCMData((char *)g_samplebuf + pos, g_nch, (int)g_bits, ti);
  281. if (mod.VSAGetMode(&a, &b)) mod.VSAAddPCMData((char *)g_samplebuf + pos, g_nch, (int)g_bits, ti);
  282. ti += ((l / sampleFrameSize * 1000) / g_srate);
  283. pos += l >> g_ds;
  284. }
  285. }
  286. }
  287. }
  288. else
  289. {
  290. int l = (576 * (int)g_bits * g_nch);
  291. int ti = decode_pos_ms;
  292. size_t pos = 0;
  293. int x = 0;
  294. while (pos < g_samplebuf_used)
  295. {
  296. do_layer3_vis((short*)(g_samplebuf + pos), &g_vis_table[x++][0][0][0], g_nch, ti);
  297. ti += (l / g_nch / 2 * 1000) / g_srate;
  298. pos += l;
  299. }
  300. }
  301. }
  302. void DecodeLoop::Decode()
  303. {
  304. while (g_samplebuf_used < (size_t)g_framesize && !killDecodeThread && seek_needed == -1)
  305. {
  306. size_t newl = 0;
  307. size_t br=0;
  308. size_t endCut=0;
  309. int res = decoder->Decode(&file, g_samplebuf + g_samplebuf_used, sizeof(g_samplebuf) / 2 - g_samplebuf_used, &newl, &br, &endCut);
  310. if (config_gapless && endCut)
  311. endCutter.SetEndSize((int)endCut* sampleFrameSize);
  312. // we're not using switch here because we sometimes need to break out of the while loop
  313. if (res == adts::SUCCESS)
  314. {
  315. if (!file.m_vbr_frames)
  316. {
  317. if (br) {
  318. bool do_real_br=false;
  319. if (!(config_miscopts&2) && br != decoder->GetCurrentBitrate())
  320. {
  321. do_real_br=true;
  322. }
  323. int r = (int)br;
  324. g_br_add += r;
  325. g_br_div++;
  326. r = (g_br_add + g_br_div / 2) / g_br_div;
  327. if (g_br != r)
  328. {
  329. need_synclight = false;
  330. g_br = r;
  331. if (!file.m_vbr_frames && file.IsSeekable()) g_length = MulDiv(file.GetContentLength(), 8, g_br);
  332. if (!do_real_br)
  333. mod.SetInfo(g_br, -1, -1, 1);
  334. }
  335. if (do_real_br)
  336. mod.SetInfo((int)br, -1, -1, 1);
  337. }
  338. }
  339. else
  340. {
  341. if (br) {
  342. int r;
  343. if (!(config_miscopts&2) || !g_avg_vbr_br)
  344. r = (int)br;
  345. else r = g_avg_vbr_br;
  346. if (g_br != r)
  347. {
  348. need_synclight = false;
  349. g_br = r;
  350. mod.SetInfo(g_br, -1, -1, 1);
  351. }
  352. }
  353. }
  354. if (need_synclight)
  355. {
  356. need_synclight = false;
  357. mod.SetInfo(-1, -1, -1, 1);
  358. }
  359. g_samplebuf_used += newl;
  360. }
  361. else if (res == adts::ENDOFFILE)
  362. {
  363. done = 1;
  364. break;
  365. }
  366. else if (res == adts::NEEDMOREDATA)
  367. {
  368. if (file.IsStream() && !need_synclight)
  369. {
  370. need_synclight = true; mod.SetInfo(-1, -1, -1, 0);
  371. }
  372. if (file.IsStream() && !mod.outMod->IsPlaying())
  373. {
  374. need_prebuffer = CalcPreBuffer(config_http_prebuffer_underrun, (int)br);
  375. }
  376. break;
  377. }
  378. else
  379. {
  380. if (!need_synclight) mod.SetInfo(-1, -1, -1, 0);
  381. need_synclight = true;
  382. break;
  383. }
  384. }
  385. }
  386. void DecodeLoop::PreBuffer()
  387. {
  388. int p = file.RunStream();
  389. int pa = file.PercentAvailable();
  390. if (pa >= need_prebuffer || p == 2)
  391. {
  392. EnterCriticalSection(&g_lfnscs);
  393. lastfn_status[0] = 0;
  394. LeaveCriticalSection(&g_lfnscs);
  395. PostMessage(mod.hMainWindow, WM_USER, 0, IPC_UPDTITLE);
  396. need_prebuffer = 0;
  397. g_bufferstat = 0;
  398. last_bpos = -1;
  399. }
  400. else
  401. {
  402. int bpos = pa * 100 / need_prebuffer;
  403. if (!g_bufferstat) g_bufferstat = decode_pos_ms;
  404. if (bpos != last_bpos)
  405. {
  406. last_bpos = bpos;
  407. EnterCriticalSection(&g_lfnscs);
  408. if (stricmp(lastfn_status, "stream temporarily interrupted"))
  409. {
  410. char langbuf[512] = {0};
  411. wsprintfA(lastfn_status, WASABI_API_LNGSTRING_BUF(IDS_BUFFER_X,langbuf,512), bpos);
  412. }
  413. LeaveCriticalSection(&g_lfnscs);
  414. int csa = mod.SAGetMode();
  415. char tempdata[75*2] = {0, };
  416. int x;
  417. if (csa&1)
  418. {
  419. for (x = 0; x < bpos*75 / 100; x ++)
  420. {
  421. tempdata[x] = x * 16 / 75;
  422. }
  423. }
  424. if (csa&2)
  425. {
  426. int offs = (csa & 1) ? 75 : 0;
  427. x = 0;
  428. while (x < bpos*75 / 100)
  429. {
  430. tempdata[offs + x++] = -6 + x * 14 / 75;
  431. }
  432. while (x < 75)
  433. {
  434. tempdata[offs + x++] = 0;
  435. }
  436. }
  437. if (csa == 4)
  438. {
  439. tempdata[0] = tempdata[1] = (bpos * 127 / 100);
  440. }
  441. if (csa) mod.SAAdd(tempdata, ++g_bufferstat, (csa == 3) ? 0x80000003 : csa);
  442. PostMessage(mod.hMainWindow, WM_USER, 0, IPC_UPDTITLE);
  443. }
  444. }
  445. }
  446. void DecodeLoop::Seek(int seekPosition)
  447. {
  448. if (done == 3)
  449. return;
  450. done=0;
  451. int br = (int)decoder->GetCurrentBitrate();
  452. need_prebuffer = CalcPreBuffer(config_http_prebuffer_underrun, br);
  453. if (need_prebuffer < 1) need_prebuffer = 5;
  454. last_decode_pos_ms = decode_pos_ms = seekPosition;
  455. seek_needed = -1;
  456. endCutter.Flush(decode_pos_ms);
  457. decoder->Flush(&file);
  458. done = 0;
  459. g_samplebuf_used = 0;
  460. int r = g_br;
  461. if (g_br_div) r = (g_br_add + g_br_div / 2) / g_br_div;
  462. file.Seek(decode_pos_ms, r);
  463. // need_prebuffer=config_http_prebuffer/8;
  464. // g_br_add=g_br_div=0;
  465. }
  466. DWORD DecodeLoop::OpenDecoder()
  467. {
  468. mod.UsesOutputPlug &= ~8;
  469. if (isAac)
  470. {
  471. if (isEAAC)
  472. {
  473. waServiceFactory *factory = mod.service->service_getServiceByGuid(adts_aac_guid);
  474. if (factory)
  475. decoder = (adts *)factory->getInterface();
  476. mod.UsesOutputPlug|=8;
  477. }
  478. if (!decoder)
  479. {
  480. decoder = new ADTS_VLB;
  481. mod.UsesOutputPlug &= ~8;
  482. }
  483. }
  484. else
  485. {
  486. waServiceFactory *factory = mod.service->service_getServiceByGuid(adts_mp2_guid);
  487. if (factory)
  488. decoder = (adts *)factory->getInterface();
  489. mod.UsesOutputPlug|=8;
  490. }
  491. if (decoder) {
  492. decoder->SetDecoderHooks(mp3GiveVisData, mp2Equalize, mp3Equalize);
  493. }
  494. if (decoder
  495. && decoder->Initialize(AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"mono", false),
  496. config_downmix == 2,
  497. AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"surround", true),
  498. (int)AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"bits", 16), true, false,
  499. (config_miscopts&1)/*crc*/) == adts::SUCCESS
  500. && decoder->Open(&file))
  501. {
  502. // sync to stream
  503. while (1)
  504. {
  505. switch (decoder->Sync(&file, g_samplebuf, sizeof(g_samplebuf), &g_samplebuf_used, &br))
  506. {
  507. case adts::SUCCESS:
  508. return 1;
  509. case adts::FAILURE:
  510. case adts::ENDOFFILE:
  511. if (!killDecodeThread)
  512. {
  513. if (!lastfn_status_err)
  514. {
  515. EnterCriticalSection(&g_lfnscs);
  516. WASABI_API_LNGSTRING_BUF(IDS_ERROR_SYNCING_TO_STREAM,lastfn_status,256);
  517. LeaveCriticalSection(&g_lfnscs);
  518. PostMessage(mod.hMainWindow, WM_USER, 0, IPC_UPDTITLE);
  519. }
  520. }
  521. if (!killDecodeThread) Sleep(200);
  522. if (!killDecodeThread) PostMessage(mod.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
  523. return 0;
  524. case adts::NEEDMOREDATA:
  525. if (!killDecodeThread && file.IsStream()) Sleep(25);
  526. if (killDecodeThread) return 0;
  527. }
  528. }
  529. }
  530. return 0;
  531. }
  532. DWORD DecodeLoop::Loop()
  533. {
  534. last_decode_pos_ms = 0;
  535. if (file.Open(lastfn, config_max_bufsize_k) != NErr_Success)
  536. {
  537. if (!killDecodeThread) Sleep(200);
  538. if (!killDecodeThread) PostMessage(mod.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
  539. return 0;
  540. }
  541. if (file.IsSeekable()) mod.is_seekable = 1;
  542. wchar_t *ext = PathFindExtension(lastfn);
  543. if (!_wcsicmp(ext, L".aac")
  544. || !_wcsicmp(ext, L".vlb")
  545. || !_wcsicmp(ext, L".apl"))
  546. {
  547. if (file.IsStream())
  548. SetupStream();
  549. else
  550. {
  551. isAac = 1;
  552. if (!_wcsicmp(ext, L".aac") || !_wcsicmp(ext, L".apl")) isEAAC = 1;
  553. }
  554. }
  555. else if (file.IsStream())
  556. SetupStream();
  557. if (OpenDecoder() == 0)
  558. return 0;
  559. EnterCriticalSection(&streamInfoLock);
  560. g_playing_file = &file;
  561. if (file.uvox_3901)
  562. {
  563. PostMessage(mod.hMainWindow, WM_WA_IPC, (WPARAM) "0x3901", IPC_METADATA_CHANGED);
  564. PostMessage(mod.hMainWindow, WM_WA_IPC, 0, IPC_UPDTITLE);
  565. }
  566. LeaveCriticalSection(&streamInfoLock);
  567. EnterCriticalSection(&g_lfnscs);
  568. lastfn_status[0] = 0;
  569. LeaveCriticalSection(&g_lfnscs);
  570. lastfn_data_ready = 1;
  571. // TODO? if (decoder != &aacp) // hack because aac+ bitrate isn't accurate at this point
  572. br = decoder->GetCurrentBitrate();
  573. need_prebuffer = CalcPreBuffer(config_http_prebuffer, (int)br);
  574. if (((!(config_eqmode&4) && decoder->GetLayer() == 3) ||
  575. ((config_eqmode&8) && decoder->GetLayer() < 3)))
  576. {
  577. mod.UsesOutputPlug |= 2;
  578. }
  579. else
  580. mod.UsesOutputPlug &= ~2;
  581. decoder->CalculateFrameSize(&g_framesize);
  582. decoder->GetOutputParameters(&g_bits, &g_nch, &g_srate);
  583. if (!killDecodeThread && file.IsStream() == 1)
  584. {
  585. DWORD_PTR dw;
  586. if (!killDecodeThread) SendMessageTimeout(mod.hMainWindow, WM_USER, 0, IPC_UPDTITLE, SMTO_BLOCK, 100, &dw);
  587. if (!killDecodeThread) SendMessageTimeout(mod.hMainWindow, WM_TIMER, 38, 0, SMTO_BLOCK, 100, &dw);
  588. }
  589. sampleFrameSize = g_nch * ((int)g_bits/8);
  590. if (config_gapless)
  591. CalculateCodecDelay();
  592. if (OpenOutput(g_nch, g_srate, (int)g_bits) == 0)
  593. return 0;
  594. /* ----- send info to winamp and vis: bitrate, etc ----- */
  595. g_br = (int)decoder->GetCurrentBitrate();
  596. g_br_add = g_br;
  597. g_br_div = 1;
  598. g_avg_vbr_br = file.GetAvgVBRBitrate();
  599. mod.SetInfo(g_br, g_srate / 1000, g_nch, 0);
  600. // initialize visualization stuff
  601. mod.SAVSAInit((maxlatency << g_ds), g_srate);
  602. mod.VSASetInfo(g_srate, g_nch);
  603. /* ----- end send info to winamp and vis ----- */
  604. if (file.IsSeekable() && g_br)
  605. {
  606. mod.is_seekable = 1;
  607. if (!file.m_vbr_frames) g_length = MulDiv(file.GetContentLength(), 8, g_br);
  608. else g_length = file.m_vbr_ms;
  609. }
  610. if (file.IsStream())
  611. {
  612. if (need_prebuffer < config_http_prebuffer / 2)
  613. need_prebuffer = config_http_prebuffer / 2;
  614. }
  615. while (!killDecodeThread)
  616. {
  617. if (seek_needed != -1)
  618. Seek(seek_needed);
  619. if (need_prebuffer && file.IsStream() && maxlatency && !file.EndOf())
  620. PreBuffer();
  621. int needsleep = 1;
  622. if (done == 2) // done was set to TRUE during decoding, signaling eof
  623. {
  624. mod.outMod->CanWrite(); // some output drivers need CanWrite
  625. // to be called on a regular basis.
  626. if (!mod.outMod->IsPlaying())
  627. {
  628. // we're done playing, so tell Winamp and quit the thread.
  629. if (!killDecodeThread) PostMessage(mod.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
  630. done=3;
  631. break;
  632. }
  633. }
  634. else
  635. {
  636. int fs = (g_framesize * ((mod.dsp_isactive() == 1) ? 2 : 1));
  637. // TODO: we should really support partial writes, there's no gaurantee that CanWrite() will EVER get big enough
  638. if (mod.outMod->CanWrite() >= fs && (!need_prebuffer || !file.IsStream() || !maxlatency))
  639. // CanWrite() returns the number of bytes you can write, so we check that
  640. // to the block size. the reason we multiply the block size by two if
  641. // mod.dsp_isactive() is that DSP plug-ins can change it by up to a
  642. // factor of two (for tempo adjustment).
  643. {
  644. int p = mod.SAGetMode();
  645. g_vis_enabled = ((p & 1) || p == 4);
  646. if (!g_vis_enabled)
  647. {
  648. int s, a;
  649. mod.VSAGetMode(&s, &a);
  650. if (s) g_vis_enabled = 1;
  651. }
  652. Decode();
  653. if ((g_samplebuf_used >= (size_t)g_framesize || (done && g_samplebuf_used > 0)) && seek_needed == -1)
  654. {
  655. // adjust decode position variable
  656. if (file.isSeekReset())
  657. last_decode_pos_ms = decode_pos_ms = 0;
  658. else
  659. decode_pos_ms += ((int)g_samplebuf_used / sampleFrameSize * 1000) / g_srate;
  660. // if we have a DSP plug-in, then call it on our samples
  661. if (mod.dsp_isactive())
  662. {
  663. g_samplebuf_used = mod.dsp_dosamples((short *)g_samplebuf, (int)g_samplebuf_used / sampleFrameSize, (int)g_bits, g_nch, g_srate) * sampleFrameSize;
  664. }
  665. Viz();
  666. endCutter.Write((char *)g_samplebuf, (int)g_samplebuf_used);
  667. g_samplebuf_used = 0;
  668. needsleep = 0;
  669. //memcpy(g_samplebuf,g_samplebuf+r,g_samplebuf_used);
  670. }
  671. if (done)
  672. {
  673. endCutter.Write(0, 0);
  674. done = 2;
  675. }
  676. }
  677. }
  678. if (decode_pos_ms > last_decode_pos_ms + 1000)
  679. {
  680. last_decode_pos_ms = decode_pos_ms;
  681. }
  682. if (needsleep) Sleep(10);
  683. // if we can't write data, wait a little bit. Otherwise, continue
  684. // through the loop writing more data (without sleeping)
  685. }
  686. /* ---- change some globals to let everyone know we're done */
  687. EnterCriticalSection(&g_lfnscs);
  688. lastfn_status[0] = 0;
  689. LeaveCriticalSection(&g_lfnscs);
  690. g_bufferstat = 0;
  691. g_closeaudio = 1;
  692. /* ---- */
  693. return 0;
  694. }
  695. DWORD WINAPI DecodeThread(LPVOID b)
  696. {
  697. DecodeLoop loop;
  698. DWORD ret = loop.Loop();
  699. EnterCriticalSection(&streamInfoLock);
  700. g_playing_file = 0;
  701. LeaveCriticalSection(&streamInfoLock);
  702. return ret;
  703. }