diff options
-rw-r--r-- | encode2.c | 61 | ||||
-rw-r--r-- | hevc.c | 32 | ||||
-rw-r--r-- | hevc.h | 12 |
3 files changed, 88 insertions, 17 deletions
@@ -50,8 +50,10 @@ struct EncodeContext { VASurfaceID input_surface_id; struct GpuFrame* gpu_frame; - VASurfaceID recon_surface_ids[4]; + VASurfaceID recon_surface_ids[2]; VABufferID output_buffer_id; + + size_t frame_counter; }; static const char* VaErrorString(VAStatus error) { @@ -360,6 +362,7 @@ struct EncodeContext* EncodeContextCreate(struct GpuContext* gpu_context, // TODO(mburakov): Check entry points? #if 1 + // TODO(mburakov): AMD only supports CQP and no packed headers. VAConfigAttrib config_attribs[] = { {.type = VAConfigAttribRTFormat, .value = VA_RT_FORMAT_YUV420}, {.type = VAConfigAttribRateControl, .value = VA_RC_ICQ}, @@ -520,15 +523,17 @@ static bool DrainBuffers(int fd, struct iovec* iovec, int count) { bool EncodeContextEncodeFrame(struct EncodeContext* encode_context, int fd) { VABufferID buffers[12]; VABufferID* buffer_ptr = buffers; - if (!UploadBuffer(encode_context, VAEncSequenceParameterBufferType, - sizeof(encode_context->seq), &encode_context->seq, - &buffer_ptr)) { + + bool idr = + encode_context->frame_counter % encode_context->seq.intra_idr_period == 0; + if (idr && !UploadBuffer(encode_context, VAEncSequenceParameterBufferType, + sizeof(encode_context->seq), &encode_context->seq, + &buffer_ptr)) { LOG("Failed to upload sequence parameter buffer"); return false; } bool result = false; - bool idr = true; if (idr) { if (!UploadMiscBuffer(encode_context, VAEncMiscParameterTypeRateControl, sizeof(encode_context->rc), &encode_context->rc, @@ -546,8 +551,12 @@ bool EncodeContextEncodeFrame(struct EncodeContext* encode_context, int fd) { // TODO(mburakov): Implement this!!! encode_context->pic.decoded_curr_pic = (VAPictureHEVC){ - .picture_id = encode_context->recon_surface_ids[0], // recon - .pic_order_cnt = 0, // pic->display_order - hpic->last_idr_frame + .picture_id = + encode_context + ->recon_surface_ids[encode_context->frame_counter % + LENGTH(encode_context->recon_surface_ids)], + .pic_order_cnt = (int32_t)(encode_context->frame_counter % + encode_context->seq.intra_idr_period), .flags = 0, }; for (size_t i = 0; i < LENGTH(encode_context->pic.reference_frames); i++) { @@ -556,10 +565,20 @@ bool EncodeContextEncodeFrame(struct EncodeContext* encode_context, int fd) { .flags = VA_PICTURE_HEVC_INVALID, }; } + if (!idr) { + encode_context->pic.reference_frames[0] = (VAPictureHEVC){ + .picture_id = + encode_context + ->recon_surface_ids[(encode_context->frame_counter - 1) % + LENGTH(encode_context->recon_surface_ids)], + .pic_order_cnt = (int32_t)((encode_context->frame_counter - 1) % + encode_context->seq.intra_idr_period), + }; + } encode_context->pic.coded_buf = encode_context->output_buffer_id; - encode_context->pic.nal_unit_type = IDR_W_RADL; - encode_context->pic.pic_fields.bits.idr_pic_flag = 1; - encode_context->pic.pic_fields.bits.coding_type = 1; + encode_context->pic.nal_unit_type = idr ? IDR_W_RADL : TRAIL_R; + encode_context->pic.pic_fields.bits.idr_pic_flag = idr; + encode_context->pic.pic_fields.bits.coding_type = idr ? 1 : 2; encode_context->pic.pic_fields.bits.reference_pic_flag = 1; if (!UploadBuffer(encode_context, VAEncPictureParameterBufferType, sizeof(encode_context->pic), &encode_context->pic, @@ -718,7 +737,7 @@ case PICTURE_TYPE_P: .slice_segment_address = 0, // calculated .num_ctu_in_slice = block_size, - .slice_type = I, // calculated + .slice_type = idr ? I : P, // calculated .slice_pic_parameter_set_id = encode_context->pic.slice_pic_parameter_set_id, @@ -780,6 +799,16 @@ case PICTURE_TYPE_P: slice.ref_pic_list1[i].picture_id = VA_INVALID_ID; slice.ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID; } + if (!idr) { + slice.ref_pic_list0[0] = (VAPictureHEVC){ + .picture_id = + encode_context + ->recon_surface_ids[(encode_context->frame_counter - 1) % + LENGTH(encode_context->recon_surface_ids)], + .pic_order_cnt = (int32_t)((encode_context->frame_counter - 1) % + encode_context->seq.intra_idr_period), + }; + } // TODO(mburakov): ffmpeg assign reference frame for non-I-frames here. @@ -790,6 +819,8 @@ case PICTURE_TYPE_P: }; const struct MoreSliceParamerters msp = { .first_slice_segment_in_pic_flag = 1, + .num_negative_pics = 1, + .negative_pics = &(struct NegativePics){0, 1}, }; PackSliceSegmentHeaderNalUnit(&bitstream, &encode_context->seq, &encode_context->pic, &slice, &msp); @@ -843,6 +874,10 @@ case PICTURE_TYPE_P: LOG("Failed to map va buffer (%s)", VaErrorString(status)); goto rollback_buffers; } + if (segment->next != NULL) { + LOG("Next segment non-null!"); + abort(); + } struct iovec iovec[] = { {.iov_base = &segment->size, .iov_len = sizeof(segment->size)}, @@ -853,8 +888,8 @@ case PICTURE_TYPE_P: goto rollback_segment; } - LOG("GOT FRAME!"); - result = false; + encode_context->frame_counter++; + result = true; rollback_segment: vaUnmapBuffer(encode_context->va_display, encode_context->output_buffer_id); @@ -97,6 +97,7 @@ static const bool chroma_qp_offset_list_enabled_flag = 0; static const bool deblocking_filter_override_enabled_flag = 0; static const bool deblocking_filter_override_flag = 0; static const uint32_t num_entry_point_offsets = 0; +static const bool inter_ref_pic_set_prediction_flag = 0; // 7.3.1.2 NAL unit header syntax static void PackNalUnitHeader(struct Bitstream* bitstream, @@ -552,6 +553,30 @@ void PackPicParameterSetNalUnit(struct Bitstream* bitstream, BitstreamInflate(bitstream, &pps_rbsp); } +// 7.3.7 Short-term reference picture set syntax +static void PackStRefPicSet(struct Bitstream* bitstream, uint32_t stRpsIdx, + const struct MoreSliceParamerters* msp) { + if (stRpsIdx != 0) + BitstreamAppend(bitstream, 1, inter_ref_pic_set_prediction_flag); + if (inter_ref_pic_set_prediction_flag) { + // TODO(mburakov): Implement this! + abort(); + } else { + BitstreamAppendUE(bitstream, msp->num_negative_pics); + BitstreamAppendUE(bitstream, msp->num_positive_pics); + for (uint32_t i = 0; i < msp->num_negative_pics; i++) { + BitstreamAppendUE(bitstream, msp->negative_pics[i].delta_poc_s0_minus1); + BitstreamAppend(bitstream, 1, + msp->negative_pics[i].used_by_curr_pic_s0_flag); + } + for (uint32_t i = 0; i < msp->num_positive_pics; i++) { + BitstreamAppendUE(bitstream, msp->positive_pics[i].delta_poc_s1_minus1); + BitstreamAppend(bitstream, 1, + msp->positive_pics[i].used_by_curr_pic_s1_flag); + } + } +} + // 7.3.6.1 General slice segment header syntax void PackSliceSegmentHeaderNalUnit(struct Bitstream* bitstream, const VAEncSequenceParameterBufferHEVC* seq, @@ -603,10 +628,9 @@ void PackSliceSegmentHeaderNalUnit(struct Bitstream* bitstream, BitstreamAppend(&slice_rbsp, log2_max_pic_order_cnt_lsb_minus4 + 4, slice_pic_order_cnt_lsb); BitstreamAppend(&slice_rbsp, 1, short_term_ref_pic_set_sps_flag); - if (!short_term_ref_pic_set_sps_flag) { - // TODO(mburakov): Implement this!!! - abort(); - } else if (num_short_term_ref_pic_sets > 0) { + if (!short_term_ref_pic_set_sps_flag) + PackStRefPicSet(&slice_rbsp, num_short_term_ref_pic_sets, msp); + else if (num_short_term_ref_pic_sets > 1) { // TODO(mburakov): Implement this!!! abort(); } @@ -23,6 +23,7 @@ // Table 7-1 enum NalUnitType { + TRAIL_R = 1, BLA_W_LP = 16, IDR_W_RADL = 19, IDR_N_LP = 20, @@ -64,6 +65,17 @@ struct MoreSeqParameters { struct MoreSliceParamerters { bool first_slice_segment_in_pic_flag; + // TODO(mburakov): Deduce from picture parameter buffer? + uint32_t num_negative_pics; + uint32_t num_positive_pics; + struct NegativePics { + uint32_t delta_poc_s0_minus1; + bool used_by_curr_pic_s0_flag; + }* negative_pics; + struct PositivePics { + uint32_t delta_poc_s1_minus1; + bool used_by_curr_pic_s1_flag; + }* positive_pics; }; void PackVideoParameterSetNalUnit(struct Bitstream* bitstream, |