summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--encode2.c61
-rw-r--r--hevc.c32
-rw-r--r--hevc.h12
3 files changed, 88 insertions, 17 deletions
diff --git a/encode2.c b/encode2.c
index 33bec32..c591a30 100644
--- a/encode2.c
+++ b/encode2.c
@@ -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);
diff --git a/hevc.c b/hevc.c
index 5328139..9b5a05a 100644
--- a/hevc.c
+++ b/hevc.c
@@ -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();
}
diff --git a/hevc.h b/hevc.h
index 14c3aa3..6ab312d 100644
--- a/hevc.h
+++ b/hevc.h
@@ -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,