xref: /aosp_15_r20/external/libdav1d/src/obu.c (revision c09093415860a1c2373dacd84c4fde00c507cdfd)
1*c0909341SAndroid Build Coastguard Worker /*
2*c0909341SAndroid Build Coastguard Worker  * Copyright © 2018-2021, VideoLAN and dav1d authors
3*c0909341SAndroid Build Coastguard Worker  * Copyright © 2018, Two Orioles, LLC
4*c0909341SAndroid Build Coastguard Worker  * All rights reserved.
5*c0909341SAndroid Build Coastguard Worker  *
6*c0909341SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
7*c0909341SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions are met:
8*c0909341SAndroid Build Coastguard Worker  *
9*c0909341SAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright notice, this
10*c0909341SAndroid Build Coastguard Worker  *    list of conditions and the following disclaimer.
11*c0909341SAndroid Build Coastguard Worker  *
12*c0909341SAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright notice,
13*c0909341SAndroid Build Coastguard Worker  *    this list of conditions and the following disclaimer in the documentation
14*c0909341SAndroid Build Coastguard Worker  *    and/or other materials provided with the distribution.
15*c0909341SAndroid Build Coastguard Worker  *
16*c0909341SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17*c0909341SAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*c0909341SAndroid Build Coastguard Worker  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*c0909341SAndroid Build Coastguard Worker  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20*c0909341SAndroid Build Coastguard Worker  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21*c0909341SAndroid Build Coastguard Worker  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*c0909341SAndroid Build Coastguard Worker  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23*c0909341SAndroid Build Coastguard Worker  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*c0909341SAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*c0909341SAndroid Build Coastguard Worker  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*c0909341SAndroid Build Coastguard Worker  */
27*c0909341SAndroid Build Coastguard Worker 
28*c0909341SAndroid Build Coastguard Worker #include "config.h"
29*c0909341SAndroid Build Coastguard Worker 
30*c0909341SAndroid Build Coastguard Worker #include <errno.h>
31*c0909341SAndroid Build Coastguard Worker #include <limits.h>
32*c0909341SAndroid Build Coastguard Worker #include <stdio.h>
33*c0909341SAndroid Build Coastguard Worker 
34*c0909341SAndroid Build Coastguard Worker #include "dav1d/data.h"
35*c0909341SAndroid Build Coastguard Worker 
36*c0909341SAndroid Build Coastguard Worker #include "common/frame.h"
37*c0909341SAndroid Build Coastguard Worker #include "common/intops.h"
38*c0909341SAndroid Build Coastguard Worker #include "common/validate.h"
39*c0909341SAndroid Build Coastguard Worker 
40*c0909341SAndroid Build Coastguard Worker #include "src/decode.h"
41*c0909341SAndroid Build Coastguard Worker #include "src/getbits.h"
42*c0909341SAndroid Build Coastguard Worker #include "src/levels.h"
43*c0909341SAndroid Build Coastguard Worker #include "src/log.h"
44*c0909341SAndroid Build Coastguard Worker #include "src/obu.h"
45*c0909341SAndroid Build Coastguard Worker #include "src/ref.h"
46*c0909341SAndroid Build Coastguard Worker #include "src/thread_task.h"
47*c0909341SAndroid Build Coastguard Worker 
check_trailing_bits(GetBits * const gb,const int strict_std_compliance)48*c0909341SAndroid Build Coastguard Worker static int check_trailing_bits(GetBits *const gb,
49*c0909341SAndroid Build Coastguard Worker                                const int strict_std_compliance)
50*c0909341SAndroid Build Coastguard Worker {
51*c0909341SAndroid Build Coastguard Worker     const int trailing_one_bit = dav1d_get_bit(gb);
52*c0909341SAndroid Build Coastguard Worker 
53*c0909341SAndroid Build Coastguard Worker     if (gb->error)
54*c0909341SAndroid Build Coastguard Worker         return DAV1D_ERR(EINVAL);
55*c0909341SAndroid Build Coastguard Worker 
56*c0909341SAndroid Build Coastguard Worker     if (!strict_std_compliance)
57*c0909341SAndroid Build Coastguard Worker         return 0;
58*c0909341SAndroid Build Coastguard Worker 
59*c0909341SAndroid Build Coastguard Worker     if (!trailing_one_bit || gb->state)
60*c0909341SAndroid Build Coastguard Worker         return DAV1D_ERR(EINVAL);
61*c0909341SAndroid Build Coastguard Worker 
62*c0909341SAndroid Build Coastguard Worker     ptrdiff_t size = gb->ptr_end - gb->ptr;
63*c0909341SAndroid Build Coastguard Worker     while (size > 0 && gb->ptr[size - 1] == 0)
64*c0909341SAndroid Build Coastguard Worker         size--;
65*c0909341SAndroid Build Coastguard Worker 
66*c0909341SAndroid Build Coastguard Worker     if (size)
67*c0909341SAndroid Build Coastguard Worker         return DAV1D_ERR(EINVAL);
68*c0909341SAndroid Build Coastguard Worker 
69*c0909341SAndroid Build Coastguard Worker     return 0;
70*c0909341SAndroid Build Coastguard Worker }
71*c0909341SAndroid Build Coastguard Worker 
parse_seq_hdr(Dav1dSequenceHeader * const hdr,GetBits * const gb,const int strict_std_compliance)72*c0909341SAndroid Build Coastguard Worker static NOINLINE int parse_seq_hdr(Dav1dSequenceHeader *const hdr,
73*c0909341SAndroid Build Coastguard Worker                                   GetBits *const gb,
74*c0909341SAndroid Build Coastguard Worker                                   const int strict_std_compliance)
75*c0909341SAndroid Build Coastguard Worker {
76*c0909341SAndroid Build Coastguard Worker #define DEBUG_SEQ_HDR 0
77*c0909341SAndroid Build Coastguard Worker 
78*c0909341SAndroid Build Coastguard Worker #if DEBUG_SEQ_HDR
79*c0909341SAndroid Build Coastguard Worker     const unsigned init_bit_pos = dav1d_get_bits_pos(gb);
80*c0909341SAndroid Build Coastguard Worker #endif
81*c0909341SAndroid Build Coastguard Worker 
82*c0909341SAndroid Build Coastguard Worker     memset(hdr, 0, sizeof(*hdr));
83*c0909341SAndroid Build Coastguard Worker     hdr->profile = dav1d_get_bits(gb, 3);
84*c0909341SAndroid Build Coastguard Worker     if (hdr->profile > 2) goto error;
85*c0909341SAndroid Build Coastguard Worker #if DEBUG_SEQ_HDR
86*c0909341SAndroid Build Coastguard Worker     printf("SEQHDR: post-profile: off=%u\n",
87*c0909341SAndroid Build Coastguard Worker            dav1d_get_bits_pos(gb) - init_bit_pos);
88*c0909341SAndroid Build Coastguard Worker #endif
89*c0909341SAndroid Build Coastguard Worker 
90*c0909341SAndroid Build Coastguard Worker     hdr->still_picture = dav1d_get_bit(gb);
91*c0909341SAndroid Build Coastguard Worker     hdr->reduced_still_picture_header = dav1d_get_bit(gb);
92*c0909341SAndroid Build Coastguard Worker     if (hdr->reduced_still_picture_header && !hdr->still_picture) goto error;
93*c0909341SAndroid Build Coastguard Worker #if DEBUG_SEQ_HDR
94*c0909341SAndroid Build Coastguard Worker     printf("SEQHDR: post-stillpicture_flags: off=%u\n",
95*c0909341SAndroid Build Coastguard Worker            dav1d_get_bits_pos(gb) - init_bit_pos);
96*c0909341SAndroid Build Coastguard Worker #endif
97*c0909341SAndroid Build Coastguard Worker 
98*c0909341SAndroid Build Coastguard Worker     if (hdr->reduced_still_picture_header) {
99*c0909341SAndroid Build Coastguard Worker         hdr->num_operating_points = 1;
100*c0909341SAndroid Build Coastguard Worker         hdr->operating_points[0].major_level = dav1d_get_bits(gb, 3);
101*c0909341SAndroid Build Coastguard Worker         hdr->operating_points[0].minor_level = dav1d_get_bits(gb, 2);
102*c0909341SAndroid Build Coastguard Worker         hdr->operating_points[0].initial_display_delay = 10;
103*c0909341SAndroid Build Coastguard Worker     } else {
104*c0909341SAndroid Build Coastguard Worker         hdr->timing_info_present = dav1d_get_bit(gb);
105*c0909341SAndroid Build Coastguard Worker         if (hdr->timing_info_present) {
106*c0909341SAndroid Build Coastguard Worker             hdr->num_units_in_tick = dav1d_get_bits(gb, 32);
107*c0909341SAndroid Build Coastguard Worker             hdr->time_scale = dav1d_get_bits(gb, 32);
108*c0909341SAndroid Build Coastguard Worker             if (strict_std_compliance && (!hdr->num_units_in_tick || !hdr->time_scale))
109*c0909341SAndroid Build Coastguard Worker                 goto error;
110*c0909341SAndroid Build Coastguard Worker             hdr->equal_picture_interval = dav1d_get_bit(gb);
111*c0909341SAndroid Build Coastguard Worker             if (hdr->equal_picture_interval) {
112*c0909341SAndroid Build Coastguard Worker                 const unsigned num_ticks_per_picture = dav1d_get_vlc(gb);
113*c0909341SAndroid Build Coastguard Worker                 if (num_ticks_per_picture == 0xFFFFFFFFU)
114*c0909341SAndroid Build Coastguard Worker                     goto error;
115*c0909341SAndroid Build Coastguard Worker                 hdr->num_ticks_per_picture = num_ticks_per_picture + 1;
116*c0909341SAndroid Build Coastguard Worker             }
117*c0909341SAndroid Build Coastguard Worker 
118*c0909341SAndroid Build Coastguard Worker             hdr->decoder_model_info_present = dav1d_get_bit(gb);
119*c0909341SAndroid Build Coastguard Worker             if (hdr->decoder_model_info_present) {
120*c0909341SAndroid Build Coastguard Worker                 hdr->encoder_decoder_buffer_delay_length = dav1d_get_bits(gb, 5) + 1;
121*c0909341SAndroid Build Coastguard Worker                 hdr->num_units_in_decoding_tick = dav1d_get_bits(gb, 32);
122*c0909341SAndroid Build Coastguard Worker                 if (strict_std_compliance && !hdr->num_units_in_decoding_tick)
123*c0909341SAndroid Build Coastguard Worker                     goto error;
124*c0909341SAndroid Build Coastguard Worker                 hdr->buffer_removal_delay_length = dav1d_get_bits(gb, 5) + 1;
125*c0909341SAndroid Build Coastguard Worker                 hdr->frame_presentation_delay_length = dav1d_get_bits(gb, 5) + 1;
126*c0909341SAndroid Build Coastguard Worker             }
127*c0909341SAndroid Build Coastguard Worker         }
128*c0909341SAndroid Build Coastguard Worker #if DEBUG_SEQ_HDR
129*c0909341SAndroid Build Coastguard Worker         printf("SEQHDR: post-timinginfo: off=%u\n",
130*c0909341SAndroid Build Coastguard Worker                dav1d_get_bits_pos(gb) - init_bit_pos);
131*c0909341SAndroid Build Coastguard Worker #endif
132*c0909341SAndroid Build Coastguard Worker 
133*c0909341SAndroid Build Coastguard Worker         hdr->display_model_info_present = dav1d_get_bit(gb);
134*c0909341SAndroid Build Coastguard Worker         hdr->num_operating_points = dav1d_get_bits(gb, 5) + 1;
135*c0909341SAndroid Build Coastguard Worker         for (int i = 0; i < hdr->num_operating_points; i++) {
136*c0909341SAndroid Build Coastguard Worker             struct Dav1dSequenceHeaderOperatingPoint *const op =
137*c0909341SAndroid Build Coastguard Worker                 &hdr->operating_points[i];
138*c0909341SAndroid Build Coastguard Worker             op->idc = dav1d_get_bits(gb, 12);
139*c0909341SAndroid Build Coastguard Worker             if (op->idc && (!(op->idc & 0xff) || !(op->idc & 0xf00)))
140*c0909341SAndroid Build Coastguard Worker                 goto error;
141*c0909341SAndroid Build Coastguard Worker             op->major_level = 2 + dav1d_get_bits(gb, 3);
142*c0909341SAndroid Build Coastguard Worker             op->minor_level = dav1d_get_bits(gb, 2);
143*c0909341SAndroid Build Coastguard Worker             if (op->major_level > 3)
144*c0909341SAndroid Build Coastguard Worker                 op->tier = dav1d_get_bit(gb);
145*c0909341SAndroid Build Coastguard Worker             if (hdr->decoder_model_info_present) {
146*c0909341SAndroid Build Coastguard Worker                 op->decoder_model_param_present = dav1d_get_bit(gb);
147*c0909341SAndroid Build Coastguard Worker                 if (op->decoder_model_param_present) {
148*c0909341SAndroid Build Coastguard Worker                     struct Dav1dSequenceHeaderOperatingParameterInfo *const opi =
149*c0909341SAndroid Build Coastguard Worker                         &hdr->operating_parameter_info[i];
150*c0909341SAndroid Build Coastguard Worker                     opi->decoder_buffer_delay =
151*c0909341SAndroid Build Coastguard Worker                         dav1d_get_bits(gb, hdr->encoder_decoder_buffer_delay_length);
152*c0909341SAndroid Build Coastguard Worker                     opi->encoder_buffer_delay =
153*c0909341SAndroid Build Coastguard Worker                         dav1d_get_bits(gb, hdr->encoder_decoder_buffer_delay_length);
154*c0909341SAndroid Build Coastguard Worker                     opi->low_delay_mode = dav1d_get_bit(gb);
155*c0909341SAndroid Build Coastguard Worker                 }
156*c0909341SAndroid Build Coastguard Worker             }
157*c0909341SAndroid Build Coastguard Worker             if (hdr->display_model_info_present)
158*c0909341SAndroid Build Coastguard Worker                 op->display_model_param_present = dav1d_get_bit(gb);
159*c0909341SAndroid Build Coastguard Worker             op->initial_display_delay =
160*c0909341SAndroid Build Coastguard Worker                 op->display_model_param_present ? dav1d_get_bits(gb, 4) + 1 : 10;
161*c0909341SAndroid Build Coastguard Worker         }
162*c0909341SAndroid Build Coastguard Worker #if DEBUG_SEQ_HDR
163*c0909341SAndroid Build Coastguard Worker         printf("SEQHDR: post-operating-points: off=%u\n",
164*c0909341SAndroid Build Coastguard Worker                dav1d_get_bits_pos(gb) - init_bit_pos);
165*c0909341SAndroid Build Coastguard Worker #endif
166*c0909341SAndroid Build Coastguard Worker     }
167*c0909341SAndroid Build Coastguard Worker 
168*c0909341SAndroid Build Coastguard Worker     hdr->width_n_bits = dav1d_get_bits(gb, 4) + 1;
169*c0909341SAndroid Build Coastguard Worker     hdr->height_n_bits = dav1d_get_bits(gb, 4) + 1;
170*c0909341SAndroid Build Coastguard Worker     hdr->max_width = dav1d_get_bits(gb, hdr->width_n_bits) + 1;
171*c0909341SAndroid Build Coastguard Worker     hdr->max_height = dav1d_get_bits(gb, hdr->height_n_bits) + 1;
172*c0909341SAndroid Build Coastguard Worker #if DEBUG_SEQ_HDR
173*c0909341SAndroid Build Coastguard Worker     printf("SEQHDR: post-size: off=%u\n",
174*c0909341SAndroid Build Coastguard Worker            dav1d_get_bits_pos(gb) - init_bit_pos);
175*c0909341SAndroid Build Coastguard Worker #endif
176*c0909341SAndroid Build Coastguard Worker     if (!hdr->reduced_still_picture_header) {
177*c0909341SAndroid Build Coastguard Worker         hdr->frame_id_numbers_present = dav1d_get_bit(gb);
178*c0909341SAndroid Build Coastguard Worker         if (hdr->frame_id_numbers_present) {
179*c0909341SAndroid Build Coastguard Worker             hdr->delta_frame_id_n_bits = dav1d_get_bits(gb, 4) + 2;
180*c0909341SAndroid Build Coastguard Worker             hdr->frame_id_n_bits = dav1d_get_bits(gb, 3) + hdr->delta_frame_id_n_bits + 1;
181*c0909341SAndroid Build Coastguard Worker         }
182*c0909341SAndroid Build Coastguard Worker     }
183*c0909341SAndroid Build Coastguard Worker #if DEBUG_SEQ_HDR
184*c0909341SAndroid Build Coastguard Worker     printf("SEQHDR: post-frame-id-numbers-present: off=%u\n",
185*c0909341SAndroid Build Coastguard Worker            dav1d_get_bits_pos(gb) - init_bit_pos);
186*c0909341SAndroid Build Coastguard Worker #endif
187*c0909341SAndroid Build Coastguard Worker 
188*c0909341SAndroid Build Coastguard Worker     hdr->sb128 = dav1d_get_bit(gb);
189*c0909341SAndroid Build Coastguard Worker     hdr->filter_intra = dav1d_get_bit(gb);
190*c0909341SAndroid Build Coastguard Worker     hdr->intra_edge_filter = dav1d_get_bit(gb);
191*c0909341SAndroid Build Coastguard Worker     if (hdr->reduced_still_picture_header) {
192*c0909341SAndroid Build Coastguard Worker         hdr->screen_content_tools = DAV1D_ADAPTIVE;
193*c0909341SAndroid Build Coastguard Worker         hdr->force_integer_mv = DAV1D_ADAPTIVE;
194*c0909341SAndroid Build Coastguard Worker     } else {
195*c0909341SAndroid Build Coastguard Worker         hdr->inter_intra = dav1d_get_bit(gb);
196*c0909341SAndroid Build Coastguard Worker         hdr->masked_compound = dav1d_get_bit(gb);
197*c0909341SAndroid Build Coastguard Worker         hdr->warped_motion = dav1d_get_bit(gb);
198*c0909341SAndroid Build Coastguard Worker         hdr->dual_filter = dav1d_get_bit(gb);
199*c0909341SAndroid Build Coastguard Worker         hdr->order_hint = dav1d_get_bit(gb);
200*c0909341SAndroid Build Coastguard Worker         if (hdr->order_hint) {
201*c0909341SAndroid Build Coastguard Worker             hdr->jnt_comp = dav1d_get_bit(gb);
202*c0909341SAndroid Build Coastguard Worker             hdr->ref_frame_mvs = dav1d_get_bit(gb);
203*c0909341SAndroid Build Coastguard Worker         }
204*c0909341SAndroid Build Coastguard Worker         hdr->screen_content_tools = dav1d_get_bit(gb) ? DAV1D_ADAPTIVE : dav1d_get_bit(gb);
205*c0909341SAndroid Build Coastguard Worker     #if DEBUG_SEQ_HDR
206*c0909341SAndroid Build Coastguard Worker         printf("SEQHDR: post-screentools: off=%u\n",
207*c0909341SAndroid Build Coastguard Worker                dav1d_get_bits_pos(gb) - init_bit_pos);
208*c0909341SAndroid Build Coastguard Worker     #endif
209*c0909341SAndroid Build Coastguard Worker         hdr->force_integer_mv = hdr->screen_content_tools ?
210*c0909341SAndroid Build Coastguard Worker                                 dav1d_get_bit(gb) ? DAV1D_ADAPTIVE : dav1d_get_bit(gb) : 2;
211*c0909341SAndroid Build Coastguard Worker         if (hdr->order_hint)
212*c0909341SAndroid Build Coastguard Worker             hdr->order_hint_n_bits = dav1d_get_bits(gb, 3) + 1;
213*c0909341SAndroid Build Coastguard Worker     }
214*c0909341SAndroid Build Coastguard Worker     hdr->super_res = dav1d_get_bit(gb);
215*c0909341SAndroid Build Coastguard Worker     hdr->cdef = dav1d_get_bit(gb);
216*c0909341SAndroid Build Coastguard Worker     hdr->restoration = dav1d_get_bit(gb);
217*c0909341SAndroid Build Coastguard Worker #if DEBUG_SEQ_HDR
218*c0909341SAndroid Build Coastguard Worker     printf("SEQHDR: post-featurebits: off=%u\n",
219*c0909341SAndroid Build Coastguard Worker            dav1d_get_bits_pos(gb) - init_bit_pos);
220*c0909341SAndroid Build Coastguard Worker #endif
221*c0909341SAndroid Build Coastguard Worker 
222*c0909341SAndroid Build Coastguard Worker     hdr->hbd = dav1d_get_bit(gb);
223*c0909341SAndroid Build Coastguard Worker     if (hdr->profile == 2 && hdr->hbd)
224*c0909341SAndroid Build Coastguard Worker         hdr->hbd += dav1d_get_bit(gb);
225*c0909341SAndroid Build Coastguard Worker     if (hdr->profile != 1)
226*c0909341SAndroid Build Coastguard Worker         hdr->monochrome = dav1d_get_bit(gb);
227*c0909341SAndroid Build Coastguard Worker     hdr->color_description_present = dav1d_get_bit(gb);
228*c0909341SAndroid Build Coastguard Worker     if (hdr->color_description_present) {
229*c0909341SAndroid Build Coastguard Worker         hdr->pri = dav1d_get_bits(gb, 8);
230*c0909341SAndroid Build Coastguard Worker         hdr->trc = dav1d_get_bits(gb, 8);
231*c0909341SAndroid Build Coastguard Worker         hdr->mtrx = dav1d_get_bits(gb, 8);
232*c0909341SAndroid Build Coastguard Worker     } else {
233*c0909341SAndroid Build Coastguard Worker         hdr->pri = DAV1D_COLOR_PRI_UNKNOWN;
234*c0909341SAndroid Build Coastguard Worker         hdr->trc = DAV1D_TRC_UNKNOWN;
235*c0909341SAndroid Build Coastguard Worker         hdr->mtrx = DAV1D_MC_UNKNOWN;
236*c0909341SAndroid Build Coastguard Worker     }
237*c0909341SAndroid Build Coastguard Worker     if (hdr->monochrome) {
238*c0909341SAndroid Build Coastguard Worker         hdr->color_range = dav1d_get_bit(gb);
239*c0909341SAndroid Build Coastguard Worker         hdr->layout = DAV1D_PIXEL_LAYOUT_I400;
240*c0909341SAndroid Build Coastguard Worker         hdr->ss_hor = hdr->ss_ver = 1;
241*c0909341SAndroid Build Coastguard Worker         hdr->chr = DAV1D_CHR_UNKNOWN;
242*c0909341SAndroid Build Coastguard Worker     } else if (hdr->pri == DAV1D_COLOR_PRI_BT709 &&
243*c0909341SAndroid Build Coastguard Worker                hdr->trc == DAV1D_TRC_SRGB &&
244*c0909341SAndroid Build Coastguard Worker                hdr->mtrx == DAV1D_MC_IDENTITY)
245*c0909341SAndroid Build Coastguard Worker     {
246*c0909341SAndroid Build Coastguard Worker         hdr->layout = DAV1D_PIXEL_LAYOUT_I444;
247*c0909341SAndroid Build Coastguard Worker         hdr->color_range = 1;
248*c0909341SAndroid Build Coastguard Worker         if (hdr->profile != 1 && !(hdr->profile == 2 && hdr->hbd == 2))
249*c0909341SAndroid Build Coastguard Worker             goto error;
250*c0909341SAndroid Build Coastguard Worker     } else {
251*c0909341SAndroid Build Coastguard Worker         hdr->color_range = dav1d_get_bit(gb);
252*c0909341SAndroid Build Coastguard Worker         switch (hdr->profile) {
253*c0909341SAndroid Build Coastguard Worker         case 0: hdr->layout = DAV1D_PIXEL_LAYOUT_I420;
254*c0909341SAndroid Build Coastguard Worker                 hdr->ss_hor = hdr->ss_ver = 1;
255*c0909341SAndroid Build Coastguard Worker                 break;
256*c0909341SAndroid Build Coastguard Worker         case 1: hdr->layout = DAV1D_PIXEL_LAYOUT_I444;
257*c0909341SAndroid Build Coastguard Worker                 break;
258*c0909341SAndroid Build Coastguard Worker         case 2:
259*c0909341SAndroid Build Coastguard Worker             if (hdr->hbd == 2) {
260*c0909341SAndroid Build Coastguard Worker                 hdr->ss_hor = dav1d_get_bit(gb);
261*c0909341SAndroid Build Coastguard Worker                 if (hdr->ss_hor)
262*c0909341SAndroid Build Coastguard Worker                     hdr->ss_ver = dav1d_get_bit(gb);
263*c0909341SAndroid Build Coastguard Worker             } else
264*c0909341SAndroid Build Coastguard Worker                 hdr->ss_hor = 1;
265*c0909341SAndroid Build Coastguard Worker             hdr->layout = hdr->ss_hor ?
266*c0909341SAndroid Build Coastguard Worker                           hdr->ss_ver ? DAV1D_PIXEL_LAYOUT_I420 :
267*c0909341SAndroid Build Coastguard Worker                                         DAV1D_PIXEL_LAYOUT_I422 :
268*c0909341SAndroid Build Coastguard Worker                                         DAV1D_PIXEL_LAYOUT_I444;
269*c0909341SAndroid Build Coastguard Worker             break;
270*c0909341SAndroid Build Coastguard Worker         }
271*c0909341SAndroid Build Coastguard Worker         hdr->chr = (hdr->ss_hor & hdr->ss_ver) ?
272*c0909341SAndroid Build Coastguard Worker                    dav1d_get_bits(gb, 2) : DAV1D_CHR_UNKNOWN;
273*c0909341SAndroid Build Coastguard Worker     }
274*c0909341SAndroid Build Coastguard Worker     if (strict_std_compliance &&
275*c0909341SAndroid Build Coastguard Worker         hdr->mtrx == DAV1D_MC_IDENTITY && hdr->layout != DAV1D_PIXEL_LAYOUT_I444)
276*c0909341SAndroid Build Coastguard Worker     {
277*c0909341SAndroid Build Coastguard Worker         goto error;
278*c0909341SAndroid Build Coastguard Worker     }
279*c0909341SAndroid Build Coastguard Worker     if (!hdr->monochrome)
280*c0909341SAndroid Build Coastguard Worker         hdr->separate_uv_delta_q = dav1d_get_bit(gb);
281*c0909341SAndroid Build Coastguard Worker #if DEBUG_SEQ_HDR
282*c0909341SAndroid Build Coastguard Worker     printf("SEQHDR: post-colorinfo: off=%u\n",
283*c0909341SAndroid Build Coastguard Worker            dav1d_get_bits_pos(gb) - init_bit_pos);
284*c0909341SAndroid Build Coastguard Worker #endif
285*c0909341SAndroid Build Coastguard Worker 
286*c0909341SAndroid Build Coastguard Worker     hdr->film_grain_present = dav1d_get_bit(gb);
287*c0909341SAndroid Build Coastguard Worker #if DEBUG_SEQ_HDR
288*c0909341SAndroid Build Coastguard Worker     printf("SEQHDR: post-filmgrain: off=%u\n",
289*c0909341SAndroid Build Coastguard Worker            dav1d_get_bits_pos(gb) - init_bit_pos);
290*c0909341SAndroid Build Coastguard Worker #endif
291*c0909341SAndroid Build Coastguard Worker 
292*c0909341SAndroid Build Coastguard Worker     // We needn't bother flushing the OBU here: we'll check we didn't
293*c0909341SAndroid Build Coastguard Worker     // overrun in the caller and will then discard gb, so there's no
294*c0909341SAndroid Build Coastguard Worker     // point in setting its position properly.
295*c0909341SAndroid Build Coastguard Worker 
296*c0909341SAndroid Build Coastguard Worker     return check_trailing_bits(gb, strict_std_compliance);
297*c0909341SAndroid Build Coastguard Worker 
298*c0909341SAndroid Build Coastguard Worker error:
299*c0909341SAndroid Build Coastguard Worker     return DAV1D_ERR(EINVAL);
300*c0909341SAndroid Build Coastguard Worker }
301*c0909341SAndroid Build Coastguard Worker 
dav1d_parse_sequence_header(Dav1dSequenceHeader * const out,const uint8_t * const ptr,const size_t sz)302*c0909341SAndroid Build Coastguard Worker int dav1d_parse_sequence_header(Dav1dSequenceHeader *const out,
303*c0909341SAndroid Build Coastguard Worker                                 const uint8_t *const ptr, const size_t sz)
304*c0909341SAndroid Build Coastguard Worker {
305*c0909341SAndroid Build Coastguard Worker     validate_input_or_ret(out != NULL, DAV1D_ERR(EINVAL));
306*c0909341SAndroid Build Coastguard Worker     validate_input_or_ret(ptr != NULL, DAV1D_ERR(EINVAL));
307*c0909341SAndroid Build Coastguard Worker     validate_input_or_ret(sz > 0 && sz <= SIZE_MAX / 2, DAV1D_ERR(EINVAL));
308*c0909341SAndroid Build Coastguard Worker 
309*c0909341SAndroid Build Coastguard Worker     GetBits gb;
310*c0909341SAndroid Build Coastguard Worker     dav1d_init_get_bits(&gb, ptr, sz);
311*c0909341SAndroid Build Coastguard Worker     int res = DAV1D_ERR(ENOENT);
312*c0909341SAndroid Build Coastguard Worker 
313*c0909341SAndroid Build Coastguard Worker     do {
314*c0909341SAndroid Build Coastguard Worker         dav1d_get_bit(&gb); // obu_forbidden_bit
315*c0909341SAndroid Build Coastguard Worker         const enum Dav1dObuType type = dav1d_get_bits(&gb, 4);
316*c0909341SAndroid Build Coastguard Worker         const int has_extension = dav1d_get_bit(&gb);
317*c0909341SAndroid Build Coastguard Worker         const int has_length_field = dav1d_get_bit(&gb);
318*c0909341SAndroid Build Coastguard Worker         dav1d_get_bits(&gb, 1 + 8 * has_extension); // ignore
319*c0909341SAndroid Build Coastguard Worker 
320*c0909341SAndroid Build Coastguard Worker         const uint8_t *obu_end = gb.ptr_end;
321*c0909341SAndroid Build Coastguard Worker         if (has_length_field) {
322*c0909341SAndroid Build Coastguard Worker             const size_t len = dav1d_get_uleb128(&gb);
323*c0909341SAndroid Build Coastguard Worker             if (len > (size_t)(obu_end - gb.ptr)) return DAV1D_ERR(EINVAL);
324*c0909341SAndroid Build Coastguard Worker             obu_end = gb.ptr + len;
325*c0909341SAndroid Build Coastguard Worker         }
326*c0909341SAndroid Build Coastguard Worker 
327*c0909341SAndroid Build Coastguard Worker         if (type == DAV1D_OBU_SEQ_HDR) {
328*c0909341SAndroid Build Coastguard Worker             if ((res = parse_seq_hdr(out, &gb, 0)) < 0) return res;
329*c0909341SAndroid Build Coastguard Worker             if (gb.ptr > obu_end) return DAV1D_ERR(EINVAL);
330*c0909341SAndroid Build Coastguard Worker             dav1d_bytealign_get_bits(&gb);
331*c0909341SAndroid Build Coastguard Worker         }
332*c0909341SAndroid Build Coastguard Worker 
333*c0909341SAndroid Build Coastguard Worker         if (gb.error) return DAV1D_ERR(EINVAL);
334*c0909341SAndroid Build Coastguard Worker         assert(gb.state == 0 && gb.bits_left == 0);
335*c0909341SAndroid Build Coastguard Worker         gb.ptr = obu_end;
336*c0909341SAndroid Build Coastguard Worker     } while (gb.ptr < gb.ptr_end);
337*c0909341SAndroid Build Coastguard Worker 
338*c0909341SAndroid Build Coastguard Worker     return res;
339*c0909341SAndroid Build Coastguard Worker }
340*c0909341SAndroid Build Coastguard Worker 
read_frame_size(Dav1dContext * const c,GetBits * const gb,const int use_ref)341*c0909341SAndroid Build Coastguard Worker static int read_frame_size(Dav1dContext *const c, GetBits *const gb,
342*c0909341SAndroid Build Coastguard Worker                            const int use_ref)
343*c0909341SAndroid Build Coastguard Worker {
344*c0909341SAndroid Build Coastguard Worker     const Dav1dSequenceHeader *const seqhdr = c->seq_hdr;
345*c0909341SAndroid Build Coastguard Worker     Dav1dFrameHeader *const hdr = c->frame_hdr;
346*c0909341SAndroid Build Coastguard Worker 
347*c0909341SAndroid Build Coastguard Worker     if (use_ref) {
348*c0909341SAndroid Build Coastguard Worker         for (int i = 0; i < 7; i++) {
349*c0909341SAndroid Build Coastguard Worker             if (dav1d_get_bit(gb)) {
350*c0909341SAndroid Build Coastguard Worker                 const Dav1dThreadPicture *const ref =
351*c0909341SAndroid Build Coastguard Worker                     &c->refs[c->frame_hdr->refidx[i]].p;
352*c0909341SAndroid Build Coastguard Worker                 if (!ref->p.frame_hdr) return -1;
353*c0909341SAndroid Build Coastguard Worker                 hdr->width[1] = ref->p.frame_hdr->width[1];
354*c0909341SAndroid Build Coastguard Worker                 hdr->height = ref->p.frame_hdr->height;
355*c0909341SAndroid Build Coastguard Worker                 hdr->render_width = ref->p.frame_hdr->render_width;
356*c0909341SAndroid Build Coastguard Worker                 hdr->render_height = ref->p.frame_hdr->render_height;
357*c0909341SAndroid Build Coastguard Worker                 hdr->super_res.enabled = seqhdr->super_res && dav1d_get_bit(gb);
358*c0909341SAndroid Build Coastguard Worker                 if (hdr->super_res.enabled) {
359*c0909341SAndroid Build Coastguard Worker                     const int d = hdr->super_res.width_scale_denominator =
360*c0909341SAndroid Build Coastguard Worker                         9 + dav1d_get_bits(gb, 3);
361*c0909341SAndroid Build Coastguard Worker                     hdr->width[0] = imax((hdr->width[1] * 8 + (d >> 1)) / d,
362*c0909341SAndroid Build Coastguard Worker                                          imin(16, hdr->width[1]));
363*c0909341SAndroid Build Coastguard Worker                 } else {
364*c0909341SAndroid Build Coastguard Worker                     hdr->super_res.width_scale_denominator = 8;
365*c0909341SAndroid Build Coastguard Worker                     hdr->width[0] = hdr->width[1];
366*c0909341SAndroid Build Coastguard Worker                 }
367*c0909341SAndroid Build Coastguard Worker                 return 0;
368*c0909341SAndroid Build Coastguard Worker             }
369*c0909341SAndroid Build Coastguard Worker         }
370*c0909341SAndroid Build Coastguard Worker     }
371*c0909341SAndroid Build Coastguard Worker 
372*c0909341SAndroid Build Coastguard Worker     if (hdr->frame_size_override) {
373*c0909341SAndroid Build Coastguard Worker         hdr->width[1] = dav1d_get_bits(gb, seqhdr->width_n_bits) + 1;
374*c0909341SAndroid Build Coastguard Worker         hdr->height = dav1d_get_bits(gb, seqhdr->height_n_bits) + 1;
375*c0909341SAndroid Build Coastguard Worker     } else {
376*c0909341SAndroid Build Coastguard Worker         hdr->width[1] = seqhdr->max_width;
377*c0909341SAndroid Build Coastguard Worker         hdr->height = seqhdr->max_height;
378*c0909341SAndroid Build Coastguard Worker     }
379*c0909341SAndroid Build Coastguard Worker     hdr->super_res.enabled = seqhdr->super_res && dav1d_get_bit(gb);
380*c0909341SAndroid Build Coastguard Worker     if (hdr->super_res.enabled) {
381*c0909341SAndroid Build Coastguard Worker         const int d = hdr->super_res.width_scale_denominator = 9 + dav1d_get_bits(gb, 3);
382*c0909341SAndroid Build Coastguard Worker         hdr->width[0] = imax((hdr->width[1] * 8 + (d >> 1)) / d, imin(16, hdr->width[1]));
383*c0909341SAndroid Build Coastguard Worker     } else {
384*c0909341SAndroid Build Coastguard Worker         hdr->super_res.width_scale_denominator = 8;
385*c0909341SAndroid Build Coastguard Worker         hdr->width[0] = hdr->width[1];
386*c0909341SAndroid Build Coastguard Worker     }
387*c0909341SAndroid Build Coastguard Worker     hdr->have_render_size = dav1d_get_bit(gb);
388*c0909341SAndroid Build Coastguard Worker     if (hdr->have_render_size) {
389*c0909341SAndroid Build Coastguard Worker         hdr->render_width = dav1d_get_bits(gb, 16) + 1;
390*c0909341SAndroid Build Coastguard Worker         hdr->render_height = dav1d_get_bits(gb, 16) + 1;
391*c0909341SAndroid Build Coastguard Worker     } else {
392*c0909341SAndroid Build Coastguard Worker         hdr->render_width = hdr->width[1];
393*c0909341SAndroid Build Coastguard Worker         hdr->render_height = hdr->height;
394*c0909341SAndroid Build Coastguard Worker     }
395*c0909341SAndroid Build Coastguard Worker     return 0;
396*c0909341SAndroid Build Coastguard Worker }
397*c0909341SAndroid Build Coastguard Worker 
tile_log2(const int sz,const int tgt)398*c0909341SAndroid Build Coastguard Worker static inline int tile_log2(const int sz, const int tgt) {
399*c0909341SAndroid Build Coastguard Worker     int k;
400*c0909341SAndroid Build Coastguard Worker     for (k = 0; (sz << k) < tgt; k++) ;
401*c0909341SAndroid Build Coastguard Worker     return k;
402*c0909341SAndroid Build Coastguard Worker }
403*c0909341SAndroid Build Coastguard Worker 
404*c0909341SAndroid Build Coastguard Worker static const Dav1dLoopfilterModeRefDeltas default_mode_ref_deltas = {
405*c0909341SAndroid Build Coastguard Worker     .mode_delta = { 0, 0 },
406*c0909341SAndroid Build Coastguard Worker     .ref_delta = { 1, 0, 0, 0, -1, 0, -1, -1 },
407*c0909341SAndroid Build Coastguard Worker };
408*c0909341SAndroid Build Coastguard Worker 
parse_frame_hdr(Dav1dContext * const c,GetBits * const gb)409*c0909341SAndroid Build Coastguard Worker static int parse_frame_hdr(Dav1dContext *const c, GetBits *const gb) {
410*c0909341SAndroid Build Coastguard Worker #define DEBUG_FRAME_HDR 0
411*c0909341SAndroid Build Coastguard Worker 
412*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
413*c0909341SAndroid Build Coastguard Worker     const uint8_t *const init_ptr = gb->ptr;
414*c0909341SAndroid Build Coastguard Worker #endif
415*c0909341SAndroid Build Coastguard Worker     const Dav1dSequenceHeader *const seqhdr = c->seq_hdr;
416*c0909341SAndroid Build Coastguard Worker     Dav1dFrameHeader *const hdr = c->frame_hdr;
417*c0909341SAndroid Build Coastguard Worker 
418*c0909341SAndroid Build Coastguard Worker     hdr->show_existing_frame =
419*c0909341SAndroid Build Coastguard Worker         !seqhdr->reduced_still_picture_header && dav1d_get_bit(gb);
420*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
421*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-show_existing_frame: off=%td\n",
422*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
423*c0909341SAndroid Build Coastguard Worker #endif
424*c0909341SAndroid Build Coastguard Worker     if (hdr->show_existing_frame) {
425*c0909341SAndroid Build Coastguard Worker         hdr->existing_frame_idx = dav1d_get_bits(gb, 3);
426*c0909341SAndroid Build Coastguard Worker         if (seqhdr->decoder_model_info_present && !seqhdr->equal_picture_interval)
427*c0909341SAndroid Build Coastguard Worker             hdr->frame_presentation_delay = dav1d_get_bits(gb, seqhdr->frame_presentation_delay_length);
428*c0909341SAndroid Build Coastguard Worker         if (seqhdr->frame_id_numbers_present) {
429*c0909341SAndroid Build Coastguard Worker             hdr->frame_id = dav1d_get_bits(gb, seqhdr->frame_id_n_bits);
430*c0909341SAndroid Build Coastguard Worker             Dav1dFrameHeader *const ref_frame_hdr = c->refs[hdr->existing_frame_idx].p.p.frame_hdr;
431*c0909341SAndroid Build Coastguard Worker             if (!ref_frame_hdr || ref_frame_hdr->frame_id != hdr->frame_id) goto error;
432*c0909341SAndroid Build Coastguard Worker         }
433*c0909341SAndroid Build Coastguard Worker         return 0;
434*c0909341SAndroid Build Coastguard Worker     }
435*c0909341SAndroid Build Coastguard Worker 
436*c0909341SAndroid Build Coastguard Worker     hdr->frame_type = seqhdr->reduced_still_picture_header ? DAV1D_FRAME_TYPE_KEY : dav1d_get_bits(gb, 2);
437*c0909341SAndroid Build Coastguard Worker     hdr->show_frame = seqhdr->reduced_still_picture_header || dav1d_get_bit(gb);
438*c0909341SAndroid Build Coastguard Worker     if (hdr->show_frame) {
439*c0909341SAndroid Build Coastguard Worker         if (seqhdr->decoder_model_info_present && !seqhdr->equal_picture_interval)
440*c0909341SAndroid Build Coastguard Worker             hdr->frame_presentation_delay = dav1d_get_bits(gb, seqhdr->frame_presentation_delay_length);
441*c0909341SAndroid Build Coastguard Worker         hdr->showable_frame = hdr->frame_type != DAV1D_FRAME_TYPE_KEY;
442*c0909341SAndroid Build Coastguard Worker     } else
443*c0909341SAndroid Build Coastguard Worker         hdr->showable_frame = dav1d_get_bit(gb);
444*c0909341SAndroid Build Coastguard Worker     hdr->error_resilient_mode =
445*c0909341SAndroid Build Coastguard Worker         (hdr->frame_type == DAV1D_FRAME_TYPE_KEY && hdr->show_frame) ||
446*c0909341SAndroid Build Coastguard Worker         hdr->frame_type == DAV1D_FRAME_TYPE_SWITCH ||
447*c0909341SAndroid Build Coastguard Worker         seqhdr->reduced_still_picture_header || dav1d_get_bit(gb);
448*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
449*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-frametype_bits: off=%td\n",
450*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
451*c0909341SAndroid Build Coastguard Worker #endif
452*c0909341SAndroid Build Coastguard Worker     hdr->disable_cdf_update = dav1d_get_bit(gb);
453*c0909341SAndroid Build Coastguard Worker     hdr->allow_screen_content_tools = seqhdr->screen_content_tools == DAV1D_ADAPTIVE ?
454*c0909341SAndroid Build Coastguard Worker                                  dav1d_get_bit(gb) : seqhdr->screen_content_tools;
455*c0909341SAndroid Build Coastguard Worker     if (hdr->allow_screen_content_tools)
456*c0909341SAndroid Build Coastguard Worker         hdr->force_integer_mv = seqhdr->force_integer_mv == DAV1D_ADAPTIVE ?
457*c0909341SAndroid Build Coastguard Worker                                 dav1d_get_bit(gb) : seqhdr->force_integer_mv;
458*c0909341SAndroid Build Coastguard Worker     else
459*c0909341SAndroid Build Coastguard Worker         hdr->force_integer_mv = 0;
460*c0909341SAndroid Build Coastguard Worker 
461*c0909341SAndroid Build Coastguard Worker     if (IS_KEY_OR_INTRA(hdr))
462*c0909341SAndroid Build Coastguard Worker         hdr->force_integer_mv = 1;
463*c0909341SAndroid Build Coastguard Worker 
464*c0909341SAndroid Build Coastguard Worker     if (seqhdr->frame_id_numbers_present)
465*c0909341SAndroid Build Coastguard Worker         hdr->frame_id = dav1d_get_bits(gb, seqhdr->frame_id_n_bits);
466*c0909341SAndroid Build Coastguard Worker 
467*c0909341SAndroid Build Coastguard Worker     hdr->frame_size_override = seqhdr->reduced_still_picture_header ? 0 :
468*c0909341SAndroid Build Coastguard Worker                                hdr->frame_type == DAV1D_FRAME_TYPE_SWITCH ? 1 : dav1d_get_bit(gb);
469*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
470*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-frame_size_override_flag: off=%td\n",
471*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
472*c0909341SAndroid Build Coastguard Worker #endif
473*c0909341SAndroid Build Coastguard Worker     hdr->frame_offset = seqhdr->order_hint ?
474*c0909341SAndroid Build Coastguard Worker                         dav1d_get_bits(gb, seqhdr->order_hint_n_bits) : 0;
475*c0909341SAndroid Build Coastguard Worker     hdr->primary_ref_frame = !hdr->error_resilient_mode && IS_INTER_OR_SWITCH(hdr) ?
476*c0909341SAndroid Build Coastguard Worker                              dav1d_get_bits(gb, 3) : DAV1D_PRIMARY_REF_NONE;
477*c0909341SAndroid Build Coastguard Worker 
478*c0909341SAndroid Build Coastguard Worker     if (seqhdr->decoder_model_info_present) {
479*c0909341SAndroid Build Coastguard Worker         hdr->buffer_removal_time_present = dav1d_get_bit(gb);
480*c0909341SAndroid Build Coastguard Worker         if (hdr->buffer_removal_time_present) {
481*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < c->seq_hdr->num_operating_points; i++) {
482*c0909341SAndroid Build Coastguard Worker                 const struct Dav1dSequenceHeaderOperatingPoint *const seqop = &seqhdr->operating_points[i];
483*c0909341SAndroid Build Coastguard Worker                 struct Dav1dFrameHeaderOperatingPoint *const op = &hdr->operating_points[i];
484*c0909341SAndroid Build Coastguard Worker                 if (seqop->decoder_model_param_present) {
485*c0909341SAndroid Build Coastguard Worker                     int in_temporal_layer = (seqop->idc >> hdr->temporal_id) & 1;
486*c0909341SAndroid Build Coastguard Worker                     int in_spatial_layer  = (seqop->idc >> (hdr->spatial_id + 8)) & 1;
487*c0909341SAndroid Build Coastguard Worker                     if (!seqop->idc || (in_temporal_layer && in_spatial_layer))
488*c0909341SAndroid Build Coastguard Worker                         op->buffer_removal_time = dav1d_get_bits(gb, seqhdr->buffer_removal_delay_length);
489*c0909341SAndroid Build Coastguard Worker                 }
490*c0909341SAndroid Build Coastguard Worker             }
491*c0909341SAndroid Build Coastguard Worker         }
492*c0909341SAndroid Build Coastguard Worker     }
493*c0909341SAndroid Build Coastguard Worker 
494*c0909341SAndroid Build Coastguard Worker     if (IS_KEY_OR_INTRA(hdr)) {
495*c0909341SAndroid Build Coastguard Worker         hdr->refresh_frame_flags = (hdr->frame_type == DAV1D_FRAME_TYPE_KEY &&
496*c0909341SAndroid Build Coastguard Worker                                     hdr->show_frame) ? 0xff : dav1d_get_bits(gb, 8);
497*c0909341SAndroid Build Coastguard Worker         if (hdr->refresh_frame_flags != 0xff && hdr->error_resilient_mode && seqhdr->order_hint)
498*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < 8; i++)
499*c0909341SAndroid Build Coastguard Worker                 dav1d_get_bits(gb, seqhdr->order_hint_n_bits);
500*c0909341SAndroid Build Coastguard Worker         if (c->strict_std_compliance &&
501*c0909341SAndroid Build Coastguard Worker             hdr->frame_type == DAV1D_FRAME_TYPE_INTRA && hdr->refresh_frame_flags == 0xff)
502*c0909341SAndroid Build Coastguard Worker         {
503*c0909341SAndroid Build Coastguard Worker             goto error;
504*c0909341SAndroid Build Coastguard Worker         }
505*c0909341SAndroid Build Coastguard Worker         if (read_frame_size(c, gb, 0) < 0) goto error;
506*c0909341SAndroid Build Coastguard Worker         hdr->allow_intrabc = hdr->allow_screen_content_tools &&
507*c0909341SAndroid Build Coastguard Worker                              !hdr->super_res.enabled && dav1d_get_bit(gb);
508*c0909341SAndroid Build Coastguard Worker         hdr->use_ref_frame_mvs = 0;
509*c0909341SAndroid Build Coastguard Worker     } else {
510*c0909341SAndroid Build Coastguard Worker         hdr->allow_intrabc = 0;
511*c0909341SAndroid Build Coastguard Worker         hdr->refresh_frame_flags = hdr->frame_type == DAV1D_FRAME_TYPE_SWITCH ? 0xff :
512*c0909341SAndroid Build Coastguard Worker                                    dav1d_get_bits(gb, 8);
513*c0909341SAndroid Build Coastguard Worker         if (hdr->error_resilient_mode && seqhdr->order_hint)
514*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < 8; i++)
515*c0909341SAndroid Build Coastguard Worker                 dav1d_get_bits(gb, seqhdr->order_hint_n_bits);
516*c0909341SAndroid Build Coastguard Worker         hdr->frame_ref_short_signaling =
517*c0909341SAndroid Build Coastguard Worker             seqhdr->order_hint && dav1d_get_bit(gb);
518*c0909341SAndroid Build Coastguard Worker         if (hdr->frame_ref_short_signaling) { // FIXME: Nearly verbatim copy from section 7.8
519*c0909341SAndroid Build Coastguard Worker             hdr->refidx[0] = dav1d_get_bits(gb, 3);
520*c0909341SAndroid Build Coastguard Worker             hdr->refidx[1] = hdr->refidx[2] = -1;
521*c0909341SAndroid Build Coastguard Worker             hdr->refidx[3] = dav1d_get_bits(gb, 3);
522*c0909341SAndroid Build Coastguard Worker             hdr->refidx[4] = hdr->refidx[5] = hdr->refidx[6] = -1;
523*c0909341SAndroid Build Coastguard Worker 
524*c0909341SAndroid Build Coastguard Worker             int shifted_frame_offset[8];
525*c0909341SAndroid Build Coastguard Worker             const int current_frame_offset = 1 << (seqhdr->order_hint_n_bits - 1);
526*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < 8; i++) {
527*c0909341SAndroid Build Coastguard Worker                 if (!c->refs[i].p.p.frame_hdr) goto error;
528*c0909341SAndroid Build Coastguard Worker                 shifted_frame_offset[i] = current_frame_offset +
529*c0909341SAndroid Build Coastguard Worker                     get_poc_diff(seqhdr->order_hint_n_bits,
530*c0909341SAndroid Build Coastguard Worker                                  c->refs[i].p.p.frame_hdr->frame_offset,
531*c0909341SAndroid Build Coastguard Worker                                  hdr->frame_offset);
532*c0909341SAndroid Build Coastguard Worker             }
533*c0909341SAndroid Build Coastguard Worker 
534*c0909341SAndroid Build Coastguard Worker             int used_frame[8] = { 0 };
535*c0909341SAndroid Build Coastguard Worker             used_frame[hdr->refidx[0]] = 1;
536*c0909341SAndroid Build Coastguard Worker             used_frame[hdr->refidx[3]] = 1;
537*c0909341SAndroid Build Coastguard Worker 
538*c0909341SAndroid Build Coastguard Worker             int latest_frame_offset = -1;
539*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < 8; i++) {
540*c0909341SAndroid Build Coastguard Worker                 const int hint = shifted_frame_offset[i];
541*c0909341SAndroid Build Coastguard Worker                 if (!used_frame[i] && hint >= current_frame_offset &&
542*c0909341SAndroid Build Coastguard Worker                     hint >= latest_frame_offset)
543*c0909341SAndroid Build Coastguard Worker                 {
544*c0909341SAndroid Build Coastguard Worker                     hdr->refidx[6] = i;
545*c0909341SAndroid Build Coastguard Worker                     latest_frame_offset = hint;
546*c0909341SAndroid Build Coastguard Worker                 }
547*c0909341SAndroid Build Coastguard Worker             }
548*c0909341SAndroid Build Coastguard Worker             if (latest_frame_offset != -1)
549*c0909341SAndroid Build Coastguard Worker                 used_frame[hdr->refidx[6]] = 1;
550*c0909341SAndroid Build Coastguard Worker 
551*c0909341SAndroid Build Coastguard Worker             int earliest_frame_offset = INT_MAX;
552*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < 8; i++) {
553*c0909341SAndroid Build Coastguard Worker                 const int hint = shifted_frame_offset[i];
554*c0909341SAndroid Build Coastguard Worker                 if (!used_frame[i] && hint >= current_frame_offset &&
555*c0909341SAndroid Build Coastguard Worker                     hint < earliest_frame_offset)
556*c0909341SAndroid Build Coastguard Worker                 {
557*c0909341SAndroid Build Coastguard Worker                     hdr->refidx[4] = i;
558*c0909341SAndroid Build Coastguard Worker                     earliest_frame_offset = hint;
559*c0909341SAndroid Build Coastguard Worker                 }
560*c0909341SAndroid Build Coastguard Worker             }
561*c0909341SAndroid Build Coastguard Worker             if (earliest_frame_offset != INT_MAX)
562*c0909341SAndroid Build Coastguard Worker                 used_frame[hdr->refidx[4]] = 1;
563*c0909341SAndroid Build Coastguard Worker 
564*c0909341SAndroid Build Coastguard Worker             earliest_frame_offset = INT_MAX;
565*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < 8; i++) {
566*c0909341SAndroid Build Coastguard Worker                 const int hint = shifted_frame_offset[i];
567*c0909341SAndroid Build Coastguard Worker                 if (!used_frame[i] && hint >= current_frame_offset &&
568*c0909341SAndroid Build Coastguard Worker                     (hint < earliest_frame_offset))
569*c0909341SAndroid Build Coastguard Worker                 {
570*c0909341SAndroid Build Coastguard Worker                     hdr->refidx[5] = i;
571*c0909341SAndroid Build Coastguard Worker                     earliest_frame_offset = hint;
572*c0909341SAndroid Build Coastguard Worker                 }
573*c0909341SAndroid Build Coastguard Worker             }
574*c0909341SAndroid Build Coastguard Worker             if (earliest_frame_offset != INT_MAX)
575*c0909341SAndroid Build Coastguard Worker                 used_frame[hdr->refidx[5]] = 1;
576*c0909341SAndroid Build Coastguard Worker 
577*c0909341SAndroid Build Coastguard Worker             for (int i = 1; i < 7; i++) {
578*c0909341SAndroid Build Coastguard Worker                 if (hdr->refidx[i] < 0) {
579*c0909341SAndroid Build Coastguard Worker                     latest_frame_offset = -1;
580*c0909341SAndroid Build Coastguard Worker                     for (int j = 0; j < 8; j++) {
581*c0909341SAndroid Build Coastguard Worker                         const int hint = shifted_frame_offset[j];
582*c0909341SAndroid Build Coastguard Worker                         if (!used_frame[j] && hint < current_frame_offset &&
583*c0909341SAndroid Build Coastguard Worker                             hint >= latest_frame_offset)
584*c0909341SAndroid Build Coastguard Worker                         {
585*c0909341SAndroid Build Coastguard Worker                             hdr->refidx[i] = j;
586*c0909341SAndroid Build Coastguard Worker                             latest_frame_offset = hint;
587*c0909341SAndroid Build Coastguard Worker                         }
588*c0909341SAndroid Build Coastguard Worker                     }
589*c0909341SAndroid Build Coastguard Worker                     if (latest_frame_offset != -1)
590*c0909341SAndroid Build Coastguard Worker                         used_frame[hdr->refidx[i]] = 1;
591*c0909341SAndroid Build Coastguard Worker                 }
592*c0909341SAndroid Build Coastguard Worker             }
593*c0909341SAndroid Build Coastguard Worker 
594*c0909341SAndroid Build Coastguard Worker             earliest_frame_offset = INT_MAX;
595*c0909341SAndroid Build Coastguard Worker             int ref = -1;
596*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < 8; i++) {
597*c0909341SAndroid Build Coastguard Worker                 const int hint = shifted_frame_offset[i];
598*c0909341SAndroid Build Coastguard Worker                 if (hint < earliest_frame_offset) {
599*c0909341SAndroid Build Coastguard Worker                     ref = i;
600*c0909341SAndroid Build Coastguard Worker                     earliest_frame_offset = hint;
601*c0909341SAndroid Build Coastguard Worker                 }
602*c0909341SAndroid Build Coastguard Worker             }
603*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < 7; i++) {
604*c0909341SAndroid Build Coastguard Worker                 if (hdr->refidx[i] < 0)
605*c0909341SAndroid Build Coastguard Worker                     hdr->refidx[i] = ref;
606*c0909341SAndroid Build Coastguard Worker             }
607*c0909341SAndroid Build Coastguard Worker         }
608*c0909341SAndroid Build Coastguard Worker         for (int i = 0; i < 7; i++) {
609*c0909341SAndroid Build Coastguard Worker             if (!hdr->frame_ref_short_signaling)
610*c0909341SAndroid Build Coastguard Worker                 hdr->refidx[i] = dav1d_get_bits(gb, 3);
611*c0909341SAndroid Build Coastguard Worker             if (seqhdr->frame_id_numbers_present) {
612*c0909341SAndroid Build Coastguard Worker                 const unsigned delta_ref_frame_id = dav1d_get_bits(gb, seqhdr->delta_frame_id_n_bits) + 1;
613*c0909341SAndroid Build Coastguard Worker                 const unsigned ref_frame_id = (hdr->frame_id + (1 << seqhdr->frame_id_n_bits) - delta_ref_frame_id) & ((1 << seqhdr->frame_id_n_bits) - 1);
614*c0909341SAndroid Build Coastguard Worker                 Dav1dFrameHeader *const ref_frame_hdr = c->refs[hdr->refidx[i]].p.p.frame_hdr;
615*c0909341SAndroid Build Coastguard Worker                 if (!ref_frame_hdr || ref_frame_hdr->frame_id != ref_frame_id) goto error;
616*c0909341SAndroid Build Coastguard Worker             }
617*c0909341SAndroid Build Coastguard Worker         }
618*c0909341SAndroid Build Coastguard Worker         const int use_ref = !hdr->error_resilient_mode &&
619*c0909341SAndroid Build Coastguard Worker                             hdr->frame_size_override;
620*c0909341SAndroid Build Coastguard Worker         if (read_frame_size(c, gb, use_ref) < 0) goto error;
621*c0909341SAndroid Build Coastguard Worker         hdr->hp = !hdr->force_integer_mv && dav1d_get_bit(gb);
622*c0909341SAndroid Build Coastguard Worker         hdr->subpel_filter_mode = dav1d_get_bit(gb) ? DAV1D_FILTER_SWITCHABLE :
623*c0909341SAndroid Build Coastguard Worker                                                           dav1d_get_bits(gb, 2);
624*c0909341SAndroid Build Coastguard Worker         hdr->switchable_motion_mode = dav1d_get_bit(gb);
625*c0909341SAndroid Build Coastguard Worker         hdr->use_ref_frame_mvs = !hdr->error_resilient_mode &&
626*c0909341SAndroid Build Coastguard Worker             seqhdr->ref_frame_mvs && seqhdr->order_hint &&
627*c0909341SAndroid Build Coastguard Worker             IS_INTER_OR_SWITCH(hdr) && dav1d_get_bit(gb);
628*c0909341SAndroid Build Coastguard Worker     }
629*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
630*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-frametype-specific-bits: off=%td\n",
631*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
632*c0909341SAndroid Build Coastguard Worker #endif
633*c0909341SAndroid Build Coastguard Worker 
634*c0909341SAndroid Build Coastguard Worker     hdr->refresh_context = !seqhdr->reduced_still_picture_header &&
635*c0909341SAndroid Build Coastguard Worker                            !hdr->disable_cdf_update && !dav1d_get_bit(gb);
636*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
637*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-refresh_context: off=%td\n",
638*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
639*c0909341SAndroid Build Coastguard Worker #endif
640*c0909341SAndroid Build Coastguard Worker 
641*c0909341SAndroid Build Coastguard Worker     // tile data
642*c0909341SAndroid Build Coastguard Worker     hdr->tiling.uniform = dav1d_get_bit(gb);
643*c0909341SAndroid Build Coastguard Worker     const int sbsz_min1 = (64 << seqhdr->sb128) - 1;
644*c0909341SAndroid Build Coastguard Worker     const int sbsz_log2 = 6 + seqhdr->sb128;
645*c0909341SAndroid Build Coastguard Worker     const int sbw = (hdr->width[0] + sbsz_min1) >> sbsz_log2;
646*c0909341SAndroid Build Coastguard Worker     const int sbh = (hdr->height + sbsz_min1) >> sbsz_log2;
647*c0909341SAndroid Build Coastguard Worker     const int max_tile_width_sb = 4096 >> sbsz_log2;
648*c0909341SAndroid Build Coastguard Worker     const int max_tile_area_sb = 4096 * 2304 >> (2 * sbsz_log2);
649*c0909341SAndroid Build Coastguard Worker     hdr->tiling.min_log2_cols = tile_log2(max_tile_width_sb, sbw);
650*c0909341SAndroid Build Coastguard Worker     hdr->tiling.max_log2_cols = tile_log2(1, imin(sbw, DAV1D_MAX_TILE_COLS));
651*c0909341SAndroid Build Coastguard Worker     hdr->tiling.max_log2_rows = tile_log2(1, imin(sbh, DAV1D_MAX_TILE_ROWS));
652*c0909341SAndroid Build Coastguard Worker     const int min_log2_tiles = imax(tile_log2(max_tile_area_sb, sbw * sbh),
653*c0909341SAndroid Build Coastguard Worker                               hdr->tiling.min_log2_cols);
654*c0909341SAndroid Build Coastguard Worker     if (hdr->tiling.uniform) {
655*c0909341SAndroid Build Coastguard Worker         for (hdr->tiling.log2_cols = hdr->tiling.min_log2_cols;
656*c0909341SAndroid Build Coastguard Worker              hdr->tiling.log2_cols < hdr->tiling.max_log2_cols && dav1d_get_bit(gb);
657*c0909341SAndroid Build Coastguard Worker              hdr->tiling.log2_cols++) ;
658*c0909341SAndroid Build Coastguard Worker         const int tile_w = 1 + ((sbw - 1) >> hdr->tiling.log2_cols);
659*c0909341SAndroid Build Coastguard Worker         hdr->tiling.cols = 0;
660*c0909341SAndroid Build Coastguard Worker         for (int sbx = 0; sbx < sbw; sbx += tile_w, hdr->tiling.cols++)
661*c0909341SAndroid Build Coastguard Worker             hdr->tiling.col_start_sb[hdr->tiling.cols] = sbx;
662*c0909341SAndroid Build Coastguard Worker         hdr->tiling.min_log2_rows =
663*c0909341SAndroid Build Coastguard Worker             imax(min_log2_tiles - hdr->tiling.log2_cols, 0);
664*c0909341SAndroid Build Coastguard Worker 
665*c0909341SAndroid Build Coastguard Worker         for (hdr->tiling.log2_rows = hdr->tiling.min_log2_rows;
666*c0909341SAndroid Build Coastguard Worker              hdr->tiling.log2_rows < hdr->tiling.max_log2_rows && dav1d_get_bit(gb);
667*c0909341SAndroid Build Coastguard Worker              hdr->tiling.log2_rows++) ;
668*c0909341SAndroid Build Coastguard Worker         const int tile_h = 1 + ((sbh - 1) >> hdr->tiling.log2_rows);
669*c0909341SAndroid Build Coastguard Worker         hdr->tiling.rows = 0;
670*c0909341SAndroid Build Coastguard Worker         for (int sby = 0; sby < sbh; sby += tile_h, hdr->tiling.rows++)
671*c0909341SAndroid Build Coastguard Worker             hdr->tiling.row_start_sb[hdr->tiling.rows] = sby;
672*c0909341SAndroid Build Coastguard Worker     } else {
673*c0909341SAndroid Build Coastguard Worker         hdr->tiling.cols = 0;
674*c0909341SAndroid Build Coastguard Worker         int widest_tile = 0, max_tile_area_sb = sbw * sbh;
675*c0909341SAndroid Build Coastguard Worker         for (int sbx = 0; sbx < sbw && hdr->tiling.cols < DAV1D_MAX_TILE_COLS; hdr->tiling.cols++) {
676*c0909341SAndroid Build Coastguard Worker             const int tile_width_sb = imin(sbw - sbx, max_tile_width_sb);
677*c0909341SAndroid Build Coastguard Worker             const int tile_w = (tile_width_sb > 1) ?
678*c0909341SAndroid Build Coastguard Worker                                    1 + dav1d_get_uniform(gb, tile_width_sb) :
679*c0909341SAndroid Build Coastguard Worker                                    1;
680*c0909341SAndroid Build Coastguard Worker             hdr->tiling.col_start_sb[hdr->tiling.cols] = sbx;
681*c0909341SAndroid Build Coastguard Worker             sbx += tile_w;
682*c0909341SAndroid Build Coastguard Worker             widest_tile = imax(widest_tile, tile_w);
683*c0909341SAndroid Build Coastguard Worker         }
684*c0909341SAndroid Build Coastguard Worker         hdr->tiling.log2_cols = tile_log2(1, hdr->tiling.cols);
685*c0909341SAndroid Build Coastguard Worker         if (min_log2_tiles) max_tile_area_sb >>= min_log2_tiles + 1;
686*c0909341SAndroid Build Coastguard Worker         const int max_tile_height_sb = imax(max_tile_area_sb / widest_tile, 1);
687*c0909341SAndroid Build Coastguard Worker 
688*c0909341SAndroid Build Coastguard Worker         hdr->tiling.rows = 0;
689*c0909341SAndroid Build Coastguard Worker         for (int sby = 0; sby < sbh && hdr->tiling.rows < DAV1D_MAX_TILE_ROWS; hdr->tiling.rows++) {
690*c0909341SAndroid Build Coastguard Worker             const int tile_height_sb = imin(sbh - sby, max_tile_height_sb);
691*c0909341SAndroid Build Coastguard Worker             const int tile_h = (tile_height_sb > 1) ?
692*c0909341SAndroid Build Coastguard Worker                                    1 + dav1d_get_uniform(gb, tile_height_sb) :
693*c0909341SAndroid Build Coastguard Worker                                    1;
694*c0909341SAndroid Build Coastguard Worker             hdr->tiling.row_start_sb[hdr->tiling.rows] = sby;
695*c0909341SAndroid Build Coastguard Worker             sby += tile_h;
696*c0909341SAndroid Build Coastguard Worker         }
697*c0909341SAndroid Build Coastguard Worker         hdr->tiling.log2_rows = tile_log2(1, hdr->tiling.rows);
698*c0909341SAndroid Build Coastguard Worker     }
699*c0909341SAndroid Build Coastguard Worker     hdr->tiling.col_start_sb[hdr->tiling.cols] = sbw;
700*c0909341SAndroid Build Coastguard Worker     hdr->tiling.row_start_sb[hdr->tiling.rows] = sbh;
701*c0909341SAndroid Build Coastguard Worker     if (hdr->tiling.log2_cols || hdr->tiling.log2_rows) {
702*c0909341SAndroid Build Coastguard Worker         hdr->tiling.update = dav1d_get_bits(gb, hdr->tiling.log2_cols +
703*c0909341SAndroid Build Coastguard Worker                                                 hdr->tiling.log2_rows);
704*c0909341SAndroid Build Coastguard Worker         if (hdr->tiling.update >= hdr->tiling.cols * hdr->tiling.rows)
705*c0909341SAndroid Build Coastguard Worker             goto error;
706*c0909341SAndroid Build Coastguard Worker         hdr->tiling.n_bytes = dav1d_get_bits(gb, 2) + 1;
707*c0909341SAndroid Build Coastguard Worker     } else {
708*c0909341SAndroid Build Coastguard Worker         hdr->tiling.n_bytes = 0;
709*c0909341SAndroid Build Coastguard Worker         hdr->tiling.update = 0;
710*c0909341SAndroid Build Coastguard Worker     }
711*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
712*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-tiling: off=%td\n",
713*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
714*c0909341SAndroid Build Coastguard Worker #endif
715*c0909341SAndroid Build Coastguard Worker 
716*c0909341SAndroid Build Coastguard Worker     // quant data
717*c0909341SAndroid Build Coastguard Worker     hdr->quant.yac = dav1d_get_bits(gb, 8);
718*c0909341SAndroid Build Coastguard Worker     hdr->quant.ydc_delta = dav1d_get_bit(gb) ? dav1d_get_sbits(gb, 7) : 0;
719*c0909341SAndroid Build Coastguard Worker     if (!seqhdr->monochrome) {
720*c0909341SAndroid Build Coastguard Worker         // If the sequence header says that delta_q might be different
721*c0909341SAndroid Build Coastguard Worker         // for U, V, we must check whether it actually is for this
722*c0909341SAndroid Build Coastguard Worker         // frame.
723*c0909341SAndroid Build Coastguard Worker         const int diff_uv_delta = seqhdr->separate_uv_delta_q ? dav1d_get_bit(gb) : 0;
724*c0909341SAndroid Build Coastguard Worker         hdr->quant.udc_delta = dav1d_get_bit(gb) ? dav1d_get_sbits(gb, 7) : 0;
725*c0909341SAndroid Build Coastguard Worker         hdr->quant.uac_delta = dav1d_get_bit(gb) ? dav1d_get_sbits(gb, 7) : 0;
726*c0909341SAndroid Build Coastguard Worker         if (diff_uv_delta) {
727*c0909341SAndroid Build Coastguard Worker             hdr->quant.vdc_delta = dav1d_get_bit(gb) ? dav1d_get_sbits(gb, 7) : 0;
728*c0909341SAndroid Build Coastguard Worker             hdr->quant.vac_delta = dav1d_get_bit(gb) ? dav1d_get_sbits(gb, 7) : 0;
729*c0909341SAndroid Build Coastguard Worker         } else {
730*c0909341SAndroid Build Coastguard Worker             hdr->quant.vdc_delta = hdr->quant.udc_delta;
731*c0909341SAndroid Build Coastguard Worker             hdr->quant.vac_delta = hdr->quant.uac_delta;
732*c0909341SAndroid Build Coastguard Worker         }
733*c0909341SAndroid Build Coastguard Worker     }
734*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
735*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-quant: off=%td\n",
736*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
737*c0909341SAndroid Build Coastguard Worker #endif
738*c0909341SAndroid Build Coastguard Worker     hdr->quant.qm = dav1d_get_bit(gb);
739*c0909341SAndroid Build Coastguard Worker     if (hdr->quant.qm) {
740*c0909341SAndroid Build Coastguard Worker         hdr->quant.qm_y = dav1d_get_bits(gb, 4);
741*c0909341SAndroid Build Coastguard Worker         hdr->quant.qm_u = dav1d_get_bits(gb, 4);
742*c0909341SAndroid Build Coastguard Worker         hdr->quant.qm_v =
743*c0909341SAndroid Build Coastguard Worker             seqhdr->separate_uv_delta_q ? dav1d_get_bits(gb, 4) :
744*c0909341SAndroid Build Coastguard Worker                                           hdr->quant.qm_u;
745*c0909341SAndroid Build Coastguard Worker     }
746*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
747*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-qm: off=%td\n",
748*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
749*c0909341SAndroid Build Coastguard Worker #endif
750*c0909341SAndroid Build Coastguard Worker 
751*c0909341SAndroid Build Coastguard Worker     // segmentation data
752*c0909341SAndroid Build Coastguard Worker     hdr->segmentation.enabled = dav1d_get_bit(gb);
753*c0909341SAndroid Build Coastguard Worker     if (hdr->segmentation.enabled) {
754*c0909341SAndroid Build Coastguard Worker         if (hdr->primary_ref_frame == DAV1D_PRIMARY_REF_NONE) {
755*c0909341SAndroid Build Coastguard Worker             hdr->segmentation.update_map = 1;
756*c0909341SAndroid Build Coastguard Worker             hdr->segmentation.temporal = 0;
757*c0909341SAndroid Build Coastguard Worker             hdr->segmentation.update_data = 1;
758*c0909341SAndroid Build Coastguard Worker         } else {
759*c0909341SAndroid Build Coastguard Worker             hdr->segmentation.update_map = dav1d_get_bit(gb);
760*c0909341SAndroid Build Coastguard Worker             hdr->segmentation.temporal =
761*c0909341SAndroid Build Coastguard Worker                 hdr->segmentation.update_map ? dav1d_get_bit(gb) : 0;
762*c0909341SAndroid Build Coastguard Worker             hdr->segmentation.update_data = dav1d_get_bit(gb);
763*c0909341SAndroid Build Coastguard Worker         }
764*c0909341SAndroid Build Coastguard Worker 
765*c0909341SAndroid Build Coastguard Worker         if (hdr->segmentation.update_data) {
766*c0909341SAndroid Build Coastguard Worker             hdr->segmentation.seg_data.preskip = 0;
767*c0909341SAndroid Build Coastguard Worker             hdr->segmentation.seg_data.last_active_segid = -1;
768*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < DAV1D_MAX_SEGMENTS; i++) {
769*c0909341SAndroid Build Coastguard Worker                 Dav1dSegmentationData *const seg =
770*c0909341SAndroid Build Coastguard Worker                     &hdr->segmentation.seg_data.d[i];
771*c0909341SAndroid Build Coastguard Worker                 if (dav1d_get_bit(gb)) {
772*c0909341SAndroid Build Coastguard Worker                     seg->delta_q = dav1d_get_sbits(gb, 9);
773*c0909341SAndroid Build Coastguard Worker                     hdr->segmentation.seg_data.last_active_segid = i;
774*c0909341SAndroid Build Coastguard Worker                 } else {
775*c0909341SAndroid Build Coastguard Worker                     seg->delta_q = 0;
776*c0909341SAndroid Build Coastguard Worker                 }
777*c0909341SAndroid Build Coastguard Worker                 if (dav1d_get_bit(gb)) {
778*c0909341SAndroid Build Coastguard Worker                     seg->delta_lf_y_v = dav1d_get_sbits(gb, 7);
779*c0909341SAndroid Build Coastguard Worker                     hdr->segmentation.seg_data.last_active_segid = i;
780*c0909341SAndroid Build Coastguard Worker                 } else {
781*c0909341SAndroid Build Coastguard Worker                     seg->delta_lf_y_v = 0;
782*c0909341SAndroid Build Coastguard Worker                 }
783*c0909341SAndroid Build Coastguard Worker                 if (dav1d_get_bit(gb)) {
784*c0909341SAndroid Build Coastguard Worker                     seg->delta_lf_y_h = dav1d_get_sbits(gb, 7);
785*c0909341SAndroid Build Coastguard Worker                     hdr->segmentation.seg_data.last_active_segid = i;
786*c0909341SAndroid Build Coastguard Worker                 } else {
787*c0909341SAndroid Build Coastguard Worker                     seg->delta_lf_y_h = 0;
788*c0909341SAndroid Build Coastguard Worker                 }
789*c0909341SAndroid Build Coastguard Worker                 if (dav1d_get_bit(gb)) {
790*c0909341SAndroid Build Coastguard Worker                     seg->delta_lf_u = dav1d_get_sbits(gb, 7);
791*c0909341SAndroid Build Coastguard Worker                     hdr->segmentation.seg_data.last_active_segid = i;
792*c0909341SAndroid Build Coastguard Worker                 } else {
793*c0909341SAndroid Build Coastguard Worker                     seg->delta_lf_u = 0;
794*c0909341SAndroid Build Coastguard Worker                 }
795*c0909341SAndroid Build Coastguard Worker                 if (dav1d_get_bit(gb)) {
796*c0909341SAndroid Build Coastguard Worker                     seg->delta_lf_v = dav1d_get_sbits(gb, 7);
797*c0909341SAndroid Build Coastguard Worker                     hdr->segmentation.seg_data.last_active_segid = i;
798*c0909341SAndroid Build Coastguard Worker                 } else {
799*c0909341SAndroid Build Coastguard Worker                     seg->delta_lf_v = 0;
800*c0909341SAndroid Build Coastguard Worker                 }
801*c0909341SAndroid Build Coastguard Worker                 if (dav1d_get_bit(gb)) {
802*c0909341SAndroid Build Coastguard Worker                     seg->ref = dav1d_get_bits(gb, 3);
803*c0909341SAndroid Build Coastguard Worker                     hdr->segmentation.seg_data.last_active_segid = i;
804*c0909341SAndroid Build Coastguard Worker                     hdr->segmentation.seg_data.preskip = 1;
805*c0909341SAndroid Build Coastguard Worker                 } else {
806*c0909341SAndroid Build Coastguard Worker                     seg->ref = -1;
807*c0909341SAndroid Build Coastguard Worker                 }
808*c0909341SAndroid Build Coastguard Worker                 if ((seg->skip = dav1d_get_bit(gb))) {
809*c0909341SAndroid Build Coastguard Worker                     hdr->segmentation.seg_data.last_active_segid = i;
810*c0909341SAndroid Build Coastguard Worker                     hdr->segmentation.seg_data.preskip = 1;
811*c0909341SAndroid Build Coastguard Worker                 }
812*c0909341SAndroid Build Coastguard Worker                 if ((seg->globalmv = dav1d_get_bit(gb))) {
813*c0909341SAndroid Build Coastguard Worker                     hdr->segmentation.seg_data.last_active_segid = i;
814*c0909341SAndroid Build Coastguard Worker                     hdr->segmentation.seg_data.preskip = 1;
815*c0909341SAndroid Build Coastguard Worker                 }
816*c0909341SAndroid Build Coastguard Worker             }
817*c0909341SAndroid Build Coastguard Worker         } else {
818*c0909341SAndroid Build Coastguard Worker             // segmentation.update_data was false so we should copy
819*c0909341SAndroid Build Coastguard Worker             // segmentation data from the reference frame.
820*c0909341SAndroid Build Coastguard Worker             assert(hdr->primary_ref_frame != DAV1D_PRIMARY_REF_NONE);
821*c0909341SAndroid Build Coastguard Worker             const int pri_ref = hdr->refidx[hdr->primary_ref_frame];
822*c0909341SAndroid Build Coastguard Worker             if (!c->refs[pri_ref].p.p.frame_hdr) goto error;
823*c0909341SAndroid Build Coastguard Worker             hdr->segmentation.seg_data =
824*c0909341SAndroid Build Coastguard Worker                 c->refs[pri_ref].p.p.frame_hdr->segmentation.seg_data;
825*c0909341SAndroid Build Coastguard Worker         }
826*c0909341SAndroid Build Coastguard Worker     } else {
827*c0909341SAndroid Build Coastguard Worker         memset(&hdr->segmentation.seg_data, 0, sizeof(Dav1dSegmentationDataSet));
828*c0909341SAndroid Build Coastguard Worker         for (int i = 0; i < DAV1D_MAX_SEGMENTS; i++)
829*c0909341SAndroid Build Coastguard Worker             hdr->segmentation.seg_data.d[i].ref = -1;
830*c0909341SAndroid Build Coastguard Worker     }
831*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
832*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-segmentation: off=%td\n",
833*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
834*c0909341SAndroid Build Coastguard Worker #endif
835*c0909341SAndroid Build Coastguard Worker 
836*c0909341SAndroid Build Coastguard Worker     // delta q
837*c0909341SAndroid Build Coastguard Worker     hdr->delta.q.present = hdr->quant.yac ? dav1d_get_bit(gb) : 0;
838*c0909341SAndroid Build Coastguard Worker     hdr->delta.q.res_log2 = hdr->delta.q.present ? dav1d_get_bits(gb, 2) : 0;
839*c0909341SAndroid Build Coastguard Worker     hdr->delta.lf.present = hdr->delta.q.present && !hdr->allow_intrabc &&
840*c0909341SAndroid Build Coastguard Worker                             dav1d_get_bit(gb);
841*c0909341SAndroid Build Coastguard Worker     hdr->delta.lf.res_log2 = hdr->delta.lf.present ? dav1d_get_bits(gb, 2) : 0;
842*c0909341SAndroid Build Coastguard Worker     hdr->delta.lf.multi = hdr->delta.lf.present ? dav1d_get_bit(gb) : 0;
843*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
844*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-delta_q_lf_flags: off=%td\n",
845*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
846*c0909341SAndroid Build Coastguard Worker #endif
847*c0909341SAndroid Build Coastguard Worker 
848*c0909341SAndroid Build Coastguard Worker     // derive lossless flags
849*c0909341SAndroid Build Coastguard Worker     const int delta_lossless = !hdr->quant.ydc_delta && !hdr->quant.udc_delta &&
850*c0909341SAndroid Build Coastguard Worker         !hdr->quant.uac_delta && !hdr->quant.vdc_delta && !hdr->quant.vac_delta;
851*c0909341SAndroid Build Coastguard Worker     hdr->all_lossless = 1;
852*c0909341SAndroid Build Coastguard Worker     for (int i = 0; i < DAV1D_MAX_SEGMENTS; i++) {
853*c0909341SAndroid Build Coastguard Worker         hdr->segmentation.qidx[i] = hdr->segmentation.enabled ?
854*c0909341SAndroid Build Coastguard Worker             iclip_u8(hdr->quant.yac + hdr->segmentation.seg_data.d[i].delta_q) :
855*c0909341SAndroid Build Coastguard Worker             hdr->quant.yac;
856*c0909341SAndroid Build Coastguard Worker         hdr->segmentation.lossless[i] =
857*c0909341SAndroid Build Coastguard Worker             !hdr->segmentation.qidx[i] && delta_lossless;
858*c0909341SAndroid Build Coastguard Worker         hdr->all_lossless &= hdr->segmentation.lossless[i];
859*c0909341SAndroid Build Coastguard Worker     }
860*c0909341SAndroid Build Coastguard Worker 
861*c0909341SAndroid Build Coastguard Worker     // loopfilter
862*c0909341SAndroid Build Coastguard Worker     if (hdr->all_lossless || hdr->allow_intrabc) {
863*c0909341SAndroid Build Coastguard Worker         hdr->loopfilter.level_y[0] = hdr->loopfilter.level_y[1] = 0;
864*c0909341SAndroid Build Coastguard Worker         hdr->loopfilter.level_u = hdr->loopfilter.level_v = 0;
865*c0909341SAndroid Build Coastguard Worker         hdr->loopfilter.sharpness = 0;
866*c0909341SAndroid Build Coastguard Worker         hdr->loopfilter.mode_ref_delta_enabled = 1;
867*c0909341SAndroid Build Coastguard Worker         hdr->loopfilter.mode_ref_delta_update = 1;
868*c0909341SAndroid Build Coastguard Worker         hdr->loopfilter.mode_ref_deltas = default_mode_ref_deltas;
869*c0909341SAndroid Build Coastguard Worker     } else {
870*c0909341SAndroid Build Coastguard Worker         hdr->loopfilter.level_y[0] = dav1d_get_bits(gb, 6);
871*c0909341SAndroid Build Coastguard Worker         hdr->loopfilter.level_y[1] = dav1d_get_bits(gb, 6);
872*c0909341SAndroid Build Coastguard Worker         if (!seqhdr->monochrome &&
873*c0909341SAndroid Build Coastguard Worker             (hdr->loopfilter.level_y[0] || hdr->loopfilter.level_y[1]))
874*c0909341SAndroid Build Coastguard Worker         {
875*c0909341SAndroid Build Coastguard Worker             hdr->loopfilter.level_u = dav1d_get_bits(gb, 6);
876*c0909341SAndroid Build Coastguard Worker             hdr->loopfilter.level_v = dav1d_get_bits(gb, 6);
877*c0909341SAndroid Build Coastguard Worker         }
878*c0909341SAndroid Build Coastguard Worker         hdr->loopfilter.sharpness = dav1d_get_bits(gb, 3);
879*c0909341SAndroid Build Coastguard Worker 
880*c0909341SAndroid Build Coastguard Worker         if (hdr->primary_ref_frame == DAV1D_PRIMARY_REF_NONE) {
881*c0909341SAndroid Build Coastguard Worker             hdr->loopfilter.mode_ref_deltas = default_mode_ref_deltas;
882*c0909341SAndroid Build Coastguard Worker         } else {
883*c0909341SAndroid Build Coastguard Worker             const int ref = hdr->refidx[hdr->primary_ref_frame];
884*c0909341SAndroid Build Coastguard Worker             if (!c->refs[ref].p.p.frame_hdr) goto error;
885*c0909341SAndroid Build Coastguard Worker             hdr->loopfilter.mode_ref_deltas =
886*c0909341SAndroid Build Coastguard Worker                 c->refs[ref].p.p.frame_hdr->loopfilter.mode_ref_deltas;
887*c0909341SAndroid Build Coastguard Worker         }
888*c0909341SAndroid Build Coastguard Worker         hdr->loopfilter.mode_ref_delta_enabled = dav1d_get_bit(gb);
889*c0909341SAndroid Build Coastguard Worker         if (hdr->loopfilter.mode_ref_delta_enabled) {
890*c0909341SAndroid Build Coastguard Worker             hdr->loopfilter.mode_ref_delta_update = dav1d_get_bit(gb);
891*c0909341SAndroid Build Coastguard Worker             if (hdr->loopfilter.mode_ref_delta_update) {
892*c0909341SAndroid Build Coastguard Worker                 for (int i = 0; i < 8; i++)
893*c0909341SAndroid Build Coastguard Worker                     if (dav1d_get_bit(gb))
894*c0909341SAndroid Build Coastguard Worker                         hdr->loopfilter.mode_ref_deltas.ref_delta[i] =
895*c0909341SAndroid Build Coastguard Worker                             dav1d_get_sbits(gb, 7);
896*c0909341SAndroid Build Coastguard Worker                 for (int i = 0; i < 2; i++)
897*c0909341SAndroid Build Coastguard Worker                     if (dav1d_get_bit(gb))
898*c0909341SAndroid Build Coastguard Worker                         hdr->loopfilter.mode_ref_deltas.mode_delta[i] =
899*c0909341SAndroid Build Coastguard Worker                             dav1d_get_sbits(gb, 7);
900*c0909341SAndroid Build Coastguard Worker             }
901*c0909341SAndroid Build Coastguard Worker         }
902*c0909341SAndroid Build Coastguard Worker     }
903*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
904*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-lpf: off=%td\n",
905*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
906*c0909341SAndroid Build Coastguard Worker #endif
907*c0909341SAndroid Build Coastguard Worker 
908*c0909341SAndroid Build Coastguard Worker     // cdef
909*c0909341SAndroid Build Coastguard Worker     if (!hdr->all_lossless && seqhdr->cdef && !hdr->allow_intrabc) {
910*c0909341SAndroid Build Coastguard Worker         hdr->cdef.damping = dav1d_get_bits(gb, 2) + 3;
911*c0909341SAndroid Build Coastguard Worker         hdr->cdef.n_bits = dav1d_get_bits(gb, 2);
912*c0909341SAndroid Build Coastguard Worker         for (int i = 0; i < (1 << hdr->cdef.n_bits); i++) {
913*c0909341SAndroid Build Coastguard Worker             hdr->cdef.y_strength[i] = dav1d_get_bits(gb, 6);
914*c0909341SAndroid Build Coastguard Worker             if (!seqhdr->monochrome)
915*c0909341SAndroid Build Coastguard Worker                 hdr->cdef.uv_strength[i] = dav1d_get_bits(gb, 6);
916*c0909341SAndroid Build Coastguard Worker         }
917*c0909341SAndroid Build Coastguard Worker     } else {
918*c0909341SAndroid Build Coastguard Worker         hdr->cdef.n_bits = 0;
919*c0909341SAndroid Build Coastguard Worker         hdr->cdef.y_strength[0] = 0;
920*c0909341SAndroid Build Coastguard Worker         hdr->cdef.uv_strength[0] = 0;
921*c0909341SAndroid Build Coastguard Worker     }
922*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
923*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-cdef: off=%td\n",
924*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
925*c0909341SAndroid Build Coastguard Worker #endif
926*c0909341SAndroid Build Coastguard Worker 
927*c0909341SAndroid Build Coastguard Worker     // restoration
928*c0909341SAndroid Build Coastguard Worker     if ((!hdr->all_lossless || hdr->super_res.enabled) &&
929*c0909341SAndroid Build Coastguard Worker         seqhdr->restoration && !hdr->allow_intrabc)
930*c0909341SAndroid Build Coastguard Worker     {
931*c0909341SAndroid Build Coastguard Worker         hdr->restoration.type[0] = dav1d_get_bits(gb, 2);
932*c0909341SAndroid Build Coastguard Worker         if (!seqhdr->monochrome) {
933*c0909341SAndroid Build Coastguard Worker             hdr->restoration.type[1] = dav1d_get_bits(gb, 2);
934*c0909341SAndroid Build Coastguard Worker             hdr->restoration.type[2] = dav1d_get_bits(gb, 2);
935*c0909341SAndroid Build Coastguard Worker         } else {
936*c0909341SAndroid Build Coastguard Worker             hdr->restoration.type[1] =
937*c0909341SAndroid Build Coastguard Worker             hdr->restoration.type[2] = DAV1D_RESTORATION_NONE;
938*c0909341SAndroid Build Coastguard Worker         }
939*c0909341SAndroid Build Coastguard Worker 
940*c0909341SAndroid Build Coastguard Worker         if (hdr->restoration.type[0] || hdr->restoration.type[1] ||
941*c0909341SAndroid Build Coastguard Worker             hdr->restoration.type[2])
942*c0909341SAndroid Build Coastguard Worker         {
943*c0909341SAndroid Build Coastguard Worker             // Log2 of the restoration unit size.
944*c0909341SAndroid Build Coastguard Worker             hdr->restoration.unit_size[0] = 6 + seqhdr->sb128;
945*c0909341SAndroid Build Coastguard Worker             if (dav1d_get_bit(gb)) {
946*c0909341SAndroid Build Coastguard Worker                 hdr->restoration.unit_size[0]++;
947*c0909341SAndroid Build Coastguard Worker                 if (!seqhdr->sb128)
948*c0909341SAndroid Build Coastguard Worker                     hdr->restoration.unit_size[0] += dav1d_get_bit(gb);
949*c0909341SAndroid Build Coastguard Worker             }
950*c0909341SAndroid Build Coastguard Worker             hdr->restoration.unit_size[1] = hdr->restoration.unit_size[0];
951*c0909341SAndroid Build Coastguard Worker             if ((hdr->restoration.type[1] || hdr->restoration.type[2]) &&
952*c0909341SAndroid Build Coastguard Worker                 seqhdr->ss_hor == 1 && seqhdr->ss_ver == 1)
953*c0909341SAndroid Build Coastguard Worker             {
954*c0909341SAndroid Build Coastguard Worker                 hdr->restoration.unit_size[1] -= dav1d_get_bit(gb);
955*c0909341SAndroid Build Coastguard Worker             }
956*c0909341SAndroid Build Coastguard Worker         } else {
957*c0909341SAndroid Build Coastguard Worker             hdr->restoration.unit_size[0] = 8;
958*c0909341SAndroid Build Coastguard Worker         }
959*c0909341SAndroid Build Coastguard Worker     } else {
960*c0909341SAndroid Build Coastguard Worker         hdr->restoration.type[0] = DAV1D_RESTORATION_NONE;
961*c0909341SAndroid Build Coastguard Worker         hdr->restoration.type[1] = DAV1D_RESTORATION_NONE;
962*c0909341SAndroid Build Coastguard Worker         hdr->restoration.type[2] = DAV1D_RESTORATION_NONE;
963*c0909341SAndroid Build Coastguard Worker     }
964*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
965*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-restoration: off=%td\n",
966*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
967*c0909341SAndroid Build Coastguard Worker #endif
968*c0909341SAndroid Build Coastguard Worker 
969*c0909341SAndroid Build Coastguard Worker     hdr->txfm_mode = hdr->all_lossless ? DAV1D_TX_4X4_ONLY :
970*c0909341SAndroid Build Coastguard Worker                      dav1d_get_bit(gb) ? DAV1D_TX_SWITCHABLE : DAV1D_TX_LARGEST;
971*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
972*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-txfmmode: off=%td\n",
973*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
974*c0909341SAndroid Build Coastguard Worker #endif
975*c0909341SAndroid Build Coastguard Worker     hdr->switchable_comp_refs = IS_INTER_OR_SWITCH(hdr) ? dav1d_get_bit(gb) : 0;
976*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
977*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-refmode: off=%td\n",
978*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
979*c0909341SAndroid Build Coastguard Worker #endif
980*c0909341SAndroid Build Coastguard Worker     hdr->skip_mode_allowed = 0;
981*c0909341SAndroid Build Coastguard Worker     if (hdr->switchable_comp_refs && IS_INTER_OR_SWITCH(hdr) && seqhdr->order_hint) {
982*c0909341SAndroid Build Coastguard Worker         const unsigned poc = hdr->frame_offset;
983*c0909341SAndroid Build Coastguard Worker         unsigned off_before = 0xFFFFFFFFU;
984*c0909341SAndroid Build Coastguard Worker         int off_after = -1;
985*c0909341SAndroid Build Coastguard Worker         int off_before_idx, off_after_idx;
986*c0909341SAndroid Build Coastguard Worker         for (int i = 0; i < 7; i++) {
987*c0909341SAndroid Build Coastguard Worker             if (!c->refs[hdr->refidx[i]].p.p.frame_hdr) goto error;
988*c0909341SAndroid Build Coastguard Worker             const unsigned refpoc = c->refs[hdr->refidx[i]].p.p.frame_hdr->frame_offset;
989*c0909341SAndroid Build Coastguard Worker 
990*c0909341SAndroid Build Coastguard Worker             const int diff = get_poc_diff(seqhdr->order_hint_n_bits, refpoc, poc);
991*c0909341SAndroid Build Coastguard Worker             if (diff > 0) {
992*c0909341SAndroid Build Coastguard Worker                 if (off_after == -1 || get_poc_diff(seqhdr->order_hint_n_bits,
993*c0909341SAndroid Build Coastguard Worker                                                     off_after, refpoc) > 0)
994*c0909341SAndroid Build Coastguard Worker                 {
995*c0909341SAndroid Build Coastguard Worker                     off_after = refpoc;
996*c0909341SAndroid Build Coastguard Worker                     off_after_idx = i;
997*c0909341SAndroid Build Coastguard Worker                 }
998*c0909341SAndroid Build Coastguard Worker             } else if (diff < 0 && (off_before == 0xFFFFFFFFU ||
999*c0909341SAndroid Build Coastguard Worker                                     get_poc_diff(seqhdr->order_hint_n_bits,
1000*c0909341SAndroid Build Coastguard Worker                                                  refpoc, off_before) > 0))
1001*c0909341SAndroid Build Coastguard Worker             {
1002*c0909341SAndroid Build Coastguard Worker                 off_before = refpoc;
1003*c0909341SAndroid Build Coastguard Worker                 off_before_idx = i;
1004*c0909341SAndroid Build Coastguard Worker             }
1005*c0909341SAndroid Build Coastguard Worker         }
1006*c0909341SAndroid Build Coastguard Worker 
1007*c0909341SAndroid Build Coastguard Worker         if (off_before != 0xFFFFFFFFU && off_after != -1) {
1008*c0909341SAndroid Build Coastguard Worker             hdr->skip_mode_refs[0] = imin(off_before_idx, off_after_idx);
1009*c0909341SAndroid Build Coastguard Worker             hdr->skip_mode_refs[1] = imax(off_before_idx, off_after_idx);
1010*c0909341SAndroid Build Coastguard Worker             hdr->skip_mode_allowed = 1;
1011*c0909341SAndroid Build Coastguard Worker         } else if (off_before != 0xFFFFFFFFU) {
1012*c0909341SAndroid Build Coastguard Worker             unsigned off_before2 = 0xFFFFFFFFU;
1013*c0909341SAndroid Build Coastguard Worker             int off_before2_idx;
1014*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < 7; i++) {
1015*c0909341SAndroid Build Coastguard Worker                 if (!c->refs[hdr->refidx[i]].p.p.frame_hdr) goto error;
1016*c0909341SAndroid Build Coastguard Worker                 const unsigned refpoc = c->refs[hdr->refidx[i]].p.p.frame_hdr->frame_offset;
1017*c0909341SAndroid Build Coastguard Worker                 if (get_poc_diff(seqhdr->order_hint_n_bits,
1018*c0909341SAndroid Build Coastguard Worker                                  refpoc, off_before) < 0) {
1019*c0909341SAndroid Build Coastguard Worker                     if (off_before2 == 0xFFFFFFFFU ||
1020*c0909341SAndroid Build Coastguard Worker                         get_poc_diff(seqhdr->order_hint_n_bits,
1021*c0909341SAndroid Build Coastguard Worker                                      refpoc, off_before2) > 0)
1022*c0909341SAndroid Build Coastguard Worker                     {
1023*c0909341SAndroid Build Coastguard Worker                         off_before2 = refpoc;
1024*c0909341SAndroid Build Coastguard Worker                         off_before2_idx = i;
1025*c0909341SAndroid Build Coastguard Worker                     }
1026*c0909341SAndroid Build Coastguard Worker                 }
1027*c0909341SAndroid Build Coastguard Worker             }
1028*c0909341SAndroid Build Coastguard Worker 
1029*c0909341SAndroid Build Coastguard Worker             if (off_before2 != 0xFFFFFFFFU) {
1030*c0909341SAndroid Build Coastguard Worker                 hdr->skip_mode_refs[0] = imin(off_before_idx, off_before2_idx);
1031*c0909341SAndroid Build Coastguard Worker                 hdr->skip_mode_refs[1] = imax(off_before_idx, off_before2_idx);
1032*c0909341SAndroid Build Coastguard Worker                 hdr->skip_mode_allowed = 1;
1033*c0909341SAndroid Build Coastguard Worker             }
1034*c0909341SAndroid Build Coastguard Worker         }
1035*c0909341SAndroid Build Coastguard Worker     }
1036*c0909341SAndroid Build Coastguard Worker     hdr->skip_mode_enabled = hdr->skip_mode_allowed ? dav1d_get_bit(gb) : 0;
1037*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
1038*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-extskip: off=%td\n",
1039*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
1040*c0909341SAndroid Build Coastguard Worker #endif
1041*c0909341SAndroid Build Coastguard Worker     hdr->warp_motion = !hdr->error_resilient_mode && IS_INTER_OR_SWITCH(hdr) &&
1042*c0909341SAndroid Build Coastguard Worker         seqhdr->warped_motion && dav1d_get_bit(gb);
1043*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
1044*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-warpmotionbit: off=%td\n",
1045*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
1046*c0909341SAndroid Build Coastguard Worker #endif
1047*c0909341SAndroid Build Coastguard Worker     hdr->reduced_txtp_set = dav1d_get_bit(gb);
1048*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
1049*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-reducedtxtpset: off=%td\n",
1050*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
1051*c0909341SAndroid Build Coastguard Worker #endif
1052*c0909341SAndroid Build Coastguard Worker 
1053*c0909341SAndroid Build Coastguard Worker     for (int i = 0; i < 7; i++)
1054*c0909341SAndroid Build Coastguard Worker         hdr->gmv[i] = dav1d_default_wm_params;
1055*c0909341SAndroid Build Coastguard Worker 
1056*c0909341SAndroid Build Coastguard Worker     if (IS_INTER_OR_SWITCH(hdr)) {
1057*c0909341SAndroid Build Coastguard Worker         for (int i = 0; i < 7; i++) {
1058*c0909341SAndroid Build Coastguard Worker             hdr->gmv[i].type = !dav1d_get_bit(gb) ? DAV1D_WM_TYPE_IDENTITY :
1059*c0909341SAndroid Build Coastguard Worker                                 dav1d_get_bit(gb) ? DAV1D_WM_TYPE_ROT_ZOOM :
1060*c0909341SAndroid Build Coastguard Worker                                 dav1d_get_bit(gb) ? DAV1D_WM_TYPE_TRANSLATION :
1061*c0909341SAndroid Build Coastguard Worker                                                   DAV1D_WM_TYPE_AFFINE;
1062*c0909341SAndroid Build Coastguard Worker 
1063*c0909341SAndroid Build Coastguard Worker             if (hdr->gmv[i].type == DAV1D_WM_TYPE_IDENTITY) continue;
1064*c0909341SAndroid Build Coastguard Worker 
1065*c0909341SAndroid Build Coastguard Worker             const Dav1dWarpedMotionParams *ref_gmv;
1066*c0909341SAndroid Build Coastguard Worker             if (hdr->primary_ref_frame == DAV1D_PRIMARY_REF_NONE) {
1067*c0909341SAndroid Build Coastguard Worker                 ref_gmv = &dav1d_default_wm_params;
1068*c0909341SAndroid Build Coastguard Worker             } else {
1069*c0909341SAndroid Build Coastguard Worker                 const int pri_ref = hdr->refidx[hdr->primary_ref_frame];
1070*c0909341SAndroid Build Coastguard Worker                 if (!c->refs[pri_ref].p.p.frame_hdr) goto error;
1071*c0909341SAndroid Build Coastguard Worker                 ref_gmv = &c->refs[pri_ref].p.p.frame_hdr->gmv[i];
1072*c0909341SAndroid Build Coastguard Worker             }
1073*c0909341SAndroid Build Coastguard Worker             int32_t *const mat = hdr->gmv[i].matrix;
1074*c0909341SAndroid Build Coastguard Worker             const int32_t *const ref_mat = ref_gmv->matrix;
1075*c0909341SAndroid Build Coastguard Worker             int bits, shift;
1076*c0909341SAndroid Build Coastguard Worker 
1077*c0909341SAndroid Build Coastguard Worker             if (hdr->gmv[i].type >= DAV1D_WM_TYPE_ROT_ZOOM) {
1078*c0909341SAndroid Build Coastguard Worker                 mat[2] = (1 << 16) + 2 *
1079*c0909341SAndroid Build Coastguard Worker                     dav1d_get_bits_subexp(gb, (ref_mat[2] - (1 << 16)) >> 1, 12);
1080*c0909341SAndroid Build Coastguard Worker                 mat[3] = 2 * dav1d_get_bits_subexp(gb, ref_mat[3] >> 1, 12);
1081*c0909341SAndroid Build Coastguard Worker 
1082*c0909341SAndroid Build Coastguard Worker                 bits = 12;
1083*c0909341SAndroid Build Coastguard Worker                 shift = 10;
1084*c0909341SAndroid Build Coastguard Worker             } else {
1085*c0909341SAndroid Build Coastguard Worker                 bits = 9 - !hdr->hp;
1086*c0909341SAndroid Build Coastguard Worker                 shift = 13 + !hdr->hp;
1087*c0909341SAndroid Build Coastguard Worker             }
1088*c0909341SAndroid Build Coastguard Worker 
1089*c0909341SAndroid Build Coastguard Worker             if (hdr->gmv[i].type == DAV1D_WM_TYPE_AFFINE) {
1090*c0909341SAndroid Build Coastguard Worker                 mat[4] = 2 * dav1d_get_bits_subexp(gb, ref_mat[4] >> 1, 12);
1091*c0909341SAndroid Build Coastguard Worker                 mat[5] = (1 << 16) + 2 *
1092*c0909341SAndroid Build Coastguard Worker                     dav1d_get_bits_subexp(gb, (ref_mat[5] - (1 << 16)) >> 1, 12);
1093*c0909341SAndroid Build Coastguard Worker             } else {
1094*c0909341SAndroid Build Coastguard Worker                 mat[4] = -mat[3];
1095*c0909341SAndroid Build Coastguard Worker                 mat[5] = mat[2];
1096*c0909341SAndroid Build Coastguard Worker             }
1097*c0909341SAndroid Build Coastguard Worker 
1098*c0909341SAndroid Build Coastguard Worker             mat[0] = dav1d_get_bits_subexp(gb, ref_mat[0] >> shift, bits) * (1 << shift);
1099*c0909341SAndroid Build Coastguard Worker             mat[1] = dav1d_get_bits_subexp(gb, ref_mat[1] >> shift, bits) * (1 << shift);
1100*c0909341SAndroid Build Coastguard Worker         }
1101*c0909341SAndroid Build Coastguard Worker     }
1102*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
1103*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-gmv: off=%td\n",
1104*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
1105*c0909341SAndroid Build Coastguard Worker #endif
1106*c0909341SAndroid Build Coastguard Worker 
1107*c0909341SAndroid Build Coastguard Worker     hdr->film_grain.present = seqhdr->film_grain_present &&
1108*c0909341SAndroid Build Coastguard Worker                               (hdr->show_frame || hdr->showable_frame) &&
1109*c0909341SAndroid Build Coastguard Worker                               dav1d_get_bit(gb);
1110*c0909341SAndroid Build Coastguard Worker     if (hdr->film_grain.present) {
1111*c0909341SAndroid Build Coastguard Worker         const unsigned seed = dav1d_get_bits(gb, 16);
1112*c0909341SAndroid Build Coastguard Worker         hdr->film_grain.update = hdr->frame_type != DAV1D_FRAME_TYPE_INTER || dav1d_get_bit(gb);
1113*c0909341SAndroid Build Coastguard Worker         if (!hdr->film_grain.update) {
1114*c0909341SAndroid Build Coastguard Worker             const int refidx = dav1d_get_bits(gb, 3);
1115*c0909341SAndroid Build Coastguard Worker             int i;
1116*c0909341SAndroid Build Coastguard Worker             for (i = 0; i < 7; i++)
1117*c0909341SAndroid Build Coastguard Worker                 if (hdr->refidx[i] == refidx)
1118*c0909341SAndroid Build Coastguard Worker                     break;
1119*c0909341SAndroid Build Coastguard Worker             if (i == 7 || !c->refs[refidx].p.p.frame_hdr) goto error;
1120*c0909341SAndroid Build Coastguard Worker             hdr->film_grain.data = c->refs[refidx].p.p.frame_hdr->film_grain.data;
1121*c0909341SAndroid Build Coastguard Worker             hdr->film_grain.data.seed = seed;
1122*c0909341SAndroid Build Coastguard Worker         } else {
1123*c0909341SAndroid Build Coastguard Worker             Dav1dFilmGrainData *const fgd = &hdr->film_grain.data;
1124*c0909341SAndroid Build Coastguard Worker             fgd->seed = seed;
1125*c0909341SAndroid Build Coastguard Worker 
1126*c0909341SAndroid Build Coastguard Worker             fgd->num_y_points = dav1d_get_bits(gb, 4);
1127*c0909341SAndroid Build Coastguard Worker             if (fgd->num_y_points > 14) goto error;
1128*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < fgd->num_y_points; i++) {
1129*c0909341SAndroid Build Coastguard Worker                 fgd->y_points[i][0] = dav1d_get_bits(gb, 8);
1130*c0909341SAndroid Build Coastguard Worker                 if (i && fgd->y_points[i - 1][0] >= fgd->y_points[i][0])
1131*c0909341SAndroid Build Coastguard Worker                     goto error;
1132*c0909341SAndroid Build Coastguard Worker                 fgd->y_points[i][1] = dav1d_get_bits(gb, 8);
1133*c0909341SAndroid Build Coastguard Worker             }
1134*c0909341SAndroid Build Coastguard Worker 
1135*c0909341SAndroid Build Coastguard Worker             fgd->chroma_scaling_from_luma =
1136*c0909341SAndroid Build Coastguard Worker                 !seqhdr->monochrome && dav1d_get_bit(gb);
1137*c0909341SAndroid Build Coastguard Worker             if (seqhdr->monochrome || fgd->chroma_scaling_from_luma ||
1138*c0909341SAndroid Build Coastguard Worker                 (seqhdr->ss_ver == 1 && seqhdr->ss_hor == 1 && !fgd->num_y_points))
1139*c0909341SAndroid Build Coastguard Worker             {
1140*c0909341SAndroid Build Coastguard Worker                 fgd->num_uv_points[0] = fgd->num_uv_points[1] = 0;
1141*c0909341SAndroid Build Coastguard Worker             } else for (int pl = 0; pl < 2; pl++) {
1142*c0909341SAndroid Build Coastguard Worker                 fgd->num_uv_points[pl] = dav1d_get_bits(gb, 4);
1143*c0909341SAndroid Build Coastguard Worker                 if (fgd->num_uv_points[pl] > 10) goto error;
1144*c0909341SAndroid Build Coastguard Worker                 for (int i = 0; i < fgd->num_uv_points[pl]; i++) {
1145*c0909341SAndroid Build Coastguard Worker                     fgd->uv_points[pl][i][0] = dav1d_get_bits(gb, 8);
1146*c0909341SAndroid Build Coastguard Worker                     if (i && fgd->uv_points[pl][i - 1][0] >= fgd->uv_points[pl][i][0])
1147*c0909341SAndroid Build Coastguard Worker                         goto error;
1148*c0909341SAndroid Build Coastguard Worker                     fgd->uv_points[pl][i][1] = dav1d_get_bits(gb, 8);
1149*c0909341SAndroid Build Coastguard Worker                 }
1150*c0909341SAndroid Build Coastguard Worker             }
1151*c0909341SAndroid Build Coastguard Worker 
1152*c0909341SAndroid Build Coastguard Worker             if (seqhdr->ss_hor == 1 && seqhdr->ss_ver == 1 &&
1153*c0909341SAndroid Build Coastguard Worker                 !!fgd->num_uv_points[0] != !!fgd->num_uv_points[1])
1154*c0909341SAndroid Build Coastguard Worker             {
1155*c0909341SAndroid Build Coastguard Worker                 goto error;
1156*c0909341SAndroid Build Coastguard Worker             }
1157*c0909341SAndroid Build Coastguard Worker 
1158*c0909341SAndroid Build Coastguard Worker             fgd->scaling_shift = dav1d_get_bits(gb, 2) + 8;
1159*c0909341SAndroid Build Coastguard Worker             fgd->ar_coeff_lag = dav1d_get_bits(gb, 2);
1160*c0909341SAndroid Build Coastguard Worker             const int num_y_pos = 2 * fgd->ar_coeff_lag * (fgd->ar_coeff_lag + 1);
1161*c0909341SAndroid Build Coastguard Worker             if (fgd->num_y_points)
1162*c0909341SAndroid Build Coastguard Worker                 for (int i = 0; i < num_y_pos; i++)
1163*c0909341SAndroid Build Coastguard Worker                     fgd->ar_coeffs_y[i] = dav1d_get_bits(gb, 8) - 128;
1164*c0909341SAndroid Build Coastguard Worker             for (int pl = 0; pl < 2; pl++)
1165*c0909341SAndroid Build Coastguard Worker                 if (fgd->num_uv_points[pl] || fgd->chroma_scaling_from_luma) {
1166*c0909341SAndroid Build Coastguard Worker                     const int num_uv_pos = num_y_pos + !!fgd->num_y_points;
1167*c0909341SAndroid Build Coastguard Worker                     for (int i = 0; i < num_uv_pos; i++)
1168*c0909341SAndroid Build Coastguard Worker                         fgd->ar_coeffs_uv[pl][i] = dav1d_get_bits(gb, 8) - 128;
1169*c0909341SAndroid Build Coastguard Worker                     if (!fgd->num_y_points)
1170*c0909341SAndroid Build Coastguard Worker                         fgd->ar_coeffs_uv[pl][num_uv_pos] = 0;
1171*c0909341SAndroid Build Coastguard Worker                 }
1172*c0909341SAndroid Build Coastguard Worker             fgd->ar_coeff_shift = dav1d_get_bits(gb, 2) + 6;
1173*c0909341SAndroid Build Coastguard Worker             fgd->grain_scale_shift = dav1d_get_bits(gb, 2);
1174*c0909341SAndroid Build Coastguard Worker             for (int pl = 0; pl < 2; pl++)
1175*c0909341SAndroid Build Coastguard Worker                 if (fgd->num_uv_points[pl]) {
1176*c0909341SAndroid Build Coastguard Worker                     fgd->uv_mult[pl] = dav1d_get_bits(gb, 8) - 128;
1177*c0909341SAndroid Build Coastguard Worker                     fgd->uv_luma_mult[pl] = dav1d_get_bits(gb, 8) - 128;
1178*c0909341SAndroid Build Coastguard Worker                     fgd->uv_offset[pl] = dav1d_get_bits(gb, 9) - 256;
1179*c0909341SAndroid Build Coastguard Worker                 }
1180*c0909341SAndroid Build Coastguard Worker             fgd->overlap_flag = dav1d_get_bit(gb);
1181*c0909341SAndroid Build Coastguard Worker             fgd->clip_to_restricted_range = dav1d_get_bit(gb);
1182*c0909341SAndroid Build Coastguard Worker         }
1183*c0909341SAndroid Build Coastguard Worker     } else {
1184*c0909341SAndroid Build Coastguard Worker         memset(&hdr->film_grain.data, 0, sizeof(hdr->film_grain.data));
1185*c0909341SAndroid Build Coastguard Worker     }
1186*c0909341SAndroid Build Coastguard Worker #if DEBUG_FRAME_HDR
1187*c0909341SAndroid Build Coastguard Worker     printf("HDR: post-filmgrain: off=%td\n",
1188*c0909341SAndroid Build Coastguard Worker            (gb->ptr - init_ptr) * 8 - gb->bits_left);
1189*c0909341SAndroid Build Coastguard Worker #endif
1190*c0909341SAndroid Build Coastguard Worker 
1191*c0909341SAndroid Build Coastguard Worker     return 0;
1192*c0909341SAndroid Build Coastguard Worker 
1193*c0909341SAndroid Build Coastguard Worker error:
1194*c0909341SAndroid Build Coastguard Worker     dav1d_log(c, "Error parsing frame header\n");
1195*c0909341SAndroid Build Coastguard Worker     return DAV1D_ERR(EINVAL);
1196*c0909341SAndroid Build Coastguard Worker }
1197*c0909341SAndroid Build Coastguard Worker 
parse_tile_hdr(Dav1dContext * const c,GetBits * const gb)1198*c0909341SAndroid Build Coastguard Worker static void parse_tile_hdr(Dav1dContext *const c, GetBits *const gb) {
1199*c0909341SAndroid Build Coastguard Worker     const int n_tiles = c->frame_hdr->tiling.cols * c->frame_hdr->tiling.rows;
1200*c0909341SAndroid Build Coastguard Worker     const int have_tile_pos = n_tiles > 1 ? dav1d_get_bit(gb) : 0;
1201*c0909341SAndroid Build Coastguard Worker 
1202*c0909341SAndroid Build Coastguard Worker     if (have_tile_pos) {
1203*c0909341SAndroid Build Coastguard Worker         const int n_bits = c->frame_hdr->tiling.log2_cols +
1204*c0909341SAndroid Build Coastguard Worker                            c->frame_hdr->tiling.log2_rows;
1205*c0909341SAndroid Build Coastguard Worker         c->tile[c->n_tile_data].start = dav1d_get_bits(gb, n_bits);
1206*c0909341SAndroid Build Coastguard Worker         c->tile[c->n_tile_data].end = dav1d_get_bits(gb, n_bits);
1207*c0909341SAndroid Build Coastguard Worker     } else {
1208*c0909341SAndroid Build Coastguard Worker         c->tile[c->n_tile_data].start = 0;
1209*c0909341SAndroid Build Coastguard Worker         c->tile[c->n_tile_data].end = n_tiles - 1;
1210*c0909341SAndroid Build Coastguard Worker     }
1211*c0909341SAndroid Build Coastguard Worker }
1212*c0909341SAndroid Build Coastguard Worker 
dav1d_parse_obus(Dav1dContext * const c,Dav1dData * const in)1213*c0909341SAndroid Build Coastguard Worker ptrdiff_t dav1d_parse_obus(Dav1dContext *const c, Dav1dData *const in) {
1214*c0909341SAndroid Build Coastguard Worker     GetBits gb;
1215*c0909341SAndroid Build Coastguard Worker     int res;
1216*c0909341SAndroid Build Coastguard Worker 
1217*c0909341SAndroid Build Coastguard Worker     dav1d_init_get_bits(&gb, in->data, in->sz);
1218*c0909341SAndroid Build Coastguard Worker 
1219*c0909341SAndroid Build Coastguard Worker     // obu header
1220*c0909341SAndroid Build Coastguard Worker     const int obu_forbidden_bit = dav1d_get_bit(&gb);
1221*c0909341SAndroid Build Coastguard Worker     if (c->strict_std_compliance && obu_forbidden_bit) goto error;
1222*c0909341SAndroid Build Coastguard Worker     const enum Dav1dObuType type = dav1d_get_bits(&gb, 4);
1223*c0909341SAndroid Build Coastguard Worker     const int has_extension = dav1d_get_bit(&gb);
1224*c0909341SAndroid Build Coastguard Worker     const int has_length_field = dav1d_get_bit(&gb);
1225*c0909341SAndroid Build Coastguard Worker     dav1d_get_bit(&gb); // reserved
1226*c0909341SAndroid Build Coastguard Worker 
1227*c0909341SAndroid Build Coastguard Worker     int temporal_id = 0, spatial_id = 0;
1228*c0909341SAndroid Build Coastguard Worker     if (has_extension) {
1229*c0909341SAndroid Build Coastguard Worker         temporal_id = dav1d_get_bits(&gb, 3);
1230*c0909341SAndroid Build Coastguard Worker         spatial_id = dav1d_get_bits(&gb, 2);
1231*c0909341SAndroid Build Coastguard Worker         dav1d_get_bits(&gb, 3); // reserved
1232*c0909341SAndroid Build Coastguard Worker     }
1233*c0909341SAndroid Build Coastguard Worker 
1234*c0909341SAndroid Build Coastguard Worker     if (has_length_field) {
1235*c0909341SAndroid Build Coastguard Worker         const size_t len = dav1d_get_uleb128(&gb);
1236*c0909341SAndroid Build Coastguard Worker         if (len > (size_t)(gb.ptr_end - gb.ptr)) goto error;
1237*c0909341SAndroid Build Coastguard Worker         gb.ptr_end = gb.ptr + len;
1238*c0909341SAndroid Build Coastguard Worker     }
1239*c0909341SAndroid Build Coastguard Worker     if (gb.error) goto error;
1240*c0909341SAndroid Build Coastguard Worker 
1241*c0909341SAndroid Build Coastguard Worker     // We must have read a whole number of bytes at this point (1 byte
1242*c0909341SAndroid Build Coastguard Worker     // for the header and whole bytes at a time when reading the
1243*c0909341SAndroid Build Coastguard Worker     // leb128 length field).
1244*c0909341SAndroid Build Coastguard Worker     assert(gb.bits_left == 0);
1245*c0909341SAndroid Build Coastguard Worker 
1246*c0909341SAndroid Build Coastguard Worker     // skip obu not belonging to the selected temporal/spatial layer
1247*c0909341SAndroid Build Coastguard Worker     if (type != DAV1D_OBU_SEQ_HDR && type != DAV1D_OBU_TD &&
1248*c0909341SAndroid Build Coastguard Worker         has_extension && c->operating_point_idc != 0)
1249*c0909341SAndroid Build Coastguard Worker     {
1250*c0909341SAndroid Build Coastguard Worker         const int in_temporal_layer = (c->operating_point_idc >> temporal_id) & 1;
1251*c0909341SAndroid Build Coastguard Worker         const int in_spatial_layer = (c->operating_point_idc >> (spatial_id + 8)) & 1;
1252*c0909341SAndroid Build Coastguard Worker         if (!in_temporal_layer || !in_spatial_layer)
1253*c0909341SAndroid Build Coastguard Worker             return gb.ptr_end - gb.ptr_start;
1254*c0909341SAndroid Build Coastguard Worker     }
1255*c0909341SAndroid Build Coastguard Worker 
1256*c0909341SAndroid Build Coastguard Worker     switch (type) {
1257*c0909341SAndroid Build Coastguard Worker     case DAV1D_OBU_SEQ_HDR: {
1258*c0909341SAndroid Build Coastguard Worker         Dav1dRef *ref = dav1d_ref_create_using_pool(c->seq_hdr_pool,
1259*c0909341SAndroid Build Coastguard Worker                                                     sizeof(Dav1dSequenceHeader));
1260*c0909341SAndroid Build Coastguard Worker         if (!ref) return DAV1D_ERR(ENOMEM);
1261*c0909341SAndroid Build Coastguard Worker         Dav1dSequenceHeader *seq_hdr = ref->data;
1262*c0909341SAndroid Build Coastguard Worker         if ((res = parse_seq_hdr(seq_hdr, &gb, c->strict_std_compliance)) < 0) {
1263*c0909341SAndroid Build Coastguard Worker             dav1d_log(c, "Error parsing sequence header\n");
1264*c0909341SAndroid Build Coastguard Worker             dav1d_ref_dec(&ref);
1265*c0909341SAndroid Build Coastguard Worker             goto error;
1266*c0909341SAndroid Build Coastguard Worker         }
1267*c0909341SAndroid Build Coastguard Worker 
1268*c0909341SAndroid Build Coastguard Worker         const int op_idx =
1269*c0909341SAndroid Build Coastguard Worker             c->operating_point < seq_hdr->num_operating_points ? c->operating_point : 0;
1270*c0909341SAndroid Build Coastguard Worker         c->operating_point_idc = seq_hdr->operating_points[op_idx].idc;
1271*c0909341SAndroid Build Coastguard Worker         const unsigned spatial_mask = c->operating_point_idc >> 8;
1272*c0909341SAndroid Build Coastguard Worker         c->max_spatial_id = spatial_mask ? ulog2(spatial_mask) : 0;
1273*c0909341SAndroid Build Coastguard Worker 
1274*c0909341SAndroid Build Coastguard Worker         // If we have read a sequence header which is different from
1275*c0909341SAndroid Build Coastguard Worker         // the old one, this is a new video sequence and can't use any
1276*c0909341SAndroid Build Coastguard Worker         // previous state. Free that state.
1277*c0909341SAndroid Build Coastguard Worker 
1278*c0909341SAndroid Build Coastguard Worker         if (!c->seq_hdr) {
1279*c0909341SAndroid Build Coastguard Worker             c->frame_hdr = NULL;
1280*c0909341SAndroid Build Coastguard Worker             c->frame_flags |= PICTURE_FLAG_NEW_SEQUENCE;
1281*c0909341SAndroid Build Coastguard Worker         // see 7.5, operating_parameter_info is allowed to change in
1282*c0909341SAndroid Build Coastguard Worker         // sequence headers of a single sequence
1283*c0909341SAndroid Build Coastguard Worker         } else if (memcmp(seq_hdr, c->seq_hdr, offsetof(Dav1dSequenceHeader, operating_parameter_info))) {
1284*c0909341SAndroid Build Coastguard Worker             c->frame_hdr = NULL;
1285*c0909341SAndroid Build Coastguard Worker             c->mastering_display = NULL;
1286*c0909341SAndroid Build Coastguard Worker             c->content_light = NULL;
1287*c0909341SAndroid Build Coastguard Worker             dav1d_ref_dec(&c->mastering_display_ref);
1288*c0909341SAndroid Build Coastguard Worker             dav1d_ref_dec(&c->content_light_ref);
1289*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < 8; i++) {
1290*c0909341SAndroid Build Coastguard Worker                 if (c->refs[i].p.p.frame_hdr)
1291*c0909341SAndroid Build Coastguard Worker                     dav1d_thread_picture_unref(&c->refs[i].p);
1292*c0909341SAndroid Build Coastguard Worker                 dav1d_ref_dec(&c->refs[i].segmap);
1293*c0909341SAndroid Build Coastguard Worker                 dav1d_ref_dec(&c->refs[i].refmvs);
1294*c0909341SAndroid Build Coastguard Worker                 dav1d_cdf_thread_unref(&c->cdf[i]);
1295*c0909341SAndroid Build Coastguard Worker             }
1296*c0909341SAndroid Build Coastguard Worker             c->frame_flags |= PICTURE_FLAG_NEW_SEQUENCE;
1297*c0909341SAndroid Build Coastguard Worker         // If operating_parameter_info changed, signal it
1298*c0909341SAndroid Build Coastguard Worker         } else if (memcmp(seq_hdr->operating_parameter_info, c->seq_hdr->operating_parameter_info,
1299*c0909341SAndroid Build Coastguard Worker                           sizeof(seq_hdr->operating_parameter_info)))
1300*c0909341SAndroid Build Coastguard Worker         {
1301*c0909341SAndroid Build Coastguard Worker             c->frame_flags |= PICTURE_FLAG_NEW_OP_PARAMS_INFO;
1302*c0909341SAndroid Build Coastguard Worker         }
1303*c0909341SAndroid Build Coastguard Worker         dav1d_ref_dec(&c->seq_hdr_ref);
1304*c0909341SAndroid Build Coastguard Worker         c->seq_hdr_ref = ref;
1305*c0909341SAndroid Build Coastguard Worker         c->seq_hdr = seq_hdr;
1306*c0909341SAndroid Build Coastguard Worker         break;
1307*c0909341SAndroid Build Coastguard Worker     }
1308*c0909341SAndroid Build Coastguard Worker     case DAV1D_OBU_REDUNDANT_FRAME_HDR:
1309*c0909341SAndroid Build Coastguard Worker         if (c->frame_hdr) break;
1310*c0909341SAndroid Build Coastguard Worker         // fall-through
1311*c0909341SAndroid Build Coastguard Worker     case DAV1D_OBU_FRAME:
1312*c0909341SAndroid Build Coastguard Worker     case DAV1D_OBU_FRAME_HDR:
1313*c0909341SAndroid Build Coastguard Worker         if (!c->seq_hdr) goto error;
1314*c0909341SAndroid Build Coastguard Worker         if (!c->frame_hdr_ref) {
1315*c0909341SAndroid Build Coastguard Worker             c->frame_hdr_ref = dav1d_ref_create_using_pool(c->frame_hdr_pool,
1316*c0909341SAndroid Build Coastguard Worker                                                            sizeof(Dav1dFrameHeader));
1317*c0909341SAndroid Build Coastguard Worker             if (!c->frame_hdr_ref) return DAV1D_ERR(ENOMEM);
1318*c0909341SAndroid Build Coastguard Worker         }
1319*c0909341SAndroid Build Coastguard Worker #ifndef NDEBUG
1320*c0909341SAndroid Build Coastguard Worker         // ensure that the reference is writable
1321*c0909341SAndroid Build Coastguard Worker         assert(dav1d_ref_is_writable(c->frame_hdr_ref));
1322*c0909341SAndroid Build Coastguard Worker #endif
1323*c0909341SAndroid Build Coastguard Worker         c->frame_hdr = c->frame_hdr_ref->data;
1324*c0909341SAndroid Build Coastguard Worker         memset(c->frame_hdr, 0, sizeof(*c->frame_hdr));
1325*c0909341SAndroid Build Coastguard Worker         c->frame_hdr->temporal_id = temporal_id;
1326*c0909341SAndroid Build Coastguard Worker         c->frame_hdr->spatial_id = spatial_id;
1327*c0909341SAndroid Build Coastguard Worker         if ((res = parse_frame_hdr(c, &gb)) < 0) {
1328*c0909341SAndroid Build Coastguard Worker             c->frame_hdr = NULL;
1329*c0909341SAndroid Build Coastguard Worker             goto error;
1330*c0909341SAndroid Build Coastguard Worker         }
1331*c0909341SAndroid Build Coastguard Worker         for (int n = 0; n < c->n_tile_data; n++)
1332*c0909341SAndroid Build Coastguard Worker             dav1d_data_unref_internal(&c->tile[n].data);
1333*c0909341SAndroid Build Coastguard Worker         c->n_tile_data = 0;
1334*c0909341SAndroid Build Coastguard Worker         c->n_tiles = 0;
1335*c0909341SAndroid Build Coastguard Worker         if (type != DAV1D_OBU_FRAME) {
1336*c0909341SAndroid Build Coastguard Worker             // This is actually a frame header OBU so read the
1337*c0909341SAndroid Build Coastguard Worker             // trailing bit and check for overrun.
1338*c0909341SAndroid Build Coastguard Worker             if (check_trailing_bits(&gb, c->strict_std_compliance) < 0) {
1339*c0909341SAndroid Build Coastguard Worker                 c->frame_hdr = NULL;
1340*c0909341SAndroid Build Coastguard Worker                 goto error;
1341*c0909341SAndroid Build Coastguard Worker             }
1342*c0909341SAndroid Build Coastguard Worker         }
1343*c0909341SAndroid Build Coastguard Worker 
1344*c0909341SAndroid Build Coastguard Worker         if (c->frame_size_limit && (int64_t)c->frame_hdr->width[1] *
1345*c0909341SAndroid Build Coastguard Worker             c->frame_hdr->height > c->frame_size_limit)
1346*c0909341SAndroid Build Coastguard Worker         {
1347*c0909341SAndroid Build Coastguard Worker             dav1d_log(c, "Frame size %dx%d exceeds limit %u\n", c->frame_hdr->width[1],
1348*c0909341SAndroid Build Coastguard Worker                       c->frame_hdr->height, c->frame_size_limit);
1349*c0909341SAndroid Build Coastguard Worker             c->frame_hdr = NULL;
1350*c0909341SAndroid Build Coastguard Worker             return DAV1D_ERR(ERANGE);
1351*c0909341SAndroid Build Coastguard Worker         }
1352*c0909341SAndroid Build Coastguard Worker 
1353*c0909341SAndroid Build Coastguard Worker         if (type != DAV1D_OBU_FRAME)
1354*c0909341SAndroid Build Coastguard Worker             break;
1355*c0909341SAndroid Build Coastguard Worker         // OBU_FRAMEs shouldn't be signaled with show_existing_frame
1356*c0909341SAndroid Build Coastguard Worker         if (c->frame_hdr->show_existing_frame) {
1357*c0909341SAndroid Build Coastguard Worker             c->frame_hdr = NULL;
1358*c0909341SAndroid Build Coastguard Worker             goto error;
1359*c0909341SAndroid Build Coastguard Worker         }
1360*c0909341SAndroid Build Coastguard Worker 
1361*c0909341SAndroid Build Coastguard Worker         // This is the frame header at the start of a frame OBU.
1362*c0909341SAndroid Build Coastguard Worker         // There's no trailing bit at the end to skip, but we do need
1363*c0909341SAndroid Build Coastguard Worker         // to align to the next byte.
1364*c0909341SAndroid Build Coastguard Worker         dav1d_bytealign_get_bits(&gb);
1365*c0909341SAndroid Build Coastguard Worker         // fall-through
1366*c0909341SAndroid Build Coastguard Worker     case DAV1D_OBU_TILE_GRP: {
1367*c0909341SAndroid Build Coastguard Worker         if (!c->frame_hdr) goto error;
1368*c0909341SAndroid Build Coastguard Worker         if (c->n_tile_data_alloc < c->n_tile_data + 1) {
1369*c0909341SAndroid Build Coastguard Worker             if ((c->n_tile_data + 1) > INT_MAX / (int)sizeof(*c->tile)) goto error;
1370*c0909341SAndroid Build Coastguard Worker             struct Dav1dTileGroup *tile = dav1d_realloc(ALLOC_TILE, c->tile,
1371*c0909341SAndroid Build Coastguard Worker                                                         (c->n_tile_data + 1) * sizeof(*c->tile));
1372*c0909341SAndroid Build Coastguard Worker             if (!tile) goto error;
1373*c0909341SAndroid Build Coastguard Worker             c->tile = tile;
1374*c0909341SAndroid Build Coastguard Worker             memset(c->tile + c->n_tile_data, 0, sizeof(*c->tile));
1375*c0909341SAndroid Build Coastguard Worker             c->n_tile_data_alloc = c->n_tile_data + 1;
1376*c0909341SAndroid Build Coastguard Worker         }
1377*c0909341SAndroid Build Coastguard Worker         parse_tile_hdr(c, &gb);
1378*c0909341SAndroid Build Coastguard Worker         // Align to the next byte boundary and check for overrun.
1379*c0909341SAndroid Build Coastguard Worker         dav1d_bytealign_get_bits(&gb);
1380*c0909341SAndroid Build Coastguard Worker         if (gb.error) goto error;
1381*c0909341SAndroid Build Coastguard Worker 
1382*c0909341SAndroid Build Coastguard Worker         dav1d_data_ref(&c->tile[c->n_tile_data].data, in);
1383*c0909341SAndroid Build Coastguard Worker         c->tile[c->n_tile_data].data.data = gb.ptr;
1384*c0909341SAndroid Build Coastguard Worker         c->tile[c->n_tile_data].data.sz = (size_t)(gb.ptr_end - gb.ptr);
1385*c0909341SAndroid Build Coastguard Worker         // ensure tile groups are in order and sane, see 6.10.1
1386*c0909341SAndroid Build Coastguard Worker         if (c->tile[c->n_tile_data].start > c->tile[c->n_tile_data].end ||
1387*c0909341SAndroid Build Coastguard Worker             c->tile[c->n_tile_data].start != c->n_tiles)
1388*c0909341SAndroid Build Coastguard Worker         {
1389*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i <= c->n_tile_data; i++)
1390*c0909341SAndroid Build Coastguard Worker                 dav1d_data_unref_internal(&c->tile[i].data);
1391*c0909341SAndroid Build Coastguard Worker             c->n_tile_data = 0;
1392*c0909341SAndroid Build Coastguard Worker             c->n_tiles = 0;
1393*c0909341SAndroid Build Coastguard Worker             goto error;
1394*c0909341SAndroid Build Coastguard Worker         }
1395*c0909341SAndroid Build Coastguard Worker         c->n_tiles += 1 + c->tile[c->n_tile_data].end -
1396*c0909341SAndroid Build Coastguard Worker                           c->tile[c->n_tile_data].start;
1397*c0909341SAndroid Build Coastguard Worker         c->n_tile_data++;
1398*c0909341SAndroid Build Coastguard Worker         break;
1399*c0909341SAndroid Build Coastguard Worker     }
1400*c0909341SAndroid Build Coastguard Worker     case DAV1D_OBU_METADATA: {
1401*c0909341SAndroid Build Coastguard Worker #define DEBUG_OBU_METADATA 0
1402*c0909341SAndroid Build Coastguard Worker #if DEBUG_OBU_METADATA
1403*c0909341SAndroid Build Coastguard Worker         const uint8_t *const init_ptr = gb.ptr;
1404*c0909341SAndroid Build Coastguard Worker #endif
1405*c0909341SAndroid Build Coastguard Worker         // obu metadta type field
1406*c0909341SAndroid Build Coastguard Worker         const enum ObuMetaType meta_type = dav1d_get_uleb128(&gb);
1407*c0909341SAndroid Build Coastguard Worker         if (gb.error) goto error;
1408*c0909341SAndroid Build Coastguard Worker 
1409*c0909341SAndroid Build Coastguard Worker         switch (meta_type) {
1410*c0909341SAndroid Build Coastguard Worker         case OBU_META_HDR_CLL: {
1411*c0909341SAndroid Build Coastguard Worker             Dav1dRef *ref = dav1d_ref_create(ALLOC_OBU_META,
1412*c0909341SAndroid Build Coastguard Worker                                              sizeof(Dav1dContentLightLevel));
1413*c0909341SAndroid Build Coastguard Worker             if (!ref) return DAV1D_ERR(ENOMEM);
1414*c0909341SAndroid Build Coastguard Worker             Dav1dContentLightLevel *const content_light = ref->data;
1415*c0909341SAndroid Build Coastguard Worker 
1416*c0909341SAndroid Build Coastguard Worker             content_light->max_content_light_level = dav1d_get_bits(&gb, 16);
1417*c0909341SAndroid Build Coastguard Worker #if DEBUG_OBU_METADATA
1418*c0909341SAndroid Build Coastguard Worker             printf("CLLOBU: max-content-light-level: %d [off=%td]\n",
1419*c0909341SAndroid Build Coastguard Worker                    content_light->max_content_light_level,
1420*c0909341SAndroid Build Coastguard Worker                    (gb.ptr - init_ptr) * 8 - gb.bits_left);
1421*c0909341SAndroid Build Coastguard Worker #endif
1422*c0909341SAndroid Build Coastguard Worker             content_light->max_frame_average_light_level = dav1d_get_bits(&gb, 16);
1423*c0909341SAndroid Build Coastguard Worker #if DEBUG_OBU_METADATA
1424*c0909341SAndroid Build Coastguard Worker             printf("CLLOBU: max-frame-average-light-level: %d [off=%td]\n",
1425*c0909341SAndroid Build Coastguard Worker                    content_light->max_frame_average_light_level,
1426*c0909341SAndroid Build Coastguard Worker                    (gb.ptr - init_ptr) * 8 - gb.bits_left);
1427*c0909341SAndroid Build Coastguard Worker #endif
1428*c0909341SAndroid Build Coastguard Worker 
1429*c0909341SAndroid Build Coastguard Worker             if (check_trailing_bits(&gb, c->strict_std_compliance) < 0) {
1430*c0909341SAndroid Build Coastguard Worker                 dav1d_ref_dec(&ref);
1431*c0909341SAndroid Build Coastguard Worker                 goto error;
1432*c0909341SAndroid Build Coastguard Worker             }
1433*c0909341SAndroid Build Coastguard Worker 
1434*c0909341SAndroid Build Coastguard Worker             dav1d_ref_dec(&c->content_light_ref);
1435*c0909341SAndroid Build Coastguard Worker             c->content_light = content_light;
1436*c0909341SAndroid Build Coastguard Worker             c->content_light_ref = ref;
1437*c0909341SAndroid Build Coastguard Worker             break;
1438*c0909341SAndroid Build Coastguard Worker         }
1439*c0909341SAndroid Build Coastguard Worker         case OBU_META_HDR_MDCV: {
1440*c0909341SAndroid Build Coastguard Worker             Dav1dRef *ref = dav1d_ref_create(ALLOC_OBU_META,
1441*c0909341SAndroid Build Coastguard Worker                                              sizeof(Dav1dMasteringDisplay));
1442*c0909341SAndroid Build Coastguard Worker             if (!ref) return DAV1D_ERR(ENOMEM);
1443*c0909341SAndroid Build Coastguard Worker             Dav1dMasteringDisplay *const mastering_display = ref->data;
1444*c0909341SAndroid Build Coastguard Worker 
1445*c0909341SAndroid Build Coastguard Worker             for (int i = 0; i < 3; i++) {
1446*c0909341SAndroid Build Coastguard Worker                 mastering_display->primaries[i][0] = dav1d_get_bits(&gb, 16);
1447*c0909341SAndroid Build Coastguard Worker                 mastering_display->primaries[i][1] = dav1d_get_bits(&gb, 16);
1448*c0909341SAndroid Build Coastguard Worker #if DEBUG_OBU_METADATA
1449*c0909341SAndroid Build Coastguard Worker                 printf("MDCVOBU: primaries[%d]: (%d, %d) [off=%td]\n", i,
1450*c0909341SAndroid Build Coastguard Worker                        mastering_display->primaries[i][0],
1451*c0909341SAndroid Build Coastguard Worker                        mastering_display->primaries[i][1],
1452*c0909341SAndroid Build Coastguard Worker                        (gb.ptr - init_ptr) * 8 - gb.bits_left);
1453*c0909341SAndroid Build Coastguard Worker #endif
1454*c0909341SAndroid Build Coastguard Worker             }
1455*c0909341SAndroid Build Coastguard Worker             mastering_display->white_point[0] = dav1d_get_bits(&gb, 16);
1456*c0909341SAndroid Build Coastguard Worker #if DEBUG_OBU_METADATA
1457*c0909341SAndroid Build Coastguard Worker             printf("MDCVOBU: white-point-x: %d [off=%td]\n",
1458*c0909341SAndroid Build Coastguard Worker                    mastering_display->white_point[0],
1459*c0909341SAndroid Build Coastguard Worker                    (gb.ptr - init_ptr) * 8 - gb.bits_left);
1460*c0909341SAndroid Build Coastguard Worker #endif
1461*c0909341SAndroid Build Coastguard Worker             mastering_display->white_point[1] = dav1d_get_bits(&gb, 16);
1462*c0909341SAndroid Build Coastguard Worker #if DEBUG_OBU_METADATA
1463*c0909341SAndroid Build Coastguard Worker             printf("MDCVOBU: white-point-y: %d [off=%td]\n",
1464*c0909341SAndroid Build Coastguard Worker                    mastering_display->white_point[1],
1465*c0909341SAndroid Build Coastguard Worker                    (gb.ptr - init_ptr) * 8 - gb.bits_left);
1466*c0909341SAndroid Build Coastguard Worker #endif
1467*c0909341SAndroid Build Coastguard Worker             mastering_display->max_luminance = dav1d_get_bits(&gb, 32);
1468*c0909341SAndroid Build Coastguard Worker #if DEBUG_OBU_METADATA
1469*c0909341SAndroid Build Coastguard Worker             printf("MDCVOBU: max-luminance: %d [off=%td]\n",
1470*c0909341SAndroid Build Coastguard Worker                    mastering_display->max_luminance,
1471*c0909341SAndroid Build Coastguard Worker                    (gb.ptr - init_ptr) * 8 - gb.bits_left);
1472*c0909341SAndroid Build Coastguard Worker #endif
1473*c0909341SAndroid Build Coastguard Worker             mastering_display->min_luminance = dav1d_get_bits(&gb, 32);
1474*c0909341SAndroid Build Coastguard Worker #if DEBUG_OBU_METADATA
1475*c0909341SAndroid Build Coastguard Worker             printf("MDCVOBU: min-luminance: %d [off=%td]\n",
1476*c0909341SAndroid Build Coastguard Worker                    mastering_display->min_luminance,
1477*c0909341SAndroid Build Coastguard Worker                    (gb.ptr - init_ptr) * 8 - gb.bits_left);
1478*c0909341SAndroid Build Coastguard Worker #endif
1479*c0909341SAndroid Build Coastguard Worker             if (check_trailing_bits(&gb, c->strict_std_compliance) < 0) {
1480*c0909341SAndroid Build Coastguard Worker                 dav1d_ref_dec(&ref);
1481*c0909341SAndroid Build Coastguard Worker                 goto error;
1482*c0909341SAndroid Build Coastguard Worker             }
1483*c0909341SAndroid Build Coastguard Worker 
1484*c0909341SAndroid Build Coastguard Worker             dav1d_ref_dec(&c->mastering_display_ref);
1485*c0909341SAndroid Build Coastguard Worker             c->mastering_display = mastering_display;
1486*c0909341SAndroid Build Coastguard Worker             c->mastering_display_ref = ref;
1487*c0909341SAndroid Build Coastguard Worker             break;
1488*c0909341SAndroid Build Coastguard Worker         }
1489*c0909341SAndroid Build Coastguard Worker         case OBU_META_ITUT_T35: {
1490*c0909341SAndroid Build Coastguard Worker             ptrdiff_t payload_size = gb.ptr_end - gb.ptr;
1491*c0909341SAndroid Build Coastguard Worker             // Don't take into account all the trailing bits for payload_size
1492*c0909341SAndroid Build Coastguard Worker             while (payload_size > 0 && !gb.ptr[payload_size - 1])
1493*c0909341SAndroid Build Coastguard Worker                 payload_size--; // trailing_zero_bit x 8
1494*c0909341SAndroid Build Coastguard Worker             payload_size--; // trailing_one_bit + trailing_zero_bit x 7
1495*c0909341SAndroid Build Coastguard Worker 
1496*c0909341SAndroid Build Coastguard Worker             int country_code_extension_byte = 0;
1497*c0909341SAndroid Build Coastguard Worker             const int country_code = dav1d_get_bits(&gb, 8);
1498*c0909341SAndroid Build Coastguard Worker             payload_size--;
1499*c0909341SAndroid Build Coastguard Worker             if (country_code == 0xFF) {
1500*c0909341SAndroid Build Coastguard Worker                 country_code_extension_byte = dav1d_get_bits(&gb, 8);
1501*c0909341SAndroid Build Coastguard Worker                 payload_size--;
1502*c0909341SAndroid Build Coastguard Worker             }
1503*c0909341SAndroid Build Coastguard Worker 
1504*c0909341SAndroid Build Coastguard Worker             if (payload_size <= 0 || gb.ptr[payload_size] != 0x80) {
1505*c0909341SAndroid Build Coastguard Worker                 dav1d_log(c, "Malformed ITU-T T.35 metadata message format\n");
1506*c0909341SAndroid Build Coastguard Worker                 break;
1507*c0909341SAndroid Build Coastguard Worker             }
1508*c0909341SAndroid Build Coastguard Worker 
1509*c0909341SAndroid Build Coastguard Worker             if ((c->n_itut_t35 + 1) > INT_MAX / (int)sizeof(*c->itut_t35)) goto error;
1510*c0909341SAndroid Build Coastguard Worker             struct Dav1dITUTT35 *itut_t35 = dav1d_realloc(ALLOC_OBU_META, c->itut_t35,
1511*c0909341SAndroid Build Coastguard Worker                                                           (c->n_itut_t35 + 1) * sizeof(*c->itut_t35));
1512*c0909341SAndroid Build Coastguard Worker             if (!itut_t35) goto error;
1513*c0909341SAndroid Build Coastguard Worker             c->itut_t35 = itut_t35;
1514*c0909341SAndroid Build Coastguard Worker             memset(c->itut_t35 + c->n_itut_t35, 0, sizeof(*c->itut_t35));
1515*c0909341SAndroid Build Coastguard Worker 
1516*c0909341SAndroid Build Coastguard Worker             struct itut_t35_ctx_context *itut_t35_ctx;
1517*c0909341SAndroid Build Coastguard Worker             if (!c->n_itut_t35) {
1518*c0909341SAndroid Build Coastguard Worker                 assert(!c->itut_t35_ref);
1519*c0909341SAndroid Build Coastguard Worker                 itut_t35_ctx = dav1d_malloc(ALLOC_OBU_META, sizeof(struct itut_t35_ctx_context));
1520*c0909341SAndroid Build Coastguard Worker                 if (!itut_t35_ctx) goto error;
1521*c0909341SAndroid Build Coastguard Worker                 c->itut_t35_ref = dav1d_ref_init(&itut_t35_ctx->ref, c->itut_t35,
1522*c0909341SAndroid Build Coastguard Worker                                                  dav1d_picture_free_itut_t35, itut_t35_ctx, 0);
1523*c0909341SAndroid Build Coastguard Worker             } else {
1524*c0909341SAndroid Build Coastguard Worker                 assert(c->itut_t35_ref && atomic_load(&c->itut_t35_ref->ref_cnt) == 1);
1525*c0909341SAndroid Build Coastguard Worker                 itut_t35_ctx = c->itut_t35_ref->user_data;
1526*c0909341SAndroid Build Coastguard Worker                 c->itut_t35_ref->const_data = (uint8_t *)c->itut_t35;
1527*c0909341SAndroid Build Coastguard Worker             }
1528*c0909341SAndroid Build Coastguard Worker             itut_t35_ctx->itut_t35 = c->itut_t35;
1529*c0909341SAndroid Build Coastguard Worker             itut_t35_ctx->n_itut_t35 = c->n_itut_t35 + 1;
1530*c0909341SAndroid Build Coastguard Worker 
1531*c0909341SAndroid Build Coastguard Worker             Dav1dITUTT35 *const itut_t35_metadata = &c->itut_t35[c->n_itut_t35];
1532*c0909341SAndroid Build Coastguard Worker             itut_t35_metadata->payload = dav1d_malloc(ALLOC_OBU_META, payload_size);
1533*c0909341SAndroid Build Coastguard Worker             if (!itut_t35_metadata->payload) goto error;
1534*c0909341SAndroid Build Coastguard Worker 
1535*c0909341SAndroid Build Coastguard Worker             itut_t35_metadata->country_code = country_code;
1536*c0909341SAndroid Build Coastguard Worker             itut_t35_metadata->country_code_extension_byte = country_code_extension_byte;
1537*c0909341SAndroid Build Coastguard Worker             itut_t35_metadata->payload_size = payload_size;
1538*c0909341SAndroid Build Coastguard Worker 
1539*c0909341SAndroid Build Coastguard Worker             // We know that we've read a whole number of bytes and that the
1540*c0909341SAndroid Build Coastguard Worker             // payload is within the OBU boundaries, so just use memcpy()
1541*c0909341SAndroid Build Coastguard Worker             assert(gb.bits_left == 0);
1542*c0909341SAndroid Build Coastguard Worker             memcpy(itut_t35_metadata->payload, gb.ptr, payload_size);
1543*c0909341SAndroid Build Coastguard Worker 
1544*c0909341SAndroid Build Coastguard Worker             c->n_itut_t35++;
1545*c0909341SAndroid Build Coastguard Worker             break;
1546*c0909341SAndroid Build Coastguard Worker         }
1547*c0909341SAndroid Build Coastguard Worker         case OBU_META_SCALABILITY:
1548*c0909341SAndroid Build Coastguard Worker         case OBU_META_TIMECODE:
1549*c0909341SAndroid Build Coastguard Worker             // ignore metadata OBUs we don't care about
1550*c0909341SAndroid Build Coastguard Worker             break;
1551*c0909341SAndroid Build Coastguard Worker         default:
1552*c0909341SAndroid Build Coastguard Worker             // print a warning but don't fail for unknown types
1553*c0909341SAndroid Build Coastguard Worker             dav1d_log(c, "Unknown Metadata OBU type %d\n", meta_type);
1554*c0909341SAndroid Build Coastguard Worker             break;
1555*c0909341SAndroid Build Coastguard Worker         }
1556*c0909341SAndroid Build Coastguard Worker 
1557*c0909341SAndroid Build Coastguard Worker         break;
1558*c0909341SAndroid Build Coastguard Worker     }
1559*c0909341SAndroid Build Coastguard Worker     case DAV1D_OBU_TD:
1560*c0909341SAndroid Build Coastguard Worker         c->frame_flags |= PICTURE_FLAG_NEW_TEMPORAL_UNIT;
1561*c0909341SAndroid Build Coastguard Worker         break;
1562*c0909341SAndroid Build Coastguard Worker     case DAV1D_OBU_PADDING:
1563*c0909341SAndroid Build Coastguard Worker         // ignore OBUs we don't care about
1564*c0909341SAndroid Build Coastguard Worker         break;
1565*c0909341SAndroid Build Coastguard Worker     default:
1566*c0909341SAndroid Build Coastguard Worker         // print a warning but don't fail for unknown types
1567*c0909341SAndroid Build Coastguard Worker         dav1d_log(c, "Unknown OBU type %d of size %td\n", type, gb.ptr_end - gb.ptr);
1568*c0909341SAndroid Build Coastguard Worker         break;
1569*c0909341SAndroid Build Coastguard Worker     }
1570*c0909341SAndroid Build Coastguard Worker 
1571*c0909341SAndroid Build Coastguard Worker     if (c->seq_hdr && c->frame_hdr) {
1572*c0909341SAndroid Build Coastguard Worker         if (c->frame_hdr->show_existing_frame) {
1573*c0909341SAndroid Build Coastguard Worker             if (!c->refs[c->frame_hdr->existing_frame_idx].p.p.frame_hdr) goto error;
1574*c0909341SAndroid Build Coastguard Worker             switch (c->refs[c->frame_hdr->existing_frame_idx].p.p.frame_hdr->frame_type) {
1575*c0909341SAndroid Build Coastguard Worker             case DAV1D_FRAME_TYPE_INTER:
1576*c0909341SAndroid Build Coastguard Worker             case DAV1D_FRAME_TYPE_SWITCH:
1577*c0909341SAndroid Build Coastguard Worker                 if (c->decode_frame_type > DAV1D_DECODEFRAMETYPE_REFERENCE)
1578*c0909341SAndroid Build Coastguard Worker                     goto skip;
1579*c0909341SAndroid Build Coastguard Worker                 break;
1580*c0909341SAndroid Build Coastguard Worker             case DAV1D_FRAME_TYPE_INTRA:
1581*c0909341SAndroid Build Coastguard Worker                 if (c->decode_frame_type > DAV1D_DECODEFRAMETYPE_INTRA)
1582*c0909341SAndroid Build Coastguard Worker                     goto skip;
1583*c0909341SAndroid Build Coastguard Worker                 // fall-through
1584*c0909341SAndroid Build Coastguard Worker             default:
1585*c0909341SAndroid Build Coastguard Worker                 break;
1586*c0909341SAndroid Build Coastguard Worker             }
1587*c0909341SAndroid Build Coastguard Worker             if (!c->refs[c->frame_hdr->existing_frame_idx].p.p.data[0]) goto error;
1588*c0909341SAndroid Build Coastguard Worker             if (c->strict_std_compliance &&
1589*c0909341SAndroid Build Coastguard Worker                 !c->refs[c->frame_hdr->existing_frame_idx].p.showable)
1590*c0909341SAndroid Build Coastguard Worker             {
1591*c0909341SAndroid Build Coastguard Worker                 goto error;
1592*c0909341SAndroid Build Coastguard Worker             }
1593*c0909341SAndroid Build Coastguard Worker             if (c->n_fc == 1) {
1594*c0909341SAndroid Build Coastguard Worker                 dav1d_thread_picture_ref(&c->out,
1595*c0909341SAndroid Build Coastguard Worker                                          &c->refs[c->frame_hdr->existing_frame_idx].p);
1596*c0909341SAndroid Build Coastguard Worker                 dav1d_picture_copy_props(&c->out.p,
1597*c0909341SAndroid Build Coastguard Worker                                          c->content_light, c->content_light_ref,
1598*c0909341SAndroid Build Coastguard Worker                                          c->mastering_display, c->mastering_display_ref,
1599*c0909341SAndroid Build Coastguard Worker                                          c->itut_t35, c->itut_t35_ref, c->n_itut_t35,
1600*c0909341SAndroid Build Coastguard Worker                                          &in->m);
1601*c0909341SAndroid Build Coastguard Worker                 // Must be removed from the context after being attached to the frame
1602*c0909341SAndroid Build Coastguard Worker                 dav1d_ref_dec(&c->itut_t35_ref);
1603*c0909341SAndroid Build Coastguard Worker                 c->itut_t35 = NULL;
1604*c0909341SAndroid Build Coastguard Worker                 c->n_itut_t35 = 0;
1605*c0909341SAndroid Build Coastguard Worker                 c->event_flags |= dav1d_picture_get_event_flags(&c->refs[c->frame_hdr->existing_frame_idx].p);
1606*c0909341SAndroid Build Coastguard Worker             } else {
1607*c0909341SAndroid Build Coastguard Worker                 pthread_mutex_lock(&c->task_thread.lock);
1608*c0909341SAndroid Build Coastguard Worker                 // need to append this to the frame output queue
1609*c0909341SAndroid Build Coastguard Worker                 const unsigned next = c->frame_thread.next++;
1610*c0909341SAndroid Build Coastguard Worker                 if (c->frame_thread.next == c->n_fc)
1611*c0909341SAndroid Build Coastguard Worker                     c->frame_thread.next = 0;
1612*c0909341SAndroid Build Coastguard Worker 
1613*c0909341SAndroid Build Coastguard Worker                 Dav1dFrameContext *const f = &c->fc[next];
1614*c0909341SAndroid Build Coastguard Worker                 while (f->n_tile_data > 0)
1615*c0909341SAndroid Build Coastguard Worker                     pthread_cond_wait(&f->task_thread.cond,
1616*c0909341SAndroid Build Coastguard Worker                                       &f->task_thread.ttd->lock);
1617*c0909341SAndroid Build Coastguard Worker                 Dav1dThreadPicture *const out_delayed =
1618*c0909341SAndroid Build Coastguard Worker                     &c->frame_thread.out_delayed[next];
1619*c0909341SAndroid Build Coastguard Worker                 if (out_delayed->p.data[0] || atomic_load(&f->task_thread.error)) {
1620*c0909341SAndroid Build Coastguard Worker                     unsigned first = atomic_load(&c->task_thread.first);
1621*c0909341SAndroid Build Coastguard Worker                     if (first + 1U < c->n_fc)
1622*c0909341SAndroid Build Coastguard Worker                         atomic_fetch_add(&c->task_thread.first, 1U);
1623*c0909341SAndroid Build Coastguard Worker                     else
1624*c0909341SAndroid Build Coastguard Worker                         atomic_store(&c->task_thread.first, 0);
1625*c0909341SAndroid Build Coastguard Worker                     atomic_compare_exchange_strong(&c->task_thread.reset_task_cur,
1626*c0909341SAndroid Build Coastguard Worker                                                    &first, UINT_MAX);
1627*c0909341SAndroid Build Coastguard Worker                     if (c->task_thread.cur && c->task_thread.cur < c->n_fc)
1628*c0909341SAndroid Build Coastguard Worker                         c->task_thread.cur--;
1629*c0909341SAndroid Build Coastguard Worker                 }
1630*c0909341SAndroid Build Coastguard Worker                 const int error = f->task_thread.retval;
1631*c0909341SAndroid Build Coastguard Worker                 if (error) {
1632*c0909341SAndroid Build Coastguard Worker                     c->cached_error = error;
1633*c0909341SAndroid Build Coastguard Worker                     f->task_thread.retval = 0;
1634*c0909341SAndroid Build Coastguard Worker                     dav1d_data_props_copy(&c->cached_error_props, &out_delayed->p.m);
1635*c0909341SAndroid Build Coastguard Worker                     dav1d_thread_picture_unref(out_delayed);
1636*c0909341SAndroid Build Coastguard Worker                 } else if (out_delayed->p.data[0]) {
1637*c0909341SAndroid Build Coastguard Worker                     const unsigned progress = atomic_load_explicit(&out_delayed->progress[1],
1638*c0909341SAndroid Build Coastguard Worker                                                                    memory_order_relaxed);
1639*c0909341SAndroid Build Coastguard Worker                     if ((out_delayed->visible || c->output_invisible_frames) &&
1640*c0909341SAndroid Build Coastguard Worker                         progress != FRAME_ERROR)
1641*c0909341SAndroid Build Coastguard Worker                     {
1642*c0909341SAndroid Build Coastguard Worker                         dav1d_thread_picture_ref(&c->out, out_delayed);
1643*c0909341SAndroid Build Coastguard Worker                         c->event_flags |= dav1d_picture_get_event_flags(out_delayed);
1644*c0909341SAndroid Build Coastguard Worker                     }
1645*c0909341SAndroid Build Coastguard Worker                     dav1d_thread_picture_unref(out_delayed);
1646*c0909341SAndroid Build Coastguard Worker                 }
1647*c0909341SAndroid Build Coastguard Worker                 dav1d_thread_picture_ref(out_delayed,
1648*c0909341SAndroid Build Coastguard Worker                                          &c->refs[c->frame_hdr->existing_frame_idx].p);
1649*c0909341SAndroid Build Coastguard Worker                 out_delayed->visible = 1;
1650*c0909341SAndroid Build Coastguard Worker                 dav1d_picture_copy_props(&out_delayed->p,
1651*c0909341SAndroid Build Coastguard Worker                                          c->content_light, c->content_light_ref,
1652*c0909341SAndroid Build Coastguard Worker                                          c->mastering_display, c->mastering_display_ref,
1653*c0909341SAndroid Build Coastguard Worker                                          c->itut_t35, c->itut_t35_ref, c->n_itut_t35,
1654*c0909341SAndroid Build Coastguard Worker                                          &in->m);
1655*c0909341SAndroid Build Coastguard Worker                 // Must be removed from the context after being attached to the frame
1656*c0909341SAndroid Build Coastguard Worker                 dav1d_ref_dec(&c->itut_t35_ref);
1657*c0909341SAndroid Build Coastguard Worker                 c->itut_t35 = NULL;
1658*c0909341SAndroid Build Coastguard Worker                 c->n_itut_t35 = 0;
1659*c0909341SAndroid Build Coastguard Worker 
1660*c0909341SAndroid Build Coastguard Worker                 pthread_mutex_unlock(&c->task_thread.lock);
1661*c0909341SAndroid Build Coastguard Worker             }
1662*c0909341SAndroid Build Coastguard Worker             if (c->refs[c->frame_hdr->existing_frame_idx].p.p.frame_hdr->frame_type == DAV1D_FRAME_TYPE_KEY) {
1663*c0909341SAndroid Build Coastguard Worker                 const int r = c->frame_hdr->existing_frame_idx;
1664*c0909341SAndroid Build Coastguard Worker                 c->refs[r].p.showable = 0;
1665*c0909341SAndroid Build Coastguard Worker                 for (int i = 0; i < 8; i++) {
1666*c0909341SAndroid Build Coastguard Worker                     if (i == r) continue;
1667*c0909341SAndroid Build Coastguard Worker 
1668*c0909341SAndroid Build Coastguard Worker                     if (c->refs[i].p.p.frame_hdr)
1669*c0909341SAndroid Build Coastguard Worker                         dav1d_thread_picture_unref(&c->refs[i].p);
1670*c0909341SAndroid Build Coastguard Worker                     dav1d_thread_picture_ref(&c->refs[i].p, &c->refs[r].p);
1671*c0909341SAndroid Build Coastguard Worker 
1672*c0909341SAndroid Build Coastguard Worker                     dav1d_cdf_thread_unref(&c->cdf[i]);
1673*c0909341SAndroid Build Coastguard Worker                     dav1d_cdf_thread_ref(&c->cdf[i], &c->cdf[r]);
1674*c0909341SAndroid Build Coastguard Worker 
1675*c0909341SAndroid Build Coastguard Worker                     dav1d_ref_dec(&c->refs[i].segmap);
1676*c0909341SAndroid Build Coastguard Worker                     c->refs[i].segmap = c->refs[r].segmap;
1677*c0909341SAndroid Build Coastguard Worker                     if (c->refs[r].segmap)
1678*c0909341SAndroid Build Coastguard Worker                         dav1d_ref_inc(c->refs[r].segmap);
1679*c0909341SAndroid Build Coastguard Worker                     dav1d_ref_dec(&c->refs[i].refmvs);
1680*c0909341SAndroid Build Coastguard Worker                 }
1681*c0909341SAndroid Build Coastguard Worker             }
1682*c0909341SAndroid Build Coastguard Worker             c->frame_hdr = NULL;
1683*c0909341SAndroid Build Coastguard Worker         } else if (c->n_tiles == c->frame_hdr->tiling.cols * c->frame_hdr->tiling.rows) {
1684*c0909341SAndroid Build Coastguard Worker             switch (c->frame_hdr->frame_type) {
1685*c0909341SAndroid Build Coastguard Worker             case DAV1D_FRAME_TYPE_INTER:
1686*c0909341SAndroid Build Coastguard Worker             case DAV1D_FRAME_TYPE_SWITCH:
1687*c0909341SAndroid Build Coastguard Worker                 if (c->decode_frame_type > DAV1D_DECODEFRAMETYPE_REFERENCE ||
1688*c0909341SAndroid Build Coastguard Worker                     (c->decode_frame_type == DAV1D_DECODEFRAMETYPE_REFERENCE &&
1689*c0909341SAndroid Build Coastguard Worker                      !c->frame_hdr->refresh_frame_flags))
1690*c0909341SAndroid Build Coastguard Worker                     goto skip;
1691*c0909341SAndroid Build Coastguard Worker                 break;
1692*c0909341SAndroid Build Coastguard Worker             case DAV1D_FRAME_TYPE_INTRA:
1693*c0909341SAndroid Build Coastguard Worker                 if (c->decode_frame_type > DAV1D_DECODEFRAMETYPE_INTRA ||
1694*c0909341SAndroid Build Coastguard Worker                     (c->decode_frame_type == DAV1D_DECODEFRAMETYPE_REFERENCE &&
1695*c0909341SAndroid Build Coastguard Worker                      !c->frame_hdr->refresh_frame_flags))
1696*c0909341SAndroid Build Coastguard Worker                     goto skip;
1697*c0909341SAndroid Build Coastguard Worker                 // fall-through
1698*c0909341SAndroid Build Coastguard Worker             default:
1699*c0909341SAndroid Build Coastguard Worker                 break;
1700*c0909341SAndroid Build Coastguard Worker             }
1701*c0909341SAndroid Build Coastguard Worker             if (!c->n_tile_data)
1702*c0909341SAndroid Build Coastguard Worker                 goto error;
1703*c0909341SAndroid Build Coastguard Worker             if ((res = dav1d_submit_frame(c)) < 0)
1704*c0909341SAndroid Build Coastguard Worker                 return res;
1705*c0909341SAndroid Build Coastguard Worker             assert(!c->n_tile_data);
1706*c0909341SAndroid Build Coastguard Worker             c->frame_hdr = NULL;
1707*c0909341SAndroid Build Coastguard Worker             c->n_tiles = 0;
1708*c0909341SAndroid Build Coastguard Worker         }
1709*c0909341SAndroid Build Coastguard Worker     }
1710*c0909341SAndroid Build Coastguard Worker 
1711*c0909341SAndroid Build Coastguard Worker     return gb.ptr_end - gb.ptr_start;
1712*c0909341SAndroid Build Coastguard Worker 
1713*c0909341SAndroid Build Coastguard Worker skip:
1714*c0909341SAndroid Build Coastguard Worker     // update refs with only the headers in case we skip the frame
1715*c0909341SAndroid Build Coastguard Worker     for (int i = 0; i < 8; i++) {
1716*c0909341SAndroid Build Coastguard Worker         if (c->frame_hdr->refresh_frame_flags & (1 << i)) {
1717*c0909341SAndroid Build Coastguard Worker             dav1d_thread_picture_unref(&c->refs[i].p);
1718*c0909341SAndroid Build Coastguard Worker             c->refs[i].p.p.frame_hdr = c->frame_hdr;
1719*c0909341SAndroid Build Coastguard Worker             c->refs[i].p.p.seq_hdr = c->seq_hdr;
1720*c0909341SAndroid Build Coastguard Worker             c->refs[i].p.p.frame_hdr_ref = c->frame_hdr_ref;
1721*c0909341SAndroid Build Coastguard Worker             c->refs[i].p.p.seq_hdr_ref = c->seq_hdr_ref;
1722*c0909341SAndroid Build Coastguard Worker             dav1d_ref_inc(c->frame_hdr_ref);
1723*c0909341SAndroid Build Coastguard Worker             dav1d_ref_inc(c->seq_hdr_ref);
1724*c0909341SAndroid Build Coastguard Worker         }
1725*c0909341SAndroid Build Coastguard Worker     }
1726*c0909341SAndroid Build Coastguard Worker 
1727*c0909341SAndroid Build Coastguard Worker     dav1d_ref_dec(&c->frame_hdr_ref);
1728*c0909341SAndroid Build Coastguard Worker     c->frame_hdr = NULL;
1729*c0909341SAndroid Build Coastguard Worker     c->n_tiles = 0;
1730*c0909341SAndroid Build Coastguard Worker 
1731*c0909341SAndroid Build Coastguard Worker     return gb.ptr_end - gb.ptr_start;
1732*c0909341SAndroid Build Coastguard Worker 
1733*c0909341SAndroid Build Coastguard Worker error:
1734*c0909341SAndroid Build Coastguard Worker     dav1d_data_props_copy(&c->cached_error_props, &in->m);
1735*c0909341SAndroid Build Coastguard Worker     dav1d_log(c, gb.error ? "Overrun in OBU bit buffer\n" :
1736*c0909341SAndroid Build Coastguard Worker                             "Error parsing OBU data\n");
1737*c0909341SAndroid Build Coastguard Worker     return DAV1D_ERR(EINVAL);
1738*c0909341SAndroid Build Coastguard Worker }
1739