Merge mozilla-central to autoland. CLOSED TREE
[gecko.git] / gfx / layers / CompositionRecorder.cpp
blob61d43330e9ca63e28b1afe00f7255e49dcc51df6
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/. */
7 #include "CompositionRecorder.h"
8 #include "gfxUtils.h"
9 #include "mozilla/gfx/2D.h"
10 #include "mozilla/gfx/gfxVars.h"
11 #include "nsIInputStream.h"
12 #include "nsIBinaryOutputStream.h"
13 #include "nsIObjectOutputStream.h"
14 #include "prtime.h"
16 #include <ctime>
17 #include <iomanip>
18 #include "stdio.h"
19 #ifdef XP_WIN
20 # include "direct.h"
21 #else
22 # include <sys/types.h>
23 # include "sys/stat.h"
24 #endif
26 using namespace mozilla::gfx;
28 namespace mozilla {
29 namespace layers {
31 CompositionRecorder::CompositionRecorder(TimeStamp aRecordingStart)
32 : mRecordingStart(aRecordingStart) {}
34 void CompositionRecorder::RecordFrame(RecordedFrame* aFrame) {
35 mRecordedFrames.AppendElement(aFrame);
38 Maybe<FrameRecording> CompositionRecorder::GetRecording() {
39 FrameRecording recording;
41 recording.startTime() = mRecordingStart;
43 nsTArray<uint8_t> bytes;
44 for (RefPtr<RecordedFrame>& recordedFrame : mRecordedFrames) {
45 RefPtr<DataSourceSurface> surf = recordedFrame->GetSourceSurface();
46 if (!surf) {
47 return Nothing();
50 nsCOMPtr<nsIInputStream> imgStream;
51 nsresult rv = gfxUtils::EncodeSourceSurfaceAsStream(
52 surf, ImageType::PNG, u""_ns, getter_AddRefs(imgStream));
53 if (NS_FAILED(rv)) {
54 return Nothing();
57 uint64_t bufSize64;
58 rv = imgStream->Available(&bufSize64);
59 if (NS_FAILED(rv) || bufSize64 > UINT32_MAX) {
60 return Nothing();
63 const uint32_t frameLength = static_cast<uint32_t>(bufSize64);
64 size_t startIndex = bytes.Length();
65 bytes.SetLength(startIndex + frameLength);
67 uint8_t* bytePtr = &bytes[startIndex];
68 uint32_t bytesLeft = frameLength;
70 while (bytesLeft > 0) {
71 uint32_t bytesRead = 0;
72 rv = imgStream->Read(reinterpret_cast<char*>(bytePtr), bytesLeft,
73 &bytesRead);
74 if (NS_FAILED(rv) || bytesRead == 0) {
75 return Nothing();
78 bytePtr += bytesRead;
79 bytesLeft -= bytesRead;
82 #ifdef DEBUG
84 // Currently, all implementers of imgIEncoder report their exact size
85 // through nsIInputStream::Available(), but let's explicitly state that we
86 // rely on that behavior for the algorithm above.
88 char dummy = 0;
89 uint32_t bytesRead = 0;
90 rv = imgStream->Read(&dummy, 1, &bytesRead);
91 MOZ_ASSERT(NS_SUCCEEDED(rv) && bytesRead == 0);
93 #endif
95 RecordedFrameData frameData;
97 frameData.timeOffset() = recordedFrame->GetTimeStamp();
98 frameData.length() = frameLength;
100 recording.frames().AppendElement(std::move(frameData));
102 // Now that we're done, release the frame so we can free up its memory
103 recordedFrame = nullptr;
106 mRecordedFrames.Clear();
108 recording.bytes() = ipc::BigBuffer(bytes);
110 return Some(std::move(recording));
113 } // namespace layers
114 } // namespace mozilla