Bug 1839170 - Refactor Snap pulling, Add Firefox Snap Core22 and GNOME 42 SDK symbols...
[gecko.git] / dom / media / MediaSpan.h
blob4bb512a7dc0f1b6ecabdc3710f900df6611e3ac1
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 #if !defined(MediaSpan_h)
7 # define MediaSpan_h
9 # include "MediaData.h"
10 # include "mozilla/RefPtr.h"
11 # include "mozilla/Span.h"
13 namespace mozilla {
15 // A MediaSpan wraps a MediaByteBuffer and exposes a slice/span, or subregion,
16 // of the buffer. This allows you to slice off a logical subregion without
17 // needing to reallocate a new buffer to hold it. You can also append to a
18 // MediaSpan without affecting other MediaSpans referencing the same buffer
19 // (the MediaSpan receiving the append will allocate a new buffer to store its
20 // result if necessary, to ensure other MediaSpans referencing its original
21 // buffer are unaffected). Note there are no protections here that something
22 // other than MediaSpans doesn't modify the underlying MediaByteBuffer while
23 // a MediaSpan is alive.
24 class MediaSpan {
25 public:
26 ~MediaSpan() = default;
28 explicit MediaSpan(const MediaSpan& aOther) = default;
30 MediaSpan(MediaSpan&& aOther) = default;
32 explicit MediaSpan(const RefPtr<MediaByteBuffer>& aBuffer)
33 : mBuffer(aBuffer), mStart(0), mLength(aBuffer ? aBuffer->Length() : 0) {
34 MOZ_DIAGNOSTIC_ASSERT(mBuffer);
37 explicit MediaSpan(MediaByteBuffer* aBuffer)
38 : mBuffer(aBuffer), mStart(0), mLength(aBuffer ? aBuffer->Length() : 0) {
39 MOZ_DIAGNOSTIC_ASSERT(mBuffer);
42 MediaSpan& operator=(const MediaSpan& aOther) = default;
44 static MediaSpan WithCopyOf(const RefPtr<MediaByteBuffer>& aBuffer) {
45 RefPtr<MediaByteBuffer> buffer = new MediaByteBuffer(aBuffer->Length());
46 buffer->AppendElements(*aBuffer);
47 return MediaSpan(buffer);
50 bool IsEmpty() const { return Length() == 0; }
52 // Note: It's unsafe to store the pointer returned by this function, as an
53 // append operation could cause the wrapped MediaByteBuffer to be
54 // reallocated, invalidating pointers previously returned by this function.
55 const uint8_t* Elements() const {
56 MOZ_DIAGNOSTIC_ASSERT(mStart < mBuffer->Length());
57 return mBuffer->Elements() + mStart;
60 size_t Length() const { return mLength; }
62 uint8_t operator[](size_t aIndex) const {
63 MOZ_DIAGNOSTIC_ASSERT(aIndex < Length());
64 return (*mBuffer)[mStart + aIndex];
67 bool Append(const MediaSpan& aBuffer) { return Append(aBuffer.Buffer()); }
69 bool Append(MediaByteBuffer* aBuffer) {
70 if (!aBuffer) {
71 return true;
73 if (mStart + mLength < mBuffer->Length()) {
74 // This MediaSpan finishes before the end of its buffer. The buffer
75 // could be shared with another MediaSpan. So we can't just append to
76 // the underlying buffer without risking damaging other MediaSpans' data.
77 // So we must reallocate a new buffer, copy our old data into it, and
78 // append the new data into it.
79 RefPtr<MediaByteBuffer> buffer =
80 new MediaByteBuffer(mLength + aBuffer->Length());
81 if (!buffer->AppendElements(Elements(), Length(), fallible) ||
82 !buffer->AppendElements(*aBuffer, fallible)) {
83 return false;
85 mBuffer = buffer;
86 mLength += aBuffer->Length();
87 return true;
89 if (!mBuffer->AppendElements(*aBuffer, fallible)) {
90 return false;
92 mLength += aBuffer->Length();
93 return true;
96 // Returns a new MediaSpan, spanning from the start of this span,
97 // up until aEnd.
98 MediaSpan To(size_t aEnd) const {
99 MOZ_DIAGNOSTIC_ASSERT(aEnd <= Length());
100 return MediaSpan(mBuffer, mStart, aEnd);
103 // Returns a new MediaSpan, spanning from aStart bytes offset from
104 // the start of this span, until the end of this span.
105 MediaSpan From(size_t aStart) const {
106 MOZ_DIAGNOSTIC_ASSERT(aStart <= Length());
107 return MediaSpan(mBuffer, mStart + aStart, Length() - aStart);
110 void RemoveFront(size_t aNumBytes) {
111 MOZ_DIAGNOSTIC_ASSERT(aNumBytes <= Length());
112 mStart += aNumBytes;
113 mLength -= aNumBytes;
116 MediaByteBuffer* Buffer() const { return mBuffer; }
118 private:
119 MediaSpan(MediaByteBuffer* aBuffer, size_t aStart, size_t aLength)
120 : mBuffer(aBuffer), mStart(aStart), mLength(aLength) {
121 MOZ_DIAGNOSTIC_ASSERT(mStart + mLength <= mBuffer->Length());
124 RefPtr<MediaByteBuffer> mBuffer;
125 size_t mStart = 0;
126 size_t mLength = 0;
129 } // namespace mozilla
131 #endif // MediaSpan_h