int pa_rtsp_record(pa_rtsp_client *c, uint16_t *seq, uint32_t *rtptime) { pa_headerlist *headers; char *info; int rv; pa_assert(c); if (!c->session) { /* No session in progress */ return -1; } pa_random(seq, sizeof(*seq)); pa_random(rtptime, sizeof(*rtptime)); headers = pa_headerlist_new(); pa_headerlist_puts(headers, "Range", "npt=0-"); info = pa_sprintf_malloc("seq=%u;rtptime=%u", *seq, *rtptime); pa_headerlist_puts(headers, "RTP-Info", info); pa_xfree(info); c->state = STATE_RECORD; rv = rtsp_exec(c, "RECORD", NULL, NULL, 1, headers); pa_headerlist_free(headers); return rv; }
/* Generate a new authorization key, store it in file fd and return it in *data */ static int generate(int fd, void *ret_data, size_t length) { ssize_t r; pa_assert(fd >= 0); pa_assert(ret_data); pa_assert(length > 0); pa_random(ret_data, length); lseek(fd, (off_t) 0, SEEK_SET); if (ftruncate(fd, (off_t) 0) < 0) { pa_log("Failed to truncate cookie file: %s", pa_cstrerror(errno)); return -1; } if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) { pa_log("Failed to write cookie file: %s", pa_cstrerror(errno)); return -1; } return 0; }
static void run_test(void) { int16_t samples[SAMPLES]; int16_t samples_ref[SAMPLES]; int16_t samples_orig[SAMPLES]; int32_t volumes[CHANNELS + PADDING]; int i, j, padding; pa_do_volume_func_t func; pa_usec_t start, stop; int k; pa_usec_t min = INT_MAX, max = 0; double s1 = 0, s2 = 0; func = pa_get_volume_func(PA_SAMPLE_S16NE); printf("checking ORC %zd\n", sizeof(samples)); pa_random(samples, sizeof(samples)); memcpy(samples_ref, samples, sizeof(samples)); memcpy(samples_orig, samples, sizeof(samples)); for (i = 0; i < CHANNELS; i++) volumes[i] = PA_CLAMP_VOLUME(rand() >> 1); for (padding = 0; padding < PADDING; padding++, i++) volumes[i] = volumes[padding]; func(samples_ref, volumes, CHANNELS, sizeof(samples)); pa_volume_s16ne_orc(samples, volumes, CHANNELS, sizeof(samples)); for (i = 0; i < SAMPLES; i++) { if (samples[i] != samples_ref[i]) { printf ("%d: %04x != %04x (%04x * %04x)\n", i, samples[i], samples_ref[i], samples_orig[i], volumes[i % CHANNELS]); } } for (k = 0; k < TIMES2; k++) { start = pa_rtclock_now(); for (j = 0; j < TIMES; j++) { memcpy(samples, samples_orig, sizeof(samples)); pa_volume_s16ne_orc(samples, volumes, CHANNELS, sizeof(samples)); } stop = pa_rtclock_now(); if (min > (stop - start)) min = stop - start; if (max < (stop - start)) max = stop - start; s1 += stop - start; s2 += (stop - start) * (stop - start); } pa_log_info("ORC: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1, (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2); min = INT_MAX; max = 0; s1 = s2 = 0; for (k = 0; k < TIMES2; k++) { start = pa_rtclock_now(); for (j = 0; j < TIMES; j++) { memcpy(samples_ref, samples_orig, sizeof(samples)); func(samples_ref, volumes, CHANNELS, sizeof(samples)); } stop = pa_rtclock_now(); if (min > (stop - start)) min = stop - start; if (max < (stop - start)) max = stop - start; s1 += stop - start; s2 += (stop - start) * (stop - start); } pa_log_info("ref: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1, (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2); pa_assert_se(memcmp(samples_ref, samples, sizeof(samples)) == 0); }
int pa_shm_create_rw(pa_shm *m, size_t size, bool shared, mode_t mode) { #ifdef HAVE_SHM_OPEN char fn[32]; int fd = -1; #endif pa_assert(m); pa_assert(size > 0); pa_assert(size <= MAX_SHM_SIZE); pa_assert(!(mode & ~0777)); pa_assert(mode >= 0600); /* Each time we create a new SHM area, let's first drop all stale * ones */ pa_shm_cleanup(); /* Round up to make it page aligned */ size = PA_PAGE_ALIGN(size); if (!shared) { m->id = 0; m->size = size; #ifdef MAP_ANONYMOUS if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (off_t) 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } #elif defined(HAVE_POSIX_MEMALIGN) { int r; if ((r = posix_memalign(&m->ptr, PA_PAGE_SIZE, size)) < 0) { pa_log("posix_memalign() failed: %s", pa_cstrerror(r)); goto fail; } } #else m->ptr = pa_xmalloc(m->size); #endif m->do_unlink = false; } else { #ifdef HAVE_SHM_OPEN struct shm_marker *marker; pa_random(&m->id, sizeof(m->id)); segment_name(fn, sizeof(fn), m->id); if ((fd = shm_open(fn, O_RDWR|O_CREAT|O_EXCL, mode)) < 0) { pa_log("shm_open() failed: %s", pa_cstrerror(errno)); goto fail; } m->size = size + SHM_MARKER_SIZE; if (ftruncate(fd, (off_t) m->size) < 0) { pa_log("ftruncate() failed: %s", pa_cstrerror(errno)); goto fail; } #ifndef MAP_NORESERVE #define MAP_NORESERVE 0 #endif if ((m->ptr = mmap(NULL, PA_PAGE_ALIGN(m->size), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, fd, (off_t) 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } /* We store our PID at the end of the shm block, so that we * can check for dead shm segments later */ marker = (struct shm_marker*) ((uint8_t*) m->ptr + m->size - SHM_MARKER_SIZE); pa_atomic_store(&marker->pid, (int) getpid()); pa_atomic_store(&marker->marker, SHM_MARKER); pa_assert_se(pa_close(fd) == 0); m->do_unlink = true; #else goto fail; #endif } m->shared = shared; return 0; fail: #ifdef HAVE_SHM_OPEN if (fd >= 0) { shm_unlink(fn); pa_close(fd); } #endif return -1; }
static int sharedmem_create(pa_shm *m, pa_mem_type_t type, size_t size, mode_t mode) { #if defined(HAVE_SHM_OPEN) || defined(HAVE_MEMFD) char fn[32]; int fd = -1; struct shm_marker *marker; bool do_unlink = false; /* Each time we create a new SHM area, let's first drop all stale * ones */ pa_shm_cleanup(); pa_random(&m->id, sizeof(m->id)); switch (type) { #ifdef HAVE_SHM_OPEN case PA_MEM_TYPE_SHARED_POSIX: segment_name(fn, sizeof(fn), m->id); fd = shm_open(fn, O_RDWR|O_CREAT|O_EXCL, mode); do_unlink = true; break; #endif #ifdef HAVE_MEMFD case PA_MEM_TYPE_SHARED_MEMFD: fd = memfd_create("pulseaudio", MFD_ALLOW_SEALING); break; #endif default: goto fail; } if (fd < 0) { pa_log("%s open() failed: %s", pa_mem_type_to_string(type), pa_cstrerror(errno)); goto fail; } m->type = type; m->size = size + shm_marker_size(type); m->do_unlink = do_unlink; if (ftruncate(fd, (off_t) m->size) < 0) { pa_log("ftruncate() failed: %s", pa_cstrerror(errno)); goto fail; } #ifndef MAP_NORESERVE #define MAP_NORESERVE 0 #endif if ((m->ptr = mmap(NULL, PA_PAGE_ALIGN(m->size), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, fd, (off_t) 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } if (type == PA_MEM_TYPE_SHARED_POSIX) { /* We store our PID at the end of the shm block, so that we * can check for dead shm segments later */ marker = (struct shm_marker*) ((uint8_t*) m->ptr + m->size - shm_marker_size(type)); pa_atomic_store(&marker->pid, (int) getpid()); pa_atomic_store(&marker->marker, SHM_MARKER); } /* For memfds, we keep the fd open until we pass it * to the other PA endpoint over unix domain socket. */ if (type == PA_MEM_TYPE_SHARED_MEMFD) m->fd = fd; else { pa_assert_se(pa_close(fd) == 0); m->fd = -1; } return 0; fail: if (fd >= 0) { #ifdef HAVE_SHM_OPEN if (type == PA_MEM_TYPE_SHARED_POSIX) shm_unlink(fn); #endif pa_close(fd); } #endif /* defined(HAVE_SHM_OPEN) || defined(HAVE_MEMFD) */ return -1; }
pa_core* pa_core_new(pa_mainloop_api *m, bool shared, size_t shm_size) { pa_core* c; pa_mempool *pool; int j; pa_assert(m); if (shared) { if (!(pool = pa_mempool_new(shared, shm_size))) { pa_log_warn("Failed to allocate shared memory pool. Falling back to a normal memory pool."); shared = false; } } if (!shared) { if (!(pool = pa_mempool_new(shared, shm_size))) { pa_log("pa_mempool_new() failed."); return NULL; } } c = pa_msgobject_new(pa_core); c->parent.parent.free = core_free; c->parent.process_msg = core_process_msg; c->state = PA_CORE_STARTUP; c->mainloop = m; c->clients = pa_idxset_new(NULL, NULL); c->cards = pa_idxset_new(NULL, NULL); c->sinks = pa_idxset_new(NULL, NULL); c->sources = pa_idxset_new(NULL, NULL); c->sink_inputs = pa_idxset_new(NULL, NULL); c->source_outputs = pa_idxset_new(NULL, NULL); c->modules = pa_idxset_new(NULL, NULL); c->scache = pa_idxset_new(NULL, NULL); c->namereg = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); c->shared = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); c->default_source = NULL; c->default_sink = NULL; c->default_sample_spec.format = PA_SAMPLE_S16NE; c->default_sample_spec.rate = 44100; c->default_sample_spec.channels = 2; pa_channel_map_init_extend(&c->default_channel_map, c->default_sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); c->default_n_fragments = 4; c->default_fragment_size_msec = 25; c->deferred_volume_safety_margin_usec = 8000; c->deferred_volume_extra_delay_usec = 0; c->module_defer_unload_event = NULL; c->modules_pending_unload = pa_hashmap_new(NULL, NULL); c->subscription_defer_event = NULL; PA_LLIST_HEAD_INIT(pa_subscription, c->subscriptions); PA_LLIST_HEAD_INIT(pa_subscription_event, c->subscription_event_queue); c->subscription_event_last = NULL; c->mempool = pool; pa_silence_cache_init(&c->silence_cache); if (shared && !(c->rw_mempool = pa_mempool_new(shared, shm_size))) pa_log_warn("Failed to allocate shared writable memory pool."); if (c->rw_mempool) pa_mempool_set_is_remote_writable(c->rw_mempool, true); c->exit_event = NULL; c->scache_auto_unload_event = NULL; c->exit_idle_time = -1; c->scache_idle_time = 20; c->flat_volumes = true; c->disallow_module_loading = false; c->disallow_exit = false; c->running_as_daemon = false; c->realtime_scheduling = false; c->realtime_priority = 5; c->disable_remixing = false; c->disable_lfe_remixing = false; c->lfe_crossover_freq = 120; c->deferred_volume = true; c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 1; for (j = 0; j < PA_CORE_HOOK_MAX; j++) pa_hook_init(&c->hooks[j], c); for (j = 0; j < PA_ACCESS_HOOK_MAX; j++) pa_hook_init(&c->access[j], c); pa_random(&c->cookie, sizeof(c->cookie)); #ifdef SIGPIPE pa_check_signal_is_blocked(SIGPIPE); #endif pa_core_check_idle(c); c->state = PA_CORE_RUNNING; return c; }