1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/test/video_frame_writer.h"
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
13 #include "ui/gfx/codec/png_codec.h"
14 #include "ui/gfx/geometry/size.h"
18 const base::FilePath::CharType kFrameFileName
[] =
19 FILE_PATH_LITERAL("frame.png");
20 const base::FilePath::CharType kRemotingFolder
[] =
21 FILE_PATH_LITERAL("remoting");
22 const base::FilePath::CharType kDumpFrameFolder
[] =
23 FILE_PATH_LITERAL("dumped_images");
25 // Used to create a unique folder path.
26 const char kDateAndTimeFormatString
[] = "%d-%d-%d_%d-%d-%d";
33 VideoFrameWriter::VideoFrameWriter()
34 : instance_creation_time_(base::Time::Now()),
35 frame_name_unique_number_(0) {}
37 VideoFrameWriter::~VideoFrameWriter() {}
39 void VideoFrameWriter::WriteFrameToPath(const webrtc::DesktopFrame
& frame
,
40 const base::FilePath
& image_path
) {
41 unsigned char* frame_data
= reinterpret_cast<unsigned char*>(frame
.data());
42 std::vector
<unsigned char> png_encoded_data
;
44 if (!gfx::PNGCodec::Encode(
45 frame_data
, gfx::PNGCodec::FORMAT_BGRA
,
46 gfx::Size(frame
.size().width(), frame
.size().height()),
47 frame
.stride(), true, std::vector
<gfx::PNGCodec::Comment
>(),
49 LOG(WARNING
) << "Failed to encode frame to PNG file";
53 // Dump contents (unsigned chars) to a file as a sequence of chars.
54 int write_bytes
= base::WriteFile(
55 image_path
, reinterpret_cast<char*>(&*png_encoded_data
.begin()),
56 static_cast<int>(png_encoded_data
.size()));
57 if (write_bytes
!= static_cast<int>(png_encoded_data
.size())) {
58 LOG(WARNING
) << "Failed to write frame to disk";
62 // Save video frame to path named with the |instance_creation_time|.
63 void VideoFrameWriter::WriteFrameToDefaultPath(
64 const webrtc::DesktopFrame
& frame
) {
65 base::FilePath dump_frame_file_path
;
66 if (!GetTempDir(&dump_frame_file_path
)) {
67 LOG(WARNING
) << "Failed to retrieve temporary directory path";
71 dump_frame_file_path
= dump_frame_file_path
.Append(kRemotingFolder
);
72 dump_frame_file_path
= dump_frame_file_path
.Append(kDumpFrameFolder
);
73 if (!CreateDirectoryIfNotExists(dump_frame_file_path
)) {
77 // Create a sub-folder using date and time to identify a particular test run.
78 dump_frame_file_path
= AppendCreationDateAndTime(dump_frame_file_path
);
79 if (!CreateDirectoryIfNotExists(dump_frame_file_path
)) {
83 dump_frame_file_path
= dump_frame_file_path
.Append(kFrameFileName
);
85 dump_frame_file_path
= dump_frame_file_path
.InsertBeforeExtensionASCII(
86 base::StringPrintf("(%d)", ++frame_name_unique_number_
));
88 LOG(INFO
) << "Video frame dumped to: " << dump_frame_file_path
.value();
90 WriteFrameToPath(frame
, dump_frame_file_path
);
93 base::FilePath
VideoFrameWriter::AppendCreationDateAndTime(
94 const base::FilePath
& file_path
) {
95 base::Time::Exploded exploded_time
;
96 instance_creation_time_
.LocalExplode(&exploded_time
);
98 int year
= exploded_time
.year
;
99 int month
= exploded_time
.month
;
100 int day
= exploded_time
.day_of_month
;
101 int hour
= exploded_time
.hour
;
102 int minute
= exploded_time
.minute
;
103 int second
= exploded_time
.second
;
105 return file_path
.AppendASCII(base::StringPrintf(
106 kDateAndTimeFormatString
, year
, month
, day
, hour
, minute
, second
));
109 bool VideoFrameWriter::CreateDirectoryIfNotExists(
110 const base::FilePath
& file_path
) {
111 if (!base::DirectoryExists(file_path
) && !base::CreateDirectory(file_path
)) {
112 LOG(WARNING
) << "Failed to create directory: " << file_path
.value();
119 } // namespace remoting