summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Yuan <shengquan.yuan@intel.com>2015-07-21 17:37:44 +0800
committerAustin Yuan <shengquan.yuan@intel.com>2015-07-21 17:43:47 +0800
commitb672394d89bb609c1dd2ef9fa39002e610f1384c (patch)
tree1b0c85bd4ba372e114b6f4d0c414f3cc67895658
parent4d24331d9bf4813d64e6aa098ff09b3d6cae9fb2 (diff)
Update va_encode for bugfixing and ROI feature
Signed-off-by: Austin Yuan <shengquan.yuan@intel.com> Signed-off-by: Mingruo Sun <mingruo.sun@intel.com>
-rw-r--r--vaenc/Android.mk8
-rw-r--r--vaenc/README423
-rw-r--r--vaenc/h264encode.c158
-rw-r--r--vaenc/va_encode.c196
-rw-r--r--vaenc/va_encode.h13
-rw-r--r--vaenc/va_surface.c4
6 files changed, 576 insertions, 226 deletions
diff --git a/vaenc/Android.mk b/vaenc/Android.mk
index 65b9f5b..db9dd48 100644
--- a/vaenc/Android.mk
+++ b/vaenc/Android.mk
@@ -12,11 +12,11 @@ LOCAL_SRC_FILES := \
../android/gralloc.cpp ../utils/psnr.c ../utils/ssim.c
LOCAL_CFLAGS += \
- -DANDROID
+ -DANDROID -D_LINK_C
-#ifeq ($(TARGET_ARCH),x86_64)
-LOCAL_CFLAGS += -march=x86-64 -D_LINK_C
-#endif
+ifeq ($(TARGET_ARCH),x86_64)
+LOCAL_CFLAGS += -march=x86-64
+endif
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../../va \
diff --git a/vaenc/README b/vaenc/README
index e8c42c5..a591027 100644
--- a/vaenc/README
+++ b/vaenc/README
@@ -1,150 +1,277 @@
-1). new_va_encode has an option "-configfile", which could read dynamic RC settings from configure file.
-
-I. The RC settings include:
-frame_start
-frame_end
-frame_width
-frame_height
-bits_per_second
-target_percentage
-window_size
-initial_qp
-min_qp
-max_qp
-force_kf
-no_ref_last
-no_ref_gf
-no_ref_arf
-frame_rate
-intra_period
-intra_idr_period
-ip_period
-quality
-refresh_entropy_probs
-copy_buffer_to_golden
-copy_buffer_to_alternate
-refresh_last
-refresh_golden_frame
-refresh_alternate_frame
-
-II. How to use "-configfile"
-Below is a configure file to support dynamic bitrate change. Take it for example.
-[beginrc]
-frame_width=1280
-frame_height=720
-frame_start=0
-frame_end=999
-bits_per_second=1000000
-[endrc]
-[beginrc]
-bits_per_second=2000000
-frame_start=1000
-frame_end=1999
-[endrc]
-[beginrc]
-frame_start=2000
-frame_end=2999
-bits_per_second=3000000
-[endrc]
-[beginrc]
-frame_start=3000
-frame_end=3999
-bits_per_second=5000000
-[endrc]
-
-
-2). new_va_encode has options available for VP8 encoding:
--w, -h, -framecount, -o, -f, -configfile, -bitrate, -rcMode, -syncmode, -srcyuv, -recyuv, -enablePSNR, -surface(va|malloc), -frame_size_log, -minqp, -maxqp, -raw, -riff, -dynamic_resolution
-
--rcMode VBR will translated to rc_end_usage=CBR mode in psbvideo driver
--rcMode CBR will translated to rc_end_usage=CBR_HRD mode in psbvideo driver
--raw output is vp8 element stream
--riff will add RIFF file header to VP8 element stream
+ va_encode: libVA encoding tool
+
+Content:
+ 1. Introduction
+ 2. Quick start
+ 3. Bitrate control setting
+ 4. Performance testing
+ 5. Special feature testing
+ 6. Dynamic encoding testing
+
+1. Introduction
+
+va_encode is a command line encoding tool through VAAPI. It encodes a video
+file from a YUV source. The YUV source can be from a storage file, or the
+tool itself can auto-generate a white-black checkerboard sequence.
+
+The tools supports some advanced testing features which is useful for driver
+development and tunning.
+
+2. Quick start
+
+Simply type "va_encode" on command line, it will encode a clip with bellow
+configuration:
+(a) codec is H264, resolution 176x144, frame number 60, VBR
+(b) input YUV is the auto-generated white-black checkerboard
+(c) coded file is saved into /tmp/test.out (Linux) or /sdcard/test.out (Android)
+
+To encode VP8, the command line is "va_encoder -t VP8"
+To encode JPEG, the command line is "va_encoder -t JPEG"
+To specify a resolution, use "va_encode -w 1280 -h 720"
+To encode more than 60 frames, use "va_encode -n 100"
+To encode from a YUV file, use "va_encode -srcyuv yuv_file_name"
+To save to another file, use "va_encode -o file_path_and_name"
+
+For encoding from a YUV file, the tool supports various fourcc, use "-fourcc"
+parameter to specify it, e.g. "-fourcc IYUV", "-fourcc YV12". The default format
+is NV12
+
+3. Rate control settings
+(1) RC mode
+RC mode can be specified by "-rcMode", e.g.
+ -rcMode CBR
+ -rcMode VBR
+ -rcMode VCM
+ -rcMode CQP
+
+(2) Bitrate
+Bitrate is set by "-bitrate", e.g.
+ -bitrate 500000
+It sets the bitrate to 500000bps
+
+(3) QP
+The tool can set the min and max value of QP,e.g.
+ -minqp 15
+ -maxqp 30
+ -initalqp 20
+It limites qp range to [15, 30], and set the first IDR frame qp to 20
+This option may not take effect because of the underline HW/driver bit rate
+control constrains
+
+minqp/maxqp is not applicable to CQP mode. Use "-initialqp" to set the qp
+
+(4) I/P/B setting
+Parameters that are used to set I/P/B sequence
+ -intra_period <number>
+ -idr_period <number>
+ -ip_period <number>
+
+The number for "-idr_period" is special. It means after number of "intra_period",
+there will be an IDR frame.
+
+Bellow is detailed explanation about these parameters (intra_id_period is the result
+of "idr_peroid number" * "intra_perid number" from command line):
+================================================================
+Assume frame sequence is: Frame#0,#1,#2,...,#M,...,#X,... (encoding order)
+ 1) period between Frame #X and Frame #N = #X - #N
+ 2) 0 means infinite for intra_period/intra_idr_period, and 0 is invalid for ip_period
+ 3) intra_idr_period % intra_period (intra_period > 0) and intra_period % ip_period must be 0
+ 4) intra_period and intra_idr_period take precedence over ip_period
+ 5) if ip_period > 1, intra_period and intra_idr_period are not the strict periods
+ of I/IDR frames, see bellow examples
+ -------------------------------------------------------------------
+ intra_period intra_idr_period ip_period frame sequence (intra_period/intra_idr_period/ip_period)
+ 0 ignored 1 IDRPPPPPPP ... (No IDR/I any more)
+ 0 ignored >=2 IDR(PBB)(PBB)... (No IDR/I any more)
+ 1 0 ignored IDRIIIIIII... (No IDR any more)
+ 1 1 ignored IDR IDR IDR IDR...
+ 1 >=2 ignored IDRII IDRII IDR... (1/3/ignore)
+ >=2 0 1 IDRPPP IPPP I... (3/0/1)
+ >=2 0 >=2 IDR(PBB)(PBB)(IBB) (6/0/3)
+ (PBB)(IBB)(PBB)(IBB)...
+ >=2 >=2 1 IDRPPPPP IPPPPP IPPPPP (6/18/1)
+ IDRPPPPP IPPPPP IPPPPP...
+ >=2 >=2 >=2 {IDR(PBB)(PBB)(IBB)(PBB)(IBB)(PBB)} (6/18/3)
+ {IDR(PBB)(PBB)(IBB)(PBB)(IBB)(PBB)}...
+ {IDR(PBB)(PBB)(IBB)(PBB)} (6/12/3)
+ {IDR(PBB)(PBB)(IBB)(PBB)}...
+ {IDR(PBB)(PBB)} (6/6/3)
+ {IDR(PBB)(PBB)}.
+================================================================
+
+(4) VP8 parameters
+ -raw output is vp8 element stream
+ -riff will add RIFF file header to VP8 element stream
Note: default output data for VP8 is IVF file
-To do correctness test:
--correctness_test MUST be used
-
-some options only for VP8 key frame control:
--auto_kf
--kf_min_dist
--kf_max_dist
-
-option for error concealment:
--error_resilient: default value = 0
-0=off(reset context tables for key frame only), 1=on(reset context tables for both key frames and golden frames)
-
-VP8 firmware could support resolution change:
--dynamic_resolution to test dynamic resolution change feature, create surface with 1080p resolution
-
-
-An example for VP8 dynmaic bitrate testing
-[beginrc]
-frame_width=176
-frame_height=144
-frame_start=0
-frame_end=4
-force_kf=1
-[endrc]
-[beginrc]
-frame_start=5
-frame_end=9
-force_kf=0
-[endrc]
-[beginrc]
-frame_start=10
-frame_end=19
-no_ref_last=1
-no_ref_arf=1
-no_ref_gf=0
-[endrc]
-[beginrc]
-frame_start=20
-frame_end=29
-no_ref_last=1
-no_ref_arf=0
-no_ref_gf=1
-[endrc]
-[beginrc]
-frame_start=30
-frame_end=39
-no_ref_last=1
-no_ref_arf=0
-no_ref_gf=0
-[endrc]
-[beginrc]
-frame_start=40
-frame_end=49
-no_ref_last=0
-no_ref_arf=1
-no_ref_gf=1
-[endrc]
-[beginrc]
-frame_start=50
-frame_end=59
-no_ref_last=0
-no_ref_arf=1
-no_ref_gf=0
-[endrc]
-[beginrc]
-frame_start=60
-frame_end=69
-no_ref_last=0
-no_ref_arf=0
-no_ref_gf=1
-[endrc]
-[beginrc]
-frame_start=70
-frame_end=79
-refresh_last=0
-[endrc]
-[beginrc]
-frame_start=80
-frame_end=139
-refresh_golden_frame=0
-[endrc]
-[beginrc]
-frame_start=140
-frame_end=199
-refresh_alternate_frame=0
-[endrc]
+Correctness test:
+ -correctness_test
+
+Key frame control:
+ -auto_kf
+ -kf_min_dist
+ -kf_max_dist
+
+Error concealment:
+ -error_resilient: default value = 0
+ 0 = off(reset context tables for key frame only),
+ 1 = on(reset context tables for both key frames and golden frames)
+
+4. Performance testing
+
+(1) Minimize source YUV loading cost
+The end-to-end encoding testing includes source YUV loading. It is usually
+very slow for large resolutions. Two options here:
+(a) don't set "-srcyuv", it will use auto-generated source, and only load once
+(b) use "-srcyuv XXX -perf", it always encoding the first 16 frames of the YUV file
+
+(2) Single thread vs Multiple thread
+Parameter "-syncmode" runs encoding with single thread, while without this
+parameter, the tool create two threads: one is continously sending encoding frames,
+and another continously read from source YUV and save coded file into storage
+
+Multiple thread or single thread should only have impact to end-to-end fps, the
+core encoding fps is a little different:
+(1) single thread: core encoding fps counts the time of bellow VAAPIs:
+ vaBeginPicture/vaRenderPicture/vaEndPicture/vaSyncSurface
+(2) multiple thread: core encoding fps counts the time of bellow VAAPIs:
+ vaBeginPicture/vaRenderPicture/vaEndPicture
+ vaSyncSurface is not counted because it runs in another thread which may be
+ in parallel with vaBeginPicture/vaRenderPicture/vaEndPicture
+
+5. Special feature testing
+(1) ROI testing
+ -roi_enable: enable ROI feature (default 0)
+ -roi_value: the priority of the ROI region (defautl -2)
+ -roi_minqp: the min allowed delta QP (defaut -4)
+ -roi_maxqp: the max allowed delta QP (default 4)
+ -roi_rect_x/y/w/h: ROI rectangle (default the 1/3 center area of the frame)
+
+
+6. Dynamic encoding testing
+
+Option "-configfile", which could read dynamic RC settings from configure file.
+The RC settings include:
+ frame_start
+ frame_end
+ frame_width
+ frame_height
+ bits_per_second
+ target_percentage
+ window_size
+ initial_qp
+ min_qp
+ max_qp
+ force_kf
+ no_ref_last
+ no_ref_gf
+ no_ref_arf
+ frame_rate
+ intra_period
+ intra_idr_period
+ ip_period
+ quality
+ refresh_entropy_probs
+ copy_buffer_to_golden
+ copy_buffer_to_alternate
+ refresh_last
+ refresh_golden_frame
+ refresh_alternate_frame
+
+Write dynamic change settings into a configuration file, e.g.
+ [beginrc]
+ frame_width=1280
+ frame_height=720
+ frame_start=0
+ frame_end=999
+ bits_per_second=1000000
+ [endrc]
+ [beginrc]
+ bits_per_second=2000000
+ frame_start=1000
+ frame_end=1999
+ [endrc]
+ [beginrc]
+ frame_start=2000
+ frame_end=2999
+ bits_per_second=3000000
+ [endrc]
+ [beginrc]
+ frame_start=3000
+ frame_end=3999
+ bits_per_second=5000000
+ [endrc]
+
+Another example for VP8 dynmaic bitrate testing
+ [beginrc]
+ frame_width=176
+ frame_height=144
+ frame_start=0
+ frame_end=4
+ force_kf=1
+ [endrc]
+ [beginrc]
+ frame_start=5
+ frame_end=9
+ force_kf=0
+ [endrc]
+ [beginrc]
+ frame_start=10
+ frame_end=19
+ no_ref_last=1
+ no_ref_arf=1
+ no_ref_gf=0
+ [endrc]
+ [beginrc]
+ frame_start=20
+ frame_end=29
+ no_ref_last=1
+ no_ref_arf=0
+ no_ref_gf=1
+ [endrc]
+ [beginrc]
+ frame_start=30
+ frame_end=39
+ no_ref_last=1
+ no_ref_arf=0
+ no_ref_gf=0
+ [endrc]
+ [beginrc]
+ frame_start=40
+ frame_end=49
+ no_ref_last=0
+ no_ref_arf=1
+ no_ref_gf=1
+ [endrc]
+ [beginrc]
+ frame_start=50
+ frame_end=59
+ no_ref_last=0
+ no_ref_arf=1
+ no_ref_gf=0
+ [endrc]
+ [beginrc]
+ frame_start=60
+ frame_end=69
+ no_ref_last=0
+ no_ref_arf=0
+ no_ref_gf=1
+ [endrc]
+ [beginrc]
+ frame_start=70
+ frame_end=79
+ refresh_last=0
+ [endrc]
+ [beginrc]
+ frame_start=80
+ frame_end=139
+ refresh_golden_frame=0
+ [endrc]
+ [beginrc]
+ frame_start=140
+ frame_end=199
+ refresh_alternate_frame=0
+ [endrc]
+
+Parameter "-dynamic_resolution" is used to singal application to allocate surface at
+1080P resolutioin, then it can test dynamic resolution change feature
diff --git a/vaenc/h264encode.c b/vaenc/h264encode.c
index d69a2ba..bd4e93a 100644
--- a/vaenc/h264encode.c
+++ b/vaenc/h264encode.c
@@ -83,6 +83,15 @@ static VAProfile h264_profile = -1;
unsigned int h264_entropy_mode = 1; /* cabac */
unsigned int h264_8x8_dct = 0;
+unsigned int roi_enable = 0;
+unsigned int roi_value = -2;
+int roi_minqp = -4;
+int roi_maxqp = 4;
+unsigned int roi_rec_x = 0;
+unsigned int roi_rec_y = 0;
+unsigned int roi_rec_w = 0;
+unsigned int roi_rec_h = 0;
+
struct __bitstream {
unsigned int *buffer;
int bit_offset;
@@ -554,7 +563,8 @@ static int update_RefPicList(void)
static int render_sequence(void)
{
- VABufferID seq_param_buf, rc_param_buf, misc_param_tmpbuf, render_id[2];
+ VABufferID seq_param_buf = VA_INVALID_ID, rc_param_buf = VA_INVALID_ID;
+ VABufferID misc_param_tmpbuf = VA_INVALID_ID, render_id[2] = { VA_INVALID_ID, VA_INVALID_ID };
VAStatus va_status;
VAEncMiscParameterBuffer *misc_param, *misc_param_tmp;
VAEncMiscParameterRateControl *misc_rate_ctrl;
@@ -608,13 +618,16 @@ static int render_sequence(void)
va_status = vaRenderPicture(va_dpy,context_id, &misc_param_tmpbuf, 1);
}
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 5, seq_param_buf, rc_param_buf,
+ misc_param_tmpbuf, render_id[0], render_id[1]);
return va_status;
}
static int render_framerate()
{
- VABufferID frame_rate_param_buf;
+ VABufferID frame_rate_param_buf = VA_INVALID_ID;
VAStatus va_status;
VAEncMiscParameterBuffer *misc_param, *misc_param_tmp;
VAEncMiscParameterFrameRate *misc_frame_rate;
@@ -643,12 +656,15 @@ static int render_framerate()
va_status = vaRenderPicture(va_dpy,context_id, &frame_rate_param_buf, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");;
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 1, frame_rate_param_buf);
+
return 0;
}
static int render_rcparam(unsigned int mask, struct rc_param_t *rc_param)
{
- VABufferID rc_param_buf;
+ VABufferID rc_param_buf = VA_INVALID_ID;
VAStatus va_status;
VAEncMiscParameterBuffer *misc_param, *misc_param_tmp;
VAEncMiscParameterRateControl *misc_rate_ctrl;
@@ -702,6 +718,9 @@ static int render_rcparam(unsigned int mask, struct rc_param_t *rc_param)
va_status = vaRenderPicture(va_dpy,context_id, &rc_param_buf, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");;
+
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 1, rc_param_buf);
return 0;
}
@@ -740,7 +759,7 @@ static int calc_poc(int pic_order_cnt_lsb)
static int render_picture(void)
{
- VABufferID pic_param_buf;
+ VABufferID pic_param_buf = VA_INVALID_ID;
VAStatus va_status;
int i = 0;
@@ -763,7 +782,8 @@ static int render_picture(void)
} else {
if (h264_autoref == 0) {
memcpy(pic_param.ReferenceFrames, ReferenceFrames, numShortTerm*sizeof(VAPictureH264));
- for (i = numShortTerm; i < surface_num; i++) {
+ /* Reset the rest of non-used references */
+ for (i = numShortTerm; i < 16; i++) {
pic_param.ReferenceFrames[i].picture_id = VA_INVALID_SURFACE;
pic_param.ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
}
@@ -792,13 +812,17 @@ static int render_picture(void)
va_status = vaRenderPicture(va_dpy,context_id, &pic_param_buf, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 1, pic_param_buf);
+
return 0;
}
static int render_packedsequence(void)
{
VAEncPackedHeaderParameterBuffer packedheader_param_buffer;
- VABufferID packedseq_para_bufid, packedseq_data_bufid, render_id[2];
+ VABufferID packedseq_para_bufid = VA_INVALID_ID, packedseq_data_bufid = VA_INVALID_ID;
+ VABufferID render_id[2] = { VA_INVALID_ID, VA_INVALID_ID };
unsigned int length_in_bits;
unsigned char *packedseq_buffer = NULL;
VAStatus va_status;
@@ -829,6 +853,10 @@ static int render_packedsequence(void)
CHECK_VASTATUS(va_status,"vaRenderPicture");
free(packedseq_buffer);
+
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 4, packedseq_para_bufid, packedseq_data_bufid,
+ render_id[0], render_id[1]);
return 0;
}
@@ -836,7 +864,8 @@ static int render_packedsequence(void)
static int render_packedpicture(void)
{
VAEncPackedHeaderParameterBuffer packedheader_param_buffer;
- VABufferID packedpic_para_bufid, packedpic_data_bufid, render_id[2];
+ VABufferID packedpic_para_bufid = VA_INVALID_ID, packedpic_data_bufid = VA_INVALID_ID;
+ VABufferID render_id[2] = { VA_INVALID_ID, VA_INVALID_ID };
unsigned int length_in_bits;
unsigned char *packedpic_buffer = NULL;
VAStatus va_status;
@@ -866,14 +895,19 @@ static int render_packedpicture(void)
CHECK_VASTATUS(va_status,"vaRenderPicture");
free(packedpic_buffer);
+
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 4, packedpic_para_bufid, packedpic_data_bufid,
+ render_id[0], render_id[1]);
return 0;
}
static void render_packedsei(void)
{
+ VABufferID packed_sei_header_param_buf_id = VA_INVALID_ID;
+ VABufferID packed_sei_buf_id = VA_INVALID_ID, render_id[2] = { VA_INVALID_ID, VA_INVALID_ID };
VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
- VABufferID packed_sei_header_param_buf_id, packed_sei_buf_id, render_id[2];
unsigned int length_in_bits /*offset_in_bytes*/;
unsigned char *packed_sei_buffer = NULL;
VAStatus va_status;
@@ -925,14 +959,18 @@ static void render_packedsei(void)
CHECK_VASTATUS(va_status,"vaRenderPicture");
free(packed_sei_buffer);
-
+
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 4, packed_sei_header_param_buf_id, packed_sei_buf_id,
+ render_id[0], render_id[1]);
+
return;
}
static int render_air(void)
{
VAStatus va_status;
- VABufferID misc_parameter_air_buf_id;
+ VABufferID misc_parameter_air_buf_id = VA_INVALID_ID;
VAEncMiscParameterBuffer *misc_param;
VAEncMiscParameterAIR *misc_air_param;
@@ -959,13 +997,16 @@ static int render_air(void)
va_status = vaRenderPicture(va_dpy,context_id, &misc_parameter_air_buf_id, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");;
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 1, misc_parameter_air_buf_id);
+
return 0;
}
static int render_cir(void)
{
VAStatus va_status;
- VABufferID misc_parameter_cir_buf_id;
+ VABufferID misc_parameter_cir_buf_id = VA_INVALID_ID;
VAEncMiscParameterBuffer *misc_param;
VAEncMiscParameterCIR *misc_cir_param;
@@ -990,12 +1031,15 @@ static int render_cir(void)
va_status = vaRenderPicture(va_dpy,context_id, &misc_parameter_cir_buf_id, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 1, misc_parameter_cir_buf_id);
+
return 0;
}
static int render_hrd(void)
{
- VABufferID misc_parameter_hrd_buf_id;
+ VABufferID misc_parameter_hrd_buf_id = VA_INVALID_ID;
VAStatus va_status;
VAEncMiscParameterBuffer *misc_param;
VAEncMiscParameterHRD *misc_hrd_param;
@@ -1031,12 +1075,15 @@ static int render_hrd(void)
va_status = vaRenderPicture(va_dpy,context_id, &misc_parameter_hrd_buf_id, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");;
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 1, misc_parameter_hrd_buf_id);
+
return 0;
}
static int render_slice(void)
{
- VABufferID slice_param_buf;
+ VABufferID slice_param_buf = VA_INVALID_ID;
VAStatus va_status;
VAEncSliceParameterBufferH264 *slice_param, *current_slice;
int i, j, frame_slice_cc = frame_slice_count;
@@ -1055,7 +1102,7 @@ static int render_slice(void)
for (j = 0; j < frame_slice_cc; j++) {
current_slice = slice_param + j;
- current_slice->disable_deblocking_filter_idc = 1;
+ current_slice->disable_deblocking_filter_idc = 0;
current_slice->macroblock_address = mb_rendered;
if (j == frame_slice_cc - 1) {
current_slice->num_macroblocks = (frame_width_mbaligned * frame_height_mbaligned) / (16 * 16) - mb_rendered;
@@ -1067,6 +1114,13 @@ static int render_slice(void)
if (current_frame_type == FRAME_IDR) {
if (current_frame_encoding != 0)
++current_slice->idr_pic_id;
+ /* Reset reference for IDR also */
+ for (i = 0; i < 32; i++) {
+ current_slice->RefPicList0[i].picture_id = VA_INVALID_SURFACE;
+ current_slice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID;
+ current_slice->RefPicList1[i].picture_id = VA_INVALID_SURFACE;
+ current_slice->RefPicList1[i].flags = VA_PICTURE_H264_INVALID;
+ }
} else if (current_frame_type == FRAME_P) {
int refpiclist0_max = h264_maxref & 0xffff;
memcpy(current_slice->RefPicList0, RefPicList0_P, refpiclist0_max*sizeof(VAPictureH264));
@@ -1092,8 +1146,8 @@ static int render_slice(void)
}
}
- current_slice->slice_alpha_c0_offset_div2 = 0;
- current_slice->slice_beta_offset_div2 = 0;
+ current_slice->slice_alpha_c0_offset_div2 = 2;
+ current_slice->slice_beta_offset_div2 = 2;
current_slice->direct_spatial_mv_pred_flag = 1;
current_slice->pic_order_cnt_lsb = (current_frame_display - current_IDR_display) % MaxPicOrderCntLsb;
}
@@ -1103,13 +1157,17 @@ static int render_slice(void)
va_status = vaRenderPicture(va_dpy, context_id, &slice_param_buf, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");
+
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 1, slice_param_buf);
+
return 0;
}
static int render_max_slice_size(void)
{
VAStatus va_status;
- VABufferID misc_parameter_max_slice_size_buf_id;
+ VABufferID misc_parameter_max_slice_size_buf_id = VA_INVALID_ID;
VAEncMiscParameterBuffer *misc_param;
VAEncMiscParameterMaxSliceSize *misc_max_slize_size_param;
@@ -1139,6 +1197,62 @@ static int render_max_slice_size(void)
va_status = vaRenderPicture(va_dpy, context_id, &misc_parameter_max_slice_size_buf_id, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");;
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 1, misc_parameter_max_slice_size_buf_id);
+
+ return 0;
+}
+
+static int render_roi(void)
+{
+ VAStatus va_status;
+ VABufferID misc_roi_buf_id = VA_INVALID_ID;
+ VAEncMiscParameterBuffer *misc_param;
+ VAEncMiscParameterBufferROI *misc_roi_param;
+ VAEncROI encroi;
+
+
+ roi_rec_x = (!roi_rec_x)?frame_width / 3:roi_rec_x;
+ roi_rec_y = (!roi_rec_x)?frame_height / 3:roi_rec_y;
+ roi_rec_w = (!roi_rec_w)?frame_width / 3:roi_rec_w;
+ roi_rec_h = (!roi_rec_h)?frame_height / 3:roi_rec_h;
+
+ va_status = vaCreateBuffer(va_dpy, context_id,
+ VAEncMiscParameterBufferType,
+ sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterBufferROI),
+ 1,
+ NULL,
+ &misc_roi_buf_id);
+ CHECK_VASTATUS(va_status, "vaCreateBuffer");
+
+ vaMapBuffer(va_dpy,
+ misc_roi_buf_id,
+ (void **)&misc_param);
+
+ misc_param->type = VAEncMiscParameterTypeROI;
+ misc_roi_param = (VAEncMiscParameterBufferROI *)misc_param->data;
+
+ misc_roi_param->num_roi = 1;
+ misc_roi_param->max_delta_qp = roi_maxqp;
+ misc_roi_param->min_delta_qp = roi_minqp;
+
+ encroi.roi_rectangle.x = roi_rec_x;
+ encroi.roi_rectangle.y = roi_rec_y;
+ encroi.roi_rectangle.width = roi_rec_w;
+ encroi.roi_rectangle.height = roi_rec_h;
+
+ encroi.roi_value = roi_value;
+
+ misc_roi_param->roi = &encroi;
+
+ vaUnmapBuffer(va_dpy, misc_roi_buf_id);
+
+ va_status = vaRenderPicture(va_dpy, context_id, &misc_roi_buf_id, 1);
+ CHECK_VASTATUS(va_status,"vaRenderPicture");;
+
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 1, misc_roi_buf_id);
+
return 0;
}
@@ -1170,9 +1284,13 @@ static VAStatus h264_render_frame(unsigned int mask, struct rc_param_t *rc_param
if (max_slice_size) {
render_max_slice_size();
}
+ if (roi_enable)
+ render_roi();
} else {
//render_sequence();
render_picture();
+ if (roi_enable)
+ render_roi();
//if (rc_mode == VA_RC_CBR)
// render_packedsei();
//render_hrd();
@@ -1390,7 +1508,11 @@ static VAStatus h264_get_config(void)
printf("Support VAConfigAttribEncAutoReference\n");
h264_autoref = 1;
}
-
+
+ if (h264_attrib[VAConfigAttribEncROI].value != VA_ATTRIB_NOT_SUPPORTED) {
+ printf("Support VAConfigAttribEncROI\n");
+ }
+
va_profile = h264_profile;
/*
diff --git a/vaenc/va_encode.c b/vaenc/va_encode.c
index bb34656..ce2a0ad 100644
--- a/vaenc/va_encode.c
+++ b/vaenc/va_encode.c
@@ -46,6 +46,7 @@
#include <pthread.h>
#include <errno.h>
#include <math.h>
+#include <stdarg.h>
#include <va/va.h>
#include <va/va_enc_h264.h>
#include "va_display.h"
@@ -119,8 +120,9 @@ unsigned int misc_priv_type = 0;
unsigned int misc_priv_value = 0;
int pm_active = 0;
-int interactive_mode = 0;
-
+int interactive_mode = 0; /* stop at every vaEndPicture */
+int buf_destroy = 1; /* explicitly call vaDestroyBuffer */
+
static char *current_codec_str = NULL;
/* thread to save coded data/upload source YUV */
@@ -319,52 +321,53 @@ static int print_help(void)
printf(" -framecount <frame number>\n");
printf(" -n <frame number>\n");
printf(" if set to 0 and srcyuv is set, the frame count is from srcyuv file\n");
+ printf(" if set to a negative value, the test will loop endlessly\n");
printf(" -slices <1|2|3...> slice number each frame\n");
printf(" -o <coded_file>\n");
printf(" -dumpframe, save each frame into seperated file coded_file.0, coded_file.1, ... \n");
printf(" -f <frame rate>\n");
printf(" -r <encode fps>, throttle encoding speed instead of running as fast as possible\n");
printf(" -configfile <framename> read dynamic RC settings from configure file\n");
- printf(" --intra_period <number>\n");
- printf(" --idr_period <number>\n");
+ printf(" -intra_period <number>\n");
+ printf(" -idr_period <number>\n");
printf(" e.g. if set to 2, the real intra_idr_peroid of libva is 2*intra_period\n");
- printf(" --ip_period <number>\n");
- printf(" --bitrate <bitrate>\n");
- printf(" --qpluma <number>\n");
- printf(" --initialqp <number>, initial_qp of VAEncMiscParameterRateControl structure");
- printf(" also set into pic_init_qp of pps\n");
- printf(" --minqp <number>, min_qp of VAEncMiscParameterRateControl structure\n");
- printf(" --maxqp <number>, max_qp of VAEncMiscParameterRateControl structure\n");
- printf(" --sliceqp <number>, qp that set into slice_qp_delta of slice header\n");
- printf(" --rcMode <NONE|CBR|VBR|VCM|CQP|VBR_CONTRAINED>\n");
- printf(" --syncmode: sequentially upload source, encoding, save result, no multi-thread\n");
- printf(" --perf: Only load YUV at the beginning, then continously re-use surface content and skip loading\n");
- printf(" --srcyuv <filename> load YUV from a file\n");
- printf(" --fourcc <NV12|IYUV|YV12> source YUV fourcc\n");
- printf(" --recyuv <filename> save reconstructed YUV into a file\n");
- printf(" --enablePSNR calculate PSNR of recyuv vs. srcyuv\n");
- printf(" --sum print encoding statistics calculate PSNR of recyuv vs. srcyuv\n");
- printf(" --entropy <0|1>, 1 means cabac, 0 cavlc\n");
- printf(" --8x8, enable 8x8 transform\n");
- printf(" --profile <BP|MP|HP>\n");
- printf(" --bit_stuffing_dis, disable bit stuffing for CBR mode\n");
- printf(" --carc, enable Content Adaptive Rate Control. A hardware mechanism that calculates\n");
+ printf(" -ip_period <number>\n");
+ printf(" -bitrate <bitrate>\n");
+ printf(" -qpluma <number>\n");
+ printf(" -initialqp <number>, initial_qp of VAEncMiscParameterRateControl structure\n");
+ printf(" also set into pic_init_qp of pps\n");
+ printf(" -minqp <number>, min_qp of VAEncMiscParameterRateControl structure\n");
+ printf(" -maxqp <number>, max_qp of VAEncMiscParameterRateControl structure\n");
+ printf(" -sliceqp <number>, qp that set into slice_qp_delta of slice header\n");
+ printf(" -rcMode <NONE|CBR|VBR|VCM|CQP|VBR_CONTRAINED>\n");
+ printf(" -syncmode: sequentially upload source, encoding, save result, no multi-thread\n");
+ printf(" -perf: Only load YUV at the beginning, then continously re-use surface content and skip loading\n");
+ printf(" -srcyuv <filename> load YUV from a file\n");
+ printf(" -fourcc <NV12|IYUV|YV12> source YUV fourcc\n");
+ printf(" -recyuv <filename> save reconstructed YUV into a file\n");
+ printf(" -enablePSNR calculate PSNR of recyuv vs. srcyuv\n");
+ printf(" -sum print encoding statistics calculate PSNR of recyuv vs. srcyuv\n");
+ printf(" -entropy <0|1>, 1 means cabac, 0 cavlc\n");
+ printf(" -8x8, enable 8x8 transform\n");
+ printf(" -profile <BP|MP|HP>\n");
+ printf(" -bit_stuffing_dis, disable bit stuffing for CBR mode\n");
+ printf(" -carc, enable Content Adaptive Rate Control. A hardware mechanism that calculates\n");
printf(" a Qp for each H.264 macroblock based on the complexity of the macroblock.\n");
- printf(" --level <level>\n");
- printf(" --surface <va|malloc|gralloc|linear_gralloc>\n");
- printf(" --stridealign <4|8|16|32|64|...>\n");
- printf(" --heightalign <4|8|16|32|64|...>\n");
+ printf(" -level <level>\n");
+ printf(" -surface <va|malloc|gralloc|linear_gralloc>\n");
+ printf(" -stridealign <4|8|16|32|64|...>\n");
+ printf(" -heightalign <4|8|16|32|64|...>\n");
printf(" for VA surface creatation with VASurfaceAttribExternalBufferDescriptor\n");
printf(" It is mainly for video encode share buffer testing\n");
printf(" va: VA_SURFACE_ATTRIB_MEM_TYPE_VA\n");
printf(" malloc: VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR\n");
printf(" gralloc: VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC\n");
- printf(" --quality <number>, JPEG encoder's quality setting\n");
- printf(" --autokf <1|0>, VP8 Encoder setting\n");
- printf(" --kf_dist_min <0-kf_dist_max>, VP8 Encoder setting\n");
- printf(" --kf_dist_max <kf_dist_min-1000>, VP8 Encoder setting\n");
- printf(" --error_resilient <kf_dist_min-1000>, VP8 Encoder setting\n");
- printf(" --hrd <buffer size> H264 CBR HRD setting\n");
+ printf(" -quality <number>, JPEG encoder's quality setting\n");
+ printf(" -autokf <1|0>, VP8 Encoder setting\n");
+ printf(" -kf_dist_min <0-kf_dist_max>, VP8 Encoder setting\n");
+ printf(" -kf_dist_max <kf_dist_min-1000>, VP8 Encoder setting\n");
+ printf(" -error_resilient <kf_dist_min-1000>, VP8 Encoder setting\n");
+ printf(" -hrd <buffer size> H264 CBR HRD setting\n");
printf(" -frame_size_log [log_file_path] the log file to save the size of every frame\n");
printf(" -raw to generate vp8 element stream, VP8 Encoder setting\n");
printf(" -riff to generate WebP file, VP8 Encoder setting\n");
@@ -383,15 +386,25 @@ static int print_help(void)
printf(" -bitrate_layer0 to set bitrate for layer 0, VP8 Encoder setting\n");
printf(" -bitrate_layer1 to set bitrate for layer 1, VP8 Encoder setting\n");
printf(" -bitrate_layer2 to set bitrate for layer 2, VP8 Encoder setting\n");
- printf(" -surface_num [surface number, 4 - 16], default is 16\n");
- printf(" -entrypoint <LP> to enable VDENC work, default is VAEntrypointEncSlice");
+ printf(" -surface_num [surface number, 4 - 16], default is 16 for auto-generated YUV\n");
+ printf(" If encoding from source YUV, and surface_num is not set, default is 4\n");
+ printf(" -entrypoint <LP> to enable VDENC work, default is VAEntrypointEncSlice\n");
+ printf(" -skip_bufdestroy to skip vaDestroyBuffer after vaRenderPicture\n");
+ printf(" -roi_enable to make ROI work with CQP mode, AVC Encoder setting\n");
+ printf(" -roi_value specifies the priority of the ROI region, AVC Encoder setting\n");
+ printf(" -roi_minqp specifies the min allowed delta QPs, AVC Encoder setting\n");
+ printf(" -roi_maxqp specifies the max allowed delta QPs, AVC Encoder setting\n");
+ printf(" -roi_rec_x defines the ROI boundary in pixels, AVC Encoder setting\n");
+ printf(" -roi_rec_y defines the ROI boundary in pixels, AVC Encoder setting\n");
+ printf(" -roi_rec_w defines the ROI boundary in pixels, AVC Encoder setting\n");
+ printf(" -roi_rec_h defines the ROI boundary in pixels, AVC Encoder setting\n");
return 0;
}
static int process_cmdline(int argc, char *argv[])
{
int atoi_rtn = 0;
- char c;
+ char c, has_surface_num = 0;
const struct option long_opts[] = {
{"help", no_argument, NULL, 0 },
{"bitrate", required_argument, NULL, 1 },
@@ -451,7 +464,16 @@ static int process_cmdline(int argc, char *argv[])
{"carc", required_argument, NULL, 56},
{"sum", no_argument, NULL, 57},
{"active_pm", no_argument, NULL, 58},
- {"entrypoint", required_argument, NULL, 59},
+ {"entrypoint", required_argument, NULL, 59},
+ {"skip_bufdestroy", no_argument, NULL, 60},
+ {"roi_enable", no_argument, NULL, 61},
+ {"roi_value", no_argument, NULL, 62},
+ {"roi_minqp", required_argument, NULL, 64},
+ {"roi_maxqp", required_argument, NULL, 65},
+ {"roi_rec_x", required_argument, NULL, 66},
+ {"roi_rec_y", required_argument, NULL, 67},
+ {"roi_rec_w", required_argument, NULL, 68},
+ {"roi_rec_h", required_argument, NULL, 69},
{NULL, no_argument, NULL, 0 }};
int long_index, i, tmp, intra_idr_period_tmp = -1;
@@ -702,6 +724,7 @@ static int process_cmdline(int argc, char *argv[])
break;
case 55:
ref_surface_num = surface_num = atoi(optarg);
+ has_surface_num = 1;
break;
case 56:
carc = 1;
@@ -715,7 +738,54 @@ static int process_cmdline(int argc, char *argv[])
//case ':':
case 59:
if (!strncmp(optarg, "LP", 2))
- va_entrypoint = VAEntrypointEncSliceLP;
+ va_entrypoint = VAEntrypointEncSliceLP;
+ break;
+ case 60:
+ buf_destroy = 0;
+ break;
+ case 61:
+ roi_enable = 1;
+ break;
+ case 62:
+ roi_value = 1;
+ break;
+ case 64:
+ roi_minqp = atoi(optarg);
+ break;
+ case 65:
+ roi_maxqp = atoi(optarg);
+ break;
+ case 66:
+ atoi_rtn = atoi(optarg);
+ if (atoi_rtn <= 0) {
+ fprintf(stderr, "rec_x value must be positive!\n");
+ exit(1);
+ }
+ roi_rec_x = atoi_rtn;
+ break;
+ case 67:
+ atoi_rtn = atoi(optarg);
+ if (atoi_rtn <= 0) {
+ fprintf(stderr, "rec_y value must be positive!\n");
+ exit(1);
+ }
+ roi_rec_y = atoi_rtn;
+ break;
+ case 68:
+ atoi_rtn = atoi(optarg);
+ if (atoi_rtn <= 0) {
+ fprintf(stderr, "rec_w value must be positive!\n");
+ exit(1);
+ }
+ roi_rec_w = atoi_rtn;
+ break;
+ case 69:
+ atoi_rtn = atoi(optarg);
+ if (atoi_rtn <= 0) {
+ fprintf(stderr, "rec_h value must be positive!\n");
+ exit(1);
+ }
+ roi_rec_h = atoi_rtn;
break;
case '?':
print_help();
@@ -748,19 +818,18 @@ static int process_cmdline(int argc, char *argv[])
fstat(fileno(srcyuv_fp), &tmp);
srcyuv_frames = tmp.st_size / (frame_width * frame_height * 1.5);
- if (0 == frame_count)
- frame_count = srcyuv_frames;
-
- if (0 == srcyuv_frames) {
+ if (srcyuv_frames == 0) {
fclose(srcyuv_fp);
srcyuv_fp = NULL;
- printf("Source YUV file %s contains 0 valid frame, use auto-generated YUV data\n\n", srcyuv_fn);
- }
- else
+ printf("Source YUV file %s contains 0 frame, use auto-generated YUV data\n\n", srcyuv_fn);
+ } else {
+ if (frame_count==0)
+ frame_count = srcyuv_frames;
printf("Source YUV file %s with %d frames\n\n", srcyuv_fn, srcyuv_frames);
-
- if (0 == frame_count)
- frame_count = 60;
+ /* Use 4 surfaces if encoding from a source YUV and user doesn't set surface_num */
+ if (!has_surface_num)
+ ref_surface_num = surface_num = 4;
+ }
}
}
@@ -1319,6 +1388,23 @@ static void * storage_task_thread(void *t)
return 0;
}
+int destroy_vabuffers(VADisplay dpy, int buf_num, ...)
+{
+ va_list argp;
+ VABufferID buf_id;
+ int i;
+
+ va_start(argp, buf_num);
+ for (i=0; i<buf_num; i++) {
+ buf_id = va_arg(argp, VABufferID);
+ if (buf_id != VA_INVALID_ID)
+ vaDestroyBuffer(dpy, buf_id);
+ }
+ va_end(argp);
+
+ return 0;
+}
+
static int encode_frames(void)
{
int tmp;
@@ -1490,7 +1576,7 @@ static int print_performance(unsigned int PictureCount)
printf("\n\n");
- printf("PERFORMANCE: Frame Rate : %.2f fps (%d frames, %d ms (%.2f ms per frame))\n",
+ printf("PERFORMANCE: End-to-End FPS : %.2f fps (%d frames, %d ms (%.2f ms per frame))\n",
(double) 1000*PictureCount / TotalTicks, PictureCount,
TotalTicks, ((double) TotalTicks) / (double) PictureCount);
printf("PERFORMANCE: Core Encoding FPS : %.2f fps (%d frames, %d ms (%.2f ms per frame))\n",
@@ -1501,8 +1587,12 @@ static int print_performance(unsigned int PictureCount)
else
printf(" (Core Encoding includes vaBegin/vaRender/vaEnd; vaSync in another thread and not counted)\n");
- printf("PERFORMANCE: Compression ratio : %.2f%% (%.0f vs %.0f)\n", frame_size * 100.0/total_size,
- frame_size, total_size);
+ printf("PERFORMANCE: Compression ratio : %.2f", total_size/frame_size);
+ if ((total_size/(1<<20)) > 999)
+ printf(" (%.0fM vs %.0fM)\n", total_size/(1<<20), frame_size/(1<<20));
+ else
+ printf(" (%.0fK vs %.0fK)\n", total_size/(1<<10), frame_size/(1<<10));
+
if (&jpeg_codec == current_codec) {
float tmp = (float)frame_width * frame_height * 1.5 * frame_count/((float)TotalTicks/1000)/1024/1024;
float tmp1 = (float)frame_width * frame_height * 1.5 * frame_count/(core_time/1000)/1024/1024;
diff --git a/vaenc/va_encode.h b/vaenc/va_encode.h
index 11ba3a7..6bca627 100644
--- a/vaenc/va_encode.h
+++ b/vaenc/va_encode.h
@@ -139,6 +139,7 @@ extern unsigned int surface_type;
/* h264 specific variables */
extern unsigned int h264_entropy_mode; /* cabac */
extern unsigned int h264_8x8_dct;
+extern unsigned int layer_num;
extern unsigned int jpeg_quality;
@@ -167,6 +168,16 @@ extern unsigned int bitrate_layer1;
extern unsigned int bitrate_layer2;
extern unsigned int windows_size;
extern int pm_active;
+extern int buf_destroy;
+
+extern unsigned int roi_enable;
+extern unsigned int roi_value;
+extern int roi_minqp;
+extern int roi_maxqp;
+extern unsigned int roi_rec_x;
+extern unsigned int roi_rec_y;
+extern unsigned int roi_rec_w;
+extern unsigned int roi_rec_h;
int access_statitics(void *p, int encoder_order);
int print_statitics(int frame_number, int width, int height);
@@ -284,6 +295,7 @@ static inline int string_to_rc(char *str)
return rc_mode;
}
+int destroy_vabuffers(VADisplay dpy, int buf_num, ...);
VAStatus create_surfaces();
VAStatus destroy_surfaces();
VAStatus get_surface_attrib();
@@ -300,4 +312,3 @@ extern struct codec_table_t h263_codec;
extern struct codec_table_t vp8_codec;
extern struct codec_table_t jpeg_codec;
static struct codec_table_t *current_codec = &h264_codec;
-extern unsigned int layer_num;
diff --git a/vaenc/va_surface.c b/vaenc/va_surface.c
index bbb4d16..f80a183 100644
--- a/vaenc/va_surface.c
+++ b/vaenc/va_surface.c
@@ -132,8 +132,8 @@ VAStatus create_surfaces_external(struct codec_table_t *current_codec)
} else if (surface_type == SURFACE_TYPE_GRALLOC || surface_type == SURFACE_TYPE_GRALLOC_LINEAR) {
unsigned long buffers[SURFACE_NUM];
- //va_status = alloc_gralloc_buffer(surface_num, buffers, frame_width_mbaligned, frame_height_mbaligned,
- // (surface_type == SURFACE_TYPE_GRALLOC_LINEAR));
+ va_status = alloc_gralloc_buffer(surface_num, buffers, frame_width_mbaligned, frame_height_mbaligned,
+ (surface_type == SURFACE_TYPE_GRALLOC_LINEAR));
/* stride need to follow gralloc allocator */
setup_externalbuf(&external_srcbuf, surface_type, &attrib_list[0]);