Qt Audio and Video Development 22-General GPU Display

I. Introducción

Usar GPU para dibujar videos en tiempo real siempre ha sido un punto difícil. Si se trata de una persona en la industria de la seguridad que se dedica al desarrollo de la videovigilancia, este obstáculo debe superarse. Yo he estado involucrado en la cerca electrónica de la industria de la seguridad, que es un segmento de mercado bastante especializado. El desarrollo de la videovigilancia es solo un juego y una discusión con las tecnologías periféricas Ha habido muchos desvíos con respecto al dibujo de la GPU.

Al decodificar con ffmpeg antes, se realizó una decodificación rígida, como el soporte de qsv, dxva2, d3d11va, etc. para la decodificación rígida, pero después de la decodificación en ese momento, se convirtió a QImage para dibujar, lo que se redujo considerablemente. Aunque puede ver la tasa de uso de la GPU, la operación que consume mucho tiempo todavía se dibuja y se muestra en la CPU, lo cual es muy vergonzoso. Qt encapsula la mayoría de las operaciones de opengl y crea directamente QOPenGLWidget, que admite la decodificación ffmpeg. La visualización de datos en formato yuyv también es compatible con la visualización de datos en formato nv12 con decodificación rígida, que es muy buena y potente. De esta manera, la presión sobre la CPU se reduce en gran medida y se entrega especialmente a la GPU para dibujar. Después de una transformación tan completa, se mejora la eficiencia. Al menos 5 veces, ¡no seas demasiado genial! Si el dibujo opengl está habilitado, la memoria correspondiente aumentará mucho. Tal vez el dibujo opengl necesite abrir mucha memoria para intercambiar datos.

La pantalla de la GPU debe admitir el formato yuyv y el formato nv12 al mismo tiempo, debido a que algunas computadoras con una configuración deficiente, es probable que la decodificación dura se detenga, luego debe usar opengl para dibujar directamente los datos yuyv decodificados por ffmpeg suavemente, para que cambien automáticamente. Compatible con todas las situaciones posibles. La prueba encontró que el rendimiento de ffmpeg4 es mejor que el de ffmpeg3, y el de 64 bits es mejor que el de 32 bits. En un sistema operativo de 64 bits, el rendimiento del protocolo UDP es mejor que el de TCP, pero puede ocurrir pérdida de paquetes.

Programa UPC RAM GPU
ninguno + ninguno 12% 147 MB 0%
dxva2 + ninguno 3% 360 MB 38%
d3d11va + ninguno 2% 277 MB 62%
ninguno + pintor 30% 147 MB 0%
dxva2 + pintor 30% 360 MB 38%
d3d11va + pintor 21% 277 MB 62%
ninguno + yuyv 17% 177 MB 22%
dxva2 + yuyv 25% 400 MB 38%
d3d11va + yuyv 18% 30 MB sesenta y cinco%
qsv + nv12 22% 970 MB 40%
dxva2 + nv12 20% 380 MB 40%
d3d11va + nv12 15% 320 MB 62%

2. Características

  1. Admite cambio de pantalla múltiple, cambio de pantalla completa, etc., incluido el cambio de pantalla 1 + 4 + 6 + 8 + 9 + 13 + 16 + 25 + 36 + 64.
  2. Soporte alt + entrar en pantalla completa, esc salir de pantalla completa.
  3. Cuadro de información personalizado + cuadro de error + cuadro de consulta + cuadro de aviso en la esquina inferior derecha (incluidos varios formatos).
  4. Se pueden cambiar 17 conjuntos de estilos de piel a voluntad, todos los estilos están unificados, incluidos los menús.
  5. Mueva el mouse en el tablero del cardán para resaltar, y las ocho direcciones se identificarán con precisión.
  6. La barra de herramientas de la pantalla inferior (interruptor de división de pantalla + sonido de captura de pantalla y otras configuraciones) se mueve hacia arriba y se resalta.
  7. El logotipo + el nombre del software chino + el nombre del software en inglés se pueden cambiar en el archivo de configuración.
  8. Encapsula el mapa de Baidu, el cambio de vista, la pista de movimiento, la posición del dispositivo y el clic del mouse para obtener la latitud y la longitud, etc.
  9. Admite mapa de imágenes, el botón del dispositivo se puede arrastrar libremente en el mapa de imágenes para guardar automáticamente la información de ubicación.
  10. En el mapa de Baidu y el mapa de imágenes, haga doble clic en el video para obtener una vista previa del video de la cámara en tiempo real.
  11. Ventana de pila, cada ventana es un qwidget separado, conveniente para escribir su propio código.
  12. El menú de clic derecho del mouse superior puede controlar dinámicamente la visualización y la ocultación del tiempo CPU + panel superior izquierdo + panel inferior izquierdo + panel superior derecho + panel inferior derecho, y admite restaurar el diseño predeterminado.
  13. La barra de herramientas puede colocar varios iconos pequeños y cerrar iconos.
  14. Los lados izquierdo y derecho se pueden arrastrar y estirar, y las posiciones de ancho y alto se memorizan automáticamente y se restaurarán después de reiniciar.
  15. Haga doble clic en el nodo de la cámara para reproducir automáticamente el video, haga doble clic en el nodo para agregar automáticamente videos en secuencia y saltará automáticamente al siguiente. Haga doble clic en el nodo principal para agregar automáticamente todos los videos debajo del nodo.
  16. El nodo de la cámara se arrastra a la ventana correspondiente para reproducir el video y los archivos locales son compatibles con la reproducción directa.
  17. El cuadro de video admite arrastrar e intercambiar, y responde instantáneamente.
  18. Haga doble clic en el nodo + arrastre el nodo + arrastre el formulario para intercambiar posiciones, y url.txt se actualizará automáticamente.
  19. Admite la reproducción de video del canal de carga desde url.txt, recuerda automáticamente el video correspondiente al último canal y se abre y reproduce automáticamente después de que se inicia el software.
  20. El control de la barra de volumen en la esquina inferior derecha se oculta automáticamente cuando se pierde el enfoque, y la barra de volumen tiene un icono de silencio.
  21. Mapa en línea integrado de Baidu y mapa fuera de línea, puede agregar la ubicación correspondiente del dispositivo, generar automáticamente un mapa, admitir el zoom y agregar superposiciones, etc.
  22. Arrastre el video fuera de la ventana del canal para eliminarlo automáticamente.
  23. El botón derecho del mouse puede eliminar el actual + todos los videos, la captura de pantalla actual + todos los videos.
  24. Administración de grabadoras, administración de cámaras, puede agregar, eliminar, modificar, importar y exportar información de impresión, y aplicar inmediatamente la información del nuevo dispositivo para generar una lista de árbol sin reiniciar.
  25. Puede habilitar libremente si desea cargar el mapa en el archivo profesional.
  26. Se pueden cambiar libremente dos tipos de núcleos para la reproducción de video, vlc + ffmpeg, ambos se pueden configurar en pro.
  27. Se puede configurar el sondeo de pantalla 1 + 4 + 9 + 16, el intervalo de sondeo y el tipo de flujo de sondeo se pueden configurar, simplemente haga clic en el botón Iniciar sondeo en el lado derecho de la barra de herramientas en la parte inferior de la interfaz principal y haga clic nuevamente para detener el sondeo .
  28. De forma predeterminada, el puntero del mouse se ocultará automáticamente sin operación durante más de 10 segundos.
  29. Admite equipos de búsqueda onvif, admite cualquier cámara onvif, incluidos, entre otros, Haikang Dahuayu Shitiandi Weiye Huawei, etc.
  30. Admite el control onvif PTZ, puede mover la cámara PTZ hacia arriba, abajo, izquierda y derecha, incluido el restablecimiento y el ajuste de enfoque.
  31. Al mismo tiempo, admite bases de datos como sqlite, mysql y postsql.
  32. El video se puede guardar, el almacenamiento de tiempo o el almacenamiento de un solo archivo es opcional y el intervalo de almacenamiento es opcional.
  33. Puede configurar el método de comunicación de transmisión de video tcp + udp, y puede configurar la decodificación de video como prioridad de velocidad, prioridad de calidad, ecualización, etc.
  34. Puede configurar el tipo de decodificación rígida, admite qsv, dxva2, d3d11va, etc.
  35. De forma predeterminada, opengl se usa para dibujar video, que tiene un consumo de recursos de CPU ultra bajo y admite el dibujo en formato yuyv y nv12, lo cual es muy impresionante.
  36. Altamente personalizable, los usuarios pueden derivar fácilmente sus propias funciones sobre esta base, admitiendo sistemas Linux y Mac.

Tres, representaciones

Inserte la descripción de la imagen aquí

Cuatro sitios relacionados

  1. Sitio nacional: https://gitee.com/feiyangqingyun/QWidgetDemo
  2. Sitio internacional: https://github.com/feiyangqingyun/QWidgetDemo
  3. Página de inicio personal: https://blog.csdn.net/feiyangqingyun
  4. Página de inicio de Zhihu: https://www.zhihu.com/people/feiyangqingyun/
  5. Dirección de experiencia: https://blog.csdn.net/feiyangqingyun/article/details/97565652

Cinco, el código central

void YUVOpenGLWidget2::initializeGL()
{
    initializeOpenGLFunctions();
    glDisable(GL_DEPTH_TEST);

    //传递顶点和纹理坐标
    static const GLfloat ver[] = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f};
    static const GLfloat tex[] = {0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f};

    //设置顶点,纹理数组并启用
    glVertexAttribPointer(0, 2, GL_FLOAT, 0, 0, ver);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 2, GL_FLOAT, 0, 0, tex);
    glEnableVertexAttribArray(1);

    //初始化shader
    this->initShader();
    //初始化textures
    this->initTextures();
    //初始化颜色
    this->initColor();
}

void YUVOpenGLWidget2::paintGL()
{
    if (!dataY || !dataU || !dataV || width == 0 || height == 0) {
        this->initColor();
        return;
    }

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, textureY);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, linesizeY);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, dataY);
    glUniform1i(textureUniformY, 0);

    glActiveTexture(GL_TEXTURE0 + 1);
    glBindTexture(GL_TEXTURE_2D, textureU);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, linesizeU);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width >> 1, height >> 1, 0, GL_RED, GL_UNSIGNED_BYTE, dataU);
    glUniform1i(textureUniformU, 1);

    glActiveTexture(GL_TEXTURE0 + 2);
    glBindTexture(GL_TEXTURE_2D, textureV);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, linesizeV);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width >> 1, height >> 1, 0, GL_RED, GL_UNSIGNED_BYTE, dataV);
    glUniform1i(textureUniformV, 2);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void YUVOpenGLWidget2::initColor()
{
    //取画板背景颜色
    QColor color = palette().background().color();
    //设置背景清理色
    glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF());
    //清理颜色背景
    glClear(GL_COLOR_BUFFER_BIT);
}

void YUVOpenGLWidget2::initShader()
{
    //加载顶点和片元脚本
    program.addShaderFromSourceCode(QOpenGLShader::Vertex, vertShader);
    program.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader);

    //设置顶点位置
    program.bindAttributeLocation("vertexIn", 0);
    //设置纹理位置
    program.bindAttributeLocation("textureIn", 1);
    //编译shader
    program.link();
    program.bind();    

    //从shader获取地址
    textureUniformY = program.uniformLocation("textureY");
    textureUniformU = program.uniformLocation("textureU");
    textureUniformV = program.uniformLocation("textureV");
}

void YUVOpenGLWidget2::initTextures()
{
    //创建纹理
    glGenTextures(1, &textureY);
    glBindTexture(GL_TEXTURE_2D, textureY);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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);

    glGenTextures(1, &textureU);
    glBindTexture(GL_TEXTURE_2D, textureU);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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);

    glGenTextures(1, &textureV);
    glBindTexture(GL_TEXTURE_2D, textureV);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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);
}

Supongo que te gusta

Origin blog.csdn.net/feiyangqingyun/article/details/108336252
Recomendado
Clasificación