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