1 #pragma once
2 
3 #include <assert.h>
4 
5 #include <algorithm>
6 #include <chrono>
7 #include <iostream>
8 #include <map>
9 #include <thread>
10 using namespace std;
11 
12 #include <scx/Conv.h>
13 #include <scx/FileHelper.h>
14 #include <scx/Mailbox.h>
15 using namespace scx;
16 
17 #include <core/Plugin.h>
18 #include <plugin/IDecoder.h>
19 #include <plugin/IRenderer.h>
20 
21 namespace mous {
22 struct UnitBuffer
23 {
24     uint32_t used;
25     uint32_t unitCount;
26     char data[];
27 };
28 
29 struct DecoderPluginNode
30 {
31     const Plugin* agent;
32     IDecoder* decoder;
33 };
34 
35 enum : std::size_t
36 {
37     // mail contents
38     TYPE = 0,
39     DATA = 1,
40     FROM = 2,
41 
42     // worker status
43     IDLE = 1u << 0,
44     RUNNING = 1u << 1,
45 
46     // mail type
47     PROCEED = 1u << 2,
48     SUSPEND = 1u << 3,
49     DECODE = 1u << 4,
50     RENDER = 1u << 5,
51     QUIT = 1u << 6
52 };
53 
54 class Player::Impl
55 {
56   using Mailbox = scx::Mailbox<int, UnitBuffer*>;
57   using Mail = Mailbox::Mail;
58 
59   public:
Impl()60     Impl()
61     {
62         m_DecoderThread = std::thread([this]() {
63             int status = IDLE;
64             int quit = false;
65 
66             while (!quit) {
67                 auto mail = m_DecoderMailbox.Take();
68 
69                 const int opcode = status | std::get<TYPE>(mail);
70 
71                 switch (opcode) {
72                     case IDLE | QUIT:
73                     case RUNNING | QUIT: {
74                         quit = true;
75                     } break;
76 
77                     case IDLE | PROCEED: {
78                         status = RUNNING;
79                     } break;
80 
81                     case IDLE | DECODE: {
82                         std::get<TYPE>(mail) = 0;
83                         m_BufferMailbox.PushBack(std::move(mail));
84                     } break;
85 
86                     case IDLE | SUSPEND:
87                     case RUNNING | SUSPEND: {
88                         status = IDLE;
89                     } break;
90 
91                     case RUNNING | DECODE: {
92                         auto& buf = std::get<DATA>(mail);
93 
94                         if (m_DecoderIndex < m_UnitEnd) {
95                             m_Decoder->DecodeUnit(buf->data, buf->used, buf->unitCount);
96                             m_DecoderIndex += buf->unitCount;
97 
98                             std::get<TYPE>(mail) = RENDER;
99                             m_RendererMailbox.PushBack(std::move(mail));
100 
101                             if (m_DecoderIndex >= m_UnitEnd) {
102                                 status = IDLE;
103                             }
104                         } else {
105                             std::get<TYPE>(mail) = 0;
106                             m_BufferMailbox.PushBack(std::move(mail));
107                         }
108                     } break;
109 
110                     default: {
111                         // unexpected
112                     } break;
113                 }
114             }
115         });
116 
117         m_RendererThread = std::thread([this]() {
118             int status = IDLE;
119             int quit = false;
120 
121             while (!quit) {
122                 auto mail = m_RendererMailbox.Take();
123 
124                 const int opcode = status | std::get<TYPE>(mail);
125 
126                 switch (opcode) {
127                     case IDLE | QUIT:
128                     case RUNNING | QUIT: {
129                         quit = true;
130                     } break;
131 
132                     case IDLE | PROCEED: {
133                         status = RUNNING;
134                     } break;
135 
136                     case IDLE | RENDER: {
137                         std::get<TYPE>(mail) = 0;
138                         m_BufferMailbox.PushBack(std::move(mail));
139                     } break;
140 
141                     case IDLE | SUSPEND:
142                     case RUNNING | SUSPEND: {
143                         status = IDLE;
144                     } break;
145 
146                     case RUNNING | RENDER: {
147                         auto& buf = std::get<DATA>(mail);
148 
149                         if (m_RendererIndex < m_UnitEnd) {
150                             if (m_Renderer->Write(buf->data, buf->used) != ErrorCode::Ok) {
151                                 // avoid busy write
152                                 const int64_t delay = buf->unitCount / m_UnitPerMs * 1e6;
153                                 std::this_thread::sleep_for(std::chrono::nanoseconds(delay));
154                             }
155                             m_RendererIndex += buf->unitCount;
156 
157                             std::get<TYPE>(mail) = DECODE;
158                             m_DecoderMailbox.PushBack(std::move(mail));
159 
160                             if (m_RendererIndex >= m_UnitEnd) {
161                                 status = IDLE;
162                                 std::thread([this]() { m_SigFinished(); }).detach();
163                             }
164                         } else {
165                             std::get<TYPE>(mail) = 0;
166                             m_BufferMailbox.PushBack(std::move(mail));
167                         }
168                     } break;
169 
170                     default: {
171                         // unexpected
172                     } break;
173                 }
174             }
175         });
176     }
177 
~Impl()178     ~Impl()
179     {
180         Close();
181 
182         m_DecoderMailbox.EmplaceFront(QUIT, nullptr, std::weak_ptr<Mailbox>());
183         m_RendererMailbox.EmplaceFront(QUIT, nullptr, std::weak_ptr<Mailbox>());
184 
185         if (m_DecoderThread.joinable()) {
186             m_DecoderThread.join();
187         }
188         if (m_RendererThread.joinable()) {
189             m_RendererThread.join();
190         }
191 
192         m_BufferMailbox.Clear();
193 
194         UnregisterAll();
195     }
196 
Status()197     PlayerStatus Status() const { return m_Status; }
198 
RegisterDecoderPlugin(const Plugin * pAgent)199     void RegisterDecoderPlugin(const Plugin* pAgent)
200     {
201         if (pAgent->Type() == PluginType::Decoder) {
202             AddDecoderPlugin(pAgent);
203         }
204     }
205 
RegisterDecoderPlugin(vector<const Plugin * > & agents)206     void RegisterDecoderPlugin(vector<const Plugin*>& agents)
207     {
208         for (const auto agent : agents) {
209             RegisterDecoderPlugin(agent);
210         }
211     }
212 
RegisterRendererPlugin(const Plugin * pAgent)213     void RegisterRendererPlugin(const Plugin* pAgent)
214     {
215         if (pAgent->Type() == PluginType::Renderer) {
216             SetRendererPlugin(pAgent);
217         }
218     }
219 
UnregisterPlugin(const Plugin * pAgent)220     void UnregisterPlugin(const Plugin* pAgent)
221     {
222         switch (pAgent->Type()) {
223             case PluginType::Decoder:
224                 RemoveDecoderPlugin(pAgent);
225                 break;
226 
227             case PluginType::Renderer:
228                 UnsetRendererPlugin(pAgent);
229                 break;
230 
231             default:
232                 break;
233         }
234     }
235 
UnregisterPlugin(vector<const Plugin * > & agents)236     void UnregisterPlugin(vector<const Plugin*>& agents)
237     {
238         for (const auto agent : agents) {
239             UnregisterPlugin(agent);
240         }
241     }
242 
UnregisterAll()243     void UnregisterAll()
244     {
245         while (!m_DecoderPluginMap.empty()) {
246             auto iter = m_DecoderPluginMap.begin();
247             RemoveDecoderPlugin(iter->second.agent);
248         }
249 
250         UnsetRendererPlugin(m_RendererPlugin);
251     }
252 
SupportedSuffixes()253     vector<string> SupportedSuffixes() const
254     {
255         vector<string> list;
256         list.reserve(m_DecoderPluginMap.size());
257         for (const auto& entry : m_DecoderPluginMap) {
258             list.push_back(entry.first);
259         }
260         return list;
261     }
262 
BufferCount()263     int BufferCount() const
264     {
265         return m_BufferCount;
266     }
267 
SetBufferCount(int count)268     void SetBufferCount(int count)
269     {
270         m_BufferCount = count;
271     }
272 
Volume()273     int Volume() const { return m_Renderer != nullptr ? m_Renderer->VolumeLevel() : -1; }
274 
SetVolume(int level)275     void SetVolume(int level)
276     {
277         if (m_Renderer != nullptr) {
278             m_Renderer->SetVolumeLevel(level);
279         }
280     }
281 
Open(const string & path)282     ErrorCode Open(const string& path)
283     {
284         string suffix = ToLower(FileHelper::FileSuffix(path));
285         // cout << "Suffix:" << suffix << endl;
286         auto iter = m_DecoderPluginMap.find(suffix);
287         if (iter != m_DecoderPluginMap.end()) {
288             m_Decoder = iter->second.decoder;
289         } else {
290             return ErrorCode::PlayerNoDecoder;
291         }
292 
293         if (m_Renderer == nullptr) {
294             return ErrorCode::PlayerNoRenderer;
295         }
296 
297         ErrorCode err = m_Decoder->Open(path);
298         if (err != ErrorCode::Ok) {
299             // cout << "FATAL: failed to open!" << endl;
300             return err;
301         } else {
302             m_DecodeFile = path;
303         }
304 
305         const uint32_t maxBytesPerUnit = m_Decoder->MaxBytesPerUnit();
306         // cout << "unit buf size:" << maxBytesPerUnit << endl;
307 
308         m_BufferMailbox.Clear();
309         m_Buffer = std::make_unique<char[]>(m_BufferCount * (sizeof(UnitBuffer) + maxBytesPerUnit));
310         for (size_t i = 0; i < m_BufferCount; ++i) {
311             auto ptr = m_Buffer.get() + (sizeof(UnitBuffer) + maxBytesPerUnit) * i;
312             UnitBuffer* unitBuffer = reinterpret_cast<UnitBuffer*>(ptr);
313             m_BufferMailbox.EmplaceBack(0, unitBuffer, std::weak_ptr<Mailbox>());
314         }
315 
316         m_UnitPerMs = (double)m_Decoder->UnitCount() / m_Decoder->Duration();
317 
318         int32_t channels = m_Decoder->Channels();
319         int32_t samleRate = m_Decoder->SampleRate();
320         int32_t bitsPerSamle = m_Decoder->BitsPerSample();
321         // cout << "channels:" << channels << endl;
322         // cout << "samleRate:" << samleRate << endl;
323         // cout << "bitsPerSamle:" << bitsPerSamle << endl;
324         err = m_Renderer->Setup(channels, samleRate, bitsPerSamle);
325         if (err != ErrorCode::Ok) {
326             cout << "FATAL: failed to set renderer:" << static_cast<uint8_t>(err) << endl;
327             cout << "       channels:" << channels << endl;
328             cout << "       samleRate:" << samleRate << endl;
329             cout << "       bitsPerSamle:" << bitsPerSamle << endl;
330             return err;
331         }
332 
333         m_Status = PlayerStatus::Stopped;
334 
335         return err;
336     }
337 
Close()338     void Close()
339     {
340         if (m_Status == PlayerStatus::Closed) {
341             return;
342         }
343 
344         Pause();
345 
346         m_Decoder->Close();
347         m_Decoder = nullptr;
348         m_DecodeFile.clear();
349 
350         m_Status = PlayerStatus::Closed;
351     }
352 
FileName()353     string FileName() const { return m_DecodeFile; }
354 
Play()355     void Play()
356     {
357         uint64_t beg = 0;
358         uint64_t end = m_Decoder->UnitCount();
359         PlayRange(beg, end);
360     }
361 
Play(uint64_t msBegin,uint64_t msEnd)362     void Play(uint64_t msBegin, uint64_t msEnd)
363     {
364         const uint64_t total = m_Decoder->UnitCount();
365 
366         uint64_t beg = 0;
367         uint64_t end = 0;
368 
369         beg = m_UnitPerMs * msBegin;
370         if (beg > total) {
371             beg = total;
372         }
373 
374         if (msEnd != (uint64_t)-1) {
375             end = m_UnitPerMs * msEnd;
376             if (end > total) {
377                 end = total;
378             }
379         } else {
380             end = total;
381         }
382 
383         // cout << "begin:" << beg << endl;
384         // cout << "end:" << end << endl;
385         // cout << "total:" << total << endl;
386 
387         PlayRange(beg, end);
388     }
389 
PlayRange(uint64_t beg,uint64_t end)390     void PlayRange(uint64_t beg, uint64_t end)
391     {
392         m_UnitBeg = beg;
393         m_UnitEnd = end;
394 
395         m_RendererIndex = m_UnitBeg;
396         m_RendererMailbox.EmplaceBack(PROCEED, nullptr, std::weak_ptr<Mailbox>());
397 
398         m_DecoderIndex = m_UnitBeg;
399         m_Decoder->SetUnitIndex(m_UnitBeg);
400         m_DecoderMailbox.EmplaceBack(PROCEED, nullptr, std::weak_ptr<Mailbox>());
401         while (!m_BufferMailbox.Empty()) {
402             auto mail = m_BufferMailbox.Take();
403             std::get<TYPE>(mail) = DECODE;
404             m_DecoderMailbox.PushBack(std::move(mail));
405         }
406 
407         m_Status = PlayerStatus::Playing;
408     }
409 
Pause()410     void Pause()
411     {
412         if (m_Status == PlayerStatus::Paused) {
413             return;
414         }
415 
416         m_DecoderMailbox.EmplaceFront(SUSPEND, nullptr, std::weak_ptr<Mailbox>());
417         m_RendererMailbox.EmplaceFront(SUSPEND, nullptr, std::weak_ptr<Mailbox>());
418         m_BufferMailbox.Wait(m_BufferCount);
419 
420         m_Status = PlayerStatus::Paused;
421     }
422 
Resume()423     void Resume()
424     {
425         m_RendererMailbox.EmplaceBack(PROCEED, nullptr, std::weak_ptr<Mailbox>());
426 
427         m_DecoderIndex = m_RendererIndex;
428         m_Decoder->SetUnitIndex(m_DecoderIndex);
429         m_DecoderMailbox.EmplaceBack(PROCEED, nullptr, std::weak_ptr<Mailbox>());
430         while (!m_BufferMailbox.Empty()) {
431             auto mail = m_BufferMailbox.Take();
432             std::get<TYPE>(mail) = DECODE;
433             m_DecoderMailbox.PushBack(std::move(mail));
434         }
435 
436         m_Status = PlayerStatus::Playing;
437     }
438 
SeekTime(uint64_t msPos)439     void SeekTime(uint64_t msPos)
440     {
441         switch (m_Status) {
442             case PlayerStatus::Playing:
443                 Pause();
444                 DoSeekTime(msPos);
445                 Resume();
446                 break;
447 
448             case PlayerStatus::Paused:
449             case PlayerStatus::Stopped:
450                 DoSeekTime(msPos);
451                 break;
452 
453             default:
454                 break;
455         }
456     }
457 
SeekPercent(double percent)458     void SeekPercent(double percent)
459     {
460         uint64_t unit = m_UnitBeg + (m_UnitEnd - m_UnitBeg) * percent;
461 
462         switch (m_Status) {
463             case PlayerStatus::Playing:
464                 Pause();
465                 DoSeekUnit(unit);
466                 Resume();
467                 break;
468 
469             case PlayerStatus::Paused:
470             case PlayerStatus::Stopped:
471                 DoSeekUnit(unit);
472                 break;
473 
474             default:
475                 break;
476         }
477     }
478 
DoSeekTime(uint64_t msPos)479     void DoSeekTime(uint64_t msPos)
480     {
481         uint64_t unitPos = std::min((uint64_t)(m_UnitPerMs * msPos), m_Decoder->UnitCount());
482         DoSeekUnit(unitPos);
483     }
484 
DoSeekUnit(uint64_t unit)485     void DoSeekUnit(uint64_t unit)
486     {
487         if (unit < m_UnitBeg) {
488             unit = m_UnitBeg;
489         } else if (unit > m_UnitEnd) {
490             unit = m_UnitEnd;
491         }
492 
493         m_Decoder->SetUnitIndex(unit);
494 
495         m_DecoderIndex = unit;
496         m_RendererIndex = unit;
497     }
498 
PauseDecoder()499     void PauseDecoder()
500     {
501         /*
502         if (!m_PauseDecoder) {
503             m_PauseDecoder = true;
504         }
505         m_SemDecoderEnd.Wait();
506 
507         m_Decoder->Close();
508         */
509     }
510 
ResumeDecoder()511     void ResumeDecoder()
512     {
513         /*
514         // cout << "data:" << m_UnitBuffers.DataCount() << endl;
515         // cout << "free:" << m_UnitBuffers.FreeCount() << endl;
516 
517         m_Decoder->Open(m_DecodeFile);
518         m_Decoder->SetUnitIndex(m_DecoderIndex);
519 
520         m_PauseDecoder = false;
521         m_SemWakeDecoder.Post();
522         m_SemDecoderBegin.Wait();
523         */
524     }
525 
BitRate()526     int32_t BitRate() const { return (m_Decoder != nullptr) ? m_Decoder->BitRate() : -1; }
527 
SamleRate()528     int32_t SamleRate() const { return (m_Decoder != nullptr) ? m_Decoder->SampleRate() : -1; }
529 
Duration()530     uint64_t Duration() const { return m_Decoder->Duration(); }
531 
RangeBegin()532     uint64_t RangeBegin() const { return m_UnitBeg / m_UnitPerMs; }
533 
RangeEnd()534     uint64_t RangeEnd() const { return m_UnitEnd / m_UnitPerMs; }
535 
RangeDuration()536     uint64_t RangeDuration() const { return (m_UnitEnd - m_UnitBeg) / m_UnitPerMs; }
537 
OffsetMs()538     uint64_t OffsetMs() const { return CurrentMs() - RangeBegin(); }
539 
CurrentMs()540     uint64_t CurrentMs() const { return m_RendererIndex / m_UnitPerMs; }
541 
AudioMode()542     enum AudioMode AudioMode() const { return (m_Decoder != nullptr) ? m_Decoder->AudioMode() : AudioMode::None; }
543 
DecoderPluginOption()544     std::vector<PluginOption> DecoderPluginOption() const
545     {
546         std::vector<PluginOption> list;
547 
548         list.reserve(m_DecoderPluginMap.size());
549 
550         for (const auto entry : m_DecoderPluginMap) {
551             auto node = entry.second;
552             list.emplace_back(node.agent->Type(), node.agent->Info(), node.decoder->Options());
553         }
554 
555         return list;
556     }
557 
RendererPluginOption()558     PluginOption RendererPluginOption() const
559     {
560         if (m_RendererPlugin != nullptr && m_Renderer != nullptr) {
561             return { m_RendererPlugin->Type(), m_RendererPlugin->Info(), m_Renderer->Options() };
562         } else {
563             return {};
564         }
565     }
566 
SigFinished()567     Signal<void(void)>* SigFinished() { return &m_SigFinished; }
568 
569   private:
AddDecoderPlugin(const Plugin * pAgent)570     void AddDecoderPlugin(const Plugin* pAgent)
571     {
572         // create Decoder & get suffix
573         IDecoder* pDecoder = (IDecoder*)pAgent->CreateObject();
574         const vector<string>& list = pDecoder->FileSuffix();
575 
576         // try add
577         bool usedAtLeastOnce = false;
578         for (const string& item : list) {
579             const string& suffix = ToLower(item);
580             auto iter = m_DecoderPluginMap.find(suffix);
581             if (iter == m_DecoderPluginMap.end()) {
582                 m_DecoderPluginMap.emplace(suffix, DecoderPluginNode{ pAgent, pDecoder });
583                 usedAtLeastOnce = true;
584             }
585         }
586 
587         // clear if not used
588         if (!usedAtLeastOnce) {
589             pAgent->FreeObject(pDecoder);
590         }
591     }
592 
RemoveDecoderPlugin(const Plugin * pAgent)593     void RemoveDecoderPlugin(const Plugin* pAgent)
594     {
595         // get suffix
596         IDecoder* pDecoder = (IDecoder*)pAgent->CreateObject();
597         const vector<string>& list = pDecoder->FileSuffix();
598         pAgent->FreeObject(pDecoder);
599 
600         // find plugin
601         bool freedOnce = false;
602         for (const string& item : list) {
603             const string& suffix = ToLower(item);
604             auto iter = m_DecoderPluginMap.find(suffix);
605             if (iter != m_DecoderPluginMap.end()) {
606                 const DecoderPluginNode& node = iter->second;
607                 if (node.agent == pAgent) {
608                     if (!freedOnce) {
609                         if (node.decoder == m_Decoder) {
610                             Close();
611                         }
612                         pAgent->FreeObject(node.decoder);
613                         freedOnce = true;
614                     }
615                     m_DecoderPluginMap.erase(iter);
616                 }
617             }
618         }
619     }
620 
SetRendererPlugin(const Plugin * pAgent)621     void SetRendererPlugin(const Plugin* pAgent)
622     {
623         if (pAgent == nullptr || m_RendererPlugin != nullptr) {
624             return;
625         }
626 
627         m_RendererPlugin = pAgent;
628         m_Renderer = (IRenderer*)pAgent->CreateObject();
629         m_Renderer->Open();
630     }
631 
UnsetRendererPlugin(const Plugin * pAgent)632     void UnsetRendererPlugin(const Plugin* pAgent)
633     {
634         if (pAgent != m_RendererPlugin || m_RendererPlugin == nullptr) {
635             return;
636         }
637 
638         m_Renderer->Close();
639         m_RendererPlugin->FreeObject(m_Renderer);
640         m_Renderer = nullptr;
641         m_RendererPlugin = nullptr;
642     }
643 
644   private:
645     PlayerStatus m_Status = PlayerStatus::Closed;
646 
647     std::string m_DecodeFile;
648 
649     IDecoder* m_Decoder = nullptr;
650     IRenderer* m_Renderer = nullptr;
651     std::thread m_DecoderThread;
652     std::thread m_RendererThread;
653     Mailbox m_DecoderMailbox;
654     Mailbox m_RendererMailbox;
655 
656     Mailbox m_BufferMailbox;
657     int m_BufferCount = 5;
658     std::unique_ptr<char[]> m_Buffer;
659 
660     uint64_t m_UnitBeg = 0;
661     uint64_t m_UnitEnd = 0;
662 
663     uint64_t m_DecoderIndex = 0;
664     uint64_t m_RendererIndex = 0;
665 
666     double m_UnitPerMs = 0;
667 
668     const Plugin* m_RendererPlugin = nullptr;
669     std::map<std::string, DecoderPluginNode> m_DecoderPluginMap;
670 
671     scx::Signal<void(void)> m_SigFinished;
672 };
673 }
674