mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1065219 - Move track format rejection from switch to init time. r=cajbir
This commit is contained in:
parent
aac36c1acd
commit
925a080866
@ -227,44 +227,8 @@ MediaSourceReader::BreakCycles()
|
||||
mTrackBuffers.Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
MediaSourceReader::CanSelectAudioReader(MediaDecoderReader* aNewReader)
|
||||
{
|
||||
AudioInfo currentInfo = mAudioReader->GetMediaInfo().mAudio;
|
||||
AudioInfo newInfo = aNewReader->GetMediaInfo().mAudio;
|
||||
|
||||
// TODO: We can't handle switching audio formats yet.
|
||||
if (currentInfo.mRate != newInfo.mRate ||
|
||||
currentInfo.mChannels != newInfo.mChannels) {
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::CanSelectAudioReader(%p) skip reader due to format mismatch",
|
||||
this, aNewReader);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aNewReader->AudioQueue().AtEndOfStream()) {
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::CanSelectAudioReader(%p) skip reader due to queue EOS",
|
||||
this, aNewReader);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MediaSourceReader::CanSelectVideoReader(MediaDecoderReader* aNewReader)
|
||||
{
|
||||
if (aNewReader->VideoQueue().AtEndOfStream()) {
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::CanSelectVideoReader(%p) skip reader due to queue EOS",
|
||||
this, aNewReader);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<MediaDecoderReader>
|
||||
MediaSourceReader::SelectReader(int64_t aTarget,
|
||||
bool (MediaSourceReader::*aCanSelectReader)(MediaDecoderReader*),
|
||||
const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders)
|
||||
{
|
||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
@ -274,13 +238,6 @@ MediaSourceReader::SelectReader(int64_t aTarget,
|
||||
for (int32_t i = aTrackDecoders.Length() - 1; i >= 0; --i) {
|
||||
nsRefPtr<MediaDecoderReader> newReader = aTrackDecoders[i]->GetReader();
|
||||
|
||||
// Check the track-type-specific aspects first, as it's assumed these
|
||||
// are cheaper than a buffered range comparison, which seems worthwhile
|
||||
// to avoid on any reader we'd subsequently reject.
|
||||
if (!(this->*aCanSelectReader)(newReader)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
|
||||
aTrackDecoders[i]->GetBuffered(ranges);
|
||||
if (ranges->Find(double(aTarget) / USECS_PER_S) == dom::TimeRanges::NoIndex) {
|
||||
@ -303,9 +260,7 @@ MediaSourceReader::SwitchAudioReader(int64_t aTarget)
|
||||
if (!mAudioTrack) {
|
||||
return false;
|
||||
}
|
||||
nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget,
|
||||
&MediaSourceReader::CanSelectAudioReader,
|
||||
mAudioTrack->Decoders());
|
||||
nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget, mAudioTrack->Decoders());
|
||||
if (newReader && newReader != mAudioReader) {
|
||||
mAudioReader->SetIdle();
|
||||
mAudioReader = newReader;
|
||||
@ -323,9 +278,7 @@ MediaSourceReader::SwitchVideoReader(int64_t aTarget)
|
||||
if (!mVideoTrack) {
|
||||
return false;
|
||||
}
|
||||
nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget,
|
||||
&MediaSourceReader::CanSelectVideoReader,
|
||||
mVideoTrack->Decoders());
|
||||
nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget, mVideoTrack->Decoders());
|
||||
if (newReader && newReader != mVideoReader) {
|
||||
mVideoReader->SetIdle();
|
||||
mVideoReader = newReader;
|
||||
|
@ -105,22 +105,11 @@ private:
|
||||
bool SwitchAudioReader(int64_t aTarget);
|
||||
bool SwitchVideoReader(int64_t aTarget);
|
||||
|
||||
// Return a reader from the set available in aTrackDecoders that is considered
|
||||
// usable by the aCanUserReader callback and has data available in the range
|
||||
// requested by aTarget.
|
||||
// aCanSelectReader is passed each reader available in aTrackDecoders and is
|
||||
// expected to return true if the reader is considerable selectable.
|
||||
// Return a reader from the set available in aTrackDecoders that has data
|
||||
// available in the range requested by aTarget.
|
||||
already_AddRefed<MediaDecoderReader> SelectReader(int64_t aTarget,
|
||||
bool (MediaSourceReader::*aCanSelectReader)(MediaDecoderReader*),
|
||||
const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders);
|
||||
|
||||
// Passed to SelectReader to enforce any track format specific requirements.
|
||||
// In the case of CanSelectAudioReader, verifies that aNewReader has a
|
||||
// matching audio format to the existing reader, as format switching is not
|
||||
// yet supported.
|
||||
bool CanSelectAudioReader(MediaDecoderReader* aNewReader);
|
||||
bool CanSelectVideoReader(MediaDecoderReader* aNewReader);
|
||||
|
||||
// Waits on the decoder monitor for aTime to become available in the active
|
||||
// TrackBuffers. Used to block a Seek call until the necessary data has been
|
||||
// provided to the relevant SourceBuffers.
|
||||
|
@ -49,8 +49,6 @@ TrackBuffer::TrackBuffer(MediaSourceDecoder* aParentDecoder, const nsACString& a
|
||||
, mLastStartTimestamp(0)
|
||||
, mLastEndTimestamp(0)
|
||||
, mHasInit(false)
|
||||
, mHasAudio(false)
|
||||
, mHasVideo(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(TrackBuffer);
|
||||
mTaskQueue = new MediaTaskQueue(GetMediaDecodeThreadPool());
|
||||
@ -218,11 +216,7 @@ TrackBuffer::InitializeDecoder(nsRefPtr<SourceBufferDecoder> aDecoder)
|
||||
MSE_DEBUG("TrackBuffer(%p): Reader %p failed to initialize rv=%x audio=%d video=%d",
|
||||
this, reader, rv, mi.HasAudio(), mi.HasVideo());
|
||||
aDecoder->SetTaskQueue(nullptr);
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
|
||||
mDecoders.RemoveElement(aDecoder);
|
||||
}
|
||||
NS_DispatchToMainThread(new ReleaseDecoderTask(aDecoder));
|
||||
RemoveDecoder(aDecoder);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -235,11 +229,36 @@ TrackBuffer::InitializeDecoder(nsRefPtr<SourceBufferDecoder> aDecoder)
|
||||
this, reader, mi.mAudio.mRate, mi.mAudio.mChannels);
|
||||
}
|
||||
|
||||
if (!RegisterDecoder(aDecoder)) {
|
||||
// XXX: Need to signal error back to owning SourceBuffer.
|
||||
MSE_DEBUG("TrackBuffer(%p): Reader %p not activated", this, reader);
|
||||
RemoveDecoder(aDecoder);
|
||||
return;
|
||||
}
|
||||
MSE_DEBUG("TrackBuffer(%p): Reader %p activated", this, reader);
|
||||
RegisterDecoder(aDecoder);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
TrackBuffer::ValidateTrackFormats(const MediaInfo& aInfo)
|
||||
{
|
||||
if (mInfo.HasAudio() != aInfo.HasAudio() ||
|
||||
mInfo.HasVideo() != aInfo.HasVideo()) {
|
||||
MSE_DEBUG("TrackBuffer(%p)::ValidateTrackFormats audio/video track mismatch", this);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Support dynamic audio format changes.
|
||||
if (mInfo.HasAudio() &&
|
||||
(mInfo.mAudio.mRate != aInfo.mAudio.mRate ||
|
||||
mInfo.mAudio.mChannels != aInfo.mAudio.mChannels)) {
|
||||
MSE_DEBUG("TrackBuffer(%p)::ValidateTrackFormats audio format mismatch", this);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TrackBuffer::RegisterDecoder(nsRefPtr<SourceBufferDecoder> aDecoder)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
|
||||
@ -247,14 +266,16 @@ TrackBuffer::RegisterDecoder(nsRefPtr<SourceBufferDecoder> aDecoder)
|
||||
const MediaInfo& info = aDecoder->GetReader()->GetMediaInfo();
|
||||
// Initialize the track info since this is the first decoder.
|
||||
if (mInitializedDecoders.IsEmpty()) {
|
||||
mHasAudio = info.HasAudio();
|
||||
mHasVideo = info.HasVideo();
|
||||
mParentDecoder->OnTrackBufferConfigured(this, info);
|
||||
} else if ((info.HasAudio() && !mHasAudio) || (info.HasVideo() && !mHasVideo)) {
|
||||
mInfo = info;
|
||||
mParentDecoder->OnTrackBufferConfigured(this, mInfo);
|
||||
}
|
||||
if (!ValidateTrackFormats(info)) {
|
||||
MSE_DEBUG("TrackBuffer(%p)::RegisterDecoder with mismatched audio/video tracks", this);
|
||||
return false;
|
||||
}
|
||||
mInitializedDecoders.AppendElement(aDecoder);
|
||||
mParentDecoder->NotifyTimeRangesChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
@ -287,8 +308,8 @@ bool
|
||||
TrackBuffer::IsReady()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
|
||||
MOZ_ASSERT((mHasAudio || mHasVideo) || mInitializedDecoders.IsEmpty());
|
||||
return HasInitSegment() && (mHasAudio || mHasVideo);
|
||||
MOZ_ASSERT((mInfo.HasAudio() || mInfo.HasVideo()) || mInitializedDecoders.IsEmpty());
|
||||
return HasInitSegment() && (mInfo.HasAudio() || mInfo.HasVideo());
|
||||
}
|
||||
|
||||
void
|
||||
@ -373,4 +394,13 @@ TrackBuffer::Dump(const char* aPath)
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
TrackBuffer::RemoveDecoder(nsRefPtr<SourceBufferDecoder> aDecoder)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
|
||||
MOZ_ASSERT(!mInitializedDecoders.Contains(aDecoder));
|
||||
mDecoders.RemoveElement(aDecoder);
|
||||
NS_DispatchToMainThread(new ReleaseDecoderTask(aDecoder));
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -98,8 +98,19 @@ private:
|
||||
|
||||
// Adds a successfully initialized decoder to mDecoders and (if it's the
|
||||
// first decoder initialized), initializes mHasAudio/mHasVideo. Called
|
||||
// from the decode thread pool.
|
||||
void RegisterDecoder(nsRefPtr<SourceBufferDecoder> aDecoder);
|
||||
// from the decode thread pool. Return true if the decoder was
|
||||
// successfully registered.
|
||||
bool RegisterDecoder(nsRefPtr<SourceBufferDecoder> aDecoder);
|
||||
|
||||
// Returns true if aInfo is considered a supported or the same format as
|
||||
// the TrackBuffer was initialized as.
|
||||
bool ValidateTrackFormats(const MediaInfo& aInfo);
|
||||
|
||||
// Remove aDecoder from mDecoders and dispatch an event to the main thread
|
||||
// to clean up the decoder. If aDecoder was added to
|
||||
// mInitializedDecoders, it must have been removed before calling this
|
||||
// function.
|
||||
void RemoveDecoder(nsRefPtr<SourceBufferDecoder> aDecoder);
|
||||
|
||||
// A task queue using the shared media thread pool. Used exclusively to
|
||||
// initialize (i.e. call ReadMetadata on) decoders as they are created via
|
||||
@ -131,8 +142,7 @@ private:
|
||||
|
||||
// Set when the first decoder used by this TrackBuffer is initialized.
|
||||
// Protected by mParentDecoder's monitor.
|
||||
bool mHasAudio;
|
||||
bool mHasVideo;
|
||||
MediaInfo mInfo;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
Loading…
Reference in New Issue
Block a user