backout 29799f914cab, Bug 917642 - [Helix] Please update the helix blobs
[gecko.git] / content / media / RtspMediaResource.cpp
blob2c6c65d2d862518f425ab72f6c993a1650b2022a
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/DebugOnly.h"
9 #include "RtspMediaResource.h"
11 #include "MediaDecoder.h"
12 #include "mozilla/dom/HTMLMediaElement.h"
13 #include "mozilla/Monitor.h"
14 #include "mozilla/Preferences.h"
15 #include "nsIScriptSecurityManager.h"
16 #include "nsIStreamingProtocolService.h"
17 #include "nsServiceManagerUtils.h"
19 #ifdef PR_LOGGING
20 PRLogModuleInfo* gRtspMediaResourceLog;
21 #define LOG(msg, ...) PR_LOG(gRtspMediaResourceLog, PR_LOG_DEBUG, \
22 (msg, ##__VA_ARGS__))
23 // Debug logging macro with object pointer and class name.
24 #define RTSPMLOG(msg, ...) \
25 LOG("%p [RtspMediaResource]: " msg, this, ##__VA_ARGS__)
26 #else
27 #define LOG(msg, ...)
28 #define RTSPMLOG(msg, ...)
29 #endif
31 namespace mozilla {
33 /* class RtspTrackBuffer: a ring buffer implementation for audio/video track
34 * un-decoded data.
35 * The ring buffer is divided into BUFFER_SLOT_NUM slots,
36 * and each slot's size is fixed(mSlotSize).
37 * Even though the ring buffer is divided into fixed size slots, it still can
38 * store the data which size is larger than one slot size.
39 * */
40 #define BUFFER_SLOT_NUM 8192
41 #define BUFFER_SLOT_DEFAULT_SIZE 256
42 #define BUFFER_SLOT_MAX_SIZE 8192
43 #define BUFFER_SLOT_INVALID -1
44 #define BUFFER_SLOT_EMPTY 0
46 struct BufferSlotData {
47 int32_t mLength;
48 uint64_t mTime;
51 class RtspTrackBuffer
53 public:
54 RtspTrackBuffer(const char *aMonitor, int32_t aTrackIdx, uint32_t aSlotSize)
55 : mMonitor(aMonitor)
56 , mSlotSize(aSlotSize)
57 , mTotalBufferSize(BUFFER_SLOT_NUM * mSlotSize)
58 , mFrameType(0)
59 , mIsStarted(false) {
60 MOZ_COUNT_CTOR(RtspTrackBuffer);
61 #ifdef PR_LOGGING
62 mTrackIdx = aTrackIdx;
63 #endif
64 MOZ_ASSERT(mSlotSize < UINT32_MAX / BUFFER_SLOT_NUM);
65 mRingBuffer = new uint8_t[mTotalBufferSize];
66 Reset();
68 ~RtspTrackBuffer() {
69 MOZ_COUNT_DTOR(RtspTrackBuffer);
70 mRingBuffer = nullptr;
72 void Start() {
73 MonitorAutoLock monitor(mMonitor);
74 mIsStarted = true;
76 void Stop() {
77 MonitorAutoLock monitor(mMonitor);
78 mIsStarted = false;
81 // Read the data from mRingBuffer[mConsumerIdx*mSlotSize] into aToBuffer.
82 // If the aToBufferSize is smaller than mBufferSlotDataLength[mConsumerIdx],
83 // early return and set the aFrameSize to notify the reader the aToBuffer
84 // doesn't have enough space. The reader must realloc the aToBuffer if it
85 // wishes to read the data.
86 nsresult ReadBuffer(uint8_t* aToBuffer, uint32_t aToBufferSize,
87 uint32_t& aReadCount, uint64_t& aFrameTime,
88 uint32_t& aFrameSize);
89 // Write the data from aFromBuffer into mRingBuffer[mProducerIdx*mSlotSize].
90 void WriteBuffer(const char *aFromBuffer, uint32_t aWriteCount,
91 uint64_t aFrameTime, uint32_t aFrameType);
92 // Reset the mProducerIdx, mConsumerIdx, mBufferSlotDataLength[],
93 // mBufferSlotDataTime[].
94 void Reset();
96 // We should call SetFrameType first then reset().
97 // If we call reset() first, the queue may still has some "garbage" frame
98 // from another thread's |OnMediaDataAvailable| before |SetFrameType|.
99 void ResetWithFrameType(uint32_t aFrameType) {
100 SetFrameType(aFrameType);
101 Reset();
104 private:
105 // The FrameType is sync to nsIStreamingProtocolController.h
106 void SetFrameType(uint32_t aFrameType) {
107 MonitorAutoLock monitor(mMonitor);
108 mFrameType = mFrameType | aFrameType;
111 // A monitor lock to prevent racing condition.
112 Monitor mMonitor;
113 #ifdef PR_LOGGING
114 // Indicate the track number for Rtsp.
115 int32_t mTrackIdx;
116 #endif
117 // mProducerIdx: A slot index that we store data from
118 // nsIStreamingProtocolController.
119 // mConsumerIdx: A slot index that we read when decoder need(from OMX decoder).
120 int32_t mProducerIdx;
121 int32_t mConsumerIdx;
123 // Because each slot's size is fixed, we need an array to record the real
124 // data length and data time stamp.
125 // The value in mBufferSlotData[index].mLength represents:
126 // -1(BUFFER_SLOT_INVALID): The index of slot data is invalid, mConsumerIdx
127 // should go forward.
128 // 0(BUFFER_SLOT_EMPTY): The index slot is empty. mConsumerIdx should wait here.
129 // positive value: The index slot contains valid data and the value is data size.
130 BufferSlotData mBufferSlotData[BUFFER_SLOT_NUM];
132 // The ring buffer pointer.
133 nsAutoArrayPtr<uint8_t> mRingBuffer;
134 // Each slot's size.
135 uint32_t mSlotSize;
136 // Total mRingBuffer's total size.
137 uint32_t mTotalBufferSize;
138 // A flag that that indicate the incoming data should be dropped or stored.
139 // When we are seeking, the incoming data should be dropped.
140 // Bit definition in |nsIStreamingProtocolController.h|
141 uint32_t mFrameType;
143 // Set true/false when |Start()/Stop()| is called.
144 bool mIsStarted;
147 nsresult RtspTrackBuffer::ReadBuffer(uint8_t* aToBuffer, uint32_t aToBufferSize,
148 uint32_t& aReadCount, uint64_t& aFrameTime,
149 uint32_t& aFrameSize)
151 MonitorAutoLock monitor(mMonitor);
152 RTSPMLOG("ReadBuffer mTrackIdx %d mProducerIdx %d mConsumerIdx %d "
153 "mBufferSlotData[mConsumerIdx].mLength %d"
154 ,mTrackIdx ,mProducerIdx ,mConsumerIdx
155 ,mBufferSlotData[mConsumerIdx].mLength);
156 // Reader should skip the slots with mLength==BUFFER_SLOT_INVALID.
157 // The loop ends when
158 // 1. Read data successfully
159 // 2. Fail to read data due to aToBuffer's space
160 // 3. No data in this buffer
161 // 4. mIsStarted is not set
162 while (1) {
163 if (mBufferSlotData[mConsumerIdx].mLength > 0) {
164 // Check the aToBuffer space is enough for data copy.
165 if ((int32_t)aToBufferSize < mBufferSlotData[mConsumerIdx].mLength) {
166 aFrameSize = mBufferSlotData[mConsumerIdx].mLength;
167 break;
169 uint32_t slots = (mBufferSlotData[mConsumerIdx].mLength / mSlotSize) + 1;
170 // we have data, copy to aToBuffer
171 MOZ_ASSERT(mBufferSlotData[mConsumerIdx].mLength <=
172 (int32_t)((BUFFER_SLOT_NUM - mConsumerIdx) * mSlotSize));
173 memcpy(aToBuffer,
174 (void *)(&mRingBuffer[mSlotSize * mConsumerIdx]),
175 mBufferSlotData[mConsumerIdx].mLength);
177 aFrameSize = aReadCount = mBufferSlotData[mConsumerIdx].mLength;
178 aFrameTime = mBufferSlotData[mConsumerIdx].mTime;
179 RTSPMLOG("DataLength %d, data time %lld"
180 ,mBufferSlotData[mConsumerIdx].mLength
181 ,mBufferSlotData[mConsumerIdx].mTime);
182 // After reading the data, we set current index of mBufferSlotDataLength
183 // to BUFFER_SLOT_EMPTY to indicate these slots are free.
184 for (uint32_t i = mConsumerIdx; i < mConsumerIdx + slots; ++i) {
185 mBufferSlotData[i].mLength = BUFFER_SLOT_EMPTY;
186 mBufferSlotData[i].mTime = BUFFER_SLOT_EMPTY;
188 mConsumerIdx = (mConsumerIdx + slots) % BUFFER_SLOT_NUM;
189 break;
190 } else if (mBufferSlotData[mConsumerIdx].mLength == BUFFER_SLOT_INVALID) {
191 mConsumerIdx = (mConsumerIdx + 1) % BUFFER_SLOT_NUM;
192 RTSPMLOG("BUFFER_SLOT_INVALID move forward");
193 } else {
194 // No data, and disconnected.
195 if (!mIsStarted) {
196 return NS_ERROR_FAILURE;
198 // No data, the decode thread is blocked here until we receive
199 // OnMediaDataAvailable. The OnMediaDataAvailable will call WriteBuffer()
200 // to wake up the decode thread.
201 RTSPMLOG("monitor.Wait()");
202 monitor.Wait();
205 return NS_OK;
208 /* When we perform a WriteBuffer, we check mIsStarted and aFrameType first.
209 * These flags prevent "garbage" frames from being written into the buffer.
211 * After writing the data into the buffer, we check to see if we wrote over a
212 * slot, and update mConsumerIdx if necessary.
213 * This ensures that the decoder will get the "oldest" data available in the
214 * buffer.
216 * If the incoming data is larger than one slot size (isMultipleSlots), we do
217 * |mBufferSlotData[].mLength = BUFFER_SLOT_INVALID;| for other slots except the
218 * first slot, in order to notify the reader that some slots are unavailable.
220 * If the incoming data is isMultipleSlots and crosses the end of
221 * BUFFER_SLOT_NUM, returnToHead is set to true and the data will continue to
222 * be written from head(index 0).
224 * MEDIASTREAM_FRAMETYPE_DISCONTINUITY currently is used when we are seeking.
225 * */
226 void RtspTrackBuffer::WriteBuffer(const char *aFromBuffer, uint32_t aWriteCount,
227 uint64_t aFrameTime, uint32_t aFrameType)
229 MonitorAutoLock monitor(mMonitor);
230 if (!mIsStarted) {
231 RTSPMLOG("mIsStarted is false");
232 return;
234 if (mTotalBufferSize < aWriteCount) {
235 RTSPMLOG("mTotalBufferSize < aWriteCount, incoming data is too large");
236 return;
238 // Checking the incoming data's frame type.
239 // If we receive MEDIASTREAM_FRAMETYPE_DISCONTINUITY, clear the mFrameType
240 // imply the RtspTrackBuffer is ready for receive data.
241 if (aFrameType & MEDIASTREAM_FRAMETYPE_DISCONTINUITY) {
242 mFrameType = mFrameType & (~MEDIASTREAM_FRAMETYPE_DISCONTINUITY);
243 RTSPMLOG("Clear mFrameType");
244 return;
246 // Checking current buffer frame type.
247 // If the MEDIASTREAM_FRAMETYPE_DISCONTINUNITY bit is set, imply the
248 // RtspTrackBuffer can't receive data now. So we drop the frame until we
249 // receive MEDIASTREAM_FRAMETYPE_DISCONTINUNITY.
250 if (mFrameType & MEDIASTREAM_FRAMETYPE_DISCONTINUITY) {
251 RTSPMLOG("Return because the mFrameType is set");
252 return;
254 // The flag is true if the incoming data is larger than one slot size.
255 bool isMultipleSlots = false;
256 // The flag is true if the incoming data is larger than remainder free slots
257 bool returnToHead = false;
258 // Calculate how many slots the incoming data needed.
259 int32_t slots = 1;
260 int32_t i;
261 RTSPMLOG("WriteBuffer mTrackIdx %d mProducerIdx %d mConsumerIdx %d",
262 mTrackIdx, mProducerIdx,mConsumerIdx);
263 if (aWriteCount > mSlotSize) {
264 isMultipleSlots = true;
265 slots = (aWriteCount / mSlotSize) + 1;
267 if (isMultipleSlots &&
268 (aWriteCount > (BUFFER_SLOT_NUM - mProducerIdx) * mSlotSize)) {
269 returnToHead = true;
271 RTSPMLOG("slots %d isMultipleSlots %d returnToHead %d",
272 slots, isMultipleSlots, returnToHead);
273 if (returnToHead) {
274 // Clear the rest index of mBufferSlotData[].mLength
275 for (i = mProducerIdx; i < BUFFER_SLOT_NUM; ++i) {
276 mBufferSlotData[i].mLength = BUFFER_SLOT_INVALID;
278 // We wrote one or more slots that the decode thread has not yet read.
279 // So the mConsumerIdx returns to the head of slot buffer and moves forward
280 // to the oldest slot.
281 if (mProducerIdx <= mConsumerIdx && mConsumerIdx < mProducerIdx + slots) {
282 mConsumerIdx = 0;
283 for (i = mConsumerIdx; i < BUFFER_SLOT_NUM; ++i) {
284 if (mBufferSlotData[i].mLength > 0) {
285 mConsumerIdx = i;
286 break;
290 mProducerIdx = 0;
293 memcpy(&(mRingBuffer[mSlotSize * mProducerIdx]), aFromBuffer, aWriteCount);
295 if (mProducerIdx <= mConsumerIdx && mConsumerIdx < mProducerIdx + slots
296 && mBufferSlotData[mConsumerIdx].mLength > 0) {
297 // Wrote one or more slots that the decode thread has not yet read.
298 RTSPMLOG("overwrite!! %d time %lld"
299 ,mTrackIdx,mBufferSlotData[mConsumerIdx].mTime);
300 mBufferSlotData[mProducerIdx].mLength = aWriteCount;
301 mBufferSlotData[mProducerIdx].mTime = aFrameTime;
302 // Clear the mBufferSlotDataLength except the start slot.
303 if (isMultipleSlots) {
304 for (i = mProducerIdx + 1; i < mProducerIdx + slots; ++i) {
305 mBufferSlotData[i].mLength = BUFFER_SLOT_INVALID;
308 mProducerIdx = (mProducerIdx + slots) % BUFFER_SLOT_NUM;
309 // Move the mConsumerIdx forward to ensure that the decoder reads the
310 // oldest data available.
311 mConsumerIdx = mProducerIdx;
312 } else {
313 // Normal case, the writer doesn't take over the reader.
314 mBufferSlotData[mProducerIdx].mLength = aWriteCount;
315 mBufferSlotData[mProducerIdx].mTime = aFrameTime;
316 // Clear the mBufferSlotData[].mLength except the start slot.
317 if (isMultipleSlots) {
318 for (i = mProducerIdx + 1; i < mProducerIdx + slots; ++i) {
319 mBufferSlotData[i].mLength = BUFFER_SLOT_INVALID;
322 mProducerIdx = (mProducerIdx + slots) % BUFFER_SLOT_NUM;
325 mMonitor.NotifyAll();
328 void RtspTrackBuffer::Reset() {
329 MonitorAutoLock monitor(mMonitor);
330 mProducerIdx = 0;
331 mConsumerIdx = 0;
332 for (uint32_t i = 0; i < BUFFER_SLOT_NUM; ++i) {
333 mBufferSlotData[i].mLength = BUFFER_SLOT_EMPTY;
334 mBufferSlotData[i].mTime = BUFFER_SLOT_EMPTY;
336 mMonitor.NotifyAll();
339 RtspMediaResource::RtspMediaResource(MediaDecoder* aDecoder,
340 nsIChannel* aChannel, nsIURI* aURI, const nsACString& aContentType)
341 : BaseMediaResource(aDecoder, aChannel, aURI, aContentType)
342 , mIsConnected(false)
343 , mRealTime(false)
345 nsCOMPtr<nsIStreamingProtocolControllerService> mediaControllerService =
346 do_GetService(MEDIASTREAMCONTROLLERSERVICE_CONTRACTID);
347 MOZ_ASSERT(mediaControllerService);
348 if (mediaControllerService) {
349 mediaControllerService->Create(mChannel,
350 getter_AddRefs(mMediaStreamController));
351 MOZ_ASSERT(mMediaStreamController);
352 mListener = new Listener(this);
353 mMediaStreamController->AsyncOpen(mListener);
355 #ifdef PR_LOGGING
356 if (!gRtspMediaResourceLog) {
357 gRtspMediaResourceLog = PR_NewLogModule("RtspMediaResource");
359 #endif
362 RtspMediaResource::~RtspMediaResource()
364 RTSPMLOG("~RtspMediaResource");
365 if (mListener) {
366 // Kill its reference to us since we're going away
367 mListener->Revoke();
371 NS_IMPL_ISUPPORTS2(RtspMediaResource::Listener,
372 nsIInterfaceRequestor, nsIStreamingProtocolListener);
374 nsresult
375 RtspMediaResource::Listener::OnMediaDataAvailable(uint8_t aTrackIdx,
376 const nsACString &data,
377 uint32_t length,
378 uint32_t offset,
379 nsIStreamingProtocolMetaData *meta)
381 if (!mResource)
382 return NS_OK;
383 return mResource->OnMediaDataAvailable(aTrackIdx, data, length, offset, meta);
386 nsresult
387 RtspMediaResource::Listener::OnConnected(uint8_t aTrackIdx,
388 nsIStreamingProtocolMetaData *meta)
390 if (!mResource)
391 return NS_OK;
392 return mResource->OnConnected(aTrackIdx, meta);
395 nsresult
396 RtspMediaResource::Listener::OnDisconnected(uint8_t aTrackIdx, uint32_t reason)
398 if (!mResource)
399 return NS_OK;
400 return mResource->OnDisconnected(aTrackIdx, reason);
403 nsresult
404 RtspMediaResource::Listener::GetInterface(const nsIID & aIID, void **aResult)
406 return QueryInterface(aIID, aResult);
409 nsresult
410 RtspMediaResource::ReadFrameFromTrack(uint8_t* aBuffer, uint32_t aBufferSize,
411 uint32_t aTrackIdx, uint32_t& aBytes,
412 uint64_t& aTime, uint32_t& aFrameSize)
414 NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
415 NS_ASSERTION(aTrackIdx < mTrackBuffer.Length(),
416 "ReadTrack index > mTrackBuffer");
417 MOZ_ASSERT(aBuffer);
419 return mTrackBuffer[aTrackIdx]->ReadBuffer(aBuffer, aBufferSize, aBytes,
420 aTime, aFrameSize);
423 nsresult
424 RtspMediaResource::OnMediaDataAvailable(uint8_t aTrackIdx,
425 const nsACString &data,
426 uint32_t length,
427 uint32_t offset,
428 nsIStreamingProtocolMetaData *meta)
430 uint64_t time;
431 uint32_t frameType;
432 meta->GetTimeStamp(&time);
433 meta->GetFrameType(&frameType);
434 if (mRealTime) {
435 time = 0;
437 mTrackBuffer[aTrackIdx]->WriteBuffer(data.BeginReading(), length, time,
438 frameType);
439 return NS_OK;
442 nsresult
443 RtspMediaResource::OnConnected(uint8_t aTrackIdx,
444 nsIStreamingProtocolMetaData *meta)
446 if (mIsConnected) {
447 return NS_OK;
450 uint8_t tracks;
451 mMediaStreamController->GetTotalTracks(&tracks);
452 uint64_t duration = 0;
453 for (int i = 0; i < tracks; ++i) {
454 nsCString rtspTrackId("RtspTrack");
455 rtspTrackId.AppendInt(i);
456 nsCOMPtr<nsIStreamingProtocolMetaData> trackMeta;
457 mMediaStreamController->GetTrackMetaData(i, getter_AddRefs(trackMeta));
458 MOZ_ASSERT(trackMeta);
459 trackMeta->GetDuration(&duration);
461 // Here is a heuristic to estimate the slot size.
462 // For video track, calculate the width*height.
463 // For audio track, use the BUFFER_SLOT_DEFAULT_SIZE because the w*h is 0.
464 // Finally clamp them into (BUFFER_SLOT_DEFAULT_SIZE,BUFFER_SLOT_MAX_SIZE)
465 uint32_t w, h;
466 uint32_t slotSize;
467 trackMeta->GetWidth(&w);
468 trackMeta->GetHeight(&h);
469 slotSize = clamped((int32_t)(w * h), BUFFER_SLOT_DEFAULT_SIZE,
470 BUFFER_SLOT_MAX_SIZE);
471 mTrackBuffer.AppendElement(new RtspTrackBuffer(rtspTrackId.get(),
472 i, slotSize));
473 mTrackBuffer[i]->Start();
476 // If the duration is 0, imply the stream is live stream.
477 if (duration) {
478 // Not live stream.
479 mRealTime = false;
480 bool seekable = true;
481 mDecoder->SetInfinite(false);
482 mDecoder->SetTransportSeekable(seekable);
483 mDecoder->SetDuration(duration);
484 } else {
485 // Live stream.
486 // Check the preference "media.realtime_decoder.enabled".
487 if (!Preferences::GetBool("media.realtime_decoder.enabled", false)) {
488 // Give up, report error to media element.
489 nsCOMPtr<nsIRunnable> event =
490 NS_NewRunnableMethod(mDecoder, &MediaDecoder::DecodeError);
491 NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
492 return NS_ERROR_FAILURE;
493 } else {
494 mRealTime = true;
495 bool seekable = false;
496 mDecoder->SetInfinite(true);
497 mDecoder->SetTransportSeekable(seekable);
498 mDecoder->SetMediaSeekable(seekable);
501 // Fires an initial progress event and sets up the stall counter so stall events
502 // fire if no download occurs within the required time frame.
503 mDecoder->Progress(false);
505 MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
506 NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
507 HTMLMediaElement* element = owner->GetMediaElement();
508 NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
510 element->FinishDecoderSetup(mDecoder, this);
511 mIsConnected = true;
513 return NS_OK;
516 nsresult
517 RtspMediaResource::OnDisconnected(uint8_t aTrackIdx, uint32_t aReason)
519 NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
521 for (uint32_t i = 0 ; i < mTrackBuffer.Length(); ++i) {
522 mTrackBuffer[i]->Stop();
523 mTrackBuffer[i]->Reset();
526 if (aReason == (uint32_t)NS_ERROR_CONNECTION_REFUSED) {
527 mDecoder->NetworkError();
529 return NS_OK;
532 void RtspMediaResource::Suspend(bool aCloseImmediately)
534 NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
536 MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
537 NS_ENSURE_TRUE_VOID(owner);
538 HTMLMediaElement* element = owner->GetMediaElement();
539 NS_ENSURE_TRUE_VOID(element);
541 mMediaStreamController->Suspend();
542 element->DownloadSuspended();
545 void RtspMediaResource::Resume()
547 NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
549 MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
550 NS_ENSURE_TRUE_VOID(owner);
551 HTMLMediaElement* element = owner->GetMediaElement();
552 NS_ENSURE_TRUE_VOID(element);
554 if (mChannel) {
555 element->DownloadResumed();
557 mMediaStreamController->Resume();
560 nsresult RtspMediaResource::Open(nsIStreamListener **aStreamListener)
562 return NS_OK;
565 nsresult RtspMediaResource::Close()
567 NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
568 mMediaStreamController->Stop();
569 return NS_OK;
572 already_AddRefed<nsIPrincipal> RtspMediaResource::GetCurrentPrincipal()
574 NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
576 nsCOMPtr<nsIPrincipal> principal;
577 nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
578 if (!secMan || !mChannel)
579 return nullptr;
580 secMan->GetChannelPrincipal(mChannel, getter_AddRefs(principal));
581 return principal.forget();
584 nsresult RtspMediaResource::SeekTime(int64_t aOffset)
586 NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
588 RTSPMLOG("Seek requested for aOffset [%lld] for decoder [%p]",
589 aOffset, mDecoder);
590 // Clear buffer and raise the frametype flag.
591 for(uint32_t i = 0 ; i < mTrackBuffer.Length(); ++i) {
592 mTrackBuffer[i]->ResetWithFrameType(MEDIASTREAM_FRAMETYPE_DISCONTINUITY);
595 return mMediaStreamController->Seek(aOffset);
598 } // namespace mozilla