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>
32 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 9, 0)
33 #include <libavutil/hwcontext.h>
35 #pragma warning You have asked for VA - API decoding, \
36 but your version of libavutil is too old !Disabling.
42 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100)
43 #define AV_CODEC_ID_H264 CODEC_ID_H264
46 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 34, 2)
47 #define AV_CODEC_FLAG_LOOP_FILTER CODEC_FLAG_LOOP_FILTER
48 #define AV_CODEC_CAP_TRUNCATED CODEC_CAP_TRUNCATED
49 #define AV_CODEC_FLAG_TRUNCATED CODEC_FLAG_TRUNCATED
52 #if LIBAVUTIL_VERSION_MAJOR < 52
53 #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
58 #if !defined(av_err2str)
59 static inline char* error_string(
char* errbuf,
size_t errbuf_size,
int errnum)
61 av_strerror(errnum, errbuf, errbuf_size);
65 #define av_err2str(errnum) error_string((char[64]){ 0 }, 64, errnum)
69 #define VAAPI_DEVICE "/dev/dri/renderD128"
74 const AVCodec* codecDecoder;
75 AVCodecContext* codecDecoderContext;
76 const AVCodec* codecEncoder;
77 AVCodecContext* codecEncoderContext;
78 AVCodecParserContext* codecParser;
80 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
81 AVPacket bufferpacket;
86 AVFrame* hwVideoFrame;
87 enum AVPixelFormat hw_pix_fmt;
88 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100)
89 AVBufferRef* hw_frames_ctx;
92 } H264_CONTEXT_LIBAVCODEC;
94 static void libavcodec_destroy_encoder(H264_CONTEXT* WINPR_RESTRICT h264)
96 H264_CONTEXT_LIBAVCODEC* sys = NULL;
98 if (!h264 || !h264->subsystem)
101 sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
103 if (sys->codecEncoderContext)
105 avcodec_close(sys->codecEncoderContext);
106 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100)
107 avcodec_free_context(&sys->codecEncoderContext);
109 av_free(sys->codecEncoderContext);
113 sys->codecEncoder = NULL;
114 sys->codecEncoderContext = NULL;
117 static BOOL libavcodec_create_encoder(H264_CONTEXT* WINPR_RESTRICT h264)
119 BOOL recreate = FALSE;
120 H264_CONTEXT_LIBAVCODEC* sys = NULL;
122 if (!h264 || !h264->subsystem)
125 if ((h264->width > INT_MAX) || (h264->height > INT_MAX))
128 sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
131 recreate = !sys->codecEncoder || !sys->codecEncoderContext;
133 if (sys->codecEncoderContext)
135 if ((sys->codecEncoderContext->width != (
int)h264->width) ||
136 (sys->codecEncoderContext->height != (int)h264->height))
143 libavcodec_destroy_encoder(h264);
144 sys->codecEncoder = avcodec_find_encoder(AV_CODEC_ID_H264);
146 if (!sys->codecEncoder)
149 sys->codecEncoderContext = avcodec_alloc_context3(sys->codecEncoder);
151 if (!sys->codecEncoderContext)
154 switch (h264->RateControlMode)
156 case H264_RATECONTROL_VBR:
157 sys->codecEncoderContext->bit_rate = h264->BitRate;
160 case H264_RATECONTROL_CQP:
168 sys->codecEncoderContext->width = (int)MIN(INT32_MAX, h264->width);
169 sys->codecEncoderContext->height = (int)MIN(INT32_MAX, h264->height);
170 sys->codecEncoderContext->delay = 0;
171 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 13, 100)
172 sys->codecEncoderContext->framerate = (AVRational){ h264->FrameRate, 1 };
174 sys->codecEncoderContext->time_base = (AVRational){ 1, h264->FrameRate };
175 av_opt_set(sys->codecEncoderContext,
"preset",
"medium", AV_OPT_SEARCH_CHILDREN);
176 av_opt_set(sys->codecEncoderContext,
"tune",
"zerolatency", AV_OPT_SEARCH_CHILDREN);
177 sys->codecEncoderContext->flags |= AV_CODEC_FLAG_LOOP_FILTER;
178 sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_YUV420P;
180 if (avcodec_open2(sys->codecEncoderContext, sys->codecEncoder, NULL) < 0)
185 libavcodec_destroy_encoder(h264);
189 static int libavcodec_decompress(H264_CONTEXT* WINPR_RESTRICT h264,
190 const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize)
200 AVPacket* packet = NULL;
203 WINPR_ASSERT(pSrcData || (SrcSize == 0));
205 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
206 BYTE** pYUVData = h264->pYUVData;
207 UINT32* iStride = h264->iStride;
211 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
212 packet = &sys->bufferpacket;
213 WINPR_ASSERT(packet);
214 av_init_packet(packet);
216 packet = av_packet_alloc();
220 WLog_Print(h264->log, WLOG_ERROR,
"Failed to allocate AVPacket");
225 packet->data = cnv.pv;
226 packet->size = (int)MIN(SrcSize, INT32_MAX);
228 WINPR_ASSERT(sys->codecDecoderContext);
230 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
231 status = avcodec_send_packet(sys->codecDecoderContext, packet);
235 WLog_Print(h264->log, WLOG_ERROR,
"Failed to decode video frame (status=%d)", status);
239 sys->videoFrame->format = AV_PIX_FMT_YUV420P;
244 status = avcodec_receive_frame(sys->codecDecoderContext,
245 sys->hwctx ? sys->hwVideoFrame : sys->videoFrame);
247 status = avcodec_receive_frame(sys->codecDecoderContext, sys->videoFrame);
249 }
while (status == AVERROR(EAGAIN));
251 gotFrame = (status == 0);
255 avcodec_decode_video2(sys->codecDecoderContext,
256 sys->hwctx ? sys->hwVideoFrame : sys->videoFrame, &gotFrame, packet);
258 status = avcodec_decode_video2(sys->codecDecoderContext, sys->videoFrame, &gotFrame, packet);
263 WLog_Print(h264->log, WLOG_ERROR,
"Failed to decode video frame (status=%d)", status);
271 if (sys->hwVideoFrame->format == sys->hw_pix_fmt)
273 sys->videoFrame->width = sys->hwVideoFrame->width;
274 sys->videoFrame->height = sys->hwVideoFrame->height;
275 status = av_hwframe_transfer_data(sys->videoFrame, sys->hwVideoFrame, 0);
279 status = av_frame_copy(sys->videoFrame, sys->hwVideoFrame);
283 gotFrame = (status == 0);
287 WLog_Print(h264->log, WLOG_ERROR,
"Failed to transfer video frame (status=%d) (%s)", status,
294 WLog_Print(h264->log, WLOG_INFO,
295 "libavcodec_decompress: frame decoded (status=%d, gotFrame=%d, width=%d, height=%d, Y=[%p,%d], U=[%p,%d], V=[%p,%d])",
296 status, gotFrame, sys->videoFrame->width, sys->videoFrame->height,
297 (
void*) sys->videoFrame->data[0], sys->videoFrame->linesize[0],
298 (
void*) sys->videoFrame->data[1], sys->videoFrame->linesize[1],
299 (
void*) sys->videoFrame->data[2], sys->videoFrame->linesize[2]);
304 WINPR_ASSERT(sys->videoFrame);
306 pYUVData[0] = sys->videoFrame->data[0];
307 pYUVData[1] = sys->videoFrame->data[1];
308 pYUVData[2] = sys->videoFrame->data[2];
309 iStride[0] = (UINT32)MAX(0, sys->videoFrame->linesize[0]);
310 iStride[1] = (UINT32)MAX(0, sys->videoFrame->linesize[1]);
311 iStride[2] = (UINT32)MAX(0, sys->videoFrame->linesize[2]);
319 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
320 av_packet_unref(packet);
322 av_packet_free(&packet);
328 static int libavcodec_compress(H264_CONTEXT* WINPR_RESTRICT h264,
329 const BYTE** WINPR_RESTRICT pSrcYuv,
330 const UINT32* WINPR_RESTRICT pStride,
331 BYTE** WINPR_RESTRICT ppDstData, UINT32* WINPR_RESTRICT pDstSize)
344 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
347 if (!libavcodec_create_encoder(h264))
350 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
351 sys->packet = &sys->bufferpacket;
352 av_packet_unref(sys->packet);
353 av_init_packet(sys->packet);
355 av_packet_free(&sys->packet);
356 sys->packet = av_packet_alloc();
360 WLog_Print(h264->log, WLOG_ERROR,
"Failed to allocate AVPacket");
364 WINPR_ASSERT(sys->packet);
365 sys->packet->data = NULL;
366 sys->packet->size = 0;
368 WINPR_ASSERT(sys->videoFrame);
369 WINPR_ASSERT(sys->codecEncoderContext);
370 sys->videoFrame->format = sys->codecEncoderContext->pix_fmt;
371 sys->videoFrame->width = sys->codecEncoderContext->width;
372 sys->videoFrame->height = sys->codecEncoderContext->height;
373 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 48, 100)
374 sys->videoFrame->colorspace = AVCOL_SPC_BT709;
376 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 92, 100)
377 sys->videoFrame->chroma_location = AVCHROMA_LOC_LEFT;
379 cnv.cpv = pSrcYuv[0];
380 sys->videoFrame->data[0] = cnv.pv;
382 cnv.cpv = pSrcYuv[1];
383 sys->videoFrame->data[1] = cnv.pv;
385 cnv.cpv = pSrcYuv[2];
386 sys->videoFrame->data[2] = cnv.pv;
388 sys->videoFrame->linesize[0] = (int)pStride[0];
389 sys->videoFrame->linesize[1] = (int)pStride[1];
390 sys->videoFrame->linesize[2] = (int)pStride[2];
391 sys->videoFrame->pts++;
393 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
394 status = avcodec_send_frame(sys->codecEncoderContext, sys->videoFrame);
398 WLog_Print(h264->log, WLOG_ERROR,
"Failed to encode video frame (%s [%d])",
399 av_err2str(status), status);
403 status = avcodec_receive_packet(sys->codecEncoderContext, sys->packet);
407 WLog_Print(h264->log, WLOG_ERROR,
"Failed to encode video frame (%s [%d])",
408 av_err2str(status), status);
412 gotFrame = (status == 0);
413 #elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
417 status = avcodec_encode_video2(sys->codecEncoderContext, sys->packet, sys->videoFrame,
419 }
while ((status >= 0) && (gotFrame == 0));
423 avpicture_get_size(sys->codecDecoderContext->pix_fmt, sys->codecDecoderContext->width,
424 sys->codecDecoderContext->height);
425 sys->packet->data = av_malloc(sys->packet->size);
427 if (!sys->packet->data)
431 status = avcodec_encode_video(sys->codecDecoderContext, sys->packet->data,
432 sys->packet->size, sys->videoFrame);
439 WLog_Print(h264->log, WLOG_ERROR,
"Failed to encode video frame (%s [%d])",
440 av_err2str(status), status);
444 WINPR_ASSERT(sys->packet);
445 *ppDstData = sys->packet->data;
446 *pDstSize = (UINT32)MAX(0, sys->packet->size);
450 WLog_Print(h264->log, WLOG_ERROR,
"Did not get frame! (%s [%d])", av_err2str(status),
460 static void libavcodec_uninit(H264_CONTEXT* h264)
464 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
471 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
472 av_packet_unref(sys->packet);
474 av_packet_free(&sys->packet);
480 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
481 av_frame_free(&sys->videoFrame);
483 av_free(sys->videoFrame);
489 if (sys->hwVideoFrame)
491 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
492 av_frame_free(&sys->hwVideoFrame);
494 av_free(sys->hwVideoFrame);
499 av_buffer_unref(&sys->hwctx);
501 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100)
503 if (sys->hw_frames_ctx)
504 av_buffer_unref(&sys->hw_frames_ctx);
509 if (sys->codecParser)
510 av_parser_close(sys->codecParser);
512 if (sys->codecDecoderContext)
514 avcodec_close(sys->codecDecoderContext);
515 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100)
516 avcodec_free_context(&sys->codecDecoderContext);
518 av_free(sys->codecDecoderContext);
522 libavcodec_destroy_encoder(h264);
524 h264->pSystemData = NULL;
528 static enum AVPixelFormat libavcodec_get_format(
struct AVCodecContext* ctx,
529 const enum AVPixelFormat* fmts)
533 H264_CONTEXT* h264 = (H264_CONTEXT*)ctx->opaque;
536 H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
539 for (
const enum AVPixelFormat* p = fmts; *p != AV_PIX_FMT_NONE; p++)
541 if (*p == sys->hw_pix_fmt)
543 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100)
544 sys->hw_frames_ctx = av_hwframe_ctx_alloc(sys->hwctx);
546 if (!sys->hw_frames_ctx)
548 return AV_PIX_FMT_NONE;
551 sys->codecDecoderContext->pix_fmt = *p;
552 AVHWFramesContext* frames = (AVHWFramesContext*)sys->hw_frames_ctx->data;
554 frames->height = sys->codecDecoderContext->coded_height;
555 frames->width = sys->codecDecoderContext->coded_width;
557 (sys->codecDecoderContext->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? AV_PIX_FMT_P010
559 frames->initial_pool_size = 20;
561 if (sys->codecDecoderContext->active_thread_type & FF_THREAD_FRAME)
562 frames->initial_pool_size += sys->codecDecoderContext->thread_count;
564 int err = av_hwframe_ctx_init(sys->hw_frames_ctx);
568 WLog_Print(h264->log, WLOG_ERROR,
"Could not init hwframes context: %s",
570 return AV_PIX_FMT_NONE;
573 sys->codecDecoderContext->hw_frames_ctx = av_buffer_ref(sys->hw_frames_ctx);
579 return AV_PIX_FMT_NONE;
583 static BOOL libavcodec_init(H264_CONTEXT* h264)
585 H264_CONTEXT_LIBAVCODEC* sys = NULL;
588 sys = (H264_CONTEXT_LIBAVCODEC*)calloc(1,
sizeof(H264_CONTEXT_LIBAVCODEC));
595 h264->pSystemData = (
void*)sys;
597 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
598 avcodec_register_all();
601 if (!h264->Compressor)
603 sys->codecDecoder = avcodec_find_decoder(AV_CODEC_ID_H264);
605 if (!sys->codecDecoder)
607 WLog_Print(h264->log, WLOG_ERROR,
"Failed to find libav H.264 codec");
611 sys->codecDecoderContext = avcodec_alloc_context3(sys->codecDecoder);
613 if (!sys->codecDecoderContext)
615 WLog_Print(h264->log, WLOG_ERROR,
"Failed to allocate libav codec context");
619 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100)
620 if (sys->codecDecoder->capabilities & AV_CODEC_CAP_TRUNCATED)
622 sys->codecDecoderContext->flags |= AV_CODEC_FLAG_TRUNCATED;
631 av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VAAPI, VAAPI_DEVICE, NULL, 0);
635 WLog_Print(h264->log, WLOG_ERROR,
636 "Could not initialize hardware decoder, falling back to software: %s",
639 goto fail_hwdevice_create;
642 WLog_Print(h264->log, WLOG_INFO,
"Using VAAPI for accelerated H264 decoding");
644 sys->codecDecoderContext->get_format = libavcodec_get_format;
645 sys->hw_pix_fmt = AV_PIX_FMT_VAAPI;
646 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 80, 100)
647 sys->codecDecoderContext->hw_device_ctx = av_buffer_ref(sys->hwctx);
649 sys->codecDecoderContext->opaque = (
void*)h264;
650 fail_hwdevice_create:
653 if (avcodec_open2(sys->codecDecoderContext, sys->codecDecoder, NULL) < 0)
655 WLog_Print(h264->log, WLOG_ERROR,
"Failed to open libav codec");
659 sys->codecParser = av_parser_init(AV_CODEC_ID_H264);
661 if (!sys->codecParser)
663 WLog_Print(h264->log, WLOG_ERROR,
"Failed to initialize libav parser");
668 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
669 sys->videoFrame = av_frame_alloc();
671 sys->hwVideoFrame = av_frame_alloc();
674 sys->videoFrame = avcodec_alloc_frame();
677 if (!sys->videoFrame)
679 WLog_Print(h264->log, WLOG_ERROR,
"Failed to allocate libav frame");
685 if (!sys->hwVideoFrame)
687 WLog_Print(h264->log, WLOG_ERROR,
"Failed to allocate libav hw frame");
692 sys->videoFrame->pts = 0;
695 libavcodec_uninit(h264);
699 const H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec = {
"libavcodec", libavcodec_init,
700 libavcodec_uninit, libavcodec_decompress,
701 libavcodec_compress };