Merge ; commit '63746a2f835f9521273ae82a594393cc8ad9baff'

Conflicts:
	.obsidian/workspace
This commit is contained in:
2022-06-10 11:21:04 +08:00
16 changed files with 554 additions and 53 deletions

View File

@@ -1 +1,5 @@
{"folder":"Daily","format":"YYYY-MM-DD(ddd)","template":"PARA/003 - Resources資源/99. templates/日記"}
{
"folder": "01. Daily",
"format": "YYYY-MM-DD(ddd)",
"template": "02. PARA/03. Resources資源/99. templates/日記"
}

121
.obsidian/workspace vendored
View File

@@ -11,7 +11,7 @@
"type": "markdown",
"state": {
"file": "00. TOP/01. TODO.md",
"mode": "source",
"mode": "preview",
"source": true
}
}
@@ -35,25 +35,31 @@
"type": "mobile-drawer",
"children": [
{
"id": "88e1cff7a30f6953",
"type": "leaf",
"state": {
"type": "file-explorer",
"state": {}
}
},
{
"id": "ceb171daf1327c40",
"type": "leaf",
"state": {
"type": "search",
"state": {
"query": "",
"matchingCase": false,
"explainSearch": false,
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical"
"id": "dbd6f1d450f54a18",
"type": "tabs",
"children": [
{
"id": "f0c230180a9faaa1",
"type": "leaf",
"state": {
"type": "file-explorer",
"state": {}
}
},
{
"id": "81a47da514b9d823",
"type": "leaf",
"state": {
"type": "search",
"state": {
"query": "shared_ptr",
"matchingCase": false,
"explainSearch": false,
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical"
}
}
}
}
},
@@ -76,19 +82,50 @@
"type": "mobile-drawer",
"children": [
{
"id": "e3c9f68a35edf017",
"type": "leaf",
"state": {
"type": "backlink",
"state": {
"file": "00. TOP/01. TODO.md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
"showSearch": false,
"searchQuery": "",
"backlinkCollapsed": false,
"unlinkedCollapsed": true
"id": "74ab9d565ea062c4",
"type": "tabs",
"children": [
{
"id": "bcf01574fb3a7a3b",
"type": "leaf",
"state": {
"type": "backlink",
"state": {
"file": "00. TOP/01. TODO.md",
"collapseAll": true,
"extraContext": true,
"sortOrder": "alphabetical",
"showSearch": false,
"searchQuery": "",
"backlinkCollapsed": false,
"unlinkedCollapsed": false
}
}
},
{
"id": "509990f938113653",
"type": "leaf",
"state": {
"type": "advanced-tables-toolbar",
"state": {}
}
}
]
},
{
"id": "2b8688e445848e2a",
"type": "tabs",
"children": [
{
"id": "11f4d517d7b320b2",
"type": "leaf",
"state": {
"type": "tag",
"state": {
"sortOrder": "frequency",
"useHierarchy": true
}
}
}
}
}
@@ -98,14 +135,14 @@
"active": "94f0e8a81af6c9e2",
"lastOpenFiles": [
"00. TOP/01. TODO.md",
"00. TOP/00. Inbox.md",
"02. PARA/03. Resources資源/C++17/Class template.md",
"02. PARA/03. Resources資源/C++17/C++17.md",
"02. PARA/03. Resources資源/01. 架站/04. Gitea.md",
"02. PARA/03. Resources資源/Tool Setup/Obisidian.md",
"README.md",
"test.md",
"02. PARA/03. Resources資源/Proxmox VE.md",
"02. PARA/03. Resources資源/01. 架站/01. Nginx Layer4 Reverse Proxy.md"
"02. PARA/03. Resources資源/C++17/rvalue.md",
"02. PARA/03. Resources資源/C++17/move operator.md",
"02. PARA/03. Resources資源/C++17/智慧指標.md",
"02. PARA/03. Resources資源/git/submodule.md",
"02. PARA/03. Resources資源/git.md",
"02. PARA/01. Project專案/008. Sentinel.md",
"02. PARA/03. Resources資源/C++17/lvalue.md",
"02. PARA/03. Resources資源/FFMPEG/01. Setup.md",
"02. PARA/03. Resources資源/FFMPEG/00. Introduction.md"
]
}

View File

@@ -1,5 +1,5 @@
# ME
- [ ] 作筆記C++17 - share_ptr
- [x] 作筆記C++17 - share_ptr ✅ 2022-06-06
- [ ] 作筆記C++17 - R value reference與std::move
- [ ] 作筆記C++17 - Lambda
- [ ] 補充英格蘭與蘇格蘭的歷史
@@ -8,4 +8,30 @@
# WORK
## Logitech
### RobotRunQA
- [ ] 檢查Amily的test task 🛫 2022-05-30 📅 2022-06-03
- [x] 檢查Amily的test task 🛫 2022-05-30 📅 2022-06-03 ✅ 2022-06-06
- 改進RobotRunQA report
- TT
- [x] 在測試項目的主欄位上顯示resolution, format, fps 🛫 2022-06-06 📅 2022-06-10 ✅ 2022-06-09
- [ ] 在測試項目的主欄位上顯示test time 🛫 2022-06-06 📅 2022-06-10
- [x] test config 🛫 2022-06-06 📅 2022-06-10 ✅ 2022-06-09
- TestAllFormatsVTF
- [x] 在測試細項表格上顯示詳細說明 🛫 2022-06-06 📅 2022-06-10 ✅ 2022-06-07
- [x] Show "VideoFormats: "MaxFpsMaxResolutionOnly" to outside, let user understand the test purpose. 🛫 2022-06-06 📅 2022-06-10 ✅ 2022-06-08
- [x] List max fps of all resolution of all format on side bar of section 🛫 2022-06-06 📅 2022-06-10 ✅ 2022-06-08
- TestGpsDiff
- [ ] List all format 🛫 2022-06-06 📅 2022-06-10
# All TODOs
```tasks
not done
path does not include 2021
path does not include 2022/01
path does not include 2022/02
path does not include 2022/03
path does not include 2022/04
path does not include 02. PARA/04. Archives歸檔
path does not include 001. Kong
group by folder
group by filename
group by heading
```

View File

@@ -0,0 +1,48 @@
時間10:21:22
### TAG
### All TODOs
```tasks
not done
path does not include 2021
path does not include 2022/01
path does not include 2022/02
path does not include 2022/03
path does not include 2022/04
path does not include 02. PARA/04. Archives歸檔
path does not include 001. Kong
group by folder
group by filename
group by heading
```
---
### Doing TODOs
```tasks
not done
has start date
happens before tomorrow
path does not include 2021
path does not include 2022/01
path does not include 2022/02
path does not include 2022/03
path does not include 2022/04
path does not include 02. PARA/04. Archives歸檔
path does not include 001. Kong
group by folder
group by filename
group by heading
```
---
### 新增TODO
#### 私事
#### 公事
### 今日回顧
趁著早上還算是不太厭世趕快來清一下TODO先把簡單的shared_ptr寫一寫。

View File

@@ -11,7 +11,7 @@ path does not include 2022/01
path does not include 2022/02
path does not include 2022/03
path does not include 2022/04
path does not include 004 - Archives歸檔
path does not include 02. PARA/04. Archives歸檔
path does not include 001. Kong
group by folder
group by filename
@@ -30,7 +30,7 @@ path does not include 2022/01
path does not include 2022/02
path does not include 2022/03
path does not include 2022/04
path does not include 004 - Archives歸檔
path does not include 02. PARA/04. Archives歸檔
path does not include 001. Kong
group by folder
group by filename

View File

@@ -1,2 +1,3 @@
lvalue 是指:
- 等號左邊的值
- 「有固定address」的變數
- 可以被「取址」的變數

View File

@@ -1,9 +1,210 @@
rvalue 是指:
- 等號右邊的值
- 臨時的值,例如運算的結果
- 無法被取址address-of的物件
# rvalue參考
可以用兩個`&`來參考rvalue。例如
## rvalue reference
一般的參考只能參考[[lvalue]]如下的程式是ok的
```cpp
int a = 10;
int& b = a;
```
int c{5};
int&& rtepm {c + 3};
```
但是像這樣就不行了:
```cpp
int a = 10;
int b = 5;
int& c = a + b;
```
因為`a+b`是一個 rvalue臨時的值沒辦法取址所以無法參考。
但是可以用`&&`來參考 rvalue。例如
```cpp
int a = 10;
int b = 5;
int&& c = a + b; // c = 15
```
而不用這樣:
```cpp
int a = 10;
int b = 5;
int r = a + b;
int& c = r;
```
了解 rvalue reference 之後,就可以實作類別的 move constructor 跟 move assignment operator。這可以減少複製的成本。
## Move constructor
假設我們有一個 class 叫 BigBuffer定義如下
```cpp
class BigBuffer {
public:
BigBuffer(int size=100*1024*1024) :
bufferSize(size)
{
std::cout << "BigBuffer constructor\n";
this->buffer = std::make_unique<uint8_t[]>(bufferSize);
}
~BigBuffer() {
std::cout << "BigBuffer destructor\n";
}
BigBuffer(const BigBuffer& src) {
std::cout << "BigBuffer copy constructor\n";
bufferSize = src.bufferSize;
buffer = std::make_unique<uint8_t[]>(bufferSize);
std::memcpy(buffer.get(), src.buffer.get(), bufferSize);
}
BigBuffer& operator= (BigBuffer& src) {
std::cout << "BigBuffer copy operator\n";
bufferSize = src.bufferSize;
buffer = std::make_unique<uint8_t[]>(bufferSize);
std::memcpy(buffer.get(), src.buffer.get(), bufferSize);
return *this;
}
private:
int bufferSize = 0;
std::unique_ptr<uint8_t[]> buffer = nullptr;
};
```
這個 class 的特色就是每一次使用都會佔用100MB的記憶體空間想像下面的程式的動作
```cpp
BigBuffer buf1;
// Do something with buf1
// Assign to buf2
BigBuffer buf2 = buf1;
```
執行訊息:
```
BigBuffer constructor // create buf1
BigBuffer copy constructor, copy 104857600Bytes // copy buf1 to buf2
...
```
這會先產生 buf1然後把 buf1 copy 給 buf2。如果我們想要省下 copy 的成本,這時候 Move constructor 就可以派上用場了。
幫 BigBuffer 加一個 Move constructor
```cpp
class BigBuffer {
public:
...
BigBuffer(BigBuffer&& src) noexcept {
std::cout << "BigBuffer move constructor\n";
bufferSize = src.bufferSize;
buffer = std::move(src.buffer);
src.buffer.reset();
src.bufferSize = 0;
}
...
};
```
這個 move constructor 的參數就是一個 rvalue reference我們把來源的 bufferSize 跟 buffer 指標「移到」我們這邊,而不是完整的複製一份。在轉移之後呢,當然也要把來源清空,讓轉移更加明確。
有了 Move assignment operator 之後,在執行一次原本的程式,你會發現訊息......沒有變,還是一樣呼叫 copy constructor 來複製了100MB 的 buffer這時我們需要明確的告訴 compiler 我們要「移動」物件,而不是複製它,把原本的程式改為:
```cpp
BigBuffer buf1;
// Do something with buf1
// Assign to buf2
BigBuffer buf2 = std::move(buf1);
```
我們用 `std::move()` 來「移動」物件,這時輸出變成
```
BigBuffer constructor // create buf1
BigBuffer move constructor // move buf1 to buf2, buf1 has nullptr now
...
```
另外一個情形也可以受益於此,假如我們有個 function 會產生 `BigBuffer`,如下:
```cpp
BigBuffer BigBufferCreator() {
std::cout << "BigBufferCreator: Create a BigBuffer!\n";
BigBuffer tempb;
// do something
std::cout << "BigBufferCreator: return\n";
return tempb;
}
BigBuffer b = BigBufferCreator(); // copy tempb to b
```
在沒有 Move constructor 的情況下,上面的程式會先產生一個 `tempb`,然後複製給 `b`,訊息:
```
BigBufferCreator: Create a BigBuffer!
BigBuffer constructor
BigBufferCreator: return
BigBuffer copy constructor, copy 104857600Bytes // Copy 100MB!
...
```
在有 Move constructor 的情況下,訊息就變成:
```
BigBufferCreator: Create a BigBuffer!
BigBuffer constructor
BigBufferCreator: return
BigBuffer move constructor // Use MOVE!
BigBuffer destructor
BigBuffer destructor
```
因為 `BigBufferCreator()` 產生的就是一個 `BigBuffer` rvalue所以 compiler 會使用 move constructor`BigBuffer(BigBuffer&& src)` 而不是 copy constructor。
## Move assignment operator(`=`)
Move assignment operator 的行為跟 move constructor 是一樣的,幫 `BigBuffer` 加入 move assignment operator
```cpp
class BigBuffer {
public:
...
BigBuffer& operator=(BigBuffer&& src) noexcept {
std::cout << "BigBuffer move operator\n";
bufferSize = src.bufferSize;
buffer = std::move(src.buffer);
src.buffer.reset();
src.bufferSize = 0;
return *this;
}
...
};
```
測試程式:
```cpp
BigBuffer b1, b2;
b2 = b1;
```
訊息:
```
BigBuffer constructor
BigBuffer constructor
BigBuffer copy operator, copy 104857600Bytes
```
還是使用 copy assignment operator 來複製,理由是一樣的,需要一個明確的 `std::move()` 來表示「轉移」的行動,把程式改成:
```cpp
BigBuffer b1, b2;
b2 = std::move(b1);
```
這樣就可以了。訊息:
```
BigBuffer constructor
BigBuffer constructor
BigBuffer move operator // Use MOVE!
```
## 參考
- [Value categories - cppreference.com](https://en.cppreference.com/w/cpp/language/value_category)
- [rvalue 參考](https://openhome.cc/Gossip/CppGossip/RvalueReference.html)
- [Move constructors - cppreference.com](https://en.cppreference.com/w/cpp/language/move_constructor)
- [Move assignment operator - cppreference.com](https://en.cppreference.com/w/cpp/language/move_assignment)

View File

@@ -0,0 +1,110 @@
[`unique_ptr`](https://en.cppreference.com/w/cpp/memory/unique_ptr)與[`shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr)都是智慧指標箱對於原本的raw pointer智慧指標使用起來更方便也不用擔心delete的問題。
## unique_ptr
`unique_ptr` 的特點是,它保證在一個時間內,只會有一個指標的擁有者,也就是這個指標不能被複製跟移動,當 `unique_ptr` 離開它的scope時候它所擁有的指標也隨之被delete。這讓你不用擔心memory leak的問題。
假設我們有一個class叫 `BigBuffer` ,原本分配記憶體的方法:
```cpp
BigBuffer* bigBuf = new BigBuffer(bufferSize);
// Use buffer here
delete bigBuf;
```
`unique_ptr`
```cpp
auto bigBuf = std::make_unique<BigBuffer>(bufferSize);
// Use buffer here
// bigBuf will be released when exiting scope
```
我們統一用[`std::make_unique<>`](https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique)這個template function來建立 `unique_ptr` ,角括號 `<>` 裡面要帶入你要建立的型別,後面的括號 `()` 就是型別的constructor使用起來跟 `new` 是一樣的。
因為 `std::make_unique<>` 裡面已經有表明型別了,所以變數就用 `auto` 就可以了,不用再寫一次型別。
一旦 `unique_ptr` 建立之後,使用起來就跟一般指標沒有兩樣,都是用 `->` 來操作:`bigBuf->setXXX()` or `bigBuf->getXXX()`
但是別忘記 `unique_ptr` 本身還是一個local variable所以我們可以用 `.` 來操作 `unique_ptr` ,例如我們可以用 `.reset()` 重新配一個指標:
```cpp
BigBuffer* pBuffer = new BigBuffer();
bigBuf.reset(pBuffer);
```
這時候舊指標會自動delete如果記憶體分配有成功的話bigBuf會接管剛剛new出來的指標或者變成 `nullptr` (記憶體分配失敗)。
如果單純想要釋放指標,那就單純的呼叫 `reset()` 就好。
```cpp
bigBuf.reset(); // Now I'm nullptr
```
如果要分配陣列的話:
```cpp
auto intArray = std::make_unique<int[]>(1024);
```
使用方式也是一樣的:
```cpp
intArray[5] = 555;
```
不過對於陣列的操作更建議使用 `std::array`
如果有什麼特殊原因讓你決定不再讓 `unique_ptr` 來幫你管理指標,可以用 `release()` 來讓出指標:
```cpp
auto intArray = std::make_unique<int[]>(1024);
int* intArrayRaw = intArray.release(); // Now I don't care anymore
```
但是這時候呼叫 `delete[]` (或 `delete` )的責任又回到你身上了。所以千萬不要把 `release()``reset()` 搞混了。
`unique_ptr` 不能被複製跟移動,所以下列的寫法都編不過:
```cpp
auto ptr1 = std::make_unique<int>(5);
std::unique_ptr<int> ptr2(ptr1); // Error
std::unique_ptr<int> ptr2 = ptr1; // Error
```
在Visual Studio 2017上錯誤訊息是這樣`error C2280: 'std::unique_ptr<int,std::default_delete<int>>::unique_ptr(const std::unique_ptr<int,std::default_delete<int>> &)': attempting to reference a deleted function`
其實就是`unique_ptr`的copy constructor跟assignment operator都被標記為delete了。
### Move a unique_ptr
如果一定要把 unique_ptr 指定給別人可以嗎?可以的,用 `std::move()` 來轉移:
```cpp
auto ptr1 = std::make_unique<int>(5);
// do something
auto anotherPtr = std::move(ptr1);
```
ptr1原本所管理的指標會轉移給 anotherPtrptr1 會變成 nullptr。
## shared_ptr
建立一個 `shared_ptr` 是使用[`std::make_shared()`](https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared)
```cpp
auto myBuf = std::make_shared<BigBuffer>(bufferSize);
```
但是 `shared_ptr` 可以被複製與移動,這是跟 `unique_ptr` 的差別:
```cpp
auto myBuf = std::make_shared<BigBuffer>(bufferSize);
std::shared_ptr<BigBuffer> bufCopy = myBuf;
```
現在 bufCopy 跟 myBuf 都指向同一個指標,他們都可以操作這個指標:
```cpp
myBuf->setZero(startAddr, endAddr);
bufCopy->setOne(startAddr, endAddr);
```
`shared_ptr` 內部有一個參考記數reference count來紀錄它所擁有的指標已經分享給幾個變數了只要有變數離開了他的scope參考記數就會減少反之要是像上面那樣有人複製指標參考記數就會增加參考記數歸0的時候指標就會被釋放。
有了 `shared_ptr` 我們就不必擔心 delete 的責任問題:
```cpp
std::shared_ptr<BigBuffer> getBuffer(int32_t bufferSize) {
return std::make_shared<BigBuffer>(bufferSize);
}
int main() {
auto myBuf = getBuffer(1024); // new(malloc) memory
// use myBuf
return 0;
} // myBuf delete memory here
```
`shared_ptr` 有一個問題是可以會「循環參考」cyclic references也就是 share_ptr A 指向另一個 share_ptr B ,然後 share_ptr B 又指向 share_ptr A這造成參考記數reference count不會減少而永遠無法釋出指標。這個是需要注意的。
但是 `shared_ptr` 還是讓記憶體的管理問題大大減少,應該用 `shared_ptr` 來代替 `new` & `delete`

View File

@@ -0,0 +1,17 @@
- [FFmpeg](https://www.ffmpeg.org/)
- Open source
- For handling multimedia files and streams
- GPL/LGPS license
- Inspired by MPEG(Moving Picture Experts Group), FF means "Fast Foward"
- Libraries
- libavcodec: Contain all the encoders and decoders
- libavformat: Muxers and demuxers
- libavfilter: Filters that you can use on your video and audio according to your requirements
- libavdevice: Input and output devices
- libavutil
- libswscale
- libswresample
- Tools
- ffmpeg: Main transcoding engine
- ffplay: Minimum tool to play a video or audio
- ffprobe: For inspecting medias and extract valuable information

View File

@@ -0,0 +1,30 @@
FFmpeg doesn't support any official builds for any operation systems. You can build the codes from source, or use the prebuilt packages.
## From source
Get source code from [snapshot](https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2) or git(`git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg`).
## From prebuilt packages
### MacOS
Use homebrew to install FFMPEG package
```
brew install ffmpeg
```
### Ubuntu
```
sudo apt update ;\
sudo apt install ffmpeg
```
### Windows
Goto https://www.ffmpeg.org/download.html, and
![[Pasted image 20220607105807.png]]
And then browser jumps to https://www.gyan.dev/ffmpeg/builds/, click [release build](https://www.gyan.dev/ffmpeg/builds/#release-builds), download **release-full**.
![[Pasted image 20220607110211.png]]
Unzip the file, then put the folder to anywhere you like, e.g. `C:\libs`, so the full path of ffmpeg packages should looks like: `C:\libs\ffmpeg-5.0.1-full_build`
#### Add to system variable
Add the path of bin of ffmpeg packages to `PATH` system variable.
![[Pasted image 20220607110949.png]]

View File

@@ -0,0 +1,27 @@
## 建立 Git Submodule
```
git submodule add <repository> [<local_path>]
```
新增之後,用 git status 會發現多了兩個東西需要 commit
![[Pasted image 20220608152709.png]]
第一個檔案 .gitmodules裡面紀錄 submodule 的對應關係,內容大概像這樣:
```
[submodule "RobotRunQA"]
path = RobotRunQA
url = git@github.com-logi:JuiwenHsu/RobotRunQA.git
```
接下來剩3個步驟
1. 提交 `.gitmodule``git add .gitmodule ; git push origin master`
2. 跟git說我們有新增一個submodule`git submodule init`
3. 把submodule pull下來`git submodule update`
## Clone repository and submodule
當clone一個有submodule的repo的時候我們還需要 `git submodule init``git submodule update` ,例如:
```
git clone https://xxx/xxx.git
cd xxx
git submodule init
git submodule update
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB