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

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: 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.
DaleCurtis 2014/11/20 23:03:30 Definitely needs a unit test in this CL, this is s
sandersd (OOO until July 31) 2014/11/20 23:58:25 Acknowledged. I'll ping when I have added that. I
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 static bool HasMMCO5(const media::H264SliceHeader& slice_hdr) {
DaleCurtis 2014/11/20 23:03:30 Needs docs.
sandersd (OOO until July 31) 2014/11/20 23:58:24 Done.
30 if (slice_hdr.nal_ref_idc == 0 ||
31 slice_hdr.idr_pic_flag ||
32 !slice_hdr.adaptive_ref_pic_marking_mode_flag) {
33 return false;
34 }
35
36 for (size_t i = 0; i < arraysize(slice_hdr.ref_pic_marking); i++) {
DaleCurtis 2014/11/20 23:03:29 Why is this a loop? It seems this is all just: re
sandersd (OOO until July 31) 2014/11/20 23:58:24 No, it loops until ref_pic_marking[i].mmco == 0, r
37 switch (slice_hdr.ref_pic_marking[i].memory_mgmnt_control_operation) {
38 case 0:
39 return false;
40 case 5:
41 return true;
42 default:
43 break;
44 }
45 }
46
47 // Should not get here, the list is always zero terminated.
48 return false;
49 }
50
51 bool H264POC::ComputePicOrderCnt(
52 const media::H264SPS* sps,
53 const media::H264SliceHeader& slice_hdr,
54 int32_t *pic_order_cnt) {
55 if (slice_hdr.field_pic_flag) {
56 DLOG(ERROR) << "Interlaced frames are not supported";
57 return false;
58 }
59
60 // TODO(sandersd): Handle |gaps_in_frame_num_value|.
61 if (prev_frame_num_ > 0 && prev_frame_num_ < slice_hdr.frame_num - 1) {
62 DLOG(ERROR) << "Gaps in frame_num are not supported";
63 return false;
64 }
65
66 bool mmco5 = HasMMCO5(slice_hdr);
DaleCurtis 2014/11/20 23:03:30 Docs or a link to the spec this is implementing?
sandersd (OOO until July 31) 2014/11/20 23:58:24 Done.
67 int32_t max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4);
68 int32_t max_pic_order_cnt_lsb =
69 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
70
71 // Reorganized slightly from spec pseudocode to handle MMCO5 when storing.
72 switch (sps->pic_order_cnt_type) {
DaleCurtis 2014/11/20 23:03:30 nit: This actually seems like it would look better
sandersd (OOO until July 31) 2014/11/20 23:58:24 I tried it both ways, I think it's more clear as a
73 case 0:
74 {
DaleCurtis 2014/11/20 23:03:29 Move { to above line and save 2 spaces of indent.
sandersd (OOO until July 31) 2014/11/20 23:58:24 Done.
75 int32_t prev_pic_order_cnt_msb = ref_pic_order_cnt_msb_;
76 int32_t prev_pic_order_cnt_lsb = ref_pic_order_cnt_lsb_;
77
78 if (slice_hdr.idr_pic_flag) {
79 prev_pic_order_cnt_msb = 0;
80 prev_pic_order_cnt_lsb = 0;
81 }
82
83 // 8-3.
DaleCurtis 2014/11/20 23:03:29 Helps to include summary of this step :) Ditto for
sandersd (OOO until July 31) 2014/11/20 23:58:24 Done. At least as much as possible, the steps are
84 int32_t pic_order_cnt_msb;
85 if ((slice_hdr.pic_order_cnt_lsb < prev_pic_order_cnt_lsb) &&
86 (prev_pic_order_cnt_lsb - slice_hdr.pic_order_cnt_lsb >=
87 max_pic_order_cnt_lsb / 2)) {
88 pic_order_cnt_msb = prev_pic_order_cnt_msb + max_pic_order_cnt_lsb;
89 } else if ((slice_hdr.pic_order_cnt_lsb > prev_pic_order_cnt_lsb) &&
90 (slice_hdr.pic_order_cnt_lsb - prev_pic_order_cnt_lsb >
91 max_pic_order_cnt_lsb / 2)) {
92 pic_order_cnt_msb = prev_pic_order_cnt_msb - max_pic_order_cnt_lsb;
93 } else {
94 pic_order_cnt_msb = prev_pic_order_cnt_msb;
95 }
96
97 // 8-4, 8-5.
98 int32_t top_poc = pic_order_cnt_msb + slice_hdr.pic_order_cnt_lsb;
99 int32_t bottom_poc = top_poc + slice_hdr.delta_pic_order_cnt_bottom;
100 *pic_order_cnt = std::min(top_poc, bottom_poc);
101
102 // Store state.
103 prev_frame_num_ = slice_hdr.frame_num;
104 if (slice_hdr.nal_ref_idc != 0) {
105 if (mmco5) {
106 ref_pic_order_cnt_msb_ = 0;
107 ref_pic_order_cnt_lsb_ = top_poc;
108 } else {
109 ref_pic_order_cnt_msb_ = pic_order_cnt_msb;
110 ref_pic_order_cnt_lsb_ = slice_hdr.pic_order_cnt_lsb;
111 }
112 }
113
114 break;
115 }
116
117 case 1:
118 {
119 // AVC 8.2.1.2.
DaleCurtis 2014/11/20 23:03:30 Again, this is all gibberish to me, so you'll need
sandersd (OOO until July 31) 2014/11/20 23:58:24 Acknowledged.
120 // 8-6.
121 int32_t frame_num_offset;
122 if (slice_hdr.idr_pic_flag)
123 frame_num_offset = 0;
124 else if (prev_frame_num_ > slice_hdr.frame_num)
125 frame_num_offset = prev_frame_num_offset_ + max_frame_num;
126 else
127 frame_num_offset = prev_frame_num_offset_;
128
129 // 8-7.
130 int32_t abs_frame_num;
131 if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
132 abs_frame_num = frame_num_offset + slice_hdr.frame_num;
133 else
134 abs_frame_num = 0;
135
136 if (slice_hdr.nal_ref_idc == 0 && abs_frame_num > 0)
137 abs_frame_num--;
138
139 // 8-9.
140 int32_t expected_pic_order_cnt = 0;
141 if (abs_frame_num > 0) {
142 // 8-8.
143 if (sps->num_ref_frames_in_pic_order_cnt_cycle == 0) {
144 DLOG(ERROR) << "Invalid num_ref_frames_in_pic_order_cnt_cycle";
145 return false;
146 }
147
148 int32_t pic_order_cnt_cycle_cnt =
149 (abs_frame_num - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle;
150 int32_t frame_num_in_pic_order_cnt_cycle =
151 (abs_frame_num - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle;
152 expected_pic_order_cnt = pic_order_cnt_cycle_cnt *
153 sps->expected_delta_per_pic_order_cnt_cycle;
154
155 // H264Parser checks that num_ref_frames_in_pic_order_cnt_cycle < 255.
156 for (int32_t i = 0; i <= frame_num_in_pic_order_cnt_cycle; i++)
157 expected_pic_order_cnt += sps->offset_for_ref_frame[i];
158 }
159 if (slice_hdr.nal_ref_idc == 0)
160 expected_pic_order_cnt += sps->offset_for_non_ref_pic;
161
162 // 8-10.
163 int32_t top_poc = expected_pic_order_cnt +
164 slice_hdr.delta_pic_order_cnt[0];
165 int32_t bottom_poc = top_poc + sps->offset_for_top_to_bottom_field +
166 slice_hdr.delta_pic_order_cnt[1];
167 *pic_order_cnt = std::min(top_poc, bottom_poc);
168
169 // Store state.
170 prev_frame_num_ = slice_hdr.frame_num;
171 prev_frame_num_offset_ = frame_num_offset;
172 if (mmco5)
173 prev_frame_num_offset_ = 0;
174
175 break;
176 }
177
178 case 2:
179 {
180 // AVC 8.2.1.3.
181 // 8-11.
182 int32_t frame_num_offset;
183 if (slice_hdr.idr_pic_flag)
184 frame_num_offset = 0;
185 else if (prev_frame_num_ > slice_hdr.frame_num)
186 frame_num_offset = prev_frame_num_offset_ + max_frame_num;
187 else
188 frame_num_offset = prev_frame_num_offset_;
189
190 // 8-12, 8-13.
191 if (slice_hdr.idr_pic_flag)
192 *pic_order_cnt = 0;
193 else if (slice_hdr.nal_ref_idc == 0)
194 *pic_order_cnt = 2 * (frame_num_offset + slice_hdr.frame_num) - 1;
195 else
196 *pic_order_cnt = 2 * (frame_num_offset + slice_hdr.frame_num);
197
198 // Store state.
199 prev_frame_num_ = slice_hdr.frame_num;
200 prev_frame_num_offset_ = frame_num_offset;
201 if (mmco5)
202 prev_frame_num_offset_ = 0;
203
204 break;
205 }
206
207 default:
208 DLOG(ERROR) << "Invalid pic_order_cnt_type: " << sps->pic_order_cnt_type;
209 return false;
210 }
211
212 return true;
213 }
214
215 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698