代码概述
这段代码是OpenVVC(一个符合ITU - T H.266 - MPEG - I - Part 3 VVC标准的开源实时软件解码器)中关于序列参数集(Sequence Parameter Set, SPS)读取和处理的实现。代码主要完成了SPS的读取、验证、存储和释放等功能,同时还处理了SPS中的各种子信息,如子图像信息、VUI(Video Usability Information)有效负载、HRD(Hypothetical Reference Decoder)定时参数等。
代码结构与功能模块
1. 头文件包含与版权声明
/**
* ...版权声明...
**/
#include <string.h>
#include "ovmem.h"
#include "overror.h"
#include "hls_structures.h"
#include "nvcl.h"
#include "nvcl_utils.h"
#include "nvcl_structures.h"
#include "nvcl_private.h"
//TODOgpm: do not init here
#include "rcn.h"
包含了必要的头文件,其中一些是自定义的头文件,用于提供内存管理、错误处理、HLS(High - Level Syntax)结构定义等功能。
2. 辅助函数
-
probe_sps_id
:从OVNVCLReader
中提取SPS ID。
static uint8_t
probe_sps_id(OVNVCLReader *const rdr)
{
uint8_t sps_id = fetch_bits(rdr, 4);
return sps_id;
}
-
storage_in_nvcl_ctx
:根据SPS ID找到在OVNVCLCtx
中存储SPS数据的位置。
static const union HLSData **
storage_in_nvcl_ctx(OVNVCLReader *const rdr, OVNVCLCtx *const nvcl_ctx)
{
uint8_t id = probe_sps_id(rdr);
OVSPS **list = nvcl_ctx->sps_list;
const union HLSData **storage = (const union HLSData**)&list[id];
return storage;
}
-
validate_sps
:验证SPS数据的有效性,检查是否包含不支持的特性,如加权预测、子图像、WPP等。
static int
validate_sps(OVNVCLReader *rdr, const union HLSData *const data)
{
const OVSPS *const sps = (const OVSPS *)data;
if (sps->sps_weighted_pred_flag || sps->sps_weighted_bipred_flag) {
ov_log(NULL, OVLOG_ERROR, "Unsupported weighted pred\n");
return OVVC_EINDATA;
}
// 其他检查...
return 1;
}
-
free_sps
:释放SPS数据占用的内存。
static void
free_sps(const union HLSData *const data)
{
const OVSPS *const sps = (const OVSPS *)data;
ov_free((void *)sps);
}
-
replace_sps
:用新的SPS数据替换旧的SPS数据,并释放旧数据的内存。
static int
replace_sps(const struct HLSReader *const manager,
const union HLSData **storage,
const OVHLSData *const hls_data)
{
const union HLSData *to_free = *storage;
union HLSData *new = ov_malloc(manager->data_size);
if (!new) {
return OVVC_ENOMEM;
}
memcpy(new, hls_data, manager->data_size);
*storage = new;
if (to_free) {
manager->free(to_free);
}
return 0;
}
3. 子信息处理函数
-
subpic_info
:处理SPS中的子图像信息。
static void
subpic_info(OVNVCLReader *const rdr, OVSPS *const sps)
{
// 读取子图像数量等信息
sps->sps_num_subpics_minus1 = nvcl_read_u_expgolomb(rdr);
if (sps->sps_num_subpics_minus1 > 0) {
// 处理子图像的各种参数
// ...
}
// 处理子图像ID映射等信息
// ...
}
-
vui_payload
:处理SPS中的VUI有效负载信息。
static void
vui_payload(OVNVCLReader *const rdr, struct OVVUI *vui)
{
// 读取VUI的各种标志和参数
vui->vui_progressive_source_flag = nvcl_read_flag(rdr);
vui->vui_interlaced_source_flag = nvcl_read_flag(rdr);
// ...
}
-
general_timing_hrd_parameters
:处理SPS中的HRD一般定时参数。
static void
general_timing_hrd_parameters(OVNVCLReader *const rdr, struct HRDTiming *hrd)
{
hrd->num_units_in_tick = nvcl_read_bits(rdr, 32);
hrd->time_scale = nvcl_read_bits(rdr, 32);
// ...
}
-
sublayer_hrd_parameters
:处理SPS中的HRD子层参数。
static void
sublayer_hrd_parameters(OVNVCLReader *const rdr, const struct HRDTiming *const hrd, uint8_t i) {
int j;
for (j = 0; j <= hrd->hrd_cpb_cnt_minus1; ++j) {
uint16_t bit_rate_value_minus1 = nvcl_read_u_expgolomb(rdr);
uint16_t cpb_size_value_minus1 = nvcl_read_u_expgolomb(rdr);
// ...
}
}
-
ols_timing_hrd_parameters
:处理SPS中的HRD层集定时参数。
static void
ols_timing_hrd_parameters(OVNVCLReader *const rdr, const struct HRDTiming *const hrd, uint8_t first_sublayer, uint8_t max_sublayer)
{
int i;
for (i = first_sublayer; i <= max_sublayer; ++i) {
uint8_t fixed_pic_rate_general_flag = nvcl_read_flag(rdr);
// ...
}
}
4. SPS读取函数
-
nvcl_sps_read
:读取SPS数据,调用上述子信息处理函数处理各种子信息。
int
nvcl_sps_read(OVNVCLReader *const rdr, OVHLSData *const hls_data,
const OVNVCLCtx *const nvcl_ctx)
{
OVSPS *const sps = &hls_data->sps;
// 读取SPS的基本信息
sps->sps_seq_parameter_set_id = nvcl_read_bits(rdr, 4);
sps->sps_video_parameter_set_id = nvcl_read_bits(rdr, 4);
// ...
// 处理各种子信息
if (sps->sps_subpic_info_present_flag) {
subpic_info(rdr, sps);
}
if (sps->sps_vui_parameters_present_flag) {
vui_payload(rdr, &sps->vui);
}
// ...
return 0;
}
5. SPS管理器
-
sps_manager
:定义了一个HLSReader
结构体,用于管理SPS的读取、验证、存储和释放等操作。
const struct HLSReader sps_manager =
{
.name = "SPS",
.data_size = sizeof(struct OVSPS),
.probe_id = &probe_sps_id,
.find_storage = &storage_in_nvcl_ctx,
.read = &nvcl_sps_read,
.validate = &validate_sps,
.replace = &replace_sps,
.free = &free_sps
};
代码问题与改进建议
- 代码注释:虽然代码中有一些注释,但部分注释可以更加详细,特别是一些复杂的逻辑部分,如子图像信息处理和HRD参数处理。
-
错误处理:在
nvcl_sps_read
函数中,当读取某些参数失败时,没有进行相应的错误处理,建议添加错误处理逻辑,提高代码的健壮性。 - 代码复用:部分代码存在重复,如在处理不同颜色分量的QP表时,可以考虑将重复的代码提取成函数,提高代码的可维护性。
-
TODO标记:代码中存在一些
TODO
标记,如TODOgpm: do not init here
,需要及时处理这些待办事项。
总结
这段代码实现了OpenVVC中SPS的读取和处理功能,通过一系列辅助函数和子信息处理函数,完成了SPS数据的解析和验证。同时,通过sps_manager
结构体提供了统一的管理接口,方便后续的使用和扩展。