normaltrickplay.cpp 7.22 KB
Newer Older
1 2 3 4 5
/*******************************************************************************
* normaltrickplay.cpp: The normal implementation from trickplay. It only supports
*                      start, stop, suspend and resume operations.
*-------------------------------------------------------------------------------
* (c)1999-2003 VideoLAN
6
* $Id: normaltrickplay.cpp,v 1.13 2003/08/14 17:20:36 adq Exp $
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
*
* Authors: Jean-Paul Saman <jpsaman@wxs.nl>          
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
*-------------------------------------------------------------------------------
*
*******************************************************************************/


//------------------------------------------------------------------------------
// Preamble
//------------------------------------------------------------------------------
#include "../../core/defs.h"

#include "../../core/core.h"

#include "../../mpeg/mpeg.h"
#include "../../mpeg/ts.h"
38
#include "../../mpeg/rtp.h"
39 40
#include "../../server/buffer.h"
#include "../../server/program.h"
41 42
#include "../../server/output.h"
#include "../../server/channel.h"
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
#include "../../server/broadcast.h"
#include "../../server/request.h"
#include "../../server/input.h"

#include "../../mpeg/reader.h"
#include "../../mpeg/converter.h"
#include "../../mpeg/trickplay.h"

#include "normaltrickplay.h"


//------------------------------------------------------------------------------
// Library declaration
//------------------------------------------------------------------------------
#ifdef __PLUGIN__
GENERATE_LIB_ARGS(C_NormalTrickPlayModule, handle);
#endif


//------------------------------------------------------------------------------
// Builtin declaration
//------------------------------------------------------------------------------
#ifdef __BUILTIN__
C_Module* NewBuiltin_normaltrickplay(handle hLog)
67
{
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  return new C_NormalTrickPlayModule(hLog);
}
#endif


/*******************************************************************************
* C_NormalTrickPlayModule
********************************************************************************
*
*******************************************************************************/


//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
C_NormalTrickPlay::C_NormalTrickPlay(C_Module* pModule,
                               C_TrickPlayConfig& cConfig)
: C_TrickPlay(pModule,cConfig)
{
}


//------------------------------------------------------------------------------
// Main job
//------------------------------------------------------------------------------

void C_NormalTrickPlay::HandlePacket(C_TsPacket* pPacket)
{
96 97 98
  if (!m_pHandler->HandlePacket(pPacket)) {
    m_pTsProvider->ReleasePacket(pPacket);
  }
99 100 101 102
}

void C_NormalTrickPlay::DoWork()
{
103 104
  C_TsPacket * pPacket;
  int iRc = NO_ERR;
105

106 107 108
  // Initialize the condition in the new thread.
  m_cResumeCond.Protect();

109
  // log it
110 111 112
  C_String strPgrmName = m_pBroadcast->GetProgram()->GetName();
  LogDbg(m_hLog, "Starting to read program \"" + strPgrmName + "\"");

113

114 115
  // the main loop
  unsigned int prefillCount = 0;
116 117
  while(!m_bStop && !iRc)
  {
118

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    if (m_iTrickPlayStatus != m_iRequestTrickPlayStatus)
    {
      switch (m_iRequestTrickPlayStatus)
      {
        case TRICKPLAY_PLAY:
          // implement your own policy here
          // ..
          m_iTrickPlayStatus = TRICKPLAY_PLAY;
          break;
        case TRICKPLAY_PAUSE:
          // implement your own policy here
          // ..
          m_iTrickPlayStatus = TRICKPLAY_PAUSE;
          m_cResumeCond.Wait();
          break;
        case TRICKPLAY_FORWARD: // Not implemented yet
          m_iTrickPlayStatus = TRICKPLAY_PLAY;
          m_iRequestTrickPlayStatus = TRICKPLAY_PLAY;
          break;
        case TRICKPLAY_REWIND: // Not implemented yet
          m_iTrickPlayStatus = TRICKPLAY_PLAY;
          m_iRequestTrickPlayStatus = TRICKPLAY_PLAY;
          break;
        case TRICKPLAY_STOP:
          m_iTrickPlayStatus = TRICKPLAY_STOP;
          m_bStop = true;
          break;
        default:
          LogDbg(m_hLog, "Unknown TrickPlay mode requested.");
          m_iRequestTrickPlayStatus = m_iTrickPlayStatus;
          break;
      }
    }
152

153
    iRc = m_pConverter->GetNextTsPackets(m_pPackets);
154

155
    int iVectorSize = m_pPackets->Size();
156

157
    if ((iRc == NO_ERR) && (!m_bStop))
158
    {
159 160
      for(int i = 0; i < iVectorSize;  i++)
      {
161
        pPacket =  m_pPackets->Pop();
162
        ASSERT(pPacket);
163 164 165 166 167 168 169 170 171 172 173
        if (prefillCount >= m_iInitFill) {
          HandlePacket(pPacket);
        } else {
          if (!m_pHandler->HandlePrefillPacket(pPacket)) {
            HandlePacket(pPacket);
            m_pHandler->PrefillComplete();
            prefillCount = m_iInitFill+1; // make sure we don't do any more prefilling
          } else if (++prefillCount >= m_iInitFill) {
            m_pHandler->PrefillComplete();
          }
        }
174
      }
175
    }
176
    else
177
    {
178 179
      for(int i = 0; i < iVectorSize;  i++)
      {
180
        pPacket = m_pPackets->Pop();
181 182 183 184 185
        ASSERT(pPacket);
        if (pPacket->RefCount()>0)
          m_pTsProvider->ReleasePacket(pPacket);
      }
    }
186
  }
187 188 189 190 191 192 193 194 195 196 197

  if(!m_bStop)
  {
    LogDbg(m_hLog, "Stopping converter by callback for program " + strPgrmName);
    m_bStop = true;
    C_Event cEvent(m_pBroadcast->GetInput()->GetName());
    cEvent.SetCode(EOF_EVENT);
    cEvent.SetBroadcast(m_pBroadcast);
    m_pEventHandler->HandleEvent(cEvent);
  }

198 199 200
  m_pHandler->PrefillComplete();
  delete m_pPackets;

201 202 203 204 205 206
  m_cResumeCond.Release();
  LogDbg(m_hLog, "Converter stopped for program " + strPgrmName);
}

void C_NormalTrickPlay::StopWork()
{
207 208 209 210
  // TODO
  // Should test the resumecond state before releasing it
  // debuggers like valgrind really don't like that
  // nitrox
211 212
  m_cResumeCond.Release();
  C_TrickPlay::StopWork();
213
  m_pHandler->Shutdown();
214 215 216 217 218 219 220 221
}

void C_NormalTrickPlay::InitWork()
{
  C_TrickPlay::InitWork();

  if (m_iInitFill < 1)
    m_iInitFill = 1;
222

223 224
  // Fill the buffer
  int iRc = NO_ERR;
225
  int iVectorSize = 0;
226

227 228
  m_pPackets = new C_Fifo<C_TsPacket>(700);
  m_pHandler->PrefillStart();
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
}

void C_NormalTrickPlay::CleanWork()
{
  m_pConverter->CleanWork();
}

// TrickPlay functionality
void C_NormalTrickPlay::Resume()
{
  C_TrickPlay::Resume();
  if (m_iRequestTrickPlayStatus == TRICKPLAY_PLAY)
  {
    m_cResumeCond.Protect();
    m_cResumeCond.Signal();
  }
}

void C_NormalTrickPlay::Suspend()
{
  C_TrickPlay::Suspend();    
}

void C_NormalTrickPlay::Forward(int speed)
{
  C_TrickPlay::Forward(speed);    
}

void C_NormalTrickPlay::Rewind(int speed)
{
  C_TrickPlay::Rewind(speed);    
}