PlayThread.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. #include "MKVPlayer.h"
  2. #include "api__in_mkv.h"
  3. #include "main.h"
  4. #include "../Winamp/wa_ipc.h"
  5. #include "../nsmkv/nsmkv.h"
  6. #include "../nu/AutoLock.h"
  7. #include "../nu/ns_wc.h"
  8. #include "../nu/AutoWide.h"
  9. #include "../nu/AudioOutput.h"
  10. #include "ifc_mkvaudiodecoder.h"
  11. #include "svc_mkvdecoder.h"
  12. #include "ifc_mkvvideodecoder.h"
  13. #include "../nsmkv/file_mkv_reader.h"
  14. #include <api/service/waservicefactory.h>
  15. #include <api/service/services.h>
  16. #include <windows.h>
  17. #include <strsafe.h>
  18. // {B6CB4A7C-A8D0-4c55-8E60-9F7A7A23DA0F}
  19. static const GUID playbackConfigGroupGUID =
  20. {
  21. 0xb6cb4a7c, 0xa8d0, 0x4c55, { 0x8e, 0x60, 0x9f, 0x7a, 0x7a, 0x23, 0xda, 0xf }
  22. };
  23. IVideoOutput *videoOutput = 0;
  24. /* benski>
  25. TODO: keep track of "fully parsed position" we don't have to always start over at segment_position
  26. TODO: if we have multiple audio or video tracks, do that weird winamp interface for it
  27. */
  28. void MKVPlayer::MKVWait::Wait_SetEvents(HANDLE killswitch, HANDLE seek_event)
  29. {
  30. handles[0]=killswitch;
  31. handles[1]=seek_event;
  32. }
  33. int MKVPlayer::MKVWait::WaitOrAbort(int time_in_ms)
  34. {
  35. switch(WaitForMultipleObjects(2, handles, FALSE, 55))
  36. {
  37. case WAIT_TIMEOUT: // all good, wait successful
  38. return 0;
  39. case WAIT_OBJECT_0: // killswitch
  40. return MKVPlayer::MKV_STOP;
  41. case WAIT_OBJECT_0+1: // seek event
  42. return MKVPlayer::MKV_ABORT;
  43. default: // some OS error?
  44. return MKVPlayer::MKV_ERROR;
  45. }
  46. }
  47. MKVPlayer::MKVPlayer(const wchar_t *_filename) : audio_output(&plugin)
  48. {
  49. first_cluster_found = false;
  50. cues_searched = false;
  51. segment_position=0;
  52. segment_size = 0;
  53. filename = _wcsdup(_filename);
  54. m_needseek = -1;
  55. audio_decoder=0;
  56. audio_track_num=0;
  57. audio_output_len = 65536;
  58. audio_opened=false;
  59. audio_flushing=FLUSH_START;
  60. audio_first_timestamp=0;
  61. audio_buffered=0;
  62. audio_bitrate=0;
  63. video_decoder=0;
  64. video_track_num=0;
  65. video_opened = false;
  66. video_stream = 0;
  67. video_thread = 0;
  68. video_timecode_scale = 0;
  69. video_cluster_position = 0;
  70. video_track_entry = 0;
  71. video_bitrate = 0;
  72. consecutive_early_frames = 0;
  73. if (!videoOutput)
  74. videoOutput = (IVideoOutput *)SendMessage(plugin.hMainWindow, WM_WA_IPC, 0, IPC_GET_IVIDEOOUTPUT);
  75. killswitch = CreateEvent(NULL, TRUE, FALSE, NULL);
  76. seek_event = CreateEvent(NULL, TRUE, FALSE, NULL);
  77. /* video events */
  78. video_break = CreateEvent(NULL, TRUE, FALSE, NULL);
  79. video_flush_done = CreateEvent(NULL, FALSE, FALSE, NULL);
  80. video_flush = CreateEvent(NULL, TRUE, FALSE, NULL);
  81. video_resume = CreateEvent(NULL, TRUE, FALSE, NULL);
  82. video_ready = CreateEvent(NULL, TRUE, FALSE, NULL);
  83. audio_output.Wait_SetEvents(killswitch, seek_event);
  84. }
  85. MKVPlayer::~MKVPlayer() {
  86. free(filename);
  87. CloseHandle(killswitch);
  88. CloseHandle(seek_event);
  89. CloseHandle(video_break);
  90. CloseHandle(video_flush_done);
  91. CloseHandle(video_flush);
  92. CloseHandle(video_resume);
  93. CloseHandle(video_ready);
  94. if (audio_decoder) {
  95. audio_decoder->Close();
  96. }
  97. delete main_reader;
  98. }
  99. void MKVPlayer::Kill()
  100. {
  101. SetEvent(killswitch);
  102. if (video_thread)
  103. WaitForSingleObject(video_thread, INFINITE);
  104. video_thread = 0;
  105. if (video_decoder)
  106. video_decoder->Close();
  107. video_decoder=0;
  108. }
  109. void MKVPlayer::Seek(int seek_pos)
  110. {
  111. m_needseek = seek_pos;
  112. SetEvent(seek_event);
  113. }
  114. int MKVPlayer::GetOutputTime() const
  115. {
  116. if (m_needseek != -1)
  117. return m_needseek;
  118. else
  119. return plugin.outMod->GetOutputTime() + audio_first_timestamp;
  120. }
  121. DWORD CALLBACK MKVThread(LPVOID param)
  122. {
  123. MKVPlayer *player = (MKVPlayer *)param;
  124. DWORD ret = player->ThreadFunction();
  125. return ret;
  126. }
  127. bool MKVPlayer::FindCues()
  128. {
  129. if (cues_searched)
  130. return true;
  131. uint64_t original_position = main_reader->Tell();
  132. // first, let's try the seek table
  133. uint64_t cues_position = 0;
  134. if (seek_table.GetEntry(mkv_segment_cues, &cues_position))
  135. {
  136. main_reader->Seek(cues_position+segment_position);
  137. ebml_node node;
  138. if (read_ebml_node(main_reader, &node) == 0)
  139. return false;
  140. if (node.id == mkv_segment_cues) // great success!
  141. {
  142. if (nsmkv::ReadCues(main_reader, node.size, cues) == 0)
  143. return false;
  144. cues_searched=true;
  145. main_reader->Seek(original_position);
  146. return true;
  147. }
  148. }
  149. main_reader->Seek(segment_position); // TODO: keep track of how far Step() has gotten so we don't have to start from scratch
  150. /* --- TODO: make this block into a function in nsmkv --- */
  151. while (1) // TODO: key off segment size to make sure we don't overread
  152. {
  153. uint64_t this_position = main_reader->Tell();
  154. ebml_node node;
  155. if (read_ebml_node(main_reader, &node) == 0)
  156. return false;
  157. if (node.id != mkv_void)
  158. {
  159. nsmkv::SeekEntry seek_entry(node.id, this_position-segment_position);
  160. seek_table.AddEntry(seek_entry, nsmkv::SeekTable::ADDENTRY_FOUND);
  161. }
  162. if (node.id == mkv_segment_cues)
  163. {
  164. if (nsmkv::ReadCues(main_reader, node.size, cues) == 0)
  165. return false;
  166. break;
  167. }
  168. else
  169. {
  170. main_reader->Skip(node.size);
  171. }
  172. }
  173. /* ------ */
  174. cues_searched=true;
  175. main_reader->Seek(original_position);
  176. return true;
  177. }
  178. bool MKVPlayer::ParseHeader()
  179. {
  180. ebml_node node;
  181. if (read_ebml_node(main_reader, &node) == 0)
  182. return false;
  183. if (node.id != mkv_header)
  184. return false;
  185. if (nsmkv::ReadHeader(main_reader, node.size, header) == 0)
  186. return false;
  187. if (OnHeader(header) != MKV_CONTINUE)
  188. return false;
  189. return true;
  190. }
  191. bool MKVPlayer::FindSegment()
  192. {
  193. ebml_node node;
  194. while (segment_position == 0)
  195. {
  196. if (read_ebml_node(main_reader, &node) == 0)
  197. return false;
  198. if (node.id == mkv_segment)
  199. {
  200. segment_position = main_reader->Tell();
  201. segment_size = node.size;
  202. }
  203. else
  204. {
  205. if (nsmkv::SkipNode(main_reader, node.id, node.size) == 0)
  206. return false;
  207. }
  208. }
  209. return true;
  210. }
  211. static ifc_mkvvideodecoder *FindVideoDecoder(const nsmkv::TrackEntry *track_entry)
  212. {
  213. size_t n = 0;
  214. waServiceFactory *sf = 0;
  215. while (sf = plugin.service->service_enumService(WaSvc::MKVDECODER, n++))
  216. {
  217. svc_mkvdecoder *dec = static_cast<svc_mkvdecoder *>(sf->getInterface());
  218. if (dec)
  219. {
  220. ifc_mkvvideodecoder *decoder=0;
  221. if (dec->CreateVideoDecoder(track_entry->codec_id, track_entry, &track_entry->video, &decoder) == svc_mkvdecoder::CREATEDECODER_SUCCESS)
  222. {
  223. sf->releaseInterface(dec);
  224. return decoder;
  225. }
  226. sf->releaseInterface(dec);
  227. }
  228. }
  229. return 0;
  230. }
  231. static ifc_mkvaudiodecoder *FindAudioDecoder(const nsmkv::TrackEntry *track_entry)
  232. {
  233. unsigned int bits_per_sample = (unsigned int)AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"bits", 16);
  234. if (bits_per_sample >= 24) bits_per_sample = 24;
  235. else bits_per_sample = 16;
  236. unsigned int max_channels;
  237. // get max channels
  238. if (AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"surround", true))
  239. max_channels = 6;
  240. else if (AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"mono", false))
  241. max_channels = 1;
  242. else
  243. max_channels = 2;
  244. size_t n=0;
  245. waServiceFactory *sf = 0;
  246. while (sf = plugin.service->service_enumService(WaSvc::MKVDECODER, n++))
  247. {
  248. svc_mkvdecoder *dec = static_cast<svc_mkvdecoder *>(sf->getInterface());
  249. if (dec)
  250. {
  251. ifc_mkvaudiodecoder *decoder=0;
  252. // TODO: read from api_config!!
  253. if (dec->CreateAudioDecoder(track_entry->codec_id, track_entry, &track_entry->audio, bits_per_sample, max_channels, false, &decoder) == svc_mkvdecoder::CREATEDECODER_SUCCESS)
  254. {
  255. sf->releaseInterface(dec);
  256. return decoder;
  257. }
  258. sf->releaseInterface(dec);
  259. }
  260. }
  261. return 0;
  262. }
  263. int MKVPlayer::OnAudio(const nsmkv::Cluster &cluster, const nsmkv::BlockBinary &binary)
  264. {
  265. if (video_decoder)
  266. {
  267. HANDLE handles[3] = {killswitch, seek_event, video_ready};
  268. if (WaitForMultipleObjects(3, handles, FALSE, INFINITE) != WAIT_OBJECT_0+2)
  269. return MKV_ABORT;
  270. }
  271. if (audio_flushing != FLUSH_NONE)
  272. {
  273. uint64_t timestamp=cluster.time_code + binary.time_code;
  274. uint64_t timestamp_ms = segment_info.time_code_scale * timestamp / 1000000ULL;
  275. if (audio_flushing == FLUSH_START || !audio_opened)
  276. {
  277. audio_first_timestamp = (int)timestamp_ms;
  278. }
  279. else
  280. {
  281. audio_first_timestamp=0;
  282. audio_output.Flush((int)timestamp_ms);
  283. m_needseek = -1;
  284. }
  285. audio_flushing=FLUSH_NONE;
  286. }
  287. nsmkv::LacingState lacing_state;
  288. uint32_t i = 0;
  289. if (nsmkv::Lacing::GetState(binary.flags, (const uint8_t *)binary.data, binary.data_size, &lacing_state))
  290. {
  291. const uint8_t *frame = 0;
  292. size_t frame_len = 0;
  293. while (nsmkv::Lacing::GetFrame(i++, (const uint8_t *)binary.data, binary.data_size, &frame, &frame_len, &lacing_state))
  294. {
  295. size_t decoded_size = audio_output_len-audio_buffered;
  296. if (audio_decoder->DecodeBlock((void *)frame, frame_len, audio_buffer+audio_buffered, &decoded_size) == ifc_mkvaudiodecoder::MKV_SUCCESS)
  297. {
  298. decoded_size+=audio_buffered;
  299. audio_buffered=0;
  300. if (!audio_opened)
  301. {
  302. unsigned int sample_rate, channels, bps;
  303. bool is_float;
  304. if (audio_decoder->GetOutputProperties(&sample_rate, &channels, &bps, &is_float) == ifc_mkvaudiodecoder::MKV_SUCCESS)
  305. {
  306. // TODO: pass -666 for 5th param if video
  307. if (!audio_output.Open(audio_first_timestamp, channels, sample_rate, bps, -1, -1))
  308. {
  309. return MKV_STOP;
  310. }
  311. audio_opened=true;
  312. }
  313. }
  314. if (audio_opened && decoded_size)
  315. {
  316. int ret = audio_output.Write((char *)audio_buffer, decoded_size);
  317. if (ret != 0)
  318. return ret;
  319. }
  320. else
  321. {
  322. audio_buffered=decoded_size;
  323. }
  324. }
  325. }
  326. }
  327. return MKV_CONTINUE;
  328. }
  329. int MKVPlayer::OutputPictures(uint64_t default_timestamp)
  330. {
  331. void *data=0, *decoder_data=0;
  332. uint64_t timestamp=default_timestamp;
  333. while (video_decoder->GetPicture(&data, &decoder_data, &timestamp) == ifc_mkvvideodecoder::MKV_SUCCESS)
  334. {
  335. if (!video_opened)
  336. {
  337. int color_format = 0;
  338. int width = 0, height = 0;
  339. double aspect_ratio = 1.0;
  340. if (video_decoder->GetOutputProperties(&width, &height, &color_format, &aspect_ratio) == ifc_mkvvideodecoder::MKV_SUCCESS)
  341. {
  342. if (video_track_entry && video_track_entry->video.display_height && video_track_entry->video.display_width && video_track_entry->video.pixel_height && video_track_entry->video.pixel_width)
  343. {
  344. aspect_ratio = (double)video_track_entry->video.pixel_width / (double)video_track_entry->video.pixel_height / ((double)video_track_entry->video.display_width / (double)video_track_entry->video.display_height);
  345. }
  346. else
  347. {
  348. // winamp wants an "aspect correction value" not the true aspect ratio itself
  349. aspect_ratio = 1.0/aspect_ratio;
  350. }
  351. videoOutput->extended(VIDUSER_SET_THREAD_SAFE, 1, 0);
  352. videoOutput->open(width, height, 0, aspect_ratio, color_format);
  353. video_opened=true;
  354. SetEvent(video_ready);
  355. }
  356. }
  357. if (video_opened)
  358. {
  359. uint64_t timestamp_ms;
  360. if (video_timecode_scale == 0)
  361. timestamp_ms = segment_info.time_code_scale * timestamp / 1000000ULL;
  362. else
  363. timestamp_ms = (uint64_t) (video_timecode_scale * (double)segment_info.time_code_scale * (double)timestamp / 1000000.0);
  364. again:
  365. int realTime = plugin.outMod->GetOutputTime() + audio_first_timestamp;
  366. int time_diff = (int)timestamp_ms - realTime;
  367. if (time_diff > 12 && consecutive_early_frames) // plenty of time, go ahead and turn off frame dropping
  368. {
  369. if (--consecutive_early_frames == 0)
  370. video_decoder->HurryUp(0);
  371. }
  372. else if (time_diff < -50) // shit we're way late, start dropping frames
  373. {
  374. video_decoder->HurryUp(1);
  375. consecutive_early_frames += 3;
  376. }
  377. if (time_diff > 3)
  378. {
  379. HANDLE handles[] = {killswitch, video_break};
  380. int ret= WaitForMultipleObjects(2, handles, FALSE, (DWORD)(timestamp_ms-realTime));
  381. if (ret != WAIT_TIMEOUT)
  382. {
  383. video_decoder->FreePicture(data, decoder_data);
  384. if (ret == WAIT_OBJECT_0+1) /* second event doesn't stop stream*/
  385. return MKV_ABORT;
  386. return MKV_STOP;
  387. }
  388. goto again; // TODO: handle paused state a little better than this
  389. }
  390. videoOutput->draw(data);
  391. }
  392. video_decoder->FreePicture(data, decoder_data);
  393. }
  394. return MKV_CONTINUE;
  395. }
  396. int MKVPlayer::OnVideo(const nsmkv::Cluster &cluster, const nsmkv::BlockBinary &binary)
  397. {
  398. if (video_decoder)
  399. {
  400. nsmkv::LacingState lacing_state;
  401. uint32_t i = 0;
  402. if (nsmkv::Lacing::GetState(binary.flags, (const uint8_t *)binary.data, binary.data_size, &lacing_state))
  403. {
  404. const uint8_t *frame = 0;
  405. size_t frame_len = 0;
  406. while (nsmkv::Lacing::GetFrame(i++, (const uint8_t *)binary.data, binary.data_size, &frame, &frame_len, &lacing_state))
  407. {
  408. // matroska epic fail: laced frames don't have separate timestamps!
  409. if (video_decoder) video_decoder->DecodeBlock(frame, frame_len, cluster.time_code+binary.time_code);
  410. uint64_t timestamp=cluster.time_code + binary.time_code;
  411. int ret = OutputPictures(timestamp);
  412. if (ret != MKV_CONTINUE)
  413. return ret;
  414. }
  415. }
  416. }
  417. return MKV_CONTINUE;
  418. }
  419. DWORD CALLBACK MKVPlayer::VideoThreadFunction()
  420. {
  421. //video_stream = _wfopen(filename, L"rb");
  422. if (!video_stream)
  423. return 1;
  424. video_stream->Seek(video_cluster_position);
  425. HANDLE handles[] = { killswitch, video_break, video_flush, video_resume };
  426. DWORD waitTime = 0;
  427. while (1)
  428. {
  429. int ret = WaitForMultipleObjects(4, handles, FALSE, waitTime);
  430. if (ret == WAIT_TIMEOUT)
  431. {
  432. int ret = Step(video_stream, &video_track_num, 1);
  433. if (ret == MKV_EOF)
  434. {
  435. video_decoder->EndOfStream();
  436. OutputPictures(0);
  437. // TODO: tell decoder about end-of-stream to flush buffers
  438. waitTime = INFINITE;
  439. }
  440. else if (ret == MKV_ERROR || ret == MKV_STOP)
  441. {
  442. waitTime = INFINITE; // wait for killswitch
  443. }
  444. }
  445. else if (ret == WAIT_OBJECT_0)
  446. {
  447. break;
  448. }
  449. else if (ret == WAIT_OBJECT_0 + 1) // video break
  450. {
  451. waitTime = INFINITE; // this will stop us from decoding samples for a while
  452. ResetEvent(video_break);
  453. SetEvent(video_flush_done);
  454. }
  455. else if (ret == WAIT_OBJECT_0 + 2) // video flush
  456. {
  457. if (video_decoder)
  458. video_decoder->Flush();
  459. ResetEvent(video_flush);
  460. waitTime = 0;
  461. SetEvent(video_flush_done);
  462. }
  463. else if (ret == WAIT_OBJECT_0 + 3) // resume video
  464. {
  465. ResetEvent(video_resume);
  466. waitTime = 0;
  467. SetEvent(video_flush_done);
  468. }
  469. }
  470. if (videoOutput)
  471. videoOutput->close();
  472. delete video_stream;
  473. video_stream=0;
  474. return 0;
  475. }
  476. int MKVPlayer::OnHeader(const nsmkv::Header &header)
  477. {
  478. // TODO: figure out if the file is really matroska, and if we can support the ebml version
  479. return MKV_CONTINUE;
  480. }
  481. void MKVPlayer::OnSegmentInfo(const nsmkv::SegmentInfo &segment_info)
  482. {
  483. g_duration = segment_info.GetDurationMilliseconds();
  484. uint64_t content_length = main_reader->GetContentLength();
  485. if (content_length && g_duration)
  486. {
  487. int bitrate = (int)(8ULL * content_length / (uint64_t)g_duration);
  488. plugin.SetInfo(bitrate, -1, -1, -1);
  489. }
  490. }
  491. int MKVPlayer::OnTracks(const nsmkv::Tracks &tracks)
  492. {
  493. wchar_t audio_info[256] = {0};
  494. wchar_t video_info[256] = {0};
  495. // ===== enumerate tracks and find decoders =====
  496. size_t i=0;
  497. const nsmkv::TrackEntry *track_entry;
  498. while (track_entry = tracks.EnumTrack(i++))
  499. {
  500. if (track_entry->track_type == mkv_track_type_audio && !audio_decoder)
  501. {
  502. audio_decoder = FindAudioDecoder(track_entry);
  503. if (audio_decoder)
  504. {
  505. MultiByteToWideCharSZ(CP_UTF8, 0, track_entry->codec_id, -1, audio_info, 256);
  506. audio_track_num = track_entry->track_number;
  507. }
  508. }
  509. else if (track_entry->track_type == mkv_track_type_video && !video_decoder)
  510. {
  511. video_decoder = FindVideoDecoder(track_entry);
  512. if (video_decoder)
  513. {
  514. StringCbPrintfW(video_info, sizeof(video_info), L"%s %I64ux%I64u", AutoWide(track_entry->codec_id, CP_UTF8), track_entry->video.pixel_width, track_entry->video.pixel_height);
  515. video_track_num = track_entry->track_number;
  516. video_stream = new MKVReaderFILE(filename);
  517. video_timecode_scale = track_entry->track_timecode_scale;
  518. video_track_entry = track_entry;
  519. }
  520. }
  521. }
  522. // TODO this prevents trying to play video only files
  523. // which the plug-in is not at all happy playing
  524. /*if (!audio_decoder)// && !video_decoder)
  525. return MKV_STOP;*/
  526. wchar_t video_status[512] = {0};
  527. if (audio_decoder && video_decoder)
  528. {
  529. StringCbPrintf(video_status, sizeof(video_status), L"MKV: %s, %s", audio_info, video_info);
  530. videoOutput->extended(VIDUSER_SET_INFOSTRINGW,(INT_PTR)video_status,0);
  531. }
  532. else if (audio_decoder)
  533. {
  534. StringCbPrintf(video_status, sizeof(video_status), L"MKV: %s", audio_info);
  535. videoOutput->extended(VIDUSER_SET_INFOSTRINGW,(INT_PTR)video_status,0);
  536. }
  537. else if (video_decoder)
  538. {
  539. StringCbPrintf(video_status, sizeof(video_status), L"MKV: %s, %s", audio_info, video_info);
  540. videoOutput->extended(VIDUSER_SET_INFOSTRINGW,(INT_PTR)video_status,0);
  541. }
  542. return MKV_CONTINUE;
  543. }
  544. DWORD CALLBACK VideoThread(LPVOID param)
  545. {
  546. MKVPlayer *player = (MKVPlayer *)param;
  547. return player->VideoThreadFunction();
  548. }
  549. int MKVPlayer::ParseCluster(nsmkv::MKVReader *stream, uint64_t size, uint64_t *track_numbers, size_t track_numbers_len)
  550. {
  551. nsmkv::Cluster cluster;
  552. uint64_t total_bytes_read=0;
  553. while (size)
  554. {
  555. ebml_node node;
  556. uint64_t bytes_read = read_ebml_node(stream, &node);
  557. if (bytes_read == 0)
  558. return MKV_ERROR;
  559. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  560. if (bytes_read > size)
  561. return MKV_ERROR;
  562. total_bytes_read+=bytes_read;
  563. size-=bytes_read;
  564. if (node.size > size)
  565. return MKV_ERROR;
  566. total_bytes_read+=node.size;
  567. size-=node.size;
  568. switch(node.id)
  569. {
  570. case mkv_cluster_timecode:
  571. {
  572. uint64_t val;
  573. if (read_unsigned(stream, node.size, &val) == 0)
  574. return MKV_ERROR;
  575. printf("Time Code: %I64u\n", val);
  576. cluster.time_code = val;
  577. }
  578. break;
  579. case mkv_cluster_blockgroup:
  580. {
  581. printf("Block Group\n");
  582. nsmkv::Block block;
  583. if (nsmkv::ReadBlockGroup(stream, node.size, block, track_numbers, track_numbers_len) == 0)
  584. return MKV_ERROR;
  585. if (block.binary.data)
  586. {
  587. int ret = OnBlock(cluster, block);
  588. if (ret != MKV_CONTINUE)
  589. return ret;
  590. }
  591. }
  592. break;
  593. case mkv_cluster_simpleblock:
  594. {
  595. printf("simple block, size: %I64u\n", node.size);
  596. nsmkv::Block block;
  597. if (ReadBlockBinary(stream, node.size, block.binary, track_numbers, track_numbers_len) == 0)
  598. return 0;
  599. if (block.binary.data)
  600. {
  601. int ret = OnBlock(cluster, block);
  602. if (ret != MKV_CONTINUE)
  603. return ret;
  604. }
  605. }
  606. break;
  607. default:
  608. nsmkv::ReadGlobal(stream, node.id, node.size);
  609. }
  610. }
  611. return MKV_CONTINUE;
  612. }
  613. int MKVPlayer::OnBlock(const nsmkv::Cluster &cluster, const nsmkv::Block &block)
  614. {
  615. if (WaitForSingleObject(killswitch, 0) == WAIT_TIMEOUT)
  616. {
  617. if (block.binary.track_number == audio_track_num)
  618. {
  619. return OnAudio(cluster, block.binary);
  620. }
  621. else if (block.binary.track_number == video_track_num)
  622. {
  623. return OnVideo(cluster, block.binary);
  624. }
  625. return MKV_CONTINUE;
  626. }
  627. else
  628. return MKV_ABORT;
  629. }
  630. int MKVPlayer::OnFirstCluster(uint64_t position)
  631. {
  632. if (video_decoder)
  633. {
  634. video_cluster_position = position;
  635. video_thread = CreateThread(0, 0, VideoThread, this, 0, 0);
  636. SetThreadPriority(video_thread, (int)AGAVE_API_CONFIG->GetInt(playbackConfigGroupGUID, L"priority", THREAD_PRIORITY_HIGHEST));
  637. }
  638. return MKV_CONTINUE;
  639. }
  640. int MKVPlayer::Step(nsmkv::MKVReader *stream, uint64_t *track_numbers, size_t track_numbers_len)
  641. {
  642. uint64_t this_position = stream->Tell();
  643. ebml_node node;
  644. if (read_ebml_node(stream, &node) == 0)
  645. return MKV_EOF;
  646. if (node.id != mkv_void)
  647. {
  648. nsmkv::SeekEntry seek_entry(node.id, this_position-segment_position);
  649. seek_table.AddEntry(seek_entry, nsmkv::SeekTable::ADDENTRY_FOUND);
  650. }
  651. switch(node.id)
  652. {
  653. case mkv_segment_segmentinfo:
  654. if (nsmkv::ReadSegmentInfo(stream, node.size, segment_info) == 0)
  655. return MKV_EOF;
  656. OnSegmentInfo(segment_info);
  657. break;
  658. case mkv_metaseek_seekhead:
  659. if (nsmkv::ReadSeekHead(stream, node.size, seek_table) == 0)
  660. return MKV_EOF;
  661. break;
  662. case mkv_segment_tracks:
  663. if (nsmkv::ReadTracks(stream, node.size, tracks) == 0)
  664. return MKV_EOF;
  665. return OnTracks(tracks);
  666. break;
  667. case mkv_segment_cues:
  668. if (!cues_searched)
  669. {
  670. if (nsmkv::ReadCues(stream, node.size, cues) == 0)
  671. return MKV_EOF;
  672. cues_searched=true;
  673. }
  674. else
  675. {
  676. stream->Skip(node.size);
  677. }
  678. break;
  679. case mkv_segment_cluster:
  680. if (!first_cluster_found)
  681. {
  682. first_cluster_found=true;
  683. OnFirstCluster(this_position);
  684. }
  685. return ParseCluster(stream, node.size, track_numbers, track_numbers_len);
  686. break;
  687. case mkv_segment_attachments:
  688. if (nsmkv::ReadAttachment(stream, node.size, attachments) == 0)
  689. return MKV_EOF;
  690. break;
  691. default:
  692. if (nsmkv::ReadGlobal(stream, node.id, node.size) == 0)
  693. return MKV_EOF;
  694. break;
  695. }
  696. return MKV_CONTINUE;
  697. }
  698. DWORD CALLBACK MKVPlayer::ThreadFunction()
  699. {
  700. // ===== tell audio output helper object about the output plugin =====
  701. audio_output.Init(plugin.outMod);
  702. FILE *f = _wfopen(filename, L"rb");
  703. if (!f)
  704. goto btfo;
  705. main_reader = new MKVReaderFILE(f);
  706. // ===== read the header =====
  707. if (!ParseHeader())
  708. goto btfo;
  709. // ===== find segment start =====
  710. if (!FindSegment())
  711. goto btfo;
  712. // TODO: try to find more segments?
  713. HANDLE handles[] = {killswitch, seek_event};
  714. while(1)
  715. {
  716. int ret = WaitForMultipleObjects(2, handles, FALSE, 0);
  717. if (ret == WAIT_TIMEOUT)
  718. {
  719. int ret = Step(main_reader, &audio_track_num, 1);
  720. if (ret == MKV_EOF)
  721. {
  722. break;
  723. }
  724. else if (ret == MKV_ERROR || ret == MKV_STOP)
  725. {
  726. break;
  727. }
  728. }
  729. else if (ret == WAIT_OBJECT_0) // kill
  730. {
  731. break;
  732. }
  733. else if (ret == WAIT_OBJECT_0+1) // seek event
  734. {
  735. ResetEvent(seek_event);
  736. // pause video thread
  737. if (video_decoder)
  738. {
  739. SetEvent(video_break);
  740. WaitForSingleObject(video_flush_done, INFINITE);
  741. }
  742. FindCues();
  743. uint64_t seek_time = segment_info.ConvertMillisecondsToTime(m_needseek);
  744. uint64_t curr_time = segment_info.ConvertMillisecondsToTime(plugin.outMod->GetOutputTime() + audio_first_timestamp);
  745. int direction = (curr_time < seek_time)?nsmkv::Cues::SEEK_FORWARD:nsmkv::Cues::SEEK_BACKWARD;
  746. nsmkv::CuePoint *cue_point = cues.GetCuePoint(seek_time, curr_time, direction);
  747. if (cue_point)
  748. {
  749. nsmkv::CueTrackPosition *position = cue_point->GetPosition(audio_track_num);
  750. if (!position) // some files don't have the audio track. we're going to assume the data is interleaved and just use the video track
  751. position = cue_point->GetPosition(video_track_num);
  752. if (position)
  753. {
  754. audio_flushing=FLUSH_SEEK;
  755. if (audio_decoder) audio_decoder->Flush();
  756. main_reader->Seek(position->cluster_position + segment_position);
  757. }
  758. if (video_stream)
  759. {
  760. position = cue_point->GetPosition(video_track_num);
  761. if (position)
  762. {
  763. video_stream->Seek(position->cluster_position + segment_position);
  764. }
  765. }
  766. }
  767. else
  768. {
  769. // TODO enumerate clusters & blocks to find closest time (ugh)
  770. }
  771. if (video_decoder)
  772. {
  773. SetEvent(video_flush);
  774. WaitForSingleObject(video_flush_done, INFINITE);
  775. }
  776. }
  777. }
  778. delete main_reader;
  779. main_reader=0;
  780. if (WaitForSingleObject(killswitch, 0) != WAIT_OBJECT_0)
  781. {
  782. // TODO: tell audio decoder about end-of-stream and get remaining audio
  783. audio_output.Write(0,0);
  784. audio_output.WaitWhilePlaying();
  785. if (WaitForSingleObject(killswitch, 0) != WAIT_OBJECT_0)
  786. PostMessage(plugin.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
  787. }
  788. if (audio_decoder)
  789. {
  790. audio_decoder->Close();
  791. audio_decoder=0;
  792. audio_output.Close();
  793. }
  794. return 0;
  795. btfo: // bail the fuck out
  796. if (WaitForSingleObject(killswitch, 0) != WAIT_OBJECT_0)
  797. PostMessage(plugin.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
  798. delete main_reader;
  799. main_reader=0;
  800. if (audio_decoder)
  801. {
  802. audio_decoder->Close();
  803. audio_decoder=0;
  804. audio_output.Close();
  805. }
  806. return 1;
  807. }