Home | History | Annotate | Download | only in source
      1 /*
      2  * Copyright 2012, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef WIFI_DISPLAY_SOURCE_H_
     18 
     19 #define WIFI_DISPLAY_SOURCE_H_
     20 
     21 #include "ANetworkSession.h"
     22 #include "VideoFormats.h"
     23 
     24 #include <media/stagefright/foundation/AHandler.h>
     25 
     26 #include <netinet/in.h>
     27 
     28 namespace android {
     29 
     30 struct IHDCP;
     31 struct IRemoteDisplayClient;
     32 struct ParsedMessage;
     33 
     34 // Represents the RTSP server acting as a wifi display source.
     35 // Manages incoming connections, sets up Playback sessions as necessary.
     36 struct WifiDisplaySource : public AHandler {
     37     static const unsigned kWifiDisplayDefaultPort = 7236;
     38 
     39     WifiDisplaySource(
     40             const sp<ANetworkSession> &netSession,
     41             const sp<IRemoteDisplayClient> &client,
     42             const char *path = NULL);
     43 
     44     status_t start(const char *iface);
     45     status_t stop();
     46 
     47     status_t pause();
     48     status_t resume();
     49 
     50 protected:
     51     virtual ~WifiDisplaySource();
     52     virtual void onMessageReceived(const sp<AMessage> &msg);
     53 
     54 private:
     55     struct PlaybackSession;
     56     struct HDCPObserver;
     57 
     58     enum State {
     59         INITIALIZED,
     60         AWAITING_CLIENT_CONNECTION,
     61         AWAITING_CLIENT_SETUP,
     62         AWAITING_CLIENT_PLAY,
     63         ABOUT_TO_PLAY,
     64         PLAYING,
     65         PLAYING_TO_PAUSED,
     66         PAUSED,
     67         PAUSED_TO_PLAYING,
     68         AWAITING_CLIENT_TEARDOWN,
     69         STOPPING,
     70         STOPPED,
     71     };
     72 
     73     enum {
     74         kWhatStart,
     75         kWhatRTSPNotify,
     76         kWhatStop,
     77         kWhatPause,
     78         kWhatResume,
     79         kWhatReapDeadClients,
     80         kWhatPlaybackSessionNotify,
     81         kWhatKeepAlive,
     82         kWhatHDCPNotify,
     83         kWhatFinishStop2,
     84         kWhatTeardownTriggerTimedOut,
     85     };
     86 
     87     struct ResponseID {
     88         int32_t mSessionID;
     89         int32_t mCSeq;
     90 
     91         bool operator<(const ResponseID &other) const {
     92             return mSessionID < other.mSessionID
     93                 || (mSessionID == other.mSessionID
     94                         && mCSeq < other.mCSeq);
     95         }
     96     };
     97 
     98     typedef status_t (WifiDisplaySource::*HandleRTSPResponseFunc)(
     99             int32_t sessionID, const sp<ParsedMessage> &msg);
    100 
    101     static const int64_t kReaperIntervalUs = 1000000ll;
    102 
    103     // We request that the dongle send us a "TEARDOWN" in order to
    104     // perform an orderly shutdown. We're willing to wait up to 2 secs
    105     // for this message to arrive, after that we'll force a disconnect
    106     // instead.
    107     static const int64_t kTeardownTriggerTimeouSecs = 2;
    108 
    109     static const int64_t kPlaybackSessionTimeoutSecs = 30;
    110 
    111     static const int64_t kPlaybackSessionTimeoutUs =
    112         kPlaybackSessionTimeoutSecs * 1000000ll;
    113 
    114     static const AString sUserAgent;
    115 
    116     State mState;
    117     VideoFormats mSupportedSourceVideoFormats;
    118     sp<ANetworkSession> mNetSession;
    119     sp<IRemoteDisplayClient> mClient;
    120     AString mMediaPath;
    121     struct in_addr mInterfaceAddr;
    122     int32_t mSessionID;
    123 
    124     uint32_t mStopReplyID;
    125 
    126     AString mWfdClientRtpPorts;
    127     int32_t mChosenRTPPort;  // extracted from "wfd_client_rtp_ports"
    128 
    129     bool mSinkSupportsVideo;
    130     VideoFormats mSupportedSinkVideoFormats;
    131 
    132     VideoFormats::ResolutionType mChosenVideoResolutionType;
    133     size_t mChosenVideoResolutionIndex;
    134 
    135     bool mSinkSupportsAudio;
    136 
    137     bool mUsingPCMAudio;
    138     int32_t mClientSessionID;
    139 
    140     struct ClientInfo {
    141         AString mRemoteIP;
    142         AString mLocalIP;
    143         int32_t mLocalPort;
    144         int32_t mPlaybackSessionID;
    145         sp<PlaybackSession> mPlaybackSession;
    146     };
    147     ClientInfo mClientInfo;
    148 
    149     bool mReaperPending;
    150 
    151     int32_t mNextCSeq;
    152 
    153     KeyedVector<ResponseID, HandleRTSPResponseFunc> mResponseHandlers;
    154 
    155     // HDCP specific section >>>>
    156     bool mUsingHDCP;
    157     bool mIsHDCP2_0;
    158     int32_t mHDCPPort;
    159     sp<IHDCP> mHDCP;
    160     sp<HDCPObserver> mHDCPObserver;
    161 
    162     bool mHDCPInitializationComplete;
    163     bool mSetupTriggerDeferred;
    164 
    165     bool mPlaybackSessionEstablished;
    166 
    167     status_t makeHDCP();
    168     // <<<< HDCP specific section
    169 
    170     status_t sendM1(int32_t sessionID);
    171     status_t sendM3(int32_t sessionID);
    172     status_t sendM4(int32_t sessionID);
    173 
    174     enum TriggerType {
    175         TRIGGER_SETUP,
    176         TRIGGER_TEARDOWN,
    177         TRIGGER_PAUSE,
    178         TRIGGER_PLAY,
    179     };
    180 
    181     // M5
    182     status_t sendTrigger(int32_t sessionID, TriggerType triggerType);
    183 
    184     status_t sendM16(int32_t sessionID);
    185 
    186     status_t onReceiveM1Response(
    187             int32_t sessionID, const sp<ParsedMessage> &msg);
    188 
    189     status_t onReceiveM3Response(
    190             int32_t sessionID, const sp<ParsedMessage> &msg);
    191 
    192     status_t onReceiveM4Response(
    193             int32_t sessionID, const sp<ParsedMessage> &msg);
    194 
    195     status_t onReceiveM5Response(
    196             int32_t sessionID, const sp<ParsedMessage> &msg);
    197 
    198     status_t onReceiveM16Response(
    199             int32_t sessionID, const sp<ParsedMessage> &msg);
    200 
    201     void registerResponseHandler(
    202             int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func);
    203 
    204     status_t onReceiveClientData(const sp<AMessage> &msg);
    205 
    206     status_t onOptionsRequest(
    207             int32_t sessionID,
    208             int32_t cseq,
    209             const sp<ParsedMessage> &data);
    210 
    211     status_t onSetupRequest(
    212             int32_t sessionID,
    213             int32_t cseq,
    214             const sp<ParsedMessage> &data);
    215 
    216     status_t onPlayRequest(
    217             int32_t sessionID,
    218             int32_t cseq,
    219             const sp<ParsedMessage> &data);
    220 
    221     status_t onPauseRequest(
    222             int32_t sessionID,
    223             int32_t cseq,
    224             const sp<ParsedMessage> &data);
    225 
    226     status_t onTeardownRequest(
    227             int32_t sessionID,
    228             int32_t cseq,
    229             const sp<ParsedMessage> &data);
    230 
    231     status_t onGetParameterRequest(
    232             int32_t sessionID,
    233             int32_t cseq,
    234             const sp<ParsedMessage> &data);
    235 
    236     status_t onSetParameterRequest(
    237             int32_t sessionID,
    238             int32_t cseq,
    239             const sp<ParsedMessage> &data);
    240 
    241     void sendErrorResponse(
    242             int32_t sessionID,
    243             const char *errorDetail,
    244             int32_t cseq);
    245 
    246     static void AppendCommonResponse(
    247             AString *response, int32_t cseq, int32_t playbackSessionID = -1ll);
    248 
    249     void scheduleReaper();
    250     void scheduleKeepAlive(int32_t sessionID);
    251 
    252     int32_t makeUniquePlaybackSessionID() const;
    253 
    254     sp<PlaybackSession> findPlaybackSession(
    255             const sp<ParsedMessage> &data, int32_t *playbackSessionID) const;
    256 
    257     void finishStop();
    258     void disconnectClientAsync();
    259     void disconnectClient2();
    260     void finishStopAfterDisconnectingClient();
    261     void finishStop2();
    262 
    263     void finishPlay();
    264 
    265     DISALLOW_EVIL_CONSTRUCTORS(WifiDisplaySource);
    266 };
    267 
    268 }  // namespace android
    269 
    270 #endif  // WIFI_DISPLAY_SOURCE_H_
    271