0fb8c0be8bbec8135a0207d769d346dabca425a1
[vlc.git] / modules / codec / x265.c
1 /*****************************************************************************
2  * x265.c: HEVC/H.265 video encoder
3  *****************************************************************************
4  * Copyright (C) 2013 Rafaël Carré
5  *
6  * Authors: Rafaël Carré <funman@videolanorg>
7  *
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.
12  *
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.
17  *
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  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #define VLC_MODULE_LICENSE VLC_LICENSE_GPL_2_PLUS
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_threads.h>
34 #include <vlc_sout.h>
35 #include <vlc_codec.h>
36
37 #include <x265.h>
38
39 /*****************************************************************************
40  * Module descriptor
41  *****************************************************************************/
42 static int  Open (vlc_object_t *);
43 static void Close(vlc_object_t *);
44
45 vlc_module_begin ()
46     set_description(N_("H.265/HEVC encoder (x265)"))
47     set_capability("encoder", 200)
48     set_callbacks(Open, Close)
49     set_category(CAT_INPUT)
50     set_subcategory(SUBCAT_INPUT_VCODEC)
51 vlc_module_end ()
52
53 typedef struct
54 {
55     x265_encoder    *h;
56     x265_param      param;
57
58     unsigned        frame_count;
59     vlc_tick_t      initial_date;
60 #ifndef NDEBUG
61     vlc_tick_t      start;
62 #endif
63 } encoder_sys_t;
64
65 static block_t *Encode(encoder_t *p_enc, picture_t *p_pict)
66 {
67     encoder_sys_t *p_sys = p_enc->p_sys;
68     x265_picture pic;
69
70     x265_picture_init(&p_sys->param, &pic);
71
72     if (likely(p_pict)) {
73         pic.pts = p_pict->date;
74         if (unlikely(p_sys->initial_date == VLC_TICK_INVALID)) {
75             p_sys->initial_date = p_pict->date;
76 #ifndef NDEBUG
77             p_sys->start = vlc_tick_now();
78 #endif
79         }
80
81         for (int i = 0; i < p_pict->i_planes; i++) {
82             pic.planes[i] = p_pict->p[i].p_pixels;
83             pic.stride[i] = p_pict->p[i].i_pitch;
84         }
85     }
86
87     x265_nal *nal;
88     uint32_t i_nal = 0;
89     x265_encoder_encode(p_sys->h, &nal, &i_nal,
90             likely(p_pict) ? &pic : NULL, &pic);
91
92     if (!i_nal)
93         return NULL;
94
95     int i_out = 0;
96     for (uint32_t i = 0; i < i_nal; i++)
97         i_out += nal[i].sizeBytes;
98
99     block_t *p_block = block_Alloc(i_out);
100     if (!p_block)
101         return NULL;
102
103     /* all payloads are sequentially laid out in memory */
104     memcpy(p_block->p_buffer, nal[0].payload, i_out);
105
106     /* This isn't really valid for streams with B-frames */
107     p_block->i_length = vlc_tick_from_samples(
108                 p_enc->fmt_in.video.i_frame_rate_base,
109                 p_enc->fmt_in.video.i_frame_rate );
110
111     p_block->i_pts = p_sys->initial_date + pic.poc * p_block->i_length;
112     p_block->i_dts = p_sys->initial_date + p_sys->frame_count++ * p_block->i_length;
113
114     switch (pic.sliceType)
115     {
116     case X265_TYPE_I:
117     case X265_TYPE_IDR:
118         p_block->i_flags |= BLOCK_FLAG_TYPE_I;
119         break;
120     case X265_TYPE_P:
121         p_block->i_flags |= BLOCK_FLAG_TYPE_P;
122         break;
123     case X265_TYPE_B:
124     case X265_TYPE_BREF:
125         p_block->i_flags |= BLOCK_FLAG_TYPE_B;
126         break;
127     }
128
129 #ifndef NDEBUG
130     msg_Dbg(p_enc, "%zu bytes (frame %u, %.2ffps)", p_block->i_buffer,
131         p_sys->frame_count, (float)p_sys->frame_count * CLOCK_FREQ / (vlc_tick_now() - p_sys->start));
132 #endif
133
134     return p_block;
135 }
136
137 static int  Open (vlc_object_t *p_this)
138 {
139     encoder_t     *p_enc = (encoder_t *)p_this;
140     encoder_sys_t *p_sys;
141
142     if (p_enc->fmt_out.i_codec != VLC_CODEC_HEVC && !p_enc->obj.force)
143         return VLC_EGENERIC;
144
145     p_enc->fmt_out.i_cat = VIDEO_ES;
146     p_enc->fmt_out.i_codec = VLC_CODEC_HEVC;
147     p_enc->p_sys = p_sys = malloc(sizeof(encoder_sys_t));
148     if (!p_sys)
149         return VLC_ENOMEM;
150
151     p_enc->fmt_in.i_codec = VLC_CODEC_I420;
152
153     x265_param *param = &p_sys->param;
154     x265_param_default(param);
155
156     param->frameNumThreads = vlc_GetCPUCount();
157     param->bEnableWavefront = 0; // buggy in x265, use frame threading for now
158     param->maxCUSize = 16; /* use smaller macroblock */
159
160 #if X265_BUILD >= 6
161     param->fpsNum = p_enc->fmt_in.video.i_frame_rate;
162     param->fpsDenom = p_enc->fmt_in.video.i_frame_rate_base;
163     if (!param->fpsNum) {
164         param->fpsNum = 25;
165         param->fpsDenom = 1;
166     }
167 #else
168     if (p_enc->fmt_in.video.i_frame_rate_base) {
169         param->frameRate = p_enc->fmt_in.video.i_frame_rate /
170             p_enc->fmt_in.video.i_frame_rate_base;
171     } else {
172         param->frameRate = 25;
173     }
174 #endif
175     param->sourceWidth = p_enc->fmt_in.video.i_visible_width;
176     param->sourceHeight = p_enc->fmt_in.video.i_visible_height;
177
178     if (param->sourceWidth & (param->maxCUSize - 1)) {
179         msg_Err(p_enc, "Width (%d) must be a multiple of %d",
180             param->sourceWidth, param->maxCUSize);
181         free(p_sys);
182         return VLC_EGENERIC;
183     }
184     if (param->sourceHeight & 7) {
185         msg_Err(p_enc, "Height (%d) must be a multiple of 8", param->sourceHeight);
186         free(p_sys);
187         return VLC_EGENERIC;
188     }
189
190     if (p_enc->fmt_out.i_bitrate > 0) {
191         param->rc.bitrate = p_enc->fmt_out.i_bitrate / 1000;
192         param->rc.rateControlMode = X265_RC_ABR;
193     }
194
195     p_sys->h = x265_encoder_open(param);
196     if (p_sys->h == NULL) {
197         msg_Err(p_enc, "cannot open x265 encoder");
198         free(p_sys);
199         return VLC_EGENERIC;
200     }
201
202     x265_nal *nal;
203     uint32_t i_nal;
204     if (x265_encoder_headers(p_sys->h, &nal, &i_nal) < 0) {
205         msg_Err(p_enc, "cannot get x265 headers");
206         Close(VLC_OBJECT(p_enc));
207         return VLC_EGENERIC;
208     }
209
210     size_t i_extra = 0;
211     for (uint32_t i = 0; i < i_nal; i++)
212         i_extra += nal[i].sizeBytes;
213
214     p_enc->fmt_out.i_extra = i_extra;
215
216     uint8_t *p_extra = p_enc->fmt_out.p_extra = malloc(i_extra);
217     if (!p_extra) {
218         Close(VLC_OBJECT(p_enc));
219         return VLC_ENOMEM;
220     }
221
222     for (uint32_t i = 0; i < i_nal; i++) {
223         memcpy(p_extra, nal[i].payload, nal[i].sizeBytes);
224         p_extra += nal[i].sizeBytes;
225     }
226
227     p_sys->frame_count = 0;
228     p_sys->initial_date = VLC_TICK_INVALID;
229
230     p_enc->pf_encode_video = Encode;
231     p_enc->pf_encode_audio = NULL;
232
233     return VLC_SUCCESS;
234 }
235
236 static void Close(vlc_object_t *p_this)
237 {
238     encoder_t     *p_enc = (encoder_t *)p_this;
239     encoder_sys_t *p_sys = p_enc->p_sys;
240
241     x265_encoder_close(p_sys->h);
242
243     free(p_sys);
244 }