@@ -100,6 +100,11 @@ enum {
100100 PROP_MAX
101101};
102102
103+ typedef struct {
104+ GstBuffer * buf ;
105+ GstMapInfo dest_info ;
106+ } GstSt20pRxExternalData ;
107+
103108/* pad template */
104109static GstStaticPadTemplate gst_mtl_st20p_rx_src_pad_template =
105110 GST_STATIC_PAD_TEMPLATE ("src" , GST_PAD_SRC , GST_PAD_ALWAYS ,
@@ -125,8 +130,15 @@ static void gst_mtl_st20p_rx_finalize(GObject* object);
125130
126131static gboolean gst_mtl_st20p_rx_start (GstBaseSrc * basesrc );
127132static gboolean gst_mtl_st20p_rx_negotiate (GstBaseSrc * basesrc );
128- static GstFlowReturn gst_mtl_st20p_rx_create (GstBaseSrc * basesrc , guint64 offset ,
129- guint length , GstBuffer * * buffer );
133+ static GstFlowReturn gst_mtl_st20p_rx_chain (GstBaseSrc * basesrc , guint64 offset ,
134+ guint length , GstBuffer * * buffer );
135+
136+ static GstFlowReturn gst_mtl_st20p_rx_get_external_frame (Gst_Mtl_St20p_Rx * src ,
137+ GstBuffer * * buffer );
138+ static GstFlowReturn gst_mtl_st20p_rx_get_internal_frame (Gst_Mtl_St20p_Rx * src ,
139+ GstBuffer * * buffer );
140+ static int gst_mtl_st20p_rx_query_ext_frame (void * priv , struct st_ext_frame * ext_frame ,
141+ struct st20_rx_frame_meta * meta );
130142
131143static void gst_mtl_st20p_rx_class_init (Gst_Mtl_St20p_RxClass * klass ) {
132144 GObjectClass * gobject_class ;
@@ -151,7 +163,7 @@ static void gst_mtl_st20p_rx_class_init(Gst_Mtl_St20p_RxClass* klass) {
151163
152164 gstbasesrc_class -> start = GST_DEBUG_FUNCPTR (gst_mtl_st20p_rx_start );
153165 gstbasesrc_class -> negotiate = GST_DEBUG_FUNCPTR (gst_mtl_st20p_rx_negotiate );
154- gstbasesrc_class -> create = GST_DEBUG_FUNCPTR (gst_mtl_st20p_rx_create );
166+ gstbasesrc_class -> create = GST_DEBUG_FUNCPTR (gst_mtl_st20p_rx_chain );
155167
156168 gst_mtl_common_init_general_arguments (gobject_class );
157169
@@ -196,10 +208,9 @@ static void gst_mtl_st20p_rx_class_init(Gst_Mtl_St20p_RxClass* klass) {
196208}
197209
198210static gboolean gst_mtl_st20p_rx_start (GstBaseSrc * basesrc ) {
199- struct st20p_rx_ops * ops_rx ;
211+ struct st20p_rx_ops ops_rx = { 0 } ;
200212
201213 Gst_Mtl_St20p_Rx * src = GST_MTL_ST20P_RX (basesrc );
202- ops_rx = & src -> ops_rx ;
203214
204215 GST_DEBUG_OBJECT (src , "start" );
205216 GST_DEBUG ("Media Transport Initialization start" );
@@ -223,42 +234,62 @@ static gboolean gst_mtl_st20p_rx_start(GstBaseSrc* basesrc) {
223234 return FALSE;
224235 }
225236
226- ops_rx -> name = "st20src" ;
227- ops_rx -> device = ST_PLUGIN_DEVICE_AUTO ;
228- ops_rx -> width = src -> width ;
229- ops_rx -> height = src -> height ;
230- ops_rx -> transport_fmt = ST20_FMT_YUV_422_10BIT ;
231- ops_rx -> interlaced = src -> interlaced ;
232- ops_rx -> flags |= ST20P_RX_FLAG_BLOCK_GET ;
237+ ops_rx . name = "st20src" ;
238+ ops_rx . device = ST_PLUGIN_DEVICE_AUTO ;
239+ ops_rx . width = src -> width ;
240+ ops_rx . height = src -> height ;
241+ ops_rx . transport_fmt = ST20_FMT_YUV_422_10BIT ;
242+ ops_rx . interlaced = src -> interlaced ;
243+ ops_rx . flags |= ST20P_RX_FLAG_BLOCK_GET ;
233244
234- ops_rx -> fps = st_frame_rate_to_st_fps ((double )src -> fps_n / src -> fps_d );
235- if (ops_rx -> fps == ST_FPS_MAX ) {
245+ ops_rx . fps = st_frame_rate_to_st_fps ((double )src -> fps_n / src -> fps_d );
246+ if (ops_rx . fps == ST_FPS_MAX ) {
236247 GST_ERROR ("Invalid framerate: %d/%d" , src -> fps_n , src -> fps_d );
237248 return FALSE;
238249 }
239250
240251 if (src -> framebuffer_num ) {
241- ops_rx -> framebuff_cnt = src -> framebuffer_num ;
252+ ops_rx . framebuff_cnt = src -> framebuffer_num ;
242253 } else {
243- ops_rx -> framebuff_cnt = 3 ;
254+ ops_rx . framebuff_cnt = 3 ;
244255 }
245256
246- if (!gst_mtl_common_parse_pixel_format (src -> pixel_format , & ops_rx -> output_fmt )) {
257+ if (!gst_mtl_common_parse_pixel_format (src -> pixel_format , & ops_rx . output_fmt )) {
247258 GST_ERROR ("Failed to parse input format \"%s\"" , src -> pixel_format );
248- ops_rx = NULL ;
249259 return FALSE;
250260 }
251261
262+ switch (ops_rx .output_fmt ) {
263+ case ST_FRAME_FMT_V210 :
264+ src -> format = GST_VIDEO_FORMAT_v210 ;
265+ break ;
266+ case ST_FRAME_FMT_YUV422PLANAR10LE :
267+ src -> format = GST_VIDEO_FORMAT_I422_10LE ;
268+ break ;
269+ default :
270+ GST_ERROR ("Unsupported pixel format" );
271+ return FALSE;
272+ }
273+
274+ src -> zero_copy = (ops_rx .transport_fmt != st_frame_fmt_to_transport (ops_rx .output_fmt ));
275+ if (src -> zero_copy ) {
276+ ops_rx .flags |= ST20P_RX_FLAG_EXT_FRAME ;
277+ ops_rx .query_ext_frame = gst_mtl_st20p_rx_query_ext_frame ;
278+ ops_rx .priv = src ;
279+ } else {
280+ GST_WARNING ("Using memcpy path" );
281+ }
282+
252283 gst_mtl_common_copy_general_to_session_args (& (src -> generalArgs ), & (src -> portArgs ));
253284
254- ops_rx -> port .num_port =
255- gst_mtl_common_parse_rx_port_arguments (& ops_rx -> port , & src -> portArgs );
256- if (!ops_rx -> port .num_port ) {
285+ ops_rx . port .num_port =
286+ gst_mtl_common_parse_rx_port_arguments (& ops_rx . port , & src -> portArgs );
287+ if (!ops_rx . port .num_port ) {
257288 GST_ERROR ("Failed to parse port arguments" );
258289 return FALSE;
259290 }
260291
261- src -> rx_handle = st20p_rx_create (src -> mtl_lib_handle , & src -> ops_rx );
292+ src -> rx_handle = st20p_rx_create (src -> mtl_lib_handle , & ops_rx );
262293 if (!src -> rx_handle ) {
263294 GST_ERROR ("Failed to create st20p rx handle" );
264295 return FALSE;
@@ -372,7 +403,6 @@ static void gst_mtl_st20p_rx_get_property(GObject* object, guint prop_id, GValue
372403static gboolean gst_mtl_st20p_rx_negotiate (GstBaseSrc * basesrc ) {
373404 GstVideoInfo * info ;
374405 Gst_Mtl_St20p_Rx * src = GST_MTL_ST20P_RX (basesrc );
375- struct st20p_rx_ops * ops_rx = & src -> ops_rx ;
376406 gint ret ;
377407 GstCaps * caps ;
378408
@@ -393,18 +423,7 @@ static gboolean gst_mtl_st20p_rx_negotiate(GstBaseSrc* basesrc) {
393423 info -> fps_n = src -> fps_n ;
394424 info -> fps_d = src -> fps_d ;
395425
396- switch (ops_rx -> output_fmt ) {
397- case ST_FRAME_FMT_V210 :
398- info -> finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_v210 );
399- break ;
400- case ST20_FMT_YUV_422_10BIT :
401- info -> finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_I422_10LE );
402- break ;
403- default :
404- GST_ERROR ("Unsupported pixel format" );
405- gst_video_info_free (info );
406- return FALSE;
407- }
426+ info -> finfo = gst_video_format_get_info (src -> format );
408427
409428 caps = gst_caps_new_simple (
410429 "video/x-raw" , "format" , G_TYPE_STRING ,
@@ -433,26 +452,47 @@ static gboolean gst_mtl_st20p_rx_negotiate(GstBaseSrc* basesrc) {
433452 return TRUE;
434453}
435454
436- static GstFlowReturn gst_mtl_st20p_rx_create (GstBaseSrc * basesrc , guint64 offset ,
437- guint length , GstBuffer * * buffer ) {
438- GstBuffer * buf ;
439- Gst_Mtl_St20p_Rx * src = GST_MTL_ST20P_RX (basesrc );
455+ static GstFlowReturn gst_mtl_st20p_rx_get_external_frame (Gst_Mtl_St20p_Rx * src ,
456+ GstBuffer * * buffer ) {
457+ struct st_frame * frame ;
458+ GstSt20pRxExternalData * ext_data ;
459+
460+ for (guint i = 0 ; i < src -> retry_frame ; i ++ ) {
461+ frame = st20p_rx_get_frame (src -> rx_handle );
462+ if (frame ) {
463+ break ;
464+ }
465+ }
466+
467+ if (!frame ) {
468+ GST_INFO ("Failed to get frame EOS" );
469+ return GST_FLOW_EOS ;
470+ }
471+
472+ ext_data = frame -> opaque ;
473+ * buffer = ext_data -> buf ;
474+ GST_BUFFER_PTS (* buffer ) = frame -> timestamp ;
475+
476+ gst_buffer_unmap (ext_data -> buf , & ext_data -> dest_info );
477+ st20p_rx_put_frame (src -> rx_handle , frame );
478+ free (ext_data );
479+
480+ return GST_FLOW_OK ;
481+ }
482+
483+ static GstFlowReturn gst_mtl_st20p_rx_get_internal_frame (Gst_Mtl_St20p_Rx * src ,
484+ GstBuffer * * buffer ) {
440485 struct st_frame * frame ;
441486 GstMapInfo dest_info ;
442- gint ret ;
443487 gsize fill_size ;
444488
445- buf = gst_buffer_new_allocate (NULL , src -> frame_size , NULL );
446- if (!buf ) {
489+ * buffer = gst_buffer_new_allocate (NULL , src -> frame_size , NULL );
490+ if (!* buffer ) {
447491 GST_ERROR ("Failed to allocate buffer" );
448492 return GST_FLOW_ERROR ;
449493 }
450494
451- * buffer = buf ;
452-
453- GST_OBJECT_LOCK (src );
454-
455- for (int i = 0 ; i < src -> retry_frame ; i ++ ) {
495+ for (guint i = 0 ; i < src -> retry_frame ; i ++ ) {
456496 frame = st20p_rx_get_frame (src -> rx_handle );
457497 if (frame ) {
458498 break ;
@@ -461,25 +501,39 @@ static GstFlowReturn gst_mtl_st20p_rx_create(GstBaseSrc* basesrc, guint64 offset
461501
462502 if (!frame ) {
463503 GST_INFO ("Failed to get frame EOS" );
464- GST_OBJECT_UNLOCK (src );
465504 return GST_FLOW_EOS ;
466505 }
467506
468- gst_buffer_map (buf , & dest_info , GST_MAP_WRITE );
507+ gst_buffer_map (* buffer , & dest_info , GST_MAP_WRITE );
469508
470- fill_size = gst_buffer_fill (buf , 0 , frame -> addr [0 ], src -> frame_size );
471- GST_BUFFER_PTS (buf ) = frame -> timestamp ;
509+ fill_size = gst_buffer_fill (* buffer , 0 , frame -> addr [0 ], src -> frame_size );
510+ GST_BUFFER_PTS (* buffer ) = frame -> timestamp ;
472511
473- gst_buffer_unmap (buf , & dest_info );
512+ gst_buffer_unmap (* buffer , & dest_info );
474513
475514 if (fill_size != src -> frame_size ) {
476515 GST_ERROR ("Failed to fill buffer" );
477- ret = GST_FLOW_ERROR ;
478- } else {
479- ret = GST_FLOW_OK ;
516+ return GST_FLOW_ERROR ;
480517 }
481518
482519 st20p_rx_put_frame (src -> rx_handle , frame );
520+
521+ return GST_FLOW_OK ;
522+ }
523+
524+ static GstFlowReturn gst_mtl_st20p_rx_chain (GstBaseSrc * basesrc , guint64 offset ,
525+ guint length , GstBuffer * * buffer ) {
526+ Gst_Mtl_St20p_Rx * src = GST_MTL_ST20P_RX (basesrc );
527+ gint ret = GST_FLOW_OK ;
528+
529+ GST_OBJECT_LOCK (src );
530+
531+ if (src -> zero_copy ) {
532+ ret = gst_mtl_st20p_rx_get_external_frame (src , buffer );
533+ } else {
534+ ret = gst_mtl_st20p_rx_get_internal_frame (src , buffer );
535+ }
536+
483537 GST_OBJECT_UNLOCK (src );
484538 return ret ;
485539}
@@ -511,3 +565,47 @@ GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, GST_VERSION_MINOR, mtl_st20p_rx,
511565 "software-based solution designed for high-throughput transmission" ,
512566 plugin_init , PACKAGE_VERSION , GST_LICENSE , GST_PACKAGE_NAME ,
513567 GST_PACKAGE_ORIGIN )
568+
569+ static int gst_mtl_st20p_rx_query_ext_frame (void * priv , struct st_ext_frame * ext_frame ,
570+ struct st20_rx_frame_meta * meta ) {
571+ GstVideoMeta * video_meta ;
572+ guint8 planes ;
573+ Gst_Mtl_St20p_Rx * s = (Gst_Mtl_St20p_Rx * )priv ;
574+
575+ GstSt20pRxExternalData * ext_data =
576+ (GstSt20pRxExternalData * )malloc (sizeof (GstSt20pRxExternalData ));
577+ if (!ext_data ) {
578+ GST_ERROR ("Failed to allocate memory for external data" );
579+ return GST_FLOW_ERROR ;
580+ }
581+
582+ ext_data -> buf = gst_buffer_new_allocate (NULL , s -> frame_size , NULL );
583+ if (!ext_data -> buf ) {
584+ GST_ERROR ("Failed to allocate buffer" );
585+ free (ext_data );
586+ return GST_FLOW_ERROR ;
587+ }
588+
589+ video_meta = gst_buffer_add_video_meta (ext_data -> buf , GST_VIDEO_FRAME_FLAG_NONE ,
590+ s -> format , s -> width , s -> height );
591+ if (!video_meta ) {
592+ GST_ERROR ("Failed to add video meta to buffer" );
593+ gst_buffer_unref (ext_data -> buf );
594+ free (ext_data );
595+ return GST_FLOW_ERROR ;
596+ }
597+
598+ gst_buffer_map (ext_data -> buf , & ext_data -> dest_info , GST_MAP_WRITE );
599+
600+ /* fill the ext frame */
601+ planes = st_frame_fmt_planes (video_meta -> n_planes );
602+ for (guint8 i = 0 ; i < planes ; i ++ ) {
603+ ext_frame -> addr [i ] = ext_data -> dest_info .data + video_meta -> offset [i ];
604+ ext_frame -> linesize [i ] = video_meta -> stride [i ];
605+ ext_frame -> iova [i ] = 0 ;
606+ }
607+ ext_frame -> size = s -> frame_size ;
608+ ext_frame -> opaque = ext_data ;
609+
610+ return GST_FLOW_OK ;
611+ }
0 commit comments