|
|
|
@ -37,6 +37,7 @@ typedef struct SVCContext { |
|
|
|
|
int slice_mode; |
|
|
|
|
int loopfilter; |
|
|
|
|
char *profile; |
|
|
|
|
int max_nal_size; |
|
|
|
|
} SVCContext; |
|
|
|
|
|
|
|
|
|
#define OPENH264_VER_AT_LEAST(maj, min) \ |
|
|
|
@ -50,8 +51,10 @@ static const AVOption options[] = { |
|
|
|
|
{ "fixed", "a fixed number of slices", 0, AV_OPT_TYPE_CONST, { .i64 = SM_FIXEDSLCNUM_SLICE }, 0, 0, VE, "slice_mode" }, |
|
|
|
|
{ "rowmb", "one slice per row of macroblocks", 0, AV_OPT_TYPE_CONST, { .i64 = SM_ROWMB_SLICE }, 0, 0, VE, "slice_mode" }, |
|
|
|
|
{ "auto", "automatic number of slices according to number of threads", 0, AV_OPT_TYPE_CONST, { .i64 = SM_AUTO_SLICE }, 0, 0, VE, "slice_mode" }, |
|
|
|
|
{ "dyn", "Dynamic slicing", 0, AV_OPT_TYPE_CONST, { .i64 = SM_DYN_SLICE }, 0, 0, VE, "slice_mode" }, |
|
|
|
|
{ "loopfilter", "enable loop filter", OFFSET(loopfilter), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, |
|
|
|
|
{ "profile", "set profile restrictions", OFFSET(profile), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, |
|
|
|
|
{ "max_nal_size", "Set maximum NAL size in bytes", OFFSET(max_nal_size), AV_OPT_TYPE_INT, { 0 }, 0, INT_MAX, VE }, |
|
|
|
|
{ NULL } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -165,11 +168,36 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) |
|
|
|
|
param.sSpatialLayers[0].iSpatialBitrate = param.iTargetBitrate; |
|
|
|
|
param.sSpatialLayers[0].iMaxSpatialBitrate = param.iMaxBitrate; |
|
|
|
|
|
|
|
|
|
if ((avctx->slices > 1) && (s->max_nal_size)){ |
|
|
|
|
av_log(avctx,AV_LOG_ERROR,"Invalid combination -slices %d and -max_nal_size %d.\n",avctx->slices,s->max_nal_size); |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (avctx->slices > 1) |
|
|
|
|
s->slice_mode = SM_FIXEDSLCNUM_SLICE; |
|
|
|
|
|
|
|
|
|
if (s->max_nal_size) |
|
|
|
|
s->slice_mode = SM_DYN_SLICE; |
|
|
|
|
|
|
|
|
|
param.sSpatialLayers[0].sSliceCfg.uiSliceMode = s->slice_mode; |
|
|
|
|
param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = avctx->slices; |
|
|
|
|
|
|
|
|
|
if (s->slice_mode == SM_DYN_SLICE) { |
|
|
|
|
if (s->max_nal_size){ |
|
|
|
|
param.uiMaxNalSize = s->max_nal_size; |
|
|
|
|
param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = s->max_nal_size; |
|
|
|
|
} else { |
|
|
|
|
if (avctx->rtp_payload_size) { |
|
|
|
|
av_log(avctx,AV_LOG_DEBUG,"Using RTP Payload size for uiMaxNalSize"); |
|
|
|
|
param.uiMaxNalSize = avctx->rtp_payload_size; |
|
|
|
|
param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = avctx->rtp_payload_size; |
|
|
|
|
} else { |
|
|
|
|
av_log(avctx,AV_LOG_ERROR,"Invalid -max_nal_size, specify a valid max_nal_size to use -slice_mode dyn\n"); |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((*s->encoder)->InitializeExt(s->encoder, ¶m) != cmResultSuccess) { |
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Initialize failed\n"); |
|
|
|
|
goto fail; |
|
|
|
|