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

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: Moved file recording to ViEEncoder 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 {
pbos-webrtc 2016/04/05 13:31:28 I think this class needs unittests, can you add an
sprang_webrtc 2016/04/05 16:00:53 Uhh.. That feels like a lot of work for a hack you
18
19 IvfFileWriter::IvfFileWriter(const char* file_name, FILE* file)
20 : num_frames_(0), file_name_(file_name), file_(file) {
21 RTC_CHECK(file != nullptr);
22 }
23
24 IvfFileWriter::~IvfFileWriter() {
25 Close();
26 }
27
28 const int kResolutionOffset = 12;
29 const int kFrameCountOffset = 24;
30 const size_t kIvfHeaderSize = 32;
31
32 bool IvfFileWriter::SeekTo(size_t offset) {
33 int err = fseek(file_, offset, SEEK_SET);
34 RTC_DCHECK_EQ(0, err);
35 return err == 0;
36 }
37
38 std::unique_ptr<IvfFileWriter> IvfFileWriter::Open(
39 const char* file_name,
40 RtpVideoCodecTypes codec_type) {
41 std::unique_ptr<IvfFileWriter> file_writer;
42
43 FILE* file = fopen(file_name, "wb");
44 if (file == nullptr) {
45 LOG(LS_ERROR) << "Unable to open IVF file " << file_name
46 << " for binary output.";
47 return file_writer;
48 }
49
50 uint8_t ivf_header[kIvfHeaderSize] = {0};
51 ivf_header[0] = 'D';
52 ivf_header[1] = 'K';
53 ivf_header[2] = 'I';
54 ivf_header[3] = 'F';
55 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[4], 0); // Verison.
56 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[6], 32); // Header size.
57
58 switch (codec_type) {
59 case kRtpVideoVp8:
60 ivf_header[8] = 'V';
61 ivf_header[9] = 'P';
62 ivf_header[10] = '8';
63 ivf_header[11] = '0';
64 break;
65 case kRtpVideoVp9:
66 ivf_header[8] = 'V';
67 ivf_header[9] = 'P';
68 ivf_header[10] = '9';
69 ivf_header[11] = '0';
70 break;
71 case kRtpVideoH264:
72 ivf_header[8] = 'H';
73 ivf_header[9] = '2';
74 ivf_header[10] = '6';
75 ivf_header[11] = '4';
76 break;
77 default:
78 LOG(LS_ERROR) << "Unknown CODEC type: " << codec_type;
79 return file_writer;
80 }
81
82 // Width and Height (populated on first frame).
83 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[12], 0);
84 ByteWriter<uint16_t>::WriteLittleEndian(&ivf_header[14], 0);
85 // Timestamps in milliseconds => time scale of 1/1000.
86 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[16], 1000);
87 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[20], 1);
88 // Number of frames (populated on close).
89 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[24], 0);
90 ByteWriter<uint32_t>::WriteLittleEndian(&ivf_header[28], 0); // Reserved.
91
92 if (fwrite(ivf_header, sizeof(uint8_t), kIvfHeaderSize, file) !=
93 kIvfHeaderSize) {
94 LOG(LS_ERROR) << "Unable to write IVF header to file " << file_name;
95 fclose(file);
96 return file_writer;
97 }
98
99 file_writer.reset(new IvfFileWriter(file_name, file));
100 return file_writer;
101 }
102
103 bool IvfFileWriter::WriteFrame(const EncodedImage& encoded_image) {
104 RTC_CHECK(file_ != nullptr);
105
106 if (num_frames_ == 0) {
107 if (!SeekTo(kResolutionOffset))
108 return false;
109 const size_t kResolutionDataSize = 4;
110 uint8_t buffer[kResolutionDataSize];
111 ByteWriter<uint16_t>::WriteLittleEndian(&buffer[0],
112 encoded_image._encodedWidth);
113 ByteWriter<uint16_t>::WriteLittleEndian(&buffer[2],
114 encoded_image._encodedHeight);
115 size_t bytes_written =
116 fwrite(buffer, sizeof(uint8_t), kResolutionDataSize, file_);
117 if (bytes_written != kResolutionDataSize) {
118 LOG(LS_ERROR) << "Unable to write resolution to IVF file " << file_name_;
119 return false;
120 }
121 if (!SeekTo(kIvfHeaderSize))
122 return false;
123 }
124
125 const size_t kFrameHeaderSize = 12;
126 uint8_t frame_header[kFrameHeaderSize] = {};
127 ByteWriter<uint32_t>::WriteLittleEndian(&frame_header[0],
128 encoded_image._length);
129 ByteWriter<uint64_t>::WriteLittleEndian(&frame_header[4],
130 encoded_image.ntp_time_ms_);
131 size_t bytes_written =
132 fwrite(frame_header, sizeof(uint8_t), kFrameHeaderSize, file_);
133 bytes_written += fwrite(encoded_image._buffer, sizeof(uint8_t),
134 encoded_image._length, file_);
135 if (bytes_written != kFrameHeaderSize + encoded_image._length) {
136 LOG(LS_ERROR) << "Unable to write frame to file " << file_name_;
137 return false;
138 }
139
140 ++num_frames_;
141 return true;
142 }
143
144 bool IvfFileWriter::Close() {
145 if (file_ == nullptr)
146 return false;
147
148 if (num_frames_ == 0) {
149 // No frame written to file, remove it entirely.
150 fclose(file_);
151 remove(file_name_.c_str());
152 return true;
153 }
154
155 if (!SeekTo(kFrameCountOffset))
156 return false;
157 const size_t kFrameCountLength = 4;
158 uint8_t size_data[kFrameCountLength];
159 ByteWriter<uint32_t>::WriteLittleEndian(size_data, num_frames_);
160 size_t bytes_written =
161 fwrite(size_data, sizeof(uint8_t), kFrameCountLength, file_);
162 RTC_DCHECK_EQ(kFrameCountLength, bytes_written);
163
164 fflush(file_);
165 fclose(file_);
166 file_ = nullptr;
167
168 return true;
169 }
170
171 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698