blob: 784b51c52d40e696544190f486d77cf5702666cb
1 | /* |
2 | * libx265 encoder |
3 | * |
4 | * Copyright (c) 2013-2014 Derek Buitenhuis |
5 | * |
6 | * This file is part of FFmpeg. |
7 | * |
8 | * FFmpeg is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU Lesser General Public |
10 | * License as published by the Free Software Foundation; either |
11 | * version 2.1 of the License, or (at your option) any later version. |
12 | * |
13 | * FFmpeg is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * Lesser General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU Lesser General Public |
19 | * License along with FFmpeg; if not, write to the Free Software |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | */ |
22 | |
23 | #if defined(_MSC_VER) |
24 | #define X265_API_IMPORTS 1 |
25 | #endif |
26 | |
27 | #include <x265.h> |
28 | #include <float.h> |
29 | |
30 | #include "libavutil/internal.h" |
31 | #include "libavutil/common.h" |
32 | #include "libavutil/opt.h" |
33 | #include "libavutil/pixdesc.h" |
34 | #include "avcodec.h" |
35 | #include "internal.h" |
36 | |
37 | typedef struct libx265Context { |
38 | const AVClass *class; |
39 | |
40 | x265_encoder *encoder; |
41 | x265_param *params; |
42 | const x265_api *api; |
43 | |
44 | float crf; |
45 | int forced_idr; |
46 | char *preset; |
47 | char *tune; |
48 | char *x265_opts; |
49 | } libx265Context; |
50 | |
51 | static int is_keyframe(NalUnitType naltype) |
52 | { |
53 | switch (naltype) { |
54 | case NAL_UNIT_CODED_SLICE_BLA_W_LP: |
55 | case NAL_UNIT_CODED_SLICE_BLA_W_RADL: |
56 | case NAL_UNIT_CODED_SLICE_BLA_N_LP: |
57 | case NAL_UNIT_CODED_SLICE_IDR_W_RADL: |
58 | case NAL_UNIT_CODED_SLICE_IDR_N_LP: |
59 | case NAL_UNIT_CODED_SLICE_CRA: |
60 | return 1; |
61 | default: |
62 | return 0; |
63 | } |
64 | } |
65 | |
66 | static av_cold int libx265_encode_close(AVCodecContext *avctx) |
67 | { |
68 | libx265Context *ctx = avctx->priv_data; |
69 | |
70 | ctx->api->param_free(ctx->params); |
71 | |
72 | if (ctx->encoder) |
73 | ctx->api->encoder_close(ctx->encoder); |
74 | |
75 | return 0; |
76 | } |
77 | |
78 | static av_cold int libx265_encode_init(AVCodecContext *avctx) |
79 | { |
80 | libx265Context *ctx = avctx->priv_data; |
81 | |
82 | ctx->api = x265_api_get(av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth); |
83 | if (!ctx->api) |
84 | ctx->api = x265_api_get(0); |
85 | |
86 | ctx->params = ctx->api->param_alloc(); |
87 | if (!ctx->params) { |
88 | av_log(avctx, AV_LOG_ERROR, "Could not allocate x265 param structure.\n"); |
89 | return AVERROR(ENOMEM); |
90 | } |
91 | |
92 | if (ctx->api->param_default_preset(ctx->params, ctx->preset, ctx->tune) < 0) { |
93 | int i; |
94 | |
95 | av_log(avctx, AV_LOG_ERROR, "Error setting preset/tune %s/%s.\n", ctx->preset, ctx->tune); |
96 | av_log(avctx, AV_LOG_INFO, "Possible presets:"); |
97 | for (i = 0; x265_preset_names[i]; i++) |
98 | av_log(avctx, AV_LOG_INFO, " %s", x265_preset_names[i]); |
99 | |
100 | av_log(avctx, AV_LOG_INFO, "\n"); |
101 | av_log(avctx, AV_LOG_INFO, "Possible tunes:"); |
102 | for (i = 0; x265_tune_names[i]; i++) |
103 | av_log(avctx, AV_LOG_INFO, " %s", x265_tune_names[i]); |
104 | |
105 | av_log(avctx, AV_LOG_INFO, "\n"); |
106 | |
107 | return AVERROR(EINVAL); |
108 | } |
109 | |
110 | ctx->params->frameNumThreads = avctx->thread_count; |
111 | ctx->params->fpsNum = avctx->time_base.den; |
112 | ctx->params->fpsDenom = avctx->time_base.num * avctx->ticks_per_frame; |
113 | ctx->params->sourceWidth = avctx->width; |
114 | ctx->params->sourceHeight = avctx->height; |
115 | ctx->params->bEnablePsnr = !!(avctx->flags & AV_CODEC_FLAG_PSNR); |
116 | |
117 | if ((avctx->color_primaries <= AVCOL_PRI_BT2020 && |
118 | avctx->color_primaries != AVCOL_PRI_UNSPECIFIED) || |
119 | (avctx->color_trc <= AVCOL_TRC_BT2020_12 && |
120 | avctx->color_trc != AVCOL_TRC_UNSPECIFIED) || |
121 | (avctx->colorspace <= AVCOL_SPC_BT2020_CL && |
122 | avctx->colorspace != AVCOL_SPC_UNSPECIFIED)) { |
123 | |
124 | ctx->params->vui.bEnableVideoSignalTypePresentFlag = 1; |
125 | ctx->params->vui.bEnableColorDescriptionPresentFlag = 1; |
126 | |
127 | // x265 validates the parameters internally |
128 | ctx->params->vui.colorPrimaries = avctx->color_primaries; |
129 | ctx->params->vui.transferCharacteristics = avctx->color_trc; |
130 | ctx->params->vui.matrixCoeffs = avctx->colorspace; |
131 | } |
132 | |
133 | if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) { |
134 | char sar[12]; |
135 | int sar_num, sar_den; |
136 | |
137 | av_reduce(&sar_num, &sar_den, |
138 | avctx->sample_aspect_ratio.num, |
139 | avctx->sample_aspect_ratio.den, 65535); |
140 | snprintf(sar, sizeof(sar), "%d:%d", sar_num, sar_den); |
141 | if (ctx->api->param_parse(ctx->params, "sar", sar) == X265_PARAM_BAD_VALUE) { |
142 | av_log(avctx, AV_LOG_ERROR, "Invalid SAR: %d:%d.\n", sar_num, sar_den); |
143 | return AVERROR_INVALIDDATA; |
144 | } |
145 | } |
146 | |
147 | switch (avctx->pix_fmt) { |
148 | case AV_PIX_FMT_YUV420P: |
149 | case AV_PIX_FMT_YUV420P10: |
150 | case AV_PIX_FMT_YUV420P12: |
151 | ctx->params->internalCsp = X265_CSP_I420; |
152 | break; |
153 | case AV_PIX_FMT_YUV422P: |
154 | case AV_PIX_FMT_YUV422P10: |
155 | case AV_PIX_FMT_YUV422P12: |
156 | ctx->params->internalCsp = X265_CSP_I422; |
157 | break; |
158 | case AV_PIX_FMT_GBRP: |
159 | case AV_PIX_FMT_GBRP10: |
160 | case AV_PIX_FMT_GBRP12: |
161 | ctx->params->vui.matrixCoeffs = AVCOL_SPC_RGB; |
162 | ctx->params->vui.bEnableVideoSignalTypePresentFlag = 1; |
163 | ctx->params->vui.bEnableColorDescriptionPresentFlag = 1; |
164 | case AV_PIX_FMT_YUV444P: |
165 | case AV_PIX_FMT_YUV444P10: |
166 | case AV_PIX_FMT_YUV444P12: |
167 | ctx->params->internalCsp = X265_CSP_I444; |
168 | break; |
169 | case AV_PIX_FMT_GRAY8: |
170 | case AV_PIX_FMT_GRAY10: |
171 | case AV_PIX_FMT_GRAY12: |
172 | if (ctx->api->api_build_number < 85) { |
173 | av_log(avctx, AV_LOG_ERROR, |
174 | "libx265 version is %d, must be at least 85 for gray encoding.\n", |
175 | ctx->api->api_build_number); |
176 | return AVERROR_INVALIDDATA; |
177 | } |
178 | ctx->params->internalCsp = X265_CSP_I400; |
179 | break; |
180 | } |
181 | |
182 | if (ctx->crf >= 0) { |
183 | char crf[6]; |
184 | |
185 | snprintf(crf, sizeof(crf), "%2.2f", ctx->crf); |
186 | if (ctx->api->param_parse(ctx->params, "crf", crf) == X265_PARAM_BAD_VALUE) { |
187 | av_log(avctx, AV_LOG_ERROR, "Invalid crf: %2.2f.\n", ctx->crf); |
188 | return AVERROR(EINVAL); |
189 | } |
190 | } else if (avctx->bit_rate > 0) { |
191 | ctx->params->rc.bitrate = avctx->bit_rate / 1000; |
192 | ctx->params->rc.rateControlMode = X265_RC_ABR; |
193 | } |
194 | |
195 | if (!(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) |
196 | ctx->params->bRepeatHeaders = 1; |
197 | |
198 | if (ctx->x265_opts) { |
199 | AVDictionary *dict = NULL; |
200 | AVDictionaryEntry *en = NULL; |
201 | |
202 | if (!av_dict_parse_string(&dict, ctx->x265_opts, "=", ":", 0)) { |
203 | while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) { |
204 | int parse_ret = ctx->api->param_parse(ctx->params, en->key, en->value); |
205 | |
206 | switch (parse_ret) { |
207 | case X265_PARAM_BAD_NAME: |
208 | av_log(avctx, AV_LOG_WARNING, |
209 | "Unknown option: %s.\n", en->key); |
210 | break; |
211 | case X265_PARAM_BAD_VALUE: |
212 | av_log(avctx, AV_LOG_WARNING, |
213 | "Invalid value for %s: %s.\n", en->key, en->value); |
214 | break; |
215 | default: |
216 | break; |
217 | } |
218 | } |
219 | av_dict_free(&dict); |
220 | } |
221 | } |
222 | |
223 | ctx->encoder = ctx->api->encoder_open(ctx->params); |
224 | if (!ctx->encoder) { |
225 | av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n"); |
226 | libx265_encode_close(avctx); |
227 | return AVERROR_INVALIDDATA; |
228 | } |
229 | |
230 | if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { |
231 | x265_nal *nal; |
232 | int nnal; |
233 | |
234 | avctx->extradata_size = ctx->api->encoder_headers(ctx->encoder, &nal, &nnal); |
235 | if (avctx->extradata_size <= 0) { |
236 | av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n"); |
237 | libx265_encode_close(avctx); |
238 | return AVERROR_INVALIDDATA; |
239 | } |
240 | |
241 | avctx->extradata = av_malloc(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); |
242 | if (!avctx->extradata) { |
243 | av_log(avctx, AV_LOG_ERROR, |
244 | "Cannot allocate HEVC header of size %d.\n", avctx->extradata_size); |
245 | libx265_encode_close(avctx); |
246 | return AVERROR(ENOMEM); |
247 | } |
248 | |
249 | memcpy(avctx->extradata, nal[0].payload, avctx->extradata_size); |
250 | } |
251 | |
252 | return 0; |
253 | } |
254 | |
255 | static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
256 | const AVFrame *pic, int *got_packet) |
257 | { |
258 | libx265Context *ctx = avctx->priv_data; |
259 | x265_picture x265pic; |
260 | x265_picture x265pic_out = { 0 }; |
261 | x265_nal *nal; |
262 | uint8_t *dst; |
263 | int payload = 0; |
264 | int nnal; |
265 | int ret; |
266 | int i; |
267 | |
268 | ctx->api->picture_init(ctx->params, &x265pic); |
269 | |
270 | if (pic) { |
271 | for (i = 0; i < 3; i++) { |
272 | x265pic.planes[i] = pic->data[i]; |
273 | x265pic.stride[i] = pic->linesize[i]; |
274 | } |
275 | |
276 | x265pic.pts = pic->pts; |
277 | x265pic.bitDepth = av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth; |
278 | |
279 | x265pic.sliceType = pic->pict_type == AV_PICTURE_TYPE_I ? |
280 | (ctx->forced_idr ? X265_TYPE_IDR : X265_TYPE_I) : |
281 | pic->pict_type == AV_PICTURE_TYPE_P ? X265_TYPE_P : |
282 | pic->pict_type == AV_PICTURE_TYPE_B ? X265_TYPE_B : |
283 | X265_TYPE_AUTO; |
284 | } |
285 | |
286 | ret = ctx->api->encoder_encode(ctx->encoder, &nal, &nnal, |
287 | pic ? &x265pic : NULL, &x265pic_out); |
288 | if (ret < 0) |
289 | return AVERROR_EXTERNAL; |
290 | |
291 | if (!nnal) |
292 | return 0; |
293 | |
294 | for (i = 0; i < nnal; i++) |
295 | payload += nal[i].sizeBytes; |
296 | |
297 | ret = ff_alloc_packet(pkt, payload); |
298 | if (ret < 0) { |
299 | av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); |
300 | return ret; |
301 | } |
302 | dst = pkt->data; |
303 | |
304 | for (i = 0; i < nnal; i++) { |
305 | memcpy(dst, nal[i].payload, nal[i].sizeBytes); |
306 | dst += nal[i].sizeBytes; |
307 | |
308 | if (is_keyframe(nal[i].type)) |
309 | pkt->flags |= AV_PKT_FLAG_KEY; |
310 | } |
311 | |
312 | pkt->pts = x265pic_out.pts; |
313 | pkt->dts = x265pic_out.dts; |
314 | |
315 | #if FF_API_CODED_FRAME |
316 | FF_DISABLE_DEPRECATION_WARNINGS |
317 | switch (x265pic_out.sliceType) { |
318 | case X265_TYPE_IDR: |
319 | case X265_TYPE_I: |
320 | avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; |
321 | break; |
322 | case X265_TYPE_P: |
323 | avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P; |
324 | break; |
325 | case X265_TYPE_B: |
326 | avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B; |
327 | break; |
328 | } |
329 | FF_ENABLE_DEPRECATION_WARNINGS |
330 | #endif |
331 | |
332 | *got_packet = 1; |
333 | return 0; |
334 | } |
335 | |
336 | static const enum AVPixelFormat x265_csp_eight[] = { |
337 | AV_PIX_FMT_YUV420P, |
338 | AV_PIX_FMT_YUV422P, |
339 | AV_PIX_FMT_YUV444P, |
340 | AV_PIX_FMT_GBRP, |
341 | AV_PIX_FMT_GRAY8, |
342 | AV_PIX_FMT_NONE |
343 | }; |
344 | |
345 | static const enum AVPixelFormat x265_csp_ten[] = { |
346 | AV_PIX_FMT_YUV420P, |
347 | AV_PIX_FMT_YUV422P, |
348 | AV_PIX_FMT_YUV444P, |
349 | AV_PIX_FMT_GBRP, |
350 | AV_PIX_FMT_YUV420P10, |
351 | AV_PIX_FMT_YUV422P10, |
352 | AV_PIX_FMT_YUV444P10, |
353 | AV_PIX_FMT_GBRP10, |
354 | AV_PIX_FMT_GRAY8, |
355 | AV_PIX_FMT_GRAY10, |
356 | AV_PIX_FMT_NONE |
357 | }; |
358 | |
359 | static const enum AVPixelFormat x265_csp_twelve[] = { |
360 | AV_PIX_FMT_YUV420P, |
361 | AV_PIX_FMT_YUV422P, |
362 | AV_PIX_FMT_YUV444P, |
363 | AV_PIX_FMT_GBRP, |
364 | AV_PIX_FMT_YUV420P10, |
365 | AV_PIX_FMT_YUV422P10, |
366 | AV_PIX_FMT_YUV444P10, |
367 | AV_PIX_FMT_GBRP10, |
368 | AV_PIX_FMT_YUV420P12, |
369 | AV_PIX_FMT_YUV422P12, |
370 | AV_PIX_FMT_YUV444P12, |
371 | AV_PIX_FMT_GBRP12, |
372 | AV_PIX_FMT_GRAY8, |
373 | AV_PIX_FMT_GRAY10, |
374 | AV_PIX_FMT_GRAY12, |
375 | AV_PIX_FMT_NONE |
376 | }; |
377 | |
378 | static av_cold void libx265_encode_init_csp(AVCodec *codec) |
379 | { |
380 | if (x265_api_get(12)) |
381 | codec->pix_fmts = x265_csp_twelve; |
382 | else if (x265_api_get(10)) |
383 | codec->pix_fmts = x265_csp_ten; |
384 | else if (x265_api_get(8)) |
385 | codec->pix_fmts = x265_csp_eight; |
386 | } |
387 | |
388 | #define OFFSET(x) offsetof(libx265Context, x) |
389 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
390 | static const AVOption options[] = { |
391 | { "crf", "set the x265 crf", OFFSET(crf), AV_OPT_TYPE_FLOAT, { .dbl = -1 }, -1, FLT_MAX, VE }, |
392 | { "forced-idr", "if forcing keyframes, force them as IDR frames", OFFSET(forced_idr),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, |
393 | { "preset", "set the x265 preset", OFFSET(preset), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, |
394 | { "tune", "set the x265 tune parameter", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, |
395 | { "x265-params", "set the x265 configuration using a :-separated list of key=value parameters", OFFSET(x265_opts), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, |
396 | { NULL } |
397 | }; |
398 | |
399 | static const AVClass class = { |
400 | .class_name = "libx265", |
401 | .item_name = av_default_item_name, |
402 | .option = options, |
403 | .version = LIBAVUTIL_VERSION_INT, |
404 | }; |
405 | |
406 | static const AVCodecDefault x265_defaults[] = { |
407 | { "b", "0" }, |
408 | { NULL }, |
409 | }; |
410 | |
411 | AVCodec ff_libx265_encoder = { |
412 | .name = "libx265", |
413 | .long_name = NULL_IF_CONFIG_SMALL("libx265 H.265 / HEVC"), |
414 | .type = AVMEDIA_TYPE_VIDEO, |
415 | .id = AV_CODEC_ID_HEVC, |
416 | .init = libx265_encode_init, |
417 | .init_static_data = libx265_encode_init_csp, |
418 | .encode2 = libx265_encode_frame, |
419 | .close = libx265_encode_close, |
420 | .priv_data_size = sizeof(libx265Context), |
421 | .priv_class = &class, |
422 | .defaults = x265_defaults, |
423 | .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, |
424 | }; |
425 |