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; | |
114 | ||
115 | if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) { | |
116 | av_reduce(&sar_num, &sar_den, | |
117 | avctx->sample_aspect_ratio.num, | |
118 | avctx->sample_aspect_ratio.den, 65535); | |
119 | snprintf(sar, sizeof(sar), "%d:%d", sar_num, sar_den); | |
120 | if (x265_param_parse(ctx->params, "sar", sar) == X265_PARAM_BAD_VALUE) { | |
121 | av_log(avctx, AV_LOG_ERROR, "Invalid SAR: %d:%d.\n", sar_num, sar_den); | |
122 | return AVERROR_INVALIDDATA; | |
123 | } | |
124 | } | |
125 | ||
126 | switch (avctx->pix_fmt) { | |
127 | case AV_PIX_FMT_YUV420P: | |
128 | case AV_PIX_FMT_YUV420P10: | |
129 | ctx->params->internalCsp = X265_CSP_I420; | |
130 | break; | |
131 | case AV_PIX_FMT_YUV422P: | |
132 | case AV_PIX_FMT_YUV422P10: | |
133 | ctx->params->internalCsp = X265_CSP_I422; | |
134 | break; | |
135 | case AV_PIX_FMT_YUV444P: | |
136 | case AV_PIX_FMT_YUV444P10: | |
137 | ctx->params->internalCsp = X265_CSP_I444; | |
138 | break; | |
139 | } | |
140 | ||
141 | if (avctx->bit_rate > 0) { | |
142 | ctx->params->rc.bitrate = avctx->bit_rate / 1000; | |
143 | ctx->params->rc.rateControlMode = X265_RC_ABR; | |
144 | } | |
145 | ||
146 | if (!(avctx->flags & CODEC_FLAG_GLOBAL_HEADER)) | |
147 | ctx->params->bRepeatHeaders = 1; | |
148 | ||
149 | if (ctx->x265_opts) { | |
150 | AVDictionary *dict = NULL; | |
151 | AVDictionaryEntry *en = NULL; | |
152 | ||
153 | if (!av_dict_parse_string(&dict, ctx->x265_opts, "=", ":", 0)) { | |
154 | while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) { | |
155 | int parse_ret = x265_param_parse(ctx->params, en->key, en->value); | |
156 | ||
157 | switch (parse_ret) { | |
158 | case X265_PARAM_BAD_NAME: | |
159 | av_log(avctx, AV_LOG_WARNING, | |
160 | "Unknown option: %s.\n", en->key); | |
161 | break; | |
162 | case X265_PARAM_BAD_VALUE: | |
163 | av_log(avctx, AV_LOG_WARNING, | |
164 | "Invalid value for %s: %s.\n", en->key, en->value); | |
165 | break; | |
166 | default: | |
167 | break; | |
168 | } | |
169 | } | |
170 | av_dict_free(&dict); | |
171 | } | |
172 | } | |
173 | ||
174 | ctx->encoder = x265_encoder_open(ctx->params); | |
175 | if (!ctx->encoder) { | |
176 | av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n"); | |
177 | libx265_encode_close(avctx); | |
178 | return AVERROR_INVALIDDATA; | |
179 | } | |
180 | ||
181 | if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { | |
182 | avctx->extradata_size = x265_encoder_headers(ctx->encoder, &nal, &nnal); | |
183 | if (avctx->extradata_size <= 0) { | |
184 | av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n"); | |
185 | libx265_encode_close(avctx); | |
186 | return AVERROR_INVALIDDATA; | |
187 | } | |
188 | ||
189 | avctx->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); | |
190 | if (!avctx->extradata) { | |
191 | av_log(avctx, AV_LOG_ERROR, | |
192 | "Cannot allocate HEVC header of size %d.\n", avctx->extradata_size); | |
193 | libx265_encode_close(avctx); | |
194 | return AVERROR(ENOMEM); | |
195 | } | |
196 | ||
197 | memcpy(avctx->extradata, nal[0].payload, avctx->extradata_size); | |
198 | } | |
199 | ||
200 | return 0; | |
201 | } | |
202 | ||
203 | static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, | |
204 | const AVFrame *pic, int *got_packet) | |
205 | { | |
206 | libx265Context *ctx = avctx->priv_data; | |
207 | x265_picture x265pic; | |
208 | x265_picture x265pic_out = { { 0 } }; | |
209 | x265_nal *nal; | |
210 | uint8_t *dst; | |
211 | int payload = 0; | |
212 | int nnal; | |
213 | int ret; | |
214 | int i; | |
215 | ||
216 | x265_picture_init(ctx->params, &x265pic); | |
217 | ||
218 | if (pic) { | |
219 | for (i = 0; i < 3; i++) { | |
220 | x265pic.planes[i] = pic->data[i]; | |
221 | x265pic.stride[i] = pic->linesize[i]; | |
222 | } | |
223 | ||
224 | x265pic.pts = pic->pts; | |
225 | x265pic.bitDepth = av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth_minus1 + 1; | |
226 | } | |
227 | ||
228 | ret = x265_encoder_encode(ctx->encoder, &nal, &nnal, | |
229 | pic ? &x265pic : NULL, &x265pic_out); | |
230 | if (ret < 0) | |
231 | return AVERROR_EXTERNAL; | |
232 | ||
233 | if (!nnal) | |
234 | return 0; | |
235 | ||
236 | for (i = 0; i < nnal; i++) | |
237 | payload += nal[i].sizeBytes; | |
238 | ||
239 | ret = ff_alloc_packet(pkt, payload); | |
240 | if (ret < 0) { | |
241 | av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); | |
242 | return ret; | |
243 | } | |
244 | dst = pkt->data; | |
245 | ||
246 | for (i = 0; i < nnal; i++) { | |
247 | memcpy(dst, nal[i].payload, nal[i].sizeBytes); | |
248 | dst += nal[i].sizeBytes; | |
249 | ||
250 | if (is_keyframe(nal[i].type)) | |
251 | pkt->flags |= AV_PKT_FLAG_KEY; | |
252 | } | |
253 | ||
254 | pkt->pts = x265pic_out.pts; | |
255 | pkt->dts = x265pic_out.dts; | |
256 | ||
257 | *got_packet = 1; | |
258 | return 0; | |
259 | } | |
260 | ||
261 | static const enum AVPixelFormat x265_csp_eight[] = { | |
262 | AV_PIX_FMT_YUV420P, | |
263 | AV_PIX_FMT_YUV422P, | |
264 | AV_PIX_FMT_YUV444P, | |
265 | AV_PIX_FMT_NONE | |
266 | }; | |
267 | ||
268 | static const enum AVPixelFormat x265_csp_twelve[] = { | |
269 | AV_PIX_FMT_YUV420P, | |
270 | AV_PIX_FMT_YUV422P, | |
271 | AV_PIX_FMT_YUV444P, | |
272 | AV_PIX_FMT_YUV420P10, | |
273 | AV_PIX_FMT_YUV422P10, | |
274 | AV_PIX_FMT_YUV444P10, | |
275 | AV_PIX_FMT_NONE | |
276 | }; | |
277 | ||
278 | static av_cold void libx265_encode_init_csp(AVCodec *codec) | |
279 | { | |
280 | if (x265_max_bit_depth == 8) | |
281 | codec->pix_fmts = x265_csp_eight; | |
282 | else if (x265_max_bit_depth == 12) | |
283 | codec->pix_fmts = x265_csp_twelve; | |
284 | } | |
285 | ||
286 | #define OFFSET(x) offsetof(libx265Context, x) | |
287 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM | |
288 | static const AVOption options[] = { | |
289 | { "preset", "set the x265 preset", OFFSET(preset), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, | |
290 | { "tune", "set the x265 tune parameter", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, | |
291 | { "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 }, | |
292 | { NULL } | |
293 | }; | |
294 | ||
295 | static const AVClass class = { | |
296 | .class_name = "libx265", | |
297 | .item_name = av_default_item_name, | |
298 | .option = options, | |
299 | .version = LIBAVUTIL_VERSION_INT, | |
300 | }; | |
301 | ||
302 | static const AVCodecDefault x265_defaults[] = { | |
303 | { "b", "0" }, | |
304 | { NULL }, | |
305 | }; | |
306 | ||
307 | AVCodec ff_libx265_encoder = { | |
308 | .name = "libx265", | |
309 | .long_name = NULL_IF_CONFIG_SMALL("libx265 H.265 / HEVC"), | |
310 | .type = AVMEDIA_TYPE_VIDEO, | |
311 | .id = AV_CODEC_ID_HEVC, | |
312 | .init = libx265_encode_init, | |
313 | .init_static_data = libx265_encode_init_csp, | |
314 | .encode2 = libx265_encode_frame, | |
315 | .close = libx265_encode_close, | |
316 | .priv_data_size = sizeof(libx265Context), | |
317 | .priv_class = &class, | |
318 | .defaults = x265_defaults, | |
319 | .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, | |
320 | }; |