EMIPLIB
|
00001 /* 00002 00003 This file is a part of EMIPLIB, the EDM Media over IP Library. 00004 00005 Copyright (C) 2006-2011 Hasselt University - Expertise Centre for 00006 Digital Media (EDM) (http://www.edm.uhasselt.be) 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Lesser General Public 00010 License as published by the Free Software Foundation; either 00011 version 2.1 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Lesser General Public License for more details. 00017 00018 You should have received a copy of the GNU Lesser General Public 00019 License along with this library; if not, write to the Free Software 00020 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 00021 USA 00022 00023 */ 00024 00029 #ifndef MIPVIDEOMIXER_H 00030 00031 #define MIPVIDEOMIXER_H 00032 00033 #include "mipconfig.h" 00034 #include "mipcomponent.h" 00035 #include "miptime.h" 00036 #include "miprawvideomessage.h" 00037 #include <list> 00038 00048 class EMIPLIB_IMPORTEXPORT MIPVideoMixer : public MIPComponent 00049 { 00050 public: 00051 MIPVideoMixer(); 00052 ~MIPVideoMixer(); 00053 00060 bool init(real_t frameRate, int maxStreams = -1); 00061 00063 bool destroy(); 00064 00071 bool setExtraDelay(MIPTime t); 00072 00073 bool push(const MIPComponentChain &chain, int64_t iteration, MIPMessage *pMsg); 00074 bool pull(const MIPComponentChain &chain, int64_t iteration, MIPMessage **pMsg); 00075 bool processFeedback(const MIPComponentChain &chain, int64_t feedbackChainID, MIPFeedback *feedback); 00076 private: 00077 class VideoFrame 00078 { 00079 public: 00080 VideoFrame(int64_t playInterval, MIPRawYUV420PVideoMessage *pMsg) { m_interval = playInterval; m_pMsg = pMsg; } 00081 MIPRawYUV420PVideoMessage *getMessage() { return m_pMsg; } 00082 int64_t getInterval() const { return m_interval; } 00083 private: 00084 MIPRawYUV420PVideoMessage *m_pMsg; 00085 int64_t m_interval; 00086 }; 00087 00088 class SourceStream 00089 { 00090 public: 00091 SourceStream(uint64_t sourceID) { m_sourceID = sourceID; } 00092 ~SourceStream() { std::list<VideoFrame>::iterator it; for (it = m_videoFrames.begin() ; it != m_videoFrames.end(); it++) if ((*it).getMessage()) delete (*it).getMessage(); } 00093 uint64_t getSourceID() const { return m_sourceID; } 00094 std::list<VideoFrame> &getFrames() { return m_videoFrames; } 00095 MIPTime getLastInsertTime() const { return m_lastInsertTime; } 00096 MIPRawYUV420PVideoMessage *ExtractMessage(int64_t curInterval) 00097 { 00098 if (m_videoFrames.empty()) 00099 return 0; 00100 00101 VideoFrame frame = *(m_videoFrames.begin()); 00102 if (frame.getInterval() == curInterval) 00103 { 00104 m_videoFrames.pop_front(); 00105 return frame.getMessage(); 00106 } 00107 return 0; 00108 } 00109 void insertFrame(int64_t frameNum, MIPRawYUV420PVideoMessage *pMsg) 00110 { 00111 m_lastInsertTime = MIPTime::getCurrentTime(); 00112 00113 std::list<VideoFrame>::iterator it; 00114 00115 it = m_videoFrames.begin(); 00116 00117 if (it == m_videoFrames.end()) 00118 { 00119 m_videoFrames.push_back(VideoFrame(frameNum,pMsg)); 00120 return; 00121 } 00122 00123 if (frameNum < (*it).getInterval()) 00124 { 00125 m_videoFrames.insert(it, VideoFrame(frameNum,pMsg)); 00126 return; 00127 } 00128 00129 if (frameNum == (*it).getInterval()) 00130 { 00131 // already a frame present, replace it with the new frame 00132 delete (*it).getMessage(); 00133 (*it) = VideoFrame(frameNum,pMsg); 00134 return; 00135 } 00136 00137 // frameNum > (*it).getInterval() 00138 00139 bool done = false; 00140 00141 while (!done) 00142 { 00143 it++; 00144 if (it == m_videoFrames.end()) 00145 { 00146 done = true; 00147 } 00148 else 00149 { 00150 if ((*it).getInterval() == frameNum) 00151 { 00152 // already a frame present, replace it with the new frame 00153 delete (*it).getMessage(); 00154 (*it) = VideoFrame(frameNum,pMsg); 00155 return; 00156 } 00157 00158 if (frameNum < (*it).getInterval()) 00159 { 00160 m_videoFrames.insert(it, VideoFrame(frameNum,pMsg)); 00161 return; 00162 } 00163 } 00164 } 00165 00166 m_videoFrames.push_back(VideoFrame(frameNum,pMsg)); 00167 } 00168 private: 00169 uint64_t m_sourceID; 00170 std::list<VideoFrame> m_videoFrames; 00171 MIPTime m_lastInsertTime; 00172 }; 00173 00174 bool initFrameSearch(uint64_t sourceID); 00175 void clearOutputMessages(); 00176 void createNewOutputMessages(); 00177 void deleteOldSources(); 00178 00179 bool m_init; 00180 int m_maxStreams; 00181 int64_t m_prevIteration; 00182 int64_t m_curInterval; 00183 MIPTime m_playTime, m_frameTime, m_lastCheckTime; 00184 MIPTime m_extraDelay; 00185 std::list<SourceStream *> m_streams; 00186 std::list<MIPRawYUV420PVideoMessage *> m_outputMessages; 00187 std::list<MIPRawYUV420PVideoMessage *>::const_iterator m_msgIt; 00188 }; 00189 00190 #endif // MIPVIDEOMIXER_H 00191