-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
1,517 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 - |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(¶ms); | |||
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; | |||
} |
Oops, something went wrong.