Bug 1296531 - Implement MediaSegment move constructor. r?jesup draft
authorAndreas Pehrson <pehrsons@gmail.com>
Fri, 17 Feb 2017 14:31:50 +0100
changeset 670284 297d5256d0259be80eea325a60a9c334bfe2af5a
parent 669742 5f3f19824efa14cc6db546baf59c54a0fc15ddc9
child 670285 eb1ba0f0ffc3fa440743b7c8dce3fb54ed128f5e
push id81598
push userbmo:apehrson@mozilla.com
push dateTue, 26 Sep 2017 09:13:19 +0000
reviewersjesup
bugs1296531
milestone58.0a1
Bug 1296531 - Implement MediaSegment move constructor. r?jesup This helps simplify code in places where we want to move all chunks in one segment to another, new, segment. For clarity this also explicitly forbids copying a MediaSegment. MozReview-Commit-ID: 49rzUwFqE7V
dom/media/AudioSegment.h
dom/media/MediaSegment.h
dom/media/VideoSegment.cpp
dom/media/VideoSegment.h
--- a/dom/media/AudioSegment.h
+++ b/dom/media/AudioSegment.h
@@ -145,17 +145,19 @@ DownmixAndInterleave(const nsTArray<cons
  * of the buffer. An AudioChunk maintains its own duration and channel data
  * pointers so it can represent a subinterval of a buffer without copying.
  * An AudioChunk can store its individual channels anywhere; it maintains
  * separate pointers to each channel's buffer.
  */
 struct AudioChunk {
   typedef mozilla::AudioSampleFormat SampleFormat;
 
-  AudioChunk() : mPrincipalHandle(PRINCIPAL_HANDLE_NONE) {}
+  AudioChunk()
+    : mPrincipalHandle(PRINCIPAL_HANDLE_NONE)
+  {}
 
   // Generic methods
   void SliceTo(StreamTime aStart, StreamTime aEnd)
   {
     MOZ_ASSERT(aStart >= 0 && aStart < aEnd && aEnd <= mDuration,
                "Slice out of bounds");
     if (mBuffer) {
       MOZ_ASSERT(aStart < INT32_MAX, "Can't slice beyond 32-bit sample lengths");
@@ -266,16 +268,25 @@ struct AudioChunk {
  * The audio rate is determined by the track, not stored in this class.
  */
 class AudioSegment : public MediaSegmentBase<AudioSegment, AudioChunk> {
 public:
   typedef mozilla::AudioSampleFormat SampleFormat;
 
   AudioSegment() : MediaSegmentBase<AudioSegment, AudioChunk>(AUDIO) {}
 
+  AudioSegment(AudioSegment&& aSegment)
+    : MediaSegmentBase<AudioSegment, AudioChunk>(Move(aSegment))
+  {}
+
+  AudioSegment(const AudioSegment&)=delete;
+  AudioSegment& operator= (const AudioSegment&)=delete;
+
+  ~AudioSegment() {}
+
   // Resample the whole segment in place.
   template<typename T>
   void Resample(SpeexResamplerState* aResampler, uint32_t aInRate, uint32_t aOutRate)
   {
     mDuration = 0;
 #ifdef DEBUG
     uint32_t segmentChannelCount = ChannelCount();
 #endif
--- a/dom/media/MediaSegment.h
+++ b/dom/media/MediaSegment.h
@@ -110,16 +110,19 @@ inline bool PrincipalHandleMatches(Princ
  * a fixed constant for all tracks of that type (e.g. 1MHz for video).
  *
  * Each media segment defines a concept of "null media data" (e.g. silence
  * for audio or "no video frame" for video), which can be efficiently
  * represented. This is used for padding.
  */
 class MediaSegment {
 public:
+  MediaSegment(const MediaSegment&) = delete;
+  MediaSegment& operator= (const MediaSegment&) = delete;
+
   virtual ~MediaSegment()
   {
     MOZ_COUNT_DTOR(MediaSegment);
   }
 
   enum Type {
     AUDIO,
     VIDEO,
@@ -199,16 +202,24 @@ public:
 
 protected:
   explicit MediaSegment(Type aType)
     : mDuration(0), mType(aType), mLastPrincipalHandle(PRINCIPAL_HANDLE_NONE)
   {
     MOZ_COUNT_CTOR(MediaSegment);
   }
 
+  MediaSegment(MediaSegment&& aSegment)
+    : mDuration(Move(aSegment.mDuration))
+    , mType(Move(aSegment.mType))
+    , mLastPrincipalHandle(Move(aSegment.mLastPrincipalHandle))
+  {
+    MOZ_COUNT_CTOR(MediaSegment);
+  }
+
   StreamTime mDuration; // total of mDurations of all chunks
   Type mType;
 
   // The latest principal handle that the MediaStreamGraph has processed for
   // this segment.
   PrincipalHandle mLastPrincipalHandle;
 };
 
@@ -408,16 +419,24 @@ public:
       return nullptr;
     }
     return &mChunks[mChunks.Length() - 1];
   }
 
 protected:
   explicit MediaSegmentBase(Type aType) : MediaSegment(aType) {}
 
+  MediaSegmentBase(MediaSegmentBase&& aSegment)
+    : MediaSegment(Move(aSegment))
+    , mChunks(Move(aSegment.mChunks))
+#ifdef MOZILLA_INTERNAL_API
+    , mTimeStamp(Move(aSegment.mTimeStamp))
+#endif
+  {}
+
   /**
    * Appends the contents of aSource to this segment, clearing aSource.
    */
   void AppendFromInternal(MediaSegmentBase<C, Chunk>* aSource)
   {
     MOZ_ASSERT(aSource->mDuration >= 0);
     mDuration += aSource->mDuration;
     aSource->mDuration = 0;
--- a/dom/media/VideoSegment.cpp
+++ b/dom/media/VideoSegment.cpp
@@ -82,22 +82,16 @@ VideoFrame::CreateBlackImage(const gfx::
   // Copies data, so we can free data.
   if (!image->CopyData(data)) {
     return nullptr;
   }
 
   return image.forget();
 }
 
-VideoChunk::VideoChunk()
-{}
-
-VideoChunk::~VideoChunk()
-{}
-
 void
 VideoSegment::AppendFrame(already_AddRefed<Image>&& aImage,
                           StreamTime aDuration,
                           const IntSize& aIntrinsicSize,
                           const PrincipalHandle& aPrincipalHandle,
                           bool aForceBlack,
                           TimeStamp aTimeStamp)
 {
@@ -108,12 +102,16 @@ VideoSegment::AppendFrame(already_AddRef
   frame.SetPrincipalHandle(aPrincipalHandle);
   chunk->mFrame.TakeFrom(&frame);
 }
 
 VideoSegment::VideoSegment()
   : MediaSegmentBase<VideoSegment, VideoChunk>(VIDEO)
 {}
 
+VideoSegment::VideoSegment(VideoSegment&& aSegment)
+  : MediaSegmentBase<VideoSegment, VideoChunk>(Move(aSegment))
+{}
+
 VideoSegment::~VideoSegment()
 {}
 
 } // namespace mozilla
--- a/dom/media/VideoSegment.h
+++ b/dom/media/VideoSegment.h
@@ -57,18 +57,16 @@ protected:
   gfx::IntSize mIntrinsicSize;
   bool mForceBlack;
   // principalHandle for the image in this frame.
   // This can be compared to an nsIPrincipal when back on main thread.
   PrincipalHandle mPrincipalHandle;
 };
 
 struct VideoChunk {
-  VideoChunk();
-  ~VideoChunk();
   void SliceTo(StreamTime aStart, StreamTime aEnd)
   {
     NS_ASSERTION(aStart >= 0 && aStart < aEnd && aEnd <= mDuration,
                  "Slice out of bounds");
     mDuration = aEnd - aStart;
   }
   StreamTime GetDuration() const { return mDuration; }
   bool CanCombineWithFollowing(const VideoChunk& aOther) const
@@ -99,16 +97,21 @@ struct VideoChunk {
 };
 
 class VideoSegment : public MediaSegmentBase<VideoSegment, VideoChunk> {
 public:
   typedef mozilla::layers::Image Image;
   typedef mozilla::gfx::IntSize IntSize;
 
   VideoSegment();
+  VideoSegment(VideoSegment&& aSegment);
+
+  VideoSegment(const VideoSegment&)=delete;
+  VideoSegment& operator= (const VideoSegment&)=delete;
+
   ~VideoSegment();
 
   void AppendFrame(already_AddRefed<Image>&& aImage,
                    StreamTime aDuration,
                    const IntSize& aIntrinsicSize,
                    const PrincipalHandle& aPrincipalHandle,
                    bool aForceBlack = false,
                    TimeStamp aTimeStamp = TimeStamp::Now());