Enabled Audio Sync
This commit is contained in:
@@ -9,7 +9,6 @@ Requires 5G Wifi connection.
|
|||||||
1. Video and audio are supported out of the box.
|
1. Video and audio are supported out of the box.
|
||||||
3. Gstreamer decoding is plugin agnostic. Uses accelerated decoders if availible. VAAPI is preferable.
|
3. Gstreamer decoding is plugin agnostic. Uses accelerated decoders if availible. VAAPI is preferable.
|
||||||
4. Automatic screen orientation.
|
4. Automatic screen orientation.
|
||||||
5. No source timesync by now.
|
|
||||||
6. GTK+ support
|
6. GTK+ support
|
||||||
|
|
||||||
##Building:
|
##Building:
|
||||||
@@ -20,4 +19,4 @@ Requires 5G Wifi connection.
|
|||||||
|
|
||||||
##GTK+ Features:
|
##GTK+ Features:
|
||||||
1. Double click switches between fullscreen mode and normal window.
|
1. Double click switches between fullscreen mode and normal window.
|
||||||
2. Escape key ends fullscreen mode.
|
2. Escape key ends fullscreen mode.
|
||||||
|
|||||||
@@ -130,14 +130,13 @@ std::string find_mac() {
|
|||||||
|
|
||||||
void print_info(char *name) {
|
void print_info(char *name) {
|
||||||
printf("RPiPlay %s: An open-source AirPlay mirroring server for Raspberry Pi\n", VERSION);
|
printf("RPiPlay %s: An open-source AirPlay mirroring server for Raspberry Pi\n", VERSION);
|
||||||
printf("Usage: %s [-b (on|auto|off)] [-n name] [-a (hdmi|analog|off)]\n", name);
|
printf("Usage: %s [-n name]\n", name);
|
||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf("-n name Specify the network name of the AirPlay server\n");
|
printf("-n name Specify the network name of the AirPlay server\n");
|
||||||
printf("-b (on|auto|off) Show black background always, only during active connection, or never\n");
|
printf("-a Turn audio off. Only video output\n");
|
||||||
printf("-a (hdmi|analog|off) Set audio output device\n");
|
|
||||||
printf("-l Enable low-latency mode (disables render clock)\n");
|
printf("-l Enable low-latency mode (disables render clock)\n");
|
||||||
printf("-d Enable debug logging\n");
|
printf("-d Enable debug logging\n");
|
||||||
printf("-v/-h Displays this help and version information\n");
|
printf("-v/-h Displays this help and version information\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_destroy (GtkWidget * widget, gpointer data) {
|
static void gtk_destroy (GtkWidget * widget, gpointer data) {
|
||||||
@@ -220,24 +219,10 @@ int main(int argc, char *argv[]) {
|
|||||||
if (arg == "-n") {
|
if (arg == "-n") {
|
||||||
if (i == argc - 1) continue;
|
if (i == argc - 1) continue;
|
||||||
server_name = std::string(argv[++i]);
|
server_name = std::string(argv[++i]);
|
||||||
} else if (arg == "-b") {
|
|
||||||
// For backwards-compatibility, make just -b disable the background
|
|
||||||
if (i == argc - 1 || argv[i + 1][0] == '-') {
|
|
||||||
background = BACKGROUND_MODE_OFF;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string background_mode(argv[++i]);
|
|
||||||
background = background_mode == "off" ? BACKGROUND_MODE_OFF :
|
|
||||||
background_mode == "auto" ? BACKGROUND_MODE_AUTO :
|
|
||||||
BACKGROUND_MODE_ON;
|
|
||||||
} else if (arg == "-a") {
|
} else if (arg == "-a") {
|
||||||
if (i == argc - 1) continue;
|
audio_device = AUDIO_DEVICE_NONE;
|
||||||
std::string audio_device_name(argv[++i]);
|
} else if (arg == "-l") {
|
||||||
audio_device = audio_device_name == "hdmi" ? AUDIO_DEVICE_HDMI :
|
|
||||||
audio_device_name == "analog" ? AUDIO_DEVICE_ANALOG :
|
|
||||||
AUDIO_DEVICE_NONE;
|
|
||||||
} else if (arg == "-l") {
|
|
||||||
low_latency = !low_latency;
|
low_latency = !low_latency;
|
||||||
} else if (arg == "-d") {
|
} else if (arg == "-d") {
|
||||||
debug_log = !debug_log;
|
debug_log = !debug_log;
|
||||||
@@ -431,7 +416,7 @@ int stop_server() {
|
|||||||
raop_destroy(raop);
|
raop_destroy(raop);
|
||||||
dnssd_unregister_raop(dnssd);
|
dnssd_unregister_raop(dnssd);
|
||||||
dnssd_unregister_airplay(dnssd);
|
dnssd_unregister_airplay(dnssd);
|
||||||
audio_renderer_destroy(audio_renderer);
|
if (audio_renderer) audio_renderer_destroy(audio_renderer);
|
||||||
video_renderer_destroy(video_renderer);
|
video_renderer_destroy(video_renderer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#define RAOP_CN "0,1,2,3" /* Audio codec: PCM, ALAC, AAC, AAC ELD */
|
#define RAOP_CN "0,1,2,3" /* Audio codec: PCM, ALAC, AAC, AAC ELD */
|
||||||
#define RAOP_ET "0,3,5" /* Encryption type: None, FairPlay, FairPlay SAPv2.5 */
|
#define RAOP_ET "0,3,5" /* Encryption type: None, FairPlay, FairPlay SAPv2.5 */
|
||||||
#define RAOP_VV "2"
|
#define RAOP_VV "2"
|
||||||
#define RAOP_FT "0x5A7FFFF7,0x1E"
|
#define RAOP_FT "0x5A7FFFE6"
|
||||||
#define RAOP_RHD "5.6.0.0"
|
#define RAOP_RHD "5.6.0.0"
|
||||||
#define RAOP_SF "0x4"
|
#define RAOP_SF "0x4"
|
||||||
#define RAOP_SV "false"
|
#define RAOP_SV "false"
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
#define RAOP_VN "65537"
|
#define RAOP_VN "65537"
|
||||||
#define RAOP_PK "b07727d6f6cd6e08b58ede525ec3cdeaa252ad9f683feb212ef8a205246554e7"
|
#define RAOP_PK "b07727d6f6cd6e08b58ede525ec3cdeaa252ad9f683feb212ef8a205246554e7"
|
||||||
|
|
||||||
#define AIRPLAY_FEATURES "0x5A7FFFF7,0x1E"
|
#define AIRPLAY_FEATURES "0x5A7FFFE6"
|
||||||
#define AIRPLAY_SRCVERS "220.68"
|
#define AIRPLAY_SRCVERS "220.68"
|
||||||
#define AIRPLAY_FLAGS "0x4"
|
#define AIRPLAY_FLAGS "0x4"
|
||||||
#define AIRPLAY_VV "2"
|
#define AIRPLAY_VV "2"
|
||||||
#define AIRPLAY_PK "b07727d6f6cd6e08b58ede525ec3cdeaa252ad9f683feb212ef8a205246554e7"
|
#define AIRPLAY_PK "b07727d6f6cd6e08b58ede525ec3cdeaa252ad9f683feb212ef8a205246554e7"
|
||||||
#define AIRPLAY_PI "2e388006-13ba-4041-9a67-25dd4a43d536"
|
#define AIRPLAY_PI "2e388006-13ba-4041-9a67-25dd4a43d536"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,11 +24,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
#include <gst/app/gstappsrc.h>
|
#include <gst/app/gstappsrc.h>
|
||||||
|
|
||||||
struct audio_renderer_s {
|
struct audio_renderer_s {
|
||||||
logger_t *logger;
|
logger_t *logger;
|
||||||
video_renderer_t *video_renderer;
|
|
||||||
GstElement *appsrc;
|
GstElement *appsrc;
|
||||||
GstElement *pipeline;
|
GstElement *pipeline;
|
||||||
GstElement *volume;
|
GstElement *volume;
|
||||||
@@ -44,7 +44,8 @@ audio_renderer_t *audio_renderer_init(logger_t *logger, video_renderer_t *video_
|
|||||||
}
|
}
|
||||||
renderer->logger = logger;
|
renderer->logger = logger;
|
||||||
|
|
||||||
renderer->pipeline = gst_parse_launch("appsrc name=audio_source is-live=true ! queue ! decodebin ! audioconvert ! audiorate ! volume name=volume volume=6 ! queue ! autoaudiosink sync=false", &error);
|
renderer->pipeline = gst_parse_launch("appsrc name=audio_source stream-type=0 format=GST_FORMAT_TIME is-live=true ! queue ! decodebin !"
|
||||||
|
"audioconvert ! volume name=volume ! level ! autoaudiosink sync=false", &error);
|
||||||
g_assert (renderer->pipeline);
|
g_assert (renderer->pipeline);
|
||||||
|
|
||||||
renderer->appsrc = gst_bin_get_by_name (GST_BIN (renderer->pipeline), "audio_source");
|
renderer->appsrc = gst_bin_get_by_name (GST_BIN (renderer->pipeline), "audio_source");
|
||||||
@@ -89,14 +90,18 @@ void audio_renderer_render_buffer(audio_renderer_t *renderer, raop_ntp_t *ntp, u
|
|||||||
|
|
||||||
buffer = gst_buffer_new_and_alloc(data_len);
|
buffer = gst_buffer_new_and_alloc(data_len);
|
||||||
assert(buffer != NULL);
|
assert(buffer != NULL);
|
||||||
|
GST_BUFFER_DTS(buffer) = (GstClockTime)pts;
|
||||||
gst_buffer_fill(buffer, 0, data, data_len);
|
gst_buffer_fill(buffer, 0, data, data_len);
|
||||||
gst_app_src_push_buffer(GST_APP_SRC(renderer->appsrc), buffer);
|
gst_app_src_push_buffer(GST_APP_SRC(renderer->appsrc), buffer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_renderer_set_volume(audio_renderer_t *renderer, float volume) {
|
void audio_renderer_set_volume(audio_renderer_t *renderer, float volume) {
|
||||||
//g_object_set(renderer->volume, "volume", volume, NULL);
|
float avol;
|
||||||
|
if (fabs(volume) < 28) {
|
||||||
|
avol=floorf(((28-fabs(volume))/28)*10)/10;
|
||||||
|
g_object_set(renderer->volume, "volume", avol, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_renderer_flush(audio_renderer_t *renderer) {
|
void audio_renderer_flush(audio_renderer_t *renderer) {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ video_renderer_t *video_renderer_init(logger_t *logger, background_mode_t backgr
|
|||||||
|
|
||||||
renderer->logger = logger;
|
renderer->logger = logger;
|
||||||
|
|
||||||
renderer->pipeline = gst_parse_launch("appsrc name=video_source is-live=true ! queue ! decodebin ! videoconvert ! videoscale ! xvimagesink name=video_sink sync=false", &error);
|
renderer->pipeline = gst_parse_launch("appsrc name=video_source stream-type=0 format=GST_FORMAT_TIME is-live=true ! queue ! decodebin ! videoconvert ! videoscale ! xvimagesink name=video_sink sync=false", &error);
|
||||||
/*
|
/*
|
||||||
renderer->pipeline = gst_pipeline_new("test-pipeline");
|
renderer->pipeline = gst_pipeline_new("test-pipeline");
|
||||||
renderer->appsrc = gst_element_factory_make("appsrc","video_source");
|
renderer->appsrc = gst_element_factory_make("appsrc","video_source");
|
||||||
@@ -91,7 +91,7 @@ void video_renderer_render_buffer(video_renderer_t *renderer, raop_ntp_t *ntp, u
|
|||||||
|
|
||||||
buffer = gst_buffer_new_and_alloc(data_len);
|
buffer = gst_buffer_new_and_alloc(data_len);
|
||||||
assert(buffer != NULL);
|
assert(buffer != NULL);
|
||||||
|
GST_BUFFER_DTS(buffer) = (GstClockTime)pts;
|
||||||
gst_buffer_fill(buffer, 0, data, data_len);
|
gst_buffer_fill(buffer, 0, data, data_len);
|
||||||
GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_CORRUPTED);
|
GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_CORRUPTED);
|
||||||
gst_app_src_push_buffer (GST_APP_SRC(renderer->appsrc), buffer);
|
gst_app_src_push_buffer (GST_APP_SRC(renderer->appsrc), buffer);
|
||||||
|
|||||||
Reference in New Issue
Block a user