diff --git a/DeckLink/Mac/DeckLinkAPIVersion.h b/DeckLink/Mac/DeckLinkAPIVersion.h index 2e767a892..628668482 100644 --- a/DeckLink/Mac/DeckLinkAPIVersion.h +++ b/DeckLink/Mac/DeckLinkAPIVersion.h @@ -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 diff --git a/Makefile.in b/Makefile.in index 3cf50d050..ab6b4f0a8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -9,13 +9,14 @@ COMMON_FLAGS = -g @DEFS@ -DPATH_PREFIX=@prefix@ -DLIB_DIR=@libdir@ -Wall -Wextr CFLAGS = @CFLAGS@ @X_CFLAGS@ $(COMMON_FLAGS) -D_GNU_SOURCE CPPFLAGS = @CPPFLAGS@ -D_GNU_SOURCE CXXFLAGS = @CXXFLAGS@ $(COMMON_FLAGS) -D_GNU_SOURCE -NVCCFLAGS = @NVCCFLAGS@ +MKDIR_P = mkdir -p +NVCCFLAGS = @NVCCFLAGS@ -gencode arch=compute_20,code=sm_20 -gencode arch=compute_30,code=sm_30 -gencode arch=compute_35,code=sm_35 LDFLAGS = @LDFLAGS@ LIBS += @LIBS@ @JACK_TRANS_LIB@ @MATHLIBS@ @COREAUDIO_LIB@ \ -lm -pthread -INC = -I. -Isrc -Itest @DVS_INC@ @DELTACAST_INC@ @QUICKTIME_INC@ @RTSP_INC@ @RTSP_SERVER_INC@ @DECKLINK_INC@ @PORTAUDIO_INC@ \ +INC = -Isrc -I$(srcdir) -I$(srcdir)/src -I$(srcdir)/test @DVS_INC@ @DELTACAST_INC@ @QUICKTIME_INC@ @RTSP_INC@ @DECKLINK_INC@ @PORTAUDIO_INC@ \ @GL_INC@ @SAGE_INC@ @JACK_TRANS_INC@ @JPEG_INC@ @COREAUDIO_INC@ @SPEEX_INC@ \ - @BLUEFISH444_INC@ @CURSES_CFLAGS@ + @BLUEFISH444_INC@ @CURSES_CFLAGS@ @CUDA_INC@ DECKLINK_PATH = @DECKLINK_PATH@ EXEEXT = @EXEEXT@ TARGET = bin/uv$(EXEEXT) @@ -25,7 +26,6 @@ PERF = bin/uv_perf BUNDLE = uv.app DXT_GLSL_CFLAGS = @DXT_GLSL_CFLAGS@ NVCC = @NVCC@ - DOCS = README REPORTING-BUGS GUI_TARGET = @GUI_TARGET@ @@ -41,13 +41,16 @@ datadir = @datadir@ docdir = @docdir@/ultragrid/ datarootdir = @datarootdir@ uv_datadir = @datadir@/ultragrid/ +srcdir = @srcdir@ +VPATH = @srcdir@ # autogenerated headers GENERATED_HEADERS = @GENERATED_HEADERS@ -ALL_INCLUDES = $(wildcard src/*.h) $(wildcard src/*/*.h) +ALL_INCLUDES = $(wildcard $(srcdir)/src/*.h $(srcdir)/src/*/*.h $(srcdir)/src/*/*/*.h) OBJS = @OBJS@ \ + src/blackmagic_common.o \ src/bitstream.o \ src/control_socket.o \ src/debug.o \ @@ -138,6 +141,7 @@ OBJS = @OBJS@ \ src/video_display.o \ src/video_display/aggregate.o \ src/video_display/null.o \ + src/video_display/pipe.o \ src/video_export.o \ src/video_rxtx.o \ src/video_rxtx/ihdtv.o \ @@ -145,6 +149,7 @@ OBJS = @OBJS@ \ src/video_rxtx/sage.o \ src/video_rxtx/ultragrid_rtp.o \ src/vo_postprocess.o \ + src/vo_postprocess/deinterlace.o \ src/vo_postprocess/3d-interlaced.o \ src/vo_postprocess/interlace.o \ src/vo_postprocess/double-framerate.o \ @@ -165,24 +170,25 @@ IMPORT_CONTROL_KEYBOARD_OBJS = src/import_control_keyboard.o SWITCHER_CONTROL_KEYBOARD_OBJS = src/switcher_control_keyboard.o # ------------------------------------------------------------------------------------------------- -all: $(TARGET) $(GUI_TARGET) $(IMPORT_C_TARGET) $(SWITCHER_TARGET) $(REFLECTOR_TARGET) modules ag-plugins configure-messages +all: src/dir-stamp $(TARGET) $(GUI_TARGET) $(IMPORT_C_TARGET) $(SWITCHER_TARGET) $(REFLECTOR_TARGET) modules ag-plugins configure-messages + +src/dir-stamp: + ${MKDIR_P} src src/audio src/audio/capture src/audio/codec src/audio/playback src/capture_filter src/compat src/crypto src/hd-rum-translator src/ihdtv src/rtp src/rtsp src/utils src/video_capture src/video_compress src/video_decompress src/video_display src/video_rxtx src/vo_postprocess ag_plugin bin cuda_dxt dxt_compress ldgm-coding ldgm-coding/matrix-gen lib lib/ultragrid + touch $@ modules: @LIB_TARGETS@ -bindir: - @if [ ! -d bin ]; then mkdir bin; fi - -$(TARGET): bindir $(OBJS) $(ULTRAGRID_OBJS) $(GENERATED_HEADERS) +$(TARGET): $(OBJS) $(ULTRAGRID_OBJS) $(GENERATED_HEADERS) $(LINKER) $(LDFLAGS) $(OBJS) $(ULTRAGRID_OBJS) $(LIBS) -o $(TARGET) if [ -n "@DLL_LIBS@" ]; then $(INSTALL) -m 644 @DLL_LIBS@ bin; fi -$(IMPORT_C_TARGET): bindir $(IMPORT_CONTROL_KEYBOARD_OBJS) +$(IMPORT_C_TARGET): $(IMPORT_CONTROL_KEYBOARD_OBJS) $(LINKER) $(LDFLAGS) $(IMPORT_CONTROL_KEYBOARD_OBJS) @CURSES_LIBS@ @NET_LIBS@ -o $@ -$(SWITCHER_TARGET): bindir $(SWITCHER_CONTROL_KEYBOARD_OBJS) +$(SWITCHER_TARGET): $(SWITCHER_CONTROL_KEYBOARD_OBJS) $(LINKER) $(LDFLAGS) $(SWITCHER_CONTROL_KEYBOARD_OBJS) @CURSES_LIBS@ @NET_LIBS@ -o $@ -pthread -$(REFLECTOR_TARGET): bindir $(OBJS) $(GENERATED_HEADERS) $(REFLECTOR_OBJS) +$(REFLECTOR_TARGET): $(OBJS) $(GENERATED_HEADERS) $(REFLECTOR_OBJS) $(LINKER) $(LDFLAGS) $(OBJS) $(REFLECTOR_OBJS) $(LIBS) -o $@ %.o: %.c $(ALL_INCLUDES) @@ -206,33 +212,33 @@ $(REFLECTOR_TARGET): bindir $(OBJS) $(GENERATED_HEADERS) $(REFLECTOR_OBJS) %.cu.lib: %.cu $(ALL_INCLUDES) "$(NVCC)" $(NVCCFLAGS) -DEXPORT_DLL_SYMBOLS $(INC) --shared $< -o $<.dll +SPEEX_FLAGS=-Wno-sign-compare -Wno-unused-parameter -Wno-bad-function-cast -Wno-missing-prototypes -Wno-missing-declarations src/audio/resample.o: - $(CC) $(CFLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c speex-1.2rc1/libspeex/resample.c -fPIC -DPIC -o $@ + $(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/resample.c -fPIC -DPIC -o $@ src/audio/preprocess.o: - $(CC) $(CFLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c speex-1.2rc1/libspeex/preprocess.c -fPIC -DPIC -o $@ + $(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/preprocess.c -fPIC -DPIC -o $@ src/audio/filterbank.o: - $(CC) $(CFLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -I/include -fvisibility=hidden -c speex-1.2rc1/libspeex/filterbank.c -fPIC -DPIC -o $@ + $(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -I/include -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/filterbank.c -fPIC -DPIC -o $@ src/audio/fftwrap.o: - $(CC) $(CFLAGS) $(INC) -DUSE_SMALLFT -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c speex-1.2rc1/libspeex/fftwrap.c -fPIC -DPIC -o $@ + $(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DUSE_SMALLFT -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/fftwrap.c -fPIC -DPIC -o $@ src/audio/smallft.o: - $(CC) $(CFLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c speex-1.2rc1/libspeex/smallft.c -fPIC -DPIC -o $@ + $(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/smallft.c -fPIC -DPIC -o $@ src/audio/mdf.o: - $(CC) $(CFLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c speex-1.2rc1/libspeex/mdf.c -fPIC -DPIC -o $@ + $(CC) $(CFLAGS) $(SPEEX_FLAGS) $(INC) -DEXPORT="" -DRANDOM_PREFIX=speex -DFLOATING_POINT -DOUTSIDE_SPEEX -I. -I $(srcdir)/speex-1.2rc1/include/speex -Iinclude -fvisibility=hidden -c $(srcdir)/speex-1.2rc1/libspeex/mdf.c -fPIC -DPIC -o $@ +src/audio/capture/coreaudio.o: src/audio/capture/coreaudio.c $(ALL_INCLUDES) + $(CC) $(CFLAGS) -Wno-error=deprecated-declarations $(INC) -c $< -o $@ -src/mac_gl_common.o: src/mac_gl_common.m src/mac_gl_common.h - $(CC) $(CFLAGS) $(INC) -x objective-c -c $< -o $@ +src/audio/playback/coreaudio.o: src/audio/playback/coreaudio.c $(ALL_INCLUDES) + $(CC) $(CFLAGS) -Wno-error=deprecated-declarations $(INC) -c $< -o $@ -src/utils/autorelease_pool.o: src/utils/autorelease_pool.m src/utils/autorelease_pool.h - $(CC) $(CFLAGS) $(INC) -x objective-c -c $< -o $@ - -src/utils/packet_counter.o: src/utils/packet_counter.cpp src/utils/packet_counter.h - $(CXX) $(CXXFLAGS) $(INC) -c $< -o $@ +src/video_display/quicktime.o: src/video_display/quicktime.c $(ALL_INCLUDES) + $(CC) $(CFLAGS) -Wno-error=deprecated-declarations $(INC) -c $< -o $@ src/video_capture/DeckLinkAPIDispatch.o: $(DECKLINK_PATH)/DeckLinkAPIDispatch.cpp $(CXX) $(CXXFLAGS) -c $(INC) -o src/video_capture/DeckLinkAPIDispatch.o $(DECKLINK_PATH)/DeckLinkAPIDispatch.cpp @@ -413,18 +419,18 @@ tests: test/run_tests # ------------------------------------------------------------------------------------------------- ag-plugins: ag_plugin/uvReceiverService.zip ag_plugin/uvSenderService.zip -AG_PLUGIN_TX_SCRIPTS = ag_plugin/uvSenderService.py \ - ag_plugin/uvSenderService.svc \ - ag_plugin/uvSenderService.manifest +AG_PLUGIN_TX_SCRIPTS = $(srcdir)/ag_plugin/uvSenderService.py \ + $(srcdir)/ag_plugin/uvSenderService.svc \ + $(srcdir)/ag_plugin/uvSenderService.manifest ag_plugin/uvSenderService.zip: $(AG_PLUGIN_TX_SCRIPTS) $(TARGET) @echo "Creating AccessGrid plugin: uvSenderService.zip" @rm -f ag_plugin/uvSenderService.zip @zip -j ag_plugin/uvSenderService.zip $(AG_PLUGIN_TX_SCRIPTS) $(TARGET) -AG_PLUGIN_RX_SCRIPTS = ag_plugin/uvReceiverService.py \ - ag_plugin/uvReceiverService.svc \ - ag_plugin/uvReceiverService.manifest +AG_PLUGIN_RX_SCRIPTS = $(srcdir)/ag_plugin/uvReceiverService.py \ + $(srcdir)/ag_plugin/uvReceiverService.svc \ + $(srcdir)/ag_plugin/uvReceiverService.manifest ag_plugin/uvReceiverService.zip: $(AG_PLUGIN_RX_SCRIPTS) $(TARGET) @echo "Creating AccessGrid plugin: uvReceiverService.zip" @@ -511,149 +517,116 @@ rtsp: @RTSP_LIB_TARGET@ rtsp_server: @RTSP_SERVER_LIB_TARGET@ @SDL_LIB_TARGET@: @SDL_OBJ@ @X_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_sdl.so.@video_display_abi_version@ $^ @SDL_LIBS@ -o $@ @GL_LIB_TARGET@: @GL_OBJ@ @X_OBJ@ @GL_COMMON_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_gl.so.@video_display_abi_version@ $^ @GL_LIB@ -o $@ @RTSP_LIB_TARGET@: @RTSP_OBJ@ - mkdir -p lib/ultragrid - $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_rtsp.so.@video_capture_abi_version@ $^ @RTSP_LIB@ -o $@ + $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_rtsp.so.@video_capture_abi_version@ $^ @RTSP_LIBS@ -o $@ @TESTCARD_LIB_TARGET@: @TESTCARD_COMMON@ @TESTCARD_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_testcard.so.@video_capture_abi_version@ $^ @TESTCARD_LIB@ -o $@ @SWMIX_LIB_TARGET@: @GL_COMMON_OBJ@ @SWMIX_OBJ@ @X_OBJ@ src/host.o - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_swmix.so.@video_capture_abi_version@ $^ @SWMIX_LIB@ -o $@ @TESTCARD2_LIB_TARGET@: @TESTCARD_COMMON@ @TESTCARD2_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_testcard2.so.@video_capture_abi_version@ $^ @TESTCARD2_LIB@ -o $@ -@DECKLINK_CAP_LIB_TARGET@: @DECKLINK_COMMON@ @DECKLINK_CAP_OBJ@ - mkdir -p lib/ultragrid +@DECKLINK_CAP_LIB_TARGET@: @DECKLINK_CAP_OBJ@ $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_decklink.so.@video_capture_abi_version@ $^ @DECKLINK_LIB@ -o $@ -@DECKLINK_DISP_LIB_TARGET@: src/video_capture/decklink.o @DECKLINK_COMMON@ @DECKLINK_DISP_OBJ@ - mkdir -p lib/ultragrid +@DECKLINK_DISP_LIB_TARGET@: src/video_capture/decklink.o @DECKLINK_DISP_OBJ@ $(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_decklink.so.@video_display_abi_version@ $^ @DECKLINK_LIB@ -o $@ @BLUEFISH444_CAP_LIB_TARGET@: @BLUEFISH444_CAP_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_bluefish444.so.@video_capture_abi_version@ $^ @BLUEFISH444_LIB@ -o $@ @BLUEFISH444_DISP_LIB_TARGET@: @BLUEFISH444_DISP_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_bluefish444.so.@video_display_abi_version@ $^ @BLUEFISH444_LIB@ -o $@ @DELTACAST_CAP_LIB_TARGET@: @DELTACAST_DISP_OBJ@ @DELTACAST_CAP_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_deltacast.so.@video_capture_abi_version@ $^ @DELTACAST_LIB@ -o $@ @DELTACAST_DISP_LIB_TARGET@: @DELTACAST_DISP_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_deltacast.so.@video_display_abi_version@ $^ @DELTACAST_LIB@ -o $@ @DVS_CAP_LIB_TARGET@: src/video_display/dvs.o @DVS_CAP_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_dvs.so.@video_capture_abi_version@ $^ @DVS_LIB@ -o $@ @DVS_DISP_LIB_TARGET@: @DVS_DISP_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_dvs.so.@video_display_abi_version@ $^ @DVS_LIB@ -o $@ @SCREEN_CAP_LIB_TARGET@: @SCREEN_CAP_OBJ@ @X_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_screen.so.@video_capture_abi_version@ $^ @SCREEN_CAP_LIB@ -o $@ @SAGE_LIB_TARGET@: @SAGE_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,display_sage.so.@video_display_abi_version@ $^ @SAGE_LIB@ -o $@ @RTDXT_COMPRESS_LIB_TARGET@: @GL_COMMON_OBJ@ @X_OBJ@ @RTDXT_COMMON_OBJ@ @RTDXT_COMPRESS_OBJ@ @RTDXT_COMMON_HEADERS@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vcompress_rtdxt.so.@video_compress_abi_version@ @GL_COMMON_OBJ@ @X_OBJ@ @RTDXT_COMMON_OBJ@ @RTDXT_COMPRESS_OBJ@ @RTDXT_LIB@ -o $@ @UYVY_COMPRESS_LIB_TARGET@: @GL_COMMON_OBJ@ @X_OBJ@ @UYVY_COMPRESS_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vcompress_uyvy.so.@video_compress_abi_version@ @GL_COMMON_OBJ@ @X_OBJ@ @UYVY_COMPRESS_OBJ@ -o $@ @LIBAVCODEC_COMPRESS_LIB_TARGET@: @LIBAVCODEC_COMPRESS_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vcompress_libavcodec.so.@video_compress_abi_version@ $^ @LIBAVCODEC_LIBS@ -o $@ @LIBAVCODEC_DECOMPRESS_LIB_TARGET@: @LIBAVCODEC_DECOMPRESS_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vdecompress_libavcodec.so.@video_decompress_abi_version@ $^ @LIBAVCODEC_LIBS@ -o $@ @LIBAVCODEC_AUDIO_CODEC_LIB_TARGET@: @LIBAVCODEC_AUDIO_CODEC_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,acodec_libavcodec.so.@audio_codec_abi_version@ $^ @LIBAVCODEC_LIBS@ -o $@ -@JPEG_COMPRESS_LIB_TARGET@: @JPEG_COMPRESS_OBJ@ @JPEG_COMMON_OBJ@ - mkdir -p lib/ultragrid +@JPEG_COMPRESS_LIB_TARGET@: @JPEG_COMPRESS_OBJ@ $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vcompress_jpeg.so.@video_compress_abi_version@ $^ @JPEG_LIB@ -o $@ @CUDA_DXT_COMPRESS_LIB_TARGET@: @CUDA_DXT_OBJ@ @CUDA_COMMON_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vcompress_cuda_dxt.so.@video_compress_abi_version@ $^ @CUDA_DXT_LIB@ -o $@ @RTDXT_DECOMPRESS_LIB_TARGET@: @GL_COMMON_OBJ@ @X_OBJ@ @RTDXT_COMMON_OBJ@ @RTDXT_DECOMPRESS_OBJ@ @RTDXT_COMMON_HEADERS@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vdecompress_rtdxt.so.@video_decompress_abi_version@ @GL_COMMON_OBJ@ @X_OBJ@ @RTDXT_COMMON_OBJ@ @RTDXT_DECOMPRESS_OBJ@ @RTDXT_LIB@ -o $@ -@JPEG_DECOMPRESS_LIB_TARGET@: @JPEG_DECOMPRESS_OBJ@ @JPEG_COMMON_OBJ@ - mkdir -p lib/ultragrid +@JPEG_DECOMPRESS_LIB_TARGET@: @JPEG_DECOMPRESS_OBJ@ $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vdecompress_jpeg.so.@video_decompress_abi_version@ $^ @JPEG_LIB@ -o $@ -@JPEG_TO_DXT_DECOMPRESS_LIB_TARGET@: @JPEG_TO_DXT_OBJ@ @JPEG_DECOMPRESS_OBJ@ @JPEG_COMMON_OBJ@ @CUDA_COMMON_OBJ@ - mkdir -p lib/ultragrid +@JPEG_TO_DXT_DECOMPRESS_LIB_TARGET@: @JPEG_TO_DXT_OBJ@ @JPEG_DECOMPRESS_OBJ@ @CUDA_COMMON_OBJ@ $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vdecompress_jpeg_to_dxt.so.@video_decompress_abi_version@ $^ @JPEG_TO_DXT_LIB@ -o $@ @ALSA_PLAY_LIB_TARGET@: @ALSA_PLAY_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,aplay_alsa.so.@audio_playback_abi_version@ $^ @ALSA_LIB@ -o $@ @ALSA_CAP_LIB_TARGET@: @ALSA_CAP_OBJ@ src/audio/playback/alsa.o - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,acap_alsa.so.@audio_capture_abi_version@ $^ @ALSA_LIB@ -o $@ @PORTAUDIO_PLAY_LIB_TARGET@: @PORTAUDIO_PLAY_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,aplay_portaudio.so.@audio_playback_abi_version@ $^ @PORTAUDIO_LIB@ -o $@ @PORTAUDIO_CAP_LIB_TARGET@: @PORTAUDIO_CAP_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,acap_portaudio.so.@audio_capture_abi_version@ $^ @PORTAUDIO_LIB@ -o $@ @JACK_CAP_LIB_TARGET@: @JACK_CAP_OBJ@ @SPEEX_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,acap_jack.so.@audio_capture_abi_version@ $^ @JACK_LIB@ -o $@ @JACK_PLAY_LIB_TARGET@: @JACK_PLAY_OBJ@ @SPEEX_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,aplay_jack.so.@audio_playback_abi_version@ $^ @JACK_LIB@ -o $@ -@DECKLINK_SOUND_PLAY_LIB_TARGET@: @DECKLINK_SOUND_PLAY_OBJ@ @DECKLINK_COMMON@ - mkdir -p lib/ultragrid +@DECKLINK_SOUND_PLAY_LIB_TARGET@: @DECKLINK_SOUND_PLAY_OBJ@ $(LINKER) $(LDFLAGS) -shared -Wl,-soname,aplay_jack.so.@audio_playback_abi_version@ $^ @DECKLINK_LIB@ -o $@ @SCALE_LIB_TARGET@: @SCALE_OBJ@ @GL_COMMON_OBJ@ @X_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vo_pp_scale.so.@vo_pp_abi_version@ $^ @SCALE_LIB@ -o $@ @V4L2_LIB_TARGET@: @V4L2_OBJ@ - mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_v4l2.so.@video_capture_abi_version@ $^ @V4L2_LIBS@ -o $@ @RTSP_SERVER_LIB_TARGET@: @RTSP_SERVER_OBJ@ - mkdir -p lib/ultragrid - $(LINKER) $(LDFLAGS) -shared -Wl,-soname,video_rxtx_h264.so.@video_rxtx_abi_version@ $^ @RTSP_SERVER_LIB@ -o $@ + $(LINKER) $(LDFLAGS) -shared -Wl,-soname,video_rxtx_h264.so.@video_rxtx_abi_version@ $^ @RTSP_SERVER_LIBS@ -o $@ + +@VCAPTURE_FILTER_RESIZE_LIB_TARGET@: @RESIZE_OBJ@ + $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_resize.so.@vcapture_filter_abi_version@ $^ @RESIZE_LIBS@ -o $@ install: all $(INSTALL) -d -m 755 $(DESTDIR)/$(bindir) diff --git a/autogen.sh b/autogen.sh index 8d7e2beb6..14ca714e4 100755 --- a/autogen.sh +++ b/autogen.sh @@ -13,7 +13,15 @@ aclocal autoheader autoconf -$srcdir/configure --enable-gpl $@ +CONFIGURE_OPTS="--enable-gpl" + +if [ -n "$DEBUG" ]; then + CONFIGURE_OPTS="$CONFIGURE_OPTS --enable-debug" +fi + +cd $ORIGDIR + +$srcdir/configure $CONFIGURE_OPTS $@ cd $ORIGDIR diff --git a/configure.ac b/configure.ac index ffc47fb3c..3aaac001e 100644 --- a/configure.ac +++ b/configure.ac @@ -45,9 +45,9 @@ AC_CHECK_HEADERS(stropts.h sys/filio.h sys/wait.h) # ------------------------------------------------------------------------------------------------- POST_COMPILE_MSG="" -CFLAGS="$CFLAGS -I." -CPPFLAGS="$CPPFLAGS -I." -CXXFLAGS="$CXXFLAGS -I. -D__STRICT_ANSI__ -std=c++0x" +CFLAGS="$CFLAGS -I$srcdir" +CPPFLAGS="$CPPFLAGS -I$srcdir" +CXXFLAGS="$CXXFLAGS -I$srcdir -D__STRICT_ANSI__ -std=c++0x" LIB_MODULES= AC_SUBST(LIBS) AC_SUBST(OBJS) @@ -60,6 +60,20 @@ AC_C_BIGENDIAN( AC_DEFINE([WORDS_SMALLENDIAN], 1, [This is little endian system]) ) +if test "$ac_cv_prog_cc_c99" = no +then + AC_MSG_ERROR([Your compiler does not accept C99.]) +fi + +AC_CHECK_SIZEOF([size_t]) + +if test $ac_cv_sizeof_size_t -eq 8 +then + WORD_LEN=64 +else + WORD_LEN=32 +fi + AC_DEFUN([HM_VERSION_WARNING], [ AC_MSG_WARN([If you still want to try with unsupported version of dependency, you may want to try --disable-depends-version-check option. @@ -81,15 +95,6 @@ then fi fi -case "$host" in - x86_64-*-linux-*) - AC_DEFINE([HAVE_64B_LINUX], [1], [We have 64-bit Linux]) - ;; - i*86-*-linux-*) - AC_DEFINE([HAVE_32B_LINUX], [1], [We have 32-bit Linux]) - ;; -esac - AC_MSG_CHECKING([OS family]) if expr "$host_os" : ".*darwin.*" > /dev/null; then @@ -121,7 +126,7 @@ AC_MSG_RESULT($os_version_minor); if test $system = MacOSX then - COMMON_OSX_FLAGS="-m32 -I/opt/local/include -mmacosx-version-min=10.7" + COMMON_OSX_FLAGS="-I/opt/local/include -mmacosx-version-min=10.7" if test $os_version_major = 11 then OSX_SDK="macosx10.7" @@ -132,7 +137,10 @@ then CFLAGS="$CFLAGS $COMMON_OSX_FLAGS" CPPFLAGS="$CPPFLAGS $COMMON_OSX_FLAGS" CXXFLAGS="$CXXFLAGS $COMMON_OSX_FLAGS" - NVCCFLAGS="$NVCCFLAGS -m32 -I/opt/local/include -Xcompiler -Wno-error=unused-command-line-argument-hard-error-in-future" + NVCCFLAGS="$NVCCFLAGS -I/opt/local/include" + if test $WORD_LEN = 32; then + NVCCFLAGS="$NVCCFLAGS -Xcompiler -Wno-error=unused-command-line-argument-hard-error-in-future" + fi LDFLAGS="$LDFLAGS $COMMON_OSX_FLAGS" X_CFLAGS="$X_CFLAGS -I/usr/X11R6/include" OBJS="$OBJS src/utils/autorelease_pool.o" @@ -197,20 +205,6 @@ static inline int posix_memalign(void **memptr, size_t alignment, size_t size) #endif // defined HAVE_MACOSX && OS_VERSION_MAJOR <= 9 ]) -if test "$ac_cv_prog_cc_c99" = no -then - AC_MSG_ERROR([Your compiler does not accept C99.]) -fi - -AC_CHECK_SIZEOF([size_t]) - -if test $ac_cv_sizeof_size_t -eq 8 -then - WORD_LEN=64 -else - WORD_LEN=32 -fi - # ------------------------------------------------------------------------------------------------- # Licensing # ------------------------------------------------------------------------------------------------- @@ -277,14 +271,22 @@ AC_DEFUN([DEFINE_CUDA], [ ]) AC_SUBST(DLL_LIBS) -AC_MSG_CHECKING([if_nametoindex]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#include - ]], [[ -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 + #include + ]], [[ + 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( diff --git a/cuda_dxt/cuda_dxt.cu b/cuda_dxt/cuda_dxt.cu index d9067b323..0db545714 100644 --- a/cuda_dxt/cuda_dxt.cu +++ b/cuda_dxt/cuda_dxt.cu @@ -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 -__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]; diff --git a/dxt_compress/dxt_decoder.c b/dxt_compress/dxt_decoder.c index 2ef6694fa..8c97b02ed 100644 --- a/dxt_compress/dxt_decoder.c +++ b/dxt_compress/dxt_decoder.c @@ -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); diff --git a/dxt_compress/dxt_encoder.c b/dxt_compress/dxt_encoder.c index 542d33e06..354404ab1 100644 --- a/dxt_compress/dxt_encoder.c +++ b/dxt_compress/dxt_encoder.c @@ -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); diff --git a/dxt_compress/dxt_util.c b/dxt_compress/dxt_util.c index 830629560..4698869ba 100644 --- a/dxt_compress/dxt_util.c +++ b/dxt_compress/dxt_util.c @@ -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; diff --git a/dxt_compress/dxt_util.h b/dxt_compress/dxt_util.h index ff1255b1a..9d61c113d 100644 --- a/dxt_compress/dxt_util.h +++ b/dxt_compress/dxt_util.h @@ -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); diff --git a/gpujpeg b/gpujpeg index e7d7e09a7..0b3af8368 160000 --- a/gpujpeg +++ b/gpujpeg @@ -1 +1 @@ -Subproject commit e7d7e09a7248c995289e353ff2635f63c5e33d90 +Subproject commit 0b3af8368529686be92baa7cebcd04c50ea16048 diff --git a/hd-rum-transcode.c b/hd-rum-transcode.c deleted file mode 100644 index bfbf9b238..000000000 --- a/hd-rum-transcode.c +++ /dev/null @@ -1,283 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define __USE_GNU 1 -#include -#include - - -#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; -} - diff --git a/ldgm-coding/gpu.cu b/ldgm-coding/gpu.cu index a016a6211..75a0652d0 100644 --- a/ldgm-coding/gpu.cu +++ b/ldgm-coding/gpu.cu @@ -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 +#include +#include +#include #include - +#include #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 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 valid_data ) +char* +LDGM_session_cpu::decode_frame ( char* received, int buf_size, int* frame_size, + std::map 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::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 (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 (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::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::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::iterator it_v; - for(vector::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::iterator it_v; + for(vector::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::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::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 ); diff --git a/ldgm-coding/ldgm-session-cpu.h b/ldgm-coding/ldgm-session-cpu.h index bb70e4c16..278a73cf3 100644 --- a/ldgm-coding/ldgm-session-cpu.h +++ b/ldgm-coding/ldgm-session-cpu.h @@ -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 ----- */ diff --git a/ldgm-coding/ldgm-session-gpu.cpp b/ldgm-coding/ldgm-session-gpu.cpp index a18be6b57..7f6a1ca1d 100644 --- a/ldgm-coding/ldgm-session-gpu.cpp +++ b/ldgm-coding/ldgm-session-gpu.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include #include - -#include #include +#include +#include +#include +#include #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 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 merged_intervals; + std::map::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 (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 ); } diff --git a/ldgm-coding/ldgm-session-gpu.h b/ldgm-coding/ldgm-session-gpu.h index 029202ff6..de416a4ef 100644 --- a/ldgm-coding/ldgm-session-gpu.h +++ b/ldgm-coding/ldgm-session-gpu.h @@ -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 +#include #include "ldgm-session.h" +#include +#include + +// 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 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 freeBuffers; + std::map 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 ----- */ diff --git a/ldgm-coding/ldgm-session.cpp b/ldgm-coding/ldgm-session.cpp index d32dff780..e9afed6aa 100644 --- a/ldgm-coding/ldgm-session.cpp +++ b/ldgm-coding/ldgm-session.cpp @@ -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 #include #include +#include +#include #include - +#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::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::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::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 ----- */ diff --git a/ldgm-coding/ldgm-session.h b/ldgm-coding/ldgm-session.h index f995c6b23..c33cf08be 100644 --- a/ldgm-coding/ldgm-session.h +++ b/ldgm-coding/ldgm-session.h @@ -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 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 ----- */ diff --git a/ldgm-coding/matrix-gen/matrix-generator.cpp b/ldgm-coding/matrix-gen/matrix-generator.cpp index cc28b0dcf..02708401f 100644 --- a/ldgm-coding/matrix-gen/matrix-generator.cpp +++ b/ldgm-coding/matrix-gen/matrix-generator.cpp @@ -22,13 +22,12 @@ #include #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); diff --git a/ldgm-coding/matrix-gen/matrix-generator.h b/ldgm-coding/matrix-gen/matrix-generator.h index 5f2230195..82f3c205d 100644 --- a/ldgm-coding/matrix-gen/matrix-generator.h +++ b/ldgm-coding/matrix-gen/matrix-generator.h @@ -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); diff --git a/ldgm-coding/tanner.cpp b/ldgm-coding/tanner.cpp index 0f36e6fec..e5d651364 100644 --- a/ldgm-coding/tanner.cpp +++ b/ldgm-coding/tanner.cpp @@ -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 (index, n)); + Node n(this, type, data); + nodes.insert(std::pair (index, n)); } else { - Node n(this, type, data); - nodes.insert(std::pair (index, n)); + Node n(this, type, data); + nodes.insert(std::pair (index, n)); } } diff --git a/prepare_tarball.sh b/prepare_tarball.sh new file mode 100644 index 000000000..c8056564a --- /dev/null +++ b/prepare_tarball.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +./autogen.sh + +rm -rf .git +find -name .gitignore -print0 |xargs -0 rm + diff --git a/src/audio/audio.c b/src/audio/audio.cpp similarity index 91% rename from src/audio/audio.c rename to src/audio/audio.cpp index 3cb595b47..3cd23e00b 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.cpp @@ -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; +} diff --git a/src/audio/audio.h b/src/audio/audio.h index b0e70dce8..dc61f276d 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -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 +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 +#include +#include + +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, 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, diff --git a/src/audio/audio_playback.h b/src/audio/audio_playback.h index 2e9bbcc00..ece29b2cf 100644 --- a/src/audio/audio_playback.h +++ b/src/audio/audio_playback.h @@ -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 */ diff --git a/src/audio/capture/coreaudio.c b/src/audio/capture/coreaudio.c index 01cd48220..1870c484f 100644 --- a/src/audio/capture/coreaudio.c +++ b/src/audio/capture/coreaudio.c @@ -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"); diff --git a/src/audio/capture/jack.c b/src/audio/capture/jack.c index b7b39b2b9..6b3e5b2c4 100644 --- a/src/audio/capture/jack.c +++ b/src/audio/capture/jack.c @@ -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: diff --git a/src/audio/capture/portaudio.c b/src/audio/capture/portaudio.c index 4bd1c298f..4a733516a 100644 --- a/src/audio/capture/portaudio.c +++ b/src/audio/capture/portaudio.c @@ -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; } diff --git a/src/audio/capture/sdi.h b/src/audio/capture/sdi.h index aa6c8f4e3..29e8126e4 100644 --- a/src/audio/capture/sdi.h +++ b/src/audio/capture/sdi.h @@ -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 */ diff --git a/src/audio/capture/testcard.c b/src/audio/capture/testcard.c index 5857aa97f..7a9fc89cf 100644 --- a/src/audio/capture/testcard.c +++ b/src/audio/capture/testcard.c @@ -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; diff --git a/src/audio/codec.c b/src/audio/codec.cpp similarity index 74% rename from src/audio/codec.c rename to src/audio/codec.cpp index 11358ffc1..30b41f3a4 100644 --- a/src/audio/codec.c +++ b/src/audio/codec.cpp @@ -60,24 +60,24 @@ #include "lib_common.h" -#define MAX_AUDIO_CODECS 20 +#include -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_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 [:sample_rate=][: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; diff --git a/src/audio/codec.h b/src/audio/codec.h index a54705aea..619495b25 100644 --- a/src/audio/codec.h +++ b/src/audio/codec.h @@ -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 */ diff --git a/src/audio/codec/libavcodec.c b/src/audio/codec/libavcodec.cpp similarity index 78% rename from src/audio/codec/libavcodec.c rename to src/audio/codec/libavcodec.cpp index ba0cf6370..3bea0736e 100644 --- a/src/audio/codec/libavcodec.c +++ b/src/audio/codec/libavcodec.cpp @@ -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 + +extern "C" { #include #if LIBAVCODEC_VERSION_MAJOR >= 54 #include #endif #include +} +#include #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> 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 int32_data; + unique_ptr 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(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(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 }; diff --git a/src/audio/echo.h b/src/audio/echo.h index 09e19b8ad..3b1b44f25 100644 --- a/src/audio/echo.h +++ b/src/audio/echo.h @@ -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_ */ diff --git a/src/audio/export.c b/src/audio/export.c index 76f3d33c5..fd5c9b1e6 100644 --- a/src/audio/export.c +++ b/src/audio/export.c @@ -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); diff --git a/src/audio/export.h b/src/audio/export.h index 6d3b705c1..034bd13d4 100644 --- a/src/audio/export.h +++ b/src/audio/export.h @@ -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_ */ diff --git a/src/audio/playback/decklink.cpp b/src/audio/playback/decklink.cpp index 64e35c146..187063363 100644 --- a/src/audio/playback/decklink.cpp +++ b/src/audio/playback/decklink.cpp @@ -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 #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) diff --git a/src/audio/playback/jack.c b/src/audio/playback/jack.c index 97fb16022..99d1b16a4 100644 --- a/src/audio/playback/jack.c +++ b/src/audio/playback/jack.c @@ -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; } diff --git a/src/audio/playback/portaudio.c b/src/audio/playback/portaudio.c index c40e2214d..23b9be5ee 100644 --- a/src/audio/playback/portaudio.c +++ b/src/audio/playback/portaudio.c @@ -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); diff --git a/src/audio/playback/sdi.h b/src/audio/playback/sdi.h index f5a5af6e4..70dbb96fc 100644 --- a/src/audio/playback/sdi.h +++ b/src/audio/playback/sdi.h @@ -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 */ diff --git a/src/audio/resampler.c b/src/audio/resampler.c deleted file mode 100644 index c9f6392ab..000000000 --- a/src/audio/resampler.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "audio/resampler.h" -#include "audio/utils.h" - -#include - -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; -} - diff --git a/src/audio/resampler.cpp b/src/audio/resampler.cpp new file mode 100644 index 000000000..cca0f5bec --- /dev/null +++ b/src/audio/resampler.cpp @@ -0,0 +1,95 @@ +#include "audio/resampler.h" +#include "audio/utils.h" + +#include + +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; +} + diff --git a/src/audio/resampler.h b/src/audio/resampler.h index 524a42582..d8fab5086 100644 --- a/src/audio/resampler.h +++ b/src/audio/resampler.h @@ -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 diff --git a/src/audio/utils.c b/src/audio/utils.cpp similarity index 59% rename from src/audio/utils.c rename to src/audio/utils.cpp index 3e4b45d76..2e28a7a0b 100644 --- a/src/audio/utils.c +++ b/src/audio/utils.cpp @@ -62,73 +62,185 @@ #include #include +#include + #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 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 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 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 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(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) { diff --git a/src/audio/utils.h b/src/audio/utils.h index efb024fa9..0dee9c3fe 100644 --- a/src/audio/utils.h +++ b/src/audio/utils.h @@ -54,9 +54,6 @@ #include