static GstFlowReturn create(GstPushSrc *base, GstBuffer **buf) { GstTICaptureSrc *src = (GstTICaptureSrc *)base; Buffer_Handle hDstBuf; GstBuffer *outBuf; gint ret = GST_FLOW_OK; BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; Int32 width, height; GST_LOG("create begin"); /* create capture device */ if (src->hCapture == NULL) { /* set framerate based on video standard */ switch(dmai_video_std(src->video_standard)) { case VideoStd_D1_NTSC: gst_value_set_fraction(&src->framerate,30000,1001); break; case VideoStd_D1_PAL: gst_value_set_fraction(&src->framerate,25,1); break; default: gst_value_set_fraction(&src->framerate,30,1); break; } /* set width & height based on video standard */ src->cAttrs.videoStd = dmai_video_std(src->video_standard); VideoStd_getResolution(src->cAttrs.videoStd, &width, &height); width = 720; height = 576; GST_WARNING("force video size to %dx%d", src->width, src->height); src->width = width; src->height = height; gfxAttrs.dim.height = src->height; gfxAttrs.dim.width = src->width; src->cAttrs.captureDimension = &gfxAttrs.dim; if (!capture_create(src)) return GST_FLOW_ERROR; } /* Get buffer from driver */ if (Capture_get(src->hCapture, &hDstBuf)) { GST_ELEMENT_ERROR(src, RESOURCE, FAILED, ("Failed to allocate buffer\n"), (NULL)); return GST_FLOW_ERROR; } /* Create a DMAI transport buffer object to carry a DMAI buffer to * the source pad. The transport buffer knows how to release the * buffer for re-use in this element when the source pad calls * gst_buffer_unref(). */ outBuf = gst_tidmaibuffertransport_new(hDstBuf, src->hBufTab, capture_buffer_finalize, (void*)src); gst_buffer_set_data(outBuf, GST_BUFFER_DATA(outBuf), Buffer_getSize(hDstBuf)); *buf = outBuf; /* set buffer metadata */ if (G_LIKELY (ret == GST_FLOW_OK && *buf)) { GstClock *clock; GstClockTime timestamp; GST_BUFFER_OFFSET (*buf) = src->offset++; GST_BUFFER_OFFSET_END (*buf) = src->offset; /* timestamps, LOCK to get clock and base time. */ GST_OBJECT_LOCK (src); if ((clock = GST_ELEMENT_CLOCK (src))) { /* we have a clock, get base time and ref clock */ timestamp = GST_ELEMENT (src)->base_time; gst_object_ref (clock); } else { /* no clock, can't set timestamps */ timestamp = GST_CLOCK_TIME_NONE; } GST_OBJECT_UNLOCK (src); if (G_LIKELY (clock)) { /* the time now is the time of the clock minus the base time */ timestamp = gst_clock_get_time (clock) - timestamp; gst_object_unref (clock); /* if we have a framerate adjust timestamp for frame latency */ if (GST_CLOCK_TIME_IS_VALID (src->duration)) { if (timestamp > src->duration) timestamp -= src->duration; else timestamp = 0; } } /* FIXME: use the timestamp from the buffer itself! */ GST_BUFFER_TIMESTAMP (*buf) = timestamp; GST_BUFFER_DURATION (*buf) = src->duration; } /* Create caps for buffer */ GstCaps *mycaps; GstStructure *structure; mycaps = gst_caps_new_empty(); if (src->cAttrs.colorSpace == ColorSpace_UYVY) { structure = gst_structure_new( "video/x-raw-yuv", "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'), "framerate", GST_TYPE_FRACTION, gst_value_get_fraction_numerator(&src->framerate), gst_value_get_fraction_denominator(&src->framerate), "width", G_TYPE_INT, src->width, "height", G_TYPE_INT, src->height, (gchar*) NULL); } else if(src->cAttrs.colorSpace == ColorSpace_YUV420PSEMI) { structure = gst_structure_new( "video/x-raw-yuv", "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('N', 'V', '1', '2'), "framerate", GST_TYPE_FRACTION, gst_value_get_fraction_numerator(&src->framerate), gst_value_get_fraction_denominator(&src->framerate), "width", G_TYPE_INT, src->width, "height", G_TYPE_INT, src->height, (gchar*) NULL); } else { GST_ERROR("unsupported fourcc\n"); return FALSE; } gst_caps_append_structure(mycaps, gst_structure_copy (structure)); gst_structure_free(structure); gst_buffer_set_caps(*buf, mycaps); gst_caps_unref(mycaps); { static int fn; fn++; GST_INFO("capture frame %d", fn); } GST_LOG("create end"); return GST_FLOW_OK; }
int main(int argc, char * const argv[]) { int result,i,r; int opt_index; int opt_rate = -1; int opt_channels = -1; int opt_period = 0; int opt_duration = 0; int opt_assert = 0; int opt_invalid_log_size = 0; const char *opt_device = NULL; const char *opt_config = NULL; const char *opt_priority = NULL; struct alsa_config config; struct ev_io stdin_watcher; struct ev_timer duration_timer; loop = ev_default_loop(0); while (1) { if ((result = getopt_long( argc, argv, "+r:c:p:D:C:P:d:aI:", options, &opt_index )) == EOF) break; switch (result) { case '?': usage(); break; case 'r': opt_rate = atoi(optarg); break; case 'c': opt_channels = atoi(optarg); break; case 'p': opt_period = atoi(optarg); break; case 'd': opt_duration = atoi(optarg); break; case 'D': opt_device = optarg; break; case 'C': opt_config = optarg; break; case 'P': opt_priority = optarg; break; case 'a': opt_assert = 1; break; case 'I': opt_invalid_log_size = atoi(optarg); break; } } /* generate the config */ alsa_config_init( &config, opt_config ); if (opt_rate > 0) config.rate = opt_rate; if (opt_channels > 0) config.channels = opt_channels; if (opt_period > 0) config.period = opt_period; if (opt_device) { strncpy( config.device, opt_device, sizeof(config.device)-1 ); config.device[ sizeof(config.device)-1 ] = '\0'; } if (opt_priority) { strncpy( config.priority, opt_priority, sizeof(config.priority)-1 ); config.priority[ sizeof(config.priority)-1 ] = '\0'; } /* check if the config is valid */ if (config.device[0] == '\0') { printf("Undefined device.\n"); exit(1); } dbg("dev: '%s'", config.device); #define MAX_TESTS 2 struct test *tests[MAX_TESTS]; int tests_count = 0; /* build the tests objects */ argc -= optind; argv += optind; while (argc) { struct test *t = NULL; if (!strcmp( argv[0], "play" )) { struct playback_create_opts opts = {0}; optind = 1; while (1) { if ((result = getopt( argc, argv, "+x:r:" )) == EOF) break; switch (result) { case '?': printf("invalid option '%s' for test 'play'\n", optarg); usage(); break; case 'x': opts.xrun = atoi(optarg); break; case 'r': if (sscanf(optarg, "%d,%d", &opts.restart_play_time, &opts.restart_pause_time) != 2) { printf("invalid value '%s' for test 'play' option '-r'\n", optarg); usage(); } dbg("%d,%d", opts.restart_play_time, opts.restart_pause_time); break; } } argc -= optind-1; argv += optind-1; t = playback_create( &config, &opts ); if (!t) { err("failed to create a playback test"); exit(1); } } else if (!strcmp( argv[0], "capture" )) { struct capture_create_opts opts = {0}; optind = 1; while (1) { if ((result = getopt( argc, argv, "+x:r:" )) == EOF) break; switch (result) { case '?': printf("invalid option '%s' for test 'capture'\n", optarg); usage(); break; case 'x': opts.xrun = atoi(optarg); break; case 'r': if (sscanf(optarg, "%d,%d", &opts.restart_play_time, &opts.restart_pause_time) != 2) { printf("invalid value '%s' for test 'capture' option '-r'\n", optarg); usage(); } dbg("%d,%d", opts.restart_play_time, opts.restart_pause_time); break; } } argc -= optind-1; argv += optind-1; t = capture_create( &config, &opts ); if (!t) { err("failed to create a capture test"); exit(1); } } else if (!strcmp( argv[0], "loopback_delay" )) { struct loopback_delay_create_opts opts = {0}; optind = 1; while (1) { if ((result = getopt( argc, argv, "+a:s:x:" )) == EOF) break; switch (result) { case '?': printf("invalid option '%s' for test 'loopback_delay'\n", optarg); usage(); break; case 'a': opts.assert_delay = 1; opts.expected_delay = atoi(optarg); break; case 's': if (!strcmp(optarg, "capture")) opts.start_sync_mode = LSM_PREPARE_CAPTURE_PLAYBACK; else if (!strcmp(optarg, "play")) opts.start_sync_mode = LSM_PREPARE_PLAYBACK_CAPTURE; else if (!strcmp(optarg, "link")) opts.start_sync_mode = LSM_LINK; else { printf("invalid value '%s' for test 'loopback_delay' option '-s'\n", optarg); usage(); } break; } } argc -= optind-1; argv += optind-1; t = loopback_delay_create( &config, &opts ); if (!t) { err("failed to create a capture test"); exit(1); } } if (t) { if (tests_count >= MAX_TESTS) { err("too many tests defined."); exit(1); } tests[tests_count++] = t; } else { printf("undefined test '%s'.\n", argv[0]); usage(); } argc--; argv++; } if (tests_count == 0) { printf("no tests specified.\n"); exit(1); } /* change the scheduling priority is required */ if (config.priority[0]) { int p; if (sscanf(config.priority, "fifo,%d", &p )==1) { struct sched_param param; param.sched_priority = p; dbg("priority: fifo,%d", p); if (sched_setscheduler(0, SCHED_FIFO, ¶m)) err("sched_setscheduler"); } else if (sscanf(config.priority, "rr,%d", &p )==1) { struct sched_param param; param.sched_priority = p; dbg("priority: rr,%d", p); if (sched_setscheduler(0, SCHED_RR, ¶m)) err("sched_setscheduler"); } else if (sscanf(config.priority, "other,%d", &p )==1) { struct sched_param param; param.sched_priority = p; dbg("priority: other,%d", p); if (sched_setscheduler(0, SCHED_OTHER, ¶m)) err("sched_setscheduler"); } else { printf("Invalid priority '%s'\n", config.priority); } } /* start the various tests */ for (i=0; i < tests_count; i++) { struct test *t = tests[i]; r = t->ops->start( t ); if (r < 0) { err("starting test %s failed", t->name ); exit(1); } } /* setup signal handlers to exist cleanly */ ev_signal_init(&evw_intsig, on_exit_signal, SIGINT); ev_signal_start(loop, &evw_intsig); ev_signal_init(&evw_termsig, on_exit_signal, SIGTERM); ev_signal_start(loop, &evw_termsig); ev_io_init(&stdin_watcher, on_stdin, 0, EV_READ); ev_io_start( loop, &stdin_watcher ); if (opt_assert) { seq_error_notify = &seq_error_assert; } if (opt_invalid_log_size > 0) { seq_consecutive_invalid_frames_log = opt_invalid_log_size; } if (opt_duration > 0) { dbg("start a %d seconds duration timer", opt_duration); ev_timer_init( &duration_timer, on_duration_timer, opt_duration, 0 ); ev_timer_start( loop, &duration_timer ); } ev_run( loop, 0 ); int test_exit_status = 0; for (i=0; i < tests_count; i++) { struct test *t = tests[i]; if (t->ops->close( t )) { err("%s exit status: failed", t->name); test_exit_status = 1; } } printf("total number of sequence errors: %u\n", seq_errors_total); printf("global tests exit status: %s\n", test_exit_status ? "FAILED" : "OK"); /* exit with a good status only if no error was detected */ return (seq_errors_total || test_exit_status) ? 2 : 0; }