merge for opus codec over rtp transmission support

This commit is contained in:
Gerard CL
2014-10-09 12:28:54 +02:00
203 changed files with 6292 additions and 5326 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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(

View File

@@ -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];

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

Submodule gpujpeg updated: e7d7e09a72...0b3af83685

View File

@@ -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;
}

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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 );

View File

@@ -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 ----- */

View File

@@ -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 );
}

View File

@@ -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 ----- */

View File

@@ -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 ----- */

View File

@@ -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 ----- */

View File

@@ -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);

View File

@@ -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);

View File

@@ -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
View File

@@ -0,0 +1,7 @@
#!/bin/sh
./autogen.sh
rm -rf .git
find -name .gitignore -print0 |xargs -0 rm

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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 */

View File

@@ -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");

View File

@@ -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:

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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
};

View File

@@ -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_ */

View File

@@ -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);

View File

@@ -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_ */

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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
View 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;
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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
View 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;
}

View File

@@ -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_

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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];

View File

@@ -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

View File

@@ -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));

View File

@@ -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 */

View File

@@ -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

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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,

View File

@@ -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)

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
View 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();
}
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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

View File

@@ -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"

View File

@@ -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 *);

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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!");
}

View File

@@ -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() {}

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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,

View File

@@ -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 */

View File

@@ -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++];
}

View File

@@ -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

View File

@@ -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++;

View File

@@ -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)) {

View File

@@ -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,

View File

@@ -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"

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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