59

我需要播放包含经典视频流、音频流和自定义数据流的自定义 AVI 文件。

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

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

我想避免对整个qt-multimedia.


到目前为止,我的想法是:

  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  |           
                         +---------------+           
    

    问题:同步数据流的时间,QMediaPlayer正确处理标头和元数据。


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

4

2 回答 2

1

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

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

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

于 2015-11-21T21:33:11.950 回答
1

看起来 Qt 实际上已经在某种程度上支持数据流的概念 - http://doc.qt.io/qt-5/qmediastreamscontrol.html#details表明它是 qmediastreamscontrol 的可选流类型之一。

包括http://doc.qt.io/qt-5/qmediaserviceproviderplugin.html在内的其他文档建议您可以创建一个 QMediaServiceProviderPlugin实现视频和音频 QMediaControl 接口(可能通过子类化现有媒体服务提供者),还可以创建自己的QMediaControl接口子类来创建一个控件来处理您的原始数据。

希望以这种方式实现将允许您使用现有的工具来拆分流、处理标头和类似的功能。

不幸的是,构建 QMediaService 的细节似乎“超出了本文档的范围,应该寻求相关邮件列表或 IRC 频道的支持”。(http://doc.qt.io/qt-5/qmediaservice.html#details)。源代码(http://code.qt.io/cgit/qt/qtmultimedia.git/tree/src/multimedia)可能有一些用处,但是,除了http://的源代码之外code.qt.io/cgit/qt/qtmultimedia.git/tree/src/plugins,其中包括directshow / gstreamer / coreaudio 插件。

在任何情况下,我都会尝试尽可能少地进行子类化和重新实现

于 2015-12-26T21:54:59.403 回答