@@ -334,11 +334,6 @@ static void camera_format_list(struct camera_device *dev, obs_property_t *prop)
334334 struct spa_rectangle resolution ;
335335
336336 const struct spa_pod_prop * framerate_prop = NULL ;
337- struct spa_pod * framerate_pod ;
338- uint32_t n_framerates ;
339- enum spa_choice_type framerate_choice ;
340- const struct spa_fraction * framerate_values ;
341- g_autoptr (GArray ) framerates = NULL ;
342337
343338 if (p -> id != SPA_PARAM_EnumFormat || p -> param == NULL )
344339 continue ;
@@ -378,61 +373,68 @@ static void camera_format_list(struct camera_device *dev, obs_property_t *prop)
378373 obs_data_set_int (data , "height" , resolution .height );
379374
380375 framerate_prop = spa_pod_find_prop (p -> param , NULL , SPA_FORMAT_VIDEO_framerate );
381- if (!framerate_prop )
382- continue ;
376+ if (framerate_prop ) {
377+ struct spa_pod * framerate_pod ;
378+ uint32_t n_framerates ;
379+ enum spa_choice_type framerate_choice ;
380+ const struct spa_fraction * framerate_values ;
381+ g_autoptr (GArray ) framerates = NULL ;
382+
383+ framerate_pod = spa_pod_get_values (& framerate_prop -> value , & n_framerates , & framerate_choice );
384+ if (framerate_pod -> type != SPA_TYPE_Fraction ) {
385+ blog (LOG_WARNING , "Framerate is not a fraction" );
386+ continue ;
387+ }
383388
384- framerate_pod = spa_pod_get_values (& framerate_prop -> value , & n_framerates , & framerate_choice );
385- if (framerate_pod -> type != SPA_TYPE_Fraction ) {
386- blog (LOG_WARNING , "Framerate is not a fraction" );
387- continue ;
388- }
389+ framerate_values = SPA_POD_BODY (framerate_pod );
390+ framerates = g_array_new (FALSE, FALSE, sizeof (struct spa_fraction ));
389391
390- framerate_values = SPA_POD_BODY (framerate_pod );
391- framerates = g_array_new (FALSE, FALSE, sizeof (struct spa_fraction ));
392+ switch (framerate_choice ) {
393+ case SPA_CHOICE_None :
394+ g_array_append_val (framerates , framerate_values [0 ]);
395+ break ;
396+ case SPA_CHOICE_Range :
397+ blog (LOG_WARNING , "Ranged framerates not supported" );
398+ continue ;
399+ case SPA_CHOICE_Step :
400+ blog (LOG_WARNING , "Stepped framerates not supported" );
401+ continue ;
402+ case SPA_CHOICE_Enum :
403+ /* i=0 is the default framerate, skip it */
404+ for (uint32_t i = 1 ; i < n_framerates ; i ++ )
405+ g_array_append_val (framerates , framerate_values [i ]);
406+ break ;
407+ default :
408+ continue ;
409+ }
392410
393- switch (framerate_choice ) {
394- case SPA_CHOICE_None :
395- g_array_append_val (framerates , framerate_values [0 ]);
396- break ;
397- case SPA_CHOICE_Range :
398- blog (LOG_WARNING , "Ranged framerates not supported" );
399- continue ;
400- case SPA_CHOICE_Step :
401- blog (LOG_WARNING , "Stepped framerates not supported" );
402- continue ;
403- case SPA_CHOICE_Enum :
404- /* i=0 is the default framerate, skip it */
405- for (uint32_t i = 1 ; i < n_framerates ; i ++ )
406- g_array_append_val (framerates , framerate_values [i ]);
407- break ;
408- default :
409- continue ;
410- }
411+ dstr_printf (& str , "%ux%u" , resolution .width , resolution .height );
411412
412- dstr_printf (& str , "%ux%u" , resolution .width , resolution .height );
413+ aspect_ratio = aspect_ratio_from_spa_rectangle (resolution );
414+ if (aspect_ratio .len != 0 ) {
415+ dstr_catf (& str , " (%s)" , aspect_ratio .array );
416+ dstr_free (& aspect_ratio );
417+ }
413418
414- aspect_ratio = aspect_ratio_from_spa_rectangle (resolution );
415- if (aspect_ratio .len != 0 ) {
416- dstr_catf (& str , " (%s)" , aspect_ratio .array );
417- dstr_free (& aspect_ratio );
418- }
419+ dstr_cat (& str , " - " );
419420
420- dstr_cat (& str , " - " );
421+ for (int i = framerates -> len - 1 ; i >= 0 ; i -- ) {
422+ const struct spa_fraction * framerate =
423+ & g_array_index (framerates , struct spa_fraction , i );
421424
422- for ( int i = framerates -> len - 1 ; i >= 0 ; i -- ) {
423- const struct spa_fraction * framerate = & g_array_index ( framerates , struct spa_fraction , i );
425+ if ( i != ( int ) framerates -> len - 1 )
426+ dstr_cat ( & str , ", " );
424427
425- if (i != (int )framerates -> len - 1 )
426- dstr_cat (& str , ", " );
428+ if (framerate -> denom == 1 )
429+ dstr_catf (& str , "%u" , framerate -> num );
430+ else
431+ dstr_catf (& str , "%.2f" , framerate -> num / (double )framerate -> denom );
432+ }
427433
428- if (framerate -> denom == 1 )
429- dstr_catf (& str , "%u" , framerate -> num );
430- else
431- dstr_catf (& str , "%.2f" , framerate -> num / (double )framerate -> denom );
434+ dstr_cat (& str , " FPS" );
432435 }
433436
434- dstr_catf (& str , " FPS - %s" , format_name );
435-
437+ dstr_catf (& str , " - %s" , format_name );
436438 obs_property_list_add_string (prop , str .array , obs_data_get_json (data ));
437439 dstr_free (& str );
438440 }
@@ -635,7 +637,7 @@ static int compare_framerates(gconstpointer a, gconstpointer b)
635637 return da - db ;
636638}
637639
638- static void framerate_list (struct camera_device * dev , uint32_t pixelformat , const struct spa_rectangle * resolution ,
640+ static bool framerate_list (struct camera_device * dev , uint32_t pixelformat , const struct spa_rectangle * resolution ,
639641 obs_property_t * prop )
640642{
641643 g_autoptr (GArray ) framerates = NULL ;
@@ -739,6 +741,8 @@ static void framerate_list(struct camera_device *dev, uint32_t pixelformat, cons
739741 dstr_free (& str );
740742 }
741743 obs_data_release (data );
744+
745+ return framerates -> len != 0 ;
742746}
743747
744748static bool parse_framerate (struct spa_fraction * dest , const char * json )
@@ -826,6 +830,7 @@ static bool format_selected(void *data, obs_properties_t *properties, obs_proper
826830 struct camera_device * device ;
827831 enum spa_media_subtype last_subtype = camera_source -> subtype ;
828832 enum spa_video_format last_format = camera_source -> format .spa_format ;
833+ bool has_framerates ;
829834
830835 blog (LOG_INFO , "[camera-portal] Selected format for '%s'" , camera_source -> device_id );
831836
@@ -845,7 +850,18 @@ static bool format_selected(void *data, obs_properties_t *properties, obs_proper
845850 }
846851
847852 property = obs_properties_get (properties , "framerate" );
848- framerate_list (device , camera_source -> format .spa_format , & camera_source -> resolution .rect , property );
853+ obs_property_set_modified_callback2 (property , NULL , NULL );
854+
855+ has_framerates =
856+ framerate_list (device , camera_source -> format .spa_format , & camera_source -> resolution .rect , property );
857+ obs_property_set_enabled (property , has_framerates );
858+
859+ if (has_framerates ) {
860+ obs_property_set_modified_callback2 (property , framerate_selected , camera_source );
861+ obs_property_modified (property , settings );
862+ } else if (camera_source -> obs_pw_stream ) {
863+ obs_pipewire_stream_set_framerate (camera_source -> obs_pw_stream , NULL );
864+ }
849865
850866 return true;
851867}
@@ -1260,7 +1276,6 @@ static obs_properties_t *pipewire_camera_get_properties(void *data)
12601276
12611277 obs_property_set_modified_callback2 (device_list , device_selected , camera_source );
12621278 obs_property_set_modified_callback2 (format_list , format_selected , camera_source );
1263- obs_property_set_modified_callback2 (framerate_list , framerate_selected , camera_source );
12641279
12651280 return props ;
12661281}
0 commit comments