LCOV - app.info - objdir/dist/include/nsMediaDecoder.h

LCOV - code coverage report
| Current view: | directory - objdir/dist/include - nsMediaDecoder.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 29 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 11 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
           3                 : /* ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is Mozilla code.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is the Mozilla Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 2007
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *  Chris Double <chris.double@double.co.nz>
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 : #if !defined(nsMediaDecoder_h_)
          39                 : #define nsMediaDecoder_h_
          40                 :
          41                 : #include "ImageLayers.h"
          42                 : #include "mozilla/ReentrantMonitor.h"
          43                 : #include "VideoFrameContainer.h"
          44                 :
          45                 : class nsHTMLMediaElement;
          46                 : class nsIStreamListener;
          47                 : class nsTimeRanges;
          48                 : class nsIMemoryReporter;
          49                 : class nsIPrincipal;
          50                 : class nsITimer;
          51                 :
          52                 : namespace mozilla {
          53                 : class MediaResource;
          54                 : }
          55                 :
          56                 : // The size to use for audio data frames in MozAudioAvailable events.
          57                 : // This value is per channel, and is chosen to give ~43 fps of events,
          58                 : // for example, 44100 with 2 channels, 2*1024 = 2048.
          59                 : static const PRUint32 FRAMEBUFFER_LENGTH_PER_CHANNEL = 1024;
          60                 :
          61                 : // The total size of the framebuffer used for MozAudioAvailable events
          62                 : // has to be within the following range.
          63                 : static const PRUint32 FRAMEBUFFER_LENGTH_MIN = 512;
          64                 : static const PRUint32 FRAMEBUFFER_LENGTH_MAX = 16384;
          65                 :
          66                 : // All methods of nsMediaDecoder must be called from the main thread only
          67                 : // with the exception of GetVideoFrameContainer and GetStatistics,
          68                 : // which can be called from any thread.
          69                 : class nsMediaDecoder : public nsIObserver
          70                 : {
          71                 : public:
          72                 :   typedef mozilla::MediaResource MediaResource;
          73                 :   typedef mozilla::ReentrantMonitor ReentrantMonitor;
          74                 :   typedef mozilla::TimeStamp TimeStamp;
          75                 :   typedef mozilla::TimeDuration TimeDuration;
          76                 :   typedef mozilla::VideoFrameContainer VideoFrameContainer;
          77                 :   typedef mozilla::layers::Image Image;
          78                 :   typedef mozilla::layers::ImageContainer ImageContainer;
          79                 :
          80                 :   nsMediaDecoder();
          81                 :   virtual ~nsMediaDecoder();
          82                 :
          83                 :   // Create a new decoder of the same type as this one.
          84                 :   virtual nsMediaDecoder* Clone() = 0;
          85                 :
          86                 :   // Perform any initialization required for the decoder.
          87                 :   // Return true on successful initialisation, false
          88                 :   // on failure.
          89                 :   virtual bool Init(nsHTMLMediaElement* aElement);
          90                 :
          91                 :   // Get the current MediaResource being used. Its URI will be returned
          92                 :   // by currentSrc. Returns what was passed to Load(), if Load() has been called.
          93                 :   virtual MediaResource* GetResource() = 0;
          94                 :
          95                 :   // Return the principal of the current URI being played or downloaded.
          96                 :   virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() = 0;
          97                 :
          98                 :   // Return the time position in the video stream being
          99                 :   // played measured in seconds.
         100                 :   virtual double GetCurrentTime() = 0;
         101                 :
         102                 :   // Seek to the time position in (seconds) from the start of the video.
         103                 :   virtual nsresult Seek(double aTime) = 0;
         104                 :
         105                 :   // Called by the element when the playback rate has been changed.
         106                 :   // Adjust the speed of the playback, optionally with pitch correction,
         107                 :   // when this is called.
         108                 :   virtual nsresult PlaybackRateChanged() = 0;
         109                 :
         110                 :   // Return the duration of the video in seconds.
         111                 :   virtual double GetDuration() = 0;
         112                 :
         113                 :   // A media stream is assumed to be infinite if the metadata doesn't
         114                 :   // contain the duration, and range requests are not supported, and
         115                 :   // no headers give a hint of a possible duration (Content-Length,
         116                 :   // Content-Duration, and variants), and we cannot seek in the media
         117                 :   // stream to determine the duration.
         118                 :   //
         119                 :   // When the media stream ends, we can know the duration, thus the stream is
         120                 :   // no longer considered to be infinite.
         121                 :   virtual void SetInfinite(bool aInfinite) = 0;
         122                 :
         123                 :   // Return true if the stream is infinite (see SetInfinite).
         124                 :   virtual bool IsInfinite() = 0;
         125                 :
         126                 :   // Pause video playback.
         127                 :   virtual void Pause() = 0;
         128                 :
         129                 :   // Set the audio volume. It should be a value from 0 to 1.0.
         130                 :   virtual void SetVolume(double aVolume) = 0;
         131                 :
         132                 :   // Start playback of a video. 'Load' must have previously been
         133                 :   // called.
         134                 :   virtual nsresult Play() = 0;
         135                 :
         136                 :   // Start downloading the media. Decode the downloaded data up to the
         137                 :   // point of the first frame of data.
         138                 :   // aResource is the media stream to use. Ownership of aResource passes to
         139                 :   // the decoder, even if Load returns an error.
         140                 :   // This is called at most once per decoder, after Init().
         141                 :   virtual nsresult Load(MediaResource* aResource,
         142                 :                         nsIStreamListener **aListener,
         143                 :                         nsMediaDecoder* aCloneDonor) = 0;
         144                 :
         145                 :   // Called when the video file has completed downloading.
         146                 :   virtual void ResourceLoaded() = 0;
         147                 :
         148                 :   // Called if the media file encounters a network error.
         149                 :   virtual void NetworkError() = 0;
         150                 :
         151                 :   // Call from any thread safely. Return true if we are currently
         152                 :   // seeking in the media resource.
         153                 :   virtual bool IsSeeking() const = 0;
         154                 :
         155                 :   // Return true if the decoder has reached the end of playback.
         156                 :   // Call in the main thread only.
         157                 :   virtual bool IsEnded() const = 0;
         158                 :
         159                 :   // Called when a "MozAudioAvailable" event listener is added. This enables
         160                 :   // the decoder to only dispatch "MozAudioAvailable" events when a
         161                 :   // handler exists, reducing overhead. Called on the main thread.
         162                 :   virtual void NotifyAudioAvailableListener() = 0;
         163                 :
         164                 :   struct Statistics {
         165                 :     // Estimate of the current playback rate (bytes/second).
         166                 :     double mPlaybackRate;
         167                 :     // Estimate of the current download rate (bytes/second). This
         168                 :     // ignores time that the channel was paused by Gecko.
         169                 :     double mDownloadRate;
         170                 :     // Total length of media stream in bytes; -1 if not known
         171                 :     PRInt64 mTotalBytes;
         172                 :     // Current position of the download, in bytes. This is the offset of
         173                 :     // the first uncached byte after the decoder position.
         174                 :     PRInt64 mDownloadPosition;
         175                 :     // Current position of decoding, in bytes (how much of the stream
         176                 :     // has been consumed)
         177                 :     PRInt64 mDecoderPosition;
         178                 :     // Current position of playback, in bytes
         179                 :     PRInt64 mPlaybackPosition;
         180                 :     // If false, then mDownloadRate cannot be considered a reliable
         181                 :     // estimate (probably because the download has only been running
         182                 :     // a short time).
         183                 :     bool mDownloadRateReliable;
         184                 :     // If false, then mPlaybackRate cannot be considered a reliable
         185                 :     // estimate (probably because playback has only been running
         186                 :     // a short time).
         187                 :     bool mPlaybackRateReliable;
         188                 :   };
         189                 :
         190                 :   // Frame decoding/painting related performance counters.
         191                 :   // Threadsafe.
         192                 :   class FrameStatistics {
         193                 :   public:
         194                 :
         195                 :     FrameStatistics() :
         196                 :         mReentrantMonitor("nsMediaDecoder::FrameStats"),
         197                 :         mParsedFrames(0),
         198                 :         mDecodedFrames(0),
         199                 :         mPresentedFrames(0) {}
         200                 :
         201                 :     // Returns number of frames which have been parsed from the media.
         202                 :     // Can be called on any thread.
         203               0 :     PRUint32 GetParsedFrames() {
         204               0 :       mozilla::ReentrantMonitorAutoEnter mon(mReentrantMonitor);
         205               0 :       return mParsedFrames;
         206                 :     }
         207                 :
         208                 :     // Returns the number of parsed frames which have been decoded.
         209                 :     // Can be called on any thread.
         210               0 :     PRUint32 GetDecodedFrames() {
         211               0 :       mozilla::ReentrantMonitorAutoEnter mon(mReentrantMonitor);
         212               0 :       return mDecodedFrames;
         213                 :     }
         214                 :
         215                 :     // Returns the number of decoded frames which have been sent to the rendering
         216                 :     // pipeline for painting ("presented").
         217                 :     // Can be called on any thread.
         218               0 :     PRUint32 GetPresentedFrames() {
         219               0 :       mozilla::ReentrantMonitorAutoEnter mon(mReentrantMonitor);
         220               0 :       return mPresentedFrames;
         221                 :     }
         222                 :
         223                 :     // Increments the parsed and decoded frame counters by the passed in counts.
         224                 :     // Can be called on any thread.
         225               0 :     void NotifyDecodedFrames(PRUint32 aParsed, PRUint32 aDecoded) {
         226               0 :       if (aParsed == 0 && aDecoded == 0)
         227               0 :         return;
         228               0 :       mozilla::ReentrantMonitorAutoEnter mon(mReentrantMonitor);
         229               0 :       mParsedFrames += aParsed;
         230               0 :       mDecodedFrames += aDecoded;
         231                 :     }
         232                 :
         233                 :     // Increments the presented frame counters.
         234                 :     // Can be called on any thread.
         235                 :     void NotifyPresentedFrame() {
         236                 :       mozilla::ReentrantMonitorAutoEnter mon(mReentrantMonitor);
         237                 :       ++mPresentedFrames;
         238                 :     }
         239                 :
         240                 :   private:
         241                 :
         242                 :     // ReentrantMonitor to protect access of playback statistics.
         243                 :     ReentrantMonitor mReentrantMonitor;
         244                 :
         245                 :     // Number of frames parsed and demuxed from media.
         246                 :     // Access protected by mStatsReentrantMonitor.
         247                 :     PRUint32 mParsedFrames;
         248                 :
         249                 :     // Number of parsed frames which were actually decoded.
         250                 :     // Access protected by mStatsReentrantMonitor.
         251                 :     PRUint32 mDecodedFrames;
         252                 :
         253                 :     // Number of decoded frames which were actually sent down the rendering
         254                 :     // pipeline to be painted ("presented"). Access protected by mStatsReentrantMonitor.
         255                 :     PRUint32 mPresentedFrames;
         256                 :   };
         257                 :
         258                 :   // Stack based class to assist in notifying the frame statistics of
         259                 :   // parsed and decoded frames. Use inside video demux & decode functions
         260                 :   // to ensure all parsed and decoded frames are reported on all return paths.
         261                 :   class AutoNotifyDecoded {
         262                 :   public:
         263               0 :     AutoNotifyDecoded(nsMediaDecoder* aDecoder, PRUint32& aParsed, PRUint32& aDecoded)
         264               0 :       : mDecoder(aDecoder), mParsed(aParsed), mDecoded(aDecoded) {}
         265               0 :     ~AutoNotifyDecoded() {
         266               0 :       mDecoder->GetFrameStatistics().NotifyDecodedFrames(mParsed, mDecoded);
         267               0 :     }
         268                 :   private:
         269                 :     nsMediaDecoder* mDecoder;
         270                 :     PRUint32& mParsed;
         271                 :     PRUint32& mDecoded;
         272                 :   };
         273                 :
         274                 :   // Return statistics. This is used for progress events and other things.
         275                 :   // This can be called from any thread. It's only a snapshot of the
         276                 :   // current state, since other threads might be changing the state
         277                 :   // at any time.
         278                 :   virtual Statistics GetStatistics() = 0;
         279                 :
         280                 :   // Return the frame decode/paint related statistics.
         281               0 :   FrameStatistics& GetFrameStatistics() { return mFrameStats; }
         282                 :
         283                 :   // Set the duration of the media resource in units of seconds.
         284                 :   // This is called via a channel listener if it can pick up the duration
         285                 :   // from a content header. Must be called from the main thread only.
         286                 :   virtual void SetDuration(double aDuration) = 0;
         287                 :
         288                 :   // Set a flag indicating whether seeking is supported
         289                 :   virtual void SetSeekable(bool aSeekable) = 0;
         290                 :
         291                 :   // Return true if seeking is supported.
         292                 :   virtual bool IsSeekable() = 0;
         293                 :
         294                 :   // Return the time ranges that can be seeked into.
         295                 :   virtual nsresult GetSeekable(nsTimeRanges* aSeekable) = 0;
         296                 :
         297                 :   // Set the end time of the media resource. When playback reaches
         298                 :   // this point the media pauses. aTime is in seconds.
         299                 :   virtual void SetEndTime(double aTime) = 0;
         300                 :
         301                 :   // Invalidate the frame.
         302               0 :   void Invalidate()
         303                 :   {
         304               0 :     if (mVideoFrameContainer) {
         305               0 :       mVideoFrameContainer->Invalidate();
         306                 :     }
         307               0 :   }
         308                 :
         309                 :   // Fire progress events if needed according to the time and byte
         310                 :   // constraints outlined in the specification. aTimer is true
         311                 :   // if the method is called as a result of the progress timer rather
         312                 :   // than the result of downloaded data.
         313                 :   virtual void Progress(bool aTimer);
         314                 :
         315                 :   // Fire timeupdate events if needed according to the time constraints
         316                 :   // outlined in the specification.
         317                 :   virtual void FireTimeUpdate();
         318                 :
         319                 :   // Called by MediaResource when the "cache suspended" status changes.
         320                 :   // If MediaResource::IsSuspendedByCache returns true, then the decoder
         321                 :   // should stop buffering or otherwise waiting for download progress and
         322                 :   // start consuming data, if possible, because the cache is full.
         323                 :   virtual void NotifySuspendedStatusChanged() = 0;
         324                 :
         325                 :   // Called by MediaResource when some data has been received.
         326                 :   // Call on the main thread only.
         327                 :   virtual void NotifyBytesDownloaded() = 0;
         328                 :
         329                 :   // Called by nsChannelToPipeListener or MediaResource when the
         330                 :   // download has ended. Called on the main thread only. aStatus is
         331                 :   // the result from OnStopRequest.
         332                 :   virtual void NotifyDownloadEnded(nsresult aStatus) = 0;
         333                 :
         334                 :   // Called as data arrives on the stream and is read into the cache.  Called
         335                 :   // on the main thread only.
         336                 :   virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset) = 0;
         337                 :
         338                 :   // Cleanup internal data structures. Must be called on the main
         339                 :   // thread by the owning object before that object disposes of this object.
         340                 :   virtual void Shutdown();
         341                 :
         342                 :   // Suspend any media downloads that are in progress. Called by the
         343                 :   // media element when it is sent to the bfcache, or when we need
         344                 :   // to throttle the download. Call on the main thread only. This can
         345                 :   // be called multiple times, there's an internal "suspend count".
         346                 :   virtual void Suspend() = 0;
         347                 :
         348                 :   // Resume any media downloads that have been suspended. Called by the
         349                 :   // media element when it is restored from the bfcache, or when we need
         350                 :   // to stop throttling the download. Call on the main thread only.
         351                 :   // The download will only actually resume once as many Resume calls
         352                 :   // have been made as Suspend calls. When aForceBuffering is true,
         353                 :   // we force the decoder to go into buffering state before resuming
         354                 :   // playback.
         355                 :   virtual void Resume(bool aForceBuffering) = 0;
         356                 :
         357                 :   // Returns a weak reference to the media element we're decoding for,
         358                 :   // if it's available.
         359                 :   nsHTMLMediaElement* GetMediaElement();
         360                 :
         361                 :   // Returns the current size of the framebuffer used in
         362                 :   // MozAudioAvailable events.
         363               0 :   PRUint32 GetFrameBufferLength() { return mFrameBufferLength; };
         364                 :
         365                 :   // Sets the length of the framebuffer used in MozAudioAvailable events.
         366                 :   // The new size must be between 512 and 16384.
         367                 :   virtual nsresult RequestFrameBufferLength(PRUint32 aLength);
         368                 :
         369                 :   // Moves any existing channel loads into the background, so that they don't
         370                 :   // block the load event. This is called when we stop delaying the load
         371                 :   // event. Any new loads initiated (for example to seek) will also be in the
         372                 :   // background. Implementations of this must call MoveLoadsToBackground() on
         373                 :   // their MediaResource.
         374                 :   virtual void MoveLoadsToBackground()=0;
         375                 :
         376                 :   // Constructs the time ranges representing what segments of the media
         377                 :   // are buffered and playable.
         378                 :   virtual nsresult GetBuffered(nsTimeRanges* aBuffered) = 0;
         379                 :
         380                 :   // Returns true if we can play the entire media through without stopping
         381                 :   // to buffer, given the current download and playback rates.
         382                 :   bool CanPlayThrough();
         383                 :
         384                 :   // Returns the size, in bytes, of the heap memory used by the currently
         385                 :   // queued decoded video and audio data.
         386                 :   virtual PRInt64 VideoQueueMemoryInUse() = 0;
         387                 :   virtual PRInt64 AudioQueueMemoryInUse() = 0;
         388                 :
         389               0 :   VideoFrameContainer* GetVideoFrameContainer() { return mVideoFrameContainer; }
         390               0 :   ImageContainer* GetImageContainer()
         391                 :   {
         392               0 :     return mVideoFrameContainer ? mVideoFrameContainer->GetImageContainer() : nsnull;
         393                 :   }
         394                 :
         395                 : protected:
         396                 :
         397                 :   // Start timer to update download progress information.
         398                 :   nsresult StartProgress();
         399                 :
         400                 :   // Stop progress information timer.
         401                 :   nsresult StopProgress();
         402                 :
         403                 :   // Ensures our media stream has been pinned.
         404                 :   void PinForSeek();
         405                 :
         406                 :   // Ensures our media stream has been unpinned.
         407                 :   void UnpinForSeek();
         408                 :
         409                 :   // Timer used for updating progress events
         410                 :   nsCOMPtr<nsITimer> mProgressTimer;
         411                 :
         412                 :   // This should only ever be accessed from the main thread.
         413                 :   // It is set in Init and cleared in Shutdown when the element goes away.
         414                 :   // The decoder does not add a reference the element.
         415                 :   nsHTMLMediaElement* mElement;
         416                 :
         417                 :   // Counters related to decode and presentation of frames.
         418                 :   FrameStatistics mFrameStats;
         419                 :
         420                 :   nsRefPtr<VideoFrameContainer> mVideoFrameContainer;
         421                 :
         422                 :   // Time that the last progress event was fired. Read/Write from the
         423                 :   // main thread only.
         424                 :   TimeStamp mProgressTime;
         425                 :
         426                 :   // Time that data was last read from the media resource. Used for
         427                 :   // computing if the download has stalled and to rate limit progress events
         428                 :   // when data is arriving slower than PROGRESS_MS. A value of null indicates
         429                 :   // that a stall event has already fired and not to fire another one until
         430                 :   // more data is received. Read/Write from the main thread only.
         431                 :   TimeStamp mDataTime;
         432                 :
         433                 :   // The framebuffer size to use for audioavailable events.
         434                 :   PRUint32 mFrameBufferLength;
         435                 :
         436                 :   // True when our media stream has been pinned. We pin the stream
         437                 :   // while seeking.
         438                 :   bool mPinnedForSeek;
         439                 :
         440                 :   // True if the decoder is being shutdown. At this point all events that
         441                 :   // are currently queued need to return immediately to prevent javascript
         442                 :   // being run that operates on the element and decoder during shutdown.
         443                 :   // Read/Write from the main thread only.
         444                 :   bool mShuttingDown;
         445                 : };
         446                 :
         447                 : namespace mozilla {
         448                 : class MediaMemoryReporter
         449                 : {
         450                 :   MediaMemoryReporter();
         451                 :   ~MediaMemoryReporter();
         452                 :   static MediaMemoryReporter* sUniqueInstance;
         453                 :
         454                 :   static MediaMemoryReporter* UniqueInstance() {
         455                 :     if (!sUniqueInstance) {
         456                 :       sUniqueInstance = new MediaMemoryReporter;
         457                 :     }
         458                 :     return sUniqueInstance;
         459                 :   }
         460                 :
         461                 :   typedef nsTArray<nsMediaDecoder*> DecodersArray;
         462                 :   static DecodersArray& Decoders() {
         463                 :     return UniqueInstance()->mDecoders;
         464                 :   }
         465                 :
         466                 :   DecodersArray mDecoders;
         467                 :
         468                 :   nsCOMPtr<nsIMemoryReporter> mMediaDecodedVideoMemory;
         469                 :   nsCOMPtr<nsIMemoryReporter> mMediaDecodedAudioMemory;
         470                 :
         471                 : public:
         472                 :   static void AddMediaDecoder(nsMediaDecoder* aDecoder) {
         473                 :     Decoders().AppendElement(aDecoder);
         474                 :   }
         475                 :
         476                 :   static void RemoveMediaDecoder(nsMediaDecoder* aDecoder) {
         477                 :     DecodersArray& decoders = Decoders();
         478                 :     decoders.RemoveElement(aDecoder);
         479                 :     if (decoders.IsEmpty()) {
         480                 :       delete sUniqueInstance;
         481                 :       sUniqueInstance = nsnull;
         482                 :     }
         483                 :   }
         484                 :
         485                 :   static PRInt64 GetDecodedVideoMemory() {
         486                 :     DecodersArray& decoders = Decoders();
         487                 :     PRInt64 result = 0;
         488                 :     for (size_t i = 0; i < decoders.Length(); ++i) {
         489                 :       result += decoders[i]->VideoQueueMemoryInUse();
         490                 :     }
         491                 :     return result;
         492                 :   }
         493                 :
         494                 :   static PRInt64 GetDecodedAudioMemory() {
         495                 :     DecodersArray& decoders = Decoders();
         496                 :     PRInt64 result = 0;
         497                 :     for (size_t i = 0; i < decoders.Length(); ++i) {
         498                 :       result += decoders[i]->AudioQueueMemoryInUse();
         499                 :     }
         500                 :     return result;
         501                 :   }
         502                 : };
         503                 :
         504                 : } //namespace mozilla
         505                 : #endif

Generated by: LCOV version 1.7