From f6ec5a347b22e7b2752f19b0c519d50183d107d3 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Wed, 6 Aug 2014 12:24:39 +0200 Subject: [PATCH 01/95] RTSP: fixed type names (MSW compatibility) --- src/rtp/rtpenc_h264.c | 4 ++-- src/rtsp/BasicRTSPOnlySubsession.cpp | 2 +- src/rtsp/BasicRTSPOnlySubsession.hh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rtp/rtpenc_h264.c b/src/rtp/rtpenc_h264.c index 93da3deac..bfb23c9d7 100644 --- a/src/rtp/rtpenc_h264.c +++ b/src/rtp/rtpenc_h264.c @@ -64,7 +64,7 @@ unsigned char* startOfFrame(struct rtpenc_h264_state *rtpench264state); unsigned char* nextToParse(struct rtpenc_h264_state *rtpench264state); void checkEndOfFrame(struct rtpenc_h264_state *rtpench264state, unsigned numBytesNeeded); -u_int8_t get1Byte(struct rtpenc_h264_state *rtpench264state); +uint8_t get1Byte(struct rtpenc_h264_state *rtpench264state); void setFromState(struct rtpenc_h264_state *rtpench264state); void setToState(struct rtpenc_h264_state *rtpench264state); void skipBytes(struct rtpenc_h264_state *rtpench264state, unsigned numBytes); @@ -166,7 +166,7 @@ void checkEndOfFrame(struct rtpenc_h264_state *rtpench264state, rtpench264state->haveSeenEOF = true; } } -u_int8_t get1Byte(struct rtpenc_h264_state *rtpench264state) { // byte-aligned +uint8_t get1Byte(struct rtpenc_h264_state *rtpench264state) { // byte-aligned checkEndOfFrame(rtpench264state, 1); return startOfFrame(rtpench264state)[rtpench264state->curParserIndex++]; } diff --git a/src/rtsp/BasicRTSPOnlySubsession.cpp b/src/rtsp/BasicRTSPOnlySubsession.cpp index f2ef7d3b8..8f91e6d68 100644 --- a/src/rtsp/BasicRTSPOnlySubsession.cpp +++ b/src/rtsp/BasicRTSPOnlySubsession.cpp @@ -180,7 +180,7 @@ void BasicRTSPOnlySubsession::getStreamParameters(unsigned clientSessionId, netAddressBits clientAddress, Port const& clientRTPPort, Port const& clientRTCPPort, int tcpSocketNum, unsigned char rtpChannelId, unsigned char rtcpChannelId, - netAddressBits& destinationAddress, u_int8_t& /*destinationTTL*/, + netAddressBits& destinationAddress, uint8_t& /*destinationTTL*/, Boolean& isMulticast, Port& serverRTPPort, Port& serverRTCPPort, void*& streamToken) { if (Vdestination == NULL && (avType == video || avType == av)) { diff --git a/src/rtsp/BasicRTSPOnlySubsession.hh b/src/rtsp/BasicRTSPOnlySubsession.hh index 177ae91c5..01f8ebbd8 100644 --- a/src/rtsp/BasicRTSPOnlySubsession.hh +++ b/src/rtsp/BasicRTSPOnlySubsession.hh @@ -112,7 +112,7 @@ protected: unsigned char rtpChannelId, unsigned char rtcpChannelId, netAddressBits& destinationAddress, - u_int8_t& destinationTTL, + uint8_t& destinationTTL, Boolean& isMulticast, Port& serverRTPPort, Port& serverRTCPPort, From 71faa05ebb0b62540ed6e09fc58c90d847395a4f Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Wed, 6 Aug 2014 12:24:39 +0200 Subject: [PATCH 02/95] RTSP: fixed type names (MSW compatibility) --- src/rtp/rtpenc_h264.c | 10 +++++----- src/rtsp/BasicRTSPOnlySubsession.cpp | 2 +- src/rtsp/BasicRTSPOnlySubsession.hh | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rtp/rtpenc_h264.c b/src/rtp/rtpenc_h264.c index 93da3deac..745dfe8fb 100644 --- a/src/rtp/rtpenc_h264.c +++ b/src/rtp/rtpenc_h264.c @@ -59,12 +59,12 @@ #include "video_frame.h" //UTILS DECLARATIONS -u_int32_t test4Bytes(struct rtpenc_h264_state *rtpench264state); +uint32_t test4Bytes(struct rtpenc_h264_state *rtpench264state); unsigned char* startOfFrame(struct rtpenc_h264_state *rtpench264state); unsigned char* nextToParse(struct rtpenc_h264_state *rtpench264state); void checkEndOfFrame(struct rtpenc_h264_state *rtpench264state, unsigned numBytesNeeded); -u_int8_t get1Byte(struct rtpenc_h264_state *rtpench264state); +uint8_t get1Byte(struct rtpenc_h264_state *rtpench264state); void setFromState(struct rtpenc_h264_state *rtpench264state); void setToState(struct rtpenc_h264_state *rtpench264state); void skipBytes(struct rtpenc_h264_state *rtpench264state, unsigned numBytes); @@ -86,7 +86,7 @@ struct rtpenc_h264_state * rtpenc_h264_init_state() { unsigned rtpenc_h264_frame_parse(struct rtpenc_h264_state *rtpench264state, uint8_t *buf_in, int size) { - u_int32_t next4Bytes = NULL; + uint32_t next4Bytes = NULL; if (!rtpench264state->haveSeenFirstStartCode) { //reset pointers and params of interest for this new frame to parse and send @@ -146,7 +146,7 @@ unsigned rtpenc_h264_frame_parse(struct rtpenc_h264_state *rtpench264state, uint } //UTILS -u_int32_t test4Bytes(struct rtpenc_h264_state *rtpench264state) { +uint32_t test4Bytes(struct rtpenc_h264_state *rtpench264state) { checkEndOfFrame(rtpench264state, 4); unsigned char const* ptr = nextToParse(rtpench264state); @@ -166,7 +166,7 @@ void checkEndOfFrame(struct rtpenc_h264_state *rtpench264state, rtpench264state->haveSeenEOF = true; } } -u_int8_t get1Byte(struct rtpenc_h264_state *rtpench264state) { // byte-aligned +uint8_t get1Byte(struct rtpenc_h264_state *rtpench264state) { // byte-aligned checkEndOfFrame(rtpench264state, 1); return startOfFrame(rtpench264state)[rtpench264state->curParserIndex++]; } diff --git a/src/rtsp/BasicRTSPOnlySubsession.cpp b/src/rtsp/BasicRTSPOnlySubsession.cpp index f2ef7d3b8..8f91e6d68 100644 --- a/src/rtsp/BasicRTSPOnlySubsession.cpp +++ b/src/rtsp/BasicRTSPOnlySubsession.cpp @@ -180,7 +180,7 @@ void BasicRTSPOnlySubsession::getStreamParameters(unsigned clientSessionId, netAddressBits clientAddress, Port const& clientRTPPort, Port const& clientRTCPPort, int tcpSocketNum, unsigned char rtpChannelId, unsigned char rtcpChannelId, - netAddressBits& destinationAddress, u_int8_t& /*destinationTTL*/, + netAddressBits& destinationAddress, uint8_t& /*destinationTTL*/, Boolean& isMulticast, Port& serverRTPPort, Port& serverRTCPPort, void*& streamToken) { if (Vdestination == NULL && (avType == video || avType == av)) { diff --git a/src/rtsp/BasicRTSPOnlySubsession.hh b/src/rtsp/BasicRTSPOnlySubsession.hh index 177ae91c5..01f8ebbd8 100644 --- a/src/rtsp/BasicRTSPOnlySubsession.hh +++ b/src/rtsp/BasicRTSPOnlySubsession.hh @@ -112,7 +112,7 @@ protected: unsigned char rtpChannelId, unsigned char rtcpChannelId, netAddressBits& destinationAddress, - u_int8_t& destinationTTL, + uint8_t& destinationTTL, Boolean& isMulticast, Port& serverRTPPort, Port& serverRTCPPort, From 15fc8292e43bf7232439b396764047245ab3dcb1 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Wed, 6 Aug 2014 13:31:43 +0200 Subject: [PATCH 03/95] Audio testcard: changed description --- src/audio/capture/testcard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/capture/testcard.c b/src/audio/capture/testcard.c index 5857aa97f..ce57665e4 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"); } /** From c31a61d1a08ff5bacca16080fd366a5045fd3e2c Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Fri, 8 Aug 2014 16:39:38 +0200 Subject: [PATCH 04/95] Post merge fixes --- Makefile.in | 4 +++ configure.ac | 3 ++- src/capture_filter.cpp | 6 ----- src/capture_filter/resize.cpp | 9 ++++++- src/capture_filter/resize.h | 51 ----------------------------------- src/main.cpp | 32 +++++++++++----------- src/rtp/rtpenc_h264.c | 6 ++--- src/video_frame.c | 1 - 8 files changed, 33 insertions(+), 79 deletions(-) delete mode 100644 src/capture_filter/resize.h diff --git a/Makefile.in b/Makefile.in index 3cf50d050..925603369 100644 --- a/Makefile.in +++ b/Makefile.in @@ -655,6 +655,10 @@ rtsp_server: @RTSP_SERVER_LIB_TARGET@ mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,video_rxtx_h264.so.@video_rxtx_abi_version@ $^ @RTSP_SERVER_LIB@ -o $@ +@VCAPTURE_FILTER_RESIZE_LIB_TARGET@: @RESIZE_OBJ@ + mkdir -p lib/ultragrid + $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_resize.so.@vcapture_filter_abi_version@ $^ @RESIZE_LIB@ -o $@ + install: all $(INSTALL) -d -m 755 $(DESTDIR)/$(bindir) $(INSTALL) -m 755 bin/uv $(DESTDIR)/$(bindir) diff --git a/configure.ac b/configure.ac index ffc47fb3c..66dfea1b9 100644 --- a/configure.ac +++ b/configure.ac @@ -1343,8 +1343,9 @@ case $host in OPENCV_INC= RESIZE_LIB="${OPENCV_LIBS}" 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 diff --git a/src/capture_filter.cpp b/src/capture_filter.cpp index e876ce27e..d4b859f19 100644 --- a/src/capture_filter.cpp +++ b/src/capture_filter.cpp @@ -55,9 +55,6 @@ #include "capture_filter/logo.h" #include "capture_filter/none.h" #include "capture_filter/scale.h" -#ifdef HAVE_OPENCV -#include "capture_filter/resize.h" -#endif #include @@ -79,9 +76,6 @@ struct init_capture_filters { &capture_filter_logo, &capture_filter_none, &capture_filter_scale, -#ifdef HAVE_OPENCV - &capture_filter_resize, -#endif }; } } diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index dca03e990..9153b9181 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -185,13 +185,20 @@ static struct video_frame *filter(void *state, struct video_frame *in) return s->frame; } -struct capture_filter_info capture_filter_resize = { +static struct capture_filter_info capture_filter_resize = { "resize", init, done, filter, }; +static void init(void) __attribute__((constructor)); + +static void init(void) +{ + register_video_capture_filter(&capture_filter_resize); +} + #ifdef __cplusplus } #endif diff --git a/src/capture_filter/resize.h b/src/capture_filter/resize.h deleted file mode 100644 index cbad20e54..000000000 --- a/src/capture_filter/resize.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * FILE: capture_filter/resize.h - * AUTHORS: Gerard Castillo - * Marc Palau - * - * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya - * - * Redistribution and use in source and binary forms, with or without - * modification, is permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * - * This product includes software developed by the Fundació i2CAT, - * Internet I Innovació Digital a Catalunya. This product also includes - * software developed by CESNET z.s.p.o. - * - * 4. Neither the name of the University nor of the Institute may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef CAPTURE_FILTER_RESIZE_H_ -#define CAPTURE_FILTER_RESIZE_H_ - -struct capture_filter_info; -extern struct capture_filter_info capture_filter_resize; - -#endif // CAPTURE_FILTER_RESIZE_H_ diff --git a/src/main.cpp b/src/main.cpp index bab1af0f8..f12c61b63 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -782,22 +782,22 @@ int main(int argc, char *argv[]) requested_encryption = optarg; break; case OPT_CONTROL_PORT: - if (strchr(optarg, ':')) { - char *save_ptr = NULL; - char *tok; - control_port = atoi(strtok_r(optarg, ":", &save_ptr)); - connection_type = atoi(strtok_r(NULL, ":", &save_ptr)); - if(connection_type < 0 || connection_type > 1){ - usage(); - return EXIT_FAIL_USAGE; - } - if ((tok = strtok_r(NULL, ":", &save_ptr))) { - usage(); - return EXIT_FAIL_USAGE; - } - } else { - control_port = atoi(optarg); - } + if (strchr(optarg, ':')) { + char *save_ptr = NULL; + char *tok; + control_port = atoi(strtok_r(optarg, ":", &save_ptr)); + connection_type = atoi(strtok_r(NULL, ":", &save_ptr)); + if(connection_type < 0 || connection_type > 1){ + usage(); + return EXIT_FAIL_USAGE; + } + if ((tok = strtok_r(NULL, ":", &save_ptr))) { + usage(); + return EXIT_FAIL_USAGE; + } + } else { + control_port = atoi(optarg); + } break; case OPT_VERBOSE: verbose = true; diff --git a/src/rtp/rtpenc_h264.c b/src/rtp/rtpenc_h264.c index bfb23c9d7..745dfe8fb 100644 --- a/src/rtp/rtpenc_h264.c +++ b/src/rtp/rtpenc_h264.c @@ -59,7 +59,7 @@ #include "video_frame.h" //UTILS DECLARATIONS -u_int32_t test4Bytes(struct rtpenc_h264_state *rtpench264state); +uint32_t test4Bytes(struct rtpenc_h264_state *rtpench264state); unsigned char* startOfFrame(struct rtpenc_h264_state *rtpench264state); unsigned char* nextToParse(struct rtpenc_h264_state *rtpench264state); void checkEndOfFrame(struct rtpenc_h264_state *rtpench264state, @@ -86,7 +86,7 @@ struct rtpenc_h264_state * rtpenc_h264_init_state() { unsigned rtpenc_h264_frame_parse(struct rtpenc_h264_state *rtpench264state, uint8_t *buf_in, int size) { - u_int32_t next4Bytes = NULL; + uint32_t next4Bytes = NULL; if (!rtpench264state->haveSeenFirstStartCode) { //reset pointers and params of interest for this new frame to parse and send @@ -146,7 +146,7 @@ unsigned rtpenc_h264_frame_parse(struct rtpenc_h264_state *rtpench264state, uint } //UTILS -u_int32_t test4Bytes(struct rtpenc_h264_state *rtpench264state) { +uint32_t test4Bytes(struct rtpenc_h264_state *rtpench264state) { checkEndOfFrame(rtpench264state, 4); unsigned char const* ptr = nextToParse(rtpench264state); diff --git a/src/video_frame.c b/src/video_frame.c index 6443c1212..fe823d08a 100644 --- a/src/video_frame.c +++ b/src/video_frame.c @@ -133,7 +133,6 @@ void vf_data_deleter(struct video_frame *buf) return; for(unsigned int i = 0u; i < buf->tile_count; ++i) { - if(!buf->tiles[i].data) free(buf->tiles[i].data); } } From d3f66f211a108152a1c5798c0419fb41a2f0a494 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 11 Aug 2014 14:03:46 +0200 Subject: [PATCH 05/95] Video codec: hide codec_info structure --- src/hd-rum-translator/hd-rum-decompress.cpp | 2 +- src/rtp/video_decoders.cpp | 8 +-- src/video_capture/decklink.cpp | 55 +++++---------------- src/video_capture/deltacast_dvi.cpp | 11 +---- src/video_capture/dvs.c | 9 +--- src/video_capture/import.c | 2 +- src/video_capture/quicktime.c | 18 +++---- src/video_capture/swmix.cpp | 10 +--- src/video_capture/testcard.c | 12 ++--- src/video_capture/testcard2.c | 12 ++--- src/video_codec.c | 39 +++++++++++++-- src/video_codec.h | 25 +--------- src/video_compress/libavcodec.c | 12 ++--- src/video_decompress.c | 1 - src/video_display/dvs.c | 9 +--- src/video_display/quicktime.c | 26 +++++----- src/video_display/sage.cpp | 3 +- 17 files changed, 97 insertions(+), 157 deletions(-) diff --git a/src/hd-rum-translator/hd-rum-decompress.cpp b/src/hd-rum-translator/hd-rum-decompress.cpp index 7534484e3..10fb7f745 100644 --- a/src/hd-rum-translator/hd-rum-decompress.cpp +++ b/src/hd-rum-translator/hd-rum-decompress.cpp @@ -453,7 +453,7 @@ static bool decode_video_header(uint32_t *hdr, struct video_desc *desc, int *buf desc->width = ntohl(hdr[3]) >> 16; desc->height = ntohl(hdr[3]) & 0xffff; desc->color_spec = get_codec_from_fcc(hdr[4]); - if(desc->color_spec == (codec_t) -1) { + if(desc->color_spec == VIDEO_CODEC_NONE) { fprintf(stderr, "Unknown FourCC \"%4s\"!\n", (char *) &hdr[4]); return false; } diff --git a/src/rtp/video_decoders.cpp b/src/rtp/video_decoders.cpp index c55ccce8f..329af205b 100644 --- a/src/rtp/video_decoders.cpp +++ b/src/rtp/video_decoders.cpp @@ -991,7 +991,7 @@ bool init_decompress(codec_t in_codec, codec_t out_codec, static codec_t choose_codec_and_decoder(struct state_video_decoder *decoder, struct video_desc desc, decoder_t *decode_line) { - codec_t out_codec = (codec_t) -1; + codec_t out_codec = VIDEO_CODEC_NONE; *decode_line = NULL; size_t native; @@ -1069,7 +1069,7 @@ after_decoder_lookup: if(decoder->decoder_type == UNSET) { fprintf(stderr, "Unable to find decoder for input codec \"%s\"!!!\n", get_codec_name(desc.color_spec)); exit_uv(128); - return (codec_t) -1; + return VIDEO_CODEC_NONE; } return out_codec; @@ -1146,7 +1146,7 @@ static bool reconfigure_decoder(struct state_video_decoder *decoder, * get_video_mode_tiles_y(decoder->video_mode); out_codec = choose_codec_and_decoder(decoder, desc, &decode_line); - if(out_codec == (codec_t) -1) + if(out_codec == VIDEO_CODEC_NONE) return false; else decoder->out_codec = out_codec; @@ -1376,7 +1376,7 @@ bool parse_video_hdr(uint32_t *hdr, struct video_desc *desc) desc->width = ntohl(hdr[3]) >> 16; desc->height = ntohl(hdr[3]) & 0xffff; desc->color_spec = get_codec_from_fcc(hdr[4]); - if(desc->color_spec == (codec_t) -1) { + if(desc->color_spec == VIDEO_CODEC_NONE) { fprintf(stderr, "Unknown FourCC \"%4s\"!\n", (char *) &hdr[4]); return false; } diff --git a/src/video_capture/decklink.cpp b/src/video_capture/decklink.cpp index 2d9d36369..821e84291 100644 --- a/src/video_capture/decklink.cpp +++ b/src/video_capture/decklink.cpp @@ -121,7 +121,7 @@ struct vidcap_decklink_state { unsigned int next_frame_time; // avarege time between frames struct video_frame *frame; struct audio_frame audio; - const struct codec_info_t *c_info; + codec_t codec; BMDVideoInputFlags flags; pthread_mutex_t lock; @@ -193,7 +193,6 @@ public: }; virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(BMDVideoInputFormatChangedEvents, IDeckLinkDisplayMode* mode, BMDDetectedVideoInputFormatFlags flags) { - codec_t codec; BMDPixelFormat pf; HRESULT result; @@ -202,22 +201,15 @@ public: pthread_mutex_lock(&(s->lock)); switch(flags) { case bmdDetectedVideoInputYCbCr422: - codec = UYVY; + s->codec = UYVY; break; case bmdDetectedVideoInputRGB444: - codec = RGBA; + s->codec = RGBA; break; default: fprintf(stderr, "[Decklink] Unhandled color spec!\n"); abort(); } - int i; - for(i=0; codec_info[i].name != NULL; i++) { - if(codec_info[i].codec == codec) { - s->c_info = &codec_info[i]; - break; - } - } IDeckLinkInput *deckLinkInput = s->state[this->i].deckLinkInput; deckLinkInput->DisableVideoInput(); deckLinkInput->StopStreams(); @@ -519,13 +511,7 @@ settings_init(void *state, char *fmt) { struct vidcap_decklink_state *s = (struct vidcap_decklink_state *) state; - int i; - for(i=0; codec_info[i].name != NULL; i++) { - if(codec_info[i].codec == UYVY) { - s->c_info = &codec_info[i]; - break; - } - } + s->codec = UYVY; // default if(fmt) { char *save_ptr_top = NULL; @@ -561,24 +547,9 @@ settings_init(void *state, char *fmt) s->mode = atoi(tmp); tmp = strtok_r(NULL, ":", &save_ptr_top); - s->c_info = 0; - if(!tmp) { - int i; - for(i=0; codec_info[i].name != NULL; i++) { - if(codec_info[i].codec == UYVY) { - s->c_info = &codec_info[i]; - break; - } - } - } else { - int i; - for(i=0; codec_info[i].name != NULL; i++) { - if(strcmp(codec_info[i].name, tmp) == 0) { - s->c_info = &codec_info[i]; - break; - } - } - if(s->c_info == 0) { + if (tmp) { + s->codec = get_codec_from_name(tmp); + if(s->codec == VIDEO_CODEC_NONE) { fprintf(stderr, "Wrong config. Unknown color space %s\n", tmp); return 0; } @@ -661,7 +632,7 @@ static HRESULT set_display_mode_properties(struct vidcap_decklink_state *s, stru result = displayMode->GetName(&displayModeString); if (result == S_OK) { - switch(s->c_info->codec) { + switch (s->codec) { case RGBA: *pf = bmdFormat8BitBGRA; break; @@ -675,7 +646,7 @@ static HRESULT set_display_mode_properties(struct vidcap_decklink_state *s, stru *pf = bmdFormat10BitYUV; break; default: - printf("Unsupported codec! %s\n", s->c_info->name); + printf("Unsupported codec! %s\n", get_codec_name(s->codec)); } // get avarage time between frames BMDTimeValue frameRateDuration; @@ -683,7 +654,7 @@ static HRESULT set_display_mode_properties(struct vidcap_decklink_state *s, stru tile->width = displayMode->GetWidth(); tile->height = displayMode->GetHeight(); - s->frame->color_spec = s->c_info->codec; + s->frame->color_spec = s->codec; displayMode->GetFrameRate(&frameRateDuration, &frameRateScale); s->frame->fps = (double)frameRateScale / (double)frameRateDuration; @@ -1360,13 +1331,13 @@ vidcap_decklink_grab(void *state, struct audio_frame **audio) if (s->state[0].delegate->pixelFrame != NULL && s->state[0].delegate->pixelFrameRight != NULL) { s->frame->tiles[0].data = (char*)s->state[0].delegate->pixelFrame; - if(s->c_info->codec == RGBA) { + if (s->codec == RGBA) { vc_copylineRGBA((unsigned char*) s->frame->tiles[0].data, (unsigned char*)s->frame->tiles[0].data, s->frame->tiles[i].data_len, 16, 8, 0); } s->frame->tiles[1].data = (char*)s->state[0].delegate->pixelFrameRight; - if(s->c_info->codec == RGBA) { + if (s->codec == RGBA) { vc_copylineRGBA((unsigned char*) s->frame->tiles[1].data, (unsigned char*)s->frame->tiles[1].data, s->frame->tiles[i].data_len, 16, 8, 0); @@ -1377,7 +1348,7 @@ vidcap_decklink_grab(void *state, struct audio_frame **audio) for (i = 0; i < s->devices_cnt; ++i) { if (s->state[i].delegate->pixelFrame != NULL) { s->frame->tiles[i].data = (char*)s->state[i].delegate->pixelFrame; - if(s->c_info->codec == RGBA) { + if (s->codec == RGBA) { vc_copylineRGBA((unsigned char*) s->frame->tiles[i].data, (unsigned char*)s->frame->tiles[i].data, s->frame->tiles[i].data_len, 16, 8, 0); diff --git a/src/video_capture/deltacast_dvi.cpp b/src/video_capture/deltacast_dvi.cpp index 22b4591d5..d91cb2333 100644 --- a/src/video_capture/deltacast_dvi.cpp +++ b/src/video_capture/deltacast_dvi.cpp @@ -475,8 +475,6 @@ vidcap_deltacast_dvi_init(const struct vidcap_params *params) bool have_preset = false; VHD_DVI_MODE DviMode = NB_VHD_DVI_MODES; - int i; - printf("vidcap_deltacast_dvi_init\n"); s = (struct vidcap_deltacast_dvi_state *) calloc(1, sizeof(struct vidcap_deltacast_dvi_state)); @@ -509,13 +507,8 @@ vidcap_deltacast_dvi_init(const struct vidcap_params *params) } else if(strncasecmp(tok, "codec=", strlen("codec=")) == 0) { char *codec_str = tok + strlen("codec="); - for (i = 0; codec_info[i].name != NULL; i++) { - if (strcmp(codec_str, codec_info[i].name) == 0) { - s->codec = codec_info[i].codec; - break; - } - } - if(codec_info[i].name == NULL) { + s->codec = get_codec_from_name(codec_str); + if (s->codec == VIDEO_CODEC_NONE) { fprintf(stderr, "Unable to find codec: %s\n", codec_str); goto error; diff --git a/src/video_capture/dvs.c b/src/video_capture/dvs.c index 0db38d90d..aa8d325cd 100644 --- a/src/video_capture/dvs.c +++ b/src/video_capture/dvs.c @@ -288,13 +288,8 @@ void *vidcap_dvs_init(const struct vidcap_params *params) return 0; } - s->frame->color_spec = 0xffffffff; - for (i = 0; codec_info[i].name != NULL; i++) { - if (strcmp(tmp, codec_info[i].name) == 0) { - s->frame->color_spec = codec_info[i].codec; - } - } - if (s->frame->color_spec == (codec_t) 0xffffffff) { + s->frame->color_spec = get_codec_from_name(tmp); + if (s->frame->color_spec == VIDEO_CODEC_NONE) { fprintf(stderr, "dvs: unknown codec: %s\n", tmp); return 0; } diff --git a/src/video_capture/import.c b/src/video_capture/import.c index 7762dd6b2..8c1a85a11 100644 --- a/src/video_capture/import.c +++ b/src/video_capture/import.c @@ -408,7 +408,7 @@ vidcap_import_init(const struct vidcap_params *params) uint32_t fourcc; memcpy((void *) &fourcc, ptr, sizeof(fourcc)); desc.color_spec = get_codec_from_fcc(fourcc); - if(desc.color_spec == (codec_t) -1) { + if(desc.color_spec == VIDEO_CODEC_NONE) { fprintf(stderr, "[import] Requested codec not known.\n"); goto error; } diff --git a/src/video_capture/quicktime.c b/src/video_capture/quicktime.c index 1e621f641..97e382b20 100644 --- a/src/video_capture/quicktime.c +++ b/src/video_capture/quicktime.c @@ -565,16 +565,14 @@ static unsigned long get_color_spec(uint32_t pixfmt) { } } - // ...if it fails, try to match agains FourCC directly - for (i = 0; codec_info[i].name != NULL; i++) { - if ((unsigned)pixfmt == codec_info[i].fcc || - // try also the other endianity (QT codecs aren't - // entirely consistent in this regard) - ntohl(pixfmt) == codec_info[i].fcc) { - return codec_info[i].codec; - } + codec_t codec = get_codec_from_name(pixfmt); + if (codec != VIDEO_CODEC_NONE) { + return codec; + } else { + // try also the other endianity (QT codecs aren't + // entirely consistent in this regard) + return get_codec_from_name(ntohl(pixfmt)); } - return 0xffffffff; } /* Initialize the QuickTime grabber */ @@ -892,7 +890,7 @@ static int qt_open_grabber(struct qt_grabber_state *s, char *fmt) goto error; } - if (get_color_spec(pixfmt) == 0xffffffff) { + if (get_color_spec(pixfmt) == VIDEO_CODEC_NONE) { fprintf(stderr, "[QuickTime] Cannot find UltraGrid codec matching: %c%c%c%c!\n", pixfmt >> 24, (pixfmt >> 16) & 0xff, (pixfmt >> 8) & 0xff, (pixfmt) & 0xff); goto error; diff --git a/src/video_capture/swmix.cpp b/src/video_capture/swmix.cpp index bbaa800ac..1d1ba6042 100644 --- a/src/video_capture/swmix.cpp +++ b/src/video_capture/swmix.cpp @@ -928,7 +928,6 @@ static int parse_config_string(const char *fmt, unsigned int *width, tmp = parse_string = strdup(fmt); while((item = strtok_r(tmp, ":", &save_ptr))) { - bool found = false; switch (token_nr) { case 0: if(strcasecmp(item, "file") == 0) @@ -949,13 +948,8 @@ static int parse_config_string(const char *fmt, unsigned int *width, } break; case 3: - for (int i = 0; codec_info[i].name != NULL; i++) { - if (strcmp(item, codec_info[i].name) == 0) { - *color_spec = codec_info[i].codec; - found = true; - } - } - if(!found) { + *color_spec = get_codec_from_name(item); + if (*color_spec == VIDEO_CODEC_NONE) { fprintf(stderr, "Unrecognized color spec string: %s\n", item); return PARSE_ERROR; } diff --git a/src/video_capture/testcard.c b/src/video_capture/testcard.c index 368ffb13c..6c2579bbe 100644 --- a/src/video_capture/testcard.c +++ b/src/video_capture/testcard.c @@ -336,14 +336,12 @@ void *vidcap_testcard_init(const struct vidcap_params *params) int h_align = 0; double bpp = 0; - for (i = 0; codec_info[i].name != NULL; i++) { - if (strcmp(tmp, codec_info[i].name) == 0) { - h_align = codec_info[i].h_align; - bpp = codec_info[i].bpp; - codec = codec_info[i].codec; - break; - } + codec = get_codec_from_name(tmp); + if (codec == VIDEO_CODEC_NONE) { + codec = UYVY; } + h_align = get_halign(codec); + bpp = get_bpp(codec); s->frame->color_spec = codec; s->still_image = FALSE; diff --git a/src/video_capture/testcard2.c b/src/video_capture/testcard2.c index 2a14305e3..6d567bb7f 100644 --- a/src/video_capture/testcard2.c +++ b/src/video_capture/testcard2.c @@ -186,14 +186,12 @@ void *vidcap_testcard2_init(const struct vidcap_params *params) int h_align = 0; double bpp = 0; - for (i = 0; codec_info[i].name != NULL; i++) { - if (strcmp(tmp, codec_info[i].name) == 0) { - h_align = codec_info[i].h_align; - bpp = codec_info[i].bpp; - codec = codec_info[i].codec; - break; - } + codec = get_codec_from_name(tmp); + if (codec == VIDEO_CODEC_NONE) { + codec = UYVY; } + h_align = get_halign(codec); + bpp = get_bpp(codec); s->frame->color_spec = codec; diff --git a/src/video_codec.c b/src/video_codec.c index 7e6cb35a0..86ecde2f9 100644 --- a/src/video_codec.c +++ b/src/video_codec.c @@ -78,7 +78,6 @@ #define max(a, b) (((a) > (b))? (a): (b)) #define min(a, b) (((a) < (b))? (a): (b)) -static int get_halign(codec_t codec); static void vc_deinterlace_aligned(unsigned char *src, long src_linesize, int lines); static void vc_deinterlace_unaligned(unsigned char *src, long src_linesize, int lines); static void vc_copylineToUYVY709(unsigned char *dst, const unsigned char *src, int dst_len, @@ -86,7 +85,28 @@ static void vc_copylineToUYVY709(unsigned char *dst, const unsigned char *src, i static void vc_copylineToUYVY601(unsigned char *dst, const unsigned char *src, int dst_len, int rshift, int gshift, int bshift, int pix_size) __attribute__((unused)); -const struct codec_info_t codec_info[] = { +/** + * Defines codec metadata + * @note + * Members that are not relevant for specified codec (eg. bpp, rgb for opaque + * and interframe for not opaque) should be zero. + * @todo This should be perhaps private in .c file and properties should be + * queried by functions. + */ +struct codec_info_t { + codec_t codec; ///< codec descriptor + const char *name; ///< displayed name + uint32_t fcc; ///< FourCC + int h_align; ///< Number of pixels each line is aligned to + double bpp; ///< Number of bytes per pixel + int block_size; ///< Bytes per pixel block (pixelformats only) + unsigned rgb:1; ///< Whether pixelformat is RGB + unsigned opaque:1; ///< If codec is opaque (= compressed) + unsigned interframe:1; ///< Indicates if compression is interframe + const char *file_extension; ///< Extension that should be added to name if frame is saved to file. +}; + +static const struct codec_info_t codec_info[] = { [VIDEO_CODEC_NONE] = {VIDEO_CODEC_NONE, "(none)", 0, 0, 0.0, 0, FALSE, FALSE, FALSE, NULL}, [RGBA] = {RGBA, "RGBA", to_fourcc('R','G','B','A'), 1, 4.0, 4, TRUE, FALSE, FALSE, "rgba"}, [UYVY] = {UYVY, "UYVY", to_fourcc('U','Y','V','Y'), 2, 2, 4, FALSE, FALSE, FALSE, "yuv"}, @@ -246,7 +266,18 @@ codec_t get_codec_from_fcc(uint32_t fourcc) } i++; } - return (codec_t) -1; + return VIDEO_CODEC_NONE; +} + +codec_t get_codec_from_name(const char *name) +{ + for (int i = 0; codec_info[i].name != NULL; i++) { + if (strcmp(codec_info[i].name, name) == 0) { + return codec_info[i].codec; + } + + } + return VIDEO_CODEC_NONE; } const char *get_codec_file_extension(codec_t codec) @@ -296,7 +327,7 @@ int is_codec_interframe(codec_t codec) return 0; } -static int get_halign(codec_t codec) +int get_halign(codec_t codec) { int i = 0; diff --git a/src/video_codec.h b/src/video_codec.h index 08dff846e..0f369bd45 100644 --- a/src/video_codec.h +++ b/src/video_codec.h @@ -65,27 +65,6 @@ extern "C" { typedef void (*decoder_t)(unsigned char *dst, const unsigned char *src, int dst_len, int rshift, int gshift, int bshift); -/** - * Defines codec metadata - * @note - * Members that are not relevant for specified codec (eg. bpp, rgb for opaque - * and interframe for not opaque) should be zero. - * @todo This should be perhaps private in .c file and properties should be - * queried by functions. - */ -struct codec_info_t { - codec_t codec; ///< codec descriptor - const char *name; ///< displayed name - uint32_t fcc; ///< FourCC - int h_align; ///< Number of pixels each line is aligned to - double bpp; ///< Number of bytes per pixel - int block_size; ///< Bytes per pixel block (pixelformats only) - unsigned rgb:1; ///< Whether pixelformat is RGB - unsigned opaque:1; ///< If codec is opaque (= compressed) - unsigned interframe:1; ///< Indicates if compression is interframe - const char *file_extension; ///< Extension that should be added to name if frame is saved to file. -}; - /** Defines decoder from one pixel format to another */ struct line_decode_from_to { codec_t from; ///< source pixel format @@ -93,8 +72,6 @@ struct line_decode_from_to { decoder_t line_decoder; ///< decoding function }; -/** @brief 0-terminated list of UltraGrid supported codecs' metadata */ -extern const struct codec_info_t codec_info[]; /* defined int .c */ /** @brief 0-terminated list of available supported pixelformat decoders */ extern const struct line_decode_from_to line_decoders[]; /* defined int .c */ @@ -104,10 +81,12 @@ extern const struct line_decode_from_to line_decoders[]; /* defined int .c */ void show_codec_help(char *module); double get_bpp(codec_t codec) __attribute__((pure)); uint32_t get_fourcc(codec_t codec) __attribute__((pure)); +int get_halign(codec_t codec) __attribute__((pure)); const char *get_codec_name(codec_t codec) __attribute__((pure)); int is_codec_opaque(codec_t codec) __attribute__((pure)); int is_codec_interframe(codec_t codec) __attribute__((pure)); codec_t get_codec_from_fcc(uint32_t fourcc) __attribute__((pure)); +codec_t get_codec_from_name(const char *name) __attribute__((pure)); const char *get_codec_file_extension(codec_t codec) __attribute__((pure)); decoder_t get_decoder_from_to(codec_t in, codec_t out, bool slow) __attribute__((pure)); diff --git a/src/video_compress/libavcodec.c b/src/video_compress/libavcodec.c index fab600702..a21324f4b 100644 --- a/src/video_compress/libavcodec.c +++ b/src/video_compress/libavcodec.c @@ -192,14 +192,8 @@ static int parse_fmt(struct state_video_compress_libav *s, char *fmt) { return 1; } else if(strncasecmp("codec=", item, strlen("codec=")) == 0) { char *codec = item + strlen("codec="); - int i; - for (i = 0; codec_info[i].name != NULL; i++) { - if (strcasecmp(codec, codec_info[i].name) == 0) { - s->selected_codec_id = codec_info[i].codec; - break; - } - } - if(codec_info[i].name == NULL) { + s->selected_codec_id = get_codec_from_name(codec); + if (s->selected_codec_id == VIDEO_CODEC_NONE) { fprintf(stderr, "[lavd] Unable to find codec: \"%s\"\n", codec); return -1; } @@ -268,7 +262,7 @@ struct module * libavcodec_compress_init(struct module *parent, const struct vid platform_spin_init(&s->spin); - printf("[Lavc] Using codec: %s\n", codec_info[s->selected_codec_id].name); + printf("[Lavc] Using codec: %s\n", get_codec_name(s->selected_codec_id)); s->cpu_count = sysconf(_SC_NPROCESSORS_ONLN) / 4; // take conservatively only one fourth of cores if(s->cpu_count < 1) { diff --git a/src/video_decompress.c b/src/video_decompress.c index bb97d6d64..971bde926 100644 --- a/src/video_decompress.c +++ b/src/video_decompress.c @@ -155,7 +155,6 @@ struct decode_from_to decoders_for_codec[] = { { JPEG, DXT1, JPEG_TO_DXT_MAGIC, 900 }, { JPEG, DXT5, JPEG_TO_DXT_MAGIC, 900 }, { VP8, UYVY, LIBAVCODEC_MAGIC, 500 }, - { (codec_t) -1, (codec_t) -1, NULL_MAGIC, 0 } }; /** @brief Length of @ref decoders_for_codec members (items) */ const int decoders_for_codec_count = (sizeof(decoders_for_codec) / sizeof(struct decode_from_to)); diff --git a/src/video_display/dvs.c b/src/video_display/dvs.c index e289546bc..b2374132c 100644 --- a/src/video_display/dvs.c +++ b/src/video_display/dvs.c @@ -684,13 +684,8 @@ void *display_dvs_init(const char *cfg, unsigned int flags) tmp = strtok(NULL, ":"); if (tmp) { - s->frame->color_spec = 0xffffffff; - for (i = 0; codec_info[i].name != NULL; i++) { - if (strcmp(tmp, codec_info[i].name) == 0) { - s->frame->color_spec = codec_info[i].codec; - } - } - if (s->frame->color_spec == (codec_t) 0xffffffff) { + s->frame->color_spec = get_codec_from_name(tmp); + if (s->frame->color_spec == VIDEO_CODEC_NONE) { fprintf(stderr, "dvs: unknown codec: %s\n", tmp); free(s); return 0; diff --git a/src/video_display/quicktime.c b/src/video_display/quicktime.c index a85e2b605..05cac97b0 100644 --- a/src/video_display/quicktime.c +++ b/src/video_display/quicktime.c @@ -219,7 +219,7 @@ struct state_quicktime { int device[MAX_DEVICES]; int mode; int devices_cnt; - const struct codec_info_t *cinfo; + codec_t codec; /* Thread related information follows... */ pthread_t thread_id; @@ -300,12 +300,12 @@ static void reconf_common(struct state_quicktime *s) (**(ImageDescriptionHandle) imageDesc).idSize = sizeof(ImageDescription); - if (s->cinfo->codec == v210) + if (s->codec == v210) (**(ImageDescriptionHandle) imageDesc).cType = 'v210'; - else if (s->cinfo->codec == UYVY) + else if (s->codec == UYVY) (**(ImageDescriptionHandle) imageDesc).cType = '2vuy'; else - (**(ImageDescriptionHandle) imageDesc).cType = s->cinfo->fcc; + (**(ImageDescriptionHandle) imageDesc).cType = get_fourcc(s->codec); /* * dataSize is specified in bytes and is specified as * height*width*bytes_per_luma_instant. v210 sets @@ -681,13 +681,14 @@ void *display_quicktime_init(const char *fmt, unsigned int flags) strcpy(codec_name, "UYVY"); } - for (i = 0; codec_info[i].name != NULL; i++) { - if (strcmp(codec_name, codec_info[i].name) == 0) { - s->cinfo = &codec_info[i]; - } + s->codec = get_codec_from_name(codec_name); + if (s->codec == VIDEO_CODEC_NONE) { + fprintf(stderr, "Unknown codec name '%s'.\n", codec_name); + free(codec_name); + return NULL; } free(codec_name); - s->frame->color_spec = s->cinfo->codec; + s->frame->color_spec = s->codec; for (i = 0; i < s->devices_cnt; ++i) { struct tile *tile = vf_get_tile(s->frame, i); @@ -941,12 +942,7 @@ int display_quicktime_reconfigure(void *state, struct video_desc desc) int ret; const char *codec_name = NULL; - for (i = 0; codec_info[i].name != NULL; i++) { - if (codec_info[i].codec == desc.color_spec) { - s->cinfo = &codec_info[i]; - codec_name = s->cinfo->name; - } - } + codec_name = get_codec_name(desc.color_spec); assert(codec_name != NULL); if(desc.color_spec == UYVY) /* QT name for UYVY */ codec_name = "2vuy"; diff --git a/src/video_display/sage.cpp b/src/video_display/sage.cpp index 5b1331def..984a56450 100644 --- a/src/video_display/sage.cpp +++ b/src/video_display/sage.cpp @@ -170,7 +170,6 @@ void *display_sage_init(const char *fmt, unsigned int flags) assert(s != NULL); s->confName = NULL; - s->requestedDisplayCodec = (codec_t) -1; if(fmt) { if(strcmp(fmt, "help") == 0) { @@ -198,7 +197,7 @@ void *display_sage_init(const char *fmt, unsigned int flags) } memcpy((void *) &fourcc, item + strlen("codec="), sizeof(fourcc)); s->requestedDisplayCodec = get_codec_from_fcc(fourcc); - if(s->requestedDisplayCodec == (codec_t) -1) { + if(s->requestedDisplayCodec == VIDEO_CODEC_NONE) { fprintf(stderr, "Codec not found according to FourCC.\n"); free(s); return NULL; } From f38f94fce06178451794748821be4358b9d547b6 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 11 Aug 2014 14:15:56 +0200 Subject: [PATCH 06/95] Video codec: handle alias 2vuy as a name for UYVY + minor fixes --- src/video_codec.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/src/video_codec.c b/src/video_codec.c index 86ecde2f9..9f9254c44 100644 --- a/src/video_codec.c +++ b/src/video_codec.c @@ -151,7 +151,7 @@ const struct line_decode_from_to line_decoders[] = { /** * This struct specifies alias FourCC used for another FourCC */ -struct alternate_fourcc { +struct alternative_fourcc { uint32_t alias; uint32_t primary_fcc; }; @@ -159,7 +159,7 @@ struct alternate_fourcc { /** * This array contains FourCC aliases mapping */ -const struct alternate_fourcc fourcc_aliases[] = { +const struct alternative_fourcc fourcc_aliases[] = { // the following two are here because it was sent with wrong endiannes in past {to_fourcc('A', 'B', 'G', 'R'), to_fourcc('R', 'G', 'B', 'A')}, {to_fourcc('2', 'B', 'G', 'R'), to_fourcc('R', 'G', 'B', '2')}, @@ -172,7 +172,15 @@ const struct alternate_fourcc fourcc_aliases[] = { {to_fourcc('D', 'V', 'S', '8'), to_fourcc('U', 'Y', 'V', 'Y')}, {to_fourcc('y', 'u', 'v', '2'), to_fourcc('U', 'Y', 'V', 'Y')}, {to_fourcc('y', 'u', 'V', '2'), to_fourcc('U', 'Y', 'V', 'Y')}, - {0,0} +}; + +struct alternative_codec_name { + const char *alias; + const char *primary_name; +}; + +const struct alternative_codec_name codec_name_aliases[] = { + {"2vuy", "UYVY"}, }; void show_codec_help(char *module) @@ -246,7 +254,6 @@ uint32_t get_fcc_from_codec(codec_t codec) codec_t get_codec_from_fcc(uint32_t fourcc) { int i = 0; - while (codec_info[i].name != NULL) { if (fourcc == codec_info[i].fcc) return codec_info[i].codec; @@ -254,8 +261,7 @@ codec_t get_codec_from_fcc(uint32_t fourcc) } // try to look through aliases - i = 0; - while (fourcc_aliases[i].alias != 0) { + for (size_t i = 0; i < sizeof(fourcc_aliases) / sizeof(struct alternative_fourcc); ++i) { if (fourcc == fourcc_aliases[i].alias) { int j = 0; while (codec_info[j].name != NULL) { @@ -264,18 +270,43 @@ codec_t get_codec_from_fcc(uint32_t fourcc) j++; } } - i++; } return VIDEO_CODEC_NONE; } -codec_t get_codec_from_name(const char *name) +/** + * Helper codec finding function + * + * Iterates through codec list and finds appropriate codec. + * + * @returns codec + */ +static codec_t get_codec_from_name_wo_alias(const char *name) { for (int i = 0; codec_info[i].name != NULL; i++) { if (strcmp(codec_info[i].name, name) == 0) { return codec_info[i].codec; } + } + return VIDEO_CODEC_NONE; +} + +codec_t get_codec_from_name(const char *name) +{ + codec_t ret = get_codec_from_name_wo_alias(name); + if (ret != VIDEO_CODEC_NONE) { + return ret; + } + + // try to find if this is not an alias + for (size_t i = 0; i < sizeof(codec_name_aliases) / sizeof(struct alternative_codec_name); ++i) { + if (strcmp(name, codec_name_aliases[i].alias) == 0) { + ret = get_codec_from_name_wo_alias(name); + if (ret != VIDEO_CODEC_NONE) { + return ret; + } + } } return VIDEO_CODEC_NONE; } From b40e86e4c360d6b4594ff4fd40745241ac9308ab Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 11 Aug 2014 15:28:33 +0200 Subject: [PATCH 07/95] Decklink capture: print string repres. of errors --- Makefile.in | 1 + src/blackmagic_common.cpp | 72 ++++++++++++++++++++++++++++++++++ src/blackmagic_common.h | 52 ++++++++++++++++++++++++ src/video_capture/decklink.cpp | 60 ++++++++++++++++++++-------- 4 files changed, 169 insertions(+), 16 deletions(-) create mode 100644 src/blackmagic_common.cpp create mode 100644 src/blackmagic_common.h diff --git a/Makefile.in b/Makefile.in index 925603369..e13bd5812 100644 --- a/Makefile.in +++ b/Makefile.in @@ -48,6 +48,7 @@ GENERATED_HEADERS = @GENERATED_HEADERS@ ALL_INCLUDES = $(wildcard src/*.h) $(wildcard src/*/*.h) OBJS = @OBJS@ \ + src/blackmagic_common.o \ src/bitstream.o \ src/control_socket.o \ src/debug.o \ diff --git a/src/blackmagic_common.cpp b/src/blackmagic_common.cpp new file mode 100644 index 000000000..bf450956e --- /dev/null +++ b/src/blackmagic_common.cpp @@ -0,0 +1,72 @@ +/** + * @file blackmagic_common.cpp + * @author Martin Pulec + */ +/* + * Copyright (c) 2014 CESNET, z. s. p. o. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of CESNET nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#include "config_unix.h" +#include "config_win32.h" +#endif + +#include "blackmagic_common.h" +#include + +using namespace std; + +unordered_map bmd_hresult_to_string_map = { + {S_OK, "success"}, + {S_FALSE, "false"}, + {E_UNEXPECTED, "unexpected value"}, + {E_NOTIMPL, "not implemented"}, + {E_OUTOFMEMORY, "out of memory"}, + {E_INVALIDARG, "invalid argument"}, + {E_NOINTERFACE, "interface was not found"}, + {E_POINTER, "invalid pointer"}, + {E_HANDLE, "invalid handle"}, + {E_ABORT, "operation aborted"}, + {E_FAIL, "failure"}, + {E_ACCESSDENIED, "access denied"}, +}; + +string bmd_hresult_to_string(HRESULT res) +{ + auto it = bmd_hresult_to_string_map.find(res); + if (it != bmd_hresult_to_string_map.end()) { + return it->second; + } + return {}; +} + diff --git a/src/blackmagic_common.h b/src/blackmagic_common.h new file mode 100644 index 000000000..64a7efdee --- /dev/null +++ b/src/blackmagic_common.h @@ -0,0 +1,52 @@ +/** + * @file blackmagic_common.h + * @author Martin Pulec + */ +/* + * Copyright (c) 2014 CESNET, z. s. p. o. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of CESNET nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BLACKMAGIC_COMMON_H +#define BLACKMAGIC_COMMON_H + +#ifdef WIN32 +#include "DeckLinkAPI_h.h" /* From DeckLink SDK */ +#else +#include "DeckLinkAPI.h" /* From DeckLink SDK */ +#endif + +#include + +std::string bmd_hresult_to_string(HRESULT res); + +#endif // defined BLACKMAGIC_COMMON_H + diff --git a/src/video_capture/decklink.cpp b/src/video_capture/decklink.cpp index 821e84291..29b9282fa 100644 --- a/src/video_capture/decklink.cpp +++ b/src/video_capture/decklink.cpp @@ -73,6 +73,7 @@ extern "C" { #ifdef HAVE_DECKLINK /* From config.h */ +#include "blackmagic_common.h" #include "video_capture/decklink.h" #ifdef WIN32 @@ -98,6 +99,8 @@ extern "C" { #define STDMETHODCALLTYPE #endif +using namespace std; + // static int device = 0; // use first BlackMagic device // static int mode = 5; // for Intensity // static int mode = 6; // for Decklink 6) HD 1080i 59.94; 1920 x 1080; 29.97 FPS 7) HD 1080i 60; 1920 x 1080; 30 FPS @@ -725,8 +728,9 @@ vidcap_decklink_init(const struct vidcap_params *params) // Initialize COM on this thread result = CoInitialize(NULL); if(FAILED(result)) { - fprintf(stderr, "Initialization of COM failed - result = " - "08x.\n", result); + string err_msg = bmd_hresult_to_string(result); + fprintf(stderr, "Initialization of COM failed: " + "%s.\n", err_msg.c_str()); return NULL; } #endif @@ -893,9 +897,11 @@ vidcap_decklink_init(const struct vidcap_params *params) // Query the DeckLink for its configuration interface result = deckLink->QueryInterface(IID_IDeckLinkInput, (void**)&deckLinkInput); + string err_msg = bmd_hresult_to_string(result); if (result != S_OK) { - printf("Could not obtain the IDeckLinkInput interface - result = %08x\n", (int) result); + fprintf(stderr, "Could not obtain the IDeckLinkInput interface: %s\n", + err_msg.c_str()); goto error; } @@ -905,7 +911,9 @@ vidcap_decklink_init(const struct vidcap_params *params) result = deckLinkInput->GetDisplayModeIterator(&displayModeIterator); if (result != S_OK) { - printf("Could not obtain the video input display mode iterator - result = %08x\n", (int) result); + string err_msg = bmd_hresult_to_string(result); + fprintf(stderr, "Could not obtain the video input display mode iterator: %s\n", + err_msg.c_str()); goto error; } @@ -943,8 +951,10 @@ vidcap_decklink_init(const struct vidcap_params *params) result = deckLinkInput->QueryInterface(IID_IDeckLinkAttributes, (void**)&deckLinkAttributes); if (result != S_OK) { - printf("Could not query device attributes.\n"); - printf("Could not enable video input: %08x\n", (int) result); + string err_msg = bmd_hresult_to_string(result); + + fprintf(stderr, "Could not query device attributes: %s\n", + err_msg.c_str()); goto error; } @@ -972,8 +982,18 @@ vidcap_decklink_init(const struct vidcap_params *params) result = deckLinkInput->EnableVideoInput(displayMode->GetDisplayMode(), pf, s->flags); if (result != S_OK) { - printf("You have required invalid video mode and pixel format combination.\n"); - printf("Could not enable video input: %08x\n", (int) result); + switch (result) { + case E_INVALIDARG: + fprintf(stderr, "You have required invalid video mode and pixel format combination.\n"); + break; + case E_ACCESSDENIED: + fprintf(stderr, "Unable to access the hardware or input " + "stream currently active (another application using it?).\n"); + break; + } + string err_msg = bmd_hresult_to_string(result); + fprintf(stderr, "Could not enable video input: %s\n", + err_msg.c_str()); goto error; } @@ -981,7 +1001,8 @@ vidcap_decklink_init(const struct vidcap_params *params) result = deckLinkInput->QueryInterface(IID_IDeckLinkConfiguration, (void**)&deckLinkConfiguration); if (result != S_OK) { - printf("Could not obtain the IDeckLinkConfiguration interface: %08x\n", (int) result); + string err_msg = bmd_hresult_to_string(result); + fprintf(stderr, "Could not obtain the IDeckLinkConfiguration interface: %s\n", err_msg.c_str()); goto error; } @@ -1048,12 +1069,14 @@ vidcap_decklink_init(const struct vidcap_params *params) result = deckLinkInput->StartStreams(); if (result != S_OK) { - printf("Could not start stream: %08x\n", (int) result); + string err_msg = bmd_hresult_to_string(result); + fprintf(stderr, "Could not start stream: %s\n", err_msg.c_str()); goto error; } }else{ - printf("Could not : %08x\n", (int) result); + string err_msg = bmd_hresult_to_string(result); + fprintf(stderr, "Could not set display mode properties: %s\n", err_msg.c_str()); goto error; } @@ -1136,18 +1159,21 @@ vidcap_decklink_done(void *state) { result = s->state[i].deckLinkInput->StopStreams(); if (result != S_OK) { - fprintf(stderr, MODULE_NAME "Could not stop stream: %08x\n", (int) result); + string err_msg = bmd_hresult_to_string(result); + fprintf(stderr, MODULE_NAME "Could not stop stream: %s\n", err_msg.c_str()); } if(s->grab_audio && i == 0) { result = s->state[i].deckLinkInput->DisableAudioInput(); + string err_msg = bmd_hresult_to_string(result); if (result != S_OK) { - fprintf(stderr, MODULE_NAME "Could disable audio input: %08x\n", (int) result); + fprintf(stderr, MODULE_NAME "Could disable audio input: %s\n", err_msg.c_str()); } } result = s->state[i].deckLinkInput->DisableVideoInput(); if (result != S_OK) { - fprintf(stderr, MODULE_NAME "Could disable video input: %08x\n", (int) result); + string err_msg = bmd_hresult_to_string(result); + fprintf(stderr, MODULE_NAME "Could disable video input: %s\n", err_msg.c_str()); } if(s->state[i].deckLinkConfiguration != NULL) { @@ -1397,7 +1423,8 @@ static void print_input_modes (IDeckLink* deckLink) result = deckLink->QueryInterface(IID_IDeckLinkInput, (void**)&deckLinkInput); if (result != S_OK) { - fprintf(stderr, "Could not obtain the IDeckLinkInput interface - result = %08x\n", (int) result); + string err_msg = bmd_hresult_to_string(result); + fprintf(stderr, "Could not obtain the IDeckLinkInput interface: %s\n", err_msg.c_str()); if (result == E_NOINTERFACE) { printf("Device doesn't support video capture.\n"); } @@ -1408,7 +1435,8 @@ static void print_input_modes (IDeckLink* deckLink) result = deckLinkInput->GetDisplayModeIterator(&displayModeIterator); if (result != S_OK) { - fprintf(stderr, "Could not obtain the video input display mode iterator - result = %08x\n", (int) result); + string err_msg = bmd_hresult_to_string(result); + fprintf(stderr, "Could not obtain the video input display mode iterator: %s\n", err_msg.c_str()); goto bail; } From 19ed920654d7906b6d6e0667ac0e525c86510ec4 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 11 Aug 2014 17:43:46 +0200 Subject: [PATCH 08/95] Decklink cap.: make common string handling funcs --- src/blackmagic_common.cpp | 32 ++++++++++ src/blackmagic_common.h | 10 ++++ src/video_capture/decklink.cpp | 104 +++++++-------------------------- 3 files changed, 64 insertions(+), 82 deletions(-) diff --git a/src/blackmagic_common.cpp b/src/blackmagic_common.cpp index bf450956e..52dfa266c 100644 --- a/src/blackmagic_common.cpp +++ b/src/blackmagic_common.cpp @@ -41,6 +41,8 @@ #include "config_win32.h" #endif +#include "debug.h" + #include "blackmagic_common.h" #include @@ -70,3 +72,33 @@ string bmd_hresult_to_string(HRESULT res) return {}; } +/** + * returned c-sring needs to be freed when not used + */ +const char *get_cstr_from_bmd_api_str(BMD_STR bmd_string) +{ + const char *cstr; +#ifdef HAVE_MACOSX + cstr = (char *) malloc(128); + CFStringGetCString(bmd_string, (char *) cstr, 128, kCFStringEncodin + gMacRoman); +#elif defined WIN32 + cstr = (char *) malloc(128); + wcstombs((char *) cstr, bmd_string, 128); +#else // Linux + cstr = bmd_string; +#endif + + return cstr; +} + +void release_bmd_api_str(BMD_STR string) +{ + /// @todo what about MSW? +#ifdef HAVE_MACOSX + CFRelease(deviceNameString); +#else + UNUSED(string); +#endif +} + diff --git a/src/blackmagic_common.h b/src/blackmagic_common.h index 64a7efdee..8200f6e1c 100644 --- a/src/blackmagic_common.h +++ b/src/blackmagic_common.h @@ -48,5 +48,15 @@ std::string bmd_hresult_to_string(HRESULT res); +#ifdef HAVE_MACOSX +#define BMD_STR CFStringRef +#elif defined WIN32 +#define BMD_STR BSTR +#else +#define BMD_STR const char * +#endif +const char *get_cstr_from_bmd_api_str(BMD_STR string); +void release_bmd_api_str(BMD_STR string); + #endif // defined BLACKMAGIC_COMMON_H diff --git a/src/video_capture/decklink.cpp b/src/video_capture/decklink.cpp index 29b9282fa..cc53677c5 100644 --- a/src/video_capture/decklink.cpp +++ b/src/video_capture/decklink.cpp @@ -87,14 +87,6 @@ extern "C" { #define MAX_DEVICES 4 -#ifdef HAVE_MACOSX -#define STRING CFStringRef -#elif defined WIN32 -#define STRING BSTR -#else -#define STRING const char * -#endif - #ifndef WIN32 #define STDMETHODCALLTYPE #endif @@ -243,7 +235,7 @@ public: /* DeckLink SDK objects */ static void print_input_modes (IDeckLink* deckLink); -static int blackmagic_api_version_check(STRING *current_version); +static int blackmagic_api_version_check(BMD_STR *current_version); HRESULT VideoDelegate::VideoInputFrameArrived (IDeckLinkVideoInputFrame *arrivedFrame, IDeckLinkAudioInputPacket *audioPacket) @@ -342,7 +334,7 @@ void VideoDelegate::set_device_state(struct vidcap_decklink_state *state, int in i = index; } -static int blackmagic_api_version_check(STRING *current_version) +static int blackmagic_api_version_check(BMD_STR *current_version) { int ret = TRUE; *current_version = NULL; @@ -411,26 +403,16 @@ decklink_help() // Enumerate all cards in this system while (deckLinkIterator->Next(&deckLink) == S_OK) { - STRING deviceNameString = NULL; + BMD_STR deviceNameString = NULL; const char * deviceNameCString = NULL; // *** Print the model name of the DeckLink card - result = deckLink->GetModelName((STRING *) &deviceNameString); -#ifdef HAVE_MACOSX - deviceNameCString = (char *) malloc(128); - CFStringGetCString(deviceNameString, (char *)deviceNameCString, 128, kCFStringEncodingMacRoman); -#elif defined WIN32 - deviceNameCString = (char *) malloc(128); - wcstombs((char *) deviceNameCString, deviceNameString, 128); -#else - deviceNameCString = deviceNameString; -#endif + result = deckLink->GetModelName((BMD_STR *) &deviceNameString); + deviceNameCString = get_cstr_from_bmd_api_str(deviceNameString); if (result == S_OK) { printf("\ndevice: %d.) %s \n\n",numDevices, deviceNameCString); -#ifdef HAVE_MACOSX - CFRelease(deviceNameString); -#endif + release_bmd_api_str(deviceNameString); free((void *)deviceNameCString); } @@ -628,7 +610,7 @@ vidcap_decklink_probe(void) static HRESULT set_display_mode_properties(struct vidcap_decklink_state *s, struct tile *tile, IDeckLinkDisplayMode* displayMode, /* out */ BMDPixelFormat *pf) { - STRING displayModeString = NULL; + BMD_STR displayModeString = NULL; const char *displayModeCString; HRESULT result; @@ -675,21 +657,11 @@ static HRESULT set_display_mode_properties(struct vidcap_decklink_state *s, stru break; } - debug_msg("%-20s \t %d x %d \t %g FPS \t %d AVAREGE TIME BETWEEN FRAMES\n", displayModeString, + displayModeCString = get_cstr_from_bmd_api_str(displayModeString); + debug_msg("%-20s \t %d x %d \t %g FPS \t %d AVAREGE TIME BETWEEN FRAMES\n", displayModeCString, tile->width, tile->height, s->frame->fps, s->next_frame_time); /* TOREMOVE */ -#ifdef HAVE_MACOSX - displayModeCString = (char *) malloc(128); - CFStringGetCString(displayModeString, (char *) displayModeCString, 128, kCFStringEncodingMacRoman); -#elif defined WIN32 - displayModeCString = (char *) malloc(128); - wcstombs((char *) displayModeCString, displayModeString, 128); -#else - displayModeCString = displayModeString; -#endif printf("Enable video input: %s\n", displayModeCString); -#ifdef HAVE_MACOSX - CFRelease(displayModeString); -#endif + release_bmd_api_str(displayModeString); free((void *)displayModeCString); } @@ -736,27 +708,16 @@ vidcap_decklink_init(const struct vidcap_params *params) #endif - STRING current_version; + BMD_STR current_version; if(!blackmagic_api_version_check(¤t_version)) { fprintf(stderr, "\nThe DeckLink drivers may not be installed or are outdated.\n"); fprintf(stderr, "This UltraGrid version was compiled against DeckLink drivers %s. You should have at least this version.\n\n", BLACKMAGIC_DECKLINK_API_VERSION_STRING); fprintf(stderr, "Vendor download page is http://http://www.blackmagic-design.com/support/ \n"); if(current_version) { - const char *currentVersionCString; -#ifdef HAVE_MACOSX - currentVersionCString = (char *) malloc(128); - CFStringGetCString(current_version, (char *) currentVersionCString, 128, kCFStringEncodingMacRoman); -#elif defined WIN32 - currentVersionCString = (char *) malloc(128); - wcstombs((char *) currentVersionCString, current_version, 128); -#else - currentVersionCString = current_version; -#endif + const char *currentVersionCString = get_cstr_from_bmd_api_str(current_version); fprintf(stderr, "Currently installed version is: %s\n", currentVersionCString); -#ifdef HAVE_MACOSX - CFRelease(current_version); -#endif + release_bmd_api_str(current_version); free((void *)currentVersionCString); } else { fprintf(stderr, "No installed drivers detected\n"); @@ -872,34 +833,24 @@ vidcap_decklink_init(const struct vidcap_params *params) s->state[i].deckLink = deckLink; - STRING deviceNameString = NULL; + BMD_STR deviceNameString = NULL; const char* deviceNameCString = NULL; // Print the model name of the DeckLink card result = deckLink->GetModelName(&deviceNameString); if (result == S_OK) { -#ifdef HAVE_MACOSX - deviceNameCString = (char *) malloc(128); - CFStringGetCString(deviceNameString, (char *) deviceNameCString, 128, kCFStringEncodingMacRoman); + deviceNameCString = get_cstr_from_bmd_api_str(deviceNameString); -#elif defined WIN32 - deviceNameCString = (char *) malloc(128); - wcstombs((char *) deviceNameCString, deviceNameString, 128); -#else - deviceNameCString = deviceNameString; -#endif printf("Using device [%s]\n", deviceNameCString); -#ifdef HAVE_MACOSX - CFRelease(deviceNameString); -#endif + release_bmd_api_str(deviceNameString); free((void *) deviceNameCString); // Query the DeckLink for its configuration interface result = deckLink->QueryInterface(IID_IDeckLinkInput, (void**)&deckLinkInput); - string err_msg = bmd_hresult_to_string(result); if (result != S_OK) { + string err_msg = bmd_hresult_to_string(result); fprintf(stderr, "Could not obtain the IDeckLinkInput interface: %s\n", err_msg.c_str()); goto error; @@ -1165,8 +1116,8 @@ vidcap_decklink_done(void *state) if(s->grab_audio && i == 0) { result = s->state[i].deckLinkInput->DisableAudioInput(); - string err_msg = bmd_hresult_to_string(result); if (result != S_OK) { + string err_msg = bmd_hresult_to_string(result); fprintf(stderr, MODULE_NAME "Could disable audio input: %s\n", err_msg.c_str()); } } @@ -1444,20 +1395,11 @@ static void print_input_modes (IDeckLink* deckLink) printf("display modes:\n"); while (displayModeIterator->Next(&displayMode) == S_OK) { - STRING displayModeString = NULL; + BMD_STR displayModeString = NULL; const char *displayModeCString; - result = displayMode->GetName((STRING *) &displayModeString); -#ifdef HAVE_MACOSX - displayModeCString = (char *) malloc(128); - CFStringGetCString(displayModeString, (char *) displayModeCString, 128, kCFStringEncodingMacRoman); -#elif defined WIN32 - displayModeCString = (char *) malloc(128); - wcstombs((char *) displayModeCString, displayModeString, 128); -#else - displayModeCString = displayModeString; -#endif - + result = displayMode->GetName((BMD_STR *) &displayModeString); + displayModeCString = get_cstr_from_bmd_api_str(displayModeString); if (result == S_OK) { @@ -1476,9 +1418,7 @@ static void print_input_modes (IDeckLink* deckLink) printf("%d.) %-20s \t %d x %d \t %2.2f FPS%s\n",displayModeNumber, displayModeCString, modeWidth, modeHeight, (float) ((double)frameRateScale / (double)frameRateDuration), (flags & bmdDisplayModeSupports3D ? "\t (supports 3D)" : "")); -#ifdef HAVE_MACOSX - CFRelease(displayModeString); -#endif + release_bmd_api_str(displayModeString); free((void *)displayModeCString); } From 89995860f8abb1ce083c680fc4857ffe2678b843 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 12 Aug 2014 11:59:08 +0200 Subject: [PATCH 09/95] Quicktime: minor fix --- src/video_display/quicktime.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_display/quicktime.c b/src/video_display/quicktime.c index 05cac97b0..fd37f5b00 100644 --- a/src/video_display/quicktime.c +++ b/src/video_display/quicktime.c @@ -753,13 +753,13 @@ void *display_quicktime_init(const char *fmt, unsigned int flags) tile->height = (**gWorldImgDesc).height; tile->data_len = tile->height * - vc_get_linesize(tile->width, s->cinfo->codec); + vc_get_linesize(tile->width, s->codec); s->buffer[0] = calloc(1, tile->data_len); s->buffer[1] = calloc(1, tile->data_len); tile->data = s->buffer[0]; fprintf(stdout, "Selected mode: %dx%d, %fbpp\n", tile->width, - tile->height, s->cinfo->bpp); + tile->height, get_bpp(s->codec)); } reconf_common(s); } else { From a68fca82587b7937cae340c286aef8fcb1c9a000 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Wed, 13 Aug 2014 13:36:25 +0200 Subject: [PATCH 10/95] Fixed name of module register functions --- src/audio/codec/libavcodec.c | 4 ++-- src/capture_filter/resize.cpp | 4 ++-- src/video_rxtx/h264_rtp.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/audio/codec/libavcodec.c b/src/audio/codec/libavcodec.c index ba0cf6370..de86831c6 100644 --- a/src/audio/codec/libavcodec.c +++ b/src/audio/codec/libavcodec.c @@ -84,9 +84,9 @@ 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); } diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index 3a5725933..595dcdf95 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -185,9 +185,9 @@ static struct capture_filter_info capture_filter_resize = { filter, }; -static void init(void) __attribute__((constructor)); +static void register_module(void) __attribute__((constructor)); -static void init(void) +static void register_module(void) { register_video_capture_filter(&capture_filter_resize); } diff --git a/src/video_rxtx/h264_rtp.cpp b/src/video_rxtx/h264_rtp.cpp index fa04373dd..febb69665 100644 --- a/src/video_rxtx/h264_rtp.cpp +++ b/src/video_rxtx/h264_rtp.cpp @@ -92,9 +92,9 @@ video_rxtx *create_video_rxtx_h264_std(std::map const &par return new h264_rtp_video_rxtx(params); } -static void init(void) __attribute__((constructor)); +static void register_module(void) __attribute__((constructor)); -static void init(void) +static void register_module(void) { register_video_rxtx(H264_STD, {"H264 standard", create_video_rxtx_h264_std}); } From dc6b8e715808ffc692a02639f890428f81ce8b45 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 12 Aug 2014 12:53:10 +0200 Subject: [PATCH 11/95] Disable FEC decoding error message by default --- src/rtp/video_decoders.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtp/video_decoders.cpp b/src/rtp/video_decoders.cpp index 329af205b..b889a2dc5 100644 --- a/src/rtp/video_decoders.cpp +++ b/src/rtp/video_decoders.cpp @@ -374,7 +374,7 @@ static void *fec_thread(void *args) { if(fec_out_len == 0) { ret = FALSE; - fprintf(stderr, "[decoder] FEC: unable to reconstruct data.\n"); + verbose_msg("[decoder] FEC: unable to reconstruct data.\n"); decoder->fec_nok += 1; goto cleanup; } From 42504a39808fbb03ffb21cca96c4ea02ea973223 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 12 Aug 2014 15:55:19 +0200 Subject: [PATCH 12/95] Use C++ compiler for files using audio_frame2 --- Makefile.in | 2 +- src/audio/{audio.c => audio.cpp} | 18 +++++++++--------- src/audio/audio_playback.h | 7 +++++++ src/audio/capture/sdi.h | 7 +++++++ src/audio/{codec.c => codec.cpp} | 5 +---- src/audio/codec.h | 3 +-- .../codec/{libavcodec.c => libavcodec.cpp} | 13 ++++++++----- src/audio/echo.h | 7 +++++++ src/audio/export.h | 9 +++++++++ src/audio/playback/sdi.h | 7 +++++++ src/audio/{resampler.c => resampler.cpp} | 6 +++--- src/audio/resampler.h | 8 ++++++++ src/audio/{utils.c => utils.cpp} | 4 ++-- .../{audio_decoders.c => audio_decoders.cpp} | 0 src/{transmit.c => transmit.cpp} | 0 15 files changed, 70 insertions(+), 26 deletions(-) rename src/audio/{audio.c => audio.cpp} (97%) rename src/audio/{codec.c => codec.cpp} (98%) rename src/audio/codec/{libavcodec.c => libavcodec.cpp} (98%) rename src/audio/{resampler.c => resampler.cpp} (94%) rename src/audio/{utils.c => utils.cpp} (99%) rename src/rtp/{audio_decoders.c => audio_decoders.cpp} (100%) rename src/{transmit.c => transmit.cpp} (100%) diff --git a/Makefile.in b/Makefile.in index e13bd5812..b04a194d5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -45,7 +45,7 @@ uv_datadir = @datadir@/ultragrid/ # autogenerated headers GENERATED_HEADERS = @GENERATED_HEADERS@ -ALL_INCLUDES = $(wildcard src/*.h) $(wildcard src/*/*.h) +ALL_INCLUDES = $(wildcard src/*.h src/*/*.h src/*/*/*.h) OBJS = @OBJS@ \ src/blackmagic_common.o \ diff --git a/src/audio/audio.c b/src/audio/audio.cpp similarity index 97% rename from src/audio/audio.c rename to src/audio/audio.cpp index 3cb595b47..d68334757 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.cpp @@ -243,7 +243,7 @@ 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)); module_init_default(&s->mod); s->mod.priv_data = s; @@ -495,7 +495,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 +509,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 +520,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"); @@ -686,7 +686,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 +695,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; @@ -806,7 +806,7 @@ static void *audio_sender_thread(void *arg) 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); @@ -894,7 +894,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 +906,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); } 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/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/codec.c b/src/audio/codec.cpp similarity index 98% rename from src/audio/codec.c rename to src/audio/codec.cpp index 11358ffc1..45d1f5d02 100644 --- a/src/audio/codec.c +++ b/src/audio/codec.cpp @@ -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) { diff --git a/src/audio/codec.h b/src/audio/codec.h index a54705aea..426142e47 100644 --- a/src/audio/codec.h +++ b/src/audio/codec.h @@ -69,8 +69,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 diff --git a/src/audio/codec/libavcodec.c b/src/audio/codec/libavcodec.cpp similarity index 98% rename from src/audio/codec/libavcodec.c rename to src/audio/codec/libavcodec.cpp index de86831c6..b4162dcc9 100644 --- a/src/audio/codec/libavcodec.c +++ b/src/audio/codec/libavcodec.cpp @@ -54,11 +54,13 @@ #include "audio/codec/libavcodec.h" +extern "C" { #include #if LIBAVCODEC_VERSION_MAJOR >= 54 #include #endif #include +} #include "audio/audio.h" #include "audio/codec.h" @@ -92,7 +94,7 @@ static void register_module(void) } typedef struct { - int codec_id; + enum AVCodecID codec_id; } audio_codec_t_to_codec_id_mapping_t; static const audio_codec_t_to_codec_id_mapping_t mapping[] = @@ -140,7 +142,7 @@ 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; if(audio_codec <= sizeof(mapping) / sizeof(audio_codec_t_to_codec_id_mapping_t)) { codec_id = mapping[audio_codec].codec_id; @@ -155,7 +157,8 @@ static void *libavcodec_init(audio_codec_t audio_codec, audio_codec_direction_t 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 { @@ -191,8 +194,8 @@ static void *libavcodec_init(audio_codec_t audio_codec, audio_codec_direction_t 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; 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.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/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.cpp similarity index 94% rename from src/audio/resampler.c rename to src/audio/resampler.cpp index c9f6392ab..e227450dd 100644 --- a/src/audio/resampler.c +++ b/src/audio/resampler.cpp @@ -16,10 +16,10 @@ struct resampler struct resampler *resampler_init(int dst_sample_rate) { - struct resampler *s = calloc(1, sizeof(struct resampler)); + struct resampler *s = (struct resampler *) calloc(1, sizeof(struct resampler)); - s->resample_buffer = malloc(1024 * 1024); - s->muxed = malloc(1024 * 1024); + s->resample_buffer = (char *) malloc(1024 * 1024); + s->muxed = (char *) malloc(1024 * 1024); s->resampled = audio_frame2_init(); s->resample_to = dst_sample_rate; diff --git a/src/audio/resampler.h b/src/audio/resampler.h index 524a42582..e5a0084f8 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 *); +#ifdef __cplusplus +} +#endif + diff --git a/src/audio/utils.c b/src/audio/utils.cpp similarity index 99% rename from src/audio/utils.c rename to src/audio/utils.cpp index 3e4b45d76..cc3c93481 100644 --- a/src/audio/utils.c +++ b/src/audio/utils.cpp @@ -82,7 +82,7 @@ void audio_frame2_allocate(audio_frame2 *frame, int nr_channels, int max_size) frame->ch_count = nr_channels; for(int i = 0; i < nr_channels; ++i) { - frame->data[i] = malloc(max_size); + frame->data[i] = (char *) malloc(max_size); } } @@ -101,7 +101,7 @@ void audio_frame2_append(audio_frame2 *dest, audio_frame2 *src) 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); + dest->data[i] = (char *) realloc(dest->data[i], new_max_size); } } diff --git a/src/rtp/audio_decoders.c b/src/rtp/audio_decoders.cpp similarity index 100% rename from src/rtp/audio_decoders.c rename to src/rtp/audio_decoders.cpp diff --git a/src/transmit.c b/src/transmit.cpp similarity index 100% rename from src/transmit.c rename to src/transmit.cpp From cbd3ecc5ce9a0fdd86e43c34dd1798f013304cd8 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Fri, 8 Aug 2014 16:41:37 +0200 Subject: [PATCH 13/95] Fixed frame disposing in 'every' capture filter --- src/capture_filter/every.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/capture_filter/every.c b/src/capture_filter/every.c index 6d384644b..83e9f26eb 100644 --- a/src/capture_filter/every.c +++ b/src/capture_filter/every.c @@ -134,6 +134,7 @@ static struct video_frame *filter(void *state, struct video_frame *in) return s->frame; } else { s->current = (s->current + 1) % s->num; + VIDEO_FRAME_DISPOSE(in); return NULL; } } From 13b3555c0a8574f2aaf4fb851a17583c75ec011b Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 12 Aug 2014 17:15:14 +0200 Subject: [PATCH 14/95] Rewrite audio_frame2 to C++ class --- src/audio/audio.cpp | 48 ++-- src/audio/audio.h | 57 +++-- src/audio/codec.cpp | 69 +++--- src/audio/codec.h | 7 +- src/audio/codec/libavcodec.cpp | 38 +-- src/audio/playback/decklink.cpp | 8 - src/audio/resampler.cpp | 48 ++-- src/audio/utils.cpp | 247 ++++++++++++-------- src/audio/utils.h | 20 +- src/hd-rum-translator/hd-rum-decompress.cpp | 2 - src/hd-rum-translator/hd-rum-recompress.cpp | 2 - src/rtp/audio_decoders.cpp | 128 ++++------ src/rtsp/BasicRTSPOnlySubsession.hh | 8 - src/rtsp/c_basicRTSPOnlyServer.h | 8 - src/transmit.cpp | 64 ++--- src/transmit.h | 7 +- src/video_capture/decklink.cpp | 8 - src/video_capture/deltacast.cpp | 7 - src/video_capture/deltacast_dvi.cpp | 7 - src/video_display/decklink.cpp | 8 - src/video_display/deltacast.cpp | 8 - 21 files changed, 388 insertions(+), 411 deletions(-) diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index d68334757..f0b866ef0 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -305,7 +305,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(); @@ -431,7 +431,7 @@ error: module_done(&s->mod); } - audio_frame2_free(s->captured); + delete s->captured; audio_codec_done(s->audio_coder); free(s); @@ -481,7 +481,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); } @@ -773,10 +773,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 +785,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,7 +802,6 @@ 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)); @@ -831,35 +831,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; + 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; + 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 +866,6 @@ static void *audio_sender_thread(void *arg) } } - audio_frame2_free(buffer_new); if(resample_state.resampler) { speex_resampler_destroy(resample_state.resampler); } diff --git a/src/audio/audio.h b/src/audio/audio.h index b0e70dce8..42ea9d90c 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 { @@ -94,17 +88,6 @@ typedef struct audio_frame } audio_frame; -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 */ @@ -116,6 +99,46 @@ typedef struct struct module; +#ifdef __cplusplus +#include +#include +#include + +class audio_frame2 +{ +public: + audio_frame2(); + 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(); + audio_codec_t get_codec(); + const char *get_data(int channel); + size_t get_data_len(int channel); + int get_channel_count(); + int get_sample_count(); + int get_sample_rate(); + bool has_same_prop_as(audio_frame2 const &frame); +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; + int sample_count; ///< number of samples stored in this buffer + ///< assuming that all channels has same count... +}; +#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/codec.cpp b/src/audio/codec.cpp index 45d1f5d02..c7b5193c0 100644 --- a/src/audio/codec.cpp +++ b/src/audio/codec.cpp @@ -60,9 +60,7 @@ #include "lib_common.h" -#define MAX_AUDIO_CODECS 20 - -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 }, @@ -201,8 +199,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; } @@ -228,32 +225,39 @@ struct audio_codec_state *audio_codec_reconfigure(struct audio_codec_state *old, */ audio_frame2 *audio_codec_compress(struct audio_codec_state *s, 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) { + 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 (i == 0) { + if (frame) { + s->out->init(frame->get_channel_count(), s->codec, out->bps, out->sample_rate); + } else { + s->out->reset(); + } + } 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; } } @@ -267,41 +271,49 @@ 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) { + 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 (i == 0) { + s->out->init(frame->get_channel_count(), AC_PCM, out->bps, out->sample_rate); + } 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; } } @@ -318,10 +330,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); } diff --git a/src/audio/codec.h b/src/audio/codec.h index 426142e47..90925ab61 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, @@ -78,6 +75,7 @@ typedef struct { uint32_t tag; } audio_codec_info_t; +#ifdef __cplusplus extern audio_codec_info_t audio_codec_info[]; extern int audio_codec_info_len; @@ -100,9 +98,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.cpp b/src/audio/codec/libavcodec.cpp index b4162dcc9..65feffd51 100644 --- a/src/audio/codec/libavcodec.cpp +++ b/src/audio/codec/libavcodec.cpp @@ -62,6 +62,7 @@ extern "C" { #include } +#include #include "audio/audio.h" #include "audio/codec.h" #include "audio/utils.h" @@ -93,21 +94,16 @@ static void register_module(void) register_audio_codec(&libavcodec_audio_codec); } -typedef struct { - enum AVCodecID 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 { @@ -143,16 +139,17 @@ static void *libavcodec_init(audio_codec_t audio_codec, audio_codec_direction_t int bitrate) { 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(); @@ -472,9 +469,12 @@ static void libavcodec_done(void *state) 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 }, + .supported_codecs = supported_codecs, + .supported_bytes_per_second = supported_bytes_per_second, .init = libavcodec_init, .compress = libavcodec_compress, .decompress = libavcodec_decompress, diff --git a/src/audio/playback/decklink.cpp b/src/audio/playback/decklink.cpp index 64e35c146..846c3a411 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 diff --git a/src/audio/resampler.cpp b/src/audio/resampler.cpp index e227450dd..f5afe4432 100644 --- a/src/audio/resampler.cpp +++ b/src/audio/resampler.cpp @@ -20,7 +20,7 @@ struct resampler *resampler_init(int dst_sample_rate) s->resample_buffer = (char *) malloc(1024 * 1024); s->muxed = (char *) malloc(1024 * 1024); - s->resampled = audio_frame2_init(); + s->resampled = new audio_frame2; s->resample_to = dst_sample_rate; return s; @@ -30,62 +30,62 @@ void resampler_done(struct resampler *s) { free(s->resample_buffer); free(s->muxed); + delete s->resampled; free(s); } audio_frame2 *resampler_resample(struct resampler *s, audio_frame2 *frame) { - if(s->resample_to == frame->sample_rate) { + if(s->resample_to == frame->get_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); + s->resampled->init(frame->get_channel_count(), AC_PCM, 2, s->resample_to); 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->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->ch_count, s->resample_from, + 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->ch_count; ++i) { - mux_channel(s->muxed, frame->data[i], frame->bps, frame->data_len[i], - frame->ch_count, i, 1.0); + 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->data_len[0] * frame->ch_count; // uncompressed, so all channels + int data_len = frame->get_data_len(0) * frame->get_channel_count(); // uncompressed, so all channels // have the same size - if(frame->bps != 2) { - change_bps(s->resample_buffer, 2, s->muxed, frame->bps, + if(frame->get_bps() != 2) { + change_bps(s->resample_buffer, 2, s->muxed, frame->get_bps(), data_len); - data_len = data_len / frame->bps * 2; + data_len = data_len / frame->get_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 = 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->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); - + 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); } - s->resampled->sample_rate = s->resample_to; - s->resampled->bps = 2; } return s->resampled; diff --git a/src/audio/utils.cpp b/src/audio/utils.cpp index cc3c93481..2e9506237 100644 --- a/src/audio/utils.cpp +++ b/src/audio/utils.cpp @@ -66,69 +66,165 @@ #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) { - 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] = (char *) 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; +} + +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] = (char *) 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; + } +} + +int audio_frame2::get_bps() +{ + return bps; +} + +audio_codec_t audio_frame2::get_codec() +{ + return codec; +} + +const char *audio_frame2::get_data(int channel) +{ + return channels[channel].first.get(); +} + +size_t audio_frame2::get_data_len(int channel) +{ + return channels[channel].second; +} + +int audio_frame2::get_channel_count() +{ + return channels.size(); +} + +int audio_frame2::get_sample_count() +{ + if (channels.size() == 0) { + throw logic_error("zero channels!"); + } + + // for PCM, we can deduce samples count from length of the data + if (codec == AC_PCM) { + return channels[0].second / channels.size() / get_bps(); + } else { + throw logic_error("Unknown sample count for compressed audio!"); + } +} + +int audio_frame2::get_sample_rate() +{ + return sample_rate; +} + +bool audio_frame2::has_same_prop_as(audio_frame2 const &frame) { + return bps == frame.bps && + sample_rate == frame.sample_rate && + codec == frame.codec && + channels.size() == frame.channels.size(); +} + +static double get_normalized(const char *in, int bps) { int64_t sample = 0; bool negative = false; @@ -155,11 +251,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 +268,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 +279,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 && @@ -221,10 +295,10 @@ struct audio_desc audio_desc_from_audio_frame(struct audio_frame *frame) { } 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 (struct audio_desc) { .bps = frame->get_bps(), + .sample_rate = frame->get_sample_rate(), + .ch_count = frame->get_channel_count(), + .codec = frame->get_codec() }; } @@ -306,7 +380,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 +411,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; @@ -429,20 +503,11 @@ void signed2unsigned(char *out, char *in, int in_len) void audio_channel_demux(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 = (char *) 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..3bc9eb8e2 100644 --- a/src/audio/utils.h +++ b/src/audio/utils.h @@ -54,9 +54,6 @@ #include