Skip to content

Commit

Permalink
[项目更名为Qt-Media并集成mpv播放器]:更名为Qt-Media,并集成了mpv播放器,增强了视频播放和转码功能。
Browse files Browse the repository at this point in the history
- 在`CMakeLists.txt`中,将项目名称从`Qt-Ffmpeg`更改为`Qt-Media`,并更新了项目描述和主页URL。
- `Qt-Ffmpeg.pro`文件已重命名为`Qt-Media.pro`,以匹配项目的新名称。
- 在`README.md`中,增加了对mpv播放器的介绍,并更新了相关截图和说明,同时对FFmpeg播放器和转码器的描述也进行了更新。
- 添加了新的`mpv_player.jpeg`图片,展示了mpv播放器的界面。
- 更新了`packaging/macos/change_lib_dependencies.rb`脚本,以支持在MacOS上正确打包mpv播放器。
- `vcpkg.json`文件中的项目名称也从`qt-ffmpeg`更改为`qt-media`。
  • Loading branch information
RealChuan committed Jun 6, 2024
1 parent 356d5ce commit 4dc543b
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 39 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ on:
push:
paths-ignore:
- 'doc/**'
- 'packaging/**'
- '.clang*'
- '.gitignore'
- 'LICENSE'
- 'README*'
pull_request:
paths-ignore:
- 'doc/**'
- 'packaging/**'
- '.clang*'
- '.gitignore'
- 'LICENSE'
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/qmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
paths-ignore:
- 'doc/**'
- 'packaging/**'
- '.clang*'
- '.gitignore'
- 'LICENSE'
Expand All @@ -12,6 +13,7 @@ on:
pull_request:
paths-ignore:
- 'doc/**'
- 'packaging/**'
- '.clang*'
- '.gitignore'
- 'LICENSE'
Expand Down
7 changes: 4 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ include(utils)
include(qt_utils)

project(
Qt-Ffmpeg
Qt-Media
VERSION 0.0.1
DESCRIPTION "This is a Qt project for Ffmpeg"
HOMEPAGE_URL "https://github.com/RealChuan/Qt-Ffmpeg"
DESCRIPTION
" A Qt-powered multimedia suite featuring FFmpeg and mpv for enhanced video playback and transcoding."
HOMEPAGE_URL "https://github.com/RealChuan/Qt-Media"
LANGUAGES CXX)

option(BUILD_MPV "build mpv" ON)
Expand Down
File renamed without changes.
118 changes: 83 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
# Qt-Ffmpeg
# Qt-Media

- [简体中文](README.md)
- [English](README.en.md)

## Player
**这是一个基于Qt、FFmpeg和mpv的音视频项目,集成了播放器和转码器。**

## Ffmpeg Player

<div align=center>
<img src="doc/player.jpeg" width="90%" height="90%">
<img src="doc/ffmpeg_player.jpeg" width="90%" height="90%">
</div>

### 需要一个强大的opengl和vulkan yuv渲染模块

1. Opengl的片段着色器目前支持的图像格式有限;
2. 在WidgetRender中,尽可能使用QImage::Format_RGB32和QImage::Format_ARGB32_Premultiplied图像格式。如下原因:
1. Avoid most rendering directly to most of these formats using QPainter. Rendering is best optimized to the Format_RGB32 and Format_ARGB32_Premultiplied formats, and secondarily for rendering to the Format_RGB16, Format_RGBX8888, Format_RGBA8888_Premultiplied, Format_RGBX64 and Format_RGBA64_Premultiplied formats.
- Opengl的片段着色器目前支持的图像格式有限;
- 在WidgetRender中,尽可能使用QImage::Format_RGB32和QImage::Format_ARGB32_Premultiplied图像格式。如下原因:
- Avoid most rendering directly to most of these formats using QPainter. Rendering is best optimized to the Format_RGB32 and Format_ARGB32_Premultiplied formats, and secondarily for rendering to the Format_RGB16, Format_RGBX8888, Format_RGBA8888_Premultiplied, Format_RGBX64 and Format_RGBA64_Premultiplied formats.

### AVFrame 图像调整

1. 根据`AVColorSpace`进行色彩空间转换;
2. 根据`AVColorTransferCharacteristic`进行gamma、PQ、HLG等调整;
3. 根据`AVColorPrimaries`进行色域转换;
4. 根据`AVColorRange`进行色彩范围调整;
- 根据`AVColorSpace`进行色彩空间转换;
- 根据`AVColorTransferCharacteristic`进行gamma、PQ、HLG等调整;
- 根据`AVColorPrimaries`进行色域转换;
- 根据`AVColorRange`进行色彩范围调整;

#### 1. opengl 渲染的情况下,该怎么样修改shader?
#### opengl 渲染的情况下,该怎么样修改shader?

1. 参考[MPV video_shaders](https://github.com/mpv-player/mpv/blob/master/video/out/gpu/video_shaders.c)
- 参考[MPV video_shaders](https://github.com/mpv-player/mpv/blob/master/video/out/gpu/video_shaders.c)

#### 2. 非opengl渲染的情况下,又该怎么样添加filter实现图像补偿?
#### 非opengl渲染的情况下,又该怎么样添加filter实现图像补偿?

```bash
zscale=p=709;
Expand Down Expand Up @@ -58,11 +60,11 @@ Dialogue: 0,0:01:06.77,0:01:08.00,en,,0000,0000,0000,,Peek-a-boo!\r\n
subtitles=filename='%1':original_size=%2x%3
```

## Transcoder
## Ffmpeg Transcoder

如何设置编码参数以获得更小的文件和更好的视频质量?
**如何设置编码参数以获得更小的文件和更好的视频质量?**

1. 参考[HandBrake encavcodec](https://github.com/HandBrake/HandBrake/blob/master/libhb/encavcodec.c#L359)
- 参考[HandBrake encavcodec](https://github.com/HandBrake/HandBrake/blob/master/libhb/encavcodec.c#L359)

### 如何从AVAudioFifo获取的帧中计算pts?

Expand All @@ -73,29 +75,75 @@ frame->pts = transcodeCtx->audioPts / av_q2d(transcodeCtx->decContextInfoPtr->ti
transcodeCtx->audioPts += frame->nb_samples;
```

### [New BING的视频转码建议](./doc/bing_transcode.md)
- [New BING的视频转码建议](./doc/bing_transcode.md)
- SwsContext很棒!与 QImage 转换为和缩放相比**

## Mpv Player

<div align=center>
<img src="doc/mpv_player.jpeg" width="90%" height="90%">
</div>

- 预览窗口在使用4K视频时,会占用大量内存,因为多开了一个mpv实例,内存double;
- MacOS好像只能使用[QOpenglWidget](https://github.com/mpv-player/mpv-examples/tree/master/libmpv/qt_opengl)渲染;

```shell
[vo/gpu] opengl cocoa backend is deprecated, use vo=libmpv instead
```

但是使用 `vo=libmpv`也无法正常显示视频;

使用opengl的版本大于3,性能更好;

```cpp
QSurfaceFormat surfaceFormat;
surfaceFormat.setVersion(3, 3);
surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(surfaceFormat);
```

## SwsContext很棒!与 QImage 转换为和缩放相比
> **Note:** When setting Qt::AA_ShareOpenGLContexts, it is strongly recommended to place the call to this function before the construction of the QGuiApplication or QApplication. Otherwise format will not be applied to the global share context and therefore issues may arise with context sharing afterwards.

- Ubuntu下也好像只能使用[QOpenglWidget](https://github.com/mpv-player/mpv-examples/tree/master/libmpv/qt_opengl)渲染

```shell
qt.dbus.integration: Could not connect "org.freedesktop.IBus" to globalEngineChanged(QString)
```

- 在Windows和Unix下,ControlWidget和TitleWidget的控制方式不同

1. Windows下使用 `mpv_set_property(d_ptr->mpv, "wid", MPV_FORMAT_INT64, &wid);`,使用layout布局,会使得视频窗口在最前面,遮挡ControlWidget和TitleWidget,所以将ControlWidget和TitleWidget悬浮在视频窗口上方,使用 `eventFilter`去处理大部分情况下ControlWidget和TitleWidget的显示,写的非常啰嗦,但是为了能够使用D3D11渲染,更棒的性能,只能这样处理,也是值得的;
2. Unix下使用QOpenGLWidget,使用layout布局更加方便;

- MacOS打包需要[install_name_tool](/mac/change_lib_dependencies.rb),依赖拷贝脚本文件来自[iina](https://github.com/iina/iina/blob/develop/other/change_lib_dependencies.rb);

**当前 `brew`安装的 `mpv`中,`libmpv.dylib`的依赖是 `@loader_path/`,所以对脚本进行了一些修改;**

```shell
./mac/change_lib_dependencies.rb "$(brew --prefix)" "$(brew --prefix mpv)/lib/libmpv.dylib"
```

依赖会拷贝到 `packet/Qt-Mpv.app/Contents/Frameworks/`

## QT-BUG

### 动态切换Video Render,从opengl切换到widget,还是有GPU 0-3D占用,而且使用量是opengl的2倍!!!QT-BUG?
- 动态切换Video Render,从opengl切换到widget,还是有GPU 0-3D占用,而且使用量是opengl的2倍!!!QT-BUG?

### QOpenGLWidget内存泄漏,移动放大和缩小窗口,代码如下
- QOpenGLWidget内存泄漏,移动放大和缩小窗口,代码如下

```C++
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setCentralWidget(new QOpenGLWidget(this));
}
```C++
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
```
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setCentralWidget(new QOpenGLWidget(this));
}
```
File renamed without changes
Binary file added doc/mpv_player.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
142 changes: 142 additions & 0 deletions packaging/macos/change_lib_dependencies.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/usr/bin/env ruby

require "fileutils"
require "open3"
require "shellwords"

include FileUtils::Verbose

def safe_system(*args)
puts args.shelljoin
system(*args) || abort("Fail to run the last command!")
end

# 定义一个类 Dep,它有两个属性 dest 和 src
class Dependent
attr_accessor :dest, :src

# 定义一个初始化方法,接受两个参数
def initialize(dest, src)
@dest = dest
@src = src
end
end

class DylibFile
OTOOL_RX = /\t(.*) \(compatibility version (?:\d+\.)*\d+, current version (?:\d+\.)*\d+\)/

attr_reader :path, :id, :deps

def initialize(path)
@path = path
parse_otool_L_output!
end

def parse_otool_L_output!
stdout, stderr, status = Open3.capture3("otool -L \"#{path}\"")
abort(stderr) unless status.success?
libs = stdout.split("\n")
libs.shift # first line is the filename
@id = libs.shift[OTOOL_RX, 1]
@deps = libs.map { |lib| lib[OTOOL_RX, 1] }.compact
end

def ensure_writeable
saved_perms = nil
unless File.writable_real?(path)
saved_perms = File.stat(path).mode
FileUtils.chmod 0644, path
end
yield
ensure
FileUtils.chmod saved_perms, path if saved_perms
end

def change_id!
ensure_writeable do
safe_system "install_name_tool", "-id", "@rpath/#{File.basename(self.id)}", path
end
end

def change_install_name!(old_name, new_name)
ensure_writeable do
safe_system "install_name_tool", "-change", old_name, new_name, path
end
end
end

if ARGV.length <= 1
abort <<~END
Usage: change_lib_dependencies.rb prefix libraries...
If you're using Homebrew, your invocation might look like this:
$ ./change_lib_dependencies.rb "$(brew --prefix)" "$(brew --prefix mpv-iina)/lib/libmpv.dylib"
If you're using MacPorts, your invocation might look like this:
$ port contents mpv | grep '\.dylib$' | xargs ./change_lib_dependencies.rb /opt/local
END
end

prefix = ARGV.shift

linked_files = ARGV

proj_path = File.expand_path(File.join(File.dirname(__FILE__), '../'))
lib_folder = File.join(proj_path, "macos/lib/")

deps = []

rm_rf lib_folder
mkdir lib_folder

linked_files.each do |file|
# Grab the actual library on disk.
file = File.realpath(file)

# Keep the output filename the same as the library's install name
dylib = DylibFile.new file
dylib.parse_otool_L_output!
dest = File.join(lib_folder, File.basename(dylib.id))

puts "cp -p #{file} #{dest}"
copy_entry file, dest, preserve: true
deps << Dependent.new(dest, file)
end

fix_count = 0

while !deps.empty?
dependent = deps.pop
file = dependent.dest
loader_path = File.dirname(dependent.src)
puts "loader_path: #{loader_path}"
puts "=== Fix dependencies for #{file} ==="
dylib = DylibFile.new file
dylib.change_id!
dylib.deps.each do |dep|
old_dep = dep
if dep.start_with?("@loader_path")
dep = dep.gsub("@loader_path", loader_path)
end
# 如果是软连接,需要获取真实路径
if File.symlink?(dep)
dep = File.realpath(dep)
end
# puts "dep: #{dep}"

if dep.start_with?(prefix)
fix_count += 1
basename = File.basename(dep)
new_name = "@rpath/#{basename}"
dylib.change_install_name!(old_dep, new_name)
dest = File.join(lib_folder, basename)
# 检查是否已经存在
unless File.exist?(dest)
copy_entry dep, dest, preserve: true
deps << Dependent.new(dest, dep)
end
end
end
end

puts "Total #{fix_count}"
2 changes: 1 addition & 1 deletion vcpkg.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
"name": "qt-ffmpeg",
"name": "qt-media",
"version": "0.0.1",
"description": "manifest",
"dependencies": [
Expand Down

0 comments on commit 4dc543b

Please sign in to comment.