diff --git a/content/canvas/test/webgl/skipped_tests_linux_mesa.txt b/content/canvas/test/webgl/skipped_tests_linux_mesa.txt index 1b8f512d601c..0fe0c4956cc8 100644 --- a/content/canvas/test/webgl/skipped_tests_linux_mesa.txt +++ b/content/canvas/test/webgl/skipped_tests_linux_mesa.txt @@ -1,5 +1,7 @@ conformance/limits/gl-max-texture-dimensions.html conformance/misc/type-conversion-test.html conformance/more/conformance/quickCheckAPI-B2.html +conformance/more/conformance/quickCheckAPI-B3.html +conformance/more/conformance/quickCheckAPI-B4.html conformance/reading/read-pixels-test.html conformance/textures/texture-mips.html diff --git a/content/media/AudioStream.cpp b/content/media/AudioStream.cpp index a197fd88f3ef..88c8aa6211f6 100644 --- a/content/media/AudioStream.cpp +++ b/content/media/AudioStream.cpp @@ -79,8 +79,9 @@ bool AudioStream::sCubebLatencyPrefSet; /*static*/ void AudioStream::InitPreferredSampleRate() { StaticMutexAutoLock lock(sMutex); - if (sPreferredSampleRate != 0 || - cubeb_get_preferred_sample_rate(GetCubebContextUnlocked(), &sPreferredSampleRate) != CUBEB_OK) { + if (sPreferredSampleRate == 0 && + cubeb_get_preferred_sample_rate(GetCubebContextUnlocked(), + &sPreferredSampleRate) != CUBEB_OK) { sPreferredSampleRate = 44100; } } diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp index e4900fe9edff..6259766f8905 100644 --- a/content/media/MediaStreamGraph.cpp +++ b/content/media/MediaStreamGraph.cpp @@ -711,7 +711,7 @@ MediaStreamGraphImpl::RecomputeBlockingAt(const nsTArray& aStreams STREAM_LOG(PR_LOG_DEBUG+1, ("MediaStream %p is blocked due to being finished", stream)); // We'll block indefinitely MarkStreamBlocking(stream); - *aEnd = aEndBlockingDecisions; + *aEnd = std::min(*aEnd, aEndBlockingDecisions); continue; } else { STREAM_LOG(PR_LOG_DEBUG+1, ("MediaStream %p is finished, but not blocked yet (end at %f, with blocking at %f)", @@ -734,7 +734,7 @@ MediaStreamGraphImpl::RecomputeBlockingAt(const nsTArray& aStreams if (underrun) { // We'll block indefinitely MarkStreamBlocking(stream); - *aEnd = aEndBlockingDecisions; + *aEnd = std::min(*aEnd, aEndBlockingDecisions); continue; } } diff --git a/content/media/encoder/fmp4_muxer/ISOControl.cpp b/content/media/encoder/fmp4_muxer/ISOControl.cpp index d8bb7e456510..041b601e5983 100644 --- a/content/media/encoder/fmp4_muxer/ISOControl.cpp +++ b/content/media/encoder/fmp4_muxer/ISOControl.cpp @@ -21,6 +21,7 @@ FragmentBuffer::FragmentBuffer(uint32_t aTrackType, uint32_t aFragDuration, , mFragDuration(aFragDuration) , mMediaStartTime(0) , mFragmentNumber(0) + , mLastFrameTimeOfLastFragment(0) , mEOS(false) { mFragArray.AppendElement(); diff --git a/content/media/encoder/fmp4_muxer/ISOControl.h b/content/media/encoder/fmp4_muxer/ISOControl.h index c370aa072d38..b5d697a9cb32 100644 --- a/content/media/encoder/fmp4_muxer/ISOControl.h +++ b/content/media/encoder/fmp4_muxer/ISOControl.h @@ -72,6 +72,14 @@ public: uint32_t GetType() { return mTrackType; } + void SetLastFragmentLastFrameTime(uint32_t aTime) { + mLastFrameTimeOfLastFragment = aTime; + } + + uint32_t GetLastFragmentLastFrameTime() { + return mLastFrameTimeOfLastFragment; + } + private: uint32_t mTrackType; @@ -92,6 +100,12 @@ private: // the current 'creating' fragment mFragNum in ISOControl. uint32_t mFragmentNumber; + // The last frame time stamp of last fragment. It is for calculating the + // play duration of first frame in current fragment. The frame duration is + // defined as "current frame timestamp - last frame timestamp" here. So it + // needs to keep the last timestamp of last fragment. + uint32_t mLastFrameTimeOfLastFragment; + // Array of fragments, each element has enough samples to form a // complete fragment. nsTArray>> mFragArray; diff --git a/content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp b/content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp index 0f24b72d3a3c..bbeb90fd2b40 100644 --- a/content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp +++ b/content/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp @@ -11,6 +11,7 @@ #include "ISOTrackMetadata.h" #include "MP4ESDS.h" #include "AVCBox.h" +#include "VideoUtils.h" namespace mozilla { @@ -126,19 +127,48 @@ TrackRunBox::fillSampleTable() } uint32_t len = frames.Length(); sample_info_table = new tbl[len]; + // Create sample table according to 14496-12 8.8.8.2. for (uint32_t i = 0; i < len; i++) { - sample_info_table[i].sample_duration = 0; - sample_info_table[i].sample_size = frames.ElementAt(i)->GetFrameData().Length(); - mAllSampleSize += sample_info_table[i].sample_size; - table_size += sizeof(uint32_t); + // Sample size. + sample_info_table[i].sample_size = 0; + if (flags.to_ulong() & flags_sample_size_present) { + sample_info_table[i].sample_size = frames.ElementAt(i)->GetFrameData().Length(); + mAllSampleSize += sample_info_table[i].sample_size; + table_size += sizeof(uint32_t); + } + + // Sample flags. + sample_info_table[i].sample_flags = 0; if (flags.to_ulong() & flags_sample_flags_present) { sample_info_table[i].sample_flags = set_sample_flags( (frames.ElementAt(i)->GetFrameType() == EncodedFrame::I_FRAME)); table_size += sizeof(uint32_t); - } else { - sample_info_table[i].sample_flags = 0; } + + // Sample duration. + sample_info_table[i].sample_duration = 0; + if (flags.to_ulong() & flags_sample_duration_present) { + // Calculate each frame's duration, it is decided by "current frame + // timestamp - last frame timestamp". + uint64_t frame_time = 0; + if (i == 0) { + frame_time = frames.ElementAt(i)->GetTimeStamp() - + frag->GetLastFragmentLastFrameTime(); + } else { + frame_time = frames.ElementAt(i)->GetTimeStamp() - + frames.ElementAt(i - 1)->GetTimeStamp(); + // Keep the last frame time of current fagment, it will be used to calculate + // the first frame duration of next fragment. + if ((len - 1) == i) { + frag->SetLastFragmentLastFrameTime(frames.ElementAt(i)->GetTimeStamp()); + } + } + sample_info_table[i].sample_duration = + frame_time * mMeta.mVidMeta->VideoFrequency / USECS_PER_S; + table_size += sizeof(uint32_t); + } + sample_info_table[i].sample_composition_time_offset = 0; } return table_size; @@ -180,7 +210,12 @@ TrackRunBox::Write() mControl->Write(data_offset); } for (uint32_t i = 0; i < sample_count; i++) { - mControl->Write(sample_info_table[i].sample_size); + if (flags.to_ulong() & flags_sample_duration_present) { + mControl->Write(sample_info_table[i].sample_duration); + } + if (flags.to_ulong() & flags_sample_size_present) { + mControl->Write(sample_info_table[i].sample_size); + } if (flags.to_ulong() & flags_sample_flags_present) { mControl->Write(sample_info_table[i].sample_flags); } @@ -197,6 +232,7 @@ TrackRunBox::TrackRunBox(uint32_t aType, uint32_t aFlags, ISOControl* aControl) , mAllSampleSize(0) , mTrackType(aType) { + mMeta.Init(aControl); MOZ_COUNT_CTOR(TrackRunBox); } @@ -218,15 +254,22 @@ TrackFragmentHeaderBox::Generate(uint32_t* aBoxSize) track_ID = mControl->GetTrackID(mTrackType); size += sizeof(track_ID); - if (flags.to_ulong() | base_data_offset_present) { + if (flags.to_ulong() & base_data_offset_present) { // base_data_offset needs to add size of 'trun', 'tfhd' and - // header of 'mdat 'later. + // header of 'mdat' later. base_data_offset = 0; size += sizeof(base_data_offset); } - if (flags.to_ulong() | default_sample_duration_present) { + if (flags.to_ulong() & default_sample_duration_present) { if (mTrackType == Video_Track) { - default_sample_duration = mMeta.mVidMeta->VideoFrequency / mMeta.mVidMeta->FrameRate; + if (!mMeta.mVidMeta->FrameRate) { + // 0 means frame rate is variant, so it is wrong to write + // default_sample_duration. + MOZ_ASSERT(0); + default_sample_duration = 0; + } else { + default_sample_duration = mMeta.mVidMeta->VideoFrequency / mMeta.mVidMeta->FrameRate; + } } else if (mTrackType == Audio_Track) { default_sample_duration = mMeta.mAudMeta->FrameDuration; } else { @@ -244,22 +287,19 @@ TrackFragmentHeaderBox::Write() { WRITE_FULLBOX(mControl, size) mControl->Write(track_ID); - if (flags.to_ulong() | base_data_offset_present) { + if (flags.to_ulong() & base_data_offset_present) { mControl->Write(base_data_offset); } - if (flags.to_ulong() | default_sample_duration_present) { + if (flags.to_ulong() & default_sample_duration_present) { mControl->Write(default_sample_duration); } return NS_OK; } TrackFragmentHeaderBox::TrackFragmentHeaderBox(uint32_t aType, + uint32_t aFlags, ISOControl* aControl) - // TODO: tf_flags, we may need to customize it from caller - : FullBox(NS_LITERAL_CSTRING("tfhd"), - 0, - base_data_offset_present | default_sample_duration_present, - aControl) + : FullBox(NS_LITERAL_CSTRING("tfhd"), 0, aFlags, aControl) , track_ID(0) , base_data_offset(0) , default_sample_duration(0) @@ -274,16 +314,33 @@ TrackFragmentHeaderBox::~TrackFragmentHeaderBox() MOZ_COUNT_DTOR(TrackFragmentHeaderBox); } -TrackFragmentBox::TrackFragmentBox(uint32_t aType, uint32_t aFlags, - ISOControl* aControl) +TrackFragmentBox::TrackFragmentBox(uint32_t aType, ISOControl* aControl) : DefaultContainerImpl(NS_LITERAL_CSTRING("traf"), aControl) , mTrackType(aType) { - boxes.AppendElement(new TrackFragmentHeaderBox(aType, aControl)); + // Flags in TrackFragmentHeaderBox. + uint32_t tf_flags = base_data_offset_present; + + // Audio frame rate should be fixed; otherwise it will cause noise when playback. + // So it doesn't need to keep duration of each audio frame in TrackRunBox. It + // keeps the default sample duration in TrackFragmentHeaderBox. + tf_flags |= (mTrackType & Audio_Track ? default_sample_duration_present : 0); + + boxes.AppendElement(new TrackFragmentHeaderBox(aType, tf_flags, aControl)); + + // Always adds flags_data_offset_present in each TrackRunBox, Android + // parser requires this flag to calculate the correct bitstream offset. + uint32_t tr_flags = flags_sample_size_present | flags_data_offset_present; + + // Flags in TrackRunBox. + // If there is no default sample duration exists, each frame duration needs to + // be recored in the TrackRunBox. + tr_flags |= (tf_flags & default_sample_duration_present ? 0 : flags_sample_duration_present); // For video, add sample_flags to record I frame. - aFlags |= (mTrackType & Video_Track ? flags_sample_flags_present : 0); - boxes.AppendElement(new TrackRunBox(mTrackType, aFlags, aControl)); + tr_flags |= (mTrackType & Video_Track ? flags_sample_flags_present : 0); + + boxes.AppendElement(new TrackRunBox(mTrackType, tr_flags, aControl)); MOZ_COUNT_CTOR(TrackFragmentBox); } @@ -329,19 +386,13 @@ MovieFragmentBox::MovieFragmentBox(uint32_t aType, ISOControl* aControl) { boxes.AppendElement(new MovieFragmentHeaderBox(mTrackType, aControl)); - // Always adds flags_data_offset_present in each TrackFragmentBox, Android - // parser requires this flag to calculate the correct bitstream offset. if (mTrackType & Audio_Track) { boxes.AppendElement( - new TrackFragmentBox(Audio_Track, - flags_sample_size_present | flags_data_offset_present, - aControl)); + new TrackFragmentBox(Audio_Track, aControl)); } if (mTrackType & Video_Track) { boxes.AppendElement( - new TrackFragmentBox(Video_Track, - flags_sample_size_present | flags_data_offset_present, - aControl)); + new TrackFragmentBox(Video_Track, aControl)); } MOZ_COUNT_CTOR(MovieFragmentBox); } @@ -388,8 +439,12 @@ TrackExtendsBox::Generate(uint32_t* aBoxSize) default_sample_flags = set_sample_flags(1); } else if (mTrackType == Video_Track) { default_sample_description_index = 1; - default_sample_duration = - mMeta.mVidMeta->VideoFrequency / mMeta.mVidMeta->FrameRate; + // Video meta data has assigned framerate, it implies that this video's + // frame rate should be fixed. + if (mMeta.mVidMeta->FrameRate) { + default_sample_duration = + mMeta.mVidMeta->VideoFrequency / mMeta.mVidMeta->FrameRate; + } default_sample_size = 0; default_sample_flags = set_sample_flags(0); } else { diff --git a/content/media/encoder/fmp4_muxer/ISOMediaBoxes.h b/content/media/encoder/fmp4_muxer/ISOMediaBoxes.h index 0e9902307bab..402edf20d5ea 100644 --- a/content/media/encoder/fmp4_muxer/ISOMediaBoxes.h +++ b/content/media/encoder/fmp4_muxer/ISOMediaBoxes.h @@ -299,6 +299,7 @@ protected: uint32_t mAllSampleSize; uint32_t mTrackType; + MetaHelper mMeta; }; // tf_flags in TrackFragmentHeaderBox, 14496-12 8.8.7.1. @@ -327,7 +328,7 @@ public: nsresult UpdateBaseDataOffset(uint64_t aOffset); // The offset of the first // sample in file. - TrackFragmentHeaderBox(uint32_t aType, ISOControl* aControl); + TrackFragmentHeaderBox(uint32_t aType, uint32_t aFlags, ISOControl* aControl); ~TrackFragmentHeaderBox(); protected: @@ -340,7 +341,7 @@ protected: // TrackFragmentBox cotains TrackFragmentHeaderBox and TrackRunBox. class TrackFragmentBox : public DefaultContainerImpl { public: - TrackFragmentBox(uint32_t aType, uint32_t aFlags, ISOControl* aControl); + TrackFragmentBox(uint32_t aType, ISOControl* aControl); ~TrackFragmentBox(); protected: diff --git a/content/media/encoder/fmp4_muxer/ISOMediaWriter.cpp b/content/media/encoder/fmp4_muxer/ISOMediaWriter.cpp index 94e270fa08f8..51c9cd1a5f00 100644 --- a/content/media/encoder/fmp4_muxer/ISOMediaWriter.cpp +++ b/content/media/encoder/fmp4_muxer/ISOMediaWriter.cpp @@ -9,6 +9,7 @@ #include "ISOTrackMetadata.h" #include "nsThreadUtils.h" #include "MediaEncoder.h" +#include "VideoUtils.h" #undef LOG #ifdef MOZ_WIDGET_GONK @@ -20,7 +21,7 @@ namespace mozilla { -const static uint32_t FRAG_DURATION = 2000000; // microsecond per unit +const static uint32_t FRAG_DURATION = 2 * USECS_PER_S; // microsecond per unit ISOMediaWriter::ISOMediaWriter(uint32_t aType) : ContainerWriter() diff --git a/content/media/webaudio/AudioContext.cpp b/content/media/webaudio/AudioContext.cpp index 773cab32ba52..deeb9898c6f0 100644 --- a/content/media/webaudio/AudioContext.cpp +++ b/content/media/webaudio/AudioContext.cpp @@ -66,7 +66,7 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) static uint8_t gWebAudioOutputKey; -float GetSampleRateForAudioContext(bool aIsOffline, float aSampleRate) +static float GetSampleRateForAudioContext(bool aIsOffline, float aSampleRate) { if (aIsOffline) { return aSampleRate; diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 4b6a610ce80c..cdda1cf2564d 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -3694,11 +3694,13 @@ nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings, if (mPrintEngine->HasPrintCallbackCanvas()) { mBeforeAndAfterPrint = beforeAndAfterPrint; } - dom::Element* root = mDocument->GetRootElement(); + dom::Element* root = doc->GetRootElement(); if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdisallowselectionprint)) { + PR_PL(("PrintPreview: found mozdisallowselectionprint")); mPrintEngine->SetDisallowSelectionPrint(true); } if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::moznomarginboxes)) { + PR_PL(("PrintPreview: found moznomarginboxes")); mPrintEngine->SetNoMarginBoxes(true); } rv = mPrintEngine->PrintPreview(aPrintSettings, aChildDOMWin, aWebProgressListener); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 5c207d45b12d..87bf48fc5c44 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1315,6 +1315,11 @@ nsLayoutUtils::GetAnimatedGeometryRootFor(nsIFrame* aFrame, break; if (ActiveLayerTracker::IsOffsetOrMarginStyleAnimated(f)) break; + if (!f->GetParent() && ViewportHasDisplayPort(f->PresContext())) { + // Viewport frames in a display port need to be animated geometry roots + // for background-attachment:fixed elements. + break; + } nsIFrame* parent = GetCrossDocParentFrame(f); if (!parent) break; diff --git a/testing/mochitest/b2g.json b/testing/mochitest/b2g.json index e8e1d73c5daf..2ab3ec06ddbc 100644 --- a/testing/mochitest/b2g.json +++ b/testing/mochitest/b2g.json @@ -47,6 +47,7 @@ "content/media/webspeech/synth/test/test_speech_queue.html": "Test timed out", "content/media/webspeech/synth/test/test_speech_simple.html": "Test timed out", + "content/media/webaudio/test/test_audioBufferSourceNodeOffset.html": "bug 906752", "content/media/webaudio/test/test_mozaudiochannel.html": "", "dom/imptests/editing/selecttest/test_addRange.html": "oom?, bug 775227", diff --git a/testing/xpcshell/runxpcshelltests.py b/testing/xpcshell/runxpcshelltests.py index a150cf0dcc05..712d9ace26b8 100644 --- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -796,7 +796,11 @@ class XPCShellTests(object): self.buildTestPath() - self.alltests = mp.active_tests(**mozinfo.info) + try: + self.alltests = mp.active_tests(**mozinfo.info) + except TypeError: + sys.stderr.write("*** offending mozinfo.info: %s\n" % repr(mozinfo.info)) + raise if self.singleFile is None and self.totalChunks > 1: self.chunkTests()