EMIPLIB

mipvideomixer.h

Go to the documentation of this file.
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