Source code

Revision control

Other Tools

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
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
15
#include <ctime>
16
#include <iomanip>
17
#include "stdio.h"
18
#ifdef XP_WIN
19
# include "direct.h"
20
#else
21
# include <sys/types.h>
22
# include "sys/stat.h"
23
#endif
24
25
using namespace mozilla::gfx;
26
27
namespace mozilla {
28
namespace layers {
29
30
CompositionRecorder::CompositionRecorder(TimeStamp aRecordingStart)
31
: mRecordingStart(aRecordingStart) {}
32
33
void CompositionRecorder::RecordFrame(RecordedFrame* aFrame) {
34
mCollectedFrames.AppendElement(aFrame);
35
}
36
37
void CompositionRecorder::WriteCollectedFrames() {
38
// The directory has the format of
39
// "[LayersWindowRecordingPath]/windowrecording-[mRecordingStartTime as unix
40
// timestamp]". We need mRecordingStart as a unix timestamp here because we
41
// want the consumer of these files to be able to compute an absolute
42
// timestamp of each screenshot, so that we can align screenshots with timed
43
// data from other sources, such as Gecko profiler information. The time of
44
// each screenshot is part of the screenshot's filename, expressed as
45
// milliseconds *relative to mRecordingStart*. We want to compute the number
46
// of milliseconds between midnight 1 January 1970 UTC and mRecordingStart,
47
// unfortunately, mozilla::TimeStamp does not have a built-in way of doing
48
// that. However, PR_Now() returns the number of microseconds since midnight 1
49
// January 1970 UTC. We call PR_Now() and TimeStamp::NowUnfuzzed() very
50
// closely to each other so that they return their representation of "the same
51
// time", and then compute (Now - (Now - mRecordingStart)).
52
std::stringstream str;
53
nsCString recordingStartTime;
54
TimeDuration delta = TimeStamp::NowUnfuzzed() - mRecordingStart;
55
recordingStartTime.AppendFloat(
56
static_cast<double>(PR_Now() / 1000.0 - delta.ToMilliseconds()));
57
str << gfxVars::LayersWindowRecordingPath() << "windowrecording-"
58
<< recordingStartTime;
59
60
#ifdef XP_WIN
61
_mkdir(str.str().c_str());
62
#else
63
mkdir(str.str().c_str(), 0777);
64
#endif
65
66
uint32_t i = 1;
67
for (RefPtr<RecordedFrame>& frame : mCollectedFrames) {
68
RefPtr<DataSourceSurface> surf = frame->GetSourceSurface();
69
std::stringstream filename;
70
filename << str.str() << "/frame-" << i << "-"
71
<< uint32_t(
72
(frame->GetTimeStamp() - mRecordingStart).ToMilliseconds())
73
<< ".png";
74
gfxUtils::WriteAsPNG(surf, filename.str().c_str());
75
i++;
76
}
77
mCollectedFrames.Clear();
78
}
79
80
CollectedFrames CompositionRecorder::GetCollectedFrames() {
81
nsTArray<CollectedFrame> frames;
82
83
TimeDuration delta = TimeStamp::NowUnfuzzed() - mRecordingStart;
84
double recordingStart = PR_Now() / 1000.0 - delta.ToMilliseconds();
85
86
for (RefPtr<RecordedFrame>& frame : mCollectedFrames) {
87
nsCString buffer;
88
89
RefPtr<DataSourceSurface> surf = frame->GetSourceSurface();
90
double offset = (frame->GetTimeStamp() - mRecordingStart).ToMilliseconds();
91
92
gfxUtils::EncodeSourceSurface(surf, ImageType::PNG, EmptyString(),
93
gfxUtils::eDataURIEncode, nullptr, &buffer);
94
95
frames.EmplaceBack(offset, std::move(buffer));
96
}
97
98
mCollectedFrames.Clear();
99
100
return CollectedFrames(recordingStart, std::move(frames));
101
}
102
103
void CompositionRecorder::ClearCollectedFrames() { mCollectedFrames.Clear(); }
104
105
} // namespace layers
106
} // namespace mozilla