mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-26 02:00:33 +00:00
encoder: h264: support only the byte-stream format.
The libgstvaapi core encoders are meant to support raw bitstreams only. Henceforth, we are always producing a stream in "byte-stream" format. However, the "codec-data" buffer which holds SPS and PPS headers is always available. The "lengthSizeMinusOne" field is always set to 3 so that in-place "byte-stream" format to "avc" format conversion could be performed.
This commit is contained in:
parent
45732dcc83
commit
e2f8c059a5
3 changed files with 51 additions and 93 deletions
|
@ -112,23 +112,6 @@ h264_get_slice_type (GstVaapiPictureType type)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline gboolean
|
|
||||||
_read_sps_attributes (const guint8 * sps_data,
|
|
||||||
guint32 sps_size,
|
|
||||||
guint32 * profile_idc, guint32 * profile_comp, guint32 * level_idc)
|
|
||||||
{
|
|
||||||
g_assert (profile_idc && profile_comp && level_idc);
|
|
||||||
g_assert (sps_size >= 4);
|
|
||||||
if (sps_size < 4) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
/* skip sps_data[0], nal_type */
|
|
||||||
*profile_idc = sps_data[1];
|
|
||||||
*profile_comp = sps_data[2];
|
|
||||||
*level_idc = sps_data[3];
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get log2_max_frame_num value for H.264 specification */
|
/* Get log2_max_frame_num value for H.264 specification */
|
||||||
static guint
|
static guint
|
||||||
h264_get_log2_max_frame_num (guint num)
|
h264_get_log2_max_frame_num (guint num)
|
||||||
|
@ -1384,93 +1367,87 @@ gst_vaapi_encoder_h264_flush (GstVaapiEncoder * base_encoder)
|
||||||
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Generate "codec-data" buffer */
|
||||||
static GstVaapiEncoderStatus
|
static GstVaapiEncoderStatus
|
||||||
gst_vaapi_encoder_h264_get_avcC_codec_data (GstVaapiEncoderH264 * encoder,
|
gst_vaapi_encoder_h264_get_codec_data (GstVaapiEncoder * base_encoder,
|
||||||
GstBuffer ** buffer)
|
GstBuffer ** out_buffer_ptr)
|
||||||
{
|
{
|
||||||
GstBuffer *avc_codec;
|
GstVaapiEncoderH264 *const encoder =
|
||||||
|
GST_VAAPI_ENCODER_H264_CAST (base_encoder);
|
||||||
const guint32 configuration_version = 0x01;
|
const guint32 configuration_version = 0x01;
|
||||||
const guint32 length_size_minus_one = 0x03;
|
const guint32 nal_length_size = 4;
|
||||||
guint32 profile, profile_comp, level_idc;
|
guint8 profile_idc, profile_comp, level_idc;
|
||||||
GstMapInfo sps_info, pps_info;
|
GstMapInfo sps_info, pps_info;
|
||||||
GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
|
||||||
GstBitWriter writer;
|
GstBitWriter writer;
|
||||||
|
GstBuffer *buffer;
|
||||||
|
|
||||||
g_assert (buffer);
|
|
||||||
if (!encoder->sps_data || !encoder->pps_data)
|
if (!encoder->sps_data || !encoder->pps_data)
|
||||||
return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
|
return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
|
||||||
|
if (gst_buffer_get_size (encoder->sps_data) < 4)
|
||||||
|
return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
|
||||||
|
|
||||||
if (!gst_buffer_map (encoder->sps_data, &sps_info, GST_MAP_READ))
|
if (!gst_buffer_map (encoder->sps_data, &sps_info, GST_MAP_READ))
|
||||||
return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
|
goto error_map_sps_buffer;
|
||||||
|
|
||||||
if (FALSE == _read_sps_attributes (sps_info.data, sps_info.size,
|
if (!gst_buffer_map (encoder->pps_data, &pps_info, GST_MAP_READ))
|
||||||
&profile, &profile_comp, &level_idc)) {
|
goto error_map_pps_buffer;
|
||||||
ret = GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gst_buffer_map (encoder->pps_data, &pps_info, GST_MAP_READ)) {
|
/* skip sps_data[0], which is the nal_unit_type */
|
||||||
ret = GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
|
profile_idc = sps_info.data[1];
|
||||||
goto end;
|
profile_comp = sps_info.data[2];
|
||||||
}
|
level_idc = sps_info.data[3];
|
||||||
|
|
||||||
|
/* Header */
|
||||||
gst_bit_writer_init (&writer, (sps_info.size + pps_info.size + 64) * 8);
|
gst_bit_writer_init (&writer, (sps_info.size + pps_info.size + 64) * 8);
|
||||||
/* codec_data */
|
|
||||||
gst_bit_writer_put_bits_uint32 (&writer, configuration_version, 8);
|
gst_bit_writer_put_bits_uint32 (&writer, configuration_version, 8);
|
||||||
gst_bit_writer_put_bits_uint32 (&writer, profile, 8);
|
gst_bit_writer_put_bits_uint32 (&writer, profile_idc, 8);
|
||||||
gst_bit_writer_put_bits_uint32 (&writer, profile_comp, 8);
|
gst_bit_writer_put_bits_uint32 (&writer, profile_comp, 8);
|
||||||
gst_bit_writer_put_bits_uint32 (&writer, level_idc, 8);
|
gst_bit_writer_put_bits_uint32 (&writer, level_idc, 8);
|
||||||
gst_bit_writer_put_bits_uint32 (&writer, 0x3F, 6); /*111111 */
|
gst_bit_writer_put_bits_uint32 (&writer, 0x3f, 6); /* 111111 */
|
||||||
gst_bit_writer_put_bits_uint32 (&writer, length_size_minus_one, 2);
|
gst_bit_writer_put_bits_uint32 (&writer, nal_length_size - 1, 2);
|
||||||
gst_bit_writer_put_bits_uint32 (&writer, 0x07, 3); /* 111 */
|
gst_bit_writer_put_bits_uint32 (&writer, 0x07, 3); /* 111 */
|
||||||
|
|
||||||
/* write sps */
|
/* Write SPS */
|
||||||
gst_bit_writer_put_bits_uint32 (&writer, 1, 5); /* sps count = 1 */
|
gst_bit_writer_put_bits_uint32 (&writer, 1, 5); /* SPS count = 1 */
|
||||||
g_assert (GST_BIT_WRITER_BIT_SIZE (&writer) % 8 == 0);
|
g_assert (GST_BIT_WRITER_BIT_SIZE (&writer) % 8 == 0);
|
||||||
gst_bit_writer_put_bits_uint32 (&writer, sps_info.size, 16);
|
gst_bit_writer_put_bits_uint32 (&writer, sps_info.size, 16);
|
||||||
gst_bit_writer_put_bytes (&writer, sps_info.data, sps_info.size);
|
gst_bit_writer_put_bytes (&writer, sps_info.data, sps_info.size);
|
||||||
|
|
||||||
/* write pps */
|
/* Write PPS */
|
||||||
gst_bit_writer_put_bits_uint32 (&writer, 1, 8); /*pps count = 1 */
|
gst_bit_writer_put_bits_uint32 (&writer, 1, 8); /* PPS count = 1 */
|
||||||
gst_bit_writer_put_bits_uint32 (&writer, pps_info.size, 16);
|
gst_bit_writer_put_bits_uint32 (&writer, pps_info.size, 16);
|
||||||
gst_bit_writer_put_bytes (&writer, pps_info.data, pps_info.size);
|
gst_bit_writer_put_bytes (&writer, pps_info.data, pps_info.size);
|
||||||
|
|
||||||
avc_codec = gst_buffer_new_wrapped (GST_BIT_WRITER_DATA (&writer),
|
|
||||||
GST_BIT_WRITER_BIT_SIZE (&writer) / 8);
|
|
||||||
g_assert (avc_codec);
|
|
||||||
if (!avc_codec) {
|
|
||||||
ret = GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
|
|
||||||
goto clear_writer;
|
|
||||||
}
|
|
||||||
*buffer = avc_codec;
|
|
||||||
|
|
||||||
gst_buffer_unmap (encoder->pps_data, &pps_info);
|
gst_buffer_unmap (encoder->pps_data, &pps_info);
|
||||||
gst_bit_writer_clear (&writer, FALSE);
|
|
||||||
ret = GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
clear_writer:
|
|
||||||
gst_bit_writer_clear (&writer, TRUE);
|
|
||||||
|
|
||||||
end:
|
|
||||||
gst_buffer_unmap (encoder->sps_data, &sps_info);
|
gst_buffer_unmap (encoder->sps_data, &sps_info);
|
||||||
|
|
||||||
return ret;
|
buffer = gst_buffer_new_wrapped (GST_BIT_WRITER_DATA (&writer),
|
||||||
}
|
GST_BIT_WRITER_BIT_SIZE (&writer) / 8);
|
||||||
|
if (!buffer)
|
||||||
|
goto error_alloc_buffer;
|
||||||
|
*out_buffer_ptr = buffer;
|
||||||
|
|
||||||
static GstVaapiEncoderStatus
|
gst_bit_writer_clear (&writer, FALSE);
|
||||||
gst_vaapi_encoder_h264_get_codec_data (GstVaapiEncoder * base_encoder,
|
|
||||||
GstBuffer ** buffer)
|
|
||||||
{
|
|
||||||
GstVaapiEncoderH264 *const encoder =
|
|
||||||
GST_VAAPI_ENCODER_H264_CAST (base_encoder);
|
|
||||||
|
|
||||||
*buffer = NULL;
|
|
||||||
|
|
||||||
if (!encoder->is_avc)
|
|
||||||
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
||||||
|
|
||||||
return gst_vaapi_encoder_h264_get_avcC_codec_data (encoder, buffer);
|
/* ERRORS */
|
||||||
|
error_map_sps_buffer:
|
||||||
|
{
|
||||||
|
GST_ERROR ("failed to map SPS packed header");
|
||||||
|
return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
|
||||||
|
}
|
||||||
|
error_map_pps_buffer:
|
||||||
|
{
|
||||||
|
GST_ERROR ("failed to map PPS packed header");
|
||||||
|
gst_buffer_unmap (encoder->sps_data, &sps_info);
|
||||||
|
return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
|
||||||
|
}
|
||||||
|
error_alloc_buffer:
|
||||||
|
{
|
||||||
|
GST_ERROR ("failed to allocate codec-data buffer");
|
||||||
|
gst_bit_writer_clear (&writer, TRUE);
|
||||||
|
return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiEncoderStatus
|
static GstVaapiEncoderStatus
|
||||||
|
@ -1805,15 +1782,3 @@ gst_vaapi_encoder_h264_get_default_properties (void)
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
gst_vaapi_encoder_h264_set_avc (GstVaapiEncoderH264 * encoder, gboolean is_avc)
|
|
||||||
{
|
|
||||||
encoder->is_avc = is_avc;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
gst_vaapi_encoder_h264_is_avc (GstVaapiEncoderH264 * encoder)
|
|
||||||
{
|
|
||||||
return encoder->is_avc;
|
|
||||||
}
|
|
||||||
|
|
|
@ -54,12 +54,6 @@ gst_vaapi_encoder_h264_new (GstVaapiDisplay * display);
|
||||||
GPtrArray *
|
GPtrArray *
|
||||||
gst_vaapi_encoder_h264_get_default_properties (void);
|
gst_vaapi_encoder_h264_get_default_properties (void);
|
||||||
|
|
||||||
void
|
|
||||||
gst_vaapi_encoder_h264_set_avc (GstVaapiEncoderH264 * encoder, gboolean is_avc);
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
gst_vaapi_encoder_h264_is_avc (GstVaapiEncoderH264 * encoder);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /*GST_VAAPI_ENCODER_H264_H */
|
#endif /*GST_VAAPI_ENCODER_H264_H */
|
||||||
|
|
|
@ -66,7 +66,6 @@ struct _GstVaapiEncoderH264
|
||||||
guint32 mb_width;
|
guint32 mb_width;
|
||||||
guint32 mb_height;
|
guint32 mb_height;
|
||||||
|
|
||||||
gboolean is_avc; /* avc or bytestream */
|
|
||||||
/* re-ordering */
|
/* re-ordering */
|
||||||
GQueue reorder_frame_list;
|
GQueue reorder_frame_list;
|
||||||
guint reorder_state;
|
guint reorder_state;
|
||||||
|
|
Loading…
Reference in a new issue