MediaSpan.h (4537B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 #ifndef MediaSpan_h 7 #define MediaSpan_h 8 9 #include "MediaData.h" 10 #include "mozilla/RefPtr.h" 11 12 namespace mozilla { 13 14 // A MediaSpan wraps a MediaByteBuffer and exposes a slice/span, or subregion, 15 // of the buffer. This allows you to slice off a logical subregion without 16 // needing to reallocate a new buffer to hold it. You can also append to a 17 // MediaSpan without affecting other MediaSpans referencing the same buffer 18 // (the MediaSpan receiving the append will allocate a new buffer to store its 19 // result if necessary, to ensure other MediaSpans referencing its original 20 // buffer are unaffected). Note there are no protections here that something 21 // other than MediaSpans doesn't modify the underlying MediaByteBuffer while 22 // a MediaSpan is alive. 23 class MediaSpan { 24 public: 25 ~MediaSpan() = default; 26 27 explicit MediaSpan(const MediaSpan& aOther) = default; 28 29 MediaSpan(MediaSpan&& aOther) = default; 30 31 explicit MediaSpan(const RefPtr<MediaByteBuffer>& aBuffer) 32 : mBuffer(aBuffer), mStart(0), mLength(aBuffer ? aBuffer->Length() : 0) { 33 MOZ_DIAGNOSTIC_ASSERT(mBuffer); 34 } 35 36 explicit MediaSpan(MediaByteBuffer* aBuffer) 37 : mBuffer(aBuffer), mStart(0), mLength(aBuffer ? aBuffer->Length() : 0) { 38 MOZ_DIAGNOSTIC_ASSERT(mBuffer); 39 } 40 41 MediaSpan& operator=(const MediaSpan& aOther) = default; 42 43 static MediaSpan WithCopyOf(const RefPtr<MediaByteBuffer>& aBuffer) { 44 RefPtr<MediaByteBuffer> buffer = new MediaByteBuffer(aBuffer->Length()); 45 buffer->AppendElements(*aBuffer); 46 return MediaSpan(buffer); 47 } 48 49 bool IsEmpty() const { return Length() == 0; } 50 51 // Note: It's unsafe to store the pointer returned by this function, as an 52 // append operation could cause the wrapped MediaByteBuffer to be 53 // reallocated, invalidating pointers previously returned by this function. 54 const uint8_t* Elements() const { 55 MOZ_DIAGNOSTIC_ASSERT(mStart < mBuffer->Length()); 56 return mBuffer->Elements() + mStart; 57 } 58 59 size_t Length() const { return mLength; } 60 61 uint8_t operator[](size_t aIndex) const { 62 MOZ_DIAGNOSTIC_ASSERT(aIndex < Length()); 63 return (*mBuffer)[mStart + aIndex]; 64 } 65 66 bool Append(const MediaSpan& aBuffer) { return Append(aBuffer.Buffer()); } 67 68 bool Append(MediaByteBuffer* aBuffer) { 69 if (!aBuffer) { 70 return true; 71 } 72 if (mStart + mLength < mBuffer->Length()) { 73 // This MediaSpan finishes before the end of its buffer. The buffer 74 // could be shared with another MediaSpan. So we can't just append to 75 // the underlying buffer without risking damaging other MediaSpans' data. 76 // So we must reallocate a new buffer, copy our old data into it, and 77 // append the new data into it. 78 RefPtr<MediaByteBuffer> buffer = 79 new MediaByteBuffer(mLength + aBuffer->Length()); 80 if (!buffer->AppendElements(Elements(), Length(), fallible) || 81 !buffer->AppendElements(*aBuffer, fallible)) { 82 return false; 83 } 84 mBuffer = buffer; 85 mLength += aBuffer->Length(); 86 return true; 87 } 88 if (!mBuffer->AppendElements(*aBuffer, fallible)) { 89 return false; 90 } 91 mLength += aBuffer->Length(); 92 return true; 93 } 94 95 // Returns a new MediaSpan, spanning from the start of this span, 96 // up until aEnd. 97 MediaSpan To(size_t aEnd) const { 98 MOZ_DIAGNOSTIC_ASSERT(aEnd <= Length()); 99 return MediaSpan(mBuffer, mStart, aEnd); 100 } 101 102 // Returns a new MediaSpan, spanning from aStart bytes offset from 103 // the start of this span, until the end of this span. 104 MediaSpan From(size_t aStart) const { 105 MOZ_DIAGNOSTIC_ASSERT(aStart <= Length()); 106 return MediaSpan(mBuffer, mStart + aStart, Length() - aStart); 107 } 108 109 void RemoveFront(size_t aNumBytes) { 110 MOZ_DIAGNOSTIC_ASSERT(aNumBytes <= Length()); 111 mStart += aNumBytes; 112 mLength -= aNumBytes; 113 } 114 115 MediaByteBuffer* Buffer() const { return mBuffer; } 116 117 private: 118 MediaSpan(MediaByteBuffer* aBuffer, size_t aStart, size_t aLength) 119 : mBuffer(aBuffer), mStart(aStart), mLength(aLength) { 120 MOZ_DIAGNOSTIC_ASSERT(mStart + mLength <= mBuffer->Length()); 121 } 122 123 RefPtr<MediaByteBuffer> mBuffer; 124 size_t mStart = 0; 125 size_t mLength = 0; 126 }; 127 128 } // namespace mozilla 129 130 #endif // MediaSpan_h