mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-21 09:40:18 +00:00
merge for opus codec over rtp transmission support
This commit is contained in:
@@ -27,7 +27,7 @@
|
||||
|
||||
/* DeckLinkAPIVersion.h */
|
||||
|
||||
#ifndef __DeckLink_API_Verison_h__
|
||||
#ifndef __DeckLink_API_Version_h__
|
||||
#define __DeckLink_API_Version_h__
|
||||
|
||||
#define BLACKMAGIC_DECKLINK_API_VERSION 0x08050000
|
||||
|
||||
125
Makefile.in
125
Makefile.in
@@ -9,13 +9,14 @@ COMMON_FLAGS = -g @DEFS@ -DPATH_PREFIX=@prefix@ -DLIB_DIR=@libdir@ -Wall -Wextr
|
||||
CFLAGS = @CFLAGS@ @X_CFLAGS@ $(COMMON_FLAGS) -D_GNU_SOURCE
|
||||
CPPFLAGS = @CPPFLAGS@ -D_GNU_SOURCE
|
||||
CXXFLAGS = @CXXFLAGS@ $(COMMON_FLAGS) -D_GNU_SOURCE
|
||||
NVCCFLAGS = @NVCCFLAGS@
|
||||
MKDIR_P = mkdir -p
|
||||
NVCCFLAGS = @NVCCFLAGS@ -gencode arch=compute_20,code=sm_20 -gencode arch=compute_30,code=sm_30 -gencode arch=compute_35,code=sm_35
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBS += @LIBS@ @JACK_TRANS_LIB@ @MATHLIBS@ @COREAUDIO_LIB@ \
|
||||
-lm -pthread
|
||||
INC = -I. -Isrc -Itest @DVS_INC@ @DELTACAST_INC@ @QUICKTIME_INC@ @RTSP_INC@ @RTSP_SERVER_INC@ @DECKLINK_INC@ @PORTAUDIO_INC@ \
|
||||
INC = -Isrc -I$(srcdir) -I$(srcdir)/src -I$(srcdir)/test @DVS_INC@ @DELTACAST_INC@ @QUICKTIME_INC@ @RTSP_INC@ @DECKLINK_INC@ @PORTAUDIO_INC@ \
|
||||
@GL_INC@ @SAGE_INC@ @JACK_TRANS_INC@ @JPEG_INC@ @COREAUDIO_INC@ @SPEEX_INC@ \
|
||||
@BLUEFISH444_INC@ @CURSES_CFLAGS@
|
||||
@BLUEFISH444_INC@ @CURSES_CFLAGS@ @CUDA_INC@
|
||||
DECKLINK_PATH = @DECKLINK_PATH@
|
||||
EXEEXT = @EXEEXT@
|
||||
TARGET = bin/uv$(EXEEXT)
|
||||
@@ -25,7 +26,6 @@ PERF = bin/uv_perf
|
||||
BUNDLE = uv.app
|
||||
DXT_GLSL_CFLAGS = @DXT_GLSL_CFLAGS@
|
||||
NVCC = @NVCC@
|
||||
|
||||
DOCS = README REPORTING-BUGS
|
||||
|
||||
GUI_TARGET = @GUI_TARGET@
|
||||
@@ -41,13 +41,16 @@ datadir = @datadir@
|
||||
docdir = @docdir@/ultragrid/
|
||||
datarootdir = @datarootdir@
|
||||
uv_datadir = @datadir@/ultragrid/
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
# autogenerated headers
|
||||
GENERATED_HEADERS = @GENERATED_HEADERS@
|
||||
|
||||
ALL_INCLUDES = $(wildcard src/*.h) $(wildcard src/*/*.h)
|
||||
ALL_INCLUDES = $(wildcard $(srcdir)/src/*.h $(srcdir)/src/*/*.h $(srcdir)/src/*/*/*.h)
|
||||
|
||||
OBJS = @OBJS@ \
|
||||
src/blackmagic_common.o \
|
||||
src/bitstream.o \
|
||||
src/control_socket.o \
|
||||
src/debug.o \
|
||||
@@ -138,6 +141,7 @@ OBJS = @OBJS@ \
|
||||
src/video_display.o \
|
||||
src/video_display/aggregate.o \
|
||||
src/video_display/null.o \
|
||||
src/video_display/pipe.o \
|
||||
src/video_export.o \
|
||||
src/video_rxtx.o \
|
||||
src/video_rxtx/ihdtv.o \
|
||||
@@ -145,6 +149,7 @@ OBJS = @OBJS@ \
|
||||
src/video_rxtx/sage.o \
|
||||
src/video_rxtx/ultragrid_rtp.o \
|
||||
src/vo_postprocess.o \
|
||||
src/vo_postprocess/deinterlace.o \
|
||||
src/vo_postprocess/3d-interlaced.o \
|
||||
src/vo_postprocess/interlace.o \
|
||||
src/vo_postprocess/double-framerate.o \
|
||||
@@ -165,24 +170,25 @@ IMPORT_CONTROL_KEYBOARD_OBJS = src/import_control_keyboard.o
|
||||
SWITCHER_CONTROL_KEYBOARD_OBJS = src/switcher_control_keyboard.o
|
||||
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
all: $(TARGET) $(GUI_TARGET) $(IMPORT_C_TARGET) $(SWITCHER_TARGET) $(REFLECTOR_TARGET) modules ag-plugins configure-messages
|
||||
all: src/dir-stamp $(TARGET) $(GUI_TARGET) $(IMPORT_C_TARGET) $(SWITCHER_TARGET) $(REFLECTOR_TARGET) modules ag-plugins configure-messages
|
||||
|
||||
src/dir-stamp:
|
||||
${MKDIR_P} src src/audio src/audio/capture src/audio/codec src/audio/playback src/capture_filter src/compat src/crypto src/hd-rum-translator src/ihdtv src/rtp src/rtsp src/utils src/video_capture src/video_compress src/video_decompress src/video_display src/video_rxtx src/vo_postprocess ag_plugin bin cuda_dxt dxt_compress ldgm-coding ldgm-coding/matrix-gen lib lib/ultragrid
|
||||
touch $@
|
||||
|
||||
modules: @LIB_TARGETS@
|
||||
|
||||
bindir:
|
||||
@if [ ! -d bin ]; then mkdir bin; fi
|
||||
|
||||
$(TARGET): bindir $(OBJS) $(ULTRAGRID_OBJS) $(GENERATED_HEADERS)
|
||||
$(TARGET): $(OBJS) $(ULTRAGRID_OBJS) $(GENERATED_HEADERS)
|
||||
$(LINKER) $(LDFLAGS) $(OBJS) $(ULTRAGRID_OBJS) $(LIBS) -o $(TARGET)
|
||||
if [ -n "@DLL_LIBS@" ]; then $(INSTALL) -m 644 @DLL_LIBS@ bin; fi
|
||||
|
||||
$(IMPORT_C_TARGET): bindir $(IMPORT_CONTROL_KEYBOARD_OBJS)
|
||||
$(IMPORT_C_TARGET): $(IMPORT_CONTROL_KEYBOARD_OBJS)
|
||||
$(LINKER) $(LDFLAGS) $(IMPORT_CONTROL_KEYBOARD_OBJS) @CURSES_LIBS@ @NET_LIBS@ -o $@
|
||||
|
||||
$(SWITCHER_TARGET): bindir $(SWITCHER_CONTROL_KEYBOARD_OBJS)
|
||||
$(SWITCHER_TARGET): $(SWITCHER_CONTROL_KEYBOARD_OBJS)
|
||||
$(LINKER) $(LDFLAGS) $(SWITCHER_CONTROL_KEYBOARD_OBJS) @CURSES_LIBS@ @NET_LIBS@ -o $@ -pthread
|
||||
|
||||
$(REFLECTOR_TARGET): bindir $(OBJS) $(GENERATED_HEADERS) $(REFLECTOR_OBJS)
|
||||
$(REFLECTOR_TARGET): $(OBJS) $(GENERATED_HEADERS) $(REFLECTOR_OBJS)
|
||||
$(LINKER) $(LDFLAGS) $(OBJS) $(REFLECTOR_OBJS) $(LIBS) -o $@
|
||||
|
||||
%.o: %.c $(ALL_INCLUDES)
|
||||
@@ -206,33 +212,33 @@ $(REFLECTOR_TARGET): bindir $(OBJS) $(GENERATED_HEADERS) $(REFLECTOR_OBJS)
|
||||
%.cu.lib: %.cu $(ALL_INCLUDES)
|
||||
"$(NVCC)" $(NVCCFLAGS) -DEXPORT_DLL_SYMBOLS $(INC) --shared $< -o $<.dll
|
||||
|
||||
SPEEX_FLAGS=-Wno-sign-compare -Wno-unused-parameter -Wno-bad-function-cast -Wno-missing-prototypes -Wno-missing-declarations
|
||||
src/audio/resample.o:
|
||||
$(CC) $(CFLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c speex-1.2rc1/libspeex/resample.c -fPIC -DPIC -o $@
|
||||
$(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/resample.c -fPIC -DPIC -o $@
|
||||
|
||||
src/audio/preprocess.o:
|
||||
$(CC) $(CFLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c speex-1.2rc1/libspeex/preprocess.c -fPIC -DPIC -o $@
|
||||
$(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/preprocess.c -fPIC -DPIC -o $@
|
||||
|
||||
src/audio/filterbank.o:
|
||||
$(CC) $(CFLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -I/include -fvisibility=hidden -c speex-1.2rc1/libspeex/filterbank.c -fPIC -DPIC -o $@
|
||||
$(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -I/include -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/filterbank.c -fPIC -DPIC -o $@
|
||||
|
||||
src/audio/fftwrap.o:
|
||||
$(CC) $(CFLAGS) $(INC) -DUSE_SMALLFT -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c speex-1.2rc1/libspeex/fftwrap.c -fPIC -DPIC -o $@
|
||||
$(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DUSE_SMALLFT -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/fftwrap.c -fPIC -DPIC -o $@
|
||||
|
||||
src/audio/smallft.o:
|
||||
$(CC) $(CFLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c speex-1.2rc1/libspeex/smallft.c -fPIC -DPIC -o $@
|
||||
$(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/smallft.c -fPIC -DPIC -o $@
|
||||
|
||||
src/audio/mdf.o:
|
||||
$(CC) $(CFLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c speex-1.2rc1/libspeex/mdf.c -fPIC -DPIC -o $@
|
||||
$(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/mdf.c -fPIC -DPIC -o $@
|
||||
|
||||
src/audio/capture/coreaudio.o: src/audio/capture/coreaudio.c $(ALL_INCLUDES)
|
||||
$(CC) $(CFLAGS) -Wno-error=deprecated-declarations $(INC) -c $< -o $@
|
||||
|
||||
src/mac_gl_common.o: src/mac_gl_common.m src/mac_gl_common.h
|
||||
$(CC) $(CFLAGS) $(INC) -x objective-c -c $< -o $@
|
||||
src/audio/playback/coreaudio.o: src/audio/playback/coreaudio.c $(ALL_INCLUDES)
|
||||
$(CC) $(CFLAGS) -Wno-error=deprecated-declarations $(INC) -c $< -o $@
|
||||
|
||||
src/utils/autorelease_pool.o: src/utils/autorelease_pool.m src/utils/autorelease_pool.h
|
||||
$(CC) $(CFLAGS) $(INC) -x objective-c -c $< -o $@
|
||||
|
||||
src/utils/packet_counter.o: src/utils/packet_counter.cpp src/utils/packet_counter.h
|
||||
$(CXX) $(CXXFLAGS) $(INC) -c $< -o $@
|
||||
src/video_display/quicktime.o: src/video_display/quicktime.c $(ALL_INCLUDES)
|
||||
$(CC) $(CFLAGS) -Wno-error=deprecated-declarations $(INC) -c $< -o $@
|
||||
|
||||
src/video_capture/DeckLinkAPIDispatch.o: $(DECKLINK_PATH)/DeckLinkAPIDispatch.cpp
|
||||
$(CXX) $(CXXFLAGS) -c $(INC) -o src/video_capture/DeckLinkAPIDispatch.o $(DECKLINK_PATH)/DeckLinkAPIDispatch.cpp
|
||||
@@ -413,18 +419,18 @@ tests: test/run_tests
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
ag-plugins: ag_plugin/uvReceiverService.zip ag_plugin/uvSenderService.zip
|
||||
|
||||
AG_PLUGIN_TX_SCRIPTS = ag_plugin/uvSenderService.py \
|
||||
ag_plugin/uvSenderService.svc \
|
||||
ag_plugin/uvSenderService.manifest
|
||||
AG_PLUGIN_TX_SCRIPTS = $(srcdir)/ag_plugin/uvSenderService.py \
|
||||
$(srcdir)/ag_plugin/uvSenderService.svc \
|
||||
$(srcdir)/ag_plugin/uvSenderService.manifest
|
||||
|
||||
ag_plugin/uvSenderService.zip: $(AG_PLUGIN_TX_SCRIPTS) $(TARGET)
|
||||
@echo "Creating AccessGrid plugin: uvSenderService.zip"
|
||||
@rm -f ag_plugin/uvSenderService.zip
|
||||
@zip -j ag_plugin/uvSenderService.zip $(AG_PLUGIN_TX_SCRIPTS) $(TARGET)
|
||||
|
||||
AG_PLUGIN_RX_SCRIPTS = ag_plugin/uvReceiverService.py \
|
||||
ag_plugin/uvReceiverService.svc \
|
||||
ag_plugin/uvReceiverService.manifest
|
||||
AG_PLUGIN_RX_SCRIPTS = $(srcdir)/ag_plugin/uvReceiverService.py \
|
||||
$(srcdir)/ag_plugin/uvReceiverService.svc \
|
||||
$(srcdir)/ag_plugin/uvReceiverService.manifest
|
||||
|
||||
ag_plugin/uvReceiverService.zip: $(AG_PLUGIN_RX_SCRIPTS) $(TARGET)
|
||||
@echo "Creating AccessGrid plugin: uvReceiverService.zip"
|
||||
@@ -511,149 +517,116 @@ rtsp: @RTSP_LIB_TARGET@
|
||||
rtsp_server: @RTSP_SERVER_LIB_TARGET@
|
||||
|
||||
@SDL_LIB_TARGET@: @SDL_OBJ@ @X_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_sdl.so.@video_display_abi_version@ $^ @SDL_LIBS@ -o $@
|
||||
|
||||
@GL_LIB_TARGET@: @GL_OBJ@ @X_OBJ@ @GL_COMMON_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_gl.so.@video_display_abi_version@ $^ @GL_LIB@ -o $@
|
||||
|
||||
@RTSP_LIB_TARGET@: @RTSP_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_rtsp.so.@video_capture_abi_version@ $^ @RTSP_LIB@ -o $@
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_rtsp.so.@video_capture_abi_version@ $^ @RTSP_LIBS@ -o $@
|
||||
|
||||
@TESTCARD_LIB_TARGET@: @TESTCARD_COMMON@ @TESTCARD_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_testcard.so.@video_capture_abi_version@ $^ @TESTCARD_LIB@ -o $@
|
||||
|
||||
@SWMIX_LIB_TARGET@: @GL_COMMON_OBJ@ @SWMIX_OBJ@ @X_OBJ@ src/host.o
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_swmix.so.@video_capture_abi_version@ $^ @SWMIX_LIB@ -o $@
|
||||
|
||||
@TESTCARD2_LIB_TARGET@: @TESTCARD_COMMON@ @TESTCARD2_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_testcard2.so.@video_capture_abi_version@ $^ @TESTCARD2_LIB@ -o $@
|
||||
|
||||
@DECKLINK_CAP_LIB_TARGET@: @DECKLINK_COMMON@ @DECKLINK_CAP_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
@DECKLINK_CAP_LIB_TARGET@: @DECKLINK_CAP_OBJ@
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_decklink.so.@video_capture_abi_version@ $^ @DECKLINK_LIB@ -o $@
|
||||
|
||||
@DECKLINK_DISP_LIB_TARGET@: src/video_capture/decklink.o @DECKLINK_COMMON@ @DECKLINK_DISP_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
@DECKLINK_DISP_LIB_TARGET@: src/video_capture/decklink.o @DECKLINK_DISP_OBJ@
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_decklink.so.@video_display_abi_version@ $^ @DECKLINK_LIB@ -o $@
|
||||
|
||||
@BLUEFISH444_CAP_LIB_TARGET@: @BLUEFISH444_CAP_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_bluefish444.so.@video_capture_abi_version@ $^ @BLUEFISH444_LIB@ -o $@
|
||||
|
||||
@BLUEFISH444_DISP_LIB_TARGET@: @BLUEFISH444_DISP_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_bluefish444.so.@video_display_abi_version@ $^ @BLUEFISH444_LIB@ -o $@
|
||||
|
||||
@DELTACAST_CAP_LIB_TARGET@: @DELTACAST_DISP_OBJ@ @DELTACAST_CAP_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_deltacast.so.@video_capture_abi_version@ $^ @DELTACAST_LIB@ -o $@
|
||||
|
||||
@DELTACAST_DISP_LIB_TARGET@: @DELTACAST_DISP_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_deltacast.so.@video_display_abi_version@ $^ @DELTACAST_LIB@ -o $@
|
||||
|
||||
@DVS_CAP_LIB_TARGET@: src/video_display/dvs.o @DVS_CAP_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_dvs.so.@video_capture_abi_version@ $^ @DVS_LIB@ -o $@
|
||||
|
||||
@DVS_DISP_LIB_TARGET@: @DVS_DISP_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_dvs.so.@video_display_abi_version@ $^ @DVS_LIB@ -o $@
|
||||
|
||||
@SCREEN_CAP_LIB_TARGET@: @SCREEN_CAP_OBJ@ @X_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_screen.so.@video_capture_abi_version@ $^ @SCREEN_CAP_LIB@ -o $@
|
||||
|
||||
@SAGE_LIB_TARGET@: @SAGE_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_sage.so.@video_display_abi_version@ $^ @SAGE_LIB@ -o $@
|
||||
|
||||
@RTDXT_COMPRESS_LIB_TARGET@: @GL_COMMON_OBJ@ @X_OBJ@ @RTDXT_COMMON_OBJ@ @RTDXT_COMPRESS_OBJ@ @RTDXT_COMMON_HEADERS@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vcompress_rtdxt.so.@video_compress_abi_version@ @GL_COMMON_OBJ@ @X_OBJ@ @RTDXT_COMMON_OBJ@ @RTDXT_COMPRESS_OBJ@ @RTDXT_LIB@ -o $@
|
||||
|
||||
@UYVY_COMPRESS_LIB_TARGET@: @GL_COMMON_OBJ@ @X_OBJ@ @UYVY_COMPRESS_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vcompress_uyvy.so.@video_compress_abi_version@ @GL_COMMON_OBJ@ @X_OBJ@ @UYVY_COMPRESS_OBJ@ -o $@
|
||||
|
||||
@LIBAVCODEC_COMPRESS_LIB_TARGET@: @LIBAVCODEC_COMPRESS_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vcompress_libavcodec.so.@video_compress_abi_version@ $^ @LIBAVCODEC_LIBS@ -o $@
|
||||
|
||||
@LIBAVCODEC_DECOMPRESS_LIB_TARGET@: @LIBAVCODEC_DECOMPRESS_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vdecompress_libavcodec.so.@video_decompress_abi_version@ $^ @LIBAVCODEC_LIBS@ -o $@
|
||||
|
||||
@LIBAVCODEC_AUDIO_CODEC_LIB_TARGET@: @LIBAVCODEC_AUDIO_CODEC_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,acodec_libavcodec.so.@audio_codec_abi_version@ $^ @LIBAVCODEC_LIBS@ -o $@
|
||||
|
||||
@JPEG_COMPRESS_LIB_TARGET@: @JPEG_COMPRESS_OBJ@ @JPEG_COMMON_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
@JPEG_COMPRESS_LIB_TARGET@: @JPEG_COMPRESS_OBJ@
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vcompress_jpeg.so.@video_compress_abi_version@ $^ @JPEG_LIB@ -o $@
|
||||
|
||||
@CUDA_DXT_COMPRESS_LIB_TARGET@: @CUDA_DXT_OBJ@ @CUDA_COMMON_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vcompress_cuda_dxt.so.@video_compress_abi_version@ $^ @CUDA_DXT_LIB@ -o $@
|
||||
|
||||
@RTDXT_DECOMPRESS_LIB_TARGET@: @GL_COMMON_OBJ@ @X_OBJ@ @RTDXT_COMMON_OBJ@ @RTDXT_DECOMPRESS_OBJ@ @RTDXT_COMMON_HEADERS@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vdecompress_rtdxt.so.@video_decompress_abi_version@ @GL_COMMON_OBJ@ @X_OBJ@ @RTDXT_COMMON_OBJ@ @RTDXT_DECOMPRESS_OBJ@ @RTDXT_LIB@ -o $@
|
||||
|
||||
@JPEG_DECOMPRESS_LIB_TARGET@: @JPEG_DECOMPRESS_OBJ@ @JPEG_COMMON_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
@JPEG_DECOMPRESS_LIB_TARGET@: @JPEG_DECOMPRESS_OBJ@
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vdecompress_jpeg.so.@video_decompress_abi_version@ $^ @JPEG_LIB@ -o $@
|
||||
|
||||
@JPEG_TO_DXT_DECOMPRESS_LIB_TARGET@: @JPEG_TO_DXT_OBJ@ @JPEG_DECOMPRESS_OBJ@ @JPEG_COMMON_OBJ@ @CUDA_COMMON_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
@JPEG_TO_DXT_DECOMPRESS_LIB_TARGET@: @JPEG_TO_DXT_OBJ@ @JPEG_DECOMPRESS_OBJ@ @CUDA_COMMON_OBJ@
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vdecompress_jpeg_to_dxt.so.@video_decompress_abi_version@ $^ @JPEG_TO_DXT_LIB@ -o $@
|
||||
|
||||
|
||||
@ALSA_PLAY_LIB_TARGET@: @ALSA_PLAY_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,aplay_alsa.so.@audio_playback_abi_version@ $^ @ALSA_LIB@ -o $@
|
||||
|
||||
@ALSA_CAP_LIB_TARGET@: @ALSA_CAP_OBJ@ src/audio/playback/alsa.o
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,acap_alsa.so.@audio_capture_abi_version@ $^ @ALSA_LIB@ -o $@
|
||||
|
||||
@PORTAUDIO_PLAY_LIB_TARGET@: @PORTAUDIO_PLAY_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,aplay_portaudio.so.@audio_playback_abi_version@ $^ @PORTAUDIO_LIB@ -o $@
|
||||
|
||||
@PORTAUDIO_CAP_LIB_TARGET@: @PORTAUDIO_CAP_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,acap_portaudio.so.@audio_capture_abi_version@ $^ @PORTAUDIO_LIB@ -o $@
|
||||
|
||||
@JACK_CAP_LIB_TARGET@: @JACK_CAP_OBJ@ @SPEEX_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,acap_jack.so.@audio_capture_abi_version@ $^ @JACK_LIB@ -o $@
|
||||
|
||||
@JACK_PLAY_LIB_TARGET@: @JACK_PLAY_OBJ@ @SPEEX_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,aplay_jack.so.@audio_playback_abi_version@ $^ @JACK_LIB@ -o $@
|
||||
|
||||
@DECKLINK_SOUND_PLAY_LIB_TARGET@: @DECKLINK_SOUND_PLAY_OBJ@ @DECKLINK_COMMON@
|
||||
mkdir -p lib/ultragrid
|
||||
@DECKLINK_SOUND_PLAY_LIB_TARGET@: @DECKLINK_SOUND_PLAY_OBJ@
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,aplay_jack.so.@audio_playback_abi_version@ $^ @DECKLINK_LIB@ -o $@
|
||||
|
||||
@SCALE_LIB_TARGET@: @SCALE_OBJ@ @GL_COMMON_OBJ@ @X_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vo_pp_scale.so.@vo_pp_abi_version@ $^ @SCALE_LIB@ -o $@
|
||||
|
||||
@V4L2_LIB_TARGET@: @V4L2_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_v4l2.so.@video_capture_abi_version@ $^ @V4L2_LIBS@ -o $@
|
||||
|
||||
@RTSP_SERVER_LIB_TARGET@: @RTSP_SERVER_OBJ@
|
||||
mkdir -p lib/ultragrid
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,video_rxtx_h264.so.@video_rxtx_abi_version@ $^ @RTSP_SERVER_LIB@ -o $@
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,video_rxtx_h264.so.@video_rxtx_abi_version@ $^ @RTSP_SERVER_LIBS@ -o $@
|
||||
|
||||
@VCAPTURE_FILTER_RESIZE_LIB_TARGET@: @RESIZE_OBJ@
|
||||
$(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_resize.so.@vcapture_filter_abi_version@ $^ @RESIZE_LIBS@ -o $@
|
||||
|
||||
install: all
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)/$(bindir)
|
||||
|
||||
10
autogen.sh
10
autogen.sh
@@ -13,7 +13,15 @@ aclocal
|
||||
autoheader
|
||||
autoconf
|
||||
|
||||
$srcdir/configure --enable-gpl $@
|
||||
CONFIGURE_OPTS="--enable-gpl"
|
||||
|
||||
if [ -n "$DEBUG" ]; then
|
||||
CONFIGURE_OPTS="$CONFIGURE_OPTS --enable-debug"
|
||||
fi
|
||||
|
||||
cd $ORIGDIR
|
||||
|
||||
$srcdir/configure $CONFIGURE_OPTS $@
|
||||
|
||||
cd $ORIGDIR
|
||||
|
||||
|
||||
369
configure.ac
369
configure.ac
@@ -45,9 +45,9 @@ AC_CHECK_HEADERS(stropts.h sys/filio.h sys/wait.h)
|
||||
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
POST_COMPILE_MSG=""
|
||||
CFLAGS="$CFLAGS -I."
|
||||
CPPFLAGS="$CPPFLAGS -I."
|
||||
CXXFLAGS="$CXXFLAGS -I. -D__STRICT_ANSI__ -std=c++0x"
|
||||
CFLAGS="$CFLAGS -I$srcdir"
|
||||
CPPFLAGS="$CPPFLAGS -I$srcdir"
|
||||
CXXFLAGS="$CXXFLAGS -I$srcdir -D__STRICT_ANSI__ -std=c++0x"
|
||||
LIB_MODULES=
|
||||
AC_SUBST(LIBS)
|
||||
AC_SUBST(OBJS)
|
||||
@@ -60,6 +60,20 @@ AC_C_BIGENDIAN(
|
||||
AC_DEFINE([WORDS_SMALLENDIAN], 1, [This is little endian system])
|
||||
)
|
||||
|
||||
if test "$ac_cv_prog_cc_c99" = no
|
||||
then
|
||||
AC_MSG_ERROR([Your compiler does not accept C99.])
|
||||
fi
|
||||
|
||||
AC_CHECK_SIZEOF([size_t])
|
||||
|
||||
if test $ac_cv_sizeof_size_t -eq 8
|
||||
then
|
||||
WORD_LEN=64
|
||||
else
|
||||
WORD_LEN=32
|
||||
fi
|
||||
|
||||
AC_DEFUN([HM_VERSION_WARNING], [
|
||||
AC_MSG_WARN([If you still want to try with unsupported version of dependency,
|
||||
you may want to try --disable-depends-version-check option.
|
||||
@@ -81,15 +95,6 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$host" in
|
||||
x86_64-*-linux-*)
|
||||
AC_DEFINE([HAVE_64B_LINUX], [1], [We have 64-bit Linux])
|
||||
;;
|
||||
i*86-*-linux-*)
|
||||
AC_DEFINE([HAVE_32B_LINUX], [1], [We have 32-bit Linux])
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_MSG_CHECKING([OS family])
|
||||
|
||||
if expr "$host_os" : ".*darwin.*" > /dev/null; then
|
||||
@@ -121,7 +126,7 @@ AC_MSG_RESULT($os_version_minor);
|
||||
|
||||
if test $system = MacOSX
|
||||
then
|
||||
COMMON_OSX_FLAGS="-m32 -I/opt/local/include -mmacosx-version-min=10.7"
|
||||
COMMON_OSX_FLAGS="-I/opt/local/include -mmacosx-version-min=10.7"
|
||||
if test $os_version_major = 11
|
||||
then
|
||||
OSX_SDK="macosx10.7"
|
||||
@@ -132,7 +137,10 @@ then
|
||||
CFLAGS="$CFLAGS $COMMON_OSX_FLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $COMMON_OSX_FLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $COMMON_OSX_FLAGS"
|
||||
NVCCFLAGS="$NVCCFLAGS -m32 -I/opt/local/include -Xcompiler -Wno-error=unused-command-line-argument-hard-error-in-future"
|
||||
NVCCFLAGS="$NVCCFLAGS -I/opt/local/include"
|
||||
if test $WORD_LEN = 32; then
|
||||
NVCCFLAGS="$NVCCFLAGS -Xcompiler -Wno-error=unused-command-line-argument-hard-error-in-future"
|
||||
fi
|
||||
LDFLAGS="$LDFLAGS $COMMON_OSX_FLAGS"
|
||||
X_CFLAGS="$X_CFLAGS -I/usr/X11R6/include"
|
||||
OBJS="$OBJS src/utils/autorelease_pool.o"
|
||||
@@ -197,20 +205,6 @@ static inline int posix_memalign(void **memptr, size_t alignment, size_t size)
|
||||
#endif // defined HAVE_MACOSX && OS_VERSION_MAJOR <= 9
|
||||
])
|
||||
|
||||
if test "$ac_cv_prog_cc_c99" = no
|
||||
then
|
||||
AC_MSG_ERROR([Your compiler does not accept C99.])
|
||||
fi
|
||||
|
||||
AC_CHECK_SIZEOF([size_t])
|
||||
|
||||
if test $ac_cv_sizeof_size_t -eq 8
|
||||
then
|
||||
WORD_LEN=64
|
||||
else
|
||||
WORD_LEN=32
|
||||
fi
|
||||
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
# Licensing
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
@@ -277,14 +271,22 @@ AC_DEFUN([DEFINE_CUDA], [
|
||||
])
|
||||
AC_SUBST(DLL_LIBS)
|
||||
|
||||
AC_MSG_CHECKING([if_nametoindex])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <windows.h>
|
||||
#include <iphlpapi.h>
|
||||
]], [[
|
||||
if_nametoindex("eth");]]
|
||||
)], HAVE_IF_NAMETOINDEX=yes, HAVE_IF_NAMETOINDEX=no)
|
||||
AC_MSG_RESULT([$HAVE_IF_NAMETOINDEX])
|
||||
if test $system = Windows
|
||||
then
|
||||
AC_MSG_CHECKING([if_nametoindex])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <windows.h>
|
||||
#include <iphlpapi.h>
|
||||
]], [[
|
||||
if_nametoindex("eth");]]
|
||||
)], HAVE_IF_NAMETOINDEX=yes, HAVE_IF_NAMETOINDEX=no)
|
||||
AC_MSG_RESULT([$HAVE_IF_NAMETOINDEX])
|
||||
if test $HAVE_IF_NAMETOINDEX = yes; then
|
||||
AC_DEFINE([HAVE_IF_TONAMEINDEX], 1, [Function if_nametoindex is present.])
|
||||
fi
|
||||
else
|
||||
AC_CHECK_FUNCS(if_nametoindex)
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(strtok_r)
|
||||
|
||||
@@ -401,6 +403,9 @@ AC_ARG_ENABLE(debug,
|
||||
then
|
||||
AC_DEFINE([DEBUG], [1], [We build with debug messages])
|
||||
debug_output=yes
|
||||
DEBUG_FLAGS="-Werror -Wno-error=cast-qual -Wno-error=cast-align"
|
||||
CFLAGS="$CFLAGS $DEBUG_FLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $DEBUG_FLAGS"
|
||||
fi])
|
||||
|
||||
AC_ARG_ENABLE(ipv6,
|
||||
@@ -438,7 +443,7 @@ fi
|
||||
video_display_abi_version=6
|
||||
video_capture_abi_version=3
|
||||
vcapture_filter_abi_version=1
|
||||
video_compress_abi_version=3
|
||||
video_compress_abi_version=4
|
||||
video_decompress_abi_version=3
|
||||
video_rxtx_abi_version=1
|
||||
audio_capture_abi_version=4
|
||||
@@ -550,7 +555,8 @@ AC_DEFINE([HAVE_DV_CODEC], [1], [We have libdv])
|
||||
dvs=no
|
||||
dvs_req=auto
|
||||
AC_ARG_ENABLE(dvs,
|
||||
AS_HELP_STRING([--disable-dvs], [disable DVS (default is auto)]),
|
||||
[ --disable-dvs disable DVS (default is auto)]
|
||||
[ Requires: DVS_SDK],
|
||||
[dvs_req=$enableval])
|
||||
|
||||
case "$host" in
|
||||
@@ -646,17 +652,19 @@ DECKLINK_PATH=
|
||||
decklink=no
|
||||
decklink_req=auto
|
||||
|
||||
AC_ARG_ENABLE(decklink, AS_HELP_STRING([--disable-decklink], [disable DeckLink (default is auto)]),
|
||||
AC_ARG_ENABLE(decklink,
|
||||
[ --disable-decklink disable DeckLink (default is auto)]
|
||||
[ Requires: DesktopVideo],
|
||||
[decklink_req=$enableval])
|
||||
DECKLINK_INC=
|
||||
|
||||
case "$host_os" in
|
||||
*darwin*)
|
||||
if test -z $DECKLINK_INC; then
|
||||
DECKLINK_INC=DeckLink/Mac
|
||||
DECKLINK_INC=$srcdir/DeckLink/Mac
|
||||
fi
|
||||
OLD_LIBS=$LIBS
|
||||
LIBS="$LIBS -framework CoreFoundation DeckLink/Mac/DeckLinkAPIDispatch.cpp"
|
||||
LIBS="$LIBS -framework CoreFoundation"
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include "DeckLink/Mac/DeckLinkAPI.h"
|
||||
]],
|
||||
@@ -669,7 +677,7 @@ case "$host_os" in
|
||||
;;
|
||||
*mingw*)
|
||||
if test -z $DECKLINK_INC; then
|
||||
DECKLINK_INC=DeckLink/Windows
|
||||
DECKLINK_INC=$srcdir/DeckLink/Windows
|
||||
fi
|
||||
SAVED_LIBS=$LIBS
|
||||
LIBS="$LIBS -lOle32"
|
||||
@@ -690,7 +698,7 @@ case "$host_os" in
|
||||
;;
|
||||
*)
|
||||
if test -z $DECKLINK_INC; then
|
||||
DECKLINK_INC=DeckLink/Linux
|
||||
DECKLINK_INC=$srcdir/DeckLink/Linux
|
||||
fi
|
||||
|
||||
AC_CHECK_FILE(${DECKLINK_INC}/DeckLinkAPI.h, FOUND_DECKLINK_H=yes, FOUND_DECKLINK_H=no)
|
||||
@@ -714,16 +722,16 @@ then
|
||||
DECKLINK_DISP_OBJ="src/video_display/decklink.o"
|
||||
DECKLINK_SOUND_PLAY_OBJ="src/audio/playback/decklink.o"
|
||||
if test $system = "Windows"; then
|
||||
DECKLINK_COMMON="src/video_capture/DeckLinkAPI_i.o"
|
||||
OBJS="$OBJS src/video_capture/DeckLinkAPI_i.o"
|
||||
else
|
||||
DECKLINK_COMMON="src/video_capture/DeckLinkAPIDispatch.o"
|
||||
OBJS="$OBJS src/video_capture/DeckLinkAPIDispatch.o"
|
||||
fi
|
||||
AC_DEFINE([HAVE_DECKLINK], [1], [Build with DeckLink support])
|
||||
AC_SUBST(DECKLINK_CAP_LIB_TARGET, "lib/ultragrid/vidcap_decklink.so.$video_capture_abi_version")
|
||||
AC_SUBST(DECKLINK_DISP_LIB_TARGET, "lib/ultragrid/display_decklink.so.$video_display_abi_version")
|
||||
AC_SUBST(DECKLINK_SOUND_PLAY_LIB_TARGET, "lib/ultragrid/aplay_decklink.so.$audio_playback_abi_version")
|
||||
LIB_TARGETS="$LIB_TARGETS $DECKLINK_CAP_LIB_TARGET $DECKLINK_DISP_LIB_TARGET $DECKLINK_SOUND_PLAY_LIB_TARGET"
|
||||
LIB_OBJS="$LIB_OBJS $DECKLINK_CAP_OBJ $DECKLINK_DISP_OBJ $DECKLINK_SOUND_PLAY_OBJ $DECKLINK_COMMON"
|
||||
LIB_OBJS="$LIB_OBJS $DECKLINK_CAP_OBJ $DECKLINK_DISP_OBJ $DECKLINK_SOUND_PLAY_OBJ"
|
||||
decklink=yes
|
||||
else
|
||||
DECKLINK_PATH=
|
||||
@@ -737,10 +745,9 @@ if test $decklink_req = yes -a $decklink = no; then
|
||||
AC_MSG_ERROR([DeckLink not found.])
|
||||
fi
|
||||
|
||||
LIB_MODULES+=" $DECKLINK_LIB"
|
||||
LIB_MODULES="$LIB_MODULES $DECKLINK_LIB"
|
||||
|
||||
AC_SUBST(DECKLINK_PATH)
|
||||
AC_SUBST(DECKLINK_COMMON)
|
||||
AC_SUBST(DECKLINK_INC)
|
||||
AC_SUBST(DECKLINK_LIB)
|
||||
AC_SUBST(DECKLINK_CAP_OBJ)
|
||||
@@ -761,7 +768,8 @@ blue_audio_req=auto
|
||||
blue_audio=no
|
||||
|
||||
AC_ARG_ENABLE(bluefish444,
|
||||
AS_HELP_STRING([--disable-bluefish444], [disable Bluefish444 suppport (default is auto)]),
|
||||
[ --disable-bluefish444 disable Bluefish444 suppport (default is auto)]
|
||||
[ Requires: bluefish444_SDK],
|
||||
[bluefish444_req=$enableval],
|
||||
[bluefish444_req=auto]
|
||||
)
|
||||
@@ -897,7 +905,8 @@ DELTACAST_LIB=
|
||||
deltacast=no
|
||||
|
||||
AC_ARG_ENABLE(deltacast,
|
||||
AS_HELP_STRING([--disable-deltacast], [disable DELTACAST suppport (default is auto)]),
|
||||
[ --disable-deltacast disable DELTACAST suppport (default is auto)]
|
||||
[ Requires: VideoMasterHD_SDK],
|
||||
[deltacast_req=$enableval],
|
||||
[deltacast_req=auto]
|
||||
)
|
||||
@@ -1020,18 +1029,23 @@ QUICKTIME_OBJ=
|
||||
quicktime=no
|
||||
|
||||
AC_ARG_ENABLE(quicktime,
|
||||
AS_HELP_STRING([--disable-quicktime], [disable QuickTime support(default is auto)]),
|
||||
AS_HELP_STRING([--disable-quicktime], [enable QuickTime support(default is disable)]),
|
||||
[quicktime_req=$enableval],
|
||||
[quicktime_req=auto]
|
||||
[quicktime_req=no]
|
||||
)
|
||||
|
||||
if test $WORD_LEN = 64 -a $quicktime_req = yes; then
|
||||
AC_MSG_ERROR([QuickTime not supported in 64-bit builds, please build 32-bit UltraGrid (CFLAGS/CXXFLAGS/LDFLAGS/NVCCFLAGS=-m32)]);
|
||||
fi
|
||||
|
||||
case $host_os in
|
||||
*darwin*)
|
||||
AC_CHECK_HEADERS([QuickTime/QuickTime.h], [FOUND_QUICKTIME_H=yes], [echo "QuickTime headers not found."])
|
||||
AC_CHECK_HEADERS([Carbon/Carbon.h], [FOUND_CARBON_H=yes], [echo "Carbon headers not found."])
|
||||
|
||||
if test $quicktime_req != no -a $FOUND_QUICKTIME_H = yes -a $FOUND_CARBON_H = yes
|
||||
if test $quicktime_req != no -a $FOUND_QUICKTIME_H = yes -a $FOUND_CARBON_H = yes -a $WORD_LEN = 32
|
||||
then
|
||||
AC_DEFINE([HAVE_QUICKTIME], [1], [Build with QuickTime support])
|
||||
QUICKTIME_INC=
|
||||
QUICKTIME_LIB="-framework QuickTime -framework Carbon -framework AppKit -framework CoreAudio -framework AudioUnit"
|
||||
QUICKTIME_OBJ="src/video_capture/quicktime.o src/video_display/quicktime.o"
|
||||
@@ -1055,11 +1069,12 @@ AC_SUBST(QUICKTIME_OBJ)
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
# AV Foundation capture
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
avfoundation=no
|
||||
|
||||
if test $system = MacOSX
|
||||
then
|
||||
AVFOUNDATION_INC=""
|
||||
AVFOUNDATION_LIB="-framework AVFoundation -framework CoreMedia -framework CoreVideo"
|
||||
AVFOUNDATION_LIB="-framework AppKit -framework AVFoundation -framework CoreMedia -framework CoreVideo"
|
||||
AC_DEFINE([HAVE_AVFOUNDATION], [1], [Build with AV Foundation support])
|
||||
AVFOUNDATION_OBJ="src/video_capture/avfoundation.o"
|
||||
#LIB_TARGETS not needed here since we are not building modules on Mac
|
||||
@@ -1080,7 +1095,8 @@ SDL_LIBS=
|
||||
sdl=no
|
||||
|
||||
AC_ARG_ENABLE(sdl,
|
||||
AS_HELP_STRING([--disable-sdl], [enable SDL(default is enable)]),
|
||||
[ --disable-sdl enable SDL (default is enable)]
|
||||
[ Requires: sdl >= 1.2.14 ],
|
||||
[sdl_req=$enableval],
|
||||
[sdl_req=auto]
|
||||
)
|
||||
@@ -1214,39 +1230,36 @@ AC_SUBST(SDL_LIBS)
|
||||
# RTSP capture stuff
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
RTSP_INC=
|
||||
RTSP_LIB=
|
||||
RTSP_LIBS=
|
||||
RTSP_OBJ=
|
||||
rtsp=no
|
||||
curl=no
|
||||
glib=no
|
||||
|
||||
define(rtsp_deps, [glib-2.0 >= 2.24.1 libcurl])
|
||||
|
||||
AC_ARG_ENABLE(rtsp,
|
||||
AS_HELP_STRING([--disable-rtsp], [disable RTSP support(default is auto)]),
|
||||
[ --disable-rtsp disable RTSP support (default is auto)]
|
||||
[ Requires: rtsp_deps],
|
||||
[rtsp_req=$enableval],
|
||||
[rtsp_req=auto]
|
||||
)
|
||||
|
||||
case $host in
|
||||
*-linux-*)
|
||||
PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.24.1], FOUND_GLIB_H=yes, FOUND_GLIB_H=no)
|
||||
PKG_CHECK_MODULES([CURL], [libcurl], FOUND_CURL_H=yes, FOUND_CURL_H=no)
|
||||
PKG_CHECK_MODULES([RTSP], [rtsp_deps], FOUND_RTSP_DEPS=yes, FOUND_RTSP_DEPS=no)
|
||||
|
||||
if test $rtsp_req != no -a $FOUND_CURL_H = yes -a $FOUND_GLIB_H = yes
|
||||
if test $rtsp_req != no -a $FOUND_RTSP_DEPS = yes
|
||||
then
|
||||
AC_DEFINE([HAVE_RTSP], [1], [RTSP capture build with curl ang glib support])
|
||||
SAVED_CFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS ${GLIB_CFLAGS} ${CURL_CFLAGS}"
|
||||
CFLAGS="$CFLAGS ${RTSP_CFLAGS}"
|
||||
SAVED_CXXFLAGS=$CXXFLAGS
|
||||
CXXFLAGS="$CXXFLAGS ${GLIB_CFLAGS} ${CURL_CFLAGS}"
|
||||
CXXFLAGS="$CXXFLAGS ${RTSP_CFLAGS}"
|
||||
RTSP_INC=
|
||||
RTSP_LIB="${GLIB_LIBS} ${CURL_LIBS}"
|
||||
RTSP_OBJ="src/utils/h264_stream.o src/video_capture/rtsp.o src/rtp/rtpdec_h264.o"
|
||||
AC_SUBST(RTSP_LIB_TARGET, "lib/ultragrid/vidcap_rtsp.so.$video_capture_abi_version")
|
||||
LIB_TARGETS="$LIB_TARGETS $RTSP_LIB_TARGET"
|
||||
LIB_OBJS="$LIB_OBJS $RTSP_OBJ"
|
||||
rtsp=yes
|
||||
curl=yes
|
||||
glib=yes
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
@@ -1255,10 +1268,10 @@ if test $rtsp_req = yes -a $rtsp = no; then
|
||||
AC_MSG_ERROR([rtsp not found, check curl or glib dependencies...]);
|
||||
fi
|
||||
|
||||
LIB_MODULES="$LIB_MODULES $RTSP_LIB"
|
||||
LIB_MODULES="$LIB_MODULES $RTSP_LIBS"
|
||||
|
||||
AC_SUBST(RTSP_INC)
|
||||
AC_SUBST(RTSP_LIB)
|
||||
AC_SUBST(RTSP_LIBS)
|
||||
AC_SUBST(RTSP_OBJ)
|
||||
|
||||
|
||||
@@ -1269,32 +1282,28 @@ AC_SUBST(RTSP_OBJ)
|
||||
# TODO: create pkg-config search path for liblivemedia-dev (create live555.pc file)
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
RTSP_SERVER_INC=
|
||||
RTSP_SERVER_LIB=
|
||||
RTSP_SERVER_OBJ=
|
||||
rtsp_server=no
|
||||
livemedia=no
|
||||
|
||||
|
||||
AC_ARG_ENABLE(rtsp_server,
|
||||
AS_HELP_STRING([--disable-rtsp-server], [disable RTSP server support(default is auto)]),
|
||||
[ --disable-rtsp-server disable RTSP server support (default is auto)]
|
||||
[ Requires: live555],
|
||||
[rtsp_server_req=$enableval],
|
||||
[rtsp_server_req=auto]
|
||||
)
|
||||
|
||||
case $host in
|
||||
*-linux-*)
|
||||
|
||||
AC_CHECK_FILE(/usr/include/liveMedia/liveMedia.hh, [FOUND_LIVE_H=yes], [echo "liveMedia (live555 library) headers not found; may apt-get install liblivemedia-dev"; FOUND_LIVE_H=no])
|
||||
AC_CHECK_FILE(/usr/include/liveMedia/liveMedia.hh, [FOUND_LIVE_H=yes], [echo "liveMedia (live555 library) headers not found; may apt-get install liblivemedia-dev"; FOUND_LIVE_H=no])
|
||||
|
||||
if test $rtsp_server_req != no -a $FOUND_LIVE_H = yes
|
||||
then
|
||||
AC_DEFINE([HAVE_RTSP_SERVER], [1], [RTSP server build with live555 support])
|
||||
SAVED_CFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS -I/usr/include/groupsock -I/usr/include/liveMedia -I/usr/include/BasicUsageEnvironment -I/usr/include/UsageEnvironment"
|
||||
SAVED_CXXFLAGS=$CXXFLAGS
|
||||
CXXFLAGS="$CXXFLAGS -I/usr/include/groupsock -I/usr/include/liveMedia -I/usr/include/BasicUsageEnvironment -I/usr/include/UsageEnvironment"
|
||||
RTSP_SERVER_INC=
|
||||
RTSP_SERVER_LIB="-lliveMedia -lBasicUsageEnvironment -lUsageEnvironment -lgroupsock"
|
||||
RTSP_SERVER_FLAGS="-I/usr/include/groupsock -I/usr/include/liveMedia -I/usr/include/BasicUsageEnvironment -I/usr/include/UsageEnvironment"
|
||||
CFLAGS="$CFLAGS $RTSP_SERVER_FLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $RTSP_SERVER_FLAGS"
|
||||
RTSP_SERVER_LIBS="-lliveMedia -lBasicUsageEnvironment -lUsageEnvironment -lgroupsock"
|
||||
RTSP_SERVER_OBJ="src/rtsp/c_basicRTSPOnlyServer.o src/rtsp/BasicRTSPOnlyServer.o src/rtsp/BasicRTSPOnlySubsession.o src/video_rxtx/h264_rtp.o"
|
||||
AC_SUBST(RTSP_SERVER_LIB_TARGET, "lib/ultragrid/video_rxtx_h264.so.$video_rxtx_abi_version")
|
||||
LIB_TARGETS="$LIB_TARGETS $RTSP_SERVER_LIB_TARGET"
|
||||
@@ -1309,56 +1318,52 @@ if test $rtsp_server_req = yes -a $rtsp_server = no; then
|
||||
AC_MSG_ERROR([rtsp server not found, check live555 -livemedia lib- dependencies...]);
|
||||
fi
|
||||
|
||||
LIB_MODULES="$LIB_MODULES $RTSP_SERVER_LIB"
|
||||
LIB_MODULES="$LIB_MODULES $RTSP_SERVER_LIBS"
|
||||
|
||||
AC_SUBST(RTSP_SERVER_INC)
|
||||
AC_SUBST(RTSP_SERVER_LIB)
|
||||
AC_SUBST(RTSP_SERVER_LIBS)
|
||||
AC_SUBST(RTSP_SERVER_OBJ)
|
||||
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
# OpenCV stuff
|
||||
# Resize stuff
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
OPENCV_INC=
|
||||
OPENCV_LIB=
|
||||
OPENCV_OBJ=
|
||||
opencv=no
|
||||
RESIZE_LIBS=
|
||||
RESIZE_OBJ=
|
||||
resize=no
|
||||
|
||||
AC_ARG_ENABLE(opencv,
|
||||
AS_HELP_STRING([--disable-opencv], [disable OpenCV support (default is auto) - resize capture filter dependency]),
|
||||
[opencv_req=$enableval],
|
||||
[opencv_req=auto]
|
||||
define(resize_dep, opencv)
|
||||
|
||||
AC_ARG_ENABLE(resize,
|
||||
[ --disable-resize disable resize capture filter (default is auto)]
|
||||
[ Requires: resize_dep],
|
||||
[resize_req=$enableval],
|
||||
[resize_req=auto]
|
||||
)
|
||||
|
||||
case $host in
|
||||
*-linux-*)
|
||||
PKG_CHECK_MODULES([OPENCV], [opencv], FOUND_OPENCV_H=yes, FOUND_OPENCV_H=no)
|
||||
PKG_CHECK_MODULES([RESIZE], [resize_dep], FOUND_RESIZE_DEP=yes, FOUND_RESIZE_DEP=no)
|
||||
|
||||
if test $opencv_req != no -a $FOUND_OPENCV_H = yes
|
||||
if test $resize_req != no -a $FOUND_RESIZE_DEP = yes
|
||||
then
|
||||
AC_DEFINE([HAVE_OPENCV], [1], [OpenCV support - resize capture filter dependency])
|
||||
SAVED_CFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS ${OPENCV_CFLAGS}"
|
||||
SAVED_CXXFLAGS=$CXXFLAGS
|
||||
CXXFLAGS="$CXXFLAGS ${OPENCV_CFLAGS}"
|
||||
OPENCV_INC=
|
||||
RESIZE_LIB="${OPENCV_LIBS}"
|
||||
CFLAGS="$CFLAGS ${RESIZE_CFLAGS}"
|
||||
CXXFLAGS="$CXXFLAGS ${RESIZE_CFLAGS}"
|
||||
RESIZE_OBJ="src/capture_filter/resize.o src/capture_filter/resize_utils.o"
|
||||
AC_SUBST(VCAPTURE_FILTER_RESIZE_LIB_TARGET, "lib/ultragrid/vcapfilter_resize.so.$vcapture_filter_abi_version")
|
||||
|
||||
LIB_TARGETS="$LIB_TARGETS"
|
||||
LIB_TARGETS="$LIB_TARGETS $VCAPTURE_FILTER_RESIZE_LIB_TARGET"
|
||||
LIB_OBJS="$LIB_OBJS $RESIZE_OBJ"
|
||||
|
||||
opencv=yes
|
||||
resize=yes
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if test $opencv_req = yes -a $opencv = no; then
|
||||
if test $resize_req = yes -a $resize = no; then
|
||||
AC_MSG_ERROR([OpenCV not found, may install OpenCV...?]);
|
||||
fi
|
||||
|
||||
LIB_MODULES="$LIB_MODULES $RESIZE_LIB"
|
||||
LIB_MODULES="$LIB_MODULES $RESIZE_LIBS"
|
||||
|
||||
AC_SUBST(RESIZE_LIB)
|
||||
AC_SUBST(RESIZE_LIBS)
|
||||
AC_SUBST(RESIZE_OBJ)
|
||||
|
||||
|
||||
@@ -1444,7 +1449,8 @@ GL_LIB=
|
||||
gl=no
|
||||
|
||||
AC_ARG_ENABLE(gl,
|
||||
AS_HELP_STRING([--disable-gl], [disable OpenGL (default is auto)]),
|
||||
[ --disable-gl disable OpenGL (default is auto]
|
||||
[ Requires: glew GLUT gl],
|
||||
[gl_req=$enableval],
|
||||
[gl_req=auto]
|
||||
)
|
||||
@@ -1664,7 +1670,8 @@ SWMIX_OBJ=
|
||||
swmix=no
|
||||
|
||||
AC_ARG_ENABLE(swmix,
|
||||
AS_HELP_STRING([--disable-swmix], [disable SW mix (default is auto)]),
|
||||
[ --disable-swmix disable SW mix (default is auto)]
|
||||
[ Requires: gl],
|
||||
[swmix_req=$enableval],
|
||||
[swmix_req=auto]
|
||||
)
|
||||
@@ -1700,7 +1707,8 @@ SCREEN_CAP_LIB=
|
||||
screen_cap=no
|
||||
|
||||
AC_ARG_ENABLE(screen,
|
||||
AS_HELP_STRING([--disable-screen], [disable screen capture (default is auto)]),
|
||||
[ --disable-screen disable screen capture (default is auto)]
|
||||
[ Requires: none (OSX) x11 (Linux)],
|
||||
[screen_cap_req=$enableval],
|
||||
[screen_cap_req=auto]
|
||||
)
|
||||
@@ -1785,7 +1793,8 @@ AC_SUBST(SCREEN_CAP_OBJ)
|
||||
rtdxt=no
|
||||
|
||||
AC_ARG_ENABLE(rtdxt,
|
||||
AS_HELP_STRING([--disable-rtdxt], [disable Real-Time OpenGL DXT compression (default is auto)]),
|
||||
[ --disable-rtdxt disable Real-Time OpenGL DXT compression (default is auto)]
|
||||
[ Requires: gl],
|
||||
[rtdxt_req=$enableval],
|
||||
[rtdxt_req=auto])
|
||||
|
||||
@@ -1832,7 +1841,8 @@ AC_SUBST(DXT_GLSL_CFLAGS)
|
||||
uyvy=no
|
||||
|
||||
AC_ARG_ENABLE(uyvy,
|
||||
AS_HELP_STRING([--disable-uyvy], [disable dummy RGB to UYVY compression (default is auto)]),
|
||||
[ --disable-uyvy disable dummy RGB to UYVY compression (default is auto)]
|
||||
[ Requires: CUDA],
|
||||
[uyvy_req=$enableval],
|
||||
[uyvy_req=auto])
|
||||
|
||||
@@ -1889,6 +1899,11 @@ CUDA_LIB_PATH=
|
||||
FOUND_CUDA=no
|
||||
CUDA_PATH=$CUDA_DIRECTORY
|
||||
|
||||
AC_ARG_ENABLE(cuda,
|
||||
AS_HELP_STRING([--disable-cuda], [disable all CUDA code]),
|
||||
[cuda_req=$enableval],
|
||||
[cuda_req=auto])
|
||||
|
||||
AC_ARG_WITH(cuda,
|
||||
[ --with-cuda=DIR specify location of CUDA Toolkit],
|
||||
[CUDA_PATH=$withval
|
||||
@@ -1897,7 +1912,7 @@ AC_ARG_WITH(cuda,
|
||||
AC_PATH_PROG(NVCC, nvcc, [], [$PATH$PATH_SEPARATOR$CUDA_PATH/bin]dnl
|
||||
[$PATH_SEPARATOR/opt/cuda/bin$PATH_SEPARATOR/usr/local/cuda/bin])
|
||||
|
||||
if test -n "$NVCC"
|
||||
if test -n "$NVCC" -a $cuda_req != no
|
||||
then
|
||||
CUDA_PATH=`dirname "$NVCC"`
|
||||
CUDA_PATH=`dirname "$CUDA_PATH"`
|
||||
@@ -1918,7 +1933,7 @@ then
|
||||
nvcc_minor=`"$NVCC" --version |grep release|sed 's/^.*release @<:@0-9@:>@@<:@0-9@:>@*\.\(@<:@0-9@:>@@<:@0-9@:>@*\).*$/\1/'`
|
||||
AC_MSG_RESULT($nvcc_minor)
|
||||
|
||||
CUDA_INC=-I$CUDA_PATH/include
|
||||
CUDA_INC="\"-I$CUDA_PATH/include\""
|
||||
|
||||
if test $ac_cv_sizeof_int_p -eq 8 -a $system = Linux
|
||||
then
|
||||
@@ -1947,7 +1962,8 @@ JPEG_LIB=
|
||||
jpeg=no
|
||||
|
||||
AC_ARG_ENABLE(jpeg,
|
||||
AS_HELP_STRING([--disable-jpeg], [disable JPEG compression (auto)]),
|
||||
[ --disable-jpeg disable JPEG compression (auto)]
|
||||
[ Requires: libgpujpeg ],
|
||||
[jpeg_req=$enableval],
|
||||
[jpeg_req=auto])
|
||||
|
||||
@@ -1988,14 +2004,14 @@ then
|
||||
jpeg=yes
|
||||
|
||||
JPEG_INC="$JPEG_INC -Igpujpeg"
|
||||
JPEG_COMMON_OBJ="src/video_compress/jpeg.o"
|
||||
JPEG_LIB="$JPEG_LIB -lgpujpeg"
|
||||
JPEG_COMPRESS_OBJ="src/video_compress/jpeg.o"
|
||||
JPEG_DECOMPRESS_OBJ="src/video_decompress/jpeg.o "
|
||||
AC_DEFINE([HAVE_JPEG], [1], [Build with JPEG support])
|
||||
AC_SUBST(JPEG_COMPRESS_LIB_TARGET, "lib/ultragrid/vcompress_jpeg.so.$video_compress_abi_version")
|
||||
AC_SUBST(JPEG_DECOMPRESS_LIB_TARGET, "lib/ultragrid/vdecompress_jpeg.so.$video_decompress_abi_version")
|
||||
LIB_TARGETS="$LIB_TARGETS $JPEG_COMPRESS_LIB_TARGET $JPEG_DECOMPRESS_LIB_TARGET"
|
||||
LIB_OBJS="$LIB_OBJS $JPEG_DECOMPRESS_OBJ $JPEG_COMMON_OBJ"
|
||||
LIB_OBJS="$LIB_OBJS $JPEG_COMPRESS_OBJ $JPEG_DECOMPRESS_OBJ"
|
||||
CUDA_MESSAGE
|
||||
fi
|
||||
|
||||
@@ -2005,7 +2021,6 @@ fi
|
||||
|
||||
LIB_MODULES="$LIB_MODULES $JPEG_LIB"
|
||||
|
||||
AC_SUBST(JPEG_COMMON_OBJ)
|
||||
AC_SUBST(JPEG_COMPRESS_OBJ)
|
||||
AC_SUBST(JPEG_DECOMPRESS_OBJ)
|
||||
AC_SUBST(JPEG_INC)
|
||||
@@ -2031,7 +2046,8 @@ AC_DEFUN([ADD_CUDA_DXT_OBJ], [
|
||||
])
|
||||
|
||||
AC_ARG_ENABLE(cuda-dxt,
|
||||
AS_HELP_STRING([--disable-cuda-dxt], [disable CUDA DXT compression (auto)]),
|
||||
[ --disable-cuda-dxt disable CUDA DXT compression (auto)]
|
||||
[ Requires: CUDA],
|
||||
[cuda_dxt_req=$enableval],
|
||||
[cuda_dxt_req=auto])
|
||||
|
||||
@@ -2068,7 +2084,8 @@ AC_SUBST(CUDA_DXT_LIB)
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
jpeg_to_dxt=no
|
||||
AC_ARG_ENABLE(jpeg_to_dxt,
|
||||
AS_HELP_STRING([--disable-jpeg-to-dxt], [disable JPEG to DXT transcoder (default is auto)]),
|
||||
[ --disable-jpeg-to-dxt disable JPEG to DXT transcoder (default is auto)]
|
||||
[ Requires: CUDA libgpujpeg],
|
||||
[jpeg_to_dxt_req=$enableval],
|
||||
[jpeg_to_dxt_req=auto])
|
||||
|
||||
@@ -2108,7 +2125,8 @@ SAGE_LIB=
|
||||
sage=no
|
||||
|
||||
AC_ARG_ENABLE(sage,
|
||||
AS_HELP_STRING([--disable-sage], [disable SAGE (default is auto)]),
|
||||
[ --disable-sage disable SAGE (default is auto)]
|
||||
[ Requires: SAGE],
|
||||
[sage_req=$enableval],
|
||||
[sage_req=auto])
|
||||
|
||||
@@ -2121,22 +2139,29 @@ AC_ARG_WITH(sage,
|
||||
[ --with-sage=DIR specify location of SAGE],
|
||||
[SAGE_DIRECTORY=$withval])
|
||||
|
||||
if test -n "$SAGE_DIRECTORY"
|
||||
then
|
||||
SAGE_INC=$SAGE_DIRECTORY/include
|
||||
SAGE_LIB=$SAGE_DIRECTORY/lib
|
||||
else
|
||||
SAGE_INC=sage3.0/include
|
||||
SAGE_LIB=sage3.0/lib
|
||||
fi
|
||||
|
||||
if test $native_ycocg = yes
|
||||
then
|
||||
AC_DEFINE([SAGE_NATIVE_DXT5YCOCG], [1], [Assume that SAGE supports native DXT5 YCoCg])
|
||||
fi
|
||||
|
||||
AC_CHECK_FILE(${SAGE_INC}/sail.h, FOUND_SAGE_H=yes, FOUND_SAGE_H=no)
|
||||
# if directory not set manually, use default installation location
|
||||
if test -z "$SAGE_DIRECTORY"
|
||||
then
|
||||
SAGE_DIRECTORY=/usr/local/sage
|
||||
fi
|
||||
|
||||
SAGE_INC=$SAGE_DIRECTORY/include
|
||||
SAGE_LIB=$SAGE_DIRECTORY/lib64
|
||||
|
||||
AC_CHECK_LIB(sail, main, FOUND_SAGE_L=yes, FOUND_SAGE_L=no, -lquanta -I${SAGE_INC} -L${SAGE_LIB})
|
||||
# if library not found in lib64/ try lib/
|
||||
if test $FOUND_SAGE_L = no
|
||||
then
|
||||
SAGE_LIB=$SAGE_DIRECTORY/lib
|
||||
AC_CHECK_LIB(sail, main, FOUND_SAGE_L=yes, FOUND_SAGE_L=no, -lquanta -I${SAGE_INC} -L${SAGE_LIB})
|
||||
fi
|
||||
|
||||
AC_CHECK_FILE(${SAGE_INC}/sail.h, FOUND_SAGE_H=yes, FOUND_SAGE_H=no)
|
||||
|
||||
if test $sage_req != no -a $FOUND_SAGE_L = yes -a $FOUND_SAGE_H = yes
|
||||
then
|
||||
@@ -2175,7 +2200,8 @@ PORTAUDIO_PLAY_OBJ=
|
||||
portaudio=no
|
||||
|
||||
AC_ARG_ENABLE(portaudio,
|
||||
AS_HELP_STRING([--disable-portaudio], [disable Portaudio (default is auto)]),
|
||||
[ --disable-portaudio disable Portaudio (default is auto)]
|
||||
[ Requires: portaudio-2.0],
|
||||
[portaudio_req=$enableval],
|
||||
[portaudio_req=auto])
|
||||
|
||||
@@ -2225,7 +2251,7 @@ AC_SUBST(PORTAUDIO_PLAY_OBJ)
|
||||
|
||||
speex=yes
|
||||
SPEEX_PATH=speex-1.2rc1
|
||||
SPEEX_INC=-I${SPEEX_PATH}/include
|
||||
SPEEX_INC=-I$srcdir/${SPEEX_PATH}/include
|
||||
SPEEX_OBJ="src/audio/resample.o src/audio/preprocess.o src/audio/filterbank.o src/audio/fftwrap.o src/audio/smallft.o src/audio/mdf.o"
|
||||
SPEEX_OBJ="$SPEEX_OBJ src/audio/echo.o"
|
||||
SPEEX_LIB=
|
||||
@@ -2245,7 +2271,8 @@ jack_trans=no
|
||||
jack=no
|
||||
|
||||
AC_ARG_ENABLE(jack-transport,
|
||||
AS_HELP_STRING([--enable-jack-transport], [enable JACK transport (default is disable)]),
|
||||
[ --enable-jack-transport enable JACK transport (default is disable)]
|
||||
[ Requires: jack],
|
||||
[jack_trans_req=$enableval],
|
||||
[jack_trans_req=no])
|
||||
|
||||
@@ -2264,7 +2291,8 @@ AC_SUBST(JACK_TRANS_INC)
|
||||
|
||||
# sound system
|
||||
AC_ARG_ENABLE(jack,
|
||||
AS_HELP_STRING([--disable-jack], [disable JACK (default is auto)]),
|
||||
[ --disable-jack disable JACK (default is auto)]
|
||||
[ Requires: jack],
|
||||
[jack_req=$enableval],
|
||||
[jack_req=auto])
|
||||
|
||||
@@ -2304,7 +2332,8 @@ AC_SUBST(JACK_INC)
|
||||
# ALSA
|
||||
#
|
||||
AC_ARG_ENABLE(alsa,
|
||||
AS_HELP_STRING([--disable-alsa], [disable ALSA (default is auto)]),
|
||||
[ --disable-alsa disable ALSA (default is auto)]
|
||||
[ Requires: alsa],
|
||||
[alsa_req=$enableval],
|
||||
[alsa_req=auto])
|
||||
AC_CHECK_HEADER(alsa/asoundlib.h)
|
||||
@@ -2391,7 +2420,8 @@ SCALE_OBJ=
|
||||
scale=no
|
||||
|
||||
AC_ARG_ENABLE(scale,
|
||||
AS_HELP_STRING([--disable-scale], [disable scale support(default is auto)]),
|
||||
[ --disable-scale disable scale postprocessor (default is auto)]
|
||||
[ Requires: gl],
|
||||
[scale_req=$enableval],
|
||||
[scale_req=auto]
|
||||
)
|
||||
@@ -2446,26 +2476,18 @@ AC_SUBST(QMAKE)
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
v4l2=no
|
||||
found_v4l2=no
|
||||
|
||||
define(v4l2_deps, libv4l2 libv4lconvert)
|
||||
|
||||
AC_ARG_ENABLE(v4l2,
|
||||
AS_HELP_STRING([--disable-v4l2], [disable V4L2 support(default is auto)]),
|
||||
[ --disable-v4l2 disable V4L2 support (default is auto)]
|
||||
[ Requires: v4l2_deps],
|
||||
[v4l2_req=$enableval],
|
||||
[v4l2_req=auto]
|
||||
)
|
||||
|
||||
if test $system = Linux; then
|
||||
#PKG_CHECK_MODULES([V4L2], [libv4l2 libv4lconvert], [found_v4l2=yes], [found_v4l2=no])
|
||||
SAVED_LIBS=$LIBS
|
||||
AC_CHECK_LIB(v4l2, main)
|
||||
AC_CHECK_HEADER(libv4l2.h)
|
||||
AC_CHECK_LIB(v4lconvert, v4lconvert_create)
|
||||
AC_CHECK_HEADER(libv4lconvert.h)
|
||||
LIBS=$SAVED_LIBS
|
||||
|
||||
if test $v4l2_req != no -a $ac_cv_lib_v4l2_main = yes -a $ac_cv_header_libv4l2_h = yes -a \
|
||||
$ac_cv_lib_v4lconvert_v4lconvert_create = yes -a $ac_cv_header_libv4lconvert_h = yes
|
||||
then
|
||||
found_v4l2=yes
|
||||
fi
|
||||
PKG_CHECK_MODULES([V4L2], [libv4l2 libv4lconvert], [found_v4l2=yes], [found_v4l2=no])
|
||||
fi
|
||||
|
||||
if test $v4l2_req != no -a $found_v4l2 = yes
|
||||
@@ -2473,7 +2495,6 @@ then
|
||||
V4L2_OBJ="src/video_capture/v4l2.o"
|
||||
AC_DEFINE([HAVE_V4L2], [1], [Build with V4L2 support])
|
||||
AC_SUBST(V4L2_LIB_TARGET, "lib/ultragrid/vidcap_v4l2.so.$video_capture_abi_version")
|
||||
V4L2_LIBS="$V4L2_LIBS -lv4l2 -lv4lconvert"
|
||||
LIB_TARGETS="$LIB_TARGETS $V4L2_LIB_TARGET"
|
||||
LIB_OBJS="$LIB_OBJS $V4L2_OBJ"
|
||||
CFLAGS="$CFLAGS $V4L2_CFLAGS"
|
||||
@@ -2520,7 +2541,8 @@ fi
|
||||
libavcodec=no
|
||||
libavcodec_audio=no
|
||||
AC_ARG_ENABLE(libavcodec,
|
||||
AS_HELP_STRING([--disable-libavcodec], [disable libavcodec support(default is auto)]),
|
||||
[ --disable-libavcodec disable libavcodec support (default is auto)]
|
||||
[ Requires: libavcodec libavutil],
|
||||
[libavcodec_req=$enableval],
|
||||
[libavcodec_req=auto]
|
||||
)
|
||||
@@ -2642,11 +2664,11 @@ AC_SUBST(CURSES_LIBS)
|
||||
# OpenSSL-libcrypto
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
crypto=no
|
||||
crypto_req=auto
|
||||
AC_ARG_ENABLE(openssl,
|
||||
AS_HELP_STRING([--disable-openssl], [disable OpenSSL support(default is auto)]),
|
||||
[ --enable-openssl enable OpenSSL support (default is disable)]
|
||||
[ Requires: crypto],
|
||||
[crypto_req=$enableval],
|
||||
[crypto_req=auto]
|
||||
[crypto_req=no]
|
||||
)
|
||||
|
||||
PKG_CHECK_MODULES([CRYPTO], [libcrypto], [crypto=yes], [crypto=no])
|
||||
@@ -2665,6 +2687,33 @@ if test $crypto_req = yes -a $crypto = no; then
|
||||
AC_MSG_ERROR([OpenSSL not found]);
|
||||
fi
|
||||
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
# GPU accelerated LDGM
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
ldgm_gpu=no
|
||||
AC_ARG_ENABLE(ldgm-gpu,
|
||||
[ --enable-ldgm-gpu enable GPU accelerated LDGM (default is disable)]
|
||||
[ Requires: CUDA],
|
||||
[ldgm_gpu_req=$enableval],
|
||||
[ldgm_gpu_req=no]
|
||||
)
|
||||
|
||||
if test $ldgm_gpu_req != no -a $FOUND_CUDA = yes
|
||||
then
|
||||
OBJS="$OBJS ldgm-coding/ldgm-session-gpu.o ldgm-coding/gpu.cu.o"
|
||||
DEFINE_CUDA
|
||||
CUDA_MESSAGE
|
||||
AC_DEFINE([HAVE_LDGM_GPU], [1], [Build with GPU accelerated LDGM])
|
||||
ldgm_gpu=yes
|
||||
else
|
||||
ldgm_gpu=no
|
||||
fi
|
||||
|
||||
if test $ldgm_gpu_req = yes -a $ldgm_gpu = no; then
|
||||
AC_MSG_ERROR([LDGM accelerated GPU cannot be enabled (CUDA not found?)]);
|
||||
fi
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
# We need to add libraries then
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
@@ -2698,8 +2747,7 @@ RESULT=\
|
||||
License ..................... $license
|
||||
iHDTV support ............... $ihdtv
|
||||
OpenSSL-libcrypto ........... $crypto
|
||||
Library glib ................ $glib
|
||||
Library curl ................ $curl
|
||||
CUDA support ................ $FOUND_CUDA
|
||||
Library live555 ............. $livemedia
|
||||
|
||||
AV Foundation ............... $avfoundation
|
||||
@@ -2709,14 +2757,12 @@ RESULT=\
|
||||
DELTACAST ................... $deltacast
|
||||
DVS ......................... $dvs
|
||||
OpenGL ...................... $gl
|
||||
OpenCV ...................... $opencv
|
||||
Quicktime ................... $quicktime
|
||||
SAGE ........................ $sage
|
||||
SDL ......................... $sdl
|
||||
Screen Capture .............. $screen_cap
|
||||
V4L2 ........................ $v4l2
|
||||
RTSP Capturer Client ........ $rtsp
|
||||
RTSP Server ................. $rtsp_server
|
||||
SW Video Mix ................ $swmix
|
||||
|
||||
Portaudio ................... $portaudio
|
||||
@@ -2732,8 +2778,11 @@ RESULT=\
|
||||
UYVY dummy compression ...... $uyvy
|
||||
Libavcodec .................. $libavcodec
|
||||
|
||||
resize capture filter ....... $resize
|
||||
RTSP Server ................. $rtsp_server
|
||||
scale postprocessor ......... $scale
|
||||
testcard extras ............. $testcard_extras_req
|
||||
GPU accelerated LDGM ........ $ldgm_gpu
|
||||
"
|
||||
|
||||
AC_MSG_RESULT(
|
||||
|
||||
@@ -81,10 +81,10 @@ struct vec3 : public vec2 {
|
||||
}
|
||||
};
|
||||
|
||||
uvec3::uvec3(const vec3 & v) : r(v.r), g(v.g), b(v.b) {}
|
||||
uvec2::uvec2(const vec2 & v) : r(v.r), g(v.g) {}
|
||||
vec2::vec2(const vec3 & v) : r(v.r), g(v.g) {}
|
||||
vec2::vec2(const uvec2 & v) : r(v.r), g(v.g) {}
|
||||
__device__ uvec3::uvec3(const vec3 & v) : r(v.r), g(v.g), b(v.b) {}
|
||||
__device__ uvec2::uvec2(const vec2 & v) : r(v.r), g(v.g) {}
|
||||
__device__ vec2::vec2(const vec3 & v) : r(v.r), g(v.g) {}
|
||||
__device__ vec2::vec2(const uvec2 & v) : r(v.r), g(v.g) {}
|
||||
|
||||
|
||||
__device__ static vec3 min(const vec3 & a, const vec3 & b) {
|
||||
@@ -462,14 +462,14 @@ __device__ static void swap(T & a, T & b) {
|
||||
|
||||
/// Encodes and saves the block.
|
||||
template <int DXT_TYPE>
|
||||
__device__ static void dxt_encode(void * out, const int block_idx,
|
||||
__device__ void dxt_encode(void * out, const int block_idx,
|
||||
float r[16], float g[16], float b[16]);
|
||||
|
||||
|
||||
/// Encodes the block into DXT6 format (DXT5-YcOcG) and saves it into output
|
||||
/// buffer
|
||||
template <>
|
||||
__device__ static void dxt_encode<6>(void * out, const int block_idx,
|
||||
__device__ void dxt_encode<6>(void * out, const int block_idx,
|
||||
float r[16], float g[16], float b[16]) {
|
||||
// Read block of data
|
||||
vec3 block[16];
|
||||
@@ -510,7 +510,7 @@ __device__ static void dxt_encode<6>(void * out, const int block_idx,
|
||||
|
||||
/// Encodes the block into DXT1 format and saves it into output buffer
|
||||
template <>
|
||||
__device__ static void dxt_encode<1>(void * out, const int block_idx,
|
||||
__device__ void dxt_encode<1>(void * out, const int block_idx,
|
||||
float r[16], float g[16], float b[16]) {
|
||||
// find min and max sample values for each component
|
||||
float mincol_r = r[0];
|
||||
|
||||
@@ -194,8 +194,11 @@ dxt_decoder_create(enum dxt_type type, int width, int height, enum dxt_format ou
|
||||
} else {
|
||||
decoder->shader_vertex_display = dxt_shader_create_from_source(vp_compress, GL_VERTEX_SHADER);
|
||||
}
|
||||
if ( decoder->shader_fragment_display == 0 || decoder->shader_vertex_display == 0 )
|
||||
if ( decoder->shader_fragment_display == 0 || decoder->shader_vertex_display == 0 ) {
|
||||
/// @todo Free other stuff as well
|
||||
free(decoder);
|
||||
return NULL;
|
||||
}
|
||||
// Attach shader to program and link the program
|
||||
glAttachShader(decoder->program_display, decoder->shader_fragment_display);
|
||||
glAttachShader(decoder->program_display, decoder->shader_vertex_display);
|
||||
|
||||
@@ -362,8 +362,11 @@ dxt_encoder_create(enum dxt_type type, int width, int height, enum dxt_format fo
|
||||
//glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
if(format == DXT_FORMAT_YUV422) {
|
||||
if(!dxt_prepare_yuv422_shader(encoder))
|
||||
if(!dxt_prepare_yuv422_shader(encoder)) {
|
||||
/// @todo What about generated textures etc. ?
|
||||
free(encoder);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, encoder->texture_id);
|
||||
|
||||
@@ -52,7 +52,7 @@ dxt_shader_create_from_source(const char* source, GLenum type)
|
||||
}
|
||||
|
||||
/** Documented at declaration */
|
||||
GLhandleARB
|
||||
GLuint
|
||||
dxt_shader_create_from_file(const char* filename, GLenum type)
|
||||
{
|
||||
// Load program from file
|
||||
@@ -64,17 +64,19 @@ dxt_shader_create_from_file(const char* filename, GLenum type)
|
||||
}
|
||||
fseek(file, 0, SEEK_END);
|
||||
int data_size = ftell(file);
|
||||
assert(data_size >= 0);
|
||||
rewind(file);
|
||||
char* program = (char*)malloc((data_size + 1) * sizeof(char));
|
||||
if ( (size_t) data_size != fread(program, sizeof(char), data_size, file) ) {
|
||||
fprintf(stderr, "Failed to load program [%d bytes] from file %s!\n", data_size, filename);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
fclose(file);
|
||||
program[data_size] = '\0';
|
||||
|
||||
printf("Compiling program [%s]...\n", filename);
|
||||
GLhandleARB shader = dxt_shader_create_from_source(program, type);
|
||||
GLuint shader = dxt_shader_create_from_source(program, type);
|
||||
if ( shader == 0 )
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ dxt_shader_create_from_source(const char* source, GLenum type);
|
||||
* @param type Shader type
|
||||
* @return shader handle if succeeds, otherwise zero
|
||||
*/
|
||||
GLhandleARB
|
||||
GLuint
|
||||
dxt_shader_create_from_file(const char* filename, GLenum type);
|
||||
|
||||
|
||||
|
||||
2
gpujpeg
2
gpujpeg
Submodule gpujpeg updated: e7d7e09a72...0b3af83685
@@ -1,283 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#define __USE_GNU 1
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#define SIZE 10000
|
||||
|
||||
struct replica {
|
||||
const char *host;
|
||||
unsigned short port;
|
||||
int sock;
|
||||
};
|
||||
|
||||
|
||||
struct item {
|
||||
struct item *next;
|
||||
long size;
|
||||
char buf[SIZE];
|
||||
};
|
||||
|
||||
static struct item *queue;
|
||||
static struct item *qhead;
|
||||
static struct item *qtail;
|
||||
static int qempty = 1;
|
||||
static int qfull = 0;
|
||||
static pthread_mutex_t qempty_mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t qfull_mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t qempty_cond = PTHREAD_COND_INITIALIZER;
|
||||
static pthread_cond_t qfull_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
struct replica *replicas;
|
||||
int count;
|
||||
|
||||
void qinit(int qsize)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("initializing packet queue for %d items\n", qsize);
|
||||
|
||||
queue = (struct item *) calloc(qsize, sizeof(struct item));
|
||||
if (queue == NULL) {
|
||||
fprintf(stderr, "not enough memory\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
for (i = 0; i < qsize; i++)
|
||||
queue[i].next = queue + i + 1;
|
||||
queue[qsize - 1].next = queue;
|
||||
|
||||
qhead = qtail = queue;
|
||||
}
|
||||
|
||||
|
||||
int buffer_size(int sock, int optname, int size)
|
||||
{
|
||||
socklen_t len = sizeof(int);
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, optname, (void *) &size, len)
|
||||
|| getsockopt(sock, SOL_SOCKET, optname, (void *) &size, &len)) {
|
||||
perror("[sg]etsockopt()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("UDP %s buffer size set to %d bytes\n",
|
||||
(optname == SO_SNDBUF) ? "send" : "receiver", size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int output_socket(unsigned short port, const char *host, int bufsize)
|
||||
{
|
||||
int s;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res;
|
||||
char saddr[INET_ADDRSTRLEN];
|
||||
char p[6];
|
||||
|
||||
memset(&hints, '\0', sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_UDP;
|
||||
hints.ai_family = PF_INET;
|
||||
|
||||
snprintf(p, 6, "%d", port);
|
||||
p[5] = '\0';
|
||||
|
||||
if (getaddrinfo(host, p, &hints, &res)) {
|
||||
int err = errno;
|
||||
if (err == 0)
|
||||
fprintf(stderr, "Address not found: %s\n", host);
|
||||
else
|
||||
fprintf(stderr, "%s: %s\n", gai_strerror(err), host);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
inet_ntop(AF_INET, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
|
||||
saddr, sizeof(saddr));
|
||||
printf("connecting to %s (%s) port %d\n",
|
||||
res->ai_canonname, saddr, port);
|
||||
|
||||
if ((s = socket(res->ai_family, res->ai_socktype, 0)) == -1) {
|
||||
perror("socket");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (buffer_size(s, SO_SNDBUF, bufsize))
|
||||
exit(2);
|
||||
|
||||
if (connect(s, res->ai_addr, res->ai_addrlen)) {
|
||||
perror("connect");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
void *writer(void *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
while (1) {
|
||||
while (qhead != qtail) {
|
||||
for (i = 0; i < count; i++)
|
||||
write(replicas[i].sock, qhead->buf, qhead->size);
|
||||
|
||||
qhead = qhead->next;
|
||||
|
||||
pthread_mutex_lock(&qfull_mtx);
|
||||
qfull = 0;
|
||||
pthread_cond_signal(&qfull_cond);
|
||||
pthread_mutex_unlock(&qfull_mtx);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&qempty_mtx);
|
||||
if (qempty)
|
||||
pthread_cond_wait(&qempty_cond, &qempty_mtx);
|
||||
qempty = 1;
|
||||
pthread_mutex_unlock(&qempty_mtx);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned short port;
|
||||
int qsize;
|
||||
int bufsize;
|
||||
struct sockaddr_in addr;
|
||||
int sock_in;
|
||||
pthread_t thread;
|
||||
int err = 0;
|
||||
int i;
|
||||
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "%s buffer_size port host...\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((bufsize = atoi(argv[1])) <= 0) {
|
||||
fprintf(stderr, "invalid buffer size: %d\n", bufsize);
|
||||
return 1;
|
||||
}
|
||||
switch (argv[1][strlen(argv[1]) - 1]) {
|
||||
case 'K':
|
||||
case 'k':
|
||||
bufsize *= 1024;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
case 'm':
|
||||
bufsize *= 1024*1024;
|
||||
break;
|
||||
}
|
||||
|
||||
qsize = bufsize / 8000;
|
||||
|
||||
printf("using UDP send and receive buffer size of %d bytes\n", bufsize);
|
||||
|
||||
if ((port = atoi(argv[2])) <= 0) {
|
||||
fprintf(stderr, "invalid port: %d\n", port);
|
||||
return 1;
|
||||
}
|
||||
|
||||
qinit(qsize);
|
||||
|
||||
/* input socket */
|
||||
if ((sock_in = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
perror("input socket");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (buffer_size(sock_in, SO_RCVBUF, bufsize))
|
||||
exit(2);
|
||||
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.sin_port = htons(port);
|
||||
if (bind(sock_in, (struct sockaddr *) &addr,
|
||||
sizeof(struct sockaddr_in))) {
|
||||
perror("bind");
|
||||
return 2;
|
||||
}
|
||||
|
||||
printf("listening on *:%d\n", port);
|
||||
|
||||
/* output socket(s) */
|
||||
count = argc - 3;
|
||||
replicas = (struct replica *) calloc(count, sizeof(struct replica));
|
||||
if (replicas == NULL) {
|
||||
fprintf(stderr, "not enough memory for replica array");
|
||||
return 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
replicas[i].host = argv[3 + i];
|
||||
|
||||
if (i > 0 && strcmp(replicas[i - 1].host, replicas[i].host) == 0)
|
||||
replicas[i].port = replicas[i - 1].port + 1;
|
||||
else
|
||||
replicas[i].port = port;
|
||||
|
||||
replicas[i].sock = output_socket(replicas[i].port, replicas[i].host,
|
||||
bufsize);
|
||||
}
|
||||
|
||||
if (pthread_create(&thread, NULL, writer, NULL)) {
|
||||
fprintf(stderr, "cannot create writer thread\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* main loop */
|
||||
while (1) {
|
||||
fcntl(sock_in, F_SETFL, O_NONBLOCK);
|
||||
|
||||
while (qtail->next != qhead
|
||||
&& ((qtail->size = read(sock_in, qtail->buf, SIZE)) > 0
|
||||
|| (err = errno) == EAGAIN)) {
|
||||
|
||||
if (qtail->size <= 0) {
|
||||
pthread_yield();
|
||||
}
|
||||
else {
|
||||
qtail = qtail->next;
|
||||
|
||||
pthread_mutex_lock(&qempty_mtx);
|
||||
qempty = 0;
|
||||
pthread_cond_signal(&qempty_cond);
|
||||
pthread_mutex_unlock(&qempty_mtx);
|
||||
}
|
||||
}
|
||||
|
||||
if (qtail->size <= 0)
|
||||
break;
|
||||
|
||||
pthread_mutex_lock(&qfull_mtx);
|
||||
if (qfull)
|
||||
pthread_cond_wait(&qfull_cond, &qfull_mtx);
|
||||
qfull = 1;
|
||||
pthread_mutex_unlock(&qfull_mtx);
|
||||
}
|
||||
|
||||
if (qtail->size < 0) {
|
||||
printf("read: %s\n", strerror(err));
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -10,286 +10,559 @@
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Milan Kabat (), kabat@ics.muni.cz
|
||||
* Authors: Milan Kabat (kabat@ics.muni.cz), Vojtech David (374572@mail.muni.cz)
|
||||
* Company: FI MUNI
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <emmintrin.h>
|
||||
#include <sys/time.h>
|
||||
#include <cuda.h>
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include "timer-util.h"
|
||||
#include "gpu.cuh"
|
||||
#include "ldgm-session-gpu.h"
|
||||
|
||||
#define INTS_PER_THREAD 4
|
||||
|
||||
void make_compact_pcm ( char* pc_matrix, int* pcm, struct coding_params params );
|
||||
|
||||
void gpu_encode ( char* source_data, char* parity, int* pc_matrix, struct coding_params );
|
||||
|
||||
void gpu_decode ( char* received, int* error_vec, char* pc_matrix, struct coding_params );
|
||||
|
||||
__global__ void encode ( int* data, int* parity, int* pcm, struct coding_params params )
|
||||
__device__ unsigned int count = 0;
|
||||
__device__ unsigned int count_M = 0;
|
||||
char *xor_using_sse2 (char *source, char *dest, int packet_size)
|
||||
{
|
||||
//First, do as many 128-bit XORs as possible
|
||||
int iter_bytes_16 = 0;
|
||||
int iter_bytes_4 = 0;
|
||||
int iter_bytes_1 = 0;
|
||||
|
||||
//partial result
|
||||
extern __shared__ int shared_mem[];
|
||||
// int idx = blockIdx.x*blockDim.x + threadIdx.x;
|
||||
int num_packets = params.max_row_weight;
|
||||
int p_size = params.packet_size/4;
|
||||
iter_bytes_16 = (packet_size / 16) * 16;
|
||||
|
||||
//in each iteration, we copy corresponding packet to shared memory and XOR its content
|
||||
//into partial result
|
||||
for ( int i = 0; i < num_packets; i++ )
|
||||
{
|
||||
int index = pcm [ blockIdx.x*(num_packets+2) + i ];
|
||||
|
||||
if ( index > -1 && index < params.k )
|
||||
{
|
||||
for ( int j = 0; j < INTS_PER_THREAD; j++ )
|
||||
{
|
||||
shared_mem [ threadIdx.x*INTS_PER_THREAD + j ] ^=
|
||||
data [ index*p_size + threadIdx.x*INTS_PER_THREAD + j ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( int j = 0; j < INTS_PER_THREAD; j++ )
|
||||
{
|
||||
parity [ blockIdx.x*p_size + threadIdx.x*INTS_PER_THREAD + j ] =
|
||||
shared_mem [ threadIdx.x*INTS_PER_THREAD + j];
|
||||
shared_mem [ threadIdx.x*INTS_PER_THREAD + j] = 0;
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
}
|
||||
|
||||
__global__ void decode ( int* received, int* error_vec, int* pcm, struct coding_params params )
|
||||
{
|
||||
/* extern __shared__ int shared_mem[];
|
||||
*
|
||||
* int num_neighbours = params.max_row_weight + 2;
|
||||
*
|
||||
* int p_size = params.packet_size/sizeof(int);
|
||||
* int num_threads = p_size/4;
|
||||
*
|
||||
* //load the neighbouring packets into shared memory
|
||||
* int idx = blockIdx.x*blockDim.x + threadIdx.x;
|
||||
* for ( int i = 0; i < num_beighbours; i++ )
|
||||
* {
|
||||
* if ( threadIdx.x == 0 )
|
||||
* shared_mem[i] = pcm [ blockIdx.x*num_beighbours + i ];
|
||||
*
|
||||
* __syncthreads();
|
||||
*
|
||||
* if ( shared_mem[i] != -1 )
|
||||
* {
|
||||
* // shared_mem [ num_neighbours + threadIdx.x*4 + i ] =
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* __syncthreads();
|
||||
* for ( int i = 0; i < (params.packet_size/sizeof(int))/num_threads; i++ )
|
||||
* received [ (params.k + blockIdx.x)*p_size + threadIdx.x*4 + i] =
|
||||
* pkts [ idx + i ];
|
||||
*
|
||||
* __syncthreads();
|
||||
*/
|
||||
|
||||
// for ( int i = 0; i < params.packet_size/sizeof(int); i++ )
|
||||
// received [ params.k*p_size + blockIdx.x*p_size + idx + i ] = pkts [ idx + i ];
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void gpu_encode ( char* source_data, char* parity, int* pcm, struct coding_params params )
|
||||
{
|
||||
int* src_data_d;
|
||||
int* parity_data_d;
|
||||
int* pcm_d;
|
||||
short show_info = 0;
|
||||
|
||||
cudaError_t cuda_error;
|
||||
|
||||
struct cudaDeviceProp dev_prop;
|
||||
|
||||
cudaGetDeviceProperties (&dev_prop, 0);
|
||||
|
||||
if (show_info)
|
||||
if ( iter_bytes_16 > 0)
|
||||
{
|
||||
if (!dev_prop.canMapHostMemory)
|
||||
printf("Cannot map host memory.\n");
|
||||
printf ( "name: %s\n", dev_prop.name );
|
||||
printf ( "totalGlobalMem: %d MB\n", (unsigned int)dev_prop.totalGlobalMem/(1024*1024) );
|
||||
printf ( "sharedMemPerBlock: %d kB\n", (unsigned int)dev_prop.sharedMemPerBlock/1024 );
|
||||
printf ( "maxThreadsPerBlock: %d\n", dev_prop.maxThreadsPerBlock );
|
||||
printf ( "maxThreadsDim: %d\n", dev_prop.maxThreadsDim[0] );
|
||||
printf ( "maxThreadsDim: %d\n", dev_prop.maxThreadsDim[1] );
|
||||
printf ( "maxThreadsDim: %d\n", dev_prop.maxThreadsDim[2] );
|
||||
printf ( "maxGridSize: %d\n", dev_prop.maxGridSize[0] );
|
||||
|
||||
// printf ( "iter_bytes: %d\n", iter_bytes );
|
||||
__m128i *wrd_ptr = (__m128i *) source;
|
||||
__m128i *wrd_end = (__m128i *) (source + iter_bytes_16);
|
||||
__m128i *dst_ptr = (__m128i *) dest;
|
||||
|
||||
// printf ( "wrd_ptr address: %p\n", wrd_ptr );
|
||||
do
|
||||
{
|
||||
__m128i xmm1 = _mm_loadu_si128(wrd_ptr);
|
||||
__m128i xmm2 = _mm_loadu_si128(dst_ptr);
|
||||
|
||||
xmm1 = _mm_xor_si128(xmm1, xmm2); // XOR 4 32-bit words
|
||||
_mm_storeu_si128(dst_ptr, xmm1);
|
||||
++wrd_ptr;
|
||||
++dst_ptr;
|
||||
|
||||
}
|
||||
while (wrd_ptr < wrd_end);
|
||||
}
|
||||
//Check, whether further XORing is necessary
|
||||
if ( iter_bytes_16 < packet_size )
|
||||
{
|
||||
char *mark_source = source + iter_bytes_16;
|
||||
char *mark_dest = dest + iter_bytes_16;
|
||||
|
||||
iter_bytes_4 = ((packet_size - iter_bytes_16) / 4) * 4;
|
||||
|
||||
for ( int i = 0; i < (packet_size - iter_bytes_16) / 4; i++)
|
||||
{
|
||||
int *s = ((int *) mark_source) + i;
|
||||
int *d = ((int *) mark_dest) + i;
|
||||
*d ^= *s;
|
||||
}
|
||||
|
||||
mark_source += iter_bytes_4;
|
||||
mark_dest += iter_bytes_4;
|
||||
|
||||
iter_bytes_1 = packet_size - iter_bytes_16 - iter_bytes_4;
|
||||
|
||||
for ( int i = 0; i < iter_bytes_1; i++)
|
||||
{
|
||||
*(mark_dest + i) ^= *(mark_source + i);
|
||||
}
|
||||
}
|
||||
|
||||
// pcm = (int*) malloc (params.m*(params.max_row_weight+2)*sizeof(int*));
|
||||
|
||||
// make_compact_pcm ( pc_matrix, pcm, params );
|
||||
|
||||
cuda_error = cudaMalloc ( (void**) &src_data_d, params.k*params.packet_size);
|
||||
if ( cuda_error != cudaSuccess )
|
||||
printf ( "cudaMalloc returned %d\n", cuda_error );
|
||||
|
||||
cuda_error = cudaMalloc ( (void**) &parity_data_d, params.m*params.packet_size);
|
||||
if ( cuda_error != cudaSuccess )
|
||||
printf ( "cudaMalloc returned %d\n", cuda_error );
|
||||
|
||||
cuda_error = cudaMemset ( parity_data_d, 0, params.m*params.packet_size);
|
||||
if ( cuda_error != cudaSuccess )
|
||||
printf ( "cudaMemset returned %d\n", cuda_error );
|
||||
|
||||
cuda_error = cudaMemcpy ( src_data_d, source_data, params.k*params.packet_size,
|
||||
cudaMemcpyHostToDevice );
|
||||
if ( cuda_error != cudaSuccess )
|
||||
printf ( "cudaMemcpy returned %d\n", cuda_error );
|
||||
|
||||
cuda_error = cudaMalloc ( (void**) &pcm_d, params.m*(params.max_row_weight+2)*sizeof(int));
|
||||
if ( cuda_error != cudaSuccess )
|
||||
printf ( "cudaMalloc return %d\n", cuda_error );
|
||||
|
||||
cuda_error = cudaMemcpy ( pcm_d, pcm, sizeof(int)*params.m*(params.max_row_weight+2),
|
||||
cudaMemcpyHostToDevice );
|
||||
if ( cuda_error != cudaSuccess )
|
||||
printf ( "cudaMempcy return %d\n", cuda_error );
|
||||
cuda_error = cudaDeviceSynchronize();
|
||||
|
||||
if ( cuda_error != cudaSuccess )
|
||||
printf ( "cudaSyn returned %d\n", cuda_error );
|
||||
|
||||
|
||||
int block_size = (params.packet_size / sizeof(int))/INTS_PER_THREAD;
|
||||
int block_count = params.m;
|
||||
|
||||
int num_bytes_shared = params.packet_size;
|
||||
|
||||
|
||||
// for ( int i = 0; i < 1000; i++)
|
||||
encode <<< block_count, block_size, num_bytes_shared >>> (src_data_d, parity_data_d,
|
||||
pcm_d, params );
|
||||
|
||||
cuda_error = cudaGetLastError();
|
||||
if ( cuda_error != cudaSuccess )
|
||||
printf("kernel execution returned %d\n", cuda_error);
|
||||
|
||||
cudaThreadSynchronize();
|
||||
|
||||
|
||||
cudaMemcpy ( parity, parity_data_d, params.m*params.packet_size, cudaMemcpyDeviceToHost );
|
||||
cuda_error = cudaGetLastError();
|
||||
if ( cuda_error != cudaSuccess )
|
||||
printf("cudaMemcpy from device returned %d\n", cuda_error);
|
||||
|
||||
cudaFree(src_data_d);
|
||||
cudaFree(parity_data_d);
|
||||
|
||||
}
|
||||
|
||||
void gpu_decode ( char* received, int* error_vec, char* pc_matrix, struct coding_params params )
|
||||
{
|
||||
/* int* received_d;
|
||||
* int* pcm_d;
|
||||
* int* error_vec_d;
|
||||
* cudaError_t cuda_error;
|
||||
*
|
||||
* int k = params.k;
|
||||
* int m = params.m;
|
||||
* int packet_size = params.packet_size;
|
||||
*
|
||||
* int **pcm = make_compact_pcm ( pc_matrix, params );
|
||||
*
|
||||
* //alocate space and copy data to device
|
||||
* cuda_error = cudaMalloc ( (void**) &received_d, (k+m)*packet_size);
|
||||
* if ( cuda_error != cudaSuccess )
|
||||
* printf ( "cudaMalloc return %d\n", cuda_error );
|
||||
*
|
||||
* cuda_error = cudaMemcpy ( received_d, received, (k+m)*packet_size, cudaMemcpyHostToDevice );
|
||||
* if ( cuda_error != cudaSuccess )
|
||||
* printf ( "cudaMempcy return %d\n", cuda_error );
|
||||
*
|
||||
* cuda_error = cudaMalloc ( (void**) &pcm_d, m*params.max_row_weight*sizeof(int));
|
||||
* if ( cuda_error != cudaSuccess )
|
||||
* printf ( "cudaMalloc return %d\n", cuda_error );
|
||||
*
|
||||
* cuda_error = cudaMemcpy ( pcm_d, pcm, sizeof(int)*m*params.max_row_weight,
|
||||
* cudaMemcpyHostToDevice );
|
||||
* if ( cuda_error != cudaSuccess )
|
||||
* printf ( "cudaMempcy return %d\n", cuda_error );
|
||||
*
|
||||
* cuda_error = cudaMalloc ( (void**) &error_vec_d, params.num_lost*sizeof(int));
|
||||
* if ( cuda_error != cudaSuccess )
|
||||
* printf ( "cudaMalloc return %d\n", cuda_error );
|
||||
*
|
||||
* cuda_error = cudaMemcpy ( pcm_d, pcm, params.num_lost*sizeof(int),
|
||||
* cudaMemcpyHostToDevice );
|
||||
* if ( cuda_error != cudaSuccess )
|
||||
* printf ( "cudaMempcy pcm return %d\n", cuda_error );
|
||||
*
|
||||
* int block_size = (packet_size/sizeof(int)) / 4;
|
||||
* int block_count = m;
|
||||
* int shared_mem_size = (packet_size + sizeof(int))*(params.max_row_weight+2);
|
||||
*
|
||||
* decode <<< block_count, block_size, shared_mem_size >>> (received_d, error_vec, pcm_d, params );
|
||||
*
|
||||
* cuda_error = cudaMemcpy ( received, received_d, (k+m)*packet_size, cudaMemcpyDeviceToHost );
|
||||
* if ( cuda_error != cudaSuccess )
|
||||
* printf ( "cudaMempcy from device return %d\n", cuda_error );
|
||||
*
|
||||
* cudaFree ( received_d );
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* void make_compact_pcm ( char* pc_matrix, int* pcm, struct coding_params params)
|
||||
* {
|
||||
* //we need to create a compact representation of sparse pc_matrix
|
||||
*
|
||||
* int counter = 0;
|
||||
* int columns = params.max_row_weight + 2;
|
||||
*
|
||||
* for ( int i = 0; i < params.m; i++) {
|
||||
* for ( int j = 0; j < params.k; j++)
|
||||
* if ( pc_matrix[i*params.k + j] )
|
||||
* {
|
||||
* pcm[i*columns + counter] = j;
|
||||
* counter++;
|
||||
* }
|
||||
* //add indices from staircase matrix
|
||||
* pcm[i*columns + counter] = params.k + i;
|
||||
* counter++;
|
||||
*
|
||||
* if ( i > 0 )
|
||||
* {
|
||||
* pcm[i*columns + counter] = params.k + i - 1;
|
||||
* counter++;
|
||||
* }
|
||||
*
|
||||
* if ( counter < columns )
|
||||
* for ( int j = counter; j < columns; j++)
|
||||
* pcm[i*columns + j] = -1;
|
||||
* counter = 0;
|
||||
* }
|
||||
*
|
||||
*
|
||||
* for ( int i = 0; i < params.m; i++)
|
||||
* {
|
||||
* for ( int j = 0; j < columns; j++ )
|
||||
* printf ( "%d, ", pcm[i*columns + j] );
|
||||
* printf ( "\n" );
|
||||
* }
|
||||
*
|
||||
*
|
||||
* }
|
||||
*/
|
||||
void gpu_encode_upgrade (char * source_data,int *OUTBUF, int * PCM,int param_k,int param_m,int w_f,int packet_size ,int buf_size)
|
||||
{
|
||||
|
||||
// cudaError_t error;
|
||||
int blocksize = packet_size/sizeof(int);
|
||||
// printf("blocksize: %d\npacket size: %d\n",blocksize,packet_size );
|
||||
if(blocksize>256){
|
||||
if(blocksize>1024) blocksize=1024;
|
||||
// puts("big one");
|
||||
frame_encode_int_big <<< param_m, blocksize, packet_size >>> (OUTBUF,PCM, param_k, param_m, w_f, packet_size);
|
||||
cuda_check_error("frame_encode_int_big");
|
||||
|
||||
frame_encode_staircase<<< 1, blocksize, packet_size >>> (OUTBUF, PCM, param_k, param_m, w_f, packet_size);
|
||||
cuda_check_error("frame_encode_staircase");
|
||||
|
||||
cudaMemcpy(source_data + param_k*packet_size,OUTBUF + (param_k*packet_size)/4, param_m*packet_size,cudaMemcpyDeviceToHost );
|
||||
// // cudaMemcpy(source_data,OUTBUF, buf_size,cudaMemcpyDeviceToHost );
|
||||
cuda_check_error("memcpy out_buf");
|
||||
|
||||
|
||||
// gettimeofday(&t0, 0);
|
||||
// for ( int m = 1; m < param_m; ++m)
|
||||
// {
|
||||
// char *prev_parity = (char *) source_data + (param_k + m - 1) * packet_size;
|
||||
// char *parity_packet = (char *) source_data + (param_k + m) * packet_size;
|
||||
// xor_using_sse2(prev_parity, parity_packet, packet_size);
|
||||
|
||||
// }
|
||||
// gettimeofday(&t1, 0);
|
||||
// long elapsed = (t1.tv_sec - t0.tv_sec) * 1000000 + t1.tv_usec - t0.tv_usec;
|
||||
// printf("time staircase: %f\n",elapsed/1000.0 );
|
||||
|
||||
}
|
||||
else{
|
||||
// puts("chudy soused");
|
||||
frame_encode_int <<< param_m, blocksize, packet_size >>> (OUTBUF,PCM, param_k, param_m, w_f, packet_size);
|
||||
cuda_check_error("frame_encode_int");
|
||||
|
||||
cudaMemcpy(source_data + param_k*packet_size,OUTBUF + (param_k*packet_size)/4, param_m*packet_size,cudaMemcpyDeviceToHost );
|
||||
// cudaMemcpy(source_data,OUTBUF, buf_size,cudaMemcpyDeviceToHost );
|
||||
cuda_check_error("memcpyu out_buf");
|
||||
|
||||
for ( int m = 1; m < param_m; ++m)
|
||||
{
|
||||
char *prev_parity = (char *) source_data + (param_k + m - 1) * packet_size;
|
||||
char *parity_packet = (char *) source_data + (param_k + m) * packet_size;
|
||||
xor_using_sse2(prev_parity, parity_packet, packet_size);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// cudaEvent_t start, stop;
|
||||
// float time;
|
||||
// cudaEventCreate(&start);
|
||||
// cudaEventCreate(&stop);
|
||||
|
||||
// cudaEventRecord(start, 0);
|
||||
|
||||
// cudaStream_t pStream;
|
||||
// cudaStreamCreate(&pStream);
|
||||
// frame_encode_staircase<<< 1, blocksize, packet_size >>> (OUTBUF, PCM, param_k, param_m, w_f, packet_size);
|
||||
// cuda_check_error("frame_encode_staircase");
|
||||
|
||||
|
||||
|
||||
// cudaStreamSynchronize();
|
||||
// cudaDeviceSynchronize();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void gpu_decode_upgrade(char *data, int * PCM,int* SYNC_VEC,int* ERROR_VEC, int not_done, int *frame_size,int * error_vec,int * sync_vec,int M,int K,int w_f,int buf_size,int packet_size)
|
||||
{
|
||||
|
||||
|
||||
cudaError_t error;
|
||||
int *received_d;
|
||||
|
||||
|
||||
// int M = params->m;
|
||||
// int K = params->k;
|
||||
// int w_f = params->max_row_weight + 2;
|
||||
// int buf_size = params->buf_size;
|
||||
|
||||
int* received = (int*) data;
|
||||
// printf("K: %d, M: %d, max_row_weight: %d, buf_size: %d,\n packet_size: %d\n",K,M,w_f,buf_size,packet_size );
|
||||
// printf("NOT DONE: %d\n",not_done );
|
||||
|
||||
|
||||
error = cudaHostRegister(received, buf_size, cudaHostRegisterMapped);
|
||||
if (error != cudaSuccess) printf("1 %s\n", cudaGetErrorString(error));
|
||||
|
||||
error = cudaHostGetDevicePointer((void **) & (received_d), (void *)received, 0);
|
||||
if (error != cudaSuccess) printf("2 %s\n", cudaGetErrorString(error));
|
||||
|
||||
// error = cudaMalloc(&received_d, buf_size);
|
||||
// if (error != cudaSuccess) printf("1 %s\n", cudaGetErrorString(error));
|
||||
|
||||
// error = cudaMemcpy(received_d, received, buf_size, cudaMemcpyHostToDevice);
|
||||
// if (error != cudaSuccess) printf("2 %s\n", cudaGetErrorString(error));
|
||||
|
||||
// error = cudaMalloc(&pcm_d, w_f * M * sizeof(int));
|
||||
// if (error != cudaSuccess) printf("3 %s\n", cudaGetErrorString(error));
|
||||
|
||||
// error = cudaMemcpy(pcm_d, PCM, w_f * M * sizeof(int), cudaMemcpyHostToDevice);
|
||||
// if (error != cudaSuccess) printf("4 %s\n", cudaGetErrorString(error));
|
||||
|
||||
|
||||
// error = cudaMalloc(&error_vec_d, (K + M) * sizeof(int));
|
||||
// if (error != cudaSuccess)printf("5 %s\n", cudaGetErrorString(error));
|
||||
|
||||
// error = cudaMemcpy(error_vec_d, error_vec, (K + M) * sizeof(int), cudaMemcpyHostToDevice);
|
||||
// if (error != cudaSuccess) printf("6 %s\n", cudaGetErrorString(error));
|
||||
|
||||
// error = cudaMalloc(&sync_vec_d, (K + M) * sizeof(int));
|
||||
// if (error != cudaSuccess) printf("7 %s\n", cudaGetErrorString(error));
|
||||
|
||||
// error = cudaMemcpy(sync_vec_d, sync_vec, (K + M) * sizeof(int), cudaMemcpyHostToDevice);
|
||||
// if (error != cudaSuccess) printf("8 %s\n", cudaGetErrorString(error));
|
||||
|
||||
int ps = packet_size/sizeof(int);
|
||||
|
||||
int blocksize = packet_size/sizeof(int) +1;
|
||||
// printf("blocksize: %d\npacket size: %d\n",blocksize,packet_size );
|
||||
if(blocksize>512) blocksize=512;
|
||||
|
||||
int not_done_source=0;
|
||||
for (int i = 0; i < K; i++)
|
||||
{
|
||||
if (error_vec[i] == 1) not_done_source++;
|
||||
}
|
||||
// printf("not_done %d\n",not_done );
|
||||
// printf("not_done_source %d\n",not_done_source);
|
||||
|
||||
|
||||
unsigned int count_host = 0;
|
||||
unsigned int count_host_M = 0;
|
||||
|
||||
error = cudaMemcpyToSymbol ( count, (void *)(&count_host), sizeof(unsigned int), 0, cudaMemcpyHostToDevice);
|
||||
error = cudaMemcpyToSymbol ( count_M, (void *)(&count_host_M), sizeof(unsigned int), 0, cudaMemcpyHostToDevice);
|
||||
|
||||
|
||||
int i = 0;
|
||||
for (i = 1; i < 30; ++i)
|
||||
{
|
||||
//__global__ void frame_decode_int(int * received, int * pcm, int * error_vec,int * sync_vec,int packet_size,int max_row_weight,int K);
|
||||
frame_decode_int <<< M, blocksize , packet_size >>> (received_d, PCM, ERROR_VEC, SYNC_VEC, ps, w_f-2, K);
|
||||
error = cudaGetLastError();
|
||||
if (error != cudaSuccess) printf("3 %s\n", cudaGetErrorString(error));
|
||||
|
||||
// cudaDeviceSynchronize();
|
||||
//error = cudaMemcpyFromSymbol((void *)(&count_host), count, sizeof(int), 0, cudaMemcpyDeviceToHost);
|
||||
count_host=0;
|
||||
error = cudaMemcpyFromSymbol((void*)(&count_host), count, sizeof(unsigned int), 0, cudaMemcpyDeviceToHost);
|
||||
if (error != cudaSuccess) printf("10 %s\n", cudaGetErrorString(error));
|
||||
// printf("count host %d\n",count_host );
|
||||
|
||||
if (count_host == not_done_source)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
error = cudaMemcpyFromSymbol((void*)(&count_host_M), count_M, sizeof(unsigned int), 0, cudaMemcpyDeviceToHost);
|
||||
// printf("count host_M %d\n",count_host_M );
|
||||
if (count_host_M == M)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
count_host_M = 0;
|
||||
error = cudaMemcpyToSymbol ( count_M, (void *)(&count_host_M), sizeof(unsigned int), 0, cudaMemcpyHostToDevice);
|
||||
|
||||
|
||||
}
|
||||
// printf("iterace: %d\n",i);
|
||||
|
||||
|
||||
// cudaDeviceSynchronize();
|
||||
//cudaThreadSynchronize();
|
||||
|
||||
error = cudaMemcpy(error_vec, ERROR_VEC, (K + M) * sizeof(int), cudaMemcpyDeviceToHost);
|
||||
|
||||
|
||||
int a = 0;
|
||||
int fs = 0;
|
||||
for (int i = 0; i < K; i++)
|
||||
{
|
||||
if (error_vec[i] == 1) a++;
|
||||
}
|
||||
|
||||
// printf("UNDECODED: %d NOT DONE: %d DEKODOVANO: %d\n",a,not_done,not_done-a);
|
||||
if (a != 0)
|
||||
{
|
||||
*frame_size = 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&fs, received, 4);
|
||||
// printf("received size %d\n",fs );
|
||||
*frame_size = fs;
|
||||
}
|
||||
// printf("undecoded: %d, frame_size: %d, undecoded subtract: %d\n",a,fs,not_done-a );
|
||||
|
||||
cudaHostUnregister(received);
|
||||
// cudaFree(received_d);
|
||||
// cudaFree(pcm_d);
|
||||
// cudaFree(error_vec_d);
|
||||
// cudaFree(sync_vec_d);
|
||||
// cudaFree(params_d);
|
||||
|
||||
|
||||
// puts("END");
|
||||
return;
|
||||
|
||||
}
|
||||
__global__ void frame_encode_int_big(int *data, int *pcm,int param_k,int param_m,int w_f,int packet_size)
|
||||
{
|
||||
int ps = packet_size/sizeof(int);
|
||||
|
||||
int bx = blockIdx.x;
|
||||
int x = threadIdx.x;
|
||||
int offset;
|
||||
|
||||
|
||||
// printf("K: %d M: %d max_row_weight: %d packet_size: %d\n",param_k,param_m,max_row_weight,ps);
|
||||
extern __shared__ int parity_packet[];
|
||||
// int *parity_packet = data + (param_k + bx) * ps;
|
||||
|
||||
// if(x==0)printf("bx %d has parity packet at: %d,%d\n",bx,param_k*ps + bx*ps,param_k+bx );
|
||||
|
||||
|
||||
offset = x;
|
||||
while (offset < ps)
|
||||
{
|
||||
parity_packet[offset]=0;
|
||||
offset += blockDim.x;
|
||||
}
|
||||
// __syncthreads();
|
||||
|
||||
for ( int i = 0; i < w_f; i++)
|
||||
{
|
||||
int idx = pcm[bx * w_f + i];
|
||||
//printf ( "adept: %d\n", idx );
|
||||
|
||||
// if(x==0) printf ("block %d xor packet: %d\n",bx,idx);
|
||||
if (idx > -1 && idx < param_k)
|
||||
{
|
||||
|
||||
//xoring parity_packet ^ idx
|
||||
offset = x;
|
||||
while (offset < ps)
|
||||
{
|
||||
parity_packet[offset]^=data[idx*ps + offset];
|
||||
offset += blockDim.x;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// __syncthreads();
|
||||
offset = x;
|
||||
while (offset < ps)
|
||||
{
|
||||
data[(param_k + bx) * ps + offset]= parity_packet[offset];
|
||||
offset += blockDim.x;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
__global__ void frame_encode_int(int *data, int *pcm,int param_k,int param_m,int w_f,int packet_size)
|
||||
{
|
||||
int ps = packet_size/sizeof(int);
|
||||
|
||||
int bx = blockIdx.x;
|
||||
int offset = threadIdx.x;
|
||||
|
||||
|
||||
|
||||
// printf("K: %d M: %d max_row_weight: %d packet_size: %d\n",param_k,param_m,max_row_weight,ps);
|
||||
extern __shared__ int parity_packet[];
|
||||
// int *parity_packet = data + (param_k + bx) * ps;
|
||||
|
||||
// if(x==0)printf("bx %d has parity packet at: %d,%d\n",bx,param_k*ps + bx*ps,param_k+bx );
|
||||
|
||||
|
||||
// while (offset < ps)
|
||||
// {
|
||||
// parity_packet[offset]=0;
|
||||
// offset += blockDim.x;
|
||||
// }
|
||||
parity_packet[offset]=0;
|
||||
// __syncthreads();
|
||||
|
||||
for ( int i = 0; i < w_f; i++)
|
||||
{
|
||||
int idx = pcm[bx * w_f + i];
|
||||
//printf ( "adept: %d\n", idx );
|
||||
|
||||
// if(x==0) printf ("block %d xor packet: %d\n",bx,idx);
|
||||
if (idx > -1 && idx < param_k)
|
||||
{
|
||||
|
||||
//xoring parity_packet ^ idx
|
||||
// offset = x;
|
||||
// while (offset < ps)
|
||||
// {
|
||||
// parity_packet[offset]^=data[idx*ps + offset];
|
||||
// offset += blockDim.x;
|
||||
// }
|
||||
parity_packet[offset]^=data[idx*ps + offset];
|
||||
|
||||
}
|
||||
}
|
||||
// __syncthreads();
|
||||
// offset = x;
|
||||
// while (offset < ps)
|
||||
// {
|
||||
// data[(param_k + bx) * ps + offset]= parity_packet[offset];
|
||||
// offset += blockDim.x;
|
||||
// }
|
||||
|
||||
data[(param_k + bx) * ps + offset]= parity_packet[offset];
|
||||
// __syncthreads();
|
||||
|
||||
}
|
||||
|
||||
|
||||
__global__ void frame_decode_int(int *received, int *pcm, int *error_vec, int *sync_vec, int packet_size, int max_row_weight, int K)
|
||||
{
|
||||
//TITAN
|
||||
|
||||
__shared__ int undecoded;
|
||||
__shared__ int undecoded_index;
|
||||
__shared__ int ret;
|
||||
|
||||
|
||||
extern __shared__ int shared_parity_packet[];
|
||||
int w_f = max_row_weight + 2;
|
||||
int ps = packet_size;
|
||||
|
||||
int bx = blockIdx.x;
|
||||
int x = threadIdx.x;
|
||||
|
||||
int offset = 0;
|
||||
|
||||
if (x == 0)
|
||||
{
|
||||
ret = 0;
|
||||
undecoded = 0;
|
||||
undecoded_index = -1;
|
||||
for (int j = 0; j < w_f; j++)
|
||||
{
|
||||
int p = pcm[bx * w_f + j];
|
||||
//printf("%d %d %d\n",p, error_vec[p],x);
|
||||
if (p != -1 && error_vec[p] == 1)
|
||||
{
|
||||
undecoded++;
|
||||
undecoded_index = p;
|
||||
}
|
||||
}
|
||||
if (undecoded == 1)
|
||||
{
|
||||
ret = atomicCAS(sync_vec + undecoded_index, 1, 0);
|
||||
}
|
||||
|
||||
}
|
||||
__syncthreads();
|
||||
if (ret == 1)
|
||||
{
|
||||
|
||||
// if(x==0) printf("decoding %7d, bx %7d\n",undecoded_index,bx );
|
||||
offset = x;
|
||||
|
||||
while (offset < ps)
|
||||
{
|
||||
shared_parity_packet[offset]=0x0;
|
||||
offset += blockDim.x;
|
||||
}
|
||||
/*int zbyva = ps - offset;
|
||||
if (x < zbyva)
|
||||
{
|
||||
shared_parity_packet[x + offset] = 0;
|
||||
}*/
|
||||
|
||||
__syncthreads();
|
||||
// if(x==0) printf("decoding [%d]\n",undecoded_index);
|
||||
for (int j = 0; j < w_f; j++)
|
||||
{
|
||||
int index = pcm[bx * w_f + j];
|
||||
if (index != undecoded_index && index != -1)
|
||||
{
|
||||
offset = x;
|
||||
while ( offset < ps)
|
||||
{
|
||||
shared_parity_packet[offset] ^= received[index*ps + offset];
|
||||
offset += blockDim.x;
|
||||
}/*
|
||||
int zbyva = ps - offset;
|
||||
if (x < zbyva)
|
||||
{
|
||||
shared_parity_packet[x + offset] ^= received[(index * ps) + x + offset];
|
||||
}*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
__syncthreads();
|
||||
offset = x;
|
||||
|
||||
while ( offset < ps)
|
||||
{
|
||||
// *((int *)(received + (undecoded_index * ps) + 4*x + a)) = *((int *)(shared_parity_packet + a + 4 * x));
|
||||
received[(undecoded_index * ps) + offset] = shared_parity_packet[offset];
|
||||
offset += blockDim.x;
|
||||
}
|
||||
/*
|
||||
zbyva = ps - offset;
|
||||
if (x < zbyva)
|
||||
{
|
||||
received[(undecoded_index * ps) + x + offset] = shared_parity_packet[x + offset];
|
||||
}*/
|
||||
|
||||
|
||||
}
|
||||
if (x == 0 && ret == 1)
|
||||
{
|
||||
//error_vec[undecoded_index]=0;
|
||||
atomicCAS(error_vec + undecoded_index, 1, 0);
|
||||
// printf("node %d %d done\n",undecoded_index);
|
||||
}
|
||||
if (x == 0 && ret==1 && undecoded_index<K)
|
||||
{
|
||||
atomicAdd(&count, 1);
|
||||
}
|
||||
if (x == 0 && undecoded!=1 )
|
||||
{
|
||||
atomicAdd(&count_M, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
__global__ void frame_encode_staircase(int *data, int *pcm,int param_k,int param_m,int w_f,int packet_size)
|
||||
{
|
||||
int ps = packet_size/sizeof(int);
|
||||
|
||||
int x = threadIdx.x;
|
||||
|
||||
for (int index = param_k; index < param_k + param_m-1; index++)
|
||||
{
|
||||
|
||||
int offset = x;
|
||||
|
||||
while (offset < ps)
|
||||
{
|
||||
// *((int *)(data + (index+1)*ps + offset + intSize * x)) ^= *((int *)(data + index * ps + intSize * x + offset));
|
||||
data[(index+1)*ps + offset] ^= data[index*ps + offset];
|
||||
offset += blockDim.x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
|
||||
void test(void);
|
||||
|
||||
|
||||
struct coding_params {
|
||||
int num_lost;
|
||||
int k;
|
||||
@@ -10,7 +6,22 @@ struct coding_params {
|
||||
int max_row_weight;
|
||||
};
|
||||
|
||||
void gpu_encode ( char*, char*, int*, struct coding_params );
|
||||
void gpu_encode ( char* source_data,int* pc_matrix, struct coding_params * );
|
||||
|
||||
void gpu_decode ( char*, int*, char*, struct coding_params );
|
||||
void gpu_encode_upgrade (char* source_data,int *OUTBUF, int * PCM,int param_k,int param_m,int w_f,int packet_size ,int buf_size);
|
||||
|
||||
void gpu_decode (char * received,int * pcm,struct coding_params * params,int * error_vec,int * sync_vec,int undecoded,int * frame_size);
|
||||
|
||||
void gpu_decode_upgrade(char *data, int * PCM,int* SYNC_VEC,int* ERROR_VEC, int not_done, int *frame_size,int *, int*,int M,int K,int w_f,int buf_size,int packet_size);
|
||||
|
||||
__global__ void frame_encode(char * data,int * pcm,struct coding_params * params);
|
||||
|
||||
__global__ void frame_encode_int_big(int *data, int *pcm,int param_k,int param_m,int w_f,int packet_size);
|
||||
|
||||
__global__ void frame_encode_staircase(int *data, int *pcm,int param_k,int param_m,int w_f,int packet_size);
|
||||
|
||||
__global__ void frame_decode(char * received, int * pcm, int * error_vec,int * sync_vec,int packet_size,int max_row_weight,int K);
|
||||
|
||||
__global__ void frame_encode_int(int *data, int *pcm,int param_k,int param_m,int w_f,int packet_size);
|
||||
|
||||
__global__ void frame_decode_int(int * received, int * pcm, int * error_vec,int * sync_vec,int packet_size,int max_row_weight,int K);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Milan Kabat (), kabat@ics.muni.cz
|
||||
* Organization:
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
@@ -33,10 +33,28 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
char*
|
||||
char*
|
||||
xor_using_sse (char* source, char* dest, int packet_size)
|
||||
{
|
||||
//First, do as many 128-bit XORs as possible
|
||||
// int a = 0;
|
||||
// int II = packet_size % 16;
|
||||
// a=II*16;
|
||||
// // uint64_t* p1 = (uint64_t*) (source);
|
||||
// // uint64_t* p2 = (uint64_t*) (dest);
|
||||
|
||||
// __int128* p1 = (__int128*) (source);
|
||||
// __int128* p2 = (__int128*) (dest);
|
||||
|
||||
// for(int i=0; i<II; i++){
|
||||
// *p2 ^= *p1;
|
||||
// p2++;
|
||||
// p1++;
|
||||
// }
|
||||
// while(a<packet_size){
|
||||
// *(dest + a) ^= *(source+a);
|
||||
// a++;
|
||||
// }
|
||||
//First, do as many 128-bit XORs as possible
|
||||
int iter_bytes_16 = 0;
|
||||
int iter_bytes_4 = 0;
|
||||
int iter_bytes_1 = 0;
|
||||
@@ -46,151 +64,167 @@ xor_using_sse (char* source, char* dest, int packet_size)
|
||||
if ( iter_bytes_16 > 0)
|
||||
{
|
||||
|
||||
// printf ( "iter_bytes: %d\n", iter_bytes );
|
||||
__m128i* wrd_ptr = (__m128i *) source;
|
||||
__m128i* wrd_end = (__m128i *) (source + iter_bytes_16);
|
||||
__m128i* dst_ptr = (__m128i *) dest;
|
||||
// printf ( "iter_bytes: %d\n", iter_bytes );
|
||||
__m128i* wrd_ptr = (__m128i *) source;
|
||||
__m128i* wrd_end = (__m128i *) (source + iter_bytes_16);
|
||||
__m128i* dst_ptr = (__m128i *) dest;
|
||||
|
||||
// printf ( "wrd_ptr address: %p\n", wrd_ptr );
|
||||
do
|
||||
{
|
||||
__m128i xmm1 = _mm_loadu_si128(wrd_ptr);
|
||||
__m128i xmm2 = _mm_loadu_si128(dst_ptr);
|
||||
// printf ( "wrd_ptr address: %p\n", wrd_ptr );
|
||||
do
|
||||
{
|
||||
__m128i xmm1 = _mm_loadu_si128(wrd_ptr);
|
||||
__m128i xmm2 = _mm_loadu_si128(dst_ptr);
|
||||
|
||||
xmm1 = _mm_xor_si128(xmm1, xmm2); // XOR 4 32-bit words
|
||||
_mm_storeu_si128(dst_ptr, xmm1);
|
||||
++wrd_ptr;
|
||||
++dst_ptr;
|
||||
xmm1 = _mm_xor_si128(xmm1, xmm2); // XOR 4 32-bit words
|
||||
_mm_storeu_si128(dst_ptr, xmm1);
|
||||
++wrd_ptr;
|
||||
++dst_ptr;
|
||||
|
||||
} while (wrd_ptr < wrd_end);
|
||||
} while (wrd_ptr < wrd_end);
|
||||
}
|
||||
//Check, whether further XORing is necessary
|
||||
if ( iter_bytes_16 < packet_size )
|
||||
{
|
||||
char *mark_source = source + iter_bytes_16;
|
||||
char *mark_dest = dest + iter_bytes_16;
|
||||
char *mark_source = source + iter_bytes_16;
|
||||
char *mark_dest = dest + iter_bytes_16;
|
||||
|
||||
iter_bytes_4 = ((packet_size - iter_bytes_16)/4)*4;
|
||||
iter_bytes_4 = ((packet_size - iter_bytes_16)/4)*4;
|
||||
|
||||
for ( int i = 0; i < (packet_size - iter_bytes_16)/4; i++)
|
||||
{
|
||||
int *s = ((int*) mark_source) + i;
|
||||
int *d = ((int*) mark_dest) + i;
|
||||
*d ^= *s;
|
||||
}
|
||||
for ( int i = 0; i < (packet_size - iter_bytes_16)/4; i++)
|
||||
{
|
||||
int *s = ((int*) mark_source) + i;
|
||||
int *d = ((int*) mark_dest) + i;
|
||||
*d ^= *s;
|
||||
}
|
||||
|
||||
mark_source += iter_bytes_4;
|
||||
mark_dest += iter_bytes_4;
|
||||
mark_source += iter_bytes_4;
|
||||
mark_dest += iter_bytes_4;
|
||||
|
||||
iter_bytes_1 = packet_size - iter_bytes_16 - iter_bytes_4;
|
||||
iter_bytes_1 = packet_size - iter_bytes_16 - iter_bytes_4;
|
||||
|
||||
for ( int i = 0; i < iter_bytes_1; i++)
|
||||
{
|
||||
*(mark_dest + i) ^= *(mark_source+i);
|
||||
}
|
||||
for ( int i = 0; i < iter_bytes_1; i++)
|
||||
{
|
||||
*(mark_dest + i) ^= *(mark_source+i);
|
||||
}
|
||||
}
|
||||
|
||||
// printf ( "XORed: %d bytes using SSE, %d bytes as ints and %d bytes byte-per-byte.\n",
|
||||
// iter_bytes_16, iter_bytes_4, iter_bytes_1);
|
||||
// printf ( "XORed: %d bytes using SSE, %d bytes as ints and %d bytes byte-per-byte.\n",iter_bytes_16, iter_bytes_4, iter_bytes_1);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void
|
||||
void *
|
||||
LDGM_session_cpu::alloc_buf (int buf_size)
|
||||
{
|
||||
void *out_buf = aligned_malloc(buf_size, 16);
|
||||
if (!out_buf)
|
||||
{
|
||||
printf ( "Unable to allocate aligned memory\n" );
|
||||
|
||||
}
|
||||
return out_buf;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
LDGM_session_cpu::encode ( char* data_ptr, char* parity_ptr )
|
||||
{
|
||||
// start encoding
|
||||
// printf ( "packet_size: %d\n", this->packet_size );
|
||||
// printf ( "packet_size: %d\n", this->packet_size );
|
||||
|
||||
void *ppacket;
|
||||
char *parity_packet;
|
||||
for ( int m = 0; m < param_m; ++m) {
|
||||
|
||||
ppacket = aligned_malloc(packet_size, 16);
|
||||
|
||||
if (!ppacket)
|
||||
{
|
||||
printf ( "Error while using posix_memalign\n" );
|
||||
return;
|
||||
}
|
||||
ppacket = aligned_malloc(packet_size, 16);
|
||||
|
||||
if (!ppacket)
|
||||
{
|
||||
printf ( "Error while using posix_memalign\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// printf ( "m: %d\n", m );
|
||||
memset(ppacket, 0, packet_size);
|
||||
parity_packet = (char*)ppacket;
|
||||
memset(ppacket, 0, packet_size);
|
||||
parity_packet = (char*)ppacket;
|
||||
// printf ( "max w: %d\n", max_row_weight );
|
||||
//Find out which packets to XOR
|
||||
for ( int k = 0; k < max_row_weight+2; ++k) {
|
||||
int idx = pcm[m*(max_row_weight+2) + k];
|
||||
//Find out which packets to XOR
|
||||
for ( int k = 0; k < max_row_weight+2; ++k) {
|
||||
int idx = pcm[m*(max_row_weight+2) + k];
|
||||
// printf ( "adept: %d\n", idx );
|
||||
if (idx > -1 && idx < param_k) {
|
||||
if (idx > -1 && idx < param_k) {
|
||||
// printf ( "xoring idx: %d\n", idx );
|
||||
char *ptr = data_ptr + idx*packet_size;
|
||||
parity_packet = xor_using_sse(ptr, parity_packet, packet_size);
|
||||
}
|
||||
}
|
||||
char *ptr = data_ptr + idx*packet_size;
|
||||
parity_packet = xor_using_sse(ptr, parity_packet, packet_size);
|
||||
}
|
||||
}
|
||||
|
||||
//Apply inverted staircase matrix
|
||||
if( m > 0) {
|
||||
char *prev_parity = parity_ptr + (m-1)*packet_size;
|
||||
parity_packet = xor_using_sse(prev_parity, parity_packet, packet_size);
|
||||
}
|
||||
//Apply inverted staircase matrix
|
||||
if( m > 0) {
|
||||
char *prev_parity = parity_ptr + (m-1)*packet_size;
|
||||
parity_packet = xor_using_sse(prev_parity, parity_packet, packet_size);
|
||||
}
|
||||
|
||||
|
||||
//Add the new parity packet to overall parity
|
||||
memcpy ( parity_ptr + m*packet_size, parity_packet, packet_size );
|
||||
aligned_free(ppacket);
|
||||
//Add the new parity packet to overall parity
|
||||
memcpy ( parity_ptr + m*packet_size, parity_packet, packet_size );
|
||||
aligned_free(ppacket);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ;
|
||||
} /* ----- end of method LDGM_session_cpu::encode ----- */
|
||||
|
||||
void
|
||||
void
|
||||
LDGM_session_cpu::free_out_buf ( char *buf)
|
||||
{
|
||||
if ( buf != NULL )
|
||||
aligned_free(buf);
|
||||
aligned_free(buf);
|
||||
}
|
||||
void
|
||||
void
|
||||
LDGM_session_cpu::encode_naive ( char* data_ptr, char* parity_ptr )
|
||||
{
|
||||
// start encoding
|
||||
|
||||
void *ppacket;
|
||||
char *parity_packet;
|
||||
|
||||
|
||||
for ( int m = 0; m < param_m; ++m) {
|
||||
|
||||
ppacket = aligned_malloc(packet_size, 16);
|
||||
if (!ppacket)
|
||||
{
|
||||
printf ( "Error while using posix_memalign\n" );
|
||||
return;
|
||||
}
|
||||
memset(ppacket, 0, packet_size);
|
||||
parity_packet = (char*)ppacket;
|
||||
|
||||
//Find out which packets to XOR
|
||||
for ( int k = 0; k < max_row_weight+2; ++k) {
|
||||
int idx = pcm[m*(max_row_weight+2) + k];
|
||||
if (idx > -1 && idx < param_k) {
|
||||
char *ptr = data_ptr + idx*packet_size;
|
||||
ppacket = aligned_malloc(packet_size, 16);
|
||||
if (!ppacket)
|
||||
{
|
||||
printf ( "Error while using posix_memalign\n" );
|
||||
return;
|
||||
}
|
||||
memset(ppacket, 0, packet_size);
|
||||
parity_packet = (char*)ppacket;
|
||||
|
||||
//Find out which packets to XOR
|
||||
for ( int k = 0; k < max_row_weight+2; ++k) {
|
||||
int idx = pcm[m*(max_row_weight+2) + k];
|
||||
if (idx > -1 && idx < param_k) {
|
||||
char *ptr = data_ptr + idx*packet_size;
|
||||
// parity_packet = xor_using_sse(ptr, parity_packet, packet_size);
|
||||
for ( int i = 0; i < packet_size; i++)
|
||||
parity_packet[i] ^= *(ptr+i);
|
||||
}
|
||||
}
|
||||
for ( int i = 0; i < packet_size; i++)
|
||||
parity_packet[i] ^= *(ptr+i);
|
||||
}
|
||||
}
|
||||
|
||||
//Apply inverted staircase matrix
|
||||
if( m > 0) {
|
||||
char *prev_parity = parity_ptr + (m-1)*packet_size;
|
||||
//Apply inverted staircase matrix
|
||||
if( m > 0) {
|
||||
char *prev_parity = parity_ptr + (m-1)*packet_size;
|
||||
// parity_packet = xor_using_sse(prev_parity, parity_packet, packet_size);
|
||||
for ( int i = 0; i < packet_size; i++)
|
||||
parity_packet[i] ^= *(prev_parity+i);
|
||||
}
|
||||
for ( int i = 0; i < packet_size; i++)
|
||||
parity_packet[i] ^= *(prev_parity+i);
|
||||
}
|
||||
|
||||
|
||||
//Add the new parity packet to overall parity
|
||||
memcpy ( parity_ptr + m*packet_size, parity_packet, packet_size );
|
||||
aligned_free(ppacket);
|
||||
//Add the new parity packet to overall parity
|
||||
memcpy ( parity_ptr + m*packet_size, parity_packet, packet_size );
|
||||
aligned_free(ppacket);
|
||||
|
||||
}
|
||||
return ;
|
||||
@@ -198,11 +232,16 @@ LDGM_session_cpu::encode_naive ( char* data_ptr, char* parity_ptr )
|
||||
|
||||
void iterate ( Tanner_graph *g);
|
||||
|
||||
char*
|
||||
LDGM_session_cpu::decode_frame ( char* received, int buf_size, int* frame_size,
|
||||
std::map<int, int> valid_data )
|
||||
char*
|
||||
LDGM_session_cpu::decode_frame ( char* received, int buf_size, int* frame_size,
|
||||
std::map<int, int> valid_data )
|
||||
{
|
||||
// printf ( "buf_size: %d\n", buf_size );
|
||||
|
||||
struct timeval t0,t1;
|
||||
gettimeofday(&t0, 0);
|
||||
|
||||
|
||||
Tanner_graph graph;
|
||||
|
||||
int p_size = buf_size/(param_m+param_k);
|
||||
@@ -223,16 +262,16 @@ LDGM_session_cpu::decode_frame ( char* received, int buf_size, int* frame_size,
|
||||
|
||||
//one variable node per each data packet in block K
|
||||
for ( i = 0; i < param_k; ++i )
|
||||
graph.add_node(Node::variable_node, index++, received + i*p_size);
|
||||
graph.add_node(Node::variable_node, index++, received + i*p_size);
|
||||
|
||||
//one variable node per each parity packet in block M
|
||||
for ( i = 0; i < param_m; ++i)
|
||||
graph.add_node(Node::variable_node, index++, received + (i + param_k)*p_size);
|
||||
graph.add_node(Node::variable_node, index++, received + (i + param_k)*p_size);
|
||||
|
||||
//one constraint node per each row of generation matrix
|
||||
for ( i = 0; i < param_m; ++i)
|
||||
graph.add_node(Node::constraint_node, index++, NULL);
|
||||
|
||||
graph.add_node(Node::constraint_node, index++, NULL);
|
||||
|
||||
create_edges(&graph);
|
||||
|
||||
// printf("Graph created in: %.3f s\n", t);
|
||||
@@ -260,93 +299,93 @@ LDGM_session_cpu::decode_frame ( char* received, int buf_size, int* frame_size,
|
||||
map<int,int>::iterator map_it;
|
||||
|
||||
if ( valid_data.size() != 0 )
|
||||
{
|
||||
for ( map_it = valid_data.begin(); map_it != valid_data.end(); )
|
||||
{
|
||||
int start = map_it->first;
|
||||
int length = map_it->second;
|
||||
while ( start + length == (++map_it)->first )
|
||||
length += map_it->second;
|
||||
merged_intervals.insert ( pair<int, int> (start, length) );
|
||||
}
|
||||
{
|
||||
for ( map_it = valid_data.begin(); map_it != valid_data.end(); )
|
||||
{
|
||||
int start = map_it->first;
|
||||
int length = map_it->second;
|
||||
while ( start + length == (++map_it)->first )
|
||||
length += map_it->second;
|
||||
merged_intervals.insert ( pair<int, int> (start, length) );
|
||||
}
|
||||
}
|
||||
/* printf ( "Valid data: \n" );
|
||||
* for ( map_it = valid_data.begin(); map_it != valid_data.end(); ++map_it)
|
||||
* {
|
||||
* printf ( "|%d-%d| ", map_it->first, map_it->second );
|
||||
* }
|
||||
* printf ( "\n" );
|
||||
*
|
||||
* printf ( "Merged intervals: \n" );
|
||||
* for ( map_it = merged_intervals.begin(); map_it != merged_intervals.end(); ++map_it)
|
||||
* {
|
||||
* printf ( "|%d-%d| ", map_it->first, map_it->second );
|
||||
* }
|
||||
* printf ( "\n" );
|
||||
*
|
||||
*/
|
||||
/* printf ( "Valid data: \n" );
|
||||
* for ( map_it = valid_data.begin(); map_it != valid_data.end(); ++map_it)
|
||||
* {
|
||||
* printf ( "|%d-%d| ", map_it->first, map_it->second );
|
||||
* }
|
||||
* printf ( "\n" );
|
||||
*
|
||||
* printf ( "Merged intervals: \n" );
|
||||
* for ( map_it = merged_intervals.begin(); map_it != merged_intervals.end(); ++map_it)
|
||||
* {
|
||||
* printf ( "|%d-%d| ", map_it->first, map_it->second );
|
||||
* }
|
||||
* printf ( "\n" );
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
map<int, Node>::iterator it;
|
||||
if ( merged_intervals.size() != 0)
|
||||
{
|
||||
it = graph.nodes.find(0);
|
||||
while (it != graph.nodes.find(param_k+param_m)) {
|
||||
(*it).second.setDone(false);
|
||||
int node_offset = (*it).second.getDataPtr() - received;
|
||||
it = graph.nodes.find(0);
|
||||
while (it != graph.nodes.find(param_k+param_m)) {
|
||||
(*it).second.setDone(false);
|
||||
int node_offset = (*it).second.getDataPtr() - received;
|
||||
// printf ( "offset: %d\n", node_offset );
|
||||
|
||||
map_it = merged_intervals.begin();
|
||||
//Find the offset in valid data which is equal, or the first offset which is
|
||||
//lower than node offset
|
||||
bool found = false;
|
||||
while ( (map_it->first <= node_offset) && map_it != merged_intervals.end() )
|
||||
{
|
||||
map_it++;
|
||||
found = true;
|
||||
}
|
||||
if ( map_it->first > 0 )
|
||||
map_it--;
|
||||
map_it = merged_intervals.begin();
|
||||
//Find the offset in valid data which is equal, or the first offset which is
|
||||
//lower than node offset
|
||||
bool found = false;
|
||||
while ( (map_it->first <= node_offset) && map_it != merged_intervals.end() )
|
||||
{
|
||||
map_it++;
|
||||
found = true;
|
||||
}
|
||||
if ( map_it->first > 0 )
|
||||
map_it--;
|
||||
|
||||
//Next, find out if some interval covers this symbol
|
||||
if ( found && (map_it->first + map_it->second) >=
|
||||
(node_offset + p_size) )
|
||||
{
|
||||
(*it).second.setDone(true);
|
||||
//Next, find out if some interval covers this symbol
|
||||
if ( found && (map_it->first + map_it->second) >=
|
||||
(node_offset + p_size) )
|
||||
{
|
||||
(*it).second.setDone(true);
|
||||
// printf ( "setting node %d with offset %d and size %d as done\n", it->first,
|
||||
// node_offset, p_size);
|
||||
}
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
int not_done = 0;
|
||||
for ( it = graph.nodes.begin(); it != graph.nodes.find(param_k); it++)
|
||||
{
|
||||
if ( !it->second.isDone())
|
||||
{
|
||||
memset(it->second.getDataPtr(), 0, p_size);
|
||||
if ( !it->second.isDone())
|
||||
{
|
||||
memset(it->second.getDataPtr(), 0, p_size);
|
||||
// printf ( "resetting node: %d\n", it->first );
|
||||
not_done++;
|
||||
}
|
||||
not_done++;
|
||||
}
|
||||
}
|
||||
// printf ( "not done: %d\n", not_done );
|
||||
/* srand(time(NULL));
|
||||
* for ( int j = 0; j < 100; j++)
|
||||
* {
|
||||
* it = graph.nodes.find(rand()%(param_k+param_m));
|
||||
* (*it).second.setDone(false);
|
||||
* }
|
||||
*/
|
||||
/* srand(time(NULL));
|
||||
* for ( int j = 0; j < 100; j++)
|
||||
* {
|
||||
* it = graph.nodes.find(rand()%(param_k+param_m));
|
||||
* (*it).second.setDone(false);
|
||||
* }
|
||||
*/
|
||||
int iter = 0;
|
||||
|
||||
while ( needs_decoding(&graph) && iter < 4) {
|
||||
// printf ( "iteratin\n" );
|
||||
iterate(&graph);
|
||||
iter++;
|
||||
}
|
||||
iterate(&graph);
|
||||
iter++;
|
||||
}
|
||||
|
||||
// printf("decoding process: %.3f s\n", t);
|
||||
|
||||
@@ -355,9 +394,9 @@ LDGM_session_cpu::decode_frame ( char* received, int buf_size, int* frame_size,
|
||||
int undecoded = 0;
|
||||
it = graph.nodes.find(0);
|
||||
while ( it != graph.nodes.find(param_k) ) {
|
||||
if (!(*it).second.isDone())
|
||||
undecoded++;
|
||||
++it;
|
||||
if (!(*it).second.isDone())
|
||||
undecoded++;
|
||||
++it;
|
||||
}
|
||||
// printf ( "Number of not recovered data packets: %d\n", undecoded );
|
||||
|
||||
@@ -365,23 +404,33 @@ LDGM_session_cpu::decode_frame ( char* received, int buf_size, int* frame_size,
|
||||
|
||||
if ( undecoded == 0 )
|
||||
{
|
||||
union int_bytes {
|
||||
unsigned int number;
|
||||
unsigned char bytes[4];
|
||||
};
|
||||
union int_bytes fs;
|
||||
memcpy(&(fs.bytes), received, 4);
|
||||
*frame_size = fs.number;
|
||||
union int_bytes {
|
||||
unsigned int number;
|
||||
unsigned char bytes[4];
|
||||
};
|
||||
union int_bytes fs;
|
||||
memcpy(&(fs.bytes), received, 4);
|
||||
*frame_size = fs.number;
|
||||
}
|
||||
else
|
||||
*frame_size = 0;
|
||||
*frame_size = 0;
|
||||
|
||||
|
||||
return received+4;
|
||||
} /* ----- end of method LDGM_session_cpu::decode ----- */
|
||||
gettimeofday(&t1,0);
|
||||
long elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec;
|
||||
//printf("time: %e\n",elapsed/1000.0 );
|
||||
this->elapsed_sum2+=elapsed/1000.0;
|
||||
this->no_frames2++;
|
||||
|
||||
if(this->no_frames==150){
|
||||
//printf("TIME: %f ms\n",this->elapsed_sum/(double)this->no_frames );
|
||||
}
|
||||
|
||||
return received + LDGM_session::HEADER_SIZE;
|
||||
} /* ----- end ofmethod LDGM_session_cpu::decode ----- */
|
||||
|
||||
|
||||
void
|
||||
void
|
||||
LDGM_session_cpu::iterate ( Tanner_graph *graph )
|
||||
{
|
||||
map<int, Node>::iterator it_c;
|
||||
@@ -394,64 +443,64 @@ LDGM_session_cpu::iterate ( Tanner_graph *graph )
|
||||
|
||||
//iterate through constraint nodes
|
||||
while ( it_c != graph->nodes.end() ) {
|
||||
//iterate the node's neighbours to find out how many of them are not decoded
|
||||
map<int, Node>::iterator it_v;
|
||||
for(vector<int>::iterator j = it_c->second.neighbours.begin();
|
||||
j != it_c->second.neighbours.end(); ++j) {
|
||||
it_v = graph->nodes.find(*j);
|
||||
if ( !it_v->second.isDone() )
|
||||
vec.push_back(*j);
|
||||
}
|
||||
//iterate the node's neighbours to find out how many of them are not decoded
|
||||
map<int, Node>::iterator it_v;
|
||||
for(vector<int>::iterator j = it_c->second.neighbours.begin();
|
||||
j != it_c->second.neighbours.end(); ++j) {
|
||||
it_v = graph->nodes.find(*j);
|
||||
if ( !it_v->second.isDone() )
|
||||
vec.push_back(*j);
|
||||
}
|
||||
// printf ( "node %d has %d undecoded neighbours\n", it_c->first, vec.size() );
|
||||
|
||||
//we can restore the missing packet
|
||||
if ( vec.size() == 1)
|
||||
{
|
||||
int r_index = vec.front();
|
||||
//we can restore the missing packet
|
||||
if ( vec.size() == 1)
|
||||
{
|
||||
int r_index = vec.front();
|
||||
|
||||
// if ( r_index == 0 )
|
||||
// {
|
||||
// printf ( "repairing first block\n" );
|
||||
// }
|
||||
it_v = graph->nodes.find(r_index);
|
||||
memset(it_v->second.getDataPtr(), 0, packet_size);
|
||||
char *r_data = it_v->second.getDataPtr();
|
||||
//find other nodes connected to this constraint node and XOR their values
|
||||
int count = 0;
|
||||
for(vector<int>::iterator j = it_c->second.neighbours.begin();
|
||||
j != it_c->second.neighbours.end(); ++j)
|
||||
{
|
||||
if ( *j != r_index )
|
||||
{
|
||||
it_v = graph->nodes.find(r_index);
|
||||
memset(it_v->second.getDataPtr(), 0, packet_size);
|
||||
char *r_data = it_v->second.getDataPtr();
|
||||
//find other nodes connected to this constraint node and XOR their values
|
||||
int count = 0;
|
||||
for(vector<int>::iterator j = it_c->second.neighbours.begin();
|
||||
j != it_c->second.neighbours.end(); ++j)
|
||||
{
|
||||
if ( *j != r_index )
|
||||
{
|
||||
// printf ( "decode, packet_size: %d\n", packet_size );
|
||||
char *g_data = (graph->nodes.find(*j))->second.getDataPtr();
|
||||
//XOR
|
||||
xor_using_sse(g_data, r_data, packet_size);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
/* //validate recovered packet
|
||||
* for ( int i = 0; i < param_k; ++i) {
|
||||
* if(!memcmp(r_data, lost_ptr + i*packet_size, packet_size)) {
|
||||
* printf ( "packet ok\n" );
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
if ( count > 0 )
|
||||
it_v->second.setDone(true);
|
||||
recovered++;
|
||||
/* printf ( "restored data: \n" );
|
||||
* for ( int i = 0; i < packet_size; ++i)
|
||||
* printf ( "%2d|", (unsigned char)(*(it_v->second.getDataPtr() + i)) );
|
||||
* printf ( "---\n" );
|
||||
*/
|
||||
char *g_data = (graph->nodes.find(*j))->second.getDataPtr();
|
||||
//XOR
|
||||
xor_using_sse(g_data, r_data, packet_size);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
/* //validate recovered packet
|
||||
* for ( int i = 0; i < param_k; ++i) {
|
||||
* if(!memcmp(r_data, lost_ptr + i*packet_size, packet_size)) {
|
||||
* printf ( "packet ok\n" );
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
if ( count > 0 )
|
||||
it_v->second.setDone(true);
|
||||
recovered++;
|
||||
/* printf ( "restored data: \n" );
|
||||
* for ( int i = 0; i < packet_size; ++i)
|
||||
* printf ( "%2d|", (unsigned char)(*(it_v->second.getDataPtr() + i)) );
|
||||
* printf ( "---\n" );
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
vec.clear();
|
||||
}
|
||||
vec.clear();
|
||||
|
||||
++it_c;
|
||||
++it_c;
|
||||
}
|
||||
// printf ( "recovered: %d\n", recovered );
|
||||
|
||||
|
||||
@@ -33,8 +33,14 @@ class LDGM_session_cpu : public LDGM_session
|
||||
{
|
||||
public:
|
||||
/* ==================== LIFECYCLE ======================================= */
|
||||
LDGM_session_cpu () { } /* constructor */
|
||||
~LDGM_session_cpu () { } /* constructor */
|
||||
LDGM_session_cpu () {
|
||||
printf("CPU LDGM in progress .... \n");
|
||||
elapsed_sum=0.0;
|
||||
no_frames=0;
|
||||
} /* constructor */
|
||||
~LDGM_session_cpu () {
|
||||
printf("LDGM TIME CPU: %f ms\n",this->elapsed_sum2/(double)this->no_frames2 );
|
||||
} /* constructor */
|
||||
|
||||
void
|
||||
encode (char*, char*);
|
||||
@@ -52,11 +58,16 @@ class LDGM_session_cpu : public LDGM_session
|
||||
void
|
||||
free_out_buf (char *buf);
|
||||
|
||||
void *
|
||||
alloc_buf(int size);
|
||||
|
||||
protected:
|
||||
/* ==================== DATA MEMBERS ======================================= */
|
||||
|
||||
private:
|
||||
/* ==================== DATA MEMBERS ======================================= */
|
||||
double elapsed_sum;
|
||||
long no_frames;
|
||||
|
||||
}; /* ----- end of class LDGM_session_cpu ----- */
|
||||
|
||||
|
||||
@@ -3,95 +3,379 @@
|
||||
*
|
||||
* Filename: ldgm-session-gpu.cpp
|
||||
*
|
||||
* Description:
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 04/20/2012 02:21:11 PM
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Milan Kabat (), kabat@ics.muni.cz
|
||||
* Organization:
|
||||
* Authors: Milan Kabat (kabat@ics.muni.cz), Vojtech David (374572@mail.muni.cz)
|
||||
* Organization: FI MUNI
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <set>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <emmintrin.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
#include "ldgm-session-gpu.h"
|
||||
#include "ldgm-session-cpu.h"
|
||||
#include "gpu.cuh"
|
||||
#include "timer-util.h"
|
||||
|
||||
char*
|
||||
xor_sse (char* source, char* dest, int packet_size)
|
||||
{
|
||||
__m128i* wrd_ptr = (__m128i *) source;
|
||||
__m128i* wrd_end = (__m128i *) (source + packet_size);
|
||||
__m128i* dst_ptr = (__m128i *) dest;
|
||||
#include "tanner.h"
|
||||
|
||||
do
|
||||
{
|
||||
__m128i xmm1 = _mm_load_si128(wrd_ptr);
|
||||
__m128i xmm2 = _mm_load_si128(dst_ptr);
|
||||
#include "crypto/crc.h"
|
||||
|
||||
xmm1 = _mm_xor_si128(xmm1, xmm2); // XOR 4 32-bit words
|
||||
_mm_store_si128(dst_ptr, xmm1);
|
||||
++wrd_ptr;
|
||||
++dst_ptr;
|
||||
// static int * error_vec;
|
||||
// static int * sync_vec;
|
||||
|
||||
} while (wrd_ptr < wrd_end);
|
||||
// static int * ERROR_VEC;
|
||||
// static int * SYNC_VEC;
|
||||
|
||||
return dest;
|
||||
|
||||
// static int * PCM;
|
||||
|
||||
LDGM_session_gpu::LDGM_session_gpu() {
|
||||
printf("GPU LDGM in progress .... \n");
|
||||
|
||||
error_vec=NULL;
|
||||
sync_vec=NULL;
|
||||
|
||||
ERROR_VEC=NULL;
|
||||
SYNC_VEC=NULL;
|
||||
|
||||
PCM=NULL;
|
||||
|
||||
OUTBUF_SIZE=0;
|
||||
OUTBUF=NULL;
|
||||
}
|
||||
|
||||
void LDGM_session_gpu::encode ( char* source_data, char* parity )
|
||||
{
|
||||
struct coding_params params;
|
||||
params.k = param_k;
|
||||
params.m = param_m;
|
||||
params.packet_size = packet_size;
|
||||
params.max_row_weight = max_row_weight;
|
||||
|
||||
gpu_encode ( source_data, parity, this->pcm, params );
|
||||
|
||||
//apply inverted staircase matrix
|
||||
// char parity_packet[packet_size];
|
||||
// timespec start, end;
|
||||
// clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
for ( int i = 1; i < param_m; i++)
|
||||
{
|
||||
char *prev_parity = parity + (i - 1)*packet_size;
|
||||
xor_sse ( prev_parity, parity + i*packet_size, packet_size);
|
||||
LDGM_session_gpu::~LDGM_session_gpu () {
|
||||
printf("LDGM TIME GPU: %f ms\n",this->elapsed_sum2/(double)this->no_frames2 );
|
||||
cudaError_t error;
|
||||
while (!freeBuffers.empty()) {
|
||||
char *buf = freeBuffers.front();
|
||||
freeBuffers.pop();
|
||||
error = cudaFreeHost(buf);
|
||||
if(error != cudaSuccess)printf("memoryPool: %s\n", cudaGetErrorString(error));
|
||||
}
|
||||
// clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
|
||||
/* Timer_util t;
|
||||
* std::ofstream out;
|
||||
* out.open(data_fname, std::ios::out | std::ios::app);
|
||||
*
|
||||
* out << t.elapsed_time_us(start,end) << ";";
|
||||
*
|
||||
* out.close();
|
||||
*/
|
||||
error = cudaFreeHost(error_vec);
|
||||
cuda_check_error("error_vec");
|
||||
error = cudaFreeHost(sync_vec);
|
||||
cuda_check_error("sync_vec");
|
||||
|
||||
|
||||
// cudaFree(OUTBUF);
|
||||
cudaFree(PCM);
|
||||
|
||||
}
|
||||
cudaFree(ERROR_VEC);
|
||||
cudaFree(SYNC_VEC);
|
||||
} /* destructor */
|
||||
|
||||
void
|
||||
LDGM_session_gpu::decode ( char* received, int* error_vec, int num_lost)
|
||||
void *LDGM_session_gpu::alloc_buf (int buf_size)
|
||||
{
|
||||
struct coding_params params;
|
||||
params.num_lost = num_lost;
|
||||
params.k = param_k;
|
||||
params.m = param_m;
|
||||
params.packet_size = packet_size;
|
||||
params.max_row_weight = max_row_weight;
|
||||
// printf("cudaHostAlloc %d %d\n",this->indexMemoryPool,index);
|
||||
// printf("buf_size %d, bufferSize %d\n",buf_size,this->memoryPoolSize[index] );
|
||||
while (!freeBuffers.empty()) {
|
||||
char *buf = freeBuffers.front();
|
||||
freeBuffers.pop();
|
||||
|
||||
if (buf_size <= (int) bufferSizes[buf]) {
|
||||
return buf;
|
||||
} else {
|
||||
cudaFreeHost(buf);
|
||||
cuda_check_error("cudaFreeHost");
|
||||
bufferSizes.erase(buf);
|
||||
}
|
||||
}
|
||||
|
||||
char *buf;
|
||||
cudaHostAlloc(&buf, buf_size, cudaHostAllocDefault);
|
||||
// cudaHostAlloc(&this->memoryPool[index], buf_size, cudaHostAllocMapped);
|
||||
cuda_check_error("cudaHostAlloc");
|
||||
bufferSizes[buf] = buf_size;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void LDGM_session_gpu::free_out_buf ( char *buf)
|
||||
{
|
||||
if ( buf != NULL ) {
|
||||
freeBuffers.push(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void LDGM_session_gpu::encode ( char *source_data, char *parity )
|
||||
{
|
||||
assert(parity == source_data+param_k*get_packet_size());
|
||||
|
||||
int w_f = max_row_weight + 2;
|
||||
int buf_size = (param_k + param_m) * packet_size;
|
||||
|
||||
cudaError_t error;
|
||||
|
||||
// error = cudaHostGetDevicePointer( &(out_buf_d), source_data, 0);
|
||||
// cuda_check_error("out_buf_d");
|
||||
|
||||
if(OUTBUF==NULL){
|
||||
// puts("cudaMalloc");
|
||||
cudaMalloc(&OUTBUF,buf_size);
|
||||
OUTBUF_SIZE=buf_size;
|
||||
}
|
||||
if(buf_size>OUTBUF_SIZE){
|
||||
// puts("cudaMalloc");
|
||||
cudaFree(OUTBUF);
|
||||
cudaMalloc(&OUTBUF,buf_size);
|
||||
OUTBUF_SIZE=buf_size;
|
||||
}
|
||||
|
||||
cudaMemcpy(OUTBUF,source_data,buf_size,cudaMemcpyHostToDevice);
|
||||
cuda_check_error("memcpy OUTBUF");
|
||||
|
||||
|
||||
|
||||
if (PCM == NULL)
|
||||
{
|
||||
// puts("cudaMalloc");
|
||||
error = cudaMalloc(&PCM, w_f * param_m * sizeof(int));
|
||||
if(error != cudaSuccess)printf("7CUDA error: %s\n", cudaGetErrorString(error));
|
||||
|
||||
error = cudaMemcpy(PCM, pcm, w_f * param_m * sizeof(int), cudaMemcpyHostToDevice);
|
||||
if(error != cudaSuccess)printf("8CUDA error: %s\n", cudaGetErrorString(error));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
gpu_encode_upgrade(source_data,OUTBUF , PCM, param_k, param_m, w_f, packet_size, buf_size);
|
||||
|
||||
// puts("end");
|
||||
|
||||
}
|
||||
|
||||
char *LDGM_session_gpu::decode_frame ( char *received_data, int buf_size, int *frame_size, std::map<int, int> valid_data )
|
||||
{
|
||||
char *received = received_data;
|
||||
|
||||
struct timeval t0, t1;
|
||||
gettimeofday(&t0, 0);
|
||||
|
||||
|
||||
int p_size = buf_size / (param_m + param_k);
|
||||
// printf("%d p_size K: %d, M: %d, buf_size: %d, max_row_weight: %d \n",p_size,param_k,param_m,buf_size,max_row_weight);
|
||||
|
||||
//We need to merge intervals in the valid data vector
|
||||
std::map <int, int> merged_intervals;
|
||||
std::map<int, int>::iterator map_it;
|
||||
|
||||
if ( valid_data.size() != 0 )
|
||||
{
|
||||
for ( map_it = valid_data.begin(); map_it != valid_data.end(); )
|
||||
{
|
||||
int start = map_it->first;
|
||||
int length = map_it->second;
|
||||
while ( start + length == (++map_it)->first )
|
||||
length += map_it->second;
|
||||
merged_intervals.insert ( std::pair<int, int> (start, length) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
cudaError_t error;
|
||||
if (error_vec == NULL)
|
||||
{
|
||||
cudaHostAlloc(&error_vec, sizeof(int) * (param_k + param_m), cudaHostAllocDefault );
|
||||
cuda_check_error("error_vec");
|
||||
}
|
||||
|
||||
if (sync_vec == NULL)
|
||||
{
|
||||
cudaHostAlloc(&sync_vec, sizeof(int) * (param_k + param_m), cudaHostAllocDefault );
|
||||
cuda_check_error("sync_vec");
|
||||
}
|
||||
|
||||
// error_vec= (int* ) malloc(sizeof(int)*(param_k+param_m));
|
||||
memset(error_vec, 0, sizeof(int) * (param_k + param_m));
|
||||
// sync_vec= (int* ) malloc(sizeof(int)*(param_k+param_m));
|
||||
memset(sync_vec, 0, sizeof(int) * (param_k + param_m));
|
||||
int not_done = 0;
|
||||
|
||||
if ( merged_intervals.size() != 0
|
||||
)
|
||||
{
|
||||
|
||||
for (int i = 0; i < param_k + param_m; i++)
|
||||
{
|
||||
int node_offset = i * p_size;
|
||||
|
||||
map_it = merged_intervals.begin();
|
||||
|
||||
bool found = false;
|
||||
while ( (map_it->first <= node_offset) && map_it != merged_intervals.end() )
|
||||
{
|
||||
map_it++;
|
||||
found = true;
|
||||
}
|
||||
if ( map_it->first > 0 ) map_it--;
|
||||
|
||||
if ( found && (map_it->first + map_it->second) >=
|
||||
(node_offset + p_size) )
|
||||
{
|
||||
//OK
|
||||
error_vec[i] = 0;
|
||||
sync_vec[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//NOK
|
||||
memset(received + (i * p_size), 0x0, p_size);
|
||||
error_vec[i] = 1;
|
||||
sync_vec[i] = 1;
|
||||
not_done++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct coding_params params;
|
||||
* params.k = param_k;
|
||||
* params.m = param_m;
|
||||
* params.max_row_weight = max_row_weight;
|
||||
* params.packet_size = p_size;
|
||||
* params.buf_size = buf_size;
|
||||
*/
|
||||
int w_f = max_row_weight + 2;
|
||||
|
||||
|
||||
// printf("K: %d, M: %d, max_row_weight: %d, buf_size: %d,\n", param_k, param_m, max_row_weight, buf_size );
|
||||
// printf("not done: %d\n", not_done);
|
||||
|
||||
// int * sync_vec_d;
|
||||
// int * error_vec_d;
|
||||
// int * pcm_d;
|
||||
|
||||
if (PCM == NULL)
|
||||
{
|
||||
error = cudaMalloc(&PCM, w_f * param_m * sizeof(int));
|
||||
if (error != cudaSuccess) printf("3 %s\n", cudaGetErrorString(error));
|
||||
|
||||
error = cudaMemcpy(PCM, pcm, w_f * param_m * sizeof(int), cudaMemcpyHostToDevice);
|
||||
if (error != cudaSuccess) printf("4 %s\n", cudaGetErrorString(error));
|
||||
}
|
||||
|
||||
if (SYNC_VEC == NULL)
|
||||
{
|
||||
error = cudaMalloc(&SYNC_VEC, (param_m + param_k) * sizeof(int));
|
||||
if (error != cudaSuccess) printf("7 %s\n", cudaGetErrorString(error));
|
||||
}
|
||||
|
||||
cudaMemcpy(SYNC_VEC, sync_vec, (param_m + param_k) * sizeof(int), cudaMemcpyHostToDevice);
|
||||
cuda_check_error("SYNC_VEC");
|
||||
|
||||
|
||||
if (ERROR_VEC == NULL)
|
||||
{
|
||||
cudaMalloc(&ERROR_VEC, (param_m + param_k) * sizeof(int));
|
||||
cuda_check_error("ERROR_VEC");
|
||||
}
|
||||
|
||||
cudaMemcpy(ERROR_VEC, error_vec, (param_m + param_k) * sizeof(int), cudaMemcpyHostToDevice);
|
||||
cuda_check_error("ERROR_VEC");
|
||||
|
||||
// // }else{
|
||||
// // error = cudaMemcpy(ERROR_VEC, sync_vec, (param_m + param_k) * sizeof(int), cudaMemcpyHostToDevice);
|
||||
// // if (error != cudaSuccess) printf("8 %s\n", cudaGetErrorString(error));
|
||||
// // }
|
||||
|
||||
//(char *data, int * PCM,int* SYNC_VEC,int* ERROR_VEC, int not_done, int *frame_size,int * error_vec,int * sync_vec,int M,int K,int w_f,int buf_size,int packet_size)
|
||||
// if (not_done != 0)
|
||||
// {
|
||||
// gpu_decode_upgrade(received, PCM, SYNC_VEC, ERROR_VEC, not_done, frame_size, error_vec, sync_vec, param_m, param_k, w_f, buf_size, p_size);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// int fs = 0;
|
||||
// memcpy(&fs, received, 4);
|
||||
// *frame_size = fs;
|
||||
// printf("frame_size: %d\n",frame_size );
|
||||
// }
|
||||
|
||||
gpu_decode_upgrade(received, PCM, SYNC_VEC, ERROR_VEC, not_done, frame_size, error_vec, sync_vec, param_m, param_k, w_f, buf_size, p_size);
|
||||
|
||||
#if 0
|
||||
assert(LDGM_session::HEADER_SIZE >= 12)
|
||||
int my_frame_size = 0;
|
||||
memcpy(&my_frame_size, received + 8, 4);
|
||||
int crc_origin = 0;
|
||||
memcpy(&crc_origin, received + 4, 4);
|
||||
|
||||
// printf("my_frame_size: %d\n",my_frame_size );
|
||||
int crc =0;
|
||||
crc = crc32buf(received + LDGM_session::HEADER_SIZE, my_frame_size);
|
||||
|
||||
if (crc_origin != crc)
|
||||
{
|
||||
printf("CRC NOK\n");
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
// if (*frame_size != 0)
|
||||
// {
|
||||
|
||||
// int my_frame_size = 0;
|
||||
// memcpy(&my_frame_size, received + 8, 4);
|
||||
// int crc_origin = 0;
|
||||
// memcpy(&crc_origin, received + 4, 4);
|
||||
|
||||
// // printf("my_frame_size: %d\n",my_frame_size );
|
||||
// int crc =0;
|
||||
// // crc32buf(received + 12, my_frame_size);
|
||||
|
||||
// if (crc_origin != crc)
|
||||
// {
|
||||
// printf("CRC NOK1\n");
|
||||
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// printf("CRC NOK\n");
|
||||
// }
|
||||
|
||||
gettimeofday(&t1, 0);
|
||||
long elapsed = (t1.tv_sec - t0.tv_sec) * 1000000 + t1.tv_usec - t0.tv_usec;
|
||||
//printf("time: %e\n",elapsed/1000.0 );
|
||||
this->elapsed_sum2 += elapsed / 1000.0;
|
||||
this->no_frames2++;
|
||||
|
||||
return received + LDGM_session::HEADER_SIZE;
|
||||
|
||||
gpu_decode ( received, error_vec, this->pcMatrix, params );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Milan Kabat (), kabat@ics.muni.cz
|
||||
* Authors: Milan Kabat (kabat@ics.muni.cz), Vojtech David (374572@mail.muni.cz)
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
@@ -21,8 +21,23 @@
|
||||
#define LDGM_SESSION_GPU_INC
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "ldgm-session.h"
|
||||
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
// CUDA check error
|
||||
#define cuda_check_error(msg) \
|
||||
{ \
|
||||
cudaError_t err = cudaGetLastError(); \
|
||||
if( cudaSuccess != err) { \
|
||||
fprintf(stderr, "[LDGM GPU] [Error] %s (line %i): %s: %s.\n", \
|
||||
__FILE__, __LINE__, msg, cudaGetErrorString( err) ); \
|
||||
exit(-1); \
|
||||
} \
|
||||
} \
|
||||
|
||||
/*
|
||||
* =====================================================================================
|
||||
* Class: LDGM_session_gpu
|
||||
@@ -32,10 +47,19 @@
|
||||
class LDGM_session_gpu : public LDGM_session
|
||||
{
|
||||
public:
|
||||
|
||||
// int * error_vec;
|
||||
// int * sync_vec;
|
||||
|
||||
// int * ERROR_VEC;
|
||||
// int * SYNC_VEC;
|
||||
|
||||
|
||||
|
||||
/* ==================== LIFECYCLE ======================================= */
|
||||
LDGM_session_gpu () {} /* constructor */
|
||||
LDGM_session_gpu (); /* constructor */
|
||||
LDGM_session_gpu ( const LDGM_session_gpu &other ); /* copy constructor */
|
||||
~LDGM_session_gpu () {} /* destructor */
|
||||
~LDGM_session_gpu (); /* destructor */
|
||||
|
||||
/* ==================== ACCESSORS ======================================= */
|
||||
|
||||
@@ -47,15 +71,18 @@ class LDGM_session_gpu : public LDGM_session
|
||||
encode ( char* data_ptr, char* parity_ptr );
|
||||
|
||||
void
|
||||
encode_naive ( char* data_ptr, char* parity_ptr ) {}
|
||||
encode_naive ( char* /* data_ptr */, char* /* parity_ptr */ ) {}
|
||||
|
||||
void
|
||||
decode();
|
||||
|
||||
void
|
||||
iterate ( Tanner_graph *graph);
|
||||
free_out_buf (char *buf);
|
||||
|
||||
void decode (char* received, int* error_vec, int num_lost);
|
||||
void *
|
||||
alloc_buf(int size);
|
||||
|
||||
char * decode_frame ( char* received_data, int buf_size, int* frame_size, std::map<int, int> valid_data );
|
||||
void set_data_fname(char fname[32]) { strncpy(data_fname, fname, 32); }
|
||||
|
||||
protected:
|
||||
@@ -65,6 +92,22 @@ class LDGM_session_gpu : public LDGM_session
|
||||
/* ==================== DATA MEMBERS ======================================= */
|
||||
char data_fname[32];
|
||||
|
||||
std::queue<char *> freeBuffers;
|
||||
std::map<char *, size_t> bufferSizes;
|
||||
|
||||
int OUTBUF_SIZE;
|
||||
int * OUTBUF;
|
||||
|
||||
int * error_vec;
|
||||
int * sync_vec;
|
||||
|
||||
int * SYNC_VEC;
|
||||
int * ERROR_VEC;
|
||||
|
||||
int * PCM;
|
||||
|
||||
|
||||
|
||||
}; /* ----- end of class LDGM_session_gpu ----- */
|
||||
|
||||
#endif /* ----- #ifndef LDGM_SESSION_GPU_INC ----- */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Filename: ldgm-session.cpp
|
||||
*
|
||||
* Description:
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 04/12/2012 01:03:23 PM
|
||||
@@ -11,7 +11,7 @@
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Milan Kabat (), kabat@ics.muni.cz
|
||||
* Organization:
|
||||
* Organization:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
@@ -20,15 +20,18 @@
|
||||
#include "config.h"
|
||||
#include "config_unix.h"
|
||||
#include "config_win32.h"
|
||||
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto/crc.h"
|
||||
#include "ldgm-session.h"
|
||||
#include "gpu.cuh"
|
||||
#include "timer-util.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -40,11 +43,7 @@ using namespace std;
|
||||
* Description: constructor
|
||||
*--------------------------------------------------------------------------------------
|
||||
*/
|
||||
LDGM_session::LDGM_session ()
|
||||
{
|
||||
} /* ----- end of method LDGM_session::LDGM_session (constructor) ----- */
|
||||
|
||||
void
|
||||
void
|
||||
LDGM_session::set_pcMatrix ( char* fname)
|
||||
{
|
||||
FILE *f;
|
||||
@@ -52,34 +51,40 @@ LDGM_session::set_pcMatrix ( char* fname)
|
||||
f = fopen(fname, "rb");
|
||||
if (!f)
|
||||
{
|
||||
printf ( "Error opening matrix file\n" );
|
||||
printf ( "exiting\n" );
|
||||
abort();
|
||||
printf ( "Error opening matrix file\n" );
|
||||
printf ( "exiting\n" );
|
||||
abort();
|
||||
}
|
||||
unsigned int k_f, m_f, w_f;
|
||||
fscanf(f, "%d %d %d", &k_f, &m_f, &w_f);
|
||||
if (fscanf(f, "%d %d %d", &k_f, &m_f, &w_f) != 3) {
|
||||
throw string("Parity matrix read error!");
|
||||
}
|
||||
// printf ( "In matrix file: K %d M %d Columns %d\n", k_f, m_f, w_f );
|
||||
|
||||
if ( k_f != param_k || m_f != param_m)
|
||||
{
|
||||
printf("Parity matrix size mismatch\nExpected K = %d, M = %d\nReceived K = %d, M = %d\n",
|
||||
param_k, param_m, k_f, m_f);
|
||||
return;
|
||||
ostringstream oss;
|
||||
oss << "Parity matrix size mismatch\nExpected K = " << param_k << "% M = " << param_m <<
|
||||
"\nReceived K = " << k_f << ", M = " << m_f << "\n";
|
||||
throw oss.str();
|
||||
}
|
||||
fseek (f, 1, SEEK_CUR );
|
||||
|
||||
|
||||
pcm = (int*) malloc(w_f*param_m*sizeof(int));
|
||||
for ( int i = 0; i < (int)w_f*param_m; i++)
|
||||
fread ( pcm+i, sizeof(int), 1, f);
|
||||
for ( int i = 0; i < (int)w_f*param_m; i++) {
|
||||
if (fread ( pcm+i, sizeof(int), 1, f) != 1) {
|
||||
throw string("Parity matrix read error!");
|
||||
}
|
||||
}
|
||||
this->max_row_weight = w_f - 2; //w_f stores number of columns in adjacency list
|
||||
|
||||
/* for ( int i = 0; i < param_m; i++)
|
||||
* {
|
||||
* for ( int j = 0; j < w_f; j++)
|
||||
* printf ( "[%3d]", (unsigned int)(pcm[i*w_f+j]) );
|
||||
* printf ( "\n" );
|
||||
* }
|
||||
*/
|
||||
/* for ( int i = 0; i < param_m; i++)
|
||||
* {
|
||||
* for ( int j = 0; j < w_f; j++)
|
||||
* printf ( "[%3d]", (unsigned int)(pcm[i*w_f+j]) );
|
||||
* printf ( "\n" );
|
||||
* }
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -88,60 +93,64 @@ LDGM_session::set_pcMatrix ( char* fname)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* this->max_row_weight = 0;
|
||||
* int max_weight = 0;
|
||||
* for ( int i = 0; i < param_m; ++i) {
|
||||
* for ( int j = 0; j < param_k; ++j) {
|
||||
* if(*(matrix + i*param_k + j) == 1) {
|
||||
* *(pcMatrix + i*param_k + j) = *(matrix + i*param_k + j);
|
||||
* max_weight++;
|
||||
* }
|
||||
* }
|
||||
* if ( max_weight > this->max_row_weight )
|
||||
* this->max_row_weight = max_weight;
|
||||
* max_weight = 0;
|
||||
* }
|
||||
*
|
||||
* pcm = (int*) malloc (m*(max_row_weight+2)*sizeof(int*));
|
||||
* struct coding_params params;
|
||||
* params.m = m;
|
||||
* params.k = k;
|
||||
* params.max_row_weight = max_row_weight;
|
||||
*
|
||||
* make_compact_pcm ( matrix, pcm, params);
|
||||
*/
|
||||
/*
|
||||
* this->max_row_weight = 0;
|
||||
* int max_weight = 0;
|
||||
* for ( int i = 0; i < param_m; ++i) {
|
||||
* for ( int j = 0; j < param_k; ++j) {
|
||||
* if(*(matrix + i*param_k + j) == 1) {
|
||||
* *(pcMatrix + i*param_k + j) = *(matrix + i*param_k + j);
|
||||
* max_weight++;
|
||||
* }
|
||||
* }
|
||||
* if ( max_weight > this->max_row_weight )
|
||||
* this->max_row_weight = max_weight;
|
||||
* max_weight = 0;
|
||||
* }
|
||||
*
|
||||
* pcm = (int*) malloc (m*(max_row_weight+2)*sizeof(int*));
|
||||
* struct coding_params params;
|
||||
* params.m = m;
|
||||
* params.k = k;
|
||||
* params.max_row_weight = max_row_weight;
|
||||
*
|
||||
* make_compact_pcm ( matrix, pcm, params);
|
||||
*/
|
||||
|
||||
|
||||
return ;
|
||||
} /* ----- end of method Coding_session::set_pcMatrix ----- */
|
||||
|
||||
char*
|
||||
char*
|
||||
LDGM_session::encode_frame ( char* frame, int frame_size, int* out_buf_size )
|
||||
{
|
||||
{
|
||||
//printf("encode_frame\n");
|
||||
struct timeval t0,t1;
|
||||
gettimeofday(&t0, 0);
|
||||
|
||||
int buf_size;
|
||||
int ps;
|
||||
short header_size = 4;
|
||||
short header_size = LDGM_session::HEADER_SIZE;
|
||||
int align_coef = param_k*sizeof(int);
|
||||
|
||||
|
||||
if ( (frame_size + header_size) % param_k == 0 )
|
||||
buf_size = frame_size + header_size;
|
||||
if ( (frame_size + header_size) % align_coef == 0 )
|
||||
buf_size = frame_size + header_size;
|
||||
else
|
||||
buf_size = (((frame_size + header_size)/param_k) + 1)*param_k;
|
||||
buf_size = ( ( (frame_size + header_size) / align_coef ) + 1 ) * align_coef;
|
||||
|
||||
ps = buf_size/param_k;
|
||||
|
||||
packet_size = ps;
|
||||
// printf ( "ps: %d\n", ps );
|
||||
//printf ( "ps: %d\n", ps );
|
||||
buf_size += param_m*ps;
|
||||
*out_buf_size = buf_size;
|
||||
|
||||
void *out_buf;
|
||||
out_buf = aligned_malloc(buf_size, 16);
|
||||
out_buf = alloc_buf(buf_size);
|
||||
if (!out_buf)
|
||||
{
|
||||
printf ( "Unable to allocate aligned memory\n" );
|
||||
return NULL;
|
||||
printf ( "Unable to allocate memory\n" );
|
||||
return NULL;
|
||||
}
|
||||
memset(out_buf, 0, buf_size);
|
||||
|
||||
@@ -152,43 +161,52 @@ LDGM_session::encode_frame ( char* frame, int frame_size, int* out_buf_size )
|
||||
|
||||
memcpy( ((char*)out_buf) + header_size, frame, frame_size);
|
||||
|
||||
timespec start, end;
|
||||
//Timer_util t;
|
||||
|
||||
//printf("2buf_size %d\n",buf_size);
|
||||
//printf("2packet_size %d\n",packet_size);
|
||||
this->encode ( (char*)out_buf, ((char*)out_buf)+param_k*ps );
|
||||
|
||||
|
||||
gettimeofday(&t1,0);
|
||||
long elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec;
|
||||
// printf("time: %e\n",elapsed/1000.0 );
|
||||
this->elapsed_sum2+=elapsed/1000.0;
|
||||
this->no_frames2++;
|
||||
|
||||
return (char*)out_buf;
|
||||
|
||||
// printf ( "SSE: %.3lf\n", t.elapsed_time(start, end) );
|
||||
|
||||
/* void *out_buf_check;
|
||||
* error = posix_memalign(&out_buf_check, 16, buf_size);
|
||||
* memset(out_buf_check, 0, buf_size);
|
||||
* hdr = (int*)out_buf_check;
|
||||
* *hdr = frame_size;
|
||||
* memcpy(((char*)out_buf_check)+header_size, frame, frame_size);
|
||||
* clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
* encode_naive ( (char*)out_buf, ((char*)out_buf_check)+param_k*ps );
|
||||
* clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
* printf ( "CPU: %.3lf\n", t.elapsed_time(start, end) );
|
||||
*
|
||||
* int e = memcmp(out_buf, out_buf_check, buf_size);
|
||||
* printf ( "memcpy on parities: %d\n", e );
|
||||
* char *a = (char*)out_buf;
|
||||
* char *b = (char*)out_buf_check;
|
||||
* bool equal = true;
|
||||
* int idx = 0;
|
||||
* for ( int i = 0; i < param_m*ps; i++)
|
||||
* {
|
||||
* if(a[i] != b[i])
|
||||
* {
|
||||
* idx = i;
|
||||
* printf ( "Error at index %d: %d vs %d\n", i, (unsigned char)a[i],
|
||||
* (unsigned char)b[i] );
|
||||
* equal = false;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* printf ( "Parities %s match.\n", (equal)?"":"do not" );
|
||||
*/
|
||||
/* void *out_buf_check;
|
||||
* error = posix_memalign(&out_buf_check, 16, buf_size);
|
||||
* memset(out_buf_check, 0, buf_size);
|
||||
* hdr = (int*)out_buf_check;
|
||||
* *hdr = frame_size;
|
||||
* memcpy(((char*)out_buf_check)+header_size, frame, frame_size);
|
||||
* clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
* encode_naive ( (char*)out_buf, ((char*)out_buf_check)+param_k*ps );
|
||||
* clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
* printf ( "CPU: %.3lf\n", t.elapsed_time(start, end) );
|
||||
*
|
||||
* int e = memcmp(out_buf, out_buf_check, buf_size);
|
||||
* printf ( "memcpy on parities: %d\n", e );
|
||||
* char *a = (char*)out_buf;
|
||||
* char *b = (char*)out_buf_check;
|
||||
* bool equal = true;
|
||||
* int idx = 0;
|
||||
* for ( int i = 0; i < param_m*ps; i++)
|
||||
* {
|
||||
* if(a[i] != b[i])
|
||||
* {
|
||||
* idx = i;
|
||||
* printf ( "Error at index %d: %d vs %d\n", i, (unsigned char)a[i],
|
||||
* (unsigned char)b[i] );
|
||||
* equal = false;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* printf ( "Parities %s match.\n", (equal)?"":"do not" );
|
||||
*/
|
||||
|
||||
// printf ( "\n\nEncoded block:\n" );
|
||||
// printf ( "%-13s\v%10d B\n", "Frame hdr size:", header_size );
|
||||
@@ -200,23 +218,23 @@ LDGM_session::encode_frame ( char* frame, int frame_size, int* out_buf_size )
|
||||
// printf ( "Symbol size:\t%d\n\n\n", ps );
|
||||
|
||||
|
||||
return (char*)out_buf;
|
||||
|
||||
|
||||
}
|
||||
|
||||
char*
|
||||
char*
|
||||
LDGM_session::encode_hdr_frame ( char *my_hdr, int my_hdr_size, char* frame, int frame_size, int* out_buf_size )
|
||||
{
|
||||
int buf_size;
|
||||
int ps;
|
||||
short header_size = 4;
|
||||
short header_size = LDGM_session::HEADER_SIZE;
|
||||
int overall_size = my_hdr_size + frame_size;
|
||||
int align_coef = param_k*sizeof(int);
|
||||
|
||||
|
||||
if ( (overall_size + header_size) % param_k == 0 )
|
||||
buf_size = overall_size + header_size;
|
||||
if ( (overall_size + header_size) % align_coef == 0 )
|
||||
buf_size = overall_size + header_size;
|
||||
else
|
||||
buf_size = (((overall_size + header_size)/param_k) + 1)*param_k;
|
||||
buf_size = ( ( (overall_size + header_size) / align_coef ) + 1 ) * align_coef;
|
||||
|
||||
ps = buf_size/param_k;
|
||||
|
||||
@@ -226,59 +244,98 @@ LDGM_session::encode_hdr_frame ( char *my_hdr, int my_hdr_size, char* frame, int
|
||||
*out_buf_size = buf_size;
|
||||
|
||||
void *out_buf;
|
||||
out_buf = aligned_malloc(buf_size, 16);
|
||||
out_buf = alloc_buf(buf_size);
|
||||
if (!out_buf)
|
||||
{
|
||||
printf ( "Unable to allocate aligned memory\n" );
|
||||
return NULL;
|
||||
printf ( "Unable to allocate aligned memory\n" );
|
||||
return NULL;
|
||||
}
|
||||
memset(out_buf, 0, buf_size);
|
||||
|
||||
//Insert frame size and copy input data into buffer
|
||||
|
||||
int *hdr = (int*)out_buf;
|
||||
int32_t *hdr = (int32_t*)out_buf;
|
||||
*hdr = overall_size;
|
||||
|
||||
memcpy( ((char*)out_buf) + header_size, my_hdr, my_hdr_size);
|
||||
memcpy( ((char*)out_buf) + header_size + my_hdr_size, frame, frame_size);
|
||||
|
||||
timespec start, end;
|
||||
#if 0
|
||||
int my_frame_size=my_hdr_size+frame_size;
|
||||
|
||||
// printf("my_frame_size: %d\n",my_frame_size );
|
||||
|
||||
int crc;
|
||||
crc = crc32buf((char*)out_buf+header_size,my_frame_size);
|
||||
|
||||
memcpy( ((char*)out_buf) + 4, &crc, 4);
|
||||
memcpy( ((char*)out_buf) + 8, &my_frame_size, 4);
|
||||
assert(LDGM_session::HEADER_SIZE >= 12);
|
||||
#endif
|
||||
|
||||
//Timer_util t;
|
||||
|
||||
|
||||
struct timeval t0, t1;
|
||||
gettimeofday(&t0, 0);
|
||||
|
||||
this->encode ( (char*)out_buf, ((char*)out_buf)+param_k*ps );
|
||||
|
||||
gettimeofday(&t1,0);
|
||||
long elapsed;
|
||||
|
||||
elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec;
|
||||
// printf("time: %e\n",elapsed/1000.0 );
|
||||
this->elapsed_sum2+=elapsed/1000.0;
|
||||
this->no_frames2++;
|
||||
|
||||
|
||||
// gettimeofday(&t1,0);
|
||||
// long elapsed;
|
||||
|
||||
// elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec;
|
||||
// // printf("time: %e\n",elapsed/1000.0 );
|
||||
// this->elapsed_sum2+=elapsed/1000.0;
|
||||
// this->no_frames2++;
|
||||
// i++;
|
||||
|
||||
// if(i%100==0){
|
||||
// printf("TIME GPU: %f ms\n",this->elapsed_sum2/(double)this->no_frames2 );
|
||||
// printf("time: %f ms\n",elapsed/1000.0 );
|
||||
// }
|
||||
|
||||
// printf ( "SSE: %.3lf\n", t.elapsed_time(start, end) );
|
||||
|
||||
/* void *out_buf_check;
|
||||
* error = posix_memalign(&out_buf_check, 16, buf_size);
|
||||
* memset(out_buf_check, 0, buf_size);
|
||||
* hdr = (int*)out_buf_check;
|
||||
* *hdr = frame_size;
|
||||
* memcpy(((char*)out_buf_check)+header_size, frame, frame_size);
|
||||
* clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
* encode_naive ( (char*)out_buf, ((char*)out_buf_check)+param_k*ps );
|
||||
* clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
* printf ( "CPU: %.3lf\n", t.elapsed_time(start, end) );
|
||||
*
|
||||
* int e = memcmp(out_buf, out_buf_check, buf_size);
|
||||
* printf ( "memcpy on parities: %d\n", e );
|
||||
* char *a = (char*)out_buf;
|
||||
* char *b = (char*)out_buf_check;
|
||||
* bool equal = true;
|
||||
* int idx = 0;
|
||||
* for ( int i = 0; i < param_m*ps; i++)
|
||||
* {
|
||||
* if(a[i] != b[i])
|
||||
* {
|
||||
* idx = i;
|
||||
* printf ( "Error at index %d: %d vs %d\n", i, (unsigned char)a[i],
|
||||
* (unsigned char)b[i] );
|
||||
* equal = false;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* printf ( "Parities %s match.\n", (equal)?"":"do not" );
|
||||
*/
|
||||
/* void *out_buf_check;
|
||||
* error = posix_memalign(&out_buf_check, 16, buf_size);
|
||||
* memset(out_buf_check, 0, buf_size);
|
||||
* hdr = (int*)out_buf_check;
|
||||
* *hdr = frame_size;
|
||||
* memcpy(((char*)out_buf_check)+header_size, frame, frame_size);
|
||||
* clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
* encode_naive ( (char*)out_buf, ((char*)out_buf_check)+param_k*ps );
|
||||
* clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
* printf ( "CPU: %.3lf\n", t.elapsed_time(start, end) );
|
||||
*
|
||||
* int e = memcmp(out_buf, out_buf_check, buf_size);
|
||||
* printf ( "memcpy on parities: %d\n", e );
|
||||
* char *a = (char*)out_buf;
|
||||
* char *b = (char*)out_buf_check;
|
||||
* bool equal = true;
|
||||
* int idx = 0;
|
||||
* for ( int i = 0; i < param_m*ps; i++)
|
||||
* {
|
||||
* if(a[i] != b[i])
|
||||
* {
|
||||
* idx = i;
|
||||
* printf ( "Error at index %d: %d vs %d\n", i, (unsigned char)a[i],
|
||||
* (unsigned char)b[i] );
|
||||
* equal = false;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* printf ( "Parities %s match.\n", (equal)?"":"do not" );
|
||||
*/
|
||||
|
||||
// printf ( "\n\nEncoded block:\n" );
|
||||
// printf ( "%-13s\v%10d B\n", "Frame hdr size:", header_size );
|
||||
@@ -294,62 +351,62 @@ LDGM_session::encode_hdr_frame ( char *my_hdr, int my_hdr_size, char* frame, int
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* === FUNCTION ======================================================================
|
||||
* Name: create_edges
|
||||
* Description:
|
||||
* Description:
|
||||
* =====================================================================================
|
||||
*/
|
||||
void
|
||||
void
|
||||
LDGM_session::create_edges ( Tanner_graph *graph )
|
||||
{
|
||||
map<int, Node>::iterator it;
|
||||
// printf ( "graph: %p, param_k: %d, param_m: %d\n", graph, param_k, param_m );
|
||||
for ( int m = 0; m < param_m; ++m) {
|
||||
for ( int k = 0; k < max_row_weight+2; ++k ) {
|
||||
int idx = pcm [ m*(max_row_weight+2) + k];
|
||||
if( idx > -1 ) {
|
||||
it = graph->nodes.find(idx);
|
||||
(*it).second.neighbours.push_back(param_k + param_m + m);
|
||||
it = graph->nodes.find(param_k + param_m + m);
|
||||
(*it).second.neighbours.push_back(idx);
|
||||
}
|
||||
}
|
||||
for ( int k = 0; k < max_row_weight+2; ++k ) {
|
||||
int idx = pcm [ m*(max_row_weight+2) + k];
|
||||
if( idx > -1 ) {
|
||||
it = graph->nodes.find(idx);
|
||||
(*it).second.neighbours.push_back(param_k + param_m + m);
|
||||
it = graph->nodes.find(param_k + param_m + m);
|
||||
(*it).second.neighbours.push_back(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* it = graph->nodes.find(0);
|
||||
* while ( it != graph->nodes.end() )
|
||||
* {
|
||||
* printf ( "\nneighbours of node %d: ", it->first );
|
||||
* for (vector<int>::iterator i = it->second.neighbours.begin();
|
||||
* i != it->second.neighbours.end(); ++i)
|
||||
* printf ( "%d, ", *i );
|
||||
* it++;
|
||||
* }
|
||||
*/
|
||||
/* it = graph->nodes.find(0);
|
||||
* while ( it != graph->nodes.end() )
|
||||
* {
|
||||
* printf ( "\nneighbours of node %d: ", it->first );
|
||||
* for (vector<int>::iterator i = it->second.neighbours.begin();
|
||||
* i != it->second.neighbours.end(); ++i)
|
||||
* printf ( "%d, ", *i );
|
||||
* it++;
|
||||
* }
|
||||
*/
|
||||
|
||||
//add edges representing the staircase matrix
|
||||
/* for ( int i = param_k + param_m; i < param_k + 2*param_m; ++i) {
|
||||
* it = graph->nodes.find(i);
|
||||
* (*it).second.neighbours.push_back(i - param_m);
|
||||
* it = graph->nodes.find(i - param_m);
|
||||
* (*it).second.neighbours.push_back(i);
|
||||
* if(i > param_m + param_k) {
|
||||
* it = graph->nodes.find(i);
|
||||
* (*it).second.neighbours.push_back(i - param_m - 1);
|
||||
* it = graph->nodes.find(i - param_m - 1);
|
||||
* (*it).second.neighbours.push_back(i);
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
/* for ( int i = param_k + param_m; i < param_k + 2*param_m; ++i) {
|
||||
* it = graph->nodes.find(i);
|
||||
* (*it).second.neighbours.push_back(i - param_m);
|
||||
* it = graph->nodes.find(i - param_m);
|
||||
* (*it).second.neighbours.push_back(i);
|
||||
* if(i > param_m + param_k) {
|
||||
* it = graph->nodes.find(i);
|
||||
* (*it).second.neighbours.push_back(i - param_m - 1);
|
||||
* it = graph->nodes.find(i - param_m - 1);
|
||||
* (*it).second.neighbours.push_back(i);
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
return ;
|
||||
} /* ----- end of function create_edges ----- */
|
||||
|
||||
bool
|
||||
bool
|
||||
LDGM_session::needs_decoding ( Tanner_graph *graph )
|
||||
{
|
||||
for ( int i = 0; i < param_k; i++)
|
||||
if( ! graph->nodes.find(i)->second.isDone() )
|
||||
return true;
|
||||
if( ! graph->nodes.find(i)->second.isDone() )
|
||||
return true;
|
||||
return false;
|
||||
} /* ----- end of method LDGM_session::needs_decoding ----- */
|
||||
|
||||
|
||||
@@ -37,7 +37,10 @@ class LDGM_session : public Coding_session
|
||||
{
|
||||
public:
|
||||
/* ==================== LIFECYCLE ======================================= */
|
||||
LDGM_session (); /* constructor **/
|
||||
LDGM_session (){
|
||||
elapsed_sum2=0.0;
|
||||
no_frames2=0;
|
||||
} /* constructor **/
|
||||
virtual ~LDGM_session (); /* destructor **/
|
||||
|
||||
/* ==================== ACCESSORS ======================================= */
|
||||
@@ -76,6 +79,9 @@ class LDGM_session : public Coding_session
|
||||
virtual void
|
||||
encode_naive ( char* data, char* parity ) = 0;
|
||||
|
||||
virtual void *
|
||||
alloc_buf(int size) = 0;
|
||||
|
||||
virtual char*
|
||||
decode_frame ( char* received_data, int buf_size, int* frame_size,
|
||||
std::map<int, int> valid_data ) = 0;
|
||||
@@ -110,8 +116,15 @@ class LDGM_session : public Coding_session
|
||||
char *received_ptr;
|
||||
char *lost_ptr;
|
||||
|
||||
double elapsed_sum2;
|
||||
long no_frames2;
|
||||
|
||||
static const int HEADER_SIZE = 4;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
/* ==================== DATA MEMBERS ======================================= */
|
||||
|
||||
}; /* ----- end of class LDGM_session ----- */
|
||||
|
||||
@@ -22,13 +22,12 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "ldpc-matrix.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "rand_pmms.h"
|
||||
|
||||
int generate_ldgm_matrix(char *fname, unsigned int k, unsigned int m, unsigned int column_weight,
|
||||
unsigned int seed)
|
||||
unsigned int seed,unsigned int extend_rows)
|
||||
{
|
||||
|
||||
int random = 0;
|
||||
int rfc = 1;
|
||||
|
||||
@@ -40,7 +39,7 @@ int generate_ldgm_matrix(char *fname, unsigned int k, unsigned int m, unsigned i
|
||||
char **pc_matrix;
|
||||
|
||||
pc_matrix = (char**)malloc(m*sizeof(char*));
|
||||
for ( int i = 0; i < m; i++)
|
||||
for ( unsigned int i = 0; i < m; i++)
|
||||
pc_matrix[i] = (char*)calloc(k, sizeof(char));
|
||||
|
||||
|
||||
@@ -48,8 +47,8 @@ int generate_ldgm_matrix(char *fname, unsigned int k, unsigned int m, unsigned i
|
||||
if (random)
|
||||
{
|
||||
srand(time(NULL));
|
||||
for ( int i = 0; i < k; ++i ) {
|
||||
for ( int j = 0; j < column_weight; ++j) {
|
||||
for ( unsigned int i = 0; i < k; ++i ) {
|
||||
for ( unsigned int j = 0; j < column_weight; ++j) {
|
||||
pc_matrix[rand()%m][i] = 1;
|
||||
}
|
||||
}
|
||||
@@ -59,12 +58,40 @@ int generate_ldgm_matrix(char *fname, unsigned int k, unsigned int m, unsigned i
|
||||
{
|
||||
left_matrix_init ( pc_matrix, k, k+m, column_weight, seed );
|
||||
}
|
||||
|
||||
//Extend the matrix if necessary:
|
||||
//Each additional row is computed as follows: pseudorandomly choose a row of parity matrix
|
||||
//and shift it circularly one step to the right
|
||||
if (extend_rows > 0)
|
||||
{
|
||||
Rand_pmms rand_gen;
|
||||
rand_gen.seedi(seed);
|
||||
|
||||
for ( unsigned int i = m; i < m + extend_rows; i++ )
|
||||
{
|
||||
int row = rand_gen.pmms_rand(m - 1);
|
||||
for ( unsigned int j = 1; j < k; j++)
|
||||
{
|
||||
if (pc_matrix[row][j - 1])
|
||||
{
|
||||
pc_matrix[i][j] = 1;
|
||||
}
|
||||
}
|
||||
if (pc_matrix[row][k - 1])
|
||||
{
|
||||
pc_matrix[i][0] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m += extend_rows;
|
||||
|
||||
int max_weight = 0;
|
||||
//Compute maximum row weight
|
||||
for ( int i = 0; i < m; i++)
|
||||
for ( unsigned int i = 0; i < m; i++)
|
||||
{
|
||||
int m = 0;
|
||||
for ( int j = 0; j < k; j++)
|
||||
for ( unsigned int j = 0; j < k; j++)
|
||||
if( pc_matrix[i][j])
|
||||
m++;
|
||||
if ( m > max_weight )
|
||||
@@ -82,15 +109,15 @@ int generate_ldgm_matrix(char *fname, unsigned int k, unsigned int m, unsigned i
|
||||
|
||||
int **pcm;
|
||||
pcm = (int**)malloc(m*sizeof(int*));
|
||||
for ( int i = 0; i < m; i++)
|
||||
for ( unsigned int i = 0; i < m; i++)
|
||||
pcm[i] = (int*)malloc((max_weight+2) * sizeof(int));
|
||||
|
||||
|
||||
int columns = max_weight + 2;
|
||||
int counter = 0;
|
||||
for ( int i = 0; i < m; i++ )
|
||||
for ( unsigned int i = 0; i < m; i++ )
|
||||
{
|
||||
for ( int j = 0; j < k; j++)
|
||||
for ( unsigned int j = 0; j < k; j++)
|
||||
if( pc_matrix[i][j])
|
||||
{
|
||||
pcm[i][counter] = j;
|
||||
@@ -129,12 +156,14 @@ int generate_ldgm_matrix(char *fname, unsigned int k, unsigned int m, unsigned i
|
||||
fprintf( out, "%d ", k);
|
||||
fprintf( out, "%d ", m);
|
||||
fprintf( out, "%d\n", columns);
|
||||
for ( int i = 0; i < m; i++)
|
||||
for ( unsigned int i = 0; i < m; i++)
|
||||
{
|
||||
for ( int j = 0; j < columns; j++)
|
||||
{
|
||||
int t = pcm[i][j];
|
||||
tmp = fwrite(&t, sizeof(int), 1, out);
|
||||
if (tmp != 1)
|
||||
fprintf(stderr, "Cannot write to output file!");
|
||||
}
|
||||
// printf ( "fwrite: %d\n", tmp );
|
||||
}
|
||||
@@ -186,10 +215,10 @@ int generate_ldgm_matrix(char *fname, unsigned int k, unsigned int m, unsigned i
|
||||
*/
|
||||
|
||||
|
||||
for ( int i = 0; i < m; i++)
|
||||
for ( unsigned int i = 0; i < m; i++)
|
||||
free(pc_matrix[i]);
|
||||
free(pc_matrix);
|
||||
for ( int i = 0; i < m; i++)
|
||||
for ( unsigned int i = 0; i < m; i++)
|
||||
free(pcm[i]);
|
||||
free(pcm);
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
int generate_ldgm_matrix(char *fname, unsigned int k, unsigned int m, unsigned int column_weight,
|
||||
unsigned int seed);
|
||||
unsigned int seed,unsigned int extend_rows);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ using namespace std;
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Implementation of class Node
|
||||
*-----------------------------------------------------------------------------*/
|
||||
Node::Node(Tanner_graph *tanner, Node::Node_type t, char *d) {
|
||||
Node::Node(Tanner_graph * /* tanner */, Node::Node_type t, char *d) {
|
||||
// int size = tanner->data_size;
|
||||
this->type = t;
|
||||
data = d;
|
||||
@@ -40,12 +40,12 @@ Node::~Node() {
|
||||
}
|
||||
|
||||
int Node::setDataPtr(char *d) {
|
||||
|
||||
|
||||
if ( d != 0 ) {
|
||||
sprintf(data, d, tanner->data_size);
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
sprintf(data, d, tanner->data_size);
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,11 +71,11 @@ void Tanner_graph::add_node(Node::Node_type type, int index, char *data) {
|
||||
|
||||
if(data == NULL) {
|
||||
// void *d = calloc(data_size, sizeof(char));
|
||||
Node n(this, type, data);
|
||||
nodes.insert(std::pair <int, Node>(index, n));
|
||||
Node n(this, type, data);
|
||||
nodes.insert(std::pair <int, Node>(index, n));
|
||||
} else {
|
||||
Node n(this, type, data);
|
||||
nodes.insert(std::pair <int, Node>(index, n));
|
||||
Node n(this, type, data);
|
||||
nodes.insert(std::pair <int, Node>(index, n));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
7
prepare_tarball.sh
Normal file
7
prepare_tarball.sh
Normal file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
./autogen.sh
|
||||
|
||||
rm -rf .git
|
||||
find -name .gitignore -print0 |xargs -0 rm
|
||||
|
||||
@@ -90,8 +90,6 @@
|
||||
|
||||
static volatile bool should_exit_audio = false;
|
||||
|
||||
int audio_init_state_ok;
|
||||
|
||||
struct audio_device_t {
|
||||
int index;
|
||||
void *state;
|
||||
@@ -243,7 +241,12 @@ struct state_audio * audio_cfg_init(struct module *parent, const char *addrs, in
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s = calloc(1, sizeof(struct state_audio));
|
||||
s = (struct state_audio *) calloc(1, sizeof(struct state_audio));
|
||||
|
||||
if (strcmp("none", send_cfg) == 0 && strcmp("none", recv_cfg) == 0) {
|
||||
// nothing to do, return empty state
|
||||
return s;
|
||||
}
|
||||
|
||||
module_init_default(&s->mod);
|
||||
s->mod.priv_data = s;
|
||||
@@ -305,7 +308,7 @@ struct state_audio * audio_cfg_init(struct module *parent, const char *addrs, in
|
||||
|
||||
gettimeofday(&s->start_time, NULL);
|
||||
gettimeofday(&s->t0, NULL);
|
||||
s->captured = audio_frame2_init();
|
||||
s->captured = new audio_frame2;
|
||||
|
||||
tmp = strdup(addrs);
|
||||
s->audio_participants = pdb_init();
|
||||
@@ -319,10 +322,17 @@ struct state_audio * audio_cfg_init(struct module *parent, const char *addrs, in
|
||||
s->audio_network_parameters.mcast_if = mcast_if
|
||||
? strdup(mcast_if) : NULL;
|
||||
|
||||
if (strcmp(recv_cfg, "none") == 0) {
|
||||
// do not occupy recv port if we are not receiving (note that this disables communication with
|
||||
// our receiver, because RTCP ports are changed as well)
|
||||
s->audio_network_parameters.recv_port = 0;
|
||||
}
|
||||
|
||||
if ((s->audio_network_device = initialize_audio_network(
|
||||
&s->audio_network_parameters))
|
||||
== NULL) {
|
||||
printf("Unable to open audio network\n");
|
||||
free(tmp);
|
||||
goto error;
|
||||
}
|
||||
free(tmp);
|
||||
@@ -431,7 +441,7 @@ error:
|
||||
module_done(&s->mod);
|
||||
}
|
||||
|
||||
audio_frame2_free(s->captured);
|
||||
delete s->captured;
|
||||
|
||||
audio_codec_done(s->audio_coder);
|
||||
free(s);
|
||||
@@ -481,7 +491,7 @@ void audio_done(struct state_audio *s)
|
||||
free(s->audio_network_parameters.addr);
|
||||
free(s->audio_network_parameters.mcast_if);
|
||||
|
||||
audio_frame2_free(s->captured);
|
||||
delete s->captured;
|
||||
|
||||
free(s);
|
||||
}
|
||||
@@ -495,7 +505,7 @@ static struct rtp *initialize_audio_network(struct audio_network_parameters *par
|
||||
r = rtp_init_if(params->addr, params->mcast_if, params->recv_port,
|
||||
params->send_port, 255, rtcp_bw,
|
||||
FALSE, rtp_recv_callback,
|
||||
(void *) params->participants,
|
||||
(uint8_t *) params->participants,
|
||||
params->use_ipv6, false);
|
||||
if (r != NULL) {
|
||||
pdb_add(params->participants, rtp_my_ssrc(r));
|
||||
@@ -509,7 +519,7 @@ static struct rtp *initialize_audio_network(struct audio_network_parameters *par
|
||||
|
||||
static void *audio_receiver_thread(void *arg)
|
||||
{
|
||||
struct state_audio *s = arg;
|
||||
struct state_audio *s = (struct state_audio *) arg;
|
||||
// rtp variables
|
||||
struct timeval timeout, curr_time;
|
||||
uint32_t ts;
|
||||
@@ -520,7 +530,7 @@ static void *audio_receiver_thread(void *arg)
|
||||
memset(&pbuf_data.buffer, 0, sizeof(struct audio_frame));
|
||||
memset(&device_desc, 0, sizeof(struct audio_desc));
|
||||
|
||||
pbuf_data.decoder = audio_decoder_init(s->audio_channel_map, s->audio_scale, s->requested_encryption);
|
||||
pbuf_data.decoder = (struct state_audio_decoder *) audio_decoder_init(s->audio_channel_map, s->audio_scale, s->requested_encryption);
|
||||
assert(pbuf_data.decoder != NULL);
|
||||
|
||||
printf("Audio receiving started.\n");
|
||||
@@ -535,8 +545,9 @@ static void *audio_receiver_thread(void *arg)
|
||||
rtp_update(s->audio_network_device, curr_time);
|
||||
rtp_send_ctrl(s->audio_network_device, ts, 0, curr_time);
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 999999 / 59.94; /* audio goes almost always at the same rate
|
||||
as video frames */
|
||||
// timeout.tv_usec = 999999 / 59.94; // audio goes almost always at the same rate
|
||||
// as video frames
|
||||
timeout.tv_usec = 1000; // this stuff really smells !!!
|
||||
rtp_recv_r(s->audio_network_device, &timeout, ts);
|
||||
pdb_iter_t it;
|
||||
cp = pdb_iter_init(s->audio_participants, &it);
|
||||
@@ -686,7 +697,7 @@ static void resample(struct state_resample *s, struct audio_frame *buffer)
|
||||
|
||||
if(buffer->sample_rate == s->resample_to && s->codec_supported_bytes_per_sample == NULL) {
|
||||
memcpy(&s->resampled, buffer, sizeof(s->resampled));
|
||||
s->resampled.data = malloc(buffer->data_len);
|
||||
s->resampled.data = (char *) malloc(buffer->data_len);
|
||||
memcpy(s->resampled.data, buffer->data, buffer->data_len);
|
||||
} else {
|
||||
/**
|
||||
@@ -695,7 +706,7 @@ static void resample(struct state_resample *s, struct audio_frame *buffer)
|
||||
assert(set_contains(s->codec_supported_bytes_per_sample, 2));
|
||||
// expect that we may got as much as 12-times more data (eg 8 kHz to 96 kHz
|
||||
uint32_t write_frames = 12 * (buffer->data_len / buffer->ch_count / buffer->bps);
|
||||
s->resampled.data = malloc(write_frames * 2 * buffer->ch_count);
|
||||
s->resampled.data = (char *) malloc(write_frames * 2 * buffer->ch_count);
|
||||
if(s->resample_from != buffer->sample_rate || s->resample_ch_count != buffer->ch_count) {
|
||||
s->resample_from = buffer->sample_rate;
|
||||
s->resample_ch_count = buffer->ch_count;
|
||||
@@ -773,10 +784,11 @@ static void audio_sender_process_message(struct state_audio *s, struct msg_sende
|
||||
|
||||
static void process_statistics(struct state_audio *s, audio_frame2 *buffer)
|
||||
{
|
||||
if (s->captured->ch_count != buffer->ch_count) {
|
||||
audio_frame2_reset(s->captured);
|
||||
if (!s->captured->has_same_prop_as(*buffer)) {
|
||||
s->captured->init(buffer->get_channel_count(), buffer->get_codec(),
|
||||
buffer->get_bps(), buffer->get_sample_rate());
|
||||
}
|
||||
audio_frame2_append(s->captured, buffer);
|
||||
s->captured->append(*buffer);
|
||||
|
||||
struct timeval t;
|
||||
double seconds;
|
||||
@@ -784,16 +796,16 @@ static void process_statistics(struct state_audio *s, audio_frame2 *buffer)
|
||||
seconds = tv_diff(t, s->t0);
|
||||
if (seconds > 5.0) {
|
||||
printf("[Audio sender] Sent %d samples in last %f seconds.\n",
|
||||
audio_frame2_get_sample_count(s->captured),
|
||||
s->captured->get_sample_count(),
|
||||
seconds);
|
||||
for (int i = 0; i < s->captured->ch_count; ++i) {
|
||||
for (int i = 0; i < s->captured->get_channel_count(); ++i) {
|
||||
double rms, peak;
|
||||
rms = calculate_rms(s->captured, i, &peak);
|
||||
printf("[Audio sender] Channel %d - volume: %f dBFS RMS, %f dBFS peak.\n",
|
||||
i, 20 * log(rms) / log(10), 20 * log(peak) / log(10));
|
||||
}
|
||||
s->t0 = t;
|
||||
audio_frame2_reset(s->captured);
|
||||
s->captured->reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -801,12 +813,11 @@ static void *audio_sender_thread(void *arg)
|
||||
{
|
||||
struct state_audio *s = (struct state_audio *) arg;
|
||||
struct audio_frame *buffer = NULL;
|
||||
audio_frame2 *buffer_new = audio_frame2_init();
|
||||
struct state_resample resample_state;
|
||||
|
||||
memset(&resample_state, 0, sizeof(resample_state));
|
||||
resample_state.resample_to = s->resample_to;
|
||||
resample_state.resample_buffer = malloc(1024 * 1024);
|
||||
resample_state.resample_buffer = (char *) malloc(1024 * 1024);
|
||||
resample_state.codec_supported_bytes_per_sample =
|
||||
audio_codec_get_supported_bps(s->audio_coder);
|
||||
|
||||
@@ -831,35 +842,32 @@ static void *audio_sender_thread(void *arg)
|
||||
if (s->paused) {
|
||||
continue;
|
||||
}
|
||||
audio_frame2 buffer_new;
|
||||
if(s->sender == NET_NATIVE) {
|
||||
// RESAMPLE
|
||||
resample(&resample_state, buffer);
|
||||
// COMPRESS
|
||||
audio_frame_to_audio_frame2(buffer_new, &resample_state.resampled);
|
||||
process_statistics(s, buffer_new);
|
||||
buffer_new = audio_frame2(&resample_state.resampled);
|
||||
process_statistics(s, &buffer_new);
|
||||
free(resample_state.resampled.data);
|
||||
if(buffer_new) {
|
||||
audio_frame2 *uncompressed = buffer_new;
|
||||
audio_frame2 *compressed = NULL;
|
||||
while((compressed = audio_codec_compress(s->audio_coder, uncompressed))) {
|
||||
audio_tx_send(s->tx_session, s->audio_network_device, compressed);
|
||||
uncompressed = NULL;
|
||||
}
|
||||
audio_frame2 *uncompressed = &buffer_new;
|
||||
const audio_frame2 *compressed = NULL;
|
||||
while((compressed = audio_codec_compress(s->audio_coder, uncompressed))) {
|
||||
audio_tx_send(s->tx_session, s->audio_network_device, compressed);
|
||||
uncompressed = NULL;
|
||||
}
|
||||
}else if(s->sender == NET_STANDARD){
|
||||
// RESAMPLE
|
||||
resample(&resample_state, buffer);
|
||||
// COMPRESS
|
||||
audio_frame_to_audio_frame2(buffer_new, &resample_state.resampled);
|
||||
buffer_new = audio_frame2(&resample_state.resampled);
|
||||
free(resample_state.resampled.data);
|
||||
if(buffer_new) {
|
||||
audio_frame2 *uncompressed = buffer_new;
|
||||
audio_frame2 *compressed = NULL;
|
||||
while((compressed = audio_codec_compress(s->audio_coder, uncompressed))) {
|
||||
audio_frame2 *uncompressed = &buffer_new;
|
||||
const audio_frame2 *compressed = NULL;
|
||||
while((compressed = audio_codec_compress(s->audio_coder, uncompressed))) {
|
||||
//TODO to be dynamic as a function of the selected codec, now only accepting mulaw without checking errors
|
||||
audio_tx_send_standard(s->tx_session, s->audio_network_device, compressed);
|
||||
uncompressed = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_JACK_TRANS
|
||||
@@ -869,7 +877,6 @@ static void *audio_sender_thread(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
audio_frame2_free(buffer_new);
|
||||
if(resample_state.resampler) {
|
||||
speex_resampler_destroy(resample_state.resampler);
|
||||
}
|
||||
@@ -894,7 +901,7 @@ void audio_register_put_callback(struct state_audio *s, void (*callback)(void *,
|
||||
if(!audio_playback_get_display_flags(s->audio_playback_device))
|
||||
return;
|
||||
|
||||
sdi_playback = audio_playback_get_state_pointer(s->audio_playback_device);
|
||||
sdi_playback = (struct state_sdi_playback *) audio_playback_get_state_pointer(s->audio_playback_device);
|
||||
sdi_register_put_callback(sdi_playback, callback, udata);
|
||||
}
|
||||
|
||||
@@ -906,7 +913,7 @@ void audio_register_reconfigure_callback(struct state_audio *s, int (*callback)(
|
||||
if(!audio_playback_get_display_flags(s->audio_playback_device))
|
||||
return;
|
||||
|
||||
sdi_playback = audio_playback_get_state_pointer(s->audio_playback_device);
|
||||
sdi_playback = (struct state_sdi_playback *) audio_playback_get_state_pointer(s->audio_playback_device);
|
||||
sdi_register_reconfigure_callback(sdi_playback, callback, udata);
|
||||
}
|
||||
|
||||
@@ -928,4 +935,9 @@ struct audio_desc audio_desc_from_frame(struct audio_frame *frame)
|
||||
frame->ch_count, AC_PCM };
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const audio_desc& desc)
|
||||
{
|
||||
os << desc.ch_count << " channels, " << desc.bps << " Bps, " << desc.sample_rate << " Hz, codec: " << get_name_to_audio_codec(desc.codec);
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -49,14 +49,8 @@
|
||||
#ifndef _AUDIO_H_
|
||||
#define _AUDIO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PORT_AUDIO 5006
|
||||
|
||||
#define MAX_AUDIO_CHANNELS 32
|
||||
|
||||
extern int audio_init_state_ok;
|
||||
|
||||
typedef enum {
|
||||
@@ -80,6 +74,11 @@ struct audio_desc {
|
||||
audio_codec_t codec;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <ostream>
|
||||
std::ostream& operator<<(std::ostream& os, const audio_desc& desc);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @deprecated use audio_frame2 instead
|
||||
*/
|
||||
@@ -98,24 +97,56 @@ typedef struct
|
||||
{
|
||||
int bps; /* bytes per sample */
|
||||
int sample_rate;
|
||||
char *data[MAX_AUDIO_CHANNELS]; /* data should be at least 4B aligned */
|
||||
int data_len[MAX_AUDIO_CHANNELS]; /* size of useful data in buffer */
|
||||
int ch_count; /* count of channels */
|
||||
unsigned int max_size; /* maximal size of data in buffer */
|
||||
audio_codec_t codec;
|
||||
} audio_frame2;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int bps; /* bytes per sample */
|
||||
int sample_rate;
|
||||
char *data; /* data should be at least 4B aligned */
|
||||
const char *data; /* data should be at least 4B aligned */
|
||||
int data_len; /* size of useful data in buffer */
|
||||
audio_codec_t codec;
|
||||
double duration;
|
||||
} audio_channel;
|
||||
|
||||
struct module;
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class audio_frame2
|
||||
{
|
||||
public:
|
||||
audio_frame2();
|
||||
audio_frame2(audio_frame2&& other) = default;
|
||||
audio_frame2(struct audio_frame *);
|
||||
audio_frame2& operator=(audio_frame2&& other) = default;
|
||||
void init(int nr_channels, audio_codec_t codec, int bps, int sample_rate);
|
||||
void append(audio_frame2 const &frame);
|
||||
void append(int channel, const char *data, size_t length);
|
||||
void replace(int channel, size_t offset, const char *data, size_t length);
|
||||
void resize(int channel, size_t len);
|
||||
void reset();
|
||||
int get_bps() const;
|
||||
audio_codec_t get_codec() const;
|
||||
const char *get_data(int channel) const;
|
||||
size_t get_data_len(int channel) const;
|
||||
double get_duration() const;
|
||||
int get_channel_count() const;
|
||||
int get_sample_count() const;
|
||||
int get_sample_rate() const;
|
||||
bool has_same_prop_as(audio_frame2 const &frame) const;
|
||||
void set_duration(double duration);
|
||||
private:
|
||||
int bps; /* bytes per sample */
|
||||
int sample_rate;
|
||||
std::vector<std::pair<std::unique_ptr<char []>, size_t> > channels; /* data should be at least 4B aligned */
|
||||
audio_codec_t codec;
|
||||
double duration;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct state_audio * audio_cfg_init(struct module *parent, const char *addrs, int recv_port, int send_port,
|
||||
const char *send_cfg, const char *recv_cfg,
|
||||
char *jack_cfg, const char *fec_cfg, const char *encryption,
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct state_audio_playback;
|
||||
|
||||
@@ -78,5 +81,9 @@ void audio_register_reconfigure_callback(struct state_audio *s, int (*callback)(
|
||||
*/
|
||||
void *audio_playback_get_state_pointer(struct state_audio_playback *s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vim: set expandtab: sw=8 */
|
||||
|
||||
|
||||
@@ -316,7 +316,7 @@ void * audio_cap_ca_init(char *cfg)
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
|
||||
#if MACOSX_VERSION_MAJOR > 9
|
||||
#if OS_VERSION_MAJOR > 9
|
||||
comp = AudioComponentFindNext(NULL, &desc);
|
||||
if(!comp) {
|
||||
fprintf(stderr, "Error finding AUHAL component.\n");
|
||||
|
||||
@@ -73,6 +73,7 @@ struct state_jack_capture {
|
||||
char *tmp;
|
||||
|
||||
struct ring_buffer *data;
|
||||
bool can_process;
|
||||
};
|
||||
|
||||
static int jack_samplerate_changed_callback(jack_nframes_t nframes, void *arg)
|
||||
@@ -90,6 +91,10 @@ static int jack_process_callback(jack_nframes_t nframes, void *arg)
|
||||
int i;
|
||||
int channel_size = nframes * sizeof(int32_t);
|
||||
|
||||
if (!s->can_process) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < s->frame.ch_count; ++i) {
|
||||
jack_default_audio_sample_t *in = jack_port_get_buffer(s->input_ports[i], nframes);
|
||||
float2int((char *) in, (char *) in, channel_size);
|
||||
@@ -112,7 +117,7 @@ void audio_cap_jack_help(const char *driver_name)
|
||||
int channel_count;
|
||||
|
||||
client = jack_client_open(PACKAGE_STRING, JackNullOption, &status);
|
||||
if(status == JackFailure) {
|
||||
if(status & JackFailure) {
|
||||
fprintf(stderr, "[JACK capture] Opening JACK client failed.\n");
|
||||
return;
|
||||
}
|
||||
@@ -172,7 +177,7 @@ void * audio_cap_jack_init(char *cfg)
|
||||
}
|
||||
|
||||
s->client = jack_client_open(PACKAGE_STRING, JackNullOption, &status);
|
||||
if(status == JackFailure) {
|
||||
if(status & JackFailure) {
|
||||
fprintf(stderr, "[JACK capture] Opening JACK client failed.\n");
|
||||
goto error;
|
||||
}
|
||||
@@ -234,6 +239,8 @@ void * audio_cap_jack_init(char *cfg)
|
||||
|
||||
free(ports);
|
||||
|
||||
s->can_process = true;
|
||||
|
||||
return s;
|
||||
|
||||
release_client:
|
||||
|
||||
@@ -226,6 +226,7 @@ void * portaudio_capture_init(char *cfg)
|
||||
{
|
||||
printf("error initializing portaudio\n");
|
||||
printf("\tPortAudio error: %s\n", Pa_GetErrorText( error ) );
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//void audio_sdi_send(struct state_audio *s, struct audio_frame *frame);
|
||||
//int audio_does_send_sdi(struct state_audio *s);
|
||||
struct audio_frame;
|
||||
@@ -60,6 +64,9 @@ struct audio_frame * sdi_read(void *state);
|
||||
/* SDI specific API */
|
||||
void sdi_capture_new_incoming_frame(void *state, struct audio_frame *frame);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vim: set expandtab: sw=8 */
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ struct state_audio_capture_testcard {
|
||||
void audio_cap_testcard_help(const char *driver_name)
|
||||
{
|
||||
UNUSED(driver_name);
|
||||
printf("\ttestcard : Testing sound signal (sine at 440 Hz)\n");
|
||||
printf("\ttestcard : Testing sound signal\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,6 +189,8 @@ void * audio_cap_testcard_init(char *cfg)
|
||||
int ret = read_wav_header(wav, &metadata);
|
||||
if(ret != WAV_HDR_PARSE_OK) {
|
||||
print_wav_error(ret);
|
||||
fclose(wav);
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
s->audio.bps = metadata.bits_per_sample / 8;
|
||||
|
||||
@@ -60,24 +60,24 @@
|
||||
|
||||
#include "lib_common.h"
|
||||
|
||||
#define MAX_AUDIO_CODECS 20
|
||||
#include <unordered_map>
|
||||
|
||||
const int max_audio_codecs = MAX_AUDIO_CODECS;
|
||||
static constexpr int MAX_AUDIO_CODECS = 20;
|
||||
|
||||
audio_codec_info_t audio_codec_info[] = {
|
||||
[AC_NONE] = { "(none)", 0 },
|
||||
[AC_PCM] = { "PCM", 0x0001 },
|
||||
[AC_ALAW] = { "A-law", 0x0006 },
|
||||
[AC_MULAW] = { "u-law", 0x0007 },
|
||||
[AC_ADPCM_IMA_WAV] = { "ADPCM", 0x0011 },
|
||||
[AC_SPEEX] = { "speex", 0xA109 },
|
||||
[AC_OPUS] = { "OPUS", 0x7375704F }, // == Opus, the TwoCC isn't defined
|
||||
[AC_G722] = { "G.722", 0x028F },
|
||||
[AC_G726] = { "G.726", 0x0045 },
|
||||
using namespace std;
|
||||
|
||||
unordered_map<audio_codec_t, audio_codec_info_t, hash<int>> audio_codec_info = {
|
||||
{AC_NONE, { "(none)", 0 }},
|
||||
{AC_PCM, { "PCM", 0x0001 }},
|
||||
{AC_ALAW, { "A-law", 0x0006 }},
|
||||
{AC_MULAW, { "u-law", 0x0007 }},
|
||||
{AC_ADPCM_IMA_WAV, { "ADPCM", 0x0011 }},
|
||||
{AC_SPEEX, { "speex", 0xA109 }},
|
||||
{AC_OPUS, { "OPUS", 0x7375704F }}, // == Opus, the TwoCC isn't defined
|
||||
{AC_G722, { "G.722", 0x028F }},
|
||||
{AC_G726, { "G.726", 0x0045 }},
|
||||
};
|
||||
|
||||
int audio_codec_info_len = sizeof(audio_codec_info)/sizeof(audio_codec_info_t);
|
||||
|
||||
#ifdef BUILD_LIBRARIES
|
||||
static pthread_once_t libraries_initialized = PTHREAD_ONCE_INIT;
|
||||
static void load_libraries(void);
|
||||
@@ -89,11 +89,8 @@ static struct audio_codec *audio_codecs[MAX_AUDIO_CODECS] = {
|
||||
};
|
||||
static struct audio_codec_state *audio_codec_init_real(const char *audio_codec_cfg,
|
||||
audio_codec_direction_t direction, bool try_init);
|
||||
static void register_audio_codec_real(struct audio_codec *);
|
||||
|
||||
void (*register_audio_codec)(struct audio_codec *) = register_audio_codec_real;
|
||||
|
||||
static void register_audio_codec_real(struct audio_codec *codec)
|
||||
void register_audio_codec(struct audio_codec *codec)
|
||||
{
|
||||
for(int i = 0; i < MAX_AUDIO_CODECS; ++i) {
|
||||
if(audio_codecs[i] == 0) {
|
||||
@@ -119,11 +116,11 @@ void list_audio_codecs(void) {
|
||||
printf("\t--audio-codec <audio_codec>[:sample_rate=<sampling_rate>][:bitrate=<bitrate>]\n");
|
||||
printf("\n");
|
||||
printf("Supported audio codecs:\n");
|
||||
for(int i = 0; i < audio_codec_info_len; ++i) {
|
||||
if(i != AC_NONE) {
|
||||
printf("\t%s", audio_codec_info[i].name);
|
||||
for (auto const &it : audio_codec_info) {
|
||||
if(it.first != AC_NONE) {
|
||||
printf("\t%s", it.second.name);
|
||||
struct audio_codec_state *st = (struct audio_codec_state *)
|
||||
audio_codec_init_real(get_name_to_audio_codec((audio_codec_t) i),
|
||||
audio_codec_init_real(get_name_to_audio_codec(it.first),
|
||||
AUDIO_CODER, true);
|
||||
if(!st) {
|
||||
printf(" - unavailable");
|
||||
@@ -148,17 +145,17 @@ static void load_libraries(void)
|
||||
|
||||
struct audio_codec_state *audio_codec_init(audio_codec_t audio_codec,
|
||||
audio_codec_direction_t direction) {
|
||||
return audio_codec_init_real(get_name_to_audio_codec(audio_codec), direction, true);
|
||||
return audio_codec_init_real(get_name_to_audio_codec(audio_codec), direction, false);
|
||||
}
|
||||
|
||||
struct audio_codec_state *audio_codec_init_cfg(const char *audio_codec_cfg,
|
||||
audio_codec_direction_t direction) {
|
||||
return audio_codec_init_real(audio_codec_cfg, direction, true);
|
||||
return audio_codec_init_real(audio_codec_cfg, direction, false);
|
||||
}
|
||||
|
||||
|
||||
static struct audio_codec_state *audio_codec_init_real(const char *audio_codec_cfg,
|
||||
audio_codec_direction_t direction, bool try_init) {
|
||||
audio_codec_direction_t direction, bool silent) {
|
||||
audio_codec_t audio_codec = get_audio_codec(audio_codec_cfg);
|
||||
int bitrate = get_audio_codec_bitrate(audio_codec_cfg);
|
||||
void *state = NULL;
|
||||
@@ -171,12 +168,12 @@ static struct audio_codec_state *audio_codec_init_real(const char *audio_codec_c
|
||||
continue;
|
||||
for(unsigned int j = 0; audio_codecs[i]->supported_codecs[j] != AC_NONE; ++j) {
|
||||
if(audio_codecs[i]->supported_codecs[j] == audio_codec) {
|
||||
state = audio_codecs[i]->init(audio_codec, direction, try_init, bitrate);
|
||||
state = audio_codecs[i]->init(audio_codec, direction, silent, bitrate);
|
||||
index = i;
|
||||
if(state) {
|
||||
break;
|
||||
} else {
|
||||
if(!try_init) {
|
||||
if (!silent) {
|
||||
fprintf(stderr, "Error: initialization of audio codec failed!\n");
|
||||
}
|
||||
}
|
||||
@@ -187,7 +184,7 @@ static struct audio_codec_state *audio_codec_init_real(const char *audio_codec_c
|
||||
}
|
||||
|
||||
if(!state) {
|
||||
if (!try_init) {
|
||||
if (!silent) {
|
||||
fprintf(stderr, "Unable to find encoder for audio codec '%s'\n",
|
||||
get_name_to_audio_codec(audio_codec));
|
||||
}
|
||||
@@ -196,7 +193,7 @@ static struct audio_codec_state *audio_codec_init_real(const char *audio_codec_c
|
||||
|
||||
struct audio_codec_state *s = (struct audio_codec_state *) malloc(sizeof(struct audio_codec_state));
|
||||
|
||||
s->state = (void **) calloc(1, sizeof(void**));
|
||||
s->state = (void **) calloc(1, sizeof(void*));
|
||||
s->state[0] = state;
|
||||
s->state_count = 1;
|
||||
s->index = index;
|
||||
@@ -204,8 +201,7 @@ static struct audio_codec_state *audio_codec_init_real(const char *audio_codec_c
|
||||
s->direction = direction;
|
||||
s->bitrate = bitrate;
|
||||
|
||||
s->out = audio_frame2_init();
|
||||
s->out->ch_count = 1;
|
||||
s->out = new audio_frame2;
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -229,34 +225,44 @@ struct audio_codec_state *audio_codec_reconfigure(struct audio_codec_state *old,
|
||||
* @retval pointer pointing to data
|
||||
* @retval NULL indicating that there are no data left
|
||||
*/
|
||||
audio_frame2 *audio_codec_compress(struct audio_codec_state *s, audio_frame2 *frame)
|
||||
const audio_frame2 *audio_codec_compress(struct audio_codec_state *s, const audio_frame2 *frame)
|
||||
{
|
||||
if(frame && s->state_count < frame->ch_count) {
|
||||
s->state = (void **) realloc(s->state, sizeof(void **) * frame->ch_count);
|
||||
for(int i = s->state_count; i < frame->ch_count; ++i) {
|
||||
if(frame && s->state_count < frame->get_channel_count()) {
|
||||
s->state = (void **) realloc(s->state, sizeof(void *) * frame->get_channel_count());
|
||||
for(int i = s->state_count; i < frame->get_channel_count(); ++i) {
|
||||
s->state[i] = audio_codecs[s->index]->init(s->codec, s->direction, false, s->bitrate);
|
||||
if(s->state[i] == NULL) {
|
||||
fprintf(stderr, "Error: initialization of audio codec failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
s->state_count = frame->ch_count;
|
||||
s->out->ch_count = frame->ch_count;
|
||||
s->state_count = frame->get_channel_count();
|
||||
}
|
||||
|
||||
audio_channel channel;
|
||||
int nonzero_channels = 0;
|
||||
for(int i = 0; i < s->state_count; ++i) {
|
||||
bool out_frame_initialized = false;
|
||||
for (int i = 0; i < s->state_count; ++i) {
|
||||
audio_channel *encode_channel = NULL;
|
||||
if(frame) {
|
||||
audio_channel_demux(frame, i, &channel);
|
||||
encode_channel = &channel;
|
||||
}
|
||||
audio_channel *out = audio_codecs[s->index]->compress(s->state[i], encode_channel);
|
||||
if(!out) {
|
||||
s->out->data_len[i] = 0;
|
||||
} else {
|
||||
audio_channel_mux(s->out, i, out);
|
||||
if (out) {
|
||||
if (!out_frame_initialized) {
|
||||
if (frame) {
|
||||
s->out->init(frame->get_channel_count(), s->codec, out->bps, out->sample_rate);
|
||||
} else {
|
||||
s->out->reset();
|
||||
}
|
||||
s->out->set_duration(out->duration);
|
||||
out_frame_initialized = true;
|
||||
} else {
|
||||
assert(out->bps == s->out->get_bps()
|
||||
&& out->sample_rate == s->out->get_sample_rate());
|
||||
}
|
||||
s->out->append(i, out->data, out->data_len);
|
||||
nonzero_channels += 1;
|
||||
}
|
||||
}
|
||||
@@ -270,41 +276,51 @@ audio_frame2 *audio_codec_compress(struct audio_codec_state *s, audio_frame2 *fr
|
||||
|
||||
audio_frame2 *audio_codec_decompress(struct audio_codec_state *s, audio_frame2 *frame)
|
||||
{
|
||||
if(s->state_count < frame->ch_count) {
|
||||
s->state = (void **) realloc(s->state, sizeof(void **) * frame->ch_count);
|
||||
for(int i = s->state_count; i < frame->ch_count; ++i) {
|
||||
if (s->state_count < frame->get_channel_count()) {
|
||||
s->state = (void **) realloc(s->state, sizeof(void *) * frame->get_channel_count());
|
||||
for(int i = s->state_count; i < frame->get_channel_count(); ++i) {
|
||||
s->state[i] = audio_codecs[s->index]->init(s->codec, s->direction, false, 0);
|
||||
if(s->state[i] == NULL) {
|
||||
fprintf(stderr, "Error: initialization of audio codec failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
s->state_count = frame->ch_count;
|
||||
s->state_count = frame->get_channel_count();
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (s->out->ch_count != frame->ch_count) {
|
||||
s->out->ch_count = frame->ch_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
audio_channel channel;
|
||||
int nonzero_channels = 0;
|
||||
for(int i = 0; i < frame->ch_count; ++i) {
|
||||
bool out_frame_initialized = false;
|
||||
for (int i = 0; i < frame->get_channel_count(); ++i) {
|
||||
audio_channel_demux(frame, i, &channel);
|
||||
audio_channel *out = audio_codecs[s->index]->decompress(s->state[i], &channel);
|
||||
if(out) {
|
||||
audio_channel_mux(s->out, i, out);
|
||||
if (out) {
|
||||
if (!out_frame_initialized) {
|
||||
s->out->init(frame->get_channel_count(), AC_PCM, out->bps, out->sample_rate);
|
||||
out_frame_initialized = true;
|
||||
} else {
|
||||
assert(out->bps == s->out->get_bps()
|
||||
&& out->sample_rate == s->out->get_sample_rate());
|
||||
}
|
||||
s->out->append(i, out->data, out->data_len);
|
||||
nonzero_channels += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(nonzero_channels != frame->ch_count) {
|
||||
if(nonzero_channels != frame->get_channel_count()) {
|
||||
fprintf(stderr, "[Audio decompress] Empty channel returned !\n");
|
||||
return NULL;
|
||||
}
|
||||
for(int i = 0; i < frame->ch_count; ++i) {
|
||||
if(s->out->data_len[i] != s->out->data_len[0]) {
|
||||
fprintf(stderr, "[Audio decompress] Inequal channel lenghth detected (%d vs %d)!\n",
|
||||
s->out->data_len[0], s->out->data_len[i]);
|
||||
for(int i = 1; i < frame->get_channel_count(); ++i) {
|
||||
if(s->out->get_data_len(i) != s->out->get_data_len(0)) {
|
||||
fprintf(stderr, "[Audio decompress] Inequal channel lenghth detected (%zd vs %zd)!\n",
|
||||
s->out->get_data_len(0), s->out->get_data_len(i));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -321,10 +337,7 @@ void audio_codec_done(struct audio_codec_state *s)
|
||||
}
|
||||
free(s->state);
|
||||
|
||||
for(int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
|
||||
s->out->data[i] = NULL;
|
||||
}
|
||||
audio_frame2_free(s->out);
|
||||
delete s->out;
|
||||
free(s);
|
||||
}
|
||||
|
||||
@@ -338,10 +351,10 @@ audio_codec_t get_audio_codec(const char *codec_str) {
|
||||
if (strchr(codec, ':')) {
|
||||
*strchr(codec, ':') = '\0';
|
||||
}
|
||||
for(int i = 0; i < audio_codec_info_len; ++i) {
|
||||
if(strcasecmp(audio_codec_info[i].name, codec) == 0) {
|
||||
for (auto const &it : audio_codec_info) {
|
||||
if(strcasecmp(it.second.name, codec) == 0) {
|
||||
free(codec);
|
||||
return (audio_codec_t) i;
|
||||
return it.first;
|
||||
}
|
||||
}
|
||||
free(codec);
|
||||
@@ -404,9 +417,9 @@ uint32_t get_audio_tag(audio_codec_t codec)
|
||||
|
||||
audio_codec_t get_audio_codec_to_tag(uint32_t tag)
|
||||
{
|
||||
for(int i = 0; i < audio_codec_info_len; ++i) {
|
||||
if(audio_codec_info[i].tag == tag) {
|
||||
return (audio_codec_t) i;
|
||||
for (auto const &it : audio_codec_info) {
|
||||
if(it.second.tag == tag) {
|
||||
return it.first;
|
||||
}
|
||||
}
|
||||
return AC_NONE;
|
||||
@@ -51,9 +51,6 @@
|
||||
|
||||
#include "audio/audio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
AUDIO_CODER,
|
||||
@@ -69,8 +66,7 @@ struct audio_codec {
|
||||
void (*done)(void *);
|
||||
};
|
||||
|
||||
extern void (*register_audio_codec)(struct audio_codec *);
|
||||
|
||||
void register_audio_codec(struct audio_codec *);
|
||||
typedef struct {
|
||||
const char *name;
|
||||
/** @var tag
|
||||
@@ -79,16 +75,14 @@ typedef struct {
|
||||
uint32_t tag;
|
||||
} audio_codec_info_t;
|
||||
|
||||
extern audio_codec_info_t audio_codec_info[];
|
||||
extern int audio_codec_info_len;
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct audio_codec_state;
|
||||
|
||||
struct audio_codec_state *audio_codec_init(audio_codec_t audio_codec, audio_codec_direction_t);
|
||||
struct audio_codec_state *audio_codec_init_cfg(const char *audio_codec_cfg, audio_codec_direction_t);
|
||||
struct audio_codec_state *audio_codec_reconfigure(struct audio_codec_state *old,
|
||||
audio_codec_t audio_codec, audio_codec_direction_t);
|
||||
audio_frame2 *audio_codec_compress(struct audio_codec_state *, audio_frame2 *);
|
||||
const audio_frame2 *audio_codec_compress(struct audio_codec_state *, const audio_frame2 *);
|
||||
audio_frame2 *audio_codec_decompress(struct audio_codec_state *, audio_frame2 *);
|
||||
const int *audio_codec_get_supported_bps(struct audio_codec_state *);
|
||||
void audio_codec_done(struct audio_codec_state *);
|
||||
@@ -101,9 +95,6 @@ int get_audio_codec_bitrate(const char *audio_codec_cfg);
|
||||
const char *get_name_to_audio_codec(audio_codec_t codec);
|
||||
uint32_t get_audio_tag(audio_codec_t codec);
|
||||
audio_codec_t get_audio_codec_to_tag(uint32_t audio_tag);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AUDIO_CODEC_H */
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config_unix.h"
|
||||
@@ -54,12 +56,17 @@
|
||||
|
||||
#include "audio/codec/libavcodec.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 54
|
||||
#include <libavutil/channel_layout.h>
|
||||
#endif
|
||||
#include <libavutil/mem.h>
|
||||
}
|
||||
|
||||
#include <unordered_map>
|
||||
#include "audio/audio.h"
|
||||
#include "audio/codec.h"
|
||||
#include "audio/utils.h"
|
||||
@@ -78,34 +85,31 @@
|
||||
#define AV_CODEC_ID_ADPCM_G726 CODEC_ID_ADPCM_G726
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
static void *libavcodec_init(audio_codec_t audio_codec, audio_codec_direction_t direction,
|
||||
bool try_init, int bitrate);
|
||||
static audio_channel *libavcodec_compress(void *, audio_channel *);
|
||||
static audio_channel *libavcodec_decompress(void *, audio_channel *);
|
||||
static void libavcodec_done(void *);
|
||||
|
||||
static void init(void) __attribute__((constructor));
|
||||
static void register_module(void) __attribute__((constructor));
|
||||
|
||||
static void init(void)
|
||||
static void register_module(void)
|
||||
{
|
||||
register_audio_codec(&libavcodec_audio_codec);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int codec_id;
|
||||
} audio_codec_t_to_codec_id_mapping_t;
|
||||
|
||||
static const audio_codec_t_to_codec_id_mapping_t mapping[] =
|
||||
{
|
||||
[AC_ALAW] = { .codec_id = AV_CODEC_ID_PCM_ALAW },
|
||||
[AC_MULAW] = { .codec_id = AV_CODEC_ID_PCM_MULAW },
|
||||
[AC_ADPCM_IMA_WAV] = { .codec_id = AV_CODEC_ID_ADPCM_IMA_WAV },
|
||||
[AC_SPEEX] = { .codec_id = AV_CODEC_ID_SPEEX },
|
||||
std::unordered_map<audio_codec_t, AVCodecID, std::hash<int>> mapping {
|
||||
{ AC_ALAW, AV_CODEC_ID_PCM_ALAW },
|
||||
{ AC_MULAW, AV_CODEC_ID_PCM_MULAW },
|
||||
{ AC_ADPCM_IMA_WAV, AV_CODEC_ID_ADPCM_IMA_WAV },
|
||||
{ AC_SPEEX, AV_CODEC_ID_SPEEX },
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 54
|
||||
[AC_OPUS] = { .codec_id = AV_CODEC_ID_OPUS },
|
||||
{ AC_OPUS, AV_CODEC_ID_OPUS },
|
||||
#endif
|
||||
[AC_G722] = { .codec_id = AV_CODEC_ID_ADPCM_G722 },
|
||||
[AC_G726] = { .codec_id = AV_CODEC_ID_ADPCM_G726 },
|
||||
{ AC_G722, AV_CODEC_ID_ADPCM_G722 },
|
||||
{ AC_G726, AV_CODEC_ID_ADPCM_G726 },
|
||||
};
|
||||
|
||||
struct libavcodec_codec_state {
|
||||
@@ -140,22 +144,24 @@ struct libavcodec_codec_state {
|
||||
static void *libavcodec_init(audio_codec_t audio_codec, audio_codec_direction_t direction, bool try_init,
|
||||
int bitrate)
|
||||
{
|
||||
int codec_id = 0;
|
||||
enum AVCodecID codec_id = AV_CODEC_ID_NONE;
|
||||
|
||||
auto it = mapping.find(audio_codec);
|
||||
|
||||
if(audio_codec <= sizeof(mapping) / sizeof(audio_codec_t_to_codec_id_mapping_t)) {
|
||||
codec_id = mapping[audio_codec].codec_id;
|
||||
}
|
||||
if(codec_id == 0) {
|
||||
if (it == mapping.end()) {
|
||||
if (!try_init) {
|
||||
fprintf(stderr, "[Libavcodec] Cannot find mapping for codec \"%s\"!\n",
|
||||
get_name_to_audio_codec(audio_codec));
|
||||
}
|
||||
return NULL;
|
||||
} else {
|
||||
codec_id = it->second;
|
||||
}
|
||||
|
||||
avcodec_register_all();
|
||||
|
||||
struct libavcodec_codec_state *s = calloc(1, sizeof(struct libavcodec_codec_state));
|
||||
struct libavcodec_codec_state *s = (struct libavcodec_codec_state *)
|
||||
calloc(1, sizeof(struct libavcodec_codec_state));
|
||||
if(direction == AUDIO_CODER) {
|
||||
s->codec = avcodec_find_encoder(codec_id);
|
||||
} else {
|
||||
@@ -166,6 +172,7 @@ static void *libavcodec_init(audio_codec_t audio_codec, audio_codec_direction_t
|
||||
fprintf(stderr, "Your Libavcodec build doesn't contain codec \"%s\".\n",
|
||||
get_name_to_audio_codec(audio_codec));
|
||||
}
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -176,6 +183,7 @@ static void *libavcodec_init(audio_codec_t audio_codec, audio_codec_direction_t
|
||||
if (!try_init) {
|
||||
fprintf(stderr, "Could not allocate audio codec context\n");
|
||||
}
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -187,12 +195,12 @@ static void *libavcodec_init(audio_codec_t audio_codec, audio_codec_direction_t
|
||||
s->pkt.size = 0;
|
||||
s->pkt.data = NULL;
|
||||
|
||||
s->av_frame = avcodec_alloc_frame();
|
||||
s->av_frame = av_frame_alloc();
|
||||
|
||||
memset(&s->tmp, 0, sizeof(audio_channel));
|
||||
memset(&s->output_channel, 0, sizeof(audio_channel));
|
||||
s->tmp.data = malloc(1024*1024);
|
||||
s->output_channel.data = malloc(1024*1024);
|
||||
s->tmp.data = (char *) malloc(1024*1024);
|
||||
s->output_channel.data = (char *) malloc(1024*1024);
|
||||
|
||||
if(direction == AUDIO_CODER) {
|
||||
s->output_channel.codec = audio_codec;
|
||||
@@ -268,6 +276,7 @@ static bool reinitialize_coder(struct libavcodec_codec_state *s, struct audio_de
|
||||
s->av_frame->format = s->codec_ctx->sample_fmt;
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 54
|
||||
s->av_frame->channel_layout = AV_CH_LAYOUT_MONO;
|
||||
s->av_frame->sample_rate = s->codec_ctx->sample_rate;
|
||||
#endif
|
||||
|
||||
int channels = 1;
|
||||
@@ -292,7 +301,6 @@ static bool reinitialize_coder(struct libavcodec_codec_state *s, struct audio_de
|
||||
|
||||
s->output_channel.sample_rate = desc.sample_rate;
|
||||
s->output_channel.bps = desc.bps;
|
||||
|
||||
s->saved_desc = desc;
|
||||
|
||||
return true;
|
||||
@@ -322,8 +330,6 @@ static bool reinitialize_decoder(struct libavcodec_codec_state *s, struct audio_
|
||||
s->output_channel.bps = desc.bps;
|
||||
s->saved_desc = desc;
|
||||
|
||||
s->output_channel.bps = av_get_bytes_per_sample(s->codec_ctx->sample_fmt);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -341,18 +347,20 @@ static audio_channel *libavcodec_compress(void *state, audio_channel * channel)
|
||||
}
|
||||
|
||||
if(s->change_bps_to) {
|
||||
change_bps(s->tmp.data, s->saved_desc.bps, channel->data,
|
||||
change_bps((char *) s->tmp.data, s->saved_desc.bps, channel->data,
|
||||
s->change_bps_to, channel->data_len);
|
||||
s->tmp.data_len += channel->data_len / s->saved_desc.bps * s->change_bps_to;
|
||||
} else {
|
||||
memcpy(s->tmp.data + s->tmp.data_len, channel->data, channel->data_len);
|
||||
memcpy((char *) s->tmp.data + s->tmp.data_len, channel->data, channel->data_len);
|
||||
s->tmp.data_len += channel->data_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int bps = s->output_channel.bps;
|
||||
int offset = 0;
|
||||
s->output_channel.data_len = 0;
|
||||
s->output_channel.duration = 0.0;
|
||||
int chunk_size = s->codec_ctx->frame_size * bps;
|
||||
//while(offset + chunk_size <= s->tmp.data_len) {
|
||||
while(offset + chunk_size <= s->tmp.data_len) {
|
||||
@@ -370,6 +378,10 @@ static audio_channel *libavcodec_compress(void *state, audio_channel * channel)
|
||||
}
|
||||
if(got_packet) {
|
||||
s->output_channel.data_len += s->pkt.size;
|
||||
///@ todo
|
||||
/// well, this is wrong, denominator should be actually AVStream::time_base. Where do
|
||||
/// we get this?? Anyway, seems like it equals sample rate.
|
||||
s->output_channel.duration += s->pkt.duration / (double) s->output_channel.sample_rate;
|
||||
}
|
||||
offset += chunk_size;
|
||||
if(!(s->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE))
|
||||
@@ -377,7 +389,7 @@ static audio_channel *libavcodec_compress(void *state, audio_channel * channel)
|
||||
}
|
||||
|
||||
s->tmp.data_len -= offset;
|
||||
memmove(s->tmp.data, s->tmp.data + offset, s->tmp.data_len);
|
||||
memmove((char *) s->tmp.data, s->tmp.data + offset, s->tmp.data_len);
|
||||
|
||||
///fprintf(stderr, "%d %d\n", i++% 2, s->output_channel.data_len);
|
||||
if(s->output_channel.data_len) {
|
||||
@@ -406,7 +418,7 @@ static audio_channel *libavcodec_decompress(void *state, audio_channel * channel
|
||||
while (s->pkt.size > 0) {
|
||||
int got_frame = 0;
|
||||
|
||||
avcodec_get_frame_defaults(s->av_frame);
|
||||
av_frame_unref(s->av_frame);
|
||||
|
||||
int len = avcodec_decode_audio4(s->codec_ctx, s->av_frame, &got_frame,
|
||||
&s->pkt);
|
||||
@@ -420,13 +432,14 @@ static audio_channel *libavcodec_decompress(void *state, audio_channel * channel
|
||||
int data_size = av_samples_get_buffer_size(NULL, channels,
|
||||
s->av_frame->nb_samples,
|
||||
s->codec_ctx->sample_fmt, 1);
|
||||
memcpy(s->output_channel.data + offset, s->av_frame->data[0],
|
||||
memcpy((char *) s->output_channel.data + offset, s->av_frame->data[0],
|
||||
data_size);
|
||||
offset += len;
|
||||
s->output_channel.data_len += data_size;
|
||||
}
|
||||
s->pkt.size -= len;
|
||||
s->pkt.data += len;
|
||||
s->pkt.dts = s->pkt.pts = AV_NOPTS_VALUE;
|
||||
#if 0
|
||||
if (s->pkt.size < AUDIO_REFILL_THRESH) {
|
||||
/* Refill the input buffer, to avoid trying to decode
|
||||
@@ -443,6 +456,42 @@ static audio_channel *libavcodec_decompress(void *state, audio_channel * channel
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// perform needed conversions (float->int32, int32->dest_bps)
|
||||
//
|
||||
assert(av_get_packed_sample_fmt(s->codec_ctx->sample_fmt) != AV_SAMPLE_FMT_DBL); // not supported yet
|
||||
|
||||
unique_ptr<char []> int32_data;
|
||||
unique_ptr<char []> out_bps_data;
|
||||
const char *int_input_data;
|
||||
const char *output_data = NULL;
|
||||
int in_bps;
|
||||
// convert from float if needed
|
||||
if (av_get_packed_sample_fmt(s->codec_ctx->sample_fmt) == AV_SAMPLE_FMT_FLT) {
|
||||
int32_data = unique_ptr<char []>(new char [s->output_channel.data_len]);
|
||||
float2int(int32_data.get(), s->output_channel.data, s->output_channel.data_len);
|
||||
output_data = int_input_data = int32_data.get();
|
||||
in_bps = 4;
|
||||
} else {
|
||||
int_input_data = s->output_channel.data;
|
||||
in_bps = av_get_bytes_per_sample(s->codec_ctx->sample_fmt);
|
||||
}
|
||||
|
||||
// convert to appropriate bps
|
||||
if (s->output_channel.bps != in_bps) {
|
||||
int new_data_len = s->output_channel.data_len / in_bps * s->output_channel.bps;
|
||||
out_bps_data = unique_ptr<char []>(new char [new_data_len]);
|
||||
change_bps(out_bps_data.get(), s->output_channel.bps, int_input_data, in_bps,
|
||||
s->output_channel.data_len);
|
||||
output_data = out_bps_data.get();
|
||||
s->output_channel.data_len = new_data_len;
|
||||
}
|
||||
|
||||
// copy back if needed
|
||||
if (output_data) {
|
||||
memcpy((char *) s->output_channel.data, output_data, s->output_channel.data_len);
|
||||
}
|
||||
|
||||
return &s->output_channel;
|
||||
}
|
||||
|
||||
@@ -456,25 +505,24 @@ static void libavcodec_done(void *state)
|
||||
pthread_mutex_unlock(s->libav_global_lock);
|
||||
|
||||
rm_release_shared_lock(LAVCD_LOCK_NAME);
|
||||
free(s->output_channel.data);
|
||||
free(s->tmp.data);
|
||||
free((void *) s->output_channel.data);
|
||||
free((void *) s->tmp.data);
|
||||
av_free_packet(&s->pkt);
|
||||
av_freep(&s->samples);
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 54
|
||||
avcodec_free_frame(&s->av_frame);
|
||||
#else
|
||||
av_free(s->av_frame);
|
||||
#endif
|
||||
av_frame_free(&s->av_frame);
|
||||
|
||||
free(s);
|
||||
}
|
||||
|
||||
static audio_codec_t supported_codecs[] = { AC_ALAW, AC_MULAW, AC_ADPCM_IMA_WAV, AC_SPEEX, AC_OPUS, AC_G722, AC_G726, AC_NONE };
|
||||
static int supported_bytes_per_second[] = { 2, 0 };
|
||||
|
||||
struct audio_codec libavcodec_audio_codec = {
|
||||
.supported_codecs = (audio_codec_t[]){ AC_ALAW, AC_MULAW, AC_ADPCM_IMA_WAV, AC_SPEEX, AC_OPUS, AC_G722, AC_G726, AC_NONE },
|
||||
.supported_bytes_per_second = (int[]){ 2, 0 },
|
||||
.init = libavcodec_init,
|
||||
.compress = libavcodec_compress,
|
||||
.decompress = libavcodec_decompress,
|
||||
.done = libavcodec_done
|
||||
supported_codecs,
|
||||
supported_bytes_per_second,
|
||||
libavcodec_init,
|
||||
libavcodec_compress,
|
||||
libavcodec_decompress,
|
||||
libavcodec_done
|
||||
};
|
||||
|
||||
@@ -51,6 +51,10 @@
|
||||
|
||||
#include "audio/audio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct echo_cancellation;
|
||||
|
||||
typedef struct echo_cancellation echo_cancellation_t;
|
||||
@@ -61,5 +65,8 @@ void echo_play(struct echo_cancellation *state, struct audio_frame *frame);
|
||||
|
||||
struct audio_frame * echo_cancel(struct echo_cancellation *state, struct audio_frame *frame);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ECHO_H_ */
|
||||
|
||||
@@ -250,13 +250,18 @@ static void finalize(struct audio_export *s)
|
||||
{
|
||||
int padding_byte_len = 0;
|
||||
if((s->saved_format.ch_count * s->saved_format.bps * s->total) % 2 == 1) {
|
||||
char padding_byte;
|
||||
char padding_byte = '\0';
|
||||
padding_byte_len = 1;
|
||||
fwrite(&padding_byte, sizeof(padding_byte), 1, s->output);
|
||||
if (fwrite(&padding_byte, sizeof(padding_byte), 1, s->output) != 1) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fseek(s->output, CK_MASTER_SIZE_OFFSET, SEEK_SET);
|
||||
int ret = fseek(s->output, CK_MASTER_SIZE_OFFSET, SEEK_SET);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
uint32_t ck_master_size = 4 + 24 + (8 + s->saved_format.bps *
|
||||
s->saved_format.ch_count * s->total + padding_byte_len);
|
||||
size_t res;
|
||||
@@ -265,7 +270,10 @@ static void finalize(struct audio_export *s)
|
||||
goto error;
|
||||
}
|
||||
|
||||
fseek(s->output, CK_DATA_SIZE_OFFSET, SEEK_SET);
|
||||
ret = fseek(s->output, CK_DATA_SIZE_OFFSET, SEEK_SET);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
uint32_t ck_data_size = s->saved_format.bps *
|
||||
s->saved_format.ch_count * s->total;
|
||||
res = fwrite(&ck_data_size, sizeof(ck_data_size), 1, s->output);
|
||||
|
||||
@@ -49,6 +49,10 @@
|
||||
#ifndef _EXPORT_H_
|
||||
#define _EXPORT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct audio_export;
|
||||
struct audio_frame;
|
||||
|
||||
@@ -56,4 +60,9 @@ struct audio_export * audio_export_init(char *filename);
|
||||
void audio_export_destroy(struct audio_export *state);
|
||||
void audio_export(struct audio_export *state, struct audio_frame *frame);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _EXPORT_H_ */
|
||||
|
||||
@@ -50,10 +50,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "host.h"
|
||||
#include "debug.h"
|
||||
#include "config.h"
|
||||
@@ -74,10 +70,6 @@ extern "C" {
|
||||
#endif
|
||||
#include "DeckLinkAPIVersion.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // END of extern "C"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <objbase.h>
|
||||
#endif
|
||||
@@ -256,7 +248,7 @@ void decklink_playback_help(const char *driver_name)
|
||||
|
||||
void *decklink_playback_init(char *cfg)
|
||||
{
|
||||
struct state_decklink *s;
|
||||
struct state_decklink *s = NULL;
|
||||
IDeckLinkIterator* deckLinkIterator;
|
||||
HRESULT result;
|
||||
IDeckLinkConfiguration* deckLinkConfiguration = NULL;
|
||||
@@ -264,6 +256,11 @@ void *decklink_playback_init(char *cfg)
|
||||
//BMDAudioOutputAnalogAESSwitch audioConnection = (BMDAudioOutputAnalogAESSwitch) 0;
|
||||
int cardIdx = 0;
|
||||
int dnum = 0;
|
||||
IDeckLink *deckLink;
|
||||
IDeckLinkDisplayModeIterator *displayModeIterator = NULL;
|
||||
IDeckLinkDisplayMode *deckLinkDisplayMode = NULL;
|
||||
//BMDDisplayMode displayMode = bmdModeUnknown;
|
||||
int width, height;
|
||||
|
||||
#ifdef WIN32
|
||||
// Initialize COM on this thread
|
||||
@@ -358,14 +355,10 @@ void *decklink_playback_init(char *cfg)
|
||||
fprintf(stderr, "\nA DeckLink iterator could not be created. The DeckLink drivers may not be installed or are outdated.\n");
|
||||
fprintf(stderr, "This UltraGrid version was compiled with DeckLink drivers %s. You should have at least this version.\n\n",
|
||||
BLACKMAGIC_DECKLINK_API_VERSION_STRING);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
s->deckLink = NULL;
|
||||
s->deckLinkOutput = NULL;
|
||||
|
||||
// Connect to the first DeckLink instance
|
||||
IDeckLink *deckLink;
|
||||
while (deckLinkIterator->Next(&deckLink) == S_OK)
|
||||
{
|
||||
if (dnum == cardIdx){
|
||||
@@ -378,15 +371,12 @@ void *decklink_playback_init(char *cfg)
|
||||
|
||||
if(s->deckLink == NULL) {
|
||||
fprintf(stderr, "No DeckLink PCI card #%d found\n", cardIdx);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Obtain the audio/video output interface (IDeckLinkOutput)
|
||||
if (s->deckLink->QueryInterface(IID_IDeckLinkOutput, (void**)&s->deckLinkOutput) != S_OK) {
|
||||
if(s->deckLinkOutput != NULL)
|
||||
s->deckLinkOutput->Release();
|
||||
s->deckLink->Release();
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Query the DeckLink for its configuration interface
|
||||
@@ -394,7 +384,7 @@ void *decklink_playback_init(char *cfg)
|
||||
if (result != S_OK)
|
||||
{
|
||||
printf("Could not obtain the IDeckLinkConfiguration interface: %08x\n", (int) result);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (s->audio_consumer_levels != -1) {
|
||||
@@ -404,17 +394,14 @@ void *decklink_playback_init(char *cfg)
|
||||
fprintf(stderr, "[DeckLink capture] Unable set input audio consumer levels.\n");
|
||||
}
|
||||
}
|
||||
|
||||
IDeckLinkDisplayModeIterator *displayModeIterator;
|
||||
IDeckLinkDisplayMode* deckLinkDisplayMode;
|
||||
//BMDDisplayMode displayMode = bmdModeUnknown;
|
||||
int width, height;
|
||||
deckLinkConfiguration->Release();
|
||||
deckLinkConfiguration = NULL;
|
||||
|
||||
// Populate the display mode combo with a list of display modes supported by the installed DeckLink card
|
||||
if (FAILED(s->deckLinkOutput->GetDisplayModeIterator(&displayModeIterator)))
|
||||
{
|
||||
fprintf(stderr, "Fatal: cannot create display mode iterator [decklink].\n");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// pick first display mode, no matter which it is
|
||||
@@ -425,13 +412,11 @@ void *decklink_playback_init(char *cfg)
|
||||
deckLinkDisplayMode->GetFrameRate(&s->frameRateDuration, &s->frameRateScale);
|
||||
} else {
|
||||
fprintf(stderr, "[decklink] Fatal: cannot get any display mode.\n");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
s->frames = 0;
|
||||
|
||||
|
||||
|
||||
s->deckLinkOutput->CreateVideoFrame(width, height, width*2, bmdFormat8BitYUV, bmdFrameFlagDefault, &s->deckLinkFrame);
|
||||
|
||||
s->delegate = new PlaybackDelegate(s);
|
||||
@@ -442,10 +427,26 @@ void *decklink_playback_init(char *cfg)
|
||||
s->deckLinkOutput->EnableVideoOutput(deckLinkDisplayMode->GetDisplayMode(), bmdVideoOutputFlagDefault);
|
||||
|
||||
displayModeIterator->Release();
|
||||
displayModeIterator = NULL;
|
||||
deckLinkDisplayMode->Release();
|
||||
deckLinkDisplayMode = NULL;
|
||||
|
||||
|
||||
return (void *)s;
|
||||
|
||||
error:
|
||||
if (displayModeIterator)
|
||||
displayModeIterator->Release();
|
||||
if (deckLinkDisplayMode)
|
||||
deckLinkDisplayMode->Release();
|
||||
if (deckLinkConfiguration)
|
||||
deckLinkConfiguration->Release();
|
||||
if (s->deckLinkOutput != NULL)
|
||||
s->deckLinkOutput->Release();
|
||||
if (s->deckLink != NULL)
|
||||
s->deckLink->Release();
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void decklink_put_frame(void *state, struct audio_frame *frame)
|
||||
|
||||
@@ -142,7 +142,7 @@ void audio_play_jack_help(const char *driver_name)
|
||||
const char **ports;
|
||||
|
||||
client = jack_client_open(PACKAGE_STRING, JackNullOption, &status);
|
||||
if(status == JackFailure) {
|
||||
if(status & JackFailure) {
|
||||
fprintf(stderr, "[JACK playback] Opening JACK client failed.\n");
|
||||
return;
|
||||
}
|
||||
@@ -192,16 +192,15 @@ void * audio_play_jack_init(char *cfg)
|
||||
}
|
||||
|
||||
s = calloc(1, sizeof(struct state_jack_playback));
|
||||
|
||||
s->jack_ports_pattern = strdup(cfg);
|
||||
|
||||
if(!s) {
|
||||
fprintf(stderr, "[JACK playback] Unable to allocate memory.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
s->jack_ports_pattern = strdup(cfg);
|
||||
|
||||
s->client = jack_client_open(PACKAGE_STRING, JackNullOption, &status);
|
||||
if(status == JackFailure) {
|
||||
if(status & JackFailure) {
|
||||
fprintf(stderr, "[JACK playback] Opening JACK client failed.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -206,7 +206,13 @@ void * portaudio_playback_init(char *cfg)
|
||||
} else {
|
||||
output_device = -1;
|
||||
}
|
||||
Pa_Initialize();
|
||||
PaError error = Pa_Initialize();
|
||||
if (error != paNoError)
|
||||
{
|
||||
printf("error initializing portaudio\n");
|
||||
printf("\tPortAudio error: %s\n", Pa_GetErrorText( error ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s = calloc(1, sizeof(struct state_portaudio_playback));
|
||||
assert(output_device >= -1);
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
|
||||
struct audio_frame;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void sdi_playback_help(const char *driver_name);
|
||||
void *sdi_playback_init(char *cfg);
|
||||
void sdi_put_frame(void *state, struct audio_frame *frame);
|
||||
@@ -61,6 +65,9 @@ void sdi_register_reconfigure_callback(void *s, int (*callback)(void *, int, int
|
||||
int),
|
||||
void *udata);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vim: set expandtab: sw=8 */
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
#include "audio/resampler.h"
|
||||
#include "audio/utils.h"
|
||||
|
||||
#include <speex/speex_resampler.h>
|
||||
|
||||
struct resampler
|
||||
{
|
||||
audio_frame2 *resampled;
|
||||
|
||||
char *muxed;
|
||||
char *resample_buffer;
|
||||
SpeexResamplerState *resampler;
|
||||
int resample_from, resample_ch_count;
|
||||
int resample_to;
|
||||
};
|
||||
|
||||
struct resampler *resampler_init(int dst_sample_rate)
|
||||
{
|
||||
struct resampler *s = calloc(1, sizeof(struct resampler));
|
||||
|
||||
s->resample_buffer = malloc(1024 * 1024);
|
||||
s->muxed = malloc(1024 * 1024);
|
||||
s->resampled = audio_frame2_init();
|
||||
s->resample_to = dst_sample_rate;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void resampler_done(struct resampler *s)
|
||||
{
|
||||
free(s->resample_buffer);
|
||||
free(s->muxed);
|
||||
free(s);
|
||||
}
|
||||
|
||||
audio_frame2 *resampler_resample(struct resampler *s, audio_frame2 *frame)
|
||||
{
|
||||
if(s->resample_to == frame->sample_rate) {
|
||||
return frame;
|
||||
} else {
|
||||
audio_frame2_allocate(s->resampled, frame->ch_count,
|
||||
(long long) frame->data_len[0] * s->resample_to / frame->sample_rate * 2);
|
||||
uint32_t write_frames = 1024 * 1024;
|
||||
|
||||
if(s->resample_from != frame->sample_rate || s->resample_ch_count != frame->ch_count) {
|
||||
s->resample_from = frame->sample_rate;
|
||||
s->resample_ch_count = frame->ch_count;
|
||||
if(s->resampler) {
|
||||
speex_resampler_destroy(s->resampler);
|
||||
}
|
||||
int err;
|
||||
s->resampler = speex_resampler_init(frame->ch_count, s->resample_from,
|
||||
s->resample_to, 10, &err);
|
||||
if(err) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < frame->ch_count; ++i) {
|
||||
mux_channel(s->muxed, frame->data[i], frame->bps, frame->data_len[i],
|
||||
frame->ch_count, i, 1.0);
|
||||
}
|
||||
int data_len = frame->data_len[0] * frame->ch_count; // uncompressed, so all channels
|
||||
// have the same size
|
||||
if(frame->bps != 2) {
|
||||
change_bps(s->resample_buffer, 2, s->muxed, frame->bps,
|
||||
data_len);
|
||||
data_len = data_len / frame->bps * 2;
|
||||
} else {
|
||||
memcpy(s->resample_buffer, s->muxed, data_len);
|
||||
}
|
||||
|
||||
uint32_t in_frames = data_len / frame->ch_count / 2;
|
||||
uint32_t in_frames_orig = in_frames;
|
||||
speex_resampler_process_interleaved_int(s->resampler,
|
||||
(spx_int16_t *)(void *) s->resample_buffer, &in_frames,
|
||||
(spx_int16_t *)(void *) s->muxed, &write_frames);
|
||||
assert(in_frames_orig == in_frames);
|
||||
|
||||
for(int i = 0; i < frame->ch_count; ++i) {
|
||||
s->resampled->data_len[i] = write_frames * 2 /* bps */;
|
||||
demux_channel(s->resampled->data[i], s->muxed, 2,
|
||||
s->resampled->data_len[i] * s->resampled->ch_count,
|
||||
s->resampled->ch_count, i);
|
||||
|
||||
}
|
||||
s->resampled->sample_rate = s->resample_to;
|
||||
s->resampled->bps = 2;
|
||||
}
|
||||
|
||||
return s->resampled;
|
||||
}
|
||||
|
||||
95
src/audio/resampler.cpp
Normal file
95
src/audio/resampler.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#include "audio/resampler.h"
|
||||
#include "audio/utils.h"
|
||||
|
||||
#include <speex/speex_resampler.h>
|
||||
|
||||
struct resampler
|
||||
{
|
||||
audio_frame2 *resampled;
|
||||
|
||||
char *muxed;
|
||||
char *resample_buffer;
|
||||
SpeexResamplerState *resampler;
|
||||
int resample_from, resample_ch_count;
|
||||
int resample_to;
|
||||
};
|
||||
|
||||
struct resampler *resampler_init(int dst_sample_rate)
|
||||
{
|
||||
struct resampler *s = (struct resampler *) calloc(1, sizeof(struct resampler));
|
||||
|
||||
s->resample_buffer = (char *) malloc(1024 * 1024);
|
||||
s->muxed = (char *) malloc(1024 * 1024);
|
||||
s->resampled = new audio_frame2;
|
||||
s->resample_to = dst_sample_rate;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void resampler_done(struct resampler *s)
|
||||
{
|
||||
if (!s)
|
||||
return;
|
||||
free(s->resample_buffer);
|
||||
free(s->muxed);
|
||||
delete s->resampled;
|
||||
free(s);
|
||||
}
|
||||
|
||||
const audio_frame2 *resampler_resample(struct resampler *s, const audio_frame2 *frame)
|
||||
{
|
||||
if(s->resample_to == frame->get_sample_rate()) {
|
||||
return frame;
|
||||
} else {
|
||||
s->resampled->init(frame->get_channel_count(), AC_PCM, 2, s->resample_to);
|
||||
uint32_t write_frames = 1024 * 1024;
|
||||
|
||||
if(s->resample_from != frame->get_sample_rate() || s->resample_ch_count != frame->get_channel_count()) {
|
||||
s->resample_from = frame->get_sample_rate();
|
||||
s->resample_ch_count = frame->get_channel_count();
|
||||
if(s->resampler) {
|
||||
speex_resampler_destroy(s->resampler);
|
||||
}
|
||||
int err;
|
||||
s->resampler = speex_resampler_init(frame->get_channel_count(), s->resample_from,
|
||||
s->resample_to, 10, &err);
|
||||
if(err) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < frame->get_channel_count(); ++i) {
|
||||
mux_channel(s->muxed, frame->get_data(i), frame->get_bps(), frame->get_data_len(i),
|
||||
frame->get_channel_count(), i, 1.0);
|
||||
}
|
||||
int data_len = frame->get_data_len(0) * frame->get_channel_count(); // uncompressed, so all channels
|
||||
// have the same size
|
||||
if(frame->get_bps() != 2) {
|
||||
change_bps(s->resample_buffer, 2, s->muxed, frame->get_bps(),
|
||||
data_len);
|
||||
data_len = data_len / frame->get_bps() * 2;
|
||||
} else {
|
||||
memcpy(s->resample_buffer, s->muxed, data_len);
|
||||
}
|
||||
|
||||
uint32_t in_frames = data_len / frame->get_channel_count() / 2;
|
||||
uint32_t in_frames_orig = in_frames;
|
||||
speex_resampler_process_interleaved_int(s->resampler,
|
||||
(spx_int16_t *)(void *) s->resample_buffer, &in_frames,
|
||||
(spx_int16_t *)(void *) s->muxed, &write_frames);
|
||||
assert(in_frames_orig == in_frames);
|
||||
|
||||
for(int i = 0; i < frame->get_channel_count(); ++i) {
|
||||
size_t data_len = write_frames * 2 /* bps */;
|
||||
//s->resampled->data_len[i] =
|
||||
char *data = (char *) malloc(data_len);
|
||||
demux_channel(data, s->muxed, 2, data_len * s->resampled->get_channel_count(),
|
||||
s->resampled->get_channel_count(), i);
|
||||
s->resampled->append(i, data, data_len);
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
return s->resampled;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,17 @@
|
||||
|
||||
#include "audio/audio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct resampler;
|
||||
|
||||
struct resampler *resampler_init(int dst_sample_rate);
|
||||
void resampler_done(struct resampler *);
|
||||
audio_frame2 *resampler_resample(struct resampler *, audio_frame2 *);
|
||||
const audio_frame2 *resampler_resample(struct resampler *, const audio_frame2 *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -62,73 +62,185 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#error "This code will not run with a big-endian machine. Please report a bug to " PACKAGE_BUGREPORT " if you reach here."
|
||||
#endif // WORDS_BIGENDIAN
|
||||
|
||||
audio_frame2 *audio_frame2_init()
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* @brief Creates empty audio_frame2
|
||||
*/
|
||||
audio_frame2::audio_frame2() :
|
||||
bps(0), sample_rate(0), codec(AC_PCM), duration(0.0)
|
||||
{
|
||||
audio_frame2 *ret = (audio_frame2 *) calloc(1, sizeof(audio_frame2));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void audio_frame2_allocate(audio_frame2 *frame, int nr_channels, int max_size)
|
||||
/**
|
||||
* @brief creates audio_frame2 from POD audio_frame
|
||||
*/
|
||||
audio_frame2::audio_frame2(struct audio_frame *old)
|
||||
{
|
||||
assert(nr_channels <= MAX_AUDIO_CHANNELS);
|
||||
init(old->ch_count, AC_PCM, old->bps, old->sample_rate);
|
||||
|
||||
audio_frame2_reset(frame);
|
||||
|
||||
frame->max_size = max_size;
|
||||
frame->ch_count = nr_channels;
|
||||
|
||||
for(int i = 0; i < nr_channels; ++i) {
|
||||
frame->data[i] = malloc(max_size);
|
||||
for (int i = 0; i < old->ch_count; i++) {
|
||||
resize(i, old->data_len / old->ch_count);
|
||||
char *data = channels[i].first.get();
|
||||
demux_channel(data, old->data, old->bps, old->data_len, old->ch_count, i);
|
||||
}
|
||||
}
|
||||
|
||||
void audio_frame2_append(audio_frame2 *dest, audio_frame2 *src)
|
||||
/**
|
||||
* @brief Initializes audio_frame2 for use. If already initialized, data are dropped.
|
||||
*/
|
||||
void audio_frame2::init(int nr_channels, audio_codec_t c, int b, int sr)
|
||||
{
|
||||
assert(src->ch_count == dest->ch_count || dest->ch_count == 0);
|
||||
dest->bps = src->bps;
|
||||
int new_max_size = dest->max_size;
|
||||
for (int i = 0; i < src->ch_count; ++i) {
|
||||
if (src->data_len[i] + dest->data_len[i] > new_max_size)
|
||||
new_max_size = src->data_len[i] + dest->data_len[i];
|
||||
channels.clear();
|
||||
channels.resize(nr_channels);
|
||||
bps = b;
|
||||
codec = c;
|
||||
sample_rate = sr;
|
||||
duration = 0.0;
|
||||
}
|
||||
|
||||
void audio_frame2::append(audio_frame2 const &src)
|
||||
{
|
||||
if (bps != src.bps || sample_rate != src.sample_rate ||
|
||||
channels.size() != src.channels.size()) {
|
||||
throw std::logic_error("Trying to append frame with different parameters!");
|
||||
}
|
||||
|
||||
if (new_max_size > (int) dest->max_size) {
|
||||
//reallocate
|
||||
dest->max_size = new_max_size;
|
||||
dest->ch_count = src->ch_count;
|
||||
for (int i = 0; i < src->ch_count; ++i) {
|
||||
dest->data[i] = realloc(dest->data[i], new_max_size);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < src->ch_count; ++i) {
|
||||
memcpy(dest->data[i] + dest->data_len[i], src->data[i],
|
||||
src->data_len[i]);
|
||||
dest->data_len[i] += src->data_len[i];
|
||||
for (size_t i = 0; i < channels.size(); i++) {
|
||||
unique_ptr<char []> new_data(new char[channels[i].second + src.channels[i].second]);
|
||||
copy(channels[i].first.get(), channels[i].first.get() + channels[i].second, new_data.get());
|
||||
copy(src.channels[i].first.get(), src.channels[i].first.get() + src.channels[i].second, new_data.get() + channels[i].second);
|
||||
channels[i].second += src.channels[i].second;
|
||||
channels[i].first = std::move(new_data);
|
||||
}
|
||||
}
|
||||
|
||||
int audio_frame2_get_sample_count(audio_frame2 *frame)
|
||||
void audio_frame2::append(int channel, const char *data, size_t length)
|
||||
{
|
||||
return frame->data_len[0] / frame->bps;
|
||||
unique_ptr<char []> new_data(new char[channels[channel].second + length]);
|
||||
copy(channels[channel].first.get(), channels[channel].first.get() + channels[channel].second, new_data.get());
|
||||
copy(data, data + length, new_data.get() + channels[channel].second);
|
||||
channels[channel].second += length;
|
||||
channels[channel].first = std::move(new_data);
|
||||
}
|
||||
|
||||
void audio_frame2_reset(audio_frame2 *frame)
|
||||
/**
|
||||
* @brief replaces portion of data of specified channel. If the size of the channel is not sufficient,
|
||||
* it is extended and old data are copied.
|
||||
*/
|
||||
void audio_frame2::replace(int channel, size_t offset, const char *data, size_t length)
|
||||
{
|
||||
for(int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
|
||||
frame->data_len[i] = 0;
|
||||
free(frame->data[i]);
|
||||
frame->data[i] = NULL;
|
||||
if (channels[channel].second < length + offset) {
|
||||
unique_ptr<char []> new_data(new char[length + offset]);
|
||||
copy(channels[channel].first.get(), channels[channel].first.get() +
|
||||
channels[channel].second, new_data.get());
|
||||
|
||||
channels[channel].second = length + offset;
|
||||
channels[channel].first = std::move(new_data);
|
||||
}
|
||||
frame->max_size = 0;
|
||||
frame->ch_count = 0;
|
||||
|
||||
copy(data, data + length, channels[channel].first.get() + offset);
|
||||
}
|
||||
|
||||
static double get_normalized(char *in, int bps) {
|
||||
/**
|
||||
* If the size of the specified channel is less than lenght. Channel length is extended. Otherwise,
|
||||
* no action is performed (no shrinking when requestedlength is less than current channel length).
|
||||
*/
|
||||
void audio_frame2::resize(int channel, size_t length)
|
||||
{
|
||||
if (channels[channel].second < length) {
|
||||
unique_ptr<char []> new_data(new char[length]);
|
||||
copy(channels[channel].first.get(), channels[channel].first.get() +
|
||||
channels[channel].second, new_data.get());
|
||||
|
||||
channels[channel].second = length;
|
||||
channels[channel].first = std::move(new_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all data from audio_frame2. It is equivalent to call of audio_frame2::init with current frame
|
||||
* parameters.
|
||||
*/
|
||||
void audio_frame2::reset()
|
||||
{
|
||||
for (size_t i = 0; i < channels.size(); i++) {
|
||||
channels[i].first = unique_ptr<char []>(new char[0]);
|
||||
channels[i].second = 0;
|
||||
}
|
||||
duration = 0.0;
|
||||
}
|
||||
|
||||
int audio_frame2::get_bps() const
|
||||
{
|
||||
return bps;
|
||||
}
|
||||
|
||||
audio_codec_t audio_frame2::get_codec() const
|
||||
{
|
||||
return codec;
|
||||
}
|
||||
|
||||
const char *audio_frame2::get_data(int channel) const
|
||||
{
|
||||
return channels[channel].first.get();
|
||||
}
|
||||
|
||||
size_t audio_frame2::get_data_len(int channel) const
|
||||
{
|
||||
return channels[channel].second;
|
||||
}
|
||||
|
||||
double audio_frame2::get_duration() const
|
||||
{
|
||||
if (codec == AC_PCM) {
|
||||
int samples = get_sample_count();
|
||||
return (double) samples / get_sample_rate();
|
||||
} else {
|
||||
return duration;
|
||||
}
|
||||
}
|
||||
|
||||
int audio_frame2::get_channel_count() const
|
||||
{
|
||||
return channels.size();
|
||||
}
|
||||
|
||||
int audio_frame2::get_sample_count() const
|
||||
{
|
||||
// for PCM, we can deduce samples count from length of the data
|
||||
if (codec == AC_PCM) {
|
||||
return channels[0].second / get_bps();
|
||||
} else {
|
||||
throw logic_error("Unknown sample count for compressed audio!");
|
||||
}
|
||||
}
|
||||
|
||||
int audio_frame2::get_sample_rate() const
|
||||
{
|
||||
return sample_rate;
|
||||
}
|
||||
|
||||
bool audio_frame2::has_same_prop_as(audio_frame2 const &frame) const
|
||||
{
|
||||
return bps == frame.bps &&
|
||||
sample_rate == frame.sample_rate &&
|
||||
codec == frame.codec &&
|
||||
channels.size() == frame.channels.size();
|
||||
}
|
||||
|
||||
void audio_frame2::set_duration(double new_duration)
|
||||
{
|
||||
duration = new_duration;
|
||||
}
|
||||
|
||||
static double get_normalized(const char *in, int bps) {
|
||||
int64_t sample = 0;
|
||||
bool negative = false;
|
||||
|
||||
@@ -155,11 +267,13 @@ static double get_normalized(char *in, int bps) {
|
||||
*/
|
||||
double calculate_rms(audio_frame2 *frame, int channel, double *peak)
|
||||
{
|
||||
assert(frame->get_codec() == AC_PCM);
|
||||
double sum = 0;
|
||||
*peak = 0;
|
||||
int sample_count = frame->data_len[channel] / frame->bps;
|
||||
for (int i = 0; i < frame->data_len[channel]; i += frame->bps) {
|
||||
double val = get_normalized(&frame->data[channel][i], frame->bps);
|
||||
int sample_count = frame->get_data_len(channel) / frame->get_bps();
|
||||
const char *channel_data = frame->get_data(channel);
|
||||
for (size_t i = 0; i < frame->get_data_len(channel); i += frame->get_bps()) {
|
||||
double val = get_normalized(channel_data + i, frame->get_bps());
|
||||
sum += val;
|
||||
if (fabs(val) > *peak) {
|
||||
*peak = fabs(val);
|
||||
@@ -170,8 +284,8 @@ double calculate_rms(audio_frame2 *frame, int channel, double *peak)
|
||||
|
||||
double sumMeanSquare = 0.0;
|
||||
|
||||
for (int i = 0; i < frame->data_len[channel]; i += frame->bps) {
|
||||
sumMeanSquare += pow(get_normalized(&frame->data[channel][i], frame->bps)
|
||||
for (size_t i = 0; i < frame->get_data_len(channel); i += frame->get_bps()) {
|
||||
sumMeanSquare += pow(get_normalized(channel_data + i, frame->get_bps())
|
||||
- average, 2.0);
|
||||
}
|
||||
|
||||
@@ -181,30 +295,6 @@ double calculate_rms(audio_frame2 *frame, int channel, double *peak)
|
||||
return rootMeanSquare;
|
||||
}
|
||||
|
||||
void audio_frame_to_audio_frame2(audio_frame2 *frame, struct audio_frame *old)
|
||||
{
|
||||
if(old->ch_count > frame->ch_count || old->data_len / old->ch_count > (int) frame->max_size) {
|
||||
audio_frame2_allocate(frame, old->ch_count, old->data_len / old->ch_count);
|
||||
}
|
||||
frame->codec = AC_PCM;
|
||||
frame->bps = old->bps;
|
||||
frame->sample_rate = old->sample_rate;
|
||||
for(int i = 0; i < old->ch_count; ++i) {
|
||||
demux_channel(frame->data[i], old->data, old->bps, old->data_len, old->ch_count, i);
|
||||
frame->data_len[i] = old->data_len / old->ch_count;
|
||||
}
|
||||
}
|
||||
|
||||
void audio_frame2_free(audio_frame2 *frame)
|
||||
{
|
||||
if(!frame)
|
||||
return;
|
||||
for(int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
|
||||
free(frame->data[i]);
|
||||
}
|
||||
free(frame);
|
||||
}
|
||||
|
||||
bool audio_desc_eq(struct audio_desc a1, struct audio_desc a2) {
|
||||
return a1.bps == a2.bps &&
|
||||
a1.sample_rate == a2.sample_rate &&
|
||||
@@ -213,26 +303,26 @@ bool audio_desc_eq(struct audio_desc a1, struct audio_desc a2) {
|
||||
}
|
||||
|
||||
struct audio_desc audio_desc_from_audio_frame(struct audio_frame *frame) {
|
||||
return (struct audio_desc) { .bps = frame->bps,
|
||||
.sample_rate = frame->sample_rate,
|
||||
.ch_count = frame->ch_count,
|
||||
.codec = AC_PCM
|
||||
return audio_desc { frame->bps,
|
||||
frame->sample_rate,
|
||||
frame->ch_count,
|
||||
AC_PCM
|
||||
};
|
||||
}
|
||||
|
||||
struct audio_desc audio_desc_from_audio_frame2(audio_frame2 *frame) {
|
||||
return (struct audio_desc) { .bps = frame->bps,
|
||||
.sample_rate = frame->sample_rate,
|
||||
.ch_count = frame->ch_count,
|
||||
.codec = frame->codec
|
||||
return audio_desc { frame->get_bps(),
|
||||
frame->get_sample_rate(),
|
||||
frame->get_channel_count(),
|
||||
frame->get_codec()
|
||||
};
|
||||
}
|
||||
|
||||
struct audio_desc audio_desc_from_audio_channel(audio_channel *channel) {
|
||||
return (struct audio_desc) { .bps = channel->bps,
|
||||
.sample_rate = channel->sample_rate,
|
||||
.ch_count = 1,
|
||||
.codec = channel->codec
|
||||
return audio_desc { channel->bps,
|
||||
channel->sample_rate,
|
||||
1,
|
||||
channel->codec
|
||||
};
|
||||
}
|
||||
|
||||
@@ -306,7 +396,7 @@ void demux_channel(char *out, char *in, int bps, int in_len, int in_stream_chann
|
||||
}
|
||||
}
|
||||
|
||||
void mux_channel(char *out, char *in, int bps, int in_len, int out_stream_channels, int pos_in_stream, double scale)
|
||||
void mux_channel(char *out, const char *in, int bps, int in_len, int out_stream_channels, int pos_in_stream, double scale)
|
||||
{
|
||||
int samples = in_len / bps;
|
||||
int i;
|
||||
@@ -337,7 +427,7 @@ void mux_channel(char *out, char *in, int bps, int in_len, int out_stream_channe
|
||||
}
|
||||
}
|
||||
|
||||
void mux_and_mix_channel(char *out, char *in, int bps, int in_len, int out_stream_channels, int pos_in_stream, double scale)
|
||||
void mux_and_mix_channel(char *out, const char *in, int bps, int in_len, int out_stream_channels, int pos_in_stream, double scale)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -381,9 +471,9 @@ double get_avg_volume(char *data, int bps, int in_len, int stream_channels, int
|
||||
return average_vol;
|
||||
}
|
||||
|
||||
void float2int(char *out, char *in, int len)
|
||||
void float2int(char *out, const char *in, int len)
|
||||
{
|
||||
float *inf = (float *)(void *) in;
|
||||
const float *inf = (const float *)(const void *) in;
|
||||
int32_t *outi = (int32_t *)(void *) out;
|
||||
int items = len / sizeof(int32_t);
|
||||
|
||||
@@ -392,9 +482,9 @@ void float2int(char *out, char *in, int len)
|
||||
}
|
||||
}
|
||||
|
||||
void int2float(char *out, char *in, int len)
|
||||
void int2float(char *out, const char *in, int len)
|
||||
{
|
||||
int32_t *ini = (int32_t *)(void *) in;
|
||||
const int32_t *ini = (const int32_t *)(const void *) in;
|
||||
float *outf = (float *)(void *) out;
|
||||
int items = len / sizeof(int32_t);
|
||||
|
||||
@@ -427,22 +517,13 @@ void signed2unsigned(char *out, char *in, int in_len)
|
||||
}
|
||||
}
|
||||
|
||||
void audio_channel_demux(audio_frame2 *frame, int index, audio_channel *channel)
|
||||
void audio_channel_demux(const audio_frame2 *frame, int index, audio_channel *channel)
|
||||
{
|
||||
channel->data = frame->data[index];
|
||||
channel->data_len = frame->data_len[index];
|
||||
channel->codec = frame->codec;
|
||||
channel->bps = frame->bps;
|
||||
channel->sample_rate = frame->sample_rate;
|
||||
}
|
||||
|
||||
void audio_channel_mux(audio_frame2 *frame, int index, audio_channel *channel)
|
||||
{
|
||||
frame->data[index] = channel->data;
|
||||
frame->data_len[index] = channel->data_len;
|
||||
frame->codec = channel->codec;
|
||||
frame->bps = channel->bps;
|
||||
frame->sample_rate = channel->sample_rate;
|
||||
channel->data = frame->get_data(index);
|
||||
channel->data_len = frame->get_data_len(index);
|
||||
channel->codec = frame->get_codec();
|
||||
channel->bps = frame->get_bps();
|
||||
channel->sample_rate = frame->get_sample_rate();
|
||||
}
|
||||
|
||||
int32_t format_from_in_bps(const char * in, int bps) {
|
||||
@@ -54,9 +54,6 @@
|
||||
#include <audio/audio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
audio_frame2 *audio_frame2_init(void);
|
||||
void audio_frame2_allocate(audio_frame2 *, int nr_channels, int max_size);
|
||||
void audio_frame2_free(audio_frame2 *);
|
||||
@@ -65,15 +62,20 @@ void audio_frame_to_audio_frame2(audio_frame2 *, struct audio_frame *);
|
||||
int audio_frame2_get_sample_count(audio_frame2 *frame);
|
||||
void audio_frame2_reset(audio_frame2 *frame);
|
||||
double calculate_rms(audio_frame2 *frame, int channel, double *peak);
|
||||
struct audio_desc audio_desc_from_audio_frame2(audio_frame2 *);
|
||||
void audio_channel_demux(const audio_frame2 *, int, audio_channel*);
|
||||
void audio_channel_mux(audio_frame2 *, int, audio_channel*);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
bool audio_desc_eq(struct audio_desc, struct audio_desc);
|
||||
struct audio_desc audio_desc_from_audio_frame(struct audio_frame *);
|
||||
struct audio_desc audio_desc_from_audio_frame2(audio_frame2 *);
|
||||
struct audio_desc audio_desc_from_audio_channel(audio_channel *);
|
||||
|
||||
void audio_channel_demux(audio_frame2 *, int, audio_channel*);
|
||||
void audio_channel_mux(audio_frame2 *, int, audio_channel*);
|
||||
|
||||
/**
|
||||
* Changes bps for everey sample.
|
||||
*
|
||||
@@ -94,7 +96,7 @@ void copy_channel(char *out, const char *in, int bps, int in_len /* bytes */, in
|
||||
/*
|
||||
* Multiplexes channel into interleaved stream
|
||||
*/
|
||||
void mux_channel(char *out, char *in, int bps, int in_len, int out_stream_channels, int chan_pos_stream, double scale);
|
||||
void mux_channel(char *out, const char *in, int bps, int in_len, int out_stream_channels, int chan_pos_stream, double scale);
|
||||
void demux_channel(char *out, char *in, int bps, int in_len, int in_stream_channels, int pos_in_stream);
|
||||
|
||||
/*
|
||||
@@ -102,7 +104,7 @@ void demux_channel(char *out, char *in, int bps, int in_len, int in_stream_chann
|
||||
*
|
||||
* @return avareage volume
|
||||
*/
|
||||
void mux_and_mix_channel(char *out, char *in, int bps, int in_len, int out_stream_channels, int chan_pos_stream, double scale);
|
||||
void mux_and_mix_channel(char *out, const char *in, int bps, int in_len, int out_stream_channels, int chan_pos_stream, double scale);
|
||||
double get_avg_volume(char *data, int bps, int in_len, int stream_channels, int chan_pos_stream);
|
||||
|
||||
/**
|
||||
@@ -111,14 +113,14 @@ double get_avg_volume(char *data, int bps, int in_len, int stream_channels, int
|
||||
* @param[out] out 4-byte aligned output buffer
|
||||
* @param[in] in 4-byte aligned input buffer
|
||||
*/
|
||||
void float2int(char *out, char *in, int len);
|
||||
void float2int(char *out, const char *in, int len);
|
||||
/**
|
||||
* This fuction converts from int32_t to normalized float
|
||||
* Input and output data may overlap.
|
||||
* @param[out] out 4-byte aligned output buffer
|
||||
* @param[in] in 4-byte aligned input buffer
|
||||
*/
|
||||
void int2float(char *out, char *in, int len);
|
||||
void int2float(char *out, const char *in, int len);
|
||||
/**
|
||||
* This fuction converts from int16_t to normalized float
|
||||
* Input and output data may overlap.
|
||||
|
||||
127
src/blackmagic_common.cpp
Normal file
127
src/blackmagic_common.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* @file blackmagic_common.cpp
|
||||
* @author Martin Pulec <pulec@cesnet.cz>
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2014 CESNET, z. s. p. o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, is permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of CESNET nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config_unix.h"
|
||||
#include "config_win32.h"
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include "blackmagic_common.h"
|
||||
#include "DeckLinkAPIVersion.h"
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
unordered_map<HRESULT, string> bmd_hresult_to_string_map = {
|
||||
{S_OK, "success"},
|
||||
{S_FALSE, "false"},
|
||||
{E_UNEXPECTED, "unexpected value"},
|
||||
{E_NOTIMPL, "not implemented"},
|
||||
{E_OUTOFMEMORY, "out of memory"},
|
||||
{E_INVALIDARG, "invalid argument"},
|
||||
{E_NOINTERFACE, "interface was not found"},
|
||||
{E_POINTER, "invalid pointer"},
|
||||
{E_HANDLE, "invalid handle"},
|
||||
{E_ABORT, "operation aborted"},
|
||||
{E_FAIL, "failure"},
|
||||
{E_ACCESSDENIED, "access denied"},
|
||||
};
|
||||
|
||||
string bmd_hresult_to_string(HRESULT res)
|
||||
{
|
||||
auto it = bmd_hresult_to_string_map.find(res);
|
||||
if (it != bmd_hresult_to_string_map.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* returned c-sring needs to be freed when not used
|
||||
*/
|
||||
const char *get_cstr_from_bmd_api_str(BMD_STR bmd_string)
|
||||
{
|
||||
const char *cstr;
|
||||
#ifdef HAVE_MACOSX
|
||||
cstr = (char *) malloc(128);
|
||||
CFStringGetCString(bmd_string, (char *) cstr, 128, kCFStringEncodingMacRoman);
|
||||
#elif defined WIN32
|
||||
cstr = (char *) malloc(128);
|
||||
wcstombs((char *) cstr, bmd_string, 128);
|
||||
#else // Linux
|
||||
cstr = bmd_string;
|
||||
#endif
|
||||
|
||||
return cstr;
|
||||
}
|
||||
|
||||
void release_bmd_api_str(BMD_STR string)
|
||||
{
|
||||
/// @todo what about MSW?
|
||||
#ifdef HAVE_MACOSX
|
||||
CFRelease(string);
|
||||
#else
|
||||
UNUSED(string);
|
||||
#endif
|
||||
}
|
||||
|
||||
IDeckLinkIterator *create_decklink_iterator(bool verbose)
|
||||
{
|
||||
IDeckLinkIterator *deckLinkIterator = nullptr;
|
||||
#ifdef WIN32
|
||||
HRESULT result = CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL,
|
||||
IID_IDeckLinkIterator, (void **) &deckLinkIterator);
|
||||
if (FAILED(result)) {
|
||||
deckLinkIterator = nullptr;
|
||||
}
|
||||
#else
|
||||
deckLinkIterator = CreateDeckLinkIteratorInstance();
|
||||
#endif
|
||||
|
||||
if (!deckLinkIterator && verbose) {
|
||||
fprintf(stderr, "\nA DeckLink iterator could not be created. The DeckLink drivers may not be installed or are outdated.\n");
|
||||
fprintf(stderr, "This UltraGrid version was compiled with DeckLink drivers %s. You should have at least this version.\n\n",
|
||||
BLACKMAGIC_DECKLINK_API_VERSION_STRING);
|
||||
|
||||
}
|
||||
|
||||
return deckLinkIterator;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/**
|
||||
* @file blackmagic_common.h
|
||||
* @author Martin Pulec <pulec@cesnet.cz>
|
||||
*/
|
||||
/*
|
||||
* FILE: capture_filter/resize.h
|
||||
* AUTHORS: Gerard Castillo <gerard.castillo@i2cat.net>
|
||||
* Marc Palau <marc.palau@i2cat.net>
|
||||
*
|
||||
* Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya
|
||||
* Copyright (c) 2014 CESNET, z. s. p. o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, is permitted provided that the following conditions
|
||||
@@ -16,15 +17,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
*
|
||||
* This product includes software developed by the Fundació i2CAT,
|
||||
* Internet I Innovació Digital a Catalunya. This product also includes
|
||||
* software developed by CESNET z.s.p.o.
|
||||
*
|
||||
* 4. Neither the name of the University nor of the Institute may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* 3. Neither the name of CESNET nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
|
||||
@@ -39,13 +33,32 @@
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CAPTURE_FILTER_RESIZE_H_
|
||||
#define CAPTURE_FILTER_RESIZE_H_
|
||||
#ifndef BLACKMAGIC_COMMON_H
|
||||
#define BLACKMAGIC_COMMON_H
|
||||
|
||||
struct capture_filter_info;
|
||||
extern struct capture_filter_info capture_filter_resize;
|
||||
#ifdef WIN32
|
||||
#include "DeckLinkAPI_h.h" /* From DeckLink SDK */
|
||||
#else
|
||||
#include "DeckLinkAPI.h" /* From DeckLink SDK */
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
std::string bmd_hresult_to_string(HRESULT res);
|
||||
|
||||
#ifdef HAVE_MACOSX
|
||||
#define BMD_STR CFStringRef
|
||||
#elif defined WIN32
|
||||
#define BMD_STR BSTR
|
||||
#else
|
||||
#define BMD_STR const char *
|
||||
#endif
|
||||
const char *get_cstr_from_bmd_api_str(BMD_STR string);
|
||||
void release_bmd_api_str(BMD_STR string);
|
||||
|
||||
IDeckLinkIterator *create_decklink_iterator(bool verbose = true);
|
||||
|
||||
#endif // defined BLACKMAGIC_COMMON_H
|
||||
|
||||
#endif // CAPTURE_FILTER_RESIZE_H_
|
||||
@@ -55,9 +55,6 @@
|
||||
#include "capture_filter/logo.h"
|
||||
#include "capture_filter/none.h"
|
||||
#include "capture_filter/scale.h"
|
||||
#ifdef HAVE_OPENCV
|
||||
#include "capture_filter/resize.h"
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -79,9 +76,6 @@ struct init_capture_filters {
|
||||
&capture_filter_logo,
|
||||
&capture_filter_none,
|
||||
&capture_filter_scale,
|
||||
#ifdef HAVE_OPENCV
|
||||
&capture_filter_resize,
|
||||
#endif
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -136,6 +130,7 @@ static int create_filter(struct capture_filter *s, char *cfg)
|
||||
filter_name);
|
||||
}
|
||||
if(ret != 0) {
|
||||
free(instance);
|
||||
return ret;
|
||||
}
|
||||
simple_linked_list_append(s->filters, instance);
|
||||
@@ -183,11 +178,12 @@ int capture_filter_init(struct module *parent, const char *cfg, struct capture_f
|
||||
|
||||
while((item = strtok_r(filter_list_str, ",", &save_ptr))) {
|
||||
char filter_name[128];
|
||||
strncpy(filter_name, item, sizeof(filter_name));
|
||||
strncpy(filter_name, item, sizeof filter_name - 1);
|
||||
|
||||
int ret = create_filter(s, filter_name);
|
||||
if (ret != 0) {
|
||||
module_done(&s->mod);
|
||||
free(tmp);
|
||||
free(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ static bool parse(struct state_blank *s, char *cfg)
|
||||
s->in_relative_units = false;
|
||||
}
|
||||
|
||||
char *item, *save_ptr;
|
||||
char *item, *save_ptr = NULL;
|
||||
while ((item = strtok_r(cfg, ":", &save_ptr))) {
|
||||
if (s->in_relative_units) {
|
||||
vals_relative[counter] = atof(item) / 100.0;
|
||||
|
||||
@@ -134,6 +134,7 @@ static struct video_frame *filter(void *state, struct video_frame *in)
|
||||
return s->frame;
|
||||
} else {
|
||||
s->current = (s->current + 1) % s->num;
|
||||
VIDEO_FRAME_DISPOSE(in);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,8 +51,12 @@
|
||||
#include "video.h"
|
||||
#include "video_codec.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct state_capture_filter_logo {
|
||||
unsigned char *logo;
|
||||
unique_ptr<unsigned char []> logo;
|
||||
unsigned int width, height;
|
||||
int x, y;
|
||||
};
|
||||
@@ -75,34 +79,47 @@ static bool load_logo_data_from_file(struct state_capture_filter_logo *s, const
|
||||
throw string("Only logo in PAM format is currently supported.");
|
||||
}
|
||||
getline(file, line);
|
||||
bool rgb = false;
|
||||
int depth = 0;
|
||||
while (!file.eof()) {
|
||||
if (line.compare(0, strlen("WIDTH"), "WIDTH") == 0) {
|
||||
s->width = atoi(line.c_str() + strlen("WIDTH "));
|
||||
} else if (line.compare(0, strlen("HEIGHT"), "HEIGHT") == 0) {
|
||||
s->height = atoi(line.c_str() + strlen("HEIGHT "));
|
||||
} else if (line.compare(0, strlen("DEPTH"), "DEPTH") == 0) {
|
||||
if (atoi(line.c_str() + strlen("DEPTH ")) != 4) {
|
||||
throw string("Only depth 4 is supported.");
|
||||
}
|
||||
depth = atoi(line.c_str() + strlen("DEPTH "));
|
||||
} else if (line.compare(0, strlen("MAXVAL"), "MAXVAL") == 0) {
|
||||
if (atoi(line.c_str() + strlen("MAXVAL ")) != 255) {
|
||||
throw string("Only supported maxval is 255.");
|
||||
}
|
||||
} else if (line.compare(0, strlen("TUPLETYPE"), "MAXVAL") == 0) {
|
||||
if (line.compare("TUPLTYPE RGB_ALPHA") != 0) {
|
||||
throw string("Only supported tuple type is RGBA_APLHA.");
|
||||
if (line.compare("TUPLTYPE RGB") == 0) {
|
||||
rgb = true;
|
||||
} else if (line.compare("TUPLTYPE RGB_ALPHA") != 0) {
|
||||
throw string("Only supported tuple type is either RGB or RGBA_APLHA.");
|
||||
}
|
||||
} else if (line.compare(0, strlen("ENDHDR"), "ENDHDR") == 0) {
|
||||
break;
|
||||
}
|
||||
getline(file, line);
|
||||
}
|
||||
int datalen = 4 * s->width * s->height;
|
||||
s->logo = (unsigned char *) malloc(datalen);
|
||||
file.read((char *) s->logo, datalen);
|
||||
if ((rgb && depth != 3) || depth != 4) {
|
||||
throw string("Unsupported depth passed.");
|
||||
}
|
||||
int datalen = depth * s->width * s->height;
|
||||
auto data_read = unique_ptr<unsigned char []>(new unsigned char[datalen]);
|
||||
file.read((char *) data_read.get(), datalen);
|
||||
if (file.eof()) {
|
||||
throw string("Unable to load logo data from file.");
|
||||
}
|
||||
if (rgb) {
|
||||
datalen = 4 * s->width * s->height;
|
||||
auto tmp = unique_ptr<unsigned char []>(new unsigned char[datalen]);
|
||||
vc_copylineRGBtoRGBA(tmp.get(), data_read.get(), datalen, 0, 8, 16);
|
||||
s->logo = move(tmp);
|
||||
} else {
|
||||
s->logo = move(data_read);
|
||||
}
|
||||
file.close();
|
||||
} catch (string const & s) {
|
||||
cerr << s << endl;
|
||||
@@ -120,8 +137,7 @@ static bool load_logo_data_from_file(struct state_capture_filter_logo *s, const
|
||||
static int init(struct module *parent, const char *cfg, void **state)
|
||||
{
|
||||
UNUSED(parent);
|
||||
struct state_capture_filter_logo *s = (struct state_capture_filter_logo *)
|
||||
calloc(1, sizeof(struct state_capture_filter_logo));
|
||||
struct state_capture_filter_logo *s = new state_capture_filter_logo();
|
||||
|
||||
s->x = s->y = -1;
|
||||
|
||||
@@ -138,12 +154,11 @@ static int init(struct module *parent, const char *cfg, void **state)
|
||||
char *item;
|
||||
if ((item = strtok_r(tmp, ":", &save_ptr)) == NULL) {
|
||||
fprintf(stderr, "File name with logo required!\n");
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!load_logo_data_from_file(s, item)) {
|
||||
free(s);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((item = strtok_r(tmp, ":", &save_ptr))) {
|
||||
@@ -153,17 +168,21 @@ static int init(struct module *parent, const char *cfg, void **state)
|
||||
}
|
||||
}
|
||||
free(tmp);
|
||||
tmp = nullptr;
|
||||
|
||||
*state = s;
|
||||
return 0;
|
||||
error:
|
||||
free(tmp);
|
||||
delete s;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void done(void *state)
|
||||
{
|
||||
struct state_capture_filter_logo *s = (struct state_capture_filter_logo *)
|
||||
state;
|
||||
free(s->logo);
|
||||
free(state);
|
||||
delete s;
|
||||
}
|
||||
|
||||
static struct video_frame *filter(void *state, struct video_frame *in)
|
||||
@@ -176,6 +195,7 @@ static struct video_frame *filter(void *state, struct video_frame *in)
|
||||
coder = get_decoder_from_to(RGB, in->color_spec, true);
|
||||
int rect_x = s->x;
|
||||
int rect_y = s->y;
|
||||
assert(coder != NULL && decoder != NULL);
|
||||
|
||||
if (decoder == NULL || coder == NULL)
|
||||
return in;
|
||||
@@ -202,7 +222,7 @@ static struct video_frame *filter(void *state, struct video_frame *in)
|
||||
}
|
||||
|
||||
unsigned char *image_data = segment;
|
||||
const unsigned char *overlay_data = s->logo;
|
||||
const unsigned char *overlay_data = s->logo.get();
|
||||
for (unsigned int y = 0; y < s->height; ++y) {
|
||||
for (unsigned int x = 0; x < s->width; ++x) {
|
||||
int alpha = overlay_data[3];
|
||||
|
||||
@@ -185,13 +185,20 @@ static struct video_frame *filter(void *state, struct video_frame *in)
|
||||
return s->frame;
|
||||
}
|
||||
|
||||
struct capture_filter_info capture_filter_resize = {
|
||||
static struct capture_filter_info capture_filter_resize = {
|
||||
"resize",
|
||||
init,
|
||||
done,
|
||||
filter,
|
||||
};
|
||||
|
||||
static void register_module(void) __attribute__((constructor));
|
||||
|
||||
static void register_module(void)
|
||||
{
|
||||
register_video_capture_filter(&capture_filter_resize);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -72,6 +72,8 @@ struct state_scale {
|
||||
|
||||
static int init(struct module *parent, const char *cfg, void **state)
|
||||
{
|
||||
UNUSED(parent);
|
||||
UNUSED(cfg);
|
||||
struct video_desc desc;
|
||||
|
||||
struct state_scale *s = (struct state_scale *) calloc(1, sizeof(struct state_scale));
|
||||
|
||||
@@ -208,5 +208,7 @@ static inline void *aligned_malloc(size_t size, size_t alignment)
|
||||
|
||||
#define platform_mkdir(a) mkdir(a, 0777)
|
||||
|
||||
#define INVALID_SOCKET -1
|
||||
|
||||
#endif /* _CONFIG_UNIX_H */
|
||||
#endif /* NDEF WIN32 */
|
||||
|
||||
@@ -146,6 +146,7 @@ static fd_t create_internal_port(int *port)
|
||||
{
|
||||
fd_t sock;
|
||||
sock = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
assert(sock != INVALID_SOCKET);
|
||||
struct sockaddr_in6 s_in;
|
||||
memset(&s_in, 0, sizeof(s_in));
|
||||
s_in.sin6_family = AF_INET6;
|
||||
@@ -184,6 +185,7 @@ int control_init(int port, int connection_type, struct control_state **state, st
|
||||
|
||||
if(s->connection_type == SERVER) {
|
||||
s->socket_fd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
assert(s->socket_fd != INVALID_SOCKET);
|
||||
int val = 1;
|
||||
setsockopt(s->socket_fd, SOL_SOCKET, SO_REUSEADDR,
|
||||
(sso_val_type) &val, sizeof(val));
|
||||
@@ -201,6 +203,7 @@ int control_init(int port, int connection_type, struct control_state **state, st
|
||||
listen(s->socket_fd, MAX_CLIENTS);
|
||||
} else {
|
||||
s->socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
assert(s->socket_fd != INVALID_SOCKET);
|
||||
struct addrinfo hints, *res, *res0;
|
||||
int err;
|
||||
|
||||
@@ -212,8 +215,8 @@ int control_init(int port, int connection_type, struct control_state **state, st
|
||||
err = getaddrinfo("127.0.0.1", port_str, &hints, &res0);
|
||||
|
||||
if(err) {
|
||||
return -1;
|
||||
fprintf(stderr, "Unable to get address: %s\n", gai_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
bool connected = false;
|
||||
|
||||
@@ -316,7 +319,9 @@ static int process_msg(struct control_state *s, fd_t client_fd, char *message)
|
||||
|
||||
resp =
|
||||
send_message(s->root_module, path, (struct message *) msg);
|
||||
send_message(s->root_module, path_audio, (struct message *) msg_audio);
|
||||
struct response *resp_audio =
|
||||
send_message(s->root_module, path_audio, (struct message *) msg_audio);
|
||||
resp_audio->deleter(resp_audio);
|
||||
} else if (prefix_matches(message, "receiver-port ")) {
|
||||
struct msg_receiver *msg =
|
||||
(struct msg_receiver *)
|
||||
@@ -341,6 +346,7 @@ static int process_msg(struct control_state *s, fd_t client_fd, char *message)
|
||||
strncpy(msg->fec, fec + 6, sizeof(msg->fec) - 1);
|
||||
} else {
|
||||
resp = new_response(RESPONSE_NOT_FOUND, strdup("unknown media type"));
|
||||
free(msg);
|
||||
}
|
||||
|
||||
if(!resp) {
|
||||
@@ -414,7 +420,10 @@ static void send_response(fd_t fd, struct response *resp)
|
||||
}
|
||||
strcat(buffer, "\r\n");
|
||||
|
||||
write_all(fd, buffer, strlen(buffer));
|
||||
ssize_t ret = write_all(fd, buffer, strlen(buffer));
|
||||
if (ret < 0) {
|
||||
perror("Unable to write response");
|
||||
}
|
||||
|
||||
resp->deleter(resp);
|
||||
}
|
||||
@@ -465,6 +474,7 @@ static fd_t connect_to_internal_channel(int local_port)
|
||||
s_in.sin6_addr = in6addr_loopback;
|
||||
s_in.sin6_port = htons(local_port);
|
||||
fd_t fd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
assert(fd != INVALID_SOCKET);
|
||||
int ret;
|
||||
ret = connect(fd, (struct sockaddr *) &s_in,
|
||||
sizeof(s_in));
|
||||
@@ -654,9 +664,13 @@ void control_done(struct control_state *s)
|
||||
module_done(&s->mod);
|
||||
|
||||
if(s->started) {
|
||||
write_all(s->internal_fd[0], "quit\r\n", 6);
|
||||
pthread_join(s->thread_id, NULL);
|
||||
close(s->internal_fd[0]);
|
||||
int ret = write_all(s->internal_fd[0], "quit\r\n", 6);
|
||||
if (ret > 0) {
|
||||
pthread_join(s->thread_id, NULL);
|
||||
close(s->internal_fd[0]);
|
||||
} else {
|
||||
fprintf(stderr, "Cannot exit control thread!\n");
|
||||
}
|
||||
}
|
||||
if(s->connection_type == SERVER) {
|
||||
// for client, the socket has already been closed
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
|
||||
#include <stdlib.h> /* For size_t */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** File: ARCCRC16.C
|
||||
*/
|
||||
@@ -36,6 +40,7 @@ uint16_t updcrc(uint16_t icrc, uint8_t *icp, size_t icnt);
|
||||
|
||||
uint32_t updateCRC32(unsigned char ch, uint32_t crc);
|
||||
bool crc32file(char *name, uint32_t *crc, long *charcnt);
|
||||
|
||||
uint32_t crc32buf(char *buf, size_t len);
|
||||
|
||||
uint32_t crc32buf_with_oldcrc(const char *buf, size_t len, uint32_t oldcrc);
|
||||
@@ -53,5 +58,8 @@ unsigned checksum(void *buffer, size_t len, unsigned int seed);
|
||||
void checkexe(char *fname);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CRC__H */
|
||||
|
||||
@@ -564,8 +564,8 @@ qfDES(unsigned char *key,
|
||||
static unsigned char desKey[8], desKeys[128];
|
||||
static Word *oldKey = (Word *) desKey, *keys = (Word *) desKeys;
|
||||
static QFDES_what oldWhat;
|
||||
static QFDES_mode oldMode;
|
||||
unsigned char b0[8], b1[8]; /* feedback blocks */
|
||||
static QFDES_mode oldMode __attribute__((unused));
|
||||
unsigned char b0[8] = "", b1[8]; /* feedback blocks */
|
||||
Word *newKey = (Word *) key, /* key from user */
|
||||
*text, /* text to be [en|de]crypted */
|
||||
*cb = (Word *) b0, /* the chained block in CBC mode */
|
||||
|
||||
@@ -85,12 +85,7 @@ int openssl_decrypt_init(struct openssl_decrypt **state,
|
||||
const char *passphrase,
|
||||
enum openssl_mode mode)
|
||||
{
|
||||
#ifndef HAVE_CRYPTO
|
||||
fprintf(stderr, "This " PACKAGE_NAME " version was build "
|
||||
"without OpenSSL support!\n");
|
||||
return -1;
|
||||
#endif // HAVE_CRYPTO
|
||||
|
||||
#ifdef HAVE_CRYPTO
|
||||
struct openssl_decrypt *s =
|
||||
(struct openssl_decrypt *)
|
||||
calloc(1, sizeof(struct openssl_decrypt));
|
||||
@@ -105,14 +100,10 @@ int openssl_decrypt_init(struct openssl_decrypt **state,
|
||||
|
||||
switch(mode) {
|
||||
case MODE_AES128_ECB:
|
||||
#ifdef HAVE_CRYPTO
|
||||
AES_set_decrypt_key(hash, 128, &s->key);
|
||||
#endif
|
||||
break;
|
||||
case MODE_AES128_CTR:
|
||||
#ifdef HAVE_CRYPTO
|
||||
AES_set_encrypt_key(hash, 128, &s->key);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
@@ -122,6 +113,14 @@ int openssl_decrypt_init(struct openssl_decrypt **state,
|
||||
|
||||
*state = s;
|
||||
return 0;
|
||||
#else
|
||||
UNUSED(state);
|
||||
UNUSED(passphrase);
|
||||
UNUSED(mode);
|
||||
fprintf(stderr, "This " PACKAGE_NAME " version was build "
|
||||
"without OpenSSL support!\n");
|
||||
return -1;
|
||||
#endif // HAVE_CRYPTO
|
||||
}
|
||||
|
||||
void openssl_decrypt_destroy(struct openssl_decrypt *s)
|
||||
@@ -135,10 +134,7 @@ static void openssl_decrypt_block(struct openssl_decrypt *s,
|
||||
const unsigned char *ciphertext, unsigned char *plaintext, const char *nonce_and_counter,
|
||||
int len)
|
||||
{
|
||||
#ifndef HAVE_CRYPTO
|
||||
UNUSED(ciphertext);
|
||||
UNUSED(plaintext);
|
||||
#endif
|
||||
#ifdef HAVE_CRYPTO
|
||||
if(nonce_and_counter) {
|
||||
memcpy(s->ivec, nonce_and_counter, AES_BLOCK_SIZE);
|
||||
s->num = 0;
|
||||
@@ -147,20 +143,23 @@ static void openssl_decrypt_block(struct openssl_decrypt *s,
|
||||
switch(s->mode) {
|
||||
case MODE_AES128_ECB:
|
||||
assert(len == AES_BLOCK_SIZE);
|
||||
#ifdef HAVE_CRYPTO
|
||||
AES_ecb_encrypt(ciphertext, plaintext,
|
||||
&s->key, AES_DECRYPT);
|
||||
#endif // HAVE_CRYPTO
|
||||
break;
|
||||
case MODE_AES128_CTR:
|
||||
#ifdef HAVE_CRYPTO
|
||||
AES_ctr128_encrypt(ciphertext, plaintext, len, &s->key, s->ivec,
|
||||
s->ecount, &s->num);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
UNUSED(s);
|
||||
UNUSED(ciphertext);
|
||||
UNUSED(plaintext);
|
||||
UNUSED(nonce_and_counter);
|
||||
UNUSED(len);
|
||||
#endif
|
||||
}
|
||||
|
||||
int openssl_decrypt(struct openssl_decrypt *decrypt,
|
||||
|
||||
@@ -84,11 +84,7 @@ struct openssl_encrypt {
|
||||
int openssl_encrypt_init(struct openssl_encrypt **state, const char *passphrase,
|
||||
enum openssl_mode mode)
|
||||
{
|
||||
#ifndef HAVE_CRYPTO
|
||||
fprintf(stderr, "This " PACKAGE_NAME " version was build "
|
||||
"without OpenSSL support!\n");
|
||||
return -1;
|
||||
#endif
|
||||
#ifdef HAVE_CRYPTO
|
||||
struct openssl_encrypt *s = (struct openssl_encrypt *)
|
||||
calloc(1, sizeof(struct openssl_encrypt));
|
||||
|
||||
@@ -100,26 +96,29 @@ int openssl_encrypt_init(struct openssl_encrypt **state, const char *passphrase,
|
||||
strlen(passphrase));
|
||||
MD5Final(hash, &context);
|
||||
|
||||
#ifdef HAVE_CRYPTO
|
||||
AES_set_encrypt_key(hash, 128, &s->key);
|
||||
if (!RAND_bytes(s->ivec, 8)) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
s->mode = mode;
|
||||
assert(s->mode == MODE_AES128_CTR); // only functional by now
|
||||
|
||||
*state = s;
|
||||
return 0;
|
||||
#else
|
||||
UNUSED(state);
|
||||
UNUSED(passphrase);
|
||||
UNUSED(mode);
|
||||
fprintf(stderr, "This " PACKAGE_NAME " version was build "
|
||||
"without OpenSSL support!\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void openssl_encrypt_block(struct openssl_encrypt *s, unsigned char *plaintext,
|
||||
unsigned char *ciphertext, char *nonce_plus_counter, int len)
|
||||
{
|
||||
#ifndef HAVE_CRYPTO
|
||||
UNUSED(ciphertext);
|
||||
UNUSED(plaintext);
|
||||
#endif
|
||||
#ifdef HAVE_CRYPTO
|
||||
if(nonce_plus_counter) {
|
||||
memcpy(nonce_plus_counter, (char *) s->ivec, 16);
|
||||
/* We do start a new block so we zero the byte counter
|
||||
@@ -135,19 +134,22 @@ static void openssl_encrypt_block(struct openssl_encrypt *s, unsigned char *plai
|
||||
|
||||
switch(s->mode) {
|
||||
case MODE_AES128_CTR:
|
||||
#ifdef HAVE_CRYPTO
|
||||
AES_ctr128_encrypt(plaintext, ciphertext, len, &s->key, s->ivec,
|
||||
s->ecount, &s->num);
|
||||
#endif
|
||||
break;
|
||||
case MODE_AES128_ECB:
|
||||
assert(len == AES_BLOCK_SIZE);
|
||||
#ifdef HAVE_CRYPTO
|
||||
AES_ecb_encrypt(plaintext, ciphertext,
|
||||
&s->key, AES_ENCRYPT);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#else
|
||||
UNUSED(s);
|
||||
UNUSED(plaintext);
|
||||
UNUSED(ciphertext);
|
||||
UNUSED(nonce_plus_counter);
|
||||
UNUSED(len);
|
||||
#endif
|
||||
}
|
||||
|
||||
void openssl_encrypt_destroy(struct openssl_encrypt *s)
|
||||
|
||||
@@ -46,6 +46,14 @@
|
||||
* Communications of the ACM, Jan 1990, Vol 33 No 1.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void lbl_srandom(uint32_t seed);
|
||||
uint32_t lbl_random(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -82,9 +82,12 @@ void _dprintf(const char *format, ...)
|
||||
|
||||
void verbose_msg(const char *format, ...)
|
||||
{
|
||||
// print verbose messages in debug mode, anyway
|
||||
#ifndef DEBUG
|
||||
if (!verbose) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "win32_gl_common.h"
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "gl_context.h"
|
||||
|
||||
/**
|
||||
@@ -34,13 +35,13 @@ bool init_gl_context(struct gl_context *context, int which) {
|
||||
#ifdef HAVE_LINUX
|
||||
x11_enter_thread();
|
||||
if(which == GL_CONTEXT_ANY) {
|
||||
printf("Trying OpenGL 3.1 first.\n");
|
||||
debug_msg("Trying OpenGL 3.1 first.\n");
|
||||
context->context = glx_init(MK_OPENGL_VERSION(3,1));
|
||||
context->legacy = FALSE;
|
||||
}
|
||||
if(!context->context) {
|
||||
if(which != GL_CONTEXT_LEGACY) {
|
||||
fprintf(stderr, "[RTDXT] OpenGL 3.1 profile failed to initialize, falling back to legacy profile.\n");
|
||||
debug_msg("OpenGL 3.1 profile failed to initialize, falling back to legacy profile.\n");
|
||||
}
|
||||
context->context = glx_init(OPENGL_VERSION_UNSPECIFIED);
|
||||
context->legacy = TRUE;
|
||||
@@ -51,10 +52,10 @@ bool init_gl_context(struct gl_context *context, int which) {
|
||||
#elif defined HAVE_MACOSX
|
||||
if(which == GL_CONTEXT_ANY) {
|
||||
if(get_mac_kernel_version_major() >= 11) {
|
||||
printf("[RTDXT] Mac 10.7 or latter detected. Trying OpenGL 3.2 Core profile first.\n");
|
||||
debug_msg("Mac 10.7 or latter detected. Trying OpenGL 3.2 Core profile first.\n");
|
||||
context->context = mac_gl_init(MAC_GL_PROFILE_3_2);
|
||||
if(!context->context) {
|
||||
fprintf(stderr, "[RTDXT] OpenGL 3.2 Core profile failed to initialize, falling back to legacy profile.\n");
|
||||
debug_msg("OpenGL 3.2 Core profile failed to initialize, falling back to legacy profile.\n");
|
||||
} else {
|
||||
context->legacy = FALSE;
|
||||
}
|
||||
@@ -98,25 +99,25 @@ GLuint glsl_compile_link(const char *vprogram, const char *fprogram)
|
||||
glCompileShader(fhandle);
|
||||
/* Print compile log */
|
||||
glGetShaderInfoLog(fhandle,32768,NULL,log);
|
||||
printf("Compile Log: %s\n", log);
|
||||
debug_msg("Compile Log: %s\n", log);
|
||||
/* vertex */
|
||||
glShaderSource(vhandle, 1, &vprogram, NULL);
|
||||
glCompileShader(vhandle);
|
||||
/* Print compile log */
|
||||
glGetShaderInfoLog(vhandle,32768,NULL,log);
|
||||
printf("Compile Log: %s\n", log);
|
||||
debug_msg("Compile Log: %s\n", log);
|
||||
|
||||
/* attach and link */
|
||||
glAttachShader(phandle, vhandle);
|
||||
glAttachShader(phandle, fhandle);
|
||||
glLinkProgram(phandle);
|
||||
|
||||
printf("Program compilation/link status: ");
|
||||
debug_msg("Program compilation/link status: ");
|
||||
gl_check_error();
|
||||
|
||||
glGetProgramInfoLog(phandle, 32768, NULL, (GLchar*)log);
|
||||
if ( strlen(log) > 0 )
|
||||
printf("Link Log: %s\n", log);
|
||||
debug_msg("Link Log: %s\n", log);
|
||||
|
||||
// mark shaders for deletion when program is deleted
|
||||
glDeleteShader(vhandle);
|
||||
|
||||
@@ -112,7 +112,7 @@ void glx_free(void *arg)
|
||||
|
||||
display = x11_get_display();
|
||||
if(!display) {
|
||||
fprintf(stderr, "Unable to get shared display for GLX!\n");
|
||||
error_msg("Unable to get shared display for GLX!\n");
|
||||
x11_unlock();
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ void glx_free(void *arg)
|
||||
glXMakeCurrent( display, context->win, context->ctx );
|
||||
|
||||
glXDestroyContext( display, context->ctx );
|
||||
fprintf(stderr, "GLX context destroyed\n");
|
||||
debug_msg("GLX context destroyed\n");
|
||||
#ifdef HAVE_GPUPERFAPI
|
||||
GPA_Destroy();
|
||||
#endif
|
||||
@@ -238,22 +238,22 @@ void *glx_init(glx_opengl_version_t version)
|
||||
if ( !glXQueryVersion( display, &glx_major, &glx_minor ) ||
|
||||
( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) )
|
||||
{
|
||||
printf( "Invalid GLX version" );
|
||||
verbose_msg( "Invalid GLX version" );
|
||||
goto error;
|
||||
}
|
||||
|
||||
printf( "Getting matching framebuffer configs\n" );
|
||||
debug_msg( "Getting matching framebuffer configs\n" );
|
||||
fbc = glXChooseFBConfig( display, DefaultScreen( display ),
|
||||
visual_attribs, &fbcount );
|
||||
if ( !fbc )
|
||||
{
|
||||
printf( "Failed to retrieve a framebuffer config\n" );
|
||||
debug_msg( "Failed to retrieve a framebuffer config\n" );
|
||||
goto error;
|
||||
}
|
||||
printf( "Found %d matching FB configs.\n", fbcount );
|
||||
debug_msg( "Found %d matching FB configs.\n", fbcount );
|
||||
|
||||
// Pick the FB config/visual with the most samples per pixel
|
||||
printf( "Getting XVisualInfos\n" );
|
||||
debug_msg( "Getting XVisualInfos\n" );
|
||||
|
||||
for ( int i = 0; i < fbcount; i++ )
|
||||
{
|
||||
@@ -264,7 +264,7 @@ void *glx_init(glx_opengl_version_t version)
|
||||
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
|
||||
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLES , &samples );
|
||||
|
||||
printf( " Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
|
||||
debug_msg( " Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
|
||||
" SAMPLES = %d\n",
|
||||
i, (unsigned int) vi -> visualid, samp_buf, samples );
|
||||
|
||||
@@ -283,9 +283,9 @@ void *glx_init(glx_opengl_version_t version)
|
||||
|
||||
// Get a visual
|
||||
vi = glXGetVisualFromFBConfig( display, bestFbc );
|
||||
printf( "Chosen visual ID = 0x%x\n", (unsigned int) vi->visualid );
|
||||
debug_msg( "Chosen visual ID = 0x%x\n", (unsigned int) vi->visualid );
|
||||
|
||||
printf( "Creating colormap\n" );
|
||||
debug_msg( "Creating colormap\n" );
|
||||
XSetWindowAttributes swa;
|
||||
swa.colormap = context->cmap = XCreateColormap( display,
|
||||
RootWindow( display, vi->screen ),
|
||||
@@ -294,7 +294,7 @@ void *glx_init(glx_opengl_version_t version)
|
||||
swa.border_pixel = 0;
|
||||
swa.event_mask = StructureNotifyMask;
|
||||
|
||||
printf( "Creating window\n" );
|
||||
debug_msg( "Creating window\n" );
|
||||
context->win = XCreateWindow( display, RootWindow( display, vi->screen ),
|
||||
0, 0, 1920, 1080, 0, vi->depth, InputOutput,
|
||||
vi->visual,
|
||||
@@ -303,7 +303,7 @@ void *glx_init(glx_opengl_version_t version)
|
||||
|
||||
if ( !context->win )
|
||||
{
|
||||
printf( "Failed to create window.\n" );
|
||||
debug_msg( "Failed to create window.\n" );
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -313,7 +313,7 @@ void *glx_init(glx_opengl_version_t version)
|
||||
/* We don't need this for UG */
|
||||
/*XStoreName( display, win, "GL 3.0 Window" );
|
||||
|
||||
printf( "Mapping window\n" );
|
||||
debug_msg( "Mapping window\n" );
|
||||
XMapWindow( display, win );*/
|
||||
|
||||
// Get the default screen's GLX extension list
|
||||
@@ -342,11 +342,11 @@ void *glx_init(glx_opengl_version_t version)
|
||||
if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) ||
|
||||
!glXCreateContextAttribsARB )
|
||||
{
|
||||
printf( "glXCreateContextAttribsARB() not found"
|
||||
debug_msg( "glXCreateContextAttribsARB() not found"
|
||||
" ... using old-style GLX context\n" );
|
||||
context->ctx = glXCreateNewContext( display, bestFbc, GLX_RGBA_TYPE, 0, True );
|
||||
if(!VERSION_IS_UNSPECIFIED(version)) {
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,14 +366,14 @@ void *glx_init(glx_opengl_version_t version)
|
||||
context_attribs[3] = VERSION_GET_MINOR(version);
|
||||
}
|
||||
|
||||
printf( "Creating context\n" );
|
||||
debug_msg( "Creating context\n" );
|
||||
context->ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
|
||||
True, context_attribs );
|
||||
|
||||
// Sync to ensure any errors generated are processed.
|
||||
XSync( display, False );
|
||||
if ( !ctxErrorOccurred && context->ctx )
|
||||
printf( "Created GL %d.%d context\n", context_attribs[1], context_attribs[3]);
|
||||
debug_msg( "Created GL %d.%d context\n", context_attribs[1], context_attribs[3]);
|
||||
else
|
||||
{
|
||||
if(VERSION_IS_UNSPECIFIED(version)) {
|
||||
@@ -388,7 +388,7 @@ void *glx_init(glx_opengl_version_t version)
|
||||
|
||||
ctxErrorOccurred = FALSE;
|
||||
|
||||
printf( "Failed to create GL 3.0 context"
|
||||
debug_msg( "Failed to create GL 3.0 context"
|
||||
" ... using old-style GLX context\n" );
|
||||
context->ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
|
||||
True, context_attribs );
|
||||
@@ -407,21 +407,21 @@ void *glx_init(glx_opengl_version_t version)
|
||||
|
||||
if ( ctxErrorOccurred || !context->ctx )
|
||||
{
|
||||
printf( "Failed to create an OpenGL context\n" );
|
||||
debug_msg( "Failed to create an OpenGL context\n" );
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Verifying that context is a direct context
|
||||
if ( ! glXIsDirect ( display, context->ctx ) )
|
||||
{
|
||||
printf( "Indirect GLX rendering context obtained\n" );
|
||||
debug_msg( "Indirect GLX rendering context obtained\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "Direct GLX rendering context obtained\n" );
|
||||
debug_msg( "Direct GLX rendering context obtained\n" );
|
||||
}
|
||||
|
||||
printf( "Making context current\n" );
|
||||
debug_msg( "Making context current\n" );
|
||||
glXMakeCurrent( display, context->win, context->ctx );
|
||||
|
||||
glewInit();
|
||||
|
||||
@@ -6,122 +6,86 @@
|
||||
|
||||
#include "hd-rum-translator/hd-rum-decompress.h"
|
||||
#include "hd-rum-translator/hd-rum-recompress.h"
|
||||
#include "rtp/ldgm.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
#include "debug.h"
|
||||
#include "rtp/video_decoders.h" // init_decompress()
|
||||
#include "host.h"
|
||||
#include "rtp/rtp.h"
|
||||
#include "rtp/rtp_callback.h"
|
||||
#include "transmit.h"
|
||||
#include "tv.h"
|
||||
}
|
||||
|
||||
#include "video.h"
|
||||
#include "video_codec.h"
|
||||
#include "video_compress.h"
|
||||
#include "video_decompress.h"
|
||||
#include "video_display.h"
|
||||
#include "video_rxtx/ultragrid_rtp.h"
|
||||
|
||||
#define MAX_QUEUE_SIZE 1
|
||||
static constexpr int MAX_QUEUE_SIZE = 2;
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern int mtu; // defined in hd-rum-transcode.c
|
||||
|
||||
struct substream_frame {
|
||||
char *data;
|
||||
int data_len;
|
||||
struct output_port_info {
|
||||
output_port_info(void *s, bool a) : state(s), active(a) {}
|
||||
void *state;
|
||||
bool active;
|
||||
};
|
||||
|
||||
struct message {
|
||||
virtual ~message() {}
|
||||
struct state_transcoder_decompress : public frame_recv_delegate {
|
||||
vector<output_port_info> output_ports;
|
||||
int active_ports;
|
||||
|
||||
unique_ptr<ultragrid_rtp_video_rxtx> video_rxtx;
|
||||
|
||||
queue<shared_ptr<video_frame>> received_frame;
|
||||
|
||||
mutex lock;
|
||||
condition_variable have_frame_cv;
|
||||
condition_variable frame_consumed_cv;
|
||||
thread worker_thread;
|
||||
|
||||
struct display *display;
|
||||
struct control_state *control;
|
||||
thread receiver_thread;
|
||||
|
||||
void frame_arrived(struct video_frame *f);
|
||||
|
||||
virtual ~state_transcoder_decompress() {}
|
||||
void worker();
|
||||
};
|
||||
|
||||
struct poisoned_pill : public message {
|
||||
};
|
||||
|
||||
struct packet_desc {
|
||||
int pt;
|
||||
union {
|
||||
struct video_desc video;
|
||||
struct fec_desc fec;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
struct frame : public message {
|
||||
struct packet_desc packet_desc;
|
||||
int tile_count;
|
||||
|
||||
map <int, substream_frame> substreams;
|
||||
map <int, map<int, int> > packets;
|
||||
uint32_t ts;
|
||||
uint32_t ssrc;
|
||||
|
||||
~frame() {
|
||||
for(map<int, substream_frame>::iterator it = substreams.begin();
|
||||
it != substreams.end();
|
||||
++it) {
|
||||
free(it->second.data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct state_transcoder_decompress {
|
||||
void **output_ports;
|
||||
int output_port_count;
|
||||
|
||||
void **output_inact_ports;
|
||||
int output_inact_port_count;
|
||||
|
||||
struct rtp *network_device;
|
||||
|
||||
struct timeval start_time;
|
||||
|
||||
struct frame *network_frame;
|
||||
queue<message *> received_frame;
|
||||
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t have_frame_cv;
|
||||
pthread_t thread_id;
|
||||
|
||||
int64_t my_last_ssrc;
|
||||
|
||||
uint32_t last_packet_ts;
|
||||
};
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
static void hd_rum_receive_pkt(struct rtp *session, rtp_event *e);
|
||||
static void receive_packet(struct state_transcoder_decompress *s, rtp_packet *pckt_rtp);
|
||||
static bool decode_header(uint32_t *hdr, struct packet_desc *desc, int *buffer_len, int *substream);
|
||||
static bool decode_video_header(uint32_t *hdr, struct video_desc *desc, int *buffer_len, int *substream);
|
||||
static void *worker(void *arg);
|
||||
|
||||
void hd_rum_decompress_add_port(void *state, void *recompress_port)
|
||||
void state_transcoder_decompress::frame_arrived(struct video_frame *f)
|
||||
{
|
||||
struct state_transcoder_decompress *s = (struct state_transcoder_decompress *) state;
|
||||
|
||||
s->output_port_count += 1;
|
||||
s->output_ports = (void **) realloc(s->output_ports,
|
||||
s->output_port_count * sizeof(void *));
|
||||
s->output_ports[s->output_port_count - 1] =
|
||||
recompress_port;
|
||||
unique_lock<mutex> l(lock);
|
||||
if (received_frame.size() >= MAX_QUEUE_SIZE) {
|
||||
fprintf(stderr, "Hd-rum-decompress max queue size (%d) reached!\n", MAX_QUEUE_SIZE);
|
||||
}
|
||||
frame_consumed_cv.wait(l, [this]{ return received_frame.size() < MAX_QUEUE_SIZE; });
|
||||
received_frame.push(shared_ptr<video_frame>(f, vf_free));
|
||||
l.unlock();
|
||||
have_frame_cv.notify_one();
|
||||
}
|
||||
|
||||
void hd_rum_decompress_add_inactive_port(void *state, void *recompress_port)
|
||||
void hd_rum_decompress_add_port(void *state, void *recompress_port, bool active)
|
||||
{
|
||||
struct state_transcoder_decompress *s = (struct state_transcoder_decompress *) state;
|
||||
|
||||
s->output_inact_port_count += 1;
|
||||
s->output_inact_ports = (void **) realloc(s->output_inact_ports,
|
||||
s->output_inact_port_count * sizeof(void *));
|
||||
s->output_inact_ports[s->output_inact_port_count - 1] =
|
||||
recompress_port;
|
||||
s->output_ports.emplace_back(recompress_port, active);
|
||||
if (active)
|
||||
s->active_ports += 1;
|
||||
}
|
||||
|
||||
void hd_rum_decompress_set_active(void *state, void *recompress_port, bool active)
|
||||
{
|
||||
struct state_transcoder_decompress *s = (struct state_transcoder_decompress *) state;
|
||||
|
||||
for (auto && port : s->output_ports) {
|
||||
if (port.state == recompress_port) {
|
||||
port.active = active;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t hd_rum_decompress_write(void *state, void *buf, size_t count)
|
||||
@@ -129,523 +93,102 @@ ssize_t hd_rum_decompress_write(void *state, void *buf, size_t count)
|
||||
struct state_transcoder_decompress *s = (struct state_transcoder_decompress *) state;
|
||||
|
||||
// if there are no active output ports, simply quit
|
||||
if (s->output_port_count == 0) {
|
||||
if (s->active_ports == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct timeval curr_time;
|
||||
gettimeofday(&curr_time, NULL);
|
||||
uint32_t ts = tv_diff(curr_time, s->start_time) * 90000;
|
||||
return rtp_recv_push_data(s->network_device,
|
||||
(char *) buf, count, ts);
|
||||
return rtp_send_raw_rtp_data(s->video_rxtx->m_network_devices[0],
|
||||
(char *) buf, count);
|
||||
}
|
||||
|
||||
#define MAX_SUBSTREAMS 1024
|
||||
|
||||
static void *worker(void *arg)
|
||||
void state_transcoder_decompress::worker()
|
||||
{
|
||||
struct state_transcoder_decompress *s = (struct state_transcoder_decompress *) arg;
|
||||
struct video_desc last_desc;
|
||||
struct fec_desc last_fec_desc;
|
||||
while (1) {
|
||||
unique_lock<mutex> l(lock);
|
||||
have_frame_cv.wait(l, [this]{return !received_frame.empty();});
|
||||
|
||||
struct state_decompress *decompress = NULL;
|
||||
struct video_frame *uncompressed_frame[2] = { NULL, NULL };
|
||||
int tmp_buffers_count = 0;
|
||||
char **tmp_buffers[2] = { (char **) malloc(tmp_buffers_count * sizeof(char *)),
|
||||
(char **) malloc(tmp_buffers_count * sizeof(char *)) };
|
||||
bool decompress_accepts_corrupted_frame = false;
|
||||
fec *fec_state = NULL;
|
||||
shared_ptr<video_frame> current_frame = received_frame.front();
|
||||
received_frame.pop();
|
||||
l.unlock();
|
||||
frame_consumed_cv.notify_one();
|
||||
|
||||
char *compressed_buffers[MAX_SUBSTREAMS];
|
||||
int compressed_len[MAX_SUBSTREAMS];
|
||||
int current_idx = 0;
|
||||
|
||||
memset(&last_desc, 0, sizeof(last_desc));
|
||||
memset(&last_fec_desc, 0, sizeof(last_fec_desc));
|
||||
|
||||
struct video_desc video_header;
|
||||
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
struct frame *last_frame = NULL;
|
||||
|
||||
while(1) {
|
||||
struct frame *current_frame;
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
while(s->received_frame.empty()) {
|
||||
pthread_cond_wait(&s->have_frame_cv, &s->lock);
|
||||
}
|
||||
|
||||
message *recv_frame = s->received_frame.front();
|
||||
s->received_frame.pop();
|
||||
current_frame = dynamic_cast<frame *>(recv_frame);
|
||||
if(!current_frame) { // poisoned pill - s->rec_fr was not (frame *)
|
||||
delete recv_frame;
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
if (!current_frame) { // poisoned pill
|
||||
break;
|
||||
}
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
if(current_frame->packet_desc.pt == PT_VIDEO_LDGM) {
|
||||
unsigned int k = current_frame->packet_desc.fec.k;
|
||||
unsigned int m = current_frame->packet_desc.fec.m;
|
||||
unsigned int c = current_frame->packet_desc.fec.c;
|
||||
unsigned int seed = current_frame->packet_desc.fec.seed;
|
||||
if(last_fec_desc.k != k ||
|
||||
last_fec_desc.m != m ||
|
||||
last_fec_desc.c != c ||
|
||||
last_fec_desc.seed != seed) {
|
||||
delete fec_state;
|
||||
fec_state = new ldgm(k, m, c, seed);
|
||||
last_fec_desc = current_frame->packet_desc.fec;
|
||||
}
|
||||
|
||||
for(int i = 0; i < current_frame->tile_count; ++i) {
|
||||
compressed_len[i] = 0;
|
||||
char *data = current_frame->substreams[i].data;
|
||||
fec_state->decode(data,
|
||||
current_frame->substreams[i].data_len,
|
||||
&compressed_buffers[i], &compressed_len[i],
|
||||
current_frame->packets[i]);
|
||||
|
||||
int unused_substr;
|
||||
if(!compressed_len[i]) {
|
||||
fprintf(stderr, "LDGM: unable to reconstruct data.\n");
|
||||
delete current_frame;
|
||||
goto next_iteration;
|
||||
}
|
||||
if(!decode_video_header((uint32_t *) compressed_buffers[0], &video_header,
|
||||
&compressed_len[i], &unused_substr)) {
|
||||
delete current_frame;
|
||||
goto next_iteration;
|
||||
}
|
||||
compressed_buffers[i] += sizeof(video_payload_hdr_t);
|
||||
}
|
||||
} else {
|
||||
for(int i = 0; i < current_frame->tile_count; ++i) {
|
||||
compressed_buffers[i] = current_frame->substreams[i].data;
|
||||
compressed_len[i] = current_frame->substreams[i].data_len;
|
||||
}
|
||||
video_header = current_frame->packet_desc.video;
|
||||
}
|
||||
|
||||
// reconfiguration
|
||||
if(!video_desc_eq(last_desc, video_header)) {
|
||||
if(last_frame) {
|
||||
for(int i = 0; i < s->output_port_count; ++i) {
|
||||
recompress_wait_complete(s->output_ports[i]);
|
||||
}
|
||||
}
|
||||
delete last_frame;
|
||||
last_frame = NULL;
|
||||
for(int i = 0; i < 2; ++i) {
|
||||
vf_free(uncompressed_frame[i]);
|
||||
for(int j = 0; j < tmp_buffers_count; ++j) {
|
||||
free(tmp_buffers[i][j]);
|
||||
}
|
||||
}
|
||||
struct video_desc uncompressed_desc = video_header;
|
||||
uncompressed_desc.color_spec = UYVY;
|
||||
uncompressed_desc.tile_count = current_frame->tile_count;
|
||||
|
||||
for(int i = 0; i < 2; ++i)
|
||||
uncompressed_frame[i] = vf_alloc_desc(uncompressed_desc);
|
||||
|
||||
last_desc = video_header;
|
||||
|
||||
if(is_codec_opaque(video_header.color_spec)) {
|
||||
if(decompress)
|
||||
decompress_done(decompress);
|
||||
int ret;
|
||||
ret = init_decompress(video_header.color_spec,
|
||||
uncompressed_desc.color_spec, &decompress, 1);
|
||||
if(!ret) {
|
||||
fprintf(stderr, "Unable to initialize decompress!\n");
|
||||
abort();
|
||||
}
|
||||
uncompressed_desc.color_spec = UYVY;
|
||||
int linesize = vc_get_linesize(uncompressed_desc.width,
|
||||
uncompressed_desc.color_spec);
|
||||
int pitch = linesize;
|
||||
if(!decompress_reconfigure(decompress, video_header,
|
||||
0, 8, 16, pitch, uncompressed_desc.color_spec)) {
|
||||
|
||||
fprintf(stderr, "Unable to reconfigure decompress!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
size_t size = sizeof(res);
|
||||
ret = decompress_get_property(decompress,
|
||||
DECOMPRESS_PROPERTY_ACCEPTS_CORRUPTED_FRAME,
|
||||
&res,
|
||||
&size);
|
||||
if(ret && res) {
|
||||
decompress_accepts_corrupted_frame = true;
|
||||
} else {
|
||||
decompress_accepts_corrupted_frame = false;
|
||||
}
|
||||
|
||||
tmp_buffers_count = current_frame->tile_count;
|
||||
for(int i = 0; i < 2; ++i) {
|
||||
tmp_buffers[i] = (char **)
|
||||
realloc(tmp_buffers[i], tmp_buffers_count * sizeof(char *));
|
||||
for(int j = 0; j < current_frame->tile_count; ++j) {
|
||||
int data_len = linesize * uncompressed_desc.height;
|
||||
tmp_buffers[i][j] = (char *) malloc(data_len);
|
||||
uncompressed_frame[i]->tiles[j].data = tmp_buffers[i][j];
|
||||
uncompressed_frame[i]->tiles[j].data_len = data_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we need to decompress first
|
||||
if(is_codec_opaque(video_header.color_spec)) {
|
||||
bool corrupted = false;
|
||||
for(map <int, substream_frame>::iterator it = current_frame->substreams.begin();
|
||||
it != current_frame->substreams.end();
|
||||
++it) {
|
||||
int total_data_len = 0;
|
||||
map<int, int> &substream_packets = current_frame->packets[it->first];
|
||||
for(map <int, int>::iterator it_packets = substream_packets.begin();
|
||||
it_packets != substream_packets.end();
|
||||
++it_packets) {
|
||||
total_data_len += it_packets->second;
|
||||
}
|
||||
if(total_data_len != it->second.data_len) {
|
||||
fprintf(stderr, "Corrupted frame!\n");
|
||||
corrupted = true;
|
||||
}
|
||||
}
|
||||
if(!corrupted || decompress_accepts_corrupted_frame) {
|
||||
for(int i = 0; i < current_frame->tile_count; ++i) {
|
||||
decompress_frame(decompress,
|
||||
(unsigned char *) uncompressed_frame[current_idx]->tiles[i].data,
|
||||
(unsigned char *) compressed_buffers[i],
|
||||
compressed_len[i],
|
||||
0 // TODO: propagate correct sequence number
|
||||
);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Frame dropped by decompress.\n");
|
||||
delete current_frame;
|
||||
goto next_iteration;
|
||||
}
|
||||
|
||||
} else {
|
||||
for(int i = 0; i < current_frame->tile_count; ++i) {
|
||||
uncompressed_frame[current_idx]->tiles[i].data =
|
||||
compressed_buffers[i];
|
||||
uncompressed_frame[current_idx]->tiles[i].data_len =
|
||||
compressed_len[i];
|
||||
}
|
||||
}
|
||||
|
||||
// to meet RTP requirements, translators must not touch SSRC
|
||||
// Watch out not to run this during recompress transmission
|
||||
if(s->my_last_ssrc != current_frame->ssrc) {
|
||||
for(int i = 0; i < s->output_port_count; ++i) {
|
||||
recompress_assign_ssrc(s->output_ports[i],
|
||||
current_frame->ssrc);
|
||||
}
|
||||
s->my_last_ssrc = current_frame->ssrc;
|
||||
}
|
||||
|
||||
if(last_frame) {
|
||||
for(int i = 0; i < s->output_port_count; ++i) {
|
||||
recompress_wait_complete(s->output_ports[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < s->output_port_count; ++i) {
|
||||
recompress_process_async(s->output_ports[i], uncompressed_frame[current_idx]);
|
||||
}
|
||||
|
||||
delete last_frame;
|
||||
last_frame = current_frame;
|
||||
current_idx = (current_idx + 1) % 2;
|
||||
next_iteration:
|
||||
;
|
||||
}
|
||||
|
||||
if(last_frame) {
|
||||
for(int i = 0; i < s->output_port_count; ++i) {
|
||||
recompress_wait_complete(s->output_ports[i]);
|
||||
for (unsigned int i = 0; i < output_ports.size(); ++i) {
|
||||
if (output_ports[i].active)
|
||||
recompress_process_async(output_ports[i].state, current_frame);
|
||||
}
|
||||
}
|
||||
delete last_frame;
|
||||
last_frame = NULL;
|
||||
|
||||
for(int i = 0; i < 2; ++i) {
|
||||
for(int j = 0; j < tmp_buffers_count; ++j) {
|
||||
free(tmp_buffers[i][j]);
|
||||
}
|
||||
free(tmp_buffers[i]);
|
||||
}
|
||||
|
||||
if(decompress) {
|
||||
decompress_done(decompress);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *hd_rum_decompress_init()
|
||||
void *hd_rum_decompress_init(struct module *parent)
|
||||
{
|
||||
struct state_transcoder_decompress *s;
|
||||
int ttl = 255;
|
||||
double rtcp_bw = 5 * 1024 * 1024; /* FIXME */
|
||||
bool use_ipv6 = false;
|
||||
|
||||
initialize_video_decompress();
|
||||
s = new state_transcoder_decompress();
|
||||
|
||||
s = new state_transcoder_decompress;
|
||||
s->network_device = rtp_init_if("localhost", (char *) NULL, 0, 0, ttl,
|
||||
rtcp_bw, FALSE, hd_rum_receive_pkt, (uint8_t *) s,
|
||||
use_ipv6, false);
|
||||
s->my_last_ssrc = -1;
|
||||
if(!s->network_device) {
|
||||
fprintf(stderr, "Unable to initialize RTP.\n");
|
||||
return NULL;
|
||||
}
|
||||
rtp_set_option(s->network_device, RTP_OPT_WEAK_VALIDATION,
|
||||
TRUE);
|
||||
rtp_set_sdes(s->network_device, rtp_my_ssrc(s->network_device),
|
||||
RTCP_SDES_TOOL,
|
||||
PACKAGE_STRING, strlen(PACKAGE_STRING));
|
||||
char cfg[128] = "";
|
||||
snprintf(cfg, sizeof cfg, "%p", s);
|
||||
assert (initialize_video_display("pipe", cfg, 0, &s->display) == 0);
|
||||
|
||||
s->network_frame = NULL;
|
||||
map<string, param_u> params;
|
||||
|
||||
s->output_port_count = 0;
|
||||
s->output_ports = (void **) malloc(0);
|
||||
s->output_inact_port_count = 0;
|
||||
s->output_inact_ports = (void **) malloc(0);
|
||||
// common
|
||||
params["parent"].ptr = parent;
|
||||
params["exporter"].ptr = NULL;
|
||||
params["compression"].ptr = (void *) "none";
|
||||
params["rxtx_mode"].i = MODE_RECEIVER;
|
||||
|
||||
s->last_packet_ts = 0u;
|
||||
//RTP
|
||||
params["mtu"].i = 9000; // doesn't matter anyway...
|
||||
// should be localhost and RX TX ports the same (here dynamic) in order to work like a pipe
|
||||
params["receiver"].ptr = (void *) "localhost";
|
||||
params["rx_port"].i = 0;
|
||||
params["tx_port"].i = 0;
|
||||
params["use_ipv6"].b = use_ipv6;
|
||||
params["mcast_if"].ptr = (void *) NULL;
|
||||
params["fec"].ptr = (void *) "none";
|
||||
params["encryption"].ptr = (void *) NULL;
|
||||
params["packet_rate"].i = 0;
|
||||
|
||||
gettimeofday(&s->start_time, NULL);
|
||||
// UltraGrid RTP
|
||||
params["postprocess"].ptr = (void *) NULL;
|
||||
params["decoder_mode"].l = VIDEO_NORMAL;
|
||||
params["display_device"].ptr = s->display;
|
||||
|
||||
pthread_mutex_init(&s->lock, NULL);
|
||||
pthread_cond_init(&s->have_frame_cv, NULL);
|
||||
s->video_rxtx = unique_ptr<ultragrid_rtp_video_rxtx>(dynamic_cast<ultragrid_rtp_video_rxtx *>(video_rxtx::create(ULTRAGRID_RTP, params)));
|
||||
assert (s->video_rxtx);
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
|
||||
if(pthread_create(&s->thread_id, NULL, worker, (void *) s) != 0) {
|
||||
fprintf(stderr, "Unable to create thread\n");
|
||||
return NULL;
|
||||
}
|
||||
s->worker_thread = thread(&state_transcoder_decompress::worker, s);
|
||||
s->receiver_thread = thread(&video_rxtx::receiver_thread, s->video_rxtx.get());
|
||||
|
||||
return (void *) s;
|
||||
}
|
||||
|
||||
static bool decode_video_header(uint32_t *hdr, struct video_desc *desc, int *buffer_len, int *substream)
|
||||
{
|
||||
int fps_pt, fpsd, fd, fi;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = ntohl(hdr[0]);
|
||||
*substream = tmp >> 22;
|
||||
|
||||
|
||||
*buffer_len = ntohl(hdr[2]);
|
||||
desc->width = ntohl(hdr[3]) >> 16;
|
||||
desc->height = ntohl(hdr[3]) & 0xffff;
|
||||
desc->color_spec = get_codec_from_fcc(hdr[4]);
|
||||
if(desc->color_spec == (codec_t) -1) {
|
||||
fprintf(stderr, "Unknown FourCC \"%4s\"!\n", (char *) &hdr[4]);
|
||||
return false;
|
||||
}
|
||||
|
||||
tmp = ntohl(hdr[5]);
|
||||
desc->interlacing = (enum interlacing_t) (tmp >> 29);
|
||||
fps_pt = (tmp >> 19) & 0x3ff;
|
||||
fpsd = (tmp >> 15) & 0xf;
|
||||
fd = (tmp >> 14) & 0x1;
|
||||
fi = (tmp >> 13) & 0x1;
|
||||
|
||||
desc->fps = compute_fps(fps_pt, fpsd, fd, fi);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool decode_header(uint32_t *hdr, struct packet_desc *desc, int *buffer_len, int *substream)
|
||||
{
|
||||
if(desc->pt == PT_VIDEO) {
|
||||
return decode_video_header(hdr, &desc->video, buffer_len, substream);
|
||||
} else { // PT_VIDEO_LDGM
|
||||
uint32_t tmp;
|
||||
tmp = ntohl(hdr[0]);
|
||||
|
||||
*substream = tmp >> 22;
|
||||
*buffer_len = ntohl(hdr[2]);
|
||||
|
||||
tmp = ntohl(hdr[3]);
|
||||
desc->fec.k = tmp >> 19;
|
||||
desc->fec.m = 0x1fff & (tmp >> 6);
|
||||
desc->fec.c = 0x3f & tmp;
|
||||
desc->fec.seed = ntohl(hdr[4]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_packet(rtp_packet *pckt, char *frame_buffer, map<int, int> &packets)
|
||||
{
|
||||
int hdr_len;
|
||||
if(pckt->pt == PT_VIDEO) {
|
||||
hdr_len = sizeof(video_payload_hdr_t);
|
||||
} else {
|
||||
hdr_len = sizeof(fec_video_payload_hdr_t);
|
||||
}
|
||||
int len = pckt->data_len - hdr_len;
|
||||
char *data = (char *) pckt->data + hdr_len;
|
||||
int data_pos = ntohl(((uint32_t *) pckt->data)[1]);
|
||||
memcpy(frame_buffer + data_pos, data, len);
|
||||
packets[data_pos] = len;
|
||||
}
|
||||
|
||||
static void receive_packet(struct state_transcoder_decompress *s, rtp_packet *pckt_rtp)
|
||||
{
|
||||
if(pckt_rtp->pt != PT_VIDEO && pckt_rtp->pt != PT_VIDEO_LDGM) {
|
||||
fprintf(stderr, "Other packet types than video are not supported.\n");
|
||||
free(pckt_rtp);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
uint32_t *pkt_hdr = (uint32_t *) pckt_rtp->data;
|
||||
struct packet_desc desc;
|
||||
int buffer_len;
|
||||
int substream_idx;
|
||||
|
||||
desc.pt = pckt_rtp->pt;
|
||||
if(!decode_header(pkt_hdr, &desc, &buffer_len, &substream_idx)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(s->network_frame && pckt_rtp->ts > s->network_frame->ts) {
|
||||
// new frame starts without the previous being completed
|
||||
delete s->network_frame;
|
||||
s->network_frame = 0;
|
||||
fprintf(stderr, "Frame dropped (new arriving while old in place)!\n");
|
||||
}
|
||||
|
||||
if(!s->network_frame) { // this packet starts a new frame
|
||||
if(pckt_rtp->ts != s->last_packet_ts) { // this is not part of previous frame
|
||||
s->network_frame = new frame;
|
||||
s->network_frame->packet_desc = desc;
|
||||
s->network_frame->ts = pckt_rtp->ts;
|
||||
s->last_packet_ts = pckt_rtp->ts;
|
||||
s->network_frame->ssrc = pckt_rtp->ssrc;
|
||||
} else { // we received a late frame
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(s->network_frame->substreams.find(substream_idx) ==
|
||||
s->network_frame->substreams.end()) {
|
||||
substream_frame substr;
|
||||
substr.data = (char *) malloc(buffer_len);
|
||||
substr.data_len = buffer_len;
|
||||
s->network_frame->substreams[substream_idx] = substr;
|
||||
s->network_frame->packets[substream_idx] = map<int, int>();
|
||||
}
|
||||
|
||||
decode_packet(pckt_rtp,
|
||||
s->network_frame->substreams[substream_idx].data,
|
||||
s->network_frame->packets[substream_idx]
|
||||
);
|
||||
|
||||
if(pckt_rtp->m) { // fire
|
||||
pthread_mutex_lock(&s->lock);
|
||||
if(s->received_frame.size() >= MAX_QUEUE_SIZE) {
|
||||
fprintf(stderr, "Frame dropped (queue full)!\n");
|
||||
delete s->network_frame;
|
||||
} else {
|
||||
s->network_frame->tile_count =
|
||||
s->network_frame->substreams.size();
|
||||
s->received_frame.push(s->network_frame);
|
||||
}
|
||||
s->network_frame = 0;
|
||||
pthread_cond_signal(&s->have_frame_cv);
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
}
|
||||
|
||||
free(pckt_rtp);
|
||||
}
|
||||
|
||||
static void hd_rum_receive_pkt(struct rtp *session, rtp_event *e)
|
||||
{
|
||||
rtp_packet *pckt_rtp = (rtp_packet *) e->data;
|
||||
struct state_transcoder_decompress *s = (struct state_transcoder_decompress *)
|
||||
rtp_get_userdata(session);
|
||||
|
||||
switch (e->type) {
|
||||
case RX_RTP:
|
||||
if (pckt_rtp->data_len > 0) { /* Only process packets that contain data... */
|
||||
receive_packet(s, pckt_rtp);
|
||||
}
|
||||
break;
|
||||
case RX_TFRC_RX:
|
||||
/* compute TCP friendly data rate */
|
||||
break;
|
||||
case RX_RTCP_START:
|
||||
break;
|
||||
case RX_RTCP_FINISH:
|
||||
break;
|
||||
case RX_SR:
|
||||
break;
|
||||
case RX_RR:
|
||||
break;
|
||||
case RX_RR_EMPTY:
|
||||
break;
|
||||
case RX_SDES:
|
||||
break;
|
||||
case RX_APP:
|
||||
break;
|
||||
case RX_BYE:
|
||||
break;
|
||||
case SOURCE_DELETED:
|
||||
break;
|
||||
case SOURCE_CREATED:
|
||||
break;
|
||||
case RR_TIMEOUT:
|
||||
break;
|
||||
default:
|
||||
debug_msg("Unknown RTP event (type=%d)\n", e->type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void hd_rum_decompress_done(void *state) {
|
||||
struct state_transcoder_decompress *s = (struct state_transcoder_decompress *) state;
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
s->received_frame.push(new poisoned_pill);
|
||||
pthread_cond_signal(&s->have_frame_cv);
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
should_exit_receiver = true;
|
||||
s->receiver_thread.join();
|
||||
|
||||
pthread_join(s->thread_id, NULL);
|
||||
{
|
||||
unique_lock<mutex> l(s->lock);
|
||||
s->received_frame.push(shared_ptr<video_frame>());
|
||||
l.unlock();
|
||||
s->have_frame_cv.notify_one();
|
||||
}
|
||||
|
||||
s->worker_thread.join();
|
||||
|
||||
// cleanup
|
||||
for(int i = 0; i < s->output_port_count; ++i) {
|
||||
recompress_done(s->output_ports[i]);
|
||||
for (unsigned int i = 0; i < s->output_ports.size(); ++i) {
|
||||
recompress_done(s->output_ports[i].state);
|
||||
}
|
||||
free(s->output_ports);
|
||||
|
||||
for(int i = 0; i < s->output_inact_port_count; ++i) {
|
||||
recompress_done(s->output_inact_ports[i]);
|
||||
}
|
||||
free(s->output_inact_ports);
|
||||
|
||||
delete s->network_frame;
|
||||
|
||||
rtp_done(s->network_device);
|
||||
|
||||
pthread_mutex_destroy(&s->lock);
|
||||
pthread_cond_destroy(&s->have_frame_cv);
|
||||
display_done(s->display);
|
||||
|
||||
delete s;
|
||||
}
|
||||
|
||||
@@ -2,12 +2,24 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct module;
|
||||
|
||||
ssize_t hd_rum_decompress_write(void *state, void *buf, size_t count);
|
||||
void *hd_rum_decompress_init();
|
||||
void *hd_rum_decompress_init(struct module *parent);
|
||||
void hd_rum_decompress_done(void *state);
|
||||
void hd_rum_decompress_add_port(void *decompress_state, void *recompress_state);
|
||||
void hd_rum_decompress_add_inactive_port(void *decompress_state, void *recompress_state);
|
||||
void hd_rum_decompress_add_port(void *decompress_state, void *recompress_state, bool active);
|
||||
void hd_rum_decompress_set_active(void *decompress_state, void *recompress_state, bool active);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
struct video_frame;
|
||||
|
||||
#ifdef __cplusplus
|
||||
class frame_recv_delegate {
|
||||
public:
|
||||
virtual void frame_arrived(struct video_frame *) = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -6,265 +6,102 @@
|
||||
|
||||
#include "hd-rum-translator/hd-rum-recompress.h"
|
||||
|
||||
extern "C" {
|
||||
#include "debug.h"
|
||||
#include "host.h"
|
||||
#include "rtp/rtp.h"
|
||||
#include "rtp/rtp_callback.h"
|
||||
#include "transmit.h"
|
||||
#include "tv.h"
|
||||
}
|
||||
|
||||
#include "module.h"
|
||||
#include "video_rxtx/ultragrid_rtp.h"
|
||||
|
||||
#include "video.h"
|
||||
#include "video_codec.h"
|
||||
#include "video_compress.h"
|
||||
#include "video_decompress.h"
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
extern int mtu; // defined in hd-rum-transcode.c
|
||||
using namespace std;
|
||||
|
||||
struct state_recompress {
|
||||
int rx_port, tx_port;
|
||||
const char *host;
|
||||
struct rtp *network_device;
|
||||
struct compress_state *compress;
|
||||
char *required_compress;
|
||||
state_recompress(unique_ptr<ultragrid_rtp_video_rxtx> && vr, string const & h, int tp)
|
||||
: video_rxtx(std::move(vr)), host(h), t0(chrono::system_clock::now()),
|
||||
frames(0), tx_port(tp) {
|
||||
}
|
||||
|
||||
struct timeval start_time;
|
||||
unique_ptr<ultragrid_rtp_video_rxtx> video_rxtx;
|
||||
string host;
|
||||
|
||||
struct video_frame *frame;
|
||||
|
||||
struct tx *tx;
|
||||
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t have_frame_cv;
|
||||
pthread_cond_t frame_consumed_cv;
|
||||
pthread_t thread_id;
|
||||
|
||||
struct module *parent;
|
||||
chrono::system_clock::time_point t0;
|
||||
int frames;
|
||||
int tx_port;
|
||||
};
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
static void *worker(void *arg);
|
||||
static void recompress_rtp_callback(struct rtp *session, rtp_event *e);
|
||||
|
||||
static void *worker(void *arg)
|
||||
{
|
||||
struct state_recompress *s = (struct state_recompress *) arg;
|
||||
struct timeval t0, t;
|
||||
int frames = 0;
|
||||
struct module sender_mod;
|
||||
|
||||
int ret = compress_init(s->parent, s->required_compress, &s->compress);
|
||||
if(ret != 0) {
|
||||
fprintf(stderr, "Unable to initialize video compress: %s\n",
|
||||
s->required_compress);
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
module_init_default(&sender_mod);
|
||||
sender_mod.cls = MODULE_CLASS_SENDER;
|
||||
module_register(&sender_mod, s->parent);
|
||||
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
gettimeofday(&t0, NULL);
|
||||
|
||||
while(1) {
|
||||
pthread_mutex_lock(&s->lock);
|
||||
while(!s->frame) {
|
||||
pthread_cond_wait(&s->have_frame_cv, &s->lock);
|
||||
}
|
||||
|
||||
if(s->frame->tiles[0].data_len == 0) { // poisoned pill
|
||||
vf_free(s->frame);
|
||||
s->frame = NULL;
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
break;
|
||||
}
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
struct message *msg;
|
||||
while((msg = check_message(&sender_mod))) {
|
||||
struct msg_sender *data = (struct msg_sender *) msg;
|
||||
rtp_change_dest(s->network_device,
|
||||
data->receiver);
|
||||
free_message(msg);
|
||||
}
|
||||
|
||||
compress_frame(s->compress, s->frame);
|
||||
struct video_frame *tx_frame =
|
||||
compress_pop(s->compress);
|
||||
|
||||
if(tx_frame) {
|
||||
tx_send(s->tx, tx_frame, s->network_device);
|
||||
} else {
|
||||
fprintf(stderr, "Compress failed\n");
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
s->frame = NULL;
|
||||
pthread_cond_signal(&s->frame_consumed_cv);
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
frames += 1;
|
||||
gettimeofday(&t, NULL);
|
||||
double seconds = tv_diff(t, t0);
|
||||
if(seconds > 5) {
|
||||
double fps = frames / seconds;
|
||||
fprintf(stdout, "[%.4x->%s:%d] %d frames in %g seconds = %g FPS\n",
|
||||
rtp_my_ssrc(s->network_device),
|
||||
s->host, s->tx_port,
|
||||
frames, seconds, fps);
|
||||
t0 = t;
|
||||
frames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(s->compress) {
|
||||
module_done(CAST_MODULE(s->compress));
|
||||
s->compress = NULL;
|
||||
}
|
||||
|
||||
module_done(&sender_mod);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct rtp *initialize_network(const char *host, int rx_port, int tx_port, void *udata,
|
||||
int64_t ssrc = -1) {
|
||||
int ttl = 255;
|
||||
double rtcp_bw = 5 * 1024 * 1024; /* FIXME */
|
||||
bool use_ipv6 = false;
|
||||
|
||||
struct rtp *network_device = rtp_init(host, rx_port, tx_port, ttl,
|
||||
rtcp_bw, FALSE, recompress_rtp_callback, (uint8_t *) udata,
|
||||
use_ipv6, false);
|
||||
if(network_device) {
|
||||
if(ssrc != -1) {
|
||||
int ret = rtp_set_my_ssrc(network_device, ssrc);
|
||||
if(!ret) {
|
||||
fprintf(stderr, "Cannot set custom SSRC.\n");
|
||||
}
|
||||
|
||||
}
|
||||
rtp_set_option(network_device, RTP_OPT_WEAK_VALIDATION,
|
||||
TRUE);
|
||||
rtp_set_sdes(network_device, rtp_my_ssrc(network_device),
|
||||
RTCP_SDES_TOOL,
|
||||
PACKAGE_STRING, strlen(PACKAGE_STRING));
|
||||
}
|
||||
|
||||
return network_device;
|
||||
}
|
||||
|
||||
void *recompress_init(struct module *parent,
|
||||
const char *host, const char *compress, unsigned short rx_port,
|
||||
unsigned short tx_port, int mtu, char *fec, long packet_rate)
|
||||
{
|
||||
struct state_recompress *s;
|
||||
bool use_ipv6 = false;
|
||||
|
||||
initialize_video_decompress();
|
||||
map<string, param_u> params;
|
||||
|
||||
s = (struct state_recompress *) calloc(1, sizeof(struct state_recompress));
|
||||
// common
|
||||
params["parent"].ptr = parent;
|
||||
params["exporter"].ptr = NULL;
|
||||
params["compression"].ptr = (void *) compress;
|
||||
params["rxtx_mode"].i = MODE_SENDER;
|
||||
|
||||
s->parent = parent;
|
||||
//RTP
|
||||
params["mtu"].i = mtu;
|
||||
params["receiver"].ptr = (void *) host;
|
||||
params["rx_port"].i = rx_port;
|
||||
params["tx_port"].i = tx_port;
|
||||
params["use_ipv6"].b = use_ipv6;
|
||||
params["mcast_if"].ptr = (void *) NULL;
|
||||
params["fec"].ptr = (void *) fec;
|
||||
params["encryption"].ptr = (void *) NULL;
|
||||
params["packet_rate"].i = packet_rate;
|
||||
|
||||
s->network_device = initialize_network(host, rx_port, tx_port, s);
|
||||
s->host = host;
|
||||
s->rx_port = rx_port;
|
||||
s->tx_port = tx_port;
|
||||
if(!s->network_device) {
|
||||
fprintf(stderr, "Unable to initialize RTP.\n");
|
||||
return NULL;
|
||||
}
|
||||
// UltraGrid RTP
|
||||
params["postprocess"].ptr = (void *) NULL;
|
||||
params["decoder_mode"].l = VIDEO_NORMAL;
|
||||
params["display_device"].ptr = NULL;
|
||||
|
||||
|
||||
s->required_compress = strdup(compress);
|
||||
s->frame = NULL;
|
||||
const char *requested_encryption = NULL;
|
||||
s->tx = tx_init(s->parent, mtu, TX_MEDIA_VIDEO, fec, requested_encryption, packet_rate);
|
||||
|
||||
gettimeofday(&s->start_time, NULL);
|
||||
|
||||
pthread_mutex_init(&s->lock, NULL);
|
||||
pthread_cond_init(&s->have_frame_cv, NULL);
|
||||
pthread_cond_init(&s->frame_consumed_cv, NULL);
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
|
||||
if(pthread_create(&s->thread_id, NULL, worker, (void *) s) != 0) {
|
||||
fprintf(stderr, "Unable to create thread\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
if(s->compress == NULL) {
|
||||
pthread_join(s->thread_id, NULL);
|
||||
return NULL;
|
||||
}
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
return (void *) s;
|
||||
return new state_recompress(
|
||||
decltype(state_recompress::video_rxtx)(dynamic_cast<ultragrid_rtp_video_rxtx *>(video_rxtx::create(ULTRAGRID_RTP, params))),
|
||||
host,
|
||||
tx_port
|
||||
);
|
||||
}
|
||||
|
||||
void recompress_process_async(void *state, struct video_frame *frame)
|
||||
void recompress_process_async(void *state, shared_ptr<video_frame> frame)
|
||||
{
|
||||
struct state_recompress *s = (struct state_recompress *) state;
|
||||
auto s = static_cast<state_recompress *>(state);
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
assert(s->frame == NULL);
|
||||
s->frame = frame;
|
||||
pthread_cond_signal(&s->have_frame_cv);
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
}
|
||||
s->frames += 1;
|
||||
|
||||
void recompress_wait_complete(void *state)
|
||||
{
|
||||
struct state_recompress *s = (struct state_recompress *) state;
|
||||
chrono::system_clock::time_point now = chrono::system_clock::now();
|
||||
double seconds = chrono::duration_cast<chrono::microseconds>(now - s->t0).count() / 1000000.0;
|
||||
if(seconds > 5) {
|
||||
double fps = s->frames / seconds;
|
||||
fprintf(stdout, "[%.4x->%s:%d] %d frames in %g seconds = %g FPS\n",
|
||||
rtp_my_ssrc(s->video_rxtx->m_network_devices[0]),
|
||||
s->host.c_str(), s->tx_port,
|
||||
s->frames, seconds, fps);
|
||||
s->t0 = now;
|
||||
s->frames = 0;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
while(s->frame != NULL)
|
||||
pthread_cond_wait(&s->frame_consumed_cv, &s->lock);
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
s->video_rxtx->send(frame);
|
||||
}
|
||||
|
||||
void recompress_assign_ssrc(void *state, uint32_t ssrc)
|
||||
{
|
||||
struct state_recompress *s = (struct state_recompress *) state;
|
||||
|
||||
rtp_done(s->network_device);
|
||||
s->network_device = initialize_network(s->host, s->rx_port, s->tx_port,
|
||||
s, ssrc);
|
||||
}
|
||||
|
||||
static void recompress_rtp_callback(struct rtp *session, rtp_event *e)
|
||||
{
|
||||
UNUSED(session);
|
||||
UNUSED(e);
|
||||
// UNIMPLEMENTED NOW
|
||||
UNUSED(state);
|
||||
UNUSED(ssrc);
|
||||
}
|
||||
|
||||
void recompress_done(void *state)
|
||||
{
|
||||
struct state_recompress *s = (struct state_recompress *) state;
|
||||
auto s = static_cast<state_recompress *>(state);
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
assert(s->frame == NULL);
|
||||
s->frame = vf_alloc(1);
|
||||
pthread_cond_signal(&s->have_frame_cv);
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
s->video_rxtx->join();
|
||||
|
||||
pthread_join(s->thread_id, NULL);
|
||||
|
||||
module_done(CAST_MODULE(s->tx));
|
||||
rtp_done(s->network_device);
|
||||
pthread_mutex_destroy(&s->lock);
|
||||
pthread_cond_destroy(&s->have_frame_cv);
|
||||
pthread_cond_destroy(&s->frame_consumed_cv);
|
||||
|
||||
free(s);
|
||||
delete s;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@ void *recompress_init(struct module *parent, const char *host, const char *compr
|
||||
unsigned short rx_port, unsigned short tx_port, int mtu, char *fec,
|
||||
long packet_rate);
|
||||
void recompress_assign_ssrc(void *state, uint32_t ssrc);
|
||||
void recompress_process_async(void *state, struct video_frame *frame);
|
||||
/**
|
||||
* Waits for completion of previous call recompress_process_async
|
||||
*/
|
||||
void recompress_wait_complete(void *state);
|
||||
void recompress_done(void *state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <memory>
|
||||
void recompress_process_async(void *state, std::shared_ptr<video_frame> frame);
|
||||
#endif
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "control_socket.h"
|
||||
#include "host.h"
|
||||
#include "hd-rum-translator/hd-rum-recompress.h"
|
||||
#include "hd-rum-translator/hd-rum-decompress.h"
|
||||
#include "messaging.h"
|
||||
#include "module.h"
|
||||
#include "stats.h"
|
||||
#include "utils/misc.h"
|
||||
@@ -27,8 +29,6 @@
|
||||
#define EXIT_FAIL_USAGE 1
|
||||
#define EXIT_INIT_PORT 3
|
||||
|
||||
long packet_rate = 13600;
|
||||
|
||||
static pthread_t main_thread_id;
|
||||
struct forward;
|
||||
struct item;
|
||||
@@ -39,12 +39,15 @@ struct replica {
|
||||
const char *host;
|
||||
unsigned short port;
|
||||
|
||||
enum {
|
||||
enum type_t {
|
||||
NONE,
|
||||
USE_SOCK,
|
||||
RECOMPRESS
|
||||
} type;
|
||||
};
|
||||
enum type_t type;
|
||||
int sock;
|
||||
void *recompress;
|
||||
volatile enum type_t change_to_type;
|
||||
};
|
||||
|
||||
struct hd_rum_translator_state {
|
||||
@@ -68,13 +71,13 @@ struct hd_rum_translator_state {
|
||||
* Prototypes
|
||||
*/
|
||||
static int output_socket(unsigned short port, const char *host, int bufsize);
|
||||
static ssize_t replica_write(struct replica *s, void *buf, size_t count);
|
||||
static void replica_done(struct replica *s);
|
||||
static struct item *qinit(int qsize);
|
||||
static int buffer_size(int sock, int optname, int size);
|
||||
static void *writer(void *arg);
|
||||
static void signal_handler(int signal);
|
||||
static void usage();
|
||||
void exit_uv(int status);
|
||||
|
||||
static volatile int should_exit = false;
|
||||
|
||||
@@ -99,11 +102,6 @@ static void signal_handler(int signal)
|
||||
|
||||
#define REPLICA_MAGIC 0xd2ff3323
|
||||
|
||||
static ssize_t replica_write(struct replica *s, void *buf, size_t count)
|
||||
{
|
||||
return send(s->sock, buf, count, 0);
|
||||
}
|
||||
|
||||
static void replica_done(struct replica *s)
|
||||
{
|
||||
assert(s->magic == REPLICA_MAGIC);
|
||||
@@ -160,7 +158,7 @@ static int output_socket(unsigned short port, const char *host, int bufsize)
|
||||
{
|
||||
int s;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res;
|
||||
struct addrinfo *res = NULL;
|
||||
char saddr[INET_ADDRSTRLEN];
|
||||
char p[6];
|
||||
|
||||
@@ -200,9 +198,38 @@ static int output_socket(unsigned short port, const char *host, int bufsize)
|
||||
exit(2);
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static struct response *change_replica_type_callback(struct module *mod, struct message *msg)
|
||||
{
|
||||
struct replica *s = (struct replica *) mod->priv_data;
|
||||
|
||||
struct msg_universal *data = (struct msg_universal *) msg;
|
||||
|
||||
enum type_t new_type;
|
||||
if (strcasecmp(data->text, "sock") == 0) {
|
||||
new_type = USE_SOCK;
|
||||
} else if (strcasecmp(data->text, "recompress") == 0) {
|
||||
new_type = RECOMPRESS;
|
||||
} else {
|
||||
new_type = NONE;
|
||||
}
|
||||
free_message(msg);
|
||||
|
||||
if (new_type == NONE) {
|
||||
return new_response(RESPONSE_BAD_REQUEST, NULL);
|
||||
}
|
||||
|
||||
while (s->change_to_type != NONE)
|
||||
;
|
||||
s->change_to_type = new_type;
|
||||
|
||||
return new_response(RESPONSE_OK, NULL);
|
||||
}
|
||||
|
||||
static void *writer(void *arg)
|
||||
{
|
||||
int i;
|
||||
@@ -210,14 +237,25 @@ static void *writer(void *arg)
|
||||
(struct hd_rum_translator_state *) arg;
|
||||
|
||||
while (1) {
|
||||
for (i = 0; i < s->host_count; i++) {
|
||||
if (s->replicas[i].change_to_type != NONE) {
|
||||
s->replicas[i].type = s->replicas[i].change_to_type;
|
||||
hd_rum_decompress_set_active(s->decompress, s->replicas[i].recompress,
|
||||
s->replicas[i].change_to_type == RECOMPRESS);
|
||||
s->replicas[i].change_to_type = NONE;
|
||||
}
|
||||
}
|
||||
|
||||
while (s->qhead != s->qtail) {
|
||||
if(s->qhead->size == 0) { // poisoned pill
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < s->host_count; i++) {
|
||||
if(s->replicas[i].type == USE_SOCK) {
|
||||
replica_write(&s->replicas[i],
|
||||
s->qhead->buf, s->qhead->size);
|
||||
ssize_t ret = send(s->replicas[i].sock, s->qhead->buf, s->qhead->size, 0);
|
||||
if (ret < 0) {
|
||||
perror("Hd-rum-translator send");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +286,8 @@ static void usage(const char *progname) {
|
||||
printf("%s [global_opts] buffer_size port [host1_options] host1 [[host2_options] host2] ...\n",
|
||||
progname);
|
||||
printf("\twhere global_opts may be:\n"
|
||||
"\t\t--control-port <port_number> - control port to connect to\n");
|
||||
"\t\t--control-port <port_number>[:0|:1] - control port to connect to, optionally server/client (default)\n"
|
||||
"\t\t--help\n");
|
||||
printf("\tand hostX_options may be:\n"
|
||||
"\t\t-P <port> - TX port to be used\n"
|
||||
"\t\t-c <compression> - compression\n"
|
||||
@@ -265,21 +304,37 @@ struct host_opts {
|
||||
int mtu;
|
||||
char *compression;
|
||||
char *fec;
|
||||
int64_t packet_rate;
|
||||
int64_t bitrate;
|
||||
};
|
||||
|
||||
static void parse_fmt(int argc, char **argv, char **bufsize, unsigned short *port,
|
||||
struct host_opts **host_opts, int *host_opts_count, int *control_port)
|
||||
static bool parse_fmt(int argc, char **argv, char **bufsize, unsigned short *port,
|
||||
struct host_opts **host_opts, int *host_opts_count, int *control_port, int *control_connection_type)
|
||||
{
|
||||
int start_index = 1;
|
||||
|
||||
while(argv[start_index][0] == '-') {
|
||||
if(strcmp(argv[start_index], "--control-port") == 0) {
|
||||
*control_port = atoi(argv[++start_index]);
|
||||
char *item = argv[++start_index];
|
||||
*control_port = atoi(item);
|
||||
*control_connection_type = 1;
|
||||
if (strchr(item, ':')) {
|
||||
*control_connection_type = atoi(strchr(item, ':') + 1);
|
||||
}
|
||||
} else if(strcmp(argv[start_index], "--capabilities") == 0) {
|
||||
print_capabilities(CAPABILITY_COMPRESS);
|
||||
return false;
|
||||
} else if(strcmp(argv[start_index], "--help") == 0) {
|
||||
usage(argv[0]);
|
||||
return false;
|
||||
}
|
||||
start_index++;
|
||||
}
|
||||
|
||||
if (argc < start_index + 2) {
|
||||
usage(argv[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
*bufsize = argv[start_index];
|
||||
*port = atoi(argv[start_index + 1]);
|
||||
|
||||
@@ -308,6 +363,12 @@ static void parse_fmt(int argc, char **argv, char **bufsize, unsigned short *por
|
||||
}
|
||||
|
||||
*host_opts = calloc(*host_opts_count, sizeof(struct host_opts));
|
||||
// default values
|
||||
for(int i = 0; i < *host_opts_count; ++i) {
|
||||
(*host_opts)[i].bitrate = RATE_UNLIMITED;
|
||||
(*host_opts)[i].mtu = 1500;
|
||||
}
|
||||
|
||||
int host_idx = 0;
|
||||
for(int i = 1; i < argc; ++i) {
|
||||
if (argv[i][0] == '-') {
|
||||
@@ -326,30 +387,25 @@ static void parse_fmt(int argc, char **argv, char **bufsize, unsigned short *por
|
||||
break;
|
||||
case 'l':
|
||||
if (strcmp(argv[i + 1], "unlimited") == 0) {
|
||||
(*host_opts)[host_idx].packet_rate = 0;
|
||||
(*host_opts)[host_idx].bitrate = RATE_UNLIMITED;
|
||||
} else if (strcmp(argv[i + 1], "auto") == 0) {
|
||||
(*host_opts)[host_idx].bitrate = RATE_AUTO;
|
||||
} else {
|
||||
(*host_opts)[host_idx].packet_rate = unit_evaluate(argv[i + 1]);
|
||||
(*host_opts)[host_idx].bitrate = unit_evaluate(argv[i + 1]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: invalild option '%s'\n", argv[i]);
|
||||
exit(EXIT_FAIL_USAGE);
|
||||
}
|
||||
// make it correct
|
||||
if ((*host_opts)[host_idx].packet_rate != 0) {
|
||||
int mtu = (*host_opts)[host_idx].mtu;
|
||||
if (mtu == 0) {
|
||||
mtu = 1500;
|
||||
}
|
||||
(*host_opts)[host_idx].packet_rate = 1000ull *
|
||||
mtu * 8 / (*host_opts)[host_idx].packet_rate;
|
||||
}
|
||||
i += 1;
|
||||
} else {
|
||||
(*host_opts)[host_idx].addr = argv[i];
|
||||
host_idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void hd_rum_translator_state_init(struct hd_rum_translator_state *s)
|
||||
@@ -392,6 +448,7 @@ int main(int argc, char **argv)
|
||||
struct host_opts *hosts;
|
||||
int host_count;
|
||||
int control_port = CONTROL_DEFAULT_PORT;
|
||||
int control_connection_type = 0;
|
||||
struct control_state *control_state = NULL;
|
||||
#ifdef WIN32
|
||||
WSADATA wsaData;
|
||||
@@ -408,12 +465,15 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (argc < 4) {
|
||||
if (argc == 1) {
|
||||
usage(argv[0]);
|
||||
return EXIT_FAIL_USAGE;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uv_argc = argc;
|
||||
uv_argv = argv;
|
||||
|
||||
hd_rum_translator_state_init(&state);
|
||||
|
||||
main_thread_id = pthread_self();
|
||||
@@ -434,7 +494,12 @@ int main(int argc, char **argv)
|
||||
signal(SIGABRT, signal_handler);
|
||||
#endif
|
||||
|
||||
parse_fmt(argc, argv, &bufsize_str, &port, &hosts, &host_count, &control_port);
|
||||
bool ret = parse_fmt(argc, argv, &bufsize_str, &port, &hosts, &host_count, &control_port,
|
||||
&control_connection_type);
|
||||
|
||||
if (ret == false) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (host_count == 0) {
|
||||
usage(argv[0]);
|
||||
@@ -495,18 +560,27 @@ int main(int argc, char **argv)
|
||||
return 2;
|
||||
}
|
||||
|
||||
if(control_init(control_port, control_connection_type, &control_state, &state.mod) != 0) {
|
||||
fprintf(stderr, "Warning: Unable to create remote control.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
control_start(control_state);
|
||||
|
||||
// we need only one shared receiver decompressor for all recompressing streams
|
||||
state.decompress = hd_rum_decompress_init();
|
||||
state.decompress = hd_rum_decompress_init(&state.mod);
|
||||
if(!state.decompress) {
|
||||
return EXIT_INIT_PORT;
|
||||
}
|
||||
|
||||
state.host_count = host_count;
|
||||
for (i = 0; i < host_count; i++) {
|
||||
int mtu = 1500;
|
||||
if(hosts[i].mtu) {
|
||||
mtu = hosts[i].mtu;
|
||||
int packet_rate;
|
||||
if (hosts[i].bitrate != RATE_AUTO && hosts[i].bitrate != RATE_UNLIMITED) {
|
||||
packet_rate = compute_packet_rate(hosts[i].bitrate, hosts[i].mtu);
|
||||
} else {
|
||||
packet_rate = hosts[i].bitrate;
|
||||
}
|
||||
|
||||
int tx_port = port;
|
||||
if(hosts[i].port) {
|
||||
tx_port = hosts[i].port;
|
||||
@@ -519,6 +593,9 @@ int main(int argc, char **argv)
|
||||
bufsize);
|
||||
module_init_default(&state.replicas[i].mod);
|
||||
state.replicas[i].mod.cls = MODULE_CLASS_PORT;
|
||||
state.replicas[i].mod.msg_callback = change_replica_type_callback;
|
||||
state.replicas[i].mod.priv_data = &state.replicas[i];
|
||||
module_register(&state.replicas[i].mod, &state.mod);
|
||||
|
||||
if(hosts[i].compression == NULL) {
|
||||
state.replicas[i].type = USE_SOCK;
|
||||
@@ -526,14 +603,14 @@ int main(int argc, char **argv)
|
||||
char *fec = NULL;
|
||||
state.replicas[i].recompress = recompress_init(&state.replicas[i].mod,
|
||||
hosts[i].addr, compress,
|
||||
0, tx_port, mtu, fec, hosts[i].packet_rate);
|
||||
hd_rum_decompress_add_inactive_port(state.decompress, state.replicas[i].recompress);
|
||||
0, tx_port, hosts[i].mtu, fec, packet_rate);
|
||||
hd_rum_decompress_add_port(state.decompress, state.replicas[i].recompress, false);
|
||||
} else {
|
||||
state.replicas[i].type = RECOMPRESS;
|
||||
|
||||
state.replicas[i].recompress = recompress_init(&state.replicas[i].mod,
|
||||
hosts[i].addr, hosts[i].compression,
|
||||
0, tx_port, mtu, hosts[i].fec, hosts[i].packet_rate);
|
||||
0, tx_port, hosts[i].mtu, hosts[i].fec, packet_rate);
|
||||
if(state.replicas[i].recompress == 0) {
|
||||
fprintf(stderr, "Initializing output port '%s' failed!\n",
|
||||
hosts[i].addr);
|
||||
@@ -541,16 +618,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
// we don't care about this clients, we only tell decompressor to
|
||||
// take care about them
|
||||
hd_rum_decompress_add_port(state.decompress, state.replicas[i].recompress);
|
||||
}
|
||||
|
||||
module_register(&state.replicas[i].mod, &state.mod);
|
||||
}
|
||||
|
||||
if(control_init(control_port, 0, &control_state, &state.mod) != 0) {
|
||||
fprintf(stderr, "Warning: Unable to create remote control.\n");
|
||||
if(control_port != CONTROL_DEFAULT_PORT) {
|
||||
return EXIT_FAILURE;
|
||||
hd_rum_decompress_add_port(state.decompress, state.replicas[i].recompress, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,7 +692,6 @@ int main(int argc, char **argv)
|
||||
pthread_mutex_unlock(&state.qempty_mtx);
|
||||
|
||||
stats_destroy(stat_received);
|
||||
control_done(control_state);
|
||||
|
||||
pthread_join(thread, NULL);
|
||||
|
||||
@@ -638,6 +705,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
control_done(control_state);
|
||||
|
||||
hd_rum_translator_state_destroy(&state);
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
121
src/host.c
121
src/host.c
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* This file contains common external definitions
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config_unix.h"
|
||||
#include "config_win32.h"
|
||||
#endif
|
||||
|
||||
#include "host.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "video_capture.h"
|
||||
#include "video_display.h"
|
||||
|
||||
#include "utils/resource_manager.h"
|
||||
#include "pdb.h"
|
||||
#include "rtp/rtp.h"
|
||||
#include "rtp/rtp_callback.h"
|
||||
#include "rtp/video_decoders.h"
|
||||
#include "rtp/pbuf.h"
|
||||
|
||||
unsigned int cuda_device = 0;
|
||||
unsigned int audio_capture_channels = 1;
|
||||
|
||||
unsigned int cuda_devices[MAX_CUDA_DEVICES] = { 0 };
|
||||
unsigned int cuda_devices_count = 1;
|
||||
|
||||
int audio_init_state_ok;
|
||||
|
||||
uint32_t RTT = 0; /* this is computed by handle_rr in rtp_callback */
|
||||
|
||||
int uv_argc;
|
||||
char **uv_argv;
|
||||
|
||||
char *export_dir = NULL;
|
||||
volatile bool should_exit_receiver = false;
|
||||
|
||||
bool verbose = false;
|
||||
|
||||
bool ldgm_device_gpu = false;
|
||||
|
||||
const char *window_title = NULL;
|
||||
|
||||
int rxtx_mode; // MODE_SENDER, MODE_RECEIVER or both
|
||||
|
||||
int initialize_video_capture(struct module *parent,
|
||||
struct vidcap_params *params,
|
||||
struct vidcap **state)
|
||||
{
|
||||
struct vidcap_type *vt;
|
||||
vidcap_id_t id = 0;
|
||||
int i;
|
||||
|
||||
if(!strcmp(vidcap_params_get_driver(params), "none"))
|
||||
id = vidcap_get_null_device_id();
|
||||
|
||||
// locking here is because listing of the devices is not really thread safe
|
||||
pthread_mutex_t *vidcap_lock = rm_acquire_shared_lock("VIDCAP_LOCK");
|
||||
pthread_mutex_lock(vidcap_lock);
|
||||
|
||||
vidcap_init_devices();
|
||||
for (i = 0; i < vidcap_get_device_count(); i++) {
|
||||
vt = vidcap_get_device_details(i);
|
||||
if (strcmp(vt->name, vidcap_params_get_driver(params)) == 0) {
|
||||
id = vt->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == vidcap_get_device_count()) {
|
||||
fprintf(stderr, "WARNING: Selected '%s' capture card "
|
||||
"was not found.\n", vidcap_params_get_driver(params));
|
||||
return -1;
|
||||
}
|
||||
vidcap_free_devices();
|
||||
|
||||
pthread_mutex_unlock(vidcap_lock);
|
||||
rm_release_shared_lock("VIDCAP_LOCK");
|
||||
|
||||
return vidcap_init(parent, id, params, state);
|
||||
}
|
||||
|
||||
int initialize_video_display(const char *requested_display,
|
||||
const char *fmt, unsigned int flags,
|
||||
struct display **out)
|
||||
{
|
||||
display_type_t *dt;
|
||||
display_id_t id = 0;
|
||||
int i;
|
||||
|
||||
if(!strcmp(requested_display, "none"))
|
||||
id = display_get_null_device_id();
|
||||
|
||||
if (display_init_devices() != 0) {
|
||||
printf("Unable to initialise devices\n");
|
||||
abort();
|
||||
} else {
|
||||
debug_msg("Found %d display devices\n",
|
||||
display_get_device_count());
|
||||
}
|
||||
for (i = 0; i < display_get_device_count(); i++) {
|
||||
dt = display_get_device_details(i);
|
||||
if (strcmp(requested_display, dt->name) == 0) {
|
||||
id = dt->id;
|
||||
debug_msg("Found device\n");
|
||||
break;
|
||||
} else {
|
||||
debug_msg("Device %s does not match %s\n", dt->name,
|
||||
requested_display);
|
||||
}
|
||||
}
|
||||
if(i == display_get_device_count()) {
|
||||
fprintf(stderr, "WARNING: Selected '%s' display card "
|
||||
"was not found.\n", requested_display);
|
||||
return -1;
|
||||
}
|
||||
display_free_devices();
|
||||
|
||||
return display_init(id, fmt, flags, out);
|
||||
}
|
||||
|
||||
57
src/host.cpp
Normal file
57
src/host.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file contains common external definitions
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config_unix.h"
|
||||
#include "config_win32.h"
|
||||
#endif
|
||||
|
||||
#include "host.h"
|
||||
|
||||
#include "video_capture.h"
|
||||
#include "video_compress.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
unsigned int cuda_device = 0;
|
||||
unsigned int audio_capture_channels = 1;
|
||||
|
||||
unsigned int cuda_devices[MAX_CUDA_DEVICES] = { 0 };
|
||||
unsigned int cuda_devices_count = 1;
|
||||
|
||||
int audio_init_state_ok;
|
||||
|
||||
uint32_t RTT = 0; /* this is computed by handle_rr in rtp_callback */
|
||||
|
||||
int uv_argc;
|
||||
char **uv_argv;
|
||||
|
||||
char *export_dir = NULL;
|
||||
volatile bool should_exit_receiver = false;
|
||||
|
||||
bool verbose = false;
|
||||
|
||||
bool ldgm_device_gpu = false;
|
||||
|
||||
const char *window_title = NULL;
|
||||
|
||||
void print_capabilities(int mask)
|
||||
{
|
||||
if (mask & CAPABILITY_COMPRESS) {
|
||||
cout << "Compressions:" << endl;
|
||||
auto const & compress_capabilities = get_compress_capabilities();
|
||||
for (auto const & it : compress_capabilities) {
|
||||
cout << "(" << it.name << ";" << it.quality << ";" << it.bitrate << ";" <<
|
||||
it.enc_prop.latency << ";" << it.enc_prop.cpu_cores << ";" << it.enc_prop.gpu_gflops << ";" <<
|
||||
it.dec_prop.latency << ";" << it.dec_prop.cpu_cores << ";" << it.dec_prop.gpu_gflops <<
|
||||
")\n";
|
||||
}
|
||||
}
|
||||
if (mask & CAPABILITY_CAPTURE) {
|
||||
cout << "Capturers:" << endl;
|
||||
print_available_capturers();
|
||||
}
|
||||
}
|
||||
|
||||
24
src/host.h
24
src/host.h
@@ -67,8 +67,6 @@ struct vidcap_params;
|
||||
extern int uv_argc;
|
||||
extern char **uv_argv;
|
||||
|
||||
extern long packet_rate; // gives interval between individual packets (in ns)
|
||||
|
||||
extern volatile bool should_exit_receiver;
|
||||
|
||||
/* TODO: remove these variables (should be safe) */
|
||||
@@ -95,29 +93,21 @@ extern bool ldgm_device_gpu;
|
||||
|
||||
extern const char *window_title;
|
||||
|
||||
#define MODE_SENDER 1
|
||||
#define MODE_RECEIVER 2
|
||||
extern int rxtx_mode;
|
||||
|
||||
// for aggregate.c
|
||||
struct vidcap;
|
||||
struct display;
|
||||
struct module;
|
||||
int initialize_video_display(const char *requested_display,
|
||||
const char *fmt, unsigned int flags,
|
||||
struct display **);
|
||||
|
||||
int initialize_video_capture(struct module *parent,
|
||||
struct vidcap_params *params,
|
||||
struct vidcap **);
|
||||
#define MODE_SENDER (1<<0)
|
||||
#define MODE_RECEIVER (1<<1)
|
||||
|
||||
// if not NULL, data should be exported
|
||||
extern char *export_dir;
|
||||
extern char *sage_network_device;
|
||||
|
||||
#define RATE_UNLIMITED 0
|
||||
#define RATE_AUTO -1
|
||||
#define compute_packet_rate(bitrate, mtu) (1000ll * 1000 * 1000 * mtu * 8 / bitrate)
|
||||
|
||||
#define CAPABILITY_COMPRESS (1<<0)
|
||||
#define CAPABILITY_CAPTURE (1<<1)
|
||||
void print_capabilities(int mask);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -82,7 +82,7 @@ void open_all(const char *pattern) {
|
||||
|
||||
for(unsigned int i = 0; i < glob_buf.gl_pathc; ++i) {
|
||||
if(!dlopen(glob_buf.gl_pathv[i], RTLD_NOW|RTLD_GLOBAL))
|
||||
fprintf(stderr, "Library opening warning: %s \n", dlerror());
|
||||
verbose_msg("Library opening warning: %s \n", dlerror());
|
||||
}
|
||||
|
||||
globfree(&glob_buf);
|
||||
@@ -109,7 +109,7 @@ void *open_library(const char *name)
|
||||
if(!handle && stat(path, &buf) == 0) {
|
||||
handle = dlopen(path, RTLD_NOW|RTLD_GLOBAL);
|
||||
if(!handle)
|
||||
fprintf(stderr, "Library opening warning: %s \n", dlerror());
|
||||
verbose_msg("Library opening warning: %s \n", dlerror());
|
||||
}
|
||||
}
|
||||
free(tmp);
|
||||
@@ -119,7 +119,7 @@ void *open_library(const char *name)
|
||||
if(!handle && stat(path, &buf) == 0) {
|
||||
handle = dlopen(path, RTLD_NOW|RTLD_GLOBAL);
|
||||
if(!handle)
|
||||
fprintf(stderr, "Library opening warning: %s \n", dlerror());
|
||||
verbose_msg("Library opening warning: %s \n", dlerror());
|
||||
}
|
||||
|
||||
if(!handle) {
|
||||
|
||||
@@ -61,6 +61,7 @@ extern "C" {
|
||||
|
||||
/** @brief This macro causes that this module will be statically linked with UltraGrid. */
|
||||
#define MK_STATIC(A) A, NULL
|
||||
#define MK_STATIC_REF(A) &A, NULL
|
||||
#define STRINGIFY(A) #A
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
|
||||
@@ -70,6 +71,7 @@ extern "C" {
|
||||
/** This macro tells that the module may be statically linked as well as
|
||||
* a standalone module. */
|
||||
#define MK_NAME(A) NULL, #A
|
||||
#define MK_NAME_REF(A) NULL, #A
|
||||
|
||||
/* defined in video_display.c */
|
||||
void *open_library(const char *name);
|
||||
@@ -80,6 +82,7 @@ void open_all(const char *pattern);
|
||||
#else /* BUILD_LIBRARIES */
|
||||
|
||||
#define MK_NAME(A) A, NULL
|
||||
#define MK_NAME_REF(A) &A, NULL
|
||||
|
||||
#define NULL_IF_BUILD_LIBRARIES(x) x
|
||||
|
||||
|
||||
@@ -7,12 +7,29 @@
|
||||
#ifndef LIBAVCODEC_COMMON_H_
|
||||
#define LIBAVCODEC_COMMON_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/pixfmt.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
///
|
||||
/// compat
|
||||
///
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 55
|
||||
#define av_frame_alloc avcodec_alloc_frame
|
||||
#define av_frame_free avcodec_free_frame
|
||||
#define av_frame_unref avcodec_get_frame_defaults
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 54
|
||||
#define AV_PIX_FMT_NONE PIX_FMT_NONE
|
||||
#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
|
||||
@@ -27,6 +44,8 @@
|
||||
#define AV_CODEC_ID_VP8 CODEC_ID_VP8
|
||||
#define AVPixelFormat PixelFormat
|
||||
#define AVCodecID CodecID
|
||||
#undef av_frame_free
|
||||
#define av_frame_free av_free
|
||||
#endif
|
||||
|
||||
#define LAVCD_LOCK_NAME "lavcd_lock"
|
||||
|
||||
@@ -52,5 +52,5 @@ typedef int mac_opengl_version_t;
|
||||
int get_mac_kernel_version_major();
|
||||
void *mac_gl_init(mac_opengl_version_t);
|
||||
void mac_gl_free(void *);
|
||||
void mac_gl_set_current(void *);
|
||||
void mac_gl_make_current(void *);
|
||||
|
||||
|
||||
120
src/main.cpp
120
src/main.cpp
@@ -91,9 +91,10 @@
|
||||
#include "audio/utils.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#if defined DEBUG && defined HAVE_LINUX
|
||||
#ifdef USE_MTRACE
|
||||
#include <mcheck.h>
|
||||
#endif
|
||||
|
||||
@@ -129,6 +130,7 @@
|
||||
#define OPT_VERBOSE (('V' << 8) | 'E')
|
||||
#define OPT_LDGM_DEVICE (('L' << 8) | 'D')
|
||||
#define OPT_WINDOW_TITLE (('W' << 8) | 'T')
|
||||
#define OPT_CAPABILITIES (('C' << 8) | 'C')
|
||||
|
||||
#define MAX_CAPTURE_COUNT 17
|
||||
|
||||
@@ -153,8 +155,6 @@ static struct state_uv *uv_state;
|
||||
//
|
||||
// prototypes
|
||||
//
|
||||
static void list_video_display_devices(void);
|
||||
static void list_video_capture_devices(void);
|
||||
static void init_root_module(struct module *mod, struct state_uv *uv);
|
||||
|
||||
static void signal_handler(int signal)
|
||||
@@ -202,7 +202,7 @@ static void usage(void)
|
||||
printf("\t--verbose \tprint verbose messages\n");
|
||||
printf("\n");
|
||||
printf("\t--control-port <port>[:0|1] \tset control port (default port: 5054)\n");
|
||||
printf("\t \tconnection types: 0- Server (default), 1- Client\n");
|
||||
printf("\t \tconnection types: 0- Server, 1- Client (default)\n");
|
||||
printf("\n");
|
||||
printf
|
||||
("\t-d <display_device> \tselect display device, use '-d help'\n");
|
||||
@@ -270,7 +270,7 @@ static void usage(void)
|
||||
printf("\n");
|
||||
printf("\t-A <address> \taudio destination address\n");
|
||||
printf("\t \tIf not specified, will use same as for video\n");
|
||||
printf("\t--audio-codec <codec>[:<sample_rate>]|help\taudio codec\n");
|
||||
printf("\t--audio-codec <codec>[:sample_rate=<sr>][:bitrate=<br>]|help\taudio codec\n");
|
||||
printf("\n");
|
||||
printf("\t--capture-filter <filter>\tCapture filter(s), must preceed\n");
|
||||
printf("\n");
|
||||
@@ -285,40 +285,6 @@ static void usage(void)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void list_video_display_devices()
|
||||
{
|
||||
int i;
|
||||
display_type_t *dt;
|
||||
|
||||
printf("Available display devices:\n");
|
||||
display_init_devices();
|
||||
for (i = 0; i < display_get_device_count(); i++) {
|
||||
dt = display_get_device_details(i);
|
||||
printf("\t%s\n", dt->name);
|
||||
}
|
||||
display_free_devices();
|
||||
}
|
||||
|
||||
static void list_video_capture_devices()
|
||||
{
|
||||
int i;
|
||||
struct vidcap_type *vt;
|
||||
|
||||
printf("Available capture devices:\n");
|
||||
vidcap_init_devices();
|
||||
for (i = 0; i < vidcap_get_device_count(); i++) {
|
||||
vt = vidcap_get_device_details(i);
|
||||
printf("\t%s\n", vt->name);
|
||||
}
|
||||
vidcap_free_devices();
|
||||
}
|
||||
|
||||
static void uncompressed_frame_dispose(struct video_frame *frame)
|
||||
{
|
||||
struct wait_obj *wait_obj = (struct wait_obj *) frame->dispose_udata;
|
||||
wait_obj_notify(wait_obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function captures video and possibly compresses it.
|
||||
* It then delegates sending to another thread.
|
||||
@@ -343,16 +309,19 @@ static void *capture_thread(void *arg)
|
||||
}
|
||||
//tx_frame = vf_get_copy(tx_frame);
|
||||
bool wait_for_cur_uncompressed_frame;
|
||||
shared_ptr<video_frame> frame;
|
||||
if (!tx_frame->dispose) {
|
||||
tx_frame->dispose = uncompressed_frame_dispose;
|
||||
tx_frame->dispose_udata = wait_obj;
|
||||
wait_obj_reset(wait_obj);
|
||||
wait_for_cur_uncompressed_frame = true;
|
||||
frame = shared_ptr<video_frame>(tx_frame, [wait_obj](struct video_frame *) {
|
||||
wait_obj_notify(wait_obj);
|
||||
});
|
||||
} else {
|
||||
wait_for_cur_uncompressed_frame = false;
|
||||
frame = shared_ptr<video_frame>(tx_frame, tx_frame->dispose);
|
||||
}
|
||||
|
||||
uv->state_video_rxtx->send(tx_frame);
|
||||
uv->state_video_rxtx->send(move(frame)); // std::move really important here (!)
|
||||
|
||||
// wait for frame frame to be processed, eg. by compress
|
||||
// or sender (uncompressed video). Grab invalidates previous frame
|
||||
@@ -485,7 +454,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
int bitrate = RATE_AUTO;
|
||||
|
||||
#if defined DEBUG && defined HAVE_LINUX
|
||||
int rxtx_mode = 0;
|
||||
|
||||
#ifdef USE_MTRACE
|
||||
mtrace();
|
||||
#endif
|
||||
|
||||
@@ -535,6 +506,7 @@ int main(int argc, char *argv[])
|
||||
{"verbose", no_argument, 0, OPT_VERBOSE},
|
||||
{"ldgm-device", required_argument, 0, OPT_LDGM_DEVICE},
|
||||
{"window-title", required_argument, 0, OPT_WINDOW_TITLE},
|
||||
{"capabilities", no_argument, 0, OPT_CAPABILITIES},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
int option_index = 0;
|
||||
@@ -685,7 +657,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
case 'l':
|
||||
if(strcmp(optarg, "unlimited") == 0) {
|
||||
bitrate = 0;
|
||||
bitrate = RATE_UNLIMITED;
|
||||
} else if(strcmp(optarg, "auto") == 0) {
|
||||
bitrate = RATE_AUTO;
|
||||
} else {
|
||||
@@ -782,22 +754,24 @@ int main(int argc, char *argv[])
|
||||
requested_encryption = optarg;
|
||||
break;
|
||||
case OPT_CONTROL_PORT:
|
||||
if (strchr(optarg, ':')) {
|
||||
char *save_ptr = NULL;
|
||||
char *tok;
|
||||
control_port = atoi(strtok_r(optarg, ":", &save_ptr));
|
||||
connection_type = atoi(strtok_r(NULL, ":", &save_ptr));
|
||||
if(connection_type < 0 || connection_type > 1){
|
||||
usage();
|
||||
return EXIT_FAIL_USAGE;
|
||||
}
|
||||
if ((tok = strtok_r(NULL, ":", &save_ptr))) {
|
||||
usage();
|
||||
return EXIT_FAIL_USAGE;
|
||||
}
|
||||
} else {
|
||||
control_port = atoi(optarg);
|
||||
}
|
||||
if (strchr(optarg, ':')) {
|
||||
char *save_ptr = NULL;
|
||||
char *tok;
|
||||
control_port = atoi(strtok_r(optarg, ":", &save_ptr));
|
||||
connection_type = atoi(strtok_r(NULL, ":", &save_ptr));
|
||||
|
||||
if(connection_type < 0 || connection_type > 1){
|
||||
usage();
|
||||
return EXIT_FAIL_USAGE;
|
||||
}
|
||||
if ((tok = strtok_r(NULL, ":", &save_ptr))) {
|
||||
usage();
|
||||
return EXIT_FAIL_USAGE;
|
||||
}
|
||||
} else {
|
||||
control_port = atoi(optarg);
|
||||
connection_type = 1;
|
||||
}
|
||||
break;
|
||||
case OPT_VERBOSE:
|
||||
verbose = true;
|
||||
@@ -812,6 +786,10 @@ int main(int argc, char *argv[])
|
||||
case OPT_WINDOW_TITLE:
|
||||
window_title = optarg;
|
||||
break;
|
||||
case OPT_CAPABILITIES:
|
||||
print_capabilities(CAPABILITY_CAPTURE | CAPABILITY_COMPRESS);
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
@@ -857,7 +835,7 @@ int main(int argc, char *argv[])
|
||||
video_exporter = video_export_init(export_dir);
|
||||
}
|
||||
|
||||
if (bitrate != RATE_AUTO && bitrate != 0) {
|
||||
if (bitrate != RATE_AUTO && bitrate != RATE_UNLIMITED) {
|
||||
packet_rate = compute_packet_rate(bitrate, requested_mtu);
|
||||
} else {
|
||||
packet_rate = bitrate;
|
||||
@@ -882,11 +860,8 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
if(control_init(control_port, connection_type, &control, &root_mod) != 0) {
|
||||
fprintf(stderr, "%s Unable to initialize remote control!\n",
|
||||
control_port != CONTROL_DEFAULT_PORT ? "Warning:" : "Error:");
|
||||
if(control_port != CONTROL_DEFAULT_PORT) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
fprintf(stderr, "Error: Unable to initialize remote control!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(!audio_host) {
|
||||
@@ -983,6 +958,10 @@ int main(int argc, char *argv[])
|
||||
rxtx_mode |= MODE_SENDER;
|
||||
}
|
||||
|
||||
if (rxtx_mode == 0) {
|
||||
goto after_video_init;
|
||||
}
|
||||
|
||||
try {
|
||||
map<string, param_u> params;
|
||||
|
||||
@@ -990,6 +969,7 @@ int main(int argc, char *argv[])
|
||||
params["parent"].ptr = &root_mod;
|
||||
params["exporter"].ptr = video_exporter;
|
||||
params["compression"].ptr = (void *) requested_compression;
|
||||
params["rxtx_mode"].i = rxtx_mode;
|
||||
|
||||
// iHDTV
|
||||
params["argc"].i = argc;
|
||||
@@ -1034,7 +1014,10 @@ int main(int argc, char *argv[])
|
||||
if(strcmp("none", vidcap_params_get_driver(vidcap_params_head)) != 0 && (strcmp("none",audio_send) != 0)) avType = av; //AVStream
|
||||
else if((strcmp("none",audio_send) != 0)) avType = audio; //AStream
|
||||
else if(strcmp("none", vidcap_params_get_driver(vidcap_params_head))) avType = video; //VStream
|
||||
else printf("[RTSP SERVER CHECK] no stream type... check capture devices input...\n");
|
||||
else {
|
||||
printf("[RTSP SERVER CHECK] no stream type... check capture devices input...\n");
|
||||
avType = none;
|
||||
}
|
||||
|
||||
params["avType"].l = avType;
|
||||
}
|
||||
@@ -1092,6 +1075,7 @@ int main(int argc, char *argv[])
|
||||
exit_status = i;
|
||||
}
|
||||
|
||||
after_video_init:
|
||||
cleanup:
|
||||
if (strcmp("none", requested_display) != 0 &&
|
||||
receiver_thread_started)
|
||||
@@ -1130,7 +1114,7 @@ cleanup:
|
||||
module_done(&root_mod);
|
||||
free(uv);
|
||||
|
||||
#if defined DEBUG && defined HAVE_LINUX
|
||||
#ifdef USE_MTRACE
|
||||
muntrace();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
struct response *send_message(struct module *root, const char *const_path, struct message *msg)
|
||||
{
|
||||
char buf[1024];
|
||||
/**
|
||||
* @invariant
|
||||
* either receiver is NULL or receiver->lock is locked (exactly once)
|
||||
@@ -38,7 +37,7 @@ struct response *send_message(struct module *root, const char *const_path, struc
|
||||
malloc(sizeof(struct pair_msg_path));
|
||||
saved_message->msg = msg;
|
||||
memset(saved_message->path, 0, sizeof(saved_message->path));
|
||||
strncpy(saved_message->path, const_path + (item - tmp), sizeof(saved_message->path));
|
||||
strncpy(saved_message->path, const_path + (item - tmp), sizeof(saved_message->path) - 1);
|
||||
|
||||
simple_linked_list_append(old_receiver->msg_queue_childs, saved_message);
|
||||
pthread_mutex_unlock(&old_receiver->lock);
|
||||
@@ -51,6 +50,8 @@ struct response *send_message(struct module *root, const char *const_path, struc
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
|
||||
lock_guard guard(receiver->lock, lock_guard_retain_ownership_t());
|
||||
|
||||
if(receiver->msg_callback == NULL) {
|
||||
@@ -75,7 +76,8 @@ void module_check_undelivered_messages(struct module *node)
|
||||
struct pair_msg_path *msg = (struct pair_msg_path *) simple_linked_list_it_next(&it);
|
||||
struct module *receiver = get_matching_child(node, msg->path);
|
||||
if (receiver) {
|
||||
send_message_to_receiver(receiver, msg->msg);
|
||||
struct response *resp = send_message_to_receiver(receiver, msg->msg);
|
||||
resp->deleter(resp);
|
||||
simple_linked_list_remove(node->msg_queue_childs, msg);
|
||||
free(msg);
|
||||
// reinit iterator
|
||||
|
||||
@@ -108,9 +108,9 @@ struct response *new_response(int status, char *optional_message);
|
||||
typedef struct response *(*msg_callback_t)(struct module *mod, struct message *msg);
|
||||
|
||||
void module_check_undelivered_messages(struct module *);
|
||||
struct response *send_message(struct module *, const char *path, struct message *msg);
|
||||
struct response *send_message_to_receiver(struct module *, struct message *msg);
|
||||
struct message *new_message(size_t length);
|
||||
struct response *send_message(struct module *, const char *path, struct message *msg) __attribute__ ((warn_unused_result));
|
||||
struct response *send_message_to_receiver(struct module *, struct message *msg) __attribute__ ((warn_unused_result));
|
||||
struct message *new_message(size_t length) __attribute__ ((warn_unused_result));
|
||||
void free_message(struct message *m);
|
||||
const char *response_status_to_text(int status);
|
||||
|
||||
|
||||
16
src/module.c
16
src/module.c
@@ -87,6 +87,9 @@ void module_done(struct module *module_data)
|
||||
if(!module_data)
|
||||
return;
|
||||
|
||||
if (module_data->cls == MODULE_CLASS_NONE)
|
||||
return;
|
||||
|
||||
assert(module_data->magic == MODULE_MAGIC);
|
||||
|
||||
if(module_data->parent) {
|
||||
@@ -140,10 +143,10 @@ const char *module_class_name_pairs[] = {
|
||||
|
||||
const char *module_class_name(enum module_class cls)
|
||||
{
|
||||
if((unsigned int) cls > sizeof(module_class_name_pairs)/sizeof(const char *))
|
||||
return NULL;
|
||||
else
|
||||
if((unsigned int) cls < sizeof(module_class_name_pairs)/sizeof(const char *))
|
||||
return module_class_name_pairs[cls];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void append_message_path(char *buf, int buflen, enum module_class modules[])
|
||||
@@ -201,12 +204,12 @@ static void get_receiver_index(char *node_str, int *index) {
|
||||
|
||||
struct module *get_module(struct module *root, const char *const_path)
|
||||
{
|
||||
assert(root != NULL);
|
||||
|
||||
struct module *receiver = root;
|
||||
char *path, *tmp;
|
||||
char *item, *save_ptr;
|
||||
|
||||
assert(root != NULL);
|
||||
|
||||
pthread_mutex_lock(&root->lock);
|
||||
|
||||
tmp = path = strdup(const_path);
|
||||
@@ -217,6 +220,7 @@ struct module *get_module(struct module *root, const char *const_path)
|
||||
|
||||
if (!receiver) {
|
||||
pthread_mutex_unlock(&old_receiver->lock);
|
||||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
pthread_mutex_lock(&receiver->lock);
|
||||
@@ -236,7 +240,7 @@ struct module *get_matching_child(struct module *node, const char *const_path)
|
||||
{
|
||||
struct module *receiver = node;
|
||||
char *path, *tmp;
|
||||
char *item, *save_ptr;
|
||||
char *item, *save_ptr = NULL;
|
||||
|
||||
assert(node != NULL);
|
||||
|
||||
|
||||
@@ -113,7 +113,6 @@ struct state_audio_decoder {
|
||||
struct scale_data *scale; ///< contains scaling metadata if we want to perform audio scaling
|
||||
bool fixed_scale;
|
||||
|
||||
audio_frame2 *received_frame; ///< auxiliary buffer that holds undecoded audio frame data from network
|
||||
struct audio_codec_state *audio_decompress;
|
||||
struct resampler *resampler;
|
||||
|
||||
@@ -181,6 +180,7 @@ void *audio_decoder_init(char *audio_channel_map, const char *audio_scale, const
|
||||
struct state_audio_decoder *s;
|
||||
bool scale_auto = false;
|
||||
double scale_factor = 1.0;
|
||||
char *tmp = nullptr;
|
||||
|
||||
assert(audio_scale != NULL);
|
||||
|
||||
@@ -190,11 +190,10 @@ void *audio_decoder_init(char *audio_channel_map, const char *audio_scale, const
|
||||
gettimeofday(&s->t0, NULL);
|
||||
s->packet_counter = NULL;
|
||||
|
||||
s->received_frame = audio_frame2_init();
|
||||
s->audio_decompress = NULL;
|
||||
|
||||
s->resampler = resampler_init(48000);
|
||||
s->decoded = audio_frame2_init();
|
||||
s->decoded = new audio_frame2;
|
||||
|
||||
if(encryption) {
|
||||
#ifdef HAVE_CRYPTO
|
||||
@@ -213,7 +212,6 @@ void *audio_decoder_init(char *audio_channel_map, const char *audio_scale, const
|
||||
if(audio_channel_map) {
|
||||
char *save_ptr = NULL;
|
||||
char *item;
|
||||
char *tmp;
|
||||
char *ptr;
|
||||
tmp = ptr = strdup(audio_channel_map);
|
||||
|
||||
@@ -251,7 +249,7 @@ void *audio_decoder_init(char *audio_channel_map, const char *audio_scale, const
|
||||
}
|
||||
if(!isdigit(strchr(item, ':')[1])) {
|
||||
fprintf(stderr, "Audio destination channel not entered!\n");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
int dst = atoi(strchr(item, ':') + 1);
|
||||
if(src >= 0) {
|
||||
@@ -268,14 +266,14 @@ void *audio_decoder_init(char *audio_channel_map, const char *audio_scale, const
|
||||
|
||||
|
||||
if(!validate_mapping(&s->channel_map)) {
|
||||
free(s);
|
||||
fprintf(stderr, "Wrong audio mapping.\n");
|
||||
return NULL;
|
||||
goto error;
|
||||
} else {
|
||||
s->channel_remapping = TRUE;
|
||||
}
|
||||
|
||||
free (tmp);
|
||||
tmp = NULL;
|
||||
} else {
|
||||
s->channel_remapping = FALSE;
|
||||
s->channel_map.map = NULL;
|
||||
@@ -299,8 +297,7 @@ void *audio_decoder_init(char *audio_channel_map, const char *audio_scale, const
|
||||
scale_factor = atof(audio_scale);
|
||||
if(scale_factor <= 0.0) {
|
||||
fprintf(stderr, "Invalid audio scaling factor!\n");
|
||||
free(s);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,6 +313,14 @@ void *audio_decoder_init(char *audio_channel_map, const char *audio_scale, const
|
||||
}
|
||||
|
||||
return s;
|
||||
|
||||
error:
|
||||
free(tmp);
|
||||
if (s) {
|
||||
audio_decoder_destroy(s);
|
||||
free(s);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void audio_decoder_destroy(void *state)
|
||||
@@ -329,10 +334,9 @@ void audio_decoder_destroy(void *state)
|
||||
free(s->channel_map.map);
|
||||
free(s->channel_map.sizes);
|
||||
packet_counter_destroy(s->packet_counter);
|
||||
audio_frame2_free(s->received_frame);
|
||||
audio_codec_done(s->audio_decompress);
|
||||
resampler_done(s->resampler);
|
||||
audio_frame2_free(s->decoded);
|
||||
delete s->decoded;
|
||||
|
||||
openssl_decrypt_destroy(s->decrypt);
|
||||
|
||||
@@ -359,7 +363,6 @@ int decode_audio_frame(struct coded_data *cdata, void *data)
|
||||
int input_channels = 0;
|
||||
int output_channels = 0;
|
||||
int bps, sample_rate, channel;
|
||||
static int prints = 0;
|
||||
|
||||
if(!cdata) {
|
||||
return FALSE;
|
||||
@@ -371,6 +374,12 @@ int decode_audio_frame(struct coded_data *cdata, void *data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
audio_frame2 received_frame;
|
||||
received_frame.init(decoder->saved_desc.ch_count,
|
||||
get_audio_codec_to_tag(decoder->saved_audio_tag),
|
||||
decoder->saved_desc.bps,
|
||||
decoder->saved_desc.sample_rate);
|
||||
|
||||
while (cdata != NULL) {
|
||||
char *data;
|
||||
// for definition see rtp_callbacks.h
|
||||
@@ -455,7 +464,6 @@ int decode_audio_frame(struct coded_data *cdata, void *data)
|
||||
sample_rate, input_channels, input_channels == 1 ? "": "s", bps * 8,
|
||||
get_name_to_audio_codec(get_audio_codec_to_tag(audio_tag)));
|
||||
|
||||
audio_frame2_reset(decoder->decoded);
|
||||
|
||||
s->buffer.bps = device_bps;
|
||||
s->buffer.ch_count = output_channels;
|
||||
@@ -477,12 +485,11 @@ int decode_audio_frame(struct coded_data *cdata, void *data)
|
||||
decoder->saved_audio_tag = audio_tag;
|
||||
packet_counter_destroy(decoder->packet_counter);
|
||||
decoder->packet_counter = packet_counter_init(input_channels);
|
||||
|
||||
audio_frame2_allocate(decoder->received_frame, input_channels, sample_rate * bps/* 1 sec */);
|
||||
decoder->received_frame->bps = bps;
|
||||
decoder->received_frame->sample_rate = sample_rate;
|
||||
audio_codec_t audio_codec = get_audio_codec_to_tag(audio_tag);
|
||||
decoder->received_frame->codec = audio_codec;
|
||||
|
||||
received_frame.init(input_channels, audio_codec, bps, sample_rate);
|
||||
decoder->decoded->init(input_channels, AC_PCM, bps, device_sample_rate);
|
||||
|
||||
decoder->audio_decompress = audio_codec_reconfigure(decoder->audio_decompress, audio_codec, AUDIO_DECODER);
|
||||
if(!decoder->audio_decompress) {
|
||||
fprintf(stderr, "Unable to create audio decompress!\n");
|
||||
@@ -496,36 +503,26 @@ int decode_audio_frame(struct coded_data *cdata, void *data)
|
||||
//fprintf(stderr, "%d-%d-%d ", length, bufnum, channel);
|
||||
|
||||
|
||||
if(offset + length <= decoder->received_frame->max_size) {
|
||||
memcpy(decoder->received_frame->data[channel] + offset, data, length);
|
||||
} else { /* discarding data - buffer to small */
|
||||
if(++prints % 100 == 0)
|
||||
fprintf(stdout, "Warning: "
|
||||
"discarding audio data "
|
||||
"- buffer too small\n");
|
||||
}
|
||||
received_frame.replace(channel, offset, data, length);
|
||||
|
||||
packet_counter_register_packet(decoder->packet_counter, channel, bufnum, offset, length);
|
||||
|
||||
/* buffer size same for every packet of the frame */
|
||||
if(buffer_len <= decoder->received_frame->max_size) {
|
||||
decoder->received_frame->data_len[channel] = buffer_len;
|
||||
} else { /* overflow */
|
||||
decoder->received_frame->data_len[channel] =
|
||||
decoder->received_frame->max_size;
|
||||
}
|
||||
/// @todo do we really want to scale to expected buffer length even if some frames are missing
|
||||
/// at the end of the buffer
|
||||
received_frame.resize(channel, buffer_len);
|
||||
|
||||
cdata = cdata->nxt;
|
||||
}
|
||||
|
||||
audio_frame2 *decompressed = audio_codec_decompress(decoder->audio_decompress, decoder->received_frame);
|
||||
audio_frame2 *decompressed = audio_codec_decompress(decoder->audio_decompress, &received_frame);
|
||||
if(!decompressed) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
audio_frame2 *resampled = resampler_resample(decoder->resampler, decompressed);
|
||||
const audio_frame2 *resampled = resampler_resample(decoder->resampler, decompressed);
|
||||
|
||||
size_t new_data_len = s->buffer.data_len + resampled->data_len[0] * output_channels;
|
||||
size_t new_data_len = s->buffer.data_len + resampled->get_data_len(0) * output_channels;
|
||||
if(s->buffer.max_size < new_data_len) {
|
||||
s->buffer.max_size = new_data_len;
|
||||
s->buffer.data = (char *) realloc(s->buffer.data, new_data_len);
|
||||
@@ -534,28 +531,28 @@ int decode_audio_frame(struct coded_data *cdata, void *data)
|
||||
memset(s->buffer.data + s->buffer.data_len, 0, new_data_len - s->buffer.data_len);
|
||||
|
||||
// there is a mapping for channel
|
||||
for(int channel = 0; channel < resampled->ch_count; ++channel) {
|
||||
for(int channel = 0; channel < resampled->get_channel_count(); ++channel) {
|
||||
if(decoder->channel_remapping) {
|
||||
if(channel < decoder->channel_map.size) {
|
||||
for(int i = 0; i < decoder->channel_map.sizes[channel]; ++i) {
|
||||
mux_and_mix_channel(s->buffer.data + s->buffer.data_len,
|
||||
resampled->data[channel],
|
||||
resampled->bps, resampled->data_len[channel],
|
||||
resampled->get_data(channel),
|
||||
resampled->get_bps(), resampled->get_data_len(channel),
|
||||
output_channels, decoder->channel_map.map[channel][i],
|
||||
decoder->scale[decoder->fixed_scale ? 0 :
|
||||
decoder->channel_map.map[channel][i]].scale);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mux_and_mix_channel(s->buffer.data + s->buffer.data_len, resampled->data[channel],
|
||||
resampled->bps,
|
||||
resampled->data_len[channel], output_channels, channel,
|
||||
mux_and_mix_channel(s->buffer.data + s->buffer.data_len, resampled->get_data(channel),
|
||||
resampled->get_bps(),
|
||||
resampled->get_data_len(channel), output_channels, channel,
|
||||
decoder->scale[decoder->fixed_scale ? 0 : input_channels].scale);
|
||||
}
|
||||
}
|
||||
s->buffer.data_len = new_data_len;
|
||||
|
||||
audio_frame2_append(decoder->decoded, resampled);
|
||||
decoder->decoded->append(*resampled);
|
||||
|
||||
double seconds;
|
||||
struct timeval t;
|
||||
@@ -568,9 +565,9 @@ int decode_audio_frame(struct coded_data *cdata, void *data)
|
||||
"decoded %d samples in last %f seconds.\n",
|
||||
bytes_received,
|
||||
packet_counter_get_all_bytes(decoder->packet_counter),
|
||||
audio_frame2_get_sample_count(decoder->decoded),
|
||||
decoder->decoded->get_sample_count(),
|
||||
seconds);
|
||||
for (int i = 0; i < decoder->decoded->ch_count; ++i) {
|
||||
for (int i = 0; i < decoder->decoded->get_channel_count(); ++i) {
|
||||
double rms, peak;
|
||||
rms = calculate_rms(decoder->decoded, i, &peak);
|
||||
printf("[Audio decoder] Channel %d - volume: %f dBFS RMS, %f dBFS peak.\n",
|
||||
@@ -578,7 +575,7 @@ int decode_audio_frame(struct coded_data *cdata, void *data)
|
||||
}
|
||||
decoder->t0 = t;
|
||||
packet_counter_clear(decoder->packet_counter);
|
||||
audio_frame2_reset(decoder->decoded);
|
||||
decoder->decoded->reset();
|
||||
}
|
||||
|
||||
if(!decoder->fixed_scale) {
|
||||
@@ -606,43 +603,18 @@ int decode_audio_frame_mulaw(struct coded_data *cdata, void *data)
|
||||
|
||||
if(!cdata) return false;
|
||||
|
||||
// Reconfiguration.
|
||||
if (audio->received_frame->bps != audio->saved_desc.bps ||
|
||||
audio->received_frame->sample_rate != audio->saved_desc.sample_rate ||
|
||||
audio->received_frame->ch_count != audio->saved_desc.ch_count ||
|
||||
audio->received_frame->codec != audio->saved_desc.codec)
|
||||
{
|
||||
audio_frame2_allocate(audio->received_frame, audio->saved_desc.ch_count, audio->saved_desc.sample_rate * audio->saved_desc.bps);
|
||||
audio->received_frame->bps = audio->saved_desc.bps;
|
||||
audio->received_frame->sample_rate = audio->saved_desc.sample_rate;
|
||||
audio->received_frame->ch_count = audio->saved_desc.ch_count;
|
||||
audio->received_frame->codec = audio->saved_desc.codec;
|
||||
}
|
||||
|
||||
// Initial setup
|
||||
for (int ch = 0 ; ch < audio->received_frame->ch_count ; ch ++) {
|
||||
audio->received_frame->data_len[ch] = 0;
|
||||
}
|
||||
audio_frame2 received_frame;
|
||||
received_frame.init(audio->saved_desc.ch_count, audio->saved_desc.codec,
|
||||
audio->saved_desc.bps, audio->saved_desc.sample_rate);
|
||||
|
||||
// Check-if-there-is-only-one-channel optimization.
|
||||
if (audio->received_frame->ch_count == 1) {
|
||||
char *to = audio->received_frame->data[0];
|
||||
|
||||
if (received_frame.get_channel_count() == 1) {
|
||||
//char *to = audio->received_frame->data[0];
|
||||
while (cdata != NULL) {
|
||||
// Get the data to copy into the received_frame.
|
||||
char *from = cdata->data->data;
|
||||
|
||||
// See if the data fits.
|
||||
if (cdata->data->data_len <= (int)(audio->received_frame->max_size - audio->received_frame->data_len[0])) {
|
||||
// Copy the data
|
||||
memcpy(to, from, cdata->data->data_len);
|
||||
// Update the pointer and the counter.
|
||||
to += cdata->data->data_len;
|
||||
audio->received_frame->data_len[0] += cdata->data->data_len;
|
||||
} else {
|
||||
// Filled it out, exit now.
|
||||
return true;
|
||||
}
|
||||
received_frame.append(0, from, cdata->data->data_len);
|
||||
|
||||
cdata = cdata->nxt;
|
||||
}
|
||||
@@ -654,40 +626,25 @@ int decode_audio_frame_mulaw(struct coded_data *cdata, void *data)
|
||||
* Take a look at http://stackoverflow.com/questions/1777901/array-interleaving-problem
|
||||
*/
|
||||
|
||||
char *to;
|
||||
int bytes_copied = 0;
|
||||
|
||||
while (cdata != NULL) {
|
||||
// Check that the amount of data on cdata->data->data is congruent with 0 modulus audio->received_frame->ch_count.
|
||||
if (cdata->data->data_len % audio->received_frame->ch_count != 0) {
|
||||
if (cdata->data->data_len % received_frame.get_channel_count() != 0) {
|
||||
// printf something?
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is space on the current audio_frame2 buffer.
|
||||
if ((cdata->data->data_len / audio->received_frame->ch_count) <= (int)(audio->received_frame->max_size - bytes_copied)) {
|
||||
char *from = cdata->data->data;
|
||||
|
||||
// For each group of samples.
|
||||
for (int g = 0 ; g < (cdata->data->data_len / audio->received_frame->ch_count) ; g++) {
|
||||
for (int g = 0 ; g < (cdata->data->data_len / received_frame.get_channel_count()) ; g++) {
|
||||
// Iterate throught each channel.
|
||||
for (int ch = 0 ; ch < audio->received_frame->ch_count ; ch ++) {
|
||||
// Copy the current sample from the RTP packet to the audio_frame2.
|
||||
to = audio->received_frame->data[ch];
|
||||
to += bytes_copied;
|
||||
for (int ch = 0 ; ch < received_frame.get_channel_count(); ch ++) {
|
||||
|
||||
memcpy(to, from, audio->received_frame->bps);
|
||||
received_frame.append(ch, from, cdata->data->data_len);
|
||||
|
||||
from += audio->received_frame->bps;
|
||||
audio->received_frame->data_len[ch] += audio->received_frame->bps;
|
||||
from += received_frame.get_bps();
|
||||
}
|
||||
|
||||
bytes_copied += audio->received_frame->bps;
|
||||
}
|
||||
} else {
|
||||
// Filled audio_frame2 out, exit now.
|
||||
return true;
|
||||
}
|
||||
|
||||
cdata = cdata->nxt;
|
||||
}
|
||||
@@ -51,8 +51,8 @@ using namespace std;
|
||||
|
||||
fec *fec::create_from_config(const char *c_str)
|
||||
{
|
||||
char *str = strdup(c_str);
|
||||
if (strncmp(str, "LDGM percents ", strlen("LDGM percents ")) == 0) {
|
||||
if (strncmp(c_str, "LDGM percents ", strlen("LDGM percents ")) == 0) {
|
||||
char *str = strdup(c_str);
|
||||
int mtu_len, data_len;
|
||||
double loss_pct;
|
||||
char *ptr = str + strlen("LDGM percents ");
|
||||
@@ -60,16 +60,20 @@ fec *fec::create_from_config(const char *c_str)
|
||||
item = strtok_r(ptr, " ", &save_ptr);
|
||||
assert (item != NULL);
|
||||
mtu_len = atoi(item);
|
||||
assert(mtu_len > 0);
|
||||
item = strtok_r(NULL, " ", &save_ptr);
|
||||
assert (item != NULL);
|
||||
data_len = atoi(item);
|
||||
assert(data_len > 0);
|
||||
item = strtok_r(NULL, " ", &save_ptr);
|
||||
assert (item != NULL);
|
||||
loss_pct = atof(item);
|
||||
return new ldgm(mtu_len, data_len,
|
||||
loss_pct);
|
||||
} else if (strncmp(str, "LDGM cfg ", strlen("LDGM cfg ")) == 0) {
|
||||
return new ldgm(str + strlen("LDGM cfg "));
|
||||
assert(loss_pct > 0.0);
|
||||
fec *ret = new ldgm(mtu_len, data_len, loss_pct);
|
||||
free(str);
|
||||
return ret;
|
||||
} else if (strncmp(c_str, "LDGM cfg ", strlen("LDGM cfg ")) == 0) {
|
||||
return new ldgm(c_str + strlen("LDGM cfg "));
|
||||
} else {
|
||||
throw string("Unrecognized FEC configuration!");
|
||||
}
|
||||
|
||||
@@ -42,11 +42,12 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
struct video_frame;
|
||||
|
||||
struct fec {
|
||||
virtual struct video_frame *encode(struct video_frame *) = 0;
|
||||
virtual std::shared_ptr<video_frame> encode(std::shared_ptr<video_frame>) = 0;
|
||||
virtual void decode(const char *in, int in_len, char **out, int *len,
|
||||
const std::map<int, int> &) = 0;
|
||||
virtual ~fec() {}
|
||||
|
||||
@@ -142,7 +142,8 @@ const configuration_t suggested_configurations[] = {
|
||||
{ STD1500, UNCOMPRESSED_SIZE, PCT10, 1500, 1500, 8 },
|
||||
};
|
||||
|
||||
#define MINIMAL_VALUE 64 // reasonable minimum (seems that 32 crashes sometimes)
|
||||
#define MINIMAL_VALUE 64 ///< reasonable minimum (seems that 32 crashes sometimes)
|
||||
///< @todo Check why doesn't lower values work out
|
||||
#define DEFAULT_K 256
|
||||
#define DEFAULT_M 192
|
||||
#define DEFAULT_C 5
|
||||
@@ -172,11 +173,13 @@ void ldgm::init(unsigned int k, unsigned int m, unsigned int c, unsigned int see
|
||||
m_seed = seed;
|
||||
|
||||
if (ldgm_device_gpu) {
|
||||
throw string("GPU is not yet supported");
|
||||
// TODO: uncomment this
|
||||
//m_coding_session = new LDGM_session_gpu();
|
||||
#ifdef HAVE_LDGM_GPU
|
||||
m_coding_session = unique_ptr<LDGM_session>(new LDGM_session_gpu());
|
||||
#else
|
||||
throw string("GPU accelerated LDGM support is not compiled in");
|
||||
#endif
|
||||
} else {
|
||||
m_coding_session = new LDGM_session_cpu();
|
||||
m_coding_session = unique_ptr<LDGM_session>(new LDGM_session_cpu());
|
||||
}
|
||||
|
||||
m_coding_session->set_params(k, m, c);
|
||||
@@ -208,7 +211,7 @@ void ldgm::init(unsigned int k, unsigned int m, unsigned int c, unsigned int see
|
||||
}
|
||||
snprintf(filename, 512, "%s/ldgm_matrix-%u-%u-%u-%u.bin", path, k, m, c, seed);
|
||||
if(!file_exists(filename)) {
|
||||
int ret = generate_ldgm_matrix(filename, k, m, c, seed);
|
||||
int ret = generate_ldgm_matrix(filename, k, m, c, seed, 0);
|
||||
if(ret != 0) {
|
||||
fprintf(stderr, "[LDGM] Unable to initialize LDGM matrix.\n");
|
||||
throw 1;
|
||||
@@ -218,10 +221,6 @@ void ldgm::init(unsigned int k, unsigned int m, unsigned int c, unsigned int see
|
||||
m_coding_session->set_pcMatrix(filename);
|
||||
}
|
||||
|
||||
ldgm::~ldgm() {
|
||||
delete m_coding_session;
|
||||
}
|
||||
|
||||
ldgm::ldgm(unsigned int k, unsigned int m, unsigned int c, unsigned int seed)
|
||||
{
|
||||
init(k, m, c, seed);
|
||||
@@ -383,21 +382,19 @@ ldgm::ldgm(int packet_size, int frame_size, double max_expected_loss)
|
||||
init(k, m, c);
|
||||
}
|
||||
|
||||
static void ldgm_encoder_dispose_buffer(struct video_frame *frame)
|
||||
shared_ptr<video_frame> ldgm::encode(shared_ptr<video_frame> tx_frame)
|
||||
{
|
||||
for (unsigned int i = 0; i < frame->tile_count; ++i) {
|
||||
static_cast<ldgm *>(frame->dispose_udata)->freeBuffer(frame->tiles[i].data);
|
||||
}
|
||||
vf_free(frame);
|
||||
}
|
||||
|
||||
struct video_frame *ldgm::encode(struct video_frame *tx_frame)
|
||||
{
|
||||
struct video_frame *out = vf_alloc_desc(video_desc_from_frame(tx_frame));
|
||||
shared_ptr<video_frame> out(vf_alloc_desc(video_desc_from_frame(tx_frame.get())),
|
||||
[this](struct video_frame *frame) {
|
||||
for (unsigned int i = 0; i < frame->tile_count; ++i) {
|
||||
freeBuffer(frame->tiles[i].data);
|
||||
}
|
||||
vf_free(frame);
|
||||
});
|
||||
|
||||
for (unsigned int i = 0; i < tx_frame->tile_count; ++i) {
|
||||
video_payload_hdr_t video_hdr;
|
||||
format_video_header(tx_frame, i, 0, video_hdr);
|
||||
format_video_header(tx_frame.get(), i, 0, video_hdr);
|
||||
|
||||
int out_size;
|
||||
char *output = m_coding_session->encode_hdr_frame((char *) video_hdr, sizeof(video_hdr),
|
||||
@@ -413,8 +410,6 @@ struct video_frame *ldgm::encode(struct video_frame *tx_frame)
|
||||
out->fec_params.c = m_c;
|
||||
out->fec_params.seed = m_seed;
|
||||
out->fec_params.symbol_size = m_coding_session->get_packet_size();
|
||||
out->dispose = ldgm_encoder_dispose_buffer;
|
||||
out->dispose_udata = this;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#define LDGM_MAXIMAL_SIZE_RATIO 1
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "fec.h"
|
||||
|
||||
@@ -52,8 +53,7 @@ struct ldgm : public fec{
|
||||
ldgm(unsigned int k, unsigned int m, unsigned int c, unsigned int seed);
|
||||
ldgm(int packet_size, int frame_size, double max_expected_loss);
|
||||
ldgm(const char *cfg);
|
||||
virtual ~ldgm();
|
||||
struct video_frame *encode(struct video_frame *);
|
||||
std::shared_ptr<video_frame> encode(std::shared_ptr<video_frame>);
|
||||
void decode(const char *in, int in_len, char **out, int *len,
|
||||
const std::map<int, int> &);
|
||||
void freeBuffer(char *buffer);
|
||||
@@ -61,7 +61,7 @@ struct ldgm : public fec{
|
||||
private:
|
||||
void init(unsigned int k, unsigned int m, unsigned int c, unsigned int seed = DEFAULT_LDGM_SEED);
|
||||
|
||||
LDGM_session *m_coding_session;
|
||||
std::unique_ptr<LDGM_session> m_coding_session;
|
||||
unsigned int m_k, m_m, m_c;
|
||||
unsigned int m_seed;
|
||||
};
|
||||
|
||||
@@ -311,18 +311,17 @@ static socket_udp *udp_init4(const char *addr, const char *iface,
|
||||
s->rx_port = rx_port;
|
||||
s->tx_port = tx_port;
|
||||
s->ttl = ttl;
|
||||
s->fd = INVALID_SOCKET;
|
||||
|
||||
if (!resolve_address(s, addr)) {
|
||||
socket_error("Can't resolve IP address for %s", addr);
|
||||
free(s);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
if (iface != NULL) {
|
||||
#ifdef HAVE_IF_NAMETOINDEX
|
||||
if ((ifindex = if_nametoindex(iface)) == 0) {
|
||||
debug_msg("Illegal interface specification\n");
|
||||
free(s);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
#else
|
||||
fprintf(stderr, "Cannot set interface name, if_nametoindex not supported.\n");
|
||||
@@ -331,13 +330,9 @@ static socket_udp *udp_init4(const char *addr, const char *iface,
|
||||
ifindex = 0;
|
||||
}
|
||||
s->fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
#ifdef WIN32
|
||||
if (s->fd == INVALID_SOCKET) {
|
||||
#else
|
||||
if (s->fd < 0) {
|
||||
#endif
|
||||
socket_error("Unable to initialize socket");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
if (SETSOCKOPT
|
||||
(s->fd, SOL_SOCKET, SO_SNDBUF, (char *)&udpbufsize,
|
||||
@@ -357,22 +352,34 @@ static socket_udp *udp_init4(const char *addr, const char *iface,
|
||||
(s->fd, SOL_SOCKET, SO_REUSEPORT, (int *)&reuse,
|
||||
sizeof(reuse)) != 0) {
|
||||
socket_error("setsockopt SO_REUSEPORT");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
if (SETSOCKOPT
|
||||
(s->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse,
|
||||
sizeof(reuse)) != 0) {
|
||||
socket_error("setsockopt SO_REUSEADDR");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
s_in.sin_family = AF_INET;
|
||||
s_in.sin_addr.s_addr = INADDR_ANY;
|
||||
s_in.sin_port = htons(rx_port);
|
||||
if (bind(s->fd, (struct sockaddr *)&s_in, sizeof(s_in)) != 0) {
|
||||
socket_error("bind");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// if we do not set tx port, fake that is the same as we are bound to
|
||||
if (s->tx_port == 0) {
|
||||
struct sockaddr_in sin;
|
||||
socklen_t addrlen = sizeof(sin);
|
||||
if (getsockname(s->fd, (struct sockaddr *)&sin, &addrlen) == 0 &&
|
||||
sin.sin_family == AF_INET &&
|
||||
addrlen == sizeof(sin)) {
|
||||
s->tx_port = ntohs(sin.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
if (IN_MULTICAST(ntohl(s->addr4.s_addr))) {
|
||||
#ifndef WIN32
|
||||
char loop = 1;
|
||||
@@ -386,31 +393,37 @@ static socket_udp *udp_init4(const char *addr, const char *iface,
|
||||
(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&imr,
|
||||
sizeof(struct ip_mreq)) != 0) {
|
||||
socket_error("setsockopt IP_ADD_MEMBERSHIP");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
#ifndef WIN32
|
||||
if (SETSOCKOPT
|
||||
(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
|
||||
sizeof(loop)) != 0) {
|
||||
socket_error("setsockopt IP_MULTICAST_LOOP");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
if (SETSOCKOPT
|
||||
(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&s->ttl,
|
||||
sizeof(s->ttl)) != 0) {
|
||||
socket_error("setsockopt IP_MULTICAST_TTL");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
if (SETSOCKOPT
|
||||
(s->fd, IPPROTO_IP, IP_MULTICAST_IF,
|
||||
(char *)&ifindex, sizeof(ifindex)) != 0) {
|
||||
socket_error("setsockopt IP_MULTICAST_IF");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
s->addr = strdup(addr);
|
||||
return s;
|
||||
error:
|
||||
if (s->fd != INVALID_SOCKET) {
|
||||
close(s->fd);
|
||||
}
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void udp_exit4(socket_udp * s)
|
||||
@@ -493,7 +506,7 @@ static inline int udp_sendv4(socket_udp * s, struct iovec *vector, int count)
|
||||
|
||||
static const char *udp_host_addr4(void)
|
||||
{
|
||||
static char hname[MAXHOSTNAMELEN];
|
||||
static char hname[MAXHOSTNAMELEN + 1];
|
||||
struct hostent *hent;
|
||||
struct in_addr iaddr;
|
||||
|
||||
@@ -628,7 +641,7 @@ static socket_udp *udp_init6(const char *addr, const char *iface,
|
||||
s->rx_port = rx_port;
|
||||
s->tx_port = tx_port;
|
||||
s->ttl = ttl;
|
||||
unsigned int ifindex;
|
||||
unsigned int ifindex = 0;
|
||||
|
||||
if (iface != NULL) {
|
||||
#ifdef HAVE_IF_NAMETOINDEX
|
||||
@@ -686,6 +699,17 @@ static socket_udp *udp_init6(const char *addr, const char *iface,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if we do not set tx port, fake that is the same as we are bound to
|
||||
if (s->tx_port == 0) {
|
||||
struct sockaddr_in6 sin;
|
||||
socklen_t addrlen = sizeof(sin);
|
||||
if (getsockname(s->fd, (struct sockaddr *)&sin, &addrlen) == 0 &&
|
||||
sin.sin6_family == AF_INET6 &&
|
||||
addrlen == sizeof(sin)) {
|
||||
s->tx_port = ntohs(sin.sin6_port);
|
||||
}
|
||||
}
|
||||
|
||||
if (IN6_IS_ADDR_MULTICAST(&(s->addr6))) {
|
||||
unsigned int loop = 1;
|
||||
struct ipv6_mreq imr;
|
||||
@@ -831,15 +855,25 @@ static const char *udp_host_addr6(socket_udp * s)
|
||||
int result = 0;
|
||||
|
||||
newsock = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
if (newsock == -1) {
|
||||
perror("socket");
|
||||
return NULL;
|
||||
}
|
||||
memset((char *)&addr6, 0, len);
|
||||
addr6.sin6_family = AF_INET6;
|
||||
#ifdef HAVE_SIN6_LEN
|
||||
addr6.sin6_len = len;
|
||||
#endif
|
||||
bind(newsock, (struct sockaddr *)&addr6, len);
|
||||
result = bind(newsock, (struct sockaddr *)&addr6, len);
|
||||
if (result != 0) {
|
||||
perror("Cannot bind");
|
||||
}
|
||||
addr6.sin6_addr = s->addr6;
|
||||
addr6.sin6_port = htons(s->rx_port);
|
||||
connect(newsock, (struct sockaddr *)&addr6, len);
|
||||
result = connect(newsock, (struct sockaddr *)&addr6, len);
|
||||
if (result != 0) {
|
||||
perror("connect");
|
||||
}
|
||||
|
||||
memset((char *)&local, 0, len);
|
||||
if ((result =
|
||||
@@ -880,6 +914,7 @@ static const char *udp_host_addr6(socket_udp * s)
|
||||
&(addr6->sin6_addr),
|
||||
hname, MAXHOSTNAMELEN) == NULL) {
|
||||
error_msg("inet_ntop: %s: \n", hname);
|
||||
freeaddrinfo(ai);
|
||||
return NULL;
|
||||
}
|
||||
freeaddrinfo(ai);
|
||||
|
||||
@@ -347,11 +347,11 @@ void pbuf_insert(struct pbuf *playout_buf, rtp_packet * pkt)
|
||||
discard_pkt = true;
|
||||
}
|
||||
}
|
||||
if (pkt->m && discard_pkt) {
|
||||
debug_msg
|
||||
("Oops... dropped packet with M bit set\n");
|
||||
}
|
||||
if (discard_pkt) {
|
||||
if (pkt->m) {
|
||||
debug_msg
|
||||
("Oops... dropped packet with M bit set\n");
|
||||
}
|
||||
free(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1410,22 +1410,9 @@ void rtp_set_recv_iov(struct rtp *session, struct msghdr *m)
|
||||
session->mhdr = m;
|
||||
}
|
||||
|
||||
int rtp_recv_push_data(struct rtp *session,
|
||||
char *data, int buflen, uint32_t curr_rtp_ts)
|
||||
int rtp_send_raw_rtp_data(struct rtp *session, char *data, int buflen)
|
||||
{
|
||||
rtp_packet *packet = NULL;
|
||||
uint8_t *buffer = NULL;
|
||||
|
||||
if (!session->opt->reuse_bufs || (packet == NULL)) {
|
||||
packet = (rtp_packet *) malloc(RTP_MAX_PACKET_LEN);
|
||||
buffer = ((uint8_t *) packet) + RTP_PACKET_HEADER_SIZE;
|
||||
}
|
||||
|
||||
memcpy(buffer, data, buflen);
|
||||
|
||||
rtp_process_data(session, curr_rtp_ts, buffer, packet, buflen);
|
||||
|
||||
return buflen;
|
||||
return udp_send(session->rtp_socket, data, buflen);
|
||||
}
|
||||
|
||||
static int rtp_recv_data(struct rtp *session, uint32_t curr_rtp_ts)
|
||||
@@ -2007,6 +1994,8 @@ static void process_rtcp_app(struct rtp *session, rtcp_t * packet)
|
||||
event.type = RX_APP;
|
||||
event.data = (void *)app; /* The callback function MUST free this! */
|
||||
session->callback(session, &event);
|
||||
} else {
|
||||
free(app);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2617,7 +2606,7 @@ rtp_send_data_hdr(struct rtp *session,
|
||||
char *data, int data_len,
|
||||
char *extn, uint16_t extn_len, uint16_t extn_type)
|
||||
{
|
||||
int vlen, buffer_len, i, rc, pad, pad_len;
|
||||
int vlen, buffer_len, i, rc, pad, pad_len __attribute__((unused));
|
||||
uint8_t *buffer = NULL;
|
||||
rtp_packet *packet = NULL;
|
||||
uint8_t initVec[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
@@ -2743,10 +2732,10 @@ rtp_send_data_hdr(struct rtp *session,
|
||||
/* ...and the media data... */
|
||||
if (data_len > 0) {
|
||||
#ifdef WIN32
|
||||
send_vector[send_vector_len].buf = data;
|
||||
send_vector[send_vector_len].buf = (void *) data;
|
||||
send_vector[send_vector_len].len = data_len;
|
||||
#else
|
||||
send_vector[send_vector_len].iov_base = data;
|
||||
send_vector[send_vector_len].iov_base = (void *) data;
|
||||
send_vector[send_vector_len].iov_len = data_len;
|
||||
#endif
|
||||
send_vector_len++;
|
||||
@@ -3655,6 +3644,7 @@ int rtp_set_encryption_key(struct rtp *session, const char *passphrase)
|
||||
} else {
|
||||
debug_msg("Encryption algorithm \"%s\" not found\n",
|
||||
session->encryption_algorithm);
|
||||
free(canonical_passphrase);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -3912,7 +3902,7 @@ int rtp_compute_fract_lost(struct rtp *session, uint32_t ssrc)
|
||||
/* Much of this is taken from A.3 of draft-ietf-avt-rtp-new-01.txt */
|
||||
int extended_max = s->cycles + s->max_seq;
|
||||
int expected = extended_max - s->base_seq + 1;
|
||||
int lost = expected - s->received;
|
||||
//int lost = expected - s->received;
|
||||
int expected_interval =
|
||||
expected - s->expected_prior;
|
||||
int received_interval =
|
||||
@@ -3920,8 +3910,8 @@ int rtp_compute_fract_lost(struct rtp *session, uint32_t ssrc)
|
||||
int lost_interval =
|
||||
expected_interval - received_interval;
|
||||
int fraction;
|
||||
uint32_t lsr;
|
||||
uint32_t dlsr;
|
||||
//uint32_t lsr;
|
||||
//uint32_t dlsr;
|
||||
|
||||
//printf("lost_interval %d\n", lost_interval);
|
||||
s->expected_prior = expected;
|
||||
|
||||
@@ -51,7 +51,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define RTP_VERSION 2
|
||||
#define RTP_PACKET_HEADER_SIZE ((sizeof(char *) * 2) + sizeof(uint32_t *) + (2 * sizeof(int)))
|
||||
#define RTP_PACKET_HEADER_SIZE ((int)((sizeof(char *) * 2) + sizeof(uint32_t *) + (2 * sizeof(int))))
|
||||
#define RTP_MAX_MTU 9000
|
||||
#define RTP_MAX_PACKET_LEN (RTP_MAX_MTU+RTP_PACKET_HEADER_SIZE)
|
||||
|
||||
@@ -244,8 +244,7 @@ int rtp_recv_r(struct rtp *session,
|
||||
struct timeval *timeout, uint32_t curr_rtp_ts);
|
||||
int rtp_recv_poll_r(struct rtp **sessions,
|
||||
struct timeval *timeout, uint32_t curr_rtp_ts);
|
||||
int rtp_recv_push_data(struct rtp *session,
|
||||
char *buffer, int buffer_len, uint32_t curr_rtp_ts);
|
||||
int rtp_send_raw_rtp_data(struct rtp *session, char *buffer, int buffer_len);
|
||||
|
||||
int rtp_send_data(struct rtp *session,
|
||||
uint32_t rtp_ts, char pt, int m,
|
||||
|
||||
@@ -143,6 +143,7 @@ process_sdes(struct pdb *participants, uint32_t ssrc, rtcp_sdes_item * d)
|
||||
|
||||
switch (d->type) {
|
||||
case RTCP_SDES_END:
|
||||
free(sdes_item);
|
||||
/* This is the end of the SDES list of a packet. */
|
||||
/* Nothing for us to deal with. */
|
||||
break;
|
||||
@@ -182,8 +183,10 @@ process_sdes(struct pdb *participants, uint32_t ssrc, rtcp_sdes_item * d)
|
||||
e->sdes_note = sdes_item;
|
||||
break;
|
||||
case RTCP_SDES_PRIV:
|
||||
free(sdes_item);
|
||||
break; /* Ignore private extensions */
|
||||
default:
|
||||
free(sdes_item);
|
||||
debug_msg
|
||||
("Ignored unknown SDES item (type=0x%02x) from 0x%08x\n",
|
||||
ssrc);
|
||||
@@ -200,12 +203,12 @@ void rtp_recv_callback(struct rtp *session, rtp_event * e)
|
||||
|
||||
switch (e->type) {
|
||||
case RX_RTP:
|
||||
if (pckt_rtp->data_len > 0) { /* Only process packets that contain data... */
|
||||
pbuf_insert(state->playout_buffer, pckt_rtp);
|
||||
}
|
||||
gettimeofday(&curr_time, NULL);
|
||||
tfrc_recv_data(state->tfrc_state, curr_time, pckt_rtp->seq,
|
||||
pckt_rtp->data_len + 40);
|
||||
if (pckt_rtp->data_len > 0) { /* Only process packets that contain data... */
|
||||
pbuf_insert(state->playout_buffer, pckt_rtp);
|
||||
}
|
||||
break;
|
||||
case RX_TFRC_RX:
|
||||
/* compute TCP friendly data rate */
|
||||
|
||||
@@ -59,12 +59,12 @@
|
||||
#include "video_frame.h"
|
||||
|
||||
//UTILS DECLARATIONS
|
||||
u_int32_t test4Bytes(struct rtpenc_h264_state *rtpench264state);
|
||||
uint32_t test4Bytes(struct rtpenc_h264_state *rtpench264state);
|
||||
unsigned char* startOfFrame(struct rtpenc_h264_state *rtpench264state);
|
||||
unsigned char* nextToParse(struct rtpenc_h264_state *rtpench264state);
|
||||
void checkEndOfFrame(struct rtpenc_h264_state *rtpench264state,
|
||||
unsigned numBytesNeeded);
|
||||
u_int8_t get1Byte(struct rtpenc_h264_state *rtpench264state);
|
||||
uint8_t get1Byte(struct rtpenc_h264_state *rtpench264state);
|
||||
void setFromState(struct rtpenc_h264_state *rtpench264state);
|
||||
void setToState(struct rtpenc_h264_state *rtpench264state);
|
||||
void skipBytes(struct rtpenc_h264_state *rtpench264state, unsigned numBytes);
|
||||
@@ -86,7 +86,7 @@ struct rtpenc_h264_state * rtpenc_h264_init_state() {
|
||||
|
||||
unsigned rtpenc_h264_frame_parse(struct rtpenc_h264_state *rtpench264state, uint8_t *buf_in, int size) {
|
||||
|
||||
u_int32_t next4Bytes = NULL;
|
||||
uint32_t next4Bytes = 0l;
|
||||
|
||||
if (!rtpench264state->haveSeenFirstStartCode) {
|
||||
//reset pointers and params of interest for this new frame to parse and send
|
||||
@@ -146,7 +146,7 @@ unsigned rtpenc_h264_frame_parse(struct rtpenc_h264_state *rtpench264state, uint
|
||||
}
|
||||
|
||||
//UTILS
|
||||
u_int32_t test4Bytes(struct rtpenc_h264_state *rtpench264state) {
|
||||
uint32_t test4Bytes(struct rtpenc_h264_state *rtpench264state) {
|
||||
checkEndOfFrame(rtpench264state, 4);
|
||||
|
||||
unsigned char const* ptr = nextToParse(rtpench264state);
|
||||
@@ -166,7 +166,7 @@ void checkEndOfFrame(struct rtpenc_h264_state *rtpench264state,
|
||||
rtpench264state->haveSeenEOF = true;
|
||||
}
|
||||
}
|
||||
u_int8_t get1Byte(struct rtpenc_h264_state *rtpench264state) { // byte-aligned
|
||||
uint8_t get1Byte(struct rtpenc_h264_state *rtpench264state) { // byte-aligned
|
||||
checkEndOfFrame(rtpench264state, 1);
|
||||
return startOfFrame(rtpench264state)[rtpench264state->curParserIndex++];
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ struct rtpenc_h264_state {
|
||||
bool haveSeenEOF;
|
||||
};
|
||||
|
||||
struct rtpenc_h264_state * rtpenc_h264_init_state();
|
||||
struct rtpenc_h264_state * rtpenc_h264_init_state(void);
|
||||
unsigned rtpenc_h264_frame_parse(struct rtpenc_h264_state *rtpench264state, uint8_t *buf_in, int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -95,10 +95,10 @@
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
|
||||
using std::map;
|
||||
using std::queue;
|
||||
using namespace std;
|
||||
|
||||
struct state_video_decoder;
|
||||
|
||||
@@ -160,22 +160,20 @@ struct main_msg;
|
||||
// message definitions
|
||||
typedef char *char_p;
|
||||
struct fec_msg : public msg {
|
||||
fec_msg(int count) : substream_count(count) {
|
||||
fec_msg(int count, fec_desc && d) : fec_description(d), substream_count(count), poisoned(false) {
|
||||
buffer_len = new int[count];
|
||||
buffer_num = new int[count];
|
||||
recv_buffers = new char_p[count];
|
||||
pckt_list = 0;
|
||||
}
|
||||
~fec_msg() {
|
||||
delete [] buffer_len;
|
||||
delete [] buffer_num;
|
||||
delete [] recv_buffers;
|
||||
delete [] pckt_list;
|
||||
}
|
||||
int *buffer_len;
|
||||
int *buffer_num;
|
||||
char **recv_buffers;
|
||||
map<int, int> *pckt_list;
|
||||
unique_ptr<map<int, int>[]> pckt_list;
|
||||
fec_desc fec_description;
|
||||
int substream_count;
|
||||
bool poisoned;
|
||||
@@ -202,13 +200,10 @@ struct decompress_msg : public msg {
|
||||
bool poisoned;
|
||||
};
|
||||
|
||||
struct main_msg : public msg {
|
||||
virtual ~main_msg(){}
|
||||
};
|
||||
|
||||
struct main_msg_reconfigure : public main_msg {
|
||||
main_msg_reconfigure(struct video_desc d) : desc(d) {}
|
||||
struct video_desc desc;
|
||||
struct main_msg_reconfigure {
|
||||
main_msg_reconfigure(struct video_desc d, struct fec_msg *lf) : desc(d), last_frame(lf) {}
|
||||
struct video_desc desc;
|
||||
struct fec_msg *last_frame;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -217,11 +212,6 @@ struct main_msg_reconfigure : public main_msg {
|
||||
*/
|
||||
struct state_video_decoder
|
||||
{
|
||||
state_video_decoder() :
|
||||
decompress_queue(1), fec_queue(1)
|
||||
{}
|
||||
virtual ~state_video_decoder() {}
|
||||
|
||||
struct module *parent;
|
||||
|
||||
pthread_t decompress_thread_id,
|
||||
@@ -255,7 +245,7 @@ struct state_video_decoder
|
||||
* has been processed and we can write to a new one */
|
||||
pthread_cond_t buffer_swapped_cv; ///< condition variable associated with @ref buffer_swapped
|
||||
|
||||
message_queue decompress_queue;
|
||||
unique_ptr<message_queue<>> decompress_queue;
|
||||
|
||||
codec_t out_codec;
|
||||
// display or postprocessor
|
||||
@@ -269,7 +259,7 @@ struct state_video_decoder
|
||||
int pp_output_frames_count;
|
||||
/// @}
|
||||
|
||||
message_queue fec_queue;
|
||||
unique_ptr<message_queue<>> fec_queue;
|
||||
|
||||
enum video_mode video_mode; ///< video mode set for this decoder
|
||||
unsigned merged_fb:1; ///< flag if the display device driver requires tiled video or not
|
||||
@@ -282,7 +272,7 @@ struct state_video_decoder
|
||||
/// @}
|
||||
timed_message slow_msg; ///< shows warning ony in certain interval
|
||||
|
||||
message_queue msg_queue;
|
||||
message_queue<main_msg_reconfigure *> msg_queue;
|
||||
|
||||
struct openssl_decrypt *decrypt; ///< decrypt state
|
||||
|
||||
@@ -319,13 +309,13 @@ static void *fec_thread(void *args) {
|
||||
struct fec_desc desc(FEC_NONE);
|
||||
|
||||
while(1) {
|
||||
struct fec_msg *data = NULL;
|
||||
data = dynamic_cast<fec_msg *>(decoder->fec_queue.pop());
|
||||
struct fec_msg *data;
|
||||
data = dynamic_cast<fec_msg *>(decoder->fec_queue->pop());
|
||||
|
||||
if(data->poisoned) {
|
||||
decompress_msg *msg = new decompress_msg(0);
|
||||
msg->poisoned = true;
|
||||
decoder->decompress_queue.push(msg);
|
||||
decoder->decompress_queue->push(msg);
|
||||
delete data;
|
||||
break; // exit from loop
|
||||
}
|
||||
@@ -374,7 +364,7 @@ static void *fec_thread(void *args) {
|
||||
|
||||
if(fec_out_len == 0) {
|
||||
ret = FALSE;
|
||||
fprintf(stderr, "[decoder] FEC: unable to reconstruct data.\n");
|
||||
verbose_msg("[decoder] FEC: unable to reconstruct data.\n");
|
||||
decoder->fec_nok += 1;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -390,8 +380,8 @@ static void *fec_thread(void *args) {
|
||||
parse_video_hdr(video_hdr, &network_desc);
|
||||
if (!video_desc_eq_excl_param(decoder->received_vid_desc,
|
||||
network_desc, PARAM_TILE_COUNT)) {
|
||||
main_msg *msg = new main_msg_reconfigure(network_desc);
|
||||
decoder->msg_queue.push(msg);
|
||||
decoder->msg_queue.push(new main_msg_reconfigure(network_desc, data));
|
||||
data = nullptr;
|
||||
ERROR_GOTO_CLEANUP
|
||||
}
|
||||
|
||||
@@ -469,12 +459,15 @@ static void *fec_thread(void *args) {
|
||||
decoder->buffer_swapped = false;
|
||||
}
|
||||
pthread_mutex_unlock(&decoder->lock);
|
||||
decoder->decompress_queue.push(decompress_msg);
|
||||
decoder->decompress_queue->push(decompress_msg);
|
||||
|
||||
cleanup:
|
||||
if(ret == FALSE) {
|
||||
for(int i = 0; i < data->substream_count; ++i) {
|
||||
free(data->recv_buffers[i]);
|
||||
delete decompress_msg;
|
||||
if (data) {
|
||||
for(int i = 0; i < data->substream_count; ++i) {
|
||||
free(data->recv_buffers[i]);
|
||||
}
|
||||
}
|
||||
decoder->corrupted++;
|
||||
decoder->dropped++;
|
||||
@@ -494,7 +487,7 @@ static void *decompress_thread(void *args) {
|
||||
struct tile *tile;
|
||||
|
||||
while(1) {
|
||||
decompress_msg *msg = dynamic_cast<decompress_msg *>(decoder->decompress_queue.pop());
|
||||
decompress_msg *msg = dynamic_cast<decompress_msg *>(decoder->decompress_queue->pop());
|
||||
|
||||
if(msg->poisoned) {
|
||||
delete msg;
|
||||
@@ -638,8 +631,7 @@ struct state_video_decoder *video_decoder_init(struct module *parent,
|
||||
{
|
||||
struct state_video_decoder *s;
|
||||
|
||||
s = (state_video_decoder *) calloc(1, sizeof(state_video_decoder));
|
||||
s = new(s) state_video_decoder; // call the constructor
|
||||
s = new state_video_decoder();
|
||||
|
||||
s->parent = parent;
|
||||
|
||||
@@ -655,6 +647,9 @@ struct state_video_decoder *video_decoder_init(struct module *parent,
|
||||
s->buffer_swapped = true;
|
||||
s->last_buffer_number = -1;
|
||||
|
||||
s->decompress_queue = unique_ptr<message_queue<>>(new message_queue<>(1));
|
||||
s->fec_queue = unique_ptr<message_queue<>>(new message_queue<>(1));
|
||||
|
||||
if (encryption) {
|
||||
if(openssl_decrypt_init(&s->decrypt,
|
||||
encryption, MODE_AES128_CTR) != 0) {
|
||||
@@ -670,19 +665,22 @@ struct state_video_decoder *video_decoder_init(struct module *parent,
|
||||
s->postprocess = vo_postprocess_init(tmp_pp_config);
|
||||
free(tmp_pp_config);
|
||||
if(strcmp(postprocess, "help") == 0) {
|
||||
delete s;
|
||||
exit_uv(0);
|
||||
return NULL;
|
||||
}
|
||||
if(!s->postprocess) {
|
||||
fprintf(stderr, "Initializing postprocessor \"%s\" failed.\n", postprocess);
|
||||
free(s);
|
||||
delete s;
|
||||
exit_uv(129);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(!video_decoder_register_display(s, display))
|
||||
if(!video_decoder_register_display(s, display)) {
|
||||
delete s;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -802,9 +800,9 @@ bool video_decoder_register_display(struct state_video_decoder *decoder, struct
|
||||
void video_decoder_remove_display(struct state_video_decoder *decoder)
|
||||
{
|
||||
if(decoder->display) {
|
||||
fec_msg *msg = new fec_msg(0);
|
||||
fec_msg *msg = new fec_msg(0, {});
|
||||
msg->poisoned = true;
|
||||
decoder->fec_queue.push(msg);
|
||||
decoder->fec_queue->push(msg);
|
||||
|
||||
pthread_join(decoder->fec_thread_id, NULL);
|
||||
pthread_join(decoder->decompress_thread_id, NULL);
|
||||
@@ -871,7 +869,7 @@ void video_decoder_destroy(struct state_video_decoder *decoder)
|
||||
|
||||
PRINT_STATISTICS
|
||||
|
||||
free(decoder);
|
||||
delete decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -991,7 +989,7 @@ bool init_decompress(codec_t in_codec, codec_t out_codec,
|
||||
static codec_t choose_codec_and_decoder(struct state_video_decoder *decoder, struct video_desc desc,
|
||||
decoder_t *decode_line)
|
||||
{
|
||||
codec_t out_codec = (codec_t) -1;
|
||||
codec_t out_codec = VIDEO_CODEC_NONE;
|
||||
*decode_line = NULL;
|
||||
|
||||
size_t native;
|
||||
@@ -1069,7 +1067,7 @@ after_decoder_lookup:
|
||||
if(decoder->decoder_type == UNSET) {
|
||||
fprintf(stderr, "Unable to find decoder for input codec \"%s\"!!!\n", get_codec_name(desc.color_spec));
|
||||
exit_uv(128);
|
||||
return (codec_t) -1;
|
||||
return VIDEO_CODEC_NONE;
|
||||
}
|
||||
|
||||
return out_codec;
|
||||
@@ -1146,7 +1144,7 @@ static bool reconfigure_decoder(struct state_video_decoder *decoder,
|
||||
* get_video_mode_tiles_y(decoder->video_mode);
|
||||
|
||||
out_codec = choose_codec_and_decoder(decoder, desc, &decode_line);
|
||||
if(out_codec == (codec_t) -1)
|
||||
if(out_codec == VIDEO_CODEC_NONE)
|
||||
return false;
|
||||
else
|
||||
decoder->out_codec = out_codec;
|
||||
@@ -1159,7 +1157,7 @@ static bool reconfigure_decoder(struct state_video_decoder *decoder,
|
||||
ret = display_get_property(decoder->display, DISPLAY_PROPERTY_VIDEO_MODE,
|
||||
&display_mode, &len);
|
||||
if(!ret) {
|
||||
debug_msg("Failed to get video display mode.");
|
||||
debug_msg("Failed to get video display mode.\n");
|
||||
display_mode = DISPLAY_PROPERTY_VIDEO_MERGED;
|
||||
}
|
||||
|
||||
@@ -1376,7 +1374,7 @@ bool parse_video_hdr(uint32_t *hdr, struct video_desc *desc)
|
||||
desc->width = ntohl(hdr[3]) >> 16;
|
||||
desc->height = ntohl(hdr[3]) & 0xffff;
|
||||
desc->color_spec = get_codec_from_fcc(hdr[4]);
|
||||
if(desc->color_spec == (codec_t) -1) {
|
||||
if(desc->color_spec == VIDEO_CODEC_NONE) {
|
||||
fprintf(stderr, "Unknown FourCC \"%4s\"!\n", (char *) &hdr[4]);
|
||||
return false;
|
||||
}
|
||||
@@ -1403,10 +1401,19 @@ static int reconfigure_if_needed(struct state_video_decoder *decoder,
|
||||
get_codec_name(network_desc.color_spec));
|
||||
decoder->received_vid_desc = network_desc;
|
||||
|
||||
#ifdef RECONFIGURE_IN_FUTURE_THREAD
|
||||
decoder->reconfiguration_in_progress = true;
|
||||
decoder->reconfiguration_future = std::async(std::launch::async,
|
||||
[decoder](){ return reconfigure_decoder(decoder, decoder->received_vid_desc); });
|
||||
|
||||
#else
|
||||
int ret = reconfigure_decoder(decoder, decoder->received_vid_desc);
|
||||
if (ret) {
|
||||
decoder->frame = display_get_frame(decoder->display);
|
||||
} else {
|
||||
fprintf(stderr, "Decoder reconfiguration failed!!!\n");
|
||||
decoder->frame = NULL;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@@ -1459,14 +1466,13 @@ int decode_video_frame(struct coded_data *cdata, void *decoder_data)
|
||||
int max_substreams = decoder->max_substreams;
|
||||
|
||||
int i;
|
||||
map<int, int> *pckt_list;
|
||||
uint32_t buffer_len[max_substreams];
|
||||
uint32_t buffer_num[max_substreams];
|
||||
// the following is just LDGM related optimalization - normally we fill up
|
||||
// allocated buffers when we have compressed data. But in case of LDGM, there
|
||||
// is just the LDGM buffer present, so we point to it instead to copying
|
||||
char *recv_buffers[max_substreams]; // for FEC or compressed data
|
||||
pckt_list = new map<int, int>[max_substreams];
|
||||
unique_ptr<map<int, int>[]> pckt_list(new map<int, int>[max_substreams]);
|
||||
for (i = 0; i < (int) max_substreams; ++i) {
|
||||
buffer_len[i] = 0;
|
||||
buffer_num[i] = 0;
|
||||
@@ -1510,15 +1516,17 @@ int decode_video_frame(struct coded_data *cdata, void *decoder_data)
|
||||
}
|
||||
}
|
||||
|
||||
main_msg *msg;
|
||||
while ((msg = dynamic_cast<main_msg *>(decoder->msg_queue.pop(true /* nonblock */)))) {
|
||||
if (dynamic_cast<main_msg_reconfigure *>(msg)) {
|
||||
main_msg_reconfigure *msg_reconf = dynamic_cast<main_msg_reconfigure *>(msg);
|
||||
if (reconfigure_if_needed(decoder, msg_reconf->desc)) {
|
||||
return FALSE;
|
||||
}
|
||||
main_msg_reconfigure *msg_reconf;
|
||||
while ((msg_reconf = decoder->msg_queue.pop(true /* nonblock */))) {
|
||||
if (reconfigure_if_needed(decoder, msg_reconf->desc)) {
|
||||
#ifdef RECONFIGURE_IN_FUTURE_THREAD
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
delete msg;
|
||||
if (msg_reconf->last_frame) {
|
||||
decoder->fec_queue->push(msg_reconf->last_frame);
|
||||
}
|
||||
delete msg_reconf;
|
||||
}
|
||||
|
||||
int pt;
|
||||
@@ -1635,7 +1643,9 @@ int decode_video_frame(struct coded_data *cdata, void *decoder_data)
|
||||
* each thread *MUST* wait here if this condition is true
|
||||
*/
|
||||
if (check_for_mode_change(decoder, hdr)) {
|
||||
#ifdef RECONFIGURE_IN_FUTURE_THREAD
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
// hereafter, display framebuffer can be used, so we
|
||||
@@ -1753,8 +1763,7 @@ next_packet:
|
||||
}
|
||||
|
||||
if(!pckt) {
|
||||
ret = FALSE;
|
||||
goto cleanup;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (decoder->frame == NULL && (pt == PT_VIDEO || pt == PT_ENCRYPT_VIDEO)) {
|
||||
@@ -1766,18 +1775,16 @@ next_packet:
|
||||
assert(ret == TRUE);
|
||||
|
||||
// format message
|
||||
fec_msg = new struct fec_msg(max_substreams);
|
||||
fec_msg->fec_description = fec_desc(fec::fec_type_from_pt(pt), k, m, c, seed);
|
||||
fec_msg->poisoned = false;
|
||||
fec_msg = new struct fec_msg(max_substreams, fec_desc(fec::fec_type_from_pt(pt), k, m, c, seed));
|
||||
memcpy(fec_msg->buffer_len, buffer_len, sizeof(buffer_len));
|
||||
memcpy(fec_msg->buffer_num, buffer_num, sizeof(buffer_num));
|
||||
memcpy(fec_msg->recv_buffers, recv_buffers, sizeof(recv_buffers));
|
||||
fec_msg->pckt_list = pckt_list;
|
||||
fec_msg->pckt_list = std::move(pckt_list);
|
||||
|
||||
if(decoder->fec_queue.size() > 0) {
|
||||
if(decoder->fec_queue->size() > 0) {
|
||||
decoder->slow_msg.print("Your computer may be too SLOW to play this !!!");
|
||||
}
|
||||
decoder->fec_queue.push(fec_msg);
|
||||
decoder->fec_queue->push(fec_msg);
|
||||
cleanup:
|
||||
;
|
||||
unsigned int frame_size = 0;
|
||||
@@ -1790,10 +1797,6 @@ cleanup:
|
||||
frame_size += buffer_len[i];
|
||||
}
|
||||
|
||||
if(ret != TRUE) {
|
||||
delete [] pckt_list;
|
||||
}
|
||||
|
||||
pbuf_data->max_frame_size = max(pbuf_data->max_frame_size, frame_size);
|
||||
pbuf_data->decoded++;
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ void BasicRTSPOnlySubsession::getStreamParameters(unsigned clientSessionId,
|
||||
netAddressBits clientAddress, Port const& clientRTPPort,
|
||||
Port const& clientRTCPPort, int tcpSocketNum,
|
||||
unsigned char rtpChannelId, unsigned char rtcpChannelId,
|
||||
netAddressBits& destinationAddress, u_int8_t& /*destinationTTL*/,
|
||||
netAddressBits& destinationAddress, uint8_t& /*destinationTTL*/,
|
||||
Boolean& isMulticast, Port& serverRTPPort, Port& serverRTCPPort,
|
||||
void*& streamToken) {
|
||||
if (Vdestination == NULL && (avType == video || avType == av)) {
|
||||
|
||||
@@ -48,19 +48,11 @@
|
||||
#include <ServerMediaSession.hh>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "rtsp/rtsp_utils.h"
|
||||
#include "audio/audio.h"
|
||||
#include "module.h"
|
||||
#include "control_socket.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// #ifndef _ON_DEMAND_SERVER_MEDIA_SUBSESSION_HH
|
||||
// #include <OnDemandServerMediaSubsession.hh>
|
||||
// #endif
|
||||
@@ -112,7 +104,7 @@ protected:
|
||||
unsigned char rtpChannelId,
|
||||
unsigned char rtcpChannelId,
|
||||
netAddressBits& destinationAddress,
|
||||
u_int8_t& destinationTTL,
|
||||
uint8_t& destinationTTL,
|
||||
Boolean& isMulticast,
|
||||
Port& serverRTPPort,
|
||||
Port& serverRTCPPort,
|
||||
|
||||
@@ -45,10 +45,6 @@
|
||||
#define C_BASIC_RTSP_ONLY_SERVER_H
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config_unix.h"
|
||||
@@ -62,10 +58,6 @@ extern "C" {
|
||||
#include "rtsp/rtsp_utils.h"
|
||||
#include "audio/audio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERNC extern "C"
|
||||
|
||||
@@ -15,7 +15,7 @@ typedef enum {
|
||||
#define EXTERNC
|
||||
#endif
|
||||
|
||||
EXTERNC void rtps_server_usage();
|
||||
EXTERNC void rtps_server_usage(void);
|
||||
EXTERNC int get_rtsp_server_port(char *config);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,7 +36,7 @@ struct stats {
|
||||
|
||||
void get_stat(char *buffer, int buffer_len) {
|
||||
platform_spin_lock(&m_spin);
|
||||
snprintf(buffer, buffer_len, "%s %lu", m_name.c_str(), m_val);
|
||||
snprintf(buffer, buffer_len, "%s %lld", m_name.c_str(), (long long) m_val);
|
||||
platform_spin_unlock(&m_spin);
|
||||
}
|
||||
|
||||
|
||||
@@ -328,7 +328,8 @@ save_arrival(struct tfrc *state, struct timeval curr_time, uint16_t seq)
|
||||
static double compute_loss_event(struct tfrc *state)
|
||||
{
|
||||
int i;
|
||||
uint32_t t, temp, I_tot0 = 0, I_tot1 = 0, I_tot = 0;
|
||||
uint32_t t __attribute__((unused));
|
||||
uint32_t temp, I_tot0 = 0, I_tot1 = 0, I_tot = 0;
|
||||
struct timeval now;
|
||||
double I_mean, p;
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@
|
||||
#include "perf.h"
|
||||
#include "audio/audio.h"
|
||||
#include "audio/codec.h"
|
||||
#include "audio/utils.h"
|
||||
#include "crypto/openssl_encrypt.h"
|
||||
#include "module.h"
|
||||
#include "rtp/fec.h"
|
||||
@@ -180,7 +179,9 @@ static void tx_update(struct tx *tx, struct video_frame *frame, int substream)
|
||||
snprintf(msg->fec_cfg, sizeof(msg->fec_cfg), "LDGM percents %d %d %f",
|
||||
data_len, tx->avg_len, tx->max_loss);
|
||||
msg->type = SENDER_MSG_CHANGE_FEC;
|
||||
send_message_to_receiver(get_parent_module(&tx->mod), (struct message *) msg);
|
||||
struct response *resp = send_message_to_receiver(get_parent_module(&tx->mod),
|
||||
(struct message *) msg);
|
||||
resp->deleter(resp);
|
||||
tx->avg_len_last = tx->avg_len;
|
||||
}
|
||||
}
|
||||
@@ -296,7 +297,9 @@ static bool set_fec(struct tx *tx, const char *fec_const)
|
||||
snprintf(msg->fec_cfg, sizeof(msg->fec_cfg), "LDGM cfg %s",
|
||||
fec_cfg ? fec_cfg : "");
|
||||
msg->type = SENDER_MSG_CHANGE_FEC;
|
||||
send_message_to_receiver(get_parent_module(&tx->mod), (struct message *) msg);
|
||||
struct response *resp = send_message_to_receiver(get_parent_module(&tx->mod),
|
||||
(struct message *) msg);
|
||||
resp->deleter(resp);
|
||||
} else { // delay creation until we have avarage frame size
|
||||
tx->max_loss = atof(fec_cfg);
|
||||
}
|
||||
@@ -633,15 +636,15 @@ tx_send_base(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session,
|
||||
* This multiplication scheme relies upon the fact, that our RTP/pbuf implementation is
|
||||
* not sensitive to packet duplication. Otherwise, we can get into serious problems.
|
||||
*/
|
||||
void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer)
|
||||
void audio_tx_send(struct tx* tx, struct rtp *rtp_session, const audio_frame2 * buffer)
|
||||
{
|
||||
int pt; /* PT set for audio in our packet format */
|
||||
unsigned int pos = 0u,
|
||||
m = 0u;
|
||||
int channel;
|
||||
char *chan_data;
|
||||
const char *chan_data;
|
||||
int data_len;
|
||||
char *data;
|
||||
const char *data;
|
||||
// see definition in rtp_callback.h
|
||||
uint32_t hdr_data[100];
|
||||
uint32_t *audio_hdr = hdr_data;
|
||||
@@ -673,9 +676,9 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
|
||||
pt = PT_AUDIO; /* PT set for audio in our packet format */
|
||||
}
|
||||
|
||||
for(channel = 0; channel < buffer->ch_count; ++channel)
|
||||
for(channel = 0; channel < buffer->get_channel_count(); ++channel)
|
||||
{
|
||||
chan_data = buffer->data[channel];
|
||||
chan_data = buffer->get_data(channel);
|
||||
pos = 0u;
|
||||
|
||||
if(tx->fec_scheme == FEC_MULT) {
|
||||
@@ -691,20 +694,36 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
|
||||
tmp |= tx->buffer; /* bits 10-31 */
|
||||
audio_hdr[0] = htonl(tmp);
|
||||
|
||||
audio_hdr[2] = htonl(buffer->data_len[channel]);
|
||||
audio_hdr[2] = htonl(buffer->get_data_len(channel));
|
||||
|
||||
/* fourth word */
|
||||
tmp = (buffer->bps * 8) << 26;
|
||||
tmp |= buffer->sample_rate;
|
||||
tmp = (buffer->get_bps() * 8) << 26;
|
||||
tmp |= buffer->get_sample_rate();
|
||||
audio_hdr[3] = htonl(tmp);
|
||||
|
||||
/* fifth word */
|
||||
audio_hdr[4] = htonl(get_audio_tag(buffer->codec));
|
||||
audio_hdr[4] = htonl(get_audio_tag(buffer->get_codec()));
|
||||
|
||||
int packet_rate = tx->packet_rate;
|
||||
if (packet_rate == RATE_AUTO) {
|
||||
/// @todo add automatic packet rate management also for audio. We currently don't
|
||||
/// know actual audio buffer length (if compressed)
|
||||
/**
|
||||
* @todo
|
||||
* Following code would actually work but seems to be useless in most of cases (eg.
|
||||
* PCM 2 channels 2 Bps takes 5 std. Eth frames). On the other hand it could cause
|
||||
* unexpectable problems (I'd write them here but if I'd expect them they wouldn't
|
||||
* be unexpectable.)
|
||||
*/
|
||||
#if 0
|
||||
double time_for_frame = buffer->get_duration() / buffer->get_channel_count();
|
||||
if (time_for_frame > 0.0) {
|
||||
long long req_bitrate = buffer->get_data_len(channel) * 8 / time_for_frame * tx->mult_count;
|
||||
// adjust computed value to 3
|
||||
req_bitrate = req_bitrate * 3;
|
||||
packet_rate = compute_packet_rate(req_bitrate, tx->mtu);
|
||||
} else {
|
||||
packet_rate = 0;
|
||||
}
|
||||
#endif
|
||||
packet_rate = 0;
|
||||
}
|
||||
|
||||
@@ -715,9 +734,9 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
|
||||
|
||||
data = chan_data + pos;
|
||||
data_len = tx->mtu - 40 - sizeof(audio_payload_hdr_t);
|
||||
if(pos + data_len >= (unsigned int) buffer->data_len[channel]) {
|
||||
data_len = buffer->data_len[channel] - pos;
|
||||
if(channel == buffer->ch_count - 1)
|
||||
if(pos + data_len >= (unsigned int) buffer->get_data_len(channel)) {
|
||||
data_len = buffer->get_data_len(channel) - pos;
|
||||
if(channel == buffer->get_channel_count() - 1)
|
||||
m = 1;
|
||||
}
|
||||
audio_hdr[1] = htonl(pos);
|
||||
@@ -730,7 +749,7 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
|
||||
if(tx->encryption) {
|
||||
crypto_hdr[0] = htonl(CRYPTO_TYPE_AES128_CTR << 24);
|
||||
data_len = openssl_encrypt(tx->encryption,
|
||||
data, data_len,
|
||||
const_cast<char *>(data), data_len,
|
||||
(char *) audio_hdr, sizeof(audio_payload_hdr_t),
|
||||
encrypted_data);
|
||||
data = encrypted_data;
|
||||
@@ -739,7 +758,7 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
|
||||
rtp_send_data_hdr(rtp_session, timestamp, pt, m, 0, /* contributing sources */
|
||||
0, /* contributing sources length */
|
||||
(char *) audio_hdr, rtp_hdr_len,
|
||||
data, data_len,
|
||||
const_cast<char *>(data), data_len,
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -750,12 +769,14 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
|
||||
mult_index = (mult_index + 1) % tx->mult_count;
|
||||
}
|
||||
|
||||
do {
|
||||
GET_STOPTIME;
|
||||
GET_DELTA;
|
||||
if (delta < 0)
|
||||
delta += 1000000000L;
|
||||
} while (packet_rate - delta > 0);
|
||||
if (pos < buffer->get_data_len(channel)) {
|
||||
do {
|
||||
GET_STOPTIME;
|
||||
GET_DELTA;
|
||||
if (delta < 0)
|
||||
delta += 1000000000L;
|
||||
} while (packet_rate - delta > 0);
|
||||
}
|
||||
|
||||
/* when trippling, we need all streams goes to end */
|
||||
if(tx->fec_scheme == FEC_MULT) {
|
||||
@@ -763,7 +784,7 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
|
||||
}
|
||||
|
||||
|
||||
} while (pos < (unsigned int) buffer->data_len[channel]);
|
||||
} while (pos < buffer->get_data_len(channel));
|
||||
}
|
||||
|
||||
tx->buffer ++;
|
||||
@@ -776,9 +797,9 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
|
||||
* as the mulaw and A-law standards (dynamic or std PT).
|
||||
*/
|
||||
void audio_tx_send_standard(struct tx* tx, struct rtp *rtp_session,
|
||||
audio_frame2 * buffer) {
|
||||
const audio_frame2 * buffer) {
|
||||
//TODO to be more abstract in order to accept A-law too and other supported standards with such implementation
|
||||
assert(buffer->codec == AC_MULAW || buffer->codec == AC_ALAW || buffer->codec == AC_OPUS);
|
||||
assert(buffer->get_codec() == AC_MULAW || buffer->get_codec() == AC_ALAW || buffer->get_codec() == AC_OPUS);
|
||||
|
||||
int pt;
|
||||
uint32_t ts;
|
||||
@@ -789,10 +810,10 @@ void audio_tx_send_standard(struct tx* tx, struct rtp *rtp_session,
|
||||
// Configure the right Payload type,
|
||||
// 8000 Hz, 1 channel and 2 bps is the ITU-T G.711 standard (should be 1 bps...)
|
||||
// Other channels or Hz goes to DynRTP-Type97
|
||||
if (buffer->ch_count == 1 && buffer->sample_rate == 8000) {
|
||||
if (buffer->codec == AC_MULAW)
|
||||
if (buffer->get_channel_count() == 1 && buffer->get_sample_rate() == 8000) {
|
||||
if (buffer->get_codec() == AC_MULAW)
|
||||
pt = PT_ITU_T_G711_PCMU;
|
||||
else if (buffer->codec == AC_ALAW)
|
||||
else if (buffer->get_codec() == AC_ALAW)
|
||||
pt = PT_ITU_T_G711_PCMA;
|
||||
else pt = PT_DynRTP_Type97;
|
||||
} else {
|
||||
@@ -800,10 +821,10 @@ void audio_tx_send_standard(struct tx* tx, struct rtp *rtp_session,
|
||||
}
|
||||
|
||||
// The sizes for the different audio_frame2 channels must be the same.
|
||||
for (int i = 1; i < buffer->ch_count; i++)
|
||||
assert(buffer->data_len[0] == buffer->data_len[i]);
|
||||
for (int i = 1; i < buffer->get_channel_count(); i++)
|
||||
assert(buffer->get_data_len(0) == buffer->get_data_len(i));
|
||||
|
||||
int data_len = buffer->data_len[0] * buffer->ch_count; /* Number of samples to send */
|
||||
int data_len = buffer->get_data_len(0) * buffer->get_channel_count(); /* Number of samples to send */
|
||||
int payload_size = tx->mtu - 40; /* Max size of an RTP payload field */
|
||||
|
||||
init_tx_mulaw_buffer();
|
||||
@@ -811,17 +832,17 @@ void audio_tx_send_standard(struct tx* tx, struct rtp *rtp_session,
|
||||
int ch, pos = 0, count = 0, pointerToSend = 0;
|
||||
|
||||
do {
|
||||
for (ch = 0; ch < buffer->ch_count; ch++) {
|
||||
memcpy(curr_sample, buffer->data[ch] + pos,
|
||||
buffer->bps * sizeof(char));
|
||||
curr_sample += buffer->bps * sizeof(char);
|
||||
count += buffer->bps * sizeof(char);
|
||||
for (ch = 0; ch < buffer->get_channel_count(); ch++) {
|
||||
memcpy(curr_sample, buffer->get_data(ch) + pos,
|
||||
buffer->get_bps() * sizeof(char));
|
||||
curr_sample += buffer->get_bps() * sizeof(char);
|
||||
count += buffer->get_bps() * sizeof(char);
|
||||
}
|
||||
pos += buffer->bps * sizeof(char);
|
||||
pos += buffer->get_bps() * sizeof(char);
|
||||
|
||||
if ((pos * buffer->ch_count) % payload_size == 0) {
|
||||
if ((pos * buffer->get_channel_count()) % payload_size == 0) {
|
||||
// Update first sample timestamp
|
||||
ts = get_std_audio_local_mediatime((double)payload_size / (double)buffer->ch_count);
|
||||
ts = get_std_audio_local_mediatime((double)payload_size / (double)buffer->get_channel_count());
|
||||
gettimeofday(&curr_time, NULL);
|
||||
rtp_send_ctrl(rtp_session, ts_prev, 0, curr_time); //send RTCP SR
|
||||
ts_prev = ts;
|
||||
@@ -833,9 +854,9 @@ void audio_tx_send_standard(struct tx* tx, struct rtp *rtp_session,
|
||||
}
|
||||
} while (count < data_len);
|
||||
|
||||
if ((pos * buffer->ch_count) % payload_size != 0) {
|
||||
if ((pos * buffer->get_channel_count()) % payload_size != 0) {
|
||||
// Update first sample timestamp
|
||||
ts = get_std_audio_local_mediatime((double)((pos * buffer->ch_count) % payload_size) / (double)buffer->ch_count);
|
||||
ts = get_std_audio_local_mediatime((double)((pos * buffer->get_channel_count()) % payload_size) / (double)buffer->get_channel_count());
|
||||
gettimeofday(&curr_time, NULL);
|
||||
rtp_send_ctrl(rtp_session, ts_prev, 0, curr_time); //send RTCP SR
|
||||
ts_prev = ts;
|
||||
@@ -843,7 +864,7 @@ void audio_tx_send_standard(struct tx* tx, struct rtp *rtp_session,
|
||||
rtp_send_data(rtp_session, ts, pt, 0, 0, /* contributing sources */
|
||||
0, /* contributing sources length */
|
||||
data_buffer_mulaw + pointerToSend,
|
||||
(pos * buffer->ch_count) % payload_size, 0, 0, 0);
|
||||
(pos * buffer->get_channel_count()) % payload_size, 0, 0, 0);
|
||||
}
|
||||
|
||||
platform_spin_unlock(&tx->spin);
|
||||
@@ -984,7 +1005,7 @@ void tx_send_h264(struct tx *tx, struct video_frame *frame,
|
||||
static uint32_t ts_prev = 0;
|
||||
uint32_t ts = 0;
|
||||
|
||||
assert(frame->tile_count = 1); // std transmit doesn't handle more than one tile
|
||||
assert(frame->tile_count == 1); // std transmit doesn't handle more than one tile
|
||||
assert(!frame->fragment || tx->fec_scheme == FEC_NONE); // currently no support for FEC with fragments
|
||||
assert(!frame->fragment || frame->tile_count); // multiple tiles are not currently supported for fragmented send
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user