/*
#  $Id$
# -----------------------------------------------------------------------------
#  The part of 'VideoNEXT MediaClient SDK'
# -----------------------------------------------------------------------------
#  Author: Petrov Maxim, 03/04/2009
#  Edited by:
#  QA by:
#  Copyright: videoNEXT LLC
# -----------------------------------------------------------------------------
*/

#ifndef VN_RTSP_MEDIA_STREAM_PRODUCER_IMPL_H_
#define VN_RTSP_MEDIA_STREAM_PRODUCER_IMPL_H_

#include <list>
#include <string>
#include <map>


#include "VideoFrameConsumer.h"
#include "AudioFrameConsumer.h"
#include "GroupsockHelper.hh"
#include "MediaStreamProducerImpl.h" 
#include "AdaptiveUsageEnvironment.h" 


namespace videonext { namespace media {

class RTSPMediaStreamProducerImpl : public MediaStreamProducerImpl
{
    struct ClientData
    {
        ClientData(RTSPMediaStreamProducerImpl *mp_,
                   MediaSubsession *mediaSubsession_) 
           : mp(mp_), mediaSubsession(mediaSubsession_) {}
        RTSPMediaStreamProducerImpl *mp;
        MediaSubsession *mediaSubsession;
    };

public:
   RTSPMediaStreamProducerImpl(MediaStreamHandler *mediaStreamHandler, const std::string &url, 
                               unsigned cacheSize, unsigned streamId, 
                               bool streamOverTCP, unsigned bufferLen /*in msec*/, float speed = 1.f);

    virtual ~RTSPMediaStreamProducerImpl();
    
public:

   // Redefined virtual functions
   virtual void open();

   virtual void play();

   virtual void pause();
    
   virtual void setStepMode(bool value);    

   virtual void setSpeed(float speed);

   virtual void setJitterBufferLen(unsigned value);

   virtual void setPlayDirection(int value);

   virtual void changeState(STREAM_STATE, int errorCode = 0);

   virtual void moveToTimestamp(time_t time) { jumpToTimestamp(time); }

   virtual void teardown() {stop();}

   virtual bool isPlayingArchive() { return fPlayingArchive; }

   virtual bool isStepMode();

   virtual bool startRecording(const char* file_name, const std::map<std::string, std::string>& metadata);

   virtual bool endRecording(bool stop = false);

public:

   // Still not virtual but candidate too :)
   void setBandwidth(int value);


public:
   virtual void jumpToTimestamp(int value, bool mark = true);


protected:
    virtual void stop();
    virtual void resume();

private:    
    static void subsessionAfterPlaying(void* clientData);
    static void subsessionByeHandler(void* clientData);
    static void sessionAfterPlaying(void* clientData);
   
 
    bool startPlayingStreams();
    void shutdown();  
 
    bool setupStreams();
    
    void tearDownStreams();
    void closeMediaSinks();
    
    char* getOptionsResponse(char const* url);

    char* getSDPDescriptionFromURL(char const* url,
                      char const* username,
                      char const* password);

    Boolean clientSetupSubsession(MediaSubsession* subsession, Boolean streamUsingTCP);

    Boolean clientStartPlayingSession(MediaSession* session);

    Boolean clientTearDownSession(MediaSession* session);
                     
    Boolean clientPauseSession(MediaSession* session);

private:                                                                                                                                     
    virtual void noteLiveness();                                                                                                                     
    static void noteServerLiveness(void* );                                                                                                  
    static void livenessTimeoutTask(void* );                                                                                                 
    static void rtcpAPPHandler(void *clientData, unsigned char* name, unsigned char* data, unsigned dataSize);                               

    static void playHandlerTriggerProc(void* );               
    static void pauseHandlerTriggerProc(void *);
    static void stepModeHandlerTriggerProc(void *);

protected:
   AdaptiveUsageEnvironment* fEnv;
   TaskScheduler* fScheduler;
    
   char fStopFlag;
   bool fDidShutdown;
   bool fIsSessionPaused;
   Mutex fCacheMutex;

   AudioVideoPlaybackController *fPlaybackController;
   unsigned fFrameSinkBufferSize;
    
   RTSPClient* fRTSPClient;
   MediaSession* fSession;
        
   struct timeval fStartTime;
    
   bool fStepMode;    
   bool fPlayingArchive;
   bool fVideoTranscoded;

   std::list<ClientData*> fClientDataList;

   int fPlayDirection;
   TaskToken fLivenessCheckTask;

   Mutex fMutex;

   EventTriggerId fPlayTriggerId;
   EventTriggerId fStepModeTriggerId;
   EventTriggerId fPauseTriggerId;
};

}}

#endif

