Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions pjmedia/include/pjmedia-codec/ffmpeg_vid_codecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,27 @@ PJ_DECL(pj_status_t) pjmedia_codec_ffmpeg_vid_init(pjmedia_vid_codec_mgr *mgr,


/**
* Initialize and register intercom Video codec. This is dummy codec that pulls
* frames from the intercom camera subsystem process over TCP socket.
* Initialize and register intercom Video codec. This is a codec that pulls
* frames from the intercom camera subsystem process over a Unix domain socket.
*
* @param mgr The video codec manager instance (NULL for default).
* @param pf Pool factory.
* @param vstream_sock_path Path to the Unix domain socket for video frames.
* @param vstream_stream_num Stream number passed to test_encode for IDR requests.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_codec_intercom_vid_init(pjmedia_vid_codec_mgr *mgr,
pj_pool_factory *pf);
pj_pool_factory *pf,
const char *vstream_sock_path,
unsigned vstream_stream_num);

/**
* Unregister intercom video codec factory.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_codec_intercom_vid_deinit(void);

/**
* Unregister FFMPEG video codecs factory from the video codec manager and
Expand Down
72 changes: 45 additions & 27 deletions pjmedia/src/pjmedia-codec/intercom_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <stdio.h>
#include <string.h>

Expand All @@ -54,8 +53,6 @@
/* AVCodec H264 default PT */
#define AVC_H264_PT PJMEDIA_RTP_PT_H264_RSV3

#define INTERCOM_SUBSYSTEM_VSTREAM_VIDEO_PORT 20001

/* Prototypes for FFMPEG codecs factory */
static pj_status_t ffmpeg_test_alloc(pjmedia_vid_codec_factory *factory,
const pjmedia_vid_codec_info *id);
Expand Down Expand Up @@ -121,6 +118,8 @@ static struct ffmpeg_factory
pj_pool_factory *pf;
pj_pool_t *pool;
pj_mutex_t *mutex;
char vstream_sock_path[256];
unsigned vstream_stream_num;
} ffmpeg_factory;

typedef struct ffmpeg_codec_desc ffmpeg_codec_desc;
Expand Down Expand Up @@ -340,7 +339,9 @@ static void init_codec(pj_bool_t is_encoder,
*/
PJ_DEF(pj_status_t)
pjmedia_codec_intercom_vid_init(pjmedia_vid_codec_mgr *mgr,
pj_pool_factory *pf)
pj_pool_factory *pf,
const char *vstream_sock_path,
unsigned vstream_stream_num)
{
pj_pool_t *pool;
pj_status_t status;
Expand All @@ -356,11 +357,21 @@ pjmedia_codec_intercom_vid_init(pjmedia_vid_codec_mgr *mgr,
mgr = pjmedia_vid_codec_mgr_instance();
PJ_ASSERT_RETURN(mgr, PJ_EINVAL);

/* Validate required config — application must set these before pjsua_init() */
PJ_ASSERT_RETURN(vstream_sock_path && vstream_sock_path[0] != '\0', PJ_EINVAL);
PJ_ASSERT_RETURN(vstream_stream_num != (unsigned)-1, PJ_EINVAL);

/* Create FFMPEG codec factory. */
ffmpeg_factory.base.op = &ffmpeg_factory_op;
ffmpeg_factory.base.factory_data = NULL;
ffmpeg_factory.mgr = mgr;
ffmpeg_factory.pf = pf;
strncpy(ffmpeg_factory.vstream_sock_path, vstream_sock_path,
sizeof(ffmpeg_factory.vstream_sock_path) - 1);
ffmpeg_factory.vstream_sock_path[sizeof(ffmpeg_factory.vstream_sock_path) - 1] = '\0';
ffmpeg_factory.vstream_stream_num = vstream_stream_num;
PJ_LOG(3, (THIS_FILE, "intercom_vid_init: sock_path='%s' stream_num=%u",
ffmpeg_factory.vstream_sock_path, ffmpeg_factory.vstream_stream_num));

pool = pj_pool_create(pf, "ffmpeg codec factory", 256, 256, NULL);
if (!pool)
Expand Down Expand Up @@ -617,40 +628,40 @@ static pj_status_t ffmpeg_dealloc_codec(pjmedia_vid_codec_factory *factory,

/*
* Socket init
* connect to intercom subsystem ( process handling camera capture and encoding ) using TCP port.
* process sends video stream on multiple ports. ports of interest in this case is 20002 for Vstream
* Connect to intercom subsystem via Unix domain socket to receive video stream.
*/
static int socket_init()
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in servaddr;
int sockfd;

/* Ensure config was set — should have been caught at init, but guard here too */
if (ffmpeg_factory.vstream_sock_path[0] == '\0') {
PJ_LOG(1, (THIS_FILE, "socket_init: vstream_sock_path not configured"));
return -1;
}

sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un servaddr;
if (sockfd == -1)
{
PJ_LOG(3, (THIS_FILE, "message=\"socket creation failed... err: %s\"", strerror(errno)));
PJ_LOG(3, (THIS_FILE, "socket creation failed, err: %s", strerror(errno)));
return -1;
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
servaddr.sin_port = htons(INTERCOM_SUBSYSTEM_VSTREAM_VIDEO_PORT);

// This is purely for testing purposes to switch between SD and HD streams
// Keeping this commented for sometime, eventually will be removed
// FILE *fp = fopen("/tmp/stream_port", "r");
// if (fp != NULL)
// {
// PJ_LOG(3, (THIS_FILE, "failed to open /tmp/stream_port file, err: %s", strerror(errno)));
// char port[10];
// fgets(port, 10, fp);
// fclose(fp);
// servaddr.sin_port = htons(atoi(port));
// }
servaddr.sun_family = AF_UNIX;
strncpy(servaddr.sun_path, ffmpeg_factory.vstream_sock_path,
sizeof(servaddr.sun_path) - 1);

PJ_LOG(3, (THIS_FILE, "socket_init: connecting to '%s'",
ffmpeg_factory.vstream_sock_path));
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
{
PJ_LOG(3, (THIS_FILE, "connection with the server failed, port: %d, err: %s", servaddr.sin_port, strerror(errno)));
PJ_LOG(3, (THIS_FILE, "socket_init: connection to '%s' failed, err: %s",
ffmpeg_factory.vstream_sock_path, strerror(errno)));
return -1;
}
PJ_LOG(3, (THIS_FILE, "socket_init: connected to '%s'",
ffmpeg_factory.vstream_sock_path));
return sockfd;
}

Expand Down Expand Up @@ -884,7 +895,14 @@ static pj_status_t ffmpeg_codec_encode_begin(pjmedia_vid_codec *codec,
break;
}

system("test_encode --stream 2 --force-idr");
{
char idr_cmd[128];
snprintf(idr_cmd, sizeof(idr_cmd),
"test_encode --stream %u --force-idr",
ffmpeg_factory.vstream_stream_num);
PJ_LOG(3, (THIS_FILE, "requesting IDR: %s", idr_cmd));
system(idr_cmd);
Comment thread
darshan-verkada marked this conversation as resolved.
}
}

status = ffmpeg_codec_encode_more(codec, out_size, output, has_more);
Expand Down
24 changes: 24 additions & 0 deletions pjsip/include/pjsua-lib/pjsua.h
Original file line number Diff line number Diff line change
Expand Up @@ -7591,6 +7591,30 @@ struct pjsua_media_config
* will not work properly.
*/
void (*on_aud_prev_rec_frame)(pjmedia_frame *frame);

/**
* Unix socket path for the intercom video stream source.
* Only used when PJMEDIA_VERKADA_INTERCOM is defined.
*
* This field MUST be set by the application before calling pjsua_init().
* Leaving it empty (default) will cause pjmedia_codec_intercom_vid_init()
* to return PJ_EINVAL.
*
* Default: "" (empty — must be configured)
*/
char vstream_sock_path[256];

/**
* Stream number passed to test_encode when requesting a key frame.
* Only used when PJMEDIA_VERKADA_INTERCOM is defined.
*
* This field MUST be set by the application before calling pjsua_init().
* Leaving it at the default sentinel value will cause
* pjmedia_codec_intercom_vid_init() to return PJ_EINVAL.
*
* Default: (unsigned)-1 (sentinel — must be configured)
*/
unsigned vstream_stream_num;
};


Expand Down
24 changes: 24 additions & 0 deletions pjsip/include/pjsua2/endpoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1171,6 +1171,30 @@ struct MediaConfig : public PersistentObject
*/
bool vidPreviewEnableNative;

/**
* Unix socket path for the intercom video stream source.
* Only used when PJMEDIA_VERKADA_INTERCOM is defined.
*
* This field MUST be set by the application before calling libInit().
* Leaving it empty (default) will cause codec initialization to fail
* with PJ_EINVAL.
*
* Default: "" (empty — must be configured)
*/
string vstreamSockPath;

/**
* Stream number passed to test_encode when requesting a key frame.
* Only used when PJMEDIA_VERKADA_INTERCOM is defined.
*
* This field MUST be set by the application before calling libInit().
* Leaving it at the default sentinel value will cause codec
* initialization to fail with PJ_EINVAL.
*
* Default: (unsigned)-1 (sentinel — must be configured)
*/
unsigned vstreamStreamNum;

public:
/** Default constructor initialises with default values */
MediaConfig();
Expand Down
2 changes: 2 additions & 0 deletions pjsip/src/pjsua-lib/pjsua_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,8 @@ PJ_DEF(void) pjsua_media_config_default(pjsua_media_config *cfg)
pj_turn_sock_tls_cfg_default(&cfg->turn_tls_setting);
#endif
cfg->vid_preview_enable_native = PJ_TRUE;
cfg->vstream_sock_path[0] = '\0'; /* must be set by application */
cfg->vstream_stream_num = (unsigned)-1; /* sentinel; must be set by application */
}

/*****************************************************************************
Expand Down
4 changes: 3 additions & 1 deletion pjsip/src/pjsua-lib/pjsua_vid.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ pj_status_t pjsua_vid_subsys_init(void)
}
#endif
#else
status = pjmedia_codec_intercom_vid_init(NULL, &pjsua_var.cp.factory);
status = pjmedia_codec_intercom_vid_init(NULL, &pjsua_var.cp.factory,
pjsua_var.media_cfg.vstream_sock_path,
pjsua_var.media_cfg.vstream_stream_num);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Error initializing ffmpeg library", status);
goto on_error;
Expand Down
9 changes: 9 additions & 0 deletions pjsip/src/pjsua2/endpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,8 @@ void MediaConfig::fromPj(const pjsua_media_config &mc)
this->jbDiscardAlgo = mc.jb_discard_algo;
this->sndAutoCloseTime = mc.snd_auto_close_time;
this->vidPreviewEnableNative = PJ2BOOL(mc.vid_preview_enable_native);
this->vstreamSockPath = mc.vstream_sock_path;
this->vstreamStreamNum = mc.vstream_stream_num;
}

pjsua_media_config MediaConfig::toPj() const
Expand Down Expand Up @@ -489,6 +491,9 @@ pjsua_media_config MediaConfig::toPj() const
mcfg.jb_discard_algo = this->jbDiscardAlgo;
mcfg.snd_auto_close_time = this->sndAutoCloseTime;
mcfg.vid_preview_enable_native = this->vidPreviewEnableNative;
pj_ansi_strncpy(mcfg.vstream_sock_path, this->vstreamSockPath.c_str(),
sizeof(mcfg.vstream_sock_path) - 1);
mcfg.vstream_stream_num = this->vstreamStreamNum;

return mcfg;
}
Expand Down Expand Up @@ -522,6 +527,8 @@ void MediaConfig::readObject(const ContainerNode &node) PJSUA2_THROW(Error)
NODE_READ_INT ( this_node, sndAutoCloseTime);
NODE_READ_BOOL ( this_node, vidPreviewEnableNative);
NODE_READ_BOOL ( this_node, sndUseSwClock);
NODE_READ_STRING ( this_node, vstreamSockPath);
NODE_READ_UNSIGNED( this_node, vstreamStreamNum);
}

void MediaConfig::writeObject(ContainerNode &node) const PJSUA2_THROW(Error)
Expand Down Expand Up @@ -553,6 +560,8 @@ void MediaConfig::writeObject(ContainerNode &node) const PJSUA2_THROW(Error)
NODE_WRITE_INT ( this_node, sndAutoCloseTime);
NODE_WRITE_BOOL ( this_node, vidPreviewEnableNative);
NODE_WRITE_BOOL ( this_node, sndUseSwClock);
NODE_WRITE_STRING ( this_node, vstreamSockPath);
NODE_WRITE_UNSIGNED( this_node, vstreamStreamNum);
}

///////////////////////////////////////////////////////////////////////////////
Expand Down
Loading