mirror of https://github.com/OpenIPC/firmware.git
				
				
				
			
		
			
				
	
	
		
			885 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Diff
		
	
	
			
		
		
	
	
			885 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Diff
		
	
	
| diff -ruN a/modules/h264passcodec/avcodec.c b/modules/h264passcodec/avcodec.c
 | |
| --- a/modules/h264passcodec/avcodec.c	1970-01-01 03:00:00.000000000 +0300
 | |
| +++ b/modules/h264passcodec/avcodec.c	2023-01-30 12:10:57.054035500 +0300
 | |
| @@ -0,0 +1,119 @@
 | |
| +/**
 | |
| + * @file avcodec.c  Video codecs using libavcodec
 | |
| + *
 | |
| + * Copyright (C) 2010 - 2016 Alfred E. Heggestad
 | |
| + */
 | |
| +#include <re.h>
 | |
| +#include <rem.h>
 | |
| +#include <baresip.h>
 | |
| +#include "h26x.h"
 | |
| +#include "avcodec.h"
 | |
| +#include "defines.h"
 | |
| +
 | |
| +/**
 | |
| + * @defgroup avcodec avcodec
 | |
| + *
 | |
| + * Video codecs using libavcodec
 | |
| + *
 | |
| + * This module implements H.263, H.264 and H.265 video codecs
 | |
| + * using libavcodec from FFmpeg or libav projects.
 | |
| + *
 | |
| + *
 | |
| + * Config options:
 | |
| + *
 | |
| + \verbatim
 | |
| +      avcodec_h264enc  <NAME>  ; e.g. h264_nvenc, h264_videotoolbox
 | |
| +      avcodec_h264dec  <NAME>  ; e.g. h264_cuvid, h264_vda, h264_qsv
 | |
| + \endverbatim
 | |
| + *
 | |
| + * References:
 | |
| + *
 | |
| + *     http://ffmpeg.org
 | |
| + *
 | |
| + *     https://libav.org
 | |
| + *
 | |
| + *     RTP Payload Format for H.264 Video
 | |
| + *     https://tools.ietf.org/html/rfc6184
 | |
| + */
 | |
| +
 | |
| +
 | |
| +//const AVCodec *avcodec_h264enc;      /* optional; specified H.264 encoder */
 | |
| +//const AVCodec *avcodec_h264dec;      /* optional; specified H.264 decoder */
 | |
| +
 | |
| +
 | |
| +
 | |
| +int avcodec_resolve_codecid(const char *s)
 | |
| +{
 | |
| +	if (0 == str_casecmp(s, "H264"))
 | |
| +		return AV_CODEC_ID_H264;
 | |
| +	else
 | |
| +		return AV_CODEC_ID_NONE;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static struct vidcodec h264 = {
 | |
| +	.name      = "H264",
 | |
| +	.variant   = "packetization-mode=0",
 | |
| +	.encupdh   = avcodec_encode_update,
 | |
| +	.ench      = avcodec_encode,
 | |
| +	.decupdh   = NULL,
 | |
| +	.dech      = NULL,
 | |
| +	.fmtp_ench = avcodec_h264_fmtp_enc,
 | |
| +	.fmtp_cmph = avcodec_h264_fmtp_cmp,
 | |
| +	.packetizeh= avcodec_packetize,
 | |
| +};
 | |
| +
 | |
| +static struct vidcodec h264_1 = {
 | |
| +	.name      = "H264",
 | |
| +	.variant   = "packetization-mode=1",
 | |
| +	.encupdh   = avcodec_encode_update,
 | |
| +	.ench      = avcodec_encode,
 | |
| +	.decupdh   = NULL,
 | |
| +	.dech      = NULL,
 | |
| +	.fmtp_ench = avcodec_h264_fmtp_enc,
 | |
| +	.fmtp_cmph = avcodec_h264_fmtp_cmp,
 | |
| +	.packetizeh= avcodec_packetize,
 | |
| +};
 | |
| +
 | |
| +static int module_init(void)
 | |
| +{
 | |
| +	struct list *vidcodecl = baresip_vidcodecl();
 | |
| +	char h264enc[64] = "h264";
 | |
| +	char h264dec[64] = "h264";
 | |
| +
 | |
| +	conf_get_str(conf_cur(), "avcodec_h264enc", h264enc, sizeof(h264enc));
 | |
| +	conf_get_str(conf_cur(), "avcodec_h264dec", h264dec, sizeof(h264dec));
 | |
| +
 | |
| +    printf(">>>>>>>>>init h264passcodec\n");
 | |
| +    //register 
 | |
| +    vidcodec_register(vidcodecl, &h264);
 | |
| +    vidcodec_register(vidcodecl, &h264_1);
 | |
| +
 | |
| +/*
 | |
| +	if (avcodec_h264enc) {
 | |
| +		info("avcodec: using H.264 encoder '%s' -- %s\n",
 | |
| +		     avcodec_h264enc->name, avcodec_h264enc->long_name);
 | |
| +	}
 | |
| +	if (avcodec_h264dec) {
 | |
| +		info("avcodec: using H.264 decoder '%s' -- %s\n",
 | |
| +		     avcodec_h264dec->name, avcodec_h264dec->long_name);
 | |
| +	}
 | |
| +*/
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int module_close(void)
 | |
| +{
 | |
| +	vidcodec_unregister(&h264);
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +EXPORT_SYM const struct mod_export DECL_EXPORTS(h264passcodec) = {
 | |
| +	"h264passcodec",
 | |
| +	"codec",
 | |
| +	module_init,
 | |
| +	module_close
 | |
| +};
 | |
| diff -ruN a/modules/h264passcodec/avcodec.h b/modules/h264passcodec/avcodec.h
 | |
| --- a/modules/h264passcodec/avcodec.h	1970-01-01 03:00:00.000000000 +0300
 | |
| +++ b/modules/h264passcodec/avcodec.h	2023-01-27 21:19:26.141734000 +0300
 | |
| @@ -0,0 +1,43 @@
 | |
| +/**
 | |
| + * @file avcodec.h  Video codecs using libavcodec -- internal API
 | |
| + *
 | |
| + * Copyright (C) 2010 Alfred E. Heggestad
 | |
| + */
 | |
| +
 | |
| +
 | |
| +/*
 | |
| + * Encode
 | |
| + */
 | |
| +
 | |
| +struct videnc_state;
 | |
| +
 | |
| +int avcodec_encode_update(struct videnc_state **vesp,
 | |
| +			  const struct vidcodec *vc,
 | |
| +			  struct videnc_param *prm, const char *fmtp,
 | |
| +			  videnc_packet_h *pkth, void *arg);
 | |
| +int avcodec_encode(struct videnc_state *st, bool update,
 | |
| +		   const struct vidframe *frame, uint64_t timestamp);
 | |
| +int avcodec_packetize(struct videnc_state *st, const struct vidpacket *packet);
 | |
| +
 | |
| +
 | |
| +int avcodec_decode_update(struct viddec_state **vdsp,
 | |
| +			  const struct vidcodec *vc, const char *fmtp);
 | |
| +int avcodec_decode_h263(struct viddec_state *st, struct vidframe *frame,
 | |
| +		bool *intra, bool eof, uint16_t seq, struct mbuf *src);
 | |
| +int avcodec_decode_h264(struct viddec_state *st, struct vidframe *frame,
 | |
| +		bool *intra, bool eof, uint16_t seq, struct mbuf *src);
 | |
| +int avcodec_decode_h265(struct viddec_state *st, struct vidframe *frame,
 | |
| +			bool *intra, bool eof, uint16_t seq, struct mbuf *src);
 | |
| +
 | |
| +
 | |
| +int avcodec_resolve_codecid(const char *s);
 | |
| +
 | |
| +
 | |
| +/*
 | |
| + * SDP
 | |
| + */
 | |
| +
 | |
| +uint32_t h264_packetization_mode(const char *fmtp);
 | |
| +int avcodec_h264_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt,
 | |
| +		  bool offer, void *arg);
 | |
| +bool avcodec_h264_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *data);
 | |
| diff -ruN a/modules/h264passcodec/defines.h b/modules/h264passcodec/defines.h
 | |
| --- a/modules/h264passcodec/defines.h	1970-01-01 03:00:00.000000000 +0300
 | |
| +++ b/modules/h264passcodec/defines.h	2023-01-28 20:25:39.609698100 +0300
 | |
| @@ -0,0 +1,14 @@
 | |
| +#ifndef __DEFINES_H
 | |
| +#define __DEFINES_H
 | |
| +
 | |
| +//some defines from ffmpeg
 | |
| +
 | |
| +
 | |
| +//only used items have declared
 | |
| +enum AVCodecID {
 | |
| +    AV_CODEC_ID_NONE,
 | |
| +    AV_CODEC_ID_H264
 | |
| +};
 | |
| +
 | |
| +
 | |
| +#endif
 | |
| diff -ruN a/modules/h264passcodec/encode.c b/modules/h264passcodec/encode.c
 | |
| --- a/modules/h264passcodec/encode.c	1970-01-01 03:00:00.000000000 +0300
 | |
| +++ b/modules/h264passcodec/encode.c	2023-01-30 12:10:13.244035500 +0300
 | |
| @@ -0,0 +1,318 @@
 | |
| +/**
 | |
| + * @file avcodec/encode.c  Video codecs using libavcodec -- encoder
 | |
| + *
 | |
| + * Copyright (C) 2010 - 2013 Alfred E. Heggestad
 | |
| + * Copyright (C) 2021 by:
 | |
| + *     Media Magic Technologies <developer@mediamagictechnologies.com>
 | |
| + *     and Divus GmbH <developer@divus.eu>
 | |
| + */
 | |
| +#include <re.h>
 | |
| +#include <rem.h>
 | |
| +#include <baresip.h>
 | |
| +#include "h26x.h"
 | |
| +#include "avcodec.h"
 | |
| +#include "defines.h"
 | |
| +
 | |
| +
 | |
| +enum {
 | |
| +	KEYFRAME_INTERVAL = 10  /* Keyframes per second */
 | |
| +};
 | |
| +
 | |
| +
 | |
| +struct picsz {
 | |
| +	enum h263_fmt fmt;  /**< Picture size */
 | |
| +	uint8_t mpi;        /**< Minimum Picture Interval (1-32) */
 | |
| +};
 | |
| +
 | |
| +
 | |
| +struct videnc_state {
 | |
| +//	const AVCodec *codec;
 | |
| +//	AVCodecContext *ctx;
 | |
| +	struct mbuf *mb_frag;
 | |
| +	struct videnc_param encprm;
 | |
| +	struct vidsz encsize;
 | |
| +	enum vidfmt fmt;
 | |
| +	enum AVCodecID codec_id;
 | |
| +	videnc_packet_h *pkth;
 | |
| +	void *arg;
 | |
| +
 | |
| +	union {
 | |
| +		struct {
 | |
| +			struct picsz picszv[8];
 | |
| +			uint32_t picszn;
 | |
| +		} h263;
 | |
| +
 | |
| +		struct {
 | |
| +			uint32_t packetization_mode;
 | |
| +			uint32_t profile_idc;
 | |
| +			uint32_t profile_iop;
 | |
| +			uint32_t level_idc;
 | |
| +			uint32_t max_fs;
 | |
| +			uint32_t max_smbps;
 | |
| +		} h264;
 | |
| +	} u;
 | |
| +};
 | |
| +
 | |
| +
 | |
| +static void destructor(void *arg)
 | |
| +{
 | |
| +	struct videnc_state *st = arg;
 | |
| +
 | |
| +	mem_deref(st->mb_frag);
 | |
| +
 | |
| +//	if (st->ctx)
 | |
| +//		avcodec_free_context(&st->ctx);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int init_encoder(struct videnc_state *st, const char *name)
 | |
| +{
 | |
| +	/*
 | |
| +	 * Special handling of H.264 encoder
 | |
| +	 */
 | |
| +
 | |
| +    printf(">>>>>init encoder\n");
 | |
| +/*
 | |
| +	if (st->codec_id == AV_CODEC_ID_H264 && avcodec_h264enc) {
 | |
| +
 | |
| +		st->codec = avcodec_h264enc;
 | |
| +
 | |
| +		info("avcodec: h264 encoder activated\n");
 | |
| +
 | |
| +		return 0;
 | |
| +	}
 | |
| +
 | |
| +	st->codec = avcodec_find_encoder(st->codec_id);
 | |
| +	if (!st->codec)
 | |
| +		return ENOENT;
 | |
| +*/
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int open_encoder(struct videnc_state *st,
 | |
| +			const struct videnc_param *prm,
 | |
| +			const struct vidsz *size,
 | |
| +			int pix_fmt)
 | |
| +{
 | |
| +	int err = 0;
 | |
| +
 | |
| +    printf(">>>>>open encoder\n");
 | |
| +//	if (st->ctx)
 | |
| +//		avcodec_free_context(&st->ctx);
 | |
| +
 | |
| +//	st->ctx = avcodec_alloc_context3(st->codec);
 | |
| +//	if (!st->ctx) {
 | |
| +//		err = ENOMEM;
 | |
| +//		goto out;
 | |
| +//	}
 | |
| +
 | |
| +//	av_opt_set_defaults(st->ctx);
 | |
| +
 | |
| +/*	st->ctx->bit_rate  = prm->bitrate;
 | |
| +	st->ctx->width     = size->w;
 | |
| +	st->ctx->height    = size->h;
 | |
| +
 | |
| +    st->ctx->pix_fmt   = pix_fmt;
 | |
| +
 | |
| +	st->ctx->time_base.num = 1;
 | |
| +	st->ctx->time_base.den = prm->fps;
 | |
| +	st->ctx->gop_size = KEYFRAME_INTERVAL * prm->fps;
 | |
| +
 | |
| +	if (0 == str_cmp(st->codec->name, "h264")) {
 | |
| +
 | |
| +		av_opt_set(st->ctx->priv_data, "profile", "baseline", 0);
 | |
| +		av_opt_set(st->ctx->priv_data, "preset", "ultrafast", 0);
 | |
| +		av_opt_set(st->ctx->priv_data, "tune", "zerolatency", 0);
 | |
| +
 | |
| +		if (st->u.h264.packetization_mode == 0) {
 | |
| +			av_opt_set_int(st->ctx->priv_data,
 | |
| +				       "slice-max-size", prm->pktsize, 0);
 | |
| +		}
 | |
| +	}
 | |
| +*/
 | |
| +
 | |
| +	/* params to avoid libavcodec/x264 default preset error */
 | |
| +/*	if (st->codec_id == AV_CODEC_ID_H264) {
 | |
| +
 | |
| +    	av_opt_set(st->ctx->priv_data, "profile", "baseline", 0);
 | |
| +    }
 | |
| +
 | |
| +	st->ctx->me_range = 16;
 | |
| +	st->ctx->qmin = 10;
 | |
| +	st->ctx->qmax = 51;
 | |
| +	st->ctx->max_qdiff = 4;
 | |
| +
 | |
| +	if (avcodec_open2(st->ctx, st->codec, NULL) < 0) {
 | |
| +		err = ENOENT;
 | |
| +		goto out;
 | |
| +	}
 | |
| +*/
 | |
| +	st->encsize = *size;
 | |
| +
 | |
| + out:
 | |
| +	if (err) {
 | |
| +/*
 | |
| +		if (st->ctx)
 | |
| +			avcodec_free_context(&st->ctx);
 | |
| +*/
 | |
| +	}
 | |
| +
 | |
| +	return err;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int decode_sdpparam_h264(struct videnc_state *st, const struct pl *name,
 | |
| +                                const struct pl *val)
 | |
| +{
 | |
| +        if (0 == pl_strcasecmp(name, "packetization-mode")) {
 | |
| +                st->u.h264.packetization_mode = pl_u32(val);
 | |
| +
 | |
| +                if (st->u.h264.packetization_mode != 0 &&
 | |
| +                    st->u.h264.packetization_mode != 1 ) {
 | |
| +                        warning("avcodec: illegal packetization-mode %u\n",
 | |
| +                                st->u.h264.packetization_mode);
 | |
| +                        return EPROTO;
 | |
| +                }
 | |
| +        }
 | |
| +        else if (0 == pl_strcasecmp(name, "profile-level-id")) {
 | |
| +                struct pl prof = *val;
 | |
| +                if (prof.l != 6) {
 | |
| +                        warning("avcodec: invalid profile-level-id (%r)\n",
 | |
| +                                val);
 | |
| +                        return EPROTO;
 | |
| +                }
 | |
| +
 | |
| +                prof.l = 2;
 | |
| +                st->u.h264.profile_idc = pl_x32(&prof); prof.p += 2;
 | |
| +                st->u.h264.profile_iop = pl_x32(&prof); prof.p += 2;
 | |
| +                st->u.h264.level_idc   = pl_x32(&prof);
 | |
| +        }
 | |
| +        else if (0 == pl_strcasecmp(name, "max-fs")) {
 | |
| +                st->u.h264.max_fs = pl_u32(val);
 | |
| +        }
 | |
| +        else if (0 == pl_strcasecmp(name, "max-smbps")) {
 | |
| +                st->u.h264.max_smbps = pl_u32(val);
 | |
| +        }
 | |
| +
 | |
| +        return 0;
 | |
| +}
 | |
| +
 | |
| +static void param_handler(const struct pl *name, const struct pl *val,
 | |
| +              void *arg)
 | |
| +{
 | |
| +    struct videnc_state *st = arg;
 | |
| +
 | |
| +    if (st->codec_id == AV_CODEC_ID_H264)
 | |
| +        (void)decode_sdpparam_h264(st, name, val);
 | |
| +}
 | |
| +
 | |
| +int avcodec_encode_update(struct videnc_state **vesp,
 | |
| +                          const struct vidcodec *vc,
 | |
| +                          struct videnc_param *prm, const char *fmtp,
 | |
| +                          videnc_packet_h *pkth, void *arg)
 | |
| +{
 | |
| +        struct videnc_state *st;
 | |
| +        int err = 0;
 | |
| +
 | |
| +        if (!vesp || !vc || !prm || !pkth)
 | |
| +                return EINVAL;
 | |
| +
 | |
| +        if (*vesp)
 | |
| +                return 0;
 | |
| +
 | |
| +        st = mem_zalloc(sizeof(*st), destructor);
 | |
| +        if (!st)
 | |
| +                return ENOMEM;
 | |
| +
 | |
| +        st->encprm = *prm;
 | |
| +        st->pkth = pkth;
 | |
| +        st->arg = arg;
 | |
| +
 | |
| +        st->codec_id = avcodec_resolve_codecid(vc->name);
 | |
| +        if (st->codec_id == AV_CODEC_ID_NONE) {
 | |
| +                warning("avcodec: unknown encoder (%s)\n", vc->name);
 | |
| +                err = EINVAL;
 | |
| +                goto out;
 | |
| +        }
 | |
| +
 | |
| +        st->mb_frag = mbuf_alloc(1024);
 | |
| +        if (!st->mb_frag) {
 | |
| +                err = ENOMEM;
 | |
| +                goto out;
 | |
| +        }
 | |
| +
 | |
| +        st->fmt = -1;
 | |
| +
 | |
| +        err = init_encoder(st, vc->name);
 | |
| +        if (err) {
 | |
| +                warning("avcodec: %s: could not init encoder\n", vc->name);
 | |
| +                goto out;
 | |
| +        }
 | |
| +
 | |
| +        if (str_isset(fmtp)) {
 | |
| +                struct pl sdp_fmtp;
 | |
| +
 | |
| +                pl_set_str(&sdp_fmtp, fmtp);
 | |
| +
 | |
| +                fmt_param_apply(&sdp_fmtp, param_handler, st);
 | |
| +        }
 | |
| +
 | |
| +        debug("avcodec: video encoder %s: %.2f fps, %d bit/s, pktsize=%u\n",
 | |
| +              vc->name, prm->fps, prm->bitrate, prm->pktsize);
 | |
| +
 | |
| + out:
 | |
| +        if (err)
 | |
| +                mem_deref(st);
 | |
| +        else
 | |
| +                *vesp = st;
 | |
| +
 | |
| +        return err;
 | |
| +}
 | |
| +
 | |
| +int avcodec_encode(struct videnc_state *st, bool update,
 | |
| +           const struct vidframe *frame, uint64_t timestamp)
 | |
| +{
 | |
| +    printf("avcodec_encode\n");
 | |
| +    return 0;
 | |
| +}
 | |
| +
 | |
| +int avcodec_packetize(struct videnc_state *st, const struct vidpacket *packet)
 | |
| +{
 | |
| +	int err = 0;
 | |
| +	uint64_t ts;
 | |
| +	struct mbuf mb;
 | |
| +
 | |
| +    printf("packetize\n");
 | |
| +
 | |
| +	if (!st || !packet)
 | |
| +		return EINVAL;
 | |
| +
 | |
| +    printf("packetize1\n");
 | |
| +
 | |
| +	mb.buf = packet->buf;
 | |
| +	mb.pos = 0;
 | |
| +	mb.end = packet->size;
 | |
| +	mb.size = packet->size;
 | |
| +
 | |
| +	ts = video_calc_rtp_timestamp_fix(packet->timestamp);
 | |
| +
 | |
| +
 | |
| +	switch (st->codec_id) {
 | |
| +
 | |
| +	case AV_CODEC_ID_H264:
 | |
| +        {
 | |
| +		    err = h264_packetize(ts, packet->buf, packet->size,
 | |
| +				     st->encprm.pktsize,
 | |
| +				     st->pkth, st->arg);
 | |
| +            printf("h264_packetize size=%d encpktsize=%d, res=%d\n",packet->size, st->encprm.pktsize, err);
 | |
| +        }
 | |
| +		break;
 | |
| +
 | |
| +	default:
 | |
| +		err = EPROTO;
 | |
| +		break;
 | |
| +	}
 | |
| +
 | |
| +	return err;
 | |
| +}
 | |
| diff -ruN a/modules/h264passcodec/h26x.h b/modules/h264passcodec/h26x.h
 | |
| --- a/modules/h264passcodec/h26x.h	1970-01-01 03:00:00.000000000 +0300
 | |
| +++ b/modules/h264passcodec/h26x.h	2022-03-27 11:22:42.000000000 +0300
 | |
| @@ -0,0 +1,96 @@
 | |
| +/**
 | |
| + * @file h26x.h  Interface to H.26x video codecs
 | |
| + *
 | |
| + * Copyright (C) 2010 Alfred E. Heggestad
 | |
| + */
 | |
| +
 | |
| +
 | |
| +/*
 | |
| + * H.263
 | |
| + */
 | |
| +
 | |
| +
 | |
| +enum h263_mode {
 | |
| +	H263_MODE_A,
 | |
| +	H263_MODE_B,
 | |
| +	H263_MODE_C
 | |
| +};
 | |
| +
 | |
| +enum {
 | |
| +	H263_HDR_SIZE_MODEA = 4,
 | |
| +	H263_HDR_SIZE_MODEB = 8,
 | |
| +	H263_HDR_SIZE_MODEC = 12
 | |
| +};
 | |
| +
 | |
| +/** H.263 picture size format */
 | |
| +enum h263_fmt {
 | |
| +	H263_FMT_SQCIF = 1, /**<  128 x 96   */
 | |
| +	H263_FMT_QCIF  = 2, /**<  176 x 144  */
 | |
| +	H263_FMT_CIF   = 3, /**<  352 x 288  */
 | |
| +	H263_FMT_4CIF  = 4, /**<  704 x 576  */
 | |
| +	H263_FMT_16CIF = 5, /**< 1408 x 1152 */
 | |
| +	H263_FMT_OTHER = 7,
 | |
| +};
 | |
| +
 | |
| +/**
 | |
| + * H.263 Header defined in RFC 2190
 | |
| + */
 | |
| +struct h263_hdr {
 | |
| +
 | |
| +	/* common */
 | |
| +	unsigned f:1;      /**< 1 bit  - Flag; 0=mode A, 1=mode B/C         */
 | |
| +	unsigned p:1;      /**< 1 bit  - PB-frames, 0=mode B, 1=mode C      */
 | |
| +	unsigned sbit:3;   /**< 3 bits - Start Bit Position (SBIT)          */
 | |
| +	unsigned ebit:3;   /**< 3 bits - End Bit Position (EBIT)            */
 | |
| +	unsigned src:3;    /**< 3 bits - Source format                      */
 | |
| +
 | |
| +	/* mode A */
 | |
| +	unsigned i:1;      /**< 1 bit  - 0=intra-coded, 1=inter-coded       */
 | |
| +	unsigned u:1;      /**< 1 bit  - Unrestricted Motion Vector         */
 | |
| +	unsigned s:1;      /**< 1 bit  - Syntax-based Arithmetic Coding     */
 | |
| +	unsigned a:1;      /**< 1 bit  - Advanced Prediction option         */
 | |
| +	unsigned r:4;      /**< 4 bits - Reserved (zero)                    */
 | |
| +	unsigned dbq:2;    /**< 2 bits - DBQUANT                            */
 | |
| +	unsigned trb:3;    /**< 3 bits - Temporal Reference for B-frame     */
 | |
| +	unsigned tr:8;     /**< 8 bits - Temporal Reference for P-frame     */
 | |
| +
 | |
| +	/* mode B */
 | |
| +	unsigned quant:5; //=0 for GOB header
 | |
| +	unsigned gobn:5;  // gob number
 | |
| +	unsigned mba:9;   // address
 | |
| +	unsigned hmv1:7;  // horizontal motion vector
 | |
| +	unsigned vmv1:7;  // vertical motion vector
 | |
| +	unsigned hmv2:7;
 | |
| +	unsigned vmv2:7;
 | |
| +
 | |
| +
 | |
| +};
 | |
| +
 | |
| +enum {I_FRAME=0, P_FRAME=1};
 | |
| +
 | |
| +/** H.263 bit-stream header */
 | |
| +struct h263_strm {
 | |
| +	uint8_t psc[2];              /**< Picture Start Code (PSC)        */
 | |
| +
 | |
| +	uint8_t temp_ref;            /**< Temporal Reference              */
 | |
| +	unsigned split_scr:1;        /**< Split Screen Indicator          */
 | |
| +	unsigned doc_camera:1;       /**< Document Camera Indicator       */
 | |
| +	unsigned pic_frz_rel:1;      /**< Full Picture Freeze Release     */
 | |
| +	unsigned src_fmt:3;          /**< Source Format. 3=CIF            */
 | |
| +	unsigned pic_type:1;         /**< Picture Coding Type. 0=I, 1=P   */
 | |
| +	unsigned umv:1;              /**< Unrestricted Motion Vector mode */
 | |
| +	unsigned sac:1;              /**< Syntax-based Arithmetic Coding  */
 | |
| +	unsigned apm:1;              /**< Advanced Prediction mode        */
 | |
| +	unsigned pb:1;               /**< PB-frames mode                  */
 | |
| +	unsigned pquant:5;           /**< Quantizer Information           */
 | |
| +	unsigned cpm:1;              /**< Continuous Presence Multipoint  */
 | |
| +	unsigned pei:1;              /**< Extra Insertion Information     */
 | |
| +	/* H.263 bit-stream ... */
 | |
| +};
 | |
| +
 | |
| +int h263_hdr_encode(const struct h263_hdr *hdr, struct mbuf *mb);
 | |
| +int h263_hdr_decode(struct h263_hdr *hdr, struct mbuf *mb);
 | |
| +enum h263_mode h263_hdr_mode(const struct h263_hdr *hdr);
 | |
| +
 | |
| +int  h263_strm_decode(struct h263_strm *s, struct mbuf *mb);
 | |
| +void h263_hdr_copy_strm(struct h263_hdr *hdr, const struct h263_strm *s);
 | |
| diff -ruN a/modules/h264passcodec/module.mk b/modules/h264passcodec/module.mk
 | |
| --- a/modules/h264passcodec/module.mk	1970-01-01 03:00:00.000000000 +0300
 | |
| +++ b/modules/h264passcodec/module.mk	2023-01-27 21:27:00.501734000 +0300
 | |
| @@ -0,0 +1,14 @@
 | |
| +#
 | |
| +# module.mk
 | |
| +#
 | |
| +# Copyright (C) 2010 Alfred E. Heggestad
 | |
| +#
 | |
| +
 | |
| +MOD		:= h264passcodec
 | |
| +$(MOD)_SRCS	+= avcodec.c
 | |
| +$(MOD)_SRCS	+= encode.c
 | |
| +$(MOD)_SRCS	+= sdp.c
 | |
| +$(MOD)_CFLAGS	+= 
 | |
| +$(MOD)_LFLAGS	+= 
 | |
| +
 | |
| +include mk/mod.mk
 | |
| diff -ruN a/modules/h264passcodec/sdp.c b/modules/h264passcodec/sdp.c
 | |
| --- a/modules/h264passcodec/sdp.c	1970-01-01 03:00:00.000000000 +0300
 | |
| +++ b/modules/h264passcodec/sdp.c	2023-01-27 21:27:19.881734000 +0300
 | |
| @@ -0,0 +1,86 @@
 | |
| +/**
 | |
| + * @file avcodec/sdp.c  Video codecs using libavcodec -- SDP functions
 | |
| + *
 | |
| + * Copyright (C) 2010 Alfred E. Heggestad
 | |
| + * Copyright (C) 2021 by:
 | |
| + *     Media Magic Technologies <developer@mediamagictechnologies.com>
 | |
| + *     and Divus GmbH <developer@divus.eu>
 | |
| + */
 | |
| +
 | |
| +#include <re.h>
 | |
| +#include <baresip.h>
 | |
| +#include "avcodec.h"
 | |
| +
 | |
| +
 | |
| +static char profile_level_id[256] = "";
 | |
| +
 | |
| +
 | |
| +uint32_t h264_packetization_mode(const char *fmtp)
 | |
| +{
 | |
| +	struct pl pl, mode;
 | |
| +
 | |
| +	if (!fmtp)
 | |
| +		return 0;
 | |
| +
 | |
| +	pl_set_str(&pl, fmtp);
 | |
| +
 | |
| +	if (fmt_param_get(&pl, "packetization-mode", &mode))
 | |
| +		return pl_u32(&mode);
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +int avcodec_h264_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt,
 | |
| +			  bool offer, void *arg)
 | |
| +{
 | |
| +	struct vidcodec *vc = arg;
 | |
| +	uint8_t profile_idc = 0x42; /* baseline profile */
 | |
| +	uint8_t profile_iop = 0xe0;
 | |
| +	uint8_t h264_level_idc = 0x1f;
 | |
| +	(void)offer;
 | |
| +
 | |
| +	if (!mb || !fmt || !vc)
 | |
| +		return 0;
 | |
| +
 | |
| +	conf_get_str(conf_cur(), "avcodec_profile_level_id",
 | |
| +		     profile_level_id, sizeof(profile_level_id));
 | |
| +
 | |
| +	if (str_isset(profile_level_id)) {
 | |
| +		struct pl prof;
 | |
| +
 | |
| +		pl_set_str(&prof, profile_level_id);
 | |
| +		if (prof.l != 6) {
 | |
| +			warning("avcodec: invalid profile_level_id"
 | |
| +				" (%r) using default\n",
 | |
| +				profile_level_id);
 | |
| +			goto out;
 | |
| +		}
 | |
| +
 | |
| +		prof.l = 2;
 | |
| +		profile_idc    = pl_x32(&prof); prof.p += 2;
 | |
| +		profile_iop    = pl_x32(&prof); prof.p += 2;
 | |
| +		h264_level_idc = pl_x32(&prof);
 | |
| +	}
 | |
| +
 | |
| + out:
 | |
| +	return mbuf_printf(mb, "a=fmtp:%s"
 | |
| +			   " %s"
 | |
| +			   ";profile-level-id=%02x%02x%02x"
 | |
| +			   "\r\n",
 | |
| +			   fmt->id, vc->variant,
 | |
| +			   profile_idc, profile_iop, h264_level_idc);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +bool avcodec_h264_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg)
 | |
| +{
 | |
| +	const struct vidcodec *vc = arg;
 | |
| +	(void)lfmtp;
 | |
| +
 | |
| +	if (!vc)
 | |
| +		return false;
 | |
| +
 | |
| +	return h264_packetization_mode(vc->variant) ==
 | |
| +		h264_packetization_mode(rfmtp);
 | |
| +}
 | |
| diff -ruN a/modules/menu/dynamic_menu.c b/modules/menu/dynamic_menu.c
 | |
| --- a/modules/menu/dynamic_menu.c	2022-03-27 11:22:42.000000000 +0300
 | |
| +++ b/modules/menu/dynamic_menu.c	2023-01-26 19:14:52.915866100 +0300
 | |
| @@ -355,8 +355,8 @@
 | |
|  	if (!pl_isset(&argdir[1]))
 | |
|  		argdir[1] = argdir[0];
 | |
|  
 | |
| -	adir = sdp_dir_decode(&argdir[0]);
 | |
| -	vdir = sdp_dir_decode(&argdir[1]);
 | |
| +	adir = decode_sdp_enum(&argdir[0]);
 | |
| +	vdir = decode_sdp_enum(&argdir[1]);
 | |
|  	if (adir == SDP_INACTIVE && vdir == SDP_INACTIVE) {
 | |
|  		(void) re_hprintf(pf, "%s", usage);
 | |
|  		return EINVAL;
 | |
| diff -ruN a/modules/menu/menu.c b/modules/menu/menu.c
 | |
| --- a/modules/menu/menu.c	2022-03-27 11:22:42.000000000 +0300
 | |
| +++ b/modules/menu/menu.c	2023-01-26 19:17:29.575866100 +0300
 | |
| @@ -928,6 +928,20 @@
 | |
|  	return 0;
 | |
|  }
 | |
|  
 | |
| +enum sdp_dir decode_sdp_enum(const struct pl *pl)
 | |
| +{
 | |
| +    if (!pl_strcmp(pl, "inactive")) {
 | |
| +        return SDP_INACTIVE;
 | |
| +    }
 | |
| +    else if (!pl_strcmp(pl, "sendonly")) {
 | |
| +        return  SDP_SENDONLY;
 | |
| +    }
 | |
| +    else if (!pl_strcmp(pl, "recvonly")) {
 | |
| +        return SDP_RECVONLY;
 | |
| +    }
 | |
| +
 | |
| +    return SDP_SENDRECV;
 | |
| +}
 | |
|  
 | |
|  static int module_init(void)
 | |
|  {
 | |
| diff -ruN a/modules/menu/static_menu.c b/modules/menu/static_menu.c
 | |
| --- a/modules/menu/static_menu.c	2022-03-27 11:22:42.000000000 +0300
 | |
| +++ b/modules/menu/static_menu.c	2023-01-26 19:15:56.745866100 +0300
 | |
| @@ -136,8 +136,8 @@
 | |
|  	if (!pl_isset(&argdir[1]))
 | |
|  		argdir[1] = argdir[0];
 | |
|  
 | |
| -	adir = sdp_dir_decode(&argdir[0]);
 | |
| -	vdir = sdp_dir_decode(&argdir[1]);
 | |
| +	adir = decode_sdp_enum(&argdir[0]);
 | |
| +	vdir = decode_sdp_enum(&argdir[1]);
 | |
|  
 | |
|  	if (adir == SDP_INACTIVE && vdir == SDP_INACTIVE) {
 | |
|  		(void) re_hprintf(pf, "%s", usage);
 | |
| @@ -541,8 +541,8 @@
 | |
|  	if (!pl_isset(&argdir[1]))
 | |
|  		argdir[1] = argdir[0];
 | |
|  
 | |
| -	adir = sdp_dir_decode(&argdir[0]);
 | |
| -	vdir = sdp_dir_decode(&argdir[1]);
 | |
| +	adir = decode_sdp_enum(&argdir[0]);
 | |
| +	vdir = decode_sdp_enum(&argdir[1]);
 | |
|  
 | |
|  	if (adir == SDP_INACTIVE && vdir == SDP_INACTIVE) {
 | |
|  		(void)re_hprintf(pf, "%s", usage);
 | |
| diff -ruN a/src/audio.c b/src/audio.c
 | |
| --- a/src/audio.c	2022-03-27 11:22:42.000000000 +0300
 | |
| +++ b/src/audio.c	2023-01-26 16:16:07.045866100 +0300
 | |
| @@ -1,3 +1,4 @@
 | |
| +#define _POSIX_C_SOURCE 200809L
 | |
|  /**
 | |
|   * @file src/audio.c  Audio stream
 | |
|   *
 | |
| diff -ruN a/src/main.c b/src/main.c
 | |
| --- a/src/main.c	2022-03-27 11:22:42.000000000 +0300
 | |
| +++ b/src/main.c	2023-01-26 18:49:09.115866100 +0300
 | |
| @@ -13,6 +13,7 @@
 | |
|  #include <re.h>
 | |
|  #include <baresip.h>
 | |
|  
 | |
| +int verbose=0;
 | |
|  
 | |
|  static void signal_handler(int sig)
 | |
|  {
 | |
| diff -ruN a/src/sdp.c b/src/sdp.c
 | |
| --- a/src/sdp.c	2022-03-27 11:22:42.000000000 +0300
 | |
| +++ b/src/sdp.c	2023-01-28 18:44:16.019698100 +0300
 | |
| @@ -63,8 +63,18 @@
 | |
|  	bool has;
 | |
|  
 | |
|  	has = sdp_media_rformat(m, NULL) != NULL;
 | |
| +
 | |
| +    if( !has )
 | |
| +        info("has_media: no codecs\n");
 | |
| +
 | |
|  	if (has)
 | |
| -		return sdp_media_rport(m) != 0;
 | |
| +    {
 | |
| +		has = sdp_media_rport(m);
 | |
| +        if( !has )
 | |
| +            info("has_media: no rport\n");
 | |
| +        return has != 0 ;
 | |
| +    }
 | |
| +
 | |
|  
 | |
|  	return false;
 | |
|  }
 | |
| diff -ruN a/src/stream.c b/src/stream.c
 | |
| --- a/src/stream.c	2022-03-27 11:22:42.000000000 +0300
 | |
| +++ b/src/stream.c	2023-01-28 18:25:24.999698100 +0300
 | |
| @@ -1029,6 +1029,7 @@
 | |
|  	s->tx.pt_enc = fmt ? fmt->pt : -1;
 | |
|  
 | |
|  	if (sdp_media_has_media(s->sdp)) {
 | |
| +        info("stream: has media\n");
 | |
|  
 | |
|  		if (bundle_state(s->bundle) == BUNDLE_MUX) {
 | |
|  
 | |
| @@ -1043,6 +1044,10 @@
 | |
|  			bundle_handle_extmap(s->bundle, s->sdp);
 | |
|  		}
 | |
|  	}
 | |
| +    else
 | |
| +    {
 | |
| +        info("stream: has no media\n");
 | |
| +    }
 | |
|  
 | |
|  	if (s->mencs && mnat_ready(s)) {
 | |
|  
 | |
| diff -ruN a/src/video.c b/src/video.c
 | |
| --- a/src/video.c	2022-03-27 11:22:42.000000000 +0300
 | |
| +++ b/src/video.c	2023-01-28 20:42:26.409698100 +0300
 | |
| @@ -1169,12 +1169,18 @@
 | |
|  
 | |
|  	if (sc) {
 | |
|  		if (dir & SDP_SENDONLY)
 | |
| +        {
 | |
|  			err = video_encoder_set(v, sc->data, sc->pt,
 | |
|  				sc->params);
 | |
| +        	debug("video: sendonly\n");
 | |
| +        }
 | |
|  
 | |
|  		if (dir & SDP_RECVONLY)
 | |
| +        {
 | |
|  			err |= video_decoder_set(v, sc->data, sc->pt,
 | |
|  				sc->rparams);
 | |
| +           	debug("video: recvonly\n");
 | |
| +        }
 | |
|  
 | |
|  		/* Stop / Start source & display*/
 | |
|  		if (dir & SDP_SENDONLY)
 | |
| @@ -1220,10 +1226,16 @@
 | |
|  	int err;
 | |
|  
 | |
|  	if (!v)
 | |
| +    {
 | |
| +        printf("video_start_source EINVAL");
 | |
|  		return EINVAL;
 | |
| +    }
 | |
|  
 | |
|  	if (v->vtx.vsrc)
 | |
| +    {
 | |
| +        printf("vsrc is set, return\n");
 | |
|  		return 0;
 | |
| +    }
 | |
|  
 | |
|  	debug("video: start source\n");
 | |
|  
 |