blob: b1d6fb0a13e70831773b6a8a160a1ad04028aa05 [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// resolution detectors
#include <linux/videodev2.h>
#ifdef HAS_VAAPI
#include <va/va.h>
#endif
#include "label_detect.h"
static const char kVideoDevicePattern[] = "/dev/video*";
static const char kDRMDevicePattern[] = "/dev/dri/renderD*";
static const int32_t width_4k = 3840;
static const int32_t height_4k = 2160;
/* Helper function for is_4k_device_h264().
* Determines if a VAAPI device associated with given |fd| supports
* H264 decoding and its maximum resolution is larger than 3840x2160.
*/
static bool is_vaapi_4k_device_h264(int fd) {
#ifdef HAS_VAAPI
#if VA_CHECK_VERSION(0, 35, 0)
VAProfile va_profiles[] = {
VAProfileH264Baseline,
VAProfileH264Main,
VAProfileH264High,
VAProfileH264ConstrainedBaseline,
VAProfileNone
};
int32_t resolution_width = 0;
int32_t resolution_height = 0;
if (is_vaapi_support_formats(
fd, va_profiles, VAEntrypointVLD, VA_RT_FORMAT_YUV420)) {
if (get_vaapi_max_resolution(fd, va_profiles, VAEntrypointVLD,
&resolution_width, &resolution_height)) {
return resolution_width >= width_4k && resolution_height >= height_4k;
}
}
#endif
#endif
return false;
}
/* Helper function for is_4k_device_vp8().
* Determines if a VAAPI device associated with given |fd| supports
* VP8 decoding and its maximum resolution is larger than 3840x2160.
*/
static bool is_vaapi_4k_device_vp8(int fd) {
#ifdef HAS_VAAPI
#if VA_CHECK_VERSION(0, 35, 0)
VAProfile va_profiles[] = {
VAProfileVP8Version0_3,
VAProfileNone
};
int32_t resolution_width = 0;
int32_t resolution_height = 0;
if (is_vaapi_support_formats(
fd, va_profiles, VAEntrypointVLD, VA_RT_FORMAT_YUV420)) {
if (get_vaapi_max_resolution(fd, va_profiles, VAEntrypointVLD,
&resolution_width, &resolution_height)) {
return resolution_width >= width_4k && resolution_height >= height_4k;
}
}
#endif
#endif
return false;
}
/* Helper function for is_4k_device_vp9().
* Determines if a VAAPI device associated with given |fd| supports
* VP9 decoding and its maximum resolution is larger than 3840x2160.
*/
static bool is_vaapi_4k_device_vp9(int fd) {
#ifdef HAS_VAAPI
#if VA_CHECK_VERSION(0, 35, 0)
VAProfile va_profiles[] = {
VAProfileVP9Profile0,
VAProfileNone
};
int32_t resolution_width;
int32_t resolution_height;
if (is_vaapi_support_formats(
fd, va_profiles, VAEntrypointVLD, VA_RT_FORMAT_YUV420)) {
if (get_vaapi_max_resolution(fd, va_profiles, VAEntrypointVLD,
&resolution_width, &resolution_height)) {
return resolution_width >= width_4k && resolution_height >= height_4k;
}
}
#endif
#endif
return false;
}
/* Helper function for is_4k_device_h264().
* A V4L2 device supports 4k resolution H264 decoding, if it supports H264
* decoding and the maximum resolution is larger than 3840x2160.
*/
static bool is_v4l2_4k_device_h264(int fd) {
int32_t resolution_width;
int32_t resolution_height;
if (!is_hw_video_acc_device(fd)) {
return false;
}
if (is_v4l2_support_format(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
V4L2_PIX_FMT_H264)) {
if (get_v4l2_max_resolution(fd, V4L2_PIX_FMT_H264,
&resolution_width, &resolution_height)) {
return resolution_width >= width_4k && resolution_height >= height_4k;
}
}
if (is_v4l2_support_format(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
V4L2_PIX_FMT_H264_SLICE)) {
if (get_v4l2_max_resolution(fd, V4L2_PIX_FMT_H264_SLICE,
&resolution_width, &resolution_height)) {
return resolution_width >= width_4k && resolution_height >= height_4k;
}
}
return false;
}
/* Helper function for is_4k_device_vp8().
* A V4L2 device supports 4k resolution VP8 decoding, if it supports VP8
* decoding and the maximum resolution is larger than 3840x2160.
*/
static bool is_v4l2_4k_device_vp8(int fd) {
int32_t resolution_width;
int32_t resolution_height;
if (!is_hw_video_acc_device(fd)) {
return false;
}
if (is_v4l2_support_format(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
V4L2_PIX_FMT_VP8)) {
if (get_v4l2_max_resolution(fd, V4L2_PIX_FMT_VP8,
&resolution_width, &resolution_height)) {
return resolution_width >= width_4k && resolution_height >= height_4k;
}
}
if (is_v4l2_support_format(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
V4L2_PIX_FMT_VP8_FRAME)) {
if (get_v4l2_max_resolution(fd, V4L2_PIX_FMT_VP8_FRAME,
&resolution_width, &resolution_height)) {
return resolution_width >= width_4k && resolution_height >= height_4k;
}
}
return false;
}
/* Helper function for is_4k_device_vp9().
* A V4L2 device supports 4k resolution VP9 decoding, if it supports VP9
* decoding and the maximum resolution is larger than 3840x2160.
*/
static bool is_v4l2_4k_device_vp9(int fd) {
int32_t resolution_width;
int32_t resolution_height;
if (!is_hw_video_acc_device(fd)) {
return false;
}
if (is_v4l2_support_format(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
V4L2_PIX_FMT_VP9)) {
if (get_v4l2_max_resolution(fd, V4L2_PIX_FMT_VP9,
&resolution_width, &resolution_height)) {
return resolution_width >= width_4k && resolution_height >= height_4k;
}
}
if (is_v4l2_support_format(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
V4L2_PIX_FMT_VP9_FRAME)) {
if (get_v4l2_max_resolution(fd, V4L2_PIX_FMT_VP9_FRAME,
&resolution_width, &resolution_height)) {
return resolution_width >= width_4k && resolution_height >= height_4k;
}
}
return false;
}
/* Determines "4k_video_h264". Return true, if either the VAAPI device
* supports 4k resolution H264 decoding, has decoding entry point,
* and input YUV420 formats. Or there is a
* /dev/video* device supporting 4k resolution H264 decoding.
*/
bool detect_4k_device_h264(void) {
return (is_any_device(kDRMDevicePattern, is_vaapi_4k_device_h264) ||
is_any_device(kVideoDevicePattern, is_v4l2_4k_device_h264));
}
/* Determines "4k_video_vp8". Return true, if either the VAAPI device
* supports 4k resolution VP8 decoding, has decoding entry point,
* and input YUV420 formats. Or there is a
* /dev/video* device supporting 4k resolution VP8 decoding.
*/
bool detect_4k_device_vp8(void) {
return (is_any_device(kDRMDevicePattern, is_vaapi_4k_device_vp8) ||
is_any_device(kVideoDevicePattern, is_v4l2_4k_device_vp8));
}
/* Determines "4k_video_vp9". Return true, if either the VAAPI device
* supports 4k resolution VP9 decoding, has decoding entry point,
* and input YUV420 formats. Or there is a
* /dev/video* device supporting 4k resolution VP9 decoding.
*/
bool detect_4k_device_vp9(void) {
return (is_any_device(kDRMDevicePattern, is_vaapi_4k_device_vp9) ||
is_any_device(kVideoDevicePattern, is_v4l2_4k_device_vp9));
}