18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Coda multi-standard codec IP - H.264 helper functions 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2012 Vista Silicon S.L. 68c2ecf20Sopenharmony_ci * Javier Martin, <javier.martin@vista-silicon.com> 78c2ecf20Sopenharmony_ci * Xavier Duret 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/string.h> 128c2ecf20Sopenharmony_ci#include <linux/videodev2.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "coda.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 }; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic const u8 *coda_find_nal_header(const u8 *buf, const u8 *end) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci u32 val = 0xffffffff; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci do { 238c2ecf20Sopenharmony_ci val = val << 8 | *buf++; 248c2ecf20Sopenharmony_ci if (buf >= end) 258c2ecf20Sopenharmony_ci return NULL; 268c2ecf20Sopenharmony_ci } while (val != 0x00000001); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci return buf; 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ciint coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci const u8 *buf = vb2_plane_vaddr(vb, 0); 348c2ecf20Sopenharmony_ci const u8 *end = buf + vb2_get_plane_payload(vb, 0); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci /* Find SPS header */ 378c2ecf20Sopenharmony_ci do { 388c2ecf20Sopenharmony_ci buf = coda_find_nal_header(buf, end); 398c2ecf20Sopenharmony_ci if (!buf) 408c2ecf20Sopenharmony_ci return -EINVAL; 418c2ecf20Sopenharmony_ci } while ((*buf++ & 0x1f) != 0x7); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci ctx->params.h264_profile_idc = buf[0]; 448c2ecf20Sopenharmony_ci ctx->params.h264_level_idc = buf[2]; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci return 0; 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ciint coda_h264_filler_nal(int size, char *p) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci if (size < 6) 528c2ecf20Sopenharmony_ci return -EINVAL; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci p[0] = 0x00; 558c2ecf20Sopenharmony_ci p[1] = 0x00; 568c2ecf20Sopenharmony_ci p[2] = 0x00; 578c2ecf20Sopenharmony_ci p[3] = 0x01; 588c2ecf20Sopenharmony_ci p[4] = 0x0c; 598c2ecf20Sopenharmony_ci memset(p + 5, 0xff, size - 6); 608c2ecf20Sopenharmony_ci /* Add rbsp stop bit and trailing at the end */ 618c2ecf20Sopenharmony_ci p[size - 1] = 0x80; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci return 0; 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ciint coda_h264_padding(int size, char *p) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci int nal_size; 698c2ecf20Sopenharmony_ci int diff; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci diff = size - (size & ~0x7); 728c2ecf20Sopenharmony_ci if (diff == 0) 738c2ecf20Sopenharmony_ci return 0; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci nal_size = coda_filler_size[diff]; 768c2ecf20Sopenharmony_ci coda_h264_filler_nal(nal_size, p); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci return nal_size; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ciint coda_h264_profile(int profile_idc) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci switch (profile_idc) { 848c2ecf20Sopenharmony_ci case 66: return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE; 858c2ecf20Sopenharmony_ci case 77: return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN; 868c2ecf20Sopenharmony_ci case 88: return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED; 878c2ecf20Sopenharmony_ci case 100: return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH; 888c2ecf20Sopenharmony_ci default: return -EINVAL; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciint coda_h264_level(int level_idc) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci switch (level_idc) { 958c2ecf20Sopenharmony_ci case 10: return V4L2_MPEG_VIDEO_H264_LEVEL_1_0; 968c2ecf20Sopenharmony_ci case 9: return V4L2_MPEG_VIDEO_H264_LEVEL_1B; 978c2ecf20Sopenharmony_ci case 11: return V4L2_MPEG_VIDEO_H264_LEVEL_1_1; 988c2ecf20Sopenharmony_ci case 12: return V4L2_MPEG_VIDEO_H264_LEVEL_1_2; 998c2ecf20Sopenharmony_ci case 13: return V4L2_MPEG_VIDEO_H264_LEVEL_1_3; 1008c2ecf20Sopenharmony_ci case 20: return V4L2_MPEG_VIDEO_H264_LEVEL_2_0; 1018c2ecf20Sopenharmony_ci case 21: return V4L2_MPEG_VIDEO_H264_LEVEL_2_1; 1028c2ecf20Sopenharmony_ci case 22: return V4L2_MPEG_VIDEO_H264_LEVEL_2_2; 1038c2ecf20Sopenharmony_ci case 30: return V4L2_MPEG_VIDEO_H264_LEVEL_3_0; 1048c2ecf20Sopenharmony_ci case 31: return V4L2_MPEG_VIDEO_H264_LEVEL_3_1; 1058c2ecf20Sopenharmony_ci case 32: return V4L2_MPEG_VIDEO_H264_LEVEL_3_2; 1068c2ecf20Sopenharmony_ci case 40: return V4L2_MPEG_VIDEO_H264_LEVEL_4_0; 1078c2ecf20Sopenharmony_ci case 41: return V4L2_MPEG_VIDEO_H264_LEVEL_4_1; 1088c2ecf20Sopenharmony_ci case 42: return V4L2_MPEG_VIDEO_H264_LEVEL_4_2; 1098c2ecf20Sopenharmony_ci case 50: return V4L2_MPEG_VIDEO_H264_LEVEL_5_0; 1108c2ecf20Sopenharmony_ci case 51: return V4L2_MPEG_VIDEO_H264_LEVEL_5_1; 1118c2ecf20Sopenharmony_ci default: return -EINVAL; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistruct rbsp { 1168c2ecf20Sopenharmony_ci char *buf; 1178c2ecf20Sopenharmony_ci int size; 1188c2ecf20Sopenharmony_ci int pos; 1198c2ecf20Sopenharmony_ci}; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic inline int rbsp_read_bit(struct rbsp *rbsp) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci int shift = 7 - (rbsp->pos % 8); 1248c2ecf20Sopenharmony_ci int ofs = rbsp->pos++ / 8; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci if (ofs >= rbsp->size) 1278c2ecf20Sopenharmony_ci return -EINVAL; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci return (rbsp->buf[ofs] >> shift) & 1; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic inline int rbsp_write_bit(struct rbsp *rbsp, int bit) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci int shift = 7 - (rbsp->pos % 8); 1358c2ecf20Sopenharmony_ci int ofs = rbsp->pos++ / 8; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (ofs >= rbsp->size) 1388c2ecf20Sopenharmony_ci return -EINVAL; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci rbsp->buf[ofs] &= ~(1 << shift); 1418c2ecf20Sopenharmony_ci rbsp->buf[ofs] |= bit << shift; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci return 0; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic inline int rbsp_read_bits(struct rbsp *rbsp, int num, int *val) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci int i, ret; 1498c2ecf20Sopenharmony_ci int tmp = 0; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (num > 32) 1528c2ecf20Sopenharmony_ci return -EINVAL; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 1558c2ecf20Sopenharmony_ci ret = rbsp_read_bit(rbsp); 1568c2ecf20Sopenharmony_ci if (ret < 0) 1578c2ecf20Sopenharmony_ci return ret; 1588c2ecf20Sopenharmony_ci tmp |= ret << (num - i - 1); 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci if (val) 1628c2ecf20Sopenharmony_ci *val = tmp; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci return 0; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic int rbsp_write_bits(struct rbsp *rbsp, int num, int value) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci int ret; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci while (num--) { 1728c2ecf20Sopenharmony_ci ret = rbsp_write_bit(rbsp, (value >> num) & 1); 1738c2ecf20Sopenharmony_ci if (ret) 1748c2ecf20Sopenharmony_ci return ret; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci return 0; 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_cistatic int rbsp_read_uev(struct rbsp *rbsp, unsigned int *val) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci int leading_zero_bits = 0; 1838c2ecf20Sopenharmony_ci unsigned int tmp = 0; 1848c2ecf20Sopenharmony_ci int ret; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci while ((ret = rbsp_read_bit(rbsp)) == 0) 1878c2ecf20Sopenharmony_ci leading_zero_bits++; 1888c2ecf20Sopenharmony_ci if (ret < 0) 1898c2ecf20Sopenharmony_ci return ret; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci if (leading_zero_bits > 0) { 1928c2ecf20Sopenharmony_ci ret = rbsp_read_bits(rbsp, leading_zero_bits, &tmp); 1938c2ecf20Sopenharmony_ci if (ret) 1948c2ecf20Sopenharmony_ci return ret; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (val) 1988c2ecf20Sopenharmony_ci *val = (1 << leading_zero_bits) - 1 + tmp; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci return 0; 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic int rbsp_write_uev(struct rbsp *rbsp, unsigned int value) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci int i; 2068c2ecf20Sopenharmony_ci int ret; 2078c2ecf20Sopenharmony_ci int tmp = value + 1; 2088c2ecf20Sopenharmony_ci int leading_zero_bits = fls(tmp) - 1; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci for (i = 0; i < leading_zero_bits; i++) { 2118c2ecf20Sopenharmony_ci ret = rbsp_write_bit(rbsp, 0); 2128c2ecf20Sopenharmony_ci if (ret) 2138c2ecf20Sopenharmony_ci return ret; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci return rbsp_write_bits(rbsp, leading_zero_bits + 1, tmp); 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic int rbsp_read_sev(struct rbsp *rbsp, int *val) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci unsigned int tmp; 2228c2ecf20Sopenharmony_ci int ret; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci ret = rbsp_read_uev(rbsp, &tmp); 2258c2ecf20Sopenharmony_ci if (ret) 2268c2ecf20Sopenharmony_ci return ret; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (val) { 2298c2ecf20Sopenharmony_ci if (tmp & 1) 2308c2ecf20Sopenharmony_ci *val = (tmp + 1) / 2; 2318c2ecf20Sopenharmony_ci else 2328c2ecf20Sopenharmony_ci *val = -(tmp / 2); 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci return 0; 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci/** 2398c2ecf20Sopenharmony_ci * coda_h264_sps_fixup - fixes frame cropping values in h.264 SPS 2408c2ecf20Sopenharmony_ci * @ctx: encoder context 2418c2ecf20Sopenharmony_ci * @width: visible width 2428c2ecf20Sopenharmony_ci * @height: visible height 2438c2ecf20Sopenharmony_ci * @buf: buffer containing h.264 SPS RBSP, starting with NAL header 2448c2ecf20Sopenharmony_ci * @size: modified RBSP size return value 2458c2ecf20Sopenharmony_ci * @max_size: available size in buf 2468c2ecf20Sopenharmony_ci * 2478c2ecf20Sopenharmony_ci * Rewrites the frame cropping values in an h.264 SPS RBSP correctly for the 2488c2ecf20Sopenharmony_ci * given visible width and height. 2498c2ecf20Sopenharmony_ci */ 2508c2ecf20Sopenharmony_ciint coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf, 2518c2ecf20Sopenharmony_ci int *size, int max_size) 2528c2ecf20Sopenharmony_ci{ 2538c2ecf20Sopenharmony_ci int profile_idc; 2548c2ecf20Sopenharmony_ci unsigned int pic_order_cnt_type; 2558c2ecf20Sopenharmony_ci int pic_width_in_mbs_minus1, pic_height_in_map_units_minus1; 2568c2ecf20Sopenharmony_ci int frame_mbs_only_flag, frame_cropping_flag; 2578c2ecf20Sopenharmony_ci int vui_parameters_present_flag; 2588c2ecf20Sopenharmony_ci unsigned int crop_right, crop_bottom; 2598c2ecf20Sopenharmony_ci struct rbsp sps; 2608c2ecf20Sopenharmony_ci int pos; 2618c2ecf20Sopenharmony_ci int ret; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (*size < 8 || *size >= max_size) 2648c2ecf20Sopenharmony_ci return -EINVAL; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci sps.buf = buf + 5; /* Skip NAL header */ 2678c2ecf20Sopenharmony_ci sps.size = *size - 5; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci profile_idc = sps.buf[0]; 2708c2ecf20Sopenharmony_ci /* Skip constraint_set[0-5]_flag, reserved_zero_2bits */ 2718c2ecf20Sopenharmony_ci /* Skip level_idc */ 2728c2ecf20Sopenharmony_ci sps.pos = 24; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci /* seq_parameter_set_id */ 2758c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, NULL); 2768c2ecf20Sopenharmony_ci if (ret) 2778c2ecf20Sopenharmony_ci return ret; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || 2808c2ecf20Sopenharmony_ci profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || 2818c2ecf20Sopenharmony_ci profile_idc == 86 || profile_idc == 118 || profile_idc == 128 || 2828c2ecf20Sopenharmony_ci profile_idc == 138 || profile_idc == 139 || profile_idc == 134 || 2838c2ecf20Sopenharmony_ci profile_idc == 135) { 2848c2ecf20Sopenharmony_ci dev_err(ctx->fh.vdev->dev_parent, 2858c2ecf20Sopenharmony_ci "%s: Handling profile_idc %d not implemented\n", 2868c2ecf20Sopenharmony_ci __func__, profile_idc); 2878c2ecf20Sopenharmony_ci return -EINVAL; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* log2_max_frame_num_minus4 */ 2918c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, NULL); 2928c2ecf20Sopenharmony_ci if (ret) 2938c2ecf20Sopenharmony_ci return ret; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, &pic_order_cnt_type); 2968c2ecf20Sopenharmony_ci if (ret) 2978c2ecf20Sopenharmony_ci return ret; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci if (pic_order_cnt_type == 0) { 3008c2ecf20Sopenharmony_ci /* log2_max_pic_order_cnt_lsb_minus4 */ 3018c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, NULL); 3028c2ecf20Sopenharmony_ci if (ret) 3038c2ecf20Sopenharmony_ci return ret; 3048c2ecf20Sopenharmony_ci } else if (pic_order_cnt_type == 1) { 3058c2ecf20Sopenharmony_ci unsigned int i, num_ref_frames_in_pic_order_cnt_cycle; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci /* delta_pic_order_always_zero_flag */ 3088c2ecf20Sopenharmony_ci ret = rbsp_read_bit(&sps); 3098c2ecf20Sopenharmony_ci if (ret < 0) 3108c2ecf20Sopenharmony_ci return ret; 3118c2ecf20Sopenharmony_ci /* offset_for_non_ref_pic */ 3128c2ecf20Sopenharmony_ci ret = rbsp_read_sev(&sps, NULL); 3138c2ecf20Sopenharmony_ci if (ret) 3148c2ecf20Sopenharmony_ci return ret; 3158c2ecf20Sopenharmony_ci /* offset_for_top_to_bottom_field */ 3168c2ecf20Sopenharmony_ci ret = rbsp_read_sev(&sps, NULL); 3178c2ecf20Sopenharmony_ci if (ret) 3188c2ecf20Sopenharmony_ci return ret; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, 3218c2ecf20Sopenharmony_ci &num_ref_frames_in_pic_order_cnt_cycle); 3228c2ecf20Sopenharmony_ci if (ret) 3238c2ecf20Sopenharmony_ci return ret; 3248c2ecf20Sopenharmony_ci for (i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) { 3258c2ecf20Sopenharmony_ci /* offset_for_ref_frame */ 3268c2ecf20Sopenharmony_ci ret = rbsp_read_sev(&sps, NULL); 3278c2ecf20Sopenharmony_ci if (ret) 3288c2ecf20Sopenharmony_ci return ret; 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci /* max_num_ref_frames */ 3338c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, NULL); 3348c2ecf20Sopenharmony_ci if (ret) 3358c2ecf20Sopenharmony_ci return ret; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci /* gaps_in_frame_num_value_allowed_flag */ 3388c2ecf20Sopenharmony_ci ret = rbsp_read_bit(&sps); 3398c2ecf20Sopenharmony_ci if (ret < 0) 3408c2ecf20Sopenharmony_ci return ret; 3418c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, &pic_width_in_mbs_minus1); 3428c2ecf20Sopenharmony_ci if (ret) 3438c2ecf20Sopenharmony_ci return ret; 3448c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, &pic_height_in_map_units_minus1); 3458c2ecf20Sopenharmony_ci if (ret) 3468c2ecf20Sopenharmony_ci return ret; 3478c2ecf20Sopenharmony_ci frame_mbs_only_flag = ret = rbsp_read_bit(&sps); 3488c2ecf20Sopenharmony_ci if (ret < 0) 3498c2ecf20Sopenharmony_ci return ret; 3508c2ecf20Sopenharmony_ci if (!frame_mbs_only_flag) { 3518c2ecf20Sopenharmony_ci /* mb_adaptive_frame_field_flag */ 3528c2ecf20Sopenharmony_ci ret = rbsp_read_bit(&sps); 3538c2ecf20Sopenharmony_ci if (ret < 0) 3548c2ecf20Sopenharmony_ci return ret; 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci /* direct_8x8_inference_flag */ 3578c2ecf20Sopenharmony_ci ret = rbsp_read_bit(&sps); 3588c2ecf20Sopenharmony_ci if (ret < 0) 3598c2ecf20Sopenharmony_ci return ret; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci /* Mark position of the frame cropping flag */ 3628c2ecf20Sopenharmony_ci pos = sps.pos; 3638c2ecf20Sopenharmony_ci frame_cropping_flag = ret = rbsp_read_bit(&sps); 3648c2ecf20Sopenharmony_ci if (ret < 0) 3658c2ecf20Sopenharmony_ci return ret; 3668c2ecf20Sopenharmony_ci if (frame_cropping_flag) { 3678c2ecf20Sopenharmony_ci unsigned int crop_left, crop_top; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, &crop_left); 3708c2ecf20Sopenharmony_ci if (ret) 3718c2ecf20Sopenharmony_ci return ret; 3728c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, &crop_right); 3738c2ecf20Sopenharmony_ci if (ret) 3748c2ecf20Sopenharmony_ci return ret; 3758c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, &crop_top); 3768c2ecf20Sopenharmony_ci if (ret) 3778c2ecf20Sopenharmony_ci return ret; 3788c2ecf20Sopenharmony_ci ret = rbsp_read_uev(&sps, &crop_bottom); 3798c2ecf20Sopenharmony_ci if (ret) 3808c2ecf20Sopenharmony_ci return ret; 3818c2ecf20Sopenharmony_ci } 3828c2ecf20Sopenharmony_ci vui_parameters_present_flag = ret = rbsp_read_bit(&sps); 3838c2ecf20Sopenharmony_ci if (ret < 0) 3848c2ecf20Sopenharmony_ci return ret; 3858c2ecf20Sopenharmony_ci if (vui_parameters_present_flag) { 3868c2ecf20Sopenharmony_ci dev_err(ctx->fh.vdev->dev_parent, 3878c2ecf20Sopenharmony_ci "%s: Handling vui_parameters not implemented\n", 3888c2ecf20Sopenharmony_ci __func__); 3898c2ecf20Sopenharmony_ci return -EINVAL; 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci crop_right = round_up(width, 16) - width; 3938c2ecf20Sopenharmony_ci crop_bottom = round_up(height, 16) - height; 3948c2ecf20Sopenharmony_ci crop_right /= 2; 3958c2ecf20Sopenharmony_ci if (frame_mbs_only_flag) 3968c2ecf20Sopenharmony_ci crop_bottom /= 2; 3978c2ecf20Sopenharmony_ci else 3988c2ecf20Sopenharmony_ci crop_bottom /= 4; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci sps.size = max_size - 5; 4028c2ecf20Sopenharmony_ci sps.pos = pos; 4038c2ecf20Sopenharmony_ci frame_cropping_flag = 1; 4048c2ecf20Sopenharmony_ci ret = rbsp_write_bit(&sps, frame_cropping_flag); 4058c2ecf20Sopenharmony_ci if (ret) 4068c2ecf20Sopenharmony_ci return ret; 4078c2ecf20Sopenharmony_ci ret = rbsp_write_uev(&sps, 0); /* crop_left */ 4088c2ecf20Sopenharmony_ci if (ret) 4098c2ecf20Sopenharmony_ci return ret; 4108c2ecf20Sopenharmony_ci ret = rbsp_write_uev(&sps, crop_right); 4118c2ecf20Sopenharmony_ci if (ret) 4128c2ecf20Sopenharmony_ci return ret; 4138c2ecf20Sopenharmony_ci ret = rbsp_write_uev(&sps, 0); /* crop_top */ 4148c2ecf20Sopenharmony_ci if (ret) 4158c2ecf20Sopenharmony_ci return ret; 4168c2ecf20Sopenharmony_ci ret = rbsp_write_uev(&sps, crop_bottom); 4178c2ecf20Sopenharmony_ci if (ret) 4188c2ecf20Sopenharmony_ci return ret; 4198c2ecf20Sopenharmony_ci ret = rbsp_write_bit(&sps, 0); /* vui_parameters_present_flag */ 4208c2ecf20Sopenharmony_ci if (ret) 4218c2ecf20Sopenharmony_ci return ret; 4228c2ecf20Sopenharmony_ci ret = rbsp_write_bit(&sps, 1); 4238c2ecf20Sopenharmony_ci if (ret) 4248c2ecf20Sopenharmony_ci return ret; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci *size = 5 + DIV_ROUND_UP(sps.pos, 8); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci return 0; 4298c2ecf20Sopenharmony_ci} 430