Skip to content

Commit 3c1f3c6

Browse files
author
openapv
authored
Merge pull request #8 from openapv/add-feature-list-in-readme
Add feature list of OpenAPV in readme and support floating number frame rate (fps)
2 parents a2b9521 + 1a621f3 commit 3c1f3c6

File tree

9 files changed

+312
-39
lines changed

9 files changed

+312
-39
lines changed

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,23 @@
33

44
[![Build & test](https://github.com/cpncf/apv/actions/workflows/build.yml/badge.svg)](https://github.com/cpncf/apv/actions/workflows/build.yml)
55

6-
OpenAPV provides the reference implementation of the APV codec which can be used to record professional-grade video and associated metadata without quality degradation.
6+
OpenAPV provides the reference implementation of the [APV codec](#apv-codec) which can be used to record professional-grade video and associated metadata without quality degradation. OpenAPV is free and open source software provided by [LICENSE](#license).
7+
8+
The OpenAPV supports the following features:
9+
10+
- fully compliant with 422-10 and 400-10 profile of [APV codec](#apv-codec)
11+
- Low complexity by optimization for ARM NEON and x86(64bit) SEE/AVX CPU
12+
- Supports tile-based multi-threading
13+
- Supports Various metadata including HDR10/10+ and user-defined format
14+
- Constant QP (CQP), average bitrate (ABR), and constant rate factor (CRF) are supported
15+
716

817
## APV codec
9-
The APV codec is a professional video codec, which was developed in response to the need for professional level high quality video recording and post production. The primary purpose of the APV codec is for use in professional video recording and editing workflows for various types of content. The APV codec supports the following features:
18+
The APV codec is a professional video codec, which was developed in response to the need for professional level high quality video recording and post production. The primary purpose of the APV codec is for use in professional video recording and editing workflows for various types of content.
19+
20+
APV codec utilizes technologies known to be over 20 years to achieve a royalty free codec. APV builds a video codec using only conventional coding technologies, which consist of traditional methods published between the early 1980s and the end of the 1990s.
21+
22+
The APV codec standard has the following features:
1023

1124
- Perceptually lossless video quality, which is close to raw video quality
1225
- Low complexity and high throughput intra frame only coding without pixel domain prediction
@@ -20,6 +33,7 @@ The APV codec is a professional video codec, which was developed in response to
2033
### Related specification
2134
- APV Codec (bitstream): [https://datatracker.ietf.org/doc/draft-lim-apv/](https://datatracker.ietf.org/doc/draft-lim-apv/)
2235
- Scope of OpenAPV project
36+
- APV ISO based media file format: [APV-ISOBMFF](/readme/apv_isobmff.md)
2337
- APV RTP payload format: [https://datatracker.ietf.org/doc/draft-lim-rtp-apv/](https://datatracker.ietf.org/doc/draft-lim-rtp-apv/)
2438

2539
## How to build
@@ -81,3 +95,4 @@ cpack -G TGZ
8195
## License
8296

8397
See [LICENSE](LICENSE) file for details.
98+

app/oapv_app_args.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct _ARGS_PARSER
6969
int (*get_help)(ARGS_PARSER * args, int idx, char * help);
7070
int (*get_str)(ARGS_PARSER * args, char * keyl, char * str, int *flag);
7171
int (*get_int)(ARGS_PARSER * args, char * keyl, int * val, int *flag);
72+
int (*set_str)(ARGS_PARSER * args, char * keyl, char * str);
7273
int (*set_int)(ARGS_PARSER * args, char * keyl, int val);
7374
int (*set_flag)(ARGS_PARSER * args, char * keyl, int flag);
7475
int (*check_mandatory)(ARGS_PARSER * args, char ** err_arg);
@@ -392,6 +393,23 @@ static int args_get(ARGS_PARSER * args, char * keyl, void ** val, int * flag)
392393
}
393394
}
394395

396+
static int args_set_str(ARGS_PARSER * args, char * keyl, char * str)
397+
{
398+
int idx;
399+
400+
idx = args_search_long_key(args->opts, keyl);
401+
if(idx >= 0)
402+
{
403+
sprintf((char*)(args->opts[idx].val), "%s", str);
404+
args->opts[idx].flag = 1;
405+
return 0;
406+
}
407+
else
408+
{
409+
return -1;
410+
}
411+
}
412+
395413
static int args_set_int(ARGS_PARSER * args, char * keyl, int val)
396414
{
397415
int idx;
@@ -579,6 +597,7 @@ static ARGS_PARSER * args_create(const ARGS_OPT * opt_table, int num_opt)
579597
args->get_help = args_get_help;
580598
args->get_str = args_get_str;
581599
args->get_int = args_get_int;
600+
args->set_str = args_set_str;
582601
args->set_int = args_set_int;
583602
args->set_flag = args_set_flag;
584603
args->check_mandatory = args_check_mandatory;

app/oapv_app_enc.c

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ static const ARGS_OPT enc_args_opts[] = {
8181
"QP value (0~51)"
8282
},
8383
{
84-
'z', "fps", ARGS_VAL_TYPE_INTEGER | ARGS_VAL_TYPE_MANDATORY, 0, NULL,
85-
"frame rate (frame per second)"
84+
'z', "fps", ARGS_VAL_TYPE_STRING | ARGS_VAL_TYPE_MANDATORY, 0, NULL,
85+
"frame rate (frame per second))"
8686
},
8787
{
8888
'm', "threads", ARGS_VAL_TYPE_INTEGER, 0, NULL,
@@ -202,6 +202,7 @@ typedef struct {
202202
char level[32];
203203
int band;
204204
char bitrate[64];
205+
char fps[256];
205206
char q_matrix_y[512];
206207
char q_matrix_u[512];
207208
char q_matrix_v[512];
@@ -241,6 +242,8 @@ static ARGS_VAR* args_init_vars(ARGS_PARSER* args, oapve_param_t* param)
241242
args_set_variable_by_key_long(opts, "band", &vars->band);
242243
vars->band = 2; /* default */
243244
args_set_variable_by_key_long(opts, "bitrate", vars->bitrate);
245+
args_set_variable_by_key_long(opts, "fps", vars->fps);
246+
strncpy(vars->fps, "60", sizeof(vars->fps) - 1);
244247
args_set_variable_by_key_long(opts, "q-matrix-y", vars->q_matrix_y);
245248
strncpy(vars->q_matrix_y, "", sizeof(vars->q_matrix_y) - 1);
246249
args_set_variable_by_key_long(opts, "q-matrix-u", vars->q_matrix_u);
@@ -255,7 +258,6 @@ static ARGS_VAR* args_init_vars(ARGS_PARSER* args, oapve_param_t* param)
255258
ARGS_SET_PARAM_VAR_KEY(opts, param, w);
256259
ARGS_SET_PARAM_VAR_KEY(opts, param, h);
257260
ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, qp);
258-
ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, fps);
259261
ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, preset);
260262
ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, rc_type);
261263
ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, use_filler);
@@ -349,7 +351,7 @@ static void print_config(ARGS_VAR* vars, oapve_param_t* param)
349351
logv2("\tprofile = %s\n", vars->profile);
350352
logv2("\twidth = %d\n", param->w);
351353
logv2("\theight = %d\n", param->h);
352-
logv2("\tFPS = %d\n", param->fps);
354+
logv2("\tFPS = %.2f\n", (float)param->fps_num / param->fps_den);
353355
logv2("\tQP = %d\n", param->qp);
354356
logv2("\tframes = %d\n", vars->frames);
355357
logv2("\trate-control type = %s\n", (param->rc_type == OAPV_RC_ABR) ? "ABR" : "CQP");
@@ -507,6 +509,24 @@ static int update_param(ARGS_VAR* vars, oapve_param_t* param)
507509
/* update band idc */
508510
param->band_idc = vars->band;
509511

512+
/* update fps */
513+
if (strpbrk(vars->fps, "/") != NULL)
514+
{
515+
sscanf(vars->fps, "%d/%d", &param->fps_num, &param->fps_den);
516+
}
517+
else if (strpbrk(vars->fps, ".") != NULL)
518+
{
519+
float tmp_fps = 0;
520+
sscanf(vars->fps, "%f", &tmp_fps);
521+
param->fps_num = tmp_fps * 10000;
522+
param->fps_den = 10000;
523+
}
524+
else
525+
{
526+
sscanf(vars->fps, "%d", &param->fps_num);
527+
param->fps_den = 1;
528+
}
529+
510530
return 0;
511531
}
512532

@@ -793,12 +813,14 @@ int main(int argc, const char** argv)
793813
ret = oapve_encode(id, &ifrms, mid, &bitb, &stat, &rfrms);
794814

795815
for(int i = 0; i < num_frames; i++) {
796-
if(args_var->input_depth != 10) {
797-
imgb_cpy(imgb_w, rfrms.frm[i].imgb);
798-
imgb_o = imgb_w;
799-
}
800-
else {
801-
imgb_o = rfrms.frm[i].imgb;
816+
if(is_rec){
817+
if(args_var->input_depth != 10) {
818+
imgb_cpy(imgb_w, rfrms.frm[i].imgb);
819+
imgb_o = imgb_w;
820+
}
821+
else {
822+
imgb_o = rfrms.frm[i].imgb;
823+
}
802824
}
803825

804826
clk_end = oapv_clk_from(clk_beg);
@@ -846,7 +868,7 @@ int main(int argc, const char** argv)
846868
total_time = total_time % 60;
847869
int s = total_time;
848870
double curr_bitrate = bitrate;
849-
curr_bitrate *= (param->fps * 8);
871+
curr_bitrate *= (((float)param->fps_num / param->fps_den) * 8);
850872
curr_bitrate /= (encod_frames + 1);
851873
curr_bitrate /= 1000;
852874
logv2("[ %d / %d frames ] [ %.2f frame/sec ] [ %.4f kbps ] [ %2dh %2dm %2ds ] \r", encod_frames, max_frames, ((float)(encod_frames + 1) * 1000) / ((float)oapv_clk_msec(clk_tot)), curr_bitrate, h, m, s);
@@ -886,7 +908,7 @@ int main(int argc, const char** argv)
886908
logv3(" PSNR T(dB) : %-5.4f\n", psnr_avg[3]);
887909
}
888910
logv3(" Total bits(bits) : %.0f\n", bitrate * 8);
889-
bitrate *= (param->fps * 8);
911+
bitrate *= (((float)param->fps_num / param->fps_den) * 8);
890912
bitrate /= pic_cnt;
891913
bitrate /= 1000;
892914

app/oapv_app_y4m.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ typedef struct _Y4M_PARAMS
3535
{
3636
int w;
3737
int h;
38-
int fps;
38+
int fps_num;
39+
int fps_den;
3940
int color_format;
4041
int bit_depth;
4142
}Y4M_INFO;
@@ -97,7 +98,8 @@ static int y4m_parse_tags(Y4M_INFO * y4m, char * tags)
9798
case 'F':
9899
{
99100
if (sscanf(p + 1, "%d:%d", &fps_n, &fps_d) != 2) return OAPV_ERR;
100-
y4m->fps = (int)((fps_n /(double)fps_d) + 0.5);
101+
y4m->fps_num = fps_n;
102+
y4m->fps_den = fps_d;
101103
break;
102104
}
103105
case 'I':
@@ -217,7 +219,9 @@ static void y4m_update_param(ARGS_PARSER * args, Y4M_INFO * y4m)
217219
{
218220
args->set_int(args, "width", y4m->w);
219221
args->set_int(args, "height", y4m->h);
220-
args->set_int(args, "fps", y4m->fps);
222+
char tmp_fps[256];
223+
sprintf(tmp_fps, "%d/%d", y4m->fps_num, y4m->fps_den);
224+
args->set_str(args, "fps", tmp_fps);
221225
args->set_int(args, "input-depth", y4m->bit_depth);
222226
}
223227

inc/oapv.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ extern "C"
127127
*****************************************************************************/
128128
#define OAPV_CFG_SET_QP (201)
129129
#define OAPV_CFG_SET_BPS (202)
130-
#define OAPV_CFG_SET_FPS (204)
130+
#define OAPV_CFG_SET_FPS_NUM (204)
131+
#define OAPV_CFG_SET_FPS_DEN (205)
131132
#define OAPV_CFG_SET_QP_MIN (208)
132133
#define OAPV_CFG_SET_QP_MAX (209)
133134
#define OAPV_CFG_SET_USE_FRM_HASH (301)
@@ -136,7 +137,8 @@ extern "C"
136137
#define OAPV_CFG_GET_QP (602)
137138
#define OAPV_CFG_GET_RCT (603)
138139
#define OAPV_CFG_GET_BPS (604)
139-
#define OAPV_CFG_GET_FPS (605)
140+
#define OAPV_CFG_GET_FPS_NUM (605)
141+
#define OAPV_CFG_GET_FPS_DEN (606)
140142
#define OAPV_CFG_GET_WIDTH (701)
141143
#define OAPV_CFG_GET_HEIGHT (702)
142144

@@ -366,9 +368,10 @@ struct oapve_param {
366368
int w;
367369
/* height of input frame */
368370
int h;
369-
/* frame rate (Hz) */
370-
int fps;
371-
/* Rate control type */
371+
/* frame rate (Hz) numerator, denominator */
372+
int fps_num;
373+
int fps_den;
374+
/* rate control type */
372375
int rc_type;
373376
/* quantization parameter */
374377
int qp;

0 commit comments

Comments
 (0)