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 "VideoFormats.h"
22
23#include <media/stagefright/foundation/AHandler.h>
24#include <media/stagefright/foundation/ANetworkSession.h>
25
26#include <netinet/in.h>
27
28namespace android {
29
30struct IHDCP;
31struct IRemoteDisplayClient;
32struct ParsedMessage;
33
34// Represents the RTSP server acting as a wifi display source.
35// Manages incoming connections, sets up Playback sessions as necessary.
36struct 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
50protected:
51    virtual ~WifiDisplaySource();
52    virtual void onMessageReceived(const sp<AMessage> &msg);
53
54private:
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    VideoFormats::ProfileType mChosenVideoProfile;
135    VideoFormats::LevelType mChosenVideoLevel;
136
137    bool mSinkSupportsAudio;
138
139    bool mUsingPCMAudio;
140    int32_t mClientSessionID;
141
142    struct ClientInfo {
143        AString mRemoteIP;
144        AString mLocalIP;
145        int32_t mLocalPort;
146        int32_t mPlaybackSessionID;
147        sp<PlaybackSession> mPlaybackSession;
148    };
149    ClientInfo mClientInfo;
150
151    bool mReaperPending;
152
153    int32_t mNextCSeq;
154
155    KeyedVector<ResponseID, HandleRTSPResponseFunc> mResponseHandlers;
156
157    // HDCP specific section >>>>
158    bool mUsingHDCP;
159    bool mIsHDCP2_0;
160    int32_t mHDCPPort;
161    sp<IHDCP> mHDCP;
162    sp<HDCPObserver> mHDCPObserver;
163
164    bool mHDCPInitializationComplete;
165    bool mSetupTriggerDeferred;
166
167    bool mPlaybackSessionEstablished;
168
169    status_t makeHDCP();
170    // <<<< HDCP specific section
171
172    status_t sendM1(int32_t sessionID);
173    status_t sendM3(int32_t sessionID);
174    status_t sendM4(int32_t sessionID);
175
176    enum TriggerType {
177        TRIGGER_SETUP,
178        TRIGGER_TEARDOWN,
179        TRIGGER_PAUSE,
180        TRIGGER_PLAY,
181    };
182
183    // M5
184    status_t sendTrigger(int32_t sessionID, TriggerType triggerType);
185
186    status_t sendM16(int32_t sessionID);
187
188    status_t onReceiveM1Response(
189            int32_t sessionID, const sp<ParsedMessage> &msg);
190
191    status_t onReceiveM3Response(
192            int32_t sessionID, const sp<ParsedMessage> &msg);
193
194    status_t onReceiveM4Response(
195            int32_t sessionID, const sp<ParsedMessage> &msg);
196
197    status_t onReceiveM5Response(
198            int32_t sessionID, const sp<ParsedMessage> &msg);
199
200    status_t onReceiveM16Response(
201            int32_t sessionID, const sp<ParsedMessage> &msg);
202
203    void registerResponseHandler(
204            int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func);
205
206    status_t onReceiveClientData(const sp<AMessage> &msg);
207
208    status_t onOptionsRequest(
209            int32_t sessionID,
210            int32_t cseq,
211            const sp<ParsedMessage> &data);
212
213    status_t onSetupRequest(
214            int32_t sessionID,
215            int32_t cseq,
216            const sp<ParsedMessage> &data);
217
218    status_t onPlayRequest(
219            int32_t sessionID,
220            int32_t cseq,
221            const sp<ParsedMessage> &data);
222
223    status_t onPauseRequest(
224            int32_t sessionID,
225            int32_t cseq,
226            const sp<ParsedMessage> &data);
227
228    status_t onTeardownRequest(
229            int32_t sessionID,
230            int32_t cseq,
231            const sp<ParsedMessage> &data);
232
233    status_t onGetParameterRequest(
234            int32_t sessionID,
235            int32_t cseq,
236            const sp<ParsedMessage> &data);
237
238    status_t onSetParameterRequest(
239            int32_t sessionID,
240            int32_t cseq,
241            const sp<ParsedMessage> &data);
242
243    void sendErrorResponse(
244            int32_t sessionID,
245            const char *errorDetail,
246            int32_t cseq);
247
248    static void AppendCommonResponse(
249            AString *response, int32_t cseq, int32_t playbackSessionID = -1ll);
250
251    void scheduleReaper();
252    void scheduleKeepAlive(int32_t sessionID);
253
254    int32_t makeUniquePlaybackSessionID() const;
255
256    sp<PlaybackSession> findPlaybackSession(
257            const sp<ParsedMessage> &data, int32_t *playbackSessionID) const;
258
259    void finishStop();
260    void disconnectClientAsync();
261    void disconnectClient2();
262    void finishStopAfterDisconnectingClient();
263    void finishStop2();
264
265    void finishPlay();
266
267    DISALLOW_EVIL_CONSTRUCTORS(WifiDisplaySource);
268};
269
270}  // namespace android
271
272#endif  // WIFI_DISPLAY_SOURCE_H_
273