Commit | Line | Data |
---|---|---|
2ba45a60 DM |
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 | ||
29 | #include "libavutil/internal.h" | |
30 | #include "libavutil/common.h" | |
31 | #include "libavutil/opt.h" | |
32 | #include "libavutil/pixdesc.h" | |
33 | #include "avcodec.h" | |
34 | #include "internal.h" | |
35 | ||
36 | typedef struct libx265Context { | |
37 | const AVClass *class; | |
38 | ||
39 | x265_encoder *encoder; | |
40 | x265_param *params; | |
41 | ||
42 | char *preset; | |
43 | char *tune; | |
44 | char *x265_opts; | |
45 | } libx265Context; | |
46 | ||
47 | static int is_keyframe(NalUnitType naltype) | |
48 | { | |
49 | switch (naltype) { | |
50 | case NAL_UNIT_CODED_SLICE_BLA_W_LP: | |
51 | case NAL_UNIT_CODED_SLICE_BLA_W_RADL: | |
52 | case NAL_UNIT_CODED_SLICE_BLA_N_LP: | |
53 | case NAL_UNIT_CODED_SLICE_IDR_W_RADL: | |
54 | case NAL_UNIT_CODED_SLICE_IDR_N_LP: | |
55 | case NAL_UNIT_CODED_SLICE_CRA: | |
56 | return 1; | |
57 | default: | |
58 | return 0; | |
59 | } | |
60 | } | |
61 | ||
62 | static av_cold int libx265_encode_close(AVCodecContext *avctx) | |
63 | { | |
64 | libx265Context *ctx = avctx->priv_data; | |
65 | ||
66 | av_frame_free(&avctx->coded_frame); | |
67 | ||
68 | x265_param_free(ctx->params); | |
69 | ||
70 | if (ctx->encoder) | |
71 | x265_encoder_close(ctx->encoder); | |
72 | ||
73 | return 0; | |
74 | } | |
75 | ||
76 | static av_cold int libx265_encode_init(AVCodecContext *avctx) | |
77 | { | |
78 | libx265Context *ctx = avctx->priv_data; | |
79 | x265_nal *nal; | |
80 | char sar[12]; | |
81 | int sar_num, sar_den; | |
82 | int nnal; | |
83 | ||
84 | if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL && | |
85 | !av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_w) { | |
86 | av_log(avctx, AV_LOG_ERROR, | |
87 | "4:2:2 and 4:4:4 support is not fully defined for HEVC yet. " | |
88 | "Set -strict experimental to encode anyway.\n"); | |
89 | return AVERROR(ENOSYS); | |
90 | } | |
91 | ||
92 | avctx->coded_frame = av_frame_alloc(); | |
93 | if (!avctx->coded_frame) { | |
94 | av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); | |
95 | return AVERROR(ENOMEM); | |
96 | } | |
97 | ||
98 | ctx->params = x265_param_alloc(); | |
99 | if (!ctx->params) { | |
100 | av_log(avctx, AV_LOG_ERROR, "Could not allocate x265 param structure.\n"); | |
101 | return AVERROR(ENOMEM); | |
102 | } | |
103 | ||
104 | if (x265_param_default_preset(ctx->params, ctx->preset, ctx->tune) < 0) { | |
105 | av_log(avctx, AV_LOG_ERROR, "Invalid preset or tune.\n"); | |
106 | return AVERROR(EINVAL); | |
107 | } | |
108 | ||
109 | ctx->params->frameNumThreads = avctx->thread_count; | |
110 | ctx->params->fpsNum = avctx->time_base.den; | |
111 | ctx->params->fpsDenom = avctx->time_base.num * avctx->ticks_per_frame; | |
112 | ctx->params->sourceWidth = avctx->width; | |
113 | ctx->params->sourceHeight = avctx->height; | |
f6fa7814 | 114 | ctx->params->bEnablePsnr = !!(avctx->flags & CODEC_FLAG_PSNR); |
2ba45a60 DM |
115 | |
116 | if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) { | |
117 | av_reduce(&sar_num, &sar_den, | |
118 | avctx->sample_aspect_ratio.num, | |
119 | avctx->sample_aspect_ratio.den, 65535); | |
120 | snprintf(sar, sizeof(sar), "%d:%d", sar_num, sar_den); | |
121 | if (x265_param_parse(ctx->params, "sar", sar) == X265_PARAM_BAD_VALUE) { | |
122 | av_log(avctx, AV_LOG_ERROR, "Invalid SAR: %d:%d.\n", sar_num, sar_den); | |
123 | return AVERROR_INVALIDDATA; | |
124 | } | |
125 | } | |
126 | ||
127 | switch (avctx->pix_fmt) { | |
128 | case AV_PIX_FMT_YUV420P: | |
129 | case AV_PIX_FMT_YUV420P10: | |
130 | ctx->params->internalCsp = X265_CSP_I420; | |
131 | break; | |
132 | case AV_PIX_FMT_YUV422P: | |
133 | case AV_PIX_FMT_YUV422P10: | |
134 | ctx->params->internalCsp = X265_CSP_I422; | |
135 | break; | |
136 | case AV_PIX_FMT_YUV444P: | |
137 | case AV_PIX_FMT_YUV444P10: | |
138 | ctx->params->internalCsp = X265_CSP_I444; | |
139 | break; | |
140 | } | |
141 | ||
142 | if (avctx->bit_rate > 0) { | |
143 | ctx->params->rc.bitrate = avctx->bit_rate / 1000; | |
144 | ctx->params->rc.rateControlMode = X265_RC_ABR; | |
145 | } | |
146 | ||
147 | if (!(avctx->flags & CODEC_FLAG_GLOBAL_HEADER)) | |
148 | ctx->params->bRepeatHeaders = 1; | |
149 | ||
150 | if (ctx->x265_opts) { | |
151 | AVDictionary *dict = NULL; | |
152 | AVDictionaryEntry *en = NULL; | |
153 | ||
154 | if (!av_dict_parse_string(&dict, ctx->x265_opts, "=", ":", 0)) { | |
155 | while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) { | |
156 | int parse_ret = x265_param_parse(ctx->params, en->key, en->value); | |
157 | ||
158 | switch (parse_ret) { | |
159 | case X265_PARAM_BAD_NAME: | |
160 | av_log(avctx, AV_LOG_WARNING, | |
161 | "Unknown option: %s.\n", en->key); | |
162 | break; | |
163 | case X265_PARAM_BAD_VALUE: | |
164 | av_log(avctx, AV_LOG_WARNING, | |
165 | "Invalid value for %s: %s.\n", en->key, en->value); | |
166 | break; | |
167 | default: | |
168 | break; | |
169 | } | |
170 | } | |
171 | av_dict_free(&dict); | |
172 | } | |
173 | } | |
174 | ||
175 | ctx->encoder = x265_encoder_open(ctx->params); | |
176 | if (!ctx->encoder) { | |
177 | av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n"); | |
178 | libx265_encode_close(avctx); | |
179 | return AVERROR_INVALIDDATA; | |
180 | } | |
181 | ||
182 | if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { | |
183 | avctx->extradata_size = x265_encoder_headers(ctx->encoder, &nal, &nnal); | |
184 | if (avctx->extradata_size <= 0) { | |
185 | av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n"); | |
186 | libx265_encode_close(avctx); | |
187 | return AVERROR_INVALIDDATA; | |
188 | } | |
189 | ||
190 | avctx->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); | |
191 | if (!avctx->extradata) { | |
192 | av_log(avctx, AV_LOG_ERROR, | |
193 | "Cannot allocate HEVC header of size %d.\n", avctx->extradata_size); | |
194 | libx265_encode_close(avctx); | |
195 | return AVERROR(ENOMEM); | |
196 | } | |
197 | ||
198 | memcpy(avctx->extradata, nal[0].payload, avctx->extradata_size); | |
199 | } | |
200 | ||
201 | return 0; | |
202 | } | |
203 | ||
204 | static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, | |
205 | const AVFrame *pic, int *got_packet) | |
206 | { | |
207 | libx265Context *ctx = avctx->priv_data; | |
208 | x265_picture x265pic; | |
209 | x265_picture x265pic_out = { { 0 } }; | |
210 | x265_nal *nal; | |
211 | uint8_t *dst; | |
212 | int payload = 0; | |
213 | int nnal; | |
214 | int ret; | |
215 | int i; | |
216 | ||
217 | x265_picture_init(ctx->params, &x265pic); | |
218 | ||
219 | if (pic) { | |
220 | for (i = 0; i < 3; i++) { | |
221 | x265pic.planes[i] = pic->data[i]; | |
222 | x265pic.stride[i] = pic->linesize[i]; | |
223 | } | |
224 | ||
225 | x265pic.pts = pic->pts; | |
226 | x265pic.bitDepth = av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth_minus1 + 1; | |
227 | } | |
228 | ||
229 | ret = x265_encoder_encode(ctx->encoder, &nal, &nnal, | |
230 | pic ? &x265pic : NULL, &x265pic_out); | |
231 | if (ret < 0) | |
232 | return AVERROR_EXTERNAL; | |
233 | ||
234 | if (!nnal) | |
235 | return 0; | |
236 | ||
237 | for (i = 0; i < nnal; i++) | |
238 | payload += nal[i].sizeBytes; | |
239 | ||
240 | ret = ff_alloc_packet(pkt, payload); | |
241 | if (ret < 0) { | |
242 | av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); | |
243 | return ret; | |
244 | } | |
245 | dst = pkt->data; | |
246 | ||
247 | for (i = 0; i < nnal; i++) { | |
248 | memcpy(dst, nal[i].payload, nal[i].sizeBytes); | |
249 | dst += nal[i].sizeBytes; | |
250 | ||
251 | if (is_keyframe(nal[i].type)) | |
252 | pkt->flags |= AV_PKT_FLAG_KEY; | |
253 | } | |
254 | ||
255 | pkt->pts = x265pic_out.pts; | |
256 | pkt->dts = x265pic_out.dts; | |
257 | ||
258 | *got_packet = 1; | |
259 | return 0; | |
260 | } | |
261 | ||
262 | static const enum AVPixelFormat x265_csp_eight[] = { | |
263 | AV_PIX_FMT_YUV420P, | |
264 | AV_PIX_FMT_YUV422P, | |
265 | AV_PIX_FMT_YUV444P, | |
266 | AV_PIX_FMT_NONE | |
267 | }; | |
268 | ||
269 | static const enum AVPixelFormat x265_csp_twelve[] = { | |
270 | AV_PIX_FMT_YUV420P, | |
271 | AV_PIX_FMT_YUV422P, | |
272 | AV_PIX_FMT_YUV444P, | |
273 | AV_PIX_FMT_YUV420P10, | |
274 | AV_PIX_FMT_YUV422P10, | |
275 | AV_PIX_FMT_YUV444P10, | |
276 | AV_PIX_FMT_NONE | |
277 | }; | |
278 | ||
279 | static av_cold void libx265_encode_init_csp(AVCodec *codec) | |
280 | { | |
281 | if (x265_max_bit_depth == 8) | |
282 | codec->pix_fmts = x265_csp_eight; | |
283 | else if (x265_max_bit_depth == 12) | |
284 | codec->pix_fmts = x265_csp_twelve; | |
285 | } | |
286 | ||
287 | #define OFFSET(x) offsetof(libx265Context, x) | |
288 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM | |
289 | static const AVOption options[] = { | |
290 | { "preset", "set the x265 preset", OFFSET(preset), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, | |
291 | { "tune", "set the x265 tune parameter", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, | |
292 | { "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 }, | |
293 | { NULL } | |
294 | }; | |
295 | ||
296 | static const AVClass class = { | |
297 | .class_name = "libx265", | |
298 | .item_name = av_default_item_name, | |
299 | .option = options, | |
300 | .version = LIBAVUTIL_VERSION_INT, | |
301 | }; | |
302 | ||
303 | static const AVCodecDefault x265_defaults[] = { | |
304 | { "b", "0" }, | |
305 | { NULL }, | |
306 | }; | |
307 | ||
308 | AVCodec ff_libx265_encoder = { | |
309 | .name = "libx265", | |
310 | .long_name = NULL_IF_CONFIG_SMALL("libx265 H.265 / HEVC"), | |
311 | .type = AVMEDIA_TYPE_VIDEO, | |
312 | .id = AV_CODEC_ID_HEVC, | |
313 | .init = libx265_encode_init, | |
314 | .init_static_data = libx265_encode_init_csp, | |
315 | .encode2 = libx265_encode_frame, | |
316 | .close = libx265_encode_close, | |
317 | .priv_data_size = sizeof(libx265Context), | |
318 | .priv_class = &class, | |
319 | .defaults = x265_defaults, | |
320 | .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, | |
321 | }; |