Skip to content

Commit

Permalink
pcaputil: Support parsing decoder options from FMTP input (#4205)
Browse files Browse the repository at this point in the history
Some codecs need specific flags that are given in the SDP media
description. For example, AMR has octet-align=1.

Instead of adding distinct flags for each codec, allow pcaputil
to accept the fmtp content and parse the attributes from there.

Example:
pcaputil \
  --dst-port=52422 \
  --codec=AMR/8000 \
  --codec-fmtp='mode-set=0,1,2,3,4,5,6,7;octet-align=1' \
  amr.pcap amr.wav
  • Loading branch information
orgads authored Dec 12, 2024
1 parent 85b38f4 commit 484c6b6
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
15 changes: 15 additions & 0 deletions pjmedia/include/pjmedia/stream_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,21 @@ PJ_DECL(pj_status_t) pjmedia_stream_info_parse_fmtp(pj_pool_t *pool,
pjmedia_codec_fmtp *fmtp);


/**
* This is an internal function for parsing fmtp data from a raw buffer.
*
* @param pool Pool to allocate memory, if pool is NULL, the fmtp
* string pointers will point to the original string.
* @param str The fmtp string to be parsed.
* @param fmtp The format parameter to store the parsing result.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_stream_info_parse_fmtp_data(pj_pool_t *pool,
const pj_str_t *str,
pjmedia_codec_fmtp *fmtp);


PJ_END_DECL


Expand Down
13 changes: 10 additions & 3 deletions pjmedia/src/pjmedia/stream_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_parse_fmtp( pj_pool_t *pool,
{
const pjmedia_sdp_attr *attr;
pjmedia_sdp_fmtp sdp_fmtp;
char *p, *p_end, fmt_buf[8];
char fmt_buf[8];
pj_str_t fmt;
pj_status_t status;

Expand All @@ -63,9 +63,16 @@ PJ_DEF(pj_status_t) pjmedia_stream_info_parse_fmtp( pj_pool_t *pool,
if (status != PJ_SUCCESS)
return status;

return pjmedia_stream_info_parse_fmtp_data(pool, &sdp_fmtp.fmt_param, fmtp);
}

PJ_DECL(pj_status_t) pjmedia_stream_info_parse_fmtp_data(pj_pool_t *pool,
const pj_str_t *str,
pjmedia_codec_fmtp *fmtp)
{
/* Prepare parsing */
p = sdp_fmtp.fmt_param.ptr;
p_end = p + sdp_fmtp.fmt_param.slen;
char *p = str->ptr;
char *p_end = p + str->slen;

/* Parse */
while (p < p_end) {
Expand Down
11 changes: 11 additions & 0 deletions pjsip-apps/src/samples/pcaputil.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ static const char *USAGE =
" AES_CM_128_HMAC_SHA1_80 \n"
" AES_CM_128_HMAC_SHA1_32\n"
" --srtp-key=KEY, -k Set the base64 key to decrypt SRTP packets.\n"
" --codec-fmtp=FMTP Set the fmtp input for parsing codec options.\n"
" For example: \"mode-set=0;octet-align=1\".\n"
#if PJMEDIA_HAS_OPUS_CODEC
" --opus-ch=CH Opus channel count \n"
" --opus-clock-rate=CR Opus clock rate \n"
Expand Down Expand Up @@ -93,6 +95,7 @@ struct args
pjmedia_aud_dev_index dev_id;
pj_str_t srtp_crypto;
pj_str_t srtp_key;
pj_str_t codec_fmtp;
#if PJMEDIA_HAS_OPUS_CODEC
int opus_clock_rate;
int opus_ch;
Expand Down Expand Up @@ -338,6 +341,9 @@ static void pcap2wav(const struct args *args)
ci = info[0];
}
T( pjmedia_codec_mgr_get_default_param(cmgr, ci, &param) );
if (args->codec_fmtp.slen > 0) {
T( pjmedia_stream_info_parse_fmtp_data(app.pool, &args->codec_fmtp, &param.setting.dec_fmtp) );
}

/* Alloc and init codec */
T( pjmedia_codec_mgr_alloc_codec(cmgr, ci, &app.codec) );
Expand Down Expand Up @@ -465,6 +471,7 @@ int main(int argc, char *argv[])
OPT_DST_PORT,
OPT_CODEC,
OPT_PLAY_DEV_ID,
OPT_CODEC_FMTP,
#if PJMEDIA_HAS_OPUS_CODEC
OPT_OPUS_CH = 'C',
OPT_OPUS_CLOCK_RATE = 'K',
Expand All @@ -481,6 +488,7 @@ int main(int argc, char *argv[])
{ "dst-port", 1, 0, OPT_DST_PORT },
{ "codec", 1, 0, OPT_CODEC },
{ "play-dev-id", 1, 0, OPT_PLAY_DEV_ID },
{ "codec-fmtp", 1, 0, OPT_CODEC_FMTP },
#if PJMEDIA_HAS_OPUS_CODEC
{ "opus-ch", 1, 0, OPT_OPUS_CH },
{ "opus-clock-rate", 1, 0, OPT_OPUS_CLOCK_RATE },
Expand Down Expand Up @@ -548,6 +556,9 @@ int main(int argc, char *argv[])
case OPT_PLAY_DEV_ID:
args.dev_id = atoi(pj_optarg);
break;
case OPT_CODEC_FMTP:
args.codec_fmtp = pj_str(pj_optarg);
break;
#if PJMEDIA_HAS_OPUS_CODEC
case OPT_OPUS_CLOCK_RATE:
args.opus_clock_rate = atoi(pj_optarg);
Expand Down

0 comments on commit 484c6b6

Please sign in to comment.