зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1062669 - Consider only SourceBuffers created before the first initialization segment is appended as essential for parent decoder initialization. r=cajbir
This commit is contained in:
Родитель
0f5f1f0b5d
Коммит
4335ec1e50
|
@ -339,6 +339,7 @@ MediaSource::Detach()
|
|||
}
|
||||
mDecoder->DetachMediaSource();
|
||||
mDecoder = nullptr;
|
||||
mFirstSourceBufferInitialization = false;
|
||||
SetReadyState(MediaSourceReadyState::Closed);
|
||||
mDuration = UnspecifiedNaN<double>();
|
||||
if (mActiveSourceBuffers) {
|
||||
|
@ -395,6 +396,7 @@ MediaSource::MediaSource(nsPIDOMWindow* aWindow)
|
|||
, mDuration(UnspecifiedNaN<double>())
|
||||
, mDecoder(nullptr)
|
||||
, mReadyState(MediaSourceReadyState::Closed)
|
||||
, mFirstSourceBufferInitialization(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mSourceBuffers = new SourceBufferList(this);
|
||||
|
@ -482,6 +484,29 @@ MediaSource::NotifyEvicted(double aStart, double aEnd)
|
|||
mSourceBuffers->Evict(aStart, aEnd);
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::QueueInitializationEvent()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mFirstSourceBufferInitialization) {
|
||||
mFirstSourceBufferInitialization = true;
|
||||
}
|
||||
MSE_DEBUG("MediaSource(%p)::QueueInitializationEvent()", this);
|
||||
nsRefPtr<nsIRunnable> task =
|
||||
NS_NewRunnableMethod(this, &MediaSource::InitializationEvent);
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::InitializationEvent()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MSE_DEBUG("MediaSource(%p)::InitializationEvent()", this);
|
||||
if (mDecoder) {
|
||||
mDecoder->PrepareReaderInitialization();
|
||||
}
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
MediaSource::GetParentObject() const
|
||||
{
|
||||
|
|
|
@ -90,6 +90,14 @@ public:
|
|||
// that were evicted are provided.
|
||||
void NotifyEvicted(double aStart, double aEnd);
|
||||
|
||||
// Queue InitializationEvent to run on the main thread. Called when a
|
||||
// SourceBuffer has an initialization segment appended, but only
|
||||
// dispatched the first time (using mFirstSourceBufferInitialization).
|
||||
// Demarcates the point in time at which only currently registered
|
||||
// TrackBuffers are treated as essential by the MediaSourceReader for
|
||||
// initialization.
|
||||
void QueueInitializationEvent();
|
||||
|
||||
private:
|
||||
~MediaSource();
|
||||
|
||||
|
@ -101,6 +109,8 @@ private:
|
|||
|
||||
void DurationChange(double aNewDuration, ErrorResult& aRv);
|
||||
|
||||
void InitializationEvent();
|
||||
|
||||
double mDuration;
|
||||
|
||||
nsRefPtr<SourceBufferList> mSourceBuffers;
|
||||
|
@ -109,6 +119,8 @@ private:
|
|||
nsRefPtr<MediaSourceDecoder> mDecoder;
|
||||
|
||||
MediaSourceReadyState mReadyState;
|
||||
|
||||
bool mFirstSourceBufferInitialization;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(MediaSource, MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)
|
||||
|
|
|
@ -188,4 +188,11 @@ MediaSourceDecoder::NotifyGotData()
|
|||
mon.NotifyAll();
|
||||
}
|
||||
|
||||
void
|
||||
MediaSourceDecoder::PrepareReaderInitialization()
|
||||
{
|
||||
MOZ_ASSERT(mReader);
|
||||
mReader->PrepareInitialization();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -61,6 +61,10 @@ public:
|
|||
// Called whenever a SourceBuffer has new data appended.
|
||||
void NotifyGotData();
|
||||
|
||||
// Indicates the point in time at which the reader should consider
|
||||
// registered TrackBuffers essential for initialization.
|
||||
void PrepareReaderInitialization();
|
||||
|
||||
private:
|
||||
// The owning MediaSource holds a strong reference to this decoder, and
|
||||
// calls Attach/DetachMediaSource on this decoder to set and clear
|
||||
|
|
|
@ -46,19 +46,33 @@ MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder)
|
|||
, mEnded(false)
|
||||
, mAudioIsSeeking(false)
|
||||
, mVideoIsSeeking(false)
|
||||
, mHasEssentialTrackBuffers(false)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
MediaSourceReader::PrepareInitialization()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
MSE_DEBUG("MediaSourceReader(%p)::PrepareInitialization trackBuffers=%u",
|
||||
this, mTrackBuffers.Length());
|
||||
mEssentialTrackBuffers.AppendElements(mTrackBuffers);
|
||||
mHasEssentialTrackBuffers = true;
|
||||
mDecoder->NotifyWaitingForResourcesStatusChanged();
|
||||
}
|
||||
|
||||
bool
|
||||
MediaSourceReader::IsWaitingMediaResources()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
|
||||
if (!mTrackBuffers[i]->IsReady()) {
|
||||
|
||||
for (uint32_t i = 0; i < mEssentialTrackBuffers.Length(); ++i) {
|
||||
if (!mEssentialTrackBuffers[i]->IsReady()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return mTrackBuffers.IsEmpty();
|
||||
|
||||
return !mHasEssentialTrackBuffers;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -367,6 +381,7 @@ void
|
|||
MediaSourceReader::OnTrackBufferConfigured(TrackBuffer* aTrackBuffer, const MediaInfo& aInfo)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
MOZ_ASSERT(aTrackBuffer->IsReady());
|
||||
MOZ_ASSERT(mTrackBuffers.Contains(aTrackBuffer));
|
||||
if (aInfo.HasAudio() && !mAudioTrack) {
|
||||
MSE_DEBUG("MediaSourceReader(%p)::OnTrackBufferConfigured %p audio", this, aTrackBuffer);
|
||||
|
@ -472,11 +487,15 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
|
|||
nsresult
|
||||
MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
||||
{
|
||||
MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata tracks=%u", this, mTrackBuffers.Length());
|
||||
bool waiting = IsWaitingMediaResources();
|
||||
MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata waiting=%d tracks=%u/%u audio=%p video=%p",
|
||||
this, waiting, mEssentialTrackBuffers.Length(), mTrackBuffers.Length(),
|
||||
mAudioTrack.get(), mVideoTrack.get());
|
||||
// ReadMetadata is called *before* checking IsWaitingMediaResources.
|
||||
if (IsWaitingMediaResources()) {
|
||||
if (waiting) {
|
||||
return NS_OK;
|
||||
}
|
||||
mEssentialTrackBuffers.Clear();
|
||||
if (!mAudioTrack && !mVideoTrack) {
|
||||
MSE_DEBUG("MediaSourceReader(%p)::ReadMetadata missing track: mAudioTrack=%p mVideoTrack=%p",
|
||||
this, mAudioTrack.get(), mVideoTrack.get());
|
||||
|
|
|
@ -40,6 +40,10 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Indicates the point in time at which the reader should consider
|
||||
// registered TrackBuffers essential for initialization.
|
||||
void PrepareInitialization();
|
||||
|
||||
bool IsWaitingMediaResources() MOZ_OVERRIDE;
|
||||
|
||||
void RequestAudioData() MOZ_OVERRIDE;
|
||||
|
@ -105,6 +109,7 @@ private:
|
|||
nsRefPtr<MediaDecoderReader> mVideoReader;
|
||||
|
||||
nsTArray<nsRefPtr<TrackBuffer>> mTrackBuffers;
|
||||
nsTArray<nsRefPtr<TrackBuffer>> mEssentialTrackBuffers;
|
||||
nsRefPtr<TrackBuffer> mAudioTrack;
|
||||
nsRefPtr<TrackBuffer> mVideoTrack;
|
||||
|
||||
|
@ -125,6 +130,8 @@ private:
|
|||
// after a seek.
|
||||
bool mAudioIsSeeking;
|
||||
bool mVideoIsSeeking;
|
||||
|
||||
bool mHasEssentialTrackBuffers;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -564,6 +564,7 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
|
|||
// TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
|
||||
if (mParser->IsInitSegmentPresent(aData, aLength)) {
|
||||
MSE_DEBUG("SourceBuffer(%p)::AppendData: New initialization segment.", this);
|
||||
mMediaSource->QueueInitializationEvent();
|
||||
mTrackBuffer->DiscardDecoder();
|
||||
if (!mTrackBuffer->NewDecoder()) {
|
||||
aRv.Throw(NS_ERROR_FAILURE); // XXX: Review error handling.
|
||||
|
|
Загрузка…
Ссылка в новой задаче