mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-09 08:55:33 +00:00
nvencoder: Add support for HDR10 static metadata
Insert HDR10 SEIs per IDR Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3992>
This commit is contained in:
parent
84ec16c67a
commit
b6d371295a
2 changed files with 253 additions and 52 deletions
|
@ -141,6 +141,8 @@ typedef struct _GstNvH264Encoder
|
||||||
|
|
||||||
gboolean packetized;
|
gboolean packetized;
|
||||||
GstH264NalParser *parser;
|
GstH264NalParser *parser;
|
||||||
|
GstMemory *sei;
|
||||||
|
GArray *sei_array;
|
||||||
|
|
||||||
GstNvEncoderDeviceMode selected_device_mode;
|
GstNvEncoderDeviceMode selected_device_mode;
|
||||||
|
|
||||||
|
@ -214,6 +216,7 @@ static void gst_nv_h264_encoder_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec);
|
GValue * value, GParamSpec * pspec);
|
||||||
static GstCaps *gst_nv_h264_encoder_getcaps (GstVideoEncoder * encoder,
|
static GstCaps *gst_nv_h264_encoder_getcaps (GstVideoEncoder * encoder,
|
||||||
GstCaps * filter);
|
GstCaps * filter);
|
||||||
|
static gboolean gst_nv_h264_encoder_stop (GstVideoEncoder * encoder);
|
||||||
static gboolean gst_nv_h264_encoder_set_format (GstNvEncoder * encoder,
|
static gboolean gst_nv_h264_encoder_set_format (GstNvEncoder * encoder,
|
||||||
GstVideoCodecState * state, gpointer session,
|
GstVideoCodecState * state, gpointer session,
|
||||||
NV_ENC_INITIALIZE_PARAMS * init_params, NV_ENC_CONFIG * config);
|
NV_ENC_INITIALIZE_PARAMS * init_params, NV_ENC_CONFIG * config);
|
||||||
|
@ -458,6 +461,7 @@ gst_nv_h264_encoder_class_init (GstNvH264EncoderClass * klass, gpointer data)
|
||||||
cdata->src_caps));
|
cdata->src_caps));
|
||||||
|
|
||||||
videoenc_class->getcaps = GST_DEBUG_FUNCPTR (gst_nv_h264_encoder_getcaps);
|
videoenc_class->getcaps = GST_DEBUG_FUNCPTR (gst_nv_h264_encoder_getcaps);
|
||||||
|
videoenc_class->stop = GST_DEBUG_FUNCPTR (gst_nv_h264_encoder_stop);
|
||||||
|
|
||||||
nvenc_class->set_format = GST_DEBUG_FUNCPTR (gst_nv_h264_encoder_set_format);
|
nvenc_class->set_format = GST_DEBUG_FUNCPTR (gst_nv_h264_encoder_set_format);
|
||||||
nvenc_class->set_output_state =
|
nvenc_class->set_output_state =
|
||||||
|
@ -528,6 +532,7 @@ gst_nv_h264_encoder_init (GstNvH264Encoder * self)
|
||||||
self->repeat_sequence_header = DEFAULT_REPEAT_SEQUENCE_HEADER;
|
self->repeat_sequence_header = DEFAULT_REPEAT_SEQUENCE_HEADER;
|
||||||
|
|
||||||
self->parser = gst_h264_nal_parser_new ();
|
self->parser = gst_h264_nal_parser_new ();
|
||||||
|
self->sei_array = g_array_new (FALSE, FALSE, sizeof (GstH264SEIMessage));
|
||||||
|
|
||||||
gst_nv_encoder_set_device_mode (GST_NV_ENCODER (self), klass->device_mode,
|
gst_nv_encoder_set_device_mode (GST_NV_ENCODER (self), klass->device_mode,
|
||||||
klass->cuda_device_id, klass->adapter_luid);
|
klass->cuda_device_id, klass->adapter_luid);
|
||||||
|
@ -540,6 +545,7 @@ gst_nv_h264_encoder_finalize (GObject * object)
|
||||||
|
|
||||||
g_mutex_clear (&self->prop_lock);
|
g_mutex_clear (&self->prop_lock);
|
||||||
gst_h264_nal_parser_free (self->parser);
|
gst_h264_nal_parser_free (self->parser);
|
||||||
|
g_array_unref (self->sei_array);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
@ -1039,6 +1045,21 @@ gst_nv_h264_encoder_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
|
||||||
return supported_caps;
|
return supported_caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_nv_h264_encoder_stop (GstVideoEncoder * encoder)
|
||||||
|
{
|
||||||
|
GstNvH264Encoder *self = GST_NV_H264_ENCODER (encoder);
|
||||||
|
|
||||||
|
if (self->sei) {
|
||||||
|
gst_memory_unref (self->sei);
|
||||||
|
self->sei = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_array_set_size (self->sei_array, 0);
|
||||||
|
|
||||||
|
return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (encoder);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_nv_h264_encoder_set_format (GstNvEncoder * encoder,
|
gst_nv_h264_encoder_set_format (GstNvEncoder * encoder,
|
||||||
GstVideoCodecState * state, gpointer session,
|
GstVideoCodecState * state, gpointer session,
|
||||||
|
@ -1398,6 +1419,64 @@ gst_nv_h264_encoder_set_format (GstNvEncoder * encoder,
|
||||||
if (temporal_aq_aborted)
|
if (temporal_aq_aborted)
|
||||||
g_object_notify (G_OBJECT (self), "temporal-aq");
|
g_object_notify (G_OBJECT (self), "temporal-aq");
|
||||||
|
|
||||||
|
if (state->mastering_display_info) {
|
||||||
|
GstH264SEIMessage sei;
|
||||||
|
GstH264MasteringDisplayColourVolume *mdcv;
|
||||||
|
|
||||||
|
memset (&sei, 0, sizeof (GstH264SEIMessage));
|
||||||
|
|
||||||
|
sei.payloadType = GST_H264_SEI_MASTERING_DISPLAY_COLOUR_VOLUME;
|
||||||
|
mdcv = &sei.payload.mastering_display_colour_volume;
|
||||||
|
|
||||||
|
/* AVC uses GBR order */
|
||||||
|
mdcv->display_primaries_x[0] =
|
||||||
|
state->mastering_display_info->display_primaries[1].x;
|
||||||
|
mdcv->display_primaries_y[0] =
|
||||||
|
state->mastering_display_info->display_primaries[1].y;
|
||||||
|
mdcv->display_primaries_x[1] =
|
||||||
|
state->mastering_display_info->display_primaries[2].x;
|
||||||
|
mdcv->display_primaries_y[1] =
|
||||||
|
state->mastering_display_info->display_primaries[2].y;
|
||||||
|
mdcv->display_primaries_x[2] =
|
||||||
|
state->mastering_display_info->display_primaries[0].x;
|
||||||
|
mdcv->display_primaries_y[2] =
|
||||||
|
state->mastering_display_info->display_primaries[0].y;
|
||||||
|
|
||||||
|
mdcv->white_point_x = state->mastering_display_info->white_point.x;
|
||||||
|
mdcv->white_point_y = state->mastering_display_info->white_point.y;
|
||||||
|
mdcv->max_display_mastering_luminance =
|
||||||
|
state->mastering_display_info->max_display_mastering_luminance;
|
||||||
|
mdcv->min_display_mastering_luminance =
|
||||||
|
state->mastering_display_info->min_display_mastering_luminance;
|
||||||
|
|
||||||
|
g_array_append_val (self->sei_array, sei);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->content_light_level) {
|
||||||
|
GstH264SEIMessage sei;
|
||||||
|
GstH264ContentLightLevel *cll;
|
||||||
|
|
||||||
|
memset (&sei, 0, sizeof (GstH264SEIMessage));
|
||||||
|
|
||||||
|
sei.payloadType = GST_H264_SEI_CONTENT_LIGHT_LEVEL;
|
||||||
|
cll = &sei.payload.content_light_level;
|
||||||
|
|
||||||
|
cll->max_content_light_level =
|
||||||
|
state->content_light_level->max_content_light_level;
|
||||||
|
cll->max_pic_average_light_level =
|
||||||
|
state->content_light_level->max_frame_average_light_level;
|
||||||
|
|
||||||
|
g_array_append_val (self->sei_array, sei);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->sei_array->len > 0) {
|
||||||
|
if (!self->packetized) {
|
||||||
|
self->sei = gst_h264_create_sei_memory (4, self->sei_array);
|
||||||
|
} else {
|
||||||
|
self->sei = gst_h264_create_sei_memory_avc (4, self->sei_array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1563,41 +1642,59 @@ gst_nv_h264_encoder_create_output_buffer (GstNvEncoder * encoder,
|
||||||
NV_ENC_LOCK_BITSTREAM * bitstream)
|
NV_ENC_LOCK_BITSTREAM * bitstream)
|
||||||
{
|
{
|
||||||
GstNvH264Encoder *self = GST_NV_H264_ENCODER (encoder);
|
GstNvH264Encoder *self = GST_NV_H264_ENCODER (encoder);
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer = nullptr;
|
||||||
GstH264ParserResult rst;
|
GstH264ParserResult rst;
|
||||||
GstH264NalUnit nalu;
|
GstH264NalUnit nalu;
|
||||||
|
|
||||||
if (!self->packetized) {
|
if (!self->packetized) {
|
||||||
return gst_buffer_new_memdup (bitstream->bitstreamBufferPtr,
|
buffer = gst_buffer_new_memdup (bitstream->bitstreamBufferPtr,
|
||||||
bitstream->bitstreamSizeInBytes);
|
bitstream->bitstreamSizeInBytes);
|
||||||
}
|
} else {
|
||||||
|
buffer = gst_buffer_new ();
|
||||||
buffer = gst_buffer_new ();
|
|
||||||
rst = gst_h264_parser_identify_nalu (self->parser,
|
|
||||||
(guint8 *) bitstream->bitstreamBufferPtr, 0,
|
|
||||||
bitstream->bitstreamSizeInBytes, &nalu);
|
|
||||||
|
|
||||||
if (rst == GST_H264_PARSER_NO_NAL_END)
|
|
||||||
rst = GST_H264_PARSER_OK;
|
|
||||||
|
|
||||||
while (rst == GST_H264_PARSER_OK) {
|
|
||||||
GstMemory *mem;
|
|
||||||
guint8 *data;
|
|
||||||
|
|
||||||
data = (guint8 *) g_malloc0 (nalu.size + 4);
|
|
||||||
GST_WRITE_UINT32_BE (data, nalu.size);
|
|
||||||
memcpy (data + 4, nalu.data + nalu.offset, nalu.size);
|
|
||||||
|
|
||||||
mem = gst_memory_new_wrapped ((GstMemoryFlags) 0, data, nalu.size + 4,
|
|
||||||
0, nalu.size + 4, data, (GDestroyNotify) g_free);
|
|
||||||
gst_buffer_append_memory (buffer, mem);
|
|
||||||
|
|
||||||
rst = gst_h264_parser_identify_nalu (self->parser,
|
rst = gst_h264_parser_identify_nalu (self->parser,
|
||||||
(guint8 *) bitstream->bitstreamBufferPtr, nalu.offset + nalu.size,
|
(guint8 *) bitstream->bitstreamBufferPtr, 0,
|
||||||
bitstream->bitstreamSizeInBytes, &nalu);
|
bitstream->bitstreamSizeInBytes, &nalu);
|
||||||
|
|
||||||
if (rst == GST_H264_PARSER_NO_NAL_END)
|
if (rst == GST_H264_PARSER_NO_NAL_END)
|
||||||
rst = GST_H264_PARSER_OK;
|
rst = GST_H264_PARSER_OK;
|
||||||
|
|
||||||
|
while (rst == GST_H264_PARSER_OK) {
|
||||||
|
GstMemory *mem;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
data = (guint8 *) g_malloc0 (nalu.size + 4);
|
||||||
|
GST_WRITE_UINT32_BE (data, nalu.size);
|
||||||
|
memcpy (data + 4, nalu.data + nalu.offset, nalu.size);
|
||||||
|
|
||||||
|
mem = gst_memory_new_wrapped ((GstMemoryFlags) 0, data, nalu.size + 4,
|
||||||
|
0, nalu.size + 4, data, (GDestroyNotify) g_free);
|
||||||
|
gst_buffer_append_memory (buffer, mem);
|
||||||
|
|
||||||
|
rst = gst_h264_parser_identify_nalu (self->parser,
|
||||||
|
(guint8 *) bitstream->bitstreamBufferPtr, nalu.offset + nalu.size,
|
||||||
|
bitstream->bitstreamSizeInBytes, &nalu);
|
||||||
|
|
||||||
|
if (rst == GST_H264_PARSER_NO_NAL_END)
|
||||||
|
rst = GST_H264_PARSER_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitstream->pictureType == NV_ENC_PIC_TYPE_IDR && self->sei) {
|
||||||
|
GstBuffer *new_buf = nullptr;
|
||||||
|
|
||||||
|
if (!self->packetized) {
|
||||||
|
new_buf = gst_h264_parser_insert_sei (self->parser, buffer, self->sei);
|
||||||
|
} else {
|
||||||
|
new_buf = gst_h264_parser_insert_sei_avc (self->parser, 4, buffer,
|
||||||
|
self->sei);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_buf) {
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
buffer = new_buf;
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (self, "Couldn't insert SEI memory");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
|
@ -147,6 +147,8 @@ typedef struct _GstNvH265Encoder
|
||||||
|
|
||||||
GstNvH265EncoderStreamFormat stream_format;
|
GstNvH265EncoderStreamFormat stream_format;
|
||||||
GstH265Parser *parser;
|
GstH265Parser *parser;
|
||||||
|
GstMemory *sei;
|
||||||
|
GArray *sei_array;
|
||||||
|
|
||||||
GstNvEncoderDeviceMode selected_device_mode;
|
GstNvEncoderDeviceMode selected_device_mode;
|
||||||
|
|
||||||
|
@ -219,6 +221,7 @@ static void gst_nv_h265_encoder_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec);
|
GValue * value, GParamSpec * pspec);
|
||||||
static GstCaps *gst_nv_h265_encoder_getcaps (GstVideoEncoder * encoder,
|
static GstCaps *gst_nv_h265_encoder_getcaps (GstVideoEncoder * encoder,
|
||||||
GstCaps * filter);
|
GstCaps * filter);
|
||||||
|
static gboolean gst_nv_h265_encoder_stop (GstVideoEncoder * encoder);
|
||||||
static gboolean gst_nv_h265_encoder_set_format (GstNvEncoder * encoder,
|
static gboolean gst_nv_h265_encoder_set_format (GstNvEncoder * encoder,
|
||||||
GstVideoCodecState * state, gpointer session,
|
GstVideoCodecState * state, gpointer session,
|
||||||
NV_ENC_INITIALIZE_PARAMS * init_params, NV_ENC_CONFIG * config);
|
NV_ENC_INITIALIZE_PARAMS * init_params, NV_ENC_CONFIG * config);
|
||||||
|
@ -459,6 +462,7 @@ gst_nv_h265_encoder_class_init (GstNvH265EncoderClass * klass, gpointer data)
|
||||||
cdata->src_caps));
|
cdata->src_caps));
|
||||||
|
|
||||||
videoenc_class->getcaps = GST_DEBUG_FUNCPTR (gst_nv_h265_encoder_getcaps);
|
videoenc_class->getcaps = GST_DEBUG_FUNCPTR (gst_nv_h265_encoder_getcaps);
|
||||||
|
videoenc_class->stop = GST_DEBUG_FUNCPTR (gst_nv_h265_encoder_stop);
|
||||||
|
|
||||||
nvenc_class->set_format = GST_DEBUG_FUNCPTR (gst_nv_h265_encoder_set_format);
|
nvenc_class->set_format = GST_DEBUG_FUNCPTR (gst_nv_h265_encoder_set_format);
|
||||||
nvenc_class->set_output_state =
|
nvenc_class->set_output_state =
|
||||||
|
@ -527,6 +531,7 @@ gst_nv_h265_encoder_init (GstNvH265Encoder * self)
|
||||||
self->repeat_sequence_header = DEFAULT_REPEAT_SEQUENCE_HEADER;
|
self->repeat_sequence_header = DEFAULT_REPEAT_SEQUENCE_HEADER;
|
||||||
|
|
||||||
self->parser = gst_h265_parser_new ();
|
self->parser = gst_h265_parser_new ();
|
||||||
|
self->sei_array = g_array_new (FALSE, FALSE, sizeof (GstH265SEIMessage));
|
||||||
|
|
||||||
gst_nv_encoder_set_device_mode (GST_NV_ENCODER (self), klass->device_mode,
|
gst_nv_encoder_set_device_mode (GST_NV_ENCODER (self), klass->device_mode,
|
||||||
klass->cuda_device_id, klass->adapter_luid);
|
klass->cuda_device_id, klass->adapter_luid);
|
||||||
|
@ -539,6 +544,7 @@ gst_nv_h265_encoder_finalize (GObject * object)
|
||||||
|
|
||||||
g_mutex_clear (&self->prop_lock);
|
g_mutex_clear (&self->prop_lock);
|
||||||
gst_h265_parser_free (self->parser);
|
gst_h265_parser_free (self->parser);
|
||||||
|
g_array_unref (self->sei_array);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
@ -1018,6 +1024,21 @@ gst_nv_h265_encoder_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
|
||||||
return supported_caps;
|
return supported_caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_nv_h265_encoder_stop (GstVideoEncoder * encoder)
|
||||||
|
{
|
||||||
|
GstNvH265Encoder *self = GST_NV_H265_ENCODER (encoder);
|
||||||
|
|
||||||
|
if (self->sei) {
|
||||||
|
gst_memory_unref (self->sei);
|
||||||
|
self->sei = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_array_set_size (self->sei_array, 0);
|
||||||
|
|
||||||
|
return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (encoder);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_nv_h265_encoder_set_format (GstNvEncoder * encoder,
|
gst_nv_h265_encoder_set_format (GstNvEncoder * encoder,
|
||||||
GstVideoCodecState * state, gpointer session,
|
GstVideoCodecState * state, gpointer session,
|
||||||
|
@ -1338,6 +1359,71 @@ gst_nv_h265_encoder_set_format (GstNvEncoder * encoder,
|
||||||
if (temporal_aq_aborted)
|
if (temporal_aq_aborted)
|
||||||
g_object_notify (G_OBJECT (self), "temporal-aq");
|
g_object_notify (G_OBJECT (self), "temporal-aq");
|
||||||
|
|
||||||
|
if (self->sei) {
|
||||||
|
gst_memory_unref (self->sei);
|
||||||
|
self->sei = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_array_set_size (self->sei_array, 0);
|
||||||
|
|
||||||
|
if (state->mastering_display_info) {
|
||||||
|
GstH265SEIMessage sei;
|
||||||
|
GstH265MasteringDisplayColourVolume *mdcv;
|
||||||
|
|
||||||
|
memset (&sei, 0, sizeof (GstH265SEIMessage));
|
||||||
|
|
||||||
|
sei.payloadType = GST_H265_SEI_MASTERING_DISPLAY_COLOUR_VOLUME;
|
||||||
|
mdcv = &sei.payload.mastering_display_colour_volume;
|
||||||
|
|
||||||
|
/* HEVC uses GBR order */
|
||||||
|
mdcv->display_primaries_x[0] =
|
||||||
|
state->mastering_display_info->display_primaries[1].x;
|
||||||
|
mdcv->display_primaries_y[0] =
|
||||||
|
state->mastering_display_info->display_primaries[1].y;
|
||||||
|
mdcv->display_primaries_x[1] =
|
||||||
|
state->mastering_display_info->display_primaries[2].x;
|
||||||
|
mdcv->display_primaries_y[1] =
|
||||||
|
state->mastering_display_info->display_primaries[2].y;
|
||||||
|
mdcv->display_primaries_x[2] =
|
||||||
|
state->mastering_display_info->display_primaries[0].x;
|
||||||
|
mdcv->display_primaries_y[2] =
|
||||||
|
state->mastering_display_info->display_primaries[0].y;
|
||||||
|
|
||||||
|
mdcv->white_point_x = state->mastering_display_info->white_point.x;
|
||||||
|
mdcv->white_point_y = state->mastering_display_info->white_point.y;
|
||||||
|
mdcv->max_display_mastering_luminance =
|
||||||
|
state->mastering_display_info->max_display_mastering_luminance;
|
||||||
|
mdcv->min_display_mastering_luminance =
|
||||||
|
state->mastering_display_info->min_display_mastering_luminance;
|
||||||
|
|
||||||
|
g_array_append_val (self->sei_array, sei);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->content_light_level) {
|
||||||
|
GstH265SEIMessage sei;
|
||||||
|
GstH265ContentLightLevel *cll;
|
||||||
|
|
||||||
|
memset (&sei, 0, sizeof (GstH265SEIMessage));
|
||||||
|
|
||||||
|
sei.payloadType = GST_H265_SEI_CONTENT_LIGHT_LEVEL;
|
||||||
|
cll = &sei.payload.content_light_level;
|
||||||
|
|
||||||
|
cll->max_content_light_level =
|
||||||
|
state->content_light_level->max_content_light_level;
|
||||||
|
cll->max_pic_average_light_level =
|
||||||
|
state->content_light_level->max_frame_average_light_level;
|
||||||
|
|
||||||
|
g_array_append_val (self->sei_array, sei);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->sei_array->len > 0) {
|
||||||
|
if (self->stream_format == GST_NV_H265_ENCODER_BYTE_STREAM) {
|
||||||
|
self->sei = gst_h265_create_sei_memory (0, 1, 4, self->sei_array);
|
||||||
|
} else {
|
||||||
|
self->sei = gst_h265_create_sei_memory_hevc (0, 1, 4, self->sei_array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1571,45 +1657,63 @@ gst_nv_h265_encoder_set_output_state (GstNvEncoder * encoder,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstBuffer *
|
static GstBuffer *
|
||||||
gst_nv_h265_encoder_create_output_buffer (GstNvEncoder *
|
gst_nv_h265_encoder_create_output_buffer (GstNvEncoder * encoder,
|
||||||
encoder, NV_ENC_LOCK_BITSTREAM * bitstream)
|
NV_ENC_LOCK_BITSTREAM * bitstream)
|
||||||
{
|
{
|
||||||
GstNvH265Encoder *self = GST_NV_H265_ENCODER (encoder);
|
GstNvH265Encoder *self = GST_NV_H265_ENCODER (encoder);
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer = nullptr;
|
||||||
GstH265ParserResult rst;
|
GstH265ParserResult rst;
|
||||||
GstH265NalUnit nalu;
|
GstH265NalUnit nalu;
|
||||||
|
|
||||||
if (self->stream_format == GST_NV_H265_ENCODER_BYTE_STREAM) {
|
if (self->stream_format == GST_NV_H265_ENCODER_BYTE_STREAM) {
|
||||||
return gst_buffer_new_memdup (bitstream->bitstreamBufferPtr,
|
buffer = gst_buffer_new_memdup (bitstream->bitstreamBufferPtr,
|
||||||
bitstream->bitstreamSizeInBytes);
|
bitstream->bitstreamSizeInBytes);
|
||||||
}
|
} else {
|
||||||
|
buffer = gst_buffer_new ();
|
||||||
buffer = gst_buffer_new ();
|
|
||||||
rst = gst_h265_parser_identify_nalu (self->parser,
|
|
||||||
(guint8 *) bitstream->bitstreamBufferPtr, 0,
|
|
||||||
bitstream->bitstreamSizeInBytes, &nalu);
|
|
||||||
|
|
||||||
if (rst == GST_H265_PARSER_NO_NAL_END)
|
|
||||||
rst = GST_H265_PARSER_OK;
|
|
||||||
|
|
||||||
while (rst == GST_H265_PARSER_OK) {
|
|
||||||
GstMemory *mem;
|
|
||||||
guint8 *data;
|
|
||||||
|
|
||||||
data = (guint8 *) g_malloc0 (nalu.size + 4);
|
|
||||||
GST_WRITE_UINT32_BE (data, nalu.size);
|
|
||||||
memcpy (data + 4, nalu.data + nalu.offset, nalu.size);
|
|
||||||
|
|
||||||
mem = gst_memory_new_wrapped ((GstMemoryFlags) 0, data, nalu.size + 4,
|
|
||||||
0, nalu.size + 4, data, (GDestroyNotify) g_free);
|
|
||||||
gst_buffer_append_memory (buffer, mem);
|
|
||||||
|
|
||||||
rst = gst_h265_parser_identify_nalu (self->parser,
|
rst = gst_h265_parser_identify_nalu (self->parser,
|
||||||
(guint8 *) bitstream->bitstreamBufferPtr, nalu.offset + nalu.size,
|
(guint8 *) bitstream->bitstreamBufferPtr, 0,
|
||||||
bitstream->bitstreamSizeInBytes, &nalu);
|
bitstream->bitstreamSizeInBytes, &nalu);
|
||||||
|
|
||||||
if (rst == GST_H265_PARSER_NO_NAL_END)
|
if (rst == GST_H265_PARSER_NO_NAL_END)
|
||||||
rst = GST_H265_PARSER_OK;
|
rst = GST_H265_PARSER_OK;
|
||||||
|
|
||||||
|
while (rst == GST_H265_PARSER_OK) {
|
||||||
|
GstMemory *mem;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
data = (guint8 *) g_malloc0 (nalu.size + 4);
|
||||||
|
GST_WRITE_UINT32_BE (data, nalu.size);
|
||||||
|
memcpy (data + 4, nalu.data + nalu.offset, nalu.size);
|
||||||
|
|
||||||
|
mem = gst_memory_new_wrapped ((GstMemoryFlags) 0, data, nalu.size + 4,
|
||||||
|
0, nalu.size + 4, data, (GDestroyNotify) g_free);
|
||||||
|
gst_buffer_append_memory (buffer, mem);
|
||||||
|
|
||||||
|
rst = gst_h265_parser_identify_nalu (self->parser,
|
||||||
|
(guint8 *) bitstream->bitstreamBufferPtr, nalu.offset + nalu.size,
|
||||||
|
bitstream->bitstreamSizeInBytes, &nalu);
|
||||||
|
|
||||||
|
if (rst == GST_H265_PARSER_NO_NAL_END)
|
||||||
|
rst = GST_H265_PARSER_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitstream->pictureType == NV_ENC_PIC_TYPE_IDR && self->sei) {
|
||||||
|
GstBuffer *new_buf = nullptr;
|
||||||
|
|
||||||
|
if (self->stream_format == GST_NV_H265_ENCODER_BYTE_STREAM) {
|
||||||
|
new_buf = gst_h265_parser_insert_sei (self->parser, buffer, self->sei);
|
||||||
|
} else {
|
||||||
|
new_buf = gst_h265_parser_insert_sei_hevc (self->parser, 4, buffer,
|
||||||
|
self->sei);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_buf) {
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
buffer = new_buf;
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (self, "Couldn't insert SEI memory");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
Loading…
Reference in a new issue