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
--- 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());