21#include <freerdp/config.h>
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>
31#ifdef WITH_VIDEOTOOLBOX
32#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 9, 0)
33#include <libavutil/hwcontext.h>
35#pragma warning You have asked for VideoToolbox decoding, \
36 but your version of libavutil is too old !Disabling.
37#undef WITH_VIDEOTOOLBOX
42#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 9, 0)
43#include <libavutil/hwcontext.h>
45#pragma warning You have asked for VA - API decoding, \
46 but your version of libavutil is too old !Disabling.
52#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100)
53#define AV_CODEC_ID_H264 CODEC_ID_H264
56#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 34, 2)
57#define AV_CODEC_FLAG_LOOP_FILTER CODEC_FLAG_LOOP_FILTER
58#define AV_CODEC_CAP_TRUNCATED CODEC_CAP_TRUNCATED
59#define AV_CODEC_FLAG_TRUNCATED CODEC_FLAG_TRUNCATED
62#if LIBAVUTIL_VERSION_MAJOR < 52
63#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
68#if !defined(av_err2str)
69static inline char* error_string(
char* errbuf,
size_t errbuf_size,
int errnum)
71 av_strerror(errnum, errbuf, errbuf_size);
75#define av_err2str(errnum) error_string((char[64])WINPR_C_ARRAY_INIT, 64, errnum)
78#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
79static const char* get_vaapi_device(
void)
81 static char device[MAX_PATH] = WINPR_C_ARRAY_INIT;
82 static bool initialized =
false;
86 const char* env = getenv(
"FREERDP_VAAPI_DEVICE");
88 (void)_snprintf(device,
sizeof(device),
"%s", env);
90 (
void)_snprintf(device,
sizeof(device),
"/dev/dri/renderD128");
98 const AVCodec* codecDecoder;
99 AVCodecContext* codecDecoderContext;
100 const AVCodec* codecEncoder;
101 AVCodecContext* codecEncoderContext;
102 AVCodecParserContext* codecParser;
104#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
105 AVPacket bufferpacket;
108#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING) || defined(WITH_VIDEOTOOLBOX)
110 AVFrame* hwVideoFrame;
111 enum AVPixelFormat hw_pix_fmt;
112#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100) || defined(WITH_VIDEOTOOLBOX)
113 AVBufferRef* hw_frames_ctx;
117} H264_CONTEXT_LIBAVCODEC;
119static void libavcodec_destroy_encoder_context(H264_CONTEXT* WINPR_RESTRICT h264)
121 H264_CONTEXT_LIBAVCODEC* sys =
nullptr;
123 if (!h264 || !h264->subsystem)
126 sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
128 if (sys->codecEncoderContext)
130#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100)
131 avcodec_free_context(&sys->codecEncoderContext);
133 avcodec_close(sys->codecEncoderContext);
134 av_free(sys->codecEncoderContext);
138 sys->codecEncoderContext =
nullptr;
141#ifdef WITH_VAAPI_H264_ENCODING
142static int set_hw_frames_ctx(H264_CONTEXT* WINPR_RESTRICT h264)
144 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
145 AVBufferRef* hw_frames_ref =
nullptr;
146 AVHWFramesContext* frames_ctx =
nullptr;
149 if (!(hw_frames_ref = av_hwframe_ctx_alloc(sys->hwctx)))
151 WLog_Print(h264->log, WLOG_ERROR,
"Failed to create VAAPI frame context");
154 frames_ctx = (AVHWFramesContext*)(hw_frames_ref->data);
155 frames_ctx->format = AV_PIX_FMT_VAAPI;
156 frames_ctx->sw_format = AV_PIX_FMT_NV12;
157 frames_ctx->width = sys->codecEncoderContext->width;
158 frames_ctx->height = sys->codecEncoderContext->height;
159 frames_ctx->initial_pool_size = 20;
160 if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0)
162 WLog_Print(h264->log, WLOG_ERROR,
163 "Failed to initialize VAAPI frame context."
166 av_buffer_unref(&hw_frames_ref);
169 sys->codecEncoderContext->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
170 if (!sys->codecEncoderContext->hw_frames_ctx)
171 err = AVERROR(ENOMEM);
173 av_buffer_unref(&hw_frames_ref);
178static BOOL libavcodec_create_encoder_context(H264_CONTEXT* WINPR_RESTRICT h264)
180 BOOL recreate = FALSE;
181 H264_CONTEXT_LIBAVCODEC* sys =
nullptr;
183 if (!h264 || !h264->subsystem)
186 if ((h264->width > INT_MAX) || (h264->height > INT_MAX))
189 sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
190 if (!sys || !sys->codecEncoder)
193 recreate = !sys->codecEncoderContext;
195 if (sys->codecEncoderContext)
197 if ((sys->codecEncoderContext->width != (
int)h264->width) ||
198 (sys->codecEncoderContext->height != (
int)h264->height))
205 libavcodec_destroy_encoder_context(h264);
207 sys->codecEncoderContext = avcodec_alloc_context3(sys->codecEncoder);
209 if (!sys->codecEncoderContext)
212 switch (h264->RateControlMode)
214 case H264_RATECONTROL_VBR:
215 sys->codecEncoderContext->bit_rate = h264->BitRate;
218 case H264_RATECONTROL_CQP:
219 if (av_opt_set_int(sys->codecEncoderContext,
"qp", h264->QP, AV_OPT_SEARCH_CHILDREN) <
222 WLog_Print(h264->log, WLOG_ERROR,
"av_opt_set_int failed");
230 sys->codecEncoderContext->width = (int)MIN(INT32_MAX, h264->width);
231 sys->codecEncoderContext->height = (int)MIN(INT32_MAX, h264->height);
232 sys->codecEncoderContext->delay = 0;
233#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 13, 100)
234 sys->codecEncoderContext->framerate =
235 (AVRational){ WINPR_ASSERTING_INT_CAST(
int, h264->FrameRate), 1 };
237 sys->codecEncoderContext->time_base =
238 (AVRational){ 1, WINPR_ASSERTING_INT_CAST(
int, h264->FrameRate) };
239 av_opt_set(sys->codecEncoderContext,
"tune",
"zerolatency", AV_OPT_SEARCH_CHILDREN);
241 sys->codecEncoderContext->flags |= AV_CODEC_FLAG_LOOP_FILTER;
243#ifdef WITH_VAAPI_H264_ENCODING
246 av_opt_set(sys->codecEncoderContext,
"preset",
"veryslow", AV_OPT_SEARCH_CHILDREN);
248 sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_VAAPI;
250 if (set_hw_frames_ctx(h264) < 0)
256 av_opt_set(sys->codecEncoderContext,
"preset",
"medium", AV_OPT_SEARCH_CHILDREN);
257 sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_YUV420P;
260 if (avcodec_open2(sys->codecEncoderContext, sys->codecEncoder,
nullptr) < 0)
265 libavcodec_destroy_encoder_context(h264);
269static int libavcodec_decompress(H264_CONTEXT* WINPR_RESTRICT h264,
270 const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize)
280 AVPacket* packet =
nullptr;
283 WINPR_ASSERT(pSrcData || (SrcSize == 0));
285 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
286 BYTE** pYUVData = h264->pYUVData;
287 UINT32* iStride = h264->iStride;
291#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
292 packet = &sys->bufferpacket;
293 WINPR_ASSERT(packet);
294 av_init_packet(packet);
296 packet = av_packet_alloc();
300 WLog_Print(h264->log, WLOG_ERROR,
"Failed to allocate AVPacket");
305 packet->data = cnv.pv;
306 packet->size = (int)MIN(SrcSize, INT32_MAX);
308 WINPR_ASSERT(sys->codecDecoderContext);
310#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
311 status = avcodec_send_packet(sys->codecDecoderContext, packet);
315 WLog_Print(h264->log, WLOG_ERROR,
"Failed to decode video frame (status=%d)", status);
319 sys->videoFrame->format = AV_PIX_FMT_YUV420P;
321#if defined(WITH_VAAPI) || defined(WITH_VIDEOTOOLBOX)
322 status = avcodec_receive_frame(sys->codecDecoderContext,
323 sys->hwctx ? sys->hwVideoFrame : sys->videoFrame);
325 status = avcodec_receive_frame(sys->codecDecoderContext, sys->videoFrame);
327 if (status == AVERROR(EAGAIN))
333 gotFrame = (status == 0);
335#if defined(WITH_VAAPI) || defined(WITH_VIDEOTOOLBOX)
337 avcodec_decode_video2(sys->codecDecoderContext,
338 sys->hwctx ? sys->hwVideoFrame : sys->videoFrame, &gotFrame, packet);
340 status = avcodec_decode_video2(sys->codecDecoderContext, sys->videoFrame, &gotFrame, packet);
345 WLog_Print(h264->log, WLOG_ERROR,
"Failed to decode video frame (status=%d)", status);
349#if defined(WITH_VAAPI) || defined(WITH_VIDEOTOOLBOX)
353 if (sys->hwVideoFrame->format == sys->hw_pix_fmt)
355 sys->videoFrame->width = sys->hwVideoFrame->width;
356 sys->videoFrame->height = sys->hwVideoFrame->height;
357 status = av_hwframe_transfer_data(sys->videoFrame, sys->hwVideoFrame, 0);
361 status = av_frame_copy(sys->videoFrame, sys->hwVideoFrame);
365 gotFrame = (status == 0);
369 WLog_Print(h264->log, WLOG_ERROR,
"Failed to transfer video frame (status=%d) (%s)", status,
378 WINPR_ASSERT(sys->videoFrame);
380 pYUVData[0] = sys->videoFrame->data[0];
381 pYUVData[1] = sys->videoFrame->data[1];
382 pYUVData[2] = sys->videoFrame->data[2];
383 iStride[0] = (UINT32)MAX(0, sys->videoFrame->linesize[0]);
384 iStride[1] = (UINT32)MAX(0, sys->videoFrame->linesize[1]);
385 iStride[2] = (UINT32)MAX(0, sys->videoFrame->linesize[2]);
392#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
393 av_packet_unref(packet);
395 av_packet_free(&packet);
401static int libavcodec_compress(H264_CONTEXT* WINPR_RESTRICT h264,
402 const BYTE** WINPR_RESTRICT pSrcYuv,
403 const UINT32* WINPR_RESTRICT pStride,
404 BYTE** WINPR_RESTRICT ppDstData, UINT32* WINPR_RESTRICT pDstSize)
417 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
420 if (!libavcodec_create_encoder_context(h264))
423#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
424 sys->packet = &sys->bufferpacket;
425 av_packet_unref(sys->packet);
426 av_init_packet(sys->packet);
428 av_packet_free(&sys->packet);
429 sys->packet = av_packet_alloc();
433 WLog_Print(h264->log, WLOG_ERROR,
"Failed to allocate AVPacket");
437 WINPR_ASSERT(sys->packet);
438 sys->packet->data =
nullptr;
439 sys->packet->size = 0;
441 WINPR_ASSERT(sys->videoFrame);
442 WINPR_ASSERT(sys->codecEncoderContext);
443 sys->videoFrame->format = AV_PIX_FMT_YUV420P;
444 sys->videoFrame->width = sys->codecEncoderContext->width;
445 sys->videoFrame->height = sys->codecEncoderContext->height;
446#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 48, 100)
447 sys->videoFrame->colorspace = AVCOL_SPC_BT709;
449#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 92, 100)
450 sys->videoFrame->chroma_location = AVCHROMA_LOC_LEFT;
452 cnv.cpv = pSrcYuv[0];
453 sys->videoFrame->data[0] = cnv.pv;
455 cnv.cpv = pSrcYuv[1];
456 sys->videoFrame->data[1] = cnv.pv;
458 cnv.cpv = pSrcYuv[2];
459 sys->videoFrame->data[2] = cnv.pv;
461 sys->videoFrame->linesize[0] = (int)pStride[0];
462 sys->videoFrame->linesize[1] = (int)pStride[1];
463 sys->videoFrame->linesize[2] = (int)pStride[2];
464 sys->videoFrame->pts++;
466#ifdef WITH_VAAPI_H264_ENCODING
469 av_frame_unref(sys->hwVideoFrame);
470 if ((status = av_hwframe_get_buffer(sys->codecEncoderContext->hw_frames_ctx,
471 sys->hwVideoFrame, 0)) < 0 ||
472 !sys->hwVideoFrame->hw_frames_ctx)
474 WLog_Print(h264->log, WLOG_ERROR,
"av_hwframe_get_buffer failed (%s [%d])",
475 av_err2str(status), status);
478 sys->videoFrame->format = AV_PIX_FMT_NV12;
479 if ((status = av_hwframe_transfer_data(sys->hwVideoFrame, sys->videoFrame, 0)) < 0)
481 WLog_Print(h264->log, WLOG_ERROR,
"av_hwframe_transfer_data failed (%s [%d])",
482 av_err2str(status), status);
489#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
490#ifdef WITH_VAAPI_H264_ENCODING
491 status = avcodec_send_frame(sys->codecEncoderContext,
492 sys->hwctx ? sys->hwVideoFrame : sys->videoFrame);
494 status = avcodec_send_frame(sys->codecEncoderContext, sys->videoFrame);
499 WLog_Print(h264->log, WLOG_ERROR,
"Failed to encode video frame (%s [%d])",
500 av_err2str(status), status);
504 status = avcodec_receive_packet(sys->codecEncoderContext, sys->packet);
508 WLog_Print(h264->log, WLOG_ERROR,
"Failed to encode video frame (%s [%d])",
509 av_err2str(status), status);
513 gotFrame = (status == 0);
514#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
518 status = avcodec_encode_video2(sys->codecEncoderContext, sys->packet, sys->videoFrame,
520 }
while ((status >= 0) && (gotFrame == 0));
524 avpicture_get_size(sys->codecDecoderContext->pix_fmt, sys->codecDecoderContext->width,
525 sys->codecDecoderContext->height);
526 sys->packet->data = av_malloc(sys->packet->size);
528 if (!sys->packet->data)
532 status = avcodec_encode_video(sys->codecDecoderContext, sys->packet->data,
533 sys->packet->size, sys->videoFrame);
540 WLog_Print(h264->log, WLOG_ERROR,
"Failed to encode video frame (%s [%d])",
541 av_err2str(status), status);
545 WINPR_ASSERT(sys->packet);
546 *ppDstData = sys->packet->data;
547 *pDstSize = (UINT32)MAX(0, sys->packet->size);
551 WLog_Print(h264->log, WLOG_ERROR,
"Did not get frame! (%s [%d])", av_err2str(status),
561static void libavcodec_uninit(H264_CONTEXT* h264)
565 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
572#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
573 av_packet_unref(sys->packet);
575 av_packet_free(&sys->packet);
581#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
582 av_frame_free(&sys->videoFrame);
584 av_free(sys->videoFrame);
588#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING) || defined(WITH_VIDEOTOOLBOX)
589 if (sys->hwVideoFrame)
591#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
592 av_frame_free(&sys->hwVideoFrame);
594 av_free(sys->hwVideoFrame);
599 av_buffer_unref(&sys->hwctx);
601#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100) || defined(WITH_VIDEOTOOLBOX)
603 if (sys->hw_frames_ctx)
604 av_buffer_unref(&sys->hw_frames_ctx);
610 if (sys->codecParser)
611 av_parser_close(sys->codecParser);
613 if (sys->codecDecoderContext)
615#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100)
616 avcodec_free_context(&sys->codecDecoderContext);
618 avcodec_close(sys->codecDecoderContext);
619 av_free(sys->codecDecoderContext);
623 libavcodec_destroy_encoder_context(h264);
625 h264->pSystemData =
nullptr;
628#if defined(WITH_VAAPI) || defined(WITH_VIDEOTOOLBOX)
629static enum AVPixelFormat libavcodec_get_format(
struct AVCodecContext* ctx,
630 const enum AVPixelFormat* fmts)
634 H264_CONTEXT* h264 = (H264_CONTEXT*)ctx->opaque;
637 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
640 for (
const enum AVPixelFormat* p = fmts; *p != AV_PIX_FMT_NONE; p++)
642 if (*p == sys->hw_pix_fmt)
644#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100) || defined(WITH_VIDEOTOOLBOX)
645 if (sys->hw_frames_ctx)
646 av_buffer_unref(&sys->hw_frames_ctx);
648 sys->hw_frames_ctx = av_hwframe_ctx_alloc(sys->hwctx);
650 if (!sys->hw_frames_ctx)
652 return AV_PIX_FMT_NONE;
655 sys->codecDecoderContext->pix_fmt = *p;
656 AVHWFramesContext* frames = (AVHWFramesContext*)sys->hw_frames_ctx->data;
658 frames->height = sys->codecDecoderContext->coded_height;
659 frames->width = sys->codecDecoderContext->coded_width;
660#ifdef WITH_VIDEOTOOLBOX
661 frames->sw_format = AV_PIX_FMT_YUV420P;
664 (sys->codecDecoderContext->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? AV_PIX_FMT_P010
667 frames->initial_pool_size = 20;
669 if (sys->codecDecoderContext->active_thread_type & FF_THREAD_FRAME)
670 frames->initial_pool_size += sys->codecDecoderContext->thread_count;
672 int err = av_hwframe_ctx_init(sys->hw_frames_ctx);
676 WLog_Print(h264->log, WLOG_ERROR,
"Could not init hwframes context: %s",
678 return AV_PIX_FMT_NONE;
681 sys->codecDecoderContext->hw_frames_ctx = av_buffer_ref(sys->hw_frames_ctx);
687 return AV_PIX_FMT_NONE;
691static BOOL libavcodec_init(H264_CONTEXT* h264)
694 H264_CONTEXT_LIBAVCODEC* sys =
695 (H264_CONTEXT_LIBAVCODEC*)calloc(1,
sizeof(H264_CONTEXT_LIBAVCODEC));
702 h264->pSystemData = (
void*)sys;
704#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
705 avcodec_register_all();
708 if (!h264->Compressor)
710 sys->codecDecoder = avcodec_find_decoder(AV_CODEC_ID_H264);
712 if (!sys->codecDecoder)
714 WLog_Print(h264->log, WLOG_ERROR,
"Failed to find libav H.264 codec");
718 sys->codecDecoderContext = avcodec_alloc_context3(sys->codecDecoder);
720 if (!sys->codecDecoderContext)
722 WLog_Print(h264->log, WLOG_ERROR,
"Failed to allocate libav codec context");
726#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100)
727 if (sys->codecDecoder->capabilities & AV_CODEC_CAP_TRUNCATED)
729 sys->codecDecoderContext->flags |= AV_CODEC_FLAG_TRUNCATED;
737 int ret = av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VAAPI,
738 get_vaapi_device(),
nullptr, 0);
742 WLog_Print(h264->log, WLOG_ERROR,
743 "Could not initialize hardware decoder, falling back to software: %s",
745 sys->hwctx =
nullptr;
746 goto fail_hwdevice_create;
749 WLog_Print(h264->log, WLOG_INFO,
"Using VAAPI for accelerated H264 decoding");
751 sys->codecDecoderContext->get_format = libavcodec_get_format;
752 sys->hw_pix_fmt = AV_PIX_FMT_VAAPI;
753#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 80, 100)
754 sys->codecDecoderContext->hw_device_ctx = av_buffer_ref(sys->hwctx);
756 sys->codecDecoderContext->opaque = (
void*)h264;
757 fail_hwdevice_create:
760#ifdef WITH_VIDEOTOOLBOX
764 int ret = av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VIDEOTOOLBOX,
nullptr,
770 h264->log, WLOG_ERROR,
771 "Could not initialize VideoToolbox decoder, falling back to software: %s",
773 sys->hwctx =
nullptr;
777 WLog_Print(h264->log, WLOG_INFO,
"Using VideoToolbox for accelerated H264 decoding");
779 sys->codecDecoderContext->get_format = libavcodec_get_format;
780 sys->hw_pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX;
781 sys->codecDecoderContext->hw_device_ctx = av_buffer_ref(sys->hwctx);
782 sys->codecDecoderContext->opaque = (
void*)h264;
786 if (avcodec_open2(sys->codecDecoderContext, sys->codecDecoder,
nullptr) < 0)
788 WLog_Print(h264->log, WLOG_ERROR,
"Failed to open libav codec");
792 sys->codecParser = av_parser_init(AV_CODEC_ID_H264);
794 if (!sys->codecParser)
796 WLog_Print(h264->log, WLOG_ERROR,
"Failed to initialize libav parser");
802#ifdef WITH_VAAPI_H264_ENCODING
805 sys->codecEncoder = avcodec_find_encoder_by_name(
"h264_vaapi");
806 if (!sys->codecEncoder)
808 WLog_Print(h264->log, WLOG_ERROR,
"H264 VAAPI encoder not found");
810 else if (av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VAAPI, get_vaapi_device(),
813 WLog_Print(h264->log, WLOG_ERROR,
"av_hwdevice_ctx_create failed");
814 sys->codecEncoder =
nullptr;
815 sys->hwctx =
nullptr;
819 WLog_Print(h264->log, WLOG_INFO,
"Using VAAPI for accelerated H264 encoding");
823 if (!sys->codecEncoder)
825 sys->codecEncoder = avcodec_find_encoder(AV_CODEC_ID_H264);
826 h264->hwAccel = FALSE;
829 if (!sys->codecEncoder)
831 WLog_Print(h264->log, WLOG_ERROR,
"Failed to initialize H264 encoder");
836#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
837 sys->videoFrame = av_frame_alloc();
838#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING) || defined(WITH_VIDEOTOOLBOX)
839 sys->hwVideoFrame = av_frame_alloc();
842 sys->videoFrame = avcodec_alloc_frame();
845 if (!sys->videoFrame)
847 WLog_Print(h264->log, WLOG_ERROR,
"Failed to allocate libav frame");
851#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING) || defined(WITH_VIDEOTOOLBOX)
852 if (!sys->hwVideoFrame)
854 WLog_Print(h264->log, WLOG_ERROR,
"Failed to allocate libav hw frame");
859 sys->videoFrame->pts = 0;
862 libavcodec_uninit(h264);
866const H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec = {
"libavcodec", libavcodec_init,
867 libavcodec_uninit, libavcodec_decompress,
868 libavcodec_compress };