8484#include "video_codec.h" // for vc_get_linesize, vc_get_datalen
8585#include "video_frame.h" // for parse_fps, vf_alloc_desc, vf_...
8686
87- #define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_RATE * AUDIO_BPS * \
88- s->audio.ch_count * BUFFER_SEC)
89- #define AUDIO_BPS 2
90- #define AUDIO_SAMPLE_RATE 48000
91- #define BANNER_HEIGHT 150L
92- #define BANNER_MARGIN_BOTTOM 75L
93- #define BUFFER_SEC 1
9487#define EPS_PLUS_1 1.0001
95- #define FONT_HEIGHT 108
9688enum {
97- NOISE_DEFAULT = 30 ,
89+ AUDIO_BPS = 2 ,
90+ AUDIO_FREQUENCY = 200 ,
91+ AUDIO_SAMPLE_RATE = 48000 ,
92+ BANNER_HEIGHT = 150 ,
93+ BANNER_MARGIN_BOTTOM = 75 ,
94+ BUFFER_SEC = 1 ,
95+ FONT_HEIGHT = 108 ,
96+ NOISE_DEFAULT = 30 ,
9897};
9998
100- #define DEFAULT_FORMAT "1920:1080:24:UYVY"
99+ #define DEFAULT_FORMAT \
100+ (struct video_desc){ 1920, 1080, UYVY, 24, PROGRESSIVE, 1 }
101101#define MOD_NAME "[testcard2] "
102102
103103#ifdef HAVE_SDL3
@@ -127,35 +127,40 @@ struct testcard_state2 {
127127 seconds_tone_played ;
128128 struct timeval last_audio_time ;
129129 char * audio_tone , * audio_silence ;
130- unsigned int grab_audio : 1 ;
130+ bool grab_audio ;
131131 sem_t semaphore ;
132132
133133 pthread_t thread_id ;
134134
135135 volatile bool should_exit ;
136136};
137137
138- static int configure_audio (struct testcard_state2 * s )
138+ static void
139+ configure_audio (struct testcard_state2 * s )
139140{
140141 s -> audio .bps = AUDIO_BPS ;
141142 s -> audio .ch_count = audio_capture_channels > 0 ? audio_capture_channels : DEFAULT_AUDIO_CAPTURE_CHANNELS ;
142143 s -> audio .sample_rate = AUDIO_SAMPLE_RATE ;
143-
144- s -> audio_silence = calloc (1 , AUDIO_BUFFER_SIZE /* 1 sec */ );
145-
146- s -> audio_tone = calloc (1 , AUDIO_BUFFER_SIZE /* 1 sec */ );
144+
145+ const size_t audio_buffer_size = (size_t ) AUDIO_SAMPLE_RATE *
146+ AUDIO_BPS * s -> audio .ch_count *
147+ BUFFER_SEC ;
148+ s -> audio_silence = calloc (1 , audio_buffer_size );
149+ s -> audio_tone = calloc (1 , audio_buffer_size );
147150 short int * data = (short int * )(void * ) s -> audio_tone ;
148- for (int i = 0 ; i < (int ) AUDIO_BUFFER_SIZE /2 ; i += 2 )
149- {
150- data [i ] = data [i + 1 ] = (float ) sin ( ((double )i /(double )200 ) * M_PI * 2. ) * SHRT_MAX ;
151+ for (size_t i = 0 ; i < audio_buffer_size / 2 ; i += 2 ) {
152+ data [i ] = data [i + 1 ] =
153+ (float ) sin (((double ) i / (double ) AUDIO_FREQUENCY ) * M_PI *
154+ 2. ) *
155+ SHRT_MAX ;
151156 }
152157
153158 printf ("[testcard2] playing audio\n" );
154-
155- return 0 ;
156159}
157160
158- static bool parse_fmt (struct testcard_state2 * s , char * fmt ) {
161+ static bool
162+ parse_fmt_positional (struct testcard_state2 * s , char * fmt )
163+ {
159164 char * save_ptr = 0 ;
160165 char * tmp = strtok_r (fmt , ":" , & save_ptr );
161166 if (!tmp ) {
@@ -198,92 +203,103 @@ static bool parse_fmt(struct testcard_state2 *s, char *fmt) {
198203 return true;
199204}
200205
206+ static bool
207+ parse_fmt (struct testcard_state2 * s , char * fmt )
208+ {
209+ bool ret = true;
210+ char * save_ptr = NULL ;
211+ char * tmp = strtok_r (fmt , ":" , & save_ptr );
212+ while (tmp ) {
213+ if (IS_KEY_PREFIX (tmp , "codec" )) {
214+ s -> desc .color_spec =
215+ get_codec_from_name (strchr (tmp , '=' ) + 1 );
216+ if (s -> desc .color_spec == VIDEO_CODEC_NONE ) {
217+ log_msg (LOG_LEVEL_ERROR ,
218+ MOD_NAME "Wrong color spec: %s\n" ,
219+ strchr (tmp , '=' ) + 1 );
220+ return ret ;
221+ }
222+ } else if (IS_KEY_PREFIX (tmp , "mode" )) {
223+ codec_t saved_codec = s -> desc .color_spec ;
224+ s -> desc =
225+ get_video_desc_from_string (strchr (tmp , '=' ) + 1 );
226+ s -> desc .color_spec = saved_codec ;
227+ } else if (IS_KEY_PREFIX (tmp , "size" )) {
228+ tmp = strchr (tmp , '=' ) + 1 ;
229+ if (isdigit (tmp [0 ]) && strchr (tmp , 'x' ) != NULL ) {
230+ s -> desc .width = atoi (tmp );
231+ s -> desc .height = atoi (strchr (tmp , 'x' ) + 1 );
232+ } else {
233+ struct video_desc size_dsc =
234+ get_video_desc_from_string (tmp );
235+ s -> desc .width = size_dsc .width ;
236+ s -> desc .height = size_dsc .height ;
237+ }
238+ } else if (IS_KEY_PREFIX (tmp , "fps" )) {
239+ if (!parse_fps (strchr (tmp , '=' ) + 1 , & s -> desc )) {
240+ return false;
241+ }
242+ } else if (IS_PREFIX (tmp , "noise" ) ||
243+ IS_KEY_PREFIX (tmp , "noise" )) {
244+ s -> noise = IS_KEY_PREFIX (tmp , "noise" )
245+ ? atoi (strchr (tmp , '=' ) + 1 )
246+ : NOISE_DEFAULT ;
247+ } else {
248+ MSG (ERROR , "Unknown option: %s\n" , tmp );
249+ return false;
250+ }
251+ tmp = strtok_r (NULL , ":" , & save_ptr );
252+ }
253+ return true;
254+ }
255+
256+ static void
257+ usage ()
258+ {
259+ color_printf ("testcard2 is an alternative implementation of testing "
260+ "signal source.\n" );
261+ color_printf ("It is less maintained than mainline testcard and has "
262+ "less features but has some extra ones, i. a. a timer (if "
263+ "SDL(2)_ttf is found.\n" );
264+ color_printf ("\n" );
265+ color_printf ("testcard2 usage:\n" );
266+ color_printf (TBOLD (
267+ TRED ("\t-t testcard2" ) "[:<width>:<height>:<fps>:<codec>]" ) "\n" );
268+ color_printf ("or\n" );
269+ color_printf (
270+ TBOLD (TRED ("\t-t testcard2" ) "[:size=<width>x<height>][:fps=<fps>]["
271+ ":codec=<codec>][:mode=<mode>]" ) "\n" );
272+ printf ("\nOptions:\n" );
273+ color_printf ("\t" TBOLD ("noise[=<val>]" ) " - add noise to the image\n" );
274+ printf ("\n" );
275+ testcard_show_codec_help ("testcard2" , true);
276+ }
277+
201278static int vidcap_testcard2_init (struct vidcap_params * params , void * * state )
202279{
203280 if (vidcap_params_get_fmt (params ) == NULL || strcmp (vidcap_params_get_fmt (params ), "help" ) == 0 ) {
204- color_printf ("testcard2 is an alternative implementation of testing signal source.\n" );
205- color_printf ("It is less maintained than mainline testcard and has less features but has some extra ones, i. a. a timer (if SDL(2)_ttf is found.\n" );
206- color_printf ("\n" );
207- color_printf ("testcard2 usage:\n" );
208- color_printf (TBOLD (TRED ("\t-t testcard2" ) "[:<width>:<height>:<fps>:<codec>]" ) "\n" );
209- color_printf ("or\n" );
210- color_printf (TBOLD (TRED ("\t-t testcard2" ) "[:size=<width>x<height>][:fps=<fps>][:codec=<codec>][:mode=<mode>]" ) "\n" );
211- printf ("\nOptions:\n" );
212- color_printf ("\t" TBOLD ("noise[=<val>]" ) " - add noise to the image\n" );
213- printf ("\n" );
214- testcard_show_codec_help ("testcard2" , true);
215-
281+ usage ();
216282 return VIDCAP_INIT_NOERR ;
217283 }
218284
219285 struct testcard_state2 * s = calloc (1 , sizeof (struct testcard_state2 ));
220- if (!s )
286+ if (!s ) {
221287 return VIDCAP_INIT_FAIL ;
222- s -> desc .tile_count = 1 ;
223- s -> desc .interlacing = PROGRESSIVE ;
224-
225- char * fmt = strdup (strlen (vidcap_params_get_fmt (params )) != 0 ? vidcap_params_get_fmt (params ) : DEFAULT_FORMAT );
226- char * ptr = fmt ;
227-
228- if (strlen (ptr ) > 0 && isdigit (ptr [0 ])) {
229- bool ret = parse_fmt (s , fmt );
230- free (fmt );
231- if (!ret ) {
232- free (s );
233- return VIDCAP_INIT_FAIL ;
234- }
288+ }
289+ s -> desc = DEFAULT_FORMAT ;
290+
291+ char * fmt = strdup (vidcap_params_get_fmt (params ));
292+ bool ret = true;
293+
294+ if (strlen (fmt ) > 0 && isdigit (fmt [0 ])) {
295+ ret = parse_fmt_positional (s , fmt );
235296 } else {
236- char * default_fmt = strdup (DEFAULT_FORMAT );
237- parse_fmt (s , default_fmt );
238- free (default_fmt );
239-
240- bool ret = true;
241- char * save_ptr = NULL ;
242- char * tmp = strtok_r (ptr , ":" , & save_ptr );
243- while (tmp ) {
244- if (IS_KEY_PREFIX (tmp , "codec" )) {
245- s -> desc .color_spec = get_codec_from_name (strchr (tmp , '=' ) + 1 );
246- if (s -> desc .color_spec == VIDEO_CODEC_NONE ) {
247- log_msg (LOG_LEVEL_ERROR , MOD_NAME "Wrong color spec: %s\n" , strchr (tmp , '=' ) + 1 );
248- ret = false;
249- break ;
250- }
251- } else if (IS_KEY_PREFIX (tmp , "mode" )) {
252- codec_t saved_codec = s -> desc .color_spec ;
253- s -> desc = get_video_desc_from_string (strchr (tmp , '=' ) + 1 );
254- s -> desc .color_spec = saved_codec ;
255- } else if (IS_KEY_PREFIX (tmp , "size" )) {
256- tmp = strchr (tmp , '=' ) + 1 ;
257- if (isdigit (tmp [0 ]) && strchr (tmp , 'x' ) != NULL ) {
258- s -> desc .width = atoi (tmp );
259- s -> desc .height = atoi (strchr (tmp , 'x' ) + 1 );
260- } else {
261- struct video_desc size_dsc =
262- get_video_desc_from_string (tmp );
263- s -> desc .width = size_dsc .width ;
264- s -> desc .height = size_dsc .height ;
265- }
266- } else if (IS_KEY_PREFIX (tmp , "fps" )) {
267- if (!parse_fps (strchr (tmp , '=' ) + 1 , & s -> desc )) {
268- ret = false;
269- break ;
270- }
271- } else if (IS_PREFIX (tmp , "noise" ) || IS_KEY_PREFIX (tmp , "noise" )) {
272- s -> noise = IS_KEY_PREFIX (tmp , "noise" )
273- ? atoi (strchr (tmp , '=' ) + 1 )
274- : NOISE_DEFAULT ;
275- } else {
276- fprintf (stderr , "[testcard2] Unknown option: %s\n" , tmp );
277- ret = false;
278- break ;
279- }
280- tmp = strtok_r (NULL , ":" , & save_ptr );
281- }
282- free (fmt );
283- if (!ret ) {
284- free (s );
285- return VIDCAP_INIT_FAIL ;
286- }
297+ ret = parse_fmt (s , fmt );
298+ }
299+ free (fmt );
300+ if (!ret ) {
301+ free (s );
302+ return VIDCAP_INIT_FAIL ;
287303 }
288304
289305 if (s -> desc .width <= 0 || s -> desc .height <= 0 ) {
@@ -316,15 +332,10 @@ static int vidcap_testcard2_init(struct vidcap_params *params, void **state)
316332 free (surface .data );
317333 }
318334
319- if (vidcap_params_get_flags (params ) & VIDCAP_FLAG_AUDIO_EMBEDDED ) {
320- s -> grab_audio = 1 ;
321- if (configure_audio (s ) != 0 ) {
322- s -> grab_audio = 0 ;
323- fprintf (stderr , "[testcard2] Disabling audio output. "
324- "\n" );
325- }
326- } else {
327- s -> grab_audio = 0 ;
335+ s -> grab_audio =
336+ vidcap_params_get_flags (params ) & VIDCAP_FLAG_AUDIO_EMBEDDED ;
337+ if (s -> grab_audio ) {
338+ configure_audio (s );
328339 }
329340
330341 s -> count = 0 ;
@@ -335,22 +346,6 @@ static int vidcap_testcard2_init(struct vidcap_params *params, void **state)
335346 platform_sem_init (& s -> semaphore , 0 , 0 );
336347 printf ("Testcard capture set to %dx%d\n" , s -> desc .width , s -> desc .height );
337348
338- if (vidcap_params_get_flags (params ) & VIDCAP_FLAG_AUDIO_EMBEDDED ) {
339- s -> grab_audio = 1 ;
340- if (configure_audio (s ) != 0 ) {
341- s -> grab_audio = 0 ;
342- fprintf (stderr , "[testcard] Disabling audio output. "
343- "SDL-mixer missing, running on Mac or other problem." );
344- }
345- } else {
346- s -> grab_audio = 0 ;
347- }
348-
349- if (!s -> grab_audio ) {
350- s -> audio_tone = NULL ;
351- s -> audio_silence = NULL ;
352- }
353-
354349 gettimeofday (& s -> start_time , NULL );
355350
356351 pthread_mutex_init (& s -> lock , NULL );
0 commit comments