From 173b70b53ff55ea367842f38131170a88ce1e4f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Tue, 8 Sep 2015 13:57:15 +0300 Subject: [PATCH 1/9] Rename SLICE_* enum constants to KVZ_SLICE_*. --- src/cli.c | 2 +- src/encoder_state-bitstream.c | 8 ++++---- src/encoderstate.c | 18 +++++++++--------- src/encoderstate.h | 2 +- src/filter.c | 2 +- src/global.h | 6 +++++- src/inter.c | 6 +++--- src/rate_control.c | 2 +- src/search.c | 4 ++-- src/search_inter.c | 2 +- src/transform.c | 2 +- 11 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/cli.c b/src/cli.c index 38b475f88..dd6cde8a8 100644 --- a/src/cli.c +++ b/src/cli.c @@ -365,7 +365,7 @@ void print_frame_info(encoder_state_t *state, double frame_psnr[3]) frame_psnr[0], frame_psnr[1], frame_psnr[2]); // Print reference picture lists - if (state->global->slicetype != SLICE_I) { + if (state->global->slicetype != KVZ_SLICE_I) { int j, ref_list[2] = { 0, 0 }, ref_list_poc[2][16]; // List all pocs of lists for (j = 0; j < state->global->ref->used_size; j++) { diff --git a/src/encoder_state-bitstream.c b/src/encoder_state-bitstream.c index 2622a1dfb..188d8c391 100644 --- a/src/encoder_state-bitstream.c +++ b/src/encoder_state-bitstream.c @@ -33,8 +33,8 @@ static void encoder_state_write_bitstream_aud(encoder_state_t * const state) bitstream_t * const stream = &state->stream; kvz_nal_write(stream, AUD_NUT, 0, 1); - uint8_t pic_type = state->global->slicetype == SLICE_I ? 0 - : state->global->slicetype == SLICE_P ? 1 + uint8_t pic_type = state->global->slicetype == KVZ_SLICE_I ? 0 + : state->global->slicetype == KVZ_SLICE_P ? 1 : 2; WRITE_U(stream, pic_type, 3, "pic_type"); @@ -745,10 +745,10 @@ void kvz_encoder_state_write_bitstream_slice_header(encoder_state_t * const stat WRITE_U(stream, 1, 1, "slice_sao_chroma_flag"); } - if (state->global->slicetype != SLICE_I) { + if (state->global->slicetype != KVZ_SLICE_I) { WRITE_U(stream, 1, 1, "num_ref_idx_active_override_flag"); WRITE_UE(stream, ref_negative != 0 ? ref_negative - 1: 0, "num_ref_idx_l0_active_minus1"); - if (state->global->slicetype == SLICE_B) { + if (state->global->slicetype == KVZ_SLICE_B) { WRITE_UE(stream, ref_positive != 0 ? ref_positive - 1 : 0, "num_ref_idx_l1_active_minus1"); WRITE_U(stream, 0, 1, "mvd_l1_zero_flag"); } diff --git a/src/encoderstate.c b/src/encoderstate.c index be7a5155b..0e7530c2a 100644 --- a/src/encoderstate.c +++ b/src/encoderstate.c @@ -369,7 +369,7 @@ static void encoder_state_encode_leaf(encoder_state_t * const state) { // once. The added dependancy is for the first LCU of each wavefront // row to depend on the reconstruction status of the row below in the // previous frame. - if (state->previous_encoder_state != state && state->previous_encoder_state->tqj_recon_done && state->global->slicetype != SLICE_I) { + if (state->previous_encoder_state != state && state->previous_encoder_state->tqj_recon_done && state->global->slicetype != KVZ_SLICE_I) { if (!lcu->left) { if (lcu->below) { kvz_threadqueue_job_dep_add(state->tile->wf_jobs[lcu->id], lcu->below->encoder_state->previous_encoder_state->tqj_recon_done); @@ -688,7 +688,7 @@ static void encoder_state_remove_refs(encoder_state_t *state) { if (encoder->cfg->gop_len) { refnumber = encoder->cfg->gop[state->global->gop_offset].ref_neg_count + encoder->cfg->gop[state->global->gop_offset].ref_pos_count; check_refs = 1; - } else if (state->global->slicetype == SLICE_I) { + } else if (state->global->slicetype == KVZ_SLICE_I) { refnumber = 0; } // Remove the ref pic (if present) @@ -758,14 +758,14 @@ static void encoder_state_new_frame(encoder_state_t * const state) { if (state->global->is_idr_frame) { encoder_state_reset_poc(state); - state->global->slicetype = SLICE_I; + state->global->slicetype = KVZ_SLICE_I; state->global->pictype = NAL_IDR_W_RADL; } else { - state->global->slicetype = encoder->cfg->intra_period==1 ? SLICE_I : (state->encoder_control->cfg->gop_len?SLICE_B:SLICE_P); + state->global->slicetype = encoder->cfg->intra_period==1 ? KVZ_SLICE_I : (state->encoder_control->cfg->gop_len?KVZ_SLICE_B:KVZ_SLICE_P); state->global->pictype = NAL_TRAIL_R; if (state->encoder_control->cfg->gop_len) { if (encoder->cfg->intra_period > 1 && (state->global->poc % encoder->cfg->intra_period) == 0) { - state->global->slicetype = SLICE_I; + state->global->slicetype = KVZ_SLICE_I; } } @@ -779,7 +779,7 @@ static void encoder_state_new_frame(encoder_state_t * const state) { lambda = kvz_select_picture_lambda(state); state->global->QP = kvz_lambda_to_QP(lambda); } else { - if (encoder->cfg->gop_len > 0 && state->global->slicetype != SLICE_I) { + if (encoder->cfg->gop_len > 0 && state->global->slicetype != KVZ_SLICE_I) { kvz_gop_config const * const gop = encoder->cfg->gop + state->global->gop_offset; state->global->QP = encoder->cfg->qp + gop->qp_offset; @@ -1011,7 +1011,7 @@ void kvz_encode_coding_tree(encoder_state_t * const state, // Encode skip flag - if (state->global->slicetype != SLICE_I) { + if (state->global->slicetype != KVZ_SLICE_I) { int8_t ctx_skip = 0; // uiCtxSkip = aboveskipped + leftskipped; int ui; int16_t num_cand = MRG_MAX_NUM_CANDS; @@ -1050,7 +1050,7 @@ void kvz_encode_coding_tree(encoder_state_t * const state, // ENDIF SKIP // Prediction mode - if (state->global->slicetype != SLICE_I) { + if (state->global->slicetype != KVZ_SLICE_I) { cabac->cur_ctx = &(cabac->ctx.cu_pred_mode_model); CABAC_BIN(cabac, (cur_cu->type == CU_INTRA), "PredMode"); } @@ -1106,7 +1106,7 @@ void kvz_encode_coding_tree(encoder_state_t * const state, } // Void TEncSbac::codeInterDir( TComDataCU* pcCU, UInt uiAbsPartIdx ) - if (state->global->slicetype == SLICE_B) + if (state->global->slicetype == KVZ_SLICE_B) { // Code Inter Dir uint8_t inter_dir = cur_cu->inter.mv_dir-1; diff --git a/src/encoderstate.h b/src/encoderstate.h index b1b05dbb4..02a7822f3 100644 --- a/src/encoderstate.h +++ b/src/encoderstate.h @@ -81,7 +81,7 @@ typedef struct { bool is_idr_frame; uint8_t pictype; - uint8_t slicetype; + enum kvz_slice_type slicetype; //! Total number of bits written. uint64_t total_bits_coded; diff --git a/src/filter.c b/src/filter.c index 6fcdcef23..465e3cce9 100644 --- a/src/filter.c +++ b/src/filter.c @@ -246,7 +246,7 @@ void kvz_filter_deblock_edge_luma(encoder_state_t * const state, } // B-slice related checks - if(!strength && state->global->slicetype == SLICE_B) { + if(!strength && state->global->slicetype == KVZ_SLICE_B) { // Zero all undefined motion vectors for easier usage if(!(cu_q->inter.mv_dir & 1)) { diff --git a/src/global.h b/src/global.h index dbf3252dd..7fdb0b7f2 100644 --- a/src/global.h +++ b/src/global.h @@ -216,6 +216,10 @@ typedef int16_t coeff_t; //Constants typedef enum { COLOR_Y = 0, COLOR_U, COLOR_V, NUM_COLORS } color_t; -enum { SLICE_B = 0, SLICE_P = 1, SLICE_I = 2 }; +enum kvz_slice_type { + KVZ_SLICE_B = 0, + KVZ_SLICE_P = 1, + KVZ_SLICE_I = 2, +}; #endif diff --git a/src/inter.c b/src/inter.c index c84b7166d..cd26486fb 100644 --- a/src/inter.c +++ b/src/inter.c @@ -763,7 +763,7 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, int32_t x, } #endif - if (candidates < MRG_MAX_NUM_CANDS && state->global->slicetype == SLICE_B) { + if (candidates < MRG_MAX_NUM_CANDS && state->global->slicetype == KVZ_SLICE_B) { #define NUM_PRIORITY_LIST 12; static const uint8_t priorityList0[] = { 0, 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3 }; static const uint8_t priorityList1[] = { 1, 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2 }; @@ -798,7 +798,7 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, int32_t x, int num_ref = state->global->ref->used_size; - if (candidates < MRG_MAX_NUM_CANDS && state->global->slicetype == SLICE_B) { + if (candidates < MRG_MAX_NUM_CANDS && state->global->slicetype == KVZ_SLICE_B) { int j; int ref_negative = 0; int ref_positive = 0; @@ -819,7 +819,7 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, int32_t x, mv_cand[candidates].ref[0] = (zero_idx>=num_ref-1)?0:zero_idx; mv_cand[candidates].ref[1] = mv_cand[candidates].ref[0]; mv_cand[candidates].dir = 1; - if (state->global->slicetype == SLICE_B) { + if (state->global->slicetype == KVZ_SLICE_B) { mv_cand[candidates].mv[1][0] = 0; mv_cand[candidates].mv[1][1] = 0; mv_cand[candidates].dir = 3; diff --git a/src/rate_control.c b/src/rate_control.c index 7c5a0f582..7f8f6c7cd 100644 --- a/src/rate_control.c +++ b/src/rate_control.c @@ -160,7 +160,7 @@ double kvz_select_picture_lambda_from_qp(encoder_state_t const * const state) const double qp_temp = state->global->QP - 12; double qp_factor; - if (state->global->slicetype == SLICE_I) { + if (state->global->slicetype == KVZ_SLICE_I) { const double lambda_scale = 1.0 - CLIP(0.0, 0.5, 0.05 * gop_len); qp_factor = 0.57 * lambda_scale; } else if (gop_len > 0) { diff --git a/src/search.c b/src/search.c index 985601a2b..0017ce2f5 100644 --- a/src/search.c +++ b/src/search.c @@ -517,7 +517,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, y + cu_width <= frame->height) { - if (state->global->slicetype != SLICE_I && + if (state->global->slicetype != KVZ_SLICE_I && WITHIN(depth, ctrl->pu_depth_inter.min, ctrl->pu_depth_inter.max)) { int mode_cost = kvz_search_cu_inter(state, x, y, depth, &work_tree[depth]); @@ -606,7 +606,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, } // Recursively split all the way to max search depth. - if (depth < ctrl->pu_depth_intra.max || (depth < ctrl->pu_depth_inter.max && state->global->slicetype != SLICE_I)) { + if (depth < ctrl->pu_depth_intra.max || (depth < ctrl->pu_depth_inter.max && state->global->slicetype != KVZ_SLICE_I)) { int half_cu = cu_width / 2; // Using Cost = lambda * 9 to compensate on the price of the split double split_cost = state->global->cur_lambda_cost * CU_COST; diff --git a/src/search_inter.c b/src/search_inter.c index bb89909d4..29f4ed834 100644 --- a/src/search_inter.c +++ b/src/search_inter.c @@ -1052,7 +1052,7 @@ int kvz_search_cu_inter(const encoder_state_t * const state, int x, int y, int d } // Search bi-pred positions - if (state->global->slicetype == SLICE_B && state->encoder_control->cfg->bipred) { + if (state->global->slicetype == KVZ_SLICE_B && state->encoder_control->cfg->bipred) { lcu_t *templcu = MALLOC(lcu_t, 1); cost_pixel_nxn_func *satd = kvz_pixels_get_satd_func(LCU_WIDTH >> depth); #define NUM_PRIORITY_LIST 12; diff --git a/src/transform.c b/src/transform.c index e95387aa9..163b6273c 100644 --- a/src/transform.c +++ b/src/transform.c @@ -147,7 +147,7 @@ void kvz_quant(const encoder_state_t * const state, coeff_t *coef, coeff_t *q_co const int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6]; const int32_t transform_shift = MAX_TR_DYNAMIC_RANGE - encoder->bitdepth - log2_tr_size; //!< Represents scaling through forward transform const int32_t q_bits = QUANT_SHIFT + qp_scaled/6 + transform_shift; - const int32_t add = ((state->global->slicetype == SLICE_I) ? 171 : 85) << (q_bits - 9); + const int32_t add = ((state->global->slicetype == KVZ_SLICE_I) ? 171 : 85) << (q_bits - 9); const int32_t q_bits8 = q_bits - 8; uint32_t ac_sum = 0; From c856a6b598d5654624529871d8ced4a11f5cff26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Tue, 8 Sep 2015 13:59:55 +0300 Subject: [PATCH 2/9] Output frame info from encoder_encode. Adds a new output parameter info_out to encoder_encode. It returns a struct containing information about the encoded frame, including POC, QP and slice type. --- src/encmain.c | 2 +- src/global.h | 5 ----- src/kvazaar.c | 12 +++++++++++- src/kvazaar.h | 40 +++++++++++++++++++++++++++++++++++----- src/kvazaar_version.h | 2 +- 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/encmain.c b/src/encmain.c index 583fc2489..58356b99e 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -212,7 +212,7 @@ int main(int argc, char *argv[]) kvz_data_chunk* chunks_out = NULL; kvz_picture *img_rec = NULL; uint32_t len_out = 0; - if (!api->encoder_encode(enc, img_in, &chunks_out, &len_out, &img_rec)) { + if (!api->encoder_encode(enc, img_in, &chunks_out, &len_out, &img_rec, NULL)) { fprintf(stderr, "Failed to encode image.\n"); api->picture_free(img_in); goto exit_failure; diff --git a/src/global.h b/src/global.h index 7fdb0b7f2..f8016f71d 100644 --- a/src/global.h +++ b/src/global.h @@ -216,10 +216,5 @@ typedef int16_t coeff_t; //Constants typedef enum { COLOR_Y = 0, COLOR_U, COLOR_V, NUM_COLORS } color_t; -enum kvz_slice_type { - KVZ_SLICE_B = 0, - KVZ_SLICE_P = 1, - KVZ_SLICE_I = 2, -}; #endif diff --git a/src/kvazaar.c b/src/kvazaar.c index 3643a29b4..ea7f92a18 100644 --- a/src/kvazaar.c +++ b/src/kvazaar.c @@ -113,11 +113,20 @@ static kvz_encoder * kvazaar_open(const kvz_config *cfg) } +static void set_frame_info(kvz_frame_info *const info, const encoder_state_t *const state) +{ + info->poc = state->global->poc, + info->qp = state->global->QP; + info->slice_type = state->global->slicetype; +} + + static int kvazaar_encode(kvz_encoder *enc, kvz_picture *pic_in, kvz_data_chunk **data_out, uint32_t *len_out, - kvz_picture **pic_out) + kvz_picture **pic_out, + kvz_frame_info *info_out) { if (data_out) *data_out = NULL; if (len_out) *len_out = 0; @@ -164,6 +173,7 @@ static int kvazaar_encode(kvz_encoder *enc, if (len_out) *len_out = kvz_bitstream_tell(&output_state->stream) / 8; if (data_out) *data_out = kvz_bitstream_take_chunks(&output_state->stream); if (pic_out) *pic_out = kvz_image_copy_ref(output_state->tile->frame->rec); + if (info_out) set_frame_info(info_out, output_state); output_state->frame_done = 1; output_state->prepared = 0; diff --git a/src/kvazaar.h b/src/kvazaar.h index 3f3122c05..f8b1a6fbd 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -191,6 +191,34 @@ typedef struct kvz_picture { int64_t dts; //!< \brief Decompression timestamp. } kvz_picture; +enum kvz_slice_type { + KVZ_SLICE_B = 0, + KVZ_SLICE_P = 1, + KVZ_SLICE_I = 2, +}; + +/** + * \brief Other information about an encoded frame + */ +typedef struct kvz_frame_info { + + /** + * \brief Picture order count + */ + int32_t poc; + + /** + * \brief Quantization parameter + */ + int8_t qp; + + /** + * \brief Type of the slice + */ + enum kvz_slice_type slice_type; + +} kvz_frame_info; + /** * \brief A linked list of chunks of data. * @@ -303,9 +331,9 @@ typedef struct kvz_api { * \brief Encode one frame. * * Add pic_in to the encoding pipeline. If an encoded frame is ready, return - * the bitstream, length of the bitstream and the reconstructed frame in - * data_out, len_out and pic_out, respectively. Otherwise, set the output - * parameters to NULL. + * the bitstream, length of the bitstream, the reconstructed frame and frame + * info in data_out, len_out, pic_out and info_out, respectively. Otherwise, + * set the output parameters to NULL. * * After passing all of the input frames, the caller should keep calling this * function with pic_in set to NULL, until no more data is returned in the @@ -317,20 +345,22 @@ typedef struct kvz_api { * responsible for calling picture_free and chunk_free on them. * * A null pointer may be passed in place of any of the parameters data_out, - * len_out or pic_out to skip returning the corresponding value. + * len_out, pic_out or info_out to skip returning the corresponding value. * * \param encoder encoder * \param pic_in input frame or NULL * \param data_out Returns the encoded data. * \param len_out Returns number of bytes in the encoded data. * \param pic_out Returns the reconstructed picture. + * \param info_out Returns information about the encoded picture. * \return 1 on success, 0 on error. */ int (*encoder_encode)(kvz_encoder *encoder, kvz_picture *pic_in, kvz_data_chunk **data_out, uint32_t *len_out, - kvz_picture **pic_out); + kvz_picture **pic_out, + kvz_frame_info *info_out); } kvz_api; // Append API version to the getters name to prevent linking against incompatible versions. diff --git a/src/kvazaar_version.h b/src/kvazaar_version.h index caa17fa63..fd9a628d6 100644 --- a/src/kvazaar_version.h +++ b/src/kvazaar_version.h @@ -21,6 +21,6 @@ ****************************************************************************/ // KVZ_API_VERSION is incremented every time the public api changes. -#define KVZ_API_VERSION 4 +#define KVZ_API_VERSION 5 #endif // KVAZAAR_VERSION_H_ From d5dceb45f12e1523d879532bb0e94f279771619f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Wed, 9 Sep 2015 10:01:02 +0300 Subject: [PATCH 3/9] Factor out a function for building ref lists. The code for building the reference picture lists was duplicated in functions encoder_state_ref_sort and print_frame_info. This commit moves it to a new function kvz_encoder_get_ref_lists. Also makes encoder_ref_insertion_sort static since it is not used outside the encoderstate module any more. --- src/cli.c | 23 +++++++-------------- src/encoderstate.c | 51 ++++++++++++++++++++++++++++++++++------------ src/encoderstate.h | 4 +++- 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/cli.c b/src/cli.c index dd6cde8a8..3a590df6b 100644 --- a/src/cli.c +++ b/src/cli.c @@ -364,28 +364,19 @@ void print_frame_info(encoder_state_t *state, double frame_psnr[3]) "BPI"[state->global->slicetype % 3], state->stats_bitstream_length << 3, frame_psnr[0], frame_psnr[1], frame_psnr[2]); - // Print reference picture lists if (state->global->slicetype != KVZ_SLICE_I) { - int j, ref_list[2] = { 0, 0 }, ref_list_poc[2][16]; - // List all pocs of lists - for (j = 0; j < state->global->ref->used_size; j++) { - if (state->global->ref->pocs[j] < state->global->poc) { - ref_list_poc[0][ref_list[0]] = state->global->ref->pocs[j]; - ref_list[0]++; - } else { - ref_list_poc[1][ref_list[1]] = state->global->ref->pocs[j]; - ref_list[1]++; - } - } - kvz_encoder_ref_insertion_sort(ref_list_poc[0], ref_list[0]); - kvz_encoder_ref_insertion_sort(ref_list_poc[1], ref_list[1]); + // Print reference picture lists + int ref_list_len[2]; + int ref_list_poc[2][16]; + + kvz_encoder_get_ref_lists(state, ref_list_len, ref_list_poc); fprintf(stderr, " [L0 "); - for (j = ref_list[0] - 1; j >= 0; j--) { + for (int j = ref_list_len[0] - 1; j >= 0; j--) { fprintf(stderr, "%d ", ref_list_poc[0][j]); } fprintf(stderr, "] [L1 "); - for (j = 0; j < ref_list[1]; j++) { + for (int j = 0; j < ref_list_len[1]; j++) { fprintf(stderr, "%d ", ref_list_poc[1][j]); } fprintf(stderr, "]"); diff --git a/src/encoderstate.c b/src/encoderstate.c index 0e7530c2a..302818b14 100644 --- a/src/encoderstate.c +++ b/src/encoderstate.c @@ -629,7 +629,7 @@ static void encoder_state_encode(encoder_state_t * const main_state) { } -void kvz_encoder_ref_insertion_sort(int reflist[16], int length) { +static void encoder_ref_insertion_sort(int reflist[16], int length) { for (uint8_t i = 1; i < length; ++i) { const int16_t cur_poc = reflist[i]; @@ -641,35 +641,60 @@ void kvz_encoder_ref_insertion_sort(int reflist[16], int length) { reflist[j] = cur_poc; } } -static void encoder_state_ref_sort(encoder_state_t *state) { - int j, ref_list[2] = { 0, 0 }, ref_list_poc[2][16]; + +/** + * \brief Return reference picture lists. + * + * \param state main encoder state + * \param ref_list_len_out Returns the lengths of the reference lists. + * \param ref_list_poc_out Returns two lists of POCs of the reference pictures. + */ +void kvz_encoder_get_ref_lists(const encoder_state_t *const state, + int ref_list_len_out[2], + int ref_list_poc_out[2][16]) +{ + FILL_ARRAY(ref_list_len_out, 0, 2); // List all pocs of lists + int j = 0; for (j = 0; j < state->global->ref->used_size; j++) { if (state->global->ref->pocs[j] < state->global->poc) { - ref_list_poc[0][ref_list[0]] = state->global->ref->pocs[j]; - ref_list[0]++; + ref_list_poc_out[0][ref_list_len_out[0]] = state->global->ref->pocs[j]; + ref_list_len_out[0]++; } else { - ref_list_poc[1][ref_list[1]] = state->global->ref->pocs[j]; - ref_list[1]++; + ref_list_poc_out[1][ref_list_len_out[1]] = state->global->ref->pocs[j]; + ref_list_len_out[1]++; } } - kvz_encoder_ref_insertion_sort(ref_list_poc[0], ref_list[0]); - kvz_encoder_ref_insertion_sort(ref_list_poc[1], ref_list[1]); + // Fill the rest of ref_list_poc_out array with -1s. + for (; j < 16; j++) { + ref_list_poc_out[0][j] = -1; + ref_list_poc_out[1][j] = -1; + } - for (j = 0; j < state->global->ref->used_size; j++) { + encoder_ref_insertion_sort(ref_list_poc_out[0], ref_list_len_out[0]); + encoder_ref_insertion_sort(ref_list_poc_out[1], ref_list_len_out[1]); +} + +static void encoder_state_ref_sort(encoder_state_t *state) { + int ref_list_len[2]; + int ref_list_poc[2][16]; + + kvz_encoder_get_ref_lists(state, ref_list_len, ref_list_poc); + + for (int j = 0; j < state->global->ref->used_size; j++) { if (state->global->ref->pocs[j] < state->global->poc) { - for (int ref_idx = 0; ref_idx < ref_list[0]; ref_idx++) { + for (int ref_idx = 0; ref_idx < ref_list_len[0]; ref_idx++) { if (ref_list_poc[0][ref_idx] == state->global->ref->pocs[j]) { - state->global->refmap[j].idx = ref_list[0] - ref_idx - 1; + state->global->refmap[j].idx = ref_list_len[0] - ref_idx - 1; break; } } state->global->refmap[j].list = 1; } else { - for (int ref_idx = 0; ref_idx < ref_list[1]; ref_idx++) { + for (int ref_idx = 0; ref_idx < ref_list_len[1]; ref_idx++) { if (ref_list_poc[1][ref_idx] == state->global->ref->pocs[j]) { state->global->refmap[j].idx = ref_idx; break; diff --git a/src/encoderstate.h b/src/encoderstate.h index 02a7822f3..31f793b79 100644 --- a/src/encoderstate.h +++ b/src/encoderstate.h @@ -228,7 +228,9 @@ int kvz_encoder_state_match_children_of_previous_frame(encoder_state_t * const s coeff_scan_order_t kvz_get_scan_order(int8_t cu_type, int intra_mode, int depth); -void kvz_encoder_ref_insertion_sort(int reflist[16], int length); +void kvz_encoder_get_ref_lists(const encoder_state_t *const state, + int ref_list_len_out[2], + int ref_list_poc_out[2][16]); static const uint8_t g_group_idx[32] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, From 7edc1b0b1c8a0a351b70c78facb7b9775d4b3722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Wed, 9 Sep 2015 10:16:59 +0300 Subject: [PATCH 4/9] Add reference picture lists to kvz_frame_info. --- src/kvazaar.c | 1 + src/kvazaar.h | 13 +++++++++++++ src/kvazaar_version.h | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/kvazaar.c b/src/kvazaar.c index ea7f92a18..7d6c48b3c 100644 --- a/src/kvazaar.c +++ b/src/kvazaar.c @@ -118,6 +118,7 @@ static void set_frame_info(kvz_frame_info *const info, const encoder_state_t *co info->poc = state->global->poc, info->qp = state->global->QP; info->slice_type = state->global->slicetype; + kvz_encoder_get_ref_lists(state, info->ref_list_len, info->ref_list); } diff --git a/src/kvazaar.h b/src/kvazaar.h index f8b1a6fbd..d46db10ec 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -217,6 +217,19 @@ typedef struct kvz_frame_info { */ enum kvz_slice_type slice_type; + /** + * \brief Reference picture lists + * + * The first list contains the reference picture POCs that are less than the + * POC of this frame and the second one contains those that are greater. + */ + int ref_list[2][16]; + + /** + * \brief Lengths of the reference picture lists + */ + int ref_list_len[2]; + } kvz_frame_info; /** diff --git a/src/kvazaar_version.h b/src/kvazaar_version.h index fd9a628d6..8584c4aef 100644 --- a/src/kvazaar_version.h +++ b/src/kvazaar_version.h @@ -21,6 +21,6 @@ ****************************************************************************/ // KVZ_API_VERSION is incremented every time the public api changes. -#define KVZ_API_VERSION 5 +#define KVZ_API_VERSION 6 #endif // KVAZAAR_VERSION_H_ From afd0d3eee084ec8dbe24ea39c9d7d992a40ca915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Wed, 9 Sep 2015 10:28:45 +0300 Subject: [PATCH 5/9] Remove encoderstate dependency from cli module. Changes function print_frame_info to use a kvz_frame_info struct to get the data to be printed. --- src/cli.c | 27 ++++++++++++--------------- src/cli.h | 4 +++- src/encmain.c | 5 +++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/cli.c b/src/cli.c index 3a590df6b..689f70a75 100644 --- a/src/cli.c +++ b/src/cli.c @@ -24,7 +24,6 @@ */ #include "cli.h" -#include "encoderstate.h" #include #include @@ -356,28 +355,26 @@ void print_help(void) } -void print_frame_info(encoder_state_t *state, double frame_psnr[3]) +void print_frame_info(const kvz_frame_info *const info, + const double frame_psnr[3], + const uint32_t bytes) { fprintf(stderr, "POC %4d QP %2d (%c-frame) %10d bits PSNR: %2.4f %2.4f %2.4f", - state->global->poc, - state->global->QP, - "BPI"[state->global->slicetype % 3], state->stats_bitstream_length << 3, + info->poc, + info->qp, + "BPI"[info->slice_type % 3], + bytes << 3, frame_psnr[0], frame_psnr[1], frame_psnr[2]); - if (state->global->slicetype != KVZ_SLICE_I) { + if (info->slice_type != KVZ_SLICE_I) { // Print reference picture lists - int ref_list_len[2]; - int ref_list_poc[2][16]; - - kvz_encoder_get_ref_lists(state, ref_list_len, ref_list_poc); - fprintf(stderr, " [L0 "); - for (int j = ref_list_len[0] - 1; j >= 0; j--) { - fprintf(stderr, "%d ", ref_list_poc[0][j]); + for (int j = info->ref_list_len[0] - 1; j >= 0; j--) { + fprintf(stderr, "%d ", info->ref_list[0][j]); } fprintf(stderr, "] [L1 "); - for (int j = 0; j < ref_list_len[1]; j++) { - fprintf(stderr, "%d ", ref_list_poc[1][j]); + for (int j = 0; j < info->ref_list_len[1]; j++) { + fprintf(stderr, "%d ", info->ref_list[1][j]); } fprintf(stderr, "]"); } diff --git a/src/cli.h b/src/cli.h index 190fe73fd..f2dc82a7a 100644 --- a/src/cli.h +++ b/src/cli.h @@ -49,6 +49,8 @@ void cmdline_opts_free(const kvz_api *api, cmdline_opts_t *opts); void print_version(void); void print_help(void); -void print_frame_info(encoder_state_t *state, double frame_psnr[3]); +void print_frame_info(const kvz_frame_info *const info, + const double frame_psnr[3], + const uint32_t bytes); #endif diff --git a/src/encmain.c b/src/encmain.c index 58356b99e..170be23c8 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -212,7 +212,8 @@ int main(int argc, char *argv[]) kvz_data_chunk* chunks_out = NULL; kvz_picture *img_rec = NULL; uint32_t len_out = 0; - if (!api->encoder_encode(enc, img_in, &chunks_out, &len_out, &img_rec, NULL)) { + kvz_frame_info info_out; + if (!api->encoder_encode(enc, img_in, &chunks_out, &len_out, &img_rec, &info_out)) { fprintf(stderr, "Failed to encode image.\n"); api->picture_free(img_in); goto exit_failure; @@ -269,7 +270,7 @@ int main(int argc, char *argv[]) psnr_sum[1] += frame_psnr[1]; psnr_sum[2] += frame_psnr[2]; - print_frame_info(state, frame_psnr); + print_frame_info(&info_out, frame_psnr, len_out); } api->picture_free(img_in); From efd361ee8ed424e788c9a13905671341ececef47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Wed, 9 Sep 2015 11:21:39 +0300 Subject: [PATCH 6/9] Return the original picture from encoder_encode. --- src/encmain.c | 2 +- src/kvazaar.c | 3 +++ src/kvazaar.h | 15 +++++++++------ src/kvazaar_version.h | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/encmain.c b/src/encmain.c index 170be23c8..2ee58c267 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -213,7 +213,7 @@ int main(int argc, char *argv[]) kvz_picture *img_rec = NULL; uint32_t len_out = 0; kvz_frame_info info_out; - if (!api->encoder_encode(enc, img_in, &chunks_out, &len_out, &img_rec, &info_out)) { + if (!api->encoder_encode(enc, img_in, &chunks_out, &len_out, &img_rec, NULL, &info_out)) { fprintf(stderr, "Failed to encode image.\n"); api->picture_free(img_in); goto exit_failure; diff --git a/src/kvazaar.c b/src/kvazaar.c index 7d6c48b3c..59d24d05f 100644 --- a/src/kvazaar.c +++ b/src/kvazaar.c @@ -127,11 +127,13 @@ static int kvazaar_encode(kvz_encoder *enc, kvz_data_chunk **data_out, uint32_t *len_out, kvz_picture **pic_out, + kvz_picture **src_out, kvz_frame_info *info_out) { if (data_out) *data_out = NULL; if (len_out) *len_out = 0; if (pic_out) *pic_out = NULL; + if (src_out) *src_out = NULL; encoder_state_t *state = &enc->states[enc->cur_state_num]; @@ -174,6 +176,7 @@ static int kvazaar_encode(kvz_encoder *enc, if (len_out) *len_out = kvz_bitstream_tell(&output_state->stream) / 8; if (data_out) *data_out = kvz_bitstream_take_chunks(&output_state->stream); if (pic_out) *pic_out = kvz_image_copy_ref(output_state->tile->frame->rec); + if (src_out) *src_out = kvz_image_copy_ref(output_state->tile->frame->source); if (info_out) set_frame_info(info_out, output_state); output_state->frame_done = 1; diff --git a/src/kvazaar.h b/src/kvazaar.h index d46db10ec..a0939d24d 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -344,9 +344,9 @@ typedef struct kvz_api { * \brief Encode one frame. * * Add pic_in to the encoding pipeline. If an encoded frame is ready, return - * the bitstream, length of the bitstream, the reconstructed frame and frame - * info in data_out, len_out, pic_out and info_out, respectively. Otherwise, - * set the output parameters to NULL. + * the bitstream, length of the bitstream, the reconstructed frame, the + * original frame and frame info in data_out, len_out, pic_out, src_out and + * info_out, respectively. Otherwise, set the output parameters to NULL. * * After passing all of the input frames, the caller should keep calling this * function with pic_in set to NULL, until no more data is returned in the @@ -354,17 +354,19 @@ typedef struct kvz_api { * * The caller must not modify pic_in after passing it to this function. * - * If pic_out and data_out are set to non-NULL values, the caller is - * responsible for calling picture_free and chunk_free on them. + * If data_out, pic_out and src_out are set to non-NULL values, the caller is + * responsible for calling chunk_free and picture_free on them. * * A null pointer may be passed in place of any of the parameters data_out, - * len_out, pic_out or info_out to skip returning the corresponding value. + * len_out, pic_out, src_out or info_out to skip returning the corresponding + * value. * * \param encoder encoder * \param pic_in input frame or NULL * \param data_out Returns the encoded data. * \param len_out Returns number of bytes in the encoded data. * \param pic_out Returns the reconstructed picture. + * \param src_out Returns the original picture. * \param info_out Returns information about the encoded picture. * \return 1 on success, 0 on error. */ @@ -373,6 +375,7 @@ typedef struct kvz_api { kvz_data_chunk **data_out, uint32_t *len_out, kvz_picture **pic_out, + kvz_picture **src_out, kvz_frame_info *info_out); } kvz_api; diff --git a/src/kvazaar_version.h b/src/kvazaar_version.h index 8584c4aef..9f4d2453c 100644 --- a/src/kvazaar_version.h +++ b/src/kvazaar_version.h @@ -21,6 +21,6 @@ ****************************************************************************/ // KVZ_API_VERSION is incremented every time the public api changes. -#define KVZ_API_VERSION 6 +#define KVZ_API_VERSION 7 #endif // KVAZAAR_VERSION_H_ From 4e5c7fe6e8da313bac559b2fd3d257b634c5c102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Wed, 9 Sep 2015 11:32:29 +0300 Subject: [PATCH 7/9] Remove function kvz_encoder_compute_stats. Changes main function to compute frame PSNR by calling kvz_videoframe_compute_psnr directly with the source and reconstructed pictures returned from encoder_encode. --- src/encmain.c | 21 +++++++++++---------- src/encoderstate.c | 6 ------ src/encoderstate.h | 1 - src/videoframe.c | 24 ++++++++++++++++-------- src/videoframe.h | 4 +++- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/encmain.c b/src/encmain.c index 2ee58c267..08177633e 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -40,10 +40,9 @@ #include "checkpoint.h" #include "global.h" -#include "config.h" #include "threadqueue.h" #include "encoder.h" -#include "encoderstate.h" +#include "videoframe.h" #include "cli.h" #include "yuv_io.h" @@ -211,9 +210,16 @@ int main(int argc, char *argv[]) kvz_data_chunk* chunks_out = NULL; kvz_picture *img_rec = NULL; + kvz_picture *img_src = NULL; uint32_t len_out = 0; kvz_frame_info info_out; - if (!api->encoder_encode(enc, img_in, &chunks_out, &len_out, &img_rec, NULL, &info_out)) { + if (!api->encoder_encode(enc, + img_in, + &chunks_out, + &len_out, + &img_rec, + &img_src, + &info_out)) { fprintf(stderr, "Failed to encode image.\n"); api->picture_free(img_in); goto exit_failure; @@ -245,14 +251,8 @@ int main(int argc, char *argv[]) // Compute and print stats. - // Number of the state that was finished is one less than - // enc->out_state_num. - encoder_state_t *state = &enc->states[ - (enc->out_state_num + enc->num_encoder_states - 1) % - enc->num_encoder_states - ]; double frame_psnr[3] = { 0.0, 0.0, 0.0 }; - kvz_encoder_compute_stats(state, frame_psnr); + kvz_videoframe_compute_psnr(img_src, img_rec, frame_psnr); if (recout) { // Since chunks_out was not NULL, img_rec should have been set. @@ -276,6 +276,7 @@ int main(int argc, char *argv[]) api->picture_free(img_in); api->chunk_free(chunks_out); api->picture_free(img_rec); + api->picture_free(img_src); } GET_TIME(&encoding_end_real_time); diff --git a/src/encoderstate.c b/src/encoderstate.c index 302818b14..5b5349f2b 100644 --- a/src/encoderstate.c +++ b/src/encoderstate.c @@ -889,12 +889,6 @@ void kvz_encode_one_frame(encoder_state_t * const state) } -void kvz_encoder_compute_stats(encoder_state_t *state, double frame_psnr[3]) -{ - assert(state->frame_done); - kvz_videoframe_compute_psnr(state->tile->frame, frame_psnr); -} - void kvz_encoder_next_frame(encoder_state_t *state) { const encoder_control_t * const encoder = state->encoder_control; diff --git a/src/encoderstate.h b/src/encoderstate.h index 31f793b79..edc7b33f7 100644 --- a/src/encoderstate.h +++ b/src/encoderstate.h @@ -206,7 +206,6 @@ typedef struct encoder_state_t { void kvz_encode_one_frame(encoder_state_t *state); -void kvz_encoder_compute_stats(encoder_state_t *state, double psnr[3]); void kvz_encoder_next_frame(encoder_state_t *state); diff --git a/src/videoframe.c b/src/videoframe.c index ac569ab9e..b69d78848 100644 --- a/src/videoframe.c +++ b/src/videoframe.c @@ -118,23 +118,31 @@ cu_info_t* kvz_videoframe_get_cu(videoframe_t * const frame, const unsigned int /** * \brief Calculates image PSNR value + * + * \param src source picture + * \param rec reconstructed picture + * \prama psnr returns the PSNR */ -void kvz_videoframe_compute_psnr(const videoframe_t * const frame, double psnr[NUM_COLORS]) +void kvz_videoframe_compute_psnr(const kvz_picture *const src, + const kvz_picture *const rec, + double psnr[NUM_COLORS]) { - int32_t pixels = frame->width * frame->height; - int32_t i, c; - - for (c = 0; c < NUM_COLORS; ++c) { + assert(src->width == rec->width); + assert(src->height == rec->height); + + int32_t pixels = src->width * src->height; + + for (int32_t c = 0; c < NUM_COLORS; ++c) { int32_t num_pixels = pixels; if (c != COLOR_Y) { num_pixels >>= 2; } psnr[c] = 0; - for (i = 0; i < num_pixels; ++i) { - const int32_t error = frame->source->data[c][i] - frame->rec->data[c][i]; + for (int32_t i = 0; i < num_pixels; ++i) { + const int32_t error = src->data[c][i] - rec->data[c][i]; psnr[c] += error * error; } - + // Avoid division by zero if (psnr[c] == 0) psnr[c] = 99.0; psnr[c] = 10 * log10((num_pixels * PSNRMAX) / ((double)psnr[c]));; diff --git a/src/videoframe.h b/src/videoframe.h index caa0303de..c5ed17376 100644 --- a/src/videoframe.h +++ b/src/videoframe.h @@ -62,7 +62,9 @@ void kvz_videoframe_set_poc(videoframe_t * frame, int32_t poc); const cu_info_t* kvz_videoframe_get_cu_const(const videoframe_t * const frame, unsigned int x_in_scu, unsigned int y_in_scu); cu_info_t* kvz_videoframe_get_cu(videoframe_t * const frame, const unsigned int x_in_scu, const unsigned int y_in_scu); -void kvz_videoframe_compute_psnr(const videoframe_t * const frame, double psnr[NUM_COLORS]); +void kvz_videoframe_compute_psnr(const kvz_picture *const src, + const kvz_picture *const rec, + double psnr[NUM_COLORS]); #endif From 1c898a2f4a6f9eaec93a91fd0bfeca1090cc0132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Tue, 15 Sep 2015 10:19:31 +0300 Subject: [PATCH 8/9] Prefix NAL unit type enum constants with KVZ_. --- src/encoder_state-bitstream.c | 26 ++++++------- src/encoderstate.c | 4 +- src/nal.h | 72 ++++++++++++++++++++--------------- 3 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/encoder_state-bitstream.c b/src/encoder_state-bitstream.c index 188d8c391..9307bc381 100644 --- a/src/encoder_state-bitstream.c +++ b/src/encoder_state-bitstream.c @@ -31,7 +31,7 @@ static void encoder_state_write_bitstream_aud(encoder_state_t * const state) { bitstream_t * const stream = &state->stream; - kvz_nal_write(stream, AUD_NUT, 0, 1); + kvz_nal_write(stream, KVZ_NAL_AUD_NUT, 0, 1); uint8_t pic_type = state->global->slicetype == KVZ_SLICE_I ? 0 : state->global->slicetype == KVZ_SLICE_P ? 1 @@ -654,8 +654,8 @@ void kvz_encoder_state_write_bitstream_slice_header(encoder_state_t * const stat #endif WRITE_U(stream, (state->slice->start_in_rs == 0), 1, "first_slice_segment_in_pic_flag"); - if (state->global->pictype >= NAL_BLA_W_LP - && state->global->pictype <= NAL_RSV_IRAP_VCL23) { + if (state->global->pictype >= KVZ_NAL_BLA_W_LP + && state->global->pictype <= KVZ_NAL_RSV_IRAP_VCL23) { WRITE_U(stream, 1, 1, "no_output_of_prior_pics_flag"); } @@ -674,8 +674,8 @@ void kvz_encoder_state_write_bitstream_slice_header(encoder_state_t * const stat //WRITE_U(stream, 1, 1, "pic_output_flag"); //end if //if( IdrPicFlag ) <- nal_unit_type == 5 - if (state->global->pictype != NAL_IDR_W_RADL - && state->global->pictype != NAL_IDR_N_LP) { + if (state->global->pictype != KVZ_NAL_IDR_W_RADL + && state->global->pictype != KVZ_NAL_IDR_N_LP) { int last_poc = 0; int poc_shift = 0; @@ -790,7 +790,7 @@ static void add_checksum(encoder_state_t * const state) uint32_t checksum_val; unsigned int i; - kvz_nal_write(stream, NAL_SUFFIT_SEI_NUT, 0, 0); + kvz_nal_write(stream, KVZ_NAL_SUFFIX_SEI_NUT, 0, 0); kvz_image_checksum(frame->rec, checksum, state->encoder_control->bitdepth); @@ -845,21 +845,21 @@ static void encoder_state_write_bitstream_main(encoder_state_t * const state) first_nal_in_au = false; // Video Parameter Set (VPS) - kvz_nal_write(stream, NAL_VPS_NUT, 0, 1); + kvz_nal_write(stream, KVZ_NAL_VPS_NUT, 0, 1); encoder_state_write_bitstream_vid_parameter_set(state); // Sequence Parameter Set (SPS) - kvz_nal_write(stream, NAL_SPS_NUT, 0, 1); + kvz_nal_write(stream, KVZ_NAL_SPS_NUT, 0, 1); encoder_state_write_bitstream_seq_parameter_set(state); // Picture Parameter Set (PPS) - kvz_nal_write(stream, NAL_PPS_NUT, 0, 1); + kvz_nal_write(stream, KVZ_NAL_PPS_NUT, 0, 1); encoder_state_write_bitstream_pic_parameter_set(state); } // Send Kvazaar version information only in the first frame. if (state->global->frame == 0 && state->encoder_control->cfg->add_encoder_info) { - kvz_nal_write(stream, PREFIX_SEI_NUT, 0, first_nal_in_au); + kvz_nal_write(stream, KVZ_NAL_PREFIX_SEI_NUT, 0, first_nal_in_au); encoder_state_write_bitstream_prefix_sei_version(state); // spec:sei_rbsp() rbsp_trailing_bits @@ -870,11 +870,11 @@ static void encoder_state_write_bitstream_main(encoder_state_t * const state) if (state->encoder_control->vui.frame_field_info_present_flag){ // These should be optional, needed for earlier versions // of HM decoder to accept bitstream - //kvz_nal_write(stream, PREFIX_SEI_NUT, 0, 0); + //kvz_nal_write(stream, KVZ_NAL_PREFIX_SEI_NUT, 0, 0); //encoder_state_write_active_parameter_sets_sei_message(state); //kvz_bitstream_rbsp_trailing_bits(stream); - kvz_nal_write(stream, PREFIX_SEI_NUT, 0, first_nal_in_au); + kvz_nal_write(stream, KVZ_NAL_PREFIX_SEI_NUT, 0, first_nal_in_au); encoder_state_write_picture_timing_sei_message(state); // spec:sei_rbsp() rbsp_trailing_bits @@ -882,7 +882,7 @@ static void encoder_state_write_bitstream_main(encoder_state_t * const state) } { - uint8_t nal_type = (state->global->is_idr_frame ? NAL_IDR_W_RADL : NAL_TRAIL_R); + uint8_t nal_type = (state->global->is_idr_frame ? KVZ_NAL_IDR_W_RADL : KVZ_NAL_TRAIL_R); kvz_nal_write(stream, nal_type, 0, first_nal_in_au); } diff --git a/src/encoderstate.c b/src/encoderstate.c index 5b5349f2b..01ac41680 100644 --- a/src/encoderstate.c +++ b/src/encoderstate.c @@ -784,10 +784,10 @@ static void encoder_state_new_frame(encoder_state_t * const state) { if (state->global->is_idr_frame) { encoder_state_reset_poc(state); state->global->slicetype = KVZ_SLICE_I; - state->global->pictype = NAL_IDR_W_RADL; + state->global->pictype = KVZ_NAL_IDR_W_RADL; } else { state->global->slicetype = encoder->cfg->intra_period==1 ? KVZ_SLICE_I : (state->encoder_control->cfg->gop_len?KVZ_SLICE_B:KVZ_SLICE_P); - state->global->pictype = NAL_TRAIL_R; + state->global->pictype = KVZ_NAL_TRAIL_R; if (state->encoder_control->cfg->gop_len) { if (encoder->cfg->intra_period > 1 && (state->global->poc % encoder->cfg->intra_period) == 0) { state->global->slicetype = KVZ_SLICE_I; diff --git a/src/nal.h b/src/nal.h index 7db5d3e27..d2e334a95 100644 --- a/src/nal.h +++ b/src/nal.h @@ -40,51 +40,61 @@ * \brief NAL unit type codes. * * These are the nal_unit_type codes from Table 7-1 ITU-T H.265 v1.0. - * The type codes have been prefixed with "NAL_". */ -enum { - NAL_TRAIL_N = 0, - NAL_TRAIL_R = 1, +enum kvz_nal_unit_type { - NAL_TSA_N = 2, - NAL_TSA_R = 3, + // Trailing pictures - NAL_STSA_N = 4, - NAL_STSA_R = 5, + KVZ_NAL_TRAIL_N = 0, + KVZ_NAL_TRAIL_R = 1, - NAL_RADL_N = 6, - NAL_RADL_R = 7, + KVZ_NAL_TSA_N = 2, + KVZ_NAL_TSA_R = 3, - NAL_RASL_N = 8, - NAL_RASL_R = 9, + KVZ_NAL_STSA_N = 4, + KVZ_NAL_STSA_R = 5, - // Reserved RSV_VCL_ N/R 10-15 + // Leading pictures - NAL_BLA_W_LP = 16, - NAL_BLA_W_RADL = 17, - NAL_BLA_N_LP = 18, + KVZ_NAL_RADL_N = 6, + KVZ_NAL_RADL_R = 7, - NAL_IDR_W_RADL = 19, - NAL_IDR_N_LP = 20, + KVZ_NAL_RASL_N = 8, + KVZ_NAL_RASL_R = 9, - NAL_CRA_NUT = 21, + // Reserved non-IRAP RSV_VCL_N/R 10-15 - // Reserved RSV_IRAP_VCL 22-23 - NAL_RSV_IRAP_VCL23 = 23, + // Intra random access point pictures - // Reserved RSV_VCL 24-31 + KVZ_NAL_BLA_W_LP = 16, + KVZ_NAL_BLA_W_RADL = 17, + KVZ_NAL_BLA_N_LP = 18, - NAL_VPS_NUT = 32, - NAL_SPS_NUT = 33, - NAL_PPS_NUT = 34, + KVZ_NAL_IDR_W_RADL = 19, + KVZ_NAL_IDR_N_LP = 20, - AUD_NUT = 35, - EOS_NUT = 36, - EOB_NUT = 37, - FD_NUT = 38, + KVZ_NAL_CRA_NUT = 21, - PREFIX_SEI_NUT = 39, - NAL_SUFFIT_SEI_NUT = 40, + // Reserved IRAP + + KVZ_NAL_RSV_IRAP_VCL22 = 22, + KVZ_NAL_RSV_IRAP_VCL23 = 23, + + // Reserved non-IRAP RSV_VCL 24-32 + + // non-VCL + + KVZ_NAL_VPS_NUT = 32, + KVZ_NAL_SPS_NUT = 33, + KVZ_NAL_PPS_NUT = 34, + + KVZ_NAL_AUD_NUT = 35, + KVZ_NAL_EOS_NUT = 36, + KVZ_NAL_EOB_NUT = 37, + KVZ_NAL_FD_NUT = 38, + + KVZ_NAL_PREFIX_SEI_NUT = 39, + KVZ_NAL_SUFFIX_SEI_NUT = 40, // Reserved RSV_NVCL 41-47 // Unspecified UNSPEC 48-63 From 8f404a3b6f8a8a619f412ae84578e69d19807eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Tue, 15 Sep 2015 10:29:10 +0300 Subject: [PATCH 9/9] Add NAL unit type to frame_info. --- src/kvazaar.c | 1 + src/kvazaar.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/nal.h | 68 -------------------------------------------------- 3 files changed, 70 insertions(+), 68 deletions(-) diff --git a/src/kvazaar.c b/src/kvazaar.c index 59d24d05f..651f934ad 100644 --- a/src/kvazaar.c +++ b/src/kvazaar.c @@ -117,6 +117,7 @@ static void set_frame_info(kvz_frame_info *const info, const encoder_state_t *co { info->poc = state->global->poc, info->qp = state->global->QP; + info->nal_unit_type = state->global->pictype; info->slice_type = state->global->slicetype; kvz_encoder_get_ref_lists(state, info->ref_list_len, info->ref_list); } diff --git a/src/kvazaar.h b/src/kvazaar.h index a0939d24d..117918618 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -191,6 +191,70 @@ typedef struct kvz_picture { int64_t dts; //!< \brief Decompression timestamp. } kvz_picture; +/** + * \brief NAL unit type codes. + * + * These are the nal_unit_type codes from Table 7-1 ITU-T H.265 v1.0. + */ +enum kvz_nal_unit_type { + + // Trailing pictures + + KVZ_NAL_TRAIL_N = 0, + KVZ_NAL_TRAIL_R = 1, + + KVZ_NAL_TSA_N = 2, + KVZ_NAL_TSA_R = 3, + + KVZ_NAL_STSA_N = 4, + KVZ_NAL_STSA_R = 5, + + // Leading pictures + + KVZ_NAL_RADL_N = 6, + KVZ_NAL_RADL_R = 7, + + KVZ_NAL_RASL_N = 8, + KVZ_NAL_RASL_R = 9, + + // Reserved non-IRAP RSV_VCL_N/R 10-15 + + // Intra random access point pictures + + KVZ_NAL_BLA_W_LP = 16, + KVZ_NAL_BLA_W_RADL = 17, + KVZ_NAL_BLA_N_LP = 18, + + KVZ_NAL_IDR_W_RADL = 19, + KVZ_NAL_IDR_N_LP = 20, + + KVZ_NAL_CRA_NUT = 21, + + // Reserved IRAP + + KVZ_NAL_RSV_IRAP_VCL22 = 22, + KVZ_NAL_RSV_IRAP_VCL23 = 23, + + // Reserved non-IRAP RSV_VCL 24-32 + + // non-VCL + + KVZ_NAL_VPS_NUT = 32, + KVZ_NAL_SPS_NUT = 33, + KVZ_NAL_PPS_NUT = 34, + + KVZ_NAL_AUD_NUT = 35, + KVZ_NAL_EOS_NUT = 36, + KVZ_NAL_EOB_NUT = 37, + KVZ_NAL_FD_NUT = 38, + + KVZ_NAL_PREFIX_SEI_NUT = 39, + KVZ_NAL_SUFFIX_SEI_NUT = 40, + + // Reserved RSV_NVCL 41-47 + // Unspecified UNSPEC 48-63 +}; + enum kvz_slice_type { KVZ_SLICE_B = 0, KVZ_SLICE_P = 1, @@ -212,6 +276,11 @@ typedef struct kvz_frame_info { */ int8_t qp; + /** + * \brief Type of the NAL VCL unit + */ + enum kvz_nal_unit_type nal_unit_type; + /** * \brief Type of the slice */ diff --git a/src/nal.h b/src/nal.h index d2e334a95..5f94645c8 100644 --- a/src/nal.h +++ b/src/nal.h @@ -32,74 +32,6 @@ #include "image.h" #include "bitstream.h" - -////////////////////////////////////////////////////////////////////////// -// TYPES - -/** - * \brief NAL unit type codes. - * - * These are the nal_unit_type codes from Table 7-1 ITU-T H.265 v1.0. - */ -enum kvz_nal_unit_type { - - // Trailing pictures - - KVZ_NAL_TRAIL_N = 0, - KVZ_NAL_TRAIL_R = 1, - - KVZ_NAL_TSA_N = 2, - KVZ_NAL_TSA_R = 3, - - KVZ_NAL_STSA_N = 4, - KVZ_NAL_STSA_R = 5, - - // Leading pictures - - KVZ_NAL_RADL_N = 6, - KVZ_NAL_RADL_R = 7, - - KVZ_NAL_RASL_N = 8, - KVZ_NAL_RASL_R = 9, - - // Reserved non-IRAP RSV_VCL_N/R 10-15 - - // Intra random access point pictures - - KVZ_NAL_BLA_W_LP = 16, - KVZ_NAL_BLA_W_RADL = 17, - KVZ_NAL_BLA_N_LP = 18, - - KVZ_NAL_IDR_W_RADL = 19, - KVZ_NAL_IDR_N_LP = 20, - - KVZ_NAL_CRA_NUT = 21, - - // Reserved IRAP - - KVZ_NAL_RSV_IRAP_VCL22 = 22, - KVZ_NAL_RSV_IRAP_VCL23 = 23, - - // Reserved non-IRAP RSV_VCL 24-32 - - // non-VCL - - KVZ_NAL_VPS_NUT = 32, - KVZ_NAL_SPS_NUT = 33, - KVZ_NAL_PPS_NUT = 34, - - KVZ_NAL_AUD_NUT = 35, - KVZ_NAL_EOS_NUT = 36, - KVZ_NAL_EOB_NUT = 37, - KVZ_NAL_FD_NUT = 38, - - KVZ_NAL_PREFIX_SEI_NUT = 39, - KVZ_NAL_SUFFIX_SEI_NUT = 40, - - // Reserved RSV_NVCL 41-47 - // Unspecified UNSPEC 48-63 -}; - #define SEI_HASH_MAX_LENGTH 4 //////////////////////////////////////////////////////////////////////////