Welcome to mirror list, hosted at ThFree Co, Russian Federation.

LAVPixFmtConverter.h « LAVVideo « decoder - github.com/mpc-hc/LAVFilters.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 5a3d88b27d4c2d94154fa57878450c67780c3894 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
 *      Copyright (C) 2010-2013 Hendrik Leppkes
 *      http://www.1f0.de
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#pragma once

#include "LAVVideoSettings.h"
#include "decoders/ILAVDecoder.h"

#define CONV_FUNC_PARAMS (const uint8_t* const src[4], const int srcStride[4], uint8_t *dst, int dstStride, int width, int height, LAVPixelFormat inputFormat, int bpp, LAVOutPixFmts outputFormat)

#define DECLARE_CONV_FUNC(name) \
  HRESULT name CONV_FUNC_PARAMS

#define DECLARE_CONV_FUNC_IMPL(name) \
  DECLARE_CONV_FUNC(CLAVPixFmtConverter::name)

// Important, when adding new pixel formats, they need to be added in LAVPixFmtConverter.cpp as well to the format descriptors// Important, when adding new pixel formats, they need to be added in LAVPixFmtConverter.cpp as well to the format descriptors
typedef struct {
  GUID subtype;
  int bpp;
  int codedbytes;
  int planes;
  int planeHeight[4];
  int planeWidth[4];
} LAVOutPixFmtDesc;

typedef struct _RGBCoeffs {
  __m128i Ysub;
  __m128i CbCr_center;
  __m128i rgb_add;
  __m128i cy;
  __m128i cR_Cr;
  __m128i cG_Cb_cG_Cr;
  __m128i cB_Cb;
} RGBCoeffs;

extern LAVOutPixFmtDesc lav_pixfmt_desc[];

class CLAVPixFmtConverter
{
public:
  CLAVPixFmtConverter();
  ~CLAVPixFmtConverter();

  void SetSettings(ILAVVideoSettings *pSettings) { m_pSettings = pSettings; }

  BOOL SetInputFmt(enum LAVPixelFormat pixfmt, int bpp) { if (m_InputPixFmt != pixfmt || m_InBpp != bpp) { m_InputPixFmt = pixfmt; m_InBpp = bpp; DestroySWScale(); SelectConvertFunction(); return TRUE; } return FALSE; }
  HRESULT SetOutputPixFmt(enum LAVOutPixFmts pix_fmt) { m_OutputPixFmt = pix_fmt; DestroySWScale(); SelectConvertFunction(); return S_OK; }
  
  LAVOutPixFmts GetOutputBySubtype(const GUID *guid);
  LAVOutPixFmts GetPreferredOutput();

  LAVOutPixFmts GetOutputPixFmt() { return m_OutputPixFmt; }
  void SetColorProps(DXVA2_ExtendedFormat props, int RGBOutputRange) { if (props.value != m_ColorProps.value || swsOutputRange != RGBOutputRange) { DestroySWScale(); m_ColorProps = props; swsOutputRange = RGBOutputRange; } }

  int GetNumMediaTypes();
  void GetMediaType(CMediaType *mt, int index, LONG biWidth, LONG biHeight, DWORD dwAspectX, DWORD dwAspectY, REFERENCE_TIME rtAvgTime, BOOL bInterlaced = TRUE, BOOL bVIH1 = FALSE);
  BOOL IsAllowedSubtype(const GUID *guid);

  inline HRESULT Convert(LAVFrame *pFrame, uint8_t *dst, int width, int height, int dstStride) {
    uint8_t *out = dst;
    int outStride = dstStride;
    // Check if we have proper pixel alignment and the dst memory is actually aligned
    if (m_RequiredAlignment && (FFALIGN(dstStride, m_RequiredAlignment) != dstStride || ((uintptr_t)dst % 16u))) {
      outStride = FFALIGN(dstStride, m_RequiredAlignment);
      size_t requiredSize = (outStride * height * lav_pixfmt_desc[m_OutputPixFmt].bpp) << 3;
      if (requiredSize > m_nAlignedBufferSize) {
        DbgLog((LOG_TRACE, 10, L"::Convert(): Conversion requires a bigger stride (need: %d, have: %d), allocating buffer...", outStride, dstStride));
        av_freep(&m_pAlignedBuffer);
        m_nAlignedBufferSize = requiredSize;
        m_pAlignedBuffer = (uint8_t *)av_malloc(m_nAlignedBufferSize+FF_INPUT_BUFFER_PADDING_SIZE);
      }
      out = m_pAlignedBuffer;
    }
    HRESULT hr = (this->*convert)(pFrame->data, pFrame->stride, out, outStride, width, height, m_InputPixFmt, m_InBpp, m_OutputPixFmt);
    if (out != dst) {
      ChangeStride(out, outStride, dst, dstStride, width, height, m_OutputPixFmt);
    }
    return hr;
  }

  BOOL IsRGBConverterActive() { return m_bRGBConverter; }

private:
  AVPixelFormat GetFFInput() {
    return getFFPixelFormatFromLAV(m_InputPixFmt, m_InBpp);
  }

  int GetFilteredFormatCount();
  LAVOutPixFmts GetFilteredFormat(int index);

  void SelectConvertFunction();

  // Helper functions for convert_generic
  HRESULT swscale_scale(enum AVPixelFormat srcPix, enum AVPixelFormat dstPix, const uint8_t* const src[], const int srcStride[], BYTE *pOut, int width, int height, int stride, LAVOutPixFmtDesc pixFmtDesc, bool swapPlanes12 = false);
  HRESULT ConvertTo422Packed(const uint8_t* const src[4], const int srcStride[4], uint8_t *dst, int width, int height, int dstStride);
  HRESULT ConvertToAYUV(const uint8_t* const src[4], const int srcStride[4], uint8_t *dst, int width, int height, int dstStride);
  HRESULT ConvertToPX1X(const uint8_t* const src[4], const int srcStride[4], uint8_t *dst, int width, int height, int dstStride, int chromaVertical);
  HRESULT ConvertToY410(const uint8_t* const src[4], const int srcStride[4], uint8_t *dst, int width, int height, int dstStride);
  HRESULT ConvertToY416(const uint8_t* const src[4], const int srcStride[4], uint8_t *dst, int width, int height, int dstStride);
  HRESULT ConvertTov210(const uint8_t* const src[4], const int srcStride[4], uint8_t *dst, int width, int height, int dstStride);
  HRESULT ConvertTov410(const uint8_t* const src[4], const int srcStride[4], uint8_t *dst, int width, int height, int dstStride);

  void DestroySWScale() { if (m_pSwsContext) sws_freeContext(m_pSwsContext); m_pSwsContext = NULL; if (m_rgbCoeffs) _aligned_free(m_rgbCoeffs); m_rgbCoeffs = NULL; if (m_pRandomDithers) _aligned_free(m_pRandomDithers); m_pRandomDithers = NULL; };
  SwsContext *GetSWSContext(int width, int height, enum AVPixelFormat srcPix, enum AVPixelFormat dstPix, int flags);

  void ChangeStride(const uint8_t* src, int srcStride, uint8_t *dst, int dstStride, int width, int height, LAVOutPixFmts format);

  typedef HRESULT (CLAVPixFmtConverter::*ConverterFn) CONV_FUNC_PARAMS;

  // Conversion function pointer
  ConverterFn convert;

  // Pixel Implementations
  DECLARE_CONV_FUNC(convert_generic);
  DECLARE_CONV_FUNC(plane_copy);
  DECLARE_CONV_FUNC(convert_yuv444_ayuv);
  DECLARE_CONV_FUNC(convert_yuv444_ayuv_dither_le);
  DECLARE_CONV_FUNC(convert_yuv444_y410);
  DECLARE_CONV_FUNC(convert_yuv420_px1x_le);
  DECLARE_CONV_FUNC(convert_yuv420_nv12);
  DECLARE_CONV_FUNC(convert_yuv_yv);
  DECLARE_CONV_FUNC(convert_nv12_yv12);
  DECLARE_CONV_FUNC(convert_nv12_nv12);
  template <int uyvy> DECLARE_CONV_FUNC(convert_yuv420_yuy2);
  template <int uyvy> DECLARE_CONV_FUNC(convert_yuv422_yuy2_uyvy);
  template <int uyvy> DECLARE_CONV_FUNC(convert_yuv422_yuy2_uyvy_dither_le);
  template <int nv12> DECLARE_CONV_FUNC(convert_yuv_yv_nv12_dither_le);

  DECLARE_CONV_FUNC(convert_rgb48_rgb32_ssse3);
  template <int out32> DECLARE_CONV_FUNC(convert_rgb48_rgb);

  template <int out32> DECLARE_CONV_FUNC(convert_yuv_rgb);
  RGBCoeffs* getRGBCoeffs(int width, int height);
  const uint16_t* GetRandomDitherCoeffs(int height, int coeffs, int bits, int line);

private:
  LAVPixelFormat  m_InputPixFmt;
  LAVOutPixFmts   m_OutputPixFmt;
  int             m_InBpp;

  int swsWidth, swsHeight;
  int swsOutputRange;

  DXVA2_ExtendedFormat m_ColorProps;

  unsigned m_RequiredAlignment;

  SwsContext *m_pSwsContext;

  size_t   m_nAlignedBufferSize;
  uint8_t *m_pAlignedBuffer;

  int m_NumThreads;

  ILAVVideoSettings *m_pSettings;

  RGBCoeffs *m_rgbCoeffs;
  BOOL m_bRGBConverter;

  uint16_t *m_pRandomDithers;
  int m_ditherWidth;
  int m_ditherHeight;
  int m_ditherBits;
};