分享

KODI(原XBMC)二次开发完全解析(三)

 昵称14340561 2020-08-07

  上篇讲到player的建立流程KODI(原XBMC)二次开发完全解析(二)-------创建player,接着上篇确定哪一个才是真正干活的player。

m_pPlayer->CreatePlayer(newPlayer, *this);//创建player,下篇重点讲   这个就开始创建player,这个m_pPlayer就是xbmc/ApplicationPlayer.h的实例,调用源码如下:

  1. void CApplicationPlayer::CreatePlayer(const std::string &player, IPlayerCallback& callback)
  2. {
  3. CSingleLock lock(m_player_lock);
  4. if (!m_pPlayer)
  5. {
  6. m_pPlayer.reset(CPlayerCoreFactory::GetInstance().CreatePlayer(player, callback));
  7. }
  8. }

player就是需要创建的player,继续查看CPlayerCoreFactory::GetInstance().CreatePlayer(player, callback)

  1. IPlayer* CPlayerCoreFactory::CreatePlayer(const std::string& nameId, IPlayerCallback& callback) const
  2. {
  3. CSingleLock lock(m_section);
  4. size_t idx = GetPlayerIndex(nameId);
  5. if (m_vecPlayerConfigs.empty() || idx > m_vecPlayerConfigs.size())
  6. return nullptr;
  7. return m_vecPlayerConfigs[idx]->CreatePlayer(callback);
  8. }

根据nameId调用PlayerCoreConfig.h创建Player

  1. IPlayer* CreatePlayer(IPlayerCallback& callback) const
  2. {
  3. IPlayer* pPlayer;
  4. if (m_type.compare("video") == 0)
  5. {
  6. pPlayer = new CVideoPlayer(callback);//创建VideoPlayer
  7. }
  8. else if (m_type.compare("music") == 0)
  9. {
  10. pPlayer = new PAPlayer(callback);
  11. }
  12. else if (m_type.compare("external") == 0)
  13. {
  14. pPlayer = new CExternalPlayer(callback);
  15. }
  16. #if defined(HAS_UPNP)
  17. else if (m_type.compare("remote") == 0)
  18. {
  19. pPlayer = new UPNP::CUPnPPlayer(callback, m_id.c_str());
  20. }
  21. #endif
  22. else
  23. return nullptr;
  24. pPlayer->m_name = m_name;
  25. pPlayer->m_type = m_type;
  26. if (pPlayer->Initialize(m_config))
  27. {
  28. return pPlayer;
  29. }
  30. else
  31. {
  32. SAFE_DELETE(pPlayer);
  33. return nullptr;
  34. }
  35. }

根据type类型,创建需要的player,至此,我们找到了VideoPlayer,这个才是这篇要说的重点,下面先查看VideoPlayer.h文件,位于xbmc/cores/VideoPlayer/VideoPlayer.h

  1. class CVideoPlayer : public IPlayer, public CThread, public IVideoPlayer, public IDispResource, public IRenderMsg
  2. {
  3. public:
  4. CVideoPlayer(IPlayerCallback& callback);
  5. virtual ~CVideoPlayer();
  6. virtual bool OpenFile(const CFileItem& file, const CPlayerOptions &options);
  7. virtual bool CloseFile(bool reopen = false);
  8. virtual bool IsPlaying() const;
  9. virtual void Pause() override;
  10. virtual bool HasVideo() const;
  11. virtual bool HasAudio() const;
  12. virtual bool HasRDS() const;
  13. virtual bool IsPassthrough() const;
  14. virtual bool CanSeek();
  15. virtual void Seek(bool bPlus, bool bLargeStep, bool bChapterOverride);
  16. virtual bool SeekScene(bool bPlus = true);
  17. virtual void SeekPercentage(float iPercent);
  18. virtual float GetPercentage();
  19. virtual float GetCachePercentage();
  20. virtual void SetVolume(float nVolume) override;
  21. virtual void SetMute(bool bOnOff) override;
  22. virtual void SetDynamicRangeCompression(long drc) override;
  23. virtual bool CanRecord();
  24. virtual bool IsRecording();
  25. virtual bool CanPause();
  26. virtual bool Record(bool bOnOff);
  27. virtual void SetAVDelay(float fValue = 0.0f);
  28. virtual float GetAVDelay();
  29. virtual bool IsInMenu() const override;
  30. virtual bool HasMenu() const override;
  31. virtual void SetSubTitleDelay(float fValue = 0.0f);
  32. virtual float GetSubTitleDelay();
  33. virtual int GetSubtitleCount();
  34. virtual int GetSubtitle();
  35. virtual void GetSubtitleStreamInfo(int index, SPlayerSubtitleStreamInfo &info);
  36. virtual void SetSubtitle(int iStream);
  37. virtual bool GetSubtitleVisible();
  38. virtual void SetSubtitleVisible(bool bVisible);
  39. virtual void AddSubtitle(const std::string& strSubPath);
  40. virtual int GetAudioStreamCount();
  41. virtual int GetAudioStream();
  42. virtual void SetAudioStream(int iStream);
  43. virtual int GetVideoStream() const override;
  44. virtual int GetVideoStreamCount() const override;
  45. virtual void GetVideoStreamInfo(int streamId, SPlayerVideoStreamInfo &info) override;
  46. virtual void SetVideoStream(int iStream);
  47. virtual TextCacheStruct_t* GetTeletextCache();
  48. virtual void LoadPage(int p, int sp, unsigned char* buffer);
  49. virtual std::string GetRadioText(unsigned int line);
  50. virtual int GetChapterCount();
  51. virtual int GetChapter();
  52. virtual void GetChapterName(std::string& strChapterName, int chapterIdx=-1);
  53. virtual int64_t GetChapterPos(int chapterIdx=-1);
  54. virtual int SeekChapter(int iChapter);
  55. virtual void SeekTime(int64_t iTime);
  56. virtual bool SeekTimeRelative(int64_t iTime);
  57. virtual int64_t GetTime();
  58. virtual int64_t GetTotalTime();
  59. virtual void SetSpeed(float speed) override;
  60. virtual float GetSpeed() override;
  61. virtual bool SupportsTempo() override;
  62. virtual bool OnAction(const CAction &action);
  63. virtual int GetSourceBitrate();
  64. virtual bool GetStreamDetails(CStreamDetails &details);
  65. virtual void GetAudioStreamInfo(int index, SPlayerAudioStreamInfo &info);
  66. virtual std::string GetPlayerState();
  67. virtual bool SetPlayerState(const std::string& state);
  68. virtual std::string GetPlayingTitle();
  69. virtual bool SwitchChannel(const PVR::CPVRChannelPtr &channel);
  70. virtual void FrameMove();
  71. virtual void Render(bool clear, uint32_t alpha = 255, bool gui = true);
  72. virtual void FlushRenderer();
  73. virtual void SetRenderViewMode(int mode);
  74. float GetRenderAspectRatio();
  75. virtual void TriggerUpdateResolution();
  76. virtual bool IsRenderingVideo();
  77. virtual bool IsRenderingGuiLayer();
  78. virtual bool IsRenderingVideoLayer();
  79. virtual bool Supports(EINTERLACEMETHOD method) override;
  80. virtual EINTERLACEMETHOD GetDeinterlacingMethodDefault() override;
  81. virtual bool Supports(ESCALINGMETHOD method) override;
  82. virtual bool Supports(ERENDERFEATURE feature) override;
  83. virtual unsigned int RenderCaptureAlloc();
  84. virtual void RenderCapture(unsigned int captureId, unsigned int width, unsigned int height, int flags);
  85. virtual void RenderCaptureRelease(unsigned int captureId);
  86. virtual bool RenderCaptureGetPixels(unsigned int captureId, unsigned int millis, uint8_t *buffer, unsigned int size);
  87. // IDispResource interface
  88. virtual void OnLostDisplay();
  89. virtual void OnResetDisplay();
  90. virtual bool IsCaching() const override;
  91. virtual int GetCacheLevel() const override;
  92. virtual int OnDVDNavResult(void* pData, int iMessage) override;
  93. void GetVideoResolution(unsigned int &width, unsigned int &height) override;
  94. protected:
  95. friend class CSelectionStreams;
  96. virtual void OnStartup();
  97. virtual void OnExit();
  98. virtual void Process();
  99. virtual void VideoParamsChange() override;
  100. virtual void GetDebugInfo(std::string &audio, std::string &video, std::string &general) override;
  101. virtual void UpdateClockSync(bool enabled) override;
  102. virtual void UpdateRenderInfo(CRenderInfo &info) override;
  103. virtual void UpdateRenderBuffers(int queued, int discard, int free) override;
  104. void CreatePlayers();
  105. void DestroyPlayers();
  106. bool OpenStream(CCurrentStream& current, int64_t demuxerId, int iStream, int source, bool reset = true);
  107. bool OpenAudioStream(CDVDStreamInfo& hint, bool reset = true);
  108. bool OpenVideoStream(CDVDStreamInfo& hint, bool reset = true);
  109. bool OpenSubtitleStream(CDVDStreamInfo& hint);
  110. bool OpenTeletextStream(CDVDStreamInfo& hint);
  111. bool OpenRadioRDSStream(CDVDStreamInfo& hint);
  112. /** \brief Switches forced subtitles to forced subtitles matching the language of the current audio track.
  113. * If these are not available, subtitles are disabled.
  114. */
  115. void AdaptForcedSubtitles();
  116. bool CloseStream(CCurrentStream& current, bool bWaitForBuffers);
  117. bool CheckIsCurrent(CCurrentStream& current, CDemuxStream* stream, DemuxPacket* pkg);
  118. void ProcessPacket(CDemuxStream* pStream, DemuxPacket* pPacket);
  119. void ProcessAudioData(CDemuxStream* pStream, DemuxPacket* pPacket);
  120. void ProcessVideoData(CDemuxStream* pStream, DemuxPacket* pPacket);
  121. void ProcessSubData(CDemuxStream* pStream, DemuxPacket* pPacket);
  122. void ProcessTeletextData(CDemuxStream* pStream, DemuxPacket* pPacket);
  123. void ProcessRadioRDSData(CDemuxStream* pStream, DemuxPacket* pPacket);
  124. bool ShowPVRChannelInfo();
  125. int AddSubtitleFile(const std::string& filename, const std::string& subfilename = "");
  126. void SetSubtitleVisibleInternal(bool bVisible);
  127. /**
  128. * one of the DVD_PLAYSPEED defines
  129. */
  130. void SetPlaySpeed(int iSpeed);
  131. int GetPlaySpeed() { return m_playSpeed; }
  132. enum ECacheState
  133. {
  134. CACHESTATE_DONE = 0,
  135. CACHESTATE_FULL, // player is filling up the demux queue
  136. CACHESTATE_INIT, // player is waiting for first packet of each stream
  137. CACHESTATE_PLAY, // player is waiting for players to not be stalled
  138. CACHESTATE_FLUSH, // temporary state player will choose startup between init or full
  139. };
  140. void SetCaching(ECacheState state);
  141. int64_t GetTotalTimeInMsec();
  142. double GetQueueTime();
  143. bool GetCachingTimes(double& play_left, double& cache_left, double& file_offset);
  144. void FlushBuffers(double pts, bool accurate, bool sync);
  145. void HandleMessages();
  146. void HandlePlaySpeed();
  147. bool IsInMenuInternal() const;
  148. void SynchronizeDemuxer();
  149. void CheckAutoSceneSkip();
  150. bool CheckContinuity(CCurrentStream& current, DemuxPacket* pPacket);
  151. bool CheckSceneSkip(CCurrentStream& current);
  152. bool CheckPlayerInit(CCurrentStream& current);
  153. void UpdateCorrection(DemuxPacket* pkt, double correction);
  154. void UpdateTimestamps(CCurrentStream& current, DemuxPacket* pPacket);
  155. IDVDStreamPlayer* GetStreamPlayer(unsigned int player);
  156. void SendPlayerMessage(CDVDMsg* pMsg, unsigned int target);
  157. bool ReadPacket(DemuxPacket*& packet, CDemuxStream*& stream);
  158. bool IsValidStream(CCurrentStream& stream);
  159. bool IsBetterStream(CCurrentStream& current, CDemuxStream* stream);
  160. void CheckBetterStream(CCurrentStream& current, CDemuxStream* stream);
  161. void CheckStreamChanges(CCurrentStream& current, CDemuxStream* stream);
  162. bool CheckDelayedChannelEntry(void);
  163. bool OpenInputStream();
  164. bool OpenDemuxStream();
  165. void CloseDemuxer();
  166. void OpenDefaultStreams(bool reset = true);
  167. void UpdateApplication(double timeout);
  168. void UpdatePlayState(double timeout);
  169. void UpdateStreamInfos();
  170. void GetGeneralInfo(std::string& strVideoInfo);
  171. double m_UpdateApplication;
  172. bool m_players_created;
  173. bool m_bAbortRequest;
  174. ECacheState m_caching;
  175. XbmcThreads::EndTime m_cachingTimer;
  176. CFileItem m_item;
  177. XbmcThreads::EndTime m_ChannelEntryTimeOut;
  178. std::unique_ptr<CProcessInfo> m_processInfo;
  179. CCurrentStream m_CurrentAudio;
  180. CCurrentStream m_CurrentVideo;
  181. CCurrentStream m_CurrentSubtitle;
  182. CCurrentStream m_CurrentTeletext;
  183. CCurrentStream m_CurrentRadioRDS;
  184. CSelectionStreams m_SelectionStreams;
  185. std::atomic_int m_playSpeed;
  186. std::atomic_int m_newPlaySpeed;
  187. int m_streamPlayerSpeed;
  188. struct SSpeedState
  189. {
  190. double lastpts; // holds last display pts during ff/rw operations
  191. int64_t lasttime;
  192. int lastseekpts;
  193. double lastabstime;
  194. } m_SpeedState;
  195. std::atomic_bool m_canTempo;
  196. int m_errorCount;
  197. double m_offset_pts;
  198. CDVDMessageQueue m_messenger; // thread messenger
  199. IDVDStreamPlayerVideo *m_VideoPlayerVideo; // video part
  200. IDVDStreamPlayerAudio *m_VideoPlayerAudio; // audio part
  201. CVideoPlayerSubtitle *m_VideoPlayerSubtitle; // subtitle part
  202. CDVDTeletextData *m_VideoPlayerTeletext; // teletext part
  203. CDVDRadioRDSData *m_VideoPlayerRadioRDS; // rds part
  204. CDVDClock m_clock; // master clock
  205. CDVDOverlayContainer m_overlayContainer;
  206. CDVDInputStream* m_pInputStream; // input stream for current playing file
  207. CDVDDemux* m_pDemuxer; // demuxer for current playing file
  208. CDVDDemux* m_pSubtitleDemuxer;
  209. CDVDDemuxCC* m_pCCDemuxer;
  210. CRenderManager m_renderManager;
  211. struct SDVDInfo
  212. {
  213. void Clear()
  214. {
  215. state = DVDSTATE_NORMAL;
  216. iSelectedSPUStream = -1;
  217. iSelectedAudioStream = -1;
  218. iSelectedVideoStream = -1;
  219. iDVDStillTime = 0;
  220. iDVDStillStartTime = 0;
  221. syncClock = false;
  222. }
  223. int state; // current dvdstate
  224. bool syncClock;
  225. unsigned int iDVDStillTime; // total time in ticks we should display the still before continuing
  226. unsigned int iDVDStillStartTime; // time in ticks when we started the still
  227. int iSelectedSPUStream; // mpeg stream id, or -1 if disabled
  228. int iSelectedAudioStream; // mpeg stream id, or -1 if disabled
  229. int iSelectedVideoStream; // mpeg stream id or angle, -1 if disabled
  230. } m_dvd;
  231. friend class CVideoPlayerVideo;
  232. friend class CVideoPlayerAudio;
  233. #ifdef HAS_OMXPLAYER
  234. friend class OMXPlayerVideo;
  235. friend class OMXPlayerAudio;
  236. #endif
  237. SPlayerState m_State;
  238. CCriticalSection m_StateSection;
  239. XbmcThreads::EndTime m_syncTimer;
  240. CEvent m_ready;
  241. CEdl m_Edl;
  242. bool m_SkipCommercials;
  243. CPlayerOptions m_PlayerOptions;
  244. bool m_HasVideo;
  245. bool m_HasAudio;
  246. std::atomic<bool> m_displayLost;
  247. // omxplayer variables
  248. struct SOmxPlayerState m_OmxPlayerState;
  249. bool m_omxplayer_mode; // using omxplayer acceleration
  250. XbmcThreads::EndTime m_player_status_timer;
  251. };

其中定义了很多诸如seek、pause函数,看完这个就确定我们找的VideoPlayer是没有错误的,而VideoPlayer extends Thread,这个子线程明显就是要解析视频的线程,查看当前thread的Process函数

  1. void CVideoPlayer::Process()
  2. {
  3. CFFmpegLog::SetLogLevel(1);
  4. if (!OpenInputStream())//创建输入流
  5. {
  6. m_bAbortRequest = true;
  7. return;
  8. }
  9. if (CDVDInputStream::IMenus* ptr = dynamic_cast<CDVDInputStream::IMenus*>(m_pInputStream))
  10. {
  11. CLog::Log(LOGNOTICE, "VideoPlayer: playing a file with menu's");
  12. if(dynamic_cast<CDVDInputStreamNavigator*>(m_pInputStream))
  13. m_PlayerOptions.starttime = 0;
  14. if(!m_PlayerOptions.state.empty())
  15. ptr->SetState(m_PlayerOptions.state);
  16. else if(CDVDInputStreamNavigator* nav = dynamic_cast<CDVDInputStreamNavigator*>(m_pInputStream))
  17. nav->EnableSubtitleStream(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_SubtitleOn);
  18. CMediaSettings::GetInstance().GetCurrentVideoSettings().m_SubtitleCached = true;
  19. }
  20. if(!OpenDemuxStream())//创建demux
  21. {
  22. m_bAbortRequest = true;
  23. return;
  24. }
  25. // give players a chance to reconsider now codecs are known
  26. CreatePlayers();
  27. // allow renderer to switch to fullscreen if requested
  28. m_VideoPlayerVideo->EnableFullscreen(m_PlayerOptions.fullscreen);
  29. if (m_omxplayer_mode)
  30. {
  31. if (!m_OmxPlayerState.av_clock.OMXInitialize(&m_clock))
  32. m_bAbortRequest = true;
  33. if (CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_ADJUSTREFRESHRATE) != ADJUST_REFRESHRATE_OFF)
  34. m_OmxPlayerState.av_clock.HDMIClockSync();
  35. m_OmxPlayerState.av_clock.OMXStateIdle();
  36. m_OmxPlayerState.av_clock.OMXStateExecute();
  37. m_OmxPlayerState.av_clock.OMXStop();
  38. m_OmxPlayerState.av_clock.OMXPause();
  39. }
  40. OpenDefaultStreams();
  41. // look for any EDL files
  42. m_Edl.Clear();
  43. if (m_CurrentVideo.id >= 0 && m_CurrentVideo.hint.fpsrate > 0 && m_CurrentVideo.hint.fpsscale > 0)
  44. {
  45. float fFramesPerSecond = (float)m_CurrentVideo.hint.fpsrate / (float)m_CurrentVideo.hint.fpsscale;
  46. m_Edl.ReadEditDecisionLists(m_item.GetPath(), fFramesPerSecond, m_CurrentVideo.hint.height);
  47. }
  48. /*
  49. * Check to see if the demuxer should start at something other than time 0. This will be the case
  50. * if there was a start time specified as part of the "Start from where last stopped" (aka
  51. * auto-resume) feature or if there is an EDL cut or commercial break that starts at time 0.
  52. */
  53. CEdl::Cut cut;
  54. int starttime = 0;
  55. if (m_PlayerOptions.starttime > 0 || m_PlayerOptions.startpercent > 0)
  56. {
  57. if (m_PlayerOptions.startpercent > 0 && m_pDemuxer)
  58. {
  59. int playerStartTime = (int)( ( (float) m_pDemuxer->GetStreamLength() ) * ( m_PlayerOptions.startpercent/(float)100 ) );
  60. starttime = m_Edl.RestoreCutTime(playerStartTime);
  61. }
  62. else
  63. {
  64. starttime = m_Edl.RestoreCutTime(m_PlayerOptions.starttime * 1000); // s to ms
  65. }
  66. CLog::Log(LOGDEBUG, "%s - Start position set to last stopped position: %d", __FUNCTION__, starttime);
  67. }
  68. else if (m_Edl.InCut(starttime, &cut))
  69. {
  70. if (cut.action == CEdl::CUT)
  71. {
  72. starttime = cut.end;
  73. CLog::Log(LOGDEBUG, "%s - Start position set to end of first cut: %d", __FUNCTION__, starttime);
  74. }
  75. else if (cut.action == CEdl::COMM_BREAK)
  76. {
  77. if (m_SkipCommercials)
  78. {
  79. starttime = cut.end;
  80. CLog::Log(LOGDEBUG, "%s - Start position set to end of first commercial break: %d", __FUNCTION__, starttime);
  81. }
  82. std::string strTimeString = StringUtils::SecondsToTimeString(cut.end / 1000, TIME_FORMAT_MM_SS);
  83. CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(25011), strTimeString);
  84. }
  85. }
  86. if (starttime > 0)//判断上次播放时长,选择从上次播放时开始播放
  87. {
  88. double startpts = DVD_NOPTS_VALUE;
  89. if (m_pDemuxer)
  90. {
  91. if (m_pDemuxer->SeekTime(starttime, false, &startpts))
  92. CLog::Log(LOGDEBUG, "%s - starting demuxer from: %d", __FUNCTION__, starttime);
  93. else
  94. CLog::Log(LOGDEBUG, "%s - failed to start demuxing from: %d", __FUNCTION__, starttime);
  95. }
  96. if (m_pSubtitleDemuxer)
  97. {
  98. if(m_pSubtitleDemuxer->SeekTime(starttime, false, &startpts))
  99. CLog::Log(LOGDEBUG, "%s - starting subtitle demuxer from: %d", __FUNCTION__, starttime);
  100. else
  101. CLog::Log(LOGDEBUG, "%s - failed to start subtitle demuxing from: %d", __FUNCTION__, starttime);
  102. }
  103. m_clock.Discontinuity(DVD_MSEC_TO_TIME(starttime));
  104. }
  105. // make sure application know our info
  106. UpdateApplication(0);
  107. UpdatePlayState(0);
  108. if(m_PlayerOptions.identify == false)
  109. m_callback.OnPlayBackStarted();
  110. // we are done initializing now, set the readyevent
  111. m_ready.Set();
  112. SetCaching(CACHESTATE_FLUSH);
  113. while (!m_bAbortRequest)//开启循环demux,将数据抛给下层decode
  114. {
  115. #ifdef HAS_OMXPLAYER
  116. if (m_omxplayer_mode && OMXDoProcessing(m_OmxPlayerState, m_playSpeed, m_VideoPlayerVideo, m_VideoPlayerAudio, m_CurrentAudio, m_CurrentVideo, m_HasVideo, m_HasAudio, m_renderManager))
  117. {
  118. CloseStream(m_CurrentVideo, false);
  119. OpenStream(m_CurrentVideo, m_CurrentVideo.demuxerId, m_CurrentVideo.id, m_CurrentVideo.source);
  120. if (m_State.canseek)
  121. {
  122. CDVDMsgPlayerSeek::CMode mode;
  123. mode.time = (int)GetTime();
  124. mode.backward = true;
  125. mode.accurate = true;
  126. mode.sync = true;
  127. m_messenger.Put(new CDVDMsgPlayerSeek(mode));
  128. }
  129. }
  130. #endif
  131. // check display lost
  132. if (m_displayLost)
  133. {
  134. Sleep(50);
  135. continue;
  136. }
  137. // check if in a cut or commercial break that should be automatically skipped
  138. CheckAutoSceneSkip();
  139. // handle messages send to this thread, like seek or demuxer reset requests
  140. HandleMessages();
  141. if(m_bAbortRequest)
  142. break;
  143. // should we open a new input stream?
  144. if(!m_pInputStream)
  145. {
  146. if (OpenInputStream() == false)
  147. {
  148. m_bAbortRequest = true;
  149. break;
  150. }
  151. }
  152. // should we open a new demuxer?
  153. if(!m_pDemuxer)
  154. {
  155. if (m_pInputStream->NextStream() == CDVDInputStream::NEXTSTREAM_NONE)
  156. break;
  157. if (m_pInputStream->IsEOF())
  158. break;
  159. if (OpenDemuxStream() == false)
  160. {
  161. m_bAbortRequest = true;
  162. break;
  163. }
  164. // on channel switch we don't want to close stream players at this
  165. // time. we'll get the stream change event later
  166. if (!m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER) ||
  167. !m_SelectionStreams.m_Streams.empty())
  168. OpenDefaultStreams();
  169. UpdateApplication(0);
  170. UpdatePlayState(0);
  171. }
  172. // handle eventual seeks due to playspeed
  173. HandlePlaySpeed();
  174. // update player state
  175. UpdatePlayState(200);
  176. // update application with our state
  177. UpdateApplication(1000);
  178. // make sure we run subtitle process here
  179. m_VideoPlayerSubtitle->Process(m_clock.GetClock() + m_State.time_offset - m_VideoPlayerVideo->GetSubtitleDelay(), m_State.time_offset);
  180. if (CheckDelayedChannelEntry())
  181. continue;
  182. // if the queues are full, no need to read more
  183. if ((!m_VideoPlayerAudio->AcceptsData() && m_CurrentAudio.id >= 0) ||
  184. (!m_VideoPlayerVideo->AcceptsData() && m_CurrentVideo.id >= 0))
  185. {
  186. Sleep(10);
  187. continue;
  188. }
  189. // always yield to players if they have data levels > 50 percent
  190. if((m_VideoPlayerAudio->GetLevel() > 50 || m_CurrentAudio.id < 0)
  191. && (m_VideoPlayerVideo->GetLevel() > 50 || m_CurrentVideo.id < 0))
  192. Sleep(0);
  193. DemuxPacket* pPacket = NULL;
  194. CDemuxStream *pStream = NULL;
  195. ReadPacket(pPacket, pStream);//开始将流封包,方便传给下一层decode
  196. if (pPacket && !pStream)
  197. {
  198. /* probably a empty packet, just free it and move on */
  199. CDVDDemuxUtils::FreeDemuxPacket(pPacket);
  200. continue;
  201. }
  202. if (!pPacket)
  203. {
  204. // when paused, demuxer could be be returning empty
  205. if (m_playSpeed == DVD_PLAYSPEED_PAUSE)
  206. continue;
  207. // check for a still frame state
  208. if (CDVDInputStream::IMenus* pStream = dynamic_cast<CDVDInputStream::IMenus*>(m_pInputStream))
  209. {
  210. // stills will be skipped
  211. if(m_dvd.state == DVDSTATE_STILL)
  212. {
  213. if (m_dvd.iDVDStillTime > 0)
  214. {
  215. if ((XbmcThreads::SystemClockMillis() - m_dvd.iDVDStillStartTime) >= m_dvd.iDVDStillTime)
  216. {
  217. m_dvd.iDVDStillTime = 0;
  218. m_dvd.iDVDStillStartTime = 0;
  219. m_dvd.state = DVDSTATE_NORMAL;
  220. pStream->SkipStill();
  221. continue;
  222. }
  223. }
  224. }
  225. }
  226. // if there is another stream available, reopen demuxer
  227. CDVDInputStream::ENextStream next = m_pInputStream->NextStream();
  228. if(next == CDVDInputStream::NEXTSTREAM_OPEN)
  229. {
  230. CloseDemuxer();
  231. SetCaching(CACHESTATE_DONE);
  232. CLog::Log(LOGNOTICE, "VideoPlayer: next stream, wait for old streams to be finished");
  233. CloseStream(m_CurrentAudio, true);
  234. CloseStream(m_CurrentVideo, true);
  235. m_CurrentAudio.Clear();
  236. m_CurrentVideo.Clear();
  237. m_CurrentSubtitle.Clear();
  238. continue;
  239. }
  240. // input stream asked us to just retry
  241. if(next == CDVDInputStream::NEXTSTREAM_RETRY)
  242. {
  243. Sleep(100);
  244. continue;
  245. }
  246. // make sure we tell all players to finish it's data
  247. if (m_omxplayer_mode && !m_OmxPlayerState.bOmxSentEOFs)
  248. {
  249. if(m_CurrentAudio.inited)
  250. m_OmxPlayerState.bOmxWaitAudio = true;
  251. if(m_CurrentVideo.inited)
  252. m_OmxPlayerState.bOmxWaitVideo = true;
  253. m_OmxPlayerState.bOmxSentEOFs = true;
  254. }
  255. if(m_CurrentAudio.inited)
  256. m_VideoPlayerAudio->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));
  257. if(m_CurrentVideo.inited)
  258. m_VideoPlayerVideo->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));
  259. if(m_CurrentSubtitle.inited)
  260. m_VideoPlayerSubtitle->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));
  261. if(m_CurrentTeletext.inited)
  262. m_VideoPlayerTeletext->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));
  263. if(m_CurrentRadioRDS.inited)
  264. m_VideoPlayerRadioRDS->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));
  265. m_CurrentAudio.inited = false;
  266. m_CurrentVideo.inited = false;
  267. m_CurrentSubtitle.inited = false;
  268. m_CurrentTeletext.inited = false;
  269. m_CurrentRadioRDS.inited = false;
  270. // if we are caching, start playing it again
  271. SetCaching(CACHESTATE_DONE);
  272. // while players are still playing, keep going to allow seekbacks
  273. if(m_VideoPlayerAudio->HasData()
  274. || m_VideoPlayerVideo->HasData())
  275. {
  276. Sleep(100);
  277. continue;
  278. }
  279. #ifdef HAS_OMXPLAYER
  280. if (m_omxplayer_mode && OMXStillPlaying(m_OmxPlayerState.bOmxWaitVideo, m_OmxPlayerState.bOmxWaitAudio, m_VideoPlayerVideo->IsEOS(), m_VideoPlayerAudio->IsEOS()))
  281. {
  282. Sleep(100);
  283. continue;
  284. }
  285. #endif
  286. if (!m_pInputStream->IsEOF())
  287. CLog::Log(LOGINFO, "%s - eof reading from demuxer", __FUNCTION__);
  288. break;
  289. }
  290. // it's a valid data packet, reset error counter
  291. m_errorCount = 0;
  292. // see if we can find something better to play
  293. CheckBetterStream(m_CurrentAudio, pStream);
  294. CheckBetterStream(m_CurrentVideo, pStream);
  295. CheckBetterStream(m_CurrentSubtitle, pStream);
  296. CheckBetterStream(m_CurrentTeletext, pStream);
  297. CheckBetterStream(m_CurrentRadioRDS, pStream);
  298. // demux video stream
  299. if (CSettings::GetInstance().GetBool(CSettings::SETTING_SUBTITLES_PARSECAPTIONS) && CheckIsCurrent(m_CurrentVideo, pStream, pPacket))
  300. {
  301. if (m_pCCDemuxer)
  302. {
  303. bool first = true;
  304. while(!m_bAbortRequest)
  305. {
  306. DemuxPacket *pkt = m_pCCDemuxer->Read(first ? pPacket : NULL);
  307. if (!pkt)
  308. break;
  309. first = false;
  310. if (m_pCCDemuxer->GetNrOfStreams() != m_SelectionStreams.CountSource(STREAM_SUBTITLE, STREAM_SOURCE_VIDEOMUX))
  311. {
  312. m_SelectionStreams.Clear(STREAM_SUBTITLE, STREAM_SOURCE_VIDEOMUX);
  313. m_SelectionStreams.Update(NULL, m_pCCDemuxer, "");
  314. OpenDefaultStreams(false);
  315. }
  316. CDemuxStream *pSubStream = m_pCCDemuxer->GetStream(pkt->iStreamId);
  317. if (pSubStream && m_CurrentSubtitle.id == pkt->iStreamId && m_CurrentSubtitle.source == STREAM_SOURCE_VIDEOMUX)
  318. ProcessSubData(pSubStream, pkt);
  319. else
  320. CDVDDemuxUtils::FreeDemuxPacket(pkt);
  321. }
  322. }
  323. }
  324. if (IsInMenuInternal())
  325. {
  326. if (CDVDInputStream::IMenus* menu = dynamic_cast<CDVDInputStream::IMenus*>(m_pInputStream))
  327. {
  328. double correction = menu->GetTimeStampCorrection();
  329. if (pPacket->dts != DVD_NOPTS_VALUE && pPacket->dts > correction)
  330. pPacket->dts -= correction;
  331. if (pPacket->pts != DVD_NOPTS_VALUE && pPacket->pts > correction)
  332. pPacket->pts -= correction;
  333. }
  334. if (m_dvd.syncClock)
  335. {
  336. m_clock.Discontinuity(pPacket->dts);
  337. m_dvd.syncClock = false;
  338. }
  339. }
  340. // process the packet
  341. ProcessPacket(pStream, pPacket);//将音频流、视频流、字幕流等分开,创建decode的Player并将数据传递给他们
  342. // update the player info for streams
  343. if (m_player_status_timer.IsTimePast())
  344. {
  345. m_player_status_timer.Set(500);
  346. UpdateStreamInfos();
  347. }
  348. }
  349. }

第一步是OpenInputStream,调用

  1. bool CVideoPlayer::OpenInputStream()
  2. {
  3. if(m_pInputStream)
  4. SAFE_DELETE(m_pInputStream);
  5. CLog::Log(LOGNOTICE, "Creating InputStream");
  6. // correct the filename if needed
  7. std::string filename(m_item.GetPath());
  8. if (URIUtils::IsProtocol(filename, "dvd") ||
  9. StringUtils::EqualsNoCase(filename, "iso9660://video_ts/video_ts.ifo"))
  10. {
  11. m_item.SetPath(g_mediaManager.TranslateDevicePath(""));
  12. }
  13. m_pInputStream = CDVDFactoryInputStream::CreateInputStream(this, m_item, true);//创建
  14. if(m_pInputStream == NULL)
  15. {
  16. CLog::Log(LOGERROR, "CVideoPlayer::OpenInputStream - unable to create input stream for [%s]", CURL::GetRedacted(m_item.GetPath()).c_str());
  17. return false;
  18. }
  19. if (!m_pInputStream->Open())
  20. {
  21. CLog::Log(LOGERROR, "CVideoPlayer::OpenInputStream - error opening [%s]", CURL::GetRedacted(m_item.GetPath()).c_str());
  22. return false;
  23. }
  24. // find any available external subtitles for non dvd files
  25. if (!m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)
  26. && !m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)
  27. && !m_pInputStream->IsStreamType(DVDSTREAM_TYPE_TV))
  28. {
  29. // find any available external subtitles
  30. std::vector<std::string> filenames;
  31. CUtil::ScanForExternalSubtitles(m_item.GetPath(), filenames);
  32. // load any subtitles from file item
  33. std::string key("subtitle:1");
  34. for(unsigned s = 1; m_item.HasProperty(key); key = StringUtils::Format("subtitle:%u", ++s))
  35. filenames.push_back(m_item.GetProperty(key).asString());
  36. for(unsigned int i=0;i<filenames.size();i++)
  37. {
  38. // if vobsub subtitle:
  39. if (URIUtils::HasExtension(filenames[i], ".idx"))
  40. {
  41. std::string strSubFile;
  42. if ( CUtil::FindVobSubPair( filenames, filenames[i], strSubFile ) )
  43. AddSubtitleFile(filenames[i], strSubFile);
  44. }
  45. else
  46. {
  47. if ( !CUtil::IsVobSub(filenames, filenames[i] ) )
  48. {
  49. AddSubtitleFile(filenames[i]);
  50. }
  51. }
  52. } // end loop over all subtitle files
  53. CMediaSettings::GetInstance().GetCurrentVideoSettings().m_SubtitleCached = true;
  54. }
  55. SetAVDelay(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_AudioDelay);
  56. SetSubTitleDelay(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_SubtitleDelay);
  57. m_clock.Reset();
  58. m_dvd.Clear();
  59. m_errorCount = 0;
  60. m_ChannelEntryTimeOut.SetInfinite();
  61. if (CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEDISPLAYASCLOCK) &&
  62. !m_pInputStream->IsRealtime())
  63. {
  64. m_canTempo = true;
  65. }
  66. else
  67. {
  68. m_canTempo = false;
  69. }
  70. return true;
  71. }

调用m_pInputStream = CDVDFactoryInputStream::CreateInputStream(this, m_item, true);创建,查看位于xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp

  1. CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IVideoPlayer* pPlayer, const CFileItem &fileitem, bool scanforextaudio)//根据文件类型创建不同的InputStream
  2. {
  3. std::string file = fileitem.GetPath();
  4. if (scanforextaudio)
  5. {
  6. // find any available external audio tracks
  7. std::vector<std::string> filenames;
  8. filenames.push_back(file);
  9. CUtil::ScanForExternalAudio(file, filenames);
  10. CUtil::ScanForExternalDemuxSub(file, filenames);
  11. if (filenames.size() >= 2)
  12. {
  13. return CreateInputStream(pPlayer, fileitem, filenames);
  14. }
  15. }
  16. ADDON::VECADDONS addons;
  17. ADDON::CBinaryAddonCache &addonCache = CServiceBroker::GetBinaryAddonCache();
  18. addonCache.GetAddons(addons, ADDON::ADDON_INPUTSTREAM);
  19. for (size_t i=0; i<addons.size(); ++i)
  20. {
  21. std::shared_ptr<ADDON::CInputStream> input(std::static_pointer_cast<ADDON::CInputStream>(addons[i]));
  22. if (input->Supports(fileitem))
  23. {
  24. std::shared_ptr<ADDON::CInputStream> addon = input;
  25. if (!input->UseParent())
  26. addon = std::shared_ptr<ADDON::CInputStream>(new ADDON::CInputStream(*input));
  27. ADDON_STATUS status = addon->Create();
  28. if (status == ADDON_STATUS_OK)
  29. {
  30. unsigned int videoWidth, videoHeight;
  31. pPlayer->GetVideoResolution(videoWidth, videoHeight);
  32. addon->SetVideoResolution(videoWidth, videoHeight);
  33. return new CInputStreamAddon(fileitem, addon);
  34. }
  35. }
  36. }
  37. if (fileitem.IsDiscImage())
  38. {
  39. #ifdef HAVE_LIBBLURAY
  40. CURL url("udf://");
  41. url.SetHostName(file);
  42. url.SetFileName("BDMV/index.bdmv");
  43. if(XFILE::CFile::Exists(url.Get()))
  44. return new CDVDInputStreamBluray(pPlayer, fileitem);
  45. #endif
  46. return new CDVDInputStreamNavigator(pPlayer, fileitem);
  47. }
  48. #ifdef HAS_DVD_DRIVE
  49. if(file.compare(g_mediaManager.TranslateDevicePath("")) == 0)
  50. {
  51. #ifdef HAVE_LIBBLURAY
  52. if(XFILE::CFile::Exists(URIUtils::AddFileToFolder(file, "BDMV", "index.bdmv")))
  53. return new CDVDInputStreamBluray(pPlayer, fileitem);
  54. #endif
  55. return new CDVDInputStreamNavigator(pPlayer, fileitem);
  56. }
  57. #endif
  58. if (fileitem.IsDVDFile(false, true))
  59. return (new CDVDInputStreamNavigator(pPlayer, fileitem));
  60. else if(file.substr(0, 6) == "pvr://")
  61. return new CDVDInputStreamPVRManager(pPlayer, fileitem);
  62. #ifdef HAVE_LIBBLURAY
  63. else if (fileitem.IsType(".bdmv") || fileitem.IsType(".mpls") || file.substr(0, 7) == "bluray:")
  64. return new CDVDInputStreamBluray(pPlayer, fileitem);
  65. #endif
  66. else if(file.substr(0, 6) == "rtp://"
  67. || file.substr(0, 7) == "rtsp://"
  68. || file.substr(0, 6) == "sdp://"
  69. || file.substr(0, 6) == "udp://"
  70. || file.substr(0, 6) == "tcp://"
  71. || file.substr(0, 6) == "mms://"
  72. || file.substr(0, 7) == "mmst://"
  73. || file.substr(0, 7) == "mmsh://")
  74. return new CDVDInputStreamFFmpeg(fileitem);
  75. #ifdef ENABLE_DVDINPUTSTREAM_STACK
  76. else if(file.substr(0, 8) == "stack://")
  77. return new CDVDInputStreamStack(fileitem);
  78. #endif
  79. else if(file.substr(0, 7) == "rtmp://"
  80. || file.substr(0, 8) == "rtmpt://"
  81. || file.substr(0, 8) == "rtmpe://"
  82. || file.substr(0, 9) == "rtmpte://"
  83. || file.substr(0, 8) == "rtmps://")
  84. return new CDVDInputStreamFFmpeg(fileitem);
  85. CFileItem finalFileitem(fileitem);
  86. if (finalFileitem.IsInternetStream())
  87. {
  88. if (finalFileitem.ContentLookup())
  89. {
  90. CURL origUrl(finalFileitem.GetURL());
  91. XFILE::CCurlFile curlFile;
  92. // try opening the url to resolve all redirects if any
  93. try
  94. {
  95. if (curlFile.Open(finalFileitem.GetURL()))
  96. {
  97. CURL finalUrl(curlFile.GetURL());
  98. finalUrl.SetProtocolOptions(origUrl.GetProtocolOptions());
  99. finalUrl.SetUserName(origUrl.GetUserName());
  100. finalUrl.SetPassword(origUrl.GetPassWord());
  101. finalFileitem.SetPath(finalUrl.Get());
  102. }
  103. curlFile.Close();
  104. }
  105. catch (XFILE::CRedirectException *pRedirectEx)
  106. {
  107. if (pRedirectEx)
  108. {
  109. delete pRedirectEx->m_pNewFileImp;
  110. delete pRedirectEx;
  111. }
  112. }
  113. }
  114. if (finalFileitem.IsType(".m3u8"))
  115. return new CDVDInputStreamFFmpeg(finalFileitem);
  116. if (finalFileitem.GetMimeType() == "application/vnd.apple.mpegurl")
  117. return new CDVDInputStreamFFmpeg(finalFileitem);
  118. if (URIUtils::IsProtocol(finalFileitem.GetPath(), "udp"))
  119. return new CDVDInputStreamFFmpeg(finalFileitem);
  120. }
  121. // our file interface handles all these types of streams
  122. return (new CDVDInputStreamFile(finalFileitem));
  123. }

其中很容易理解,kodi是一个全能的播放器,会支持许许多多的InputStream,根据类型判断初始化什么播放器,而DVDInputStreamFFmpeg能获取很多种类型的inputStream,下篇我们主要讲高大上的DVDInputStreamDDmpeg。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多