From 3f846213b7d32dcb91cbda72a5efe66a62cfde5f Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Thu, 5 Feb 2015 15:44:09 +0100 Subject: [PATCH] Testcard: small rewrite --- src/config_unix.h | 5 + .../{testcard.c => testcard.cpp} | 283 +++++++++--------- src/video_capture/testcard_common.h | 10 +- src/video_codec.c | 2 +- src/video_codec.h | 2 +- 5 files changed, 159 insertions(+), 143 deletions(-) rename src/video_capture/{testcard.c => testcard.cpp} (79%) diff --git a/src/config_unix.h b/src/config_unix.h index 158c8e0a0..f7f7bdf3c 100644 --- a/src/config_unix.h +++ b/src/config_unix.h @@ -210,5 +210,10 @@ static inline void *aligned_malloc(size_t size, size_t alignment) #define INVALID_SOCKET -1 +// GCC 4.6 (Ubuntu 12.04) compat +#if !__llvm__ && __GNUC__ == 4 && __GNUC_MINOR__ == 6 +#define steady_clock monotonic_clock +#endif + #endif /* _CONFIG_UNIX_H */ #endif /* NDEF WIN32 */ diff --git a/src/video_capture/testcard.c b/src/video_capture/testcard.cpp similarity index 79% rename from src/video_capture/testcard.c rename to src/video_capture/testcard.cpp index 7d474ca0d..2aef5c56e 100644 --- a/src/video_capture/testcard.c +++ b/src/video_capture/testcard.cpp @@ -19,18 +19,18 @@ * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * + * * This product includes software developed by the University of Southern * California Information Sciences Institute. This product also includes * software developed by CESNET z.s.p.o. - * + * * 4. Neither the name of the University, Institute, CESNET nor the names of * its contributors may be used to endorse or promote products derived from * this software without specific prior written permission. @@ -65,6 +65,7 @@ #include "utils/vf_split.h" #include #include +#include #ifdef HAVE_LIBSDL_MIXER #include #include @@ -86,22 +87,22 @@ struct testcard_pixmap { }; struct testcard_state { - struct timeval last_frame_time; + std::chrono::steady_clock::time_point last_frame_time; int count; int size; int pan; struct testcard_pixmap pixmap; char *data; - struct timeval t0; + std::chrono::steady_clock::time_point t0; struct video_frame *frame; int frame_linesize; struct video_frame *tiled; - + struct audio_frame audio; char **tiles_data; int tiles_cnt_horizontal; int tiles_cnt_vertical; - + char *audio_data; volatile int audio_start, audio_end; unsigned int grab_audio:1; @@ -113,7 +114,7 @@ static void testcard_fillRect(struct testcard_pixmap *s, struct testcard_rect *r { int cur_x, cur_y; int *data = (int *) s->data; - + for (cur_x = r->x; cur_x < r->x + r->w; ++cur_x) for(cur_y = r->y; cur_y < r->y + r->h; ++cur_y) if(cur_x < s->w) @@ -125,7 +126,7 @@ static void grab_audio(int chan, void *stream, int len, void *udata) { UNUSED(chan); struct testcard_state *s = (struct testcard_state *) udata; - + if(s->audio_end + len <= (int) AUDIO_BUFFER_SIZE) { memcpy(s->audio_data + s->audio_end, stream, len); s->audio_end += len; @@ -143,15 +144,15 @@ static void grab_audio(int chan, void *stream, int len, void *udata) static int configure_audio(struct testcard_state *s) { UNUSED(s); - + #if defined HAVE_LIBSDL_MIXER && ! defined HAVE_MACOSX char filename[1024] = ""; int fd; Mix_Music *music; ssize_t bytes_written = 0l; - + SDL_Init(SDL_INIT_AUDIO); - + if( Mix_OpenAudio( AUDIO_SAMPLE_RATE, AUDIO_S16LSB, audio_capture_channels, 4096 ) == -1 ) { fprintf(stderr,"[testcard] error initalizing sound\n"); @@ -163,7 +164,7 @@ static int configure_audio(struct testcard_state *s) perror("mkstemp"); return -1; } - + do { ssize_t ret; ret = write(fd, song1 + bytes_written, @@ -180,7 +181,7 @@ static int configure_audio(struct testcard_state *s) s->audio.bps = AUDIO_BPS; s->audio.ch_count = audio_capture_channels; s->audio.sample_rate = AUDIO_SAMPLE_RATE; - + // register grab as a postmix processor if(!Mix_RegisterEffect(MIX_CHANNEL_POST, grab_audio, NULL, s)) { printf("[testcard] Mix_RegisterEffect: %s\n", Mix_GetError()); @@ -192,9 +193,9 @@ static int configure_audio(struct testcard_state *s) return -1; } Mix_Volume(-1, 0); - + printf("[testcard] playing audio\n"); - + return 0; #else return -2; @@ -206,18 +207,18 @@ static int configure_tiling(struct testcard_state *s, const char *fmt) char *tmp, *token, *saveptr = NULL; int tile_cnt; int x; - + int grid_w, grid_h; if(fmt[1] != '=') return 1; - + tmp = strdup(&fmt[2]); token = strtok_r(tmp, "x", &saveptr); grid_w = atoi(token); token = strtok_r(NULL, "x", &saveptr); grid_h = atoi(token); free(tmp); - + s->tiled = vf_alloc(grid_w * grid_h); s->tiles_cnt_horizontal = grid_w; s->tiles_cnt_vertical = grid_h; @@ -241,30 +242,30 @@ static int configure_tiling(struct testcard_state *s, const char *fmt) int y; s->tiles_data[x] = s->tiled->tiles[x].data; - + s->tiled->tiles[x].width = s->frame->tiles[0].width/ grid_w; s->tiled->tiles[x].height = s->frame->tiles[0].height / grid_h; s->tiled->tiles[x].data_len = s->frame->tiles[0].data_len / (grid_w * grid_h); s->tiled->tiles[x].data = - s->tiles_data[x] = (char *) realloc(s->tiled->tiles[x].data, + s->tiles_data[x] = (char *) realloc(s->tiled->tiles[x].data, s->tiled->tiles[x].data_len * grid_h * 2); - - + + memcpy(s->tiled->tiles[x].data + s->tiled->tiles[x].data_len * grid_h, - s->tiled->tiles[x].data, s->tiled->tiles[x].data_len * grid_h); + s->tiled->tiles[x].data, s->tiled->tiles[x].data_len * grid_h); /* recopy tiles vertically */ for(y = 1; y < grid_h; ++y) { - memcpy(&s->tiled->tiles[y * grid_w + x], + memcpy(&s->tiled->tiles[y * grid_w + x], &s->tiled->tiles[x], sizeof(struct tile)); /* make the pointers correct */ s->tiles_data[y * grid_w + x] = s->tiles_data[x] + y * s->tiled->tiles[x].height * vc_get_linesize(s->tiled->tiles[x].width, s->tiled->color_spec); - + s->tiled->tiles[y * grid_w + x].data = - s->tiles_data[x] + + s->tiles_data[x] + y * s->tiled->tiles[x].height * vc_get_linesize(s->tiled->tiles[x].width, s->tiled->color_spec); } @@ -296,14 +297,17 @@ void *vidcap_testcard_init(const struct vidcap_params *params) return &vidcap_init_noerr; } - s = calloc(1, sizeof(struct testcard_state)); + s = new testcard_state(); if (!s) return NULL; s->frame = vf_alloc(1); - + char *fmt = strdup(vidcap_params_get_fmt(params)); char *tmp; + int h_align = 0; + double bpp = 0; + tmp = strtok_r(fmt, ":", &save_ptr); if (!tmp) { @@ -331,9 +335,6 @@ void *vidcap_testcard_init(const struct vidcap_params *params) goto error; } - int h_align = 0; - double bpp = 0; - codec = get_codec_from_name(tmp); if (codec == VIDEO_CODEC_NONE) { codec = UYVY; @@ -347,7 +348,7 @@ void *vidcap_testcard_init(const struct vidcap_params *params) if(bpp == 0) { fprintf(stderr, "Unknown codec '%s'\n", tmp); free(tmp); - free(s); + delete s; return NULL; } @@ -357,7 +358,7 @@ void *vidcap_testcard_init(const struct vidcap_params *params) } rect_size = (vf_get_tile(s->frame, 0)->width + rect_size - 1) / rect_size; - + s->frame_linesize = aligned_x * bpp; s->frame->interlacing = PROGRESSIVE; s->size = aligned_x * vf_get_tile(s->frame, 0)->height * bpp; @@ -371,7 +372,7 @@ void *vidcap_testcard_init(const struct vidcap_params *params) if (!in) { perror("fopen"); free(fmt); - free(s); + delete s; return NULL; } fseek(in, 0L, SEEK_END); @@ -379,7 +380,7 @@ void *vidcap_testcard_init(const struct vidcap_params *params) assert(filesize >= 0); fseek(in, 0L, SEEK_SET); - s->data = malloc(s->size * bpp * 2); + s->data = (char *) malloc(s->size * bpp * 2); if (s->size < filesize) { fprintf(stderr, "Error wrong file size for selected " @@ -387,7 +388,7 @@ void *vidcap_testcard_init(const struct vidcap_params *params) "computed size %d\n", filesize, s->size); free(fmt); free(s->data); - free(s); + delete s; fclose(in); return NULL; } @@ -396,7 +397,7 @@ void *vidcap_testcard_init(const struct vidcap_params *params) fprintf(stderr, "Cannot read file %s\n", filename); free(fmt); free(s->data); - free(s); + delete s; if (in) fclose(in); return NULL; @@ -443,7 +444,7 @@ void *vidcap_testcard_init(const struct vidcap_params *params) } } } - s->data = s->pixmap.data; + s->data = (char *) s->pixmap.data; if (codec == UYVY || codec == v210) { rgb2yuv422((unsigned char *) s->data, aligned_x, vf_get_tile(s->frame, 0)->height); @@ -460,17 +461,17 @@ void *vidcap_testcard_init(const struct vidcap_params *params) toR10k((unsigned char *) s->data, vf_get_tile(s->frame, 0)->width, vf_get_tile(s->frame, 0)->height); } - + if(codec == RGB) { s->data = (char *)toRGB((unsigned char *) s->data, vf_get_tile(s->frame, 0)->width, vf_get_tile(s->frame, 0)->height); free(s->pixmap.data); } - + tmp = filename; - vf_get_tile(s->frame, 0)->data = malloc(2 * s->size); + vf_get_tile(s->frame, 0)->data = (char *) malloc(2 * s->size); memcpy(vf_get_tile(s->frame, 0)->data, s->data, s->size); memcpy(vf_get_tile(s->frame, 0)->data + s->size, vf_get_tile(s->frame, 0)->data, s->size); @@ -496,7 +497,7 @@ void *vidcap_testcard_init(const struct vidcap_params *params) s->count = 0; - gettimeofday(&(s->last_frame_time), NULL); + s->last_frame_time = std::chrono::steady_clock::now(); printf("Testcard capture set to %dx%d, bpp %f\n", vf_get_tile(s->frame, 0)->width, vf_get_tile(s->frame, 0)->height, bpp); @@ -508,7 +509,7 @@ void *vidcap_testcard_init(const struct vidcap_params *params) goto error; } } - + if(vidcap_params_get_flags(params) & VIDCAP_FLAG_AUDIO_EMBEDDED) { s->grab_audio = TRUE; if(configure_audio(s) != 0) { @@ -526,13 +527,13 @@ void *vidcap_testcard_init(const struct vidcap_params *params) error: free(fmt); - free(s); + delete s; return NULL; } void vidcap_testcard_done(void *state) { - struct testcard_state *s = state; + struct testcard_state *s = (struct testcard_state *) state; free(s->data); if (s->tiled) { int i; @@ -545,107 +546,109 @@ void vidcap_testcard_done(void *state) if(s->audio_data) { free(s->audio_data); } - free(s); + delete s; } struct video_frame *vidcap_testcard_grab(void *arg, struct audio_frame **audio) { - struct timeval curr_time; struct testcard_state *state; - state = (struct testcard_state *)arg; - gettimeofday(&curr_time, NULL); - if (tv_diff(curr_time, state->last_frame_time) > + std::chrono::steady_clock::time_point curr_time = + std::chrono::steady_clock::now(); + + if (std::chrono::duration_cast>(curr_time - state->last_frame_time).count() < 1.0 / (double)state->frame->fps) { - state->last_frame_time = curr_time; - state->count++; - - double seconds = tv_diff(curr_time, state->t0); - if (seconds >= 5) { - float fps = state->count / seconds; - fprintf(stderr, "[testcard] %d frames in %g seconds = %g FPS\n", - state->count, seconds, fps); - state->t0 = curr_time; - state->count = 0; - } - - if (state->grab_audio) { -#ifdef HAVE_LIBSDL_MIXER - state->audio.data = state->audio_data + state->audio_start; - if(state->audio_start <= state->audio_end) { - int tmp = state->audio_end; - state->audio.data_len = tmp - state->audio_start; - state->audio_start = tmp; - } else { - state->audio.data_len = - AUDIO_BUFFER_SIZE - - state->audio_start; - state->audio_start = 0; - } - if(state->audio.data_len > 0) - *audio = &state->audio; - else - *audio = NULL; -#endif - } else { - *audio = NULL; - } - - if(!state->still_image) { - vf_get_tile(state->frame, 0)->data += state->frame_linesize; - } - if(vf_get_tile(state->frame, 0)->data > state->data + state->size) - vf_get_tile(state->frame, 0)->data = state->data; - - /*char line[state->frame.src_linesize * 2 + state->pan]; - unsigned int i; - memcpy(line, state->frame.data, - state->frame.src_linesize * 2 + state->pan); - for (i = 0; i < state->frame.height - 3; i++) { - memcpy(state->frame.data + i * state->frame.src_linesize, - state->frame.data + (i + 2) * state->frame.src_linesize + - state->pan, state->frame.src_linesize); - } - memcpy(state->frame.data + i * state->frame.src_linesize, - state->frame.data + (i + 2) * state->frame.src_linesize + - state->pan, state->frame.src_linesize - state->pan); - memcpy(state->frame.data + - (state->frame.height - 2) * state->frame.src_linesize - state->pan, - line, state->frame.src_linesize * 2 + state->pan); -#ifdef USE_EPILEPSY - if(!(state->count % 2)) { - unsigned int *p = state->frame.data; - for(i=0; i < state->frame.src_linesize*state->frame.height/4; i++) { - *p = *p ^ 0x00ffffffL; - p++; - } - } -#endif - */ - if (state->tiled) { - /* update tile data instead */ - int i; - int count = state->tiled->tile_count; - - for (i = 0; i < count; ++i) { - /* shift - for semantics of vars refer to configure_tiling*/ - state->tiled->tiles[i].data += vc_get_linesize( - state->tiled->tiles[i].width, state->tiled->color_spec); - /* if out of data, move to beginning - * keep in mind that we have two "pictures" for - * every tile stored sequentially */ - if(state->tiled->tiles[i].data >= state->tiles_data[i] + - state->tiled->tiles[i].data_len * state->tiles_cnt_vertical) { - state->tiled->tiles[i].data = state->tiles_data[i]; - } - } - - return state->tiled; - } - return state->frame; + return NULL; } - return NULL; + + state->last_frame_time = curr_time; + state->count++; + + double seconds = + std::chrono::duration_cast>(curr_time - state->t0).count(); + if (seconds >= 5.0) { + float fps = state->count / seconds; + fprintf(stderr, "[testcard] %d frames in %g seconds = %g FPS\n", + state->count, seconds, fps); + state->t0 = curr_time; + state->count = 0; + } + + if (state->grab_audio) { +#ifdef HAVE_LIBSDL_MIXER + state->audio.data = state->audio_data + state->audio_start; + if(state->audio_start <= state->audio_end) { + int tmp = state->audio_end; + state->audio.data_len = tmp - state->audio_start; + state->audio_start = tmp; + } else { + state->audio.data_len = + AUDIO_BUFFER_SIZE - + state->audio_start; + state->audio_start = 0; + } + if(state->audio.data_len > 0) + *audio = &state->audio; + else + *audio = NULL; +#endif + } else { + *audio = NULL; + } + + if(!state->still_image) { + vf_get_tile(state->frame, 0)->data += state->frame_linesize; + } + if(vf_get_tile(state->frame, 0)->data > state->data + state->size) + vf_get_tile(state->frame, 0)->data = state->data; + + /*char line[state->frame.src_linesize * 2 + state->pan]; + unsigned int i; + memcpy(line, state->frame.data, + state->frame.src_linesize * 2 + state->pan); + for (i = 0; i < state->frame.height - 3; i++) { + memcpy(state->frame.data + i * state->frame.src_linesize, + state->frame.data + (i + 2) * state->frame.src_linesize + + state->pan, state->frame.src_linesize); + } + memcpy(state->frame.data + i * state->frame.src_linesize, + state->frame.data + (i + 2) * state->frame.src_linesize + + state->pan, state->frame.src_linesize - state->pan); + memcpy(state->frame.data + + (state->frame.height - 2) * state->frame.src_linesize - state->pan, + line, state->frame.src_linesize * 2 + state->pan); +#ifdef USE_EPILEPSY +if(!(state->count % 2)) { +unsigned int *p = state->frame.data; +for(i=0; i < state->frame.src_linesize*state->frame.height/4; i++) { + *p = *p ^ 0x00ffffffL; + p++; + } + } +#endif +*/ + if (state->tiled) { + /* update tile data instead */ + int i; + int count = state->tiled->tile_count; + + for (i = 0; i < count; ++i) { + /* shift - for semantics of vars refer to configure_tiling*/ + state->tiled->tiles[i].data += vc_get_linesize( + state->tiled->tiles[i].width, state->tiled->color_spec); + /* if out of data, move to beginning + * keep in mind that we have two "pictures" for + * every tile stored sequentially */ + if(state->tiled->tiles[i].data >= state->tiles_data[i] + + state->tiled->tiles[i].data_len * state->tiles_cnt_vertical) { + state->tiled->tiles[i].data = state->tiles_data[i]; + } + } + + return state->tiled; + } + return state->frame; } struct vidcap_type *vidcap_testcard_probe(bool verbose) @@ -660,7 +663,7 @@ struct vidcap_type *vidcap_testcard_probe(bool verbose) if (verbose) { vt->card_count = 1; - vt->cards = calloc(vt->card_count, sizeof(struct vidcap_card)); + vt->cards = (struct vidcap_card *) calloc(vt->card_count, sizeof(struct vidcap_card)); snprintf(vt->cards[0].id, sizeof vt->cards[0].name, "1920:1080:25:UYVY:i"); snprintf(vt->cards[0].name, sizeof vt->cards[0].name, "Testing 1080@50i signal"); } diff --git a/src/video_capture/testcard_common.h b/src/video_capture/testcard_common.h index c461dd435..86a377fa9 100644 --- a/src/video_capture/testcard_common.h +++ b/src/video_capture/testcard_common.h @@ -44,7 +44,11 @@ */ #define COL_NUM 6 -const int rect_colors[COL_NUM]; +extern const int rect_colors[COL_NUM]; + +#ifdef __cplusplus +extern "C" { +#endif void rgb2yuv422(unsigned char *in, unsigned int width, unsigned int height); unsigned char *tov210(unsigned char *in, unsigned int width, unsigned int align_x, @@ -52,3 +56,7 @@ unsigned char *tov210(unsigned char *in, unsigned int width, unsigned int align_ void toR10k(unsigned char *in, unsigned int width, unsigned int height); char * toRGB(unsigned char *in, unsigned int width, unsigned int height); +#ifdef __cplusplus +} +#endif + diff --git a/src/video_codec.c b/src/video_codec.c index 46aad45b7..cfb33fe55 100644 --- a/src/video_codec.c +++ b/src/video_codec.c @@ -182,7 +182,7 @@ const struct alternative_codec_name codec_name_aliases[] = { {"2vuy", "UYVY"}, }; -void show_codec_help(char *module) +void show_codec_help(const char *module) { printf("\tSupported codecs (%s):\n", module); diff --git a/src/video_codec.h b/src/video_codec.h index e8410ff3a..0d2f78cc5 100644 --- a/src/video_codec.h +++ b/src/video_codec.h @@ -78,7 +78,7 @@ extern const struct line_decode_from_to line_decoders[]; /* defined int .c */ /** Prints list of suppored codecs for video module * @deprecated Individual modules should print list of supported codecs by itself. */ -void show_codec_help(char *module); +void show_codec_help(const char *module); double get_bpp(codec_t codec) __attribute__((pure)); uint32_t get_fourcc(codec_t codec) __attribute__((pure)); int get_halign(codec_t codec) __attribute__((pure));