Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(113)

Side by Side Diff: webrtc/modules/video_coding/utility/ivf_file_writer.cc

Issue 1853813002: Add support for writing raw encoder output to .ivf files. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h"
12
13 #include "webrtc/base/checks.h"
14 #include "webrtc/base/logging.h"
15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
16
17 namespace webrtc {
18
19 IvfFileWriter::IvfFileWriter(const std::string& file_name,
20 std::unique_ptr<FileWrapper> file,
21 RtpVideoCodecTypes codec_type)
22 : codec_type_(codec_type),
23 num_frames_(0),
24 width_(0),
25 height_(0),
26 last_timestamp_(-1),
27 using_capture_timestamps_(false),
28 file_name_(file_name),
29 file_(std::move(file)) {}
30
31 IvfFileWriter::~IvfFileWriter() {
32 Close();
33 }
34
35 const size_t kIvfHeaderSize = 32;
36
37 std::unique_ptr<IvfFileWriter> IvfFileWriter::Open(
38 const std::string& file_name,
39 RtpVideoCodecTypes codec_type) {
40 std::unique_ptr<IvfFileWriter> file_writer;
41 std::unique_ptr<FileWrapper> file(FileWrapper::Create());
42 if (file->OpenFile(file_name.c_str(), false) != 0)
43 return file_writer;
44
45 file_writer.reset(new IvfFileWriter(
46 file_name, std::unique_ptr<FileWrapper>(std::move(file)), codec_type));
47 if (!file_writer->WriteHeader())
48 file_writer.reset();
49
50 return file_writer;
51 }
52
53 bool IvfFileWriter::WriteHeader() {
54 if (file_->Rewind() != 0) {
55 LOG(LS_WARNING) << "Unable to rewind output file " << file_name_;
56 return false;
57 }
58
59 uint8_t ivf_header[kIvfHeaderSize] = {0};
60 ivf_header[0] = 'D';
61 ivf_header[1] = 'K';
62 ivf_header[2] = 'I';
63 ivf_header[3] = 'F';
64 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[4], 0); // Version.
65 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[6], 32); // Header size.
66
67 switch (codec_type_) {
68 case kRtpVideoVp8:
69 ivf_header[8] = 'V';
70 ivf_header[9] = 'P';
71 ivf_header[10] = '8';
72 ivf_header[11] = '0';
73 break;
74 case kRtpVideoVp9:
75 ivf_header[8] = 'V';
76 ivf_header[9] = 'P';
77 ivf_header[10] = '9';
78 ivf_header[11] = '0';
79 break;
80 case kRtpVideoH264:
81 ivf_header[8] = 'H';
82 ivf_header[9] = '2';
83 ivf_header[10] = '6';
84 ivf_header[11] = '4';
85 break;
86 default:
87 LOG(LS_ERROR) << "Unknown CODEC type: " << codec_type_;
88 return false;
89 }
90
91 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[12], width_);
92 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[14], height_);
93 // Render timestamps are in ms (1/1000 scale), while RTP timestamps use a
94 // 90kHz clock.
95 ByteWriter<uint32_t>::WriteLittleEndian(
96 &ivf_header[16], using_capture_timestamps_ ? 1000 : 90000);
97 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[20], 1);
98 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[24],
99 static_cast<uint32_t>(num_frames_));
100 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[28], 0); // Reserved.
101
102 if (!file_->Write(ivf_header, kIvfHeaderSize)) {
103 LOG(LS_ERROR) << "Unable to write IVF header for file " << file_name_;
104 return false;
105 }
106
107 return true;
108 }
109
110 bool IvfFileWriter::InitFromFirstFrame(const EncodedImage& encoded_image) {
111 width_ = encoded_image._encodedWidth;
112 height_ = encoded_image._encodedHeight;
113 RTC_CHECK_GT(width_, 0);
114 RTC_CHECK_GT(height_, 0);
115 using_capture_timestamps_ = encoded_image._timeStamp == 0;
116
117 if (!WriteHeader())
118 return false;
119
120 std::string codec_name;
121 switch (codec_type_) {
122 case kRtpVideoVp8:
123 codec_name = "VP8";
124 break;
125 case kRtpVideoVp9:
126 codec_name = "VP9";
127 break;
128 case kRtpVideoH264:
129 codec_name = "H264";
130 break;
131 default:
132 codec_name = "Unkown";
133 }
134 LOG(LS_WARNING) << "Created IVF file " << file_name_
135 << " for codec data of type " << codec_name
136 << " at resolution " << width_ << " x " << height_
137 << ", using " << (using_capture_timestamps_ ? "1" : "90")
138 << "kHz clock resolution.";
139 return true;
140 }
141
142 bool IvfFileWriter::WriteFrame(const EncodedImage& encoded_image) {
143 RTC_DCHECK(file_->Open());
144
145 if (num_frames_ == 0 && !InitFromFirstFrame(encoded_image))
146 return false;
147
148 if ((encoded_image._encodedWidth > 0 || encoded_image._encodedHeight > 0) &&
149 (encoded_image._encodedHeight != height_ ||
150 encoded_image._encodedWidth != width_)) {
151 LOG(LS_WARNING)
152 << "Incomig frame has diffferent resolution then previous: (" << width_
153 << "x" << height_ << ") -> (" << encoded_image._encodedWidth << "x"
154 << encoded_image._encodedHeight << ")";
155 }
156
157 int64_t timestamp = using_capture_timestamps_
158 ? encoded_image.capture_time_ms_
159 : wrap_handler_.Unwrap(encoded_image._timeStamp);
160 if (last_timestamp_ != -1 && timestamp <= last_timestamp_) {
161 LOG(LS_WARNING) << "Timestamp no increasing: " << last_timestamp_ << " -> "
162 << timestamp;
163 }
164 last_timestamp_ = timestamp;
165
166 const size_t kFrameHeaderSize = 12;
167 uint8_t frame_header[kFrameHeaderSize] = {};
168 ByteWriter<uint32_t>::WriteLittleEndian(
169 &frame_header[0], static_cast<uint32_t>(encoded_image._length));
170 ByteWriter<uint64_t>::WriteLittleEndian(&frame_header[4], timestamp);
171 if (!file_->Write(frame_header, kFrameHeaderSize) ||
172 !file_->Write(encoded_image._buffer, encoded_image._length)) {
173 LOG(LS_ERROR) << "Unable to write frame to file " << file_name_;
174 return false;
175 }
176
177 ++num_frames_;
178 return true;
179 }
180
181 bool IvfFileWriter::Close() {
182 if (!file_->Open())
183 return false;
184
185 if (num_frames_ == 0) {
186 // No frame written to file, close and remove it entirely if possible.
187 file_->CloseFile();
188 if (remove(file_name_.c_str()) != 0)
189 LOG(LS_WARNING) << "Failed to remove empty IVF file " << file_name_;
190
191 return true;
192 }
193
194 return WriteHeader() && (file_->CloseFile() == 0);
195 }
196
197 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/utility/ivf_file_writer.h ('k') | webrtc/modules/video_coding/utility/ivf_file_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698