|
1 /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #if !defined(RtspMediaResource_h_) |
|
7 #define RtspMediaResource_h_ |
|
8 |
|
9 #include "MediaResource.h" |
|
10 |
|
11 namespace mozilla { |
|
12 |
|
13 class RtspTrackBuffer; |
|
14 |
|
15 /* RtspMediaResource |
|
16 * RtspMediaResource provides an interface to deliver and control RTSP media |
|
17 * data to RtspDecoder. |
|
18 * |
|
19 * RTSP Flow Start vs HTTP Flow Start: |
|
20 * For HTTP (and files stored on disk), once the channel is created and response |
|
21 * data is available, HTMLMediaElement::MediaLoadListener::OnStartRequest is |
|
22 * called. (Note, this is an asynchronous call following channel->AsyncOpen). |
|
23 * The decoder and MediaResource are set up to talk to each other: |
|
24 * InitializeDecoderForChannel and FinishDecoderSetup. |
|
25 * RtspMediaResource is different from this, in that FinishDecoderSetup is |
|
26 * postponed until after the initial connection with the server is made. |
|
27 * RtspController, owned by RtspMediaResource, provides the interface to setup |
|
28 * the connection, and calls RtspMediaResource::Listener::OnConnected |
|
29 * (from nsIStreamingProtocolListener). FinishDecoderSetup is then called to |
|
30 * connect RtspMediaResource with RtspDecoder and allow HTMLMediaElement to |
|
31 * request playback etc. |
|
32 * |
|
33 * Playback: |
|
34 * When the user presses play/pause, HTMLMediaElement::Play/::Pause is called, |
|
35 * subsequently making calls to the decoder state machine. Upon these state |
|
36 * changes, the decoder is told to start reading and decoding data. This causes |
|
37 * the nsIStreamingMediaController object to send play/pause commands to the |
|
38 * server. |
|
39 * Data is then delivered to the host and eventually written to the |
|
40 * RtspTrackBuffer objects. Note that RtspMediaResource does not know about the |
|
41 * play or pause state. It only knows about the data written into its buffers. |
|
42 * |
|
43 * Data Structures and Flow: |
|
44 * Unlike HTTP, RTSP provides separate streams for audio and video. |
|
45 * As such, it creates two RtspTrackBuffer objects for the audio and video data. |
|
46 * Data is read using the function ReadFrameFromTrack. These buffer objects are |
|
47 * ring buffers, implying that data from the network may be discarded if the |
|
48 * decoder cannot read at a high enough rate. |
|
49 * |
|
50 * Data is delivered via RtspMediaResource::Listener::OnMediaDataAvailable. |
|
51 * This Listener implements nsIStreamingProtocolListener, and writes the data to |
|
52 * the appropriate RtspTrackBuffer. The decoder then reads the data by calling |
|
53 * RtspMediaResource::ReadFrameFromTrack. Note that the decoder and decode |
|
54 * thread will be blocked until data is available in one of the two buffers. |
|
55 * |
|
56 * Seeking: |
|
57 * Since the frame data received after seek is not continuous with existing |
|
58 * frames in RtspTrackBuffer, the buffer must be cleared. If we don't clear the |
|
59 * old frame data in RtspTrackBuffer, the decoder's behavior will be |
|
60 * unpredictable. So we add |mFrameType| in RtspTrackBuffer to do this: |
|
61 * When we are seeking, the mFrameType flag is set, and RtspTrackBuffer will |
|
62 * drop the incoming data until the RTSP server completes the seek operation. |
|
63 * Note: seeking for RTSP is carried out based on sending the seek time to the |
|
64 * server, unlike HTTP in which the seek time is converted to a byte offset. |
|
65 * Thus, RtspMediaResource has a SeekTime function which should be called |
|
66 * instead of Seek. |
|
67 * */ |
|
68 class RtspMediaResource : public BaseMediaResource |
|
69 { |
|
70 public: |
|
71 RtspMediaResource(MediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI, |
|
72 const nsACString& aContentType); |
|
73 virtual ~RtspMediaResource(); |
|
74 |
|
75 // The following methods can be called on any thread. |
|
76 |
|
77 // Get the RtspMediaResource pointer if this MediaResource is a |
|
78 // RtspMediaResource. For calling Rtsp specific functions. |
|
79 virtual RtspMediaResource* GetRtspPointer() MOZ_OVERRIDE MOZ_FINAL { |
|
80 return this; |
|
81 } |
|
82 |
|
83 // Returns the nsIStreamingProtocolController in the RtspMediaResource. |
|
84 // RtspMediaExtractor: request it to get mime type for creating decoder. |
|
85 // RtspOmxDecoder: request it to send play/pause commands to RTSP server. |
|
86 // The lifetime of mMediaStreamController is controlled by RtspMediaResource |
|
87 // because the RtspMediaExtractor and RtspOmxDecoder won't hold the reference. |
|
88 nsIStreamingProtocolController* GetMediaStreamController() { |
|
89 return mMediaStreamController; |
|
90 } |
|
91 |
|
92 virtual bool IsRealTime() MOZ_OVERRIDE { |
|
93 return mRealTime; |
|
94 } |
|
95 |
|
96 // The following methods can be called on any thread except main thread. |
|
97 |
|
98 // Read data from track. |
|
99 // Parameters: |
|
100 // aToBuffer, aToBufferSize: buffer pointer and buffer size. |
|
101 // aReadCount: output actual read bytes. |
|
102 // aFrameTime: output frame time stamp. |
|
103 // aFrameSize: actual data size in track. |
|
104 nsresult ReadFrameFromTrack(uint8_t* aBuffer, uint32_t aBufferSize, |
|
105 uint32_t aTrackIdx, uint32_t& aBytes, |
|
106 uint64_t& aTime, uint32_t& aFrameSize); |
|
107 |
|
108 // Seek to the given time offset |
|
109 nsresult SeekTime(int64_t aOffset); |
|
110 |
|
111 // dummy |
|
112 virtual nsresult ReadAt(int64_t aOffset, char* aBuffer, |
|
113 uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE{ |
|
114 return NS_ERROR_FAILURE; |
|
115 } |
|
116 // dummy |
|
117 virtual void SetReadMode(MediaCacheStream::ReadMode aMode) MOZ_OVERRIDE {} |
|
118 // dummy |
|
119 virtual void SetPlaybackRate(uint32_t aBytesPerSecond) MOZ_OVERRIDE {} |
|
120 // dummy |
|
121 virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) |
|
122 MOZ_OVERRIDE { |
|
123 return NS_OK; |
|
124 } |
|
125 // dummy |
|
126 virtual nsresult Seek(int32_t aWhence, int64_t aOffset) MOZ_OVERRIDE { |
|
127 return NS_OK; |
|
128 } |
|
129 // dummy |
|
130 virtual void StartSeekingForMetadata() MOZ_OVERRIDE {} |
|
131 // dummy |
|
132 virtual void EndSeekingForMetadata() MOZ_OVERRIDE {} |
|
133 // dummy |
|
134 virtual int64_t Tell() MOZ_OVERRIDE { return 0; } |
|
135 |
|
136 // Any thread |
|
137 virtual void Pin() MOZ_OVERRIDE {} |
|
138 virtual void Unpin() MOZ_OVERRIDE {} |
|
139 |
|
140 // dummy |
|
141 virtual bool IsSuspendedByCache() MOZ_OVERRIDE { return false; } |
|
142 |
|
143 virtual bool IsSuspended() MOZ_OVERRIDE { return false; } |
|
144 virtual bool IsTransportSeekable() MOZ_OVERRIDE { return true; } |
|
145 // dummy |
|
146 virtual double GetDownloadRate(bool* aIsReliable) MOZ_OVERRIDE { return 0; } |
|
147 |
|
148 virtual int64_t GetLength() MOZ_OVERRIDE { |
|
149 if (mRealTime) { |
|
150 return -1; |
|
151 } |
|
152 return 0; |
|
153 } |
|
154 |
|
155 // dummy |
|
156 virtual int64_t GetNextCachedData(int64_t aOffset) MOZ_OVERRIDE { return 0; } |
|
157 // dummy |
|
158 virtual int64_t GetCachedDataEnd(int64_t aOffset) MOZ_OVERRIDE { return 0; } |
|
159 // dummy |
|
160 virtual bool IsDataCachedToEndOfResource(int64_t aOffset) MOZ_OVERRIDE { |
|
161 return false; |
|
162 } |
|
163 // dummy |
|
164 nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) MOZ_OVERRIDE { |
|
165 return NS_ERROR_FAILURE; |
|
166 } |
|
167 |
|
168 // The following methods can be called on main thread only. |
|
169 |
|
170 virtual nsresult Open(nsIStreamListener** aStreamListener) MOZ_OVERRIDE; |
|
171 virtual nsresult Close() MOZ_OVERRIDE; |
|
172 virtual void Suspend(bool aCloseImmediately) MOZ_OVERRIDE; |
|
173 virtual void Resume() MOZ_OVERRIDE; |
|
174 virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() MOZ_OVERRIDE; |
|
175 virtual bool CanClone() MOZ_OVERRIDE { |
|
176 return false; |
|
177 } |
|
178 virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) |
|
179 MOZ_OVERRIDE { |
|
180 return nullptr; |
|
181 } |
|
182 // dummy |
|
183 virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, |
|
184 uint32_t aCount) MOZ_OVERRIDE { |
|
185 return NS_ERROR_FAILURE; |
|
186 } |
|
187 |
|
188 virtual size_t SizeOfExcludingThis( |
|
189 MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; |
|
190 |
|
191 virtual size_t SizeOfIncludingThis( |
|
192 MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE { |
|
193 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); |
|
194 } |
|
195 |
|
196 // Listener implements nsIStreamingProtocolListener as |
|
197 // mMediaStreamController's callback function. |
|
198 // It holds RtspMediaResource reference to notify the connection status and |
|
199 // data arrival. The Revoke function releases the reference when |
|
200 // RtspMediaResource::OnDisconnected is called. |
|
201 class Listener MOZ_FINAL : public nsIInterfaceRequestor, |
|
202 public nsIStreamingProtocolListener |
|
203 { |
|
204 public: |
|
205 Listener(RtspMediaResource* aResource) : mResource(aResource) {} |
|
206 ~Listener() {} |
|
207 |
|
208 NS_DECL_ISUPPORTS |
|
209 NS_DECL_NSIINTERFACEREQUESTOR |
|
210 NS_DECL_NSISTREAMINGPROTOCOLLISTENER |
|
211 |
|
212 void Revoke(); |
|
213 |
|
214 private: |
|
215 nsRefPtr<RtspMediaResource> mResource; |
|
216 }; |
|
217 friend class Listener; |
|
218 |
|
219 protected: |
|
220 // Main thread access only. |
|
221 // These are called on the main thread by Listener. |
|
222 NS_DECL_NSISTREAMINGPROTOCOLLISTENER |
|
223 |
|
224 nsRefPtr<Listener> mListener; |
|
225 |
|
226 private: |
|
227 bool IsVideoEnabled(); |
|
228 bool IsVideo(uint8_t tracks, nsIStreamingProtocolMetaData *meta); |
|
229 // These two members are created at |RtspMediaResource::OnConnected|. |
|
230 nsCOMPtr<nsIStreamingProtocolController> mMediaStreamController; |
|
231 nsTArray<nsAutoPtr<RtspTrackBuffer>> mTrackBuffer; |
|
232 |
|
233 // A flag that indicates the |RtspMediaResource::OnConnected| has already been |
|
234 // called. |
|
235 bool mIsConnected; |
|
236 // live stream |
|
237 bool mRealTime; |
|
238 }; |
|
239 |
|
240 } // namespace mozilla |
|
241 |
|
242 #endif |
|
243 |