Reproducción de video mejorada del motor axmol: compatibilidad con reproducción de video en Linux (Ubuntu)

introducción

UbuntuContinuando con "Mejora de la reproducción de video del motor axmol: compatibilidad con la reproducción de video de Android", este artículo describe principalmente cómo admitir la representación de video para la reproducción de texturas en la famosa distribución de Linux . A menos que se especifique lo contrario, Linuxtodas las referencias en las siguientes descripciones se refieren a Ubuntu Linuxla versión Ubuntu 22.04+.

¿Por qué desarrollar?

Después de que el autor completó con éxito la renderización de texturas de video de Android, la única plataforma compatible con el motor axmol (macos, windows, ios/tvos, android, linux) fue Linux, así que pensé, por cierto, ¿por qué no admitir Linux?

Investigación

Después de la investigación, se descubrió que entre los mejores reproductores en Linux, VLC proporciona libvlcautorización LGPL-2.1 (uso comercial gratuito en forma de biblioteca dinámica sin modificar el código fuente), por lo que la integración libvlces una mejor solución.

Como alcanzar

Sigue siendo la interfaz que implementa axmol MediaEngine, pero usamos libvlccomo backend.

  1. Instalar el paquete de desarrollo libvlc

    sudo apt install libvlc-dev libvlccore-dev vlc
    

    Entre ellos libvlc-dev, y libvlccore-devson necesarios para la compilación y la conexión, y la instalación vlces en realidad instalar el reproductor y el complemento. Entonces, el reproductor no lo necesita y el complemento es necesario para ejecutarse. De lo contrario, el video no se podrá ver. descifrado.
    CONSEJOS: Reglas ocultas para la carga de complementos:

    • De forma predeterminada, al llamar libvlc_newa la API, libvlc buscará el complemento de decodificación necesario para reproducir el video desde el directorio libvlc.sodonde libvlccore.sose encuentra la biblioteca . pluginsLa instalación vlcpondrá el complemento en la ruta correcta.
    • A través de variables de entorno: VLC_PLUGIN_PATHespecifique libvlcla ruta para cargar el complemento
      • Linux setenvse puede configurar dinámicamente a través de API:setenv("VLC_PLUGIN_PATH", "/path/to/vlc/plugins", true);
      • Windows se puede configurar a través de API _putenv_s, pero se debe prestar especial atención en función de la biblioteca de tiempo de ejecución de c libvlc.dlly libvlccore.dll. La biblioteca oficial precompilada libvlc usa libvlc msvcrt, lo que significa que en el sistema win10, las llamadas directas _putenv_sno son válidas. Las llamadas directas _putenv_sgeneralmente se configuran ucrten Cuando las variables de entorno coexisten msvcrtcon ucrtbased/ucrtbasediferentes bibliotecas de tiempo de ejecución de C, la memoria está aislada. Si desea que ambas bibliotecas de tiempo de ejecución surtan efecto, puede configurarlas de la siguiente manera:
        _putenv_s("VLC_PLUGIN_PATH", R"(D:\dev\axmol\thirdparty\vlc\win\lib\plugins)");
        
        HMODULE hmsvcrt = GetModuleHandleW(L"msvcrt.dll");
        auto msvcrt_getenv = (decltype(getenv)*)GetProcAddress(hmsvcrt, "getenv");
        
        if (msvcrt_getenv)
        {
                  
                  
            auto msvcrt_putenv_s = (decltype(_putenv_s)*)GetProcAddress(hmsvcrt, "_putenv_s");
            if (msvcrt_putenv_s)
                msvcrt_putenv_s("VLC_PLUGIN_PATH", R"(D:\dev\axmol\thirdparty\vlc\win\lib\plugins)");
        }
        
  2. Escriba código para implementar MediaEnginefunciones principales, como reproducir, pausar, etc., registrar devoluciones de llamadas (eventos multimedia, eventos de fotograma NV12 de video) y otras funciones.

  3. Con respecto a cómo obtener datos de video NV12 decodificados por VLC (principalmente RGBA en Internet), este artículo solo publica el código clave

    libvlcEn la devolución de llamada de bloqueo, bloquee la memoria de este cuadro de datos de video para escribir:

    static constexpr auto VLC_OUTPUT_FORMAT = ax::MEVideoPixelFormat::NV12;
    
    void* VlcMediaEngine::libvlc_video_lock(void* data, void** p_pixels)
    {
          
          
        VlcMediaEngine* mediaEngine = static_cast<VlcMediaEngine*>(data);
    
        auto& bufferDim    = mediaEngine->_videoDim;
        auto& outputBuffer = mediaEngine->_frameBuffer1;
        mediaEngine->_frameBuffer1Mtx.lock();
        if constexpr (VLC_OUTPUT_FORMAT == ax::MEVideoPixelFormat::NV12)
        {
          
          
            outputBuffer.resize_fit(bufferDim.x * bufferDim.y + (bufferDim.x * bufferDim.y >> 1));  // NV12
            p_pixels[0] = outputBuffer.data();
            p_pixels[1] = outputBuffer.data() + (bufferDim.x * bufferDim.y);
        }
        else if constexpr (VLC_OUTPUT_FORMAT == ax::MEVideoPixelFormat::YUY2)
        {
          
          
            outputBuffer.resize_fit(bufferDim.x * bufferDim.y + ((bufferDim.x >> 1) * bufferDim.y * 4));  // YUY2
            p_pixels[0] = outputBuffer.data();
        }
        else
        {
          
          
            outputBuffer.resize_fit(bufferDim.x * bufferDim.y * 4);  // RGBA32
            p_pixels[0] = outputBuffer.data();
        }
        return nullptr;
    }
    void VlcMediaEngine::libvlc_video_unlock(void* data, void* id, void* const* p_pixels)
    {
          
          
        VlcMediaEngine* mediaEngine = static_cast<VlcMediaEngine*>(data);
        mediaEngine->_frameBuffer1Mtx.unlock();
        ++mediaEngine->_frameIndex;
        assert(id == nullptr);
    }
    

    libvlcAl utilizar el formato del modo de devolución de llamada, vale la pena señalar que NV12 necesita especificar el segundo plane( pitchbytesPorfila) y lines(altura de representación esperada del video/2)

    unsigned int VlcMediaEngine::libvlc_video_format_setup(void** opaque,
                                                           char* chroma,  // forcc, refer to:vlc_fourcc.h
                                                           unsigned* width,
                                                           unsigned* height,
                                                           unsigned* pitches,
                                                           unsigned* lines)
    {
          
          
        // refer to: vmem.c:Open https://github.com/videolan/vlc/blob/3.0.18/modules/video_output/vmem.c#L150
        // future: 4.0: will be widths, heights:
        // https://github.com/videolan/vlc/blob/master/modules/video_output/vmem.c#L156
        VlcMediaEngine* mediaEngine = static_cast<VlcMediaEngine*>(*opaque);
    
        // vlc tell us the original codecDim(ALIGNED)
        mediaEngine->_codecDim.set(width[0], height[0]);
    
        // tell vlc we want render as video size
        width[0]  = mediaEngine->_videoDim.x;
        height[0] = mediaEngine->_videoDim.y;
    
        // plane0
        pitches[0] = width[0];   // bytesPerRow
        lines[0]   = height[0];  // rows
    
    #    if LIBVLC_VERSION_MAJOR >= 4
        mediaEngine->_videoDim.set(width[1], height[1]);
    #    endif
    
        int num_of_plane = 1;
    
        if constexpr (VLC_OUTPUT_FORMAT == ax::MEVideoPixelFormat::NV12)
        {
          
          
            memcpy(chroma, "NV12", 4);
    
            // plane1
            pitches[1] = mediaEngine->_videoDim.x;       // bytesPerRow
            lines[1]   = mediaEngine->_videoDim.y >> 1;  // rows
    
            num_of_plane = 2;
        }
        else if constexpr (VLC_OUTPUT_FORMAT == ax::MEVideoPixelFormat::YUY2)
        {
          
          
            memcpy(chroma, "YUY2", 4);
            pitches[0] = width[0] * 2;  // bytesPerRow
        }
        else
        {
          
          
            memcpy(chroma, "RGBA", 4);
            pitches[0] = width[0] * 4;  // bytesPerRow
        }
    
        // return the number of picture buffers allocated, 0 indicates failure
        return num_of_plane;
    }
    

Operación y precauciones

Descargue el código fuente más reciente del motor axmolUbuntu 22.04+ para compilarlo y ejecutarlo en el sistema. Si encuentra el problema de no poder decodificar al reproducir un video, instálelo con ubuntu扩展组件el siguiente comando:

sudo apt install ubuntu-restricted-extras

Conclusión

Desde entonces, el motor axmol ui::MediaPlayerha admitido la representación y reproducción de texturas de video en todas las plataformas, lo que también se ha beneficiado del MediaEnginemarco rediseñado, que no solo puede axmolfuncionar en el motor, sino que también se puede compilar de forma independiente, como el ejemplo escrito de reproducción de video bgfx. por el autor: bgfx -axplay .
Además: libvlces multiplataforma en sí, por lo que la implementación de este artículo VlcMediaEnginetambién puede ejecutarse en otras plataformas después de una configuración simple, comoWindows

Supongo que te gusta

Origin blog.csdn.net/xyzzf/article/details/131176345
Recomendado
Clasificación