From 484c6b6126d3922706938db4f2db33329f7f0cf3 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 12 Dec 2024 09:39:14 +0200 Subject: [PATCH] pcaputil: Support parsing decoder options from FMTP input (#4205) 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 --- pjmedia/include/pjmedia/stream_common.h | 15 +++++++++++++++ pjmedia/src/pjmedia/stream_common.c | 13 ++++++++++--- pjsip-apps/src/samples/pcaputil.c | 11 +++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/pjmedia/include/pjmedia/stream_common.h b/pjmedia/include/pjmedia/stream_common.h index 61a0c1708e..bcbd7a59be 100644 --- a/pjmedia/include/pjmedia/stream_common.h +++ b/pjmedia/include/pjmedia/stream_common.h @@ -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 diff --git a/pjmedia/src/pjmedia/stream_common.c b/pjmedia/src/pjmedia/stream_common.c index 75b5ac3957..95bb1a64fe 100644 --- a/pjmedia/src/pjmedia/stream_common.c +++ b/pjmedia/src/pjmedia/stream_common.c @@ -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; @@ -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) { diff --git a/pjsip-apps/src/samples/pcaputil.c b/pjsip-apps/src/samples/pcaputil.c index 0cb746c2dc..f87bd43dc3 100644 --- a/pjsip-apps/src/samples/pcaputil.c +++ b/pjsip-apps/src/samples/pcaputil.c @@ -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" @@ -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; @@ -338,6 +341,9 @@ static void pcap2wav(const struct args *args) ci = info[0]; } T( pjmedia_codec_mgr_get_default_param(cmgr, ci, ¶m) ); + if (args->codec_fmtp.slen > 0) { + T( pjmedia_stream_info_parse_fmtp_data(app.pool, &args->codec_fmtp, ¶m.setting.dec_fmtp) ); + } /* Alloc and init codec */ T( pjmedia_codec_mgr_alloc_codec(cmgr, ci, &app.codec) ); @@ -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', @@ -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 }, @@ -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);