From 661c31f0bf4635a5b4f0c3cb7e4c213ea2a31aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 27 Dec 2024 18:02:12 +0100 Subject: [PATCH] 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: --- .../ext/svtjpegxs/gstsvtjpegxsenc.c | 179 ++++++++++-------- 1 file changed, 95 insertions(+), 84 deletions(-) diff --git a/subprojects/gst-plugins-bad/ext/svtjpegxs/gstsvtjpegxsenc.c b/subprojects/gst-plugins-bad/ext/svtjpegxs/gstsvtjpegxsenc.c index c2f695c104..7b7850b3db 100644 --- a/subprojects/gst-plugins-bad/ext/svtjpegxs/gstsvtjpegxsenc.c +++ b/subprojects/gst-plugins-bad/ext/svtjpegxs/gstsvtjpegxsenc.c @@ -7,8 +7,8 @@ /** * SECTION:element-svtjpegxsenc * - * The svtjpegxsenc element does JPEG XS encoding using Scalable - * Video Technology for JPEG_XS Encoder (SVT JPEG XS Encoder). + * The svtjpegxsenc element does JPEG XS encoding using the Scalable + * Video Technology for JPEG_XS Encoder (SVT JPEG XS Encoder) library. * * 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; } +// The codestream data is either a full progressive image or a single field. static GstFlowReturn -gst_svt_jpeg_xs_enc_handle_frame (GstVideoEncoder * vencoder, - GstVideoCodecFrame * frame) +gst_svt_jpeg_xs_enc_encode_codestream (GstSvtJpegXsEnc * jxsenc, GstVideoFrame * video_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 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,} }; - 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[2] = GST_VIDEO_FRAME_PLANE_DATA (&video_frame, 2); + 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[2] = GST_VIDEO_FRAME_PLANE_DATA (video_frame, 2); // 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) - / GST_VIDEO_FRAME_COMP_PSTRIDE (&video_frame, 0); - img.stride[1] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 1) - / GST_VIDEO_FRAME_COMP_PSTRIDE (&video_frame, 1); - img.stride[2] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 2) - / GST_VIDEO_FRAME_COMP_PSTRIDE (&video_frame, 2); + img.stride[0] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 0) + / GST_VIDEO_FRAME_COMP_PSTRIDE (video_frame, 0); + img.stride[1] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 1) + / GST_VIDEO_FRAME_COMP_PSTRIDE (video_frame, 1); + img.stride[2] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 2) + / GST_VIDEO_FRAME_COMP_PSTRIDE (video_frame, 2); - img.alloc_size[0] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 0) - * GST_VIDEO_FRAME_COMP_HEIGHT (&video_frame, 0); - img.alloc_size[1] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 1) - * GST_VIDEO_FRAME_COMP_HEIGHT (&video_frame, 1); - img.alloc_size[2] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 2) - * GST_VIDEO_FRAME_COMP_HEIGHT (&video_frame, 2); + img.alloc_size[0] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 0) + * GST_VIDEO_FRAME_COMP_HEIGHT (video_frame, 0); + img.alloc_size[1] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 1) + * GST_VIDEO_FRAME_COMP_HEIGHT (video_frame, 1); + img.alloc_size[2] = GST_VIDEO_FRAME_COMP_STRIDE (video_frame, 2) + * GST_VIDEO_FRAME_COMP_HEIGHT (video_frame, 2); for (int i = 0; i < 3; ++i) { 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; } - 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; - - // 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.bitstream = *bitstream_buffer; encoder_frame.user_prv_ctx_ptr = NULL; @@ -676,14 +634,83 @@ gst_svt_jpeg_xs_enc_handle_frame (GstVideoEncoder * vencoder, 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", - encoder_frame.bitstream.used_size, - encoder_frame.bitstream.last_packet_in_frame); + out_buf.used_size, out_buf.last_packet_in_frame); // Shouldn't happen, but let's play it safe - if (encoder_frame.bitstream.used_size < jxsenc->bytes_per_frame) - gst_buffer_set_size (frame->output_buffer, - encoder_frame.bitstream.used_size); + if (out_buf.used_size < jxsenc->bytes_per_frame) + gst_buffer_set_size (frame->output_buffer, out_buf.used_size); gst_buffer_unmap (frame->output_buffer, &outbuf_map); @@ -731,22 +758,6 @@ output_buffer_map_write_failure: flow = GST_FLOW_ERROR; 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