diff options
author | Sreerenj Balachandran <sreerenj.balachandran@intel.com> | 2020-12-02 12:03:23 -0800 |
---|---|---|
committer | Sreerenj Balachandran <sreerenj.balachandran@intel.com> | 2020-12-02 12:03:23 -0800 |
commit | 60eca871f1bca3d601e1a30baa1f1f2e78fcad35 (patch) | |
tree | 5a82f420e296a013a085fdd20cb59b9536ba4893 | |
parent | 564ca931f490fefce38793547db993073897bcad (diff) |
Fix temporal SVC reference picture model for VP9Enc
Now the 2 layer temporal model is similar to libvpx mode.
eg: libvpx:
./vp9_spatial_svc_encoder --width=1280 --height=720 --passes=1 --rc-end-usage=1 --target-bitrate=4096 --min-bitrate=4096 --max-bitrate=4096 --spatial-layers=1 --temporal-layers=2 --temporal-layering-mode=2 --timebase=1/30 --kf-dist=30 -o sample_vp9.webm /home/sreerenj/Videos/raw/sample_1280_720_300f_i420.yuv
eg: gst:gst-launch-1.0 videotestsrc num-buffers=300 ! video/x-raw, width=1280, height=720, framerate=30/1 ! vaapivp9enc enable-software-brc=true bitrate=4096 k-svc=false temporal-svc=true ! webmmux ! filesink location=sample.webm
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapiencoder_vp9.c | 84 |
1 files changed, 59 insertions, 25 deletions
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_vp9.c b/gst-libs/gst/vaapi/gstvaapiencoder_vp9.c index fbd8b856..798c7f1f 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_vp9.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_vp9.c @@ -30,6 +30,8 @@ #include "gstvaapisurface.h" #include "gstvaapifilter.h" +#define GST_VP9_REF_FRAMES_TEMPORAL_SVC 2 + #if USE_LIBMEBO #include <libmebo/libmebo.h> #endif @@ -406,24 +408,37 @@ get_ref_indices_k_svc (guint ref_list_idx, guint spatial_group_count, } static void -get_ref_indices_temporal_svc (guint ref_list_idx, guint temporal_id, +get_ref_indices_temporal_svc (guint frame_num, guint ref_list_idx, guint temporal_id, guint * last_idx, guint * gf_idx, guint * arf_idx, guint * ref_frame_ctrl_l0, guint8 * refresh_frame_flags) { gint last_filled_idx; - last_filled_idx = (ref_list_idx - 1) & (GST_VP9_REF_FRAMES - 1); + last_filled_idx = (ref_list_idx - 1) % GST_VP9_REF_FRAMES_TEMPORAL_SVC; *ref_frame_ctrl_l0 = 0x07; - *refresh_frame_flags = 1 << ((last_filled_idx + 1) % GST_VP9_REF_FRAMES); + + if (frame_num % 2 != 0) + *refresh_frame_flags = 2; + else + *refresh_frame_flags = 1; + + //g_message ("Debug: frame_num=%d get_ref_indices last-filled-idx= %d temporal_id=%d refresh_frame_flags=%d",frame_num, last_filled_idx, temporal_id,*refresh_frame_flags); //Non Base Layer if (temporal_id == 1) { - *last_idx = last_filled_idx; - *arf_idx = *gf_idx = (last_filled_idx - 1) & (GST_VP9_REF_FRAMES - 1); + *last_idx = *gf_idx = last_filled_idx; + if (frame_num == 1) { + *arf_idx = *last_idx; + } else { + if (last_filled_idx == 0) + *arf_idx = 1; + else + *arf_idx = 0; + } } else if (temporal_id == 0) { //Base Layer - *last_idx = *arf_idx = *gf_idx = ((last_filled_idx-1) & (GST_VP9_REF_FRAMES - 1)); + *last_idx = *arf_idx = *gf_idx = 0;; } else { g_message ("Temproal id is >1, something went wrong! "); } @@ -480,7 +495,29 @@ fill_picture_temporal_svc (GstVaapiEncoderVP9 * encoder, guint8 refresh_frame_flags = 0; guint width, height; guint ref_frame_ctrl_l0 = 0; + guint i =0; + /* Update Reference Frame list */ + if (picture->type == GST_VAAPI_PICTURE_TYPE_I) + memset (pic_param->reference_frames, 0xFF, + sizeof (pic_param->reference_frames)); + else { + for (i = 0; i < G_N_ELEMENTS (pic_param->reference_frames); i++) { + if (encoder->ref_list[i]) + pic_param->reference_frames[i] = + GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->ref_list[i]); + else + pic_param->reference_frames[i] = VA_INVALID_ID; + } + } + pic_param->luma_ac_qindex = encoder->yac_qi; + pic_param->luma_dc_qindex_delta = 1; + pic_param->chroma_ac_qindex_delta = 1; + pic_param->chroma_dc_qindex_delta = 1; + pic_param->filter_level = encoder->loop_filter_level; + pic_param->sharpness_level = encoder->sharpness_level; + + pic_param->pic_flags.bits.show_frame = 1; width = gst_vaapi_surface_get_width (GST_VAAPI_SURFACE_PROXY_SURFACE (surface)); height = @@ -497,7 +534,7 @@ fill_picture_temporal_svc (GstVaapiEncoderVP9 * encoder, if (picture->type == GST_VAAPI_PICTURE_TYPE_P) { pic_param->pic_flags.bits.frame_type = GST_VP9_INTER_FRAME; - get_ref_indices_temporal_svc (encoder->ref_list_idx, picture->temporal_id, + get_ref_indices_temporal_svc (encoder->frame_num-1,encoder->ref_list_idx, picture->temporal_id, &last_idx, &gf_idx, &arf_idx, &ref_frame_ctrl_l0, &refresh_frame_flags); pic_param->ref_flags.bits.ref_frame_ctrl_l0 = ref_frame_ctrl_l0; @@ -524,6 +561,10 @@ fill_picture (GstVaapiEncoderVP9 * encoder, pic_param->reconstructed_frame = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface); pic_param->coded_buf = GST_VAAPI_CODED_BUFFER_ID (codedbuf); + //temporal-svc + if (encoder->temporal_svc && (encoder->num_temporal_layers)) + return fill_picture_temporal_svc (encoder, picture, codedbuf, surface, pic_param); + /* Update Reference Frame list */ if (picture->type == GST_VAAPI_PICTURE_TYPE_I) memset (pic_param->reference_frames, 0xFF, @@ -548,9 +589,6 @@ fill_picture (GstVaapiEncoderVP9 * encoder, if (encoder->k_svc && (encoder->num_spatial_layers)) return fill_picture_k_svc (encoder, picture, codedbuf, surface, pic_param); - //temporal-svc - if (encoder->temporal_svc && (encoder->num_temporal_layers)) - return fill_picture_temporal_svc (encoder, picture, codedbuf, surface, pic_param); /* It is possible to have dynamic scaling with gpu by providing * src and destination resoltuion. For now we are just using @@ -658,22 +696,11 @@ update_ref_list_temporal_svc (GstVaapiEncoderVP9 * encoder, GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * ref) { guint i; - - if (picture->type == GST_VAAPI_PICTURE_TYPE_I) { - for (i = 0; i < G_N_ELEMENTS (encoder->ref_list); i++) - gst_vaapi_surface_proxy_replace (&encoder->ref_list[i], ref); - gst_vaapi_surface_proxy_unref (ref); - /* set next free slot index */ - encoder->ref_list_idx = 1; - return; - } else { - if (encoder->ref_list_idx == 0) - encoder->ref_list_idx = 1; - } i = encoder->ref_list_idx; gst_vaapi_surface_proxy_replace (&encoder->ref_list[i], ref); gst_vaapi_surface_proxy_unref (ref); - encoder->ref_list_idx = (encoder->ref_list_idx + 1) % GST_VP9_REF_FRAMES; + encoder->ref_list_idx = (encoder->ref_list_idx + 1) % GST_VP9_REF_FRAMES_TEMPORAL_SVC; + //g_message ("Debug: update_ref_list: ref_list_idx=next_free_slot = %d",encoder->ref_list_idx); } static GstVaapiEncoderStatus @@ -813,7 +840,10 @@ gst_vaapi_encoder_vp9_encode (GstVaapiEncoder * base_encoder, encoder->loop_filter_level = lf; - g_message ("QP = %d : LF_Strength = %d",qp,lf); + if (picture->type != GST_VAAPI_PICTURE_TYPE_P) + g_message ("KeyFrame: QP = %d : LF_Strength = %d",qp,lf); + else + g_message ("PFrame: QP = %d : LF_Strength = %d",qp,lf); } #endif @@ -843,7 +873,10 @@ gst_vaapi_encoder_vp9_encode (GstVaapiEncoder * base_encoder, if (encoder->software_brc) { gint32 buf_size; buf_size = gst_vaapi_coded_buffer_get_size (GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf)); - g_message ("PostEncodeBufferSize = %d ",buf_size); + if (picture->type != GST_VAAPI_PICTURE_TYPE_P) + g_message ("KeyFrame: PostEncodeBufferSize = %d ",buf_size); + else + g_message ("PFrame: PostEncodeBufferSize = %d ",buf_size); libmebo_rate_controller_update_frame_size (encoder->libmebo_rc, buf_size); } @@ -1021,6 +1054,7 @@ gst_vaapi_encoder_vp9_reordering_temporal_svc (GstVaapiEncoder * base_encoder, picture->temporal_id = encoder->temporal_id; encoder->temporal_id = (encoder->temporal_id + 1) % encoder->num_temporal_layers; + //g_message ("Debug:Reordering_TemporalId = %d \n",picture->temporal_id); return status; } static GstVaapiEncoderStatus |