2013-07-12 53 views
1

我在Ubuntu 12.04和live555的最後一個版本上使用QT5.02。在qt應用程序中實現live555的QT-C++錯誤

這是我的課(CameraStream.cpp)將讀取的RTSP流的:

#include "CameraStream.h" 
#include <DummySink.h> 
#include <ourRTSPClient.h> 
#include "liveMedia.hh" 
#include "BasicUsageEnvironment.hh" 

CameraStream::CameraStream(){ 
    eventLoopWatchVariable = 0; 

    // Begin by setting up our usage environment: 
    TaskScheduler* scheduler = BasicTaskScheduler::createNew(); 
    UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler); 

    openURL(*env, "argv[0]", "rtsp://[email protected]:1234/file.sdp"); 

    // All subsequent activity takes place within the event loop: 
    env->taskScheduler().doEventLoop(&eventLoopWatchVariable); 

} 

#define RTSP_CLIENT_VERBOSITY_LEVEL 1 

static unsigned rtspClientCount = 0; 

void CameraStream::openURL(UsageEnvironment& env, char const* progName, char const* rtspURL) { 

    RTSPClient* rtspClient = ourRTSPClient::createNew(env, rtspURL, RTSP_CLIENT_VERBOSITY_LEVEL, progName); 
    if (rtspClient == NULL) { 
     env << "Failed to create a RTSP client for URL \"" << rtspURL << "\": " << env.getResultMsg() << "\n"; 
     return; 
    } 

    ++rtspClientCount; 

    rtspClient->sendDescribeCommand(continueAfterDESCRIBE); 
} 


// Implementation of the RTSP 'response handlers': 

void CameraStream::continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode, char* resultString) { 
    do { 
     UsageEnvironment& env = rtspClient->envir(); // alias 
     StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias 

     if (resultCode != 0) { 
      env << *rtspClient << "Failed to get a SDP description: " << resultString << "\n"; 
      delete[] resultString; 
      break; 
     } 

     char* const sdpDescription = resultString; 
     env << *rtspClient << "Got a SDP description:\n" << sdpDescription << "\n"; 

     // Create a media session object from this SDP description: 
     scs.session = MediaSession::createNew(env, sdpDescription); 
     delete[] sdpDescription; // because we don't need it anymore 
     if (scs.session == NULL) { 
      env << *rtspClient << "Failed to create a MediaSession object from the SDP description: " << env.getResultMsg() << "\n"; 
      break; 
     } else if (!scs.session->hasSubsessions()) { 
      env << *rtspClient << "This session has no media subsessions (i.e., no \"m=\" lines)\n"; 
      break; 
     } 

     scs.iter = new MediaSubsessionIterator(*scs.session); 
     setupNextSubsession(rtspClient); 
     return; 
    } while (0); 

    // An unrecoverable error occurred with this stream. 
    shutdownStream(rtspClient); 
} 

// By default, we request that the server stream its data using RTP/UDP. 
// If, instead, you want to request that the server stream via RTP-over-TCP, change the following to True: 
#define REQUEST_STREAMING_OVER_TCP False 

void CameraStream::setupNextSubsession(RTSPClient* rtspClient) { 
    UsageEnvironment& env = rtspClient->envir(); // alias 
    StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias 

    scs.subsession = scs.iter->next(); 
    if (scs.subsession != NULL) { 
     if (!scs.subsession->initiate()) { 
      env << *rtspClient << "Failed to initiate the \"" << *scs.subsession << "\" subsession: " << env.getResultMsg() << "\n"; 
      setupNextSubsession(rtspClient); // give up on this subsession; go to the next one 
     } else { 
      env << *rtspClient << "Initiated the \"" << *scs.subsession 
      << "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n"; 

      // Continue setting up this subsession, by sending a RTSP "SETUP" command: 
      rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP, False, REQUEST_STREAMING_OVER_TCP); 
     } 
     return; 
    } 

    // We've finished setting up all of the subsessions. Now, send a RTSP "PLAY" command to start the streaming: 
    if (scs.session->absStartTime() != NULL) { 
     // Special case: The stream is indexed by 'absolute' time, so send an appropriate "PLAY" command: 
     rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY, scs.session->absStartTime(), scs.session->absEndTime()); 
    } else { 
     scs.duration = scs.session->playEndTime() - scs.session->playStartTime(); 
     rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY); 
    } 
} 

void CameraStream::continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString) { 
    do { 
     UsageEnvironment& env = rtspClient->envir(); // alias 
     StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias 

     if (resultCode != 0) { 
      env << *rtspClient << "Failed to set up the \"" << *scs.subsession << "\" subsession: " << resultString << "\n"; 
      break; 
     } 

     env << *rtspClient << "Set up the \"" << *scs.subsession 
     << "\" subsession (client ports " << scs.subsession->clientPortNum() << "-" << scs.subsession->clientPortNum()+1 << ")\n"; 

     // Having successfully setup the subsession, create a data sink for it, and call "startPlaying()" on it. 
     // (This will prepare the data sink to receive data; the actual flow of data from the client won't start happening until later, 
     // after we've sent a RTSP "PLAY" command.) 

     scs.subsession->sink = DummySink::createNew(env, *scs.subsession, rtspClient->url()); 
     // perhaps use your own custom "MediaSink" subclass instead 
     if (scs.subsession->sink == NULL) { 
      env << *rtspClient << "Failed to create a data sink for the \"" << *scs.subsession 
      << "\" subsession: " << env.getResultMsg() << "\n"; 
      break; 
     } 

     env << *rtspClient << "Created a data sink for the \"" << *scs.subsession << "\" subsession\n"; 
     scs.subsession->miscPtr = rtspClient; // a hack to let subsession handle functions get the "RTSPClient" from the subsession 
     scs.subsession->sink->startPlaying(*(scs.subsession->readSource()), 
             subsessionAfterPlaying, scs.subsession); 
    // Also set a handler to be called if a RTCP "BYE" arrives for this subsession: 
     if (scs.subsession->rtcpInstance() != NULL) { 
      scs.subsession->rtcpInstance()->setByeHandler(subsessionByeHandler, scs.subsession); 
     } 
    } while (0); 
    delete[] resultString; 

    // Set up the next subsession, if any: 
    setupNextSubsession(rtspClient); 
} 

void CameraStream::continueAfterPLAY(RTSPClient* rtspClient, int resultCode, char* resultString) { 
    Boolean success = False; 

    do { 
     UsageEnvironment& env = rtspClient->envir(); // alias 
     StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias 

     if (resultCode != 0) { 
      env << *rtspClient << "Failed to start playing session: " << resultString << "\n"; 
      break; 
     } 

     // Set a timer to be handled at the end of the stream's expected duration (if the stream does not already signal its end 
     // using a RTCP "BYE"). This is optional. If, instead, you want to keep the stream active - e.g., so you can later 
     // 'seek' back within it and do another RTSP "PLAY" - then you can omit this code. 
     // (Alternatively, if you don't want to receive the entire stream, you could set this timer for some shorter value.) 
     if (scs.duration > 0) { 
      unsigned const delaySlop = 2; // number of seconds extra to delay, after the stream's expected duration. (This is optional.) 
      scs.duration += delaySlop; 
      unsigned uSecsToDelay = (unsigned)(scs.duration*1000000); 
      scs.streamTimerTask = env.taskScheduler().scheduleDelayedTask(uSecsToDelay, (TaskFunc*)streamTimerHandler, rtspClient); 
     } 

     env << *rtspClient << "Started playing session"; 
     if (scs.duration > 0) { 
      env << " (for up to " << scs.duration << " seconds)"; 
     } 
     env << "...\n"; 

     success = True; 
    } while (0); 
    delete[] resultString; 

    if (!success) { 
     // An unrecoverable error occurred with this stream. 
     shutdownStream(rtspClient); 
    } 
} 


// Implementation of the other event handlers: 

void CameraStream::subsessionAfterPlaying(void* clientData) { 
    MediaSubsession* subsession = (MediaSubsession*)clientData; 
    RTSPClient* rtspClient = (RTSPClient*)(subsession->miscPtr); 

    // Begin by closing this subsession's stream: 
    Medium::close(subsession->sink); 
    subsession->sink = NULL; 

    // Next, check whether *all* subsessions' streams have now been closed: 
    MediaSession& session = subsession->parentSession(); 
    MediaSubsessionIterator iter(session); 
    while ((subsession = iter.next()) != NULL) { 
     if (subsession->sink != NULL) return; // this subsession is still active 
    } 

    // All subsessions' streams have now been closed, so shutdown the client: 
    shutdownStream(rtspClient); 
} 

void CameraStream::subsessionByeHandler(void* clientData) { 
    MediaSubsession* subsession = (MediaSubsession*)clientData; 
    RTSPClient* rtspClient = (RTSPClient*)subsession->miscPtr; 
    UsageEnvironment& env = rtspClient->envir(); // alias 

    env << *rtspClient << "Received RTCP \"BYE\" on \"" << *subsession << "\" subsession\n"; 

    // Now act as if the subsession had closed: 
    subsessionAfterPlaying(subsession); 
} 

void CameraStream::streamTimerHandler(void* clientData) { 
    ourRTSPClient* rtspClient = (ourRTSPClient*)clientData; 
    StreamClientState& scs = rtspClient->scs; // alias 

    scs.streamTimerTask = NULL; 

    // Shut down the stream: 
    shutdownStream(rtspClient); 
} 

void CameraStream::shutdownStream(RTSPClient* rtspClient, int exitCode) { 
    UsageEnvironment& env = rtspClient->envir(); // alias 
    StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias 

    // First, check whether any subsessions have still to be closed: 
    if (scs.session != NULL) { 
     Boolean someSubsessionsWereActive = False; 
     MediaSubsessionIterator iter(*scs.session); 
     MediaSubsession* subsession; 

     while ((subsession = iter.next()) != NULL) { 
      if (subsession->sink != NULL) { 
       Medium::close(subsession->sink); 
       subsession->sink = NULL; 

       if (subsession->rtcpInstance() != NULL) { 
        subsession->rtcpInstance()->setByeHandler(NULL, NULL); // in case the server sends a RTCP "BYE" while handling "TEARDOWN" 
       } 

       someSubsessionsWereActive = True; 
      } 
     } 

     if (someSubsessionsWereActive) { 
      // Send a RTSP "TEARDOWN" command, to tell the server to shutdown the stream. 
      // Don't bother handling the response to the "TEARDOWN". 
      rtspClient->sendTeardownCommand(*scs.session, NULL); 
     } 
    } 

    env << *rtspClient << "Closing the stream.\n"; 
    Medium::close(rtspClient); 
    // Note that this will also cause this stream's "StreamClientState" structure to get reclaimed. 

    if (--rtspClientCount == 0) { 
     // The final stream has ended, so exit the application now. 
     // (Of course, if you're embedding this code into your own application, you might want to comment this out, 
     // and replace it with "eventLoopWatchVariable = 1;", so that we leave the LIVE555 event loop, and continue running "main()".) 
     exit(exitCode); 
    } 
} 

UsageEnvironment& operator<<(UsageEnvironment& env, const RTSPClient& rtspClient) { 
    return env << "[URL:\"" << rtspClient.url() << "\"]: "; 
} 

UsageEnvironment& operator<<(UsageEnvironment& env, const MediaSubsession& subsession) { 
    return env << subsession.mediumName() << "/" << subsession.codecName(); 
} 

這是文件頭(CameraStream.h):

#ifndef CAMERASTREAM_H 
#define CAMERASTREAM_H 

#include <liveMedia.hh> 


class CameraStream 
{ 
public: 
    CameraStream(); 

private: 
    // Forward function definitions: 

    // RTSP 'response handlers': 
    void continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode, char* resultString); 
    void continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString); 
    void continueAfterPLAY(RTSPClient* rtspClient, int resultCode, char* resultString); 

    // Other event handler functions: 
    void subsessionAfterPlaying(void* clientData); // called when a stream's subsession (e.g., audio or video substream) ends 
    void subsessionByeHandler(void* clientData); // called when a RTCP "BYE" is received for a subsession 
    void streamTimerHandler(void* clientData); 
    // called at the end of a stream's expected duration (if the stream has not already signaled its end using a RTCP "BYE") 

    // The main streaming routine (for each "rtsp://" URL): 
    void openURL(UsageEnvironment& env, char const* progName, char const* rtspURL); 

    // Used to iterate through each stream's 'subsessions', setting up each one: 
    void setupNextSubsession(RTSPClient* rtspClient); 

    // Used to shut down and close a stream (including its "RTSPClient" object): 
    void shutdownStream(RTSPClient* rtspClient, int exitCode = 1); 

    char eventLoopWatchVariable; 
}; 
// A function that outputs a string that identifies each stream (for debugging output). Modify this if you wish: 
UsageEnvironment& operator<<(UsageEnvironment& env, const RTSPClient& rtspClient) ; 

// A function that outputs a string that identifies each subsession (for debugging output). Modify this if you wish: 
UsageEnvironment& operator<<(UsageEnvironment& env, const MediaSubsession& subsession); 


#endif // CAMERASTREAM_H 

當我嘗試編譯我得到以下錯誤:

../CameraProva/CameraStream.cpp: In member function 'void CameraStream::setupNextSubsession(RTSPClient*)': 
../CameraProva/CameraStream.cpp:110:112: error: no matching function for call to 'RTSPClient::sendSetupCommand(MediaSubsession&, <unresolved overloaded function type>, const Boolean&, const Boolean&)' 

../CameraProva/CameraStream.cpp:110:112: note: candidate is: 
../include/RTSPClient.hh:85:12: note: unsigned int RTSPClient::sendSetupCommand(MediaSubsession&, void (*)(RTSPClient*, int, char*), Boolean, Boolean, Boolean, Authenticator*) 

../include/RTSPClient.hh:85:12: note: no known conversion for argument 2 from '<unresolved overloaded function type>' to 'void (*)(RTSPClient*, int, char*)' 
../CameraProva/CameraStream.cpp:118:124: error: no matching function for call to 'RTSPClient::sendPlayCommand(MediaSession&, <unresolved overloaded function type>, char*, char*)' 

../CameraProva/CameraStream.cpp:118:124: note: candidates are: 
../include/RTSPClient.hh:93:12: note: unsigned int RTSPClient::sendPlayCommand(MediaSession&, void (*)(RTSPClient*, int, char*), double, double, float, Authenticator*) 

../include/RTSPClient.hh:93:12: note: no known conversion for argument 2 from '<unresolved overloaded function type>' to 'void (*)(RTSPClient*, int, char*)' 
../include/RTSPClient.hh:99:12: note: unsigned int RTSPClient::sendPlayCommand(MediaSubsession&, void (*)(RTSPClient*, int, char*), double, double, float, Authenticator*) 

../include/RTSPClient.hh:99:12: note: no known conversion for argument 1 from 'MediaSession' to 'MediaSubsession&' 
../include/RTSPClient.hh:109:12: note: unsigned int RTSPClient::sendPlayCommand(MediaSession&, void (*)(RTSPClient*, int, char*), const char*, const char*, float, Authenticator*) 

../include/RTSPClient.hh:109:12: note: no known conversion for argument 2 from '<unresolved overloaded function type>' to 'void (*)(RTSPClient*, int, char*)' 
../include/RTSPClient.hh:112:12: note: unsigned int RTSPClient::sendPlayCommand(MediaSubsession&, void (*)(RTSPClient*, int, char*), const char*, const char*, float, Authenticator*) 

../include/RTSPClient.hh:112:12: note: no known conversion for argument 1 from 'MediaSession' to 'MediaSubsession&' 
../CameraProva/CameraStream.cpp:121:68: error: no matching function for call to 'RTSPClient::sendPlayCommand(MediaSession&, <unresolved overloaded function type>)' 
../CameraProva/CameraStream.cpp:121:68: note: candidates are: 
../include/RTSPClient.hh:93:12: note: unsigned int RTSPClient::sendPlayCommand(MediaSession&, void (*)(RTSPClient*, int, char*), double, double, float, Authenticator*) 

../include/RTSPClient.hh:93:12: note: no known conversion for argument 2 from '<unresolved overloaded function type>' to 'void (*)(RTSPClient*, int, char*)' 
../include/RTSPClient.hh:99:12: note: unsigned int RTSPClient::sendPlayCommand(MediaSubsession&, void (*)(RTSPClient*, int, char*), double, double, float, Authenticator*) 

../include/RTSPClient.hh:99:12: note: no known conversion for argument 1 from 'MediaSession' to 'MediaSubsession&' 
../include/RTSPClient.hh:109:12: note: unsigned int RTSPClient::sendPlayCommand(MediaSession&, void (*)(RTSPClient*, int, char*), const char*, const char*, float, Authenticator*) 

../include/RTSPClient.hh:109:12: note: candidate expects 6 arguments, 2 provided 
../include/RTSPClient.hh:112:12: note: unsigned int RTSPClient::sendPlayCommand(MediaSubsession&, void (*)(RTSPClient*, int, char*), const char*, const char*, float, Authenticator*) 

../include/RTSPClient.hh:112:12: note: candidate expects 6 arguments, 2 provided 
../CameraProva/CameraStream.cpp: In member function 'void CameraStream::continueAfterSETUP(RTSPClient*, int, char*)': 
../CameraProva/CameraStream.cpp:153:82: error: no matching function for call to 'MediaSink::startPlaying(FramedSource&, <unresolved overloaded function type>, MediaSubsession*&)' 

../CameraProva/CameraStream.cpp:153:82: note: candidate is: 
../include/MediaSink.hh:34:11: note: Boolean MediaSink::startPlaying(MediaSource&, void (*)(void*), void*) 
../include/MediaSink.hh:34:11: note: no known conversion for argument 2 from '<unresolved overloaded function type>' to 'void (*)(void*)' 

../CameraProva/CameraStream.cpp:156:95: error: no matching function for call to 'RTCPInstance::setByeHandler(<unresolved overloaded function type>, MediaSubsession*&)' 
../CameraProva/CameraStream.cpp:156:95: note: candidate is: 
../include/RTCP.hh:59:8: note: void RTCPInstance::setByeHandler(void (*)(void*), void*, Boolean) 

../include/RTCP.hh:59:8: note: no known conversion for argument 1 from '<unresolved overloaded function type>' to 'void (*)(void*)' 
../CameraProva/CameraStream.cpp: In member function 'void CameraStream::continueAfterPLAY(RTSPClient*, int, char*)': 
../CameraProva/CameraStream.cpp:185:100: error: invalid use of member (did you forget the '&' ?) 

make: *** [CameraStream.o] Error 1 

我複製testRTSPClient的例子源代碼中的代碼蜂巢的live555。我做錯了什麼?有任何使用live555的QT應用程序的例子?

回答

0

您需要將回調放入RTSPClient類或更改sendSetupCommand和sendPlayCommand(以及可能其他人)的函數簽名以獲取CameraStream類中的函數指針。