diff --git a/media/libstagefright/include/ARTSPController.h b/media/libstagefright/include/ARTSPController.h index 55efd41c2ce59..2542e4ecc2097 100644 --- a/media/libstagefright/include/ARTSPController.h +++ b/media/libstagefright/include/ARTSPController.h @@ -19,6 +19,7 @@ #define A_RTSP_CONTROLLER_H_ #include +#include #include namespace android { @@ -38,12 +39,32 @@ struct ARTSPController : public MediaExtractor { virtual sp getTrackMetaData( size_t index, uint32_t flags); + void onMessageReceived(const sp &msg); + protected: virtual ~ARTSPController(); private: + enum { + kWhatConnectDone = 'cdon', + kWhatDisconnectDone = 'ddon', + }; + + enum State { + DISCONNECTED, + CONNECTED, + CONNECTING, + }; + + Mutex mLock; + Condition mCondition; + + State mState; + status_t mConnectionResult; + sp mLooper; sp mHandler; + sp > mReflector; DISALLOW_EVIL_CONSTRUCTORS(ARTSPController); }; diff --git a/media/libstagefright/rtsp/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp index 195323ed025e0..ceae3a676ea35 100644 --- a/media/libstagefright/rtsp/ARTSPController.cpp +++ b/media/libstagefright/rtsp/ARTSPController.cpp @@ -26,31 +26,57 @@ namespace android { ARTSPController::ARTSPController(const sp &looper) - : mLooper(looper) { + : mState(DISCONNECTED), + mLooper(looper) { + mReflector = new AHandlerReflector(this); + looper->registerHandler(mReflector); } ARTSPController::~ARTSPController() { + disconnect(); + mLooper->unregisterHandler(mReflector->id()); } status_t ARTSPController::connect(const char *url) { - if (mHandler != NULL) { + Mutex::Autolock autoLock(mLock); + + if (mState != DISCONNECTED) { return ERROR_ALREADY_CONNECTED; } + sp msg = new AMessage(kWhatConnectDone, mReflector->id()); + mHandler = new MyHandler(url, mLooper); - mHandler->connect(); - sleep(10); + mState = CONNECTING; - return OK; + mHandler->connect(msg); + + while (mState == CONNECTING) { + mCondition.wait(mLock); + } + + if (mState != CONNECTED) { + mHandler.clear(); + } + + return mConnectionResult; } void ARTSPController::disconnect() { - if (mHandler == NULL) { + Mutex::Autolock autoLock(mLock); + + if (mState != CONNECTED) { return; } - mHandler->disconnect(); + sp msg = new AMessage(kWhatDisconnectDone, mReflector->id()); + mHandler->disconnect(msg); + + while (mState == CONNECTED) { + mCondition.wait(mLock); + } + mHandler.clear(); } @@ -75,4 +101,31 @@ sp ARTSPController::getTrackMetaData( return mHandler->getPacketSource(index)->getFormat(); } +void ARTSPController::onMessageReceived(const sp &msg) { + switch (msg->what()) { + case kWhatConnectDone: + { + Mutex::Autolock autoLock(mLock); + + CHECK(msg->findInt32("result", &mConnectionResult)); + mState = (mConnectionResult == OK) ? CONNECTED : DISCONNECTED; + + mCondition.signal(); + break; + } + + case kWhatDisconnectDone: + { + Mutex::Autolock autoLock(mLock); + mState = DISCONNECTED; + mCondition.signal(); + break; + } + + default: + TRESPASS(); + break; + } +} + } // namespace android diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h index b19ad4851e2c4..90070c97b99fa 100644 --- a/media/libstagefright/rtsp/MyHandler.h +++ b/media/libstagefright/rtsp/MyHandler.h @@ -45,18 +45,21 @@ struct MyHandler : public AHandler { PRIORITY_HIGHEST); } - void connect() { + void connect(const sp &doneMsg) { + mDoneMsg = doneMsg; + mLooper->registerHandler(this); mLooper->registerHandler(mConn); (1 ? mNetLooper : mLooper)->registerHandler(mRTPConn); - sp reply = new AMessage('conn', id()); + sp reply = new AMessage('conn', id()); mConn->connect(mSessionURL.c_str(), reply); } - void disconnect() { - sp reply = new AMessage('disc', id()); - mConn->disconnect(reply); + void disconnect(const sp &doneMsg) { + mDoneMsg = doneMsg; + + (new AMessage('abor', id()))->post(); } virtual void onMessageReceived(const sp &msg) { @@ -250,8 +253,9 @@ struct MyHandler : public AHandler { CHECK_EQ(response->mStatusCode, 200u); - sp msg = new AMessage('abor', id()); - msg->post(60000000ll); + mDoneMsg->setInt32("result", OK); + mDoneMsg->post(); + mDoneMsg = NULL; } else { sp reply = new AMessage('disc', id()); mConn->disconnect(reply); @@ -301,6 +305,11 @@ struct MyHandler : public AHandler { case 'quit': { + if (mDoneMsg != NULL) { + mDoneMsg->setInt32("result", UNKNOWN_ERROR); + mDoneMsg->post(); + mDoneMsg = NULL; + } break; } @@ -380,6 +389,8 @@ private: }; Vector mTracks; + sp mDoneMsg; + void setupTrack(size_t index) { sp source = new APacketSource(mSessionDesc, index);