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

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

Issue 2303273002: Expose Ivf logging through the native API (Closed)
Patch Set: Nit Created 4 years, 2 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
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h" 11 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h"
12 12
13 #include <string>
14 #include <utility>
15
13 #include "webrtc/base/checks.h" 16 #include "webrtc/base/checks.h"
14 #include "webrtc/base/logging.h" 17 #include "webrtc/base/logging.h"
15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" 18 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
16 19
20 // TODO(palmkvist): make logging more informative in the absence of a file name
21 // (or get one)
22
17 namespace webrtc { 23 namespace webrtc {
18 24
19 IvfFileWriter::IvfFileWriter(const std::string& file_name, 25 const size_t kIvfHeaderSize = 32;
20 std::unique_ptr<FileWrapper> file, 26
21 VideoCodecType codec_type) 27 IvfFileWriter::IvfFileWriter(rtc::File file, size_t byte_limit)
22 : codec_type_(codec_type), 28 : codec_type_(kVideoCodecUnknown),
29 bytes_written_(0),
30 byte_limit_(byte_limit),
23 num_frames_(0), 31 num_frames_(0),
24 width_(0), 32 width_(0),
25 height_(0), 33 height_(0),
26 last_timestamp_(-1), 34 last_timestamp_(-1),
27 using_capture_timestamps_(false), 35 using_capture_timestamps_(false),
28 file_name_(file_name), 36 file_(std::move(file)) {
29 file_(std::move(file)) {} 37 RTC_DCHECK(byte_limit == 0 || kIvfHeaderSize <= byte_limit)
38 << "The byte_limit is too low, not even the header will fit.";
39 }
30 40
31 IvfFileWriter::~IvfFileWriter() { 41 IvfFileWriter::~IvfFileWriter() {
32 Close(); 42 Close();
33 } 43 }
34 44
35 const size_t kIvfHeaderSize = 32; 45 std::unique_ptr<IvfFileWriter> IvfFileWriter::Wrap(rtc::File file,
36 46 size_t byte_limit) {
37 std::unique_ptr<IvfFileWriter> IvfFileWriter::Open(const std::string& file_name, 47 return std::unique_ptr<IvfFileWriter>(
38 VideoCodecType codec_type) { 48 new IvfFileWriter(std::move(file), byte_limit));
39 std::unique_ptr<IvfFileWriter> file_writer;
40 std::unique_ptr<FileWrapper> file(FileWrapper::Create());
41 if (!file->OpenFile(file_name.c_str(), false))
42 return file_writer;
43
44 file_writer.reset(new IvfFileWriter(
45 file_name, std::unique_ptr<FileWrapper>(std::move(file)), codec_type));
46 if (!file_writer->WriteHeader())
47 file_writer.reset();
48
49 return file_writer;
50 } 49 }
51 50
52 bool IvfFileWriter::WriteHeader() { 51 bool IvfFileWriter::WriteHeader() {
53 if (file_->Rewind() != 0) { 52 if (!file_.Seek(0)) {
54 LOG(LS_WARNING) << "Unable to rewind output file " << file_name_; 53 LOG(LS_WARNING) << "Unable to rewind ivf output file.";
55 return false; 54 return false;
56 } 55 }
57 56
58 uint8_t ivf_header[kIvfHeaderSize] = {0}; 57 uint8_t ivf_header[kIvfHeaderSize] = {0};
59 ivf_header[0] = 'D'; 58 ivf_header[0] = 'D';
60 ivf_header[1] = 'K'; 59 ivf_header[1] = 'K';
61 ivf_header[2] = 'I'; 60 ivf_header[2] = 'I';
62 ivf_header[3] = 'F'; 61 ivf_header[3] = 'F';
63 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[4], 0); // Version. 62 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[4], 0); // Version.
64 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[6], 32); // Header size. 63 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[6], 32); // Header size.
(...skipping 26 matching lines...) Expand all
91 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[14], height_); 90 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[14], height_);
92 // Render timestamps are in ms (1/1000 scale), while RTP timestamps use a 91 // Render timestamps are in ms (1/1000 scale), while RTP timestamps use a
93 // 90kHz clock. 92 // 90kHz clock.
94 ByteWriter<uint32_t>::WriteLittleEndian( 93 ByteWriter<uint32_t>::WriteLittleEndian(
95 &ivf_header[16], using_capture_timestamps_ ? 1000 : 90000); 94 &ivf_header[16], using_capture_timestamps_ ? 1000 : 90000);
96 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[20], 1); 95 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[20], 1);
97 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[24], 96 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[24],
98 static_cast<uint32_t>(num_frames_)); 97 static_cast<uint32_t>(num_frames_));
99 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[28], 0); // Reserved. 98 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[28], 0); // Reserved.
100 99
101 if (!file_->Write(ivf_header, kIvfHeaderSize)) { 100 if (file_.Write(ivf_header, kIvfHeaderSize) < kIvfHeaderSize) {
102 LOG(LS_ERROR) << "Unable to write IVF header for file " << file_name_; 101 LOG(LS_ERROR) << "Unable to write IVF header for ivf output file.";
103 return false; 102 return false;
104 } 103 }
105 104
105 if (bytes_written_ < kIvfHeaderSize) {
106 bytes_written_ = kIvfHeaderSize;
107 }
108
106 return true; 109 return true;
107 } 110 }
108 111
109 bool IvfFileWriter::InitFromFirstFrame(const EncodedImage& encoded_image) { 112 bool IvfFileWriter::InitFromFirstFrame(const EncodedImage& encoded_image,
113 VideoCodecType codec_type) {
110 width_ = encoded_image._encodedWidth; 114 width_ = encoded_image._encodedWidth;
111 height_ = encoded_image._encodedHeight; 115 height_ = encoded_image._encodedHeight;
112 RTC_CHECK_GT(width_, 0); 116 RTC_CHECK_GT(width_, 0);
113 RTC_CHECK_GT(height_, 0); 117 RTC_CHECK_GT(height_, 0);
114 using_capture_timestamps_ = encoded_image._timeStamp == 0; 118 using_capture_timestamps_ = encoded_image._timeStamp == 0;
115 119
120 codec_type_ = codec_type;
121
116 if (!WriteHeader()) 122 if (!WriteHeader())
117 return false; 123 return false;
118 124
119 std::string codec_name; 125 std::string codec_name;
120 switch (codec_type_) { 126 switch (codec_type_) {
121 case kVideoCodecVP8: 127 case kVideoCodecVP8:
122 codec_name = "VP8"; 128 codec_name = "VP8";
123 break; 129 break;
124 case kVideoCodecVP9: 130 case kVideoCodecVP9:
125 codec_name = "VP9"; 131 codec_name = "VP9";
126 break; 132 break;
127 case kVideoCodecH264: 133 case kVideoCodecH264:
128 codec_name = "H264"; 134 codec_name = "H264";
129 break; 135 break;
130 default: 136 default:
131 codec_name = "Unknown"; 137 codec_name = "Unknown";
132 } 138 }
133 LOG(LS_WARNING) << "Created IVF file " << file_name_ 139 LOG(LS_WARNING) << "Created IVF file for codec data of type " << codec_name
134 << " for codec data of type " << codec_name
135 << " at resolution " << width_ << " x " << height_ 140 << " at resolution " << width_ << " x " << height_
136 << ", using " << (using_capture_timestamps_ ? "1" : "90") 141 << ", using " << (using_capture_timestamps_ ? "1" : "90")
137 << "kHz clock resolution."; 142 << "kHz clock resolution.";
138 return true; 143 return true;
139 } 144 }
140 145
141 bool IvfFileWriter::WriteFrame(const EncodedImage& encoded_image) { 146 bool IvfFileWriter::WriteFrame(const EncodedImage& encoded_image,
142 RTC_DCHECK(file_->is_open()); 147 VideoCodecType codec_type) {
148 if (!file_.IsOpen())
149 return false;
143 150
144 if (num_frames_ == 0 && !InitFromFirstFrame(encoded_image)) 151 if (num_frames_ == 0 && !InitFromFirstFrame(encoded_image, codec_type))
145 return false; 152 return false;
153 RTC_DCHECK_EQ(codec_type_, codec_type);
146 154
147 if ((encoded_image._encodedWidth > 0 || encoded_image._encodedHeight > 0) && 155 if ((encoded_image._encodedWidth > 0 || encoded_image._encodedHeight > 0) &&
148 (encoded_image._encodedHeight != height_ || 156 (encoded_image._encodedHeight != height_ ||
149 encoded_image._encodedWidth != width_)) { 157 encoded_image._encodedWidth != width_)) {
150 LOG(LS_WARNING) 158 LOG(LS_WARNING)
151 << "Incomig frame has diffferent resolution then previous: (" << width_ 159 << "Incomig frame has diffferent resolution then previous: (" << width_
152 << "x" << height_ << ") -> (" << encoded_image._encodedWidth << "x" 160 << "x" << height_ << ") -> (" << encoded_image._encodedWidth << "x"
153 << encoded_image._encodedHeight << ")"; 161 << encoded_image._encodedHeight << ")";
154 } 162 }
155 163
156 int64_t timestamp = using_capture_timestamps_ 164 int64_t timestamp = using_capture_timestamps_
157 ? encoded_image.capture_time_ms_ 165 ? encoded_image.capture_time_ms_
158 : wrap_handler_.Unwrap(encoded_image._timeStamp); 166 : wrap_handler_.Unwrap(encoded_image._timeStamp);
159 if (last_timestamp_ != -1 && timestamp <= last_timestamp_) { 167 if (last_timestamp_ != -1 && timestamp <= last_timestamp_) {
160 LOG(LS_WARNING) << "Timestamp no increasing: " << last_timestamp_ << " -> " 168 LOG(LS_WARNING) << "Timestamp no increasing: " << last_timestamp_ << " -> "
161 << timestamp; 169 << timestamp;
162 } 170 }
163 last_timestamp_ = timestamp; 171 last_timestamp_ = timestamp;
164 172
165 const size_t kFrameHeaderSize = 12; 173 const size_t kFrameHeaderSize = 12;
174 if (byte_limit_ != 0 &&
175 bytes_written_ + kFrameHeaderSize + encoded_image._length > byte_limit_) {
176 LOG(LS_WARNING) << "Closing IVF file due to reaching size limit: "
177 << byte_limit_ << " bytes.";
178 Close();
179 return false;
180 }
166 uint8_t frame_header[kFrameHeaderSize] = {}; 181 uint8_t frame_header[kFrameHeaderSize] = {};
167 ByteWriter<uint32_t>::WriteLittleEndian( 182 ByteWriter<uint32_t>::WriteLittleEndian(
168 &frame_header[0], static_cast<uint32_t>(encoded_image._length)); 183 &frame_header[0], static_cast<uint32_t>(encoded_image._length));
169 ByteWriter<uint64_t>::WriteLittleEndian(&frame_header[4], timestamp); 184 ByteWriter<uint64_t>::WriteLittleEndian(&frame_header[4], timestamp);
170 if (!file_->Write(frame_header, kFrameHeaderSize) || 185 if (file_.Write(frame_header, kFrameHeaderSize) < kFrameHeaderSize ||
171 !file_->Write(encoded_image._buffer, encoded_image._length)) { 186 file_.Write(encoded_image._buffer, encoded_image._length) <
172 LOG(LS_ERROR) << "Unable to write frame to file " << file_name_; 187 encoded_image._length) {
188 LOG(LS_ERROR) << "Unable to write frame to file.";
173 return false; 189 return false;
174 } 190 }
175 191
192 bytes_written_ += kFrameHeaderSize + encoded_image._length;
193
176 ++num_frames_; 194 ++num_frames_;
177 return true; 195 return true;
178 } 196 }
179 197
180 bool IvfFileWriter::Close() { 198 bool IvfFileWriter::Close() {
181 if (!file_->is_open()) 199 if (!file_.IsOpen())
182 return false; 200 return false;
183 201
184 if (num_frames_ == 0) { 202 if (num_frames_ == 0) {
185 // No frame written to file, close and remove it entirely if possible. 203 file_.Close();
186 file_->CloseFile();
187 if (remove(file_name_.c_str()) != 0)
188 LOG(LS_WARNING) << "Failed to remove empty IVF file " << file_name_;
189
190 return true; 204 return true;
191 } 205 }
192 206
193 bool ret = WriteHeader(); 207 bool ret = WriteHeader();
194 file_->CloseFile(); 208 file_.Close();
195 return ret; 209 return ret;
196 } 210 }
197 211
198 } // namespace webrtc 212 } // 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