From 1a19a835a9c4a7452389144a8e18ced17def6518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Thu, 3 Mar 2022 09:59:28 +0100 Subject: [PATCH] vah264enc: Avoid mapping coded buffer twice. Currently for copying the coded buffer onto a GStreamer buffer, the coded buffer is mapped two times: one for getting the size, and later for do the actual copy. We can avoid this by doing directly in the element rather than in the general encoder object. Part-of: --- .../gst-plugins-bad/sys/va/gstvaencoder.c | 84 ------------------- .../gst-plugins-bad/sys/va/gstvaencoder.h | 3 - .../gst-plugins-bad/sys/va/gstvah264enc.c | 49 ++++++++--- 3 files changed, 38 insertions(+), 98 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c index 9521b314be..a07fcef5f7 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.c @@ -1114,90 +1114,6 @@ gst_va_encode_picture_get_raw_surface (GstVaEncodePicture * pic) return gst_va_buffer_get_surface (pic->raw_buffer); } -gint -gst_va_encode_picture_get_coded_size (GstVaEncodePicture * pic) -{ - VADisplay dpy; - VACodedBufferSegment *segment_list; - VACodedBufferSegment *segment; - VAStatus status; - gint size; - - g_return_val_if_fail (pic, -1); - g_return_val_if_fail (pic->coded_buffer != VA_INVALID_ID, -1); - - dpy = gst_va_display_get_va_dpy (pic->display); - - status = vaMapBuffer (dpy, pic->coded_buffer, (gpointer *) & segment_list); - if (status != VA_STATUS_SUCCESS) { - GST_WARNING ("coded buffer vaMapBuffer: %s", vaErrorStr (status)); - return -1; - } - - if (!segment_list) { - GST_WARNING ("coded buffer has no segment list"); - return -1; - } - - size = 0; - for (segment = segment_list; segment != NULL; segment = segment->next) - size += segment->size; - - status = vaUnmapBuffer (dpy, pic->coded_buffer); - if (status != VA_STATUS_SUCCESS) { - GST_WARNING ("coded buffer vaUnmapBuffer: %s", vaErrorStr (status)); - return -1; - } - - return size; -} - -gboolean -gst_va_encode_picture_copy_coded_data (GstVaEncodePicture * pic, - GstBuffer * dest) -{ - VADisplay dpy; - VACodedBufferSegment *segment_list; - VACodedBufferSegment *segment; - VAStatus status; - goffset offset; - gsize size; - - g_return_val_if_fail (pic, FALSE); - g_return_val_if_fail (dest && GST_IS_BUFFER (dest), FALSE); - g_return_val_if_fail (pic->coded_buffer != VA_INVALID_ID, FALSE); - - dpy = gst_va_display_get_va_dpy (pic->display); - - status = vaMapBuffer (dpy, pic->coded_buffer, (gpointer *) & segment_list); - if (status != VA_STATUS_SUCCESS) { - GST_WARNING ("coded buffer vaMapBuffer: %s", vaErrorStr (status)); - return FALSE; - } - - if (!segment_list) { - GST_WARNING ("coded buffer has no segment list"); - return FALSE; - } - - offset = 0; - for (segment = segment_list; segment != NULL; segment = segment->next) { - size = gst_buffer_fill (dest, offset, segment->buf, segment->size); - if (size != segment->size) { - GST_WARNING ("Segment size is %d, but copied %" G_GSIZE_FORMAT, - segment->size, size); - break; - } - offset += segment->size; - } - - status = vaUnmapBuffer (dpy, pic->coded_buffer); - if (status != VA_STATUS_SUCCESS) - GST_WARNING ("coded buffer vaUnmapBuffer: %s", vaErrorStr (status)); - - return TRUE; -} - GstVaEncodePicture * gst_va_encode_picture_new (GstVaEncoder * self, GstBuffer * raw_buffer) { diff --git a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h index ba6f0c50ee..016cb4f8d5 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h +++ b/subprojects/gst-plugins-bad/sys/va/gstvaencoder.h @@ -107,8 +107,5 @@ GstVaEncodePicture * gst_va_encode_picture_new (GstVaEncoder * self, void gst_va_encode_picture_free (GstVaEncodePicture * pic); VASurfaceID gst_va_encode_picture_get_raw_surface (GstVaEncodePicture * pic); VASurfaceID gst_va_encode_picture_get_reconstruct_surface (GstVaEncodePicture * pic); -gint gst_va_encode_picture_get_coded_size (GstVaEncodePicture * pic); -gboolean gst_va_encode_picture_copy_coded_data (GstVaEncodePicture * pic, - GstBuffer * dest); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c b/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c index f804b90fb0..85ae97db5e 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvah264enc.c @@ -3211,27 +3211,43 @@ _push_buffer_to_downstream (GstVaH264Enc * self, GstVaH264EncFrame * frame_enc) { GstVideoCodecFrame *frame; GstFlowReturn ret; - gint coded_size; - GstBuffer *buf = NULL; + guint coded_size; + goffset offset; + GstBuffer *buf; + VADisplay dpy; VASurfaceID surface; - VADisplay dpy = gst_va_display_get_va_dpy (self->display); VAStatus status; + VACodedBufferSegment *seg, *seg_list; frame = frame_enc->frame; + dpy = gst_va_display_get_va_dpy (self->display); + + /* Wait for encoding to finish */ surface = gst_va_encode_picture_get_raw_surface (frame_enc->picture); status = vaSyncSurface (dpy, surface); if (status != VA_STATUS_SUCCESS) { - GST_WARNING ("vaSyncSurface: %s", vaErrorStr (status)); + GST_WARNING_OBJECT (self, "vaSyncSurface: %s", vaErrorStr (status)); goto error; } - coded_size = gst_va_encode_picture_get_coded_size (frame_enc->picture); - if (coded_size <= 0) { - GST_ERROR_OBJECT (self, "Failed to get the coded size,"); + seg_list = NULL; + status = vaMapBuffer (dpy, frame_enc->picture->coded_buffer, + (gpointer *) & seg_list); + if (status != VA_STATUS_SUCCESS) { + GST_WARNING_OBJECT (self, "vaMapBuffer: %s", vaErrorStr (status)); goto error; } + if (!seg_list) { + GST_WARNING_OBJECT (self, "coded buffer has no segment list"); + goto error; + } + + coded_size = 0; + for (seg = seg_list; seg; seg = seg->next) + coded_size += seg->size; + buf = gst_video_encoder_allocate_output_buffer (GST_VIDEO_ENCODER_CAST (self), coded_size); if (!buf) { @@ -3240,12 +3256,23 @@ _push_buffer_to_downstream (GstVaH264Enc * self, GstVaH264EncFrame * frame_enc) goto error; } - if (!gst_va_encode_picture_copy_coded_data (frame_enc->picture, buf)) { - GST_ERROR_OBJECT (self, "Failed to copy output buffer, size %d", - coded_size); - goto error; + offset = 0; + for (seg = seg_list; seg; seg = seg->next) { + gsize write_size; + + write_size = gst_buffer_fill (buf, offset, seg->buf, seg->size); + if (write_size != seg->size) { + GST_WARNING_OBJECT (self, "Segment size is %d, but copied %" + G_GSIZE_FORMAT, seg->size, write_size); + break; + } + offset += seg->size; } + status = vaUnmapBuffer (dpy, frame_enc->picture->coded_buffer); + if (status != VA_STATUS_SUCCESS) + GST_WARNING ("vaUnmapBuffer: %s", vaErrorStr (status)); + frame->pts = self->start_pts + self->frame_duration * frame_enc->total_frame_count; /* The PTS should always be later than the DTS. */