You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

449 lines
18KB

  1. /*
  2. * OpenH264 video encoder
  3. * Copyright (C) 2014 Martin Storsjo
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include <wels/codec_api.h>
  22. #include <wels/codec_ver.h>
  23. #include "libavutil/attributes.h"
  24. #include "libavutil/common.h"
  25. #include "libavutil/opt.h"
  26. #include "libavutil/internal.h"
  27. #include "libavutil/intreadwrite.h"
  28. #include "libavutil/mathematics.h"
  29. #include "avcodec.h"
  30. #include "internal.h"
  31. #include "libopenh264.h"
  32. #if !OPENH264_VER_AT_LEAST(1, 6)
  33. #define SM_SIZELIMITED_SLICE SM_DYN_SLICE
  34. #endif
  35. #define TARGET_BITRATE_DEFAULT 2*1000*1000
  36. typedef struct SVCContext {
  37. const AVClass *av_class;
  38. ISVCEncoder *encoder;
  39. int slice_mode;
  40. int loopfilter;
  41. int profile;
  42. int max_nal_size;
  43. int skip_frames;
  44. int skipped;
  45. #if FF_API_OPENH264_CABAC
  46. int cabac; // deprecated
  47. #endif
  48. int coder;
  49. // rate control mode
  50. int rc_mode;
  51. } SVCContext;
  52. #define OFFSET(x) offsetof(SVCContext, x)
  53. #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
  54. #define DEPRECATED AV_OPT_FLAG_DEPRECATED
  55. static const AVOption options[] = {
  56. #if FF_API_OPENH264_SLICE_MODE
  57. #if OPENH264_VER_AT_LEAST(1, 6)
  58. { "slice_mode", "set slice mode, use slices/max_nal_size", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_FIXEDSLCNUM_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE|DEPRECATED, "slice_mode" },
  59. #else
  60. { "slice_mode", "set slice mode, use slices/max_nal_size", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_AUTO_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE|DEPRECATED, "slice_mode" },
  61. #endif
  62. { "fixed", "a fixed number of slices", 0, AV_OPT_TYPE_CONST, { .i64 = SM_FIXEDSLCNUM_SLICE }, 0, 0, VE, "slice_mode" },
  63. #if OPENH264_VER_AT_LEAST(1, 6)
  64. { "dyn", "Size limited (compatibility name)", 0, AV_OPT_TYPE_CONST, { .i64 = SM_SIZELIMITED_SLICE }, 0, 0, VE, "slice_mode" },
  65. { "sizelimited", "Size limited", 0, AV_OPT_TYPE_CONST, { .i64 = SM_SIZELIMITED_SLICE }, 0, 0, VE, "slice_mode" },
  66. #else
  67. { "rowmb", "one slice per row of macroblocks", 0, AV_OPT_TYPE_CONST, { .i64 = SM_ROWMB_SLICE }, 0, 0, VE, "slice_mode" },
  68. { "auto", "automatic number of slices according to number of threads", 0, AV_OPT_TYPE_CONST, { .i64 = SM_AUTO_SLICE }, 0, 0, VE, "slice_mode" },
  69. { "dyn", "Dynamic slicing", 0, AV_OPT_TYPE_CONST, { .i64 = SM_DYN_SLICE }, 0, 0, VE, "slice_mode" },
  70. #endif
  71. #endif
  72. { "loopfilter", "enable loop filter", OFFSET(loopfilter), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE },
  73. { "profile", "set profile restrictions", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, 0xffff, VE, "profile" },
  74. #define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, { .i64 = value }, 0, 0, VE, "profile"
  75. { PROFILE("constrained_baseline", FF_PROFILE_H264_CONSTRAINED_BASELINE) },
  76. { PROFILE("main", FF_PROFILE_H264_MAIN) },
  77. { PROFILE("high", FF_PROFILE_H264_HIGH) },
  78. #undef PROFILE
  79. { "max_nal_size", "set maximum NAL size in bytes", OFFSET(max_nal_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
  80. { "allow_skip_frames", "allow skipping frames to hit the target bitrate", OFFSET(skip_frames), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
  81. #if FF_API_OPENH264_CABAC
  82. { "cabac", "Enable cabac(deprecated, use coder)", OFFSET(cabac), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE|DEPRECATED },
  83. #endif
  84. { "coder", "Coder type", OFFSET(coder), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE, "coder" },
  85. { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, VE, "coder" },
  86. { "cavlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "coder" },
  87. { "cabac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "coder" },
  88. { "vlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "coder" },
  89. { "ac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "coder" },
  90. { "rc_mode", "Select rate control mode", OFFSET(rc_mode), AV_OPT_TYPE_INT, { .i64 = RC_QUALITY_MODE }, RC_OFF_MODE, RC_TIMESTAMP_MODE, VE, "rc_mode" },
  91. { "off", "bit rate control off", 0, AV_OPT_TYPE_CONST, { .i64 = RC_OFF_MODE }, 0, 0, VE, "rc_mode" },
  92. { "quality", "quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RC_QUALITY_MODE }, 0, 0, VE, "rc_mode" },
  93. { "bitrate", "bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = RC_BITRATE_MODE }, 0, 0, VE, "rc_mode" },
  94. { "buffer", "using buffer status to adjust the video quality (no bitrate control)", 0, AV_OPT_TYPE_CONST, { .i64 = RC_BUFFERBASED_MODE }, 0, 0, VE, "rc_mode" },
  95. #if OPENH264_VER_AT_LEAST(1, 4)
  96. { "timestamp", "bit rate control based on timestamp", 0, AV_OPT_TYPE_CONST, { .i64 = RC_TIMESTAMP_MODE }, 0, 0, VE, "rc_mode" },
  97. #endif
  98. { NULL }
  99. };
  100. static const AVClass class = {
  101. .class_name = "libopenh264enc",
  102. .item_name = av_default_item_name,
  103. .option = options,
  104. .version = LIBAVUTIL_VERSION_INT,
  105. };
  106. static av_cold int svc_encode_close(AVCodecContext *avctx)
  107. {
  108. SVCContext *s = avctx->priv_data;
  109. if (s->encoder)
  110. WelsDestroySVCEncoder(s->encoder);
  111. if (s->skipped > 0)
  112. av_log(avctx, AV_LOG_WARNING, "%d frames skipped\n", s->skipped);
  113. return 0;
  114. }
  115. static av_cold int svc_encode_init(AVCodecContext *avctx)
  116. {
  117. SVCContext *s = avctx->priv_data;
  118. SEncParamExt param = { 0 };
  119. int err;
  120. int log_level;
  121. WelsTraceCallback callback_function;
  122. AVCPBProperties *props;
  123. if ((err = ff_libopenh264_check_version(avctx)) < 0)
  124. return err;
  125. if (WelsCreateSVCEncoder(&s->encoder)) {
  126. av_log(avctx, AV_LOG_ERROR, "Unable to create encoder\n");
  127. return AVERROR_UNKNOWN;
  128. }
  129. // Pass all libopenh264 messages to our callback, to allow ourselves to filter them.
  130. log_level = WELS_LOG_DETAIL;
  131. (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_LEVEL, &log_level);
  132. // Set the logging callback function to one that uses av_log() (see implementation above).
  133. callback_function = (WelsTraceCallback) ff_libopenh264_trace_callback;
  134. (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK, &callback_function);
  135. // Set the AVCodecContext as the libopenh264 callback context so that it can be passed to av_log().
  136. (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK_CONTEXT, &avctx);
  137. (*s->encoder)->GetDefaultParams(s->encoder, &param);
  138. param.fMaxFrameRate = 1/av_q2d(avctx->time_base);
  139. param.iPicWidth = avctx->width;
  140. param.iPicHeight = avctx->height;
  141. param.iTargetBitrate = avctx->bit_rate > 0 ? avctx->bit_rate : TARGET_BITRATE_DEFAULT;
  142. param.iMaxBitrate = FFMAX(avctx->rc_max_rate, avctx->bit_rate);
  143. param.iRCMode = s->rc_mode;
  144. if (avctx->qmax >= 0)
  145. param.iMaxQp = av_clip(avctx->qmax, 1, 51);
  146. if (avctx->qmin >= 0)
  147. param.iMinQp = av_clip(avctx->qmin, 1, param.iMaxQp);
  148. param.iTemporalLayerNum = 1;
  149. param.iSpatialLayerNum = 1;
  150. param.bEnableDenoise = 0;
  151. param.bEnableBackgroundDetection = 1;
  152. param.bEnableAdaptiveQuant = 1;
  153. param.bEnableFrameSkip = s->skip_frames;
  154. param.bEnableLongTermReference = 0;
  155. param.iLtrMarkPeriod = 30;
  156. if (avctx->gop_size >= 0)
  157. param.uiIntraPeriod = avctx->gop_size;
  158. #if OPENH264_VER_AT_LEAST(1, 4)
  159. param.eSpsPpsIdStrategy = CONSTANT_ID;
  160. #else
  161. param.bEnableSpsPpsIdAddition = 0;
  162. #endif
  163. param.bPrefixNalAddingCtrl = 0;
  164. param.iLoopFilterDisableIdc = !s->loopfilter;
  165. param.iEntropyCodingModeFlag = 0;
  166. param.iMultipleThreadIdc = avctx->thread_count;
  167. /* Allow specifying the libopenh264 profile through AVCodecContext. */
  168. if (FF_PROFILE_UNKNOWN == s->profile &&
  169. FF_PROFILE_UNKNOWN != avctx->profile)
  170. switch (avctx->profile) {
  171. case FF_PROFILE_H264_HIGH:
  172. case FF_PROFILE_H264_MAIN:
  173. case FF_PROFILE_H264_CONSTRAINED_BASELINE:
  174. s->profile = avctx->profile;
  175. break;
  176. default:
  177. av_log(avctx, AV_LOG_WARNING,
  178. "Unsupported avctx->profile: %d.\n", avctx->profile);
  179. break;
  180. }
  181. #if FF_API_CODER_TYPE && FF_API_OPENH264_CABAC
  182. FF_DISABLE_DEPRECATION_WARNINGS
  183. if (s->coder < 0 && avctx->coder_type == FF_CODER_TYPE_AC)
  184. s->coder = 1;
  185. if (s->coder < 0)
  186. s->coder = s->cabac;
  187. FF_ENABLE_DEPRECATION_WARNINGS
  188. #endif
  189. if (s->profile == FF_PROFILE_UNKNOWN && s->coder >= 0)
  190. s->profile = s->coder == 0 ? FF_PROFILE_H264_CONSTRAINED_BASELINE :
  191. #if OPENH264_VER_AT_LEAST(1, 8)
  192. FF_PROFILE_H264_HIGH;
  193. #else
  194. FF_PROFILE_H264_MAIN;
  195. #endif
  196. switch (s->profile) {
  197. #if OPENH264_VER_AT_LEAST(1, 8)
  198. case FF_PROFILE_H264_HIGH:
  199. param.iEntropyCodingModeFlag = 1;
  200. av_log(avctx, AV_LOG_VERBOSE, "Using CABAC, "
  201. "select EProfileIdc PRO_HIGH in libopenh264.\n");
  202. break;
  203. #else
  204. case FF_PROFILE_H264_MAIN:
  205. param.iEntropyCodingModeFlag = 1;
  206. av_log(avctx, AV_LOG_VERBOSE, "Using CABAC, "
  207. "select EProfileIdc PRO_MAIN in libopenh264.\n");
  208. break;
  209. #endif
  210. case FF_PROFILE_H264_CONSTRAINED_BASELINE:
  211. case FF_PROFILE_UNKNOWN:
  212. param.iEntropyCodingModeFlag = 0;
  213. av_log(avctx, AV_LOG_VERBOSE, "Using CAVLC, "
  214. "select EProfileIdc PRO_BASELINE in libopenh264.\n");
  215. break;
  216. default:
  217. param.iEntropyCodingModeFlag = 0;
  218. av_log(avctx, AV_LOG_WARNING, "Unsupported profile, "
  219. "select EProfileIdc PRO_BASELINE in libopenh264.\n");
  220. break;
  221. }
  222. param.sSpatialLayers[0].iVideoWidth = param.iPicWidth;
  223. param.sSpatialLayers[0].iVideoHeight = param.iPicHeight;
  224. param.sSpatialLayers[0].fFrameRate = param.fMaxFrameRate;
  225. param.sSpatialLayers[0].iSpatialBitrate = param.iTargetBitrate;
  226. param.sSpatialLayers[0].iMaxSpatialBitrate = param.iMaxBitrate;
  227. #if OPENH264_VER_AT_LEAST(1, 7)
  228. if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den) {
  229. // Table E-1.
  230. static const AVRational sar_idc[] = {
  231. { 0, 0 }, // Unspecified (never written here).
  232. { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 },
  233. { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 },
  234. { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 },
  235. { 160, 99 }, // Last 3 are unknown to openh264: { 4, 3 }, { 3, 2 }, { 2, 1 },
  236. };
  237. static const ESampleAspectRatio asp_idc[] = {
  238. ASP_UNSPECIFIED,
  239. ASP_1x1, ASP_12x11, ASP_10x11, ASP_16x11,
  240. ASP_40x33, ASP_24x11, ASP_20x11, ASP_32x11,
  241. ASP_80x33, ASP_18x11, ASP_15x11, ASP_64x33,
  242. ASP_160x99,
  243. };
  244. int num, den, i;
  245. av_reduce(&num, &den, avctx->sample_aspect_ratio.num,
  246. avctx->sample_aspect_ratio.den, 65535);
  247. for (i = 1; i < FF_ARRAY_ELEMS(sar_idc); i++) {
  248. if (num == sar_idc[i].num &&
  249. den == sar_idc[i].den)
  250. break;
  251. }
  252. if (i == FF_ARRAY_ELEMS(sar_idc)) {
  253. param.sSpatialLayers[0].eAspectRatio = ASP_EXT_SAR;
  254. param.sSpatialLayers[0].sAspectRatioExtWidth = num;
  255. param.sSpatialLayers[0].sAspectRatioExtHeight = den;
  256. } else {
  257. param.sSpatialLayers[0].eAspectRatio = asp_idc[i];
  258. }
  259. param.sSpatialLayers[0].bAspectRatioPresent = true;
  260. } else {
  261. param.sSpatialLayers[0].bAspectRatioPresent = false;
  262. }
  263. #endif
  264. if ((avctx->slices > 1) && (s->max_nal_size)) {
  265. av_log(avctx, AV_LOG_ERROR,
  266. "Invalid combination -slices %d and -max_nal_size %d.\n",
  267. avctx->slices, s->max_nal_size);
  268. return AVERROR(EINVAL);
  269. }
  270. if (avctx->slices > 1)
  271. s->slice_mode = SM_FIXEDSLCNUM_SLICE;
  272. if (s->max_nal_size)
  273. s->slice_mode = SM_SIZELIMITED_SLICE;
  274. #if OPENH264_VER_AT_LEAST(1, 6)
  275. param.sSpatialLayers[0].sSliceArgument.uiSliceMode = s->slice_mode;
  276. param.sSpatialLayers[0].sSliceArgument.uiSliceNum = avctx->slices;
  277. #else
  278. param.sSpatialLayers[0].sSliceCfg.uiSliceMode = s->slice_mode;
  279. param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = avctx->slices;
  280. #endif
  281. if (avctx->slices == 0 && s->slice_mode == SM_FIXEDSLCNUM_SLICE)
  282. av_log(avctx, AV_LOG_WARNING, "Slice count will be set automatically\n");
  283. if (s->slice_mode == SM_SIZELIMITED_SLICE) {
  284. if (s->max_nal_size) {
  285. param.uiMaxNalSize = s->max_nal_size;
  286. #if OPENH264_VER_AT_LEAST(1, 6)
  287. param.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = s->max_nal_size;
  288. #else
  289. param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = s->max_nal_size;
  290. #endif
  291. } else {
  292. av_log(avctx, AV_LOG_ERROR, "Invalid -max_nal_size, "
  293. "specify a valid max_nal_size to use -slice_mode dyn\n");
  294. return AVERROR(EINVAL);
  295. }
  296. }
  297. if ((*s->encoder)->InitializeExt(s->encoder, &param) != cmResultSuccess) {
  298. av_log(avctx, AV_LOG_ERROR, "Initialize failed\n");
  299. return AVERROR_UNKNOWN;
  300. }
  301. if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
  302. SFrameBSInfo fbi = { 0 };
  303. int i, size = 0;
  304. (*s->encoder)->EncodeParameterSets(s->encoder, &fbi);
  305. for (i = 0; i < fbi.sLayerInfo[0].iNalCount; i++)
  306. size += fbi.sLayerInfo[0].pNalLengthInByte[i];
  307. avctx->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
  308. if (!avctx->extradata)
  309. return AVERROR(ENOMEM);
  310. avctx->extradata_size = size;
  311. memcpy(avctx->extradata, fbi.sLayerInfo[0].pBsBuf, size);
  312. }
  313. props = ff_add_cpb_side_data(avctx);
  314. if (!props)
  315. return AVERROR(ENOMEM);
  316. props->max_bitrate = param.iMaxBitrate;
  317. props->avg_bitrate = param.iTargetBitrate;
  318. return 0;
  319. }
  320. static int svc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
  321. const AVFrame *frame, int *got_packet)
  322. {
  323. SVCContext *s = avctx->priv_data;
  324. SFrameBSInfo fbi = { 0 };
  325. int i, ret;
  326. int encoded;
  327. SSourcePicture sp = { 0 };
  328. int size = 0, layer, first_layer = 0;
  329. int layer_size[MAX_LAYER_NUM_OF_FRAME] = { 0 };
  330. sp.iColorFormat = videoFormatI420;
  331. for (i = 0; i < 3; i++) {
  332. sp.iStride[i] = frame->linesize[i];
  333. sp.pData[i] = frame->data[i];
  334. }
  335. sp.iPicWidth = avctx->width;
  336. sp.iPicHeight = avctx->height;
  337. if (frame->pict_type == AV_PICTURE_TYPE_I) {
  338. (*s->encoder)->ForceIntraFrame(s->encoder, true);
  339. }
  340. encoded = (*s->encoder)->EncodeFrame(s->encoder, &sp, &fbi);
  341. if (encoded != cmResultSuccess) {
  342. av_log(avctx, AV_LOG_ERROR, "EncodeFrame failed\n");
  343. return AVERROR_UNKNOWN;
  344. }
  345. if (fbi.eFrameType == videoFrameTypeSkip) {
  346. s->skipped++;
  347. av_log(avctx, AV_LOG_DEBUG, "frame skipped\n");
  348. return 0;
  349. }
  350. first_layer = 0;
  351. // Normal frames are returned with one single layer, while IDR
  352. // frames have two layers, where the first layer contains the SPS/PPS.
  353. // If using global headers, don't include the SPS/PPS in the returned
  354. // packet - thus, only return one layer.
  355. if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)
  356. first_layer = fbi.iLayerNum - 1;
  357. for (layer = first_layer; layer < fbi.iLayerNum; layer++) {
  358. for (i = 0; i < fbi.sLayerInfo[layer].iNalCount; i++)
  359. layer_size[layer] += fbi.sLayerInfo[layer].pNalLengthInByte[i];
  360. size += layer_size[layer];
  361. }
  362. av_log(avctx, AV_LOG_DEBUG, "%d slices\n", fbi.sLayerInfo[fbi.iLayerNum - 1].iNalCount);
  363. if ((ret = ff_alloc_packet2(avctx, avpkt, size, size))) {
  364. av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
  365. return ret;
  366. }
  367. size = 0;
  368. for (layer = first_layer; layer < fbi.iLayerNum; layer++) {
  369. memcpy(avpkt->data + size, fbi.sLayerInfo[layer].pBsBuf, layer_size[layer]);
  370. size += layer_size[layer];
  371. }
  372. avpkt->pts = frame->pts;
  373. if (fbi.eFrameType == videoFrameTypeIDR)
  374. avpkt->flags |= AV_PKT_FLAG_KEY;
  375. *got_packet = 1;
  376. return 0;
  377. }
  378. static const AVCodecDefault svc_enc_defaults[] = {
  379. { "b", "0" },
  380. { "g", "-1" },
  381. { "qmin", "-1" },
  382. { "qmax", "-1" },
  383. { NULL },
  384. };
  385. AVCodec ff_libopenh264_encoder = {
  386. .name = "libopenh264",
  387. .long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
  388. .type = AVMEDIA_TYPE_VIDEO,
  389. .id = AV_CODEC_ID_H264,
  390. .priv_data_size = sizeof(SVCContext),
  391. .init = svc_encode_init,
  392. .encode2 = svc_encode_frame,
  393. .close = svc_encode_close,
  394. .capabilities = AV_CODEC_CAP_AUTO_THREADS,
  395. .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
  396. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P,
  397. AV_PIX_FMT_NONE },
  398. .defaults = svc_enc_defaults,
  399. .priv_class = &class,
  400. .wrapper_name = "libopenh264",
  401. };