mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-13 15:12:58 +00:00
svtjpegxsenc: factor out encoding of codestream into separate function
Prepare for interlacing support where an interlaced image is coded as two codestreams each representing a field. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8219>
This commit is contained in:
parent
ef57213426
commit
661c31f0bf
1 changed files with 95 additions and 84 deletions
|
@ -7,8 +7,8 @@
|
||||||
/**
|
/**
|
||||||
* SECTION:element-svtjpegxsenc
|
* SECTION:element-svtjpegxsenc
|
||||||
*
|
*
|
||||||
* The svtjpegxsenc element does JPEG XS encoding using Scalable
|
* The svtjpegxsenc element does JPEG XS encoding using the Scalable
|
||||||
* Video Technology for JPEG_XS Encoder (SVT JPEG XS Encoder).
|
* Video Technology for JPEG_XS Encoder (SVT JPEG XS Encoder) library.
|
||||||
*
|
*
|
||||||
* See https://jpeg.org/jpegxs/ for more information about the JPEG XS format.
|
* See https://jpeg.org/jpegxs/ for more information about the JPEG XS format.
|
||||||
*
|
*
|
||||||
|
@ -566,26 +566,11 @@ gst_svt_jpeg_xs_enc_set_format (GstVideoEncoder * encoder,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The codestream data is either a full progressive image or a single field.
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_svt_jpeg_xs_enc_handle_frame (GstVideoEncoder * vencoder,
|
gst_svt_jpeg_xs_enc_encode_codestream (GstSvtJpegXsEnc * jxsenc, GstVideoFrame * video_frame, //
|
||||||
GstVideoCodecFrame * frame)
|
svt_jpeg_xs_bitstream_buffer_t * bitstream_buffer)
|
||||||
{
|
{
|
||||||
GstSvtJpegXsEnc *jxsenc = GST_SVT_JPEG_XS_ENC (vencoder);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (jxsenc, "Frame to encode");
|
|
||||||
|
|
||||||
if (jxsenc->jxs_encoder == NULL || jxsenc->state == NULL) {
|
|
||||||
GST_ERROR_OBJECT (jxsenc,
|
|
||||||
"Encoder not initialised yet. No input caps set?");
|
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
|
||||||
}
|
|
||||||
// Map input buffer
|
|
||||||
GstVideoFrame video_frame;
|
|
||||||
|
|
||||||
if (!gst_video_frame_map (&video_frame, &jxsenc->state->info,
|
|
||||||
frame->input_buffer, GST_MAP_READ))
|
|
||||||
goto map_error;
|
|
||||||
|
|
||||||
// Encoder input/output frame struct
|
// Encoder input/output frame struct
|
||||||
svt_jpeg_xs_frame_t encoder_frame;
|
svt_jpeg_xs_frame_t encoder_frame;
|
||||||
|
|
||||||
|
@ -594,24 +579,24 @@ gst_svt_jpeg_xs_enc_handle_frame (GstVideoEncoder * vencoder,
|
||||||
svt_jpeg_xs_image_buffer_t img = { {0,}
|
svt_jpeg_xs_image_buffer_t img = { {0,}
|
||||||
};
|
};
|
||||||
|
|
||||||
img.data_yuv[0] = GST_VIDEO_FRAME_PLANE_DATA (&video_frame, 0);
|
img.data_yuv[0] = GST_VIDEO_FRAME_PLANE_DATA (video_frame, 0);
|
||||||
img.data_yuv[1] = GST_VIDEO_FRAME_PLANE_DATA (&video_frame, 1);
|
img.data_yuv[1] = GST_VIDEO_FRAME_PLANE_DATA (video_frame, 1);
|
||||||
img.data_yuv[2] = GST_VIDEO_FRAME_PLANE_DATA (&video_frame, 2);
|
img.data_yuv[2] = GST_VIDEO_FRAME_PLANE_DATA (video_frame, 2);
|
||||||
|
|
||||||
// Note: wants stride in pixels not in bytes (might need tweaks for 10-bit)
|
// Note: wants stride in pixels not in bytes (might need tweaks for 10-bit)
|
||||||
img.stride[0] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 0)
|
img.stride[0] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 0)
|
||||||
/ GST_VIDEO_FRAME_COMP_PSTRIDE (&video_frame, 0);
|
/ GST_VIDEO_FRAME_COMP_PSTRIDE (video_frame, 0);
|
||||||
img.stride[1] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 1)
|
img.stride[1] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 1)
|
||||||
/ GST_VIDEO_FRAME_COMP_PSTRIDE (&video_frame, 1);
|
/ GST_VIDEO_FRAME_COMP_PSTRIDE (video_frame, 1);
|
||||||
img.stride[2] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 2)
|
img.stride[2] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 2)
|
||||||
/ GST_VIDEO_FRAME_COMP_PSTRIDE (&video_frame, 2);
|
/ GST_VIDEO_FRAME_COMP_PSTRIDE (video_frame, 2);
|
||||||
|
|
||||||
img.alloc_size[0] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 0)
|
img.alloc_size[0] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 0)
|
||||||
* GST_VIDEO_FRAME_COMP_HEIGHT (&video_frame, 0);
|
* GST_VIDEO_FRAME_COMP_HEIGHT (video_frame, 0);
|
||||||
img.alloc_size[1] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 1)
|
img.alloc_size[1] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 1)
|
||||||
* GST_VIDEO_FRAME_COMP_HEIGHT (&video_frame, 1);
|
* GST_VIDEO_FRAME_COMP_HEIGHT (video_frame, 1);
|
||||||
img.alloc_size[2] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 2)
|
img.alloc_size[2] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 2)
|
||||||
* GST_VIDEO_FRAME_COMP_HEIGHT (&video_frame, 2);
|
* GST_VIDEO_FRAME_COMP_HEIGHT (video_frame, 2);
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
GST_TRACE_OBJECT (jxsenc, "img stride[%u] = %u, alloc_size[%u]: %u",
|
GST_TRACE_OBJECT (jxsenc, "img stride[%u] = %u, alloc_size[%u]: %u",
|
||||||
|
@ -621,34 +606,7 @@ gst_svt_jpeg_xs_enc_handle_frame (GstVideoEncoder * vencoder,
|
||||||
encoder_frame.image = img;
|
encoder_frame.image = img;
|
||||||
}
|
}
|
||||||
|
|
||||||
GstFlowReturn flow;
|
encoder_frame.bitstream = *bitstream_buffer;
|
||||||
|
|
||||||
// Allocate output buffer
|
|
||||||
{
|
|
||||||
// Could use a bufferpool here, since output frames are all the same size.
|
|
||||||
flow =
|
|
||||||
gst_video_encoder_allocate_output_frame (vencoder, frame,
|
|
||||||
jxsenc->bytes_per_frame);
|
|
||||||
|
|
||||||
if (flow != GST_FLOW_OK)
|
|
||||||
goto allocate_output_frame_failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
GstMapInfo outbuf_map = GST_MAP_INFO_INIT;
|
|
||||||
|
|
||||||
// Set up encoder output buffer struct
|
|
||||||
{
|
|
||||||
svt_jpeg_xs_bitstream_buffer_t out_buf;
|
|
||||||
|
|
||||||
if (!gst_buffer_map (frame->output_buffer, &outbuf_map, GST_MAP_WRITE))
|
|
||||||
goto output_buffer_map_write_failure;
|
|
||||||
|
|
||||||
out_buf.buffer = outbuf_map.data;
|
|
||||||
out_buf.allocation_size = outbuf_map.size;
|
|
||||||
out_buf.used_size = 0;
|
|
||||||
|
|
||||||
encoder_frame.bitstream = out_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
encoder_frame.user_prv_ctx_ptr = NULL;
|
encoder_frame.user_prv_ctx_ptr = NULL;
|
||||||
|
|
||||||
|
@ -676,14 +634,83 @@ gst_svt_jpeg_xs_enc_handle_frame (GstVideoEncoder * vencoder,
|
||||||
goto get_packet_error;
|
goto get_packet_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*bitstream_buffer = encoder_frame.bitstream;
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
/* Errors */
|
||||||
|
send_picture_error:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (jxsenc, LIBRARY, ENCODE, (NULL),
|
||||||
|
("Error encoding image (%s): 0x%08x", "send_picture", enc_ret));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_packet_error:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (jxsenc, LIBRARY, ENCODE, (NULL),
|
||||||
|
("Error encoding image (%s): 0x%08x", "get_packet", enc_ret));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_svt_jpeg_xs_enc_handle_frame (GstVideoEncoder * vencoder,
|
||||||
|
GstVideoCodecFrame * frame)
|
||||||
|
{
|
||||||
|
GstSvtJpegXsEnc *jxsenc = GST_SVT_JPEG_XS_ENC (vencoder);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (jxsenc, "Frame to encode");
|
||||||
|
|
||||||
|
if (jxsenc->jxs_encoder == NULL || jxsenc->state == NULL) {
|
||||||
|
GST_ERROR_OBJECT (jxsenc,
|
||||||
|
"Encoder not initialised yet. No input caps set?");
|
||||||
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
}
|
||||||
|
// Map input buffer
|
||||||
|
GstVideoFrame video_frame;
|
||||||
|
|
||||||
|
if (!gst_video_frame_map (&video_frame, &jxsenc->state->info,
|
||||||
|
frame->input_buffer, GST_MAP_READ))
|
||||||
|
goto map_error;
|
||||||
|
|
||||||
|
GstFlowReturn flow;
|
||||||
|
|
||||||
|
// Allocate output buffer
|
||||||
|
{
|
||||||
|
// Could use a bufferpool here, since output frames are all the same size.
|
||||||
|
flow =
|
||||||
|
gst_video_encoder_allocate_output_frame (vencoder, frame,
|
||||||
|
jxsenc->bytes_per_frame);
|
||||||
|
|
||||||
|
if (flow != GST_FLOW_OK)
|
||||||
|
goto allocate_output_frame_failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstMapInfo outbuf_map = GST_MAP_INFO_INIT;
|
||||||
|
svt_jpeg_xs_bitstream_buffer_t out_buf;
|
||||||
|
|
||||||
|
// Set up encoder output buffer struct
|
||||||
|
{
|
||||||
|
if (!gst_buffer_map (frame->output_buffer, &outbuf_map, GST_MAP_WRITE))
|
||||||
|
goto output_buffer_map_write_failure;
|
||||||
|
|
||||||
|
out_buf.buffer = outbuf_map.data;
|
||||||
|
out_buf.allocation_size = outbuf_map.size;
|
||||||
|
out_buf.used_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
flow = gst_svt_jpeg_xs_enc_encode_codestream (jxsenc, &video_frame, &out_buf);
|
||||||
|
|
||||||
|
if (flow != GST_FLOW_OK)
|
||||||
|
goto out_unmap;
|
||||||
|
|
||||||
GST_LOG_OBJECT (jxsenc, "Output buffer size: %u, last=%d",
|
GST_LOG_OBJECT (jxsenc, "Output buffer size: %u, last=%d",
|
||||||
encoder_frame.bitstream.used_size,
|
out_buf.used_size, out_buf.last_packet_in_frame);
|
||||||
encoder_frame.bitstream.last_packet_in_frame);
|
|
||||||
|
|
||||||
// Shouldn't happen, but let's play it safe
|
// Shouldn't happen, but let's play it safe
|
||||||
if (encoder_frame.bitstream.used_size < jxsenc->bytes_per_frame)
|
if (out_buf.used_size < jxsenc->bytes_per_frame)
|
||||||
gst_buffer_set_size (frame->output_buffer,
|
gst_buffer_set_size (frame->output_buffer, out_buf.used_size);
|
||||||
encoder_frame.bitstream.used_size);
|
|
||||||
|
|
||||||
gst_buffer_unmap (frame->output_buffer, &outbuf_map);
|
gst_buffer_unmap (frame->output_buffer, &outbuf_map);
|
||||||
|
|
||||||
|
@ -731,22 +758,6 @@ output_buffer_map_write_failure:
|
||||||
flow = GST_FLOW_ERROR;
|
flow = GST_FLOW_ERROR;
|
||||||
goto out_unmap;
|
goto out_unmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_picture_error:
|
|
||||||
{
|
|
||||||
GST_ELEMENT_ERROR (jxsenc, LIBRARY, ENCODE, (NULL),
|
|
||||||
("Error encoding image: 0x%08x", enc_ret));
|
|
||||||
flow = GST_FLOW_ERROR;
|
|
||||||
goto out_unmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_packet_error:
|
|
||||||
{
|
|
||||||
GST_ELEMENT_ERROR (jxsenc, LIBRARY, ENCODE, (NULL),
|
|
||||||
("Error encoding image (%s): 0x%08x", "get_packet", enc_ret));
|
|
||||||
flow = GST_FLOW_ERROR;
|
|
||||||
goto out_unmap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
Loading…
Reference in a new issue