mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 1002297 - Seek in unbuffered ranges with MSE - r=kinetik
This commit is contained in:
parent
74c49d3d46
commit
1d1a56c87a
@ -3064,6 +3064,14 @@ void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatu
|
||||
return;
|
||||
}
|
||||
|
||||
// Section 2.4.3.1 of the Media Source Extensions spec requires
|
||||
// changing to HAVE_METADATA when seeking into an unbuffered
|
||||
// range.
|
||||
if (aNextFrame == MediaDecoderOwner::NEXT_FRAME_WAIT_FOR_MSE_DATA) {
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mReadyState > nsIDOMHTMLMediaElement::HAVE_METADATA &&
|
||||
mDownloadSuspendedByCache &&
|
||||
mDecoder &&
|
||||
|
@ -119,6 +119,9 @@ public:
|
||||
NEXT_FRAME_UNAVAILABLE_BUFFERING,
|
||||
// The next frame of audio/video is unavailable for some other reasons
|
||||
NEXT_FRAME_UNAVAILABLE,
|
||||
// The next frame is unavailable due to waiting for more Media Source
|
||||
// Extensions data to become available.
|
||||
NEXT_FRAME_WAIT_FOR_MSE_DATA,
|
||||
// Sentinel value
|
||||
NEXT_FRAME_UNINITIALIZED
|
||||
};
|
||||
|
@ -299,6 +299,7 @@ MediaSource::MediaSource(nsPIDOMWindow* aWindow)
|
||||
, mDuration(UnspecifiedNaN<double>())
|
||||
, mDecoder(nullptr)
|
||||
, mReadyState(MediaSourceReadyState::Closed)
|
||||
, mWaitForDataMonitor("MediaSource.WaitForData.Monitor")
|
||||
{
|
||||
mSourceBuffers = new SourceBufferList(this);
|
||||
mActiveSourceBuffers = new SourceBufferList(this);
|
||||
@ -395,6 +396,20 @@ MediaSource::NotifyEvicted(double aStart, double aEnd)
|
||||
mSourceBuffers->Evict(aStart, aEnd);
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::WaitForData()
|
||||
{
|
||||
MonitorAutoLock lock(mWaitForDataMonitor);
|
||||
lock.Wait();
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::NotifyGotData()
|
||||
{
|
||||
MonitorAutoLock lock(mWaitForDataMonitor);
|
||||
lock.NotifyAll();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaSource, DOMEventTargetHelper,
|
||||
mSourceBuffers, mActiveSourceBuffers)
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/MediaSourceBinding.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionNoteChild.h"
|
||||
@ -89,6 +90,12 @@ public:
|
||||
// that were evicted are provided.
|
||||
void NotifyEvicted(double aStart, double aEnd);
|
||||
|
||||
// Block thread waiting for data to be appended to a SourceBuffer.
|
||||
void WaitForData();
|
||||
|
||||
// Unblock threads waiting for data to be appended to a SourceBuffer.
|
||||
void NotifyGotData();
|
||||
|
||||
private:
|
||||
explicit MediaSource(nsPIDOMWindow* aWindow);
|
||||
|
||||
@ -106,6 +113,10 @@ private:
|
||||
nsRefPtr<MediaSourceDecoder> mDecoder;
|
||||
|
||||
MediaSourceReadyState mReadyState;
|
||||
|
||||
// Monitor for waiting for when new data is appended to
|
||||
// a Source Buffer.
|
||||
Monitor mWaitForDataMonitor;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(MediaSource, MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)
|
||||
|
@ -130,6 +130,11 @@ public:
|
||||
|
||||
void InitializePendingDecoders();
|
||||
|
||||
bool IsShutdown() {
|
||||
ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
|
||||
return mDecoder->IsShutdown();
|
||||
}
|
||||
|
||||
private:
|
||||
bool MaybeSwitchVideoReaders(int64_t aTimeThreshold) {
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
@ -383,25 +388,60 @@ MediaSourceReader::CreateSubDecoder(const nsACString& aType, MediaSourceDecoder*
|
||||
return decoder.forget();
|
||||
}
|
||||
|
||||
namespace {
|
||||
class ChangeToHaveMetadata : public nsRunnable {
|
||||
public:
|
||||
ChangeToHaveMetadata(AbstractMediaDecoder* aDecoder) :
|
||||
mDecoder(aDecoder)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
|
||||
auto owner = mDecoder->GetOwner();
|
||||
if (owner) {
|
||||
owner->UpdateReadyStateForData(MediaDecoderOwner::NEXT_FRAME_WAIT_FOR_MSE_DATA);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<AbstractMediaDecoder> mDecoder;
|
||||
};
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
|
||||
int64_t aCurrentTime)
|
||||
{
|
||||
ResetDecode();
|
||||
if (!mMediaSource->ActiveSourceBuffers()->AllContainsTime (aTime / USECS_PER_S)) {
|
||||
NS_DispatchToMainThread(new ChangeToHaveMetadata(mDecoder));
|
||||
}
|
||||
|
||||
dom::SourceBufferList* sbl = mMediaSource->ActiveSourceBuffers();
|
||||
if (sbl->AllContainsTime (aTime / USECS_PER_S)) {
|
||||
if (GetAudioReader()) {
|
||||
nsresult rv = GetAudioReader()->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
// Loop until we have the requested time range in the source buffers.
|
||||
// This is a workaround for our lack of async functionality in the
|
||||
// MediaDecoderStateMachine. Bug 979104 implements what we need and
|
||||
// we'll remove this for an async approach based on that in bug XXXXXXX.
|
||||
while (!mMediaSource->ActiveSourceBuffers()->AllContainsTime (aTime / USECS_PER_S)
|
||||
&& !IsShutdown()) {
|
||||
mMediaSource->WaitForData();
|
||||
MaybeSwitchVideoReaders(aTime);
|
||||
}
|
||||
|
||||
if (IsShutdown()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ResetDecode();
|
||||
if (GetAudioReader()) {
|
||||
nsresult rv = GetAudioReader()->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (GetVideoReader()) {
|
||||
nsresult rv = GetVideoReader()->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
if (GetVideoReader()) {
|
||||
nsresult rv = GetVideoReader()->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -493,6 +493,8 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
|
||||
// Schedule the state machine thread to ensure playback starts
|
||||
// if required when data is appended.
|
||||
mMediaSource->GetDecoder()->ScheduleStateMachineThread();
|
||||
|
||||
mMediaSource->NotifyGotData();
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user