momoで任意のビデオ解像度を指定可能にする修正

## 現状のmomoのビデオ解像度

現状のmomoではビデオ解像度として `--resolution` のオプションで{4K,FHD,HD,QVGA,VGA}の5種類の解像度しか指定することができません。
864x480 とか 500x500 の指定をしたいと思ってmomoを修正してみました。

2020.1.21 追記
momoのリリース 2020.1 で任意の解像度を指定できるようになりましたので、この記事の修正は不要になりました。
[WebRTC Native Client Momo 2020.1 リリースノート](https://medium.com/shiguredo/webrtc-native-client-momo-2020-1-%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%83%8E%E3%83%BC%E3%83%88-b7ffd5435fa4)

## 追加するオプション

解像度の指定方法として`--width` と `--height` を追加します。
従来との互換性のために、これらの初期値は0になっていて`--width` と `--height` の両方を指定した時だけこちらの指定が使用され、そうでない場合は`--resolution` の指定が使用されます。

また、このオプションは「この解像度をカメラに要求する」だけで、実際にどのような解像度になるかはカメラ次第です。
カメラが指定された解像度をサポートしている場合はそれが採用されますが、そうでない場合はエラー終了したり、近い解像度が選択されたりします。

実際にどのような解像度でカメラから映像を受け取っているかは配信中に別のターミナルから以下のコマンドを実行すると調べることができます。

```
v4l2-ctl -d /dev/videoX --all
```

(`-d` で使用しているビデオキャプチャデバイスを指定する。)

そのビデオキャプチャデバイスで指定可能な解像度は以下のコマンドで調べることができますので、あらかじめ調べておくのがよいでしょう。

```
v4l2-ctl -d /dev/videoX --list-formats-ext
```


## ソースコードの変更点

19.08.1をベースにしています。

```diff
diff --git a/src/connection_settings.h b/src/connection_settings.h
index 4b2dabb..0145e31 100644
--- a/src/connection_settings.h
+++ b/src/connection_settings.h
@@ -27,6 +27,8 @@ struct ConnectionSettings
   int video_bitrate = 0;
   int audio_bitrate = 0;
   std::string resolution = "VGA";
+  int width = 0;
+  int height = 0;
   int framerate = 30;
   bool fixed_resolution = false;
   std::string priority = "BALANCE";
@@ -45,6 +47,9 @@ struct ConnectionSettings
   std::string ayame_signaling_key = "";
 
   int getWidth() {
+    if (width * height != 0) {
+      return width;
+    }
     if (resolution == "QVGA") {
       return 480;
     } else if (resolution == "HD") {
@@ -58,6 +63,9 @@ struct ConnectionSettings
   }
 
   int getHeight() {
+    if (width * height != 0) {
+      return height;
+    }
     if (resolution == "QVGA") {
       return 320;
     } else if (resolution == "HD") {
diff --git a/src/util.cpp b/src/util.cpp
index cfd707c..3774518 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -63,6 +63,8 @@ void Util::parseArgs(int argc, char *argv[], bool &is_daemon,
   local_nh.param<int>("video_bitrate", cs.video_bitrate, cs.video_bitrate);
   local_nh.param<int>("audio_bitrate", cs.audio_bitrate, cs.audio_bitrate);
   local_nh.param<std::string>("resolution", cs.resolution, cs.resolution);
+  local_nh.param<int>("width", cs.width, cs.width);
+  local_nh.param<int>("height", cs.height, cs.height);
   local_nh.param<int>("framerate", cs.framerate, cs.framerate);
   local_nh.param<int>("audio_topic_rate", cs.audio_topic_rate, cs.audio_topic_rate);
   local_nh.param<int>("audio_topic_ch", cs.audio_topic_ch, cs.audio_topic_ch);
@@ -116,6 +118,8 @@ void Util::parseArgs(int argc, char *argv[], bool &is_daemon,
 #endif
   app.add_set("--resolution", cs.resolution, {"QVGA", "VGA", "HD", "FHD", "4K"},
               "解像度");
+  app.add_option("--width", cs.width, "width of video")->check(CLI::Range(1, 4096));
+  app.add_option("--height", cs.height, "height of video")->check(CLI::Range(1, 4096));
   app.add_option("--framerate", cs.framerate, "フレームレート")->check(CLI::Range(1, 60));
   app.add_flag("--fixed-resolution", cs.fixed_resolution, "固定解像度");
   app.add_set("--priority", cs.priority, {"BALANCE", "FRAMERATE", "RESOLUTION"},
```

## 実際にやってみて

### Raspberry Pi カメラモジュール V2

3280×2464 より小さい解像度ならば任意の解像度を指定可能のようです。しかし1920x1080より大きなものは内部の処理が追いつかないようなので現実的ではありません。

### ロジクール c270

`v4l2-ctl -d /dev/videoX --list-formats-ext` で調べた解像度が選択可能です。
それ以外の場合はより近い解像度が選択されます。
例えば、300x300 を指定すると実際には 352x288 が選択されます。

## 関連

[Webcamで設定可能な解像度やフレームレートを調べる方法 (video4linux2)](https://qiita.com/tetsu_koba/items/01491f96daddf15677df)