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

Side by Side Diff: webrtc/modules/rtp_rtcp/source/h264/bitstream_rewriter_unittest.cc

Issue 1979443004: Add H264 bitstream rewriting to limit frame reordering marker in header (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rewriting on the receiver side as well Created 4 years, 7 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 <vector>
12
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 #include "webrtc/base/bitbuffer.h"
16 #include "webrtc/base/bytebuffer.h"
17 #include "webrtc/base/fileutils.h"
18 #include "webrtc/base/logging.h"
19 #include "webrtc/base/pathutils.h"
20 #include "webrtc/base/stream.h"
21
22 #include "webrtc/modules/rtp_rtcp/source/h264/bitstream_rewriter.h"
23 #include "webrtc/modules/rtp_rtcp/source/h264/h264_common.h"
24
25 namespace webrtc {
26
27 enum SpsMode {
28 kNoRewriteRequired_PocCorrect,
29 kNoRewriteRequired_VuiOptimal,
30 kRewriteRequired_NoVui,
31 kRewriteRequired_NoBitstreamRestriction,
32 kRewriteRequired_VuiSuboptimal,
33 };
34
35 static const size_t kSpsBufferMaxSize = 256;
36 static const size_t kWidth = 640;
37 static const size_t kHeight = 480;
38
39 // Generates a fake SPS with basically everything empty and with characteristics
40 // based off SpsMode.
41 // Pass in a buffer of at least kSpsBufferMaxSize.
42 // The fake SPS that this generates also always has at least one emulation byte
43 // at offset 2, since the first two bytes are always 0, and has a 0x3 as the
44 // level_idc, to make sure the parser doesn't eat all 0x3 bytes.
45 void GenerateFakeSps(SpsMode mode, uint8_t buffer[]) {
46 uint8_t rbsp[kSpsBufferMaxSize] = {0};
47 rtc::BitBufferWriter writer(rbsp, kSpsBufferMaxSize);
48 // Profile byte.
49 writer.WriteUInt8(0);
50 // Constraint sets and reserved zero bits.
51 writer.WriteUInt8(0);
52 // level_idc.
53 writer.WriteUInt8(0x3u);
54 // seq_paramter_set_id.
55 writer.WriteExponentialGolomb(0);
56 // Profile is not special, so we skip all the chroma format settings.
57
58 // Now some bit magic.
59 // log2_max_frame_num_minus4: ue(v). 0 is fine.
60 writer.WriteExponentialGolomb(0);
61 // pic_order_cnt_type: ue(v).
62 // POC type 2 is the one that doesn't need to be rewritten.
63 if (mode == kNoRewriteRequired_PocCorrect) {
64 writer.WriteExponentialGolomb(2);
65 } else {
66 writer.WriteExponentialGolomb(0);
67 // log2_max_pic_order_cnt_lsb_minus4: ue(v). 0 is fine.
68 writer.WriteExponentialGolomb(0);
69 }
70 // max_num_ref_frames: ue(v). Use 1, to make optimal/suboptimal more obvious.
71 writer.WriteExponentialGolomb(1);
72 // gaps_in_frame_num_value_allowed_flag: u(1).
73 writer.WriteBits(0, 1);
74 // Next are width/height. First, calculate the mbs/map_units versions.
75 uint16_t width_in_mbs_minus1 = (kWidth + 15) / 16 - 1;
76
77 // For the height, we're going to define frame_mbs_only_flag, so we need to
78 // divide by 2. See the parser for the full calculation.
79 uint16_t height_in_map_units_minus1 = ((kHeight + 15) / 16 - 1) / 2;
80 // Write each as ue(v).
81 writer.WriteExponentialGolomb(width_in_mbs_minus1);
82 writer.WriteExponentialGolomb(height_in_map_units_minus1);
83 // frame_mbs_only_flag: u(1). Needs to be false.
84 writer.WriteBits(0, 1);
85 // mb_adaptive_frame_field_flag: u(1).
86 writer.WriteBits(0, 1);
87 // direct_8x8_inferene_flag: u(1).
88 writer.WriteBits(0, 1);
89 // frame_cropping_flag: u(1). 1, so we can supply crop.
90 writer.WriteBits(1, 1);
91 // Now we write the left/right/top/bottom crop. For simplicity, we'll put all
92 // the crop at the left/top.
93 // We picked a 4:2:0 format, so the crops are 1/2 the pixel crop values.
94 // Left/right.
95 writer.WriteExponentialGolomb(((16 - (kWidth % 16)) % 16) / 2);
96 writer.WriteExponentialGolomb(0);
97 // Top/bottom.
98 writer.WriteExponentialGolomb(((16 - (kHeight % 16)) % 16) / 2);
99 writer.WriteExponentialGolomb(0);
100
101 // Finally! The VUI.
102 // vui_parameters_present_flag: u(1)
103 if (mode == kNoRewriteRequired_PocCorrect || mode == kRewriteRequired_NoVui) {
104 writer.WriteBits(0, 1);
105 } else {
106 writer.WriteBits(1, 1);
107 // VUI time. 8 flags to ignore followed by the bitstream restriction flag.
108 writer.WriteBits(0, 8);
109 if (mode == kRewriteRequired_NoBitstreamRestriction) {
110 writer.WriteBits(0, 1);
111 } else {
112 writer.WriteBits(1, 1);
113 // Write some defaults. Shouldn't matter for parsing, though.
114 // motion_vectors_over_pic_boundaries_flag: u(1)
115 writer.WriteBits(1, 1);
116 // max_bytes_per_pic_denom: ue(v)
117 writer.WriteExponentialGolomb(2);
118 // max_bits_per_mb_denom: ue(v)
119 writer.WriteExponentialGolomb(1);
120 // log2_max_mv_length_horizontal: ue(v)
121 // log2_max_mv_length_vertical: ue(v)
122 writer.WriteExponentialGolomb(16);
123 writer.WriteExponentialGolomb(16);
124
125 // Next are the limits we care about.
126 // max_num_reorder_frames: ue(v)
127 // max_dec_frame_buffering: ue(v)
128 if (mode == kRewriteRequired_VuiSuboptimal) {
129 writer.WriteExponentialGolomb(4);
130 writer.WriteExponentialGolomb(4);
131 } else if (kNoRewriteRequired_VuiOptimal) {
132 writer.WriteExponentialGolomb(0);
133 writer.WriteExponentialGolomb(1);
134 }
135 }
136 }
137
138 // Get the number of bytes written (including the last partial byte).
139 size_t byte_count, bit_offset;
140 writer.GetCurrentOffset(&byte_count, &bit_offset);
141 if (bit_offset > 0) {
142 byte_count++;
143 }
144
145 // Write the NALU header and type; {0 0 0 1} and 7 for the SPS header type.
146 *buffer++ = 0;
147 *buffer++ = 0;
148 *buffer++ = 0;
149 *buffer++ = 1;
150 *buffer++ = 7;
151
152 // Now, we need to write the rbsp into bytes. To do that, we'll need to add
153 // emulation 0x03 bytes if there's ever a sequence of 00 00 01 or 00 00 00 01.
154 // To be simple, just add a 0x03 after every 0x00. Extra emulation doesn't
155 // hurt.
156 for (size_t i = 0; i < byte_count;) {
157 // The -3 is intentional; we never need to write an emulation byte if the 00
158 // is at the end.
159 if (i < byte_count - 3 && rbsp[i] == 0 && rbsp[i + 1] == 0) {
160 *buffer++ = rbsp[i];
161 *buffer++ = rbsp[i + 1];
162 *buffer++ = 0x3u;
163 i += 2;
164 } else {
165 *buffer++ = rbsp[i];
166 ++i;
167 }
168 }
169 }
170
171 void TestSps(SpsMode mode, bool should_be_rewritten) {
172 rtc::LogMessage::LogToDebug(rtc::LS_VERBOSE);
173 uint8_t buffer[kSpsBufferMaxSize] = {0};
174 GenerateFakeSps(mode, buffer);
175 std::vector<size_t> start_offsets =
176 H264Common::FindNaluStartOffsets(buffer, kSpsBufferMaxSize);
177 EXPECT_EQ(1u, start_offsets.size());
178 size_t offset = start_offsets[0] + H264Common::kNaluHeaderSize;
179 H264BitstreamRewriter bitstream_rewriter;
180 bool success = bitstream_rewriter.ParseAndRewriteSps(
181 &buffer[offset], kSpsBufferMaxSize - offset);
182 EXPECT_EQ(should_be_rewritten, success);
183 }
184
185 #define REWRITE_TEST(test_name, mode, should_be_rewritten) \
186 TEST(H264BitstreamRewriterTest, test_name) { \
187 TestSps(mode, should_be_rewritten); \
188 }
189
190 REWRITE_TEST(PocCorrect, kNoRewriteRequired_PocCorrect, false);
191 REWRITE_TEST(VuiAlreadyOptimal, kNoRewriteRequired_VuiOptimal, false);
192 REWRITE_TEST(RewriteFullVui, kRewriteRequired_NoVui, true);
193 REWRITE_TEST(AddBitstreamRestriction,
194 kRewriteRequired_NoBitstreamRestriction,
195 true);
196 REWRITE_TEST(RewriteSuboptimalVui, kRewriteRequired_VuiSuboptimal, true);
197
198 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698