worst init ever
This commit is contained in:
37
.clang-format
Normal file
37
.clang-format
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
|
||||||
|
AlignAfterOpenBracket: DontAlign
|
||||||
|
BreakConstructorInitializers: AfterColon
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
PointerAlignment: Left
|
||||||
|
SortIncludes: true
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
UseTab: Always
|
||||||
|
MaxEmptyLinesToKeep: 5
|
||||||
|
|
||||||
|
TabWidth: 4
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
IndentWidth: 4
|
||||||
|
IndentCaseLabels: true
|
||||||
|
|
||||||
|
ColumnLimit: 135
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
bad_apple.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||||
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Xmake cache
|
||||||
|
.xmake/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# MacOS Cache
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
|
||||||
|
*.mp4
|
||||||
|
*.mkv
|
||||||
20
README.md
Normal file
20
README.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# VideoToAscii
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Have a file called bad_apple.mp4 in the root.
|
||||||
|
Then,
|
||||||
|
|
||||||
|
```sh
|
||||||
|
xmake run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Install libs
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apt install libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libavutil-dev libpostproc-dev libswresample-dev libswscale-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Future
|
||||||
|
|
||||||
|
I'm too lazy right now to continue this.
|
||||||
BIN
bad_apple.mp4
LFS
Normal file
BIN
bad_apple.mp4
LFS
Normal file
Binary file not shown.
499
src/main.cpp
Normal file
499
src/main.cpp
Normal file
@@ -0,0 +1,499 @@
|
|||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static constexpr const char vertexShader[] = R"(
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
// Input vertex attributes
|
||||||
|
in vec2 vertexPosition;
|
||||||
|
in vec2 vertexTexCoord;
|
||||||
|
|
||||||
|
// Output vertex attributes (to fragment shader)
|
||||||
|
out vec2 fragTexCoord;
|
||||||
|
|
||||||
|
// NOTE: Add your custom variables here
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Send vertex attributes to fragment shader
|
||||||
|
fragTexCoord = vertexTexCoord;
|
||||||
|
|
||||||
|
// Calculate final vertex position
|
||||||
|
gl_Position = vec4(vertexPosition, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
static constexpr const char fragmentShader[] = R"(
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
// Input from the vertex shader
|
||||||
|
in vec2 fragTexCoord;
|
||||||
|
|
||||||
|
// Output color for the screen
|
||||||
|
out vec4 finalColor;
|
||||||
|
|
||||||
|
uniform sampler2D texture0;
|
||||||
|
uniform vec2 resolution;
|
||||||
|
|
||||||
|
// Fontsize less then 9 may be not complete
|
||||||
|
uniform float fontSize;
|
||||||
|
|
||||||
|
float GreyScale(in vec3 col)
|
||||||
|
{
|
||||||
|
return dot(col, vec3(0.2126, 0.7152, 0.0722));
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetCharacter(int n, vec2 p)
|
||||||
|
{
|
||||||
|
p = floor(p*vec2(-4.0, 4.0) + 2.5);
|
||||||
|
|
||||||
|
// Check if the coordinate is inside the 5x5 grid (0 to 4)
|
||||||
|
if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
|
||||||
|
{
|
||||||
|
int a = int(round(p.x) + 5.0*round(p.y));
|
||||||
|
if (((n >> a) & 1) == 1)
|
||||||
|
{
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0; // The bit is off, or we are outside the grid
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Main shader logic
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 charPixelSize = vec2(fontSize, fontSize);
|
||||||
|
vec2 uvCellSize = charPixelSize/resolution;
|
||||||
|
|
||||||
|
// The cell size is based on the fontSize set by application
|
||||||
|
vec2 cellUV = floor(fragTexCoord/uvCellSize)*uvCellSize;
|
||||||
|
|
||||||
|
vec3 cellColor = texture(texture0, cellUV).rgb;
|
||||||
|
|
||||||
|
// Gray is used to define what character will be selected to draw
|
||||||
|
float gray = GreyScale(cellColor);
|
||||||
|
|
||||||
|
int n = 4096;
|
||||||
|
|
||||||
|
// Character set from https://www.shadertoy.com/view/lssGDj
|
||||||
|
// Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
|
||||||
|
// limited character set
|
||||||
|
// if (gray > 0.2) n = 65600; // :
|
||||||
|
// if (gray > 0.3) n = 163153; // *
|
||||||
|
// if (gray > 0.4) n = 15255086; // o
|
||||||
|
// if (gray > 0.5) n = 13121101; // &
|
||||||
|
// if (gray > 0.6) n = 15252014; // 8
|
||||||
|
// if (gray > 0.7) n = 13195790; // @
|
||||||
|
// if (gray > 0.8) n = 11512810; // #
|
||||||
|
|
||||||
|
if (gray > 0.0233) n = 4096;
|
||||||
|
if (gray > 0.0465) n = 131200;
|
||||||
|
if (gray > 0.0698) n = 4329476;
|
||||||
|
if (gray > 0.0930) n = 459200;
|
||||||
|
if (gray > 0.1163) n = 4591748;
|
||||||
|
if (gray > 0.1395) n = 12652620;
|
||||||
|
if (gray > 0.1628) n = 14749828;
|
||||||
|
if (gray > 0.1860) n = 18393220;
|
||||||
|
if (gray > 0.2093) n = 15239300;
|
||||||
|
if (gray > 0.2326) n = 17318431;
|
||||||
|
if (gray > 0.2558) n = 32641156;
|
||||||
|
if (gray > 0.2791) n = 18393412;
|
||||||
|
if (gray > 0.3023) n = 18157905;
|
||||||
|
if (gray > 0.3256) n = 17463428;
|
||||||
|
if (gray > 0.3488) n = 14954572;
|
||||||
|
if (gray > 0.3721) n = 13177118;
|
||||||
|
if (gray > 0.3953) n = 6566222;
|
||||||
|
if (gray > 0.4186) n = 16269839;
|
||||||
|
if (gray > 0.4419) n = 18444881;
|
||||||
|
if (gray > 0.4651) n = 18400814;
|
||||||
|
if (gray > 0.4884) n = 33061392;
|
||||||
|
if (gray > 0.5116) n = 15255086;
|
||||||
|
if (gray > 0.5349) n = 32045584;
|
||||||
|
if (gray > 0.5581) n = 18405034;
|
||||||
|
if (gray > 0.5814) n = 15022158;
|
||||||
|
if (gray > 0.6047) n = 15018318;
|
||||||
|
if (gray > 0.6279) n = 16272942;
|
||||||
|
if (gray > 0.6512) n = 18415153;
|
||||||
|
if (gray > 0.6744) n = 32641183;
|
||||||
|
if (gray > 0.6977) n = 32540207;
|
||||||
|
if (gray > 0.7209) n = 18732593;
|
||||||
|
if (gray > 0.7442) n = 18667121;
|
||||||
|
if (gray > 0.7674) n = 16267326;
|
||||||
|
if (gray > 0.7907) n = 32575775;
|
||||||
|
if (gray > 0.8140) n = 15022414;
|
||||||
|
if (gray > 0.8372) n = 15255537;
|
||||||
|
if (gray > 0.8605) n = 32032318;
|
||||||
|
if (gray > 0.8837) n = 32045617;
|
||||||
|
if (gray > 0.9070) n = 33081316;
|
||||||
|
if (gray > 0.9302) n = 32045630;
|
||||||
|
if (gray > 0.9535) n = 33061407;
|
||||||
|
if (gray > 0.9767) n = 11512810;
|
||||||
|
|
||||||
|
vec2 localUV = (fragTexCoord - cellUV)/uvCellSize; // Range [0.0, 1.0]
|
||||||
|
|
||||||
|
vec2 p = localUV*2.0 - 1.0; // Range [-1.0, 1.0]
|
||||||
|
|
||||||
|
vec3 color = cellColor*GetCharacter(n, p);
|
||||||
|
|
||||||
|
finalColor = vec4(color, 1.0);
|
||||||
|
|
||||||
|
// finalColor = texture(texture0, fragTexCoord);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
static unsigned int vertexShaderID, fragmentShaderID, programID;
|
||||||
|
static unsigned int location_resolution, location_fontSize;
|
||||||
|
static unsigned int location_texture0;
|
||||||
|
|
||||||
|
static constexpr float vertexData[] = {
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
-1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
-1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
-1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const EGLint configAttribs[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8,
|
||||||
|
EGL_DEPTH_SIZE, 8,
|
||||||
|
|
||||||
|
// Uncomment the following to enable MSAA
|
||||||
|
// EGL_SAMPLE_BUFFERS, 1, // <-- Must be set to 1 to enable multisampling!
|
||||||
|
// EGL_SAMPLES, 4, // <-- Number of samples
|
||||||
|
|
||||||
|
// Uncomment the following to enable stencil buffer
|
||||||
|
EGL_STENCIL_SIZE, 1,
|
||||||
|
|
||||||
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE};
|
||||||
|
|
||||||
|
static const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||||
|
|
||||||
|
static const char* eglGetErrorStr() {
|
||||||
|
switch (eglGetError()) {
|
||||||
|
case EGL_SUCCESS:
|
||||||
|
return "The last function succeeded without error.";
|
||||||
|
case EGL_NOT_INITIALIZED:
|
||||||
|
return "EGL is not initialized, or could not be initialized, for the "
|
||||||
|
"specified EGL display connection.";
|
||||||
|
case EGL_BAD_ACCESS:
|
||||||
|
return "EGL cannot access a requested resource (for example a context "
|
||||||
|
"is bound in another thread).";
|
||||||
|
case EGL_BAD_ALLOC:
|
||||||
|
return "EGL failed to allocate resources for the requested operation.";
|
||||||
|
case EGL_BAD_ATTRIBUTE:
|
||||||
|
return "An unrecognized attribute or attribute value was passed in the "
|
||||||
|
"attribute list.";
|
||||||
|
case EGL_BAD_CONTEXT:
|
||||||
|
return "An EGLContext argument does not name a valid EGL rendering "
|
||||||
|
"context.";
|
||||||
|
case EGL_BAD_CONFIG:
|
||||||
|
return "An EGLConfig argument does not name a valid EGL frame buffer "
|
||||||
|
"configuration.";
|
||||||
|
case EGL_BAD_CURRENT_SURFACE:
|
||||||
|
return "The current surface of the calling thread is a window, pixel "
|
||||||
|
"buffer or pixmap that is no longer valid.";
|
||||||
|
case EGL_BAD_DISPLAY:
|
||||||
|
return "An EGLDisplay argument does not name a valid EGL display "
|
||||||
|
"connection.";
|
||||||
|
case EGL_BAD_SURFACE:
|
||||||
|
return "An EGLSurface argument does not name a valid surface (window, "
|
||||||
|
"pixel buffer or pixmap) configured for GL rendering.";
|
||||||
|
case EGL_BAD_MATCH:
|
||||||
|
return "Arguments are inconsistent (for example, a valid context "
|
||||||
|
"requires buffers not supplied by a valid surface).";
|
||||||
|
case EGL_BAD_PARAMETER:
|
||||||
|
return "One or more argument values are invalid.";
|
||||||
|
case EGL_BAD_NATIVE_PIXMAP:
|
||||||
|
return "A NativePixmapType argument does not refer to a valid native "
|
||||||
|
"pixmap.";
|
||||||
|
case EGL_BAD_NATIVE_WINDOW:
|
||||||
|
return "A NativeWindowType argument does not refer to a valid native "
|
||||||
|
"window.";
|
||||||
|
case EGL_CONTEXT_LOST:
|
||||||
|
return "A power management event has occurred. The application must "
|
||||||
|
"destroy all contexts and reinitialise OpenGL ES state and "
|
||||||
|
"objects to continue rendering.";
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "Unknown error!";
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLint width, height;
|
||||||
|
|
||||||
|
static EGLContext context;
|
||||||
|
static EGLDisplay display;
|
||||||
|
static EGLSurface surface;
|
||||||
|
|
||||||
|
bool createContext(const int& viewport_width, const int& viewport_height) {
|
||||||
|
width = viewport_width;
|
||||||
|
height = viewport_height;
|
||||||
|
|
||||||
|
int major, minor;
|
||||||
|
|
||||||
|
if ((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) {
|
||||||
|
fprintf(stderr, "Failed to get EGL display! Error: %s\n", eglGetErrorStr());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eglInitialize(display, &major, &minor) == EGL_FALSE) {
|
||||||
|
fprintf(stderr, "Failed to get EGL version! Error: %s\n", eglGetErrorStr());
|
||||||
|
eglTerminate(display);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Initialized EGL version: %d.%d\n", major, minor);
|
||||||
|
|
||||||
|
EGLint numConfigs;
|
||||||
|
EGLConfig config;
|
||||||
|
if (!eglChooseConfig(display, configAttribs, &config, 1, &numConfigs)) {
|
||||||
|
fprintf(stderr, "Failed to get EGL config! Error: %s\n", eglGetErrorStr());
|
||||||
|
eglTerminate(display);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//----------------------------------------------
|
||||||
|
EGLint pbufferAttribs[] = {
|
||||||
|
EGL_WIDTH,
|
||||||
|
width,
|
||||||
|
EGL_HEIGHT,
|
||||||
|
height,
|
||||||
|
EGL_NONE,
|
||||||
|
};
|
||||||
|
surface = eglCreatePbufferSurface(display, config, pbufferAttribs);
|
||||||
|
if (surface == EGL_NO_SURFACE) {
|
||||||
|
fprintf(stderr, "Failed to create EGL surface! Error: %s\n", eglGetErrorStr());
|
||||||
|
eglTerminate(display);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
eglBindAPI(EGL_OPENGL_API);
|
||||||
|
|
||||||
|
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
|
||||||
|
if (context == EGL_NO_CONTEXT) {
|
||||||
|
fprintf(stderr, "Failed to create EGL context! Error: %s\n", eglGetErrorStr());
|
||||||
|
eglDestroySurface(display, surface);
|
||||||
|
eglTerminate(display);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
eglMakeCurrent(display, surface, surface, context);
|
||||||
|
|
||||||
|
// Set GL Viewport size, always needed!
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
|
||||||
|
// Get GL Viewport size and test if it is correct.
|
||||||
|
// NOTE! DO NOT UPDATE EGL LIBRARY ON RASPBERRY PI AS IT WILL INSTALL FAKE
|
||||||
|
// EGL! If you have fake/faulty EGL library, the glViewport and
|
||||||
|
// glGetIntegerv won't work! The following piece of code checks if the gl
|
||||||
|
// functions are working as intended!
|
||||||
|
GLint viewport[4];
|
||||||
|
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||||
|
|
||||||
|
// viewport[2] and viewport[3] are viewport width and height respectively
|
||||||
|
printf("GL Viewport size: %dx%d\n", viewport[2], viewport[3]);
|
||||||
|
|
||||||
|
// Test if the desired width and height match the one returned by
|
||||||
|
// glGetIntegerv
|
||||||
|
if (width != viewport[2] || height != viewport[3]) {
|
||||||
|
fprintf(stderr, "Error! The glViewport/glGetIntegerv are not working! "
|
||||||
|
"EGL might be faulty!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* getRawPixels() {
|
||||||
|
// Create buffer to hold entire front buffer pixels
|
||||||
|
// We multiply width and height by 4 to because we use RGBA!
|
||||||
|
const int comp = 3;
|
||||||
|
const int dataSize = width * height * comp;
|
||||||
|
unsigned char* buffer = new unsigned char[dataSize];
|
||||||
|
|
||||||
|
glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, buffer);
|
||||||
|
|
||||||
|
/*if (flipped){
|
||||||
|
unsigned char flipPixels[dataSize];
|
||||||
|
for (int i = 0; i < width; ++i){
|
||||||
|
for (int j = 0; j < height; ++j){
|
||||||
|
for (int k = 0; k < comp; ++k){
|
||||||
|
flipPixels[(i + j * width) * comp + k] = buffer[(i
|
||||||
|
+ (height - 1 - j) * width) * comp + k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::copy(flipPixels, flipPixels + dataSize, buffer);
|
||||||
|
}*/
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroyContext() {
|
||||||
|
// Cleanup
|
||||||
|
eglDestroyContext(display, context);
|
||||||
|
eglDestroySurface(display, surface);
|
||||||
|
eglTerminate(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int initShader(GLenum type, const char* shader, int size) {
|
||||||
|
unsigned int shaderID = glCreateShader(type);
|
||||||
|
|
||||||
|
glShaderSource(shaderID, 1, &shader, &size); // @suppress("Function cannot be resolved")
|
||||||
|
glCompileShader(shaderID);
|
||||||
|
GLint compilesuccessful;
|
||||||
|
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compilesuccessful);
|
||||||
|
if (compilesuccessful == (int)GL_FALSE) {
|
||||||
|
std::cout << "Could not compile shader !" << std::endl;
|
||||||
|
GLsizei size;
|
||||||
|
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &size);
|
||||||
|
char error[size];
|
||||||
|
glGetShaderInfoLog(shaderID, size, &size, error);
|
||||||
|
std::cout << error;
|
||||||
|
}
|
||||||
|
return shaderID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initShaders(int width, int height) {
|
||||||
|
programID = glCreateProgram();
|
||||||
|
vertexShaderID = initShader(GL_VERTEX_SHADER, vertexShader, sizeof(vertexShader));
|
||||||
|
fragmentShaderID = initShader(GL_FRAGMENT_SHADER, fragmentShader, sizeof(fragmentShader));
|
||||||
|
glAttachShader(programID, vertexShaderID);
|
||||||
|
glAttachShader(programID, fragmentShaderID);
|
||||||
|
glBindAttribLocation(vertexShaderID, 0, "vertexPosition");
|
||||||
|
glBindAttribLocation(vertexShaderID, 1, "vertexTexCoord");
|
||||||
|
glLinkProgram(programID);
|
||||||
|
glValidateProgram(programID);
|
||||||
|
location_texture0 = glGetUniformLocation(programID, "texture0");
|
||||||
|
location_resolution = glGetUniformLocation(programID, "resolution");
|
||||||
|
location_fontSize = glGetUniformLocation(programID, "fontSize");
|
||||||
|
glUseProgram(programID);
|
||||||
|
glUniform2f(location_resolution, width, height);
|
||||||
|
glUniform1f(location_fontSize, 6.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int vboID;
|
||||||
|
|
||||||
|
void initGL(int width, int height) {
|
||||||
|
if (!glewInit()) {
|
||||||
|
std::cout << "Failed to initialize glew!\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
initShaders(width, height);
|
||||||
|
glCreateBuffers(1, &vboID);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vboID);
|
||||||
|
glVertexAttribPointer(0, 2, GL_FLOAT, false, 4 * sizeof(float), (void*)0);
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, false, 4 * sizeof(float), (void*)8);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadTextureImage(int textureID, int width, int height, const cv::Mat& image) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
// This prevents having weird edges
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, image.ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void draw() {
|
||||||
|
|
||||||
|
glClearColor(0, 0, 0, 1);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vboID);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(1);
|
||||||
|
glDisableVertexAttribArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
cv::VideoCapture video("bad_apple.mp4");
|
||||||
|
int width = video.get(cv::VideoCaptureProperties::CAP_PROP_FRAME_WIDTH);
|
||||||
|
int height = video.get(cv::VideoCaptureProperties::CAP_PROP_FRAME_HEIGHT);
|
||||||
|
int frameCount = video.get(cv::VideoCaptureProperties::CAP_PROP_FRAME_COUNT);
|
||||||
|
int fps = video.get(cv::VideoCaptureProperties::CAP_PROP_FPS);
|
||||||
|
|
||||||
|
cv::VideoWriter output("outcpp.mkv", cv::VideoWriter::fourcc('H', '2', '6', '4'), fps, cv::Size(width, height));
|
||||||
|
createContext(width, height);
|
||||||
|
|
||||||
|
initGL(width, height);
|
||||||
|
|
||||||
|
int currentFrame = 0;
|
||||||
|
|
||||||
|
unsigned int texture0;
|
||||||
|
glGenTextures(1, &texture0);
|
||||||
|
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
glUseProgram(programID);
|
||||||
|
|
||||||
|
int writtenFrame = 0;
|
||||||
|
|
||||||
|
std::cout << "Converting...\n";
|
||||||
|
|
||||||
|
auto start = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
for (int i = 0; i < frameCount; i++) {
|
||||||
|
std::cout << "\rFrame " << i << " / " << frameCount;
|
||||||
|
cv::Mat image;
|
||||||
|
video >> image;
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
loadTextureImage(texture0, width, height, image);
|
||||||
|
|
||||||
|
writtenFrame++;
|
||||||
|
|
||||||
|
draw();
|
||||||
|
unsigned char* pixels = getRawPixels();
|
||||||
|
cv::Mat pixelArray(cv::Size(width, height), CV_8UC3, cv::Scalar(0, 0, 0));
|
||||||
|
pixelArray.data = pixels;
|
||||||
|
output << pixelArray;
|
||||||
|
pixelArray.release();
|
||||||
|
delete pixels;
|
||||||
|
writtenFrame++;
|
||||||
|
|
||||||
|
image.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
auto end = std::chrono::system_clock::now();
|
||||||
|
std::cout << "Done in " << std::chrono::duration_cast<std::chrono::seconds>(end - start).count() << "s!\n";
|
||||||
|
|
||||||
|
destroyContext();
|
||||||
|
}
|
||||||
83
xmake.lua
Normal file
83
xmake.lua
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
add_rules("mode.debug", "mode.release")
|
||||||
|
|
||||||
|
add_requires("ffmpeg", {system = true})
|
||||||
|
add_requires("opencv", "glew")
|
||||||
|
|
||||||
|
add_requires("raylib")
|
||||||
|
|
||||||
|
target("VideoToAscii")
|
||||||
|
set_kind("binary")
|
||||||
|
add_packages("opencv", "glew")
|
||||||
|
add_links("EGL")
|
||||||
|
add_files("src/main.cpp")
|
||||||
|
set_rundir(".")
|
||||||
|
|
||||||
|
--
|
||||||
|
-- If you want to known more usage about xmake, please see https://xmake.io
|
||||||
|
--
|
||||||
|
-- ## FAQ
|
||||||
|
--
|
||||||
|
-- You can enter the project directory firstly before building project.
|
||||||
|
--
|
||||||
|
-- $ cd projectdir
|
||||||
|
--
|
||||||
|
-- 1. How to build project?
|
||||||
|
--
|
||||||
|
-- $ xmake
|
||||||
|
--
|
||||||
|
-- 2. How to configure project?
|
||||||
|
--
|
||||||
|
-- $ xmake f -p [macosx|linux|iphoneos ..] -a [x86_64|i386|arm64 ..] -m [debug|release]
|
||||||
|
--
|
||||||
|
-- 3. Where is the build output directory?
|
||||||
|
--
|
||||||
|
-- The default output directory is `./build` and you can configure the output directory.
|
||||||
|
--
|
||||||
|
-- $ xmake f -o outputdir
|
||||||
|
-- $ xmake
|
||||||
|
--
|
||||||
|
-- 4. How to run and debug target after building project?
|
||||||
|
--
|
||||||
|
-- $ xmake run [targetname]
|
||||||
|
-- $ xmake run -d [targetname]
|
||||||
|
--
|
||||||
|
-- 5. How to install target to the system directory or other output directory?
|
||||||
|
--
|
||||||
|
-- $ xmake install
|
||||||
|
-- $ xmake install -o installdir
|
||||||
|
--
|
||||||
|
-- 6. Add some frequently-used compilation flags in xmake.lua
|
||||||
|
--
|
||||||
|
-- @code
|
||||||
|
-- -- add debug and release modes
|
||||||
|
-- add_rules("mode.debug", "mode.release")
|
||||||
|
--
|
||||||
|
-- -- add macro definition
|
||||||
|
-- add_defines("NDEBUG", "_GNU_SOURCE=1")
|
||||||
|
--
|
||||||
|
-- -- set warning all as error
|
||||||
|
-- set_warnings("all", "error")
|
||||||
|
--
|
||||||
|
-- -- set language: c99, c++11
|
||||||
|
-- set_languages("c99", "c++11")
|
||||||
|
--
|
||||||
|
-- -- set optimization: none, faster, fastest, smallest
|
||||||
|
-- set_optimize("fastest")
|
||||||
|
--
|
||||||
|
-- -- add include search directories
|
||||||
|
-- add_includedirs("/usr/include", "/usr/local/include")
|
||||||
|
--
|
||||||
|
-- -- add link libraries and search directories
|
||||||
|
-- add_links("tbox")
|
||||||
|
-- add_linkdirs("/usr/local/lib", "/usr/lib")
|
||||||
|
--
|
||||||
|
-- -- add system link libraries
|
||||||
|
-- add_syslinks("z", "pthread")
|
||||||
|
--
|
||||||
|
-- -- add compilation and link flags
|
||||||
|
-- add_cxflags("-stdnolib", "-fno-strict-aliasing")
|
||||||
|
-- add_ldflags("-L/usr/local/lib", "-lpthread", {force = true})
|
||||||
|
--
|
||||||
|
-- @endcode
|
||||||
|
--
|
||||||
|
|
||||||
Reference in New Issue
Block a user