diff options
Diffstat (limited to '')
-rw-r--r-- | gfx/layers/CompositionRecorder.cpp | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/gfx/layers/CompositionRecorder.cpp b/gfx/layers/CompositionRecorder.cpp new file mode 100644 index 0000000000..61d43330e9 --- /dev/null +++ b/gfx/layers/CompositionRecorder.cpp @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "CompositionRecorder.h" +#include "gfxUtils.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/gfx/gfxVars.h" +#include "nsIInputStream.h" +#include "nsIBinaryOutputStream.h" +#include "nsIObjectOutputStream.h" +#include "prtime.h" + +#include <ctime> +#include <iomanip> +#include "stdio.h" +#ifdef XP_WIN +# include "direct.h" +#else +# include <sys/types.h> +# include "sys/stat.h" +#endif + +using namespace mozilla::gfx; + +namespace mozilla { +namespace layers { + +CompositionRecorder::CompositionRecorder(TimeStamp aRecordingStart) + : mRecordingStart(aRecordingStart) {} + +void CompositionRecorder::RecordFrame(RecordedFrame* aFrame) { + mRecordedFrames.AppendElement(aFrame); +} + +Maybe<FrameRecording> CompositionRecorder::GetRecording() { + FrameRecording recording; + + recording.startTime() = mRecordingStart; + + nsTArray<uint8_t> bytes; + for (RefPtr<RecordedFrame>& recordedFrame : mRecordedFrames) { + RefPtr<DataSourceSurface> surf = recordedFrame->GetSourceSurface(); + if (!surf) { + return Nothing(); + } + + nsCOMPtr<nsIInputStream> imgStream; + nsresult rv = gfxUtils::EncodeSourceSurfaceAsStream( + surf, ImageType::PNG, u""_ns, getter_AddRefs(imgStream)); + if (NS_FAILED(rv)) { + return Nothing(); + } + + uint64_t bufSize64; + rv = imgStream->Available(&bufSize64); + if (NS_FAILED(rv) || bufSize64 > UINT32_MAX) { + return Nothing(); + } + + const uint32_t frameLength = static_cast<uint32_t>(bufSize64); + size_t startIndex = bytes.Length(); + bytes.SetLength(startIndex + frameLength); + + uint8_t* bytePtr = &bytes[startIndex]; + uint32_t bytesLeft = frameLength; + + while (bytesLeft > 0) { + uint32_t bytesRead = 0; + rv = imgStream->Read(reinterpret_cast<char*>(bytePtr), bytesLeft, + &bytesRead); + if (NS_FAILED(rv) || bytesRead == 0) { + return Nothing(); + } + + bytePtr += bytesRead; + bytesLeft -= bytesRead; + } + +#ifdef DEBUG + + // Currently, all implementers of imgIEncoder report their exact size + // through nsIInputStream::Available(), but let's explicitly state that we + // rely on that behavior for the algorithm above. + + char dummy = 0; + uint32_t bytesRead = 0; + rv = imgStream->Read(&dummy, 1, &bytesRead); + MOZ_ASSERT(NS_SUCCEEDED(rv) && bytesRead == 0); + +#endif + + RecordedFrameData frameData; + + frameData.timeOffset() = recordedFrame->GetTimeStamp(); + frameData.length() = frameLength; + + recording.frames().AppendElement(std::move(frameData)); + + // Now that we're done, release the frame so we can free up its memory + recordedFrame = nullptr; + } + + mRecordedFrames.Clear(); + + recording.bytes() = ipc::BigBuffer(bytes); + + return Some(std::move(recording)); +} + +} // namespace layers +} // namespace mozilla |