使用QtMultimedia播放自定义avi数据流

sba*_*bbi 58 c++ qt ffmpeg qtmultimedia

我需要播放一个自定义AVI文件,其中包含经典视频流,音频流以及自定义数据流.

自定义流包含由某些自定义小部件可视化的数据; 这些小部件只需要在适当的时间将每个自定义帧写入缓冲区.

我们的应用程序基于Qt,并且已经使用QMediaPlayer/ QVideoWidget播放传统视频,但额外的自定义流使事情变得更复杂,因为AFAIK QMediaPlayer只播放视频/音频并忽略其他所有内容.

我想避免重新发明整个qt-multimedia,但我不知道如何充分利用可用的Qt类.


我到目前为止的想法是:

  1. 编写一个自定义媒体播放器类,使用解复用和解码视频ffmpeg,实现定时,QAudioOutput用于播放音频,生成QVideoFrame要在视频上播放的s 流,并将自定义数据写入某个缓冲区以进行可视化.

    问题:为了避免编写代码来重新缩放/转换视频帧,我想重用QVideoWidget,但它似乎只适用于"真实" QMediaPlayer.

  2. 将输入文件解复用并QMediaPlayer与AV流一起提供. 将输入解复用ffmpeg(可能将解码留给Qt后端),让一个QIODevice只检索输入文件中的视频/音频流,另一个检索数据流.播放视频/音频QMediaPlayer.

                  +-------+                          
                  | QFile |                          
                  +---^---+                          
                      |                              
                   inherits                          
                      |                              
            +--------------------+
            |    MyAviDemuxer    |
            |                    |
            |  holds a queue of  |
            |  demuxed packets   |
            +--------------------+
            |                    |
      readDataPacket      readVideoPacket
            |                    |
    +-------v--------+  +--------v-----------+            +-----------+
    | MyCustomReader |  | MyVideoAudioStream +--inherits--> QIODevice |
    +----------------+  +--------+-----------+            +-----------+
                                 |       
                              setMedia                  
                                 |                  
                         +-------v-------+           
                         | QMediaPlayer  |           
                         +---------------+           
    
    Run Code Online (Sandbox Code Playgroud)

    问题是:正确地同步数据流的时序QMediaPlayer,处理标题和元数据.


我稍微倾向于选项1,只是因为它给了我更多的控制权,但我想知道我是否错过了一个更简单的解决方案(甚至仅限Windows).

小智 1

我知道您有相当定制的类结构,但也许您可以使用编码新手的一些建议。我认为您应该将一些更基本的现有数据类型与自定义类一起使用。

解决方案:与 QMediaPlayer 同步数据流的计时:
尝试使用一些计时器线程(Threadtimer的组合)。制作一个使用 MyVideoAudioStream 的流索引(使用时间作为索引中的变量)和“Mycustomreader”(使用时间作为索引中的变量的数据包数组)作为其主体的流索引。在主体中添加一些循环通过 QMediaPlayer 中的位置(@param:time)的逻辑。由此可以同时解析两者的执行代码。随着时间的增加,QMediaPlayer 中的位置和流的索引会增加。

如果您的自定义流中没有索引或位置,我强烈建议您创建一个。