Add ability in stream to modify video codec bitrate on the fly (#3556)
This commit is contained in:
parent
022ce68be9
commit
e8f58dd6d6
|
@ -713,14 +713,15 @@ PJ_INLINE(pj_status_t) pjmedia_vid_codec_close( pjmedia_vid_codec *codec )
|
|||
|
||||
|
||||
/**
|
||||
* Modify the codec parameter after the codec is open.
|
||||
* Note that not all codec parameters can be modified during run-time.
|
||||
* When the parameter cannot be changed, this function will return
|
||||
* non-PJ_SUCCESS, and the original parameters will not be changed.
|
||||
* Modify the codec parameter after the codec is opened.
|
||||
* Note that not all codec backends support modifying parameters during
|
||||
* runtime and only certain parameters can be changed.
|
||||
*
|
||||
* Currently, only Video Toolbox and OpenH264 backends support runtime
|
||||
* adjustment of encoding bitrate (avg_bps and max_bps).
|
||||
*
|
||||
* @param codec The codec instance.
|
||||
* @param param The new codec parameter. Note that encoding video
|
||||
* codec resolution must be even numbers.
|
||||
* @param param The new codec parameter.
|
||||
*
|
||||
* @return PJ_SUCCESS on success, or the appropriate error code.
|
||||
*/
|
||||
|
|
|
@ -390,6 +390,24 @@ PJ_DECL(pj_status_t) pjmedia_vid_stream_get_info(
|
|||
PJ_DECL(pj_status_t) pjmedia_vid_stream_start(pjmedia_vid_stream *stream);
|
||||
|
||||
|
||||
/**
|
||||
* Modify the video stream's codec parameter after the codec is opened.
|
||||
* Note that not all codec backends support modifying parameters during
|
||||
* runtime and only certain parameters can be changed.
|
||||
*
|
||||
* Currently, only Video Toolbox and OpenH264 backends support runtime
|
||||
* adjustment of encoding bitrate (avg_bps and max_bps).
|
||||
*
|
||||
* @param stream The video stream.
|
||||
* @param param The new codec parameter.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t)
|
||||
pjmedia_vid_stream_modify_codec_param(pjmedia_vid_stream *stream,
|
||||
const pjmedia_vid_codec_param *param);
|
||||
|
||||
|
||||
/**
|
||||
* Query if the stream is started on the specified direction.
|
||||
*
|
||||
|
|
|
@ -631,10 +631,41 @@ static pj_status_t oh264_codec_close(pjmedia_vid_codec *codec)
|
|||
static pj_status_t oh264_codec_modify(pjmedia_vid_codec *codec,
|
||||
const pjmedia_vid_codec_param *param)
|
||||
{
|
||||
struct oh264_codec_data *oh264_data;
|
||||
int rc;
|
||||
SBitrateInfo bitrate;
|
||||
|
||||
PJ_ASSERT_RETURN(codec && param, PJ_EINVAL);
|
||||
PJ_UNUSED_ARG(codec);
|
||||
PJ_UNUSED_ARG(param);
|
||||
return PJ_EINVALIDOP;
|
||||
|
||||
oh264_data = (oh264_codec_data*) codec->codec_data;
|
||||
|
||||
bitrate.iLayer = SPATIAL_LAYER_ALL;
|
||||
bitrate.iBitrate = param->enc_fmt.det.vid.avg_bps;
|
||||
rc = oh264_data->enc->SetOption (ENCODER_OPTION_BITRATE, &bitrate);
|
||||
if (rc != cmResultSuccess) {
|
||||
PJ_LOG(4,(THIS_FILE, "OpenH264 encoder SetOption bitrate failed, "
|
||||
"rc=%d", rc));
|
||||
return PJMEDIA_CODEC_EUNSUP;
|
||||
}
|
||||
|
||||
oh264_data->prm->enc_fmt.det.vid.avg_bps = param->enc_fmt.det.vid.avg_bps;
|
||||
|
||||
bitrate.iBitrate = param->enc_fmt.det.vid.max_bps;
|
||||
rc = oh264_data->enc->SetOption (ENCODER_OPTION_MAX_BITRATE, &bitrate);
|
||||
if (rc != cmResultSuccess) {
|
||||
PJ_LOG(4,(THIS_FILE, "OpenH264 encoder SetOption max bitrate failed, "
|
||||
"rc=%d", rc));
|
||||
} else {
|
||||
oh264_data->prm->enc_fmt.det.vid.max_bps =
|
||||
param->enc_fmt.det.vid.max_bps;
|
||||
|
||||
PJ_LOG(4, (THIS_FILE, "OpenH264 encoder bitrate is modified to "
|
||||
"%d avg bps and %d max bps",
|
||||
param->enc_fmt.det.vid.avg_bps,
|
||||
param->enc_fmt.det.vid.max_bps));
|
||||
}
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
static pj_status_t oh264_codec_get_param(pjmedia_vid_codec *codec,
|
||||
|
@ -985,7 +1016,7 @@ static pj_status_t oh264_codec_decode(pjmedia_vid_codec *codec,
|
|||
pj_bool_t has_frame = PJ_FALSE;
|
||||
pj_bool_t kf_requested = PJ_FALSE;
|
||||
unsigned buf_pos, whole_len = 0;
|
||||
unsigned i, frm_cnt;
|
||||
unsigned i;
|
||||
pj_status_t status = PJ_SUCCESS;
|
||||
DECODING_STATE ret;
|
||||
|
||||
|
@ -1051,7 +1082,7 @@ static pj_status_t oh264_codec_decode(pjmedia_vid_codec *codec,
|
|||
* Step 2: parse the individual NAL and give to decoder
|
||||
*/
|
||||
buf_pos = 0;
|
||||
for ( frm_cnt=0; ; ++frm_cnt) {
|
||||
while (1) {
|
||||
unsigned frm_size;
|
||||
unsigned char *start;
|
||||
|
||||
|
|
|
@ -573,6 +573,11 @@ static OSStatus create_encoder(vtool_codec_data *vtool_data)
|
|||
|
||||
VTCompressionSessionPrepareToEncodeFrames(vtool_data->enc);
|
||||
|
||||
PJ_LOG(4, (THIS_FILE, "Video Toolbox encoder bitrate initialized to "
|
||||
"%d avg bps and %d max bps",
|
||||
param->enc_fmt.det.vid.avg_bps,
|
||||
param->enc_fmt.det.vid.max_bps));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -737,10 +742,36 @@ static pj_status_t vtool_codec_close(pjmedia_vid_codec *codec)
|
|||
static pj_status_t vtool_codec_modify(pjmedia_vid_codec *codec,
|
||||
const pjmedia_vid_codec_param *param)
|
||||
{
|
||||
struct vtool_codec_data *vtool_data;
|
||||
OSStatus ret;
|
||||
|
||||
PJ_ASSERT_RETURN(codec && param, PJ_EINVAL);
|
||||
PJ_UNUSED_ARG(codec);
|
||||
PJ_UNUSED_ARG(param);
|
||||
return PJ_EINVALIDOP;
|
||||
|
||||
vtool_data = (vtool_codec_data*) codec->codec_data;
|
||||
|
||||
SET_PROPERTY(vtool_data->enc,
|
||||
kVTCompressionPropertyKey_AverageBitRate,
|
||||
(__bridge CFTypeRef)@(param->enc_fmt.det.vid.avg_bps));
|
||||
if (ret != noErr)
|
||||
return PJMEDIA_CODEC_EUNSUP;
|
||||
|
||||
vtool_data->prm->enc_fmt.det.vid.avg_bps = param->enc_fmt.det.vid.avg_bps;
|
||||
|
||||
SET_PROPERTY(vtool_data->enc,
|
||||
kVTCompressionPropertyKey_DataRateLimits,
|
||||
((__bridge CFArrayRef) // [Bytes, second]
|
||||
@[@(param->enc_fmt.det.vid.max_bps >> 3), @(1)]));
|
||||
if (ret == noErr) {
|
||||
vtool_data->prm->enc_fmt.det.vid.max_bps =
|
||||
param->enc_fmt.det.vid.max_bps;
|
||||
|
||||
PJ_LOG(4, (THIS_FILE, "Video Toolbox encoder bitrate is modified to "
|
||||
"%d avg bps and %d max bps",
|
||||
param->enc_fmt.det.vid.avg_bps,
|
||||
param->enc_fmt.det.vid.max_bps));
|
||||
}
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
static pj_status_t vtool_codec_get_param(pjmedia_vid_codec *codec,
|
||||
|
@ -1127,7 +1158,7 @@ static pj_status_t vtool_codec_decode(pjmedia_vid_codec *codec,
|
|||
const int code_size = PJ_ARRAY_SIZE(start_code);
|
||||
pj_bool_t has_frame = PJ_FALSE;
|
||||
unsigned buf_pos, whole_len = 0;
|
||||
unsigned i, frm_cnt;
|
||||
unsigned i;
|
||||
pj_status_t status = PJ_SUCCESS;
|
||||
pj_bool_t decode_whole = DECODE_WHOLE;
|
||||
OSStatus ret;
|
||||
|
@ -1198,7 +1229,7 @@ static pj_status_t vtool_codec_decode(pjmedia_vid_codec *codec,
|
|||
* Step 2: parse the individual NAL and give to decoder
|
||||
*/
|
||||
buf_pos = 0;
|
||||
for ( frm_cnt=0; ; ++frm_cnt) {
|
||||
while (1) {
|
||||
uint32_t frm_size, nalu_type, data_length;
|
||||
unsigned char *start;
|
||||
|
||||
|
|
|
@ -2363,6 +2363,19 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_start(pjmedia_vid_stream *stream)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Modify codec parameter.
|
||||
*/
|
||||
PJ_DEF(pj_status_t)
|
||||
pjmedia_vid_stream_modify_codec_param(pjmedia_vid_stream *stream,
|
||||
const pjmedia_vid_codec_param *param)
|
||||
{
|
||||
PJ_ASSERT_RETURN(stream && param, PJ_EINVAL);
|
||||
|
||||
return pjmedia_vid_codec_modify(stream->codec, param);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check status.
|
||||
*/
|
||||
|
|
|
@ -6146,6 +6146,27 @@ PJ_DECL(pj_status_t) pjsua_call_set_vid_strm (
|
|||
pjsua_call_vid_strm_op op,
|
||||
const pjsua_call_vid_strm_op_param *param);
|
||||
|
||||
|
||||
/**
|
||||
* Modify the video stream's codec parameter after the codec is opened.
|
||||
* Note that not all codec backends support modifying parameters during
|
||||
* runtime and only certain parameters can be changed.
|
||||
*
|
||||
* Currently, only Video Toolbox and OpenH264 backends support runtime
|
||||
* adjustment of encoding bitrate (avg_bps and max_bps).
|
||||
*
|
||||
* @param call_id Call identification.
|
||||
* @param med_idx Video stream index.
|
||||
* @param param The new codec parameter.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t)
|
||||
pjsua_call_vid_stream_modify_codec_param(pjsua_call_id call_id,
|
||||
int med_idx,
|
||||
const pjmedia_vid_codec_param *param);
|
||||
|
||||
|
||||
/**
|
||||
* Modify the audio stream's codec parameter after the codec is opened.
|
||||
* Note that not all codec parameters can be modified during run-time.
|
||||
|
|
|
@ -1774,6 +1774,22 @@ public:
|
|||
void vidSetStream(pjsua_call_vid_strm_op op,
|
||||
const CallVidSetStreamParam ¶m) PJSUA2_THROW(Error);
|
||||
|
||||
/**
|
||||
* Modify the video stream's codec parameter after the codec is opened.
|
||||
* Note that not all codec backends support modifying parameters during
|
||||
* runtime and only certain parameters can be changed.
|
||||
*
|
||||
* Currently, only Video Toolbox and OpenH264 backends support runtime
|
||||
* adjustment of encoding bitrate (avg_bps and max_bps).
|
||||
*
|
||||
* @param med_idx Video stream index.
|
||||
* @param param The new codec parameter.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
void vidStreamModifyCodecParam(int med_idx, const VidCodecParam ¶m)
|
||||
PJSUA2_THROW(Error);
|
||||
|
||||
/**
|
||||
* Modify the audio stream's codec parameter after the codec is opened.
|
||||
* Note that not all codec parameters can be modified during run-time.
|
||||
|
|
|
@ -2718,6 +2718,43 @@ on_return:
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Modify video stream's codec parameters.
|
||||
*/
|
||||
PJ_DEF(pj_status_t)
|
||||
pjsua_call_vid_stream_modify_codec_param(pjsua_call_id call_id,
|
||||
int med_idx,
|
||||
const pjmedia_vid_codec_param *param)
|
||||
{
|
||||
pjsua_call *call;
|
||||
pjsua_call_media *call_med;
|
||||
pj_status_t status;
|
||||
|
||||
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls &&
|
||||
med_idx>=0 &&
|
||||
med_idx<(int)pjsua_var.calls[call_id].med_cnt && param,
|
||||
PJ_EINVAL);
|
||||
|
||||
PJSUA_LOCK();
|
||||
|
||||
/* Verify media index */
|
||||
call = &pjsua_var.calls[call_id];
|
||||
|
||||
/* Verify if the media is audio */
|
||||
call_med = &call->media[med_idx];
|
||||
if (call_med->type != PJMEDIA_TYPE_VIDEO || !call_med->strm.v.stream) {
|
||||
PJSUA_UNLOCK();
|
||||
return PJ_EINVALIDOP;
|
||||
}
|
||||
|
||||
status = pjmedia_vid_stream_modify_codec_param(call_med->strm.v.stream,
|
||||
param);
|
||||
|
||||
PJSUA_UNLOCK();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the media stream index of the default video stream in the call.
|
||||
*/
|
||||
|
|
|
@ -879,6 +879,20 @@ void Call::vidSetStream(pjsua_call_vid_strm_op op,
|
|||
#endif
|
||||
}
|
||||
|
||||
void Call::vidStreamModifyCodecParam(int med_idx, const VidCodecParam ¶m)
|
||||
PJSUA2_THROW(Error)
|
||||
{
|
||||
#if PJSUA_HAS_VIDEO
|
||||
pjmedia_vid_codec_param prm = param.toPj();
|
||||
PJSUA2_CHECK_EXPR( pjsua_call_vid_stream_modify_codec_param(id, med_idx,
|
||||
&prm) );
|
||||
#else
|
||||
PJ_UNUSED_ARG(med_idx);
|
||||
PJ_UNUSED_ARG(param);
|
||||
PJSUA2_RAISE_ERROR(PJ_EINVALIDOP);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Call::audStreamModifyCodecParam(int med_idx, const CodecParam ¶m)
|
||||
PJSUA2_THROW(Error)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue