xref: /aosp_15_r20/external/intel-media-driver/media_driver/linux/common/codec/ddi/media_libvpx_vp9.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2017, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     media_libvpx_vp9.cpp
24 //! \brief    Defines the VP9 structure/function that is from libvpx
25 //!
26 
27 /*
28  * This file defines some functions related with vp9 enc, and
29  * they are ported from libvpx (https://github.com/webmproject/libvpx/).
30  * The original copyright and licence statement as below.
31  */
32 
33 /*
34  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
35  *
36  *  Use of this source code is governed by a BSD-style license
37  *  that can be found in the media_libvpx.LICENSE file in the root of the source
38  *  tree. An additional intellectual property rights grant can be found
39  *  in the file media_libvpx.PATENTS.  All contributing project authors may
40  *  be found in the media_libvpx.AUTHORS file in the root of the source tree.
41  */
42 
43 #include <stdio.h>
44 #include <stdint.h>
45 #include "media_libva_encoder.h"
46 #include "media_libvpx_vp9.h"
47 
48 struct vp9_write_bit_buffer {
49     uint8_t *bit_buffer;
50     int bit_offset;
51 };
52 
53 static
vp9_wb_write_bit(struct vp9_write_bit_buffer * wb,int bit)54 void vp9_wb_write_bit(struct vp9_write_bit_buffer *wb, int bit)
55 {
56     const int off = wb->bit_offset;
57     const int p = off / 8;
58     const int q = 7 - off % 8;
59 
60     if (q == 7)
61     {
62         wb->bit_buffer[p] = bit << q;
63     }
64     else
65     {
66         wb->bit_buffer[p] &= ~(1 << q);
67         wb->bit_buffer[p] |= bit << q;
68     }
69     wb->bit_offset = off + 1;
70 }
71 
72 static
vp9_wb_write_literal(struct vp9_write_bit_buffer * wb,int data,int bits)73 void vp9_wb_write_literal(struct vp9_write_bit_buffer *wb, int data, int bits)
74 {
75     int bit;
76     for (bit = bits - 1; bit >= 0; bit--)
77         vp9_wb_write_bit(wb, (data >> bit) & 1);
78 }
79 
80 static
write_bitdepth_colorspace_sampling(uint32_t codecProfile,struct vp9_write_bit_buffer * wb)81 void write_bitdepth_colorspace_sampling(uint32_t codecProfile,
82                                         struct vp9_write_bit_buffer *wb)
83 {
84 
85     if (codecProfile >= VP9_PROFILE_2)
86     {
87         /* Profile 2 can support 10/12 bits */
88         /* Currently it is 10 bits */
89         vp9_wb_write_literal(wb, 0, 1);
90     }
91 
92     /* Add the default color-space */
93     vp9_wb_write_literal(wb, 0, 3);
94     vp9_wb_write_bit(wb, 0);  // 0: [16, 235] (i.e. xvYCC), 1: [0, 255]
95 
96     if ((codecProfile == VP9_PROFILE_1) ||
97         (codecProfile == VP9_PROFILE_3))
98     {
99         /* sub_sampling_x/y */
100         /* Currently the sub_sampling_x = 0, sub_sampling_y = 0 */
101         vp9_wb_write_bit(wb, 0);
102         vp9_wb_write_bit(wb, 0);
103         vp9_wb_write_bit(wb, 0); // unused
104     }
105 }
106 
107 #define    MAX_TILE_WIDTH_B64    64
108 #define    MIN_TILE_WIDTH_B64    4
109 
get_min_log2_tile_cols(const int sb_cols)110 static int get_min_log2_tile_cols(const int sb_cols)
111 {
112     int min_log2 = 0;
113 
114     while ((MAX_TILE_WIDTH_B64 << min_log2) < sb_cols)
115         ++min_log2;
116 
117     return min_log2;
118 }
119 
get_max_log2_tile_cols(const int sb_cols)120 static int get_max_log2_tile_cols(const int sb_cols)
121 {
122     int max_log2 = 1;
123 
124     while ((sb_cols >> max_log2) >= MIN_TILE_WIDTH_B64)
125         ++max_log2;
126 
127     return max_log2 - 1;
128 }
129 
Vp9WriteUncompressHeader(struct _DDI_ENCODE_CONTEXT * ddiEncContext,uint32_t codecProfile,uint8_t * headerData,uint32_t * headerLen,vp9_header_bitoffset * headerBitoffset)130 bool Vp9WriteUncompressHeader(struct _DDI_ENCODE_CONTEXT *ddiEncContext,
131                                 uint32_t codecProfile,
132                                 uint8_t  *headerData,
133                                 uint32_t *headerLen,
134                                 vp9_header_bitoffset *headerBitoffset)
135 {
136 #define    VP9_SYNC_CODE_0    0x49
137 #define    VP9_SYNC_CODE_1    0x83
138 #define    VP9_SYNC_CODE_2    0x42
139 
140 #define    VP9_FRAME_MARKER   0x2
141 
142 #define    REFS_PER_FRAME     3
143 
144 #define    REF_FRAMES_LOG2    3
145 #define    REF_FRAMES         (1 << REF_FRAMES_LOG2)
146 
147 #define    VP9_KEY_FRAME      0
148 
149     if ((ddiEncContext == nullptr) ||
150         (headerData == nullptr) ||
151         (headerLen == nullptr) ||
152         (headerBitoffset == nullptr))
153         return false;
154 
155     CODEC_VP9_ENCODE_PIC_PARAMS *picParam = (CODEC_VP9_ENCODE_PIC_PARAMS *)ddiEncContext->pPicParams;
156     CODEC_VP9_ENCODE_SEGMENT_PARAMS *segParams = (CODEC_VP9_ENCODE_SEGMENT_PARAMS *)ddiEncContext->pVpxSegParams;
157 
158     if (picParam == nullptr)
159         return false;
160 
161     struct vp9_write_bit_buffer *wb, vp9_wb;
162 
163     memset(headerBitoffset, 0, sizeof(vp9_header_bitoffset));
164 
165     vp9_wb.bit_buffer = (uint8_t *)headerData;
166     vp9_wb.bit_offset = 0;
167     wb = &vp9_wb;
168     vp9_wb_write_literal(wb, VP9_FRAME_MARKER, 2);
169 
170     /* Only Profile0/1/2/3 is supported */
171     if (codecProfile > VP9_PROFILE_3)
172         codecProfile = VP9_PROFILE_0;
173 
174     switch(codecProfile)
175     {
176     case VP9_PROFILE_0:
177         //Profile 0
178         vp9_wb_write_literal(wb, 0, 2);
179         break;
180     case VP9_PROFILE_1:
181         //Profile 1
182         vp9_wb_write_literal(wb, 2, 2);
183         break;
184     case VP9_PROFILE_2:
185         //Profile 2
186         vp9_wb_write_literal(wb, 1, 2);
187         break;
188     case VP9_PROFILE_3:
189         vp9_wb_write_literal(wb, 6, 3);
190         break;
191     default:
192         break;
193     }
194 
195     vp9_wb_write_bit(wb, 0);  // show_existing_frame
196     vp9_wb_write_bit(wb, picParam->PicFlags.fields.frame_type);
197     vp9_wb_write_bit(wb, picParam->PicFlags.fields.show_frame);
198     vp9_wb_write_bit(wb, picParam->PicFlags.fields.error_resilient_mode);
199 
200     if (picParam->PicFlags.fields.frame_type == VP9_KEY_FRAME)
201     {
202         vp9_wb_write_literal(wb, VP9_SYNC_CODE_0, 8);
203         vp9_wb_write_literal(wb, VP9_SYNC_CODE_1, 8);
204         vp9_wb_write_literal(wb, VP9_SYNC_CODE_2, 8);
205 
206         write_bitdepth_colorspace_sampling(codecProfile, wb);
207 
208         /* write the encoded frame size */
209         vp9_wb_write_literal(wb, picParam->DstFrameWidthMinus1, 16);
210         vp9_wb_write_literal(wb, picParam->DstFrameHeightMinus1, 16);
211         /* write display size */
212         if ((picParam->DstFrameWidthMinus1 != picParam->SrcFrameWidthMinus1) ||
213             (picParam->DstFrameHeightMinus1 != picParam->SrcFrameHeightMinus1))
214         {
215             vp9_wb_write_bit(wb, 1);
216             vp9_wb_write_literal(wb, picParam->SrcFrameWidthMinus1, 16);
217             vp9_wb_write_literal(wb, picParam->SrcFrameHeightMinus1, 16);
218         }
219         else
220         {
221             vp9_wb_write_bit(wb, 0);
222         }
223     }
224     else
225     {
226         /* for the non-Key frame */
227         if (!picParam->PicFlags.fields.show_frame)
228         {
229             vp9_wb_write_bit(wb, picParam->PicFlags.fields.intra_only);
230         }
231 
232         if (!picParam->PicFlags.fields.error_resilient_mode)
233         {
234             vp9_wb_write_literal(wb, picParam->PicFlags.fields.reset_frame_context, 2);
235         }
236 
237         if (picParam->PicFlags.fields.intra_only)
238         {
239             vp9_wb_write_literal(wb, VP9_SYNC_CODE_0, 8);
240             vp9_wb_write_literal(wb, VP9_SYNC_CODE_1, 8);
241             vp9_wb_write_literal(wb, VP9_SYNC_CODE_2, 8);
242 
243             /* Add the bit_depth for VP9Profile1/2/3 */
244             if (codecProfile)
245                 write_bitdepth_colorspace_sampling(codecProfile, wb);
246 
247             /* write the refreshed_frame_flags */
248             vp9_wb_write_literal(wb, picParam->RefFlags.fields.refresh_frame_flags, REF_FRAMES);
249             /* write the encoded frame size */
250             vp9_wb_write_literal(wb, picParam->DstFrameWidthMinus1, 16);
251             vp9_wb_write_literal(wb, picParam->DstFrameHeightMinus1, 16);
252             /* write display size */
253             if ((picParam->DstFrameWidthMinus1 != picParam->SrcFrameWidthMinus1) ||
254                 (picParam->DstFrameHeightMinus1 != picParam->SrcFrameHeightMinus1))
255             {
256                 vp9_wb_write_bit(wb, 1);
257                 vp9_wb_write_literal(wb, picParam->SrcFrameWidthMinus1, 16);
258                 vp9_wb_write_literal(wb, picParam->SrcFrameHeightMinus1, 16);
259             }
260             else
261             {
262                 vp9_wb_write_bit(wb, 0);
263             }
264         }
265         else
266         {
267             /* The refresh_frame_map is  for the next frame so that it can select Last/Godlen/Alt ref_index */
268             /*
269             if ((picParam->RefFlags.fields.ref_frame_ctrl_l0) & (1 << 0))
270                 refresh_flags = 1 << picParam->RefFlags.fields.ref_last_idx;
271             if ((picParam->RefFlags.fields.ref_frame_ctrl_l0) & (1 << 0))
272                 refresh_flags = 1 << picParam->RefFlags.fields.ref_last_idx;
273             if ((picParam->RefFlags.fields.ref_frame_ctrl_l0) & (1 << 0))
274                 refresh_flags = 1 << picParam->RefFlags.fields.ref_last_idx;
275             */
276             vp9_wb_write_literal(wb, picParam->RefFlags.fields.refresh_frame_flags, REF_FRAMES);
277 
278             vp9_wb_write_literal(wb, picParam->RefFlags.fields.LastRefIdx, REF_FRAMES_LOG2);
279             vp9_wb_write_bit(wb, picParam->RefFlags.fields.LastRefSignBias);
280             vp9_wb_write_literal(wb, picParam->RefFlags.fields.GoldenRefIdx, REF_FRAMES_LOG2);
281             vp9_wb_write_bit(wb, picParam->RefFlags.fields.GoldenRefSignBias);
282             vp9_wb_write_literal(wb, picParam->RefFlags.fields.AltRefIdx, REF_FRAMES_LOG2);
283             vp9_wb_write_bit(wb, picParam->RefFlags.fields.AltRefSignBias);
284 
285             /* write three bits with zero so that it can parse width/height directly */
286             vp9_wb_write_literal(wb, 0, 3);
287             vp9_wb_write_literal(wb, picParam->DstFrameWidthMinus1, 16);
288             vp9_wb_write_literal(wb, picParam->DstFrameHeightMinus1, 16);
289 
290             /* write display size */
291             if ((picParam->DstFrameWidthMinus1 != picParam->SrcFrameWidthMinus1) ||
292                 (picParam->DstFrameHeightMinus1 != picParam->SrcFrameHeightMinus1))
293             {
294                 vp9_wb_write_bit(wb, 1);
295                 vp9_wb_write_literal(wb, picParam->SrcFrameWidthMinus1, 16);
296                 vp9_wb_write_literal(wb, picParam->SrcFrameHeightMinus1, 16);
297             }
298             else
299             {
300                 vp9_wb_write_bit(wb, 0);
301             }
302 
303             vp9_wb_write_bit(wb, picParam->PicFlags.fields.allow_high_precision_mv);
304 
305 #define    SWITCHABLE_FILTER    4
306 #define    FILTER_MASK          3
307 
308             if (picParam->PicFlags.fields.mcomp_filter_type == SWITCHABLE_FILTER)
309             {
310                 vp9_wb_write_bit(wb, 1);
311             }
312             else
313             {
314                 const int filter_to_literal[4] = { 1, 0, 2, 3 };
315                 uint8_t filter_flag = picParam->PicFlags.fields.mcomp_filter_type;
316                 filter_flag = filter_flag & FILTER_MASK;
317                 vp9_wb_write_bit(wb, 0);
318                 vp9_wb_write_literal(wb, filter_to_literal[filter_flag], 2);
319             }
320         }
321     }
322 
323     /* write refresh_frame_context/paralle frame_decoding */
324     if (!picParam->PicFlags.fields.error_resilient_mode)
325     {
326         vp9_wb_write_bit(wb, picParam->PicFlags.fields.refresh_frame_context);
327         vp9_wb_write_bit(wb, picParam->PicFlags.fields.frame_parallel_decoding_mode);
328     }
329 
330     vp9_wb_write_literal(wb, picParam->PicFlags.fields.frame_context_idx, 2);
331 
332     /* write loop filter */
333     headerBitoffset->bit_offset_lf_level = wb->bit_offset;
334     vp9_wb_write_literal(wb, picParam->filter_level, 6);
335     vp9_wb_write_literal(wb, picParam->sharpness_level, 3);
336 
337     {
338         int i, mode_flag;
339 
340         vp9_wb_write_bit(wb, 1);
341         vp9_wb_write_bit(wb, 1);
342         headerBitoffset->bit_offset_ref_lf_delta = wb->bit_offset;
343         for (i = 0; i < 4; i++)
344         {
345             /*
346              * This check is skipped to prepare the bit_offset_lf_ref
347             if (picParam->LFRefDelta[i] == 0) {
348                 vp9_wb_write_bit(wb, 0);
349                 continue;
350             }
351              */
352             vp9_wb_write_bit(wb, 1);
353             mode_flag = picParam->LFRefDelta[i];
354             if (mode_flag >= 0)
355             {
356                 vp9_wb_write_literal(wb, mode_flag & (0x3F), 6);
357                 vp9_wb_write_bit(wb, 0);
358             }
359             else
360             {
361                 mode_flag = -mode_flag;
362                 vp9_wb_write_literal(wb, mode_flag & (0x3F), 6);
363                 vp9_wb_write_bit(wb, 1);
364             }
365         }
366 
367         headerBitoffset->bit_offset_mode_lf_delta = wb->bit_offset;
368         for (i = 0; i < 2; i++)
369         {
370             /*
371              * This check is skipped to prepare the bit_offset_lf_mode
372             if (picParam->LFModeDelta[i] == 0) {
373                 vp9_wb_write_bit(wb, 0);
374                 continue;
375             }
376              */
377             vp9_wb_write_bit(wb, 1);
378             mode_flag = picParam->LFRefDelta[i];
379             if (mode_flag >= 0)
380             {
381                 vp9_wb_write_literal(wb, mode_flag & (0x3F), 6);
382                 vp9_wb_write_bit(wb, 0);
383             }
384             else
385             {
386                 mode_flag = -mode_flag;
387                 vp9_wb_write_literal(wb, mode_flag & (0x3F), 6);
388                 vp9_wb_write_bit(wb, 1);
389             }
390         }
391     }
392 
393     /* write basic quantizer */
394     headerBitoffset->bit_offset_qindex = wb->bit_offset;
395     vp9_wb_write_literal(wb, picParam->LumaACQIndex, 8);
396     if (picParam->LumaDCQIndexDelta)
397     {
398         int delta_q = picParam->LumaDCQIndexDelta;
399         vp9_wb_write_bit(wb, 1);
400         vp9_wb_write_literal(wb, abs(delta_q), 4);
401         vp9_wb_write_bit(wb, delta_q < 0);
402     }
403     else
404     {
405         vp9_wb_write_bit(wb, 0);
406     }
407 
408     if (picParam->ChromaDCQIndexDelta)
409     {
410         int delta_q = picParam->ChromaDCQIndexDelta;
411         vp9_wb_write_bit(wb, 1);
412         vp9_wb_write_literal(wb, abs(delta_q), 4);
413         vp9_wb_write_bit(wb, delta_q < 0);
414     }
415     else
416     {
417         vp9_wb_write_bit(wb, 0);
418     }
419 
420     if (picParam->ChromaACQIndexDelta)
421     {
422         int delta_q = picParam->ChromaACQIndexDelta;
423         vp9_wb_write_bit(wb, 1);
424         vp9_wb_write_literal(wb, abs(delta_q), 4);
425         vp9_wb_write_bit(wb, delta_q < 0);
426     }
427     else
428     {
429         vp9_wb_write_bit(wb, 0);
430     }
431 
432     headerBitoffset->bit_offset_segmentation = wb->bit_offset;
433     vp9_wb_write_bit(wb, picParam->PicFlags.fields.segmentation_enabled);
434     if (picParam->PicFlags.fields.segmentation_enabled)
435     {
436         // Segmentation syntax will be filled by HW, need leave dummy here.
437         vp9_wb_write_bit(wb, 0);
438         vp9_wb_write_bit(wb, 0);
439     }
440     headerBitoffset->bit_size_segmentation = wb->bit_offset - headerBitoffset->bit_offset_segmentation;
441 
442     /* write tile info */
443     {
444         int sb_cols = (picParam->DstFrameWidthMinus1 + 64) / 64;
445         int min_log2_tile_cols, max_log2_tile_cols;
446         int col_data;
447 
448         /* write tile column info */
449         min_log2_tile_cols = get_min_log2_tile_cols(sb_cols);
450         max_log2_tile_cols = get_max_log2_tile_cols(sb_cols);
451 
452         col_data = picParam->log2_tile_columns - min_log2_tile_cols;
453         while (col_data--)
454         {
455             vp9_wb_write_bit(wb, 1);
456         }
457         if (picParam->log2_tile_columns < max_log2_tile_cols)
458         {
459             vp9_wb_write_bit(wb, 0);
460         }
461 
462         /* write tile row info */
463         vp9_wb_write_bit(wb, picParam->log2_tile_rows);
464         if (picParam->log2_tile_rows)
465         {
466             vp9_wb_write_bit(wb, (picParam->log2_tile_rows != 1));
467         }
468     }
469 
470     /* get the bit_offset of the first partition size */
471     headerBitoffset->bit_offset_first_partition_size = wb->bit_offset;
472 
473     /* reserve the space for writing the first partitions ize */
474     vp9_wb_write_literal(wb, 0, 16);
475 
476     *headerLen = (wb->bit_offset + 7) / 8;
477 
478     return true;
479 }
480