mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
MS-RDPECAM: VAAPI h264 encoding
This commit is contained in:
@@ -130,8 +130,12 @@ static BOOL ecam_init_sws_context(CameraDeviceStream* stream, enum AVPixelFormat
|
||||
const int width = (int)stream->currMediaType.Width;
|
||||
const int height = (int)stream->currMediaType.Height;
|
||||
|
||||
stream->sws = sws_getContext(width, height, pixFormat, width, height, AV_PIX_FMT_YUV420P, 0,
|
||||
NULL, NULL, NULL);
|
||||
const enum AVPixelFormat outPixFormat =
|
||||
h264_context_get_option(stream->h264, H264_CONTEXT_OPTION_HW_ACCEL) ? AV_PIX_FMT_NV12
|
||||
: AV_PIX_FMT_YUV420P;
|
||||
|
||||
stream->sws =
|
||||
sws_getContext(width, height, pixFormat, width, height, outPixFormat, 0, NULL, NULL, NULL);
|
||||
if (!stream->sws)
|
||||
{
|
||||
WLog_ERR(TAG, "sws_getContext failed");
|
||||
@@ -152,8 +156,8 @@ static BOOL ecam_encoder_compress_h264(CameraDeviceStream* stream, const BYTE* s
|
||||
UINT32 dstSize = 0;
|
||||
BYTE* srcSlice[4] = { 0 };
|
||||
int srcLineSizes[4] = { 0 };
|
||||
BYTE* yuv420pData[3] = { 0 };
|
||||
UINT32 yuv420pStride[3] = { 0 };
|
||||
BYTE* yuvData[3] = { 0 };
|
||||
UINT32 yuvLineSizes[3] = { 0 };
|
||||
prim_size_t size = { stream->currMediaType.Width, stream->currMediaType.Height };
|
||||
CAM_MEDIA_FORMAT inputFormat = streamInputFormat(stream);
|
||||
enum AVPixelFormat pixFormat = AV_PIX_FMT_NONE;
|
||||
@@ -205,21 +209,20 @@ static BOOL ecam_encoder_compress_h264(CameraDeviceStream* stream, const BYTE* s
|
||||
}
|
||||
}
|
||||
|
||||
/* get buffers for YUV420P */
|
||||
if (h264_get_yuv_buffer(stream->h264, WINPR_ASSERTING_INT_CAST(uint32_t, srcLineSizes[0]),
|
||||
size.width, size.height, yuv420pData, yuv420pStride) < 0)
|
||||
/* get buffers for YUV420P or NV12 */
|
||||
if (h264_get_yuv_buffer(stream->h264, 0, size.width, size.height, yuvData, yuvLineSizes) < 0)
|
||||
return FALSE;
|
||||
|
||||
/* convert from source format to YUV420P */
|
||||
/* convert from source format to YUV420P or NV12 */
|
||||
if (!ecam_init_sws_context(stream, pixFormat))
|
||||
return FALSE;
|
||||
|
||||
const BYTE* cSrcSlice[4] = { srcSlice[0], srcSlice[1], srcSlice[2], srcSlice[3] };
|
||||
if (sws_scale(stream->sws, cSrcSlice, srcLineSizes, 0, (int)size.height, yuv420pData,
|
||||
(int*)yuv420pStride) <= 0)
|
||||
if (sws_scale(stream->sws, cSrcSlice, srcLineSizes, 0, (int)size.height, yuvData,
|
||||
(int*)yuvLineSizes) <= 0)
|
||||
return FALSE;
|
||||
|
||||
/* encode from YUV420P to H264 */
|
||||
/* encode from YUV420P or NV12 to H264 */
|
||||
if (h264_compress(stream->h264, ppDstData, &dstSize) < 0)
|
||||
return FALSE;
|
||||
|
||||
@@ -337,10 +340,6 @@ static BOOL ecam_encoder_context_init_h264(CameraDeviceStream* stream)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!h264_context_reset(stream->h264, stream->currMediaType.Width,
|
||||
stream->currMediaType.Height))
|
||||
goto fail;
|
||||
|
||||
if (!h264_context_set_option(stream->h264, H264_CONTEXT_OPTION_USAGETYPE,
|
||||
H264_CAMERA_VIDEO_REAL_TIME))
|
||||
goto fail;
|
||||
@@ -354,13 +353,30 @@ static BOOL ecam_encoder_context_init_h264(CameraDeviceStream* stream)
|
||||
ecam_encoder_h264_get_max_bitrate(stream)))
|
||||
goto fail;
|
||||
|
||||
/* Using CQP mode for rate control. It produces more comparable quality
|
||||
* between VAAPI and software encoding than VBR mode
|
||||
*/
|
||||
if (!h264_context_set_option(stream->h264, H264_CONTEXT_OPTION_RATECONTROL,
|
||||
H264_RATECONTROL_VBR))
|
||||
H264_RATECONTROL_CQP))
|
||||
goto fail;
|
||||
|
||||
if (!h264_context_set_option(stream->h264, H264_CONTEXT_OPTION_QP, 0))
|
||||
/* Using 26 as CQP value. Lower values will produce better quality but
|
||||
* higher bitrate; higher values - lower bitrate but degraded quality
|
||||
*/
|
||||
if (!h264_context_set_option(stream->h264, H264_CONTEXT_OPTION_QP, 26))
|
||||
goto fail;
|
||||
|
||||
/* Requesting hardware acceleration before calling h264_context_reset */
|
||||
if (!h264_context_set_option(stream->h264, H264_CONTEXT_OPTION_HW_ACCEL, TRUE))
|
||||
goto fail;
|
||||
|
||||
if (!h264_context_reset(stream->h264, stream->currMediaType.Width,
|
||||
stream->currMediaType.Height))
|
||||
{
|
||||
WLog_ERR(TAG, "h264_context_reset failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if defined(WITH_INPUT_FORMAT_MJPG)
|
||||
if (streamInputFormat(stream) == CAM_MEDIA_FORMAT_MJPG && !ecam_init_mjpeg_decoder(stream))
|
||||
goto fail;
|
||||
|
||||
@@ -161,6 +161,10 @@ option(WITH_FFMPEG "Enable FFMPEG for audio/video encoding/decoding" ON)
|
||||
cmake_dependent_option(WITH_DSP_FFMPEG "Use FFMPEG for audio encoding/decoding" ON "WITH_FFMPEG" OFF)
|
||||
cmake_dependent_option(WITH_VIDEO_FFMPEG "Use FFMPEG for video encoding/decoding" ON "WITH_FFMPEG" OFF)
|
||||
cmake_dependent_option(WITH_VAAPI "Use FFMPEG VAAPI" OFF "WITH_VIDEO_FFMPEG" OFF)
|
||||
cmake_dependent_option(WITH_VAAPI_H264_ENCODING "Use FFMPEG VAAPI hardware H264 encoding" ON "WITH_VIDEO_FFMPEG" OFF)
|
||||
if(WITH_VAAPI_H264_ENCODING)
|
||||
add_definitions("-DWITH_VAAPI_H264_ENCODING")
|
||||
endif()
|
||||
|
||||
option(USE_VERSION_FROM_GIT_TAG "Extract FreeRDP version from git tag." ON)
|
||||
|
||||
|
||||
@@ -61,6 +61,8 @@ extern "C"
|
||||
H264_CONTEXT_OPTION_FRAMERATE,
|
||||
H264_CONTEXT_OPTION_QP,
|
||||
H264_CONTEXT_OPTION_USAGETYPE, /** @since version 3.6.0 */
|
||||
H264_CONTEXT_OPTION_HW_ACCEL, /** set to request hw accel, get to check if hw accel is on,
|
||||
@since version 3.11.0 */
|
||||
} H264_CONTEXT_OPTION;
|
||||
|
||||
FREERDP_API void free_h264_metablock(RDPGFX_H264_METABLOCK* meta);
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, DWORD nDstHeight);
|
||||
|
||||
BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT32 height)
|
||||
BOOL yuv_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT32 height)
|
||||
{
|
||||
BOOL isNull = FALSE;
|
||||
UINT32 pheight = height;
|
||||
@@ -54,7 +54,9 @@ BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT3
|
||||
if (pheight % 16 != 0)
|
||||
pheight += 16 - pheight % 16;
|
||||
|
||||
for (size_t x = 0; x < 3; x++)
|
||||
const size_t nPlanes = h264->hwAccel ? 2 : 3;
|
||||
|
||||
for (size_t x = 0; x < nPlanes; x++)
|
||||
{
|
||||
if (!h264->pYUVData[x] || !h264->pOldYUVData[x])
|
||||
isNull = TRUE;
|
||||
@@ -68,13 +70,23 @@ BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT3
|
||||
if (isNull || (width != h264->width) || (height != h264->height) ||
|
||||
(stride != h264->iStride[0]))
|
||||
{
|
||||
h264->iStride[0] = stride;
|
||||
h264->iStride[1] = (stride + 1) / 2;
|
||||
h264->iStride[2] = (stride + 1) / 2;
|
||||
if (h264->hwAccel) /* NV12 */
|
||||
{
|
||||
h264->iStride[0] = stride;
|
||||
h264->iStride[1] = stride;
|
||||
h264->iStride[2] = 0;
|
||||
}
|
||||
else /* I420 */
|
||||
{
|
||||
h264->iStride[0] = stride;
|
||||
h264->iStride[1] = (stride + 1) / 2;
|
||||
h264->iStride[2] = (stride + 1) / 2;
|
||||
}
|
||||
|
||||
h264->width = width;
|
||||
h264->height = height;
|
||||
|
||||
for (size_t x = 0; x < 3; x++)
|
||||
for (size_t x = 0; x < nPlanes; x++)
|
||||
{
|
||||
BYTE* tmp1 = winpr_aligned_recalloc(h264->pYUVData[x], h264->iStride[x], pheight, 16);
|
||||
BYTE* tmp2 =
|
||||
@@ -91,6 +103,11 @@ BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT3
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT32 height)
|
||||
{
|
||||
return yuv_ensure_buffer(h264, stride, width, height);
|
||||
}
|
||||
|
||||
INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData,
|
||||
DWORD DstFormat, UINT32 nDstStep, UINT32 nDstWidth, UINT32 nDstHeight,
|
||||
const RECTANGLE_16* regionRects, UINT32 numRegionRects)
|
||||
@@ -238,7 +255,7 @@ INT32 h264_get_yuv_buffer(H264_CONTEXT* h264, UINT32 nSrcStride, UINT32 nSrcWidt
|
||||
if (!h264 || !h264->Compressor || !h264->subsystem || !h264->subsystem->Compress)
|
||||
return -1;
|
||||
|
||||
if (!avc420_ensure_buffer(h264, nSrcStride, nSrcWidth, nSrcHeight))
|
||||
if (!yuv_ensure_buffer(h264, nSrcStride, nSrcWidth, nSrcHeight))
|
||||
return -1;
|
||||
|
||||
for (size_t x = 0; x < 3; x++)
|
||||
@@ -708,7 +725,6 @@ H264_CONTEXT* h264_context_new(BOOL Compressor)
|
||||
|
||||
h264->Compressor = Compressor;
|
||||
if (Compressor)
|
||||
|
||||
{
|
||||
/* Default compressor settings, may be changed by caller */
|
||||
h264->BitRate = 1000000;
|
||||
@@ -786,6 +802,9 @@ BOOL h264_context_set_option(H264_CONTEXT* h264, H264_CONTEXT_OPTION option, UIN
|
||||
case H264_CONTEXT_OPTION_USAGETYPE:
|
||||
h264->UsageType = value;
|
||||
return TRUE;
|
||||
case H264_CONTEXT_OPTION_HW_ACCEL:
|
||||
h264->hwAccel = value ? TRUE : FALSE;
|
||||
return TRUE;
|
||||
default:
|
||||
WLog_Print(h264->log, WLOG_WARN, "Unknown H264_CONTEXT_OPTION[0x%08" PRIx32 "]",
|
||||
option);
|
||||
@@ -808,6 +827,8 @@ UINT32 h264_context_get_option(H264_CONTEXT* h264, H264_CONTEXT_OPTION option)
|
||||
return h264->QP;
|
||||
case H264_CONTEXT_OPTION_USAGETYPE:
|
||||
return h264->UsageType;
|
||||
case H264_CONTEXT_OPTION_HW_ACCEL:
|
||||
return h264->hwAccel;
|
||||
default:
|
||||
WLog_Print(h264->log, WLOG_WARN, "Unknown H264_CONTEXT_OPTION[0x%08" PRIx32 "]",
|
||||
option);
|
||||
|
||||
@@ -62,6 +62,7 @@ extern "C"
|
||||
UINT32 FrameRate;
|
||||
UINT32 QP;
|
||||
UINT32 UsageType;
|
||||
BOOL hwAccel;
|
||||
UINT32 NumberOfThreads;
|
||||
|
||||
UINT32 iStride[3];
|
||||
|
||||
@@ -65,7 +65,7 @@ static inline char* error_string(char* errbuf, size_t errbuf_size, int errnum)
|
||||
#define av_err2str(errnum) error_string((char[64]){ 0 }, 64, errnum)
|
||||
#endif
|
||||
|
||||
#ifdef WITH_VAAPI
|
||||
#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
|
||||
#define VAAPI_DEVICE "/dev/dri/renderD128"
|
||||
#endif
|
||||
|
||||
@@ -81,7 +81,7 @@ typedef struct
|
||||
AVPacket bufferpacket;
|
||||
#endif
|
||||
AVPacket* packet;
|
||||
#ifdef WITH_VAAPI
|
||||
#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
|
||||
AVBufferRef* hwctx;
|
||||
AVFrame* hwVideoFrame;
|
||||
enum AVPixelFormat hw_pix_fmt;
|
||||
@@ -91,7 +91,7 @@ typedef struct
|
||||
#endif
|
||||
} H264_CONTEXT_LIBAVCODEC;
|
||||
|
||||
static void libavcodec_destroy_encoder(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
static void libavcodec_destroy_encoder_context(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
{
|
||||
H264_CONTEXT_LIBAVCODEC* sys = NULL;
|
||||
|
||||
@@ -110,11 +110,47 @@ static void libavcodec_destroy_encoder(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
#endif
|
||||
}
|
||||
|
||||
sys->codecEncoder = NULL;
|
||||
sys->codecEncoderContext = NULL;
|
||||
}
|
||||
|
||||
static BOOL libavcodec_create_encoder(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
#ifdef WITH_VAAPI_H264_ENCODING
|
||||
static int set_hw_frames_ctx(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
{
|
||||
H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
|
||||
AVBufferRef* hw_frames_ref = NULL;
|
||||
AVHWFramesContext* frames_ctx = NULL;
|
||||
int err = 0;
|
||||
|
||||
if (!(hw_frames_ref = av_hwframe_ctx_alloc(sys->hwctx)))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to create VAAPI frame context");
|
||||
return -1;
|
||||
}
|
||||
frames_ctx = (AVHWFramesContext*)(hw_frames_ref->data);
|
||||
frames_ctx->format = AV_PIX_FMT_VAAPI;
|
||||
frames_ctx->sw_format = AV_PIX_FMT_NV12;
|
||||
frames_ctx->width = sys->codecEncoderContext->width;
|
||||
frames_ctx->height = sys->codecEncoderContext->height;
|
||||
frames_ctx->initial_pool_size = 20;
|
||||
if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Failed to initialize VAAPI frame context."
|
||||
"Error code: %s",
|
||||
av_err2str(err));
|
||||
av_buffer_unref(&hw_frames_ref);
|
||||
return err;
|
||||
}
|
||||
sys->codecEncoderContext->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
|
||||
if (!sys->codecEncoderContext->hw_frames_ctx)
|
||||
err = AVERROR(ENOMEM);
|
||||
|
||||
av_buffer_unref(&hw_frames_ref);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOL libavcodec_create_encoder_context(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
{
|
||||
BOOL recreate = FALSE;
|
||||
H264_CONTEXT_LIBAVCODEC* sys = NULL;
|
||||
@@ -126,9 +162,10 @@ static BOOL libavcodec_create_encoder(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
return FALSE;
|
||||
|
||||
sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
|
||||
if (!sys)
|
||||
if (!sys || !sys->codecEncoder)
|
||||
return FALSE;
|
||||
recreate = !sys->codecEncoder || !sys->codecEncoderContext;
|
||||
|
||||
recreate = !sys->codecEncoderContext;
|
||||
|
||||
if (sys->codecEncoderContext)
|
||||
{
|
||||
@@ -140,11 +177,7 @@ static BOOL libavcodec_create_encoder(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
if (!recreate)
|
||||
return TRUE;
|
||||
|
||||
libavcodec_destroy_encoder(h264);
|
||||
sys->codecEncoder = avcodec_find_encoder(AV_CODEC_ID_H264);
|
||||
|
||||
if (!sys->codecEncoder)
|
||||
goto EXCEPTION;
|
||||
libavcodec_destroy_encoder_context(h264);
|
||||
|
||||
sys->codecEncoderContext = avcodec_alloc_context3(sys->codecEncoder);
|
||||
|
||||
@@ -158,7 +191,11 @@ static BOOL libavcodec_create_encoder(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
break;
|
||||
|
||||
case H264_RATECONTROL_CQP:
|
||||
/* TODO: sys->codecEncoderContext-> = h264->QP; */
|
||||
if (av_opt_set_int(sys->codecEncoderContext, "qp", h264->QP, AV_OPT_SEARCH_CHILDREN) <
|
||||
0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "av_opt_set_int failed");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -174,17 +211,33 @@ static BOOL libavcodec_create_encoder(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
#endif
|
||||
sys->codecEncoderContext->time_base =
|
||||
(AVRational){ 1, WINPR_ASSERTING_INT_CAST(int, h264->FrameRate) };
|
||||
av_opt_set(sys->codecEncoderContext, "preset", "medium", AV_OPT_SEARCH_CHILDREN);
|
||||
av_opt_set(sys->codecEncoderContext, "tune", "zerolatency", AV_OPT_SEARCH_CHILDREN);
|
||||
|
||||
sys->codecEncoderContext->flags |= AV_CODEC_FLAG_LOOP_FILTER;
|
||||
sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
|
||||
#ifdef WITH_VAAPI_H264_ENCODING
|
||||
if (sys->hwctx)
|
||||
{
|
||||
av_opt_set(sys->codecEncoderContext, "preset", "veryslow", AV_OPT_SEARCH_CHILDREN);
|
||||
|
||||
sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_VAAPI;
|
||||
/* set hw_frames_ctx for encoder's AVCodecContext */
|
||||
if (set_hw_frames_ctx(h264) < 0)
|
||||
goto EXCEPTION;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
av_opt_set(sys->codecEncoderContext, "preset", "medium", AV_OPT_SEARCH_CHILDREN);
|
||||
sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
}
|
||||
|
||||
if (avcodec_open2(sys->codecEncoderContext, sys->codecEncoder, NULL) < 0)
|
||||
goto EXCEPTION;
|
||||
|
||||
return TRUE;
|
||||
EXCEPTION:
|
||||
libavcodec_destroy_encoder(h264);
|
||||
libavcodec_destroy_encoder_context(h264);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -346,7 +399,7 @@ static int libavcodec_compress(H264_CONTEXT* WINPR_RESTRICT h264,
|
||||
H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
|
||||
WINPR_ASSERT(sys);
|
||||
|
||||
if (!libavcodec_create_encoder(h264))
|
||||
if (!libavcodec_create_encoder_context(h264))
|
||||
return -1;
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
|
||||
@@ -369,7 +422,7 @@ static int libavcodec_compress(H264_CONTEXT* WINPR_RESTRICT h264,
|
||||
|
||||
WINPR_ASSERT(sys->videoFrame);
|
||||
WINPR_ASSERT(sys->codecEncoderContext);
|
||||
sys->videoFrame->format = sys->codecEncoderContext->pix_fmt;
|
||||
sys->videoFrame->format = AV_PIX_FMT_YUV420P;
|
||||
sys->videoFrame->width = sys->codecEncoderContext->width;
|
||||
sys->videoFrame->height = sys->codecEncoderContext->height;
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 48, 100)
|
||||
@@ -391,9 +444,37 @@ static int libavcodec_compress(H264_CONTEXT* WINPR_RESTRICT h264,
|
||||
sys->videoFrame->linesize[1] = (int)pStride[1];
|
||||
sys->videoFrame->linesize[2] = (int)pStride[2];
|
||||
sys->videoFrame->pts++;
|
||||
|
||||
#ifdef WITH_VAAPI_H264_ENCODING
|
||||
if (sys->hwctx)
|
||||
{
|
||||
av_frame_unref(sys->hwVideoFrame);
|
||||
if ((status = av_hwframe_get_buffer(sys->codecEncoderContext->hw_frames_ctx,
|
||||
sys->hwVideoFrame, 0)) < 0 ||
|
||||
!sys->hwVideoFrame->hw_frames_ctx)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "av_hwframe_get_buffer failed (%s [%d])",
|
||||
av_err2str(status), status);
|
||||
goto fail;
|
||||
}
|
||||
sys->videoFrame->format = AV_PIX_FMT_NV12;
|
||||
if ((status = av_hwframe_transfer_data(sys->hwVideoFrame, sys->videoFrame, 0)) < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "av_hwframe_transfer_data failed (%s [%d])",
|
||||
av_err2str(status), status);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* avcodec_encode_video2 is deprecated with libavcodec 57.48.101 */
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
|
||||
#ifdef WITH_VAAPI_H264_ENCODING
|
||||
status = avcodec_send_frame(sys->codecEncoderContext,
|
||||
sys->hwctx ? sys->hwVideoFrame : sys->videoFrame);
|
||||
#else
|
||||
status = avcodec_send_frame(sys->codecEncoderContext, sys->videoFrame);
|
||||
#endif
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
@@ -486,8 +567,7 @@ static void libavcodec_uninit(H264_CONTEXT* h264)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WITH_VAAPI
|
||||
|
||||
#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
|
||||
if (sys->hwVideoFrame)
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
|
||||
@@ -506,6 +586,7 @@ static void libavcodec_uninit(H264_CONTEXT* h264)
|
||||
av_buffer_unref(&sys->hw_frames_ctx);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
if (sys->codecParser)
|
||||
@@ -521,7 +602,7 @@ static void libavcodec_uninit(H264_CONTEXT* h264)
|
||||
#endif
|
||||
}
|
||||
|
||||
libavcodec_destroy_encoder(h264);
|
||||
libavcodec_destroy_encoder_context(h264);
|
||||
free(sys);
|
||||
h264->pSystemData = NULL;
|
||||
}
|
||||
@@ -666,10 +747,45 @@ static BOOL libavcodec_init(H264_CONTEXT* h264)
|
||||
goto EXCEPTION;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef WITH_VAAPI_H264_ENCODING
|
||||
if (h264->hwAccel) /* user requested hw accel */
|
||||
{
|
||||
sys->codecEncoder = avcodec_find_encoder_by_name("h264_vaapi");
|
||||
if (!sys->codecEncoder)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "H264 VAAPI encoder not found");
|
||||
}
|
||||
else if (av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VAAPI, VAAPI_DEVICE, NULL,
|
||||
0) < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "av_hwdevice_ctx_create failed");
|
||||
sys->codecEncoder = NULL;
|
||||
sys->hwctx = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_INFO, "Using VAAPI for accelerated H264 encoding");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!sys->codecEncoder)
|
||||
{
|
||||
sys->codecEncoder = avcodec_find_encoder(AV_CODEC_ID_H264);
|
||||
h264->hwAccel = FALSE; /* not supported */
|
||||
}
|
||||
|
||||
if (!sys->codecEncoder)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to initialize H264 encoder");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
|
||||
sys->videoFrame = av_frame_alloc();
|
||||
#ifdef WITH_VAAPI
|
||||
#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
|
||||
sys->hwVideoFrame = av_frame_alloc();
|
||||
#endif
|
||||
#else
|
||||
@@ -682,8 +798,7 @@ static BOOL libavcodec_init(H264_CONTEXT* h264)
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
#ifdef WITH_VAAPI
|
||||
|
||||
#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
|
||||
if (!sys->hwVideoFrame)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav hw frame");
|
||||
|
||||
@@ -648,6 +648,7 @@ static BOOL openh264_init(H264_CONTEXT* h264)
|
||||
}
|
||||
}
|
||||
|
||||
h264->hwAccel = FALSE; /* not supported */
|
||||
return TRUE;
|
||||
EXCEPTION:
|
||||
openh264_uninit(h264);
|
||||
|
||||
Reference in New Issue
Block a user