22 #include <wels/codec_api.h>
23 #include <wels/codec_ver.h>
36 #if !OPENH264_VER_AT_LEAST(1, 6)
37 #define SM_SIZELIMITED_SLICE SM_DYN_SLICE
52 #define OFFSET(x) offsetof(SVCContext, x)
53 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
55 #if OPENH264_VER_AT_LEAST(1, 6)
56 {
"slice_mode",
"set slice mode",
OFFSET(slice_mode),
AV_OPT_TYPE_INT, { .i64 = SM_FIXEDSLCNUM_SLICE }, SM_SINGLE_SLICE, SM_RESERVED,
VE,
"slice_mode" },
58 {
"slice_mode",
"set slice mode",
OFFSET(slice_mode),
AV_OPT_TYPE_INT, { .i64 = SM_AUTO_SLICE }, SM_SINGLE_SLICE, SM_RESERVED,
VE,
"slice_mode" },
60 {
"fixed",
"a fixed number of slices", 0,
AV_OPT_TYPE_CONST, { .i64 = SM_FIXEDSLCNUM_SLICE }, 0, 0,
VE,
"slice_mode" },
61 #if OPENH264_VER_AT_LEAST(1, 6)
65 {
"rowmb",
"one slice per row of macroblocks", 0,
AV_OPT_TYPE_CONST, { .i64 = SM_ROWMB_SLICE }, 0, 0,
VE,
"slice_mode" },
66 {
"auto",
"automatic number of slices according to number of threads", 0,
AV_OPT_TYPE_CONST, { .i64 = SM_AUTO_SLICE }, 0, 0,
VE,
"slice_mode" },
67 {
"dyn",
"Dynamic slicing", 0,
AV_OPT_TYPE_CONST, { .i64 = SM_DYN_SLICE }, 0, 0,
VE,
"slice_mode" },
71 {
"max_nal_size",
"set maximum NAL size in bytes",
OFFSET(max_nal_size),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX,
VE },
72 {
"allow_skip_frames",
"allow skipping frames to hit the target bitrate",
OFFSET(skip_frames),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
VE },
89 WelsDestroySVCEncoder(
s->encoder);
98 SEncParamExt param = { 0 };
101 WelsTraceCallback callback_function;
107 if (WelsCreateSVCEncoder(&
s->encoder)) {
113 log_level = WELS_LOG_DETAIL;
114 (*
s->encoder)->SetOption(
s->encoder, ENCODER_OPTION_TRACE_LEVEL, &log_level);
118 (*
s->encoder)->SetOption(
s->encoder, ENCODER_OPTION_TRACE_CALLBACK, &callback_function);
121 (*
s->encoder)->SetOption(
s->encoder, ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &avctx);
123 (*
s->encoder)->GetDefaultParams(
s->encoder, ¶m);
125 #if FF_API_CODER_TYPE
133 param.iPicWidth = avctx->
width;
134 param.iPicHeight = avctx->
height;
135 param.iTargetBitrate = avctx->
bit_rate;
137 param.iRCMode = RC_QUALITY_MODE;
138 param.iTemporalLayerNum = 1;
139 param.iSpatialLayerNum = 1;
140 param.bEnableDenoise = 0;
141 param.bEnableBackgroundDetection = 1;
142 param.bEnableAdaptiveQuant = 1;
143 param.bEnableFrameSkip =
s->skip_frames;
144 param.bEnableLongTermReference = 0;
145 param.iLtrMarkPeriod = 30;
146 param.uiIntraPeriod = avctx->
gop_size;
147 #if OPENH264_VER_AT_LEAST(1, 4)
148 param.eSpsPpsIdStrategy = CONSTANT_ID;
150 param.bEnableSpsPpsIdAddition = 0;
152 param.bPrefixNalAddingCtrl = 0;
153 param.iLoopFilterDisableIdc = !
s->loopfilter;
154 param.iEntropyCodingModeFlag = 0;
156 if (
s->profile && !strcmp(
s->profile,
"main"))
157 param.iEntropyCodingModeFlag = 1;
158 else if (!
s->profile &&
s->cabac)
159 param.iEntropyCodingModeFlag = 1;
161 param.sSpatialLayers[0].iVideoWidth = param.iPicWidth;
162 param.sSpatialLayers[0].iVideoHeight = param.iPicHeight;
163 param.sSpatialLayers[0].fFrameRate = param.fMaxFrameRate;
164 param.sSpatialLayers[0].iSpatialBitrate = param.iTargetBitrate;
165 param.sSpatialLayers[0].iMaxSpatialBitrate = param.iMaxBitrate;
167 #if OPENH264_VER_AT_LEAST(1, 7)
172 { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 },
173 { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 },
174 { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 },
177 static const ESampleAspectRatio asp_idc[] = {
179 ASP_1x1, ASP_12x11, ASP_10x11, ASP_16x11,
180 ASP_40x33, ASP_24x11, ASP_20x11, ASP_32x11,
181 ASP_80x33, ASP_18x11, ASP_15x11, ASP_64x33,
190 if (num == sar_idc[
i].num &&
191 den == sar_idc[
i].den)
195 param.sSpatialLayers[0].eAspectRatio = ASP_EXT_SAR;
196 param.sSpatialLayers[0].sAspectRatioExtWidth = num;
197 param.sSpatialLayers[0].sAspectRatioExtHeight = den;
199 param.sSpatialLayers[0].eAspectRatio = asp_idc[
i];
201 param.sSpatialLayers[0].bAspectRatioPresent =
true;
204 param.sSpatialLayers[0].bAspectRatioPresent =
false;
208 if ((avctx->
slices > 1) && (
s->max_nal_size)) {
210 "Invalid combination -slices %d and -max_nal_size %d.\n",
211 avctx->
slices,
s->max_nal_size);
216 s->slice_mode = SM_FIXEDSLCNUM_SLICE;
221 #if OPENH264_VER_AT_LEAST(1, 6)
222 param.sSpatialLayers[0].sSliceArgument.uiSliceMode =
s->slice_mode;
223 param.sSpatialLayers[0].sSliceArgument.uiSliceNum = avctx->
slices;
225 param.sSpatialLayers[0].sSliceCfg.uiSliceMode =
s->slice_mode;
226 param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = avctx->
slices;
230 if (
s->max_nal_size){
231 param.uiMaxNalSize =
s->max_nal_size;
232 #if OPENH264_VER_AT_LEAST(1, 6)
233 param.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint =
s->max_nal_size;
235 param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceSizeConstraint =
s->max_nal_size;
239 "specify a valid max_nal_size to use -slice_mode dyn\n");
244 if ((*
s->encoder)->InitializeExt(
s->encoder, ¶m) != cmResultSuccess) {
250 SFrameBSInfo fbi = { 0 };
252 (*
s->encoder)->EncodeParameterSets(
s->encoder, &fbi);
253 for (
i = 0;
i < fbi.sLayerInfo[0].iNalCount;
i++)
254 size += fbi.sLayerInfo[0].pNalLengthInByte[
i];
275 SFrameBSInfo fbi = { 0 };
278 SSourcePicture
sp = { 0 };
279 int size = 0, layer, first_layer = 0;
280 int layer_size[MAX_LAYER_NUM_OF_FRAME] = { 0 };
282 sp.iColorFormat = videoFormatI420;
283 for (
i = 0;
i < 3;
i++) {
291 (*
s->encoder)->ForceIntraFrame(
s->encoder,
true);
294 encoded = (*
s->encoder)->EncodeFrame(
s->encoder, &
sp, &fbi);
295 if (encoded != cmResultSuccess) {
299 if (fbi.eFrameType == videoFrameTypeSkip) {
310 first_layer = fbi.iLayerNum - 1;
312 for (layer = first_layer; layer < fbi.iLayerNum; layer++) {
313 for (
i = 0;
i < fbi.sLayerInfo[layer].iNalCount;
i++)
314 layer_size[layer] += fbi.sLayerInfo[layer].pNalLengthInByte[
i];
315 size += layer_size[layer];
317 av_log(avctx,
AV_LOG_DEBUG,
"%d slices\n", fbi.sLayerInfo[fbi.iLayerNum - 1].iNalCount);
324 for (layer = first_layer; layer < fbi.iLayerNum; layer++) {
325 memcpy(avpkt->
data +
size, fbi.sLayerInfo[layer].pBsBuf, layer_size[layer]);
326 size += layer_size[layer];
329 if (fbi.eFrameType == videoFrameTypeIDR)
336 .
name =
"libopenh264",
348 .priv_class = &
class,
349 .wrapper_name =
"libopenh264",