Bug 880062 - Make WMF video backend call MediaDecoder::SetMediaSeekable(false) when it can't seek like it's supposed to. r=padenot

This commit is contained in:
Chris Pearce 2013-06-13 10:15:23 +12:00
parent 4812496f90
commit 66d1fa1f4a
7 changed files with 142 additions and 10 deletions

View File

@ -38,7 +38,7 @@ MOCHITEST_FILES = \
can_play_type_ogg.js \
can_play_type_wave.js \
can_play_type_webm.js \
can_play_type_dash.js \
can_play_type_dash.js \
can_play_type_mpeg.js \
cancellable_request.sjs \
dynamic_redirect.sjs \
@ -138,6 +138,7 @@ MOCHITEST_FILES = \
test_streams_tracks.html \
$(filter disabled-for-intermittent-failures--bug-608634, test_error_in_video_document.html) \
test_timeupdate_small_files.html \
test_unseekable.html \
$(NULL)
# Disabled on Windows for frequent intermittent failures
@ -187,6 +188,7 @@ MOCHITEST_FILES += \
audio-gaps.ogg \
badtags.ogg \
beta-phrasebook.ogg \
big-buck-bunny-unseekable.mp4 \
bogus.ogv \
bug495129.ogv \
bug495794.ogg \
@ -230,6 +232,7 @@ MOCHITEST_FILES += \
variable-preskip.opus \
dirac.ogg \
multiple-bos.ogg \
no-cues.webm \
owl.mp3 \
split.webm \
seek.ogv \

Binary file not shown.

View File

@ -315,6 +315,27 @@ var gSeekTests = [
{ name:"bogus.duh", type:"bogus/duh", duration:123 }
];
function IsWindows8OrLater() {
var re = /Windows NT (\d.\d)/;
var winver = navigator.userAgent.match(re);
return winver && winver.length == 2 && parseFloat(winver[1]) >= 6.2;
}
// These are files that are non seekable, due to problems with the media,
// for example broken or missing indexes.
var gUnseekableTests = [
{ name:"no-cues.webm", type:"video/webm" },
{ name:"bogus.duh", type:"bogus/duh"}
];
// Unfortunately big-buck-bunny-unseekable.mp4 is doesn't play on Windows 7, so
// only include it in the unseekable tests if we're on later versions of Windows.
if (navigator.userAgent.indexOf("Windows") == -1 ||
IsWindows8OrLater()) {
gUnseekableTests = gUnseekableTests.concat([
{ name:"big-buck-bunny-unseekable.mp4", type:"video/mp4" }
]);
}
// These are files suitable for using with a "new Audio" constructor.
var gAudioTests = [
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },

Binary file not shown.

View File

@ -0,0 +1,101 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Media test: unseekable</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
/*
Test that unseekable media can't be seeked. We load a media that shouldn't
be seekable, and play through once. While playing through we repeatedly try
to seek and check that nothing happens when we do. We also verify that the
seekable ranges are empty.
*/
var manager = new MediaTestManager;
var onseeking = function(event) {
var v = event.target;
v.actuallySeeked = true;
};
var onseeked = function(event) {
var v = event.target;
v.actuallySeeked = true;
};
var ontimeupdate = function(event) {
var v = event.target;
// Check that when we seek nothing happens.
var t = v.currentTime;
v.currentTime = v.currentTime /= 2;
ok(Math.abs(t - v.currentTime) < 0.01, "Current time shouldn't change when seeking in unseekable media: " + v.name);
// Check that the seekable ranges are empty.
is(v.seekable.length, 0, "Should have no seekable ranges in unseekable media: " + v.name);
};
var onended = function(event) {
var v = event.target;
// Remove the event listeners so that they can't run if there are any pending
// events.
v.removeEventListener("seeking", onseeking, false);
v.removeEventListener("seeked", onseeked, false);
v.removeEventListener("timeupdate", ontimeupdate, false);
v.removeEventListener("ended", onended, false);
v.src = "";
if (v.parentNode) {
v.parentNode.removeChild(v);
}
// Verify that none of the seeks we did in timeupdate actually seeked.
ok(!v.actuallySeeked, "Should not be able to seek in unseekable media: " + v.name);
manager.finished(v.token);
}
function startTest(test, token) {
var v = document.createElement('video');
manager.started(token);
v.name = test.name;
v.src = test.name;
v.token = token;
v.autoplay = "true";
v.actuallySeeked = false;
v.addEventListener("seeking", onseeking, false);
v.addEventListener("seeked", onseeked, false);
v.addEventListener("timeupdate", ontimeupdate, false);
v.addEventListener("ended", onended, false);
document.body.appendChild(v);
}
function canPlay(candidates) {
var v = document.createElement("video");
var resources = candidates.filter(function(x){return v.canPlayType(x.type);});
return (resources.length > 0);
}
if (canPlay(gUnseekableTests)) {
manager.runTests(gUnseekableTests, startTest);
} else {
todo(false, "No files of supported format to test");
}
</script>
</pre>
</body>
</html>

View File

@ -52,7 +52,6 @@ WMFReader::WMFReader(AbstractMediaDecoder* aDecoder)
mAudioFrameOffset(0),
mHasAudio(false),
mHasVideo(false),
mCanSeek(false),
mUseHwAccel(false),
mMustRecaptureAudioPosition(true),
mIsMP3Enabled(WMFDecoder::IsMP3Supported())
@ -583,14 +582,21 @@ WMFReader::ReadMetadata(VideoInfo* aInfo,
// Abort if both video and audio failed to initialize.
NS_ENSURE_TRUE(mInfo.mHasAudio || mInfo.mHasVideo, NS_ERROR_FAILURE);
// Get the duration, and report it to the decoder if we have it.
int64_t duration = 0;
if (SUCCEEDED(GetSourceReaderDuration(mSourceReader, duration))) {
hr = GetSourceReaderDuration(mSourceReader, duration);
if (SUCCEEDED(hr)) {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mDecoder->SetMediaDuration(duration);
}
hr = GetSourceReaderCanSeek(mSourceReader, mCanSeek);
NS_ASSERTION(SUCCEEDED(hr), "Can't determine if resource is seekable");
// We can seek if we get a duration *and* the reader reports that it's
// seekable.
bool canSeek = false;
if (FAILED(hr) ||
FAILED(GetSourceReaderCanSeek(mSourceReader, canSeek)) ||
!canSeek) {
mDecoder->SetMediaSeekable(false);
}
*aInfo = mInfo;
*aTags = nullptr;
@ -986,9 +992,11 @@ WMFReader::Seek(int64_t aTargetUs,
LOG("WMFReader::Seek() %lld", aTargetUs);
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
if (!mCanSeek) {
return NS_ERROR_FAILURE;
}
#ifdef DEBUG
bool canSeek = false;
GetSourceReaderCanSeek(mSourceReader, canSeek);
NS_ASSERTION(canSeek, "WMFReader::Seek() should only be called if we can seek!");
#endif
nsresult rv = ResetDecode();
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -109,7 +109,6 @@ private:
bool mHasAudio;
bool mHasVideo;
bool mCanSeek;
bool mUseHwAccel;
// We can't call WMFDecoder::IsMP3Supported() on non-main threads, since it