xref: /rockchip-linux_mpp/mpp/hal/common/h264/hal_h264e_stream_amend.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /*
2  * Copyright 2022 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define MODULE_TAG "hal_h264e_amend"
18 
19 #include <stdio.h>
20 #include <string.h>
21 #include <unistd.h>
22 
23 #include "mpp_mem.h"
24 #include "mpp_common.h"
25 #include "mpp_dmabuf.h"
26 #include "mpp_packet_impl.h"
27 
28 #include "mpp_enc_cfg.h"
29 #include "mpp_enc_refs.h"
30 
31 #include "hal_h264e_debug.h"
32 #include "hal_h264e_stream_amend.h"
33 
34 #include "h264e_sps.h"
35 #include "h264e_pps.h"
36 #include "h264e_slice.h"
37 
38 #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes
39 
get_next_nal(RK_U8 * buf,RK_S32 * length)40 static RK_S32 get_next_nal(RK_U8 *buf, RK_S32 *length)
41 {
42     RK_S32 i, consumed = 0;
43     RK_S32 len = *length;
44     RK_U8 *tmp_buf = buf;
45 
46     /* search start code */
47     while (len >= 4) {
48         if (tmp_buf[2] == 0) {
49             len--;
50             tmp_buf++;
51             continue;
52         }
53 
54         if (tmp_buf[0] != 0 || tmp_buf[1] != 0 || tmp_buf[2] != 1) {
55             RK_U32 state = (RK_U32) - 1;
56             RK_S32 has_nal = 0;
57 
58             for (i = 0; i < (RK_S32)len; i++) {
59                 state = (state << 8) | tmp_buf[i];
60                 if (((state >> 8) & 0xFFFFFF) == START_CODE) {
61                     has_nal = 1;
62                     i = i - 3;
63                     break;
64                 }
65             }
66 
67             if (has_nal) {
68                 len -= i;
69                 tmp_buf += i;
70                 consumed = *length - len - 1;
71                 break;
72             }
73 
74             consumed = *length;
75             break;
76         }
77         tmp_buf   += 3;
78         len       -= 3;
79     }
80 
81     *length = *length - consumed;
82     return consumed;
83 }
84 
h264e_vepu_stream_amend_init(HalH264eVepuStreamAmend * ctx)85 MPP_RET h264e_vepu_stream_amend_init(HalH264eVepuStreamAmend *ctx)
86 {
87     memset(ctx, 0, sizeof(*ctx));
88     ctx->buf_size = SZ_128K;
89     return MPP_OK;
90 }
91 
h264e_vepu_stream_amend_deinit(HalH264eVepuStreamAmend * ctx)92 MPP_RET h264e_vepu_stream_amend_deinit(HalH264eVepuStreamAmend *ctx)
93 {
94     MPP_FREE(ctx->src_buf);
95     MPP_FREE(ctx->dst_buf);
96     return MPP_OK;
97 }
98 
h264e_vepu_stream_amend_config(HalH264eVepuStreamAmend * ctx,MppPacket packet,MppEncCfgSet * cfg,H264eSlice * slice,H264ePrefixNal * prefix)99 MPP_RET h264e_vepu_stream_amend_config(HalH264eVepuStreamAmend *ctx,
100                                        MppPacket packet, MppEncCfgSet *cfg,
101                                        H264eSlice *slice, H264ePrefixNal *prefix)
102 {
103     MppEncRefCfgImpl *ref = (MppEncRefCfgImpl *)cfg->ref_cfg;
104     MppEncH264Cfg    *h264 = &cfg->h264;
105     MppEncH264HwCfg  *hw_cfg = &h264->hw_cfg;
106 
107     if (ref->lt_cfg_cnt || ref->st_cfg_cnt > 1 ||
108         hw_cfg->hw_poc_type != h264->poc_type ||
109         hw_cfg->hw_log2_max_frame_num_minus4 != h264->log2_max_frame_num) {
110         ctx->enable = 1;
111         ctx->slice_enabled = 0;
112 
113         if (NULL == ctx->dst_buf)
114             ctx->dst_buf = mpp_calloc(RK_U8, ctx->buf_size);
115         if (NULL == ctx->src_buf)
116             ctx->src_buf = mpp_calloc(RK_U8, ctx->buf_size);
117     } else {
118         MPP_FREE(ctx->dst_buf);
119         MPP_FREE(ctx->src_buf);
120         h264e_vepu_stream_amend_init(ctx);
121     }
122 
123     slice->pic_order_cnt_type = cfg->h264.poc_type;
124 
125     ctx->slice = slice;
126     if (ref->lt_cfg_cnt || ref->st_cfg_cnt > 1)
127         ctx->prefix = prefix;
128 
129     ctx->packet = packet;
130     ctx->buf_base = mpp_packet_get_length(packet);
131     ctx->old_length = 0;
132     ctx->new_length = 0;
133 
134     return MPP_OK;
135 }
136 
h264e_vepu_stream_amend_proc(HalH264eVepuStreamAmend * ctx,MppEncH264HwCfg * hw_cfg)137 MPP_RET h264e_vepu_stream_amend_proc(HalH264eVepuStreamAmend *ctx, MppEncH264HwCfg *hw_cfg)
138 {
139     H264ePrefixNal *prefix = ctx->prefix;
140     H264eSlice *slice = ctx->slice;
141     MppPacket pkt = ctx->packet;
142     RK_U8 *p = mpp_packet_get_pos(pkt);
143     RK_S32 base = ctx->buf_base;
144     RK_S32 len = ctx->old_length;
145     RK_S32 hw_len_bit = 0;
146     RK_S32 sw_len_bit = 0;
147     RK_S32 hw_len_byte = 0;
148     RK_S32 sw_len_byte = 0;
149     RK_S32 diff_size = 0;
150     RK_S32 tail_0bit = 0;
151     RK_U8  tail_byte = 0;
152     RK_U8  tail_tmp = 0;
153     RK_U8 *dst_buf = NULL;
154     RK_S32 buf_size;
155     RK_S32 final_len = 0;
156     RK_S32 last_slice = 0;
157     const MppPktSeg *seg = mpp_packet_get_segment_info(pkt);
158     MppPacket pkt_tmp;
159     RK_S32 offset = 0;
160     RK_U32 is_cabac = ctx->slice->entropy_coding_mode;
161 
162     mpp_packet_new(&pkt_tmp);
163 
164     if (seg) {
165         while (seg && seg->type != 1 && seg->type != 5) {
166             mpp_packet_add_segment_info(pkt_tmp, seg->type, offset, seg->len);
167             offset += seg->len;
168 
169             seg = seg->next;
170         }
171     }
172 
173     {
174         MppBuffer buf = mpp_packet_get_buffer(pkt);
175         RK_S32 fd = mpp_buffer_get_fd(buf);
176 
177         mpp_dmabuf_sync_partial_begin(fd, 1, base, len, __FUNCTION__);
178     }
179 
180     {
181         RK_S32 more_buf = 0;
182         while (len > ctx->buf_size - 16) {
183             ctx->buf_size *= 2;
184             more_buf = 1;
185         }
186 
187         if (more_buf) {
188             MPP_FREE(ctx->src_buf);
189             MPP_FREE(ctx->dst_buf);
190             ctx->src_buf = mpp_malloc(RK_U8, ctx->buf_size);
191             ctx->dst_buf = mpp_malloc(RK_U8, ctx->buf_size);
192         }
193     }
194 
195     memset(ctx->dst_buf, 0, ctx->buf_size);
196     memset(ctx->src_buf, 0, ctx->buf_size);
197     dst_buf = ctx->dst_buf;
198     buf_size = ctx->buf_size;
199     p += base;
200 
201     do {
202         RK_U32 nal_len = 0;
203 
204         tail_0bit = 0;
205         // copy hw stream to stream buffer first
206         if (slice->is_multi_slice) {
207             if ((!seg) || !hw_cfg->hw_split_out || !is_cabac) {
208                 nal_len = get_next_nal(p, &len);
209                 last_slice = (len == 0);
210             } else {
211                 nal_len = seg->len;
212                 len -= seg->len;
213                 seg = seg->next;
214                 if (!seg || !len)
215                     last_slice = 1;
216             }
217             memcpy(ctx->src_buf, p, nal_len);
218             p += nal_len;
219         } else {
220             memcpy(ctx->src_buf, p, len);
221             nal_len = len;
222             last_slice = 1;
223         }
224 
225         hal_h264e_dbg_amend("nal_len %d multi %d last %d prefix %p\n",
226                             nal_len, slice->is_multi_slice, last_slice, prefix);
227 
228         if (prefix) {
229             /* add prefix for each slice */
230             RK_S32 prefix_bit = h264e_slice_write_prefix_nal_unit_svc(prefix, dst_buf, buf_size);
231 
232             prefix_bit = (prefix_bit + 7) / 8;
233 
234             dst_buf += prefix_bit;
235             buf_size -= prefix_bit;
236             final_len += prefix_bit;
237 
238             mpp_packet_add_segment_info(pkt_tmp, H264_NALU_TYPE_PREFIX, offset, prefix_bit);
239             offset += prefix_bit;
240         }
241 
242         H264eSlice slice_rd;
243 
244         memcpy(&slice_rd, slice, sizeof(slice_rd));
245 
246         /* update slice by hw_cfg */
247         slice_rd.pic_order_cnt_type = hw_cfg->hw_poc_type;
248         slice_rd.log2_max_frame_num = hw_cfg->hw_log2_max_frame_num_minus4 + 4;
249 
250         if (ctx->reorder) {
251             slice_rd.reorder = ctx->reorder;
252             h264e_reorder_init(slice_rd.reorder);
253         }
254         if (ctx->marking) {
255             slice_rd.marking = ctx->marking;
256             h264e_marking_init(slice_rd.marking);
257         }
258 
259         hw_len_bit = h264e_slice_read(&slice_rd, ctx->src_buf, nal_len);
260 
261         // write new header to header buffer
262         slice->qp_delta = slice_rd.qp_delta;
263         slice->first_mb_in_slice = slice_rd.first_mb_in_slice;
264 
265         if (ctx->reorder)
266             slice->reorder = slice_rd.reorder;
267         if (ctx->marking)
268             slice->marking = slice_rd.marking;
269 
270         sw_len_bit = h264e_slice_write(slice, dst_buf, buf_size);
271 
272         hw_len_byte = (hw_len_bit + 7) / 8;
273         sw_len_byte = (sw_len_bit + 7) / 8;
274 
275         tail_byte = ctx->src_buf[nal_len - 1];
276         tail_tmp = tail_byte;
277 
278         while (!(tail_tmp & 1) && tail_0bit < 8) {
279             tail_tmp >>= 1;
280             tail_0bit++;
281         }
282 
283         mpp_assert(tail_0bit < 8);
284 
285         // move the reset slice data from src buffer to dst buffer
286         diff_size = h264e_slice_move(dst_buf, ctx->src_buf,
287                                      sw_len_bit, hw_len_bit, nal_len);
288 
289         hal_h264e_dbg_amend("tail 0x%02x %d hw_hdr %d sw_hdr %d len %d hw_byte %d sw_byte %d diff %d\n",
290                             tail_byte, tail_0bit, hw_len_bit, sw_len_bit, nal_len, hw_len_byte, sw_len_byte, diff_size);
291 
292         if (slice->entropy_coding_mode) {
293             memcpy(dst_buf + sw_len_byte, ctx->src_buf + hw_len_byte,
294                    nal_len - hw_len_byte);
295             final_len += nal_len - hw_len_byte + sw_len_byte;
296             nal_len = nal_len - hw_len_byte + sw_len_byte;
297         } else {
298             RK_S32 hdr_diff_bit = sw_len_bit - hw_len_bit;
299             RK_S32 bit_len = nal_len * 8 - tail_0bit + hdr_diff_bit;
300             RK_S32 new_len = (bit_len + diff_size * 8 + 7) / 8;
301 
302             hal_h264e_dbg_amend("frm %4d %c len %d bit hw %d sw %d byte hw %d sw %d diff %d -> %d\n",
303                                 slice->frame_num, (slice->idr_flag ? 'I' : 'P'),
304                                 nal_len, hw_len_bit, sw_len_bit,
305                                 hw_len_byte, sw_len_byte, diff_size, new_len);
306 
307             hal_h264e_dbg_amend("%02x %02x %02x %02x -> %02x %02x %02x %02x\n",
308                                 ctx->src_buf[nal_len - 4], ctx->src_buf[nal_len - 3],
309                                 ctx->src_buf[nal_len - 2], ctx->src_buf[nal_len - 1],
310                                 dst_buf[new_len - 4], dst_buf[new_len - 3],
311                                 dst_buf[new_len - 2], dst_buf[new_len - 1]);
312             nal_len = new_len;
313             final_len += new_len;
314         }
315 
316         {
317             H264NaluType type = slice->idr_flag ?  H264_NALU_TYPE_IDR : H264_NALU_TYPE_SLICE;
318 
319             mpp_packet_add_segment_info(pkt_tmp, type, offset, nal_len);
320             offset += nal_len;
321         }
322 
323         if (last_slice) {
324             p = mpp_packet_get_pos(pkt);
325             p += base;
326             memcpy(p, ctx->dst_buf, final_len);
327 
328             if (slice->entropy_coding_mode) {
329                 if (final_len < ctx->old_length)
330                     memset(p + final_len, 0,  ctx->old_length - final_len);
331             } else
332                 p[final_len] = 0;
333 
334             break;
335         }
336 
337         dst_buf += nal_len;
338         buf_size -= nal_len;
339     } while (1);
340 
341     ctx->new_length = final_len;
342 
343     /* update segment */
344     mpp_packet_copy_segment_info(pkt, pkt_tmp);
345 
346     mpp_packet_deinit(&pkt_tmp);
347 
348     return MPP_OK;
349 }
350 
h264e_vepu_stream_amend_sync_ref_idc(HalH264eVepuStreamAmend * ctx)351 MPP_RET h264e_vepu_stream_amend_sync_ref_idc(HalH264eVepuStreamAmend *ctx)
352 {
353     H264eSlice *slice = ctx->slice;
354     MppPacket pkt = ctx->packet;
355     RK_S32 base = ctx->buf_base;
356     RK_S32 len = ctx->old_length;
357     RK_U8 *p = mpp_packet_get_pos(pkt) + base;
358     RK_U8 val = 0;
359     RK_S32 hw_nal_ref_idc = 0;
360     RK_S32 sw_nal_ref_idc = 0;
361 
362     {
363         MppBuffer buf = mpp_packet_get_buffer(pkt);
364         RK_S32 fd = mpp_buffer_get_fd(buf);
365 
366         mpp_dmabuf_sync_partial_begin(fd, 1, base, len, __FUNCTION__);
367     }
368 
369     val = p[4];
370     hw_nal_ref_idc = (val >> 5) & 0x3;
371     sw_nal_ref_idc = slice->nal_reference_idc;
372 
373     if (hw_nal_ref_idc == sw_nal_ref_idc)
374         return MPP_OK;
375 
376     /* fix nal_ref_idc in all slice */
377     if (!slice->is_multi_slice) {
378         /* single slice do NOT scan */
379         val = val & (~0x60);
380         val |= (sw_nal_ref_idc << 5) & 0x60;
381         p[4] = val;
382         return MPP_OK;
383     }
384 
385     /* multi-slice fix each nal_ref_idc */
386     do {
387         RK_U32 nal_len = get_next_nal(p, &len);
388 
389         val = p[4];
390         val = val & (~0x60);
391         val |= (sw_nal_ref_idc << 5) & 0x60;
392         p[4] = val;
393 
394         if (len == 0)
395             break;
396 
397         p += nal_len;
398     } while (1);
399 
400     return MPP_OK;
401 }
402