2014-09-11 22:47:06 +00:00
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2013-06-21 03:14:42 +00:00
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/. */
# include "SourceBuffer.h"
2013-09-27 05:22:37 +00:00
# include "AsyncEventRunner.h"
2015-01-26 15:01:09 +00:00
# include "MediaData.h"
2015-07-22 01:09:21 +00:00
# include "MediaSourceDemuxer.h"
2014-08-20 08:07:00 +00:00
# include "MediaSourceUtils.h"
2013-09-27 05:22:37 +00:00
# include "mozilla/ErrorResult.h"
# include "mozilla/FloatingPoint.h"
2014-09-04 01:57:06 +00:00
# include "mozilla/Preferences.h"
2013-09-27 05:22:37 +00:00
# include "mozilla/dom/MediaSourceBinding.h"
# include "mozilla/dom/TimeRanges.h"
# include "nsError.h"
# include "nsIEventTarget.h"
# include "nsIRunnable.h"
# include "nsThreadUtils.h"
2015-05-19 18:15:34 +00:00
# include "mozilla/Logging.h"
2015-01-26 10:33:56 +00:00
# include <time.h>
2015-03-03 04:38:45 +00:00
# include "TimeUnits.h"
2014-08-19 05:13:27 +00:00
2016-09-21 09:24:43 +00:00
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
// GetTickCount() and conflicts with MediaDecoder::GetCurrentTime implementation.
# ifdef GetCurrentTime
# undef GetCurrentTime
# endif
2013-09-27 05:22:37 +00:00
struct JSContext ;
class JSObject ;
2015-11-15 13:49:01 +00:00
extern mozilla : : LogModule * GetMediaSourceLog ( ) ;
extern mozilla : : LogModule * GetMediaSourceAPILog ( ) ;
2014-08-11 01:21:17 +00:00
Bug 1331289 - Use MediaContainerType in MediaResource, SourceBuffer, TrackBuffersManager, and dependencies - r=jya
Continuing the work of replacing MIME strings with MediaContainerType, starting
from MediaResource and following the dependencies.
Most changes are mechanical: Just change ns*String into MediaContainerType, and
MIME string literals into MEDIAMIMETYPE("a/b").
Some checks for empty/invalid strings and lowercase comparisons can go, thanks
to the always-valid always-lowercase-MIME invariants of MediaContainerType.
One special case in is MediaSourceResource, which used to have an empty string
as its type (because its own type is not relevant, but its SourceBuffers carry
types). Because the inherited GetContentType *must* be overridden, and must
return a MediaContainerType, we needed a valid type even though it should not
be seen in the real world. I've chosen "application/x.mediasource" for that.
MozReview-Commit-ID: 1aCH75Kh2e6
--HG--
extra : rebase_source : 0d9cd9b69c264e5dcfc3845f80ee107f4bcbcd9a
2016-12-28 07:59:02 +00:00
# define MSE_DEBUG(arg, ...) MOZ_LOG(GetMediaSourceLog(), mozilla::LogLevel::Debug, ("SourceBuffer(%p:%s)::%s: " arg, this, mType.OriginalString().Data(), __func__, ##__VA_ARGS__))
# define MSE_DEBUGV(arg, ...) MOZ_LOG(GetMediaSourceLog(), mozilla::LogLevel::Verbose, ("SourceBuffer(%p:%s)::%s: " arg, this, mType.OriginalString().Data(), __func__, ##__VA_ARGS__))
# define MSE_API(arg, ...) MOZ_LOG(GetMediaSourceAPILog(), mozilla::LogLevel::Debug, ("SourceBuffer(%p:%s)::%s: " arg, this, mType.OriginalString().Data(), __func__, ##__VA_ARGS__))
2013-06-21 03:14:42 +00:00
namespace mozilla {
2013-09-27 05:22:37 +00:00
2015-07-22 01:09:21 +00:00
using media : : TimeUnit ;
2016-03-27 09:20:40 +00:00
typedef SourceBufferAttributes : : AppendState AppendState ;
2015-07-22 01:09:21 +00:00
2013-06-21 03:14:42 +00:00
namespace dom {
void
SourceBuffer : : SetMode ( SourceBufferAppendMode aMode , ErrorResult & aRv )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2016-12-16 03:16:31 +00:00
MSE_API ( " SetMode(aMode=% " PRIu32 " ) " , static_cast < uint32_t > ( aMode ) ) ;
2013-09-27 05:22:37 +00:00
if ( ! IsAttached ( ) | | mUpdating ) {
2013-06-21 03:14:42 +00:00
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return ;
}
2016-03-27 09:20:40 +00:00
if ( mCurrentAttributes . mGenerateTimestamps & &
2015-06-11 05:55:20 +00:00
aMode = = SourceBufferAppendMode : : Segments ) {
2016-07-14 10:47:02 +00:00
aRv . Throw ( NS_ERROR_DOM_TYPE_ERR ) ;
2015-06-11 05:55:20 +00:00
return ;
}
2013-09-27 05:22:37 +00:00
MOZ_ASSERT ( mMediaSource - > ReadyState ( ) ! = MediaSourceReadyState : : Closed ) ;
2013-06-21 03:14:42 +00:00
if ( mMediaSource - > ReadyState ( ) = = MediaSourceReadyState : : Ended ) {
mMediaSource - > SetReadyState ( MediaSourceReadyState : : Open ) ;
}
2016-03-27 09:20:40 +00:00
if ( mCurrentAttributes . GetAppendState ( ) = = AppendState : : PARSING_MEDIA_SEGMENT ) {
2015-06-11 05:55:20 +00:00
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return ;
}
2015-09-14 07:52:30 +00:00
if ( aMode = = SourceBufferAppendMode : : Sequence ) {
2015-06-11 05:55:20 +00:00
// Will set GroupStartTimestamp to GroupEndTimestamp.
2016-03-27 09:20:40 +00:00
mCurrentAttributes . RestartGroupStartTimestamp ( ) ;
2015-06-11 05:55:20 +00:00
}
2016-03-27 09:20:40 +00:00
mCurrentAttributes . SetAppendMode ( aMode ) ;
2013-06-21 03:14:42 +00:00
}
void
SourceBuffer : : SetTimestampOffset ( double aTimestampOffset , ErrorResult & aRv )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2015-02-12 07:52:13 +00:00
MSE_API ( " SetTimestampOffset(aTimestampOffset=%f) " , aTimestampOffset ) ;
2013-09-27 05:22:37 +00:00
if ( ! IsAttached ( ) | | mUpdating ) {
2013-06-21 03:14:42 +00:00
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return ;
}
2013-09-27 05:22:37 +00:00
MOZ_ASSERT ( mMediaSource - > ReadyState ( ) ! = MediaSourceReadyState : : Closed ) ;
2013-06-21 03:14:42 +00:00
if ( mMediaSource - > ReadyState ( ) = = MediaSourceReadyState : : Ended ) {
mMediaSource - > SetReadyState ( MediaSourceReadyState : : Open ) ;
}
2016-03-27 09:20:40 +00:00
if ( mCurrentAttributes . GetAppendState ( ) = = AppendState : : PARSING_MEDIA_SEGMENT ) {
2015-06-11 05:55:20 +00:00
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return ;
}
2016-03-27 09:20:40 +00:00
mCurrentAttributes . SetApparentTimestampOffset ( aTimestampOffset ) ;
if ( mCurrentAttributes . GetAppendMode ( ) = = SourceBufferAppendMode : : Sequence ) {
mCurrentAttributes . SetGroupStartTimestamp ( mCurrentAttributes . GetTimestampOffset ( ) ) ;
2015-06-11 05:55:20 +00:00
}
}
2015-10-19 06:10:47 +00:00
TimeRanges *
2013-06-21 03:14:42 +00:00
SourceBuffer : : GetBuffered ( ErrorResult & aRv )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2015-10-19 06:10:47 +00:00
// http://w3c.github.io/media-source/index.html#widl-SourceBuffer-buffered
// 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an InvalidStateError exception and abort these steps.
2013-09-27 05:22:37 +00:00
if ( ! IsAttached ( ) ) {
2013-06-21 03:14:42 +00:00
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return nullptr ;
}
2015-10-19 06:10:47 +00:00
bool rangeChanged = true ;
2016-03-25 00:31:30 +00:00
media : : TimeIntervals intersection = mTrackBuffersManager - > Buffered ( ) ;
2015-10-19 06:10:47 +00:00
MSE_DEBUGV ( " intersection=%s " , DumpTimeRanges ( intersection ) . get ( ) ) ;
if ( mBuffered ) {
media : : TimeIntervals currentValue ( mBuffered ) ;
rangeChanged = ( intersection ! = currentValue ) ;
MSE_DEBUGV ( " currentValue=%s " , DumpTimeRanges ( currentValue ) . get ( ) ) ;
}
// 5. If intersection ranges does not contain the exact same range information as the current value of this attribute, then update the current value of this attribute to intersection ranges.
if ( rangeChanged ) {
mBuffered = new TimeRanges ( ToSupports ( this ) ) ;
intersection . ToTimeRanges ( mBuffered ) ;
}
// 6. Return the current value of this attribute.
return mBuffered ;
2013-06-21 03:14:42 +00:00
}
2015-06-17 21:22:10 +00:00
media : : TimeIntervals
SourceBuffer : : GetTimeIntervals ( )
{
2016-03-25 00:31:30 +00:00
return mTrackBuffersManager - > Buffered ( ) ;
2015-06-17 21:22:10 +00:00
}
2013-06-21 03:14:42 +00:00
void
SourceBuffer : : SetAppendWindowStart ( double aAppendWindowStart , ErrorResult & aRv )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2015-02-12 07:52:13 +00:00
MSE_API ( " SetAppendWindowStart(aAppendWindowStart=%f) " , aAppendWindowStart ) ;
2013-09-27 05:22:37 +00:00
if ( ! IsAttached ( ) | | mUpdating ) {
2013-06-21 03:14:42 +00:00
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return ;
}
2015-08-04 03:25:47 +00:00
if ( aAppendWindowStart < 0 | |
2016-03-27 09:20:40 +00:00
aAppendWindowStart > = mCurrentAttributes . GetAppendWindowEnd ( ) ) {
2016-07-14 10:47:02 +00:00
aRv . Throw ( NS_ERROR_DOM_TYPE_ERR ) ;
2013-06-21 03:14:42 +00:00
return ;
}
2016-03-27 09:20:40 +00:00
mCurrentAttributes . SetAppendWindowStart ( aAppendWindowStart ) ;
2013-06-21 03:14:42 +00:00
}
void
SourceBuffer : : SetAppendWindowEnd ( double aAppendWindowEnd , ErrorResult & aRv )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2015-02-12 07:52:13 +00:00
MSE_API ( " SetAppendWindowEnd(aAppendWindowEnd=%f) " , aAppendWindowEnd ) ;
2013-09-27 05:22:37 +00:00
if ( ! IsAttached ( ) | | mUpdating ) {
2013-06-21 03:14:42 +00:00
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return ;
}
2015-08-04 03:25:47 +00:00
if ( IsNaN ( aAppendWindowEnd ) | |
2016-03-27 09:20:40 +00:00
aAppendWindowEnd < = mCurrentAttributes . GetAppendWindowStart ( ) ) {
2016-07-14 10:47:02 +00:00
aRv . Throw ( NS_ERROR_DOM_TYPE_ERR ) ;
2013-06-21 03:14:42 +00:00
return ;
}
2016-03-27 09:20:40 +00:00
mCurrentAttributes . SetAppendWindowEnd ( aAppendWindowEnd ) ;
2013-06-21 03:14:42 +00:00
}
void
2013-08-05 17:40:01 +00:00
SourceBuffer : : AppendBuffer ( const ArrayBuffer & aData , ErrorResult & aRv )
2013-06-21 03:14:42 +00:00
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2015-02-12 07:52:13 +00:00
MSE_API ( " AppendBuffer(ArrayBuffer) " ) ;
Bug 999651, bug 995679, bug 1009952, bug 1011007, bug 991981. r=sfink, r=shu, r=jandem, r=jdm, r=luke, r=bbouvier, r=nmatsakis, r=bz, r=ehsan, r=jgilbert, r=smaug, r=sicking, r=terrence, r=bholley, r=bent, r=efaust, r=jorendorff
2014-05-27 21:32:41 +00:00
aData . ComputeLengthAndData ( ) ;
2013-06-21 03:14:42 +00:00
AppendData ( aData . Data ( ) , aData . Length ( ) , aRv ) ;
}
void
2013-08-05 17:40:01 +00:00
SourceBuffer : : AppendBuffer ( const ArrayBufferView & aData , ErrorResult & aRv )
2013-06-21 03:14:42 +00:00
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2015-02-12 07:52:13 +00:00
MSE_API ( " AppendBuffer(ArrayBufferView) " ) ;
Bug 999651, bug 995679, bug 1009952, bug 1011007, bug 991981. r=sfink, r=shu, r=jandem, r=jdm, r=luke, r=bbouvier, r=nmatsakis, r=bz, r=ehsan, r=jgilbert, r=smaug, r=sicking, r=terrence, r=bholley, r=bent, r=efaust, r=jorendorff
2014-05-27 21:32:41 +00:00
aData . ComputeLengthAndData ( ) ;
2013-06-21 03:14:42 +00:00
AppendData ( aData . Data ( ) , aData . Length ( ) , aRv ) ;
}
void
SourceBuffer : : Abort ( ErrorResult & aRv )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2015-02-12 07:52:13 +00:00
MSE_API ( " Abort() " ) ;
2013-09-27 05:22:37 +00:00
if ( ! IsAttached ( ) ) {
2013-06-21 03:14:42 +00:00
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return ;
}
if ( mMediaSource - > ReadyState ( ) ! = MediaSourceReadyState : : Open ) {
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return ;
}
2016-07-14 11:37:04 +00:00
if ( mPendingRemoval . Exists ( ) ) {
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return ;
}
2015-02-04 09:20:16 +00:00
AbortBufferAppend ( ) ;
2016-03-27 09:20:40 +00:00
ResetParserState ( ) ;
mCurrentAttributes . SetAppendWindowStart ( 0 ) ;
mCurrentAttributes . SetAppendWindowEnd ( PositiveInfinity < double > ( ) ) ;
2013-06-21 03:14:42 +00:00
}
2015-01-24 10:45:55 +00:00
void
2015-02-04 09:20:16 +00:00
SourceBuffer : : AbortBufferAppend ( )
2015-01-24 10:45:55 +00:00
{
if ( mUpdating ) {
2017-05-09 10:23:11 +00:00
mCompletionPromise . DisconnectIfExists ( ) ;
2016-02-11 13:55:55 +00:00
if ( mPendingAppend . Exists ( ) ) {
mPendingAppend . Disconnect ( ) ;
2016-03-25 00:31:30 +00:00
mTrackBuffersManager - > AbortAppendData ( ) ;
2016-02-11 13:55:55 +00:00
}
2015-01-24 10:45:55 +00:00
AbortUpdating ( ) ;
}
}
2016-03-27 09:20:40 +00:00
void
SourceBuffer : : ResetParserState ( )
{
mTrackBuffersManager - > ResetParserState ( mCurrentAttributes ) ;
}
2013-06-21 03:14:42 +00:00
void
SourceBuffer : : Remove ( double aStart , double aEnd , ErrorResult & aRv )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2015-02-12 07:52:13 +00:00
MSE_API ( " Remove(aStart=%f, aEnd=%f) " , aStart , aEnd ) ;
2014-08-27 02:24:01 +00:00
if ( ! IsAttached ( ) ) {
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return ;
}
2015-02-25 09:35:44 +00:00
if ( mUpdating ) {
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return ;
}
2014-08-13 13:41:00 +00:00
if ( IsNaN ( mMediaSource - > Duration ( ) ) | |
aStart < 0 | | aStart > mMediaSource - > Duration ( ) | |
aEnd < = aStart | | IsNaN ( aEnd ) ) {
2016-07-14 10:47:02 +00:00
aRv . Throw ( NS_ERROR_DOM_TYPE_ERR ) ;
2014-08-13 13:41:00 +00:00
return ;
}
2014-11-19 04:16:41 +00:00
if ( mMediaSource - > ReadyState ( ) = = MediaSourceReadyState : : Ended ) {
mMediaSource - > SetReadyState ( MediaSourceReadyState : : Open ) ;
}
2015-02-12 07:52:12 +00:00
2015-06-11 05:55:12 +00:00
RangeRemoval ( aStart , aEnd ) ;
2014-11-19 04:16:41 +00:00
}
void
SourceBuffer : : RangeRemoval ( double aStart , double aEnd )
{
2013-06-21 03:14:42 +00:00
StartUpdating ( ) ;
2015-01-24 10:45:58 +00:00
2015-10-18 05:24:48 +00:00
RefPtr < SourceBuffer > self = this ;
2016-07-14 11:37:04 +00:00
mTrackBuffersManager - > RangeRemoval ( TimeUnit : : FromSeconds ( aStart ) ,
TimeUnit : : FromSeconds ( aEnd ) )
2016-11-29 05:03:36 +00:00
- > Then ( mAbstractMainThread , __func__ ,
2016-07-14 11:37:04 +00:00
[ self ] ( bool ) {
self - > mPendingRemoval . Complete ( ) ;
self - > StopUpdating ( ) ;
} ,
2017-01-11 08:33:29 +00:00
[ ] ( ) { MOZ_ASSERT ( false ) ; } )
- > Track ( mPendingRemoval ) ;
2013-06-21 03:14:42 +00:00
}
void
2013-09-27 05:22:37 +00:00
SourceBuffer : : Detach ( )
2013-06-21 03:14:42 +00:00
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2015-02-12 07:52:13 +00:00
MSE_DEBUG ( " Detach " ) ;
2015-06-11 23:26:57 +00:00
if ( ! mMediaSource ) {
MSE_DEBUG ( " Already detached " ) ;
return ;
}
2015-02-04 09:20:16 +00:00
AbortBufferAppend ( ) ;
2016-03-25 00:31:30 +00:00
if ( mTrackBuffersManager ) {
mTrackBuffersManager - > Detach ( ) ;
2015-09-14 07:52:30 +00:00
mMediaSource - > GetDecoder ( ) - > GetDemuxer ( ) - > DetachSourceBuffer (
2016-03-25 00:31:30 +00:00
mTrackBuffersManager . get ( ) ) ;
2014-09-04 01:57:06 +00:00
}
2016-03-25 00:31:30 +00:00
mTrackBuffersManager = nullptr ;
2013-09-27 05:22:37 +00:00
mMediaSource = nullptr ;
2013-06-21 03:14:42 +00:00
}
void
2013-09-27 05:22:37 +00:00
SourceBuffer : : Ended ( )
2013-06-21 03:14:42 +00:00
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2014-09-04 01:57:06 +00:00
MOZ_ASSERT ( IsAttached ( ) ) ;
2015-02-12 07:52:13 +00:00
MSE_DEBUG ( " Ended " ) ;
2016-03-25 00:31:30 +00:00
mTrackBuffersManager - > Ended ( ) ;
2013-06-21 03:14:42 +00:00
}
Bug 1331289 - Use MediaContainerType in MediaResource, SourceBuffer, TrackBuffersManager, and dependencies - r=jya
Continuing the work of replacing MIME strings with MediaContainerType, starting
from MediaResource and following the dependencies.
Most changes are mechanical: Just change ns*String into MediaContainerType, and
MIME string literals into MEDIAMIMETYPE("a/b").
Some checks for empty/invalid strings and lowercase comparisons can go, thanks
to the always-valid always-lowercase-MIME invariants of MediaContainerType.
One special case in is MediaSourceResource, which used to have an empty string
as its type (because its own type is not relevant, but its SourceBuffers carry
types). Because the inherited GetContentType *must* be overridden, and must
return a MediaContainerType, we needed a valid type even though it should not
be seen in the real world. I've chosen "application/x.mediasource" for that.
MozReview-Commit-ID: 1aCH75Kh2e6
--HG--
extra : rebase_source : 0d9cd9b69c264e5dcfc3845f80ee107f4bcbcd9a
2016-12-28 07:59:02 +00:00
SourceBuffer : : SourceBuffer ( MediaSource * aMediaSource ,
const MediaContainerType & aType )
2014-04-01 06:13:50 +00:00
: DOMEventTargetHelper ( aMediaSource - > GetParentObject ( ) )
2013-06-21 03:14:42 +00:00
, mMediaSource ( aMediaSource )
2016-11-29 05:03:36 +00:00
, mAbstractMainThread ( aMediaSource - > AbstractMainThread ( ) )
Bug 1331289 - Use MediaContainerType in MediaResource, SourceBuffer, TrackBuffersManager, and dependencies - r=jya
Continuing the work of replacing MIME strings with MediaContainerType, starting
from MediaResource and following the dependencies.
Most changes are mechanical: Just change ns*String into MediaContainerType, and
MIME string literals into MEDIAMIMETYPE("a/b").
Some checks for empty/invalid strings and lowercase comparisons can go, thanks
to the always-valid always-lowercase-MIME invariants of MediaContainerType.
One special case in is MediaSourceResource, which used to have an empty string
as its type (because its own type is not relevant, but its SourceBuffers carry
types). Because the inherited GetContentType *must* be overridden, and must
return a MediaContainerType, we needed a valid type even though it should not
be seen in the real world. I've chosen "application/x.mediasource" for that.
MozReview-Commit-ID: 1aCH75Kh2e6
--HG--
extra : rebase_source : 0d9cd9b69c264e5dcfc3845f80ee107f4bcbcd9a
2016-12-28 07:59:02 +00:00
, mCurrentAttributes ( aType . Type ( ) = = MEDIAMIMETYPE ( " audio/mpeg " ) | |
aType . Type ( ) = = MEDIAMIMETYPE ( " audio/aac " ) )
2013-06-21 03:14:42 +00:00
, mUpdating ( false )
2015-03-18 03:10:56 +00:00
, mActive ( false )
2015-02-12 07:52:13 +00:00
, mType ( aType )
2013-06-21 03:14:42 +00:00
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2013-06-21 03:14:42 +00:00
MOZ_ASSERT ( aMediaSource ) ;
2015-08-04 03:25:47 +00:00
2016-03-25 00:31:30 +00:00
mTrackBuffersManager =
2016-03-27 09:20:40 +00:00
new TrackBuffersManager ( aMediaSource - > GetDecoder ( ) , aType ) ;
2016-03-25 00:31:30 +00:00
MSE_DEBUG ( " Create mTrackBuffersManager=%p " ,
mTrackBuffersManager . get ( ) ) ;
2015-08-04 03:25:47 +00:00
2015-06-11 05:55:20 +00:00
ErrorResult dummy ;
2016-03-27 09:20:40 +00:00
if ( mCurrentAttributes . mGenerateTimestamps ) {
2015-06-11 05:55:20 +00:00
SetMode ( SourceBufferAppendMode : : Sequence , dummy ) ;
} else {
SetMode ( SourceBufferAppendMode : : Segments , dummy ) ;
}
2015-09-14 07:52:30 +00:00
mMediaSource - > GetDecoder ( ) - > GetDemuxer ( ) - > AttachSourceBuffer (
2016-03-25 00:31:30 +00:00
mTrackBuffersManager . get ( ) ) ;
2014-04-21 13:31:00 +00:00
}
2013-09-27 05:22:37 +00:00
SourceBuffer : : ~ SourceBuffer ( )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2014-09-04 01:57:06 +00:00
MOZ_ASSERT ( ! mMediaSource ) ;
2015-02-12 07:52:13 +00:00
MSE_DEBUG ( " " ) ;
2013-06-21 03:14:42 +00:00
}
MediaSource *
SourceBuffer : : GetParentObject ( ) const
{
return mMediaSource ;
}
JSObject *
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 14:13:33 +00:00
SourceBuffer : : WrapObject ( JSContext * aCx , JS : : Handle < JSObject * > aGivenProto )
2013-06-21 03:14:42 +00:00
{
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 14:13:33 +00:00
return SourceBufferBinding : : Wrap ( aCx , this , aGivenProto ) ;
2013-06-21 03:14:42 +00:00
}
void
SourceBuffer : : DispatchSimpleEvent ( const char * aName )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2015-02-12 07:52:13 +00:00
MSE_API ( " Dispatch event '%s' " , aName ) ;
2013-06-21 03:14:42 +00:00
DispatchTrustedEvent ( NS_ConvertUTF8toUTF16 ( aName ) ) ;
}
void
SourceBuffer : : QueueAsyncSimpleEvent ( const char * aName )
{
2015-02-12 07:52:13 +00:00
MSE_DEBUG ( " Queuing event '%s' " , aName ) ;
2013-09-27 05:22:37 +00:00
nsCOMPtr < nsIRunnable > event = new AsyncEventRunner < SourceBuffer > ( this , aName ) ;
2017-03-01 07:08:50 +00:00
mAbstractMainThread - > Dispatch ( event . forget ( ) ) ;
2013-06-21 03:14:42 +00:00
}
void
SourceBuffer : : StartUpdating ( )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2013-06-21 03:14:42 +00:00
MOZ_ASSERT ( ! mUpdating ) ;
mUpdating = true ;
QueueAsyncSimpleEvent ( " updatestart " ) ;
}
void
SourceBuffer : : StopUpdating ( )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2014-09-23 03:47:30 +00:00
if ( ! mUpdating ) {
2016-02-11 13:55:55 +00:00
// The buffer append or range removal algorithm has been interrupted by
// abort().
2014-09-23 03:47:30 +00:00
return ;
}
2013-06-21 03:14:42 +00:00
mUpdating = false ;
QueueAsyncSimpleEvent ( " update " ) ;
QueueAsyncSimpleEvent ( " updateend " ) ;
}
void
SourceBuffer : : AbortUpdating ( )
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2013-06-21 03:14:42 +00:00
mUpdating = false ;
QueueAsyncSimpleEvent ( " abort " ) ;
QueueAsyncSimpleEvent ( " updateend " ) ;
}
2015-01-09 01:34:41 +00:00
void
SourceBuffer : : CheckEndTime ( )
{
2015-02-04 09:20:15 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2015-01-09 01:34:41 +00:00
// Check if we need to update mMediaSource duration
2016-03-27 09:20:40 +00:00
double endTime = mCurrentAttributes . GetGroupEndTimestamp ( ) . ToSeconds ( ) ;
2015-02-04 09:20:15 +00:00
double duration = mMediaSource - > Duration ( ) ;
if ( endTime > duration ) {
2016-07-15 13:38:33 +00:00
mMediaSource - > SetDuration ( endTime ) ;
2015-01-09 01:34:41 +00:00
}
}
2013-06-21 03:14:42 +00:00
void
SourceBuffer : : AppendData ( const uint8_t * aData , uint32_t aLength , ErrorResult & aRv )
{
2015-02-12 07:52:13 +00:00
MSE_DEBUG ( " AppendData(aLength=%u) " , aLength ) ;
2015-01-26 15:01:09 +00:00
2015-10-18 05:24:48 +00:00
RefPtr < MediaByteBuffer > data = PrepareAppend ( aData , aLength , aRv ) ;
2015-01-26 15:01:09 +00:00
if ( ! data ) {
2013-06-21 03:14:42 +00:00
return ;
}
StartUpdating ( ) ;
2014-09-17 06:33:00 +00:00
2017-05-05 02:27:51 +00:00
mTrackBuffersManager - > AppendData ( data . forget ( ) , mCurrentAttributes )
2016-11-29 05:03:36 +00:00
- > Then ( mAbstractMainThread , __func__ , this ,
2017-01-11 08:33:29 +00:00
& SourceBuffer : : AppendDataCompletedWithSuccess ,
& SourceBuffer : : AppendDataErrored )
- > Track ( mPendingAppend ) ;
2015-02-04 09:20:15 +00:00
}
void
2017-02-13 17:07:40 +00:00
SourceBuffer : : AppendDataCompletedWithSuccess ( const SourceBufferTask : : AppendBufferResult & aResult )
2015-02-04 09:20:15 +00:00
{
2016-02-11 13:55:55 +00:00
MOZ_ASSERT ( mUpdating ) ;
2015-02-04 09:20:16 +00:00
mPendingAppend . Complete ( ) ;
2015-01-16 12:48:24 +00:00
2016-03-27 09:20:40 +00:00
if ( aResult . first ( ) ) {
2015-03-18 03:10:56 +00:00
if ( ! mActive ) {
mActive = true ;
2017-05-09 10:23:11 +00:00
MSE_DEBUG ( " Init segment received " ) ;
RefPtr < SourceBuffer > self = this ;
mMediaSource - > SourceBufferIsActive ( this )
- > Then ( mAbstractMainThread , __func__ ,
[ self , this ] ( ) {
MSE_DEBUG ( " Complete AppendBuffer operation " ) ;
mCompletionPromise . Complete ( ) ;
StopUpdating ( ) ;
} )
- > Track ( mCompletionPromise ) ;
2015-03-18 03:10:56 +00:00
}
2015-06-16 05:57:22 +00:00
}
2015-09-14 07:52:30 +00:00
if ( mActive ) {
2017-06-19 06:24:40 +00:00
// Tell our parent decoder that we have received new data
// and send progress event.
2015-11-11 09:59:16 +00:00
mMediaSource - > GetDecoder ( ) - > NotifyDataArrived ( ) ;
2015-02-04 09:20:15 +00:00
}
2015-01-16 12:48:24 +00:00
2016-03-27 09:20:40 +00:00
mCurrentAttributes = aResult . second ( ) ;
2015-06-05 01:52:57 +00:00
CheckEndTime ( ) ;
2014-09-10 04:54:20 +00:00
2017-05-09 10:23:11 +00:00
if ( ! mCompletionPromise . Exists ( ) ) {
StopUpdating ( ) ;
}
2015-02-04 09:20:15 +00:00
}
void
2016-09-11 22:54:10 +00:00
SourceBuffer : : AppendDataErrored ( const MediaResult & aError )
2015-02-04 09:20:15 +00:00
{
2016-02-11 13:55:55 +00:00
MOZ_ASSERT ( mUpdating ) ;
2015-02-04 09:20:16 +00:00
mPendingAppend . Complete ( ) ;
2016-02-11 13:55:55 +00:00
2016-09-11 22:54:10 +00:00
switch ( aError . Code ( ) ) {
2016-09-12 02:22:20 +00:00
case NS_ERROR_DOM_MEDIA_CANCELED :
2015-02-04 09:20:16 +00:00
// Nothing further to do as the trackbuffer has been shutdown.
// or append was aborted and abort() has handled all the events.
2015-02-04 09:20:16 +00:00
break ;
default :
2016-09-11 22:54:10 +00:00
AppendError ( aError ) ;
2015-02-04 09:20:16 +00:00
break ;
}
2015-02-04 09:20:15 +00:00
}
2014-09-10 04:54:20 +00:00
2015-01-16 12:48:25 +00:00
void
2016-09-11 22:54:10 +00:00
SourceBuffer : : AppendError ( const MediaResult & aDecodeError )
2015-01-16 12:48:25 +00:00
{
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2016-02-11 13:55:55 +00:00
2016-03-27 09:20:40 +00:00
ResetParserState ( ) ;
2015-01-16 12:48:25 +00:00
mUpdating = false ;
QueueAsyncSimpleEvent ( " error " ) ;
QueueAsyncSimpleEvent ( " updateend " ) ;
2016-09-11 22:54:10 +00:00
MOZ_ASSERT ( NS_FAILED ( aDecodeError ) ) ;
mMediaSource - > EndOfStream ( aDecodeError ) ;
2015-01-16 12:48:25 +00:00
}
2015-06-15 04:37:13 +00:00
already_AddRefed < MediaByteBuffer >
2015-01-26 15:01:09 +00:00
SourceBuffer : : PrepareAppend ( const uint8_t * aData , uint32_t aLength , ErrorResult & aRv )
2014-09-10 04:54:20 +00:00
{
2016-03-25 00:31:30 +00:00
typedef TrackBuffersManager : : EvictDataResult Result ;
2015-06-05 01:52:57 +00:00
2014-09-10 04:54:20 +00:00
if ( ! IsAttached ( ) | | mUpdating ) {
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
2015-01-26 15:01:09 +00:00
return nullptr ;
2014-09-10 04:54:20 +00:00
}
2015-08-14 02:01:15 +00:00
// If the HTMLMediaElement.error attribute is not null, then throw an
// InvalidStateError exception and abort these steps.
if ( ! mMediaSource - > GetDecoder ( ) | |
2016-02-08 04:29:58 +00:00
mMediaSource - > GetDecoder ( ) - > OwnerHasError ( ) ) {
MSE_DEBUG ( " HTMLMediaElement.error is not null " ) ;
2015-08-14 02:01:15 +00:00
aRv . Throw ( NS_ERROR_DOM_INVALID_STATE_ERR ) ;
return nullptr ;
}
2014-09-10 04:54:20 +00:00
if ( mMediaSource - > ReadyState ( ) = = MediaSourceReadyState : : Ended ) {
mMediaSource - > SetReadyState ( MediaSourceReadyState : : Open ) ;
}
2014-02-28 00:54:48 +00:00
// Eviction uses a byte threshold. If the buffer is greater than the
2016-03-27 13:58:37 +00:00
// number of bytes then data is evicted.
2014-08-11 02:05:09 +00:00
// TODO: Drive evictions off memory pressure notifications.
2014-09-09 09:12:00 +00:00
// TODO: Consider a global eviction threshold rather than per TrackBuffer.
2016-03-27 13:58:37 +00:00
// Give a chance to the TrackBuffersManager to evict some data if needed.
2015-06-05 01:52:57 +00:00
Result evicted =
2016-03-25 00:31:30 +00:00
mTrackBuffersManager - > EvictData ( TimeUnit : : FromSeconds ( mMediaSource - > GetDecoder ( ) - > GetCurrentTime ( ) ) ,
2016-03-27 13:58:37 +00:00
aLength ) ;
2014-09-08 22:29:41 +00:00
2015-02-20 01:19:13 +00:00
// See if we have enough free space to append our new data.
2016-03-27 13:58:37 +00:00
if ( evicted = = Result : : BUFFER_FULL ) {
2015-02-20 01:19:13 +00:00
aRv . Throw ( NS_ERROR_DOM_QUOTA_EXCEEDED_ERR ) ;
return nullptr ;
}
2015-10-18 05:24:48 +00:00
RefPtr < MediaByteBuffer > data = new MediaByteBuffer ( ) ;
2015-05-28 18:07:43 +00:00
if ( ! data - > AppendElements ( aData , aLength , fallible ) ) {
2015-01-26 15:01:09 +00:00
aRv . Throw ( NS_ERROR_DOM_QUOTA_EXCEEDED_ERR ) ;
return nullptr ;
}
return data . forget ( ) ;
2014-02-28 00:54:48 +00:00
}
2014-08-11 04:32:21 +00:00
double
SourceBuffer : : GetBufferedStart ( )
2014-02-28 00:54:48 +00:00
{
2014-08-11 01:21:18 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2014-04-14 11:24:00 +00:00
ErrorResult dummy ;
2015-10-18 05:24:48 +00:00
RefPtr < TimeRanges > ranges = GetBuffered ( dummy ) ;
2014-08-11 04:32:21 +00:00
return ranges - > Length ( ) > 0 ? ranges - > GetStartTime ( ) : 0 ;
}
double
SourceBuffer : : GetBufferedEnd ( )
{
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
ErrorResult dummy ;
2015-10-18 05:24:48 +00:00
RefPtr < TimeRanges > ranges = GetBuffered ( dummy ) ;
2014-08-11 04:32:21 +00:00
return ranges - > Length ( ) > 0 ? ranges - > GetEndTime ( ) : 0 ;
2014-02-28 00:54:48 +00:00
}
2016-07-15 13:38:33 +00:00
double
SourceBuffer : : HighestStartTime ( )
{
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
return mTrackBuffersManager
? mTrackBuffersManager - > HighestStartTime ( ) . ToSeconds ( )
: 0.0 ;
}
2016-08-26 04:39:36 +00:00
double
SourceBuffer : : HighestEndTime ( )
{
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
return mTrackBuffersManager
? mTrackBuffersManager - > HighestEndTime ( ) . ToSeconds ( )
: 0.0 ;
}
2014-10-15 04:02:43 +00:00
NS_IMPL_CYCLE_COLLECTION_CLASS ( SourceBuffer )
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN ( SourceBuffer )
// Tell the TrackBuffer to end its current SourceBufferResource.
2016-03-25 00:31:30 +00:00
TrackBuffersManager * manager = tmp - > mTrackBuffersManager ;
2015-06-05 01:52:57 +00:00
if ( manager ) {
manager - > Detach ( ) ;
2014-10-15 04:02:43 +00:00
}
NS_IMPL_CYCLE_COLLECTION_UNLINK ( mMediaSource )
2015-10-19 06:10:47 +00:00
NS_IMPL_CYCLE_COLLECTION_UNLINK ( mBuffered )
2014-10-15 04:02:43 +00:00
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED ( DOMEventTargetHelper )
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED ( SourceBuffer ,
DOMEventTargetHelper )
NS_IMPL_CYCLE_COLLECTION_TRAVERSE ( mMediaSource )
2015-10-19 06:10:47 +00:00
NS_IMPL_CYCLE_COLLECTION_TRAVERSE ( mBuffered )
2014-10-15 04:02:43 +00:00
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
2013-06-21 03:14:42 +00:00
2014-04-01 06:13:50 +00:00
NS_IMPL_ADDREF_INHERITED ( SourceBuffer , DOMEventTargetHelper )
NS_IMPL_RELEASE_INHERITED ( SourceBuffer , DOMEventTargetHelper )
2013-06-21 03:14:42 +00:00
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED ( SourceBuffer )
2014-04-01 06:13:50 +00:00
NS_INTERFACE_MAP_END_INHERITING ( DOMEventTargetHelper )
2013-06-21 03:14:42 +00:00
2015-02-12 07:52:13 +00:00
# undef MSE_DEBUG
# undef MSE_DEBUGV
# undef MSE_API
2013-06-21 03:14:42 +00:00
} // namespace dom
2013-09-27 05:22:37 +00:00
2013-06-21 03:14:42 +00:00
} // namespace mozilla