Testcard: small rewrite

This commit is contained in:
Martin Pulec
2015-02-05 15:44:09 +01:00
parent c9126382a7
commit 3f846213b7
5 changed files with 159 additions and 143 deletions

View File

@@ -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 */

View File

@@ -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 <stdio.h>
#include <stdlib.h>
#include <chrono>
#ifdef HAVE_LIBSDL_MIXER
#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>
@@ -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<std::chrono::duration<double>>(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<std::chrono::duration<double>>(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");
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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));