Desarrollo de audio y video Qt Sincronización de audio y video de 24 ffmpeg

I. Introducción

Utilizo ffmpeg para la sincronización de audio y video. Personalmente, creo que este es el más difícil en el procesamiento básico de ffmpeg. Innumerables personas están atrapadas aquí. De ninguna manera. He probado varias demostraciones en Internet, y son básicamente escoria, o Solo admite una cantidad muy pequeña de archivos de video. Por ejemplo, los paquetes de datos recibidos son un cuadro de video y un cuadro de audio. O es imposible sincronizar en absoluto o el progreso salta y se bloquea directamente. De hecho, el audio y video más perfectos La demostración de sincronización es ffplay. Personalmente he probado docenas de varios archivos locales de audio y video, docenas de archivos de transmisión de video, y todos son perfectos. Por supuesto, este es el mío, y no soy perfecto.

Si solo reproduce la transmisión de video (sin transmisión de audio), es posible que no necesite sincronizar el audio y el video, por lo que cuando solo reproduce la transmisión de video rtsp al principio, no consideró el problema de sincronización en absoluto, porque no lo encontró y no lo necesita. Cuando planté transmisiones de video como rtmp, http, m3u8, el problema se agravó. Provenía de los archivos de transmisión de video en formato hls a la vez, y aparecieron pequeños archivos de video. Si no están sincronizados, significa que de repente Hay muchas imágenes que se han deslizado en el pasado, y la próxima vez que vengan, se volverán a deslizar. Esto requiere que usted mismo calcule la sincronización. Los paquetes de datos recibidos la última vez se colocan en la cola y se muestran cuando deben mostrarse.

Métodos comunes de sincronización de audio y video:

  1. Controlado por fps, fps indica cuántos fotogramas se reproducen en un segundo, por ejemplo, 25 fotogramas. Puede calcular el tiempo utilizado para decodificar un fotograma usted mismo. Un fotograma ocupa (1000/25 = 40 milisegundos). Se procesa por retraso. Esto es en realidad La forma más basura.
  2. Recuerde el tiempo startTime para comenzar a decodificar y calcule el tiempo de pts a través de av_rescale_q. La diferencia entre los dos es el tiempo que debe retrasarse. Llame a av_usleep para retrasar. Solo una parte del archivo es normal, pero no es normal en muchos casos.
  3. El audio está sincronizado con el video y el reloj de video se usa como reloj maestro. No lo he probado. Mucha gente en Internet dice que este método no es bueno.
  4. El video está sincronizado con el audio y el reloj de audio se usa como reloj maestro. No lo he probado. Se dice que la mayoría de la gente usa este método.
  5. El audio y el video se sincronizan con un reloj externo, y el reloj externo se utiliza como reloj maestro. El método final es fácil de entender y no interfiere entre sí, y cada uno se sincroniza de acuerdo con el reloj externo.
  6. ffplay tiene tres estrategias de sincronización integradas, que se pueden controlar mediante parámetros. La opción predeterminada es sincronizar video con audio.

2. Características

  1. Reproducción multiproceso en tiempo real de flujo de video + video local + cámara USB, etc.
  2. Admite windows + linux + mac, admite ffmpeg3 y ffmpeg4, admite 32 bits y 64 bits.
  3. Imágenes de pantalla multiproceso, no atascadas en la interfaz principal.
  4. Vuelva a conectar la cámara web automáticamente.
  5. Puede establecer el tamaño del borde, el desplazamiento y el color del borde.
  6. Puede establecer si desea dibujar etiquetas OSD, es decir, etiquetar texto o imágenes y posiciones de etiquetas.
  7. Se pueden configurar dos posiciones y estilos de OSD.
  8. Puede establecer si guardar en archivo y nombre de archivo.
  9. Puede arrastrar el archivo directamente al control ffmpegwidget para reproducirlo.
  10. Admite transmisiones de video comunes como h265 video stream + rtmp.
  11. Puede pausar y reanudar la reproducción.
  12. Admite el almacenamiento de archivos de video individuales y el almacenamiento de tiempo de archivos de video.
  13. Personalice la barra flotante superior, envíe una notificación de señal de clic y establezca si desea habilitarla.
  14. Puede establecer el relleno de estiramiento de la pantalla o el relleno de igual proporción.
  15. Puede configurar la decodificación para que tenga prioridad de velocidad, prioridad de calidad y procesamiento de ecualización.
  16. Puede tomar capturas de pantalla (imágenes originales) y capturas de pantalla de videos.
  17. El almacenamiento de archivos de video admite archivos MP4 y de flujo desnudo.
  18. El audio y el video están perfectamente sincronizados, utilizando una estrategia de sincronización de reloj externo.
  19. Soporte buscar para localizar la posición de reproducción.
  20. Admite decodificación rígida como qsv, dxva2, d3d11va, etc.
  21. Admite OpenGL para extraer datos de video, uso de CPU muy bajo.
  22. Admite Android y Linux integrado, solo compila de forma cruzada.

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 FFmpegSync::run()
{
    reset();
    while (!stopped) {
        //暂停状态或者队列中没有帧则不处理
        if (!thread->isPause && packets.count() > 0) {
            mutex.lock();
            AVPacket *packet = packets.first();
            mutex.unlock();

            //h264的裸流文件同步有问题,获取不到pts和dts,暂时用最蠢的办法延时解决
            if (thread->formatName == "h264") {
                int sleepTime = (1000 / thread->videoFps) - 5;
                msleep(sleepTime);
            }

            //计算当前帧显示时间 外部时钟同步
            ptsTime = getPtsTime(thread->formatCtx, packet);
            if (!this->checkPtsTime()) {
                msleep(1);
                continue;
            }

            //显示当前的播放进度
            checkShowTime();

            //0-表示音频 1-表示视频
            if (type == 0) {
                thread->decodeAudio(packet);
            } else if (type == 1) {
                thread->decodeVideo(packet);
            }

            //释放资源并移除
            thread->free(packet);
            mutex.lock();
            packets.removeFirst();
            mutex.unlock();
        }

        msleep(1);
    }

    clear();
    stopped = false;
}

bool FFmpegSync::checkPtsTime()
{
    bool ok = false;
    if (ptsTime > 0) {
        if (ptsTime > offsetTime + 100000) {
            bufferTime = ptsTime - offsetTime + 100000;
        }

        int offset = (type == 0 ? 1000 : 5000);
        offsetTime = av_gettime() - startTime + bufferTime;
        if ((offsetTime <= ptsTime && ptsTime - offsetTime <= offset) || (offsetTime > ptsTime)) {
            ok = true;
        }
    } else {
        ok = true;
    }

    return ok;
}

Supongo que te gusta

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