diff --git a/.github/ci/Dockerfile b/.github/ci/Dockerfile index bd9ccfc2..be2a56f2 100644 --- a/.github/ci/Dockerfile +++ b/.github/ci/Dockerfile @@ -1,7 +1,7 @@ ARG DOCKER_ARCH ARG DEBIAN_VERSION ARG DOCKER_REPO -FROM --platform=linux/${DOCKER_ARCH} ${DOCKER_REPO}debian:${DEBIAN_VERSION} as build_env +FROM --platform=linux/${DOCKER_ARCH} ${DOCKER_REPO}debian:${DEBIAN_VERSION} AS build_env RUN apt-get -y update && apt-get -y install gnupg2 @@ -11,8 +11,9 @@ ARG BUILD_TYPE="generic" RUN [ "$BUILD_TYPE" != "raspi" ] || \ ( \ ( [ "$(dpkg --print-architecture)" != "armhf" ] || echo "deb http://raspbian.raspberrypi.org/raspbian/ $DEBIAN_VERSION main contrib non-free rpi" > /etc/apt/sources.list ) && \ + gpg --keyserver keyserver.ubuntu.com --recv-keys 9165938D90FDDD2E 82B129927FA3303E && \ + gpg --export 9165938D90FDDD2E 82B129927FA3303E > /etc/apt/trusted.gpg.d/raspi.gpg && \ echo "deb http://archive.raspberrypi.org/debian/ $DEBIAN_VERSION main" > /etc/apt/sources.list.d/raspi.list && \ - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 9165938D90FDDD2E 82B129927FA3303E && \ apt-get -y update && \ apt-get -y install libcamera-dev liblivemedia-dev \ ) @@ -21,14 +22,14 @@ RUN [ "$BUILD_TYPE" != "raspi" ] || \ RUN apt-get -y install build-essential xxd cmake ccache git-core pkg-config \ libavformat-dev libavutil-dev libavcodec-dev libssl-dev v4l-utils debhelper -FROM build_env as build +FROM build_env AS build ADD / /src WORKDIR /src RUN git clean -ffdx RUN git submodule update --init --recursive --recommend-shallow RUN git submodule foreach --recursive git clean -ffdx -FROM build as deb_make +FROM build AS deb_make ARG GIT_VERSION ARG BUILD_TYPE="generic" ENV DEB_BUILD_PROFILES="$BUILD_TYPE" diff --git a/.github/ci/arm32-cross b/.github/ci/arm32-cross new file mode 100755 index 00000000..8d5dc52f --- /dev/null +++ b/.github/ci/arm32-cross @@ -0,0 +1,6 @@ +#!/bin/bash + +apt install -y g{cc,++}-arm-linux-gnueabihf +export CC=arm-linux-gnueabihf-gcc +export CXX=arm-linux-gnueabihf-g++ +exec "$@" diff --git a/.github/ci/build-env b/.github/ci/build-env index 0163ad6b..44ff2be3 100755 --- a/.github/ci/build-env +++ b/.github/ci/build-env @@ -1,7 +1,7 @@ #!/bin/bash -if [[ $# -lt 3 ]]; then - echo "usage: $0 " +if [[ $# -lt 2 ]]; then + echo "usage: $0 [amd64|arm32v7|arm64v8] [cmdline args]" exit 1 fi @@ -9,12 +9,36 @@ docker_image="camera_streamer_build_env" build_type="raspi" [[ -n "$1" ]] && build_type="$1" +shift debian_version="bookworm" -[[ -n "$2" ]] && debian_version="$2" && docker_image="${docker_image}_${2}" - -docker_arch="" -[[ -n "$3" ]] && docker_arch="$3" && docker_image="${docker_image}_${3}" +[[ -n "$1" ]] && debian_version="$1" && docker_image="${docker_image}_${1}" +shift + +arch=${1:-$(dpkg --print-architecture)} +shift + +case "$arch" in + amd64) + docker_arch="amd64" + docker_repo="amd64/" + ;; + + armhf|arm32v7) + docker_arch="arm/v7" + docker_repo="arm32v7/" + ;; + + arm64|arm64v8) + docker_arch="arm64/v8" + docker_repo="arm64v8/" + ;; + + *) + echo "Unsupported architecture: $arch" + exit 1 + ;; +esac PWD=$(pwd) ROOT=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )/../.." &> /dev/null && pwd) @@ -23,8 +47,9 @@ set -xeo pipefail DOCKER_BUILDKIT=1 docker build -t "$docker_image" \ --build-arg "DOCKER_ARCH=$docker_arch" \ + --build-arg "DOCKER_REPO=$docker_repo" \ --build-arg "DEBIAN_VERSION=$debian_version" \ --build-arg "BUILD_TYPE=$build_type" \ --target build_env - < .github/ci/Dockerfile -exec docker run --rm -it -u "$UID" -e "CCACHE_DIR=$ROOT/tmp/ccache" -v "$ROOT:$ROOT" -w "$ROOT" "$docker_image" +exec docker run --rm -it -u "$UID" -e "CCACHE_DIR=$ROOT/tmp/ccache" -v "$ROOT:$ROOT" -w "$ROOT" "$docker_image" "$@" diff --git a/.github/workflows/build_release.yaml b/.github/workflows/build_release.yaml index 93556144..b2242b5c 100644 --- a/.github/workflows/build_release.yaml +++ b/.github/workflows/build_release.yaml @@ -8,7 +8,7 @@ jobs: contents: write strategy: matrix: - debian_version: [bullseye, bookworm] + debian_version: [bookworm, trixie] arch: - docker: amd64 runner: ubuntu-24.04 diff --git a/.github/workflows/build_test.yaml b/.github/workflows/build_test.yaml index 00f4482c..729c9d2d 100644 --- a/.github/workflows/build_test.yaml +++ b/.github/workflows/build_test.yaml @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - debian_version: [bullseye, bookworm] + debian_version: [bookworm, trixie] arch: - docker: amd64 variant: amd64 diff --git a/Makefile b/Makefile index 7c5290dd..0e9c5657 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ CFLAGS += -Wno-error=cpp # LOG_*(this, ...) CFLAGS += -Wno-error=nonnull-compare +CFLAGS += -Wno-nonnull-compare # libdatachannel deprecations on bookworm # error: 'HMAC_Init_ex' is deprecated: Since OpenSSL 3.0 @@ -24,6 +25,7 @@ CCACHE ?= ccache endif LIBDATACHANNEL_PATH ?= third_party/libdatachannel +LIBDATACHANNEL_VERSION ?= $(LIBDATACHANNEL_PATH)/v0.23.222529eb2c8ae44 USE_HW_H264 ?= 1 USE_FFMPEG ?= $(shell pkg-config libavutil libavformat libavcodec && echo 1) @@ -116,6 +118,10 @@ html/%.c: html/% xxd -i $< > $@.tmp mv $@.tmp $@ -$(LIBDATACHANNEL_PATH)/build/libdatachannel-static.a: $(LIBDATACHANNEL_PATH) +$(LIBDATACHANNEL_VERSION): + +$(LIBDATACHANNEL_PATH)/build/libdatachannel-static.a: $(LIBDATACHANNEL_PATH) $(LIBDATACHANNEL_VERSION) + git submodule update --init --recursive $(LIBDATACHANNEL_PATH) [ -e $ +#include #include #include @@ -36,12 +37,12 @@ int dummy_buffer_list_open(buffer_list_t *buf_list) buf_list->dummy->data = malloc(st.st_size); if (!buf_list->dummy->data) { - LOG_ERROR(buf_list, "Can't allocate %ld bytes for %s", st.st_size, buf_list->dev->path); + LOG_ERROR(buf_list, "Can't allocate %" PRId64 " bytes for %s", (off64_t)st.st_size, buf_list->dev->path); } buf_list->dummy->length = read(fd, buf_list->dummy->data, st.st_size); if (!buf_list->dummy->data) { - LOG_ERROR(buf_list, "Can't read %ld bytes for %s. Only read %zu.", st.st_size, buf_list->dev->path, buf_list->dummy->length); + LOG_ERROR(buf_list, "Can't read %" PRId64 " bytes for %s. Only read %zu.", (off64_t)st.st_size, buf_list->dev->path, buf_list->dummy->length); } close(fd); diff --git a/output/http_ffmpeg.c b/output/http_ffmpeg.c index bf5a7643..ac924ab4 100644 --- a/output/http_ffmpeg.c +++ b/output/http_ffmpeg.c @@ -49,7 +49,7 @@ static int http_ffmpeg_read_from_buf(void *opaque, uint8_t *buf, int buf_size) return buf_size; } -static int http_ffmpeg_write_to_stream(void *opaque, uint8_t *buf, int buf_size) +static int http_ffmpeg_write_to_stream(void *opaque, const uint8_t *buf, int buf_size) { http_ffmpeg_status_t *status = opaque; if (!status->stream) diff --git a/output/webrtc/webrtc.cc b/output/webrtc/webrtc.cc index 211c8332..05aff9ae 100644 --- a/output/webrtc/webrtc.cc +++ b/output/webrtc/webrtc.cc @@ -32,7 +32,6 @@ extern "C" { #include #include #include -#include #include #include "third_party/magic_enum/include/magic_enum.hpp" @@ -62,9 +61,6 @@ struct ClientTrackData void startStreaming() { - double currentTime_s = get_monotonic_time_us(NULL, NULL)/(1000.0*1000.0); - sender->rtpConfig->setStartTime(currentTime_s, rtc::RtpPacketizationConfig::EpochStart::T1970); - sender->startRecording(); } void sendTime() @@ -75,7 +71,7 @@ struct ClientTrackData uint32_t elapsedTimestamp = rtpConfig->secondsToTimestamp(currentTime_s); sender->rtpConfig->timestamp = sender->rtpConfig->startTimestamp + elapsedTimestamp; - auto reportElapsedTimestamp = sender->rtpConfig->timestamp - sender->previousReportedTimestamp; + auto reportElapsedTimestamp = sender->rtpConfig->timestamp - sender->lastReportedTimestamp(); if (sender->rtpConfig->timestampToSeconds(reportElapsedTimestamp) > 1) { sender->setNeedsToReport(); } @@ -248,14 +244,13 @@ static std::shared_ptr webrtc_add_video(const std::shared_ptraddTrack(video); - auto rtpConfig = std::make_shared(ssrc, cname, payloadType, rtc::H264RtpPacketizer::defaultClockRate); + auto rtpConfig = std::make_shared(ssrc, cname, payloadType, rtc::H264RtpPacketizer::ClockRate); auto packetizer = std::make_shared(rtc::H264RtpPacketizer::Separator::LongStartSequence, rtpConfig); - auto h264Handler = std::make_shared(packetizer); auto srReporter = std::make_shared(rtpConfig); - h264Handler->addToChain(srReporter); + packetizer->addToChain(srReporter); auto nackResponder = std::make_shared(); - h264Handler->addToChain(nackResponder); - track->setMediaHandler(h264Handler); + packetizer->addToChain(nackResponder); + track->setMediaHandler(packetizer); return std::shared_ptr(new ClientTrackData{track, srReporter}); } diff --git a/third_party/libdatachannel b/third_party/libdatachannel index 04cf4738..222529eb 160000 --- a/third_party/libdatachannel +++ b/third_party/libdatachannel @@ -1 +1 @@ -Subproject commit 04cf4738961f55ba3f0aa39b4a61342f66bb3781 +Subproject commit 222529eb2c8ae44f96462504ae38023f62809cec diff --git a/util/ffmpeg/remuxer.c b/util/ffmpeg/remuxer.c index 76b8c568..ca07544d 100644 --- a/util/ffmpeg/remuxer.c +++ b/util/ffmpeg/remuxer.c @@ -7,7 +7,13 @@ static AVRational time_base = {1, 1000LL * 1000LL}; static unsigned avio_ctx_buffer_size = 4096; -static int ffmpeg_remuxer_init_avcontext(AVFormatContext **context, ffmpeg_remuxer_t *remuxer, int output, int (*packet)(void *opaque, uint8_t *buf, int buf_size)) +#if LIBAVFORMAT_VERSION_MAJOR < 61 +typedef int (*ffmpeg_write_nonconst_packet)(void *opaque, uint8_t *buf, int buf_size); +#else // LIBAVFORMAT_VERSION_MAJOR < 61 +#define ffmpeg_write_nonconst_packet ffmpeg_write_packet +#endif // LIBAVFORMAT_VERSION_MAJOR < 61 + +static int ffmpeg_remuxer_init_avcontext(AVFormatContext **context, ffmpeg_remuxer_t *remuxer, int output, ffmpeg_write_packet packet_out, ffmpeg_read_packet packet_in) { uint8_t *buffer = NULL; AVIOContext *avio = NULL; @@ -20,7 +26,7 @@ static int ffmpeg_remuxer_init_avcontext(AVFormatContext **context, ffmpeg_remux buffer = av_malloc(buffer_size); if (!buffer) return AVERROR(ENOMEM); - avio = avio_alloc_context(buffer, buffer_size, output, remuxer->opaque, output ? NULL : packet, output ? packet : NULL, NULL); + avio = avio_alloc_context(buffer, buffer_size, output, remuxer->opaque, packet_in, (ffmpeg_write_nonconst_packet)packet_out, NULL); if (!avio) goto error; if (output && (ret = avformat_alloc_output_context2(context, NULL, remuxer->video_format, NULL)) < 0) @@ -106,9 +112,9 @@ int ffmpeg_remuxer_open(ffmpeg_remuxer_t *remuxer) remuxer->packet = av_packet_alloc(); if (!remuxer->packet) return AVERROR(ENOMEM); - if ((ret = ffmpeg_remuxer_init_avcontext(&remuxer->input_context, remuxer, 0, remuxer->read_packet)) < 0) + if ((ret = ffmpeg_remuxer_init_avcontext(&remuxer->input_context, remuxer, 0, NULL, remuxer->read_packet)) < 0) return ret; - if ((ret = ffmpeg_remuxer_init_avcontext(&remuxer->output_context, remuxer, 1, remuxer->write_packet)) < 0) + if ((ret = ffmpeg_remuxer_init_avcontext(&remuxer->output_context, remuxer, 1, remuxer->write_packet, NULL)) < 0) return ret; if ((ret = avformat_open_input(&remuxer->input_context, NULL, input_format, &remuxer->input_opts)) < 0) return ret; diff --git a/util/ffmpeg/remuxer.h b/util/ffmpeg/remuxer.h index 4a5c5a9e..872d2bb7 100644 --- a/util/ffmpeg/remuxer.h +++ b/util/ffmpeg/remuxer.h @@ -10,15 +10,16 @@ #define FFMPEG_DATA_PACKET_EOF -1 #endif -typedef int (*ffmpeg_data_packet)(void *opaque, uint8_t *buf, int buf_size); +typedef int (*ffmpeg_read_packet)(void *opaque, uint8_t *buf, int buf_size); +typedef int (*ffmpeg_write_packet)(void *opaque, const uint8_t *buf, int buf_size); typedef struct ffmpeg_remuxer_s { const char *name; const char *input_format; const char *video_format; void *opaque; - ffmpeg_data_packet read_packet; - ffmpeg_data_packet write_packet; + ffmpeg_read_packet read_packet; + ffmpeg_write_packet write_packet; unsigned read_buffer_size; unsigned write_buffer_size;