Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/ChannelMediaDecoder.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
#include "ChannelMediaDecoder.h"
8
#include "DecoderTraits.h"
9
#include "MediaDecoderStateMachine.h"
10
#include "MediaFormatReader.h"
11
#include "BaseMediaResource.h"
12
#include "MediaShutdownManager.h"
13
#include "mozilla/StaticPrefs.h"
14
15
namespace mozilla {
16
17
extern LazyLogModule gMediaDecoderLog;
18
#define LOG(x, ...)                                                            \
19
0
  DDMOZ_LOG(gMediaDecoderLog, LogLevel::Debug, x, ##__VA_ARGS__)
20
21
ChannelMediaDecoder::ResourceCallback::ResourceCallback(
22
  AbstractThread* aMainThread)
23
  : mAbstractMainThread(aMainThread)
24
0
{
25
0
  MOZ_ASSERT(aMainThread);
26
0
  DecoderDoctorLogger::LogConstructionAndBase(
27
0
    "ChannelMediaDecoder::ResourceCallback",
28
0
    this,
29
0
    static_cast<const MediaResourceCallback*>(this));
30
0
}
31
32
ChannelMediaDecoder::ResourceCallback::~ResourceCallback()
33
0
{
34
0
  DecoderDoctorLogger::LogDestruction("ChannelMediaDecoder::ResourceCallback",
35
0
                                      this);
36
0
}
37
38
void
39
ChannelMediaDecoder::ResourceCallback::Connect(ChannelMediaDecoder* aDecoder)
40
0
{
41
0
  MOZ_ASSERT(NS_IsMainThread());
42
0
  mDecoder = aDecoder;
43
0
  DecoderDoctorLogger::LinkParentAndChild(
44
0
    "ChannelMediaDecoder::ResourceCallback", this, "decoder", mDecoder);
45
0
  mTimer = NS_NewTimer(mAbstractMainThread->AsEventTarget());
46
0
}
47
48
void
49
ChannelMediaDecoder::ResourceCallback::Disconnect()
50
0
{
51
0
  MOZ_ASSERT(NS_IsMainThread());
52
0
  if (mDecoder) {
53
0
    DecoderDoctorLogger::UnlinkParentAndChild(
54
0
      "ChannelMediaDecoder::ResourceCallback", this, mDecoder);
55
0
    mDecoder = nullptr;
56
0
    mTimer->Cancel();
57
0
    mTimer = nullptr;
58
0
  }
59
0
}
60
61
AbstractThread*
62
ChannelMediaDecoder::ResourceCallback::AbstractMainThread() const
63
0
{
64
0
  return mAbstractMainThread;
65
0
}
66
67
MediaDecoderOwner*
68
ChannelMediaDecoder::ResourceCallback::GetMediaOwner() const
69
0
{
70
0
  MOZ_ASSERT(NS_IsMainThread());
71
0
  return mDecoder ? mDecoder->GetOwner() : nullptr;
72
0
}
73
74
void
75
ChannelMediaDecoder::ResourceCallback::NotifyNetworkError(
76
  const MediaResult& aError)
77
0
{
78
0
  MOZ_ASSERT(NS_IsMainThread());
79
0
  DDLOGEX2("ChannelMediaDecoder::ResourceCallback",
80
0
           this,
81
0
           DDLogCategory::Log,
82
0
           "network_error",
83
0
           aError);
84
0
  if (mDecoder) {
85
0
    mDecoder->NetworkError(aError);
86
0
  }
87
0
}
88
89
/* static */ void
90
ChannelMediaDecoder::ResourceCallback::TimerCallback(nsITimer* aTimer,
91
                                                     void* aClosure)
92
0
{
93
0
  MOZ_ASSERT(NS_IsMainThread());
94
0
  ResourceCallback* thiz = static_cast<ResourceCallback*>(aClosure);
95
0
  MOZ_ASSERT(thiz->mDecoder);
96
0
  thiz->mDecoder->NotifyReaderDataArrived();
97
0
  thiz->mTimerArmed = false;
98
0
}
99
100
void
101
ChannelMediaDecoder::ResourceCallback::NotifyDataArrived()
102
0
{
103
0
  MOZ_ASSERT(NS_IsMainThread());
104
0
  DDLOGEX2("ChannelMediaDecoder::ResourceCallback",
105
0
           this,
106
0
           DDLogCategory::Log,
107
0
           "data_arrived",
108
0
           true);
109
0
110
0
  if (!mDecoder) {
111
0
    return;
112
0
  }
113
0
114
0
  mDecoder->DownloadProgressed();
115
0
116
0
  if (mTimerArmed) {
117
0
    return;
118
0
  }
119
0
  // In situations where these notifications come from stochastic network
120
0
  // activity, we can save significant computation by throttling the
121
0
  // calls to MediaDecoder::NotifyDataArrived() which will update the buffer
122
0
  // ranges of the reader.
123
0
  mTimerArmed = true;
124
0
  mTimer->InitWithNamedFuncCallback(
125
0
    TimerCallback, this, sDelay, nsITimer::TYPE_ONE_SHOT,
126
0
    "ChannelMediaDecoder::ResourceCallback::TimerCallback");
127
0
}
128
129
void
130
ChannelMediaDecoder::ResourceCallback::NotifyDataEnded(nsresult aStatus)
131
0
{
132
0
  DDLOGEX2("ChannelMediaDecoder::ResourceCallback",
133
0
           this,
134
0
           DDLogCategory::Log,
135
0
           "data_ended",
136
0
           aStatus);
137
0
  MOZ_ASSERT(NS_IsMainThread());
138
0
  if (mDecoder) {
139
0
    mDecoder->NotifyDownloadEnded(aStatus);
140
0
  }
141
0
}
142
143
void
144
ChannelMediaDecoder::ResourceCallback::NotifyPrincipalChanged()
145
0
{
146
0
  MOZ_ASSERT(NS_IsMainThread());
147
0
  DDLOGEX2("ChannelMediaDecoder::ResourceCallback",
148
0
           this,
149
0
           DDLogCategory::Log,
150
0
           "principal_changed",
151
0
           true);
152
0
  if (mDecoder) {
153
0
    mDecoder->NotifyPrincipalChanged();
154
0
  }
155
0
}
156
157
void
158
ChannelMediaDecoder::NotifyPrincipalChanged()
159
0
{
160
0
  MOZ_ASSERT(NS_IsMainThread());
161
0
  MediaDecoder::NotifyPrincipalChanged();
162
0
  if (!mInitialChannelPrincipalKnown) {
163
0
    // We'll receive one notification when the channel's initial principal
164
0
    // is known, after all HTTP redirects have resolved. This isn't really a
165
0
    // principal change, so return here to avoid the mSameOriginMedia check
166
0
    // below.
167
0
    mInitialChannelPrincipalKnown = true;
168
0
    return;
169
0
  }
170
0
  if (!mSameOriginMedia &&
171
0
      Preferences::GetBool("media.block-midflight-redirects", true)) {
172
0
    // Block mid-flight redirects to non CORS same origin destinations.
173
0
    // See bugs 1441153, 1443942.
174
0
    LOG("ChannnelMediaDecoder prohibited cross origin redirect blocked.");
175
0
    NetworkError(MediaResult(NS_ERROR_DOM_BAD_URI,
176
0
                             "Prohibited cross origin redirect blocked"));
177
0
  }
178
0
}
179
180
void
181
ChannelMediaDecoder::ResourceCallback::NotifySuspendedStatusChanged(
182
  bool aSuspendedByCache)
183
0
{
184
0
  MOZ_ASSERT(NS_IsMainThread());
185
0
  DDLOGEX2("ChannelMediaDecoder::ResourceCallback",
186
0
           this,
187
0
           DDLogCategory::Log,
188
0
           "suspended_status_changed",
189
0
           aSuspendedByCache);
190
0
  MediaDecoderOwner* owner = GetMediaOwner();
191
0
  if (owner) {
192
0
    AbstractThread::AutoEnter context(owner->AbstractMainThread());
193
0
    owner->NotifySuspendedByCache(aSuspendedByCache);
194
0
  }
195
0
}
196
197
ChannelMediaDecoder::ChannelMediaDecoder(MediaDecoderInit& aInit)
198
  : MediaDecoder(aInit)
199
  , mResourceCallback(new ResourceCallback(aInit.mOwner->AbstractMainThread()))
200
0
{
201
0
  mResourceCallback->Connect(this);
202
0
}
203
204
/* static */
205
already_AddRefed<ChannelMediaDecoder>
206
ChannelMediaDecoder::Create(MediaDecoderInit& aInit,
207
                            DecoderDoctorDiagnostics* aDiagnostics)
208
0
{
209
0
  MOZ_ASSERT(NS_IsMainThread());
210
0
  RefPtr<ChannelMediaDecoder> decoder;
211
0
212
0
  const MediaContainerType& type = aInit.mContainerType;
213
0
  if (DecoderTraits::IsSupportedType(type)) {
214
0
    decoder = new ChannelMediaDecoder(aInit);
215
0
    return decoder.forget();
216
0
  }
217
0
218
0
  if (DecoderTraits::IsHttpLiveStreamingType(type)) {
219
0
    // We don't have an HLS decoder.
220
0
    Telemetry::Accumulate(Telemetry::MEDIA_HLS_DECODER_SUCCESS, false);
221
0
  }
222
0
223
0
  return nullptr;
224
0
}
225
226
bool
227
ChannelMediaDecoder::CanClone()
228
0
{
229
0
  MOZ_ASSERT(NS_IsMainThread());
230
0
  return mResource && mResource->CanClone();
231
0
}
232
233
already_AddRefed<ChannelMediaDecoder>
234
ChannelMediaDecoder::Clone(MediaDecoderInit& aInit)
235
0
{
236
0
  if (!mResource || !DecoderTraits::IsSupportedType(aInit.mContainerType)) {
237
0
    return nullptr;
238
0
  }
239
0
  RefPtr<ChannelMediaDecoder> decoder = new ChannelMediaDecoder(aInit);
240
0
  if (!decoder) {
241
0
    return nullptr;
242
0
  }
243
0
  nsresult rv = decoder->Load(mResource);
244
0
  if (NS_FAILED(rv)) {
245
0
    decoder->Shutdown();
246
0
    return nullptr;
247
0
  }
248
0
  return decoder.forget();
249
0
}
250
251
MediaDecoderStateMachine* ChannelMediaDecoder::CreateStateMachine()
252
0
{
253
0
  MOZ_ASSERT(NS_IsMainThread());
254
0
  MediaFormatReaderInit init;
255
0
  init.mVideoFrameContainer = GetVideoFrameContainer();
256
0
  init.mKnowsCompositor = GetCompositor();
257
0
  init.mCrashHelper = GetOwner()->CreateGMPCrashHelper();
258
0
  init.mFrameStats = mFrameStats;
259
0
  init.mResource = mResource;
260
0
  init.mMediaDecoderOwnerID = mOwner;
261
0
  mReader = DecoderTraits::CreateReader(ContainerType(), init);
262
0
  return new MediaDecoderStateMachine(this, mReader);
263
0
}
264
265
void
266
ChannelMediaDecoder::Shutdown()
267
0
{
268
0
  mResourceCallback->Disconnect();
269
0
  MediaDecoder::Shutdown();
270
0
271
0
  // Force any outstanding seek and byterange requests to complete
272
0
  // to prevent shutdown from deadlocking.
273
0
  if (mResource) {
274
0
    mResource->Close();
275
0
  }
276
0
}
277
278
nsresult
279
ChannelMediaDecoder::Load(nsIChannel* aChannel,
280
                          bool aIsPrivateBrowsing,
281
                          nsIStreamListener** aStreamListener)
282
0
{
283
0
  MOZ_ASSERT(NS_IsMainThread());
284
0
  MOZ_ASSERT(!mResource);
285
0
  MOZ_ASSERT(aStreamListener);
286
0
  AbstractThread::AutoEnter context(AbstractMainThread());
287
0
288
0
  mResource =
289
0
    BaseMediaResource::Create(mResourceCallback, aChannel, aIsPrivateBrowsing);
290
0
  if (!mResource) {
291
0
    return NS_ERROR_FAILURE;
292
0
  }
293
0
  DDLINKCHILD("resource", mResource.get());
294
0
295
0
  nsresult rv = MediaShutdownManager::Instance().Register(this);
296
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
297
0
    return rv;
298
0
  }
299
0
300
0
  rv = mResource->Open(aStreamListener);
301
0
  NS_ENSURE_SUCCESS(rv, rv);
302
0
303
0
  SetStateMachine(CreateStateMachine());
304
0
  NS_ENSURE_TRUE(GetStateMachine(), NS_ERROR_FAILURE);
305
0
306
0
  GetStateMachine()->DispatchIsLiveStream(mResource->IsLiveStream());
307
0
308
0
  return InitializeStateMachine();
309
0
}
310
311
nsresult
312
ChannelMediaDecoder::Load(BaseMediaResource* aOriginal)
313
0
{
314
0
  MOZ_ASSERT(NS_IsMainThread());
315
0
  MOZ_ASSERT(!mResource);
316
0
  AbstractThread::AutoEnter context(AbstractMainThread());
317
0
318
0
  mResource = aOriginal->CloneData(mResourceCallback);
319
0
  if (!mResource) {
320
0
    return NS_ERROR_FAILURE;
321
0
  }
322
0
  DDLINKCHILD("resource", mResource.get());
323
0
324
0
  nsresult rv = MediaShutdownManager::Instance().Register(this);
325
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
326
0
    return rv;
327
0
  }
328
0
329
0
  SetStateMachine(CreateStateMachine());
330
0
  NS_ENSURE_TRUE(GetStateMachine(), NS_ERROR_FAILURE);
331
0
332
0
  GetStateMachine()->DispatchIsLiveStream(mResource->IsLiveStream());
333
0
334
0
  return InitializeStateMachine();
335
0
}
336
337
void
338
ChannelMediaDecoder::NotifyDownloadEnded(nsresult aStatus)
339
0
{
340
0
  MOZ_ASSERT(NS_IsMainThread());
341
0
  MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
342
0
  AbstractThread::AutoEnter context(AbstractMainThread());
343
0
344
0
  LOG("NotifyDownloadEnded, status=%" PRIx32, static_cast<uint32_t>(aStatus));
345
0
346
0
  if (NS_SUCCEEDED(aStatus)) {
347
0
    // Download ends successfully. This is a stream with a finite length.
348
0
    GetStateMachine()->DispatchIsLiveStream(false);
349
0
  }
350
0
351
0
  MediaDecoderOwner* owner = GetOwner();
352
0
  if (NS_SUCCEEDED(aStatus) || aStatus == NS_BASE_STREAM_CLOSED) {
353
0
    nsCOMPtr<nsIRunnable> r =
354
0
      NS_NewRunnableFunction("ChannelMediaDecoder::UpdatePlaybackRate", [
355
0
        stats = mPlaybackStatistics,
356
0
        res = RefPtr<BaseMediaResource>(mResource),
357
0
        duration = mDuration
358
0
      ]() {
359
0
        auto rate = ComputePlaybackRate(stats, res, duration);
360
0
        UpdatePlaybackRate(rate, res);
361
0
      });
362
0
    nsresult rv = GetStateMachine()->OwnerThread()->Dispatch(r.forget());
363
0
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
364
0
    Unused << rv;
365
0
    owner->DownloadSuspended();
366
0
    // NotifySuspendedStatusChanged will tell the element that download
367
0
    // has been suspended "by the cache", which is true since we never
368
0
    // download anything. The element can then transition to HAVE_ENOUGH_DATA.
369
0
    owner->NotifySuspendedByCache(true);
370
0
  } else if (aStatus == NS_BINDING_ABORTED) {
371
0
    // Download has been cancelled by user.
372
0
    owner->LoadAborted();
373
0
  } else {
374
0
    NetworkError(MediaResult(aStatus, "Download aborted"));
375
0
  }
376
0
}
377
378
bool
379
ChannelMediaDecoder::CanPlayThroughImpl()
380
0
{
381
0
  MOZ_ASSERT(NS_IsMainThread());
382
0
  return mCanPlayThrough;
383
0
}
384
385
void
386
ChannelMediaDecoder::OnPlaybackEvent(MediaPlaybackEvent&& aEvent)
387
0
{
388
0
  MOZ_ASSERT(NS_IsMainThread());
389
0
  switch (aEvent.mType) {
390
0
    case MediaPlaybackEvent::PlaybackStarted:
391
0
      mPlaybackPosition = aEvent.mData.as<int64_t>();
392
0
      mPlaybackStatistics.Start();
393
0
      break;
394
0
    case MediaPlaybackEvent::PlaybackProgressed: {
395
0
      int64_t newPos = aEvent.mData.as<int64_t>();
396
0
      mPlaybackStatistics.AddBytes(newPos - mPlaybackPosition);
397
0
      mPlaybackPosition = newPos;
398
0
      break;
399
0
    }
400
0
    case MediaPlaybackEvent::PlaybackStopped: {
401
0
      int64_t newPos = aEvent.mData.as<int64_t>();
402
0
      mPlaybackStatistics.AddBytes(newPos - mPlaybackPosition);
403
0
      mPlaybackPosition = newPos;
404
0
      mPlaybackStatistics.Stop();
405
0
      break;
406
0
    }
407
0
    default:
408
0
      break;
409
0
  }
410
0
  MediaDecoder::OnPlaybackEvent(std::move(aEvent));
411
0
}
412
413
void
414
ChannelMediaDecoder::DurationChanged()
415
0
{
416
0
  MOZ_ASSERT(NS_IsMainThread());
417
0
  AbstractThread::AutoEnter context(AbstractMainThread());
418
0
  MediaDecoder::DurationChanged();
419
0
  // Duration has changed so we should recompute playback rate
420
0
  nsCOMPtr<nsIRunnable> r =
421
0
    NS_NewRunnableFunction("ChannelMediaDecoder::UpdatePlaybackRate", [
422
0
      stats = mPlaybackStatistics,
423
0
      res = RefPtr<BaseMediaResource>(mResource),
424
0
      duration = mDuration
425
0
    ]() {
426
0
      auto rate = ComputePlaybackRate(stats, res, duration);
427
0
      UpdatePlaybackRate(rate, res);
428
0
    });
429
0
  nsresult rv = GetStateMachine()->OwnerThread()->Dispatch(r.forget());
430
0
  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
431
0
  Unused << rv;
432
0
}
433
434
void
435
ChannelMediaDecoder::DownloadProgressed()
436
0
{
437
0
  MOZ_ASSERT(NS_IsMainThread());
438
0
  MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
439
0
440
0
  GetOwner()->DownloadProgressed();
441
0
442
0
  using StatsPromise = MozPromise<MediaStatistics, bool, true>;
443
0
  InvokeAsync(GetStateMachine()->OwnerThread(),
444
0
              __func__,
445
0
              [
446
0
                playbackStats = mPlaybackStatistics,
447
0
                res = RefPtr<BaseMediaResource>(mResource),
448
0
                duration = mDuration,
449
0
                pos = mPlaybackPosition
450
0
              ]() {
451
0
                auto rate = ComputePlaybackRate(playbackStats, res, duration);
452
0
                UpdatePlaybackRate(rate, res);
453
0
                MediaStatistics stats = GetStatistics(rate, res, pos);
454
0
                return StatsPromise::CreateAndResolve(stats, __func__);
455
0
              })
456
0
    ->Then(
457
0
      mAbstractMainThread,
458
0
      __func__,
459
0
      [ =, self = RefPtr<ChannelMediaDecoder>(this) ](MediaStatistics aStats) {
460
0
        if (IsShutdown()) {
461
0
          return;
462
0
        }
463
0
        mCanPlayThrough = aStats.CanPlayThrough();
464
0
        GetStateMachine()->DispatchCanPlayThrough(mCanPlayThrough);
465
0
        mResource->ThrottleReadahead(ShouldThrottleDownload(aStats));
466
0
        // Update readyState since mCanPlayThrough might have changed.
467
0
        GetOwner()->UpdateReadyState();
468
0
      },
469
0
      []() { MOZ_ASSERT_UNREACHABLE("Promise not resolved"); });
470
0
}
471
472
/* static */ ChannelMediaDecoder::PlaybackRateInfo
473
ChannelMediaDecoder::ComputePlaybackRate(const MediaChannelStatistics& aStats,
474
                                         BaseMediaResource* aResource,
475
                                         double aDuration)
476
0
{
477
0
  MOZ_ASSERT(!NS_IsMainThread());
478
0
479
0
  int64_t length = aResource->GetLength();
480
0
  if (mozilla::IsFinite<double>(aDuration) && aDuration > 0 && length >= 0) {
481
0
    return { uint32_t(length / aDuration), true };
482
0
  }
483
0
484
0
  bool reliable = false;
485
0
  uint32_t rate = aStats.GetRate(&reliable);
486
0
  return { rate, reliable };
487
0
}
488
489
/* static */ void
490
ChannelMediaDecoder::UpdatePlaybackRate(const PlaybackRateInfo& aInfo,
491
                                        BaseMediaResource* aResource)
492
0
{
493
0
  MOZ_ASSERT(!NS_IsMainThread());
494
0
495
0
  uint32_t rate = aInfo.mRate;
496
0
497
0
  if (aInfo.mReliable) {
498
0
    // Avoid passing a zero rate
499
0
    rate = std::max(rate, 1u);
500
0
  } else {
501
0
    // Set a minimum rate of 10,000 bytes per second ... sometimes we just
502
0
    // don't have good data
503
0
    rate = std::max(rate, 10000u);
504
0
  }
505
0
506
0
  aResource->SetPlaybackRate(rate);
507
0
}
508
509
/* static */ MediaStatistics
510
ChannelMediaDecoder::GetStatistics(const PlaybackRateInfo& aInfo,
511
                                   BaseMediaResource* aRes,
512
                                   int64_t aPlaybackPosition)
513
0
{
514
0
  MOZ_ASSERT(!NS_IsMainThread());
515
0
516
0
  MediaStatistics result;
517
0
  result.mDownloadRate = aRes->GetDownloadRate(&result.mDownloadRateReliable);
518
0
  result.mDownloadPosition = aRes->GetCachedDataEnd(aPlaybackPosition);
519
0
  result.mTotalBytes = aRes->GetLength();
520
0
  result.mPlaybackRate = aInfo.mRate;
521
0
  result.mPlaybackRateReliable = aInfo.mReliable;
522
0
  result.mPlaybackPosition = aPlaybackPosition;
523
0
  return result;
524
0
}
525
526
bool
527
ChannelMediaDecoder::ShouldThrottleDownload(const MediaStatistics& aStats)
528
0
{
529
0
  // We throttle the download if either the throttle override pref is set
530
0
  // (so that we can always throttle in Firefox on mobile) or if the download
531
0
  // is fast enough that there's no concern about playback being interrupted.
532
0
  MOZ_ASSERT(NS_IsMainThread());
533
0
  NS_ENSURE_TRUE(GetStateMachine(), false);
534
0
535
0
  int64_t length = aStats.mTotalBytes;
536
0
  if (length > 0 &&
537
0
      length <= int64_t(StaticPrefs::MediaMemoryCacheMaxSize()) * 1024) {
538
0
    // Don't throttle the download of small resources. This is to speed
539
0
    // up seeking, as seeks into unbuffered ranges would require starting
540
0
    // up a new HTTP transaction, which adds latency.
541
0
    return false;
542
0
  }
543
0
544
0
  if (Preferences::GetBool("media.throttle-regardless-of-download-rate",
545
0
                           false)) {
546
0
    return true;
547
0
  }
548
0
549
0
  if (!aStats.mDownloadRateReliable || !aStats.mPlaybackRateReliable) {
550
0
    return false;
551
0
  }
552
0
  uint32_t factor =
553
0
    std::max(2u, Preferences::GetUint("media.throttle-factor", 2));
554
0
  return aStats.mDownloadRate > factor * aStats.mPlaybackRate;
555
0
}
556
557
void
558
ChannelMediaDecoder::AddSizeOfResources(ResourceSizes* aSizes)
559
0
{
560
0
  MOZ_ASSERT(NS_IsMainThread());
561
0
  if (mResource) {
562
0
    aSizes->mByteSize += mResource->SizeOfIncludingThis(aSizes->mMallocSizeOf);
563
0
  }
564
0
}
565
566
already_AddRefed<nsIPrincipal>
567
ChannelMediaDecoder::GetCurrentPrincipal()
568
0
{
569
0
  MOZ_ASSERT(NS_IsMainThread());
570
0
  return mResource ? mResource->GetCurrentPrincipal() : nullptr;
571
0
}
572
573
bool
574
ChannelMediaDecoder::IsTransportSeekable()
575
0
{
576
0
  MOZ_ASSERT(NS_IsMainThread());
577
0
  return mResource->IsTransportSeekable();
578
0
}
579
580
void
581
ChannelMediaDecoder::SetLoadInBackground(bool aLoadInBackground)
582
0
{
583
0
  MOZ_ASSERT(NS_IsMainThread());
584
0
  if (mResource) {
585
0
    mResource->SetLoadInBackground(aLoadInBackground);
586
0
  }
587
0
}
588
589
void
590
ChannelMediaDecoder::Suspend()
591
0
{
592
0
  MOZ_ASSERT(NS_IsMainThread());
593
0
  if (mResource) {
594
0
    mResource->Suspend(true);
595
0
  }
596
0
}
597
598
void
599
ChannelMediaDecoder::Resume()
600
0
{
601
0
  MOZ_ASSERT(NS_IsMainThread());
602
0
  if (mResource) {
603
0
    mResource->Resume();
604
0
  }
605
0
}
606
607
void
608
ChannelMediaDecoder::MetadataLoaded(
609
  UniquePtr<MediaInfo> aInfo,
610
  UniquePtr<MetadataTags> aTags,
611
  MediaDecoderEventVisibility aEventVisibility)
612
0
{
613
0
  MediaDecoder::MetadataLoaded(std::move(aInfo), std::move(aTags), aEventVisibility);
614
0
  // Set mode to PLAYBACK after reading metadata.
615
0
  mResource->SetReadMode(MediaCacheStream::MODE_PLAYBACK);
616
0
}
617
618
nsCString
619
ChannelMediaDecoder::GetDebugInfo()
620
0
{
621
0
  nsCString str = MediaDecoder::GetDebugInfo();
622
0
  if (mResource) {
623
0
    AppendStringIfNotEmpty(str, mResource->GetDebugInfo());
624
0
  }
625
0
  return str;
626
0
}
627
628
} // namespace mozilla
629
630
// avoid redefined macro in unified build
631
#undef LOG