diff options
author | Seungha Yang <seungha@centricular.com> | 2021-08-19 21:56:05 +0900 |
---|---|---|
committer | Seungha Yang <seungha@centricular.com> | 2021-08-19 22:01:50 +0900 |
commit | 75f6f79e571dbc3aee66c4ff4e55564c527e9c71 (patch) | |
tree | 49bc606f5679e1ae2c9acc09a79980c5395e182b /sys/mediafoundation/gstmfsourcereader.cpp | |
parent | 0a6a8e3869dac3cdcf6e705e3604c58c6e3cbe1f (diff) | |
download | gstreamer-plugins-bad-75f6f79e571dbc3aee66c4ff4e55564c527e9c71.tar.gz |
mfvideosrc: Fix for negative MF stride
Negative stride value can be used in MediaFoundation to inform
whether memory layout is top-down or bottom-up manner. Note that
negative stride is allowed only for RGB, system memory.
See also
https://docs.microsoft.com/en-us/windows/win32/medfound/image-stride
Fixes: https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/1646
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2473>
Diffstat (limited to 'sys/mediafoundation/gstmfsourcereader.cpp')
-rw-r--r-- | sys/mediafoundation/gstmfsourcereader.cpp | 80 |
1 files changed, 66 insertions, 14 deletions
diff --git a/sys/mediafoundation/gstmfsourcereader.cpp b/sys/mediafoundation/gstmfsourcereader.cpp index 57a0a5a3b..ef53fdc13 100644 --- a/sys/mediafoundation/gstmfsourcereader.cpp +++ b/sys/mediafoundation/gstmfsourcereader.cpp @@ -85,6 +85,8 @@ struct _GstMFSourceReader GstMFStreamMediaType *cur_type; GstVideoInfo info; + gboolean top_down_image; + gboolean flushing; }; @@ -394,12 +396,38 @@ gst_mf_source_reader_start (GstMFSourceObject * object) } type = self->cur_type; + self->top_down_image = TRUE; if (GST_VIDEO_INFO_FORMAT (&self->info) != GST_VIDEO_FORMAT_ENCODED) { - hr = type->media_type->SetUINT32 (MF_MT_DEFAULT_STRIDE, - GST_VIDEO_INFO_PLANE_STRIDE (&self->info, 0)); - if (!gst_mf_result (hr)) - return FALSE; + UINT32 stride; + INT32 actual_stride = GST_VIDEO_INFO_PLANE_STRIDE (&self->info, 0); + + /* This MF_MT_DEFAULT_STRIDE uses UINT32 type but actual value is + * INT32, which can be negative in case of RGB image, and negative means + * its stored as bottom-up manner */ + hr = type->media_type->GetUINT32 (MF_MT_DEFAULT_STRIDE, &stride); + if (gst_mf_result (hr)) { + actual_stride = (INT32) stride; + if (actual_stride < 0) { + if (!GST_VIDEO_INFO_IS_RGB (&self->info)) { + GST_ERROR_OBJECT (self, + "Bottom-up image is allowed only for RGB format"); + return FALSE; + } + + GST_DEBUG_OBJECT (self, + "Detected bottom-up image, stride %d", actual_stride); + + self->top_down_image = FALSE; + } + } else { + /* If MF_MT_DEFAULT_STRIDE attribute is not specified, we can use our + * value */ + type->media_type->SetUINT32 (MF_MT_DEFAULT_STRIDE, + (UINT32) actual_stride); + } + gst_mf_update_video_info_with_stride (&self->info, + std::abs (actual_stride)); } hr = self->reader->SetStreamSelection (type->stream_index, TRUE); @@ -568,24 +596,48 @@ gst_mf_source_reader_fill (GstMFSourceObject * object, GstBuffer * buffer) return GST_FLOW_ERROR; } - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&self->info); i++) { + if (!self->top_down_image) { guint8 *src, *dst; gint src_stride, dst_stride; - gint width; + gint width, height; + + /* must be single plane RGB */ + width = GST_VIDEO_INFO_COMP_WIDTH (&self->info, 0) + * GST_VIDEO_INFO_COMP_PSTRIDE (&self->info, 0); + height = GST_VIDEO_INFO_HEIGHT (&self->info); - src = data + GST_VIDEO_INFO_PLANE_OFFSET (&self->info, i); - dst = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame, i); + src_stride = GST_VIDEO_INFO_PLANE_STRIDE (&self->info, 0); + dst_stride = GST_VIDEO_FRAME_PLANE_STRIDE (&frame, 0); - src_stride = GST_VIDEO_INFO_PLANE_STRIDE (&self->info, i); - dst_stride = GST_VIDEO_FRAME_PLANE_STRIDE (&frame, i); - width = GST_VIDEO_INFO_COMP_WIDTH (&self->info, i) - * GST_VIDEO_INFO_COMP_PSTRIDE (&self->info, i); + /* This is bottom up image, should copy lines in reverse order */ + src = data + src_stride * (height - 1); + dst = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame, 0); - for (j = 0; j < GST_VIDEO_INFO_COMP_HEIGHT (&self->info, i); j++) { + for (j = 0; j < height; j++) { memcpy (dst, src, width); - src += src_stride; + src -= src_stride; dst += dst_stride; } + } else { + for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&self->info); i++) { + guint8 *src, *dst; + gint src_stride, dst_stride; + gint width; + + src = data + GST_VIDEO_INFO_PLANE_OFFSET (&self->info, i); + dst = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame, i); + + src_stride = GST_VIDEO_INFO_PLANE_STRIDE (&self->info, i); + dst_stride = GST_VIDEO_FRAME_PLANE_STRIDE (&frame, i); + width = GST_VIDEO_INFO_COMP_WIDTH (&self->info, i) + * GST_VIDEO_INFO_COMP_PSTRIDE (&self->info, i); + + for (j = 0; j < GST_VIDEO_INFO_COMP_HEIGHT (&self->info, i); j++) { + memcpy (dst, src, width); + src += src_stride; + dst += dst_stride; + } + } } gst_video_frame_unmap (&frame); |