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

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

void CApplicationPlayer::CreatePlayer(const std::string &player, IPlayerCallback& callback)
{CSingleLock lock(m_player_lock);if (!m_pPlayer){m_pPlayer.reset(CPlayerCoreFactory::GetInstance().CreatePlayer(player, callback));}
}

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

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

根据nameId调用PlayerCoreConfig.h创建Player

IPlayer* CreatePlayer(IPlayerCallback& callback) const{IPlayer* pPlayer;if (m_type.compare("video") == 0){pPlayer = new CVideoPlayer(callback);//创建VideoPlayer}else if (m_type.compare("music") == 0){pPlayer = new PAPlayer(callback);}else if (m_type.compare("external") == 0){pPlayer = new CExternalPlayer(callback);}#if defined(HAS_UPNP)else if (m_type.compare("remote") == 0){pPlayer = new UPNP::CUPnPPlayer(callback, m_id.c_str());}
#endifelsereturn nullptr;pPlayer->m_name = m_name;pPlayer->m_type = m_type;if (pPlayer->Initialize(m_config)){return pPlayer;}else{SAFE_DELETE(pPlayer);return nullptr;}}

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

class CVideoPlayer : public IPlayer, public CThread, public IVideoPlayer, public IDispResource, public IRenderMsg
{
public:CVideoPlayer(IPlayerCallback& callback);virtual ~CVideoPlayer();virtual bool OpenFile(const CFileItem& file, const CPlayerOptions &options);virtual bool CloseFile(bool reopen = false);virtual bool IsPlaying() const;virtual void Pause() override;virtual bool HasVideo() const;virtual bool HasAudio() const;virtual bool HasRDS() const;virtual bool IsPassthrough() const;virtual bool CanSeek();virtual void Seek(bool bPlus, bool bLargeStep, bool bChapterOverride);virtual bool SeekScene(bool bPlus = true);virtual void SeekPercentage(float iPercent);virtual float GetPercentage();virtual float GetCachePercentage();virtual void SetVolume(float nVolume) override;virtual void SetMute(bool bOnOff) override;virtual void SetDynamicRangeCompression(long drc) override;virtual bool CanRecord();virtual bool IsRecording();virtual bool CanPause();virtual bool Record(bool bOnOff);virtual void SetAVDelay(float fValue = 0.0f);virtual float GetAVDelay();virtual bool IsInMenu() const override;virtual bool HasMenu() const override;virtual void SetSubTitleDelay(float fValue = 0.0f);virtual float GetSubTitleDelay();virtual int GetSubtitleCount();virtual int GetSubtitle();virtual void GetSubtitleStreamInfo(int index, SPlayerSubtitleStreamInfo &info);virtual void SetSubtitle(int iStream);virtual bool GetSubtitleVisible();virtual void SetSubtitleVisible(bool bVisible);virtual void AddSubtitle(const std::string& strSubPath);virtual int GetAudioStreamCount();virtual int GetAudioStream();virtual void SetAudioStream(int iStream);virtual int GetVideoStream() const override;virtual int GetVideoStreamCount() const override;virtual void GetVideoStreamInfo(int streamId, SPlayerVideoStreamInfo &info) override;virtual void SetVideoStream(int iStream);virtual TextCacheStruct_t* GetTeletextCache();virtual void LoadPage(int p, int sp, unsigned char* buffer);virtual std::string GetRadioText(unsigned int line);virtual int  GetChapterCount();virtual int  GetChapter();virtual void GetChapterName(std::string& strChapterName, int chapterIdx=-1);virtual int64_t GetChapterPos(int chapterIdx=-1);virtual int  SeekChapter(int iChapter);virtual void SeekTime(int64_t iTime);virtual bool SeekTimeRelative(int64_t iTime);virtual int64_t GetTime();virtual int64_t GetTotalTime();virtual void SetSpeed(float speed) override;virtual float GetSpeed() override;virtual bool SupportsTempo() override;virtual bool OnAction(const CAction &action);virtual int GetSourceBitrate();virtual bool GetStreamDetails(CStreamDetails &details);virtual void GetAudioStreamInfo(int index, SPlayerAudioStreamInfo &info);virtual std::string GetPlayerState();virtual bool SetPlayerState(const std::string& state);virtual std::string GetPlayingTitle();virtual bool SwitchChannel(const PVR::CPVRChannelPtr &channel);virtual void FrameMove();virtual void Render(bool clear, uint32_t alpha = 255, bool gui = true);virtual void FlushRenderer();virtual void SetRenderViewMode(int mode);float GetRenderAspectRatio();virtual void TriggerUpdateResolution();virtual bool IsRenderingVideo();virtual bool IsRenderingGuiLayer();virtual bool IsRenderingVideoLayer();virtual bool Supports(EINTERLACEMETHOD method) override;virtual EINTERLACEMETHOD GetDeinterlacingMethodDefault() override;virtual bool Supports(ESCALINGMETHOD method) override;virtual bool Supports(ERENDERFEATURE feature) override;virtual unsigned int RenderCaptureAlloc();virtual void RenderCapture(unsigned int captureId, unsigned int width, unsigned int height, int flags);virtual void RenderCaptureRelease(unsigned int captureId);virtual bool RenderCaptureGetPixels(unsigned int captureId, unsigned int millis, uint8_t *buffer, unsigned int size);// IDispResource interfacevirtual void OnLostDisplay();virtual void OnResetDisplay();virtual bool IsCaching() const override;virtual int GetCacheLevel() const override;virtual int OnDVDNavResult(void* pData, int iMessage) override;void GetVideoResolution(unsigned int &width, unsigned int &height) override;protected:friend class CSelectionStreams;virtual void OnStartup();virtual void OnExit();virtual void Process();virtual void VideoParamsChange() override;virtual void GetDebugInfo(std::string &audio, std::string &video, std::string &general) override;virtual void UpdateClockSync(bool enabled) override;virtual void UpdateRenderInfo(CRenderInfo &info) override;virtual void UpdateRenderBuffers(int queued, int discard, int free) override;void CreatePlayers();void DestroyPlayers();bool OpenStream(CCurrentStream& current, int64_t demuxerId, int iStream, int source, bool reset = true);bool OpenAudioStream(CDVDStreamInfo& hint, bool reset = true);bool OpenVideoStream(CDVDStreamInfo& hint, bool reset = true);bool OpenSubtitleStream(CDVDStreamInfo& hint);bool OpenTeletextStream(CDVDStreamInfo& hint);bool OpenRadioRDSStream(CDVDStreamInfo& hint);/** \brief Switches forced subtitles to forced subtitles matching the language of the current audio track.*          If these are not available, subtitles are disabled.*/void AdaptForcedSubtitles();bool CloseStream(CCurrentStream& current, bool bWaitForBuffers);bool CheckIsCurrent(CCurrentStream& current, CDemuxStream* stream, DemuxPacket* pkg);void ProcessPacket(CDemuxStream* pStream, DemuxPacket* pPacket);void ProcessAudioData(CDemuxStream* pStream, DemuxPacket* pPacket);void ProcessVideoData(CDemuxStream* pStream, DemuxPacket* pPacket);void ProcessSubData(CDemuxStream* pStream, DemuxPacket* pPacket);void ProcessTeletextData(CDemuxStream* pStream, DemuxPacket* pPacket);void ProcessRadioRDSData(CDemuxStream* pStream, DemuxPacket* pPacket);bool ShowPVRChannelInfo();int  AddSubtitleFile(const std::string& filename, const std::string& subfilename = "");void SetSubtitleVisibleInternal(bool bVisible);/*** one of the DVD_PLAYSPEED defines*/void SetPlaySpeed(int iSpeed);int GetPlaySpeed() { return m_playSpeed; }enum ECacheState{CACHESTATE_DONE = 0,CACHESTATE_FULL,     // player is filling up the demux queueCACHESTATE_INIT,     // player is waiting for first packet of each streamCACHESTATE_PLAY,     // player is waiting for players to not be stalledCACHESTATE_FLUSH,    // temporary state player will choose startup between init or full};void SetCaching(ECacheState state);int64_t GetTotalTimeInMsec();double GetQueueTime();bool GetCachingTimes(double& play_left, double& cache_left, double& file_offset);void FlushBuffers(double pts, bool accurate, bool sync);void HandleMessages();void HandlePlaySpeed();bool IsInMenuInternal() const;void SynchronizeDemuxer();void CheckAutoSceneSkip();bool CheckContinuity(CCurrentStream& current, DemuxPacket* pPacket);bool CheckSceneSkip(CCurrentStream& current);bool CheckPlayerInit(CCurrentStream& current);void UpdateCorrection(DemuxPacket* pkt, double correction);void UpdateTimestamps(CCurrentStream& current, DemuxPacket* pPacket);IDVDStreamPlayer* GetStreamPlayer(unsigned int player);void SendPlayerMessage(CDVDMsg* pMsg, unsigned int target);bool ReadPacket(DemuxPacket*& packet, CDemuxStream*& stream);bool IsValidStream(CCurrentStream& stream);bool IsBetterStream(CCurrentStream& current, CDemuxStream* stream);void CheckBetterStream(CCurrentStream& current, CDemuxStream* stream);void CheckStreamChanges(CCurrentStream& current, CDemuxStream* stream);bool CheckDelayedChannelEntry(void);bool OpenInputStream();bool OpenDemuxStream();void CloseDemuxer();void OpenDefaultStreams(bool reset = true);void UpdateApplication(double timeout);void UpdatePlayState(double timeout);void UpdateStreamInfos();void GetGeneralInfo(std::string& strVideoInfo);double m_UpdateApplication;bool m_players_created;bool m_bAbortRequest;ECacheState  m_caching;XbmcThreads::EndTime m_cachingTimer;CFileItem    m_item;XbmcThreads::EndTime m_ChannelEntryTimeOut;std::unique_ptr<CProcessInfo> m_processInfo;CCurrentStream m_CurrentAudio;CCurrentStream m_CurrentVideo;CCurrentStream m_CurrentSubtitle;CCurrentStream m_CurrentTeletext;CCurrentStream m_CurrentRadioRDS;CSelectionStreams m_SelectionStreams;std::atomic_int m_playSpeed;std::atomic_int m_newPlaySpeed;int m_streamPlayerSpeed;struct SSpeedState{double  lastpts;  // holds last display pts during ff/rw operationsint64_t lasttime;int lastseekpts;double  lastabstime;} m_SpeedState;std::atomic_bool m_canTempo;int m_errorCount;double m_offset_pts;CDVDMessageQueue m_messenger;     // thread messengerIDVDStreamPlayerVideo *m_VideoPlayerVideo; // video partIDVDStreamPlayerAudio *m_VideoPlayerAudio; // audio partCVideoPlayerSubtitle *m_VideoPlayerSubtitle; // subtitle partCDVDTeletextData *m_VideoPlayerTeletext; // teletext partCDVDRadioRDSData *m_VideoPlayerRadioRDS; // rds partCDVDClock m_clock;                // master clockCDVDOverlayContainer m_overlayContainer;CDVDInputStream* m_pInputStream;  // input stream for current playing fileCDVDDemux* m_pDemuxer;            // demuxer for current playing fileCDVDDemux* m_pSubtitleDemuxer;CDVDDemuxCC* m_pCCDemuxer;CRenderManager m_renderManager;struct SDVDInfo{void Clear(){state                =  DVDSTATE_NORMAL;iSelectedSPUStream   = -1;iSelectedAudioStream = -1;iSelectedVideoStream = -1;iDVDStillTime        =  0;iDVDStillStartTime   =  0;syncClock = false;}int state;                // current dvdstatebool syncClock;unsigned int iDVDStillTime;      // total time in ticks we should display the still before continuingunsigned int iDVDStillStartTime; // time in ticks when we started the stillint iSelectedSPUStream;   // mpeg stream id, or -1 if disabledint iSelectedAudioStream; // mpeg stream id, or -1 if disabledint iSelectedVideoStream; // mpeg stream id or angle, -1 if disabled} m_dvd;friend class CVideoPlayerVideo;friend class CVideoPlayerAudio;
#ifdef HAS_OMXPLAYERfriend class OMXPlayerVideo;friend class OMXPlayerAudio;
#endifSPlayerState m_State;CCriticalSection m_StateSection;XbmcThreads::EndTime m_syncTimer;CEvent m_ready;CEdl m_Edl;bool m_SkipCommercials;CPlayerOptions m_PlayerOptions;bool m_HasVideo;bool m_HasAudio;std::atomic<bool> m_displayLost;// omxplayer variablesstruct SOmxPlayerState m_OmxPlayerState;bool m_omxplayer_mode;            // using omxplayer accelerationXbmcThreads::EndTime m_player_status_timer;
};

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

void CVideoPlayer::Process()
{CFFmpegLog::SetLogLevel(1);if (!OpenInputStream())//创建输入流{m_bAbortRequest = true;return;}if (CDVDInputStream::IMenus* ptr = dynamic_cast<CDVDInputStream::IMenus*>(m_pInputStream)){CLog::Log(LOGNOTICE, "VideoPlayer: playing a file with menu's");if(dynamic_cast<CDVDInputStreamNavigator*>(m_pInputStream))m_PlayerOptions.starttime = 0;if(!m_PlayerOptions.state.empty())ptr->SetState(m_PlayerOptions.state);else if(CDVDInputStreamNavigator* nav = dynamic_cast<CDVDInputStreamNavigator*>(m_pInputStream))nav->EnableSubtitleStream(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_SubtitleOn);CMediaSettings::GetInstance().GetCurrentVideoSettings().m_SubtitleCached = true;}if(!OpenDemuxStream())//创建demux{m_bAbortRequest = true;return;}// give players a chance to reconsider now codecs are knownCreatePlayers();// allow renderer to switch to fullscreen if requestedm_VideoPlayerVideo->EnableFullscreen(m_PlayerOptions.fullscreen);if (m_omxplayer_mode){if (!m_OmxPlayerState.av_clock.OMXInitialize(&m_clock))m_bAbortRequest = true;if (CSettings::GetInstance().GetInt(CSettings::SETTING_VIDEOPLAYER_ADJUSTREFRESHRATE) != ADJUST_REFRESHRATE_OFF)m_OmxPlayerState.av_clock.HDMIClockSync();m_OmxPlayerState.av_clock.OMXStateIdle();m_OmxPlayerState.av_clock.OMXStateExecute();m_OmxPlayerState.av_clock.OMXStop();m_OmxPlayerState.av_clock.OMXPause();}OpenDefaultStreams();// look for any EDL filesm_Edl.Clear();if (m_CurrentVideo.id >= 0 && m_CurrentVideo.hint.fpsrate > 0 && m_CurrentVideo.hint.fpsscale > 0){float fFramesPerSecond = (float)m_CurrentVideo.hint.fpsrate / (float)m_CurrentVideo.hint.fpsscale;m_Edl.ReadEditDecisionLists(m_item.GetPath(), fFramesPerSecond, m_CurrentVideo.hint.height);}/** Check to see if the demuxer should start at something other than time 0. This will be the case* if there was a start time specified as part of the "Start from where last stopped" (aka* auto-resume) feature or if there is an EDL cut or commercial break that starts at time 0.*/CEdl::Cut cut;int starttime = 0;if (m_PlayerOptions.starttime > 0 || m_PlayerOptions.startpercent > 0){if (m_PlayerOptions.startpercent > 0 && m_pDemuxer){int playerStartTime = (int)( ( (float) m_pDemuxer->GetStreamLength() ) * ( m_PlayerOptions.startpercent/(float)100 ) );starttime = m_Edl.RestoreCutTime(playerStartTime);}else{starttime = m_Edl.RestoreCutTime(m_PlayerOptions.starttime * 1000); // s to ms}CLog::Log(LOGDEBUG, "%s - Start position set to last stopped position: %d", __FUNCTION__, starttime);}else if (m_Edl.InCut(starttime, &cut)){if (cut.action == CEdl::CUT){starttime = cut.end;CLog::Log(LOGDEBUG, "%s - Start position set to end of first cut: %d", __FUNCTION__, starttime);}else if (cut.action == CEdl::COMM_BREAK){if (m_SkipCommercials){starttime = cut.end;CLog::Log(LOGDEBUG, "%s - Start position set to end of first commercial break: %d", __FUNCTION__, starttime);}std::string strTimeString = StringUtils::SecondsToTimeString(cut.end / 1000, TIME_FORMAT_MM_SS);CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(25011), strTimeString);}}if (starttime > 0)//判断上次播放时长,选择从上次播放时开始播放{double startpts = DVD_NOPTS_VALUE;if (m_pDemuxer){if (m_pDemuxer->SeekTime(starttime, false, &startpts))CLog::Log(LOGDEBUG, "%s - starting demuxer from: %d", __FUNCTION__, starttime);elseCLog::Log(LOGDEBUG, "%s - failed to start demuxing from: %d", __FUNCTION__, starttime);}if (m_pSubtitleDemuxer){if(m_pSubtitleDemuxer->SeekTime(starttime, false, &startpts))CLog::Log(LOGDEBUG, "%s - starting subtitle demuxer from: %d", __FUNCTION__, starttime);elseCLog::Log(LOGDEBUG, "%s - failed to start subtitle demuxing from: %d", __FUNCTION__, starttime);}m_clock.Discontinuity(DVD_MSEC_TO_TIME(starttime));}// make sure application know our infoUpdateApplication(0);UpdatePlayState(0);if(m_PlayerOptions.identify == false)m_callback.OnPlayBackStarted();// we are done initializing now, set the readyeventm_ready.Set();SetCaching(CACHESTATE_FLUSH);while (!m_bAbortRequest)//开启循环demux,将数据抛给下层decode{
#ifdef HAS_OMXPLAYERif (m_omxplayer_mode && OMXDoProcessing(m_OmxPlayerState, m_playSpeed, m_VideoPlayerVideo, m_VideoPlayerAudio, m_CurrentAudio, m_CurrentVideo, m_HasVideo, m_HasAudio, m_renderManager)){CloseStream(m_CurrentVideo, false);OpenStream(m_CurrentVideo, m_CurrentVideo.demuxerId, m_CurrentVideo.id, m_CurrentVideo.source);if (m_State.canseek){CDVDMsgPlayerSeek::CMode mode;mode.time = (int)GetTime();mode.backward = true;mode.accurate = true;mode.sync = true;m_messenger.Put(new CDVDMsgPlayerSeek(mode));}}
#endif// check display lostif (m_displayLost){Sleep(50);continue;}// check if in a cut or commercial break that should be automatically skippedCheckAutoSceneSkip();// handle messages send to this thread, like seek or demuxer reset requestsHandleMessages();if(m_bAbortRequest)break;// should we open a new input stream?if(!m_pInputStream){if (OpenInputStream() == false){m_bAbortRequest = true;break;}}// should we open a new demuxer?if(!m_pDemuxer){if (m_pInputStream->NextStream() == CDVDInputStream::NEXTSTREAM_NONE)break;if (m_pInputStream->IsEOF())break;if (OpenDemuxStream() == false){m_bAbortRequest = true;break;}// on channel switch we don't want to close stream players at this// time. we'll get the stream change event laterif (!m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER) ||!m_SelectionStreams.m_Streams.empty())OpenDefaultStreams();UpdateApplication(0);UpdatePlayState(0);}// handle eventual seeks due to playspeedHandlePlaySpeed();// update player stateUpdatePlayState(200);// update application with our stateUpdateApplication(1000);// make sure we run subtitle process herem_VideoPlayerSubtitle->Process(m_clock.GetClock() + m_State.time_offset - m_VideoPlayerVideo->GetSubtitleDelay(), m_State.time_offset);if (CheckDelayedChannelEntry())continue;// if the queues are full, no need to read moreif ((!m_VideoPlayerAudio->AcceptsData() && m_CurrentAudio.id >= 0) ||(!m_VideoPlayerVideo->AcceptsData() && m_CurrentVideo.id >= 0)){Sleep(10);continue;}// always yield to players if they have data levels > 50 percentif((m_VideoPlayerAudio->GetLevel() > 50 || m_CurrentAudio.id < 0)&& (m_VideoPlayerVideo->GetLevel() > 50 || m_CurrentVideo.id < 0))Sleep(0);DemuxPacket* pPacket = NULL;CDemuxStream *pStream = NULL;ReadPacket(pPacket, pStream);//开始将流封包,方便传给下一层decodeif (pPacket && !pStream){/* probably a empty packet, just free it and move on */CDVDDemuxUtils::FreeDemuxPacket(pPacket);continue;}if (!pPacket){// when paused, demuxer could be be returning emptyif (m_playSpeed == DVD_PLAYSPEED_PAUSE)continue;// check for a still frame stateif (CDVDInputStream::IMenus* pStream = dynamic_cast<CDVDInputStream::IMenus*>(m_pInputStream)){// stills will be skippedif(m_dvd.state == DVDSTATE_STILL){if (m_dvd.iDVDStillTime > 0){if ((XbmcThreads::SystemClockMillis() - m_dvd.iDVDStillStartTime) >= m_dvd.iDVDStillTime){m_dvd.iDVDStillTime = 0;m_dvd.iDVDStillStartTime = 0;m_dvd.state = DVDSTATE_NORMAL;pStream->SkipStill();continue;}}}}// if there is another stream available, reopen demuxerCDVDInputStream::ENextStream next = m_pInputStream->NextStream();if(next == CDVDInputStream::NEXTSTREAM_OPEN){CloseDemuxer();SetCaching(CACHESTATE_DONE);CLog::Log(LOGNOTICE, "VideoPlayer: next stream, wait for old streams to be finished");CloseStream(m_CurrentAudio, true);CloseStream(m_CurrentVideo, true);m_CurrentAudio.Clear();m_CurrentVideo.Clear();m_CurrentSubtitle.Clear();continue;}// input stream asked us to just retryif(next == CDVDInputStream::NEXTSTREAM_RETRY){Sleep(100);continue;}// make sure we tell all players to finish it's dataif (m_omxplayer_mode && !m_OmxPlayerState.bOmxSentEOFs){if(m_CurrentAudio.inited)m_OmxPlayerState.bOmxWaitAudio = true;if(m_CurrentVideo.inited)m_OmxPlayerState.bOmxWaitVideo = true;m_OmxPlayerState.bOmxSentEOFs = true;}if(m_CurrentAudio.inited)m_VideoPlayerAudio->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));if(m_CurrentVideo.inited)m_VideoPlayerVideo->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));if(m_CurrentSubtitle.inited)m_VideoPlayerSubtitle->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));if(m_CurrentTeletext.inited)m_VideoPlayerTeletext->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));if(m_CurrentRadioRDS.inited)m_VideoPlayerRadioRDS->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));m_CurrentAudio.inited = false;m_CurrentVideo.inited = false;m_CurrentSubtitle.inited = false;m_CurrentTeletext.inited = false;m_CurrentRadioRDS.inited = false;// if we are caching, start playing it againSetCaching(CACHESTATE_DONE);// while players are still playing, keep going to allow seekbacksif(m_VideoPlayerAudio->HasData()|| m_VideoPlayerVideo->HasData()){Sleep(100);continue;}
#ifdef HAS_OMXPLAYERif (m_omxplayer_mode && OMXStillPlaying(m_OmxPlayerState.bOmxWaitVideo, m_OmxPlayerState.bOmxWaitAudio, m_VideoPlayerVideo->IsEOS(), m_VideoPlayerAudio->IsEOS())){Sleep(100);continue;}
#endifif (!m_pInputStream->IsEOF())CLog::Log(LOGINFO, "%s - eof reading from demuxer", __FUNCTION__);break;}// it's a valid data packet, reset error counterm_errorCount = 0;// see if we can find something better to playCheckBetterStream(m_CurrentAudio,    pStream);CheckBetterStream(m_CurrentVideo,    pStream);CheckBetterStream(m_CurrentSubtitle, pStream);CheckBetterStream(m_CurrentTeletext, pStream);CheckBetterStream(m_CurrentRadioRDS, pStream);// demux video streamif (CSettings::GetInstance().GetBool(CSettings::SETTING_SUBTITLES_PARSECAPTIONS) && CheckIsCurrent(m_CurrentVideo, pStream, pPacket)){if (m_pCCDemuxer){bool first = true;while(!m_bAbortRequest){DemuxPacket *pkt = m_pCCDemuxer->Read(first ? pPacket : NULL);if (!pkt)break;first = false;if (m_pCCDemuxer->GetNrOfStreams() != m_SelectionStreams.CountSource(STREAM_SUBTITLE, STREAM_SOURCE_VIDEOMUX)){m_SelectionStreams.Clear(STREAM_SUBTITLE, STREAM_SOURCE_VIDEOMUX);m_SelectionStreams.Update(NULL, m_pCCDemuxer, "");OpenDefaultStreams(false);}CDemuxStream *pSubStream = m_pCCDemuxer->GetStream(pkt->iStreamId);if (pSubStream && m_CurrentSubtitle.id == pkt->iStreamId && m_CurrentSubtitle.source == STREAM_SOURCE_VIDEOMUX)ProcessSubData(pSubStream, pkt);elseCDVDDemuxUtils::FreeDemuxPacket(pkt);}}}if (IsInMenuInternal()){if (CDVDInputStream::IMenus* menu = dynamic_cast<CDVDInputStream::IMenus*>(m_pInputStream)){double correction = menu->GetTimeStampCorrection();if (pPacket->dts != DVD_NOPTS_VALUE && pPacket->dts > correction)pPacket->dts -= correction;if (pPacket->pts != DVD_NOPTS_VALUE && pPacket->pts > correction)pPacket->pts -= correction;}if (m_dvd.syncClock){m_clock.Discontinuity(pPacket->dts);m_dvd.syncClock = false;}}// process the packetProcessPacket(pStream, pPacket);//将音频流、视频流、字幕流等分开,创建decode的Player并将数据传递给他们// update the player info for streamsif (m_player_status_timer.IsTimePast()){m_player_status_timer.Set(500);UpdateStreamInfos();}}
}

第一步是OpenInputStream,调用

bool CVideoPlayer::OpenInputStream()
{if(m_pInputStream)SAFE_DELETE(m_pInputStream);CLog::Log(LOGNOTICE, "Creating InputStream");// correct the filename if neededstd::string filename(m_item.GetPath());if (URIUtils::IsProtocol(filename, "dvd") ||StringUtils::EqualsNoCase(filename, "iso9660://video_ts/video_ts.ifo")){m_item.SetPath(g_mediaManager.TranslateDevicePath(""));}m_pInputStream = CDVDFactoryInputStream::CreateInputStream(this, m_item, true);//创建if(m_pInputStream == NULL){CLog::Log(LOGERROR, "CVideoPlayer::OpenInputStream - unable to create input stream for [%s]", CURL::GetRedacted(m_item.GetPath()).c_str());return false;}if (!m_pInputStream->Open()){CLog::Log(LOGERROR, "CVideoPlayer::OpenInputStream - error opening [%s]", CURL::GetRedacted(m_item.GetPath()).c_str());return false;}// find any available external subtitles for non dvd filesif (!m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)&&  !m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)&&  !m_pInputStream->IsStreamType(DVDSTREAM_TYPE_TV)){// find any available external subtitlesstd::vector<std::string> filenames;CUtil::ScanForExternalSubtitles(m_item.GetPath(), filenames);// load any subtitles from file itemstd::string key("subtitle:1");for(unsigned s = 1; m_item.HasProperty(key); key = StringUtils::Format("subtitle:%u", ++s))filenames.push_back(m_item.GetProperty(key).asString());for(unsigned int i=0;i<filenames.size();i++){// if vobsub subtitle:if (URIUtils::HasExtension(filenames[i], ".idx")){std::string strSubFile;if ( CUtil::FindVobSubPair( filenames, filenames[i], strSubFile ) )AddSubtitleFile(filenames[i], strSubFile);}else{if ( !CUtil::IsVobSub(filenames, filenames[i] ) ){AddSubtitleFile(filenames[i]);}}} // end loop over all subtitle filesCMediaSettings::GetInstance().GetCurrentVideoSettings().m_SubtitleCached = true;}SetAVDelay(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_AudioDelay);SetSubTitleDelay(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_SubtitleDelay);m_clock.Reset();m_dvd.Clear();m_errorCount = 0;m_ChannelEntryTimeOut.SetInfinite();if (CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEDISPLAYASCLOCK) &&!m_pInputStream->IsRealtime()){m_canTempo = true;}else{m_canTempo = false;}return true;
}

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

CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IVideoPlayer* pPlayer, const CFileItem &fileitem, bool scanforextaudio)//根据文件类型创建不同的InputStream
{std::string file = fileitem.GetPath();if (scanforextaudio){// find any available external audio tracksstd::vector<std::string> filenames;filenames.push_back(file);CUtil::ScanForExternalAudio(file, filenames);CUtil::ScanForExternalDemuxSub(file, filenames);if (filenames.size() >= 2){return CreateInputStream(pPlayer, fileitem, filenames);}}ADDON::VECADDONS addons;ADDON::CBinaryAddonCache &addonCache = CServiceBroker::GetBinaryAddonCache();addonCache.GetAddons(addons, ADDON::ADDON_INPUTSTREAM);for (size_t i=0; i<addons.size(); ++i){std::shared_ptr<ADDON::CInputStream> input(std::static_pointer_cast<ADDON::CInputStream>(addons[i]));if (input->Supports(fileitem)){std::shared_ptr<ADDON::CInputStream> addon = input;if (!input->UseParent())addon = std::shared_ptr<ADDON::CInputStream>(new ADDON::CInputStream(*input));ADDON_STATUS status = addon->Create();if (status == ADDON_STATUS_OK){unsigned int videoWidth, videoHeight;pPlayer->GetVideoResolution(videoWidth, videoHeight);addon->SetVideoResolution(videoWidth, videoHeight);return new CInputStreamAddon(fileitem, addon);}}}if (fileitem.IsDiscImage()){
#ifdef HAVE_LIBBLURAYCURL url("udf://");url.SetHostName(file);url.SetFileName("BDMV/index.bdmv");if(XFILE::CFile::Exists(url.Get()))return new CDVDInputStreamBluray(pPlayer, fileitem);
#endifreturn new CDVDInputStreamNavigator(pPlayer, fileitem);}#ifdef HAS_DVD_DRIVEif(file.compare(g_mediaManager.TranslateDevicePath("")) == 0){
#ifdef HAVE_LIBBLURAYif(XFILE::CFile::Exists(URIUtils::AddFileToFolder(file, "BDMV", "index.bdmv")))return new CDVDInputStreamBluray(pPlayer, fileitem);
#endifreturn new CDVDInputStreamNavigator(pPlayer, fileitem);}
#endifif (fileitem.IsDVDFile(false, true))return (new CDVDInputStreamNavigator(pPlayer, fileitem));else if(file.substr(0, 6) == "pvr://")return new CDVDInputStreamPVRManager(pPlayer, fileitem);
#ifdef HAVE_LIBBLURAYelse if (fileitem.IsType(".bdmv") || fileitem.IsType(".mpls") || file.substr(0, 7) == "bluray:")return new CDVDInputStreamBluray(pPlayer, fileitem);
#endifelse if(file.substr(0, 6) == "rtp://"|| file.substr(0, 7) == "rtsp://"|| file.substr(0, 6) == "sdp://"|| file.substr(0, 6) == "udp://"|| file.substr(0, 6) == "tcp://"|| file.substr(0, 6) == "mms://"|| file.substr(0, 7) == "mmst://"|| file.substr(0, 7) == "mmsh://")return new CDVDInputStreamFFmpeg(fileitem);
#ifdef ENABLE_DVDINPUTSTREAM_STACKelse if(file.substr(0, 8) == "stack://")return new CDVDInputStreamStack(fileitem);
#endifelse if(file.substr(0, 7) == "rtmp://"|| file.substr(0, 8) == "rtmpt://"|| file.substr(0, 8) == "rtmpe://"|| file.substr(0, 9) == "rtmpte://"|| file.substr(0, 8) == "rtmps://")return new CDVDInputStreamFFmpeg(fileitem);CFileItem finalFileitem(fileitem);if (finalFileitem.IsInternetStream()){if (finalFileitem.ContentLookup()){CURL origUrl(finalFileitem.GetURL());XFILE::CCurlFile curlFile;// try opening the url to resolve all redirects if anytry{if (curlFile.Open(finalFileitem.GetURL())){CURL finalUrl(curlFile.GetURL());finalUrl.SetProtocolOptions(origUrl.GetProtocolOptions());finalUrl.SetUserName(origUrl.GetUserName());finalUrl.SetPassword(origUrl.GetPassWord());finalFileitem.SetPath(finalUrl.Get());}curlFile.Close();}catch (XFILE::CRedirectException *pRedirectEx){if (pRedirectEx){delete pRedirectEx->m_pNewFileImp;delete pRedirectEx;}}}if (finalFileitem.IsType(".m3u8"))return new CDVDInputStreamFFmpeg(finalFileitem);if (finalFileitem.GetMimeType() == "application/vnd.apple.mpegurl")return new CDVDInputStreamFFmpeg(finalFileitem);if (URIUtils::IsProtocol(finalFileitem.GetPath(), "udp"))return new CDVDInputStreamFFmpeg(finalFileitem);}// our file interface handles all these types of streamsreturn (new CDVDInputStreamFile(finalFileitem));
}

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

KODI(原XBMC)二次开发完全解析(三)-------获取视频输入流相关推荐

  1. KODI(原XBMC)二次开发完全解析(二)-------创建player

    使用过kodi的都知道,kodi播放之前有一个影片列表页面,可以变换LowPanel,list等形式,那个页面对应的源代码路径就是/xbmc/video/windows/GUIVideoWindowN ...

  2. python海康威视网络摄像头_OpenCV:非海康威视大华宇视(其他)网络摄像头IPC 二次开发(Python)获取视频图像...

    # -*- coding: UTF-8 -*- # ! /usr/bin/python import cv2 # 参数 # -------------------------------------- ...

  3. 最新微信hook二次开发C#Demo之获取消息代码

    用[最新微信hook二次开发c#源代码]获取消息: 消息类型有以下几种 1 文本,2 图片,3 表情(gif),4 视频,5 文件,6 名片,7 位置,8 小程序,9 链接,10公众号文章列表 发送方 ...

  4. 人人php 路由,关于人人分销/人人商城的二次开发路由解析

    最近在做人人分销的二次开发,遇到奇葩客户,没办法,只能硬着头皮上,需要做一个后台设定可以设置是否默认会员自动升级的设置,然后就扒了一边微擎+人人分销v2的路由.记录分享下~ 首先微擎目录下有app 和 ...

  5. ENVI_IDL:批量重投影ModisSwath产品(调用二次开发接口)+解析

    目录 1. 课堂内容 1. 获取Modis Swath数据(这里只获取Lat.Lon.Aod(气溶胶厚度)三个数据集以及aod数据集的两个属性),并对aod数据进行简单的处理 2. 调用二次开发接口以 ...

  6. 【菠萝狗四足机器人】二次开发教程--第三章 【腿部校准和步态效果调试】

    腿部校准和步态效果调试 1 前言 2 腿部调中(0位校准) 3 步态效果调试 3.1 重心标定 3.2 自动重心补偿量调节 4 结束 1 前言 承接上次的教程,本次文章,将教你怎么对 Py-apple ...

  7. AIMS/MapGuide API二次开发从入门到精通视频课程系列--2

    为了大家更方便的学习AIMS/MapGuide二次开发,我将录制一系列的视频课程,陆续发布到我的博客上.这是第2讲,名字有点土,希望内容还行.这一讲主要介绍一下AIMS/MapGuide Studio ...

  8. 惠普打印机、扫描仪二次开发、支持状态获取

    一.环境介绍 运行系统环境: xp .win7.win8.win10. 目前测试支持的是HP Pro 系列的打印机,比如LaserJet Pro, OfficeJet Pro,PageWide等等,理 ...

  9. AutoCAD二次开发基础(三):船体型线绘制

    AutoCAD二次开发系列 文章目录 前言 一.绘制船体横剖线 二.绘制船体纵剖线 三.绘制船体肋骨型线图 前言 用程序生成船体型线图,无疑会提高开发效率. 一.绘制船体横剖线 任务:编制程序,根据水 ...

最新文章

  1. 没有点真的大项目工程经验,你真以为能进大厂的算法岗?
  2. Android属动画ObjectAnimator和ValueAnimator应用
  3. Acwing第 18 场周赛【完结】
  4. python中的ideavim有什么作用_Pycharm和Idea支持的vim插件的方法
  5. Linux命令【二】终端+Vim
  6. 采用批处理命令对文件进行解压及采用SQLCMD进行数据库挂载
  7. bootstrap 垂直居中 布局_网页布局都有哪种?一般都用什么布局?
  8. CentOS 7安装配置FTP服务器
  9. 对象行为型 - 模版方法模式
  10. 多线程等待/通知机制
  11. 机器人运动学 DH参数
  12. 关于vscode新建文档代码自定义模板的设置
  13. 如何制作伪原创视频?呆头鹅批量视频剪辑软件一键处理10万个视频
  14. FPGA之JESD204B接口——总体概要 实例上
  15. 你还没掌握超表「视图」, 难怪觉得数据繁杂得要命!
  16. HEVC官方软件HM源代码简单分析-解码器TAppDecoder
  17. 高中数学基础08:关系、概率与统计
  18. C++实现Win11万年历
  19. 项目管理软件中有哪些技术风险?
  20. 段码液晶屏过ESD测试

热门文章

  1. qt QRubberBand实现区域选择。
  2. python编程:从入门到实践6-7,6-8,6-9,6-10,6-11,6-12
  3. 改造analysis-dynamic-synonym源码访问远程数据库
  4. 改成短链接 The target server failed to respond 错误
  5. copy文件的Linux程序代码,Linux下C语言实现CopyFile
  6. 7年java水平_7年Java开发(月薪37K)分享正确的自学路线,不喜勿喷
  7. OpenGL使用矩阵堆栈glpushMatrix的原因
  8. 3GP文件格式的研究(有转载)
  9. Hive vs Impala
  10. 第26章、OnKeyListener键盘事件(从零开始学Android)