Mercurial > mplayer.hg
view libao2/ao_polyp.c @ 16946:47c5e9846cd3
ultra simple&slow pp filter, yes yet another spp like filter :)
this one does actually compress&decompress the video at various shifts with lavc while the other spp filters are doing optimized intra only filtering
limitations:
mpeg4 is hardcoded, all options too, pretty trivial to change though, even filtering with non dct codecs like snow could be tried ...
the qscale/qp is only taken fron the first MB of each image and then used for the whole image (would needs some small changes to lavc to let the user set the qscales for the mbs themselfs but iam to lazy ...)
this needs ALOT of cpu time and memory especially at uspp=8 ...
author | michael |
---|---|
date | Tue, 08 Nov 2005 13:15:19 +0000 |
parents | cae0dbeb44bb |
children | afcc7b017a63 |
line wrap: on
line source
#include <assert.h> #include <polyp/polyplib.h> #include <polyp/polyplib-error.h> #include <polyp/mainloop.h> #include "config.h" #include "audio_out.h" #include "audio_out_internal.h" #include "libaf/af_format.h" #include "mp_msg.h" #define POLYP_CLIENT_NAME "MPlayer" /** General driver info */ static ao_info_t info = { "Polypaudio audio output", "polyp", "Lennart Poettering", "" }; /** The sink to connect to */ static char *sink = NULL; /** Polypaudio playback stream object */ static struct pa_stream *stream = NULL; /** Polypaudio connection context */ static struct pa_context *context = NULL; /** Main event loop object */ static struct pa_mainloop *mainloop = NULL; /** Some special libao macro magic */ LIBAO_EXTERN(polyp) /** Wait until no further actions are pending on the connection context */ static void wait_for_completion(void) { assert(context && mainloop); while (pa_context_is_pending(context)) pa_mainloop_iterate(mainloop, 1, NULL); } /** Make sure that the connection context doesn't starve to death */ static void keep_alive(void) { assert(context && mainloop); while (pa_mainloop_iterate(mainloop, 0, NULL) > 0); } /** Wait until the specified operation completes */ static void wait_for_operation(struct pa_operation *o) { assert(o && context && mainloop); while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) pa_mainloop_iterate(mainloop, 1, NULL); pa_operation_unref(o); } /** libao initialization function, arguments are sampling frequency, * number of channels, sample type and some flags */ static int init(int rate_hz, int channels, int format, int flags) { struct pa_sample_spec ss; struct pa_buffer_attr a; char hn[128]; char *host = NULL; assert(!context && !stream && !mainloop); if (ao_subdevice) { int i = strcspn(ao_subdevice, ":"); if (i >= sizeof(hn)) i = sizeof(hn)-1; if (i > 0) { strncpy(host = hn, ao_subdevice, i); hn[i] = 0; } if (ao_subdevice[i] == ':') sink = ao_subdevice+i+1; } mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] -%s-%s-\n", host, sink); ss.channels = channels; ss.rate = rate_hz; switch (format) { case AF_FORMAT_U8: ss.format = PA_SAMPLE_U8; break; case AF_FORMAT_S16_LE: ss.format = PA_SAMPLE_S16LE; break; case AF_FORMAT_S16_BE: ss.format = PA_SAMPLE_S16BE; break; case AF_FORMAT_FLOAT_NE: ss.format = PA_SAMPLE_FLOAT32; break; default: mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] Unsupported sample spec\n"); goto fail; } if (!pa_sample_spec_valid(&ss)) { mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] Invalid sample spec\n"); goto fail; } mainloop = pa_mainloop_new(); assert(mainloop); context = pa_context_new(pa_mainloop_get_api(mainloop), POLYP_CLIENT_NAME); assert(context); pa_context_connect(context, host, 1, NULL); wait_for_completion(); if (pa_context_get_state(context) != PA_CONTEXT_READY) { mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] Failed to connect to server: %s\n", pa_strerror(pa_context_errno(context))); goto fail; } stream = pa_stream_new(context, "audio stream", &ss); assert(stream); a.maxlength = pa_bytes_per_second(&ss)*1; a.tlength = a.maxlength*9/10; a.prebuf = a.tlength/2; a.minreq = a.tlength/10; pa_stream_connect_playback(stream, sink, &a, PA_STREAM_INTERPOLATE_LATENCY, PA_VOLUME_NORM); wait_for_completion(); if (pa_stream_get_state(stream) != PA_STREAM_READY) { mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] Failed to connect to server: %s\n", pa_strerror(pa_context_errno(context))); goto fail; } return 1; fail: uninit(1); return 0; } /** Destroy libao driver */ static void uninit(int immed) { if (stream) { if (!immed && pa_stream_get_state(stream) == PA_STREAM_READY) wait_for_operation(pa_stream_drain(stream, NULL, NULL)); pa_stream_unref(stream); stream = NULL; } if (context) { pa_context_unref(context); context = NULL; } if (mainloop) { pa_mainloop_free(mainloop); mainloop = NULL; } } /** Play the specified data to the polypaudio server */ static int play(void* data, int len, int flags) { assert(stream && context); if (pa_stream_get_state(stream) != PA_STREAM_READY) return -1; if (!len) wait_for_operation(pa_stream_trigger(stream, NULL, NULL)); else pa_stream_write(stream, data, len, NULL, 0); wait_for_completion(); if (pa_stream_get_state(stream) != PA_STREAM_READY) return -1; return len; } /** Pause the audio stream by corking it on the server */ static void audio_pause() { assert(stream && context && pa_stream_get_state(stream) == PA_STREAM_READY); wait_for_operation(pa_stream_cork(stream, 1, NULL, NULL)); } /** Resume the audio stream by uncorking it on the server */ static void audio_resume() { assert(stream && context && pa_stream_get_state(stream) == PA_STREAM_READY); wait_for_operation(pa_stream_cork(stream, 0, NULL, NULL)); } /** Reset the audio stream, i.e. flush the playback buffer on the server side */ static void reset() { assert(stream && context && pa_stream_get_state(stream) == PA_STREAM_READY); wait_for_operation(pa_stream_flush(stream, NULL, NULL)); } /** Return number of bytes that may be written to the server without blocking */ static int get_space(void) { uint32_t l; assert(stream && context && pa_stream_get_state(stream) == PA_STREAM_READY); keep_alive(); l = pa_stream_writable_size(stream); return l; } /* A temporary latency variable */ /* static pa_usec_t latency = 0; */ /* static void latency_func(struct pa_stream *s, const struct pa_latency_info *l, void *userdata) { */ /* int negative = 0; */ /* if (!l) { */ /* mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] Invalid sample spec: %s\n", pa_strerror(pa_context_errno(context))); */ /* return; */ /* } */ /* latency = pa_stream_get_latency(s, l, &negative); */ /* /\* Nor really required *\/ */ /* if (negative) */ /* latency = 0; */ /* } */ /** Return the current latency in seconds */ static float get_delay(void) { assert(stream && context && pa_stream_get_state(stream) == PA_STREAM_READY); pa_usec_t latency; /* latency = 0; */ /* wait_for_operation(pa_stream_get_latency(stream, latency_func, NULL)); */ /* pa_operation_unref(pa_stream_get_latency(stream, latency_func, NULL)); */ latency = pa_stream_get_interpolated_latency(stream, NULL); return (float) latency/1000000; } /** A temporary variable to store the current volume */ static pa_volume_t volume = PA_VOLUME_NORM; /** A callback function that is called when the * pa_context_get_sink_input_info() operation completes. Saves the * volume field of the specified structure to the global variable volume. */ static void info_func(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) { if (is_last < 0) { mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] Failed to get sink input info: %s\n", pa_strerror(pa_context_errno(context))); return; } if (!i) return; volume = i->volume; } /** Issue special libao controls on the device */ static int control(int cmd, void *arg) { if (!context || !stream) return CONTROL_ERROR; switch (cmd) { case AOCONTROL_SET_DEVICE: /* Change the playback device */ sink = (char*)arg; return CONTROL_OK; case AOCONTROL_GET_DEVICE: /* Return the playback device */ *(char**)arg = sink; return CONTROL_OK; case AOCONTROL_GET_VOLUME: { /* Return the current volume of the playback stream */ ao_control_vol_t *vol = (ao_control_vol_t*) arg; volume = PA_VOLUME_NORM; wait_for_operation(pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_func, NULL)); vol->left = vol->right = (int) (pa_volume_to_user(volume)*100); return CONTROL_OK; } case AOCONTROL_SET_VOLUME: { /* Set the playback volume of the stream */ const ao_control_vol_t *vol = (ao_control_vol_t*) arg; int v = vol->left; if (vol->right > v) v = vol->left; wait_for_operation(pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), pa_volume_from_user((double)v/100), NULL, NULL)); return CONTROL_OK; } default: /* Unknown CONTROL command */ return CONTROL_UNKNOWN; } }