1 /*****************************************************************************
2 * x265.c: HEVC/H.265 video encoder
3 *****************************************************************************
4 * Copyright (C) 2013 Rafaël Carré
6 * Authors: Rafaël Carré <funman@videolanorg>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program 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
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_threads.h>
34 #include <vlc_codec.h>
38 /*****************************************************************************
40 *****************************************************************************/
41 static int Open (vlc_object_t *);
42 static void Close(vlc_object_t *);
45 set_description(N_("H.265/HEVC encoder (x265)"))
46 set_capability("encoder", 200)
47 set_callbacks(Open, Close)
48 set_category(CAT_INPUT)
49 set_subcategory(SUBCAT_INPUT_VCODEC)
59 mtime_t i_initial_delay;
68 static block_t *Encode(encoder_t *p_enc, picture_t *p_pict)
70 encoder_sys_t *p_sys = p_enc->p_sys;
73 x265_picture_init(&p_sys->param, &pic);
76 pic.pts = p_pict->date;
77 if (unlikely(p_sys->initial_date == 0)) {
78 p_sys->initial_date = p_pict->date;
80 p_sys->start = mdate();
84 for (int i = 0; i < p_pict->i_planes; i++) {
85 pic.planes[i] = p_pict->p[i].p_pixels;
86 pic.stride[i] = p_pict->p[i].i_pitch;
92 x265_encoder_encode(p_sys->h, &nal, &i_nal,
93 likely(p_pict) ? &pic : NULL, &pic);
99 for (uint32_t i = 0; i < i_nal; i++)
100 i_out += nal[i].sizeBytes;
103 if (unlikely(p_sys->write_headers)) {
104 i_extra = p_enc->fmt_out.i_extra;
105 p_sys->write_headers = false;
108 block_t *p_block = block_Alloc(i_extra + i_out);
112 if (unlikely(i_extra))
113 memcpy(p_block->p_buffer, p_enc->fmt_out.p_extra, i_extra);
115 /* all payloads are sequentially laid out in memory */
116 memcpy(p_block->p_buffer + i_extra, nal[0].payload, i_out);
118 /* This isn't really valid for streams with B-frames */
119 p_block->i_length = CLOCK_FREQ *
120 p_enc->fmt_in.video.i_frame_rate_base /
121 p_enc->fmt_in.video.i_frame_rate;
123 p_block->i_pts = p_sys->initial_date + pic.poc * p_block->i_length;
124 p_block->i_dts = p_sys->initial_date + p_sys->dts++ * p_block->i_length;
126 switch (pic.sliceType)
129 p_block->i_flags |= BLOCK_FLAG_TYPE_I;
132 p_block->i_flags |= BLOCK_FLAG_TYPE_P;
135 p_block->i_flags |= BLOCK_FLAG_TYPE_B;
140 msg_Dbg(p_enc, "%zu bytes (frame %"PRId64", %.2ffps)", p_block->i_buffer,
141 p_sys->dts, (float)p_sys->dts * CLOCK_FREQ / (mdate() - p_sys->start));
147 static int Open (vlc_object_t *p_this)
149 encoder_t *p_enc = (encoder_t *)p_this;
150 encoder_sys_t *p_sys;
152 if (p_enc->fmt_out.i_codec != VLC_CODEC_HEVC && !p_enc->b_force)
155 p_enc->fmt_out.i_cat = VIDEO_ES;
156 p_enc->fmt_out.i_codec = VLC_CODEC_HEVC;
157 p_enc->p_sys = p_sys = malloc(sizeof(encoder_sys_t));
161 p_enc->fmt_in.i_codec = VLC_CODEC_I420;
163 x265_param *param = &p_sys->param;
164 x265_param_default(param);
166 param->frameNumThreads = vlc_GetCPUCount();
167 param->bEnableWavefront = 0; // buggy in x265, use frame threading for now
168 param->maxCUSize = 16; /* use smaller macroblock */
171 param->fpsNum = p_enc->fmt_in.video.i_frame_rate;
172 param->fpsDenom = p_enc->fmt_in.video.i_frame_rate_base;
173 if (!param->fpsNum) {
178 if (p_enc->fmt_in.video.i_frame_rate_base) {
179 param->frameRate = p_enc->fmt_in.video.i_frame_rate /
180 p_enc->fmt_in.video.i_frame_rate_base;
182 param->frameRate = 25;
185 param->sourceWidth = p_enc->fmt_in.video.i_visible_width;
186 param->sourceHeight = p_enc->fmt_in.video.i_visible_height;
188 if (param->sourceWidth & (param->maxCUSize - 1)) {
189 msg_Err(p_enc, "Width (%d) must be a multiple of %d",
190 param->sourceWidth, param->maxCUSize);
194 if (param->sourceHeight & 7) {
195 msg_Err(p_enc, "Height (%d) must be a multiple of 8", param->sourceHeight);
200 if (p_enc->fmt_out.i_bitrate > 0) {
201 param->rc.bitrate = p_enc->fmt_out.i_bitrate / 1000;
202 param->rc.rateControlMode = X265_RC_ABR;
205 p_sys->h = x265_encoder_open(param);
206 if (p_sys->h == NULL) {
207 msg_Err(p_enc, "cannot open x265 encoder");
214 if (x265_encoder_headers(p_sys->h, &nal, &i_nal) < 0) {
215 msg_Err(p_enc, "cannot get x265 headers");
216 Close(VLC_OBJECT(p_enc));
221 for (uint32_t i = 0; i < i_nal; i++)
222 i_extra += nal[i].sizeBytes;
224 p_enc->fmt_out.i_extra = i_extra;
226 uint8_t *p_extra = p_enc->fmt_out.p_extra = malloc(i_extra);
228 Close(VLC_OBJECT(p_enc));
232 for (uint32_t i = 0; i < i_nal; i++) {
233 memcpy(p_extra, nal[i].payload, nal[i].sizeBytes);
234 p_extra += nal[i].sizeBytes;
238 p_sys->initial_date = 0;
239 p_sys->i_initial_delay = 0;
240 p_sys->write_headers = true;
242 p_enc->pf_encode_video = Encode;
243 p_enc->pf_encode_audio = NULL;
248 static void Close(vlc_object_t *p_this)
250 encoder_t *p_enc = (encoder_t *)p_this;
251 encoder_sys_t *p_sys = p_enc->p_sys;
253 x265_encoder_close(p_sys->h);