FreeRDP
Loading...
Searching...
No Matches
h264_ffmpeg.c
1
21#include <freerdp/config.h>
22
23#include <winpr/wlog.h>
24#include <freerdp/log.h>
25#include <freerdp/codec/h264.h>
26#include <libavcodec/avcodec.h>
27#include <libavutil/opt.h>
28#include <libswscale/swscale.h>
29
30#include "h264.h"
31
32#ifdef WITH_VIDEOTOOLBOX
33#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 9, 0)
34#include <libavutil/hwcontext.h>
35#else
36#pragma warning You have asked for VideoToolbox decoding, \
37 but your version of libavutil is too old !Disabling.
38#undef WITH_VIDEOTOOLBOX
39#endif
40#endif
41
42#ifdef WITH_VAAPI
43#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 9, 0)
44#include <libavutil/hwcontext.h>
45#else
46#pragma warning You have asked for VA - API decoding, \
47 but your version of libavutil is too old !Disabling.
48#undef WITH_VAAPI
49#endif
50#endif
51
52/* Fallback support for older libavcodec versions */
53#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100)
54#define AV_CODEC_ID_H264 CODEC_ID_H264
55#endif
56
57#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 34, 2)
58#define AV_CODEC_FLAG_LOOP_FILTER CODEC_FLAG_LOOP_FILTER
59#define AV_CODEC_CAP_TRUNCATED CODEC_CAP_TRUNCATED
60#define AV_CODEC_FLAG_TRUNCATED CODEC_FLAG_TRUNCATED
61#endif
62
63#if LIBAVUTIL_VERSION_MAJOR < 52
64#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
65#endif
66
67#if defined(WITH_VAAPI) || defined(WITH_VIDEOTOOLBOX)
68static const char* av_format_str(int32_t format)
69{
70#define EVCASE(x) \
71 case x: \
72 return #x
73
74 switch (format)
75 {
76 EVCASE(AV_PIX_FMT_NONE);
77 EVCASE(AV_PIX_FMT_YUV420P);
78 EVCASE(AV_PIX_FMT_YUYV422);
79 EVCASE(AV_PIX_FMT_RGB24);
80 EVCASE(AV_PIX_FMT_BGR24);
81 EVCASE(AV_PIX_FMT_YUV422P);
82 EVCASE(AV_PIX_FMT_YUV444P);
83 EVCASE(AV_PIX_FMT_YUV410P);
84 EVCASE(AV_PIX_FMT_YUV411P);
85 EVCASE(AV_PIX_FMT_GRAY8);
86 EVCASE(AV_PIX_FMT_MONOWHITE);
87 EVCASE(AV_PIX_FMT_MONOBLACK);
88 EVCASE(AV_PIX_FMT_PAL8);
89 EVCASE(AV_PIX_FMT_YUVJ420P);
90 EVCASE(AV_PIX_FMT_YUVJ422P);
91 EVCASE(AV_PIX_FMT_YUVJ444P);
92 EVCASE(AV_PIX_FMT_UYVY422);
93 EVCASE(AV_PIX_FMT_UYYVYY411);
94 EVCASE(AV_PIX_FMT_BGR8);
95 EVCASE(AV_PIX_FMT_BGR4);
96 EVCASE(AV_PIX_FMT_BGR4_BYTE);
97 EVCASE(AV_PIX_FMT_RGB8);
98 EVCASE(AV_PIX_FMT_RGB4);
99 EVCASE(AV_PIX_FMT_RGB4_BYTE);
100 EVCASE(AV_PIX_FMT_NV12);
101 EVCASE(AV_PIX_FMT_NV21);
102 EVCASE(AV_PIX_FMT_ARGB);
103 EVCASE(AV_PIX_FMT_RGBA);
104 EVCASE(AV_PIX_FMT_ABGR);
105 EVCASE(AV_PIX_FMT_BGRA);
106 EVCASE(AV_PIX_FMT_GRAY16BE);
107 EVCASE(AV_PIX_FMT_GRAY16LE);
108 EVCASE(AV_PIX_FMT_YUV440P);
109 EVCASE(AV_PIX_FMT_YUVJ440P);
110 EVCASE(AV_PIX_FMT_YUVA420P);
111 EVCASE(AV_PIX_FMT_RGB48BE);
112 EVCASE(AV_PIX_FMT_RGB48LE);
113 EVCASE(AV_PIX_FMT_RGB565BE);
114 EVCASE(AV_PIX_FMT_RGB565LE);
115 EVCASE(AV_PIX_FMT_RGB555BE);
116 EVCASE(AV_PIX_FMT_RGB555LE);
117 EVCASE(AV_PIX_FMT_BGR565BE);
118 EVCASE(AV_PIX_FMT_BGR565LE);
119 EVCASE(AV_PIX_FMT_BGR555BE);
120 EVCASE(AV_PIX_FMT_BGR555LE);
121 EVCASE(AV_PIX_FMT_VAAPI);
122 EVCASE(AV_PIX_FMT_YUV420P16LE);
123 EVCASE(AV_PIX_FMT_YUV420P16BE);
124 EVCASE(AV_PIX_FMT_YUV422P16LE);
125 EVCASE(AV_PIX_FMT_YUV422P16BE);
126 EVCASE(AV_PIX_FMT_YUV444P16LE);
127 EVCASE(AV_PIX_FMT_YUV444P16BE);
128 EVCASE(AV_PIX_FMT_DXVA2_VLD);
129 EVCASE(AV_PIX_FMT_RGB444LE);
130 EVCASE(AV_PIX_FMT_RGB444BE);
131 EVCASE(AV_PIX_FMT_BGR444LE);
132 EVCASE(AV_PIX_FMT_BGR444BE);
133 EVCASE(AV_PIX_FMT_GRAY8A);
134 EVCASE(AV_PIX_FMT_BGR48BE);
135 EVCASE(AV_PIX_FMT_BGR48LE);
136 EVCASE(AV_PIX_FMT_YUV420P9BE);
137 EVCASE(AV_PIX_FMT_YUV420P9LE);
138 EVCASE(AV_PIX_FMT_YUV420P10BE);
139 EVCASE(AV_PIX_FMT_YUV420P10LE);
140 EVCASE(AV_PIX_FMT_YUV422P10BE);
141 EVCASE(AV_PIX_FMT_YUV422P10LE);
142 EVCASE(AV_PIX_FMT_YUV444P9BE);
143 EVCASE(AV_PIX_FMT_YUV444P9LE);
144 EVCASE(AV_PIX_FMT_YUV444P10BE);
145 EVCASE(AV_PIX_FMT_YUV444P10LE);
146 EVCASE(AV_PIX_FMT_YUV422P9BE);
147 EVCASE(AV_PIX_FMT_YUV422P9LE);
148 EVCASE(AV_PIX_FMT_GBR24P);
149 EVCASE(AV_PIX_FMT_GBRP9BE);
150 EVCASE(AV_PIX_FMT_GBRP9LE);
151 EVCASE(AV_PIX_FMT_GBRP10BE);
152 EVCASE(AV_PIX_FMT_GBRP10LE);
153 EVCASE(AV_PIX_FMT_GBRP16BE);
154 EVCASE(AV_PIX_FMT_GBRP16LE);
155 EVCASE(AV_PIX_FMT_YUVA422P);
156 EVCASE(AV_PIX_FMT_YUVA444P);
157 EVCASE(AV_PIX_FMT_YUVA420P9BE);
158 EVCASE(AV_PIX_FMT_YUVA420P9LE);
159 EVCASE(AV_PIX_FMT_YUVA422P9BE);
160 EVCASE(AV_PIX_FMT_YUVA422P9LE);
161 EVCASE(AV_PIX_FMT_YUVA444P9BE);
162 EVCASE(AV_PIX_FMT_YUVA444P9LE);
163 EVCASE(AV_PIX_FMT_YUVA420P10BE);
164 EVCASE(AV_PIX_FMT_YUVA420P10LE);
165 EVCASE(AV_PIX_FMT_YUVA422P10BE);
166 EVCASE(AV_PIX_FMT_YUVA422P10LE);
167 EVCASE(AV_PIX_FMT_YUVA444P10BE);
168 EVCASE(AV_PIX_FMT_YUVA444P10LE);
169 EVCASE(AV_PIX_FMT_YUVA420P16BE);
170 EVCASE(AV_PIX_FMT_YUVA420P16LE);
171 EVCASE(AV_PIX_FMT_YUVA422P16BE);
172 EVCASE(AV_PIX_FMT_YUVA422P16LE);
173 EVCASE(AV_PIX_FMT_YUVA444P16BE);
174 EVCASE(AV_PIX_FMT_YUVA444P16LE);
175 EVCASE(AV_PIX_FMT_VDPAU);
176 EVCASE(AV_PIX_FMT_XYZ12LE);
177 EVCASE(AV_PIX_FMT_XYZ12BE);
178 EVCASE(AV_PIX_FMT_NV16);
179 EVCASE(AV_PIX_FMT_NV20LE);
180 EVCASE(AV_PIX_FMT_NV20BE);
181 EVCASE(AV_PIX_FMT_RGBA64BE);
182 EVCASE(AV_PIX_FMT_RGBA64LE);
183 EVCASE(AV_PIX_FMT_BGRA64BE);
184 EVCASE(AV_PIX_FMT_BGRA64LE);
185 EVCASE(AV_PIX_FMT_YVYU422);
186 EVCASE(AV_PIX_FMT_YA16BE);
187 EVCASE(AV_PIX_FMT_YA16LE);
188 EVCASE(AV_PIX_FMT_GBRAP);
189 EVCASE(AV_PIX_FMT_GBRAP16BE);
190 EVCASE(AV_PIX_FMT_GBRAP16LE);
191 EVCASE(AV_PIX_FMT_QSV);
192 EVCASE(AV_PIX_FMT_MMAL);
193 EVCASE(AV_PIX_FMT_D3D11VA_VLD);
194 EVCASE(AV_PIX_FMT_CUDA);
195 EVCASE(AV_PIX_FMT_0RGB);
196 EVCASE(AV_PIX_FMT_RGB0);
197 EVCASE(AV_PIX_FMT_0BGR);
198 EVCASE(AV_PIX_FMT_BGR0);
199 EVCASE(AV_PIX_FMT_YUV420P12BE);
200 EVCASE(AV_PIX_FMT_YUV420P12LE);
201 EVCASE(AV_PIX_FMT_YUV420P14BE);
202 EVCASE(AV_PIX_FMT_YUV420P14LE);
203 EVCASE(AV_PIX_FMT_YUV422P12BE);
204 EVCASE(AV_PIX_FMT_YUV422P12LE);
205 EVCASE(AV_PIX_FMT_YUV422P14BE);
206 EVCASE(AV_PIX_FMT_YUV422P14LE);
207 EVCASE(AV_PIX_FMT_YUV444P12BE);
208 EVCASE(AV_PIX_FMT_YUV444P12LE);
209 EVCASE(AV_PIX_FMT_YUV444P14BE);
210 EVCASE(AV_PIX_FMT_YUV444P14LE);
211 EVCASE(AV_PIX_FMT_GBRP12BE);
212 EVCASE(AV_PIX_FMT_GBRP12LE);
213 EVCASE(AV_PIX_FMT_GBRP14BE);
214 EVCASE(AV_PIX_FMT_GBRP14LE);
215 EVCASE(AV_PIX_FMT_YUVJ411P);
216 EVCASE(AV_PIX_FMT_BAYER_BGGR8);
217 EVCASE(AV_PIX_FMT_BAYER_RGGB8);
218 EVCASE(AV_PIX_FMT_BAYER_GBRG8);
219 EVCASE(AV_PIX_FMT_BAYER_GRBG8);
220 EVCASE(AV_PIX_FMT_BAYER_BGGR16LE);
221 EVCASE(AV_PIX_FMT_BAYER_BGGR16BE);
222 EVCASE(AV_PIX_FMT_BAYER_RGGB16LE);
223 EVCASE(AV_PIX_FMT_BAYER_RGGB16BE);
224 EVCASE(AV_PIX_FMT_BAYER_GBRG16LE);
225 EVCASE(AV_PIX_FMT_BAYER_GBRG16BE);
226 EVCASE(AV_PIX_FMT_BAYER_GRBG16LE);
227 EVCASE(AV_PIX_FMT_BAYER_GRBG16BE);
228 EVCASE(AV_PIX_FMT_YUV440P10LE);
229 EVCASE(AV_PIX_FMT_YUV440P10BE);
230 EVCASE(AV_PIX_FMT_YUV440P12LE);
231 EVCASE(AV_PIX_FMT_YUV440P12BE);
232 EVCASE(AV_PIX_FMT_AYUV64LE);
233 EVCASE(AV_PIX_FMT_AYUV64BE);
234 EVCASE(AV_PIX_FMT_VIDEOTOOLBOX);
235 EVCASE(AV_PIX_FMT_P010LE);
236 EVCASE(AV_PIX_FMT_P010BE);
237 EVCASE(AV_PIX_FMT_GBRAP12BE);
238 EVCASE(AV_PIX_FMT_GBRAP12LE);
239 EVCASE(AV_PIX_FMT_GBRAP10BE);
240 EVCASE(AV_PIX_FMT_GBRAP10LE);
241 EVCASE(AV_PIX_FMT_MEDIACODEC);
242 EVCASE(AV_PIX_FMT_GRAY12BE);
243 EVCASE(AV_PIX_FMT_GRAY12LE);
244 EVCASE(AV_PIX_FMT_GRAY10BE);
245 EVCASE(AV_PIX_FMT_GRAY10LE);
246 EVCASE(AV_PIX_FMT_P016LE);
247 EVCASE(AV_PIX_FMT_P016BE);
248 EVCASE(AV_PIX_FMT_D3D11);
249 EVCASE(AV_PIX_FMT_GRAY9BE);
250 EVCASE(AV_PIX_FMT_GRAY9LE);
251 EVCASE(AV_PIX_FMT_GBRPF32BE);
252 EVCASE(AV_PIX_FMT_GBRPF32LE);
253 EVCASE(AV_PIX_FMT_GBRAPF32BE);
254 EVCASE(AV_PIX_FMT_GBRAPF32LE);
255 EVCASE(AV_PIX_FMT_DRM_PRIME);
256 EVCASE(AV_PIX_FMT_OPENCL);
257 EVCASE(AV_PIX_FMT_GRAY14BE);
258 EVCASE(AV_PIX_FMT_GRAY14LE);
259 EVCASE(AV_PIX_FMT_GRAYF32BE);
260 EVCASE(AV_PIX_FMT_GRAYF32LE);
261 EVCASE(AV_PIX_FMT_YUVA422P12BE);
262 EVCASE(AV_PIX_FMT_YUVA422P12LE);
263 EVCASE(AV_PIX_FMT_YUVA444P12BE);
264 EVCASE(AV_PIX_FMT_YUVA444P12LE);
265 EVCASE(AV_PIX_FMT_NV24);
266 EVCASE(AV_PIX_FMT_NV42);
267 EVCASE(AV_PIX_FMT_VULKAN);
268 EVCASE(AV_PIX_FMT_Y210BE);
269 EVCASE(AV_PIX_FMT_Y210LE);
270 EVCASE(AV_PIX_FMT_X2RGB10LE);
271 EVCASE(AV_PIX_FMT_X2RGB10BE);
272 EVCASE(AV_PIX_FMT_X2BGR10LE);
273 EVCASE(AV_PIX_FMT_X2BGR10BE);
274 EVCASE(AV_PIX_FMT_P210BE);
275 EVCASE(AV_PIX_FMT_P210LE);
276 EVCASE(AV_PIX_FMT_P410BE);
277 EVCASE(AV_PIX_FMT_P410LE);
278 EVCASE(AV_PIX_FMT_P216BE);
279 EVCASE(AV_PIX_FMT_P216LE);
280 EVCASE(AV_PIX_FMT_P416BE);
281 EVCASE(AV_PIX_FMT_P416LE);
282 EVCASE(AV_PIX_FMT_VUYA);
283 EVCASE(AV_PIX_FMT_RGBAF16BE);
284 EVCASE(AV_PIX_FMT_RGBAF16LE);
285 EVCASE(AV_PIX_FMT_VUYX);
286 EVCASE(AV_PIX_FMT_P012LE);
287 EVCASE(AV_PIX_FMT_P012BE);
288 EVCASE(AV_PIX_FMT_Y212BE);
289 EVCASE(AV_PIX_FMT_Y212LE);
290 EVCASE(AV_PIX_FMT_XV30BE);
291 EVCASE(AV_PIX_FMT_XV30LE);
292 EVCASE(AV_PIX_FMT_XV36BE);
293 EVCASE(AV_PIX_FMT_XV36LE);
294 EVCASE(AV_PIX_FMT_RGBF32BE);
295 EVCASE(AV_PIX_FMT_RGBF32LE);
296 EVCASE(AV_PIX_FMT_RGBAF32BE);
297 EVCASE(AV_PIX_FMT_RGBAF32LE);
298 EVCASE(AV_PIX_FMT_P212BE);
299 EVCASE(AV_PIX_FMT_P212LE);
300 EVCASE(AV_PIX_FMT_P412BE);
301 EVCASE(AV_PIX_FMT_P412LE);
302 EVCASE(AV_PIX_FMT_GBRAP14BE);
303 EVCASE(AV_PIX_FMT_GBRAP14LE);
304 EVCASE(AV_PIX_FMT_D3D12);
305 EVCASE(AV_PIX_FMT_NB);
306 default:
307 return "AV_PIX_FMT_UNKNOWN";
308 }
309}
310#endif
311
312/* Ubuntu 14.04 ships without the functions provided by avutil,
313 * so define error to string methods here. */
314#if !defined(av_err2str)
315static inline char* error_string(char* errbuf, size_t errbuf_size, int errnum)
316{
317 av_strerror(errnum, errbuf, errbuf_size);
318 return errbuf;
319}
320
321#define av_err2str(errnum) error_string((char[64])WINPR_C_ARRAY_INIT, 64, errnum)
322#endif
323
324#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
325static const char* get_vaapi_device(void)
326{
327 static char device[MAX_PATH] = WINPR_C_ARRAY_INIT;
328 static bool initialized = false;
329 if (!initialized)
330 {
331 initialized = true;
332 // NOLINTNEXTLINE(concurrency-mt-unsafe)
333 const char* env = getenv("FREERDP_VAAPI_DEVICE");
334 if (env)
335 (void)_snprintf(device, sizeof(device), "%s", env);
336 else
337 (void)_snprintf(device, sizeof(device), "/dev/dri/renderD128");
338 }
339 return device;
340}
341#endif
342
343typedef struct
344{
345 const AVCodec* codecDecoder;
346 AVCodecContext* codecDecoderContext;
347 const AVCodec* codecEncoder;
348 AVCodecContext* codecEncoderContext;
349 AVCodecParserContext* codecParser;
350 AVFrame* videoFrame;
351#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
352 AVPacket bufferpacket;
353#endif
354 AVPacket* packet;
355#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING) || defined(WITH_VIDEOTOOLBOX)
356 AVBufferRef* hwctx;
357 struct SwsContext* swsctx;
358 int hwFrameSupportsNativeFormat;
359 AVFrame* hwVideoFrame;
360 AVFrame* cpuVideoFrame;
361 enum AVPixelFormat hw_pix_fmt;
362#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100) || defined(WITH_VIDEOTOOLBOX)
363 AVBufferRef* hw_frames_ctx;
364#endif
365
366#endif
367} H264_CONTEXT_LIBAVCODEC;
368
369static void libavcodec_destroy_encoder_context(H264_CONTEXT* WINPR_RESTRICT h264)
370{
371 H264_CONTEXT_LIBAVCODEC* sys = nullptr;
372
373 if (!h264 || !h264->subsystem)
374 return;
375
376 sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
377
378 if (sys->codecEncoderContext)
379 {
380#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100)
381 avcodec_free_context(&sys->codecEncoderContext);
382#else
383 avcodec_close(sys->codecEncoderContext);
384 av_free(sys->codecEncoderContext);
385#endif
386 }
387
388 sys->codecEncoderContext = nullptr;
389}
390
391#ifdef WITH_VAAPI_H264_ENCODING
392static int set_hw_frames_ctx(H264_CONTEXT* WINPR_RESTRICT h264)
393{
394 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
395 AVBufferRef* hw_frames_ref = nullptr;
396 AVHWFramesContext* frames_ctx = nullptr;
397 int err = 0;
398
399 if (!(hw_frames_ref = av_hwframe_ctx_alloc(sys->hwctx)))
400 {
401 WLog_Print(h264->log, WLOG_ERROR, "Failed to create VAAPI frame context");
402 return -1;
403 }
404 frames_ctx = (AVHWFramesContext*)(hw_frames_ref->data);
405 frames_ctx->format = AV_PIX_FMT_VAAPI;
406 frames_ctx->sw_format = AV_PIX_FMT_NV12;
407 frames_ctx->width = sys->codecEncoderContext->width;
408 frames_ctx->height = sys->codecEncoderContext->height;
409 frames_ctx->initial_pool_size = 20;
410 if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0)
411 {
412 WLog_Print(h264->log, WLOG_ERROR,
413 "Failed to initialize VAAPI frame context."
414 "Error code: %s",
415 av_err2str(err));
416 av_buffer_unref(&hw_frames_ref);
417 return err;
418 }
419 sys->codecEncoderContext->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
420 if (!sys->codecEncoderContext->hw_frames_ctx)
421 err = AVERROR(ENOMEM);
422
423 av_buffer_unref(&hw_frames_ref);
424 return err;
425}
426#endif
427
428static BOOL libavcodec_create_encoder_context(H264_CONTEXT* WINPR_RESTRICT h264)
429{
430 BOOL recreate = FALSE;
431 H264_CONTEXT_LIBAVCODEC* sys = nullptr;
432
433 if (!h264 || !h264->subsystem)
434 return FALSE;
435
436 if ((h264->width > INT_MAX) || (h264->height > INT_MAX))
437 return FALSE;
438
439 sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
440 if (!sys || !sys->codecEncoder)
441 return FALSE;
442
443 recreate = !sys->codecEncoderContext;
444
445 if (sys->codecEncoderContext)
446 {
447 if ((sys->codecEncoderContext->width != (int)h264->width) ||
448 (sys->codecEncoderContext->height != (int)h264->height))
449 recreate = TRUE;
450 }
451
452 if (!recreate)
453 return TRUE;
454
455 libavcodec_destroy_encoder_context(h264);
456
457 sys->codecEncoderContext = avcodec_alloc_context3(sys->codecEncoder);
458
459 if (!sys->codecEncoderContext)
460 goto EXCEPTION;
461
462 switch (h264->RateControlMode)
463 {
464 case H264_RATECONTROL_VBR:
465 sys->codecEncoderContext->bit_rate = h264->BitRate;
466 break;
467
468 case H264_RATECONTROL_CQP:
469 if (av_opt_set_int(sys->codecEncoderContext, "qp", h264->QP, AV_OPT_SEARCH_CHILDREN) <
470 0)
471 {
472 WLog_Print(h264->log, WLOG_ERROR, "av_opt_set_int failed");
473 }
474 break;
475
476 default:
477 break;
478 }
479
480 sys->codecEncoderContext->width = (int)MIN(INT32_MAX, h264->width);
481 sys->codecEncoderContext->height = (int)MIN(INT32_MAX, h264->height);
482 sys->codecEncoderContext->delay = 0;
483#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 13, 100)
484 sys->codecEncoderContext->framerate =
485 (AVRational){ WINPR_ASSERTING_INT_CAST(int, h264->FrameRate), 1 };
486#endif
487 sys->codecEncoderContext->time_base =
488 (AVRational){ 1, WINPR_ASSERTING_INT_CAST(int, h264->FrameRate) };
489 av_opt_set(sys->codecEncoderContext, "tune", "zerolatency", AV_OPT_SEARCH_CHILDREN);
490
491 sys->codecEncoderContext->flags |= AV_CODEC_FLAG_LOOP_FILTER;
492
493#ifdef WITH_VAAPI_H264_ENCODING
494 if (sys->hwctx)
495 {
496 av_opt_set(sys->codecEncoderContext, "preset", "veryslow", AV_OPT_SEARCH_CHILDREN);
497
498 sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_VAAPI;
499 /* set hw_frames_ctx for encoder's AVCodecContext */
500 if (set_hw_frames_ctx(h264) < 0)
501 goto EXCEPTION;
502 }
503 else
504#endif
505 {
506 av_opt_set(sys->codecEncoderContext, "preset", "medium", AV_OPT_SEARCH_CHILDREN);
507 sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_YUV420P;
508 }
509
510 if (avcodec_open2(sys->codecEncoderContext, sys->codecEncoder, nullptr) < 0)
511 goto EXCEPTION;
512
513 return TRUE;
514EXCEPTION:
515 libavcodec_destroy_encoder_context(h264);
516 return FALSE;
517}
518
519#if defined(WITH_VAAPI) || defined(WITH_VIDEOTOOLBOX)
520static int hw_supports_target_format(AVBufferRef* hwframectx, enum AVPixelFormat target)
521{
522 WINPR_ASSERT(hwframectx);
523
524 enum AVPixelFormat* formats = nullptr;
525 int rc = av_hwframe_transfer_get_formats(hwframectx, AV_HWFRAME_TRANSFER_DIRECTION_FROM,
526 &formats, 0);
527 if (rc == 0)
528 {
529 enum AVPixelFormat* it = formats;
530 while ((rc == 0) && (*it != AV_PIX_FMT_NONE))
531 {
532 enum AVPixelFormat cur = *it++;
533 if (cur == target)
534 rc = 1;
535 }
536 }
537
538 av_free(formats);
539 return rc;
540}
541#endif
542
543static int libavcodec_decompress(H264_CONTEXT* WINPR_RESTRICT h264,
544 const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize)
545{
546 union
547 {
548 const BYTE* cpv;
549 BYTE* pv;
550 } cnv;
551 int rc = -1;
552 int status = 0;
553 int gotFrame = 0;
554 AVPacket* packet = nullptr;
555
556 WINPR_ASSERT(h264);
557 WINPR_ASSERT(pSrcData || (SrcSize == 0));
558
559 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
560 BYTE** pYUVData = h264->pYUVData;
561 UINT32* iStride = h264->iStride;
562
563 WINPR_ASSERT(sys);
564
565#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
566 packet = &sys->bufferpacket;
567 WINPR_ASSERT(packet);
568 av_init_packet(packet);
569#else
570 packet = av_packet_alloc();
571#endif
572 if (!packet)
573 {
574 WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate AVPacket");
575 goto fail;
576 }
577
578 cnv.cpv = pSrcData;
579 packet->data = cnv.pv;
580 packet->size = (int)MIN(SrcSize, INT32_MAX);
581
582 WINPR_ASSERT(sys->codecDecoderContext);
583 /* avcodec_decode_video2 is deprecated with libavcodec 57.48.101 */
584#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
585 status = avcodec_send_packet(sys->codecDecoderContext, packet);
586
587 if (status < 0)
588 {
589 WLog_Print(h264->log, WLOG_ERROR, "Failed to decode video frame (status=%d)", status);
590 goto fail;
591 }
592
593 sys->videoFrame->format = AV_PIX_FMT_YUV420P;
594
595#if defined(WITH_VAAPI) || defined(WITH_VIDEOTOOLBOX)
596 status = avcodec_receive_frame(sys->codecDecoderContext,
597 sys->hwctx ? sys->hwVideoFrame : sys->videoFrame);
598#else
599 status = avcodec_receive_frame(sys->codecDecoderContext, sys->videoFrame);
600#endif
601 if (status == AVERROR(EAGAIN))
602 {
603 rc = 0;
604 goto fail;
605 }
606
607 if (status == 0)
608 gotFrame = 1;
609#else
610#if defined(WITH_VAAPI) || defined(WITH_VIDEOTOOLBOX)
611 status =
612 avcodec_decode_video2(sys->codecDecoderContext,
613 sys->hwctx ? sys->hwVideoFrame : sys->videoFrame, &gotFrame, packet);
614#else
615 status = avcodec_decode_video2(sys->codecDecoderContext, sys->videoFrame, &gotFrame, packet);
616#endif
617#endif
618 if (status < 0)
619 {
620 WLog_Print(h264->log, WLOG_ERROR, "Failed to decode video frame (status=%d)", status);
621 goto fail;
622 }
623
624#if defined(WITH_VAAPI) || defined(WITH_VIDEOTOOLBOX)
625
626 if (sys->hwctx)
627 {
628 AVFrame* target = sys->videoFrame;
629 if (sys->hwFrameSupportsNativeFormat < 0)
630 {
631 const int res = hw_supports_target_format(sys->codecDecoderContext->hw_frames_ctx,
632 sys->videoFrame->format);
633 if (res < 0)
634 status = res;
635 else
636 {
637 sys->hwFrameSupportsNativeFormat = res;
638 const char* msg = "hardware supported copy";
639 if (res == 0)
640 msg = "swscale format conversion";
641 WLog_Print(h264->log, WLOG_DEBUG, "formats: { src:%s, dst:%s } using %s",
642 av_format_str(sys->hwVideoFrame->format),
643 av_format_str(sys->videoFrame->format), msg);
644 }
645 }
646
647 if (sys->hwFrameSupportsNativeFormat == 0)
648 target = sys->cpuVideoFrame;
649
650 if (sys->hwFrameSupportsNativeFormat >= 0)
651 {
652 if (sys->hwVideoFrame->format == sys->hw_pix_fmt)
653 {
654 target->width = sys->hwVideoFrame->width;
655 target->height = sys->hwVideoFrame->height;
656 status = av_hwframe_transfer_data(target, sys->hwVideoFrame, 0);
657 }
658 else
659 status = av_frame_copy(target, sys->hwVideoFrame);
660 }
661
662 gotFrame = (status == 0);
663
664 if (status < 0)
665 {
666 WLog_Print(h264->log, WLOG_ERROR, "Failed to transfer video frame (status=%d) (%s)",
667 status, av_err2str(status));
668 goto fail;
669 }
670
671 if (gotFrame && (target != sys->videoFrame))
672 {
673 if (!sys->swsctx)
674 {
675 sys->swsctx = sws_getContext(target->width, target->height, target->format,
676 target->width, target->height, sys->videoFrame->format,
677 SWS_BILINEAR, nullptr, nullptr, nullptr);
678 if (!sys->swsctx)
679 goto fail;
680 }
681
682 status = sws_scale_frame(sys->swsctx, sys->videoFrame, target);
683 if (status < 0)
684 {
685 WLog_Print(h264->log, WLOG_ERROR, "Failed to convert video frame (status=%d) (%s)",
686 status, av_err2str(status));
687 goto fail;
688 }
689 }
690 }
691
692#endif
693
694 if (gotFrame)
695 {
696 WINPR_ASSERT(sys->videoFrame);
697
698 pYUVData[0] = sys->videoFrame->data[0];
699 pYUVData[1] = sys->videoFrame->data[1];
700 pYUVData[2] = sys->videoFrame->data[2];
701 iStride[0] = (UINT32)MAX(0, sys->videoFrame->linesize[0]);
702 iStride[1] = (UINT32)MAX(0, sys->videoFrame->linesize[1]);
703 iStride[2] = (UINT32)MAX(0, sys->videoFrame->linesize[2]);
704
705 h264->YUVWidth = WINPR_ASSERTING_INT_CAST(UINT32, sys->videoFrame->width);
706 h264->YUVHeight = WINPR_ASSERTING_INT_CAST(UINT32, sys->videoFrame->height);
707 rc = 1;
708 }
709 else
710 rc = -2;
711
712fail:
713#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
714 av_packet_unref(packet);
715#else
716 av_packet_free(&packet);
717#endif
718
719 return rc;
720}
721
722static int libavcodec_compress(H264_CONTEXT* WINPR_RESTRICT h264,
723 const BYTE** WINPR_RESTRICT pSrcYuv,
724 const UINT32* WINPR_RESTRICT pStride,
725 BYTE** WINPR_RESTRICT ppDstData, UINT32* WINPR_RESTRICT pDstSize)
726{
727 union
728 {
729 const BYTE* cpv;
730 uint8_t* pv;
731 } cnv;
732 int rc = -1;
733 int status = 0;
734 int gotFrame = 0;
735
736 WINPR_ASSERT(h264);
737
738 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
739 WINPR_ASSERT(sys);
740
741 if (!libavcodec_create_encoder_context(h264))
742 return -1;
743
744#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
745 sys->packet = &sys->bufferpacket;
746 av_packet_unref(sys->packet);
747 av_init_packet(sys->packet);
748#else
749 av_packet_free(&sys->packet);
750 sys->packet = av_packet_alloc();
751#endif
752 if (!sys->packet)
753 {
754 WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate AVPacket");
755 goto fail;
756 }
757
758 WINPR_ASSERT(sys->packet);
759 sys->packet->data = nullptr;
760 sys->packet->size = 0;
761
762 WINPR_ASSERT(sys->videoFrame);
763 WINPR_ASSERT(sys->codecEncoderContext);
764 sys->videoFrame->format = AV_PIX_FMT_YUV420P;
765 sys->videoFrame->width = sys->codecEncoderContext->width;
766 sys->videoFrame->height = sys->codecEncoderContext->height;
767#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 48, 100)
768 sys->videoFrame->colorspace = AVCOL_SPC_BT709;
769#endif
770#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 92, 100)
771 sys->videoFrame->chroma_location = AVCHROMA_LOC_LEFT;
772#endif
773 cnv.cpv = pSrcYuv[0];
774 sys->videoFrame->data[0] = cnv.pv;
775
776 cnv.cpv = pSrcYuv[1];
777 sys->videoFrame->data[1] = cnv.pv;
778
779 cnv.cpv = pSrcYuv[2];
780 sys->videoFrame->data[2] = cnv.pv;
781
782 sys->videoFrame->linesize[0] = (int)pStride[0];
783 sys->videoFrame->linesize[1] = (int)pStride[1];
784 sys->videoFrame->linesize[2] = (int)pStride[2];
785 sys->videoFrame->pts++;
786
787#ifdef WITH_VAAPI_H264_ENCODING
788 if (sys->hwctx)
789 {
790 av_frame_unref(sys->hwVideoFrame);
791 if ((status = av_hwframe_get_buffer(sys->codecEncoderContext->hw_frames_ctx,
792 sys->hwVideoFrame, 0)) < 0 ||
793 !sys->hwVideoFrame->hw_frames_ctx)
794 {
795 WLog_Print(h264->log, WLOG_ERROR, "av_hwframe_get_buffer failed (%s [%d])",
796 av_err2str(status), status);
797 goto fail;
798 }
799 sys->videoFrame->format = AV_PIX_FMT_NV12;
800 if ((status = av_hwframe_transfer_data(sys->hwVideoFrame, sys->videoFrame, 0)) < 0)
801 {
802 WLog_Print(h264->log, WLOG_ERROR, "av_hwframe_transfer_data failed (%s [%d])",
803 av_err2str(status), status);
804 goto fail;
805 }
806 }
807#endif
808
809 /* avcodec_encode_video2 is deprecated with libavcodec 57.48.101 */
810#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
811#ifdef WITH_VAAPI_H264_ENCODING
812 status = avcodec_send_frame(sys->codecEncoderContext,
813 sys->hwctx ? sys->hwVideoFrame : sys->videoFrame);
814#else
815 status = avcodec_send_frame(sys->codecEncoderContext, sys->videoFrame);
816#endif
817
818 if (status < 0)
819 {
820 WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])",
821 av_err2str(status), status);
822 goto fail;
823 }
824
825 status = avcodec_receive_packet(sys->codecEncoderContext, sys->packet);
826
827 if (status < 0)
828 {
829 WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])",
830 av_err2str(status), status);
831 goto fail;
832 }
833
834 gotFrame = (status == 0);
835#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
836
837 do
838 {
839 status = avcodec_encode_video2(sys->codecEncoderContext, sys->packet, sys->videoFrame,
840 &gotFrame);
841 } while ((status >= 0) && (gotFrame == 0));
842
843#else
844 sys->packet->size =
845 avpicture_get_size(sys->codecDecoderContext->pix_fmt, sys->codecDecoderContext->width,
846 sys->codecDecoderContext->height);
847 sys->packet->data = av_malloc(sys->packet->size);
848
849 if (!sys->packet->data)
850 status = -1;
851 else
852 {
853 status = avcodec_encode_video(sys->codecDecoderContext, sys->packet->data,
854 sys->packet->size, sys->videoFrame);
855 }
856
857#endif
858
859 if (status < 0)
860 {
861 WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])",
862 av_err2str(status), status);
863 goto fail;
864 }
865
866 WINPR_ASSERT(sys->packet);
867 *ppDstData = sys->packet->data;
868 *pDstSize = (UINT32)MAX(0, sys->packet->size);
869
870 if (!gotFrame)
871 {
872 WLog_Print(h264->log, WLOG_ERROR, "Did not get frame! (%s [%d])", av_err2str(status),
873 status);
874 rc = -2;
875 }
876 else
877 rc = 1;
878fail:
879 return rc;
880}
881
882static void libavcodec_uninit(H264_CONTEXT* h264)
883{
884 WINPR_ASSERT(h264);
885
886 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
887
888 if (!sys)
889 return;
890
891 if (sys->packet)
892 {
893#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
894 av_packet_unref(sys->packet);
895#else
896 av_packet_free(&sys->packet);
897#endif
898 }
899
900 if (sys->videoFrame)
901 {
902#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
903 av_frame_free(&sys->videoFrame);
904#else
905 av_free(sys->videoFrame);
906#endif
907 }
908
909#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING) || defined(WITH_VIDEOTOOLBOX)
910 if (sys->hwVideoFrame)
911 {
912#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
913 av_frame_free(&sys->hwVideoFrame);
914#else
915 av_free(sys->hwVideoFrame);
916#endif
917 }
918
919 if (sys->cpuVideoFrame)
920 {
921#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
922 av_frame_free(&sys->cpuVideoFrame);
923#else
924 av_free(sys->cpuVideoFrame);
925#endif
926 }
927
928 if (sys->hwctx)
929 av_buffer_unref(&sys->hwctx);
930 sws_freeContext(sys->swsctx);
931
932#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100) || defined(WITH_VIDEOTOOLBOX)
933
934 if (sys->hw_frames_ctx)
935 av_buffer_unref(&sys->hw_frames_ctx);
936
937#endif
938
939#endif
940
941 if (sys->codecParser)
942 av_parser_close(sys->codecParser);
943
944 if (sys->codecDecoderContext)
945 {
946#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100)
947 avcodec_free_context(&sys->codecDecoderContext);
948#else
949 avcodec_close(sys->codecDecoderContext);
950 av_free(sys->codecDecoderContext);
951#endif
952 }
953
954 libavcodec_destroy_encoder_context(h264);
955 free(sys);
956 h264->pSystemData = nullptr;
957}
958
959#if defined(WITH_VAAPI) || defined(WITH_VIDEOTOOLBOX)
960static enum AVPixelFormat libavcodec_get_format(struct AVCodecContext* ctx,
961 const enum AVPixelFormat* fmts)
962{
963 WINPR_ASSERT(ctx);
964
965 H264_CONTEXT* h264 = (H264_CONTEXT*)ctx->opaque;
966 WINPR_ASSERT(h264);
967
968 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
969 WINPR_ASSERT(sys);
970
971 for (const enum AVPixelFormat* p = fmts; *p != AV_PIX_FMT_NONE; p++)
972 {
973 if (*p == sys->hw_pix_fmt)
974 {
975#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100) || defined(WITH_VIDEOTOOLBOX)
976 if (sys->hw_frames_ctx)
977 av_buffer_unref(&sys->hw_frames_ctx);
978
979 sys->hw_frames_ctx = av_hwframe_ctx_alloc(sys->hwctx);
980
981 if (!sys->hw_frames_ctx)
982 {
983 return AV_PIX_FMT_NONE;
984 }
985
986 sys->codecDecoderContext->pix_fmt = *p;
987 AVHWFramesContext* frames = (AVHWFramesContext*)sys->hw_frames_ctx->data;
988 frames->format = *p;
989 frames->height = sys->codecDecoderContext->coded_height;
990 frames->width = sys->codecDecoderContext->coded_width;
991#ifdef WITH_VIDEOTOOLBOX
992 frames->sw_format = AV_PIX_FMT_YUV420P;
993#else
994 frames->sw_format =
995 (sys->codecDecoderContext->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? AV_PIX_FMT_P010
996 : AV_PIX_FMT_NV12);
997#endif
998 frames->initial_pool_size = 20;
999
1000 if (sys->codecDecoderContext->active_thread_type & FF_THREAD_FRAME)
1001 frames->initial_pool_size += sys->codecDecoderContext->thread_count;
1002
1003 int err = av_hwframe_ctx_init(sys->hw_frames_ctx);
1004
1005 if (err < 0)
1006 {
1007 WLog_Print(h264->log, WLOG_ERROR, "Could not init hwframes context: %s",
1008 av_err2str(err));
1009 return AV_PIX_FMT_NONE;
1010 }
1011
1012 sys->codecDecoderContext->hw_frames_ctx = av_buffer_ref(sys->hw_frames_ctx);
1013#endif
1014 return *p;
1015 }
1016 }
1017
1018 return AV_PIX_FMT_NONE;
1019}
1020#endif
1021
1022static BOOL libavcodec_init(H264_CONTEXT* h264)
1023{
1024 WINPR_ASSERT(h264);
1025 H264_CONTEXT_LIBAVCODEC* sys =
1026 (H264_CONTEXT_LIBAVCODEC*)calloc(1, sizeof(H264_CONTEXT_LIBAVCODEC));
1027
1028 if (!sys)
1029 {
1030 goto EXCEPTION;
1031 }
1032
1033 h264->pSystemData = (void*)sys;
1034
1035#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
1036 avcodec_register_all();
1037#endif
1038
1039 if (!h264->Compressor)
1040 {
1041 sys->codecDecoder = avcodec_find_decoder(AV_CODEC_ID_H264);
1042
1043 if (!sys->codecDecoder)
1044 {
1045 WLog_Print(h264->log, WLOG_ERROR, "Failed to find libav H.264 codec");
1046 goto EXCEPTION;
1047 }
1048
1049 sys->codecDecoderContext = avcodec_alloc_context3(sys->codecDecoder);
1050
1051 if (!sys->codecDecoderContext)
1052 {
1053 WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav codec context");
1054 goto EXCEPTION;
1055 }
1056
1057#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100)
1058 if (sys->codecDecoder->capabilities & AV_CODEC_CAP_TRUNCATED)
1059 {
1060 sys->codecDecoderContext->flags |= AV_CODEC_FLAG_TRUNCATED;
1061 }
1062#endif
1063
1064#ifdef WITH_VAAPI
1065 sys->hwFrameSupportsNativeFormat = -1;
1066 if (!sys->hwctx)
1067 {
1068 int ret = av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VAAPI,
1069 get_vaapi_device(), nullptr, 0);
1070
1071 if (ret < 0)
1072 {
1073 WLog_Print(h264->log, WLOG_ERROR,
1074 "Could not initialize hardware decoder, falling back to software: %s",
1075 av_err2str(ret));
1076 sys->hwctx = nullptr;
1077 goto fail_hwdevice_create;
1078 }
1079 }
1080 WLog_Print(h264->log, WLOG_INFO, "Using VAAPI for accelerated H264 decoding");
1081
1082 sys->codecDecoderContext->get_format = libavcodec_get_format;
1083 sys->hw_pix_fmt = AV_PIX_FMT_VAAPI;
1084#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 80, 100)
1085 sys->codecDecoderContext->hw_device_ctx = av_buffer_ref(sys->hwctx);
1086#endif
1087 sys->codecDecoderContext->opaque = (void*)h264;
1088
1089 fail_hwdevice_create:
1090#endif
1091
1092#ifdef WITH_VIDEOTOOLBOX
1093
1094 if (!sys->hwctx)
1095 {
1096 int ret = av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VIDEOTOOLBOX, nullptr,
1097 nullptr, 0);
1098
1099 if (ret < 0)
1100 {
1101 WLog_Print(
1102 h264->log, WLOG_ERROR,
1103 "Could not initialize VideoToolbox decoder, falling back to software: %s",
1104 av_err2str(ret));
1105 sys->hwctx = nullptr;
1106 goto fail_vt_create;
1107 }
1108 }
1109 WLog_Print(h264->log, WLOG_INFO, "Using VideoToolbox for accelerated H264 decoding");
1110
1111 sys->codecDecoderContext->get_format = libavcodec_get_format;
1112 sys->hw_pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX;
1113 sys->codecDecoderContext->hw_device_ctx = av_buffer_ref(sys->hwctx);
1114 sys->codecDecoderContext->opaque = (void*)h264;
1115 fail_vt_create:
1116#endif
1117
1118 if (avcodec_open2(sys->codecDecoderContext, sys->codecDecoder, nullptr) < 0)
1119 {
1120 WLog_Print(h264->log, WLOG_ERROR, "Failed to open libav codec");
1121 goto EXCEPTION;
1122 }
1123
1124 sys->codecParser = av_parser_init(AV_CODEC_ID_H264);
1125
1126 if (!sys->codecParser)
1127 {
1128 WLog_Print(h264->log, WLOG_ERROR, "Failed to initialize libav parser");
1129 goto EXCEPTION;
1130 }
1131 }
1132 else
1133 {
1134#ifdef WITH_VAAPI_H264_ENCODING
1135 if (h264->hwAccel) /* user requested hw accel */
1136 {
1137 sys->codecEncoder = avcodec_find_encoder_by_name("h264_vaapi");
1138 if (!sys->codecEncoder)
1139 {
1140 WLog_Print(h264->log, WLOG_ERROR, "H264 VAAPI encoder not found");
1141 }
1142 else if (av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VAAPI, get_vaapi_device(),
1143 nullptr, 0) < 0)
1144 {
1145 WLog_Print(h264->log, WLOG_ERROR, "av_hwdevice_ctx_create failed");
1146 sys->codecEncoder = nullptr;
1147 sys->hwctx = nullptr;
1148 }
1149 else
1150 {
1151 WLog_Print(h264->log, WLOG_INFO, "Using VAAPI for accelerated H264 encoding");
1152 }
1153 }
1154#endif
1155 if (!sys->codecEncoder)
1156 {
1157 sys->codecEncoder = avcodec_find_encoder(AV_CODEC_ID_H264);
1158 h264->hwAccel = FALSE; /* not supported */
1159 }
1160
1161 if (!sys->codecEncoder)
1162 {
1163 WLog_Print(h264->log, WLOG_ERROR, "Failed to initialize H264 encoder");
1164 goto EXCEPTION;
1165 }
1166 }
1167
1168#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
1169 sys->videoFrame = av_frame_alloc();
1170#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING) || defined(WITH_VIDEOTOOLBOX)
1171 sys->hwVideoFrame = av_frame_alloc();
1172 sys->cpuVideoFrame = av_frame_alloc();
1173#endif
1174#else
1175 sys->videoFrame = avcodec_alloc_frame();
1176#endif
1177
1178 if (!sys->videoFrame)
1179 {
1180 WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav frame");
1181 goto EXCEPTION;
1182 }
1183
1184#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING) || defined(WITH_VIDEOTOOLBOX)
1185 if (!sys->hwVideoFrame || !sys->cpuVideoFrame)
1186 {
1187 WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav hw frame");
1188 goto EXCEPTION;
1189 }
1190
1191#endif
1192 sys->videoFrame->pts = 0;
1193 return TRUE;
1194EXCEPTION:
1195 libavcodec_uninit(h264);
1196 return FALSE;
1197}
1198
1199const H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec = { "libavcodec", libavcodec_init,
1200 libavcodec_uninit, libavcodec_decompress,
1201 libavcodec_compress };