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

Side by Side Diff: content/common/gpu/media/h264_poc.cc

Issue 742233002: Implement |pic_order_cnt| computation for VTVideoDecode accelerator. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@vt_reorder
Patch Set: Address comments (other than unittesting). Created 6 years, 1 month 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 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <algorithm>
6
7 #include "base/logging.h"
8 #include "content/common/gpu/media/h264_poc.h"
9 #include "media/filters/h264_parser.h"
10
11 namespace content {
12
13 H264POC::H264POC() {
14 Reset();
15 }
16
17 H264POC::~H264POC() {
18 }
19
20 void H264POC::Reset() {
21 // It shouldn't be necessary to reset these values, but doing so will improve
22 // reproducibility for buggy streams.
23 ref_pic_order_cnt_msb_ = 0;
24 ref_pic_order_cnt_lsb_ = 0;
25 prev_frame_num_ = 0;
26 prev_frame_num_offset_ = 0;
27 }
28
29 // Check if a slice includes memory management control operation 5, which
30 // results in some |pic_order_cnt| state being cleared.
31 static bool HasMMCO5(const media::H264SliceHeader& slice_hdr) {
32 // Require that the frame actually has memory management control operations.
33 if (slice_hdr.nal_ref_idc == 0 ||
34 slice_hdr.idr_pic_flag ||
35 !slice_hdr.adaptive_ref_pic_marking_mode_flag) {
36 return false;
37 }
38
39 for (size_t i = 0; i < arraysize(slice_hdr.ref_pic_marking); i++) {
40 int32_t op = slice_hdr.ref_pic_marking[i].memory_mgmnt_control_operation;
41 if (op == 5)
42 return true;
43
44 // Stop at the end of the list.
DaleCurtis 2014/11/21 21:42:05 Is this really the end of the list always? If so,
sandersd (OOO until July 31) 2014/11/21 23:33:16 Well, the list is zero-terminated, but it might no
45 if (op == 0)
46 return false;
47 }
48
49 // Should not get here, the list is always zero terminated.
50 return false;
51 }
52
53 bool H264POC::ComputePicOrderCnt(
54 const media::H264SPS* sps,
55 const media::H264SliceHeader& slice_hdr,
56 int32_t *pic_order_cnt) {
57 if (slice_hdr.field_pic_flag) {
58 DLOG(ERROR) << "Interlaced frames are not supported";
59 return false;
60 }
61
62 // TODO(sandersd): Handle |gaps_in_frame_num_value|.
63 if (prev_frame_num_ > 0 && prev_frame_num_ < slice_hdr.frame_num - 1) {
64 DLOG(ERROR) << "Gaps in frame_num are not supported";
65 return false;
66 }
67
68 bool mmco5 = HasMMCO5(slice_hdr);
69 int32_t max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4);
70 int32_t max_pic_order_cnt_lsb =
71 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
72
73 // Based on T-REC-H.264 8.2.1, "Decoding process for picture order
74 // count", available from http://www.itu.int/rec/T-REC-H.264.
75 //
76 // Reorganized slightly from spec pseudocode to handle MMCO5 when storing
77 // state instead of when loading it.
78 switch (sps->pic_order_cnt_type) {
79 case 0: {
80 int32_t prev_pic_order_cnt_msb = ref_pic_order_cnt_msb_;
81 int32_t prev_pic_order_cnt_lsb = ref_pic_order_cnt_lsb_;
82
83 // For an IDR picture, clear the state.
84 if (slice_hdr.idr_pic_flag) {
85 prev_pic_order_cnt_msb = 0;
86 prev_pic_order_cnt_lsb = 0;
87 }
88
89 // 8-3. Derive |pic_order_cnt_msb|.
90 int32_t pic_order_cnt_msb;
91 if ((slice_hdr.pic_order_cnt_lsb < prev_pic_order_cnt_lsb) &&
92 (prev_pic_order_cnt_lsb - slice_hdr.pic_order_cnt_lsb >=
93 max_pic_order_cnt_lsb / 2)) {
94 pic_order_cnt_msb = prev_pic_order_cnt_msb + max_pic_order_cnt_lsb;
95 } else if ((slice_hdr.pic_order_cnt_lsb > prev_pic_order_cnt_lsb) &&
96 (slice_hdr.pic_order_cnt_lsb - prev_pic_order_cnt_lsb >
97 max_pic_order_cnt_lsb / 2)) {
98 pic_order_cnt_msb = prev_pic_order_cnt_msb - max_pic_order_cnt_lsb;
99 } else {
100 pic_order_cnt_msb = prev_pic_order_cnt_msb;
101 }
102
103 // 8-4, 8-5. Derive |top_field_order_count| and |bottom_field_order_cnt|.
104 int32_t top_foc = pic_order_cnt_msb + slice_hdr.pic_order_cnt_lsb;
105 int32_t bottom_foc = top_foc + slice_hdr.delta_pic_order_cnt_bottom;
106 *pic_order_cnt = std::min(top_foc, bottom_foc);
107
108 // Store state.
109 prev_frame_num_ = slice_hdr.frame_num;
110 if (slice_hdr.nal_ref_idc != 0) {
111 if (mmco5) {
112 ref_pic_order_cnt_msb_ = 0;
113 ref_pic_order_cnt_lsb_ = top_foc;
114 } else {
115 ref_pic_order_cnt_msb_ = pic_order_cnt_msb;
116 ref_pic_order_cnt_lsb_ = slice_hdr.pic_order_cnt_lsb;
117 }
118 }
119
120 break;
121 }
122
123 case 1: {
124 // 8-6. Derive |frame_num_offset|.
125 int32_t frame_num_offset;
126 if (slice_hdr.idr_pic_flag)
127 frame_num_offset = 0;
128 else if (prev_frame_num_ > slice_hdr.frame_num)
129 frame_num_offset = prev_frame_num_offset_ + max_frame_num;
130 else
131 frame_num_offset = prev_frame_num_offset_;
132
133 // 8-7. Derive |abs_frame_num|.
134 int32_t abs_frame_num;
135 if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
136 abs_frame_num = frame_num_offset + slice_hdr.frame_num;
137 else
138 abs_frame_num = 0;
139
140 if (slice_hdr.nal_ref_idc == 0 && abs_frame_num > 0)
141 abs_frame_num--;
142
143 // 8-9. Derive |expected_pic_order_cnt| (the |pic_order_cnt| indicated
144 // by the cycle described in the SPS).
145 int32_t expected_pic_order_cnt = 0;
146 if (abs_frame_num > 0) {
147 // 8-8. Derive pic_order_cnt_cycle_cnt and
148 // frame_num_in_pic_order_cnt_cycle.
149 // Moved inside 8-9 to avoid division when this check is not done.
150 if (sps->num_ref_frames_in_pic_order_cnt_cycle == 0) {
151 DLOG(ERROR) << "Invalid num_ref_frames_in_pic_order_cnt_cycle";
152 return false;
153 }
154
155 // H264Parser checks that num_ref_frames_in_pic_order_cnt_cycle < 255.
156 int32_t pic_order_cnt_cycle_cnt =
157 (abs_frame_num - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle;
158 int32_t frame_num_in_pic_order_cnt_cycle =
159 (abs_frame_num - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle;
160
161 // 8-9 continued.
162 expected_pic_order_cnt = pic_order_cnt_cycle_cnt *
163 sps->expected_delta_per_pic_order_cnt_cycle;
164 for (int32_t i = 0; i <= frame_num_in_pic_order_cnt_cycle; i++)
165 expected_pic_order_cnt += sps->offset_for_ref_frame[i];
166 }
167 if (slice_hdr.nal_ref_idc == 0)
168 expected_pic_order_cnt += sps->offset_for_non_ref_pic;
169
170 // 8-10. Derive |top_field_order_cnt| and |bottom_field_order_cnt|.
171 int32_t top_foc = expected_pic_order_cnt +
172 slice_hdr.delta_pic_order_cnt[0];
173 int32_t bottom_foc = top_foc + sps->offset_for_top_to_bottom_field +
174 slice_hdr.delta_pic_order_cnt[1];
175 *pic_order_cnt = std::min(top_foc, bottom_foc);
176
177 // Store state.
178 prev_frame_num_ = slice_hdr.frame_num;
179 prev_frame_num_offset_ = frame_num_offset;
180 if (mmco5)
181 prev_frame_num_offset_ = 0;
182
183 break;
184 }
185
186 case 2: {
187 // 8-11. Derive |frame_num_offset|.
188 int32_t frame_num_offset;
189 if (slice_hdr.idr_pic_flag)
190 frame_num_offset = 0;
191 else if (prev_frame_num_ > slice_hdr.frame_num)
192 frame_num_offset = prev_frame_num_offset_ + max_frame_num;
193 else
194 frame_num_offset = prev_frame_num_offset_;
195
196 // 8-12, 8-13. Derive |temp_pic_order_count| (it's always the
197 // |pic_order_cnt|).
198 if (slice_hdr.idr_pic_flag)
199 *pic_order_cnt = 0;
200 else if (slice_hdr.nal_ref_idc == 0)
201 *pic_order_cnt = 2 * (frame_num_offset + slice_hdr.frame_num) - 1;
202 else
203 *pic_order_cnt = 2 * (frame_num_offset + slice_hdr.frame_num);
204
205 // Store state.
206 prev_frame_num_ = slice_hdr.frame_num;
207 prev_frame_num_offset_ = frame_num_offset;
208 if (mmco5)
209 prev_frame_num_offset_ = 0;
210
211 break;
212 }
213
214 default:
215 DLOG(ERROR) << "Invalid pic_order_cnt_type: " << sps->pic_order_cnt_type;
216 return false;
217 }
218
219 return true;
220 }
221
222 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698