Commit 9ce0beba authored by 张泽仁's avatar 张泽仁

organize project

parent 520828d7
raspberrypi_spi
*.o
*.deb
AIPlayer
\ No newline at end of file
{
"files.associations": {
"egl_ctx.h": "c"
}
}
\ No newline at end of file
# 编译器
CC = gcc
# 编译选项
CFLAGS = -Wall -Wno-deprecated-declarations -I.
LDFLAGS = -L.
# 目标可执行文件
TARGET = AIPlayer
# 所有源代码文件
SOURCES = main.c aiplay.c egl_ctx.c opengles_ctx.c raspberrypi_spi/LocalDimming/interface.c
# 生成的目标文件列表
OBJECTS = $(SOURCES:.c=.o)
# 依赖的库
LIBS = -lavcodec -lavformat -lavutil -lswscale -lasound -lGLESv2 -lEGL -lX11 -lpthread -lwiringPi
# 默认目标:编译可执行文件
all: $(TARGET)
# 生成可执行文件
$(TARGET): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $(TARGET)
# 编译每个.c文件为.o文件
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# 清理生成的文件
clean:
rm -f $(OBJECTS) $(TARGET)
.PHONY: all clean
install:
sudo cp -rfv ./AIPlayer /usr/local/bin/
sudo cp -rfv ./Videos /usr/local/bin/
# raspberry_Holographic
each maintain version for full project
\ No newline at end of file
File added
File added
This diff is collapsed.
#ifndef __AIPLAY_H__
#define __AIPLAY_H__
typedef struct aiplay aiplay_t;
aiplay_t* aiplay_open(void *native_window_hanlder, int w, int h);
void aiplay_close(aiplay_t *ap);
void aiplay_play(aiplay_t *ap, const char *filename);
typedef struct aiplay_event {
int type;
int content;
}aiplay_event_t;
typedef void(*aiplay_event_cb_t)(void *user_ctx, aiplay_event_t event);
void aiplay_set_callback(aiplay_t *ap, aiplay_event_cb_t cb, void *user_ctx);
#endif
\ No newline at end of file
[Unit]
Description=AIPlayer
[Service]
Type=simple
ExecStart=/usr/local/bin/AIPlayer
Restart=always
User=developer
Environment="DISPLAY=:0"
[Install]
WantedBy=multi-user.target
#!/bin/bash
sudo ./install-dep.sh
make clean
make
sudo make install
./change-user.sh
sudo ./start-service.sh
#!/bin/bash
# 获取当前用户名
current_user=$(whoami)
# 定义要替换的字符串
old_user="User="
# 替换为当前用户名
new_user="User=$current_user"
# 检查aiplayer.service文件是否存在
service_file="./aiplayer.service"
if [ -f "$service_file" ]; then
# 使用sed命令进行替换
sed -i "s/$old_user.*/$new_user/g" "$service_file"
echo "已将 $old_user 替换为 $new_user"
else
echo "x.service 文件不存在,请检查路径是否正确。"
fi
#include "egl_ctx.h"
#include <stdio.h>
#include <stdlib.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#define log_trace printf
#define log_debug printf
#define log_info printf
#define log_warn printf
#define log_error printf
#define log_fatal printf
struct egl_ctx
{
EGLDisplay egl_display;
EGLContext egl_context;
EGLSurface egl_surface;
};
static void egl_ctx_print_config(EGLDisplay egl_display, EGLConfig egl_conf);
int egl_ctx_create(egl_ctx_t **pp_ctx, void *window_ctx)
{
egl_ctx_t *ctx = (egl_ctx_t *)malloc(sizeof(egl_ctx_t));
if (ctx == NULL)
{
log_error("Call malloc() failed.\n");
return -1;
}
EGLDisplay egl_display = eglGetDisplay(NULL);
if (egl_display == EGL_NO_DISPLAY)
{
log_fatal("Call eglGetDisplay() failed. error: %d\n", eglGetError());
goto FAILED;
}
EGLint egl_version_major, egl_version_minor;
if (!eglInitialize(egl_display, &egl_version_major, &egl_version_minor))
{
log_fatal("Call eglInitialize() failed. error: %d\n", eglGetError());
goto FAILED;
}
log_info("Initialized EGL version %d.%d\n", egl_version_major, egl_version_minor);
EGLint egl_config_constraints[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 0,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_CONFIG_CAVEAT, EGL_NONE,
EGL_NONE};
EGLint num_config;
EGLConfig egl_conf;
if (!eglChooseConfig(egl_display, egl_config_constraints, &egl_conf, 1, &num_config))
{
log_fatal("Call eglChooseConfig() failed. error: %d\n", eglGetError());
goto FAILED;
}
EGLint ctx_attr[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE};
EGLContext egl_context = eglCreateContext(egl_display, egl_conf, EGL_NO_CONTEXT, ctx_attr);
if (egl_context == EGL_NO_CONTEXT)
{
log_fatal("Call eglCreateContext() failed. error: %d\n", eglGetError());
goto FAILED;
}
EGLSurface egl_surface = eglCreateWindowSurface(egl_display, egl_conf, (EGLNativeWindowType)window_ctx, NULL);
if (egl_surface == EGL_NO_SURFACE)
{
log_fatal("Call eglCreateWindowSurface() failed. error: %d)", eglGetError());
goto FAILED;
}
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
egl_ctx_print_config(egl_display, egl_conf);
ctx->egl_display = egl_display;
ctx->egl_context = egl_context;
ctx->egl_surface = egl_surface;
*pp_ctx = ctx;
return 0;
FAILED:
if (egl_context != EGL_NO_CONTEXT)
{
eglDestroyContext(egl_display, egl_context);
}
if (egl_surface != EGL_NO_SURFACE)
{
eglDestroySurface(egl_display, egl_surface);
}
if (ctx != NULL)
{
free(ctx);
}
return -1;
}
void egl_ctx_release(egl_ctx_t **pp_ctx)
{
if (pp_ctx && *pp_ctx)
{
egl_ctx_t *ctx = *pp_ctx;
*pp_ctx = NULL;
eglDestroyContext(ctx->egl_display, ctx->egl_context);
eglDestroySurface(ctx->egl_display, ctx->egl_surface);
free(ctx);
}
}
void egl_ctx_make_current(egl_ctx_t *ctx)
{
if (ctx)
{
eglMakeCurrent(ctx->egl_display, ctx->egl_surface, ctx->egl_surface, ctx->egl_context);
}
}
void egl_ctx_swap_buffers(egl_ctx_t *ctx)
{
if (ctx)
{
eglSwapBuffers(ctx->egl_display, ctx->egl_surface);
}
}
static void egl_ctx_print_config(EGLDisplay egl_display, EGLConfig egl_conf)
{
log_info("EGL Client APIs: %s\n", eglQueryString(egl_display, EGL_CLIENT_APIS));
log_info("EGL Vendor: %s\n", eglQueryString(egl_display, EGL_VENDOR));
log_info("EGL Version: %s\n", eglQueryString(egl_display, EGL_VERSION));
// log_info("EGL Extensions: %s\n", eglQueryString(egl_display, EGL_EXTENSIONS));
int i = -1;
eglGetConfigAttrib(egl_display, egl_conf, EGL_CONFIG_ID, &i);
log_debug("EGL_CONFIG_ID = %d\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_RED_SIZE, &i);
log_debug("EGL_RED_SIZE = %d\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_GREEN_SIZE, &i);
log_debug("EGL_GREEN_SIZE = %d\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_BLUE_SIZE, &i);
log_debug("EGL_BLUE_SIZE = %d\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_ALPHA_SIZE, &i);
log_debug("EGL_ALPHA_SIZE = %d\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_DEPTH_SIZE, &i);
log_debug("EGL_DEPTH_SIZE = %d\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_LEVEL, &i);
log_debug("EGL_LEVEL = %d\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_NATIVE_RENDERABLE, &i);
log_debug("EGL_NATIVE_RENDERABLE = %s\n", i ? "EGL_TRUE" : "EGL_FALSE");
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_NATIVE_VISUAL_TYPE, &i);
log_debug("EGL_NATIVE_VISUAL_TYPE = %d\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_RENDERABLE_TYPE, &i);
log_debug("EGL_RENDERABLE_TYPE = 0x%04x\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_SURFACE_TYPE, &i);
log_debug("EGL_SURFACE_TYPE = 0x%04x\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_TRANSPARENT_TYPE, &i);
if (i == EGL_TRANSPARENT_RGB)
{
log_debug("EGL_TRANSPARENT_TYPE = EGL_TRANSPARENT_RGB\n");
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_TRANSPARENT_RED_VALUE, &i);
log_debug("EGL_TRANSPARENT_RED = 0x%02x\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_TRANSPARENT_GREEN_VALUE, &i);
log_debug("EGL_TRANSPARENT_GREEN = 0x%02x\n", i);
i = 0;
eglGetConfigAttrib(egl_display, egl_conf, EGL_TRANSPARENT_BLUE_VALUE, &i);
log_debug("EGL_TRANSPARENT_BLUE = 0x%02x\n", i);
}
else
{
log_debug("EGL_TRANSPARENT_TYPE = EGL_NONE\n");
}
}
\ No newline at end of file
#ifndef __AIPLAY_EGL_CTX_H__
#define __AIPLAY_EGL_CTX_H__
typedef struct egl_ctx egl_ctx_t;
int egl_ctx_create(egl_ctx_t **pp_ctx, void *window_ctx);
void egl_ctx_release(egl_ctx_t **pp_ctx);
void egl_ctx_make_current(egl_ctx_t *ctx);
void egl_ctx_swap_buffers(egl_ctx_t *ctx);
#endif
\ No newline at end of file
#!/bin/bash
sudo apt-get install -y libavformat-dev libavcodec-dev libavutil-dev libswscale-dev
sudo apt-get install -y libx11-dev libgles2-mesa-dev libegl1-mesa-dev
// egl_bar.c - self-contained example of a vertical bar moving across the screen.
// compile with gcc -Wall -O0 -g -o egl_bar egl_bar.c log.c -lX11 -lEGL -lGLESv2 -lm
#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <alsa/asoundlib.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include "aiplay.h"
#include "raspberrypi_spi/LocalDimming/interface.h"
#if 1
#define INPUT_VIDEO_FILE "/mnt/data/media/tu-shou-pan-yan.mp4"
#define INPUT_VIDEO_FILE_1 "/usr/local/bin/Videos/待机.mp4"
#define INPUT_VIDEO_FILE_2 "/usr/local/bin/Videos/回应.mp4"
#define INPUT_VIDEO_FILE_3 "/usr/local/bin/Videos/右转.mp4"
#define INPUT_VIDEO_FILE_4 "/usr/local/bin/Videos/左转.mp4"
#else
#define INPUT_VIDEO_FILE "/home/developer/Pictures/tu-shou-pan-yan.mp4"
#define INPUT_VIDEO_FILE_1 "/home/developer/Videos/待机.mp4"
#define INPUT_VIDEO_FILE_2 "/home/developer/Videos/回应.mp4"
#define INPUT_VIDEO_FILE_3 "/home/developer/Videos/左转.mp4"
#define INPUT_VIDEO_FILE_4 "/home/developer/Videos/右转.mp4"
#endif
#define log_trace printf
#define log_debug printf
#define log_info printf
#define log_warn printf
#define log_error printf
#define log_fatal printf
typedef struct
{
aiplay_t *ap;
} play_callback_ctx;
static const char *g_current_file_name = INPUT_VIDEO_FILE_1;
static int g_current_file_id = 0;
static void aiplay_event_cb(void *user_ctx, aiplay_event_t event)
{
// log_debug("play_callback type %d\n", event.type);
play_callback_ctx *ctx = (play_callback_ctx *)user_ctx;
if (event.type == 1)
{
g_current_file_name = INPUT_VIDEO_FILE_1;
aiplay_play(ctx->ap, INPUT_VIDEO_FILE_1);
}
else if (event.type == 2)
{
if (event.content == 0){
printf("id = %d\n", g_current_file_id);
if (strcmp(g_current_file_name, INPUT_VIDEO_FILE_1) == 0){
g_current_file_id = 1;
printf("\r\rg_id = %d\n", g_current_file_id);
}else if (strcmp(g_current_file_name, INPUT_VIDEO_FILE_2) == 0){
g_current_file_id = 2;
printf("\r\rg_id = %d\n", g_current_file_id);
}else if (strcmp(g_current_file_name, INPUT_VIDEO_FILE_3) == 0){
g_current_file_id = 3;
printf("\r\rg_id = %d\n", g_current_file_id);
}else if (strcmp(g_current_file_name, INPUT_VIDEO_FILE_4) == 0){
g_current_file_id = 4;
printf("\r\rg_id = %d\n", g_current_file_id);
}
}
eachPicWrite(g_current_file_id, event.content);
//log_debug("play_callback id %d\n", event.content);
}
// log_debug("play_callback exit\n");
}
static void audio_event_cb(void *user_ctx, int id)
{
play_callback_ctx *ctx = (play_callback_ctx *)user_ctx; printf("audio_event_g_id = %d\n", id);
if (id == 1){
g_current_file_name = INPUT_VIDEO_FILE_1;
aiplay_play(ctx->ap, INPUT_VIDEO_FILE_1);
}else if (id == 2){
g_current_file_name = INPUT_VIDEO_FILE_2;
aiplay_play(ctx->ap, INPUT_VIDEO_FILE_2);
}else if (id == 3){
g_current_file_name = INPUT_VIDEO_FILE_3;
aiplay_play(ctx->ap, INPUT_VIDEO_FILE_3);
}if (id == 4){
g_current_file_name = INPUT_VIDEO_FILE_4;
aiplay_play(ctx->ap, INPUT_VIDEO_FILE_4);
}
}
int get_audio_device_id()
{
snd_pcm_t *handle;
snd_pcm_info_t *info;
snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; // 选择播放流
int card = -1, usb_card = -1;
int err;
while (usb_card == -1) {
err = snd_card_next(&card);
if (err < 0) {
fprintf(stderr, "没有可用的声卡设备.\n");
break;
}
if (card < 0) {
fprintf(stderr, "没有找到声卡.\n");
break;
}
char cardName[32];
sprintf(cardName, "hw:%d", card);
if ((err = snd_pcm_open(&handle, cardName, stream, 0)) < 0) {
fprintf(stderr, "无法打开声卡 %s: %s\n", cardName, snd_strerror(err));
continue;
}
snd_pcm_info_malloc(&info);
snd_pcm_info(handle, info);
printf("声卡 %d: %s\n", card, snd_pcm_info_get_name(info));
if (strncmp("USB Audio", snd_pcm_info_get_name(info), strlen("USB Audio")) == 0){
usb_card = card;
}
snd_pcm_info_free(info);
snd_pcm_close(handle);
}
return usb_card;
}
int main(int argc, char **argv)
{
//system("ffplay -volume 255 -nodisp -autoexit /usr/local/bin/Videos/aaaa.mp3 &");
//system("aplay /usr/local/bin/Videos/tech.wav &");
//system("test_alsa /usr/local/bin/Videos/aaaa.mp3 &");
//system("cvlc --play-and-exit --aout alsa --alsa-audio-device hw:3,0 /usr/local/bin/Videos/aaaa.mp3 &");
printf("USB Auido device id: %d\n", get_audio_device_id());
char buf[256] = {0};
snprintf(buf, 256, "cvlc --play-and-exit --aout alsa --alsa-audio-device hw:%d,0 /usr/local/bin/Videos/aaaa.mp3 &", get_audio_device_id());
system(buf);
LocalDimming_Init();
sleep(2);
LocalDimming_Init();
Display *x_display = XOpenDisplay(NULL);
while (x_display == NULL)
{
log_fatal("cannot connect to X server");
sleep(3);
x_display = XOpenDisplay(NULL);
}
// 获取默认屏幕
int screen_num = DefaultScreen(x_display);
// 创建一个透明的光标来隐藏鼠标指针
Pixmap cursor_pixmap = XCreatePixmap(x_display, DefaultRootWindow(x_display), 1, 1, 1);
XColor dummy_color;
Cursor invisible_cursor = XCreatePixmapCursor(x_display, cursor_pixmap, cursor_pixmap, &dummy_color, &dummy_color, 0, 0);
// 隐藏鼠标指针
XDefineCursor(x_display, RootWindow(x_display, screen_num), invisible_cursor);
XFlush(x_display);
Window root = DefaultRootWindow(x_display); // get the root window (usually the whole screen)
int root_x, root_y;
unsigned int root_w, root_h, root_border_width, root_depth;
Window root_again;
XGetGeometry(x_display, root, &root_again, &root_x, &root_y, &root_w, &root_h, &root_border_width, &root_depth);
log_info("Matching X11 root window geometry: +%d,%d %dx%d border %d, %dbpp\n",
root_x, root_y, root_w, root_h, root_border_width, root_depth);
XSetWindowAttributes swa;
swa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask | FocusChangeMask;
Window win = XCreateWindow(x_display, root,
0, 0, root_w, root_h, 0,
CopyFromParent, InputOutput,
CopyFromParent, CWEventMask,
&swa);
XSetWindowAttributes xattr;
xattr.override_redirect = False;
XChangeWindowAttributes(x_display, win, CWOverrideRedirect, &xattr);
int one = 1;
XChangeProperty(
x_display, win,
XInternAtom(x_display, "_HILDON_NON_COMPOSITED_WINDOW", False),
XA_INTEGER, 32, PropModeReplace,
(unsigned char *)&one, 1);
XWMHints hints;
hints.input = True;
hints.flags = InputHint;
XSetWMHints(x_display, win, &hints);
XMapWindow(x_display, win); // makes the window visible on the screen
XStoreName(x_display, win, argv[0]);
//// get identifiers for the provided atom name strings
Atom wm_state = XInternAtom(x_display, "_NET_WM_STATE", False);
Atom fullscreen = XInternAtom(x_display, "_NET_WM_STATE_FULLSCREEN", False);
XEvent xev;
memset(&xev, 0, sizeof(xev));
xev.type = ClientMessage;
xev.xclient.window = win;
xev.xclient.message_type = wm_state;
xev.xclient.format = 32;
xev.xclient.data.l[0] = 1;
xev.xclient.data.l[1] = fullscreen;
XSendEvent( // set up event mask (which events we want to receive)
x_display,
DefaultRootWindow(x_display),
False,
SubstructureNotifyMask,
&xev);
XWindowAttributes gwa;
XGetWindowAttributes(x_display, win, &gwa);
aiplay_t *ap = aiplay_open((void *)win, gwa.width, gwa.height);
play_callback_ctx user_ctx;
user_ctx.ap = ap;
aiplay_set_callback(ap, aiplay_event_cb, (void *)&user_ctx);
aiplay_play(ap, INPUT_VIDEO_FILE_1);
audio_set_callback(audio_event_cb, (void *)&user_ctx);
xfm_Init();
circleReading();
#if 0
while (1)
{
XEvent event;
XNextEvent(x_display, &event);
if (event.type == KeyPress)
{
KeySym keySym;
char keyChar;
// 将键值转换为字符
if (XLookupString(&event.xkey, &keyChar, 1, &keySym, NULL) == 1)
{
printf("按下数字键: %c\n", keyChar);
if (keyChar == '1')
{
g_current_file_name = INPUT_VIDEO_FILE_1;
aiplay_play(ap, g_current_file_name);
}
else if (keyChar == '2')
{
g_current_file_name = INPUT_VIDEO_FILE_2;
aiplay_play(ap, g_current_file_name);
}
else if (keyChar == '3')
{
g_current_file_name = INPUT_VIDEO_FILE_3;
aiplay_play(ap, g_current_file_name);
}
else if (keyChar == '4')
{
g_current_file_name = INPUT_VIDEO_FILE_4;
aiplay_play(ap, g_current_file_name);
}
else if (keyChar == 'q')
{
break;
}
}
}
else if (event.type == FocusIn)
{
printf("窗口获得焦点\n");
// 在这里处理窗口获得焦点事件
}
else if (event.type == FocusOut)
{
printf("窗口失去焦点\n");
// 在这里处理窗口失去焦点事件
// break;
}
}
#endif
aiplay_close(ap);
// 恢复默认光标并清理资源
XUndefineCursor(x_display, RootWindow(x_display, screen_num));
XFreeCursor(x_display, invisible_cursor);
XFreePixmap(x_display, cursor_pixmap);
XCloseDisplay(x_display);
return 0;
}
#include "opengles_ctx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GLES2/gl2.h>
#include <GLES3/gl3.h>
#define log_trace printf
#define log_debug printf
#define log_info printf
#define log_warn printf
#define log_error printf
#define log_fatal printf
const char g_indices[] =
{0, 3, 2, 0, 2, 1};
const char g_vertextShader[] =
{"attribute vec4 aPosition;\n"
"attribute vec2 aTextureCoord;\n"
"varying vec2 vTextureCoord;\n"
"void main() {\n"
" gl_Position = aPosition;\n"
" vTextureCoord = aTextureCoord;\n"
"}\n"};
const char g_fragmentShader[] =
{"precision mediump float;\n"
"uniform sampler2D Ytex;\n"
"uniform sampler2D Utex,Vtex;\n"
"varying vec2 vTextureCoord;\n"
"void main(void) {\n"
" float nx,ny,r,g,b,y,u,v;\n"
" mediump vec4 txl,ux,vx;"
" nx=vTextureCoord[0];\n"
" ny=vTextureCoord[1];\n"
" y=texture2D(Ytex,vec2(nx,ny)).r;\n"
" u=texture2D(Utex,vec2(nx,ny)).r;\n"
" v=texture2D(Vtex,vec2(nx,ny)).r;\n"
" y=1.1643*(y-0.0625);\n"
" u=u-0.5;\n"
" v=v-0.5;\n"
" r=y+1.5958*v;\n"
" g=y-0.39173*u-0.81290*v;\n"
" b=y+2.017*u;\n"
" gl_FragColor=vec4(r,g,b,1.0);\n"
"}\n"};
struct opengles_ctx
{
int32_t id;
GLuint textureIds[3]; // Texture id of Y,U and V texture.
GLuint program;
GLsizei width;
GLsizei height;
GLfloat vertices[20];
};
static void glesPrintInfo(const char *name, GLenum s)
{
const char *v = (const char *)glGetString(s);
log_debug("GL %s = %s\n", name, v);
}
static void glesCheckStatus(const char *op)
{
for (GLint error = glGetError(); error; error = glGetError())
{
log_debug("Call %s() glError (0x%x)\n", op, error);
}
}
static void glesConfigTexture(int name, int id, int width, int height)
{
glActiveTexture(name);
glBindTexture(GL_TEXTURE_2D, id);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
}
static void glesCreateTextures(opengles_ctx_t *gles, GLsizei width, GLsizei height)
{
glGenTextures(3, gles->textureIds); // Generate the Y, U and V texture
glesConfigTexture(GL_TEXTURE0, gles->textureIds[0], width, height);
glesConfigTexture(GL_TEXTURE1, gles->textureIds[1], width / 2, height / 2);
glesConfigTexture(GL_TEXTURE2, gles->textureIds[2], width / 2, height / 2);
}
// Uploads a plane of pixel data, accounting for stride != width*bpp.
static void glesUpdateImage(GLsizei width, GLsizei height, int stride, const char *plane)
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
// Yay! We can upload the entire plane in a single GL call.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE,
GL_UNSIGNED_BYTE, (const GLvoid *)(plane));
}
static void glesUpdateTextures(opengles_ctx_t *gles, GLsizei width, GLsizei height,
const char *y, const char *u, const char *v,
int y_stride, int u_stride, int v_stride)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gles->textureIds[0]);
glesUpdateImage(width, height, y_stride, y);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gles->textureIds[1]);
glesUpdateImage(width / 2, height / 2, u_stride, u);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gles->textureIds[2]);
glesUpdateImage(width / 2, height / 2, v_stride, v);
}
static GLuint glesLoadShader(GLenum shaderType, const char *pSource)
{
GLuint shader = glCreateShader(shaderType);
if (shader)
{
glShaderSource(shader, 1, &pSource, NULL);
glCompileShader(shader);
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled)
{
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen)
{
char *buf = (char *)malloc(infoLen);
if (buf)
{
glGetShaderInfoLog(shader, infoLen, NULL, buf);
log_debug("Could not compile shader %d: %s", shaderType, buf);
free(buf);
}
glDeleteShader(shader);
shader = 0;
}
}
}
return shader;
}
static GLuint glesCreateProgram(const char *pVertexSource,
const char *pFragmentSource)
{
GLuint vertexShader = glesLoadShader(GL_VERTEX_SHADER, pVertexSource);
if (!vertexShader)
{
return 0;
}
GLuint pixelShader = glesLoadShader(GL_FRAGMENT_SHADER, pFragmentSource);
if (!pixelShader)
{
return 0;
}
GLuint program = glCreateProgram();
if (program)
{
glAttachShader(program, vertexShader);
glesCheckStatus("glAttachShader");
glAttachShader(program, pixelShader);
glesCheckStatus("glAttachShader");
glLinkProgram(program);
GLint linkStatus = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
if (linkStatus != GL_TRUE)
{
GLint bufLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
if (bufLength)
{
char *buf = (char *)malloc(bufLength);
if (buf)
{
glGetProgramInfoLog(program, bufLength, NULL, buf);
log_debug("Could not link program: %s", buf);
free(buf);
}
}
glDeleteProgram(program);
program = 0;
}
}
return program;
}
static int32_t glesInitialize(opengles_ctx_t *gles)
{
glesPrintInfo("Version", GL_VERSION);
glesPrintInfo("Vendor", GL_VENDOR);
glesPrintInfo("Renderer", GL_RENDERER);
// glesPrintInfo("Extensions", GL_EXTENSIONS);
int maxTextureImageUnits[2];
int maxTextureSize[2];
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, maxTextureImageUnits);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize);
gles->program = glesCreateProgram(g_vertextShader, g_fragmentShader);
if (!gles->program)
{
log_debug("Could not create program");
return -1;
}
int positionHandle = glGetAttribLocation(gles->program, "aPosition");
glesCheckStatus("glGetAttribLocation aPosition");
int textureHandle = glGetAttribLocation(gles->program, "aTextureCoord");
glesCheckStatus("glGetAttribLocation aTextureCoord");
// set the vertices array in the shader
// _vertices contains 4 vertices with 5 coordinates.
// 3 for (xyz) for the vertices and 2 for the texture
glVertexAttribPointer(positionHandle, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), gles->vertices);
glesCheckStatus("glVertexAttribPointer aPosition");
glEnableVertexAttribArray(positionHandle);
glesCheckStatus("glEnableVertexAttribArray positionHandle");
// set the texture coordinate array in the shader
// _vertices contains 4 vertices with 5 coordinates.
// 3 for (xyz) for the vertices and 2 for the texture
glVertexAttribPointer(textureHandle, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &gles->vertices[3]);
glesCheckStatus("glVertexAttribPointer maTextureHandle");
glEnableVertexAttribArray(textureHandle);
glesCheckStatus("glEnableVertexAttribArray textureHandle");
glUseProgram(gles->program);
int i = glGetUniformLocation(gles->program, "Ytex");
glesCheckStatus("glGetUniformLocation");
glUniform1i(i, 0); /* Bind Ytex to texture unit 0 */
glesCheckStatus("glUniform1i Ytex");
i = glGetUniformLocation(gles->program, "Utex");
glesCheckStatus("glGetUniformLocation Utex");
glUniform1i(i, 1); /* Bind Utex to texture unit 1 */
glesCheckStatus("glUniform1i Utex");
i = glGetUniformLocation(gles->program, "Vtex");
glesCheckStatus("glGetUniformLocation");
glUniform1i(i, 2); /* Bind Vtex to texture unit 2 */
glesCheckStatus("glUniform1i");
return 0;
}
int opengles_ctx_create(opengles_ctx_t **pp_ctx)
{
opengles_ctx_t *ctx = (opengles_ctx_t *)malloc(sizeof(opengles_ctx_t));
if (ctx == NULL)
{
log_error("Call malloc failed.\n");
return -1;
}
const GLfloat vertices[20] = {
// X, Y, Z, U, V
-1, -1, 0, 0, 1, // Bottom Left
1, -1, 0, 1, 1, // Bottom Right
1, 1, 0, 1, 0, // Top Right
-1, 1, 0, 0, 0 // Top Left
};
memcpy(ctx->vertices, vertices, sizeof(ctx->vertices));
if (glesInitialize(ctx) != 0)
{
log_error("Call glesInitialize(ctx) failed.\n");
free(ctx);
return -1;
}
*pp_ctx = ctx;
return 0;
}
void opengles_ctx_release(opengles_ctx_t **pp_ctx)
{
if (pp_ctx && *pp_ctx)
{
opengles_ctx_t *ctx = *pp_ctx;
*pp_ctx = NULL;
glDeleteProgram(ctx->program);
free(ctx);
}
}
int opengles_ctx_draw_yuv420p(opengles_ctx_t *ctx, int width, int height,
const char *y, const char *u, const char *v,
int y_stride, int u_stride, int v_stride)
{
glUseProgram(ctx->program);
glesCheckStatus("glUseProgram");
if (ctx->width != (GLsizei)width || ctx->height != (GLsizei)height)
{
ctx->width = width;
ctx->height = height;
glesCreateTextures(ctx, ctx->width, ctx->height);
}
glesUpdateTextures(ctx, ctx->width, ctx->height, y, u, v, y_stride, u_stride, v_stride);
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, g_indices);
glesCheckStatus("glDrawArrays");
return 0;
}
#ifndef __AIPLAY_OPENGLES_CTX_H__
#define __AIPLAY_OPENGLES_CTX_H__
typedef struct opengles_ctx opengles_ctx_t;
int opengles_ctx_create(opengles_ctx_t **pp_ctx);
void opengles_ctx_release(opengles_ctx_t **pp_ctx);
int opengles_ctx_draw_yuv420p(opengles_ctx_t *gles, int width, int height,
const char *y, const char *u, const char *v,
int y_stride, int u_stride, int v_stride);
#endif
\ No newline at end of file
#!/bin/bash
new_line="#xserver-command=X -nocursor"
file_path="/etc/lightdm/lightdm.conf"
# 检查文件中是否已存在相同的行
if ! grep -qF "$new_line" "$file_path"; then
# 如果不存在,将新行添加到文件开头
echo -e "$new_line\n$(cat $file_path)" > $file_path
fi
sudo cp aiplayer.service /etc/systemd/system/aiplayer.service
sudo systemctl enable aiplayer.service
sudo systemctl start aiplayer.service
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment