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

Side by Side Diff: webrtc/common_video/h264/sps_vui_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: Addressed comments Created 4 years, 6 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
« no previous file with comments | « webrtc/common_video/h264/sps_vui_rewriter.cc ('k') | webrtc/modules/modules.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/buffer.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/common_video/h264/sps_vui_rewriter.h"
23 #include "webrtc/common_video/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, rtc::Buffer* out_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(3);
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 uint8_t header[] = {0, 0, 0, 1, 7};
147 out_buffer->AppendData(header, sizeof(header));
148
149 H264::WriteRbsp(rbsp, byte_count, out_buffer);
150 }
151
152 void TestSps(SpsMode mode, SpsVuiRewriter::ParseResult expected_parse_result) {
153 rtc::LogMessage::LogToDebug(rtc::LS_VERBOSE);
154 rtc::Buffer buffer;
155 GenerateFakeSps(mode, &buffer);
156 std::vector<H264::NaluIndex> start_offsets =
157 H264::FindNaluIndices(buffer.data(), buffer.size());
158 EXPECT_EQ(1u, start_offsets.size());
159 H264::NaluIndex index = start_offsets[0];
160
161 H264::NaluType nal_type =
162 H264::ParseNaluType(buffer[index.payload_start_offset]);
163 EXPECT_EQ(H264::kSps, nal_type);
164 index.payload_start_offset += H264::kNaluTypeSize;
165 index.payload_size -= H264::kNaluTypeSize;
166
167 std::unique_ptr<rtc::Buffer> rbsp_decoded =
168 H264::ParseRbsp(&buffer[index.payload_start_offset], index.payload_size);
169 rtc::Optional<SpsParser::SpsState> sps;
170 rtc::Buffer out_buffer;
171 SpsVuiRewriter::ParseResult result = SpsVuiRewriter::ParseAndRewriteSps(
172 rbsp_decoded->data(), rbsp_decoded->size(), &sps, &out_buffer);
173 EXPECT_EQ(expected_parse_result, result);
174 }
175
176 #define REWRITE_TEST(test_name, mode, expected_parse_result) \
177 TEST(SpsVuiRewriterTest, test_name) { TestSps(mode, expected_parse_result); }
178
179 REWRITE_TEST(PocCorrect,
180 kNoRewriteRequired_PocCorrect,
181 SpsVuiRewriter::ParseResult::kPocOk);
182 REWRITE_TEST(VuiAlreadyOptimal,
183 kNoRewriteRequired_VuiOptimal,
184 SpsVuiRewriter::ParseResult::kVuiOk);
185 REWRITE_TEST(RewriteFullVui,
186 kRewriteRequired_NoVui,
187 SpsVuiRewriter::ParseResult::kVuiRewritten);
188 REWRITE_TEST(AddBitstreamRestriction,
189 kRewriteRequired_NoBitstreamRestriction,
190 SpsVuiRewriter::ParseResult::kVuiRewritten);
191 REWRITE_TEST(RewriteSuboptimalVui,
192 kRewriteRequired_VuiSuboptimal,
193 SpsVuiRewriter::ParseResult::kVuiRewritten);
194
195 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/common_video/h264/sps_vui_rewriter.cc ('k') | webrtc/modules/modules.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698