1af69d88dSmrg/************************************************************************** 2af69d88dSmrg * 3af69d88dSmrg * Copyright 2009 Younes Manton. 4af69d88dSmrg * All Rights Reserved. 5af69d88dSmrg * 6af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 7af69d88dSmrg * copy of this software and associated documentation files (the 8af69d88dSmrg * "Software"), to deal in the Software without restriction, including 9af69d88dSmrg * without limitation the rights to use, copy, modify, merge, publish, 10af69d88dSmrg * distribute, sub license, and/or sell copies of the Software, and to 11af69d88dSmrg * permit persons to whom the Software is furnished to do so, subject to 12af69d88dSmrg * the following conditions: 13af69d88dSmrg * 14af69d88dSmrg * The above copyright notice and this permission notice (including the 15af69d88dSmrg * next paragraph) shall be included in all copies or substantial portions 16af69d88dSmrg * of the Software. 17af69d88dSmrg * 18af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19af69d88dSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20af69d88dSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22af69d88dSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23af69d88dSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24af69d88dSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25af69d88dSmrg * 26af69d88dSmrg **************************************************************************/ 27af69d88dSmrg 28af69d88dSmrg#ifndef U_VIDEO_H 29af69d88dSmrg#define U_VIDEO_H 30af69d88dSmrg 31af69d88dSmrg#include "pipe/p_defines.h" 32af69d88dSmrg#include "pipe/p_video_enums.h" 33af69d88dSmrg 34af69d88dSmrg/* u_reduce_video_profile() needs these */ 35af69d88dSmrg#include "pipe/p_compiler.h" 36af69d88dSmrg#include "util/u_debug.h" 3701e04c3fSmrg#include "util/u_math.h" 38af69d88dSmrg 3901e04c3fSmrg#ifdef __cplusplus 4001e04c3fSmrgextern "C" { 4101e04c3fSmrg#endif 4201e04c3fSmrg 4301e04c3fSmrgstatic inline enum pipe_video_format 44af69d88dSmrgu_reduce_video_profile(enum pipe_video_profile profile) 45af69d88dSmrg{ 46af69d88dSmrg switch (profile) 47af69d88dSmrg { 48af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG1: 49af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: 50af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG2_MAIN: 51af69d88dSmrg return PIPE_VIDEO_FORMAT_MPEG12; 52af69d88dSmrg 53af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE: 54af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE: 55af69d88dSmrg return PIPE_VIDEO_FORMAT_MPEG4; 56af69d88dSmrg 57af69d88dSmrg case PIPE_VIDEO_PROFILE_VC1_SIMPLE: 58af69d88dSmrg case PIPE_VIDEO_PROFILE_VC1_MAIN: 59af69d88dSmrg case PIPE_VIDEO_PROFILE_VC1_ADVANCED: 60af69d88dSmrg return PIPE_VIDEO_FORMAT_VC1; 61af69d88dSmrg 62af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: 6301e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE: 64af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: 65af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED: 66af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: 67af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10: 68af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422: 69af69d88dSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444: 70af69d88dSmrg return PIPE_VIDEO_FORMAT_MPEG4_AVC; 71af69d88dSmrg 7201e04c3fSmrg case PIPE_VIDEO_PROFILE_HEVC_MAIN: 7301e04c3fSmrg case PIPE_VIDEO_PROFILE_HEVC_MAIN_10: 7401e04c3fSmrg case PIPE_VIDEO_PROFILE_HEVC_MAIN_STILL: 7501e04c3fSmrg case PIPE_VIDEO_PROFILE_HEVC_MAIN_12: 7601e04c3fSmrg case PIPE_VIDEO_PROFILE_HEVC_MAIN_444: 7701e04c3fSmrg return PIPE_VIDEO_FORMAT_HEVC; 7801e04c3fSmrg 7901e04c3fSmrg case PIPE_VIDEO_PROFILE_JPEG_BASELINE: 8001e04c3fSmrg return PIPE_VIDEO_FORMAT_JPEG; 8101e04c3fSmrg 8201e04c3fSmrg case PIPE_VIDEO_PROFILE_VP9_PROFILE0: 8301e04c3fSmrg case PIPE_VIDEO_PROFILE_VP9_PROFILE2: 8401e04c3fSmrg return PIPE_VIDEO_FORMAT_VP9; 8501e04c3fSmrg 867ec681f3Smrg case PIPE_VIDEO_PROFILE_AV1_MAIN: 877ec681f3Smrg return PIPE_VIDEO_FORMAT_AV1; 887ec681f3Smrg 89af69d88dSmrg default: 90af69d88dSmrg return PIPE_VIDEO_FORMAT_UNKNOWN; 91af69d88dSmrg } 92af69d88dSmrg} 93af69d88dSmrg 9401e04c3fSmrgstatic inline void 9501e04c3fSmrgu_copy_nv12_to_yv12(void *const *destination_data, 9601e04c3fSmrg uint32_t const *destination_pitches, 9701e04c3fSmrg int src_plane, int src_field, 9801e04c3fSmrg int src_stride, int num_fields, 9901e04c3fSmrg uint8_t const *src, 10001e04c3fSmrg int width, int height) 10101e04c3fSmrg{ 10201e04c3fSmrg int x, y; 10301e04c3fSmrg unsigned u_stride = destination_pitches[2] * num_fields; 10401e04c3fSmrg unsigned v_stride = destination_pitches[1] * num_fields; 10501e04c3fSmrg uint8_t *u_dst = (uint8_t *)destination_data[2] + destination_pitches[2] * src_field; 10601e04c3fSmrg uint8_t *v_dst = (uint8_t *)destination_data[1] + destination_pitches[1] * src_field; 10701e04c3fSmrg 10801e04c3fSmrg /* TODO: SIMD */ 10901e04c3fSmrg for (y = 0; y < height; y++) { 11001e04c3fSmrg for (x = 0; x < width; x++) { 11101e04c3fSmrg u_dst[x] = src[2*x]; 11201e04c3fSmrg v_dst[x] = src[2*x+1]; 11301e04c3fSmrg } 11401e04c3fSmrg u_dst += u_stride; 11501e04c3fSmrg v_dst += v_stride; 11601e04c3fSmrg src += src_stride; 11701e04c3fSmrg } 11801e04c3fSmrg} 11901e04c3fSmrg 12001e04c3fSmrg/** 12101e04c3fSmrg * \brief Copy YV12 chroma data while converting it NV12 12201e04c3fSmrg * 12301e04c3fSmrg * Given a set of YV12 source pointers and -pitches, copy the data to a 12401e04c3fSmrg * layout typical for NV12 video buffers. 12501e04c3fSmrg * 12601e04c3fSmrg * \param source data[in] The plane data pointers. Array of 3. 12701e04c3fSmrg * \param source_pitches[in] The plane pitches. Array of 3. 12801e04c3fSmrg * \param dst_plane[in] The destination plane to copy to. For NV12 always 1. 12901e04c3fSmrg * \param dst_field[in] The destination field if interlaced. 13001e04c3fSmrg * \param dst_stride[in] The destination stride for this plane. 13101e04c3fSmrg * \param num_fields[in] The number of fields in the video buffer. 13201e04c3fSmrg * \param dst[in] The destination plane pointer. 13301e04c3fSmrg * \param width[in] The source plane width. 13401e04c3fSmrg * \param height[in] The source plane height. 13501e04c3fSmrg */ 13601e04c3fSmrgstatic inline void 13701e04c3fSmrgu_copy_nv12_from_yv12(const void *const *source_data, 13801e04c3fSmrg uint32_t const *source_pitches, 13901e04c3fSmrg int dst_plane, int dst_field, 14001e04c3fSmrg int dst_stride, int num_fields, 14101e04c3fSmrg uint8_t *dst, 14201e04c3fSmrg int width, int height) 14301e04c3fSmrg{ 14401e04c3fSmrg int x, y; 14501e04c3fSmrg unsigned u_stride = source_pitches[2] * num_fields; 14601e04c3fSmrg unsigned v_stride = source_pitches[1] * num_fields; 14701e04c3fSmrg uint8_t *u_src = (uint8_t *)source_data[2] + source_pitches[2] * dst_field; 14801e04c3fSmrg uint8_t *v_src = (uint8_t *)source_data[1] + source_pitches[1] * dst_field; 14901e04c3fSmrg 15001e04c3fSmrg /* TODO: SIMD */ 15101e04c3fSmrg for (y = 0; y < height; y++) { 15201e04c3fSmrg for (x = 0; x < width; x++) { 15301e04c3fSmrg dst[2*x] = u_src[x]; 15401e04c3fSmrg dst[2*x+1] = v_src[x]; 15501e04c3fSmrg } 15601e04c3fSmrg u_src += u_stride; 15701e04c3fSmrg v_src += v_stride; 15801e04c3fSmrg dst += dst_stride; 15901e04c3fSmrg } 16001e04c3fSmrg} 16101e04c3fSmrg 16201e04c3fSmrgstatic inline void 16301e04c3fSmrgu_copy_yv12_to_nv12(void *const *destination_data, 16401e04c3fSmrg uint32_t const *destination_pitches, 16501e04c3fSmrg int src_plane, int src_field, 16601e04c3fSmrg int src_stride, int num_fields, 16701e04c3fSmrg uint8_t const *src, 16801e04c3fSmrg int width, int height) 16901e04c3fSmrg{ 17001e04c3fSmrg int x, y; 17101e04c3fSmrg unsigned offset = 2 - src_plane; 17201e04c3fSmrg unsigned stride = destination_pitches[1] * num_fields; 17301e04c3fSmrg uint8_t *dst = (uint8_t *)destination_data[1] + destination_pitches[1] * src_field; 17401e04c3fSmrg 17501e04c3fSmrg /* TODO: SIMD */ 17601e04c3fSmrg for (y = 0; y < height; y++) { 17701e04c3fSmrg for (x = 0; x < 2 * width; x += 2) { 17801e04c3fSmrg dst[x+offset] = src[x>>1]; 17901e04c3fSmrg } 18001e04c3fSmrg dst += stride; 18101e04c3fSmrg src += src_stride; 18201e04c3fSmrg } 18301e04c3fSmrg} 18401e04c3fSmrg 18501e04c3fSmrgstatic inline void 18601e04c3fSmrgu_copy_swap422_packed(void *const *destination_data, 18701e04c3fSmrg uint32_t const *destination_pitches, 18801e04c3fSmrg int src_plane, int src_field, 18901e04c3fSmrg int src_stride, int num_fields, 19001e04c3fSmrg uint8_t const *src, 19101e04c3fSmrg int width, int height) 19201e04c3fSmrg{ 19301e04c3fSmrg int x, y; 19401e04c3fSmrg unsigned stride = destination_pitches[0] * num_fields; 19501e04c3fSmrg uint8_t *dst = (uint8_t *)destination_data[0] + destination_pitches[0] * src_field; 19601e04c3fSmrg 19701e04c3fSmrg /* TODO: SIMD */ 19801e04c3fSmrg for (y = 0; y < height; y++) { 19901e04c3fSmrg for (x = 0; x < 4 * width; x += 4) { 20001e04c3fSmrg dst[x+0] = src[x+1]; 20101e04c3fSmrg dst[x+1] = src[x+0]; 20201e04c3fSmrg dst[x+2] = src[x+3]; 20301e04c3fSmrg dst[x+3] = src[x+2]; 20401e04c3fSmrg } 20501e04c3fSmrg dst += stride; 20601e04c3fSmrg src += src_stride; 20701e04c3fSmrg } 20801e04c3fSmrg} 20901e04c3fSmrg 21001e04c3fSmrgstatic inline uint32_t 21101e04c3fSmrgu_get_h264_level(uint32_t width, uint32_t height, uint32_t *max_reference) 21201e04c3fSmrg{ 21301e04c3fSmrg uint32_t max_dpb_mbs; 21401e04c3fSmrg 21501e04c3fSmrg width = align(width, 16); 21601e04c3fSmrg height = align(height, 16); 21701e04c3fSmrg 21801e04c3fSmrg /* Max references will be used for caculation of number of DPB buffers 21901e04c3fSmrg in the UVD driver, limitation of max references is 16. Some client 22001e04c3fSmrg like mpv application for VA-API, it requires references more than that, 22101e04c3fSmrg so we have to set max of references to 16 here. */ 22201e04c3fSmrg *max_reference = MIN2(*max_reference, 16); 22301e04c3fSmrg max_dpb_mbs = (width / 16) * (height / 16) * *max_reference; 22401e04c3fSmrg 22501e04c3fSmrg /* The calculation is based on "Decoded picture buffering" section 22601e04c3fSmrg from http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC */ 22701e04c3fSmrg if (max_dpb_mbs <= 8100) 22801e04c3fSmrg return 30; 22901e04c3fSmrg else if (max_dpb_mbs <= 18000) 23001e04c3fSmrg return 31; 23101e04c3fSmrg else if (max_dpb_mbs <= 20480) 23201e04c3fSmrg return 32; 23301e04c3fSmrg else if (max_dpb_mbs <= 32768) 23401e04c3fSmrg return 41; 23501e04c3fSmrg else if (max_dpb_mbs <= 34816) 23601e04c3fSmrg return 42; 23701e04c3fSmrg else if (max_dpb_mbs <= 110400) 23801e04c3fSmrg return 50; 23901e04c3fSmrg else if (max_dpb_mbs <= 184320) 24001e04c3fSmrg return 51; 24101e04c3fSmrg else 24201e04c3fSmrg return 52; 24301e04c3fSmrg} 24401e04c3fSmrg 24501e04c3fSmrgstatic inline uint32_t 24601e04c3fSmrgu_get_h264_profile_idc(enum pipe_video_profile profile) 24701e04c3fSmrg{ 24801e04c3fSmrg switch (profile) { 24901e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE: 25001e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: 25101e04c3fSmrg return 66; 25201e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: 25301e04c3fSmrg return 77; 25401e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED: 25501e04c3fSmrg return 88; 25601e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: 25701e04c3fSmrg return 100; 25801e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10: 25901e04c3fSmrg return 110; 26001e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422: 26101e04c3fSmrg return 122; 26201e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444: 26301e04c3fSmrg return 244; 26401e04c3fSmrg default: 26501e04c3fSmrg return 66; //use baseline profile instead 26601e04c3fSmrg } 26701e04c3fSmrg} 26801e04c3fSmrg 269af69d88dSmrg#ifdef __cplusplus 270af69d88dSmrg} 271af69d88dSmrg#endif 272af69d88dSmrg 273af69d88dSmrg#endif /* U_VIDEO_H */ 274