This file is indexed.

/usr/include/movit/ycbcr_input.h is in libmovit-dev 1.6.1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#ifndef _MOVIT_YCBCR_INPUT_H
#define _MOVIT_YCBCR_INPUT_H 1

// YCbCrInput is for handling Y'CbCr (also sometimes, usually rather
// imprecisely, called “YUV”), which is typically what you get from a video
// decoder. It supports these formats:
//
//   * 8-bit planar Y'CbCr, possibly subsampled (e.g. 4:2:0).
//   * 8-bit semiplanar Y'CbCr (Y' in one plane, CbCr in another),
//     possibly subsampled.
//   * 8-bit interleaved (chunked) Y'CbCr, no subsampling (4:4:4 only).
//   * All of the above in 10- and 12-bit versions, where each sample is
//     stored in a 16-bit int (so the 6 or 4 top bits are wasted).
//   * 10-bit interleaved (chunked) Y'CbCr packed into 32-bit words
//     (10:10:10:2), no subsampling (4:4:4 only).
//
// For the planar and semiplanar cases, it upsamples planes as needed, using
// the default linear upsampling OpenGL gives you. Note that YCbCr422InterleavedInput
// supports the important special case of 8-bit 4:2:2 interleaved.

#include <epoxy/gl.h>
#include <assert.h>
#include <string>

#include "effect.h"
#include "effect_chain.h"
#include "image_format.h"
#include "input.h"
#include "ycbcr.h"

namespace movit {

class ResourcePool;

// Whether the data is planar (Y', Cb and Cr in one texture each) or not.
enum YCbCrInputSplitting {
	// The standard, default case; Y', Cb and Cr in one texture each.
	YCBCR_INPUT_PLANAR,

	// Y' in one texture, and then Cb and Cr interleaved in one texture.
	// In particular, this is a superset of the relatively popular NV12 mode.
	// If you specify this mode, the “Cr” pointer texture will be unused
	// (the ”Cb” texture contains both).
	YCBCR_INPUT_SPLIT_Y_AND_CBCR,

	// Y', Cb and Cr interleaved in the same texture (the “Y” texture;
	// “Cb” and “Cr” are unused). This means you cannot have any subsampling;
	// 4:4:4 only.
	YCBCR_INPUT_INTERLEAVED,
};

class YCbCrInput : public Input {
public:
	// Type can be GL_UNSIGNED_BYTE for 8-bit, GL_UNSIGNED_SHORT for 10- or 12-bit
	// (or 8-bit, although that's a bit useless), or GL_UNSIGNED_INT_2_10_10_10_REV
	// for 10-bit (YCBCR_INPUT_INTERLEAVED only).
	YCbCrInput(const ImageFormat &image_format,
	           const YCbCrFormat &ycbcr_format,
	           unsigned width, unsigned height,
	           YCbCrInputSplitting ycbcr_input_splitting = YCBCR_INPUT_PLANAR,
	           GLenum type = GL_UNSIGNED_BYTE);
	~YCbCrInput();

	std::string effect_type_id() const override { return "YCbCrInput"; }

	bool can_output_linear_gamma() const override { return false; }
	AlphaHandling alpha_handling() const override { return OUTPUT_BLANK_ALPHA; }

	std::string output_fragment_shader() override;

	// Uploads the texture if it has changed since last time.
	void set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num) override;

	unsigned get_width() const override { return width; }
	unsigned get_height() const override { return height; }
	Colorspace get_color_space() const override { return image_format.color_space; }
	GammaCurve get_gamma_curve() const override { return image_format.gamma_curve; }
	bool can_supply_mipmaps() const override { return ycbcr_input_splitting == YCBCR_INPUT_INTERLEAVED; }
	bool is_single_texture() const override { return ycbcr_input_splitting == YCBCR_INPUT_INTERLEAVED; }

	// Tells the input where to fetch the actual pixel data. Note that if you change
	// this data, you must either call set_pixel_data() again (using the same pointer
	// is fine), or invalidate_pixel_data(). Otherwise, the texture won't be re-uploaded
	// on subsequent frames.
	//
	// The data can either be a regular pointer (if pbo==0), or a byte offset
	// into a PBO. The latter will allow you to start uploading the texture data
	// asynchronously to the GPU, if you have any CPU-intensive work between the
	// call to set_pixel_data() and the actual rendering. In either case,
	// the pointer (and PBO, if set) has to be valid at the time of the render call.
	void set_pixel_data(unsigned channel, const unsigned char *pixel_data, GLuint pbo = 0)
	{
		assert(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_2_10_10_10_REV);
		assert(channel >= 0 && channel < num_channels);
		this->pixel_data[channel] = pixel_data;
		this->pbos[channel] = pbo;
		invalidate_pixel_data();
	}

	void set_pixel_data(unsigned channel, const uint16_t *pixel_data, GLuint pbo = 0)
	{
		assert(type == GL_UNSIGNED_SHORT);
		assert(channel >= 0 && channel < num_channels);
		this->pixel_data[channel] = reinterpret_cast<const unsigned char *>(pixel_data);
		this->pbos[channel] = pbo;
		invalidate_pixel_data();
	}

	void set_pixel_data(unsigned channel, const uint32_t *pixel_data, GLuint pbo = 0)
	{
		assert(type == GL_UNSIGNED_INT_2_10_10_10_REV);
		assert(channel == 0);
		this->pixel_data[channel] = reinterpret_cast<const unsigned char *>(pixel_data);
		this->pbos[channel] = pbo;
		invalidate_pixel_data();
	}

	void invalidate_pixel_data();

	// Note: Sets pitch to width, so even if your pitch is unchanged,
	// you will need to re-set it after this call.
	void set_width(unsigned width)
	{
		assert(width != 0);
		this->width = width;

		assert(width % ycbcr_format.chroma_subsampling_x == 0);
		pitch[0] = widths[0] = width;
		pitch[1] = widths[1] = width / ycbcr_format.chroma_subsampling_x;
		pitch[2] = widths[2] = width / ycbcr_format.chroma_subsampling_x;
		invalidate_pixel_data();
	}

	void set_height(unsigned height)
	{
		assert(height != 0);
		this->height = height;

		assert(height % ycbcr_format.chroma_subsampling_y == 0);
		heights[0] = height;
		heights[1] = height / ycbcr_format.chroma_subsampling_y;
		heights[2] = height / ycbcr_format.chroma_subsampling_y;
		invalidate_pixel_data();
	}

	void set_pitch(unsigned channel, unsigned pitch)
	{
		assert(pitch != 0);
		assert(channel >= 0 && channel < num_channels);
		this->pitch[channel] = pitch;
		invalidate_pixel_data();
	}

	// Tells the input to use the specific OpenGL texture as pixel data for the given
	// channel. The comments on FlatInput::set_texture_num() also apply here, except
	// that this input generally does not use mipmaps.
	void set_texture_num(unsigned channel, GLuint texture_num)
	{
		possibly_release_texture(channel);
		this->texture_num[channel] = texture_num;
		this->owns_texture[channel] = false;
	}

	// You can change the Y'CbCr format freely, also after finalize,
	// although with one limitation: If Cb and Cr come from the same
	// texture and their offsets offsets are the same (ie., within 1e-6)
	// when finalizing, they most continue to be so forever, as this
	// optimization is compiled into the shader.
	//
	// If you change subsampling parameters, you'll need to call
	// set_width() / set_height() again after this.
	void change_ycbcr_format(const YCbCrFormat &ycbcr_format);

	void inform_added(EffectChain *chain) override
	{
		resource_pool = chain->get_resource_pool();
	}

	bool set_int(const std::string& key, int value) override;

private:
	// Release the texture in the given channel if we have any, and it is owned by us.
	void possibly_release_texture(unsigned channel);

	ImageFormat image_format;
	YCbCrFormat ycbcr_format;
	GLuint num_channels;
	YCbCrInputSplitting ycbcr_input_splitting;
	int needs_mipmaps;  // Only allowed if ycbcr_input_splitting == YCBCR_INPUT_INTERLEAVED.
	GLenum type;
	GLuint pbos[3], texture_num[3];
	GLint uniform_tex_y, uniform_tex_cb, uniform_tex_cr;
	Eigen::Matrix3d uniform_ycbcr_matrix;
	float uniform_offset[3];
	Point2D uniform_cb_offset, uniform_cr_offset;
	bool cb_cr_offsets_equal;

	unsigned width, height, widths[3], heights[3];
	const unsigned char *pixel_data[3];
	unsigned pitch[3];
	bool owns_texture[3];
	ResourcePool *resource_pool;
};

}  // namespace movit

#endif // !defined(_MOVIT_YCBCR_INPUT_H)