[vlc-devel] [PATCH] gstdecode: support alloc'ing vlc pictures with padding
Vikram Fugro
vikram.fugro at gmail.com
Fri Mar 11 13:16:11 CET 2016
Allocate the output vlc pictures with dimensions padded,
as requested by the decoder (for alignments). This further
increases the chances of direct rendering.
---
modules/codec/gstreamer/gstdecode.c | 4 +-
.../codec/gstreamer/gstvlcpictureplaneallocator.c | 87 ++++++++++++++--------
.../codec/gstreamer/gstvlcpictureplaneallocator.h | 6 +-
modules/codec/gstreamer/gstvlcvideopool.c | 41 +++++++++-
modules/codec/gstreamer/gstvlcvideopool.h | 2 +
modules/codec/gstreamer/gstvlcvideosink.c | 16 +---
6 files changed, 106 insertions(+), 50 deletions(-)
diff --git a/modules/codec/gstreamer/gstdecode.c b/modules/codec/gstreamer/gstdecode.c
index 42c6b27..ecaf2a2 100644
--- a/modules/codec/gstreamer/gstdecode.c
+++ b/modules/codec/gstreamer/gstdecode.c
@@ -179,6 +179,7 @@ static gboolean caps_handoff_cb( GstElement* p_ele, GstCaps *p_caps,
VLC_UNUSED( p_ele );
decoder_t *p_dec = p_data;
decoder_sys_t *p_sys = p_dec->p_sys;
+ GstVideoAlignment align;
msg_Info( p_dec, "got new caps %s", gst_caps_to_string( p_caps ));
@@ -189,8 +190,9 @@ static gboolean caps_handoff_cb( GstElement* p_ele, GstCaps *p_caps,
}
gst_vlc_dec_ensure_empty_queue( p_dec );
+ gst_video_alignment_reset( &align );
- return gst_vlc_set_vout_fmt( &p_sys->vinfo, p_caps, p_dec );
+ return gst_vlc_set_vout_fmt( &p_sys->vinfo, &align, p_caps, p_dec );
}
/* Emitted by vlcvideosink for every buffer,
diff --git a/modules/codec/gstreamer/gstvlcpictureplaneallocator.c b/modules/codec/gstreamer/gstvlcpictureplaneallocator.c
index 4e827eb..089c549 100644
--- a/modules/codec/gstreamer/gstvlcpictureplaneallocator.c
+++ b/modules/codec/gstreamer/gstvlcpictureplaneallocator.c
@@ -197,8 +197,8 @@ bool gst_vlc_picture_plane_allocator_alloc(
GstVlcPicturePlane *p_mem =
(GstVlcPicturePlane*) g_slice_new0( GstVlcPicturePlane );
- i_size = p_pic->p[ i_plane ].i_visible_pitch *
- p_pic->p[ i_plane ].i_visible_lines;
+ i_size = p_pic->p[ i_plane ].i_pitch *
+ p_pic->p[ i_plane ].i_lines;
i_max_size = p_pic->p[ i_plane ].i_pitch *
p_pic->p[ i_plane ].i_lines;
i_align = 0;
@@ -213,13 +213,14 @@ bool gst_vlc_picture_plane_allocator_alloc(
return true;
}
-bool gst_vlc_set_vout_fmt( GstVideoInfo *p_info, GstCaps *p_caps,
- decoder_t *p_dec )
+bool gst_vlc_set_vout_fmt( GstVideoInfo *p_info, GstVideoAlignment *p_align,
+ GstCaps *p_caps, decoder_t *p_dec )
{
es_format_t *p_outfmt = &p_dec->fmt_out;
video_format_t *p_voutfmt = &p_dec->fmt_out.video;
GstStructure *p_str = gst_caps_get_structure( p_caps, 0 );
vlc_fourcc_t i_chroma;
+ int i_padded_width, i_padded_height;
i_chroma = p_outfmt->i_codec = vlc_fourcc_GetCodecFromString(
VIDEO_ES,
@@ -230,10 +231,16 @@ bool gst_vlc_set_vout_fmt( GstVideoInfo *p_info, GstCaps *p_caps,
return false;
}
- video_format_Setup( &p_dec->fmt_out.video, i_chroma,
- GST_VIDEO_INFO_WIDTH( p_info ), GST_VIDEO_INFO_HEIGHT( p_info ),
+ i_padded_width = GST_VIDEO_INFO_WIDTH( p_info ) + p_align->padding_left +
+ p_align->padding_right;
+ i_padded_height = GST_VIDEO_INFO_HEIGHT( p_info ) + p_align->padding_top +
+ p_align->padding_bottom;
+
+ video_format_Setup( p_voutfmt, i_chroma, i_padded_width, i_padded_height,
GST_VIDEO_INFO_WIDTH( p_info ), GST_VIDEO_INFO_HEIGHT( p_info ),
GST_VIDEO_INFO_PAR_N( p_info ), GST_VIDEO_INFO_PAR_D( p_info ));
+ p_voutfmt->i_x_offset = p_align->padding_left;
+ p_voutfmt->i_y_offset = p_align->padding_top;
p_voutfmt->i_frame_rate = GST_VIDEO_INFO_FPS_N( p_info );
p_voutfmt->i_frame_rate_base = GST_VIDEO_INFO_FPS_D( p_info );
@@ -241,15 +248,19 @@ bool gst_vlc_set_vout_fmt( GstVideoInfo *p_info, GstCaps *p_caps,
return true;
}
-static bool gst_vlc_video_info_from_vout( GstVideoInfo *p_info, GstCaps *p_caps,
- decoder_t *p_dec, picture_t *p_pic_info )
+static bool gst_vlc_video_info_from_vout( GstVideoInfo *p_info,
+ GstVideoAlignment *p_align, GstCaps *p_caps, decoder_t *p_dec,
+ picture_t *p_pic_info )
{
+ const GstVideoFormatInfo *p_vinfo = p_info->finfo;
picture_t *p_pic;
+ int i;
/* Ensure the queue is empty */
gst_vlc_dec_ensure_empty_queue( p_dec );
+ gst_video_info_align( p_info, p_align );
- if( !gst_vlc_set_vout_fmt( p_info, p_caps, p_dec ))
+ if( !gst_vlc_set_vout_fmt( p_info, p_align, p_caps, p_dec ))
{
msg_Err( p_dec, "failed to set output format to vout" );
return false;
@@ -265,52 +276,70 @@ static bool gst_vlc_video_info_from_vout( GstVideoInfo *p_info, GstCaps *p_caps,
return false;
}
+ /* reject if strides don't match */
+ for( i = 0; i < p_pic->i_planes; i++ )
+ if( p_info->stride[i] != p_pic->p[i].i_pitch )
+ goto strides_mismatch;
+
+ p_info->offset[0] = 0;
+ for( i = 1; i < p_pic->i_planes; i++ )
+ {
+ p_info->offset[i] = p_info->offset[i-1] +
+ p_pic->p[i-1].i_pitch * p_pic->p[i-1].i_lines;
+ }
+ GST_VIDEO_INFO_SIZE( p_info ) = p_info->offset[i-1] +
+ p_pic->p[i-1].i_pitch * p_pic->p[i-1].i_lines;
+
+ for( i = 0; i < p_pic->i_planes; i++ )
+ {
+ int i_v_edge, i_h_edge;
+
+ i_h_edge =
+ GST_VIDEO_FORMAT_INFO_SCALE_WIDTH( p_vinfo, i,
+ p_align->padding_left);
+ i_v_edge =
+ GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT( p_vinfo, i,
+ p_align->padding_top);
+
+ p_info->offset[i] += ( i_v_edge * p_info->stride[i] ) +
+ ( i_h_edge * GST_VIDEO_FORMAT_INFO_PSTRIDE( p_vinfo, i ));
+ }
+
memcpy( p_pic_info, p_pic, sizeof( picture_t ));
picture_Release( p_pic );
return true;
+
+strides_mismatch:
+ msg_Err( p_dec, "strides mismatch" );
+ picture_Release( p_pic );
+ return false;
}
bool gst_vlc_picture_plane_allocator_query_format(
- GstVlcPicturePlaneAllocator *p_allocator,
- GstVideoInfo *p_info, GstCaps *p_caps )
+ GstVlcPicturePlaneAllocator *p_allocator, GstVideoInfo *p_info,
+ GstVideoAlignment *p_align, GstCaps *p_caps )
{
decoder_t *p_dec = p_allocator->p_dec;
video_format_t v_fmt;
picture_t *p_pic_info = &p_allocator->pic_info;
- int i_plane, i_offset = 0, i_size = 0;
/* Back up the original format; as this is just a query */
memcpy( &v_fmt, &p_dec->fmt_out.video, sizeof( video_format_t ));
- if( !gst_vlc_video_info_from_vout( p_info, p_caps, p_dec, p_pic_info ))
+ if( !gst_vlc_video_info_from_vout( p_info, p_align, p_caps, p_dec,
+ p_pic_info ))
{
msg_Err( p_allocator->p_dec, "failed to get the vout info" );
return false;
}
- //GST_VIDEO_INFO_N_PLANES( p_info ) = p_pic_info->i_planes;
- for( i_plane = 0; i_plane < p_pic_info->i_planes; i_plane++ )
- {
- GST_VIDEO_INFO_PLANE_STRIDE( p_info, i_plane ) =
- p_pic_info->p[ i_plane ].i_pitch;
- GST_VIDEO_INFO_PLANE_OFFSET( p_info, i_plane ) = i_offset;
- //i_offset += p_pic_info->p[ i_plane ].i_pitch *
- //p_pic_info->p[ i_plane ].i_lines;
- i_offset += p_pic_info->p[ i_plane ].i_visible_pitch *
- p_pic_info->p[ i_plane ].i_visible_lines;
- i_size += p_pic_info->p[ i_plane ].i_visible_pitch *
- p_pic_info->p[ i_plane ].i_visible_lines;
- }
- GST_VIDEO_INFO_SIZE( p_info ) = i_size;
-
/* Restore the original format; as this was just a query */
memcpy( &p_dec->fmt_out.video, &v_fmt, sizeof( video_format_t ));
return true;
}
-
GstVlcPicturePlaneAllocator* gst_vlc_picture_plane_allocator_new(
decoder_t *p_dec )
{
diff --git a/modules/codec/gstreamer/gstvlcpictureplaneallocator.h b/modules/codec/gstreamer/gstvlcpictureplaneallocator.h
index bd27575..7607b4a 100644
--- a/modules/codec/gstreamer/gstvlcpictureplaneallocator.h
+++ b/modules/codec/gstreamer/gstvlcpictureplaneallocator.h
@@ -77,9 +77,9 @@ GstVlcPicturePlaneAllocator* gst_vlc_picture_plane_allocator_new(
decoder_t *p_dec );
bool gst_vlc_picture_plane_allocator_query_format(
GstVlcPicturePlaneAllocator *p_gallocator, GstVideoInfo *p_info,
- GstCaps *p_caps );
-bool gst_vlc_set_vout_fmt( GstVideoInfo *p_info, GstCaps *p_caps,
- decoder_t *p_dec );
+ GstVideoAlignment *p_align, GstCaps *p_caps );
+bool gst_vlc_set_vout_fmt( GstVideoInfo *p_info, GstVideoAlignment *p_align,
+ GstCaps *p_caps, decoder_t *p_dec );
void gst_vlc_dec_ensure_empty_queue( decoder_t* p_dec );
bool gst_vlc_picture_plane_allocator_hold( GstVlcPicturePlaneAllocator
*p_allocator, GstBuffer *p_buffer );
diff --git a/modules/codec/gstreamer/gstvlcvideopool.c b/modules/codec/gstreamer/gstvlcvideopool.c
index c22b501..f28b9bd 100644
--- a/modules/codec/gstreamer/gstvlcvideopool.c
+++ b/modules/codec/gstreamer/gstvlcvideopool.c
@@ -40,7 +40,7 @@ static const gchar** gst_vlc_video_pool_get_options (GstBufferPool *p_pool)
VLC_UNUSED( p_pool );
static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META,
- NULL
+ GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT, NULL
};
return options;
@@ -52,6 +52,7 @@ static gboolean gst_vlc_video_pool_set_config( GstBufferPool *p_pool,
GstVlcVideoPool *p_vpool = GST_VLC_VIDEO_POOL_CAST( p_pool );
GstCaps *p_caps;
GstVideoInfo info;
+ GstVideoAlignment align;
guint size, min_buffers, max_buffers;
GstAllocator *p_allocator;
GstAllocationParams params;
@@ -59,7 +60,6 @@ static gboolean gst_vlc_video_pool_set_config( GstBufferPool *p_pool,
if( !gst_buffer_pool_config_get_params( p_config, &p_caps, &size,
&min_buffers, &max_buffers ))
goto wrong_config;
-
if( p_caps == NULL )
goto no_caps;
@@ -85,14 +85,37 @@ static gboolean gst_vlc_video_pool_set_config( GstBufferPool *p_pool,
gst_buffer_pool_config_has_option( p_config,
GST_BUFFER_POOL_OPTION_VIDEO_META );
+ p_vpool->b_need_aligned =
+ gst_buffer_pool_config_has_option( p_config,
+ GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT );
+
+ if( p_vpool->b_need_aligned )
+ {
+ p_vpool->b_add_metavideo = true;
+ gst_buffer_pool_config_get_video_alignment( p_config, &align );
+ }
+ else
+ gst_video_alignment_reset( &align );
+
+ // FIXME: the gst decoders' min buffers may not be equal to the number
+ // of buffers it actually allocates. Also the max buffers here could
+ // be zero. Moreover even if it was right, need to check if it can be
+ // communicated to the vout (including the dpb_size it calculates in
+ // src/input/decoder.c).
+ p_vpool->p_dec->i_extra_picture_buffers = 16;
+
if( !gst_vlc_picture_plane_allocator_query_format( p_vpool->p_allocator,
- &info, p_caps))
+ &info, &align, p_caps))
goto unknown_format;
+ if( p_vpool->b_need_aligned )
+ gst_buffer_pool_config_set_video_alignment( p_config, &align);
+
if( p_vpool->p_caps )
gst_caps_unref( p_vpool->p_caps );
p_vpool->p_caps = gst_caps_ref( p_caps );
p_vpool->info = info;
+ p_vpool->align = align;
msg_Dbg( p_vpool->p_dec, "setting the following config on the pool: %s, \
size: %lu, min buffers: %u, max buffers: %u", gst_caps_to_string( p_caps ),
@@ -206,6 +229,17 @@ static GstFlowReturn gst_vlc_video_pool_alloc_buffer( GstBufferPool *p_pool,
return GST_FLOW_OK;
}
+static gboolean gst_vlc_video_pool_start( GstBufferPool *p_pool )
+{
+ GstVlcVideoPool *p_vpool = GST_VLC_VIDEO_POOL_CAST( p_pool );
+
+ if( !gst_vlc_set_vout_fmt( &p_vpool->info, &p_vpool->align,
+ p_vpool->p_caps, p_vpool->p_dec ))
+ return FALSE;
+
+ return GST_BUFFER_POOL_CLASS( parent_class )->start( p_pool );
+}
+
static void gst_vlc_video_pool_class_init( GstVlcVideoPoolClass *p_klass )
{
GObjectClass *p_gobject_class = ( GObjectClass* )p_klass;
@@ -213,6 +247,7 @@ static void gst_vlc_video_pool_class_init( GstVlcVideoPoolClass *p_klass )
p_gobject_class->finalize = gst_vlc_video_pool_finalize;
+ p_gstbufferpool_class->start = gst_vlc_video_pool_start;
p_gstbufferpool_class->get_options = gst_vlc_video_pool_get_options;
p_gstbufferpool_class->set_config = gst_vlc_video_pool_set_config;
p_gstbufferpool_class->alloc_buffer = gst_vlc_video_pool_alloc_buffer;
diff --git a/modules/codec/gstreamer/gstvlcvideopool.h b/modules/codec/gstreamer/gstvlcvideopool.h
index 721befd..373a566 100644
--- a/modules/codec/gstreamer/gstvlcvideopool.h
+++ b/modules/codec/gstreamer/gstvlcvideopool.h
@@ -51,7 +51,9 @@ struct _GstVlcVideoPool
GstCaps *p_caps;
GstVideoInfo info;
+ GstVideoAlignment align;
bool b_add_metavideo;
+ bool b_need_aligned;
decoder_t *p_dec;
};
diff --git a/modules/codec/gstreamer/gstvlcvideosink.c b/modules/codec/gstreamer/gstvlcvideosink.c
index 5dfd8cd..6988e0d 100644
--- a/modules/codec/gstreamer/gstvlcvideosink.c
+++ b/modules/codec/gstreamer/gstvlcvideosink.c
@@ -208,7 +208,6 @@ static gboolean gst_vlc_video_sink_propose_allocation( GstBaseSink* p_bsink,
gsize i_size;
gst_query_parse_allocation (p_query, &p_caps, &b_need_pool);
-
if( p_caps == NULL )
goto no_caps;
@@ -219,18 +218,12 @@ static gboolean gst_vlc_video_sink_propose_allocation( GstBaseSink* p_bsink,
if( !gst_video_info_from_caps( &info, p_caps ))
goto invalid_caps;
- if( !gst_vlc_picture_plane_allocator_query_format(
- (GstVlcPicturePlaneAllocator*) p_vsink->p_allocator,
- &info, p_caps ))
- goto invalid_format;
-
p_pool = (GstBufferPool*) gst_vlc_video_sink_create_pool( p_vsink,
- p_caps, info.size, 0 );
-
+ p_caps, info.size, 2 );
if( p_pool == NULL )
goto no_pool;
- i_size = info.size;
+ i_size = GST_VIDEO_INFO_SIZE( &GST_VLC_VIDEO_POOL_CAST( p_pool )->info);
}
if( p_pool )
@@ -261,11 +254,6 @@ invalid_caps:
msg_Err( p_vsink->p_dec, "invalid caps in allocation query" );
return FALSE;
}
-invalid_format:
- {
- msg_Err( p_vsink->p_dec, "vout query returned invalid format" );
- return FALSE;
- }
}
static GstFlowReturn gst_vlc_video_sink_chain( GstBaseSink *p_bsink,
--
2.5.0
More information about the vlc-devel
mailing list