Skip to content

Commit

Permalink
Merge branch 'rewrite'
Browse files Browse the repository at this point in the history
  • Loading branch information
wereHamster committed Mar 18, 2012
2 parents 4bd3a97 + 2ab6f6a commit c9ba909
Show file tree
Hide file tree
Showing 24 changed files with 1,517 additions and 98 deletions.
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,11 @@
config.make
sysconf

*.o

libGL.so
libX11.so
yukon-core-lib

filter
stat
28 changes: 22 additions & 6 deletions Makefile
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,27 +3,43 @@ DESTDIR =
PREFIX = /usr/local PREFIX = /usr/local
LIBDIR = lib LIBDIR = lib


ARCH = C

CC = gcc CC = gcc
CFLAGS = -Iinclude -Wall -std=c99 -O3 ASM = yasm

CFLAGS = -Iinclude -I$(PREFIX)/include -Wall -std=c99 -O3
LDFLAGS = -L$(PREFIX)/lib


OBJS = src/core/conf.o src/core/glue.o src/core/log.o OBJS = src/core/conf.o src/core/log.o src/stream/stream.o src/core/engine.o \
src/core/opengl.o src/stream/buffer.o \
src/glue/glue.o src/core/audio.o src/stream/arch/$(ARCH)/frame.o
LIBS = libX11.so libGL.so LIBS = libX11.so libGL.so


-include config.make -include config.make


.PHONY: all clean install .PHONY: all clean install
all: $(LIBS) yukon-core-lib sysconf all: $(LIBS) yukon-core-lib filter sysconf

%.o: %.asm
$(ASM) -m $(ARCH) -f elf -o $@ $<


%.o: %.c %.o: %.c
$(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<

$(LIBS): $(LIBS):
$(CC) -shared -o $@.native -Wl,-soname,$@.native $(CC) -shared -o $@.native -Wl,-soname,$@.native
$(CC) $(CFLAGS) -fPIC -shared -o $@ src/libs/$(@:%.so=%.c) $@.native $(CC) $(CFLAGS) -fPIC -shared -o $@ src/libs/$(@:%.so=%.c) $@.native
rm -f $@.native rm -f $@.native


yukon-core-lib: $(OBJS) yukon-core-lib: $(OBJS)
$(CC) -shared -o $@ $(OBJS) -lseom $(CC) -shared -o $@ $(OBJS) $(LDFLAGS) -lasound -lseom

filter: src/filter/main.c src/filter/wav.c src/filter/y4m.c
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lasound -lseom

stat: src/tools/stat.c
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lseom


sysconf: sysconf:
echo 'LDPATH="$(PREFIX)/$(LIBDIR)/yukon"' > $@ echo 'LDPATH="$(PREFIX)/$(LIBDIR)/yukon"' > $@
Expand All @@ -38,7 +54,7 @@ install: $(LIBS) yukon-core-lib
$(foreach lib,$(LIBS),install -m 755 $(lib) $(DESTDIR)$(PREFIX)/$(LIBDIR)/yukon/$(call soname,$(lib));) $(foreach lib,$(LIBS),install -m 755 $(lib) $(DESTDIR)$(PREFIX)/$(LIBDIR)/yukon/$(call soname,$(lib));)


clean: clean:
rm -f $(OBJS) $(LIBS) yukon-core-lib sysconf rm -f $(OBJS) $(LIBS) filter yukon-core-lib sysconf


mrproper: clean mrproper: clean
rm -f config.make rm -f config.make
4 changes: 4 additions & 0 deletions convert-to-avi.sh
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh

./filter --audio "$1" | lame - audio.mp3
./filter --video "$1" | mencoder -vf scale=1280:720 -ovc xvid -xvidencopts bitrate=1800 -oac copy -audiofile audio.mp3 -o video.avi -
1 change: 1 addition & 0 deletions include/loader.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define glue(name, ...) ({ \ #define glue(name, ...) ({ \
if (__builtin_expect(core == NULL, 0)) { \ if (__builtin_expect(core == NULL, 0)) { \
void *handle = dlopen("yukon-core-lib", RTLD_LAZY); \ void *handle = dlopen("yukon-core-lib", RTLD_LAZY); \
dlerror(); \
if (handle) \ if (handle) \
core = (__typeof__(core)) dlsym(handle, name); \ core = (__typeof__(core)) dlsym(handle, name); \
} (*core)(__VA_ARGS__); }) \ } (*core)(__VA_ARGS__); }) \
Expand Down
45 changes: 45 additions & 0 deletions include/stream.h
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,45 @@

#ifndef __YUKON_STREAM__
#define __YUKON_STREAM__

#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE

#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <seom/stream.h>

struct yukonBuffer {
pthread_mutex_t mutex;
pthread_cond_t cond;

unsigned long size, head, tail;
struct seomPacket *array[0];
};

struct yukonStream {
int fileDescriptor;
seomStream *stream;
pthread_t multiplexerThread;
struct yukonBuffer *buffer;
};

struct yukonBuffer *yukonBufferCreate(unsigned long size);
void yukonBufferPut(struct yukonBuffer *buffer, struct seomPacket *packet);
struct seomPacket *yukonBufferGet(struct yukonBuffer *buffer);
unsigned long yukonBufferCount(struct yukonBuffer *buffer);
void yukonBufferDestroy(struct yukonBuffer *buffer);

struct yukonStream *yukonStreamCreate(const char *spec, unsigned long size);
unsigned long yukonStreamStatus(struct yukonStream *stream);
void yukonStreamPut(struct yukonStream *stream, struct seomPacket *packet);
void yukonStreamDestroy(struct yukonStream *stream);

#endif /* __YUKON_STREAM__ */
41 changes: 35 additions & 6 deletions include/yukon.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,34 +2,63 @@
#ifndef __YUKON_H__ #ifndef __YUKON_H__
#define __YUKON_H__ #define __YUKON_H__


#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE

#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <dlfcn.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include <stdint.h>

#include <sys/types.h>
#include <sys/stat.h>

#include <linux/limits.h> #include <linux/limits.h>


#include <seom/seom.h> #include <pthread.h>


#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/keysym.h> #include <X11/keysym.h>


#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glext.h> #include <GL/glext.h>
#include <GL/glx.h> #include <GL/glx.h>


#include <stream.h>

void logMessage(unsigned long level, const char *fmt, ...); void logMessage(unsigned long level, const char *fmt, ...);
void updateConfiguration(void); void updateConfiguration(void);


void yukonCoreCapture(Display *dpy, GLXDrawable drawable);
void yukonCoreEvent(Display *dpy, XEvent *event);

typedef struct { typedef struct {
unsigned long logLevel; unsigned long logLevel;
KeySym hotkey; KeySym hotkey;


unsigned int insets[4];
unsigned int scale; unsigned int scale;
double fps; double fps;
char output[PATH_MAX]; char output[PATH_MAX];
} yukonGlobalData; } yukonGlobalData;


extern yukonGlobalData yukonGlobal; extern yukonGlobalData yukonGlobal;


struct yukonEngine {
struct yukonStream *stream;
unsigned long size[2];

pthread_mutex_t audioMutex;
unsigned long audioRunning;
pthread_t audioThread;
};

struct yukonEngine *yukonEngineCreate(const char *spec, unsigned long scale, unsigned long size[2]);
void yukonEngineCapture(struct yukonEngine *engine);
struct yukonEngine *yukonEngineDestroy(struct yukonEngine *engine);

void *audioThreadCallback(void *data);

#endif /* __YUKON_H__ */ #endif /* __YUKON_H__ */
4 changes: 4 additions & 0 deletions play-stream.sh
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh

./filter --video "$1" | mplayer - &>/dev/null &
./filter --audio "$1" | mplayer -demuxer 35 - &>/dev/null
195 changes: 195 additions & 0 deletions src/core/audio.c
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,195 @@

#include <alsa/asoundlib.h>
#include <yukon.h>
#include <alloca.h>

static int xrun(snd_pcm_t *handle, int err)
{
if (err == -EPIPE) { /* xrun */
return snd_pcm_prepare(handle);
} else if (err == -ESTRPIPE) {
while ((err = snd_pcm_resume(handle)) == -EAGAIN)
sleep(1); /* wait until the suspend flag is released */
if (err < 0)
return snd_pcm_prepare(handle);
return 0;
} else {
return err;
}
}

snd_pcm_hw_params_t *getParams(snd_pcm_t *pcm)
{
snd_pcm_hw_params_t *params;
snd_pcm_hw_params_malloc(&params);
snd_pcm_hw_params_any(pcm, params);

logMessage(3, "params: access\n");
if (snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
goto failed;

snd_pcm_format_mask_t *formats = alloca(snd_pcm_format_mask_sizeof());
snd_pcm_format_mask_none(formats);
snd_pcm_format_mask_set(formats, SND_PCM_FORMAT_S16_LE);
snd_pcm_format_mask_set(formats, SND_PCM_FORMAT_S24_LE);
snd_pcm_format_mask_set(formats, SND_PCM_FORMAT_S32_LE);

logMessage(3, "params: format\n");
if (snd_pcm_hw_params_set_format_mask(pcm, params, formats) < 0)
goto failed;
logMessage(3, "params: channels\n");
if (snd_pcm_hw_params_set_channels(pcm, params, 2) < 0)
goto failed;
logMessage(3, "params: rate\n");
if (snd_pcm_hw_params_set_rate(pcm, params, 48000, 0) < 0)
goto failed;

snd_pcm_uframes_t size;
if (snd_pcm_hw_params_get_buffer_size_max(params, &size) < 0)
goto failed;
logMessage(3, "params: buffer size\n");
if (snd_pcm_hw_params_set_buffer_size(pcm, params, size) < 0)
goto failed;

int dir;
unsigned int periods;
if (snd_pcm_hw_params_get_periods_min(params, &periods, &dir) < 0)
goto failed;
logMessage(3, "params: periods\n");
if (snd_pcm_hw_params_set_periods(pcm, params, periods < 2 ? 2 : periods, dir) < 0)
goto failed;

return params;

failed:
logMessage(3, "failed to set PCM parameters\n");
snd_pcm_hw_params_free(params);
return NULL;
}

snd_pcm_t *openAudioDevice(const char *device, snd_pcm_uframes_t *period)
{
snd_pcm_t *pcm = NULL;

int err = snd_pcm_open(&pcm, device, SND_PCM_STREAM_CAPTURE, 0);
if (err < 0) {
logMessage(3, "failed to open PCM device: %s\n", snd_strerror(err));
return NULL;
}

snd_pcm_hw_params_t *params = getParams(pcm);
if (params == NULL)
goto failed;

if (snd_pcm_hw_params(pcm, params) < 0)
goto failed;

snd_pcm_hw_params_get_period_size(params, period, NULL);
snd_pcm_hw_params_free(params);

snd_output_t *output= NULL;
snd_output_stdio_attach(&output, stdout, 0);
snd_pcm_dump(pcm, output);

return pcm;

failed:
snd_pcm_hw_params_free(params);
snd_pcm_close(pcm);

return NULL;
}

static int wait(snd_pcm_t *pcm, struct pollfd *ufds, unsigned int count)
{
for (;;) {
poll(ufds, count, -1);

unsigned short revents;
snd_pcm_poll_descriptors_revents(pcm, ufds, count, &revents);

if (revents & POLLERR)
return -EIO;
else if (revents & POLLIN)
return 0;
}
}

void *audioThreadCallback(void *data)
{
struct yukonEngine *engine = data;

snd_pcm_uframes_t period;
snd_pcm_t *pcm = openAudioDevice("hw:0", &period);
if (pcm == NULL) {
logMessage(3, "failed to set up audio capturing device, no sound will be captured!\n");
return NULL;
}

logMessage(4, "Audio capturing device is set up (period: %u)\n", period);

int count = snd_pcm_poll_descriptors_count(pcm);
struct pollfd ufds[count];

snd_pcm_poll_descriptors(pcm, ufds, count);

uint32_t header[1] = { snd_pcm_frames_to_bytes(pcm, 1) / 2 };
struct seomPacket *pkt = seomPacketCreate(0x02, sizeof(header));
memcpy(seomPacketPayload(pkt), &header, sizeof(header));
yukonStreamPut(engine->stream, pkt);

for (;;) {
if (snd_pcm_state(pcm) == SND_PCM_STATE_PREPARED)
snd_pcm_start(pcm);

pthread_mutex_lock(&engine->audioMutex);
if (engine->audioRunning == 0)
break;
pthread_mutex_unlock(&engine->audioMutex);

int err = xrun(pcm, wait(pcm, ufds, count));
if (err < 0)
continue;

struct seomPacket *packet = seomPacketCreate(0x03, snd_pcm_frames_to_bytes(pcm, period));
if (packet == NULL)
continue;

snd_pcm_sframes_t delay;
snd_pcm_delay(pcm, &delay);
packet->time -= 1000000 / 48000 * delay;

snd_pcm_sframes_t ret = snd_pcm_readi(pcm, seomPacketPayload(packet), period);
if (ret < 0) {
logMessage(2, "overrun!\n");
ret = xrun(pcm, ret);
}

yukonStreamPut(engine->stream, packet);
}

pthread_mutex_unlock(&engine->audioMutex);

snd_pcm_drain(pcm);
snd_pcm_uframes_t left = snd_pcm_avail_update(pcm);
if (left > 0) {
struct seomPacket *packet = seomPacketCreate(0x03, snd_pcm_frames_to_bytes(pcm, left));
if (packet) {
snd_pcm_sframes_t delay;
snd_pcm_delay(pcm, &delay);
packet->time -= 1000000 / 48000 * delay;

snd_pcm_sframes_t ret = snd_pcm_readi(pcm, seomPacketPayload(packet), left);
if (ret < 0) {
logMessage(2, "overrun (%d)!\n", ret);
ret = xrun(pcm, ret);
}

yukonStreamPut(engine->stream, packet);
}
}

snd_pcm_close(pcm);

return NULL;
}
Loading

0 comments on commit c9ba909

Please sign in to comment.