xref: /aosp_15_r20/external/libopenapv/src/oapv.c (revision abb65b4b03b69e1d508d4d9a44dcf199df16e7c3)
1*abb65b4bSAndroid Build Coastguard Worker /*
2*abb65b4bSAndroid Build Coastguard Worker  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3*abb65b4bSAndroid Build Coastguard Worker  * All Rights Reserved.
4*abb65b4bSAndroid Build Coastguard Worker  *
5*abb65b4bSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*abb65b4bSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions are met:
7*abb65b4bSAndroid Build Coastguard Worker  *
8*abb65b4bSAndroid Build Coastguard Worker  * - Redistributions of source code must retain the above copyright notice,
9*abb65b4bSAndroid Build Coastguard Worker  *   this list of conditions and the following disclaimer.
10*abb65b4bSAndroid Build Coastguard Worker  *
11*abb65b4bSAndroid Build Coastguard Worker  * - Redistributions in binary form must reproduce the above copyright notice,
12*abb65b4bSAndroid Build Coastguard Worker  *   this list of conditions and the following disclaimer in the documentation
13*abb65b4bSAndroid Build Coastguard Worker  *   and/or other materials provided with the distribution.
14*abb65b4bSAndroid Build Coastguard Worker  *
15*abb65b4bSAndroid Build Coastguard Worker  * - Neither the name of the copyright owner, nor the names of its contributors
16*abb65b4bSAndroid Build Coastguard Worker  *   may be used to endorse or promote products derived from this software
17*abb65b4bSAndroid Build Coastguard Worker  *   without specific prior written permission.
18*abb65b4bSAndroid Build Coastguard Worker  *
19*abb65b4bSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20*abb65b4bSAndroid Build Coastguard Worker  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*abb65b4bSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*abb65b4bSAndroid Build Coastguard Worker  * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23*abb65b4bSAndroid Build Coastguard Worker  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*abb65b4bSAndroid Build Coastguard Worker  * CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*abb65b4bSAndroid Build Coastguard Worker  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*abb65b4bSAndroid Build Coastguard Worker  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*abb65b4bSAndroid Build Coastguard Worker  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*abb65b4bSAndroid Build Coastguard Worker  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*abb65b4bSAndroid Build Coastguard Worker  * POSSIBILITY OF SUCH DAMAGE.
30*abb65b4bSAndroid Build Coastguard Worker  */
31*abb65b4bSAndroid Build Coastguard Worker 
32*abb65b4bSAndroid Build Coastguard Worker #include "oapv_def.h"
33*abb65b4bSAndroid Build Coastguard Worker 
imgb_to_block(oapv_imgb_t * imgb,int c,int x_l,int y_l,int w_l,int h_l,s16 * block)34*abb65b4bSAndroid Build Coastguard Worker static void imgb_to_block(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block)
35*abb65b4bSAndroid Build Coastguard Worker {
36*abb65b4bSAndroid Build Coastguard Worker     u8 *src, *dst;
37*abb65b4bSAndroid Build Coastguard Worker     int i, sft_hor, sft_ver;
38*abb65b4bSAndroid Build Coastguard Worker     int bd = OAPV_CS_GET_BYTE_DEPTH(imgb->cs);
39*abb65b4bSAndroid Build Coastguard Worker 
40*abb65b4bSAndroid Build Coastguard Worker     if(c == 0) {
41*abb65b4bSAndroid Build Coastguard Worker         sft_hor = sft_ver = 0;
42*abb65b4bSAndroid Build Coastguard Worker     }
43*abb65b4bSAndroid Build Coastguard Worker     else {
44*abb65b4bSAndroid Build Coastguard Worker         u8 cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs));
45*abb65b4bSAndroid Build Coastguard Worker         sft_hor = get_chroma_sft_w(cfi);
46*abb65b4bSAndroid Build Coastguard Worker         sft_ver = get_chroma_sft_h(cfi);
47*abb65b4bSAndroid Build Coastguard Worker     }
48*abb65b4bSAndroid Build Coastguard Worker 
49*abb65b4bSAndroid Build Coastguard Worker     src = ((u8 *)imgb->a[c]) + ((y_l >> sft_ver) * imgb->s[c]) + ((x_l * bd) >> sft_hor);
50*abb65b4bSAndroid Build Coastguard Worker     dst = (u8 *)block;
51*abb65b4bSAndroid Build Coastguard Worker 
52*abb65b4bSAndroid Build Coastguard Worker     for(i = 0; i < (h_l); i++) {
53*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(dst, src, (w_l)*bd);
54*abb65b4bSAndroid Build Coastguard Worker 
55*abb65b4bSAndroid Build Coastguard Worker         src += imgb->s[c];
56*abb65b4bSAndroid Build Coastguard Worker         dst += (w_l)*bd;
57*abb65b4bSAndroid Build Coastguard Worker     }
58*abb65b4bSAndroid Build Coastguard Worker }
59*abb65b4bSAndroid Build Coastguard Worker 
imgb_to_block_10bit(void * src,int blk_w,int blk_h,int s_src,int offset_src,int s_dst,void * dst)60*abb65b4bSAndroid Build Coastguard Worker static void imgb_to_block_10bit(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst)
61*abb65b4bSAndroid Build Coastguard Worker {
62*abb65b4bSAndroid Build Coastguard Worker     const int mid_val = (1 << (10 - 1));
63*abb65b4bSAndroid Build Coastguard Worker     s16      *s = (s16 *)src;
64*abb65b4bSAndroid Build Coastguard Worker     s16      *d = (s16 *)dst;
65*abb65b4bSAndroid Build Coastguard Worker 
66*abb65b4bSAndroid Build Coastguard Worker     for(int h = 0; h < blk_h; h++) {
67*abb65b4bSAndroid Build Coastguard Worker         for(int w = 0; w < blk_w; w++) {
68*abb65b4bSAndroid Build Coastguard Worker             d[w] = s[w] - mid_val;
69*abb65b4bSAndroid Build Coastguard Worker         }
70*abb65b4bSAndroid Build Coastguard Worker         s = (s16 *)(((u8 *)s) + s_src);
71*abb65b4bSAndroid Build Coastguard Worker         d = (s16 *)(((u8 *)d) + s_dst);
72*abb65b4bSAndroid Build Coastguard Worker     }
73*abb65b4bSAndroid Build Coastguard Worker }
74*abb65b4bSAndroid Build Coastguard Worker 
imgb_to_block_p210_y(void * src,int blk_w,int blk_h,int s_src,int offset_src,int s_dst,void * dst)75*abb65b4bSAndroid Build Coastguard Worker static void imgb_to_block_p210_y(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst)
76*abb65b4bSAndroid Build Coastguard Worker {
77*abb65b4bSAndroid Build Coastguard Worker     const int mid_val = (1 << (10 - 1));
78*abb65b4bSAndroid Build Coastguard Worker     u16      *s = (s16 *)src;
79*abb65b4bSAndroid Build Coastguard Worker     s16      *d = (s16 *)dst;
80*abb65b4bSAndroid Build Coastguard Worker 
81*abb65b4bSAndroid Build Coastguard Worker     for(int h = 0; h < blk_h; h++) {
82*abb65b4bSAndroid Build Coastguard Worker         for(int w = 0; w < blk_w; w++) {
83*abb65b4bSAndroid Build Coastguard Worker             d[w] = (s16)(s[w] >> 6) - mid_val;
84*abb65b4bSAndroid Build Coastguard Worker         }
85*abb65b4bSAndroid Build Coastguard Worker         s = (u16 *)(((u8 *)s) + s_src);
86*abb65b4bSAndroid Build Coastguard Worker         d = (s16 *)(((u8 *)d) + s_dst);
87*abb65b4bSAndroid Build Coastguard Worker     }
88*abb65b4bSAndroid Build Coastguard Worker }
89*abb65b4bSAndroid Build Coastguard Worker 
imgb_to_block_p210_uv(void * src,int blk_w,int blk_h,int s_src,int offset_src,int s_dst,void * dst)90*abb65b4bSAndroid Build Coastguard Worker static void imgb_to_block_p210_uv(void *src, int blk_w, int blk_h, int s_src, int offset_src, int s_dst, void *dst)
91*abb65b4bSAndroid Build Coastguard Worker {
92*abb65b4bSAndroid Build Coastguard Worker     const int mid_val = (1 << (10 - 1));
93*abb65b4bSAndroid Build Coastguard Worker     u16      *s = (u16 *)src + offset_src;
94*abb65b4bSAndroid Build Coastguard Worker     s16      *d = (s16 *)dst;
95*abb65b4bSAndroid Build Coastguard Worker 
96*abb65b4bSAndroid Build Coastguard Worker     for(int h = 0; h < blk_h; h++) {
97*abb65b4bSAndroid Build Coastguard Worker         for(int w = 0; w < blk_w; w++) {
98*abb65b4bSAndroid Build Coastguard Worker             d[w] = (s16)(s[w * 2] >> 6) - mid_val;
99*abb65b4bSAndroid Build Coastguard Worker         }
100*abb65b4bSAndroid Build Coastguard Worker         s = (u16 *)(((u8 *)s) + s_src);
101*abb65b4bSAndroid Build Coastguard Worker         d = (s16 *)(((u8 *)d) + s_dst);
102*abb65b4bSAndroid Build Coastguard Worker     }
103*abb65b4bSAndroid Build Coastguard Worker }
104*abb65b4bSAndroid Build Coastguard Worker 
imgb_to_block_p210(oapv_imgb_t * imgb,int c,int x_l,int y_l,int w_l,int h_l,s16 * block)105*abb65b4bSAndroid Build Coastguard Worker static void imgb_to_block_p210(oapv_imgb_t *imgb, int c, int x_l, int y_l, int w_l, int h_l, s16 *block)
106*abb65b4bSAndroid Build Coastguard Worker {
107*abb65b4bSAndroid Build Coastguard Worker     u16 *src, *dst;
108*abb65b4bSAndroid Build Coastguard Worker     int  sft_hor, sft_ver, s_src;
109*abb65b4bSAndroid Build Coastguard Worker     int  bd = OAPV_CS_GET_BYTE_DEPTH(imgb->cs);
110*abb65b4bSAndroid Build Coastguard Worker     int  size_scale = 1;
111*abb65b4bSAndroid Build Coastguard Worker     int  tc = c;
112*abb65b4bSAndroid Build Coastguard Worker 
113*abb65b4bSAndroid Build Coastguard Worker     if(c == 0) {
114*abb65b4bSAndroid Build Coastguard Worker         sft_hor = sft_ver = 0;
115*abb65b4bSAndroid Build Coastguard Worker     }
116*abb65b4bSAndroid Build Coastguard Worker     else {
117*abb65b4bSAndroid Build Coastguard Worker         u8 cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs));
118*abb65b4bSAndroid Build Coastguard Worker         sft_hor = get_chroma_sft_w(cfi);
119*abb65b4bSAndroid Build Coastguard Worker         sft_ver = get_chroma_sft_h(cfi);
120*abb65b4bSAndroid Build Coastguard Worker         size_scale = 2;
121*abb65b4bSAndroid Build Coastguard Worker         tc = 1;
122*abb65b4bSAndroid Build Coastguard Worker     }
123*abb65b4bSAndroid Build Coastguard Worker 
124*abb65b4bSAndroid Build Coastguard Worker     s_src = imgb->s[tc] >> (bd > 1 ? 1 : 0);
125*abb65b4bSAndroid Build Coastguard Worker     src = ((u16 *)imgb->a[tc]) + ((y_l >> sft_ver) * s_src) + ((x_l * size_scale) >> sft_hor);
126*abb65b4bSAndroid Build Coastguard Worker     dst = (u16 *)block;
127*abb65b4bSAndroid Build Coastguard Worker 
128*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < (h_l); i++) {
129*abb65b4bSAndroid Build Coastguard Worker         for(int j = 0; j < (w_l); j++) {
130*abb65b4bSAndroid Build Coastguard Worker             dst[j] = (src[j * size_scale + (c >> 1)] >> 6);
131*abb65b4bSAndroid Build Coastguard Worker         }
132*abb65b4bSAndroid Build Coastguard Worker         src += s_src;
133*abb65b4bSAndroid Build Coastguard Worker         dst += w_l;
134*abb65b4bSAndroid Build Coastguard Worker     }
135*abb65b4bSAndroid Build Coastguard Worker }
136*abb65b4bSAndroid Build Coastguard Worker 
block_to_imgb_10bit(void * src,int blk_w,int blk_h,int s_src,int offset_dst,int s_dst,void * dst)137*abb65b4bSAndroid Build Coastguard Worker static void block_to_imgb_10bit(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst)
138*abb65b4bSAndroid Build Coastguard Worker {
139*abb65b4bSAndroid Build Coastguard Worker     const int max_val = (1 << 10) - 1;
140*abb65b4bSAndroid Build Coastguard Worker     const int mid_val = (1 << (10 - 1));
141*abb65b4bSAndroid Build Coastguard Worker     s16      *s = (s16 *)src;
142*abb65b4bSAndroid Build Coastguard Worker     u16      *d = (u16 *)dst;
143*abb65b4bSAndroid Build Coastguard Worker 
144*abb65b4bSAndroid Build Coastguard Worker     for(int h = 0; h < blk_h; h++) {
145*abb65b4bSAndroid Build Coastguard Worker         for(int w = 0; w < blk_w; w++) {
146*abb65b4bSAndroid Build Coastguard Worker             d[w] = oapv_clip3(0, max_val, s[w] + mid_val);
147*abb65b4bSAndroid Build Coastguard Worker         }
148*abb65b4bSAndroid Build Coastguard Worker         s = (s16 *)(((u8 *)s) + s_src);
149*abb65b4bSAndroid Build Coastguard Worker         d = (u16 *)(((u8 *)d) + s_dst);
150*abb65b4bSAndroid Build Coastguard Worker     }
151*abb65b4bSAndroid Build Coastguard Worker }
152*abb65b4bSAndroid Build Coastguard Worker 
block_to_imgb_p210_y(void * src,int blk_w,int blk_h,int s_src,int offset_dst,int s_dst,void * dst)153*abb65b4bSAndroid Build Coastguard Worker static void block_to_imgb_p210_y(void *src, int blk_w, int blk_h, int s_src, int offset_dst, int s_dst, void *dst)
154*abb65b4bSAndroid Build Coastguard Worker {
155*abb65b4bSAndroid Build Coastguard Worker     const int max_val = (1 << 10) - 1;
156*abb65b4bSAndroid Build Coastguard Worker     const int mid_val = (1 << (10 - 1));
157*abb65b4bSAndroid Build Coastguard Worker     s16      *s = (s16 *)src;
158*abb65b4bSAndroid Build Coastguard Worker     u16      *d = (u16 *)dst;
159*abb65b4bSAndroid Build Coastguard Worker 
160*abb65b4bSAndroid Build Coastguard Worker     for(int h = 0; h < blk_h; h++) {
161*abb65b4bSAndroid Build Coastguard Worker         for(int w = 0; w < blk_w; w++) {
162*abb65b4bSAndroid Build Coastguard Worker             d[w] = oapv_clip3(0, max_val, s[w] + mid_val) << 6;
163*abb65b4bSAndroid Build Coastguard Worker         }
164*abb65b4bSAndroid Build Coastguard Worker         s = (s16 *)(((u8 *)s) + s_src);
165*abb65b4bSAndroid Build Coastguard Worker         d = (u16 *)(((u8 *)d) + s_dst);
166*abb65b4bSAndroid Build Coastguard Worker     }
167*abb65b4bSAndroid Build Coastguard Worker }
168*abb65b4bSAndroid Build Coastguard Worker 
block_to_imgb_p210_uv(void * src,int blk_w,int blk_h,int s_src,int x_pel,int s_dst,void * dst)169*abb65b4bSAndroid Build Coastguard Worker static void block_to_imgb_p210_uv(void *src, int blk_w, int blk_h, int s_src, int x_pel, int s_dst, void *dst)
170*abb65b4bSAndroid Build Coastguard Worker {
171*abb65b4bSAndroid Build Coastguard Worker     const int max_val = (1 << 10) - 1;
172*abb65b4bSAndroid Build Coastguard Worker     const int mid_val = (1 << (10 - 1));
173*abb65b4bSAndroid Build Coastguard Worker     s16      *s = (s16 *)src;
174*abb65b4bSAndroid Build Coastguard Worker 
175*abb65b4bSAndroid Build Coastguard Worker     // x_pel is x-offset value from left boundary of picture in unit of pixel.
176*abb65b4bSAndroid Build Coastguard Worker     // the 'dst' address has calculated by
177*abb65b4bSAndroid Build Coastguard Worker     // dst = (s16*)((u8*)origin + y_pel*s_dst) + x_pel;
178*abb65b4bSAndroid Build Coastguard Worker     // in case of P210 color format,
179*abb65b4bSAndroid Build Coastguard Worker     // since 's_dst' is byte size of stride including all U and V pixel values,
180*abb65b4bSAndroid Build Coastguard Worker     // y-offset calculation is correct.
181*abb65b4bSAndroid Build Coastguard Worker     // however, the adding only x_pel is not enough to address the correct pixel
182*abb65b4bSAndroid Build Coastguard Worker     // position of U or V because U & V use the same buffer plane
183*abb65b4bSAndroid Build Coastguard Worker     // in interleaved way,
184*abb65b4bSAndroid Build Coastguard Worker     // so, the 'dst' address should be increased by 'x_pel' to address pixel
185*abb65b4bSAndroid Build Coastguard Worker     // position correctly.
186*abb65b4bSAndroid Build Coastguard Worker     u16      *d = (u16 *)dst + x_pel; // p210 pixel value needs 0~65535 range
187*abb65b4bSAndroid Build Coastguard Worker 
188*abb65b4bSAndroid Build Coastguard Worker     for(int h = 0; h < blk_h; h++) {
189*abb65b4bSAndroid Build Coastguard Worker         for(int w = 0; w < blk_w; w++) {
190*abb65b4bSAndroid Build Coastguard Worker             d[w * 2] = ((u16)oapv_clip3(0, max_val, s[w] + mid_val)) << 6;
191*abb65b4bSAndroid Build Coastguard Worker         }
192*abb65b4bSAndroid Build Coastguard Worker         s = (s16 *)(((u8 *)s) + s_src);
193*abb65b4bSAndroid Build Coastguard Worker         d = (u16 *)(((u8 *)d) + s_dst);
194*abb65b4bSAndroid Build Coastguard Worker     }
195*abb65b4bSAndroid Build Coastguard Worker }
196*abb65b4bSAndroid Build Coastguard Worker 
plus_mid_val(s16 * coef,int b_w,int b_h,int bit_depth)197*abb65b4bSAndroid Build Coastguard Worker static void plus_mid_val(s16 *coef, int b_w, int b_h, int bit_depth)
198*abb65b4bSAndroid Build Coastguard Worker {
199*abb65b4bSAndroid Build Coastguard Worker     int mid_val = 1 << (bit_depth - 1);
200*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < b_h * b_w; i++) {
201*abb65b4bSAndroid Build Coastguard Worker         coef[i] = oapv_clip3(0, (1 << bit_depth) - 1, coef[i] + mid_val);
202*abb65b4bSAndroid Build Coastguard Worker     }
203*abb65b4bSAndroid Build Coastguard Worker }
204*abb65b4bSAndroid Build Coastguard Worker 
copy_fi_to_finfo(oapv_fi_t * fi,int pbu_type,int group_id,oapv_frm_info_t * finfo)205*abb65b4bSAndroid Build Coastguard Worker static void copy_fi_to_finfo(oapv_fi_t *fi, int pbu_type, int group_id, oapv_frm_info_t *finfo)
206*abb65b4bSAndroid Build Coastguard Worker {
207*abb65b4bSAndroid Build Coastguard Worker     finfo->w = (int)fi->frame_width; // casting to 'int' would be fine here
208*abb65b4bSAndroid Build Coastguard Worker     finfo->h = (int)fi->frame_height; // casting to 'int' would be fine here
209*abb65b4bSAndroid Build Coastguard Worker     finfo->cs = OAPV_CS_SET(chroma_format_idc_to_color_format(fi->chroma_format_idc), fi->bit_depth, 0);
210*abb65b4bSAndroid Build Coastguard Worker     finfo->pbu_type = pbu_type;
211*abb65b4bSAndroid Build Coastguard Worker     finfo->group_id = group_id;
212*abb65b4bSAndroid Build Coastguard Worker     finfo->profile_idc = fi->profile_idc;
213*abb65b4bSAndroid Build Coastguard Worker     finfo->level_idc = fi->level_idc;
214*abb65b4bSAndroid Build Coastguard Worker     finfo->band_idc = fi->band_idc;
215*abb65b4bSAndroid Build Coastguard Worker     finfo->chroma_format_idc = fi->chroma_format_idc;
216*abb65b4bSAndroid Build Coastguard Worker     finfo->bit_depth = fi->bit_depth;
217*abb65b4bSAndroid Build Coastguard Worker     finfo->capture_time_distance = fi->capture_time_distance;
218*abb65b4bSAndroid Build Coastguard Worker }
219*abb65b4bSAndroid Build Coastguard Worker 
220*abb65b4bSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
221*abb65b4bSAndroid Build Coastguard Worker // start of encoder code
222*abb65b4bSAndroid Build Coastguard Worker #if ENABLE_ENCODER
223*abb65b4bSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
224*abb65b4bSAndroid Build Coastguard Worker 
enc_id_to_ctx(oapve_t id)225*abb65b4bSAndroid Build Coastguard Worker static oapve_ctx_t *enc_id_to_ctx(oapve_t id)
226*abb65b4bSAndroid Build Coastguard Worker {
227*abb65b4bSAndroid Build Coastguard Worker     oapve_ctx_t *ctx;
228*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(id, NULL);
229*abb65b4bSAndroid Build Coastguard Worker     ctx = (oapve_ctx_t *)id;
230*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv((ctx)->magic == OAPVE_MAGIC_CODE, NULL);
231*abb65b4bSAndroid Build Coastguard Worker     return ctx;
232*abb65b4bSAndroid Build Coastguard Worker }
233*abb65b4bSAndroid Build Coastguard Worker 
enc_ctx_alloc(void)234*abb65b4bSAndroid Build Coastguard Worker static oapve_ctx_t *enc_ctx_alloc(void)
235*abb65b4bSAndroid Build Coastguard Worker {
236*abb65b4bSAndroid Build Coastguard Worker     oapve_ctx_t *ctx;
237*abb65b4bSAndroid Build Coastguard Worker     ctx = (oapve_ctx_t *)oapv_malloc_fast(sizeof(oapve_ctx_t));
238*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(ctx, NULL);
239*abb65b4bSAndroid Build Coastguard Worker     oapv_mset_x64a(ctx, 0, sizeof(oapve_ctx_t));
240*abb65b4bSAndroid Build Coastguard Worker     return ctx;
241*abb65b4bSAndroid Build Coastguard Worker }
242*abb65b4bSAndroid Build Coastguard Worker 
enc_ctx_free(oapve_ctx_t * ctx)243*abb65b4bSAndroid Build Coastguard Worker static void enc_ctx_free(oapve_ctx_t *ctx)
244*abb65b4bSAndroid Build Coastguard Worker {
245*abb65b4bSAndroid Build Coastguard Worker     oapv_mfree_fast(ctx);
246*abb65b4bSAndroid Build Coastguard Worker }
247*abb65b4bSAndroid Build Coastguard Worker 
enc_core_alloc()248*abb65b4bSAndroid Build Coastguard Worker static oapve_core_t *enc_core_alloc()
249*abb65b4bSAndroid Build Coastguard Worker {
250*abb65b4bSAndroid Build Coastguard Worker     oapve_core_t *core;
251*abb65b4bSAndroid Build Coastguard Worker     core = (oapve_core_t *)oapv_malloc_fast(sizeof(oapve_core_t));
252*abb65b4bSAndroid Build Coastguard Worker 
253*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(core, NULL);
254*abb65b4bSAndroid Build Coastguard Worker     oapv_mset_x64a(core, 0, sizeof(oapve_core_t));
255*abb65b4bSAndroid Build Coastguard Worker 
256*abb65b4bSAndroid Build Coastguard Worker     return core;
257*abb65b4bSAndroid Build Coastguard Worker }
258*abb65b4bSAndroid Build Coastguard Worker 
enc_core_free(oapve_core_t * core)259*abb65b4bSAndroid Build Coastguard Worker static void enc_core_free(oapve_core_t *core)
260*abb65b4bSAndroid Build Coastguard Worker {
261*abb65b4bSAndroid Build Coastguard Worker     oapv_mfree_fast(core);
262*abb65b4bSAndroid Build Coastguard Worker }
263*abb65b4bSAndroid Build Coastguard Worker 
enc_core_init(oapve_core_t * core,oapve_ctx_t * ctx,int tile_idx,int thread_idx)264*abb65b4bSAndroid Build Coastguard Worker static int enc_core_init(oapve_core_t *core, oapve_ctx_t *ctx, int tile_idx, int thread_idx)
265*abb65b4bSAndroid Build Coastguard Worker {
266*abb65b4bSAndroid Build Coastguard Worker     core->tile_idx = tile_idx;
267*abb65b4bSAndroid Build Coastguard Worker     core->ctx = ctx;
268*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
269*abb65b4bSAndroid Build Coastguard Worker }
270*abb65b4bSAndroid Build Coastguard Worker 
enc_minus_mid_val(s16 * coef,int w_blk,int h_blk,int bit_depth)271*abb65b4bSAndroid Build Coastguard Worker static void enc_minus_mid_val(s16 *coef, int w_blk, int h_blk, int bit_depth)
272*abb65b4bSAndroid Build Coastguard Worker {
273*abb65b4bSAndroid Build Coastguard Worker     int mid_val = 1 << (bit_depth - 1);
274*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < h_blk * w_blk; i++) {
275*abb65b4bSAndroid Build Coastguard Worker         coef[i] -= mid_val;
276*abb65b4bSAndroid Build Coastguard Worker     }
277*abb65b4bSAndroid Build Coastguard Worker }
278*abb65b4bSAndroid Build Coastguard Worker 
enc_set_tile_info(oapve_tile_t * ti,int w_pel,int h_pel,int tile_w,int tile_h,int * num_tile_cols,int * num_tile_rows,int * num_tiles)279*abb65b4bSAndroid Build Coastguard Worker static int enc_set_tile_info(oapve_tile_t *ti, int w_pel, int h_pel, int tile_w,
280*abb65b4bSAndroid Build Coastguard Worker                              int tile_h, int *num_tile_cols, int *num_tile_rows, int *num_tiles)
281*abb65b4bSAndroid Build Coastguard Worker {
282*abb65b4bSAndroid Build Coastguard Worker     (*num_tile_cols) = (w_pel + (tile_w - 1)) / tile_w;
283*abb65b4bSAndroid Build Coastguard Worker     (*num_tile_rows) = (h_pel + (tile_h - 1)) / tile_h;
284*abb65b4bSAndroid Build Coastguard Worker     (*num_tiles) = (*num_tile_cols) * (*num_tile_rows);
285*abb65b4bSAndroid Build Coastguard Worker 
286*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < (*num_tiles); i++) {
287*abb65b4bSAndroid Build Coastguard Worker         int tx = (i % (*num_tile_cols)) * tile_w;
288*abb65b4bSAndroid Build Coastguard Worker         int ty = (i / (*num_tile_cols)) * tile_h;
289*abb65b4bSAndroid Build Coastguard Worker         ti[i].x = tx;
290*abb65b4bSAndroid Build Coastguard Worker         ti[i].y = ty;
291*abb65b4bSAndroid Build Coastguard Worker         ti[i].w = tx + tile_w > w_pel ? w_pel - tx : tile_w;
292*abb65b4bSAndroid Build Coastguard Worker         ti[i].h = ty + tile_h > h_pel ? h_pel - ty : tile_h;
293*abb65b4bSAndroid Build Coastguard Worker     }
294*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
295*abb65b4bSAndroid Build Coastguard Worker }
296*abb65b4bSAndroid Build Coastguard Worker 
enc_block(oapve_ctx_t * ctx,oapve_core_t * core,int log2_w,int log2_h,int c)297*abb65b4bSAndroid Build Coastguard Worker static double enc_block(oapve_ctx_t *ctx, oapve_core_t *core, int log2_w, int log2_h, int c)
298*abb65b4bSAndroid Build Coastguard Worker {
299*abb65b4bSAndroid Build Coastguard Worker     int bit_depth = ctx->bit_depth;
300*abb65b4bSAndroid Build Coastguard Worker 
301*abb65b4bSAndroid Build Coastguard Worker     oapv_trans(ctx, core->coef, log2_w, log2_h, bit_depth);
302*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_quant[0](core->coef, core->qp[c], core->q_mat_enc[c], log2_w, log2_h, bit_depth, c ? 128 : 212);
303*abb65b4bSAndroid Build Coastguard Worker 
304*abb65b4bSAndroid Build Coastguard Worker     int prev_dc = core->prev_dc[c];
305*abb65b4bSAndroid Build Coastguard Worker     core->prev_dc[c] = core->coef[0];
306*abb65b4bSAndroid Build Coastguard Worker     core->coef[0] = core->coef[0] - prev_dc;
307*abb65b4bSAndroid Build Coastguard Worker 
308*abb65b4bSAndroid Build Coastguard Worker     if(ctx->rec) {
309*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(core->coef_rec, core->coef, sizeof(s16) * OAPV_BLK_D);
310*abb65b4bSAndroid Build Coastguard Worker         core->coef_rec[0] = core->coef_rec[0] + prev_dc;
311*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_dquant[0](core->coef_rec, core->q_mat_dec[c], log2_w, log2_h, core->dq_shift[c]);
312*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_itx[0](core->coef_rec, ITX_SHIFT1, ITX_SHIFT2(bit_depth), 1 << log2_w);
313*abb65b4bSAndroid Build Coastguard Worker     }
314*abb65b4bSAndroid Build Coastguard Worker 
315*abb65b4bSAndroid Build Coastguard Worker     return 0;
316*abb65b4bSAndroid Build Coastguard Worker }
317*abb65b4bSAndroid Build Coastguard Worker 
enc_block_rdo_slow(oapve_ctx_t * ctx,oapve_core_t * core,int log2_w,int log2_h,int c)318*abb65b4bSAndroid Build Coastguard Worker static double enc_block_rdo_slow(oapve_ctx_t *ctx, oapve_core_t *core, int log2_w, int log2_h, int c)
319*abb65b4bSAndroid Build Coastguard Worker {
320*abb65b4bSAndroid Build Coastguard Worker     ALIGNED_16(s16 recon[OAPV_BLK_D]) = { 0 };
321*abb65b4bSAndroid Build Coastguard Worker     ALIGNED_16(s16 coeff[OAPV_BLK_D]) = { 0 };
322*abb65b4bSAndroid Build Coastguard Worker     int        blk_w = 1 << log2_w;
323*abb65b4bSAndroid Build Coastguard Worker     int        blk_h = 1 << log2_h;
324*abb65b4bSAndroid Build Coastguard Worker     int        bit_depth = ctx->bit_depth;
325*abb65b4bSAndroid Build Coastguard Worker     int        qp = core->qp[c];
326*abb65b4bSAndroid Build Coastguard Worker     s16        org[OAPV_BLK_D] = { 0 };
327*abb65b4bSAndroid Build Coastguard Worker     s16       *best_coeff = core->coef;
328*abb65b4bSAndroid Build Coastguard Worker     s16       *best_recon = core->coef_rec;
329*abb65b4bSAndroid Build Coastguard Worker     int        best_cost = INT_MAX;
330*abb65b4bSAndroid Build Coastguard Worker     int        zero_dist = 0;
331*abb65b4bSAndroid Build Coastguard Worker     const u16 *scanp = oapv_tbl_scan;
332*abb65b4bSAndroid Build Coastguard Worker     const int  map_idx_diff[15] = { 0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7 };
333*abb65b4bSAndroid Build Coastguard Worker 
334*abb65b4bSAndroid Build Coastguard Worker     oapv_mcpy(org, core->coef, sizeof(s16) * OAPV_BLK_D);
335*abb65b4bSAndroid Build Coastguard Worker     oapv_trans(ctx, core->coef, log2_w, log2_h, bit_depth);
336*abb65b4bSAndroid Build Coastguard Worker     oapv_mcpy(coeff, core->coef, sizeof(s16) * OAPV_BLK_D);
337*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_quant[0](coeff, qp, core->q_mat_enc[c], log2_w, log2_h, bit_depth, c ? 112 : 212);
338*abb65b4bSAndroid Build Coastguard Worker 
339*abb65b4bSAndroid Build Coastguard Worker     {
340*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(recon, coeff, sizeof(s16) * OAPV_BLK_D);
341*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_dquant[0](recon, core->q_mat_dec[c], log2_w, log2_h, core->dq_shift[c]);
342*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_itx[0](recon, ITX_SHIFT1, ITX_SHIFT2(bit_depth), 1 << log2_w);
343*abb65b4bSAndroid Build Coastguard Worker         int cost = (int)ctx->fn_ssd[0](blk_w, blk_h, org, recon, blk_w, blk_w, bit_depth);
344*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(best_coeff, coeff, sizeof(s16) * OAPV_BLK_D);
345*abb65b4bSAndroid Build Coastguard Worker         if(ctx->rec) {
346*abb65b4bSAndroid Build Coastguard Worker             oapv_mcpy(best_recon, recon, sizeof(s16) * OAPV_BLK_D);
347*abb65b4bSAndroid Build Coastguard Worker         }
348*abb65b4bSAndroid Build Coastguard Worker         if(cost == 0) {
349*abb65b4bSAndroid Build Coastguard Worker             zero_dist = 1;
350*abb65b4bSAndroid Build Coastguard Worker         }
351*abb65b4bSAndroid Build Coastguard Worker         best_cost = cost;
352*abb65b4bSAndroid Build Coastguard Worker     }
353*abb65b4bSAndroid Build Coastguard Worker 
354*abb65b4bSAndroid Build Coastguard Worker     for(int itr = 0; itr < (c == 0 ? 2 : 1) && !zero_dist; itr++) {
355*abb65b4bSAndroid Build Coastguard Worker         for(int j = 0; j < OAPV_BLK_D && !zero_dist; j++) {
356*abb65b4bSAndroid Build Coastguard Worker             int best_idx = 0;
357*abb65b4bSAndroid Build Coastguard Worker             s16 org_coef = coeff[scanp[j]];
358*abb65b4bSAndroid Build Coastguard Worker             int adj_rng = c == 0 ? 13 : 5;
359*abb65b4bSAndroid Build Coastguard Worker             if(org_coef == 0) {
360*abb65b4bSAndroid Build Coastguard Worker                 if(c == 0 && scanp[j] < 3) {
361*abb65b4bSAndroid Build Coastguard Worker                     adj_rng = 3;
362*abb65b4bSAndroid Build Coastguard Worker                 }
363*abb65b4bSAndroid Build Coastguard Worker                 else {
364*abb65b4bSAndroid Build Coastguard Worker                     continue;
365*abb65b4bSAndroid Build Coastguard Worker                 }
366*abb65b4bSAndroid Build Coastguard Worker             }
367*abb65b4bSAndroid Build Coastguard Worker 
368*abb65b4bSAndroid Build Coastguard Worker             for(int i = 1; i < adj_rng && !zero_dist; i++) {
369*abb65b4bSAndroid Build Coastguard Worker                 if(i > 2) {
370*abb65b4bSAndroid Build Coastguard Worker                     if(best_idx == 0) {
371*abb65b4bSAndroid Build Coastguard Worker                         continue;
372*abb65b4bSAndroid Build Coastguard Worker                     }
373*abb65b4bSAndroid Build Coastguard Worker                     else if(best_idx % 2 == 1 && i % 2 == 0) {
374*abb65b4bSAndroid Build Coastguard Worker                         continue;
375*abb65b4bSAndroid Build Coastguard Worker                     }
376*abb65b4bSAndroid Build Coastguard Worker                     else if(best_idx % 2 == 0 && i % 2 == 1) {
377*abb65b4bSAndroid Build Coastguard Worker                         continue;
378*abb65b4bSAndroid Build Coastguard Worker                     }
379*abb65b4bSAndroid Build Coastguard Worker                 }
380*abb65b4bSAndroid Build Coastguard Worker 
381*abb65b4bSAndroid Build Coastguard Worker                 s16 test_coef = org_coef + map_idx_diff[i];
382*abb65b4bSAndroid Build Coastguard Worker                 coeff[scanp[j]] = test_coef;
383*abb65b4bSAndroid Build Coastguard Worker 
384*abb65b4bSAndroid Build Coastguard Worker                 oapv_mcpy(recon, coeff, sizeof(s16) * OAPV_BLK_D);
385*abb65b4bSAndroid Build Coastguard Worker                 ctx->fn_dquant[0](recon, core->q_mat_dec[c], log2_w, log2_h, core->dq_shift[c]);
386*abb65b4bSAndroid Build Coastguard Worker                 ctx->fn_itx[0](recon, ITX_SHIFT1, ITX_SHIFT2(bit_depth), 1 << log2_w);
387*abb65b4bSAndroid Build Coastguard Worker                 int cost = (int)ctx->fn_ssd[0](blk_w, blk_h, org, recon, blk_w, blk_w, bit_depth);
388*abb65b4bSAndroid Build Coastguard Worker 
389*abb65b4bSAndroid Build Coastguard Worker                 if(cost < best_cost) {
390*abb65b4bSAndroid Build Coastguard Worker                     best_cost = cost;
391*abb65b4bSAndroid Build Coastguard Worker                     best_coeff[scanp[j]] = test_coef;
392*abb65b4bSAndroid Build Coastguard Worker                     if(ctx->rec) {
393*abb65b4bSAndroid Build Coastguard Worker                         oapv_mcpy(best_recon, recon, sizeof(s16) * OAPV_BLK_D);
394*abb65b4bSAndroid Build Coastguard Worker                     }
395*abb65b4bSAndroid Build Coastguard Worker                     best_idx = i;
396*abb65b4bSAndroid Build Coastguard Worker                     if(cost == 0) {
397*abb65b4bSAndroid Build Coastguard Worker                         zero_dist = 1;
398*abb65b4bSAndroid Build Coastguard Worker                     }
399*abb65b4bSAndroid Build Coastguard Worker                 }
400*abb65b4bSAndroid Build Coastguard Worker                 else {
401*abb65b4bSAndroid Build Coastguard Worker                     coeff[scanp[j]] = org_coef + map_idx_diff[best_idx];
402*abb65b4bSAndroid Build Coastguard Worker                 }
403*abb65b4bSAndroid Build Coastguard Worker             }
404*abb65b4bSAndroid Build Coastguard Worker         }
405*abb65b4bSAndroid Build Coastguard Worker     }
406*abb65b4bSAndroid Build Coastguard Worker 
407*abb65b4bSAndroid Build Coastguard Worker     int curr_dc = best_coeff[0];
408*abb65b4bSAndroid Build Coastguard Worker     best_coeff[0] -= core->prev_dc[c];
409*abb65b4bSAndroid Build Coastguard Worker     core->prev_dc[c] = curr_dc;
410*abb65b4bSAndroid Build Coastguard Worker 
411*abb65b4bSAndroid Build Coastguard Worker     return best_cost;
412*abb65b4bSAndroid Build Coastguard Worker }
413*abb65b4bSAndroid Build Coastguard Worker 
enc_block_rdo_medium(oapve_ctx_t * ctx,oapve_core_t * core,int log2_w,int log2_h,int c)414*abb65b4bSAndroid Build Coastguard Worker static double enc_block_rdo_medium(oapve_ctx_t *ctx, oapve_core_t *core, int log2_w, int log2_h, int c)
415*abb65b4bSAndroid Build Coastguard Worker {
416*abb65b4bSAndroid Build Coastguard Worker     ALIGNED_16(s16 org[OAPV_BLK_D]);
417*abb65b4bSAndroid Build Coastguard Worker     ALIGNED_16(s16 recon[OAPV_BLK_D]);
418*abb65b4bSAndroid Build Coastguard Worker     ALIGNED_16(s16 coeff[OAPV_BLK_D]);
419*abb65b4bSAndroid Build Coastguard Worker     ALIGNED_16(s16 tmp_buf[OAPV_BLK_D]);
420*abb65b4bSAndroid Build Coastguard Worker 
421*abb65b4bSAndroid Build Coastguard Worker     ALIGNED_32(int rec_ups[OAPV_BLK_D]);
422*abb65b4bSAndroid Build Coastguard Worker     ALIGNED_32(int rec_tmp[OAPV_BLK_D]);
423*abb65b4bSAndroid Build Coastguard Worker 
424*abb65b4bSAndroid Build Coastguard Worker     int        blk_w = 1 << log2_w;
425*abb65b4bSAndroid Build Coastguard Worker     int        blk_h = 1 << log2_h;
426*abb65b4bSAndroid Build Coastguard Worker     int        bit_depth = ctx->bit_depth;
427*abb65b4bSAndroid Build Coastguard Worker     int        qp = core->qp[c];
428*abb65b4bSAndroid Build Coastguard Worker 
429*abb65b4bSAndroid Build Coastguard Worker     s16       *best_coeff = core->coef;
430*abb65b4bSAndroid Build Coastguard Worker     s16       *best_recon = core->coef_rec;
431*abb65b4bSAndroid Build Coastguard Worker 
432*abb65b4bSAndroid Build Coastguard Worker     int        best_cost = INT_MAX;
433*abb65b4bSAndroid Build Coastguard Worker     int        zero_dist = 0;
434*abb65b4bSAndroid Build Coastguard Worker     const u16 *scanp = oapv_tbl_scan;
435*abb65b4bSAndroid Build Coastguard Worker     const int  map_idx_diff[15] = { 0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7 };
436*abb65b4bSAndroid Build Coastguard Worker 
437*abb65b4bSAndroid Build Coastguard Worker     oapv_mcpy(org, core->coef, sizeof(s16) * OAPV_BLK_D);
438*abb65b4bSAndroid Build Coastguard Worker     oapv_trans(ctx, core->coef, log2_w, log2_h, bit_depth);
439*abb65b4bSAndroid Build Coastguard Worker     oapv_mcpy(coeff, core->coef, sizeof(s16) * OAPV_BLK_D);
440*abb65b4bSAndroid Build Coastguard Worker 
441*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_quant[0](coeff, qp, core->q_mat_enc[c], log2_w, log2_h, bit_depth, c ? 112 : 212);
442*abb65b4bSAndroid Build Coastguard Worker 
443*abb65b4bSAndroid Build Coastguard Worker     {
444*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(recon, coeff, sizeof(s16) * OAPV_BLK_D);
445*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_dquant[0](recon, core->q_mat_dec[c], log2_w, log2_h, core->dq_shift[c]);
446*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_itx_part[0](recon, tmp_buf, ITX_SHIFT1, 1 << log2_w);
447*abb65b4bSAndroid Build Coastguard Worker         oapv_itx_get_wo_sft(tmp_buf, recon, rec_ups, ITX_SHIFT2(bit_depth), 1 << log2_h);
448*abb65b4bSAndroid Build Coastguard Worker 
449*abb65b4bSAndroid Build Coastguard Worker         int cost = (int)ctx->fn_ssd[0](blk_w, blk_h, org, recon, blk_w, blk_w, bit_depth);
450*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(best_coeff, coeff, sizeof(s16) * OAPV_BLK_D);
451*abb65b4bSAndroid Build Coastguard Worker         if(ctx->rec) {
452*abb65b4bSAndroid Build Coastguard Worker             oapv_mcpy(best_recon, recon, sizeof(s16) * OAPV_BLK_D);
453*abb65b4bSAndroid Build Coastguard Worker         }
454*abb65b4bSAndroid Build Coastguard Worker         if(cost == 0) {
455*abb65b4bSAndroid Build Coastguard Worker             zero_dist = 1;
456*abb65b4bSAndroid Build Coastguard Worker         }
457*abb65b4bSAndroid Build Coastguard Worker         best_cost = cost;
458*abb65b4bSAndroid Build Coastguard Worker     }
459*abb65b4bSAndroid Build Coastguard Worker 
460*abb65b4bSAndroid Build Coastguard Worker     for(int itr = 0; itr < (c == 0 ? 2 : 1) && !zero_dist; itr++) {
461*abb65b4bSAndroid Build Coastguard Worker         for(int j = 0; j < OAPV_BLK_D && !zero_dist; j++) {
462*abb65b4bSAndroid Build Coastguard Worker             int best_idx = 0;
463*abb65b4bSAndroid Build Coastguard Worker             s16 org_coef = coeff[scanp[j]];
464*abb65b4bSAndroid Build Coastguard Worker             int adj_rng = (c == 0 ? 13 : 5);
465*abb65b4bSAndroid Build Coastguard Worker             if(org_coef == 0) {
466*abb65b4bSAndroid Build Coastguard Worker                 if(c == 0 && scanp[j] < 3) {
467*abb65b4bSAndroid Build Coastguard Worker                     adj_rng = 3;
468*abb65b4bSAndroid Build Coastguard Worker                 }
469*abb65b4bSAndroid Build Coastguard Worker                 else {
470*abb65b4bSAndroid Build Coastguard Worker                     continue;
471*abb65b4bSAndroid Build Coastguard Worker                 }
472*abb65b4bSAndroid Build Coastguard Worker             }
473*abb65b4bSAndroid Build Coastguard Worker             int q_step = 0;
474*abb65b4bSAndroid Build Coastguard Worker             if(core->dq_shift[c] > 0) {
475*abb65b4bSAndroid Build Coastguard Worker                 q_step = (core->q_mat_dec[c][scanp[j]] + (1 << (core->dq_shift[c] - 1))) >> core->dq_shift[c];
476*abb65b4bSAndroid Build Coastguard Worker             }
477*abb65b4bSAndroid Build Coastguard Worker             else {
478*abb65b4bSAndroid Build Coastguard Worker                 q_step = (core->q_mat_dec[c][scanp[j]]) << (-core->dq_shift[c]);
479*abb65b4bSAndroid Build Coastguard Worker             }
480*abb65b4bSAndroid Build Coastguard Worker 
481*abb65b4bSAndroid Build Coastguard Worker             for(int i = 1; i < adj_rng && !zero_dist; i++) {
482*abb65b4bSAndroid Build Coastguard Worker                 if(i > 2) {
483*abb65b4bSAndroid Build Coastguard Worker                     if(best_idx == 0) {
484*abb65b4bSAndroid Build Coastguard Worker                         continue;
485*abb65b4bSAndroid Build Coastguard Worker                     }
486*abb65b4bSAndroid Build Coastguard Worker                     else if(best_idx % 2 == 1 && i % 2 == 0) {
487*abb65b4bSAndroid Build Coastguard Worker                         continue;
488*abb65b4bSAndroid Build Coastguard Worker                     }
489*abb65b4bSAndroid Build Coastguard Worker                     else if(best_idx % 2 == 0 && i % 2 == 1) {
490*abb65b4bSAndroid Build Coastguard Worker                         continue;
491*abb65b4bSAndroid Build Coastguard Worker                     }
492*abb65b4bSAndroid Build Coastguard Worker                 }
493*abb65b4bSAndroid Build Coastguard Worker 
494*abb65b4bSAndroid Build Coastguard Worker                 s16 test_coef = org_coef + map_idx_diff[i];
495*abb65b4bSAndroid Build Coastguard Worker                 coeff[scanp[j]] = test_coef;
496*abb65b4bSAndroid Build Coastguard Worker                 int step_diff = q_step * map_idx_diff[i];
497*abb65b4bSAndroid Build Coastguard Worker                 ctx->fn_itx_adj[0](rec_ups, rec_tmp, j, step_diff, 9);
498*abb65b4bSAndroid Build Coastguard Worker                 for(int k = 0; k < 64; k++) {
499*abb65b4bSAndroid Build Coastguard Worker                     recon[k] = (rec_tmp[k] + 512) >> 10;
500*abb65b4bSAndroid Build Coastguard Worker                 }
501*abb65b4bSAndroid Build Coastguard Worker 
502*abb65b4bSAndroid Build Coastguard Worker                 int cost = (int)ctx->fn_ssd[0](blk_w, blk_h, org, recon, blk_w, blk_w, bit_depth);
503*abb65b4bSAndroid Build Coastguard Worker                 if(cost < best_cost) {
504*abb65b4bSAndroid Build Coastguard Worker                     oapv_mcpy(rec_ups, rec_tmp, sizeof(int) * OAPV_BLK_D);
505*abb65b4bSAndroid Build Coastguard Worker                     best_cost = cost;
506*abb65b4bSAndroid Build Coastguard Worker                     best_coeff[scanp[j]] = test_coef;
507*abb65b4bSAndroid Build Coastguard Worker                     best_idx = i;
508*abb65b4bSAndroid Build Coastguard Worker                     if(cost == 0) {
509*abb65b4bSAndroid Build Coastguard Worker                         zero_dist = 1;
510*abb65b4bSAndroid Build Coastguard Worker                     }
511*abb65b4bSAndroid Build Coastguard Worker                 }
512*abb65b4bSAndroid Build Coastguard Worker                 else {
513*abb65b4bSAndroid Build Coastguard Worker                     coeff[scanp[j]] = org_coef + map_idx_diff[best_idx];
514*abb65b4bSAndroid Build Coastguard Worker                 }
515*abb65b4bSAndroid Build Coastguard Worker             }
516*abb65b4bSAndroid Build Coastguard Worker         }
517*abb65b4bSAndroid Build Coastguard Worker     }
518*abb65b4bSAndroid Build Coastguard Worker 
519*abb65b4bSAndroid Build Coastguard Worker     if(ctx->rec) {
520*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(best_recon, best_coeff, sizeof(s16) * OAPV_BLK_D);
521*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_dquant[0](best_recon, core->q_mat_dec[c], log2_w, log2_h, core->dq_shift[c]);
522*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_itx[0](best_recon, ITX_SHIFT1, ITX_SHIFT2(bit_depth), 1 << log2_w);
523*abb65b4bSAndroid Build Coastguard Worker     }
524*abb65b4bSAndroid Build Coastguard Worker 
525*abb65b4bSAndroid Build Coastguard Worker     int curr_dc = best_coeff[0];
526*abb65b4bSAndroid Build Coastguard Worker     best_coeff[0] -= core->prev_dc[c];
527*abb65b4bSAndroid Build Coastguard Worker     core->prev_dc[c] = curr_dc;
528*abb65b4bSAndroid Build Coastguard Worker 
529*abb65b4bSAndroid Build Coastguard Worker     return best_cost;
530*abb65b4bSAndroid Build Coastguard Worker }
531*abb65b4bSAndroid Build Coastguard Worker 
enc_block_rdo_placebo(oapve_ctx_t * ctx,oapve_core_t * core,int log2_w,int log2_h,int c)532*abb65b4bSAndroid Build Coastguard Worker static double enc_block_rdo_placebo(oapve_ctx_t *ctx, oapve_core_t *core, int log2_w, int log2_h, int c)
533*abb65b4bSAndroid Build Coastguard Worker {
534*abb65b4bSAndroid Build Coastguard Worker     int  blk_w = 1 << log2_w;
535*abb65b4bSAndroid Build Coastguard Worker     int  blk_h = 1 << log2_h;
536*abb65b4bSAndroid Build Coastguard Worker     int  bit_depth = ctx->bit_depth;
537*abb65b4bSAndroid Build Coastguard Worker     int  qp = core->qp[c];
538*abb65b4bSAndroid Build Coastguard Worker     s16 *best_coeff = core->coef;
539*abb65b4bSAndroid Build Coastguard Worker     s16 *best_recon = core->coef_rec;
540*abb65b4bSAndroid Build Coastguard Worker     ALIGNED_16(s16 org[OAPV_BLK_D]);
541*abb65b4bSAndroid Build Coastguard Worker     ALIGNED_16(s16 recon[OAPV_BLK_D]);
542*abb65b4bSAndroid Build Coastguard Worker     ALIGNED_16(s16 coeff[OAPV_BLK_D]);
543*abb65b4bSAndroid Build Coastguard Worker     int        best_cost = INT_MAX;
544*abb65b4bSAndroid Build Coastguard Worker     int        zero_dist = 0;
545*abb65b4bSAndroid Build Coastguard Worker     const u16 *scanp = oapv_tbl_scan;
546*abb65b4bSAndroid Build Coastguard Worker     const int  map_idx_diff[15] = { 0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7 };
547*abb65b4bSAndroid Build Coastguard Worker 
548*abb65b4bSAndroid Build Coastguard Worker     oapv_mcpy(org, core->coef, sizeof(s16) * OAPV_BLK_D);
549*abb65b4bSAndroid Build Coastguard Worker     oapv_trans(ctx, core->coef, log2_w, log2_h, bit_depth);
550*abb65b4bSAndroid Build Coastguard Worker     oapv_mcpy(coeff, core->coef, sizeof(s16) * OAPV_BLK_D);
551*abb65b4bSAndroid Build Coastguard Worker 
552*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_quant[0](coeff, qp, core->q_mat_enc[c], log2_w, log2_h, bit_depth, c ? 112 : 212);
553*abb65b4bSAndroid Build Coastguard Worker 
554*abb65b4bSAndroid Build Coastguard Worker     {
555*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(recon, coeff, sizeof(s16) * OAPV_BLK_D);
556*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_dquant[0](recon, core->q_mat_dec[c], log2_w, log2_h, core->dq_shift[c]);
557*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_itx[0](recon, ITX_SHIFT1, ITX_SHIFT2(bit_depth), 1 << log2_w);
558*abb65b4bSAndroid Build Coastguard Worker         int cost = (int)ctx->fn_ssd[0](blk_w, blk_h, org, recon, blk_w, blk_w, bit_depth);
559*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(best_coeff, coeff, sizeof(s16) * OAPV_BLK_D);
560*abb65b4bSAndroid Build Coastguard Worker         if(ctx->rec) {
561*abb65b4bSAndroid Build Coastguard Worker             oapv_mcpy(best_recon, recon, sizeof(s16) * OAPV_BLK_D);
562*abb65b4bSAndroid Build Coastguard Worker         }
563*abb65b4bSAndroid Build Coastguard Worker         if(cost == 0) {
564*abb65b4bSAndroid Build Coastguard Worker             zero_dist = 1;
565*abb65b4bSAndroid Build Coastguard Worker         }
566*abb65b4bSAndroid Build Coastguard Worker         best_cost = cost;
567*abb65b4bSAndroid Build Coastguard Worker     }
568*abb65b4bSAndroid Build Coastguard Worker 
569*abb65b4bSAndroid Build Coastguard Worker     for(int itr = 0; itr < (c == 0 ? 7 : 3) && !zero_dist; itr++) {
570*abb65b4bSAndroid Build Coastguard Worker         for(int j = 0; j < OAPV_BLK_D && !zero_dist; j++) {
571*abb65b4bSAndroid Build Coastguard Worker             int best_idx = 0;
572*abb65b4bSAndroid Build Coastguard Worker             s16 org_coef = coeff[scanp[j]];
573*abb65b4bSAndroid Build Coastguard Worker             int adj_rng = (c == 0 ? 15 : 5);
574*abb65b4bSAndroid Build Coastguard Worker             if(org_coef == 0) {
575*abb65b4bSAndroid Build Coastguard Worker                 if(c == 0 && scanp[j] < 3) {
576*abb65b4bSAndroid Build Coastguard Worker                     adj_rng = 3;
577*abb65b4bSAndroid Build Coastguard Worker                 }
578*abb65b4bSAndroid Build Coastguard Worker                 else {
579*abb65b4bSAndroid Build Coastguard Worker                     continue;
580*abb65b4bSAndroid Build Coastguard Worker                 }
581*abb65b4bSAndroid Build Coastguard Worker             }
582*abb65b4bSAndroid Build Coastguard Worker 
583*abb65b4bSAndroid Build Coastguard Worker             for(int i = 1; i < adj_rng && !zero_dist; i++) {
584*abb65b4bSAndroid Build Coastguard Worker                 if(i > 2) {
585*abb65b4bSAndroid Build Coastguard Worker                     if(best_idx == 0) {
586*abb65b4bSAndroid Build Coastguard Worker                         continue;
587*abb65b4bSAndroid Build Coastguard Worker                     }
588*abb65b4bSAndroid Build Coastguard Worker                     else if(best_idx % 2 == 1 && i % 2 == 0) {
589*abb65b4bSAndroid Build Coastguard Worker                         continue;
590*abb65b4bSAndroid Build Coastguard Worker                     }
591*abb65b4bSAndroid Build Coastguard Worker                     else if(best_idx % 2 == 0 && i % 2 == 1) {
592*abb65b4bSAndroid Build Coastguard Worker                         continue;
593*abb65b4bSAndroid Build Coastguard Worker                     }
594*abb65b4bSAndroid Build Coastguard Worker                 }
595*abb65b4bSAndroid Build Coastguard Worker 
596*abb65b4bSAndroid Build Coastguard Worker                 s16 test_coef = org_coef + map_idx_diff[i];
597*abb65b4bSAndroid Build Coastguard Worker                 coeff[scanp[j]] = test_coef;
598*abb65b4bSAndroid Build Coastguard Worker 
599*abb65b4bSAndroid Build Coastguard Worker                 oapv_mcpy(recon, coeff, sizeof(s16) * OAPV_BLK_D);
600*abb65b4bSAndroid Build Coastguard Worker                 ctx->fn_dquant[0](recon, core->q_mat_dec[c], log2_w, log2_h, core->dq_shift[c]);
601*abb65b4bSAndroid Build Coastguard Worker                 ctx->fn_itx[0](recon, ITX_SHIFT1, ITX_SHIFT2(bit_depth), 1 << log2_w);
602*abb65b4bSAndroid Build Coastguard Worker                 int cost = (int)ctx->fn_ssd[0](blk_w, blk_h, org, recon, blk_w, blk_w, bit_depth);
603*abb65b4bSAndroid Build Coastguard Worker 
604*abb65b4bSAndroid Build Coastguard Worker                 if(cost < best_cost) {
605*abb65b4bSAndroid Build Coastguard Worker                     best_cost = cost;
606*abb65b4bSAndroid Build Coastguard Worker                     best_coeff[scanp[j]] = test_coef;
607*abb65b4bSAndroid Build Coastguard Worker                     if(ctx->rec) {
608*abb65b4bSAndroid Build Coastguard Worker                         oapv_mcpy(best_recon, recon, sizeof(s16) * OAPV_BLK_D);
609*abb65b4bSAndroid Build Coastguard Worker                     }
610*abb65b4bSAndroid Build Coastguard Worker                     best_idx = i;
611*abb65b4bSAndroid Build Coastguard Worker                     if(cost == 0) {
612*abb65b4bSAndroid Build Coastguard Worker                         zero_dist = 1;
613*abb65b4bSAndroid Build Coastguard Worker                     }
614*abb65b4bSAndroid Build Coastguard Worker                 }
615*abb65b4bSAndroid Build Coastguard Worker                 else {
616*abb65b4bSAndroid Build Coastguard Worker                     coeff[scanp[j]] = org_coef + map_idx_diff[best_idx];
617*abb65b4bSAndroid Build Coastguard Worker                 }
618*abb65b4bSAndroid Build Coastguard Worker             }
619*abb65b4bSAndroid Build Coastguard Worker         }
620*abb65b4bSAndroid Build Coastguard Worker     }
621*abb65b4bSAndroid Build Coastguard Worker 
622*abb65b4bSAndroid Build Coastguard Worker     int curr_dc = best_coeff[0];
623*abb65b4bSAndroid Build Coastguard Worker     best_coeff[0] -= core->prev_dc[c];
624*abb65b4bSAndroid Build Coastguard Worker     core->prev_dc[c] = curr_dc;
625*abb65b4bSAndroid Build Coastguard Worker 
626*abb65b4bSAndroid Build Coastguard Worker     return best_cost;
627*abb65b4bSAndroid Build Coastguard Worker }
628*abb65b4bSAndroid Build Coastguard Worker 
enc_read_param(oapve_ctx_t * ctx,oapve_param_t * param)629*abb65b4bSAndroid Build Coastguard Worker static int enc_read_param(oapve_ctx_t *ctx, oapve_param_t *param)
630*abb65b4bSAndroid Build Coastguard Worker {
631*abb65b4bSAndroid Build Coastguard Worker     /* check input parameters */
632*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(param->w > 0 && param->h > 0, OAPV_ERR_INVALID_ARGUMENT);
633*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(param->qp >= MIN_QUANT && param->qp <= MAX_QUANT, OAPV_ERR_INVALID_ARGUMENT);
634*abb65b4bSAndroid Build Coastguard Worker 
635*abb65b4bSAndroid Build Coastguard Worker     ctx->qp[Y_C] = param->qp;
636*abb65b4bSAndroid Build Coastguard Worker     ctx->qp[U_C] = param->qp + param->qp_cb_offset;
637*abb65b4bSAndroid Build Coastguard Worker     ctx->qp[V_C] = param->qp + param->qp_cr_offset;
638*abb65b4bSAndroid Build Coastguard Worker     ctx->qp[X_C] = param->qp;
639*abb65b4bSAndroid Build Coastguard Worker 
640*abb65b4bSAndroid Build Coastguard Worker     ctx->num_comp = get_num_comp(param->csp);
641*abb65b4bSAndroid Build Coastguard Worker 
642*abb65b4bSAndroid Build Coastguard Worker     if(param->preset == OAPV_PRESET_SLOW) {
643*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_block = enc_block_rdo_slow;
644*abb65b4bSAndroid Build Coastguard Worker     }
645*abb65b4bSAndroid Build Coastguard Worker     else if(param->preset == OAPV_PRESET_PLACEBO) {
646*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_block = enc_block_rdo_placebo;
647*abb65b4bSAndroid Build Coastguard Worker     }
648*abb65b4bSAndroid Build Coastguard Worker     else if(param->preset == OAPV_PRESET_MEDIUM) {
649*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_block = enc_block_rdo_medium;
650*abb65b4bSAndroid Build Coastguard Worker     }
651*abb65b4bSAndroid Build Coastguard Worker     else {
652*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_block = enc_block;
653*abb65b4bSAndroid Build Coastguard Worker     }
654*abb65b4bSAndroid Build Coastguard Worker 
655*abb65b4bSAndroid Build Coastguard Worker     ctx->log2_block = OAPV_LOG2_BLK;
656*abb65b4bSAndroid Build Coastguard Worker 
657*abb65b4bSAndroid Build Coastguard Worker     /* set various value */
658*abb65b4bSAndroid Build Coastguard Worker     ctx->w = ((ctx->param->w + (OAPV_MB_W - 1)) >> OAPV_LOG2_MB_W) << OAPV_LOG2_MB_W;
659*abb65b4bSAndroid Build Coastguard Worker     ctx->h = ((ctx->param->h + (OAPV_MB_H - 1)) >> OAPV_LOG2_MB_H) << OAPV_LOG2_MB_H;
660*abb65b4bSAndroid Build Coastguard Worker 
661*abb65b4bSAndroid Build Coastguard Worker     int tile_w = ctx->param->tile_w_mb * OAPV_MB_W;
662*abb65b4bSAndroid Build Coastguard Worker     int tile_h = ctx->param->tile_h_mb * OAPV_MB_H;
663*abb65b4bSAndroid Build Coastguard Worker     enc_set_tile_info(ctx->tile, ctx->w, ctx->h, tile_w, tile_h, &ctx->num_tile_cols, &ctx->num_tile_rows, &ctx->num_tiles);
664*abb65b4bSAndroid Build Coastguard Worker 
665*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
666*abb65b4bSAndroid Build Coastguard Worker }
667*abb65b4bSAndroid Build Coastguard Worker 
enc_flush(oapve_ctx_t * ctx)668*abb65b4bSAndroid Build Coastguard Worker static void enc_flush(oapve_ctx_t *ctx)
669*abb65b4bSAndroid Build Coastguard Worker {
670*abb65b4bSAndroid Build Coastguard Worker     // Release thread pool controller and created threads
671*abb65b4bSAndroid Build Coastguard Worker     if(ctx->cdesc.threads >= 1) {
672*abb65b4bSAndroid Build Coastguard Worker         if(ctx->tpool) {
673*abb65b4bSAndroid Build Coastguard Worker             // thread controller instance is present
674*abb65b4bSAndroid Build Coastguard Worker             // terminate the created thread
675*abb65b4bSAndroid Build Coastguard Worker             for(int i = 0; i < ctx->cdesc.threads; i++) {
676*abb65b4bSAndroid Build Coastguard Worker                 if(ctx->thread_id[i]) {
677*abb65b4bSAndroid Build Coastguard Worker                     // valid thread instance
678*abb65b4bSAndroid Build Coastguard Worker                     ctx->tpool->release(&ctx->thread_id[i]);
679*abb65b4bSAndroid Build Coastguard Worker                 }
680*abb65b4bSAndroid Build Coastguard Worker             }
681*abb65b4bSAndroid Build Coastguard Worker             // dinitialize the tc
682*abb65b4bSAndroid Build Coastguard Worker             oapv_tpool_deinit(ctx->tpool);
683*abb65b4bSAndroid Build Coastguard Worker             oapv_mfree_fast(ctx->tpool);
684*abb65b4bSAndroid Build Coastguard Worker             ctx->tpool = NULL;
685*abb65b4bSAndroid Build Coastguard Worker         }
686*abb65b4bSAndroid Build Coastguard Worker     }
687*abb65b4bSAndroid Build Coastguard Worker 
688*abb65b4bSAndroid Build Coastguard Worker     oapv_tpool_sync_obj_delete(&ctx->sync_obj);
689*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < ctx->cdesc.threads; i++) {
690*abb65b4bSAndroid Build Coastguard Worker         enc_core_free(ctx->core[i]);
691*abb65b4bSAndroid Build Coastguard Worker         ctx->core[i] = NULL;
692*abb65b4bSAndroid Build Coastguard Worker     }
693*abb65b4bSAndroid Build Coastguard Worker 
694*abb65b4bSAndroid Build Coastguard Worker     oapv_mfree_fast(ctx->tile[0].bs_buf);
695*abb65b4bSAndroid Build Coastguard Worker }
696*abb65b4bSAndroid Build Coastguard Worker 
enc_ready(oapve_ctx_t * ctx)697*abb65b4bSAndroid Build Coastguard Worker static int enc_ready(oapve_ctx_t *ctx)
698*abb65b4bSAndroid Build Coastguard Worker {
699*abb65b4bSAndroid Build Coastguard Worker     oapve_core_t *core = NULL;
700*abb65b4bSAndroid Build Coastguard Worker     int           ret = OAPV_OK;
701*abb65b4bSAndroid Build Coastguard Worker     oapv_assert(ctx->core[0] == NULL);
702*abb65b4bSAndroid Build Coastguard Worker 
703*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < ctx->cdesc.threads; i++) {
704*abb65b4bSAndroid Build Coastguard Worker         core = enc_core_alloc();
705*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_gv(core != NULL, ret, OAPV_ERR_OUT_OF_MEMORY, ERR);
706*abb65b4bSAndroid Build Coastguard Worker         ctx->core[i] = core;
707*abb65b4bSAndroid Build Coastguard Worker     }
708*abb65b4bSAndroid Build Coastguard Worker 
709*abb65b4bSAndroid Build Coastguard Worker     // initialize the threads to NULL
710*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < OAPV_MAX_THREADS; i++) {
711*abb65b4bSAndroid Build Coastguard Worker         ctx->thread_id[i] = 0;
712*abb65b4bSAndroid Build Coastguard Worker     }
713*abb65b4bSAndroid Build Coastguard Worker 
714*abb65b4bSAndroid Build Coastguard Worker     // get the context synchronization handle
715*abb65b4bSAndroid Build Coastguard Worker     ctx->sync_obj = oapv_tpool_sync_obj_create();
716*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_gv(ctx->sync_obj != NULL, ret, OAPV_ERR_UNKNOWN, ERR);
717*abb65b4bSAndroid Build Coastguard Worker 
718*abb65b4bSAndroid Build Coastguard Worker     if(ctx->cdesc.threads >= 1) {
719*abb65b4bSAndroid Build Coastguard Worker         ctx->tpool = oapv_malloc(sizeof(oapv_tpool_t));
720*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_init(ctx->tpool, ctx->cdesc.threads);
721*abb65b4bSAndroid Build Coastguard Worker         for(int i = 0; i < ctx->cdesc.threads; i++) {
722*abb65b4bSAndroid Build Coastguard Worker             ctx->thread_id[i] = ctx->tpool->create(ctx->tpool, i);
723*abb65b4bSAndroid Build Coastguard Worker             oapv_assert_gv(ctx->thread_id[i] != NULL, ret, OAPV_ERR_UNKNOWN, ERR);
724*abb65b4bSAndroid Build Coastguard Worker         }
725*abb65b4bSAndroid Build Coastguard Worker     }
726*abb65b4bSAndroid Build Coastguard Worker 
727*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < OAPV_MAX_TILES; i++) {
728*abb65b4bSAndroid Build Coastguard Worker         ctx->tile[i].stat = ENC_TILE_STAT_NOT_ENCODED;
729*abb65b4bSAndroid Build Coastguard Worker     }
730*abb65b4bSAndroid Build Coastguard Worker     ctx->tile[0].bs_buf = (u8 *)oapv_malloc(ctx->cdesc.max_bs_buf_size);
731*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_gv(ctx->tile[0].bs_buf, ret, OAPV_ERR_UNKNOWN, ERR);
732*abb65b4bSAndroid Build Coastguard Worker 
733*abb65b4bSAndroid Build Coastguard Worker     ctx->rc_param.alpha = OAPV_RC_ALPHA;
734*abb65b4bSAndroid Build Coastguard Worker     ctx->rc_param.beta = OAPV_RC_BETA;
735*abb65b4bSAndroid Build Coastguard Worker 
736*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
737*abb65b4bSAndroid Build Coastguard Worker ERR:
738*abb65b4bSAndroid Build Coastguard Worker 
739*abb65b4bSAndroid Build Coastguard Worker     enc_flush(ctx);
740*abb65b4bSAndroid Build Coastguard Worker 
741*abb65b4bSAndroid Build Coastguard Worker     return ret;
742*abb65b4bSAndroid Build Coastguard Worker }
743*abb65b4bSAndroid Build Coastguard Worker 
enc_tile_comp(oapv_bs_t * bs,oapve_tile_t * tile,oapve_ctx_t * ctx,oapve_core_t * core,int c,int s_org,void * org,int s_rec,void * rec)744*abb65b4bSAndroid Build Coastguard Worker static int enc_tile_comp(oapv_bs_t *bs, oapve_tile_t *tile, oapve_ctx_t *ctx, oapve_core_t *core, int c, int s_org, void *org, int s_rec, void *rec)
745*abb65b4bSAndroid Build Coastguard Worker {
746*abb65b4bSAndroid Build Coastguard Worker     int  mb_h, mb_w, mb_y, mb_x, blk_x, blk_y;
747*abb65b4bSAndroid Build Coastguard Worker     s16 *o16 = NULL, *r16 = NULL;
748*abb65b4bSAndroid Build Coastguard Worker 
749*abb65b4bSAndroid Build Coastguard Worker     u8  *bs_cur = oapv_bsw_sink(bs);
750*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(bsw_is_align8(bs), OAPV_ERR_MALFORMED_BITSTREAM);
751*abb65b4bSAndroid Build Coastguard Worker 
752*abb65b4bSAndroid Build Coastguard Worker     mb_w = OAPV_MB_W >> ctx->comp_sft[c][0];
753*abb65b4bSAndroid Build Coastguard Worker     mb_h = OAPV_MB_H >> ctx->comp_sft[c][1];
754*abb65b4bSAndroid Build Coastguard Worker 
755*abb65b4bSAndroid Build Coastguard Worker     int tile_le = tile->x >> ctx->comp_sft[c][0];
756*abb65b4bSAndroid Build Coastguard Worker     int tile_ri = (tile->w >> ctx->comp_sft[c][0]) + tile_le;
757*abb65b4bSAndroid Build Coastguard Worker     int tile_to = tile->y >> ctx->comp_sft[c][1];
758*abb65b4bSAndroid Build Coastguard Worker     int tile_bo = (tile->h >> ctx->comp_sft[c][1]) + tile_to;
759*abb65b4bSAndroid Build Coastguard Worker 
760*abb65b4bSAndroid Build Coastguard Worker     for(mb_y = tile_to; mb_y < tile_bo; mb_y += mb_h) {
761*abb65b4bSAndroid Build Coastguard Worker         for(mb_x = tile_le; mb_x < tile_ri; mb_x += mb_w) {
762*abb65b4bSAndroid Build Coastguard Worker             for(blk_y = mb_y; blk_y < (mb_y + mb_h); blk_y += OAPV_BLK_H) {
763*abb65b4bSAndroid Build Coastguard Worker                 for(blk_x = mb_x; blk_x < (mb_x + mb_w); blk_x += OAPV_BLK_W) {
764*abb65b4bSAndroid Build Coastguard Worker                     o16 = (s16 *)((u8 *)org + blk_y * s_org) + blk_x;
765*abb65b4bSAndroid Build Coastguard Worker                     ctx->fn_imgb_to_block[c](o16, OAPV_BLK_W, OAPV_BLK_H, s_org, blk_x, (OAPV_BLK_W << 1), core->coef);
766*abb65b4bSAndroid Build Coastguard Worker 
767*abb65b4bSAndroid Build Coastguard Worker                     ctx->fn_block(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c);
768*abb65b4bSAndroid Build Coastguard Worker                     oapve_vlc_dc_coeff(ctx, core, bs, core->coef[0], c);
769*abb65b4bSAndroid Build Coastguard Worker                     oapve_vlc_ac_coeff(ctx, core, bs, core->coef, 0, c);
770*abb65b4bSAndroid Build Coastguard Worker                     DUMP_COEF(core->coef, OAPV_BLK_D, blk_x, blk_y, c);
771*abb65b4bSAndroid Build Coastguard Worker 
772*abb65b4bSAndroid Build Coastguard Worker                     if(rec != NULL) {
773*abb65b4bSAndroid Build Coastguard Worker                         r16 = (s16 *)((u8 *)rec + blk_y * s_rec) + blk_x;
774*abb65b4bSAndroid Build Coastguard Worker                         ctx->fn_block_to_imgb[c](core->coef_rec, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_rec, r16);
775*abb65b4bSAndroid Build Coastguard Worker                     }
776*abb65b4bSAndroid Build Coastguard Worker                 }
777*abb65b4bSAndroid Build Coastguard Worker             }
778*abb65b4bSAndroid Build Coastguard Worker         }
779*abb65b4bSAndroid Build Coastguard Worker     }
780*abb65b4bSAndroid Build Coastguard Worker 
781*abb65b4bSAndroid Build Coastguard Worker     /* byte align */
782*abb65b4bSAndroid Build Coastguard Worker     while(!bsw_is_align8(bs)) {
783*abb65b4bSAndroid Build Coastguard Worker         oapv_bsw_write1(bs, 0);
784*abb65b4bSAndroid Build Coastguard Worker     }
785*abb65b4bSAndroid Build Coastguard Worker 
786*abb65b4bSAndroid Build Coastguard Worker     /* de-init BSW */
787*abb65b4bSAndroid Build Coastguard Worker     oapv_bsw_deinit(bs);
788*abb65b4bSAndroid Build Coastguard Worker 
789*abb65b4bSAndroid Build Coastguard Worker     return (int)(bs->cur - bs_cur);
790*abb65b4bSAndroid Build Coastguard Worker }
791*abb65b4bSAndroid Build Coastguard Worker 
enc_tile(oapve_ctx_t * ctx,oapve_core_t * core,oapve_tile_t * tile)792*abb65b4bSAndroid Build Coastguard Worker static int enc_tile(oapve_ctx_t *ctx, oapve_core_t *core, oapve_tile_t *tile)
793*abb65b4bSAndroid Build Coastguard Worker {
794*abb65b4bSAndroid Build Coastguard Worker     oapv_bs_t bs;
795*abb65b4bSAndroid Build Coastguard Worker     oapv_bsw_init(&bs, tile->bs_buf, tile->bs_buf_max, NULL);
796*abb65b4bSAndroid Build Coastguard Worker 
797*abb65b4bSAndroid Build Coastguard Worker     int qp = 0;
798*abb65b4bSAndroid Build Coastguard Worker     if(ctx->param->rc_type != 0) {
799*abb65b4bSAndroid Build Coastguard Worker         oapve_rc_get_qp(ctx, tile, ctx->qp[Y_C], &qp);
800*abb65b4bSAndroid Build Coastguard Worker         oapv_assert(qp != 0);
801*abb65b4bSAndroid Build Coastguard Worker     }
802*abb65b4bSAndroid Build Coastguard Worker     else {
803*abb65b4bSAndroid Build Coastguard Worker         qp = ctx->qp[Y_C];
804*abb65b4bSAndroid Build Coastguard Worker     }
805*abb65b4bSAndroid Build Coastguard Worker 
806*abb65b4bSAndroid Build Coastguard Worker     tile->tile_size = 0;
807*abb65b4bSAndroid Build Coastguard Worker     DUMP_SAVE(0);
808*abb65b4bSAndroid Build Coastguard Worker     oapve_vlc_tile_size(&bs, tile->tile_size);
809*abb65b4bSAndroid Build Coastguard Worker     oapve_set_tile_header(ctx, &tile->th, core->tile_idx, qp);
810*abb65b4bSAndroid Build Coastguard Worker     oapve_vlc_tile_header(ctx, &bs, &tile->th);
811*abb65b4bSAndroid Build Coastguard Worker 
812*abb65b4bSAndroid Build Coastguard Worker     for(int c = 0; c < ctx->num_comp; c++) {
813*abb65b4bSAndroid Build Coastguard Worker         int cnt = 0;
814*abb65b4bSAndroid Build Coastguard Worker         core->qp[c] = tile->th.tile_qp[c];
815*abb65b4bSAndroid Build Coastguard Worker         int qscale = oapv_quant_scale[core->qp[c] % 6];
816*abb65b4bSAndroid Build Coastguard Worker         s32 scale_multiply_16 = (s32)(qscale << 4); // 15bit + 4bit
817*abb65b4bSAndroid Build Coastguard Worker         for(int y = 0; y < OAPV_BLK_H; y++) {
818*abb65b4bSAndroid Build Coastguard Worker             for(int x = 0; x < OAPV_BLK_W; x++) {
819*abb65b4bSAndroid Build Coastguard Worker                 core->q_mat_enc[c][cnt++] = scale_multiply_16 / ctx->fh.q_matrix[c][y][x];
820*abb65b4bSAndroid Build Coastguard Worker             }
821*abb65b4bSAndroid Build Coastguard Worker         }
822*abb65b4bSAndroid Build Coastguard Worker 
823*abb65b4bSAndroid Build Coastguard Worker         if(ctx->rec || ctx->param->preset > OAPV_PRESET_MEDIUM) {
824*abb65b4bSAndroid Build Coastguard Worker             core->dq_shift[c] = ctx->bit_depth - 2 - (core->qp[c] / 6);
825*abb65b4bSAndroid Build Coastguard Worker 
826*abb65b4bSAndroid Build Coastguard Worker             int cnt = 0;
827*abb65b4bSAndroid Build Coastguard Worker             int dq_scale = oapv_tbl_dq_scale[core->qp[c] % 6];
828*abb65b4bSAndroid Build Coastguard Worker             for(int y = 0; y < OAPV_BLK_H; y++) {
829*abb65b4bSAndroid Build Coastguard Worker                 for(int x = 0; x < OAPV_BLK_W; x++) {
830*abb65b4bSAndroid Build Coastguard Worker                     core->q_mat_dec[c][cnt++] = dq_scale * ctx->fh.q_matrix[c][y][x];
831*abb65b4bSAndroid Build Coastguard Worker                 }
832*abb65b4bSAndroid Build Coastguard Worker             }
833*abb65b4bSAndroid Build Coastguard Worker         }
834*abb65b4bSAndroid Build Coastguard Worker     }
835*abb65b4bSAndroid Build Coastguard Worker 
836*abb65b4bSAndroid Build Coastguard Worker     for(int c = 0; c < ctx->num_comp; c++) {
837*abb65b4bSAndroid Build Coastguard Worker         core->prev_dc_ctx[c] = 20;
838*abb65b4bSAndroid Build Coastguard Worker         core->prev_1st_ac_ctx[c] = 0;
839*abb65b4bSAndroid Build Coastguard Worker         core->prev_dc[c] = 0;
840*abb65b4bSAndroid Build Coastguard Worker 
841*abb65b4bSAndroid Build Coastguard Worker         int  tc, s_org, s_rec;
842*abb65b4bSAndroid Build Coastguard Worker         s16 *org, *rec;
843*abb65b4bSAndroid Build Coastguard Worker 
844*abb65b4bSAndroid Build Coastguard Worker         if(OAPV_CS_GET_FORMAT(ctx->imgb->cs) == OAPV_CF_PLANAR2) {
845*abb65b4bSAndroid Build Coastguard Worker             tc = c > 0 ? 1 : 0;
846*abb65b4bSAndroid Build Coastguard Worker             org = ctx->imgb->a[tc];
847*abb65b4bSAndroid Build Coastguard Worker             org += (c > 1) ? 1 : 0;
848*abb65b4bSAndroid Build Coastguard Worker             s_org = ctx->imgb->s[tc];
849*abb65b4bSAndroid Build Coastguard Worker 
850*abb65b4bSAndroid Build Coastguard Worker             if(ctx->rec) {
851*abb65b4bSAndroid Build Coastguard Worker                 rec = ctx->rec->a[tc];
852*abb65b4bSAndroid Build Coastguard Worker                 rec += (c > 1) ? 1 : 0;
853*abb65b4bSAndroid Build Coastguard Worker                 s_rec = ctx->imgb->s[tc];
854*abb65b4bSAndroid Build Coastguard Worker             }
855*abb65b4bSAndroid Build Coastguard Worker             else {
856*abb65b4bSAndroid Build Coastguard Worker                 rec = NULL;
857*abb65b4bSAndroid Build Coastguard Worker                 s_rec = 0;
858*abb65b4bSAndroid Build Coastguard Worker             }
859*abb65b4bSAndroid Build Coastguard Worker         }
860*abb65b4bSAndroid Build Coastguard Worker         else {
861*abb65b4bSAndroid Build Coastguard Worker             org = ctx->imgb->a[c];
862*abb65b4bSAndroid Build Coastguard Worker             s_org = ctx->imgb->s[c];
863*abb65b4bSAndroid Build Coastguard Worker             if(ctx->rec) {
864*abb65b4bSAndroid Build Coastguard Worker                 rec = ctx->rec->a[c];
865*abb65b4bSAndroid Build Coastguard Worker                 s_rec = ctx->imgb->s[c];
866*abb65b4bSAndroid Build Coastguard Worker             }
867*abb65b4bSAndroid Build Coastguard Worker             else {
868*abb65b4bSAndroid Build Coastguard Worker                 rec = NULL;
869*abb65b4bSAndroid Build Coastguard Worker                 s_rec = 0;
870*abb65b4bSAndroid Build Coastguard Worker             }
871*abb65b4bSAndroid Build Coastguard Worker         }
872*abb65b4bSAndroid Build Coastguard Worker 
873*abb65b4bSAndroid Build Coastguard Worker         tile->th.tile_data_size[c] = enc_tile_comp(&bs, tile, ctx, core, c, s_org, org, s_rec, rec);
874*abb65b4bSAndroid Build Coastguard Worker     }
875*abb65b4bSAndroid Build Coastguard Worker 
876*abb65b4bSAndroid Build Coastguard Worker     u32 bs_size = (int)(bs.cur - bs.beg);
877*abb65b4bSAndroid Build Coastguard Worker     if(bs_size > tile->bs_buf_max) {
878*abb65b4bSAndroid Build Coastguard Worker         return OAPV_ERR_OUT_OF_BS_BUF;
879*abb65b4bSAndroid Build Coastguard Worker     }
880*abb65b4bSAndroid Build Coastguard Worker     tile->bs_size = bs_size;
881*abb65b4bSAndroid Build Coastguard Worker 
882*abb65b4bSAndroid Build Coastguard Worker     oapv_bs_t bs_th;
883*abb65b4bSAndroid Build Coastguard Worker     bs_th.is_bin_count = 0;
884*abb65b4bSAndroid Build Coastguard Worker     oapv_bsw_init(&bs_th, tile->bs_buf, tile->bs_size, NULL);
885*abb65b4bSAndroid Build Coastguard Worker     tile->tile_size = bs_size - OAPV_TILE_SIZE_LEN;
886*abb65b4bSAndroid Build Coastguard Worker 
887*abb65b4bSAndroid Build Coastguard Worker     DUMP_SAVE(1);
888*abb65b4bSAndroid Build Coastguard Worker     DUMP_LOAD(0);
889*abb65b4bSAndroid Build Coastguard Worker     oapve_vlc_tile_size(&bs_th, tile->tile_size);
890*abb65b4bSAndroid Build Coastguard Worker     oapve_vlc_tile_header(ctx, &bs_th, &tile->th);
891*abb65b4bSAndroid Build Coastguard Worker     DUMP_LOAD(1);
892*abb65b4bSAndroid Build Coastguard Worker     oapv_bsw_deinit(&bs_th);
893*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
894*abb65b4bSAndroid Build Coastguard Worker }
895*abb65b4bSAndroid Build Coastguard Worker 
enc_thread_tile(void * arg)896*abb65b4bSAndroid Build Coastguard Worker static int enc_thread_tile(void *arg)
897*abb65b4bSAndroid Build Coastguard Worker {
898*abb65b4bSAndroid Build Coastguard Worker     oapve_core_t *core = (oapve_core_t *)arg;
899*abb65b4bSAndroid Build Coastguard Worker     oapve_ctx_t  *ctx = core->ctx;
900*abb65b4bSAndroid Build Coastguard Worker     oapve_tile_t *tile = ctx->tile;
901*abb65b4bSAndroid Build Coastguard Worker     int           ret = OAPV_OK, i;
902*abb65b4bSAndroid Build Coastguard Worker 
903*abb65b4bSAndroid Build Coastguard Worker     while(1) {
904*abb65b4bSAndroid Build Coastguard Worker         // find not encoded tile
905*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_enter_cs(ctx->sync_obj);
906*abb65b4bSAndroid Build Coastguard Worker         for(i = 0; i < ctx->num_tiles; i++) {
907*abb65b4bSAndroid Build Coastguard Worker             if(tile[i].stat == ENC_TILE_STAT_NOT_ENCODED) {
908*abb65b4bSAndroid Build Coastguard Worker                 tile[i].stat = ENC_TILE_STAT_ON_ENCODING;
909*abb65b4bSAndroid Build Coastguard Worker                 core->tile_idx = i;
910*abb65b4bSAndroid Build Coastguard Worker                 break;
911*abb65b4bSAndroid Build Coastguard Worker             }
912*abb65b4bSAndroid Build Coastguard Worker         }
913*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_leave_cs(ctx->sync_obj);
914*abb65b4bSAndroid Build Coastguard Worker         if(i == ctx->num_tiles) {
915*abb65b4bSAndroid Build Coastguard Worker             break;
916*abb65b4bSAndroid Build Coastguard Worker         }
917*abb65b4bSAndroid Build Coastguard Worker 
918*abb65b4bSAndroid Build Coastguard Worker         ret = enc_tile(ctx, core, &tile[core->tile_idx]);
919*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
920*abb65b4bSAndroid Build Coastguard Worker 
921*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_enter_cs(ctx->sync_obj);
922*abb65b4bSAndroid Build Coastguard Worker         tile[core->tile_idx].stat = ENC_TILE_STAT_ENCODED;
923*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_leave_cs(ctx->sync_obj);
924*abb65b4bSAndroid Build Coastguard Worker     }
925*abb65b4bSAndroid Build Coastguard Worker ERR:
926*abb65b4bSAndroid Build Coastguard Worker     return ret;
927*abb65b4bSAndroid Build Coastguard Worker }
928*abb65b4bSAndroid Build Coastguard Worker 
enc_img_pad_p210(oapve_ctx_t * ctx,oapv_imgb_t * imgb)929*abb65b4bSAndroid Build Coastguard Worker static void enc_img_pad_p210(oapve_ctx_t *ctx, oapv_imgb_t *imgb)
930*abb65b4bSAndroid Build Coastguard Worker {
931*abb65b4bSAndroid Build Coastguard Worker     if(ctx->w == ctx->param->w && ctx->h == ctx->param->h) {
932*abb65b4bSAndroid Build Coastguard Worker         return;
933*abb65b4bSAndroid Build Coastguard Worker     }
934*abb65b4bSAndroid Build Coastguard Worker 
935*abb65b4bSAndroid Build Coastguard Worker     if(ctx->w != ctx->param->w) {
936*abb65b4bSAndroid Build Coastguard Worker         for(int c = 0; c < imgb->np; c++) {
937*abb65b4bSAndroid Build Coastguard Worker             int  shift_w = 0;
938*abb65b4bSAndroid Build Coastguard Worker             int  shift_h = 0;
939*abb65b4bSAndroid Build Coastguard Worker 
940*abb65b4bSAndroid Build Coastguard Worker             int  sw = ctx->param->w >> shift_w;
941*abb65b4bSAndroid Build Coastguard Worker             int  ew = ctx->w >> shift_w;
942*abb65b4bSAndroid Build Coastguard Worker             int  th = ctx->h >> shift_h;
943*abb65b4bSAndroid Build Coastguard Worker             pel *dst = (pel *)imgb->a[c];
944*abb65b4bSAndroid Build Coastguard Worker             pel  src;
945*abb65b4bSAndroid Build Coastguard Worker 
946*abb65b4bSAndroid Build Coastguard Worker             for(int h = 0; h < th; h++) {
947*abb65b4bSAndroid Build Coastguard Worker                 src = dst[sw - 1];
948*abb65b4bSAndroid Build Coastguard Worker                 for(int w = sw; w < ew; w++) {
949*abb65b4bSAndroid Build Coastguard Worker                     dst[w] = src;
950*abb65b4bSAndroid Build Coastguard Worker                 }
951*abb65b4bSAndroid Build Coastguard Worker                 dst += (imgb->s[c] >> 1);
952*abb65b4bSAndroid Build Coastguard Worker             }
953*abb65b4bSAndroid Build Coastguard Worker         }
954*abb65b4bSAndroid Build Coastguard Worker     }
955*abb65b4bSAndroid Build Coastguard Worker 
956*abb65b4bSAndroid Build Coastguard Worker     if(ctx->h != ctx->param->h) {
957*abb65b4bSAndroid Build Coastguard Worker         for(int c = 0; c < imgb->np; c++) {
958*abb65b4bSAndroid Build Coastguard Worker             int  shift_w = 0;
959*abb65b4bSAndroid Build Coastguard Worker             int  shift_h = 0;
960*abb65b4bSAndroid Build Coastguard Worker 
961*abb65b4bSAndroid Build Coastguard Worker             int  sh = ctx->param->h >> shift_h;
962*abb65b4bSAndroid Build Coastguard Worker             int  eh = ctx->h >> shift_h;
963*abb65b4bSAndroid Build Coastguard Worker             int  tw = ctx->w >> shift_w;
964*abb65b4bSAndroid Build Coastguard Worker             pel *dst = ((pel *)imgb->a[c]) + sh * (imgb->s[c] >> 1);
965*abb65b4bSAndroid Build Coastguard Worker             pel *src = dst - (imgb->s[c] >> 1);
966*abb65b4bSAndroid Build Coastguard Worker 
967*abb65b4bSAndroid Build Coastguard Worker             for(int h = sh; h < eh; h++) {
968*abb65b4bSAndroid Build Coastguard Worker                 oapv_mcpy(dst, src, sizeof(pel) * tw);
969*abb65b4bSAndroid Build Coastguard Worker                 dst += (imgb->s[c] >> 1);
970*abb65b4bSAndroid Build Coastguard Worker             }
971*abb65b4bSAndroid Build Coastguard Worker         }
972*abb65b4bSAndroid Build Coastguard Worker     }
973*abb65b4bSAndroid Build Coastguard Worker }
enc_img_pad(oapve_ctx_t * ctx,oapv_imgb_t * imgb)974*abb65b4bSAndroid Build Coastguard Worker static void enc_img_pad(oapve_ctx_t *ctx, oapv_imgb_t *imgb)
975*abb65b4bSAndroid Build Coastguard Worker {
976*abb65b4bSAndroid Build Coastguard Worker     if(ctx->w == ctx->param->w && ctx->h == ctx->param->h) {
977*abb65b4bSAndroid Build Coastguard Worker         return;
978*abb65b4bSAndroid Build Coastguard Worker     }
979*abb65b4bSAndroid Build Coastguard Worker 
980*abb65b4bSAndroid Build Coastguard Worker     if(ctx->w != ctx->param->w) {
981*abb65b4bSAndroid Build Coastguard Worker         for(int c = 0; c < imgb->np; c++) {
982*abb65b4bSAndroid Build Coastguard Worker             int  sw = ctx->param->w >> ctx->comp_sft[c][0];
983*abb65b4bSAndroid Build Coastguard Worker             int  ew = ctx->w >> ctx->comp_sft[c][0];
984*abb65b4bSAndroid Build Coastguard Worker             int  th = ctx->h >> ctx->comp_sft[c][1];
985*abb65b4bSAndroid Build Coastguard Worker             pel *dst = (pel *)imgb->a[c];
986*abb65b4bSAndroid Build Coastguard Worker             pel  src;
987*abb65b4bSAndroid Build Coastguard Worker 
988*abb65b4bSAndroid Build Coastguard Worker             for(int h = 0; h < th; h++) {
989*abb65b4bSAndroid Build Coastguard Worker                 src = dst[sw - 1];
990*abb65b4bSAndroid Build Coastguard Worker                 for(int w = sw; w < ew; w++) {
991*abb65b4bSAndroid Build Coastguard Worker                     dst[w] = src;
992*abb65b4bSAndroid Build Coastguard Worker                 }
993*abb65b4bSAndroid Build Coastguard Worker                 dst += (imgb->s[c] >> 1);
994*abb65b4bSAndroid Build Coastguard Worker             }
995*abb65b4bSAndroid Build Coastguard Worker         }
996*abb65b4bSAndroid Build Coastguard Worker     }
997*abb65b4bSAndroid Build Coastguard Worker 
998*abb65b4bSAndroid Build Coastguard Worker     if(ctx->h != ctx->param->h) {
999*abb65b4bSAndroid Build Coastguard Worker         for(int c = 0; c < imgb->np; c++) {
1000*abb65b4bSAndroid Build Coastguard Worker             int  sh = ctx->param->h >> ctx->comp_sft[c][1];
1001*abb65b4bSAndroid Build Coastguard Worker             int  eh = ctx->h >> ctx->comp_sft[c][1];
1002*abb65b4bSAndroid Build Coastguard Worker             int  tw = ctx->w >> ctx->comp_sft[c][0];
1003*abb65b4bSAndroid Build Coastguard Worker             pel *dst = ((pel *)imgb->a[c]) + sh * (imgb->s[c] >> 1);
1004*abb65b4bSAndroid Build Coastguard Worker             pel *src = dst - (imgb->s[c] >> 1);
1005*abb65b4bSAndroid Build Coastguard Worker 
1006*abb65b4bSAndroid Build Coastguard Worker             for(int h = sh; h < eh; h++) {
1007*abb65b4bSAndroid Build Coastguard Worker                 oapv_mcpy(dst, src, sizeof(pel) * tw);
1008*abb65b4bSAndroid Build Coastguard Worker                 dst += (imgb->s[c] >> 1);
1009*abb65b4bSAndroid Build Coastguard Worker             }
1010*abb65b4bSAndroid Build Coastguard Worker         }
1011*abb65b4bSAndroid Build Coastguard Worker     }
1012*abb65b4bSAndroid Build Coastguard Worker }
1013*abb65b4bSAndroid Build Coastguard Worker 
enc_frm_prepare(oapve_ctx_t * ctx,oapv_imgb_t * imgb_i,oapv_imgb_t * imgb_r)1014*abb65b4bSAndroid Build Coastguard Worker static int enc_frm_prepare(oapve_ctx_t *ctx, oapv_imgb_t *imgb_i, oapv_imgb_t *imgb_r)
1015*abb65b4bSAndroid Build Coastguard Worker {
1016*abb65b4bSAndroid Build Coastguard Worker     ctx->cfi = color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb_i->cs));
1017*abb65b4bSAndroid Build Coastguard Worker     ctx->num_comp = get_num_comp(ctx->cfi);
1018*abb65b4bSAndroid Build Coastguard Worker 
1019*abb65b4bSAndroid Build Coastguard Worker     ctx->comp_sft[Y_C][0] = 0;
1020*abb65b4bSAndroid Build Coastguard Worker     ctx->comp_sft[Y_C][1] = 0;
1021*abb65b4bSAndroid Build Coastguard Worker     for(int c = 1; c < ctx->num_comp; c++) {
1022*abb65b4bSAndroid Build Coastguard Worker         ctx->comp_sft[c][0] = get_chroma_sft_w(ctx->cfi);
1023*abb65b4bSAndroid Build Coastguard Worker         ctx->comp_sft[c][1] = get_chroma_sft_h(ctx->cfi);
1024*abb65b4bSAndroid Build Coastguard Worker     }
1025*abb65b4bSAndroid Build Coastguard Worker 
1026*abb65b4bSAndroid Build Coastguard Worker     ctx->bit_depth = OAPV_CS_GET_BIT_DEPTH(imgb_i->cs);
1027*abb65b4bSAndroid Build Coastguard Worker 
1028*abb65b4bSAndroid Build Coastguard Worker     if(OAPV_CS_GET_FORMAT(imgb_i->cs) == OAPV_CF_PLANAR2) {
1029*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_imgb_to_block_rc = imgb_to_block_p210;
1030*abb65b4bSAndroid Build Coastguard Worker 
1031*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_imgb_to_block[Y_C] = imgb_to_block_p210_y;
1032*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_imgb_to_block[U_C] = imgb_to_block_p210_uv;
1033*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_imgb_to_block[V_C] = imgb_to_block_p210_uv;
1034*abb65b4bSAndroid Build Coastguard Worker 
1035*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_block_to_imgb[Y_C] = block_to_imgb_p210_y;
1036*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_block_to_imgb[U_C] = block_to_imgb_p210_uv;
1037*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_block_to_imgb[V_C] = block_to_imgb_p210_uv;
1038*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_img_pad = enc_img_pad_p210;
1039*abb65b4bSAndroid Build Coastguard Worker     }
1040*abb65b4bSAndroid Build Coastguard Worker     else {
1041*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_imgb_to_block_rc = imgb_to_block;
1042*abb65b4bSAndroid Build Coastguard Worker         for(int i = 0; i < ctx->num_comp; i++) {
1043*abb65b4bSAndroid Build Coastguard Worker             ctx->fn_imgb_to_block[i] = imgb_to_block_10bit;
1044*abb65b4bSAndroid Build Coastguard Worker             ctx->fn_block_to_imgb[i] = block_to_imgb_10bit;
1045*abb65b4bSAndroid Build Coastguard Worker         }
1046*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_img_pad = enc_img_pad;
1047*abb65b4bSAndroid Build Coastguard Worker     }
1048*abb65b4bSAndroid Build Coastguard Worker 
1049*abb65b4bSAndroid Build Coastguard Worker     /* initialize bitstream container */
1050*abb65b4bSAndroid Build Coastguard Worker     // oapv_bsw_init(&ctx->bs, bitb->addr, bitb->bsize, NULL); // TODO : remove
1051*abb65b4bSAndroid Build Coastguard Worker     ctx->w = (imgb_i->aw[Y_C] > 0) ? imgb_i->aw[Y_C] : imgb_i->w[Y_C];
1052*abb65b4bSAndroid Build Coastguard Worker     ctx->h = (imgb_i->ah[Y_C] > 0) ? imgb_i->ah[Y_C] : imgb_i->h[Y_C];
1053*abb65b4bSAndroid Build Coastguard Worker 
1054*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_img_pad(ctx, imgb_i);
1055*abb65b4bSAndroid Build Coastguard Worker 
1056*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < ctx->num_tiles; i++) {
1057*abb65b4bSAndroid Build Coastguard Worker         ctx->tile[i].stat = ENC_TILE_STAT_NOT_ENCODED;
1058*abb65b4bSAndroid Build Coastguard Worker     }
1059*abb65b4bSAndroid Build Coastguard Worker 
1060*abb65b4bSAndroid Build Coastguard Worker     ctx->imgb = imgb_i;
1061*abb65b4bSAndroid Build Coastguard Worker     imgb_addref(ctx->imgb);
1062*abb65b4bSAndroid Build Coastguard Worker     if(imgb_r != NULL) {
1063*abb65b4bSAndroid Build Coastguard Worker         for(int c = 0; c < ctx->num_comp; c++) {
1064*abb65b4bSAndroid Build Coastguard Worker             imgb_r->w[c] = imgb_i->w[c];
1065*abb65b4bSAndroid Build Coastguard Worker             imgb_r->h[c] = imgb_i->h[c];
1066*abb65b4bSAndroid Build Coastguard Worker             imgb_r->x[c] = imgb_i->x[c];
1067*abb65b4bSAndroid Build Coastguard Worker             imgb_r->y[c] = imgb_i->y[c];
1068*abb65b4bSAndroid Build Coastguard Worker         }
1069*abb65b4bSAndroid Build Coastguard Worker         ctx->rec = imgb_r;
1070*abb65b4bSAndroid Build Coastguard Worker         imgb_addref(ctx->rec);
1071*abb65b4bSAndroid Build Coastguard Worker     }
1072*abb65b4bSAndroid Build Coastguard Worker 
1073*abb65b4bSAndroid Build Coastguard Worker     int buf_size = ctx->cdesc.max_bs_buf_size / ctx->num_tiles;
1074*abb65b4bSAndroid Build Coastguard Worker     ctx->tile[0].bs_buf_max = buf_size;
1075*abb65b4bSAndroid Build Coastguard Worker     for(int i = 1; i < ctx->num_tiles; i++) {
1076*abb65b4bSAndroid Build Coastguard Worker         ctx->tile[i].bs_buf = ctx->tile[i - 1].bs_buf + buf_size;
1077*abb65b4bSAndroid Build Coastguard Worker         ctx->tile[i].bs_buf_max = buf_size;
1078*abb65b4bSAndroid Build Coastguard Worker     }
1079*abb65b4bSAndroid Build Coastguard Worker 
1080*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < ctx->cdesc.threads; i++) {
1081*abb65b4bSAndroid Build Coastguard Worker         ctx->core[i]->ctx = ctx;
1082*abb65b4bSAndroid Build Coastguard Worker         ctx->core[i]->thread_idx = i;
1083*abb65b4bSAndroid Build Coastguard Worker     }
1084*abb65b4bSAndroid Build Coastguard Worker 
1085*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1086*abb65b4bSAndroid Build Coastguard Worker }
1087*abb65b4bSAndroid Build Coastguard Worker 
enc_frm_finish(oapve_ctx_t * ctx,oapve_stat_t * stat)1088*abb65b4bSAndroid Build Coastguard Worker static int enc_frm_finish(oapve_ctx_t *ctx, oapve_stat_t *stat)
1089*abb65b4bSAndroid Build Coastguard Worker {
1090*abb65b4bSAndroid Build Coastguard Worker     imgb_release(ctx->imgb);
1091*abb65b4bSAndroid Build Coastguard Worker     if(ctx->rec) {
1092*abb65b4bSAndroid Build Coastguard Worker         imgb_release(ctx->rec);
1093*abb65b4bSAndroid Build Coastguard Worker         ctx->rec = NULL;
1094*abb65b4bSAndroid Build Coastguard Worker     }
1095*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1096*abb65b4bSAndroid Build Coastguard Worker }
1097*abb65b4bSAndroid Build Coastguard Worker 
enc_frame(oapve_ctx_t * ctx)1098*abb65b4bSAndroid Build Coastguard Worker static int enc_frame(oapve_ctx_t *ctx)
1099*abb65b4bSAndroid Build Coastguard Worker {
1100*abb65b4bSAndroid Build Coastguard Worker     oapv_bs_t *bs = &ctx->bs;
1101*abb65b4bSAndroid Build Coastguard Worker     int        ret = OAPV_OK;
1102*abb65b4bSAndroid Build Coastguard Worker 
1103*abb65b4bSAndroid Build Coastguard Worker     oapv_bs_t  bs_fh;
1104*abb65b4bSAndroid Build Coastguard Worker     oapv_mcpy(&bs_fh, bs, sizeof(oapv_bs_t));
1105*abb65b4bSAndroid Build Coastguard Worker 
1106*abb65b4bSAndroid Build Coastguard Worker     /* write frame header */
1107*abb65b4bSAndroid Build Coastguard Worker     oapve_set_frame_header(ctx, &ctx->fh);
1108*abb65b4bSAndroid Build Coastguard Worker     oapve_vlc_frame_header(bs, ctx, &ctx->fh);
1109*abb65b4bSAndroid Build Coastguard Worker 
1110*abb65b4bSAndroid Build Coastguard Worker     /* de-init BSW */
1111*abb65b4bSAndroid Build Coastguard Worker     oapv_bsw_deinit(bs);
1112*abb65b4bSAndroid Build Coastguard Worker 
1113*abb65b4bSAndroid Build Coastguard Worker     /* rc init */
1114*abb65b4bSAndroid Build Coastguard Worker     u64 cost_sum = 0;
1115*abb65b4bSAndroid Build Coastguard Worker     if(ctx->param->rc_type != 0) {
1116*abb65b4bSAndroid Build Coastguard Worker         oapve_rc_get_tile_cost_thread(ctx, &cost_sum);
1117*abb65b4bSAndroid Build Coastguard Worker 
1118*abb65b4bSAndroid Build Coastguard Worker         double bits_pic = ((double)ctx->param->bitrate * 1000) / ((double)ctx->param->fps_num / ctx->param->fps_den);
1119*abb65b4bSAndroid Build Coastguard Worker         for(int i = 0; i < ctx->num_tiles; i++) {
1120*abb65b4bSAndroid Build Coastguard Worker             ctx->tile[i].rc.target_bits_left = bits_pic * ctx->tile[i].rc.cost / cost_sum;
1121*abb65b4bSAndroid Build Coastguard Worker             ctx->tile[i].rc.target_bits = ctx->tile[i].rc.target_bits_left;
1122*abb65b4bSAndroid Build Coastguard Worker         }
1123*abb65b4bSAndroid Build Coastguard Worker 
1124*abb65b4bSAndroid Build Coastguard Worker         ctx->rc_param.lambda = oapve_rc_estimate_pic_lambda(ctx, cost_sum);
1125*abb65b4bSAndroid Build Coastguard Worker         ctx->rc_param.qp = oapve_rc_estimate_pic_qp(ctx->rc_param.lambda);
1126*abb65b4bSAndroid Build Coastguard Worker         for(int c = 0; c < ctx->num_comp; c++) {
1127*abb65b4bSAndroid Build Coastguard Worker             ctx->qp[c] = ctx->rc_param.qp;
1128*abb65b4bSAndroid Build Coastguard Worker             if(c == 1) {
1129*abb65b4bSAndroid Build Coastguard Worker                 ctx->qp[c] += ctx->param->qp_cb_offset;
1130*abb65b4bSAndroid Build Coastguard Worker             }
1131*abb65b4bSAndroid Build Coastguard Worker             else if(c == 2) {
1132*abb65b4bSAndroid Build Coastguard Worker                 ctx->qp[c] += ctx->param->qp_cr_offset;
1133*abb65b4bSAndroid Build Coastguard Worker             }
1134*abb65b4bSAndroid Build Coastguard Worker         }
1135*abb65b4bSAndroid Build Coastguard Worker     }
1136*abb65b4bSAndroid Build Coastguard Worker 
1137*abb65b4bSAndroid Build Coastguard Worker     oapv_tpool_t *tpool = ctx->tpool;
1138*abb65b4bSAndroid Build Coastguard Worker     int           res, tidx = 0, thread_num1 = 0;
1139*abb65b4bSAndroid Build Coastguard Worker     int           parallel_task = (ctx->cdesc.threads > ctx->num_tiles) ? ctx->num_tiles : ctx->cdesc.threads;
1140*abb65b4bSAndroid Build Coastguard Worker 
1141*abb65b4bSAndroid Build Coastguard Worker     /* encode tiles ************************************/
1142*abb65b4bSAndroid Build Coastguard Worker     for(tidx = 0; tidx < (parallel_task - 1); tidx++) {
1143*abb65b4bSAndroid Build Coastguard Worker         tpool->run(ctx->thread_id[tidx], enc_thread_tile,
1144*abb65b4bSAndroid Build Coastguard Worker                    (void *)ctx->core[tidx]);
1145*abb65b4bSAndroid Build Coastguard Worker     }
1146*abb65b4bSAndroid Build Coastguard Worker     ret = enc_thread_tile((void *)ctx->core[tidx]);
1147*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
1148*abb65b4bSAndroid Build Coastguard Worker 
1149*abb65b4bSAndroid Build Coastguard Worker     for(thread_num1 = 0; thread_num1 < parallel_task - 1; thread_num1++) {
1150*abb65b4bSAndroid Build Coastguard Worker         res = tpool->join(ctx->thread_id[thread_num1], &ret);
1151*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_gv(res == TPOOL_SUCCESS, ret, OAPV_ERR_FAILED_SYSCALL, ERR);
1152*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
1153*abb65b4bSAndroid Build Coastguard Worker     }
1154*abb65b4bSAndroid Build Coastguard Worker     /****************************************************/
1155*abb65b4bSAndroid Build Coastguard Worker 
1156*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < ctx->num_tiles; i++) {
1157*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(ctx->bs.cur, ctx->tile[i].bs_buf, ctx->tile[i].bs_size);
1158*abb65b4bSAndroid Build Coastguard Worker         ctx->bs.cur = ctx->bs.cur + ctx->tile[i].bs_size;
1159*abb65b4bSAndroid Build Coastguard Worker         ctx->fh.tile_size[i] = ctx->tile[i].bs_size - OAPV_TILE_SIZE_LEN;
1160*abb65b4bSAndroid Build Coastguard Worker     }
1161*abb65b4bSAndroid Build Coastguard Worker 
1162*abb65b4bSAndroid Build Coastguard Worker     /* rewrite frame header */
1163*abb65b4bSAndroid Build Coastguard Worker     if(ctx->fh.tile_size_present_in_fh_flag) {
1164*abb65b4bSAndroid Build Coastguard Worker         oapve_vlc_frame_header(&bs_fh, ctx, &ctx->fh);
1165*abb65b4bSAndroid Build Coastguard Worker     }
1166*abb65b4bSAndroid Build Coastguard Worker     if(ctx->param->rc_type != 0) {
1167*abb65b4bSAndroid Build Coastguard Worker         oapve_rc_update_after_pic(ctx, cost_sum);
1168*abb65b4bSAndroid Build Coastguard Worker     }
1169*abb65b4bSAndroid Build Coastguard Worker     return ret;
1170*abb65b4bSAndroid Build Coastguard Worker 
1171*abb65b4bSAndroid Build Coastguard Worker ERR:
1172*abb65b4bSAndroid Build Coastguard Worker     return ret;
1173*abb65b4bSAndroid Build Coastguard Worker }
1174*abb65b4bSAndroid Build Coastguard Worker 
enc_platform_init(oapve_ctx_t * ctx)1175*abb65b4bSAndroid Build Coastguard Worker static int enc_platform_init(oapve_ctx_t *ctx)
1176*abb65b4bSAndroid Build Coastguard Worker {
1177*abb65b4bSAndroid Build Coastguard Worker     // default settings
1178*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_sad = oapv_tbl_fn_sad_16b;
1179*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_ssd = oapv_tbl_fn_ssd_16b;
1180*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_diff = oapv_tbl_fn_diff_16b;
1181*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_itx_part = oapv_tbl_fn_itx_part;
1182*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_itx = oapv_tbl_fn_itx;
1183*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_itx_adj = oapv_tbl_fn_itx_adj;
1184*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_txb = oapv_tbl_fn_tx;
1185*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_quant = oapv_tbl_fn_quant;
1186*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_dquant = oapv_tbl_fn_dquant;
1187*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_had8x8 = oapv_dc_removed_had8x8;
1188*abb65b4bSAndroid Build Coastguard Worker #if X86_SSE
1189*abb65b4bSAndroid Build Coastguard Worker     int check_cpu, support_sse, support_avx2;
1190*abb65b4bSAndroid Build Coastguard Worker 
1191*abb65b4bSAndroid Build Coastguard Worker     check_cpu = oapv_check_cpu_info_x86();
1192*abb65b4bSAndroid Build Coastguard Worker     support_sse = (check_cpu >> 0) & 1;
1193*abb65b4bSAndroid Build Coastguard Worker     support_avx2 = (check_cpu >> 2) & 1;
1194*abb65b4bSAndroid Build Coastguard Worker 
1195*abb65b4bSAndroid Build Coastguard Worker     if(support_avx2) {
1196*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_ssd = oapv_tbl_fn_ssd_16b_avx;
1197*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_itx_part = oapv_tbl_fn_itx_part_avx;
1198*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_itx = oapv_tbl_fn_itx_avx;
1199*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_itx_adj = oapv_tbl_fn_itx_adj_avx;
1200*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_txb = oapv_tbl_fn_txb_avx;
1201*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_quant = oapv_tbl_fn_quant_avx;
1202*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_dquant = oapv_tbl_fn_dquant_avx;
1203*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_had8x8 = oapv_dc_removed_had8x8_sse;
1204*abb65b4bSAndroid Build Coastguard Worker     }
1205*abb65b4bSAndroid Build Coastguard Worker     else if(support_sse) {
1206*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_ssd = oapv_tbl_fn_ssd_16b_sse;
1207*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_had8x8 = oapv_dc_removed_had8x8_sse;
1208*abb65b4bSAndroid Build Coastguard Worker     }
1209*abb65b4bSAndroid Build Coastguard Worker #elif ARM_NEON
1210*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_ssd = oapv_tbl_fn_ssd_16b_neon;
1211*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_itx = oapv_tbl_fn_itx_neon;
1212*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_txb = oapv_tbl_fn_txb_neon;
1213*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_quant = oapv_tbl_fn_quant_neon;
1214*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_had8x8 = oapv_dc_removed_had8x8;
1215*abb65b4bSAndroid Build Coastguard Worker #endif
1216*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1217*abb65b4bSAndroid Build Coastguard Worker }
1218*abb65b4bSAndroid Build Coastguard Worker 
oapve_create(oapve_cdesc_t * cdesc,int * err)1219*abb65b4bSAndroid Build Coastguard Worker oapve_t oapve_create(oapve_cdesc_t *cdesc, int *err)
1220*abb65b4bSAndroid Build Coastguard Worker {
1221*abb65b4bSAndroid Build Coastguard Worker     oapve_ctx_t *ctx;
1222*abb65b4bSAndroid Build Coastguard Worker     int          ret;
1223*abb65b4bSAndroid Build Coastguard Worker 
1224*abb65b4bSAndroid Build Coastguard Worker     DUMP_CREATE(1);
1225*abb65b4bSAndroid Build Coastguard Worker     /* memory allocation for ctx and core structure */
1226*abb65b4bSAndroid Build Coastguard Worker     ctx = (oapve_ctx_t *)enc_ctx_alloc();
1227*abb65b4bSAndroid Build Coastguard Worker     if(ctx != NULL) {
1228*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(&ctx->cdesc, cdesc, sizeof(oapve_cdesc_t));
1229*abb65b4bSAndroid Build Coastguard Worker         ret = enc_platform_init(ctx);
1230*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_g(ret == OAPV_OK, ERR);
1231*abb65b4bSAndroid Build Coastguard Worker 
1232*abb65b4bSAndroid Build Coastguard Worker         ret = enc_ready(ctx);
1233*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_g(ret == OAPV_OK, ERR);
1234*abb65b4bSAndroid Build Coastguard Worker 
1235*abb65b4bSAndroid Build Coastguard Worker         /* set default value for ctx */
1236*abb65b4bSAndroid Build Coastguard Worker         ctx->magic = OAPVE_MAGIC_CODE;
1237*abb65b4bSAndroid Build Coastguard Worker         ctx->id = (oapve_t)ctx;
1238*abb65b4bSAndroid Build Coastguard Worker         if(err) {
1239*abb65b4bSAndroid Build Coastguard Worker             *err = OAPV_OK;
1240*abb65b4bSAndroid Build Coastguard Worker         }
1241*abb65b4bSAndroid Build Coastguard Worker         return (ctx->id);
1242*abb65b4bSAndroid Build Coastguard Worker     }
1243*abb65b4bSAndroid Build Coastguard Worker     else {
1244*abb65b4bSAndroid Build Coastguard Worker         ret = OAPV_ERR;
1245*abb65b4bSAndroid Build Coastguard Worker     }
1246*abb65b4bSAndroid Build Coastguard Worker ERR:
1247*abb65b4bSAndroid Build Coastguard Worker     if(ctx) {
1248*abb65b4bSAndroid Build Coastguard Worker         enc_ctx_free(ctx);
1249*abb65b4bSAndroid Build Coastguard Worker     }
1250*abb65b4bSAndroid Build Coastguard Worker     if(err) {
1251*abb65b4bSAndroid Build Coastguard Worker         *err = ret;
1252*abb65b4bSAndroid Build Coastguard Worker     }
1253*abb65b4bSAndroid Build Coastguard Worker     return NULL;
1254*abb65b4bSAndroid Build Coastguard Worker }
1255*abb65b4bSAndroid Build Coastguard Worker 
oapve_delete(oapve_t eid)1256*abb65b4bSAndroid Build Coastguard Worker void oapve_delete(oapve_t eid)
1257*abb65b4bSAndroid Build Coastguard Worker {
1258*abb65b4bSAndroid Build Coastguard Worker     oapve_ctx_t *ctx;
1259*abb65b4bSAndroid Build Coastguard Worker 
1260*abb65b4bSAndroid Build Coastguard Worker     ctx = enc_id_to_ctx(eid);
1261*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_r(ctx);
1262*abb65b4bSAndroid Build Coastguard Worker 
1263*abb65b4bSAndroid Build Coastguard Worker     DUMP_DELETE();
1264*abb65b4bSAndroid Build Coastguard Worker     enc_flush(ctx);
1265*abb65b4bSAndroid Build Coastguard Worker     enc_ctx_free(ctx);
1266*abb65b4bSAndroid Build Coastguard Worker }
1267*abb65b4bSAndroid Build Coastguard Worker 
oapve_encode(oapve_t eid,oapv_frms_t * ifrms,oapvm_t mid,oapv_bitb_t * bitb,oapve_stat_t * stat,oapv_frms_t * rfrms)1268*abb65b4bSAndroid Build Coastguard Worker int oapve_encode(oapve_t eid, oapv_frms_t *ifrms, oapvm_t mid, oapv_bitb_t *bitb, oapve_stat_t *stat, oapv_frms_t *rfrms)
1269*abb65b4bSAndroid Build Coastguard Worker {
1270*abb65b4bSAndroid Build Coastguard Worker     oapve_ctx_t *ctx;
1271*abb65b4bSAndroid Build Coastguard Worker     oapv_frm_t  *frm;
1272*abb65b4bSAndroid Build Coastguard Worker     oapv_bs_t   *bs;
1273*abb65b4bSAndroid Build Coastguard Worker     int          i, ret;
1274*abb65b4bSAndroid Build Coastguard Worker 
1275*abb65b4bSAndroid Build Coastguard Worker     ctx = enc_id_to_ctx(eid);
1276*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(ctx != NULL && bitb->addr && bitb->bsize > 0, OAPV_ERR_INVALID_ARGUMENT);
1277*abb65b4bSAndroid Build Coastguard Worker 
1278*abb65b4bSAndroid Build Coastguard Worker     bs = &ctx->bs;
1279*abb65b4bSAndroid Build Coastguard Worker 
1280*abb65b4bSAndroid Build Coastguard Worker     oapv_bsw_init(bs, bitb->addr, bitb->bsize, NULL);
1281*abb65b4bSAndroid Build Coastguard Worker     oapv_mset(stat, 0, sizeof(oapve_stat_t));
1282*abb65b4bSAndroid Build Coastguard Worker 
1283*abb65b4bSAndroid Build Coastguard Worker     u8       *bs_pos_au_beg = oapv_bsw_sink(bs); // address syntax of au size
1284*abb65b4bSAndroid Build Coastguard Worker     u8       *bs_pos_pbu_beg;
1285*abb65b4bSAndroid Build Coastguard Worker     oapv_bs_t bs_pbu_beg;
1286*abb65b4bSAndroid Build Coastguard Worker     oapv_bsw_write(bs, 0, 32);
1287*abb65b4bSAndroid Build Coastguard Worker 
1288*abb65b4bSAndroid Build Coastguard Worker     for(i = 0; i < ifrms->num_frms; i++) {
1289*abb65b4bSAndroid Build Coastguard Worker         frm = &ifrms->frm[i];
1290*abb65b4bSAndroid Build Coastguard Worker 
1291*abb65b4bSAndroid Build Coastguard Worker         /* set default value for encoding parameter */
1292*abb65b4bSAndroid Build Coastguard Worker         ctx->param = &ctx->cdesc.param[i];
1293*abb65b4bSAndroid Build Coastguard Worker         ret = enc_read_param(ctx, ctx->param);
1294*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(ret == OAPV_OK, OAPV_ERR);
1295*abb65b4bSAndroid Build Coastguard Worker 
1296*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(ctx->param->profile_idc == OAPV_PROFILE_422_10, OAPV_ERR_UNSUPPORTED);
1297*abb65b4bSAndroid Build Coastguard Worker 
1298*abb65b4bSAndroid Build Coastguard Worker         // prepare for encoding a frame
1299*abb65b4bSAndroid Build Coastguard Worker         ret = enc_frm_prepare(ctx, frm->imgb, (rfrms != NULL) ? rfrms->frm[i].imgb : NULL);
1300*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(ret == OAPV_OK, ret);
1301*abb65b4bSAndroid Build Coastguard Worker 
1302*abb65b4bSAndroid Build Coastguard Worker         bs_pos_pbu_beg = oapv_bsw_sink(bs);            /* store pbu pos to calculate size */
1303*abb65b4bSAndroid Build Coastguard Worker         oapv_mcpy(&bs_pbu_beg, bs, sizeof(oapv_bs_t)); /* store pbu pos of ai to re-write */
1304*abb65b4bSAndroid Build Coastguard Worker 
1305*abb65b4bSAndroid Build Coastguard Worker         DUMP_SAVE(0);
1306*abb65b4bSAndroid Build Coastguard Worker         oapve_vlc_pbu_size(bs, 0);
1307*abb65b4bSAndroid Build Coastguard Worker         oapve_vlc_pbu_header(bs, frm->pbu_type, frm->group_id);
1308*abb65b4bSAndroid Build Coastguard Worker         // encode a frame
1309*abb65b4bSAndroid Build Coastguard Worker         ret = enc_frame(ctx);
1310*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(ret == OAPV_OK, ret);
1311*abb65b4bSAndroid Build Coastguard Worker 
1312*abb65b4bSAndroid Build Coastguard Worker         // rewrite pbu_size
1313*abb65b4bSAndroid Build Coastguard Worker         int pbu_size = ((u8 *)oapv_bsw_sink(bs)) - bs_pos_pbu_beg - 4;
1314*abb65b4bSAndroid Build Coastguard Worker         DUMP_SAVE(1);
1315*abb65b4bSAndroid Build Coastguard Worker         DUMP_LOAD(0);
1316*abb65b4bSAndroid Build Coastguard Worker         oapve_vlc_pbu_size(&bs_pbu_beg, pbu_size);
1317*abb65b4bSAndroid Build Coastguard Worker         DUMP_LOAD(1);
1318*abb65b4bSAndroid Build Coastguard Worker 
1319*abb65b4bSAndroid Build Coastguard Worker         stat->frm_size[i] = pbu_size + 4 /* PUB size length*/;
1320*abb65b4bSAndroid Build Coastguard Worker         copy_fi_to_finfo(&ctx->fh.fi, frm->pbu_type, frm->group_id, &stat->aui.frm_info[i]);
1321*abb65b4bSAndroid Build Coastguard Worker 
1322*abb65b4bSAndroid Build Coastguard Worker         // add frame hash value of reconstructed frame into metadata list
1323*abb65b4bSAndroid Build Coastguard Worker         if(ctx->use_frm_hash) {
1324*abb65b4bSAndroid Build Coastguard Worker             if(frm->pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME ||
1325*abb65b4bSAndroid Build Coastguard Worker                frm->pbu_type == OAPV_PBU_TYPE_NON_PRIMARY_FRAME) {
1326*abb65b4bSAndroid Build Coastguard Worker                 oapv_assert_rv(mid != NULL, OAPV_ERR_INVALID_ARGUMENT);
1327*abb65b4bSAndroid Build Coastguard Worker                 ret = oapv_set_md5_pld(mid, frm->group_id, ctx->rec);
1328*abb65b4bSAndroid Build Coastguard Worker                 oapv_assert_rv(OAPV_SUCCEEDED(ret), ret);
1329*abb65b4bSAndroid Build Coastguard Worker             }
1330*abb65b4bSAndroid Build Coastguard Worker         }
1331*abb65b4bSAndroid Build Coastguard Worker 
1332*abb65b4bSAndroid Build Coastguard Worker         // finishing of encoding a frame
1333*abb65b4bSAndroid Build Coastguard Worker         ret = enc_frm_finish(ctx, stat);
1334*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(ret == OAPV_OK, ret);
1335*abb65b4bSAndroid Build Coastguard Worker     }
1336*abb65b4bSAndroid Build Coastguard Worker     stat->aui.num_frms = ifrms->num_frms;
1337*abb65b4bSAndroid Build Coastguard Worker 
1338*abb65b4bSAndroid Build Coastguard Worker     oapvm_ctx_t *md_list = mid;
1339*abb65b4bSAndroid Build Coastguard Worker     if(md_list != NULL) {
1340*abb65b4bSAndroid Build Coastguard Worker         int num_md = md_list->num;
1341*abb65b4bSAndroid Build Coastguard Worker         for(i = 0; i < num_md; i++) {
1342*abb65b4bSAndroid Build Coastguard Worker             int group_id = md_list->group_ids[i];
1343*abb65b4bSAndroid Build Coastguard Worker             bs_pos_pbu_beg = oapv_bsw_sink(bs);            /* store pbu pos to calculate size */
1344*abb65b4bSAndroid Build Coastguard Worker             oapv_mcpy(&bs_pbu_beg, bs, sizeof(oapv_bs_t)); /* store pbu pos of ai to re-write */
1345*abb65b4bSAndroid Build Coastguard Worker             DUMP_SAVE(0);
1346*abb65b4bSAndroid Build Coastguard Worker 
1347*abb65b4bSAndroid Build Coastguard Worker             oapve_vlc_pbu_size(bs, 0);
1348*abb65b4bSAndroid Build Coastguard Worker             oapve_vlc_pbu_header(bs, OAPV_PBU_TYPE_METADATA, group_id);
1349*abb65b4bSAndroid Build Coastguard Worker             oapve_vlc_metadata(&md_list->md_arr[i], bs);
1350*abb65b4bSAndroid Build Coastguard Worker 
1351*abb65b4bSAndroid Build Coastguard Worker             // rewrite pbu_size
1352*abb65b4bSAndroid Build Coastguard Worker             int pbu_size = ((u8 *)oapv_bsw_sink(bs)) - bs_pos_pbu_beg - 4;
1353*abb65b4bSAndroid Build Coastguard Worker             DUMP_SAVE(1);
1354*abb65b4bSAndroid Build Coastguard Worker             DUMP_LOAD(0);
1355*abb65b4bSAndroid Build Coastguard Worker             oapve_vlc_pbu_size(&bs_pbu_beg, pbu_size);
1356*abb65b4bSAndroid Build Coastguard Worker             DUMP_LOAD(1);
1357*abb65b4bSAndroid Build Coastguard Worker         }
1358*abb65b4bSAndroid Build Coastguard Worker     }
1359*abb65b4bSAndroid Build Coastguard Worker 
1360*abb65b4bSAndroid Build Coastguard Worker     u32 au_size = (u32)((u8 *)oapv_bsw_sink(bs) - bs_pos_au_beg) - 4;
1361*abb65b4bSAndroid Build Coastguard Worker     oapv_bsw_write_direct(bs_pos_au_beg, au_size, 32); /* u(32) */
1362*abb65b4bSAndroid Build Coastguard Worker 
1363*abb65b4bSAndroid Build Coastguard Worker     oapv_bsw_deinit(&ctx->bs); /* de-init BSW */
1364*abb65b4bSAndroid Build Coastguard Worker     stat->write = bsw_get_write_byte(&ctx->bs);
1365*abb65b4bSAndroid Build Coastguard Worker 
1366*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1367*abb65b4bSAndroid Build Coastguard Worker }
1368*abb65b4bSAndroid Build Coastguard Worker 
oapve_config(oapve_t eid,int cfg,void * buf,int * size)1369*abb65b4bSAndroid Build Coastguard Worker int oapve_config(oapve_t eid, int cfg, void *buf, int *size)
1370*abb65b4bSAndroid Build Coastguard Worker {
1371*abb65b4bSAndroid Build Coastguard Worker     oapve_ctx_t *ctx;
1372*abb65b4bSAndroid Build Coastguard Worker     int          t0;
1373*abb65b4bSAndroid Build Coastguard Worker 
1374*abb65b4bSAndroid Build Coastguard Worker     ctx = enc_id_to_ctx(eid);
1375*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(ctx, OAPV_ERR_INVALID_ARGUMENT);
1376*abb65b4bSAndroid Build Coastguard Worker 
1377*abb65b4bSAndroid Build Coastguard Worker     switch(cfg) {
1378*abb65b4bSAndroid Build Coastguard Worker     /* set config **********************************************************/
1379*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_SET_QP:
1380*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(*size == sizeof(int), OAPV_ERR_INVALID_ARGUMENT);
1381*abb65b4bSAndroid Build Coastguard Worker         t0 = *((int *)buf);
1382*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(t0 >= MIN_QUANT && t0 <= MAX_QUANT,
1383*abb65b4bSAndroid Build Coastguard Worker                        OAPV_ERR_INVALID_ARGUMENT);
1384*abb65b4bSAndroid Build Coastguard Worker         ctx->param->qp = t0;
1385*abb65b4bSAndroid Build Coastguard Worker         break;
1386*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_SET_FPS_NUM:
1387*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(*size == sizeof(int), OAPV_ERR_INVALID_ARGUMENT);
1388*abb65b4bSAndroid Build Coastguard Worker         t0 = *((int *)buf);
1389*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(t0 > 0, OAPV_ERR_INVALID_ARGUMENT);
1390*abb65b4bSAndroid Build Coastguard Worker         ctx->param->fps_num = t0;
1391*abb65b4bSAndroid Build Coastguard Worker         break;
1392*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_SET_FPS_DEN:
1393*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(*size == sizeof(int), OAPV_ERR_INVALID_ARGUMENT);
1394*abb65b4bSAndroid Build Coastguard Worker         t0 = *((int *)buf);
1395*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(t0 > 0, OAPV_ERR_INVALID_ARGUMENT);
1396*abb65b4bSAndroid Build Coastguard Worker         ctx->param->fps_den = t0;
1397*abb65b4bSAndroid Build Coastguard Worker         break;
1398*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_SET_BPS:
1399*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(*size == sizeof(int), OAPV_ERR_INVALID_ARGUMENT);
1400*abb65b4bSAndroid Build Coastguard Worker         t0 = *((int *)buf);
1401*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(t0 > 0, OAPV_ERR_INVALID_ARGUMENT);
1402*abb65b4bSAndroid Build Coastguard Worker         ctx->param->bitrate = t0;
1403*abb65b4bSAndroid Build Coastguard Worker         break;
1404*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_SET_USE_FRM_HASH:
1405*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(*size == sizeof(int), OAPV_ERR_INVALID_ARGUMENT);
1406*abb65b4bSAndroid Build Coastguard Worker         ctx->use_frm_hash = (*((int *)buf)) ? 1 : 0;
1407*abb65b4bSAndroid Build Coastguard Worker         break;
1408*abb65b4bSAndroid Build Coastguard Worker     /* get config *******************************************************/
1409*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_GET_QP:
1410*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(*size == sizeof(int), OAPV_ERR_INVALID_ARGUMENT);
1411*abb65b4bSAndroid Build Coastguard Worker         *((int *)buf) = ctx->param->qp;
1412*abb65b4bSAndroid Build Coastguard Worker         break;
1413*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_GET_WIDTH:
1414*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(*size == sizeof(int), OAPV_ERR_INVALID_ARGUMENT);
1415*abb65b4bSAndroid Build Coastguard Worker         *((int *)buf) = ctx->param->w;
1416*abb65b4bSAndroid Build Coastguard Worker         break;
1417*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_GET_HEIGHT:
1418*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(*size == sizeof(int), OAPV_ERR_INVALID_ARGUMENT);
1419*abb65b4bSAndroid Build Coastguard Worker         *((int *)buf) = ctx->param->h;
1420*abb65b4bSAndroid Build Coastguard Worker         break;
1421*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_GET_FPS_NUM:
1422*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(*size == sizeof(int), OAPV_ERR_INVALID_ARGUMENT);
1423*abb65b4bSAndroid Build Coastguard Worker         *((int *)buf) = ctx->param->fps_num;
1424*abb65b4bSAndroid Build Coastguard Worker         break;
1425*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_GET_FPS_DEN:
1426*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(*size == sizeof(int), OAPV_ERR_INVALID_ARGUMENT);
1427*abb65b4bSAndroid Build Coastguard Worker         *((int *)buf) = ctx->param->fps_den;
1428*abb65b4bSAndroid Build Coastguard Worker         break;
1429*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_GET_BPS:
1430*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(*size == sizeof(int), OAPV_ERR_INVALID_ARGUMENT);
1431*abb65b4bSAndroid Build Coastguard Worker         *((int *)buf) = ctx->param->bitrate;
1432*abb65b4bSAndroid Build Coastguard Worker         break;
1433*abb65b4bSAndroid Build Coastguard Worker     default:
1434*abb65b4bSAndroid Build Coastguard Worker         oapv_trace("unknown config value (%d)\n", cfg);
1435*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(0, OAPV_ERR_UNSUPPORTED);
1436*abb65b4bSAndroid Build Coastguard Worker     }
1437*abb65b4bSAndroid Build Coastguard Worker 
1438*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1439*abb65b4bSAndroid Build Coastguard Worker }
1440*abb65b4bSAndroid Build Coastguard Worker 
oapve_param_default(oapve_param_t * param)1441*abb65b4bSAndroid Build Coastguard Worker int oapve_param_default(oapve_param_t *param)
1442*abb65b4bSAndroid Build Coastguard Worker {
1443*abb65b4bSAndroid Build Coastguard Worker     oapv_mset(param, 0, sizeof(oapve_param_t));
1444*abb65b4bSAndroid Build Coastguard Worker     param->preset = OAPV_PRESET_DEFAULT;
1445*abb65b4bSAndroid Build Coastguard Worker 
1446*abb65b4bSAndroid Build Coastguard Worker     param->qp_cb_offset = 0;
1447*abb65b4bSAndroid Build Coastguard Worker     param->qp_cr_offset = 0;
1448*abb65b4bSAndroid Build Coastguard Worker 
1449*abb65b4bSAndroid Build Coastguard Worker     param->tile_w_mb = 16;
1450*abb65b4bSAndroid Build Coastguard Worker     param->tile_h_mb = 16;
1451*abb65b4bSAndroid Build Coastguard Worker 
1452*abb65b4bSAndroid Build Coastguard Worker     param->profile_idc = OAPV_PROFILE_422_10;
1453*abb65b4bSAndroid Build Coastguard Worker     param->level_idc = (int)(4.1 * 30);
1454*abb65b4bSAndroid Build Coastguard Worker     param->band_idc = 2;
1455*abb65b4bSAndroid Build Coastguard Worker 
1456*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1457*abb65b4bSAndroid Build Coastguard Worker }
1458*abb65b4bSAndroid Build Coastguard Worker 
1459*abb65b4bSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
1460*abb65b4bSAndroid Build Coastguard Worker // enc of encoder code
1461*abb65b4bSAndroid Build Coastguard Worker #endif // ENABLE_ENCODER
1462*abb65b4bSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
1463*abb65b4bSAndroid Build Coastguard Worker 
1464*abb65b4bSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
1465*abb65b4bSAndroid Build Coastguard Worker // start of decoder code
1466*abb65b4bSAndroid Build Coastguard Worker #if ENABLE_DECODER
1467*abb65b4bSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
dec_id_to_ctx(oapvd_t id)1468*abb65b4bSAndroid Build Coastguard Worker static oapvd_ctx_t *dec_id_to_ctx(oapvd_t id)
1469*abb65b4bSAndroid Build Coastguard Worker {
1470*abb65b4bSAndroid Build Coastguard Worker     oapvd_ctx_t *ctx;
1471*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(id, NULL);
1472*abb65b4bSAndroid Build Coastguard Worker     ctx = (oapvd_ctx_t *)id;
1473*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(ctx->magic == OAPVD_MAGIC_CODE, NULL);
1474*abb65b4bSAndroid Build Coastguard Worker     return ctx;
1475*abb65b4bSAndroid Build Coastguard Worker }
1476*abb65b4bSAndroid Build Coastguard Worker 
dec_ctx_alloc(void)1477*abb65b4bSAndroid Build Coastguard Worker static oapvd_ctx_t *dec_ctx_alloc(void)
1478*abb65b4bSAndroid Build Coastguard Worker {
1479*abb65b4bSAndroid Build Coastguard Worker     oapvd_ctx_t *ctx;
1480*abb65b4bSAndroid Build Coastguard Worker 
1481*abb65b4bSAndroid Build Coastguard Worker     ctx = (oapvd_ctx_t *)oapv_malloc_fast(sizeof(oapvd_ctx_t));
1482*abb65b4bSAndroid Build Coastguard Worker 
1483*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(ctx != NULL, NULL);
1484*abb65b4bSAndroid Build Coastguard Worker     oapv_mset_x64a(ctx, 0, sizeof(oapvd_ctx_t));
1485*abb65b4bSAndroid Build Coastguard Worker 
1486*abb65b4bSAndroid Build Coastguard Worker     return ctx;
1487*abb65b4bSAndroid Build Coastguard Worker }
1488*abb65b4bSAndroid Build Coastguard Worker 
dec_ctx_free(oapvd_ctx_t * ctx)1489*abb65b4bSAndroid Build Coastguard Worker static void dec_ctx_free(oapvd_ctx_t *ctx)
1490*abb65b4bSAndroid Build Coastguard Worker {
1491*abb65b4bSAndroid Build Coastguard Worker     oapv_mfree_fast(ctx);
1492*abb65b4bSAndroid Build Coastguard Worker }
1493*abb65b4bSAndroid Build Coastguard Worker 
dec_core_alloc(void)1494*abb65b4bSAndroid Build Coastguard Worker static oapvd_core_t *dec_core_alloc(void)
1495*abb65b4bSAndroid Build Coastguard Worker {
1496*abb65b4bSAndroid Build Coastguard Worker     oapvd_core_t *core;
1497*abb65b4bSAndroid Build Coastguard Worker 
1498*abb65b4bSAndroid Build Coastguard Worker     core = (oapvd_core_t *)oapv_malloc_fast(sizeof(oapvd_core_t));
1499*abb65b4bSAndroid Build Coastguard Worker 
1500*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(core, NULL);
1501*abb65b4bSAndroid Build Coastguard Worker     oapv_mset_x64a(core, 0, sizeof(oapvd_core_t));
1502*abb65b4bSAndroid Build Coastguard Worker 
1503*abb65b4bSAndroid Build Coastguard Worker     return core;
1504*abb65b4bSAndroid Build Coastguard Worker }
1505*abb65b4bSAndroid Build Coastguard Worker 
dec_core_free(oapvd_core_t * core)1506*abb65b4bSAndroid Build Coastguard Worker static void dec_core_free(oapvd_core_t *core)
1507*abb65b4bSAndroid Build Coastguard Worker {
1508*abb65b4bSAndroid Build Coastguard Worker     oapv_mfree_fast(core);
1509*abb65b4bSAndroid Build Coastguard Worker }
1510*abb65b4bSAndroid Build Coastguard Worker 
dec_block(oapvd_ctx_t * ctx,oapvd_core_t * core,int log2_w,int log2_h,int c)1511*abb65b4bSAndroid Build Coastguard Worker static int dec_block(oapvd_ctx_t *ctx, oapvd_core_t *core, int log2_w, int log2_h, int c)
1512*abb65b4bSAndroid Build Coastguard Worker {
1513*abb65b4bSAndroid Build Coastguard Worker     int bit_depth = ctx->bit_depth;
1514*abb65b4bSAndroid Build Coastguard Worker 
1515*abb65b4bSAndroid Build Coastguard Worker     // DC prediction
1516*abb65b4bSAndroid Build Coastguard Worker     core->coef[0] += core->prev_dc[c];
1517*abb65b4bSAndroid Build Coastguard Worker     core->prev_dc[c] = core->coef[0];
1518*abb65b4bSAndroid Build Coastguard Worker     // Inverse quantization
1519*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_dquant[0](core->coef, core->q_mat[c], log2_w, log2_h, core->dq_shift[c]);
1520*abb65b4bSAndroid Build Coastguard Worker     // Inverse transform
1521*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_itx[0](core->coef, ITX_SHIFT1, ITX_SHIFT2(bit_depth), 1 << log2_w);
1522*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1523*abb65b4bSAndroid Build Coastguard Worker }
1524*abb65b4bSAndroid Build Coastguard Worker 
dec_set_tile_info(oapvd_tile_t * tile,int w_pel,int h_pel,int tile_w,int tile_h,int num_tile_cols,int num_tiles)1525*abb65b4bSAndroid Build Coastguard Worker static int dec_set_tile_info(oapvd_tile_t* tile, int w_pel, int h_pel, int tile_w, int tile_h, int num_tile_cols, int num_tiles)
1526*abb65b4bSAndroid Build Coastguard Worker {
1527*abb65b4bSAndroid Build Coastguard Worker 
1528*abb65b4bSAndroid Build Coastguard Worker     for (int i = 0; i < num_tiles; i++)
1529*abb65b4bSAndroid Build Coastguard Worker     {
1530*abb65b4bSAndroid Build Coastguard Worker         int tx = (i % (num_tile_cols)) * tile_w;
1531*abb65b4bSAndroid Build Coastguard Worker         int ty = (i / (num_tile_cols)) * tile_h;
1532*abb65b4bSAndroid Build Coastguard Worker         tile[i].x = tx;
1533*abb65b4bSAndroid Build Coastguard Worker         tile[i].y = ty;
1534*abb65b4bSAndroid Build Coastguard Worker         tile[i].w = tx + tile_w > w_pel ? w_pel - tx : tile_w;
1535*abb65b4bSAndroid Build Coastguard Worker         tile[i].h = ty + tile_h > h_pel ? h_pel - ty : tile_h;
1536*abb65b4bSAndroid Build Coastguard Worker     }
1537*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1538*abb65b4bSAndroid Build Coastguard Worker }
1539*abb65b4bSAndroid Build Coastguard Worker 
dec_frm_prepare(oapvd_ctx_t * ctx,oapv_imgb_t * imgb)1540*abb65b4bSAndroid Build Coastguard Worker static int dec_frm_prepare(oapvd_ctx_t *ctx, oapv_imgb_t *imgb)
1541*abb65b4bSAndroid Build Coastguard Worker {
1542*abb65b4bSAndroid Build Coastguard Worker     ctx->imgb = imgb;
1543*abb65b4bSAndroid Build Coastguard Worker     imgb_addref(ctx->imgb); // increase reference count
1544*abb65b4bSAndroid Build Coastguard Worker 
1545*abb65b4bSAndroid Build Coastguard Worker     ctx->bit_depth = ctx->fh.fi.bit_depth;
1546*abb65b4bSAndroid Build Coastguard Worker     ctx->cfi = ctx->fh.fi.chroma_format_idc;
1547*abb65b4bSAndroid Build Coastguard Worker     ctx->num_comp = get_num_comp(ctx->cfi);
1548*abb65b4bSAndroid Build Coastguard Worker     ctx->comp_sft[Y_C][0] = 0;
1549*abb65b4bSAndroid Build Coastguard Worker     ctx->comp_sft[Y_C][1] = 0;
1550*abb65b4bSAndroid Build Coastguard Worker 
1551*abb65b4bSAndroid Build Coastguard Worker     for(int c = 1; c < ctx->num_comp; c++) {
1552*abb65b4bSAndroid Build Coastguard Worker         ctx->comp_sft[c][0] = get_chroma_sft_w(color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs)));
1553*abb65b4bSAndroid Build Coastguard Worker         ctx->comp_sft[c][1] = get_chroma_sft_h(color_format_to_chroma_format_idc(OAPV_CS_GET_FORMAT(imgb->cs)));
1554*abb65b4bSAndroid Build Coastguard Worker     }
1555*abb65b4bSAndroid Build Coastguard Worker 
1556*abb65b4bSAndroid Build Coastguard Worker     ctx->w = oapv_align_value(ctx->fh.fi.frame_width, OAPV_MB_W);
1557*abb65b4bSAndroid Build Coastguard Worker     ctx->h = oapv_align_value(ctx->fh.fi.frame_height, OAPV_MB_H);
1558*abb65b4bSAndroid Build Coastguard Worker 
1559*abb65b4bSAndroid Build Coastguard Worker     if(OAPV_CS_GET_FORMAT(imgb->cs) == OAPV_CF_PLANAR2) {
1560*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_block_to_imgb[Y_C] = block_to_imgb_p210_y;
1561*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_block_to_imgb[U_C] = block_to_imgb_p210_uv;
1562*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_block_to_imgb[V_C] = block_to_imgb_p210_uv;
1563*abb65b4bSAndroid Build Coastguard Worker     }
1564*abb65b4bSAndroid Build Coastguard Worker     else {
1565*abb65b4bSAndroid Build Coastguard Worker         for(int c = 0; c < ctx->num_comp; c++) {
1566*abb65b4bSAndroid Build Coastguard Worker             ctx->fn_block_to_imgb[c] = block_to_imgb_10bit;
1567*abb65b4bSAndroid Build Coastguard Worker         }
1568*abb65b4bSAndroid Build Coastguard Worker     }
1569*abb65b4bSAndroid Build Coastguard Worker 
1570*abb65b4bSAndroid Build Coastguard Worker     int tile_w = ctx->fh.tile_width_in_mbs * OAPV_MB_W;
1571*abb65b4bSAndroid Build Coastguard Worker     int tile_h = ctx->fh.tile_height_in_mbs * OAPV_MB_H;
1572*abb65b4bSAndroid Build Coastguard Worker 
1573*abb65b4bSAndroid Build Coastguard Worker     ctx->num_tile_cols = (ctx->w + (tile_w - 1)) / tile_w;
1574*abb65b4bSAndroid Build Coastguard Worker     ctx->num_tile_rows = (ctx->h + (tile_h - 1)) / tile_h;
1575*abb65b4bSAndroid Build Coastguard Worker     ctx->num_tiles = ctx->num_tile_cols * ctx->num_tile_rows;
1576*abb65b4bSAndroid Build Coastguard Worker 
1577*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv((ctx->num_tile_cols <= OAPV_MAX_TILE_COLS) && (ctx->num_tile_rows <= OAPV_MAX_TILE_ROWS), OAPV_ERR_MALFORMED_BITSTREAM);
1578*abb65b4bSAndroid Build Coastguard Worker     dec_set_tile_info(ctx->tile, ctx->w, ctx->h, tile_w, tile_h, ctx->num_tile_cols, ctx->num_tiles);
1579*abb65b4bSAndroid Build Coastguard Worker 
1580*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < ctx->num_tiles; i++) {
1581*abb65b4bSAndroid Build Coastguard Worker         ctx->tile[i].bs_beg = NULL;
1582*abb65b4bSAndroid Build Coastguard Worker     }
1583*abb65b4bSAndroid Build Coastguard Worker     ctx->tile[0].bs_beg = oapv_bsr_sink(&ctx->bs);
1584*abb65b4bSAndroid Build Coastguard Worker 
1585*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < ctx->num_tiles; i++) {
1586*abb65b4bSAndroid Build Coastguard Worker         ctx->tile[i].stat = DEC_TILE_STAT_NOT_DECODED;
1587*abb65b4bSAndroid Build Coastguard Worker     }
1588*abb65b4bSAndroid Build Coastguard Worker 
1589*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1590*abb65b4bSAndroid Build Coastguard Worker }
1591*abb65b4bSAndroid Build Coastguard Worker 
dec_frm_finish(oapvd_ctx_t * ctx)1592*abb65b4bSAndroid Build Coastguard Worker static int dec_frm_finish(oapvd_ctx_t *ctx)
1593*abb65b4bSAndroid Build Coastguard Worker {
1594*abb65b4bSAndroid Build Coastguard Worker     oapv_mset(&ctx->bs, 0, sizeof(oapv_bs_t)); // clean data
1595*abb65b4bSAndroid Build Coastguard Worker     imgb_release(ctx->imgb);                   // decrease reference cnout
1596*abb65b4bSAndroid Build Coastguard Worker     ctx->imgb = NULL;
1597*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1598*abb65b4bSAndroid Build Coastguard Worker }
1599*abb65b4bSAndroid Build Coastguard Worker 
dec_tile_comp(oapvd_tile_t * tile,oapvd_ctx_t * ctx,oapvd_core_t * core,oapv_bs_t * bs,int c,int s_dst,void * dst)1600*abb65b4bSAndroid Build Coastguard Worker static int dec_tile_comp(oapvd_tile_t *tile, oapvd_ctx_t *ctx, oapvd_core_t *core, oapv_bs_t *bs, int c, int s_dst, void *dst)
1601*abb65b4bSAndroid Build Coastguard Worker {
1602*abb65b4bSAndroid Build Coastguard Worker     int  mb_h, mb_w, mb_y, mb_x, blk_y, blk_x;
1603*abb65b4bSAndroid Build Coastguard Worker     int  le, ri, to, bo;
1604*abb65b4bSAndroid Build Coastguard Worker     int  ret;
1605*abb65b4bSAndroid Build Coastguard Worker     s16 *d16;
1606*abb65b4bSAndroid Build Coastguard Worker 
1607*abb65b4bSAndroid Build Coastguard Worker     mb_h = OAPV_MB_H >> ctx->comp_sft[c][1];
1608*abb65b4bSAndroid Build Coastguard Worker     mb_w = OAPV_MB_W >> ctx->comp_sft[c][0];
1609*abb65b4bSAndroid Build Coastguard Worker 
1610*abb65b4bSAndroid Build Coastguard Worker     le = tile->x >> ctx->comp_sft[c][0];        // left position of tile
1611*abb65b4bSAndroid Build Coastguard Worker     ri = (tile->w >> ctx->comp_sft[c][0]) + le; // right pixel position of tile
1612*abb65b4bSAndroid Build Coastguard Worker     to = tile->y >> ctx->comp_sft[c][1];        // top pixel position of tile
1613*abb65b4bSAndroid Build Coastguard Worker     bo = (tile->h >> ctx->comp_sft[c][1]) + to; // bottom pixel position of tile
1614*abb65b4bSAndroid Build Coastguard Worker 
1615*abb65b4bSAndroid Build Coastguard Worker     for(mb_y = to; mb_y < bo; mb_y += mb_h) {
1616*abb65b4bSAndroid Build Coastguard Worker         for(mb_x = le; mb_x < ri; mb_x += mb_w) {
1617*abb65b4bSAndroid Build Coastguard Worker             for(blk_y = mb_y; blk_y < (mb_y + mb_h); blk_y += OAPV_BLK_H) {
1618*abb65b4bSAndroid Build Coastguard Worker                 for(blk_x = mb_x; blk_x < (mb_x + mb_w); blk_x += OAPV_BLK_W) {
1619*abb65b4bSAndroid Build Coastguard Worker                     // parse DC coefficient
1620*abb65b4bSAndroid Build Coastguard Worker                     ret = oapvd_vlc_dc_coeff(ctx, core, bs, &core->coef[0], c);
1621*abb65b4bSAndroid Build Coastguard Worker                     oapv_assert_rv(OAPV_SUCCEEDED(ret), ret);
1622*abb65b4bSAndroid Build Coastguard Worker 
1623*abb65b4bSAndroid Build Coastguard Worker                     // parse AC coefficient
1624*abb65b4bSAndroid Build Coastguard Worker                     ret = oapvd_vlc_ac_coeff(ctx, core, bs, core->coef, c);
1625*abb65b4bSAndroid Build Coastguard Worker                     oapv_assert_rv(OAPV_SUCCEEDED(ret), ret);
1626*abb65b4bSAndroid Build Coastguard Worker                     DUMP_COEF(core->coef, OAPV_BLK_D, blk_x, blk_y, c);
1627*abb65b4bSAndroid Build Coastguard Worker 
1628*abb65b4bSAndroid Build Coastguard Worker                     // decode a block
1629*abb65b4bSAndroid Build Coastguard Worker                     ret = dec_block(ctx, core, OAPV_LOG2_BLK_W, OAPV_LOG2_BLK_H, c);
1630*abb65b4bSAndroid Build Coastguard Worker                     oapv_assert_rv(OAPV_SUCCEEDED(ret), ret);
1631*abb65b4bSAndroid Build Coastguard Worker 
1632*abb65b4bSAndroid Build Coastguard Worker                     // copy decoded block to image buffer
1633*abb65b4bSAndroid Build Coastguard Worker                     d16 = (s16 *)((u8 *)dst + blk_y * s_dst) + blk_x;
1634*abb65b4bSAndroid Build Coastguard Worker                     ctx->fn_block_to_imgb[c](core->coef, OAPV_BLK_W, OAPV_BLK_H, (OAPV_BLK_W << 1), blk_x, s_dst, d16);
1635*abb65b4bSAndroid Build Coastguard Worker                 }
1636*abb65b4bSAndroid Build Coastguard Worker             }
1637*abb65b4bSAndroid Build Coastguard Worker         }
1638*abb65b4bSAndroid Build Coastguard Worker     }
1639*abb65b4bSAndroid Build Coastguard Worker 
1640*abb65b4bSAndroid Build Coastguard Worker     /* byte align */
1641*abb65b4bSAndroid Build Coastguard Worker     oapv_bsr_align8(bs);
1642*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1643*abb65b4bSAndroid Build Coastguard Worker }
1644*abb65b4bSAndroid Build Coastguard Worker 
dec_tile(oapvd_core_t * core,oapvd_tile_t * tile)1645*abb65b4bSAndroid Build Coastguard Worker static int dec_tile(oapvd_core_t *core, oapvd_tile_t *tile)
1646*abb65b4bSAndroid Build Coastguard Worker {
1647*abb65b4bSAndroid Build Coastguard Worker     int          ret, midx, x, y, c;
1648*abb65b4bSAndroid Build Coastguard Worker     oapvd_ctx_t *ctx = core->ctx;
1649*abb65b4bSAndroid Build Coastguard Worker     oapv_bs_t    bs;
1650*abb65b4bSAndroid Build Coastguard Worker 
1651*abb65b4bSAndroid Build Coastguard Worker     oapv_bsr_init(&bs, tile->bs_beg + OAPV_TILE_SIZE_LEN, tile->data_size, NULL);
1652*abb65b4bSAndroid Build Coastguard Worker     ret = oapvd_vlc_tile_header(&bs, ctx, &tile->th);
1653*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(OAPV_SUCCEEDED(ret), ret);
1654*abb65b4bSAndroid Build Coastguard Worker     for(c = 0; c < ctx->num_comp; c++) {
1655*abb65b4bSAndroid Build Coastguard Worker         core->qp[c] = tile->th.tile_qp[c];
1656*abb65b4bSAndroid Build Coastguard Worker         int dq_scale = oapv_tbl_dq_scale[core->qp[c] % 6];
1657*abb65b4bSAndroid Build Coastguard Worker         core->dq_shift[c] = ctx->bit_depth - 2 - (core->qp[c] / 6);
1658*abb65b4bSAndroid Build Coastguard Worker 
1659*abb65b4bSAndroid Build Coastguard Worker         core->prev_dc_ctx[c] = 20;
1660*abb65b4bSAndroid Build Coastguard Worker         core->prev_1st_ac_ctx[c] = 0;
1661*abb65b4bSAndroid Build Coastguard Worker         core->prev_dc[c] = 0;
1662*abb65b4bSAndroid Build Coastguard Worker 
1663*abb65b4bSAndroid Build Coastguard Worker         midx = 0;
1664*abb65b4bSAndroid Build Coastguard Worker         for(y = 0; y < OAPV_BLK_H; y++) {
1665*abb65b4bSAndroid Build Coastguard Worker             for(x = 0; x < OAPV_BLK_W; x++) {
1666*abb65b4bSAndroid Build Coastguard Worker                 core->q_mat[c][midx++] = dq_scale * ctx->fh.q_matrix[c][y][x]; // 7bit + 8bit
1667*abb65b4bSAndroid Build Coastguard Worker             }
1668*abb65b4bSAndroid Build Coastguard Worker         }
1669*abb65b4bSAndroid Build Coastguard Worker     }
1670*abb65b4bSAndroid Build Coastguard Worker 
1671*abb65b4bSAndroid Build Coastguard Worker     for(c = 0; c < ctx->num_comp; c++) {
1672*abb65b4bSAndroid Build Coastguard Worker         int  tc, s_dst;
1673*abb65b4bSAndroid Build Coastguard Worker         s16 *dst;
1674*abb65b4bSAndroid Build Coastguard Worker 
1675*abb65b4bSAndroid Build Coastguard Worker         if(OAPV_CS_GET_FORMAT(ctx->imgb->cs) == OAPV_CF_PLANAR2) {
1676*abb65b4bSAndroid Build Coastguard Worker             tc = c > 0 ? 1 : 0;
1677*abb65b4bSAndroid Build Coastguard Worker             dst = ctx->imgb->a[tc];
1678*abb65b4bSAndroid Build Coastguard Worker             dst += (c > 1) ? 1 : 0;
1679*abb65b4bSAndroid Build Coastguard Worker             s_dst = ctx->imgb->s[tc];
1680*abb65b4bSAndroid Build Coastguard Worker         }
1681*abb65b4bSAndroid Build Coastguard Worker         else {
1682*abb65b4bSAndroid Build Coastguard Worker             dst = ctx->imgb->a[c];
1683*abb65b4bSAndroid Build Coastguard Worker             s_dst = ctx->imgb->s[c];
1684*abb65b4bSAndroid Build Coastguard Worker         }
1685*abb65b4bSAndroid Build Coastguard Worker 
1686*abb65b4bSAndroid Build Coastguard Worker         ret = dec_tile_comp(tile, ctx, core, &bs, c, s_dst, dst);
1687*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(OAPV_SUCCEEDED(ret), ret);
1688*abb65b4bSAndroid Build Coastguard Worker     }
1689*abb65b4bSAndroid Build Coastguard Worker 
1690*abb65b4bSAndroid Build Coastguard Worker     oapvd_vlc_tile_dummy_data(&bs);
1691*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1692*abb65b4bSAndroid Build Coastguard Worker }
1693*abb65b4bSAndroid Build Coastguard Worker 
dec_thread_tile(void * arg)1694*abb65b4bSAndroid Build Coastguard Worker static int dec_thread_tile(void *arg)
1695*abb65b4bSAndroid Build Coastguard Worker {
1696*abb65b4bSAndroid Build Coastguard Worker     oapv_bs_t     bs;
1697*abb65b4bSAndroid Build Coastguard Worker     int           i, ret, run, tile_idx = 0, thread_ret = OAPV_OK;
1698*abb65b4bSAndroid Build Coastguard Worker 
1699*abb65b4bSAndroid Build Coastguard Worker     oapvd_core_t *core = (oapvd_core_t *)arg;
1700*abb65b4bSAndroid Build Coastguard Worker     oapvd_ctx_t  *ctx = core->ctx;
1701*abb65b4bSAndroid Build Coastguard Worker     oapvd_tile_t *tile = ctx->tile;
1702*abb65b4bSAndroid Build Coastguard Worker 
1703*abb65b4bSAndroid Build Coastguard Worker     while(1) {
1704*abb65b4bSAndroid Build Coastguard Worker         // find not decoded tile
1705*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_enter_cs(ctx->sync_obj);
1706*abb65b4bSAndroid Build Coastguard Worker         for(i = 0; i < ctx->num_tiles; i++) {
1707*abb65b4bSAndroid Build Coastguard Worker             if(tile[i].stat == DEC_TILE_STAT_NOT_DECODED) {
1708*abb65b4bSAndroid Build Coastguard Worker                 tile[i].stat = DEC_TILE_STAT_ON_DECODING;
1709*abb65b4bSAndroid Build Coastguard Worker                 tile_idx = i;
1710*abb65b4bSAndroid Build Coastguard Worker                 break;
1711*abb65b4bSAndroid Build Coastguard Worker             }
1712*abb65b4bSAndroid Build Coastguard Worker         }
1713*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_leave_cs(ctx->sync_obj);
1714*abb65b4bSAndroid Build Coastguard Worker         if(i == ctx->num_tiles) {
1715*abb65b4bSAndroid Build Coastguard Worker             break;
1716*abb65b4bSAndroid Build Coastguard Worker         }
1717*abb65b4bSAndroid Build Coastguard Worker 
1718*abb65b4bSAndroid Build Coastguard Worker         // wait until to know bistream start position
1719*abb65b4bSAndroid Build Coastguard Worker         run = 1;
1720*abb65b4bSAndroid Build Coastguard Worker         while(run) {
1721*abb65b4bSAndroid Build Coastguard Worker             oapv_tpool_enter_cs(ctx->sync_obj);
1722*abb65b4bSAndroid Build Coastguard Worker             if(tile[tile_idx].bs_beg != NULL) {
1723*abb65b4bSAndroid Build Coastguard Worker                 run = 0;
1724*abb65b4bSAndroid Build Coastguard Worker             }
1725*abb65b4bSAndroid Build Coastguard Worker             oapv_tpool_leave_cs(ctx->sync_obj);
1726*abb65b4bSAndroid Build Coastguard Worker         }
1727*abb65b4bSAndroid Build Coastguard Worker         /* read tile size */
1728*abb65b4bSAndroid Build Coastguard Worker         oapv_bsr_init(&bs, tile[tile_idx].bs_beg, OAPV_TILE_SIZE_LEN, NULL);
1729*abb65b4bSAndroid Build Coastguard Worker         ret = oapvd_vlc_tile_size(&bs, &tile[tile_idx].data_size);
1730*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
1731*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_g(tile[tile_idx].bs_beg + OAPV_TILE_SIZE_LEN + (tile[tile_idx].data_size - 1) <= ctx->bs.end, ERR);
1732*abb65b4bSAndroid Build Coastguard Worker 
1733*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_enter_cs(ctx->sync_obj);
1734*abb65b4bSAndroid Build Coastguard Worker         if(tile_idx + 1 < ctx->num_tiles) {
1735*abb65b4bSAndroid Build Coastguard Worker             tile[tile_idx + 1].bs_beg = tile[tile_idx].bs_beg + OAPV_TILE_SIZE_LEN + tile[tile_idx].data_size;
1736*abb65b4bSAndroid Build Coastguard Worker         }
1737*abb65b4bSAndroid Build Coastguard Worker         else {
1738*abb65b4bSAndroid Build Coastguard Worker             ctx->tile_end = tile[tile_idx].bs_beg + OAPV_TILE_SIZE_LEN + tile[tile_idx].data_size;
1739*abb65b4bSAndroid Build Coastguard Worker         }
1740*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_leave_cs(ctx->sync_obj);
1741*abb65b4bSAndroid Build Coastguard Worker 
1742*abb65b4bSAndroid Build Coastguard Worker         ret = dec_tile(core, &tile[tile_idx]);
1743*abb65b4bSAndroid Build Coastguard Worker 
1744*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_enter_cs(ctx->sync_obj);
1745*abb65b4bSAndroid Build Coastguard Worker         if (OAPV_SUCCEEDED(ret)) {
1746*abb65b4bSAndroid Build Coastguard Worker             tile[tile_idx].stat = DEC_TILE_STAT_DECODED;
1747*abb65b4bSAndroid Build Coastguard Worker         }
1748*abb65b4bSAndroid Build Coastguard Worker         else {
1749*abb65b4bSAndroid Build Coastguard Worker             tile[tile_idx].stat = ret;
1750*abb65b4bSAndroid Build Coastguard Worker             thread_ret = ret;
1751*abb65b4bSAndroid Build Coastguard Worker         }
1752*abb65b4bSAndroid Build Coastguard Worker         tile[tile_idx].stat = OAPV_SUCCEEDED(ret) ? DEC_TILE_STAT_DECODED : ret;
1753*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_leave_cs(ctx->sync_obj);
1754*abb65b4bSAndroid Build Coastguard Worker     }
1755*abb65b4bSAndroid Build Coastguard Worker     return thread_ret;
1756*abb65b4bSAndroid Build Coastguard Worker 
1757*abb65b4bSAndroid Build Coastguard Worker ERR:
1758*abb65b4bSAndroid Build Coastguard Worker     oapv_tpool_enter_cs(ctx->sync_obj);
1759*abb65b4bSAndroid Build Coastguard Worker     tile[tile_idx].stat = DEC_TILE_STAT_SIZE_ERROR;
1760*abb65b4bSAndroid Build Coastguard Worker     if (tile_idx + 1 < ctx->num_tiles)
1761*abb65b4bSAndroid Build Coastguard Worker     {
1762*abb65b4bSAndroid Build Coastguard Worker         tile[tile_idx + 1].bs_beg = tile[tile_idx].bs_beg;
1763*abb65b4bSAndroid Build Coastguard Worker     }
1764*abb65b4bSAndroid Build Coastguard Worker     oapv_tpool_leave_cs(ctx->sync_obj);
1765*abb65b4bSAndroid Build Coastguard Worker     return OAPV_ERR_MALFORMED_BITSTREAM;
1766*abb65b4bSAndroid Build Coastguard Worker }
1767*abb65b4bSAndroid Build Coastguard Worker 
dec_flush(oapvd_ctx_t * ctx)1768*abb65b4bSAndroid Build Coastguard Worker static void dec_flush(oapvd_ctx_t *ctx)
1769*abb65b4bSAndroid Build Coastguard Worker {
1770*abb65b4bSAndroid Build Coastguard Worker     if(ctx->cdesc.threads >= 2) {
1771*abb65b4bSAndroid Build Coastguard Worker         if(ctx->tpool) {
1772*abb65b4bSAndroid Build Coastguard Worker             // thread controller instance is present
1773*abb65b4bSAndroid Build Coastguard Worker             // terminate the created thread
1774*abb65b4bSAndroid Build Coastguard Worker             for(int i = 0; i < ctx->cdesc.threads - 1; i++) {
1775*abb65b4bSAndroid Build Coastguard Worker                 if(ctx->thread_id[i]) {
1776*abb65b4bSAndroid Build Coastguard Worker                     // valid thread instance
1777*abb65b4bSAndroid Build Coastguard Worker                     ctx->tpool->release(&ctx->thread_id[i]);
1778*abb65b4bSAndroid Build Coastguard Worker                 }
1779*abb65b4bSAndroid Build Coastguard Worker             }
1780*abb65b4bSAndroid Build Coastguard Worker             // dinitialize the tpool
1781*abb65b4bSAndroid Build Coastguard Worker             oapv_tpool_deinit(ctx->tpool);
1782*abb65b4bSAndroid Build Coastguard Worker             oapv_mfree(ctx->tpool);
1783*abb65b4bSAndroid Build Coastguard Worker             ctx->tpool = NULL;
1784*abb65b4bSAndroid Build Coastguard Worker         }
1785*abb65b4bSAndroid Build Coastguard Worker     }
1786*abb65b4bSAndroid Build Coastguard Worker 
1787*abb65b4bSAndroid Build Coastguard Worker     oapv_tpool_sync_obj_delete(&(ctx->sync_obj));
1788*abb65b4bSAndroid Build Coastguard Worker 
1789*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < ctx->cdesc.threads; i++) {
1790*abb65b4bSAndroid Build Coastguard Worker         dec_core_free(ctx->core[i]);
1791*abb65b4bSAndroid Build Coastguard Worker     }
1792*abb65b4bSAndroid Build Coastguard Worker }
1793*abb65b4bSAndroid Build Coastguard Worker 
dec_ready(oapvd_ctx_t * ctx)1794*abb65b4bSAndroid Build Coastguard Worker static int dec_ready(oapvd_ctx_t *ctx)
1795*abb65b4bSAndroid Build Coastguard Worker {
1796*abb65b4bSAndroid Build Coastguard Worker     int i, ret = OAPV_OK;
1797*abb65b4bSAndroid Build Coastguard Worker 
1798*abb65b4bSAndroid Build Coastguard Worker     if(ctx->core[0] == NULL) {
1799*abb65b4bSAndroid Build Coastguard Worker         // create cores
1800*abb65b4bSAndroid Build Coastguard Worker         for(i = 0; i < ctx->cdesc.threads; i++) {
1801*abb65b4bSAndroid Build Coastguard Worker             ctx->core[i] = dec_core_alloc();
1802*abb65b4bSAndroid Build Coastguard Worker             oapv_assert_gv(ctx->core[i], ret, OAPV_ERR_OUT_OF_MEMORY, ERR);
1803*abb65b4bSAndroid Build Coastguard Worker             ctx->core[i]->ctx = ctx;
1804*abb65b4bSAndroid Build Coastguard Worker         }
1805*abb65b4bSAndroid Build Coastguard Worker     }
1806*abb65b4bSAndroid Build Coastguard Worker 
1807*abb65b4bSAndroid Build Coastguard Worker     // initialize the threads to NULL
1808*abb65b4bSAndroid Build Coastguard Worker     for(i = 0; i < OAPV_MAX_THREADS; i++) {
1809*abb65b4bSAndroid Build Coastguard Worker         ctx->thread_id[i] = 0;
1810*abb65b4bSAndroid Build Coastguard Worker     }
1811*abb65b4bSAndroid Build Coastguard Worker 
1812*abb65b4bSAndroid Build Coastguard Worker     // get the context synchronization handle
1813*abb65b4bSAndroid Build Coastguard Worker     ctx->sync_obj = oapv_tpool_sync_obj_create();
1814*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_gv(ctx->sync_obj != NULL, ret, OAPV_ERR_UNKNOWN, ERR);
1815*abb65b4bSAndroid Build Coastguard Worker 
1816*abb65b4bSAndroid Build Coastguard Worker     if(ctx->cdesc.threads >= 2) {
1817*abb65b4bSAndroid Build Coastguard Worker         ctx->tpool = oapv_malloc(sizeof(oapv_tpool_t));
1818*abb65b4bSAndroid Build Coastguard Worker         oapv_tpool_init(ctx->tpool, ctx->cdesc.threads - 1);
1819*abb65b4bSAndroid Build Coastguard Worker         for(i = 0; i < ctx->cdesc.threads - 1; i++) {
1820*abb65b4bSAndroid Build Coastguard Worker             ctx->thread_id[i] = ctx->tpool->create(ctx->tpool, i);
1821*abb65b4bSAndroid Build Coastguard Worker             oapv_assert_gv(ctx->thread_id[i] != NULL, ret, OAPV_ERR_UNKNOWN, ERR);
1822*abb65b4bSAndroid Build Coastguard Worker         }
1823*abb65b4bSAndroid Build Coastguard Worker     }
1824*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1825*abb65b4bSAndroid Build Coastguard Worker 
1826*abb65b4bSAndroid Build Coastguard Worker ERR:
1827*abb65b4bSAndroid Build Coastguard Worker     dec_flush(ctx);
1828*abb65b4bSAndroid Build Coastguard Worker 
1829*abb65b4bSAndroid Build Coastguard Worker     return ret;
1830*abb65b4bSAndroid Build Coastguard Worker }
1831*abb65b4bSAndroid Build Coastguard Worker 
dec_platform_init(oapvd_ctx_t * ctx)1832*abb65b4bSAndroid Build Coastguard Worker static int dec_platform_init(oapvd_ctx_t *ctx)
1833*abb65b4bSAndroid Build Coastguard Worker {
1834*abb65b4bSAndroid Build Coastguard Worker     // default settings
1835*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_itx = oapv_tbl_fn_itx;
1836*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_dquant = oapv_tbl_fn_dquant;
1837*abb65b4bSAndroid Build Coastguard Worker 
1838*abb65b4bSAndroid Build Coastguard Worker #if X86_SSE
1839*abb65b4bSAndroid Build Coastguard Worker     int check_cpu, support_sse, support_avx2;
1840*abb65b4bSAndroid Build Coastguard Worker 
1841*abb65b4bSAndroid Build Coastguard Worker     check_cpu = oapv_check_cpu_info_x86();
1842*abb65b4bSAndroid Build Coastguard Worker     support_sse = (check_cpu >> 0) & 1;
1843*abb65b4bSAndroid Build Coastguard Worker     support_avx2 = (check_cpu >> 2) & 1;
1844*abb65b4bSAndroid Build Coastguard Worker 
1845*abb65b4bSAndroid Build Coastguard Worker     if(support_avx2) {
1846*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_itx = oapv_tbl_fn_itx_avx;
1847*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_dquant = oapv_tbl_fn_dquant_avx;
1848*abb65b4bSAndroid Build Coastguard Worker     }
1849*abb65b4bSAndroid Build Coastguard Worker     else if(support_sse) {
1850*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_itx = oapv_tbl_fn_itx;
1851*abb65b4bSAndroid Build Coastguard Worker         ctx->fn_dquant = oapv_tbl_fn_dquant;
1852*abb65b4bSAndroid Build Coastguard Worker     }
1853*abb65b4bSAndroid Build Coastguard Worker #elif ARM_NEON
1854*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_itx = oapv_tbl_fn_itx_neon;
1855*abb65b4bSAndroid Build Coastguard Worker     ctx->fn_dquant = oapv_tbl_fn_dquant;
1856*abb65b4bSAndroid Build Coastguard Worker #endif
1857*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
1858*abb65b4bSAndroid Build Coastguard Worker }
1859*abb65b4bSAndroid Build Coastguard Worker 
oapvd_create(oapvd_cdesc_t * cdesc,int * err)1860*abb65b4bSAndroid Build Coastguard Worker oapvd_t oapvd_create(oapvd_cdesc_t *cdesc, int *err)
1861*abb65b4bSAndroid Build Coastguard Worker {
1862*abb65b4bSAndroid Build Coastguard Worker     oapvd_ctx_t *ctx;
1863*abb65b4bSAndroid Build Coastguard Worker     int          ret;
1864*abb65b4bSAndroid Build Coastguard Worker 
1865*abb65b4bSAndroid Build Coastguard Worker     DUMP_CREATE(0);
1866*abb65b4bSAndroid Build Coastguard Worker     ctx = NULL;
1867*abb65b4bSAndroid Build Coastguard Worker 
1868*abb65b4bSAndroid Build Coastguard Worker     /* check if any decoder argument is correctly set */
1869*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_gv(cdesc->threads > 0 && cdesc->threads <= OAPV_MAX_THREADS, ret, OAPV_ERR_INVALID_ARGUMENT, ERR);
1870*abb65b4bSAndroid Build Coastguard Worker 
1871*abb65b4bSAndroid Build Coastguard Worker     /* memory allocation for ctx and core structure */
1872*abb65b4bSAndroid Build Coastguard Worker     ctx = (oapvd_ctx_t *)dec_ctx_alloc();
1873*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_gv(ctx != NULL, ret, OAPV_ERR_OUT_OF_MEMORY, ERR);
1874*abb65b4bSAndroid Build Coastguard Worker     oapv_mcpy(&ctx->cdesc, cdesc, sizeof(oapvd_cdesc_t));
1875*abb65b4bSAndroid Build Coastguard Worker 
1876*abb65b4bSAndroid Build Coastguard Worker     /* initialize platform-specific variables */
1877*abb65b4bSAndroid Build Coastguard Worker     ret = dec_platform_init(ctx);
1878*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_g(ret == OAPV_OK, ERR);
1879*abb65b4bSAndroid Build Coastguard Worker 
1880*abb65b4bSAndroid Build Coastguard Worker     /* ready for decoding */
1881*abb65b4bSAndroid Build Coastguard Worker     ret = dec_ready(ctx);
1882*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_g(ret == OAPV_OK, ERR);
1883*abb65b4bSAndroid Build Coastguard Worker 
1884*abb65b4bSAndroid Build Coastguard Worker     ctx->magic = OAPVD_MAGIC_CODE;
1885*abb65b4bSAndroid Build Coastguard Worker     ctx->id = (oapvd_t)ctx;
1886*abb65b4bSAndroid Build Coastguard Worker     if(err) {
1887*abb65b4bSAndroid Build Coastguard Worker         *err = OAPV_OK;
1888*abb65b4bSAndroid Build Coastguard Worker     }
1889*abb65b4bSAndroid Build Coastguard Worker     return (ctx->id);
1890*abb65b4bSAndroid Build Coastguard Worker 
1891*abb65b4bSAndroid Build Coastguard Worker ERR:
1892*abb65b4bSAndroid Build Coastguard Worker     if(ctx) {
1893*abb65b4bSAndroid Build Coastguard Worker         dec_ctx_free(ctx);
1894*abb65b4bSAndroid Build Coastguard Worker     }
1895*abb65b4bSAndroid Build Coastguard Worker     if(err) {
1896*abb65b4bSAndroid Build Coastguard Worker         *err = ret;
1897*abb65b4bSAndroid Build Coastguard Worker     }
1898*abb65b4bSAndroid Build Coastguard Worker     return NULL;
1899*abb65b4bSAndroid Build Coastguard Worker }
1900*abb65b4bSAndroid Build Coastguard Worker 
oapvd_delete(oapvd_t did)1901*abb65b4bSAndroid Build Coastguard Worker void oapvd_delete(oapvd_t did)
1902*abb65b4bSAndroid Build Coastguard Worker {
1903*abb65b4bSAndroid Build Coastguard Worker     oapvd_ctx_t *ctx;
1904*abb65b4bSAndroid Build Coastguard Worker     ctx = dec_id_to_ctx(did);
1905*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_r(ctx);
1906*abb65b4bSAndroid Build Coastguard Worker 
1907*abb65b4bSAndroid Build Coastguard Worker     DUMP_DELETE();
1908*abb65b4bSAndroid Build Coastguard Worker     dec_flush(ctx);
1909*abb65b4bSAndroid Build Coastguard Worker     dec_ctx_free(ctx);
1910*abb65b4bSAndroid Build Coastguard Worker }
1911*abb65b4bSAndroid Build Coastguard Worker 
oapvd_decode(oapvd_t did,oapv_bitb_t * bitb,oapv_frms_t * ofrms,oapvm_t mid,oapvd_stat_t * stat)1912*abb65b4bSAndroid Build Coastguard Worker int oapvd_decode(oapvd_t did, oapv_bitb_t *bitb, oapv_frms_t *ofrms, oapvm_t mid, oapvd_stat_t *stat)
1913*abb65b4bSAndroid Build Coastguard Worker {
1914*abb65b4bSAndroid Build Coastguard Worker     oapvd_ctx_t *ctx;
1915*abb65b4bSAndroid Build Coastguard Worker     oapv_bs_t   *bs;
1916*abb65b4bSAndroid Build Coastguard Worker     oapv_pbuh_t  pbuh;
1917*abb65b4bSAndroid Build Coastguard Worker     int          ret = OAPV_OK;
1918*abb65b4bSAndroid Build Coastguard Worker     u32          pbu_size;
1919*abb65b4bSAndroid Build Coastguard Worker     u32          remain;
1920*abb65b4bSAndroid Build Coastguard Worker     u8          *curpos;
1921*abb65b4bSAndroid Build Coastguard Worker     int          frame_cnt = 0;
1922*abb65b4bSAndroid Build Coastguard Worker 
1923*abb65b4bSAndroid Build Coastguard Worker     ctx = dec_id_to_ctx(did);
1924*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(ctx, OAPV_ERR_INVALID_ARGUMENT);
1925*abb65b4bSAndroid Build Coastguard Worker 
1926*abb65b4bSAndroid Build Coastguard Worker     curpos = (u8 *)bitb->addr;
1927*abb65b4bSAndroid Build Coastguard Worker     remain = bitb->ssize;
1928*abb65b4bSAndroid Build Coastguard Worker 
1929*abb65b4bSAndroid Build Coastguard Worker     while(remain > 8) {
1930*abb65b4bSAndroid Build Coastguard Worker         oapv_bsr_init(&ctx->bs, curpos, remain, NULL);
1931*abb65b4bSAndroid Build Coastguard Worker         bs = &ctx->bs;
1932*abb65b4bSAndroid Build Coastguard Worker 
1933*abb65b4bSAndroid Build Coastguard Worker         ret = oapvd_vlc_pbu_size(bs, &pbu_size); // 4byte
1934*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
1935*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_g((pbu_size + 4) <= bs->size, ERR);
1936*abb65b4bSAndroid Build Coastguard Worker 
1937*abb65b4bSAndroid Build Coastguard Worker         curpos += 4; // pbu_size syntax
1938*abb65b4bSAndroid Build Coastguard Worker         remain -= 4;
1939*abb65b4bSAndroid Build Coastguard Worker 
1940*abb65b4bSAndroid Build Coastguard Worker         ret = oapvd_vlc_pbu_header(bs, &pbuh);
1941*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
1942*abb65b4bSAndroid Build Coastguard Worker 
1943*abb65b4bSAndroid Build Coastguard Worker         if(pbuh.pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME ||
1944*abb65b4bSAndroid Build Coastguard Worker            pbuh.pbu_type == OAPV_PBU_TYPE_NON_PRIMARY_FRAME ||
1945*abb65b4bSAndroid Build Coastguard Worker            pbuh.pbu_type == OAPV_PBU_TYPE_PREVIEW_FRAME ||
1946*abb65b4bSAndroid Build Coastguard Worker            pbuh.pbu_type == OAPV_PBU_TYPE_DEPTH_FRAME ||
1947*abb65b4bSAndroid Build Coastguard Worker            pbuh.pbu_type == OAPV_PBU_TYPE_ALPHA_FRAME) {
1948*abb65b4bSAndroid Build Coastguard Worker             ret = oapvd_vlc_frame_header(bs, &ctx->fh);
1949*abb65b4bSAndroid Build Coastguard Worker             oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
1950*abb65b4bSAndroid Build Coastguard Worker 
1951*abb65b4bSAndroid Build Coastguard Worker             ret = dec_frm_prepare(ctx, ofrms->frm[frame_cnt].imgb);
1952*abb65b4bSAndroid Build Coastguard Worker             oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
1953*abb65b4bSAndroid Build Coastguard Worker 
1954*abb65b4bSAndroid Build Coastguard Worker             int           res;
1955*abb65b4bSAndroid Build Coastguard Worker             oapv_tpool_t *tpool = ctx->tpool;
1956*abb65b4bSAndroid Build Coastguard Worker             int           parallel_task = 1;
1957*abb65b4bSAndroid Build Coastguard Worker             int           tidx = 0;
1958*abb65b4bSAndroid Build Coastguard Worker 
1959*abb65b4bSAndroid Build Coastguard Worker             parallel_task = (ctx->cdesc.threads > ctx->num_tiles) ? ctx->num_tiles : ctx->cdesc.threads;
1960*abb65b4bSAndroid Build Coastguard Worker 
1961*abb65b4bSAndroid Build Coastguard Worker             /* decode tiles ************************************/
1962*abb65b4bSAndroid Build Coastguard Worker             for(tidx = 0; tidx < (parallel_task - 1); tidx++) {
1963*abb65b4bSAndroid Build Coastguard Worker                 tpool->run(ctx->thread_id[tidx], dec_thread_tile,
1964*abb65b4bSAndroid Build Coastguard Worker                            (void *)ctx->core[tidx]);
1965*abb65b4bSAndroid Build Coastguard Worker             }
1966*abb65b4bSAndroid Build Coastguard Worker             ret = dec_thread_tile((void *)ctx->core[tidx]);
1967*abb65b4bSAndroid Build Coastguard Worker             for(tidx = 0; tidx < parallel_task - 1; tidx++) {
1968*abb65b4bSAndroid Build Coastguard Worker                 tpool->join(ctx->thread_id[tidx], &res);
1969*abb65b4bSAndroid Build Coastguard Worker                 if(OAPV_FAILED(res)) {
1970*abb65b4bSAndroid Build Coastguard Worker                     ret = res;
1971*abb65b4bSAndroid Build Coastguard Worker                 }
1972*abb65b4bSAndroid Build Coastguard Worker             }
1973*abb65b4bSAndroid Build Coastguard Worker             /****************************************************/
1974*abb65b4bSAndroid Build Coastguard Worker 
1975*abb65b4bSAndroid Build Coastguard Worker             /* READ FILLER HERE !!! */
1976*abb65b4bSAndroid Build Coastguard Worker 
1977*abb65b4bSAndroid Build Coastguard Worker             oapv_bsr_move(&ctx->bs, ctx->tile_end);
1978*abb65b4bSAndroid Build Coastguard Worker             stat->read += bsr_get_read_byte(&ctx->bs);
1979*abb65b4bSAndroid Build Coastguard Worker 
1980*abb65b4bSAndroid Build Coastguard Worker             copy_fi_to_finfo(&ctx->fh.fi, pbuh.pbu_type, pbuh.group_id, &stat->aui.frm_info[frame_cnt]);
1981*abb65b4bSAndroid Build Coastguard Worker             if(ret == OAPV_OK && ctx->use_frm_hash) {
1982*abb65b4bSAndroid Build Coastguard Worker                 oapv_imgb_set_md5(ctx->imgb);
1983*abb65b4bSAndroid Build Coastguard Worker             }
1984*abb65b4bSAndroid Build Coastguard Worker             ret = dec_frm_finish(ctx); // FIX-ME
1985*abb65b4bSAndroid Build Coastguard Worker             oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
1986*abb65b4bSAndroid Build Coastguard Worker 
1987*abb65b4bSAndroid Build Coastguard Worker             ofrms->frm[frame_cnt].pbu_type = pbuh.pbu_type;
1988*abb65b4bSAndroid Build Coastguard Worker             ofrms->frm[frame_cnt].group_id = pbuh.group_id;
1989*abb65b4bSAndroid Build Coastguard Worker             stat->frm_size[frame_cnt] = pbu_size + 4 /* PUB size length*/;
1990*abb65b4bSAndroid Build Coastguard Worker             frame_cnt++;
1991*abb65b4bSAndroid Build Coastguard Worker         }
1992*abb65b4bSAndroid Build Coastguard Worker         else if(pbuh.pbu_type == OAPV_PBU_TYPE_METADATA) {
1993*abb65b4bSAndroid Build Coastguard Worker             ret = oapvd_vlc_metadata(bs, pbu_size, mid, pbuh.group_id);
1994*abb65b4bSAndroid Build Coastguard Worker             oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
1995*abb65b4bSAndroid Build Coastguard Worker 
1996*abb65b4bSAndroid Build Coastguard Worker             stat->read += bsr_get_read_byte(&ctx->bs);
1997*abb65b4bSAndroid Build Coastguard Worker         }
1998*abb65b4bSAndroid Build Coastguard Worker         else if(pbuh.pbu_type == OAPV_PBU_TYPE_FILLER) {
1999*abb65b4bSAndroid Build Coastguard Worker             ret = oapvd_vlc_filler(bs, (pbu_size - 4));
2000*abb65b4bSAndroid Build Coastguard Worker             oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
2001*abb65b4bSAndroid Build Coastguard Worker         }
2002*abb65b4bSAndroid Build Coastguard Worker         curpos += pbu_size;
2003*abb65b4bSAndroid Build Coastguard Worker         remain = (remain < pbu_size)? 0: (remain - pbu_size);
2004*abb65b4bSAndroid Build Coastguard Worker     }
2005*abb65b4bSAndroid Build Coastguard Worker     stat->aui.num_frms = frame_cnt;
2006*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(ofrms->num_frms == frame_cnt, OAPV_ERR_MALFORMED_BITSTREAM);
2007*abb65b4bSAndroid Build Coastguard Worker     return ret;
2008*abb65b4bSAndroid Build Coastguard Worker 
2009*abb65b4bSAndroid Build Coastguard Worker ERR:
2010*abb65b4bSAndroid Build Coastguard Worker     return ret;
2011*abb65b4bSAndroid Build Coastguard Worker }
2012*abb65b4bSAndroid Build Coastguard Worker 
oapvd_config(oapvd_t did,int cfg,void * buf,int * size)2013*abb65b4bSAndroid Build Coastguard Worker int oapvd_config(oapvd_t did, int cfg, void *buf, int *size)
2014*abb65b4bSAndroid Build Coastguard Worker {
2015*abb65b4bSAndroid Build Coastguard Worker     oapvd_ctx_t *ctx;
2016*abb65b4bSAndroid Build Coastguard Worker 
2017*abb65b4bSAndroid Build Coastguard Worker     ctx = dec_id_to_ctx(did);
2018*abb65b4bSAndroid Build Coastguard Worker     oapv_assert_rv(ctx, OAPV_ERR_INVALID_ARGUMENT);
2019*abb65b4bSAndroid Build Coastguard Worker 
2020*abb65b4bSAndroid Build Coastguard Worker     switch(cfg) {
2021*abb65b4bSAndroid Build Coastguard Worker     /* set config ************************************************************/
2022*abb65b4bSAndroid Build Coastguard Worker     case OAPV_CFG_SET_USE_FRM_HASH:
2023*abb65b4bSAndroid Build Coastguard Worker         ctx->use_frm_hash = (*((int *)buf)) ? 1 : 0;
2024*abb65b4bSAndroid Build Coastguard Worker         break;
2025*abb65b4bSAndroid Build Coastguard Worker 
2026*abb65b4bSAndroid Build Coastguard Worker     default:
2027*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(0, OAPV_ERR_UNSUPPORTED);
2028*abb65b4bSAndroid Build Coastguard Worker     }
2029*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
2030*abb65b4bSAndroid Build Coastguard Worker }
2031*abb65b4bSAndroid Build Coastguard Worker 
oapvd_info(void * au,int au_size,oapv_au_info_t * aui)2032*abb65b4bSAndroid Build Coastguard Worker int oapvd_info(void *au, int au_size, oapv_au_info_t *aui)
2033*abb65b4bSAndroid Build Coastguard Worker {
2034*abb65b4bSAndroid Build Coastguard Worker     int ret, frm_count = 0;
2035*abb65b4bSAndroid Build Coastguard Worker     int pbu_cnt = 0;
2036*abb65b4bSAndroid Build Coastguard Worker     u8 *curpos;
2037*abb65b4bSAndroid Build Coastguard Worker     u32 remain;
2038*abb65b4bSAndroid Build Coastguard Worker 
2039*abb65b4bSAndroid Build Coastguard Worker     curpos = (u8 *)au;
2040*abb65b4bSAndroid Build Coastguard Worker     remain = au_size;
2041*abb65b4bSAndroid Build Coastguard Worker 
2042*abb65b4bSAndroid Build Coastguard Worker     DUMP_SET(0);
2043*abb65b4bSAndroid Build Coastguard Worker     while(remain > 8) // FIX-ME (8byte?)
2044*abb65b4bSAndroid Build Coastguard Worker     {
2045*abb65b4bSAndroid Build Coastguard Worker         oapv_bs_t bs;
2046*abb65b4bSAndroid Build Coastguard Worker         u32       pbu_size = 0;
2047*abb65b4bSAndroid Build Coastguard Worker 
2048*abb65b4bSAndroid Build Coastguard Worker         oapv_bsr_init(&bs, curpos, remain, NULL);
2049*abb65b4bSAndroid Build Coastguard Worker 
2050*abb65b4bSAndroid Build Coastguard Worker         ret = oapvd_vlc_pbu_size(&bs, &pbu_size); // 4 byte
2051*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(OAPV_SUCCEEDED(ret), ret);
2052*abb65b4bSAndroid Build Coastguard Worker         curpos += 4; // pbu_size syntax
2053*abb65b4bSAndroid Build Coastguard Worker         remain -= 4;
2054*abb65b4bSAndroid Build Coastguard Worker 
2055*abb65b4bSAndroid Build Coastguard Worker         /* pbu header */
2056*abb65b4bSAndroid Build Coastguard Worker         oapv_pbuh_t pbuh;
2057*abb65b4bSAndroid Build Coastguard Worker         ret = oapvd_vlc_pbu_header(&bs, &pbuh); // 4 byte
2058*abb65b4bSAndroid Build Coastguard Worker         oapv_assert_rv(OAPV_SUCCEEDED(ret), OAPV_ERR_MALFORMED_BITSTREAM);
2059*abb65b4bSAndroid Build Coastguard Worker         if(pbuh.pbu_type == OAPV_PBU_TYPE_AU_INFO) {
2060*abb65b4bSAndroid Build Coastguard Worker             // parse access_unit_info in PBU
2061*abb65b4bSAndroid Build Coastguard Worker             oapv_aui_t ai;
2062*abb65b4bSAndroid Build Coastguard Worker 
2063*abb65b4bSAndroid Build Coastguard Worker             ret = oapvd_vlc_au_info(&bs, &ai);
2064*abb65b4bSAndroid Build Coastguard Worker             oapv_assert_rv(OAPV_SUCCEEDED(ret), ret);
2065*abb65b4bSAndroid Build Coastguard Worker 
2066*abb65b4bSAndroid Build Coastguard Worker             aui->num_frms = ai.num_frames;
2067*abb65b4bSAndroid Build Coastguard Worker             for(int i = 0; i < ai.num_frames; i++) {
2068*abb65b4bSAndroid Build Coastguard Worker                 copy_fi_to_finfo(&ai.frame_info[i], ai.pbu_type[i], ai.group_id[i], &aui->frm_info[i]);
2069*abb65b4bSAndroid Build Coastguard Worker             }
2070*abb65b4bSAndroid Build Coastguard Worker             return OAPV_OK; // founded access_unit_info, no need to read more PBUs
2071*abb65b4bSAndroid Build Coastguard Worker         }
2072*abb65b4bSAndroid Build Coastguard Worker         if(pbuh.pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME ||
2073*abb65b4bSAndroid Build Coastguard Worker            pbuh.pbu_type == OAPV_PBU_TYPE_NON_PRIMARY_FRAME ||
2074*abb65b4bSAndroid Build Coastguard Worker            pbuh.pbu_type == OAPV_PBU_TYPE_PREVIEW_FRAME ||
2075*abb65b4bSAndroid Build Coastguard Worker            pbuh.pbu_type == OAPV_PBU_TYPE_DEPTH_FRAME ||
2076*abb65b4bSAndroid Build Coastguard Worker            pbuh.pbu_type == OAPV_PBU_TYPE_ALPHA_FRAME) {
2077*abb65b4bSAndroid Build Coastguard Worker             // parse frame_info in PBU
2078*abb65b4bSAndroid Build Coastguard Worker             oapv_fi_t fi;
2079*abb65b4bSAndroid Build Coastguard Worker 
2080*abb65b4bSAndroid Build Coastguard Worker             oapv_assert_rv(frm_count < OAPV_MAX_NUM_FRAMES, OAPV_ERR_REACHED_MAX)
2081*abb65b4bSAndroid Build Coastguard Worker             ret = oapvd_vlc_frame_info(&bs, &fi);
2082*abb65b4bSAndroid Build Coastguard Worker             oapv_assert_rv(OAPV_SUCCEEDED(ret), ret);
2083*abb65b4bSAndroid Build Coastguard Worker 
2084*abb65b4bSAndroid Build Coastguard Worker             copy_fi_to_finfo(&fi, pbuh.pbu_type, pbuh.group_id, &aui->frm_info[frm_count]);
2085*abb65b4bSAndroid Build Coastguard Worker             frm_count++;
2086*abb65b4bSAndroid Build Coastguard Worker         }
2087*abb65b4bSAndroid Build Coastguard Worker         aui->num_frms = frm_count;
2088*abb65b4bSAndroid Build Coastguard Worker 
2089*abb65b4bSAndroid Build Coastguard Worker         curpos += pbu_size;
2090*abb65b4bSAndroid Build Coastguard Worker         remain = (remain < pbu_size)? 0: (remain - pbu_size);
2091*abb65b4bSAndroid Build Coastguard Worker         ++pbu_cnt;
2092*abb65b4bSAndroid Build Coastguard Worker     }
2093*abb65b4bSAndroid Build Coastguard Worker     DUMP_SET(1);
2094*abb65b4bSAndroid Build Coastguard Worker     return OAPV_OK;
2095*abb65b4bSAndroid Build Coastguard Worker }
2096*abb65b4bSAndroid Build Coastguard Worker 
2097*abb65b4bSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
2098*abb65b4bSAndroid Build Coastguard Worker // end of decoder code
2099*abb65b4bSAndroid Build Coastguard Worker #endif // ENABLE_DECODER
2100*abb65b4bSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////