Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ffmpeg の -probesize オプションに相当するオプションを実装してほしい #335

Closed
tsukumijima opened this issue Apr 23, 2021 · 76 comments

Comments

@tsukumijima
Copy link

QSV/NV/VCEEncC を TVRemotePlus にて使わせていただいています。ありがとうございます。

さて、TVRemotePlus のライブ配信は TSTask から受け取った UDP の MPEG2-TS ストリーム(放送波)の映像を H.264 に再エンコードし、HLS (m3u8+TS) 形式に変換してそれをブラウザで再生する事で実現しています。
しかし、ffmpeg と、ffmpeg をベースに使用している QSV/NV/VCEEncC では受け取った TS ストリームを認識するまでに時間がかかり、その影響でブラウザ上で再生が開始されるまでに時間がかかってしまっています。

  1. TSTask が物理チューナーを開く時間
  2. TSTask がチャンネルを切り替える時間
  3. ffmpeg・QSV/NV/VCEEncC が UDP で受け取った TS ストリームを認識するまでの時間
  4. ffmpeg・QSV/NV/VCEEncC でエンコードする時間
  5. ブラウザで HLS のマニフェストをダウンロード・解析する時間
  6. ブラウザで HLS のセグメントをダウンロード・再生する時間

ストリームを開始してからブラウザ上で再生が開始されるまでにかかる時間は上記のように積み重なっていますが、このうち 3 番の「ffmpeg・QSV/NV/VCEEncC が UDP で受け取った TS ストリームを認識するまでの時間」にボトルネックがあることがわかりました。UDP が問題なのかとも思い TCP やパイプで渡してみたりもしたのですが、同様の状態でした。

ところが最近、ffmpeg にて試しに -i オプションの前に -f mpegts -probesize 8192 -analyzeduration 0 を指定してみたところ、 3 番にかかる時間が大幅に短縮され、結果的にブラウザ上で再生が開始されるまでの時間を2~3秒も短縮することができました。
-probesize-analyzeduration はいずれも入力ストリームの解析を行う上限のバイト数と時間(秒)を指定するもののようですが、これをあえて低い値にすることで入力の解析時間を短縮し、それが全体の時間短縮に繋がっているものと考えられます。
入力がパイプで出力が MPEGTS (H.264) の場合は -probesize を最小の 32 にまで小さくすることもできるようですが、UDP で HLS 出力という関係か、8192 が実用上の限界でした。それでも 2 秒も短縮されるのは大きいです。

しかし、QSV/NV/VCEEncC には ffmpeg の -probesize に相当するオプションがありません(少なくともオプションを確認した限りはそう見えます)。
-f に相当するオプションは --input-format-analyzeduration に相当するオプションは --input-analyze として存在するようですが、-probesize に相当するオプションが今のところないため、QSV/NV/VCEEncC では再生開始までの時間を短縮できていません。

そこで、QSV/NV/VCEEncC にも -probesize に相当するオプションを実装していただけないでしょうか?
試しに QSVEncC・NVEncC で --input-format mpegts --input-analyze 0 のように ffmpeg の -probesize 以外の相当するオプションを追加してやってみましたが、明らかな短縮効果は感じられませんでした。-probesize と組み合わせて初めて短縮効果が出るみたいです。

この手法を教えて頂いた方いわく、QSV/NV/VCEEncC の -probesize は 0.5GB で固定になっているとのことでした ( https://github.com/rigaya/QSVEnc/blob/8ca51bb13bd6052def2b9372fbba4d76098eaf93/QSVPipeline/rgy_input_avcodec.cpp#L1207-L1214 )。avformat_find_stream_info に probesize を指定する事は難しくないんじゃないかとも ( https://programmersought.com/article/430134736/ )。私は C++ も libav も分からないのでさっぱり理解できていませんが…

私がメインで使わせて頂いているのが NVEncC なのでこちらのリポジトリに投稿させていただきましたが、もし可能であれば他の QSVEncC・VCEEncC にも実装していただけると大変助かります。
お忙しいとは思いますが、ぜひご検討をよろしくお願いします。

@rigaya
Copy link
Owner

rigaya commented Apr 24, 2021

要望とその背景を説明いただきありがとうございます。

ご指摘の通り、probesizeを指定できるようにすること自体は比較的難しくないので、--input-probesizeとしてオプションを追加したものを添付しました。(→ NVEncC64_5.31beta1.zip)

また、このバージョンではわずかですがいくつか初期化処理の高速化を図りました。

  • 冗長な処理のスキップ
  • 内部バッファ削減(16→1)による遅延削減
  • --input-analyzeを小数点で指定できるように
  • --input-analyzeが1秒以下の時、通常48フレーム読み込んで行うフレームレート推定処理をスキップ

ただ残念ながら"--input-format mpegts --input-analyze 0 --input-probesize 8192"での動作は難しいです。

avformat_find_stream_info は映像/音声のヘッダーを認識してその情報を取得するとともに、フレームレートを推定する重要な処理となっています。

しかし、ts ではデータの先頭がGOPの先頭とは限らないことから、analyzeduration や probesize が小さすぎるとGOPの先頭にあるヘッダーにたどり着けないことがあります。その結果、デコードに必要なヘッダー情報やエンコードに必要な映像の情報(解像度、フレームレート等)が取得できなくなってしまいます。

たとえば、ffmpegでも"-f mpegts -probesize 8192 -analyzeduration 0"とすると一部tsファイルでは下記にようにエラーメッセージがでてしまいます。

[mpegts @ 00000248751fe0c0] Stream #2: not enough frames to estimate rate; consider increasing probesize
[mpegts @ 00000248751fe0c0] decoding for stream 2 failed
[mpegts @ 00000248751fe0c0] start time for stream 1 is not set in estimate_timings_from_pts
[mpegts @ 00000248751fe0c0] start time for stream 3 is not set in estimate_timings_from_pts
[mpegts @ 00000248751fe0c0] PES packet size mismatch
[mpegts @ 00000248751fe0c0] Packet corrupt (stream = 0, dts = 4864449098).
[mpegts @ 00000248751fe0c0] Could not find codec parameters for stream 2 (Video: mpeg2video ([2][0][0][0] / 0x0002), none(tv)): unspecified size
Consider increasing the value for the 'analyzeduration' and 'probesize' options

太字部分が問題で、この状態では、エンコードに必要な映像の情報が取得できず、エンコードを開始することができません。(NVEncCではエラー終了するようになっています)

ffmpegはこの状態でもなんとかしているのだとは思うのですが、いったいどうやっているのか、すみません、よくわかりません。ffmpegと同様の動作にはできていないのかと思います。

個人的に少し試した感じでは、現状のNVEncCの実装ですといまのところ下記オプションぐらいが限界のように感じていて、probesize等でそれ以上削るのは難しいかもしれません。

--input-format mpegts --input-analyze 0.66

ただ、初期化時の遅延についてもある程度は改善できているので、まずは添付した添付した5.31beta1(→ NVEncC64_5.31beta1.zip)をお試しいただき、ご意見いただければ幸いです。

よろしくお願いいたします。

@tsukumijima
Copy link
Author

早速の実装ありがとうございます!こちら側で試してみます。

@tsukumijima
Copy link
Author

tsukumijima commented Apr 26, 2021

色々試してはいるのですが、正直 ffmpeg ほどうまくいっていない感じです。
--input-analyze を 0.66 まで縮めると、UDP送信が開始された後も延々とエンコードが開始されないことがありました。エラーは出ていません。1.0 でもそんなに変わらない?ようです。
…というよりも、どういう訳か番組内容?タイミング?によってUDP送信開始からストリーム認識までの時間がかなり変わるようで、それが元々遅い番組だと --input-analyze 0.66 だと認識までの時間がさらに伸びてしまう(TVRPの場合、一定時間以上エンコードが開始されなかったら強制終了になるのでどのくらい時間を掛けたら認識するのかは不明)ことがあるみたいです。
まだ完全に挙動を検証できていないので本当に合っているかどうかは微妙ですが、取り急ぎ報告まで。

@rigaya
Copy link
Owner

rigaya commented Apr 28, 2021

状況のご連絡ありがとうございます。

まだNVEncC側の改善が必要そうですね。

GWの時間を利用してffmpegの挙動と比較するなどして、もう少し改良できないか見てみたいと思います。

@tsukumijima
Copy link
Author

tsukumijima commented Apr 28, 2021

ありがとうございます。

こちらでも色々試してはいるのですが、どうも挙動がはっきりとわからなくて、なんとも言えないもどかしい状態です。
UDPで受信しているのを標準入力からに変えたらまた変わってくるのか、エンコーダーを立ち上げてから実際にストリームが到着するまでに時間がかかるというのもあるんだろうか…など。

こちらの環境が悪いのかもしれませんが、番組やタイミングによってストリームの認識にかかる時間がかなり変わる?ようで、一定ではなく、早かったり遅かったりするみたいです。同時間に放送されているチャンネルでも、明らかにストリームの認識が早いチャンネルと遅いチャンネルが存在します。しかもチャンネルによって固定というわけでもないので、ますますよくわかりません。本当にひどいときだとUDP送信はとっくに始まっているのに、ストリームの認識に10秒以上待たされる事もありました。

ストリームの認識が早いチャンネル/番組、遅いチャンネル/番組はたしかにあるようなんですが、タイミングによっても?早い遅いは変化するようで、これも一定ではありません。それもあってよくわからないでいます。
TVRemotePlus にはすでに視聴中の場合でチャンネルを切り替える場合に TSTask を使い回す(=チューナーのオープンからやり直さず、チャンネルの切り替えだけを行う)機能があり、その場合だとエンコーダーが起動した時点でUDP送信が開始されている状態がほとんどでブラウザで再生が開始されるのもチューナーのオープンがない分早くなる(特にチューナーオープンが遅いPLEX製品、PT3はチューナーのオープン自体がかなり速いのでそこまで差を感じられない)のですが、その場合でもストリームの遅いチャンネルは本当に遅いです。
これに関しては同時に別々のチャンネルを同時にストリーム開始して確認しました。確認当時は tvk の試験放送が認識に13秒程度かかっていました。

これは今回の beta 版の更新による問題ではなく、以前からこのような状態だったようです。エンコーダーが違うからか完全に同じ認識秒数というわけでもないようですが、QSVEncC でも同様の傾向がありました。NVEncC で認識が遅いチャンネルは QSVEncC でも遅いし、その逆も然り。

そして、ffmpeg + -f mpegts -probesize 8192 -analyzeduration 0 だと、どのチャンネルも同じくらいの認識秒数(TSTaskとffmpegの挙動を見る限り、UDP送信開始直後にエンコードが開始されているのでほぼ待機なし)で安定しています。ブラウザで再生が始まるまでの秒数はトータルで8~10秒程度でしょうか。QSVEncC/NVEncC だと早いときでも10秒~12秒くらいはかかってる気がします(目測なので精度は微妙)。
先程例として挙げた tvk の試験放送も、QSVEncC・NVEncC 両方ともかなり認識に時間がかかっていましたが、ffmpeg だと他のチャンネルとほぼ変わりません。
チャンネル切り替えはチューナーのオープンを伴わず、前述したように認識にほとんど時間がかからないため爆速で、トータル4秒程度で再生が始まります。
このあたりはHLS側の再生バッファも絡んでくるので、それがなければ2秒程度までなるんじゃないかという印象です。

というわけで、現時点では ffmpeg だとチャンネルによって認識時間が変わったりもせずほぼ一定で素早くストリームを認識してくれるけど、QSVEncC・NVEncC(環境がないのでわからないけど、おそらく VCEEncC も)ではどういうわけかチャンネルによって認識時間が変わったりがあるし、--input-probesize や --input-analyze を付与してもうまくいかない状態です。

@rigaya
Copy link
Owner

rigaya commented Apr 30, 2021

1. NVEncCの改善

実際にTVRemotePlusを導入し、いろいろなチャンネルで動作確認を行いました。たしかに、エンコード開始に非常に時間のかかってしまうタイミングやチャンネルがありました。

私は従来avformat_find_stream_infoを呼ぶ時に時間がかかる想定でいたのですが、実はavformat_open_inputを呼ぶ時にも時間がかかっていることがわかりました。

より詳細に調べると、ご指摘のように--input-analyzeはどのように指定しようが、ストリームの認識が遅い場合があり、これを防ぐには--input-probesizeをavformat_open_inputを呼ぶ前に設定して防ぐ必要があることがわかりました。このあたりの実装見直しを行ったNVEncC 5.31 beta2を添付しました。NVEncC64_5.31beta2.zip

このとき、--input-probesize 8192のような設定では、0.5秒に1回程度やってくるGOPの先頭についている映像のヘッダを認識できずエラーとなってしまいます。これを防ぐため、--input-probesizeを適切に指定する必要があります。--log-level debugで詳細なログを見ると、avformat_open_inputを呼ぶ時と、avformat_find_stream_infoを呼ぶ時のそれぞれで、probesize分のデータが読まれることがわかりますので、

probesize * 2 > 余裕をもって0.6秒ぐらい * 各チャンネルのtsのビットレート

となるように設定する必要があります。

チャンネルごとにビットレート(スロット数)が違うので厄介ですが、BSの最大ビットレートを24Mbps(=3MB/s)とす仮定すると、probesize=900K程度がよさそうです。

まずは添付の実行ファイルNVEncC64_5.31beta2.zipをお使いいただき、
--input-format mpegts --fps 30000/1001 --input-analyze 0.67 --input-probesize 900k
でお試しいただけないでしょうか。ffmpegほど早くなってはいないと思いますが、長く待たされる、ということはかなり減ったのではないかと思います。

2. ffmpegの挙動の確認

次に、ffmpegの-f mpegts -probesize 8192 -analyzeduration 0を使用した場合の挙動を確認しました。

このとき、mpegtsの構造認識は終わっているものの、映像のヘッダ情報をとれていないという状態のまま、次に進んでいるようです。まあたしかに、これならavformat_find_stream_infoはすぐ終わります。

[mpegts @ 000002c737f785c0] Probe buffer size limit of 8192 bytes reached
[mpegts @ 000002c737f785c0] Stream #1: not enough frames to estimate rate; consider increasing probesize
[mpegts @ 000002c737f785c0] decoding for stream 1 failed
[mpegts @ 000002c737f785c0] Could not find codec parameters for stream 1 (Video: mpeg2video, 1 reference frame
 ([2][0][0][0] / 0x0002), none(tv)): unspecified size
Consider increasing the value for the 'analyzeduration' and 'probesize' options

ただその後、ヘッダーがない状態でデコーダを起動しているので、しばらくデコードエラーが出ていますが、

[mpeg2video @ 000002c737fb4b00] Invalid frame dimensions 0x0.
Error while decoding stream #0:1: Invalid data found when processing input
cur_dts is invalid (this is harmless if it occurs once at the start per stream)
    Last message repeated 1 times

途中で(おそらくGOPが切り替わりヘッダを認識したところで)回復しています。

[mpeg2video @ 000002c737fb4b00] Format yuv420p chosen by get_format().
[mpeg2video @ 000002c737fb4b00] video_delay is larger in decoder than demuxer 1 > 0.
If you want to help, upload a sample of this file to ftp://upload.ffmpeg.org/incoming/ and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)
cur_dts is invalid (this is harmless if it occurs once at the start per stream)
    Last message repeated 1 times
[mpeg2video @ 000002c737fb4b00] Skipping B slice due to open GOP
    Last message repeated 67 times
[mpeg2video @ 000002c737fb4b00] video_delay is larger in decoder than demuxer 1 > 0.
If you want to help, upload a sample of this file to ftp://upload.ffmpeg.org/incoming/ and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)
cur_dts is invalid (this is harmless if it occurs once at the start per stream)
    Last message repeated 2 times
[mpeg2video @ 000002c737fb4b00] Skipping B slice due to open GOP
    Last message repeated 67 times
[mpeg2video @ 000002c737fb4b00] video_delay is larger in decoder than demuxer 1 > 0.
If you want to help, upload a sample of this file to ftp://upload.ffmpeg.org/incoming/ and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)
cur_dts is invalid (this is harmless if it occurs once at the start per stream)
    Last message repeated 1 times
[mpeg2video @ 000002c737fb4b00] video_delay is larger in decoder than demuxer 1 > 0.
If you want to help, upload a sample of this file to ftp://upload.ffmpeg.org/incoming/ and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)

このように、ffmpegはとりあえずデコーダ・エンコーダを起動してしまい、デコードできるようになってから処理できるようになっているようです。

現状NVEncCはffmpegのようにデコーダのエラーを許容するようになっていないので、これとまったく同様の動作の再現は現状では難しいです。

まずは上記1.で示したような対応方法をお試しいただけないでしょうか。1.の方法でも遅いようですと、さらにNVEncCの実装見直しが必要になりそうです。

よろしくお願いいたします。

@tsukumijima
Copy link
Author

tsukumijima commented Apr 30, 2021

わざわざ導入までしていただいての素早いご対応に感謝します。ありがとうございます。

全体的にストリーム開始までの時間が(ffmpeg ほどとまではいきませんが)いくらか短縮され、またまちまちだったストリームの認識時間もあまり変わらなくなっていると思います。少なくとも、ストリームの認識に10秒以上かかることはなくなりました。
おっしゃる通り ffmpeg での -probesize 8192 はかなり無理をしているようで、失敗することはないもののエラーログがドバドバ出ながらエンコードしている感じですね。
(修正できるレベルのものかどうか分かりませんが)ちょっと気になった事としては、コンソール上でエンコードが開始されているように見えるのにも関わらず、実際の m3u8+ts 出力が行われておらず(?)、エンコード開始から5秒以上経ってからようやく一気にファイルが出力される(?)ような現象がたまにあります。

avcuvid: Input video info not parsed yet [0x0]!
avcuvid: Consider increasing the value for the --input-analyze and/or --input-probesize!
failed to initialize file reader(s).
Failed to open input file.

あとはごくまれに上記のようなエラーが出てエンコーダーが落ちてしまうことがあったくらいでしょうか。これに関してはちょっと probesize 諸々縮めすぎって事なんでしょうけど…

@rigaya
Copy link
Owner

rigaya commented May 1, 2021

早速お試しいただきありがとうございます。一定の効果が得られていてよかったです。

あとはごくまれに上記のようなエラーが出てエンコーダーが落ちてしまうことがあったくらいでしょうか。これに関してはちょっと probesize 諸々縮めすぎって事なんでしょうけど…

おっしゃる通りprobesize を縮めすぎということになるのですが、このエラーでエンコーダが落ちてしまうとストリームの立ち上がりがだいぶ遅くなってしまうので、こちらの問題への対策として、新たに--input-retry <int>というオプションを追加しました。NVEncC64_5.31beta3.zip

avcuvid: Input video info not parsed yet [0x0]!の問題が発生したことを検知した場合に、エラーで落とすのではなく、--input-probesizeと--input-analyzeを前回の1.5倍にしたうえでストリームのオープンをやり直す機能です。指定する値はやり直しの最大回数で、適当に--input-retry 15などにしておけばよいように思います。やり直しなしの時と比べて時間はどうしてもかかりますが、エンコーダが落ちてしまうのに比べればよくなったように思います。

(修正できるレベルのものかどうか分かりませんが)ちょっと気になった事としては、コンソール上でエンコードが開始されているように見えるのにも関わらず、実際の m3u8+ts 出力が行われておらず(?)、エンコード開始から5秒以上経ってからようやく一気にファイルが出力される(?)ような現象がたまにあります。

--log-level debugをつけるとファイル出力のタイミングがログに出ますが、わたしのほうではあまりラグがあるようには見受けられませんでした。なにか条件などがあるのかもしれませんが…

@tsukumijima
Copy link
Author

tsukumijima commented May 1, 2021

返信ありがとうございます。


以前書いた tvk の放送休止の番組(カラーバーとビープ音が延々と流れるやつ)は、5.31beta3 でも残念ながらストリームの認識が遅いです。ffmpeg(字幕なし)では他の番組同様速いです。
もちろん放送休止の番組が早く見れる事自体に意味はありませんが、他の番組でもそういう認識が遅くなるケースがあるのではないかと少々気になります。今のところその番組よりストリーム認識が遅い番組は見つけていませんが。
ただし、その番組以外では概ね早めに認識できていそうなので、よくわかりません。取り急ぎ報告まで。


少し話がそれてしまいますが、エンコーダーのストリーム認識時間の件と同時並行で、arib-subtitle-timedmetadater を TVRemotePlus に導入する準備をしています。develop ブランチにてテスト中です。

arib-subtitle-timedmetadater は monyone 氏が謎の技術で作成されたツールで、ARIB 字幕を timed_id3 (ID3) メタデータに変換します(具体的には ARIB 字幕のバイナリをそのまま BASE64 エンコードしているらしい)。
その ID3 メタデータをブラウザ側で aribb24.js の CanvasID3Renderer() を使って読み取ることで、ARIB 字幕を直接 HLS でエンコード後の TS 内にコピーしなくても timed_id3 ストリームが HLS でエンコード後の TS 内に入っていれば字幕を描画できるようになるというものです。

元々 ARIB 字幕を再生するような仕様が HLS にある訳がありませんから、従来の手法の場合、HLS の再生には hls-b24.js のような TS から ARIB 字幕を取り出せるようにパッチを当てた hls.js(HLS 再生ライブラリ)を使う必要がありました。また、iOS Safari の制限で hls.js を使うことができない(内蔵 HLS プレイヤーを使うほかない)iOS では字幕を TS から取り出せないので、字幕を描画できないという問題がありました。

さらに、ffmpeg 4.2.0 以降は ARIB 字幕が arib_caption と字幕の一形式として認識されるようになりました。ffmpeg の HLS エンコーダーは字幕ストリームを強制的に webvtt に変換しようとしますが、arib_caption から webvtt に変換するエンコーダーはないためエラーで落ちてしまいます。monyone 氏開発の arib-subtitle-unrecognizer という arib_caption として認識させなくするまたもや謎の技術ツールを噛ませばなんとかなるようですが…。

一方、ID3 メタデータが HLS の TS 内に入っている状態は HLS の仕様で規定されているようで、そのため TS セグメント内の ID3 メタデータであれば hls.js でも iOS Safari の内蔵 HLS プレイヤーでも標準で読み取る事が可能です。この新方式では従来の方法では不可能だった iOS Safari でも字幕を表示できるようになるので、今試しに実装してみています。


前置きが長くなりました。

さて、arib-subtitle-timedmetadater は TSTask から送信されてくるストリーム入力とエンコーダーとの間に入りそこで ARIB 字幕 → ID3 メタデータへ変換したTSを出力するため、必然的にエンコーダーではなく arib-subtitle-timedmetadater にて UDP 受信を行い、変換結果をパイプで NVEncC を含め各種エンコーダーに渡すような形態になります。

なのですが、先ほど実装いただいた --input-retry オプションをつけると、(意図的にリトライさせるために --input-probesize を 300K くらいに縮めた場合で)arib-subtitle-timedmetadater がエラーで異常終了してしまいます。
さらに標準出力に出力されたエラーメッセージを NVEncC が受け取ってしまい結果 NVEncC がフリーズするという最悪な事になってしまうので、今のところ --input-retry は機能していません…。

avcuvid: Failed to get video stream information, retry opening input (1/15)!
events.js:183
      throw er; // Unhandled 'error' event
      ^

Error: EPIPE: broken pipe, write
    at Socket._write (internal/net.js:23:7)
    at doWrite (_stream_writable.js:396:12)
    at writeOrBuffer (_stream_writable.js:382:5)
    at Socket.Writable.write (_stream_writable.js:290:11)
    at Socket.write (net.js:711:40)
    at MetadataTransform.ondata (_stream_readable.js:639:20)
    at emitOne (events.js:116:13)
    at MetadataTransform.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)

arib-subtitle-timedmetadater のエラー内容は上記の通りで、monyone 氏に問い合わせたところ「GitHub に上げられてないので差分が全く分からない…」「どのみち broken pipe になった時点でできる事ないし、入力を閉じないでくれというしかないですね」とのことでした。
エラーからして、arib-subtitle-timedmetadater は標準出力に出力しようとしたが、NVEncC の入力は閉じられているので(?)出力に失敗したって所なのかなと想像してます。
リトライした時に入力を開けたままにすることができれば arib-subtitle-timedmetadater が broken pipe で落ちることもないはずなので、もし可能であればそのあたりの対応をお願いします(大雑把な要望で本当にすみません…)。


次に、この手法の場合、あらかじめ arib-subtitle-timedmetadater によって挿入された timed_id3 ストリーム(注:ARIB 字幕のストリームを上書きするわけではなく、その隣のストリームとして挿入されるっぽい)をエンコーダーにコピーしてもらう必要があります。
ffmpeg では -map 0 -ignore_unknown もしくは -map 0:v -map 0:a -map 0:d で timed_id3 ストリームをコピーすることができます。ARIB 字幕をそのままコピーする時と同じです。
ffmpeg では timed_id3 ストリームだけを指定してコピーできないので、ARIB 字幕の bin_data ストリームと timed_id3 ストリーム両方が同じデータストリームとして HLS エンコード後の TS セグメントに入る感じになります。
NVEncC ではてっきり --metadata オプションあたりでいけるかと思ったのですが、timed_id3 ストリームは「Timed」なので普通のメタデータとは異なりデータストリーム扱いになっているらしく、現状の NVEncC のオプションではコピーする事ができなさそうでした(私が見落としているだけかもしれませんが)。

そこで、timed_id3 ストリーム(もしくはデータストリーム全体)をコピーするオプションを実装していただけないでしょうか?
timed_id3 ストリームが HLS エンコード後のストリームにコピーできれば、NVEncC でも(ストリームの認識時間はさておき)新方式で字幕を表示できるようになります。ffmpeg で -map 0:v -map 0:a -map 0:d を使い新方式で字幕が表示できることは確認しています。


正直 arib-subtitle-timedmetadater を使った新方式は、ほかにも

  • 現状 arib-subtitle-timedmetadater でパケットロスなく TSTask の TCP or UDP ストリームを受信できない
    • ffmpeg で UDP 受信する場合と異なり、エンコード当初になぜか大きめのパケットロスが起きる
    • TCP 受信では継続的に小さめのパケットロスが起きる
  • ffmpeg で -map オプションを使うと -probesize-analyzeduration を指定した場合でも HLS のエンコード開始がなぜか8~10秒程度遅れてしまい字幕と速度がトレードオフになってしまう
    • ストリームの認識はしている
    • ARIB 字幕をそのままコピーしていた頃からこうなので(そもそもコマンドがほぼ変わっていない)以前からの課題

などの面倒な課題を抱えていて一筋縄ではいきそうにないのですが、NVEncC (QSVEncC/VCEEncC) 側で対応していただければゴールが見えてきそうです。

…かなり長文になってしまいました。
次々と無理なお願いをしてしまい心苦しいのですが、もし余裕があればお願いしたいです。

@rigaya
Copy link
Owner

rigaya commented May 2, 2021

現状と今後の開発予定について詳細にお知らせいただき、ありがとうございます。

1. input-retryについて

なるほど、標準出力をNVEncCで受ける形を検討されているのですね。--input-retryを作成したときは、NVEncCがUDPを受ける形を想定していたので、このような形態は考慮しておりませんでした。--input-retryの実装はUDPから流れてきていることを想定しているので、ファイルクローズ→ファイルオープンによる再初期化を行うようになっています( 527b62a )。

さらに標準出力に出力されたエラーメッセージを NVEncC が受け取ってしまい結果 NVEncC がフリーズするという最悪な事になってしまうので、今のところ --input-retry は機能していません…。

エラーメッセージだけの問題ならエラーメッセージは標準出力でなくエラー出力に出せばよいだけですが、それだけでは解決しなそうですね。ファイルオープンしたままの再初期化は難しく、すみませんがいまのところこれ以上の改善案が浮かびません。現状のように、お手数ですがTVRemotePlus側でのプロセス再起動が妥当な対策と思います。

2. timed_id3 の転送

ご指摘のようにtimed_id3はデータストリーム扱いのため、NVEncCでは--data-copy をご利用ください。また、NVEncC64_5.31beta4.zipではコーデックを選択してのコピーを可能としました。その場合は、--data-copy timed_id3 と指定してください。

3. arib-subtitle-timedmetadater について

developブランチを使用させていただき、arib-subtitle-timedmetadater を使用してテストしてみましたが、正常に処理できなさそうでした。私の使い方の問題かもしれませんが、どうも timed_id3 ストリームのタイムスタンプがずれてしまっているように見受けられました。

本日のNHKを処理したときのNVEncCの受け取ったパケットのタイムスタンプを出力しました。(NVEncC64_5.31beta4.zip--log-packetsを指定するとstream1.m3u8と同じフォルダにstream1.m3u8.packets.csvとして出力されます)

stream1.m3u8.packets.csv.txt の一部を抜粋します。一番右の列がタイムスタンプです。

stream  0,   mpeg2video, pts, 3655619432
stream 12,          epg, pts, Unknown
stream  1,          aac, pts, 3655604920
stream  0,   mpeg2video, pts, 3655613426
stream  1,          aac, pts, 3655606840
stream  3,    timed_id3, pts, 7950612296 <<<< 周りのタイムスタンプと比べると大きくずれている
stream  2, arib_caption, pts, 3655645000
stream  1,          aac, pts, 3655608760

このように、timed_id3 ストリームのみタイムスタンプが大きくずれてしまっており、正常に処理することが難しいです。ただ、すみません、原因や問題が発生する条件などはわからなかったです (なにか私のほうで導入ミスをしたかもしれませんが…)

4. 字幕mux時の8~10秒程度の遅延

これはffmpegに限らず、NVEncC等でも発生する遅延で、muxキューによる遅延と考えらます。

出力tsに映像と音声と字幕の各トラックをmuxして出力する際、各トラックの処理にかかる遅延はトラックごとに異なるので、データが常に同時にやってくるとは限りません。mux処理では、こうしたずれを調整し、各トラックのデータパケットの時刻(=タイムスタンプ)を同期して、同時刻のデータは近くに出力するよう調整する必要があります。

このとき、字幕データの扱いは難しく、継続的にデータが流れてくる映像や音声と異なり、字幕に関しては字幕のない時間というのが存在しますので、ある時刻に字幕データがあったりなかったりします。

mux処理では、字幕がない箇所では、字幕データがないことを確認するために、一定の時間(デフォルト=10秒分)映像や音声のデータをmuxキューにためて、その間字幕データがなければ字幕データがないと判断するようになっています。字幕を出力する際に10秒遅延が増加するのはこのためです。

今回のようなリアルタイムエンコードでは、10秒も待たなくてよいのではないかと思います。muxキューが待機する長さは下記オプションで調整可能です。下記では5秒にする例を示しました。

ffmpeg: -max_interleave_delta 5M
NVEncC: -m max_interleave_delta:5M

なお、あまり短くしすぎると、字幕や音声のタイミングずれにつながりますのでご注意いただければと思います。

@tsukumijima
Copy link
Author

tsukumijima commented May 2, 2021

1. input-retryについて

そうでしたか… わかりました。折角実装していただいたのに本当に申し訳ないです。

本来は些細な事で止まりがちなエンコーダーを監視するバックグラウンドプロセスを立ち上げて、その中でエンコーダーなどの出力を管理する(エンコーダープロセスの立ち上げ、ログの監視、エンコーダーが停止したら再起動、エンコード停止命令があればプロセスをKillする)のがベストだと思うのですが、元々軽い気持ちで試しに作ってみたツールに積み木のように後先考えず機能追加を繰り返していった結果コードが最悪な事になってしまっていて、そのような大幅な変更は現状難しいです。
現状では start コマンドでエンコードプロセスを PHP 側から非同期で開始し、終了するときはコマンド列に含まれる 8201 のような UDP 受信用のポート番号から該当のエンコーダーや TSTask を割り出して taskkill するという相当強引な実装になっています…。
今もリトライ機能こそありますが、m3u8 が30秒以内に更新されているかどうかだけで見ているのでエンコーダーが落ちた場合に把握できないなど、かなりアバウトです。

ただ、いつになるかは分かりませんが TVRemotePlus の後継ソフト(機能的には似たようなソフトだが、Python(PHP では Windows 固有の問題に対処する事が難しいため)で一から作り直しもっと使いやすくする)を作る計画を練っていて、その時にはちゃんと実装するつもりでいます。
今回の arib-subtitle-timedmetadater の導入に関しても、正直私自体は iOS 端末をあまり使っていないので対応するメリットは薄いのですが、受信→エンコード→配信周りはロケフリソフトの肝であり最も難しい部分なので、先にそのあたりの技術を概ね確立しておいて、後継ソフトの開発に着手したときに比較的スムーズに実装できるようにしたいという目論見もあったりします。

2. timed_id3 の転送

最新の develop ブランチにおいて NVEncC で --data-copy timed_id3 を使うようにしました。
ストリームのコピーに関しては特に問題は発生していないように感じます。

このあたりを調査している時に音声多重放送+字幕放送の場合に副音声で再生されてしまうケースがあったため、そのあたりのエンコードコマンドを調整しました(音声多重放送の番組を見ないので知らなかったけど、この件と関係なく前からだったかもしれない…)。
音声多重放送の副音声の方に切り替える機能は、需要がそこまでない上に余計にややこしくなるのが目に見えていたので今回は考えない事にします。後継ソフトの開発時には考慮したいですね。

3. arib-subtitle-timedmetadater について

前回のレスで報告した時に挙動確認を怠った私のミスなのですが、その時点での arib-subtitle-timedmetadater には不具合があり、ビット演算が JS だと丸められてしまう(?)とかで正しくない PTS が出力されてしまっていたみたいです。
最新の develop ブランチの更新された arib-subtitle-timedmetadater では正しい PTS が出力されるようになっているとのこと。

実際、ffmpeg でも字幕の PTS タイムスタンプが不正なため、字幕が映像より10秒近く早く描画されてしまう(音声と字幕のタイミングが一致しない)事がありました。arib-subtitle-timedmetadater の更新後は ffmpeg であっても、NVEncC でもあっても字幕が音声と同じタイミングで表示されていました。ぜひご確認いただければと思います。

…ただ、なぜか「NVEncC でのみ」字幕のタイミングがずれる番組を一部で確認しました。同じ番組を ffmpeg でエンコードすると 100% 問題なく再生できているので、NVEncC 側の処理に何かしら問題があるとみています。
ちょっと厄介なのが、全ての番組がそうなるわけではなく、むしろ NVEncC でエンコードした場合でも通常通り字幕が正しいタイミングで描画される番組の方が多そうだということです。ただ「稀」と言えるほど低頻度でもないので、NVEncC 側で対応できる問題であればぜひ改善していただければと思います。

arib-subtitle-timedmetadater に関しては monyone 氏いわくまだ不具合があるかもとの事で、実際に一部の字幕がなぜか描画されない(これに関しては ffmpeg・NVEncC 共通)などの問題が残されています。もしかすると arib-subtitle-timedmetadater 側の問題なのかもしれませんが…。

4. 字幕mux時の8~10秒程度の遅延

これはffmpegに限らず、NVEncC等でも発生する遅延で、muxキューによる遅延と考えらます。

mux処理では、字幕がない箇所では、字幕データがないことを確認するために、一定の時間(デフォルト=10秒分)映像や音声のデータをmuxキューにためて、その間字幕データがなければ字幕データがないと判断するようになっています。字幕を出力する際に10秒遅延が増加するのはこのためです。

てっきり ffmpeg のバグかと思っていましたが、そういうことだったんですね…!!確かに 10 秒ほど遅延するのも説明がつきます。納得です。

muxキューが待機する長さは下記オプションで調整可能です。下記では5秒にする例を示しました。

このオプションを ffmpeg と NVEncC それぞれに付与した所、字幕ありの場合でのエンコード開始までの時間が大幅に短縮されたように感じます。
まさかこのオプション1つで解決してしまうとはびっくりです。私だけでは ffmpeg の大量のオプションの中からこのオプションを見つけ出すことはできなかったので、本当に助かりました。

字幕あり (ID3ストリームをコピーするオプションを付与) の場合、字幕なし (ID3ストリームをコピーしない) の場合で比較してみましたが、このオプションを付与するだけで再生が始まるまでの差がほとんどなくなったように感じます。番組にもよるかもしれませんが。

あまり短くしすぎると、字幕や音声のタイミングずれにつながりますので

懸念していた音声のズレに関しては ffmpeg・NVEncC とも特になく普通に再生できたので、-max_interleave_delta 1M と待機時間を 1 秒に設定してみました。そもそも 5 秒に設定した時点で 5 秒以上の短縮効果が得られている(?)ようで、5M のときと顕著な差は確認できませんでした。
先ほどの NVEncC でのみ字幕のタイミングがずれる問題に関しては、-max_interleave_delta の値を大きくしたり小さくしたり、値自体を外したり、--input-probesize を外したりしても同じ結果だったので、この値を小さくしたのが原因という訳ではないと考えられます。


ということで、現在の arib-subtitle-timedmetadater 対応の課題は下記のようになります。

  • 現状 arib-subtitle-timedmetadater でパケットロスなく TSTask の TCP or UDP ストリームを受信できない(保留)
  • 一部の字幕が描画されず、描画されなかった字幕の前の字幕が次の字幕が描画されるまで延々と表示されたままになる
  • NVEncC でエンコードした場合のみ、字幕の描画タイミングがずれる番組が一部存在する

せっかくのGWに色々対応していただいていて感謝です。
また長くなってしまいましたが、それではよろしくお願いします。

@rigaya
Copy link
Owner

rigaya commented May 3, 2021

いろいろテスト、コメントいただきありがとうございます。muxキューによる遅延の件は、お役に立ててよかったです。

iOSはいろいろややこしそうですね…林檎がハード周りで独自仕様で面倒なのは知っていましたが、web周りでも独自仕様なのですね。


さて、こちらでも arib-subtitle-timedmetadater を更新させていただき、ご指摘いただいた NVEncC 使用時に字幕の描画タイミングがずれる問題について調査いたしました。原因は少し見えてきましたので、状況をご説明したのち1点質問させてください。

まず、原因としてはtimestampが認識できないtimed_id3のパケットが arib-subtitle-timedmetadater から送出されており、こうしたtimestampの設定されていないパケットを NVEncC が正常に処理できないためのようです。

本日テストしたときのパケット情報(stream1.m3u8.packets.csv.txt) から一部を抜粋します。

stream  1,   mpeg2video, pts, 7109486765
stream  2,          aac, pts, 7109463917
stream  2,          aac, pts, 7109465837
stream  1,   mpeg2video, pts, 7109498777
stream  2,          aac, pts, 7109467757
stream  1,   mpeg2video, pts, 7109492771
stream  2,          aac, pts, 7109469677
stream  2,          aac, pts, 7109471597
stream  4,    timed_id3, pts, 7109531841  <<<<<< こちらは問題なさそうだが
stream  3, arib_caption, pts, 7109531841
stream  1,   mpeg2video, pts, 7109495774
stream  2,          aac, pts, 7109473517
stream  1,   mpeg2video, pts, 7109507786
stream  1,   mpeg2video, pts, 7109501780
stream  2,          aac, pts, 7109475437
stream  2,          aac, pts, 7109477357
stream  4,    timed_id3, pts, Unknown     <<<<<< timestampが設定されていない
stream  1,   mpeg2video, pts, 7109504783
stream  2,          aac, pts, 7109479277

パケットのtimestampが認識できないのは、NVEncCだけの問題ということではなく、ffmpegでも同様でした。同じ番組に対して、ffmpegに-debug_tsを付けた時のログの一部を記載します。ist_index:3というのが、timed_id3ストリームを示します。ここで重要なのは pkt_pts / pkt_dts ですが、これがNOPTS になっており、timestampが認識できていないことを示します。

demuxer -> ist_index:3 type:data next_dts:30128911 next_dts_time:30.1289 next_pts:30128911 next_pts_time:30.1289 pkt_pts:NOPTS pkt_pts_time:NOPTS pkt_dts:NOPTS pkt_dts_time:NOPTS off:-79163067522 off_time:-79163.1
demuxer+ffmpeg -> ist_index:3 type:data pkt_pts:NOPTS pkt_pts_time:NOPTS pkt_dts:NOPTS pkt_dts_time:NOPTS off:-79163067522 off_time:-79163.1

ffmpegはこうした状況でも(どうやってか)処理を継続できるようですが、NVEncCではこうしたtimestampを認識できないパケットのところでパケットの時刻が判断できないために以降のtimed_id3パケットの処理が停止してしまい、字幕表示の大幅な遅延につながるようです。

こうした状況が発生する条件はよくわからないのですが、番組によってはこうしたtimestampの認識できないパケットが多発しておりました。

ここで質問させていただきたいのですが、このような timed_id3 ストリームにtimestampが設定されないことがあるのはこういうもの(仕様)でしょうか、それとも「まだ不具合があるかも」のほうでしょうか? このあたりの字幕の仕様があまり理解できておらずすみません。

意図されていないものでしたら、可能であれば修正を monyone 氏にお願いいただけますと幸いです。

また、そうではなく仕様ということですと、NVEncCにパケットのtimestampが設定されていない場合の例外処理を加えないといけないかなと思っています。ただ、その場合は周囲のtimestampから適当に補完するぐらいしか思いつかないので、若干本来の時刻からずれてしまうかもしれません。

よろしくお願いいたします。

@tsukumijima
Copy link
Author

tsukumijima commented May 3, 2021

ありがとうございます。

私の方で調べたところ、NVEncC で字幕がずれるのはどうやら日テレ・テレ朝・TBS・フジテレビのみのようで、局によるようでした。
monyone 氏に問い合わせした所、どうも timed_id3 の PID を subtitle の PID + 1 にしていたら、これが一部の局で文字スーパと被っていた(?)のが原因らしいです。改良版に更新してみた所、字幕のずれがなくなりました。ライブ放送等でのリアルタイム字幕だと元がずれてるので音声と一致しないのはしょうがないですが、それでも TVTest と表示タイミングが一致していたので、問題ないと思います。現在の develop ブランチで更新版を push しました。
一部の字幕が描画されない件もこの PTS がおかしくなるのに関連していたようで、更新と同時に直ったような気がします。しばらく運用してみないとなんとも言えませんが…。

ということで、あとは arib-subtitle-timedmetadater でパケットロスが発生して画面にブロックノイズが入ってしまう問題が解決すれば、ついに正式対応できそうです。
わざわざ長いことお付き合いいただきありがとうございました!また何かあれば報告します。

@rigaya
Copy link
Owner

rigaya commented May 3, 2021

字幕がずれる件、確認いただきありがとうございました。問題が解決したとのことで安心しました。

それでは今後、今回NVEncCに行った更新をQSVEncC/VCEEncCに展開して、それぞれで同様に使えるようにしていきたいと思います。

@tsukumijima
Copy link
Author

ありがとうございます!トラブル続きで諦めかけていましたが、なんとか使える状態に持って行けて私も一安心です。

@monyone
Copy link

monyone commented May 3, 2021

@rigaya
様々な対応をしていただき、本当にありがとうございます。
arib-subtitile-timedmetadater の作者の monyone と申します。
この度は、aribb24.js のバージョンアップに伴う iOS 対応で rigaya さんにご迷惑おかけして申し訳ありません。
arib-subtitle-timedmetadater のバグで貴重なお時間をお取りしてしまいした。
何度頭を下げても足りないくらいです。本当にありがとうございました。

PTS の値がずれているというのは、JavaScript では基本的に double で数値を扱うのですが
ビット演算の場合は、符号付き 32bit 整数として評価してから bit 演算するという仕様があったのを見落としていたためです。
PTS は 33bit なので、& を取ったり、シフトしたりすると符号付き 32 bit として扱われます。
このため、PTS がおかしな負の値になる場合があり、この時に 33bit 目が常に立っていて、
本来 PTS の 33bit 目が立っていない番組では合わなくなってしまいました。
このような不手際を発見して頂き、本当にありがとうございました。こちらがプログラマとして非常に未熟でした。

noPTS が混ざっていたのは、前者で PMT の再構成の際に ARIB字幕の PID+ 1 を timed-id3 に無確認で割り当てたためです。
一部の局は、字幕と文字スーパーの PID が隣接していないのですが、そうなってない局があるというのを知りませんでした。
同じ PID では文字スーパーが入るため、文字スーパーは PTS/DTS が無いので、noPTS になります。
この点、オプションなどを新設して頂き、バグ究明の役に非常に立ちましたので、非常にありがたかったです。
(ただ、NCEnvC が自分の環境では動かす環境がないため、ffmpeg のオプションで調査いたしました)
この件も、調査せずに数値を決め打ちした点が、非常に思慮が足りなかったため、反省しています。

表示されない場合があったのは、timed-id3 PES の private_data に TS パケットに合うようパディングを入れていたためです。
private_data に値を入れるとどうも 5byte (PTS) 分がずれたりずれなかったりして安定しないようです。
これは、id3 自体に TS パケットで必要な分の無効なバイト列を追加することで、今の所対処出来ている気がします。
問題が ffmpeg (libavformat) の問題なのか、hls.js / Safari native の問題かはわかっていません。
(気がしますと書いているのは、確定で 5byte ずれるようになったので、id3 の先頭に 5byte 無効なデータを入れてるためです)
ツールが悪いのではないか調査頂いたようでして、この件も申し訳ありません。
自分の仕様を読む力が足りない事、ffmpeg や hls.js, Safari の気持ちが分からない未熟さを猛省しております。

最後に、一応、なぜ、このようなものが必要になっているかについて、説明いたします。
なぜ作っていて利用したいのか、という点の説明がないと、作業して頂いた理由が分からないと思いますので。

arib-subtitle-timedmetadater とは

このツールは名前の通り、ARIB 字幕を timed-id3 に重畳しなおすツールです。
ARIB字幕を様々なプラットフォームで Apple が定めた HLS の仕様内で重畳するために作っています。

このツールの目的

ARIB字幕と同じ PTS で TXXX フレームに ARIB 字幕のバイナリデータを base64 して mpegts に重畳することで
Apple の HLS の規格に沿う in-band なメタデータ伝送で ARIB 字幕を伝送するというのが、このツールの目的になります。
これにより、iOS Safari などがサポートする標準的な in-band メタデータ伝送で ARIB 字幕を載せる事が可能になります。

このツールの利点

このツールで timed-id3 に ARIB 字幕を変換する利点は以下の通りです。

  • ffmpeg (libavformet) で解釈可能なため、独自の改造が要らずに mpegts を HLS に変換可能
  • 様々な映像再生フレームワークでの対応が既に存在する
    • hls.js, video.js, shaka-player
    • Safari, iOS Safari のネイティブのプレイヤー
    • Android の ExoPlayer
    • iOS の AVPlayer

このため、非MSE環境、様々な OS であっても、このツールで変換すれば原理的にはクライアントは受け取る事ができます。

このツールの動作

以下の機能から構成されています。

  • PMT を再編集して timed_id3 を追加し、CRC などを変更した PMT を TSパケットに分解して remux します。
  • 字幕PESが来た際に、同じ PTS で TXXX に 字幕PESを base64 を入れた id3 PES をTSパケットに分解して remux します。

つまるところ、PMT (Seciton) と 字幕 (PES) を置き換えて remux する、という動作をしています。
Section, PES をばらして再編集して、再編集したものを TS パケットに戻して重畳しなおす簡単なプログラムです。

このツールの記述言語

現時点では node.js 製の物をつくっております。node.js の Transform で変換処理を pipe として記述できます。
そのうち、ネイティブ対応のできる Go か Rust でのコマンドラインプログラムを作る事を考えています。

このツールの利用方法

ffmpeg が現時点で arib subtitle の descriptor を落としてしまうため、ffmpeg より前段において動作する事を想定しています。

(チューナー) | arib-subtitle-timedmetadater | ffmpeg (HLS 変換) といった具合です。
一応、UDP/TCP 入力は入れていますが、UDP/TCP 出力は入れていません。

node.js 製なので、node.js であれば変換部分だけをプログラム内で利用可能です。

@rigaya
Copy link
Owner

rigaya commented May 4, 2021

@tsukumijima
こちらこそ、いろいろ要望・コメントいただき、ありがとうございました。

普段のNVEncCの実装では、処理遅延は許容してスループットを最大化する方向に振ることが多いのですが、今回は普段あまり意識しない処理遅延などについて注目したり、またはffmpegと挙動を比較したりしたことでいろいろ発見もあり、TVRemotePlusで使用する際のNVEncCの挙動改善につなげられたかと思います。

@monyone
arib-subtitile-timedmetadater を作成された背景と目的、ならびに今回修正いただいた内容について、ご説明くださりありがとうございます。

今回PTSに関して発生していた現象についても理解できました。
やはりプログラムが意図しない動作をしてしまったり、想定外の入力が来たりするというのは、どうしてもあるものだと思いますので、今回の私の行った調査がそうした点の発見の一助となっていましたら幸いです。

@xqq
Copy link

xqq commented May 4, 2021

@rigaya 関係者外から失礼いたします。要望だと思いますが、PTS 無しのパケットを支援することは可能でしょうか。

前述の通り、ARIB の文字スーパーは受信機が受信した後、すぐ表示するように想定されているため、mpegts のストリームで private_stream_2 を利用する、timestamp の無い Private PES で伝送されています。

背景としては、FFmpeg から出力された mpegts のストリームを mpegts.js + aribb24.js によって低遅延再生する際に、ARIB 字幕とARIB 文字スーパーを同時に表示できるようにしていました。https://twitter.com/magicxqq/status/1381786681926246402

EPGStation では既に mpegts.js が導入され、文字スーパーもまもなく対応するように進んでいます。@tsukumijima によると、TVRemotePlus も将来に mpegts.js を導入する予定があると聞いています。

FFmpeg の場合は、文字スーパーのパケットに対し warning が出ていますが、エラーになっていないので無事抽出できています。

もし NVEnc も PTS 無しのパケットを対応できるようになれば、文字スーパーの表示に大変助かると思います。

@rigaya
Copy link
Owner

rigaya commented May 6, 2021

@xqq PTS 無しのパケットを処理できたほうが良いこと、承知しました。

次回の更新では、データストリームについてPTS 無しのパケットをそのまま転送できるよう、変更したいと思います。

@rigaya
Copy link
Owner

rigaya commented May 8, 2021

NVEnc 5.31に更新し、要望いただいたデータストリームについてPTS 無しのパケットについて、そのまま転送できるよう変更しました。

文字スーパーも含めて転送する場合は、--data-copy timed_id3でなく、単に--data-copyとしていただければ転送されるはずですので、将来的にもし文字スーパーへ対応される際はご活用ください。

@tsukumijima
Copy link
Author

ありがとうございます!!使わせていただきます。

@tsukumijima
Copy link
Author

(本来は QSVEncC の方に書くべきでしょうが、話題が同じなのでここで)
NVEncC 5.31 と同等の機能が実装された QSVEncC 5.01 を試したのですが、5.00 の大型更新によるものなのか、私の環境だとエラーが出て、1セグメントだけエンコードした後すぐエラー終了してしまいます…。

1秒だけですが字幕は表示できていたのでそのあたりは問題ありません。字幕あり/なしは関係ありませんでした。
エラーからして、そもそも QSV のデバイス自体がうまく使えていない?ような気がします。

以下に --log-level debug でデバッグ出力したログを記します(かなり長いです)。

--------------------------------------------------------------------------------
stream1.m3u8
--------------------------------------------------------------------------------
QSVEncC    5.01 (x64)
OS        Windows 7 x64 (7601) [CP932]
CPU Info  Intel Core i7-2600K @ 3.40GHz [TB: 3.44GHz] (4C/8T) <SandyBridge>
GPU Info   850-1350MHz
Locale    Japanese_Japan.932
InitSessionInitParam: Success.
D3D9Device: Init...
D3D9Device: Direct3DCreate9Ex Success.
D3D9Device: Set Init() m_D3DPresentPrm.BackBuffer.
D3D9Device: CreateDeviceEx Success.
D3D9Device: DXVA2CreateDirect3DDeviceManager9 Success.
D3D9Device: ResetDevice Success.
D3D9Device: Closed.
avhw reader selected.
InitInput: input selected : 7.
avqsv: select audio track #1, codec aacbitrate 192
avqsv: select audio track all, codec 
avqsv: set probesize: 921.600K
avqsv: set analyzeduration: 0.67 sec
avqsv: input source set to stdin.
[mpegts @ 00000000004bb4c0] stream=1 stream_type=2 pid=100 prog_reg_desc=
[mpegts @ 00000000004bb4c0] stream=2 stream_type=f pid=110 prog_reg_desc=
[mpegts @ 00000000004bb4c0] stream=3 stream_type=6 pid=130 prog_reg_desc=
[mpegts @ 00000000004bb4c0] stream=4 stream_type=15 pid=131 prog_reg_desc=
[mpegts @ 00000000004bb4c0] stream=5 stream_type=6 pid=138 prog_reg_desc=
[mpegts @ 00000000004bb4c0] stream=6 stream_type=d pid=140 prog_reg_desc=
[mpegts @ 00000000004bb4c0] stream=7 stream_type=d pid=160 prog_reg_desc=
[mpegts @ 00000000004bb4c0] stream=8 stream_type=d pid=161 prog_reg_desc=
[mpegts @ 00000000004bb4c0] stream=9 stream_type=d pid=162 prog_reg_desc=
[mpegts @ 00000000004bb4c0] stream=10 stream_type=d pid=170 prog_reg_desc=
[mpegts @ 00000000004bb4c0] stream=11 stream_type=d pid=171 prog_reg_desc=
[mpegts @ 00000000004bb4c0] stream=12 stream_type=d pid=172 prog_reg_desc=
avqsv: opened file "pipe:0".
[mpegts @ 00000000004bb4c0] Before avformat_find_stream_info() pos: 0 bytes read:921600 seeks:0 nb_streams:13
[mpegts @ 00000000004bb4c0] parser not found for codec arib_caption, packets or times may be invalid.
[libaribb24 @ 00000000082d9a00] arib parser was created
[libaribb24 @ 00000000082d9a00] arib decoder was created
[mpegts @ 00000000004bb4c0] parser not found for codec timed_id3, packets or times may be invalid.
[mpegts @ 00000000004bb4c0] parser not found for codec none, packets or times may be invalid.
[mpegts @ 00000000004bb4c0] parser not found for codec none, packets or times may be invalid.
[mpegts @ 00000000004bb4c0] parser not found for codec none, packets or times may be invalid.
[mpegts @ 00000000004bb4c0] parser not found for codec none, packets or times may be invalid.
[mpegts @ 00000000004bb4c0] parser not found for codec none, packets or times may be invalid.
[mpegts @ 00000000004bb4c0] parser not found for codec none, packets or times may be invalid.
[mpegts @ 00000000004bb4c0] parser not found for codec none, packets or times may be invalid.
[mpegts @ 00000000004bb4c0] probing stream 2 pp:2500
[mpegts @ 00000000004bb4c0] Probe with size=680, packets=1 detected flac with score=13
[mpegts @ 00000000004bb4c0] probing stream 2 pp:2499
[mpegts @ 00000000004bb4c0] Probe with size=1276, packets=2 detected flac with score=13
[mpegts @ 00000000004bb4c0] probing stream 2 pp:2498
[mpegts @ 00000000004bb4c0] probing stream 2 pp:2497
[mpegts @ 00000000004bb4c0] Probe with size=2490, packets=4 detected aac with score=51
[mpegts @ 00000000004bb4c0] probed stream 2
[mpeg2video @ 00000000082d5740] Invalid frame dimensions 0x0.
[mpeg2video @ 00000000082d5740] Format yuv420p chosen by get_format().
[mpegts @ 00000000004bb4c0] probing stream 5 pp:2500
[mpegts @ 00000000004bb4c0] probing stream 5 pp:2499
[mpegts @ 00000000004bb4c0] probing stream 5 pp:2498
[mpegts @ 00000000004bb4c0] probing stream 5 pp:2497
[mpegts @ 00000000004bb4c0] probed stream 5
[mpegts @ 00000000004bb4c0] parser not found for codec bin_data, packets or times may be invalid.
[mpegts @ 00000000004bb4c0] Probe buffer size limit of 921600 bytes reached
[mpegts @ 00000000004bb4c0] Could not find codec parameters for stream 6 (Unknown: none ([13][0][0][0] / 0x000D)): unknown codec
Consider increasing the value for the 'analyzeduration' (670000) and 'probesize' (921600) options
[mpegts @ 00000000004bb4c0] Could not find codec parameters for stream 7 (Unknown: none ([13][0][0][0] / 0x000D)): unknown codec
Consider increasing the value for the 'analyzeduration' (670000) and 'probesize' (921600) options
[mpegts @ 00000000004bb4c0] Could not find codec parameters for stream 8 (Unknown: none ([13][0][0][0] / 0x000D)): unknown codec
Consider increasing the value for the 'analyzeduration' (670000) and 'probesize' (921600) options
[mpegts @ 00000000004bb4c0] Could not find codec parameters for stream 9 (Unknown: none ([13][0][0][0] / 0x000D)): unknown codec
Consider increasing the value for the 'analyzeduration' (670000) and 'probesize' (921600) options
[mpegts @ 00000000004bb4c0] Could not find codec parameters for stream 10 (Unknown: none ([13][0][0][0] / 0x000D)): unknown codec
Consider increasing the value for the 'analyzeduration' (670000) and 'probesize' (921600) options
[mpegts @ 00000000004bb4c0] Could not find codec parameters for stream 11 (Unknown: none ([13][0][0][0] / 0x000D)): unknown codec
Consider increasing the value for the 'analyzeduration' (670000) and 'probesize' (921600) options
[mpegts @ 00000000004bb4c0] Could not find codec parameters for stream 12 (Unknown: none ([13][0][0][0] / 0x000D)): unknown codec
Consider increasing the value for the 'analyzeduration' (670000) and 'probesize' (921600) options
[libaribb24 @ 00000000082d9a00] arib decoder destroyed
[libaribb24 @ 00000000082d9a00] arib parser was destroyed
[mpegts @ 00000000004bb4c0] After avformat_find_stream_info() pos: 3127192 bytes read:3129344 seeks:0 frames:60
avqsv: got stream information.
Input #0, mpegts, from 'pipe:0':
  Duration: N/A, start: 17386.630311, bitrate: N/A
  Program 1024 
    Metadata:
      service_name    : ホネヒAm9gアソEl5~
      service_provider: 
    Stream #0:1[0x100], 17, 1/90000: Video: mpeg2video (Main), 1 reference frame ([2][0][0][0] / 0x0002), yuv420p(tv, bt709, top first, left), 1440x1080 [SAR 4:3 DAR 16:9], 0/1, 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc
    Side data:
      cpb: bitrate max/min/avg: 20000000/0/0 buffer size: 9781248 vbv_delay: N/A
    Stream #0:2[0x110], 34, 1/90000: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 250 kb/s
    Stream #0:3[0x130], 0, 1/90000: Subtitle: arib_caption (Profile A) ([6][0][0][0] / 0x0006)
    Stream #0:4[0x131], 0, 1/90000: Data: timed_id3 (ID3  / 0x20334449), 0/1
    Stream #0:5[0x138], 1, 1/90000: Data: bin_data ([6][0][0][0] / 0x0006), 0/1
    Stream #0:6[0x140], 0, 1/90000: Unknown: none ([13][0][0][0] / 0x000D)
    Stream #0:7[0x160], 0, 1/90000: Unknown: none ([13][0][0][0] / 0x000D)
    Stream #0:8[0x161], 0, 1/90000: Unknown: none ([13][0][0][0] / 0x000D)
    Stream #0:9[0x162], 0, 1/90000: Unknown: none ([13][0][0][0] / 0x000D)
    Stream #0:10[0x170], 0, 1/90000: Unknown: none ([13][0][0][0] / 0x000D)
    Stream #0:11[0x171], 0, 1/90000: Unknown: none ([13][0][0][0] / 0x000D)
    Stream #0:12[0x172], 0, 1/90000: Unknown: none ([13][0][0][0] / 0x000D)
  Program 1025 
    Metadata:
      service_name    : ホネヒAm9gイソEl5~
      service_provider: 
  Program 1408 
    Metadata:
      service_name    : ホネヒ7HBSヌソEl5~
      service_provider: 
  No Program
    Stream #0:0[0x12], 8, 1/90000: Data: epg, 0/1
avqsv: found video stream, stream idx 1
avqsv: found audio stream, stream idx 2, trackID 1.0, aac, frame_size 1024, timebase 1/90000, delay 0 ms
avqsv: found data stream, stream idx 4, trackID 1.0, timed_id3, frame_size 0, timebase 1/90000, delay 0 ms
avqsv: use video stream #1 for input, codec mpeg2video, stream time_base 1/90000, codec_timebase 1001/60000.
avqsv: hdr10plusMetadataCopy: off
avqsv: can be decoded by qsv.
avqsv: start predecode.
avqsv: GetHeader: 162 bytes.
avqsv: initialized mpeg2video codec context for parser: time_base: 1001/60000, pkt_timebase: 1/90000.
avqsv: fps decoder 30000/1001, invalid: false
avqsv: maxCheckFrames 1, maxCheckSec: 1.000e+99
avqsv: found first key frame: timestamp 1564821290 (17386.9), offset 1
avqsv: read 1 packets.
avqsv: checking 0 frame samples.
avqsv: final AvgFps (round): 30000/1001
avqsv: checking for stream #2
avqsv: adjust trim by offset 1.
avqsv: avqsv: MPEG2, 1440x1080, 30000/1001 fps
avqsv: streamFirstKeyPts: 1564821290
avqsv: matrix:bt709,colorprim:bt709,transfer:bt709,range:limited,chromaloc:left
avqsv: sar 4:3, bitdepth 8
initReaders: Success.
Input: trim options
0-2147483647  (offset: 1)
timestamp check: 0x1
InitInput: Success.
CheckParam: Success.
InitSession: Start initilaizing... memType: d3d11+d3d9
InitSession: OS is Win7, do not check for d3d11 mode.
InitSession: initialized using d3d9 memory.
InitSession: mfx lib version: 1.4, impl 0x202
InitSession: Success.
CreateAllocator: MemType: d3d9
HWDevice: d3d9 - initializing...
D3D9Device: Init...
D3D9Device: Direct3DCreate9Ex Success.
D3D9Device: Set Init() m_D3DPresentPrm.BackBuffer.
D3D9Device: CreateDeviceEx Success.
D3D9Device: DXVA2CreateDirect3DDeviceManager9 Success.
D3D9Device: ResetDevice Success.
HWDevice: initializing device success.
CreateAllocator: CreateHWDevice success.
CreateAllocator: HW device GetHandle success.
CreateAllocator: set HW device handle to encode session.
CreateAllocator: Create d3d9 allocator.
CreateAllocator: d3d9...
CreateAllocator: frame allocator set to session.
CreateAllocator: frame allocator initialized.
Skip OpenCL init as OpenCL is not supported in SandyBridge platform.
InitMfxDecParams: QSVDec prm: MPEG2, Level 4, Profile 64
InitMfxDecParams: Frame: nv12, 1440x1088p [0,0,1440,1080] 4:3
InitMfxDecParams: color format nv12, chroma yuv420, bitdepth 0, shift 0, picstruct unknown
MFXVPP: InitSession: mfx lib version: 1.4, impl 0x202
MFXVPP: Got HW device handle: 00000000083D3A38.
MFXVPP: set HW device handle 00000000083D3A38 to encode session.
MFXVPP: SetMFXFrameIn: vpp input frame 1440x1088 (0,0,1440,1080)
MFXVPP: SetMFXFrameIn: vpp input color format nv12, chroma yuv420, bitdepth 0, shift 0, picstruct tff
MFXVPP: InitMfxVppParams: vpp deinterlace enabled.
MFXVPP: SetMFXFrameOut: vpp output frame 1440x1088 (0,0,1440,1080)
MFXVPP: SetMFXFrameOut: vpp output color format nv12, chroma yuv420, bitdepth 0, shift 0, picstruct prog
MFXVPP: SetMFXFrameOut: set all vpp params.
MFXVPP: CreateVppExtBuffers: set DoNotUse PAMP.
MFXVPP: CreateVppExtBuffers: set DoNotUse DET .
MFXVPP: CreateVppExtBuffers: set DoNotUse DNIS.
MFXVPP: CreateVppExtBuffers: set DoNotUse SCLY.
MFXVPP: Vpp SetParam success.
encodeBitDepth: 8, codecMaxQP: 51.
Detected avaliable features for hw API v1.4, H.264/AVC, Bitrate Mode - VBR
RC mode       o    
10bit depth   x    
Fixed Func    x    
Interlace     o    
VUI info      o    
Trellis       x    
Adaptive_I    x    
Adaptive_B    x    
WeightP       x    
WeightB       x    
FadeDetect    x    
B_Pyramid     x    
 +ManyBframes x    
PyramQPOffset x    
MBBRC         x    
ExtBRC        x    
Adaptive_LTR  x    
LA Quality    x    
QP Min/Max    x    
IntraRefresh  x    
No Deblock    x    
No GPB        x    
Windowed BRC  x    
PerMBQP(CQP)  x    
DirectBiasAdj x    
MVCostScaling x    
SAO           x    
Max CTU Size  x    
TSkip         x    


Min/Max QP is not supported on current platform, disabled.
InitMfxEncParams: Output FPS 30000/1001
InitMfxEncParams: set ext param CDOP.
InitMfxEncParams: enc input frame 1440x1088 (0,0,1440,1080)
InitMfxEncParams: enc input color format nv12, chroma yuv420, bitdepth 8, shift 0, picstruct prog
InitMfxEncParams: set all enc params.
Performace Monitor: none
Performace Plot   : none
Output: Using avformat writer.
Output: Audio/Subtitle muxing enabled.
Output: CopyAll=true
Output: Added audio track#4097 (stream idx 2) for mux, bitrate 192, codec: aac  , bsf: <none>, disposition: <copy>, metadata <copy>
Output: Added data track#8193 (stream idx 4) for mux, bitrate 0, codec: copy  , bsf: <none>, disposition: <copy>, metadata <copy>
avout: output filename: "stream1.m3u8"
avout: Opened file "stream1.m3u8".
avout: output video stream fps: 30000/1001
avout: opened video avcodec
avout: output video stream timebase: 1001/120000
avout: bDtsUnavailable: on
avout: Initialized video output.
avout: start initializing audio ouput...
avout: output stream index 2, trackId 1.0
avout: samplerate 48000, stream pkt_timebase 1/90000
avout: Audio Decoder opened
avout: Audio Decode Info: aac, 2ch[0x03], 48.0kHz, fltp, 1/90000 dual_mono_mode=main
avout: found encoder for codec aac selected for audio track 1
avout: Audio Encoder Param: aac, 2ch[0x03], 48.0kHz, fltp, -99 (default), 1/48000, default
[Parsed_volume_0 @ 00000000004bbec0] Setting 'volume' to value '2'
[Parsed_aformat_1 @ 00000000084bf580] Setting 'sample_fmts' to value 'fltp'
[Parsed_aformat_1 @ 00000000084bf580] Setting 'sample_rates' to value '48000'
[Parsed_aformat_1 @ 00000000084bf580] Setting 'channel_layouts' to value '0x3'
avout: Parsed filter: volume=2
[in_track_1.0 @ 0000000005c5e6c0] Setting 'time_base' to value '1/48000'
[in_track_1.0 @ 0000000005c5e6c0] Setting 'sample_rate' to value '48000'
[in_track_1.0 @ 0000000005c5e6c0] Setting 'sample_fmt' to value 'fltp'
[in_track_1.0 @ 0000000005c5e6c0] Setting 'channel_layout' to value '0x3'
[in_track_1.0 @ 0000000005c5e6c0] tb:1/48000 samplefmt:fltp samplerate:48000 chlayout:0x3
avout: filter linked with src buffer.
avout: filter linked with sink buffer.
[AVFilterGraph @ 00000000083d1f80] query_formats: 4 queried, 9 merged, 0 already done, 0 delayed
[in_track_1.0 @ 0000000005c5e6c0] tb:0.000021 sample_rate:48000.000000 nb_channels:2.000000
[Parsed_volume_0 @ 00000000004bbec0] n:nan t:nan pts:nan precision:float volume:2.000000 volume_dB:6.020600
avout: filter config done, filter ready.
avout: Copy Disposition: unset
avout: Initialized audio output - #0: track 1, substream 0.
avout: start initializing data ouput...
avout: output stream index 4, pkt_timebase 1/90000, trackId 1
avout: Copy Disposition: unset
avout: Initialized data output - 0.
avout: set mux opt: hls_time = 1.
avout: set mux opt: hls_list_size = 12.
avout: set mux opt: hls_allow_cache = 0.
avout: set mux opt: hls_flags = delete_segments.
avout: set mux opt: hls_segment_filename = stream1-05082315_1071534888.ts.
avout: set mux opt: max_interleave_delta = 1M.
avout: avwriter: h264,
avout:  #1:aac/stereo:stereo:volume -> aac/stereo/192kbps, data#1
avout:  => hls
Output: Initialized avformat writer.
pipeline element count: 3
async depth automatically set to 6
timeBeginPeriod(1)
ResetMFXComponents: Start...
ResetMFXComponents: Enc closed.
MFXVPP: Vpp Closed.
ResetMFXComponents: Vpp closed.
ResetMFXComponents: Dec closed.
MFXVPP: InitSession: mfx lib version: 1.4, impl 0x202
MFXVPP: Got HW device handle: 00000000083D3A38.
MFXVPP: set HW device handle 00000000083D3A38 to encode session.
Created pipeline.
  MFXDEC
  AUDIO
  TRIM
  CHECKPTS
  MFXVPP
  MFXENCODE

allocFrames: m_nAsyncDepth - 6 frames
AllocFrames: MFXDEC-CHECKPTS
MFXDEC:   MFXDEC required buffer: 21 [external,dxvadec,dec]
CHECKPTS:   CHECKPTS required buffer in: 5 [external,dxvaproc,vppin], out 21 [external,dxvaproc,vppout]
AllocFrames: MFXDEC-CHECKPTS, type: external,dxvadec,dec, nv12 1440x1088 [0,0,1440,1080], request 33 frames
MFXDEC: allocWorkSurfaces:   cleared old surfaces: no error..
QSVAllocator: FrameAlloc: external,dxvadec,dec, 33 frames.
QSVAllocator: Allocate type external.
QSVAllocatorD3D9::AllocImpl select DXVA2_VideoDecoderRenderTarget.
QSVAllocatorD3D9::AllocImpl GetVideoService Success.
QSVAllocatorD3D9::AllocImpl allocate surface...
QSVAllocatorD3D9::AllocImpl Success.
QSVAllocator: FrameAlloc success.
MFXDEC: allocWorkSurfaces:   allocated 33 frames.
AllocFrames: CHECKPTS-MFXVPP
CHECKPTS:   CHECKPTS required buffer in: 5 [external,dxvaproc,vppin], out 21 [external,dxvaproc,vppout]
MFXVPP:   MFXVPP required buffer in: 7 [external,dxvaproc,vppin], out 5 [external,dxvaproc,vppout]
AllocFrames: CHECKPTS-MFXVPP, type: external,dxvaproc,vppin, nv12 1440x1088 [0,0,1440,1080], request 35 frames
CHECKPTS: allocWorkSurfaces:   cleared old surfaces: no error..
QSVAllocator: FrameAlloc: external,dxvaproc,vppin, 35 frames.
QSVAllocator: Allocate type internal.
QSVAllocatorD3D9::AllocImpl select DXVA2_VideoProcessorRenderTarget.
QSVAllocatorD3D9::AllocImpl GetVideoService Success.
QSVAllocatorD3D9::AllocImpl allocate surface...
QSVAllocatorD3D9::AllocImpl Success.
QSVAllocator: FrameAlloc success.
CHECKPTS: allocWorkSurfaces:   allocated 35 frames.
AllocFrames: MFXVPP-MFXENCODE
MFXVPP:   MFXVPP required buffer in: 7 [external,dxvaproc,vppin], out 5 [external,dxvaproc,vppout]
MFXENCODE:   MFXENCODE required buffer: 6 [external,dxvadec,enc]
AllocFrames: MFXVPP-MFXENCODE, type: external,dxvadec,enc,vppout, nv12 1440x1088 [0,0,1440,1080], request 18 frames
MFXVPP: allocWorkSurfaces:   cleared old surfaces: no error..
QSVAllocator: FrameAlloc: external,dxvadec,enc,vppout, 18 frames.
QSVAllocator: Allocate type internal.
QSVAllocatorD3D9::AllocImpl select DXVA2_VideoDecoderRenderTarget.
QSVAllocatorD3D9::AllocImpl GetVideoService Success.
QSVAllocatorD3D9::AllocImpl allocate surface...
QSVAllocatorD3D9::AllocImpl Success.
QSVAllocator: FrameAlloc success.
MFXVPP: allocWorkSurfaces:   allocated 18 frames.
ResetMFXComponents: there might be error below, but it might be internal error which could be ignored.
QSVAllocator: FrameAlloc: internal,dxvadec,enc, 5 frames.
QSVAllocator: Allocate type internal.
QSVAllocatorD3D9::AllocImpl select DXVA2_VideoDecoderRenderTarget.
QSVAllocatorD3D9::AllocImpl GetVideoService Success.
QSVAllocatorD3D9::AllocImpl allocate surface...
QSVAllocatorD3D9::AllocImpl Success.
QSVAllocator: FrameAlloc success.
QSVAllocator: FrameAlloc: internal,dxvadec,enc, 3 frames.
QSVAllocator: Allocate type internal.
QSVAllocatorD3D9::AllocImpl select DXVA2_VideoDecoderRenderTarget.
QSVAllocatorD3D9::AllocImpl GetVideoService Success.
QSVAllocatorD3D9::AllocImpl allocate surface...
QSVAllocatorD3D9::AllocImpl Success.
QSVAllocator: FrameAlloc success.
Encoder initialized.
MFXVPP: There might be error below, but it might be internal error which could be ignored.
QSVAllocator: FrameAlloc: internal,system,vppin, 1 frames.
QSVAllocator: Failed CheckRequestType: undeveloped feature.
QSVAllocator: FrameAlloc: internal,system,vppin, 1 frames.
QSVAllocator: Failed CheckRequestType: undeveloped feature.
QSVAllocator: FrameAlloc: internal,system,vppin, 7 frames.
QSVAllocator: Failed CheckRequestType: undeveloped feature.
QSVAllocator: FrameAlloc: internal,system,vppout, 5 frames.
QSVAllocator: Failed CheckRequestType: undeveloped feature.
MFXVPP: Vpp initialized.
MFXVPP: There might be error below, but it might be internal error which could be ignored.
QSVAllocator: FrameAlloc: internal,system,vppin, 5 frames.
QSVAllocator: Failed CheckRequestType: undeveloped feature.
QSVAllocator: FrameAlloc: internal,system,vppout, 5 frames.
QSVAllocator: Failed CheckRequestType: undeveloped feature.
MFXVPP: Vpp initialized.
ResetMFXComponents: there might be error below, but it might be internal error which could be ignored.
QSVAllocator: FrameAlloc: external,dxvadec,dec, 21 frames.
QSVAllocator: Allocate type external.
QSVAllocator: FrameAlloc success.
Dec initialized.
vidprm.AsyncDepth value changed 0 -> 3 by driver
vidprm.mfx.BRCParamMultiplier value changed 0 -> 1 by driver
vidprm.mfx.CodecLevel value changed auto -> 4 by driver
vidprm.mfx.NumSlice value changed 0 -> 1 by driver
vidprm.mfx.NumRefFrame value changed 0 -> 2 by driver
cop.RateDistortionOpt value changed auto -> off by driver
cop.EndOfSequence value changed auto -> off by driver
cop.CAVLC value changed auto -> off by driver
cop.ViewOutput value changed auto -> off by driver
cop.VuiVclHrdParameters value changed auto -> off by driver
cop.RefPicListReordering value changed auto -> off by driver
cop.ResetRefList value changed auto -> off by driver
cop.MaxDecFrameBuffering value changed 0 -> 2 by driver
cop.EndOfStream value changed auto -> off by driver
cop.RefPicMarkRep value changed auto -> off by driver
cop.FieldOutput value changed auto -> off by driver
cop.NalHrdConformance value changed auto -> on by driver
cop.SingleSeiNalUnit value changed auto -> on by driver
cop.VuiNalHrdParameters value changed auto -> on by driver
QSVEncC (x64) 5.01 (r2279) by rigaya, May  8 2021 19:58:15 (VC 1928/Win/avx2)
OS             Windows 7 x64 (7601) [CP932]
CPU Info       Intel Core i7-2600K @ 3.40GHz [TB: 3.44GHz] (4C/8T) <SandyBridge>
GPU Info        850-1350MHz
Media SDK      QuickSyncVideo (hardware encoder), 1st GPU, API v1.4
Async Depth    6 frames
Buffer Memory  d3d9, 86 work buffer
Input Info     avqsv: MPEG2, 1440x1080, 30000/1001 fps
VPP            Deinterlace (normal)
AVSync         forcecfr
Output         H.264/AVC(yuv420) Main @ Level 4
               1440x1080p 4:3 29.970fps (30000/1001fps)
               avwriter: h264,
                #1:aac/stereo:stereo:volume -> aac/stereo/192kbps, data#1
                => hls
Target usage   7 - fastest
Encode Mode    Bitrate Mode - VBR
Bitrate        6500 kbps
Max Bitrate    15000 kbps
VBV Bufsize    30000 kbps
Ref frames     2 frames
Bframes        3 frames
Max GOP Length 30 frames
Encode Thread: RunEncode2...
MFXDEC: DecodeFrameAsync: removing 11412 bytes from input bitstream not read by decoder.
CHECKPTS: Big Gap was found between 2 frames, avsync might be corrupted.
[mpegts @ 000000000448a140] service 1 using PCR in pid=256, pcr_period=0ms
[mpegts @ 000000000448a140] muxrate VBR, sdt every 1073741822000 ms, pat/pmt every 1073741822000 ms
Output #0, hls, to 'stream1.m3u8':
  Metadata:
    encoding_tool   : QSVEncC (x64) 5.01
    encoder         : Lavf58.49.100
    Stream #0:0, 0, 1/90000: Video: h264 (Main), 1 reference frame, nv12(progressive), 1440x1080 (0x0) [SAR 4:3 DAR 16:9], 0/1, q=2-31, 200 kb/s, 29.97 fps, 90k tbn
    Stream #0:1, 0, 1/90000: Audio: aac (LC), 48000 Hz, stereo, fltp, delay 1024, 192 kb/s
    Stream #0:2, 0, 1/90000: Data: timed_id3 (ID3  / 0x20334449), 0/1
avout: audio track #1: aac frame_size 1024 sample/byte -> aac frame_size 1024 sample/byte
avout: calc dts, first dts -2 x (timebase).
[mpegts @ 00000000004bb4c0] parser not found for codec arib_caption, packets or times may be invalid.
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1017911 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1029945 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1008611 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1020644 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1032678 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1011344 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1023378 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1002045 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1014077 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1026111 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1004778 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1016811 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1028844 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1007511 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1019544 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1031578 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1010245 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1022277 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1000944 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1012978 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1025011 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1003678 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1015711 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1027744 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1006411 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1018445 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1030477 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1009144 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1021178 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1033211 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1011878 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1023911 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1002577 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1014611 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1026645 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1005311 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1017344 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1029378 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1008044 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1020078 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1032111 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1010777 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1022811 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001478 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1013511 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Opening 'stream1-05082315_00000.ts' for writing
[file @ 0000000004334680] Setting default whitelist 'file,crypto,data'
[AVIOContext @ 000000000468d9c0] Statistics: 0 seeks, 1 writeouts
[hls @ 00000000084b8140] Opening 'stream1.m3u8.tmp' for writing
[file @ 000000000468a980] Setting default whitelist 'file,crypto,data'
EXT-X-MEDIA-SEQUENCE:0
[AVIOContext @ 000000000468d9c0] Statistics: 0 seeks, 1 writeouts
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1025544 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1004211 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1016244 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1028278 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1006945 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1018977 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1031011 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1009678 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1021711 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1000378 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1012411 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1024444 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1003111 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1015145 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1027177 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1005844 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1017878 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1029911 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1008578 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1020611 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1032644 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1011311 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[mpegts @ 00000000004bb4c0] Continuity check failed for pid 256 expected 10 got 7
[mpegts @ 00000000004bb4c0] Continuity check failed for pid 272 expected 2 got 5
[mpegts @ 00000000004bb4c0] PES packet size mismatch
[mpegts @ 00000000004bb4c0] Packet corrupt (stream = 2, dts = 1565077048).
[mpegts @ 00000000004bb4c0] Continuity check failed for pid 2305 expected 14 got 11
[mpegts @ 00000000004bb4c0] Packet corrupt (stream = 1, dts = 1565082551).
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1023345 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1002011 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1014044 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1026078 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1004744 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[mpegts @ 00000000004bb4c0] Continuity check failed for pid 0 expected 1 got 15
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1016778 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1028811 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1007477 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[mpegts @ 00000000004bb4c0] Continuity check failed for pid 18 expected 3 got 7
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1019511 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1031545 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1010211 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1022244 > 1000000: forcing output
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1001000 > 1000000: forcing output
[hls @ 00000000084b8140] pkt->duration = 0, maybe the hls segment duration will not precise
[hls @ 00000000084b8140] Delay between the first packet and last packet in the muxing queue is 1000911 > 1000000: forcing output
Clear vpp filters...
Clear vpp filter (copy)...

デバッグ出力を切った場合は以下の通りになります。

--------------------------------------------------------------------------------
stream1.m3u8
--------------------------------------------------------------------------------
Min/Max QP is not supported on current platform, disabled.
Error (clGetDeviceIDs): device not found.
QSVEncC (x64) 5.01 (r2279) by rigaya, May  8 2021 19:58:15 (VC 1928/Win/avx2)
OS             Windows 7 x64 (7601) [CP932]
CPU Info       Intel Core i7-2600K @ 3.40GHz [TB: 3.52GHz] (4C/8T) <SandyBridge>
GPU Info        850-1350MHz
Media SDK      QuickSyncVideo (hardware encoder), 1st GPU, API v1.4
Async Depth    6 frames
Buffer Memory  d3d9, 86 work buffer
Input Info     avqsv: MPEG2, 1440x1080, 30000/1001 fps
VPP            Deinterlace (normal)
AVSync         forcecfr
Output         H.264/AVC(yuv420) Main @ Level 4
               1440x1080p 4:3 29.970fps (30000/1001fps)
               avwriter: h264,
                #1:aac/stereo:stereo:volume -> aac/stereo/192kbps, data#1
                => hls
Target usage   7 - fastest
Encode Mode    Bitrate Mode - VBR
Bitrate        6500 kbps
Max Bitrate    15000 kbps
VBV Bufsize    30000 kbps
Ref frames     2 frames
Bframes        3 frames
Max GOP Length 30 frames
MFXDEC: DecodeFrameAsync: removing 26688 bytes from input bitstream not read by decoder.
CHECKPTS: Big Gap was found between 2 frames, avsync might be corrupted.
70 frames: 69.86 fps, 6893 kb/s                                                
MFXDEC: DecodeFrameAsync error: device operation failure..
                                                                               
encoded 74 frames, 69.03 fps, 6794.58 kbps, 2.00 MB
encode time 0:00:01, CPULoad: 3.3
frame type IDR  3
frame type I    3,  total size  0.17 MB
frame type P   20,  total size  0.75 MB
frame type B   51,  total size  1.08 MB


[mpeg2video @ 00000000004de680] Invalid frame dimensions 0x0.
[mpeg2video @ 00000000004de680] Invalid frame dimensions 0x0.

個人的には Error (clGetDeviceIDs): device not found. が気になります。
以前の QSVEncC では普通に実行できていたと思うので、5.00 以降の問題じゃないかと踏んでいます。

もっとも今どき Windows7 で SandyBridge なボロ PC を使うなって話なんですが、録画 PC がこれなので中々変えられず…

エラーからしてこちらではどうしようもできなさそうなので取り急ぎ報告まで。
私の方でも他の QSV 環境でこうなるかどうか試してみます。

@tsukumijima
Copy link
Author

QSVEncC 5.01 と、手元にあった QSVEncC 4.04 でスタンダードに QSVEncC64.exe --avhw --interlace tff -i input.ts --audio-codec aac -o out.mp4 のように適当に録画した 30 秒程度の TS をエンコードさせてみたところ、4.04 では通常通りエンコードできているのに対し、5.01 では緑っぽくランダムにモザイクがかかるような感じになってしまいました。

ただし、HLS でないからか普通にエンコード自体は終わりました。途中でエンコードが終わっているといったこともありません。音声は両者とも問題ないように見えます。

Test_QSVEncC_4.04.mp4

これが QSVEncC 4.04 でエンコードしたもの、

Test_QSVEncC_5.01.mp4

こっちが QSVEncC 5.01 でエンコードしたものです。
何回か試しましたがこれはまだマシな方らしく、場合によっては画面全体が緑っぽくなってしまうこともありました。

Test_QSVEncC_5.01sw.mp4

なんとなくデコードがうまく行っていないような気がしたので --avsw リーダーでソフトウェアデコーダーを使うようにしてみたら、上の通りあっさり正常にエンコードできました。おそらく問題はデコード側にあると思います。

@rigaya
Copy link
Owner

rigaya commented May 9, 2021

QSVEnc 5.01でデコードがうまくいかないとのことですが、おそらく5.00で行った大規模更新に伴い、場合によってはSandyBridge環境に対応しなくなったものと思われます。

まずはじめに、ご留意いただきたい点として、QSVEnc(NVEncもVCEEncもそうですが)の想定動作環境は以下の通りとなっております。

Windows 10 (x86/x64)
Aviutl 1.00 or later (QSVEnc.auo)

ハードウェアエンコード関連はデバイスによる差異が大きく、Windows10が標準でサポートしない過去の環境についてサポートを私個人で継続していくことは作業量の増大を招くため難しいので、大変勝手ながらこのようにさせていただいています。


さて、こちらでも確認のため適当なtsで
QSVEncC64.exe --avhw --interlace tff -i input.ts --audio-codec aac -o out.mp4
でQSVEnc 5.01で確認しましたが、下記環境の全てで緑の絵が出ることなく問題なく動作することを確認しており、ご指摘いただいた問題は発生しませんでした。

CPU 世代 ドライバ Windows
i5 2410M SandyBridge 4229 8.1
i3 4170 Haswell 5107 10 20H2
i5 5500U Broadwell 5126 10 20H2
i7 7700K Kabylake 9316 10 20H2
i5 1035G7 Icelake 8681 10 20H2
i7 11700K Rocketlake 9466 10 20H2

思いつく有効と思われる対応策・回避策として下記をお試しいただけますでしょうか?

お手数をおかけしますがよろしくお願いいたします。

なお、ご指摘いただいた下記エラーメッセージについてですが、

Error (clGetDeviceIDs): device not found

これはSandyBridgeがOpenCLをサポートしないため表示されますが、その後OpenCL抜きで動作するよう回復処理が行われるようになっており、特に問題はありません。

@rigaya
Copy link
Owner

rigaya commented May 9, 2021

--input-probesizeの追加を上記QSVEnc 5.01に続き, VCEEnc 6.11でも行いましたので、ご連絡します。

よろしくお願いいたします。

@rigaya
Copy link
Owner

rigaya commented May 20, 2021

RDP の話が出るということは、そちらの検証環境では RDP でリモートデスクトップして操作事が多いようですね。
私の環境 (録画PC) では起動してから一度もリモートデスクトップで接続したりはしていません。

うちはもう他のPCでモニタの接続が使われていて、録画マシンはあまりさわらないのでRDPでしか普段は操作していないです。ただ、そちらではRDP未使用でもブロックノイズが出るのですよね。となると条件が違うことになり、もっと広く発生する可能性があるのかもしれません。

arib-subtitle-timedmetadater を挟まず、UDP 受信を QSVEncC 含めたエンコーダーで直接行う v2.5.0 のような形態に戻した状態で問題ないのでしょうか?

そうですね、条件切り分けのため、開発版のstream.phpを改変して、TSTaskからのUDPやTCPを直接QSVEncCで受信してテストしています。このとき、やはり従来のUDP直接受信は問題ないです。TCPはarib-subtitle-timedmetadaterを介した場合でも介さず直接受信してもブロックノイズが出てしまいました。(TCPの送受信のトラブルと考えると、むしろarib-subtitle-timedmetadaterを介した場合でもだめというのは逆によくわからない…)

データの入力方法というよりかは、放送波の特性上突然中途半端な(?)所から TS が流れてくるのが悪いんでしょうかね…?

tsはたしかに中途半端なところからデータ開始となることが多いですが、それについては読み込み時に対策の実装を私のほうでしています。また、それ自体はファイル読みでもそうですし、NVEncCでもそうなので、原因ではないのかなあ、と思います。

調べれば調べるほど原因が思い当たらない状況ですが、他の不具合修正と並行してもう少し調べてみます。

@tsukumijima
Copy link
Author

tsukumijima commented May 20, 2021

tsはたしかに中途半端なところからデータ開始となることが多いですが、それについては読み込み時に対策の実装を私のほうでしています。また、それ自体はファイル読みでもそうですし、NVEncCでもそうなので、原因ではないのかなあ、と思います。

ですよね… 確かに調べれば調べるほど原因がわからないって感じの…
これで UDP 受信がうまくいかないとかなら分かるんですが、TCP 受信も TCP 受信したものを標準入力で流されても両方ダメというのが腑に落ちないです。あとはプロセスの優先度諸々とか?

一応お伝えしておくと、NVEncC でも 30 分に 1 ~ 2 回あるかないか程度の頻度で極稀に若干のパケットロスが発生することはあるようです。ただし、あったとしても微々たるもので、ごく一瞬だけ音声が繰り返しになったり映像の一部が乱れたりする程度なので許容範囲だとは思います(画面全体にはっきり出るほどではなく、ぼーっと見てれば気づかないくらい)。これに関しては arib-subtitle-timedmetadater 側で TCP の受信バッファを設定できれば解決しそうな気もしますが、node.js で TCP の受信バッファを設定する方法がわからない…

TSTask に原因があるとすると ffmpeg や NVEncC でうまくいく説明がつかなくなるし、一旦 TCP で通信が行われる事による何かしらの変化とかがあるんでしょうかね…?
arib-subtitle-timedmetadater で UDP 送信したものを QSVEncC で UDP 受信するように変えたとして、それでもやはりブロックノイズが出るようだと、データの入力方法には関係なく一旦通信経路に TCP を使っている事による何かしらの変化(?)が原因だとしか言いようがない気がしますね。そんな事があるのかって所ですが。
どの仮説を立ててもどれかの検証結果と矛盾するので何もわからない…

@rigaya
Copy link
Owner

rigaya commented May 22, 2021

これで UDP 受信がうまくいかないとかなら分かるんですが、TCP 受信も TCP 受信したものを標準入力で流されても両方ダメというのが腑に落ちないです。

そうなんですよね、私はこのあたりの知識はど素人ですが、TCPとUDPでいえばTCPのほうがドロップしなそうなイメージですが。また、TCP受信か標準入力か、どちらかはうまくいきそうなものです。

あとはプロセスの優先度諸々とか?

プロセスの優先度は、TSTaskを高優先度とかQSVEncCを高優先度とか、いろいろな組み合わせを試しましたが関係ないようです。

調べるとどんどん原因の候補がつぶれてはいくのですが、原因に辿りつけず、とにかくTCPを経由した状態でQSVEncCを使うとなにかが起こってしまうようで、全く原因がわからず手詰まりの状況です。

そこで異なるアプローチとして、arib-subtitle-timedmetadaterのソースコードを最大限参考にさせていただき、QSVEncC内にtimed_id3への変換処理を内蔵することで、QSVEncC使用時にはUDP直接受信を行えるよう改変を行ってみました。いまのところ正常に動作しており、字幕は適切に表示され、ブロックノイズも出なくなりました。

ただ、この方法だと字幕なし番組→字幕あり番組に切り替わった時に字幕が表示されないという問題が残ります。そのため、これでいいかというと微妙ですので、ひとつの案としてこういう方法もある、ぐらいで考えていただければと思います。

!! 最初に同梱したQSVEncCが古いものだったので再度更新しました(5/22 11:28) !!
TVRemotePlus: https://github.com/rigaya/TVRemotePlus/tree/test (コミット)
QSVEnc: https://github.com/rigaya/QSVEnc/tree/timed_id3
NVEnc: https://github.com/rigaya/NVEnc/tree/timed_id3
VCEEnc: https://github.com/rigaya/VCEEnc/tree/timed_id3

この変更を通じてTCP使用時のブロックノイズの原因のヒントがなにかわかるかな、という目論見もあったのですが、やはりUDPだとうまくいく、ぐらいしかわかりませんでした。うーん…。

@tsukumijima
Copy link
Author

tsukumijima commented May 22, 2021

まさかのアプローチで大変驚いています。たしかにこれならパケットロスなくエンコードできると思います。
ただ、この arib-subtitle-timedmetadater を使わない状態で UDP を TCP にするとやはりパケットロスが出てしまうのでしょうか。

ただ、この方法だと字幕なし番組→字幕あり番組に切り替わった時に字幕が表示されないという問題が残ります。

これに関しては QSV/NV/VCEEncC 側の実装で改善することは可能でしょうか?
arib-subtitle-timedmetadater では ARIB 字幕ストリームの有無に関わらず常に timed_id3 ストリームを追加し、ARIB 字幕ストリームが追加されたらすでにある timed_id3 ストリームに変換して流し込むような実装になっているようです。

もしこれが可能なのであれば、ご提案いただいた方法で正式に採用することも考えたいと思います(この方法なら --input-retry が使えますね)。
逆にこれが難しいのであれば、(実際にそうなるかはわかりませんが)ファイル再生で録画マージンの関係で字幕なし番組→字幕あり番組に切り替わった時に字幕が表示されなくなってしまうと考えられるため、ちょっと厳しいです。やるとしても QSVEncC のみの限定適用という形になるでしょうか。

あと、実際の動作はおそらく問題ないとはいえ、受信方式を UDP と TCP 両方使うというのが実装的にかなりもにょります。本当はあまり複雑にしたくないしできる限り統一したいんですけどね…
あとは一度 ffmpeg でストリーム開始している状態で QSVEncC にエンコーダーを切り替えると TSTask の送信方式を UDP → TCP へ切り替えできずコケる気がします。これは TSTaskCentreEx に渡すコマンドでなんとかできるとは思いますが…。

@tsukumijima
Copy link
Author

もう一つ TCP を使わない方法として、arib-subtitle-timedmetadater で UDP 受信してしまうとどうしてもパケットロスが出るので、パケットロスなく UDP 受信できるツールをどうにかして用意することができれば、arib-subtitle-timedmetadater に標準入力で受信データを流しパケットロス(ブロックノイズ)なくエンコードできるような気はします。

ただし「パケットロスなく UDP 受信できるツール」がいくら C++ で書いたとしても実現可能なのかは不明ですし、そこをクリアしないと難しいです。そして私は C++ が書けない…

これはこちらでも検証してみようと思っていますが、あとは EpgDataCap_Bon の TCP 送信機能で受信した場合に挙動が変わるのかも気になります。
もし TSTask と EpgDataCap_Bon の挙動が同じなら QSV 利用中に TCP 通信が行われている(?)ことが原因になるでしょうし、異なるのなら何かしら TSTask の送ってくるストリームのどこかに QSVEncC だけ引っかかるポイントがある事になります。

@rigaya
Copy link
Owner

rigaya commented May 22, 2021

この arib-subtitle-timedmetadater を使わない状態で UDP を TCP にするとやはりパケットロスが出てしまうのでしょうか。

おっしゃる通りです。いとも簡単にブロックノイズが出ます。

ffmpeg/NVEncCでは問題ないが、QSVEncCで問題が出る以上、QSVEncCになにか原因がありそうとは思います。ですが逆に、libavformatでの受信方式を変える、たったそれだけでブロックノイズの有無が変わってしまうので、それはもはやQSVEncCでどうしようもないのでは、ということで堂々巡りです。

ただ、この方法だと字幕なし番組→字幕あり番組に切り替わった時に字幕が表示されないという問題が残ります。

これに関しては QSV/NV/VCEEncC 側の実装で改善することは可能でしょうか?

さすがにこれを機能として継続的にサポートするのは厳しいと考えています。

受信方式を UDP と TCP 両方使うというのが実装的にかなりもにょります。本当はあまり複雑にしたくないしできる限り統一したいんですけどね…

なるほど、私の理解不足で申し訳ありません。TCP/UDP併用は私の想像していた以上になかなかややこしいこと、説明いただいて理解できました。そう考えると、今回の方法は実装が複雑になりそうということで没にしたほうがよさそうですね。

@tsukumijima
Copy link
Author

tsukumijima commented May 22, 2021

さすがにこれを機能として継続的にサポートするのは厳しいと考えています。

そうですか… もしそれが実装できるのでしたらもうこれで暫定解決というのも考えはしたのですが。

なるほど、私の理解不足で申し訳ありません。TCP/UDP併用は私の想像していた以上になかなかややこしいこと、説明いただいて理解できました。そう考えると、今回の方法は実装が複雑になりそうということで没にしたほうがよさそうですね。

せっかく色々実装していただいたのに申し訳ないです。
確かにややこしくなりますし本来ここで複雑な構成にはしたくないのですが、そうでないとうまく行かないのならこの手法で解決させるしかないかな…という印象でした。実装が複雑になることと別途 TSTaskCentreEx に渡すコマンドの追加が必要なこと以外に他に遮る問題はなさそうですし。

libavformatでの受信方式を変える、たったそれだけでブロックノイズの有無が変わってしまうので、それはもはやQSVEncCでどうしようもないのでは、ということで堂々巡りです。

そういえばこの問題って HLS 出力でのみ発生するのでしょうか。単に TSTask なり arib-subtitle-timedmetadater なりから TCP 受信したものをファイルに書き出してみて、それでブロックノイズがないなら HLS 出力に関係するオプションや HLS 関連の実装に絞り込めそうです。

にしてもそちらがここまで調べてくださっているのに原因に全くたどり着けないとなると、色々どうしようもないですね…😥

@tsukumijima
Copy link
Author

tsukumijima commented May 22, 2021

TSTask の代わりに暫定的に EpgDataCap_Bon の TCP 送信機能を使う構成(TSTask を立ち上げるコードをコメントアウトし、代わりに EpgDataCap_Bon を 127.0.0.1:8201 に TCP 送信する状態で起動させっぱなしにしておく)で試した報告です。
結果、QSVEncC にて 5 回試したもののほぼ全てダメで、ブロックノイズが入ってしまっていました。

ただし TSTask の場合と症状が異なっていて、EpgDataCap_Bon の場合は最初の大きいブロックノイズだけでなく、10秒に1~2回くらいのペースで頻繁にブロックノイズが入ります。

さらにこの症状は NVEncC や ffmpeg でも発生します。QSVEncC より若干頻度が少ない…かとも思いましたが、場合によりけりのようで顕著な差ではありませんでした。
このうち ffmpeg では、昔 TSTask からの TCP 受信を試したときと同じ文面のエラーが度々表示されており、そのエラーが出た直後にブロックノイズが入っていました。

これは以前 ffmpeg / ffplay で TSTask からの TCP 受信を試した時に頻繁にブロックノイズが入ってうまくいかなかった症状と概ね同じです。これに関しては TSTask 側で BonDriver_TCP 用のヘッダを送信しない設定にしたり、一度に送信するサイズを 256 から 188 に変更しているのが効いているのではないかと考えています。
EpgDataCap_Bon が BonDriver_TCP 用のヘッダを送信しているのかは分かりませんが、BonDriver_TCP での使用を前提としているはずなのでおそらく入っているはずです(ただしヘッダを送信しない設定はない)。

…と、TSTask との挙動を比較する以前の問題のようで、残念ながらあまり比較になりませんでした。
一応参考になれば。

@tsukumijima
Copy link
Author

tsukumijima commented May 22, 2021

EpgDataCap_Bon の TCP 送信機能 (SendTSTCP) 内で独自ヘッダを出している箇所はどこにあるんだろうと思い軽く探してみたら、https://github.com/xtne6f/EDCB/blob/work-plus-s/SendTSTCP/SendTSTCP/SendTSTCPMain.cpp が見つかりました。

コードを読む限り、どうやらポート 22000 ~ 22999 までの間なら BonDriver_TCP 用の独自ヘッダ( SendTSTCP プロトコル?)は送信されないようになっているようでした。なんでそうなっているのかはよく分かりませんがこの仕様を活用させてもらい、EpgDataCap_Bon → arib-subtitle-timedmetadater → QSVEncC の構成にて再度 TCP 受信の試験を行いました。

試験方法

まず、TVRemotePlus の環境設定で、[UDP 送信時の開始ポート番号] を 8200 から 22000 に変更します。
次に、EpgDataCap_Bon を立ち上げて、設定から TCP 送信として 127.0.0.1:22001 を設定し、TCP 送信が有効な状態にします。
BonDriver とチャンネルは任意のものに変更しておきます。そして、EpgDataCap_Bon を起動したままにします。

EpgDataCap_Bon.exe は xtne6f 版の比較的最近のものを使っています
10.66 とかだと挙動が違うかも

最後に、modules/stream.php 内の TSTask 起動用コマンドを実行する箇所(ここここ)をコメントアウトします。

この状態で Stream 1 で適当なチャンネルでストリームを起動すると、EpgDataCap_Bon(ポート:22001)からの TCP ストリームが受信に利用されます。
もちろん簡易的なものなので、チャンネル切り替えは EpgDataCap_Bon の UI を通してやる必要がありますが。

結果と考察

驚くべき事に今まであれだけ不安定だった QSVEncC がいきなり安定し、ブロックノイズが一切なくなりました!!
前回の EpgDataCap_Bon での試験では継続的に小さなブロックノイズが入っていた ffmpeg と NVEncC でもブロックノイズが一切なくなりました。
EpgDataCap_Bon を使うようにした状態でポートのみ 8200 に戻すと、また「連続的で小さめ」のブロックノイズが発生するようになりました。

つまり、まず BonDriver_TCP 向けの独自ヘッダはエンコーダー(というより BonDriver 以外)で受信するときには完全に不要で、入れてしまうとどのエンコーダーでも正常に TS を処理しきれず、小さめのパケットロスが出てしまうようです。
188 バイトで決まってる TS パケットのどこかに(?)無理やり 8 バイトの独自データを入れられたらうまく処理できないのも無理はありません。
この挙動に関しては TSTask の設定 (TSTask-tvrp.ini) で BonDriver_TCP 向けのヘッダを送信しないようにしたら今まで悩まされていた「連続的で小さめ」なブロックノイズがなくなり ffmpeg と NVEncC で安定した事実も踏まえると、ほぼ確定だと思われます。この挙動のせいで散々振り回されてしまった…。


EpgDataCap_Bon での受信において全エンコーダー共通の「連続的で小さめ」のブロックノイズを解消できたので、本題の QSVEncC のみで発生する「最初限りの大きな」ブロックノイズが発生するかどうかを検証しました。

かれこれ 20 回以上は QSVEncC の再起動やチャンネル変更、字幕あり番組なし番組など様々なパターンで試験したのですが、結局一度も「最初限りの大きな」ブロックノイズは発生しませんでした…!!

TSTask と EpgDataCap_Bon 両方で BonDriver_TCP 向けの独自ヘッダは送信しないようにしてあります。その状態で TSTask での TCP 送信ではパケットロスが発生し、EpgDataCap_Bon ではパケットロスが全く発生しないという結果が得られました。
これらの結果から、原因は TSTask の TCP 送信機能がパケットロスするような何か(?)が含まれたストリームを送ってきている事にあるのではないかと考えます。もしかすると独自ヘッダの件が少し関連しているかもしれません。

もちろんなぜ QSVEncC でのみうまくいかないのかは未だ謎ですが、少なくともなぜ TCP 受信でのみパケットロスが発生するのかの理由の説明にはなるはずです。

元の状態に戻した状態で QSVEncC を同じチャンネルで動かしてみた所、下記のような散々たる結果になりました…
ここでのチャンネルは以前 20 回試験したときと同じチャンネルに設定してあります。
元の状態では 10 回試してこの惨状である事からしても、EpgDataCap_Bon (ポート:22001) から TCP 受信する分にはブロックノイズの心配はないと思われます。

  • 0セグメントで終了:3
  • 1~2セグメントで終了:2
  • ブロックノイズありで続行:3
  • ブロックノイズなしで続行:2

また、これは確証はないのですが、前回の試験同様に独自ヘッダが付与される 8201 ポートで TCP 受信した場合でも、「連続的で小さめ」なブロックノイズは発生しますが、「最初だけの大きな」ブロックノイズは発生しないように見えました。
後述する 1 セグメントでエンコーダーが落ちる問題に関しても、EpgDataCap_Bon からの受信だと起こらないようでした(少なくとも、元の状態に戻した時よりかは遥かに低い確率)。


さらに、今まで私の環境のみ発生していた 1 セグメントのみでエンコーダーが落ちてしまう問題に関しても一切発生しなくなりました!なんとなく予想はしていましたが、やはりパケットロスに耐えられずに落ちてしまうのが原因だったようです。

今回「通常状態」でも試験を行ったところ、2 セグメントでエンコーダーが落ちてしまった例を観測しました。その例では 1 セグメント目ではほぼブロックノイズなく通常通りエンコードできていたものの、2セグメント目でブロックノイズがいきなり酷くなり終了してしまっていました。
この挙動や以前の挙動から考えると、パケットロスの量が Sandy Bridge の HW デコーダーの貧弱なエラー耐性を超えた時に発生する問題なのではないかと考えられます。一度もセグメントがエンコードされずに終了してしまう事があるのもエンコード開始前に大量のパケットロスがあったと考えれば説明が付くと思います。

まとめ

私の手元では EpgDataCap_Bon(独自ヘッダが付与されないポート 22000 ~ 22999 の範囲)から TCP 受信することで、今まで長らく課題になっていた挙動が全て解決し、QSVEncC でも NVEncC 同等の安定性で継続してエンコードできるようになりました!!

ffmpeg・NVEncC の挙動も問題なく、字幕に関してもずれはありません。かなり理想に近い状態でした。

そして、1 セグメントでエンコーダーが落ちる問題と、ストリーム再生当初にドカっとパケットロス(ブロックノイズ)が発生する問題に関しては、TSTask の TCP 送信機能が QSVEncC にのみ悪影響を与える何かしら(?)を含んだ TS を流しているからではないか(要するに TSTask が何かしら悪い)、という仮説ができました。
少なくとも、私の環境の EpgDataCap_Bon (ポート 22000 ~ 22999 の範囲) を TSTask の代わりに使えば安定するのは確実です。

まずはそちら側で EpgDataCap_Bon (ポート 22000 ~ 22999) での TCP 受信でブロックノイズがなくなっているかを確認していただければと思います。
考察に関しては一部不正確かもしれませんが、この情報が原因の特定に繋がる事を祈ります。

TVRemotePlus で利用している TSTask は本家の最新版にスクランブル解除対応のパッチ等を当てたもの ( https://github.com/tsukumijima/TSTask )です

もし原因がわからなかったとしても、最悪 TSTask から EpgDataCap_Bon へ受信アプリを変更すればどうにかなりそうな事が分かったので、私としては一安心です。
もちろん、旧バージョンとのアップデート互換性がなくなってしまいユーザーが手間取る事が容易に予想されるので、後継ソフトならともかく TVRemotePlus での実装としてはあまりやりたくはないのですが…。

@rigaya
Copy link
Owner

rigaya commented May 23, 2021

EpgDataCap_Bon でのテスト、また結果をご連絡いただきありがとうございます。

これはもうTSTaskのTCP送信の問題で確定ですね、ということでTSTaskを実際にデバッグしてみました。

するとTCP送信のretryループがあるのですが、このbreak文で一度もretryせずすぐ抜けてしまうのでretryが機能しておらず思いっきりdropしてました(デバッグwriteさせて実際に確認しました)。ソケット通信のコードに詳しくないので、もしかすると間違っているかもしれませんが、どうも実質1秒のタイムアウトになっているように見えます。

ということでfixtcpdropブランチでretryが機能するよう修正を試みました。
https://github.com/rigaya/TSTask/tree/fixtcpdropPR
https://github.com/rigaya/TVRemotePlus/tree/fixtcpdropPR

だいぶ改善したと思いますが、お試しいただけますでしょうか。

なんでQSVEncCだけdropが発生したかについては、QSVは他と比べて内部バッファが多いため、エンジン起動が遅く、その間パケットを読み込まないため、1秒のタイムアウトではdropが不可避だったためと思われます。一度起動してしまえば、常時パケットを読み込むので、dropしないこととも整合します。(1秒未満で起動しろというのは、そりゃ無茶です…)

@tsukumijima
Copy link
Author

tsukumijima commented May 23, 2021

するとTCP送信のretryループがあるのですが、このbreak文で一度もretryせずすぐ抜けてしまうのでretryが機能しておらず思いっきりdropしてました(デバッグwriteさせて実際に確認しました)。ソケット通信のコードに詳しくないので、もしかすると間違っているかもしれませんが、どうも実質1秒のタイムアウトになっているように見えます。

なんでQSVEncCだけdropが発生したかについては、QSVは他と比べて内部バッファが多いため、エンジン起動が遅く、その間パケットを読み込まないため、1秒のタイムアウトではdropが不可避だったためと思われます。一度起動してしまえば、常時パケットを読み込むので、dropしないこととも整合します。(1秒未満で起動しろというのは、そりゃ無茶です…)

デバッグありがとうございます。やっぱり TSTask が原因でしたか…(まさか TSTask 側の不具合を直して頂けるとは思いもせず、恐縮です)
そちらの環境では改良した TSTask からの受信で QSVEncC でのブロックノイズは起きなくなっているのでしょうか?
QSVEncC のみで発生する理由も概ね納得です。QSV の起動時間が影響しているとなると、起きたり起きなかったりするのもなんとなく説明がつきそうです。

どうも実質1秒のタイムアウトになっているように見えます。
タイムアウトというのがよく理解できていないのですが、TSTask が起動してから 1 秒以内にエンコーダーが受信できる状態になっていないとパケットロスする状態になっていたということなのでしょうか…?

あと、tsukumijima/TVRemotePlus#7 にて送信する TS パケット数の拡大が行われていますが、これはデフォルトの 256 の方が好ましいのでしょうか。

ひとまず PR に関してはマージし、こちらでも検証してみます。

@tsukumijima
Copy link
Author

改良版の TSTask の導入と PR して頂いた TSTask-tvrp.ini の設定変更を行った状態で QSVEncC にて検証したところ、以前 EpgDataCap_Bon (ポート 22000 ~ 22999) で検証した際の状態と同じく、非常に安定してエンコードできるようになりました…!!!!

今回も 10 回以上はチャンネルを変えながら検証したのですが、ブロックノイズが入ることは一度もありませんでした。1 セグメント目で落ちてしまう問題も今のところ起きていません。
QSVEncC 以外の ffmpeg や NVEncC でも問題なく、字幕のズレなどもありません。素晴らしい…!
もちろん長時間のエンコードでどうなるかはまだ見れていないので、検証もかねてしばらく QSVEncC をデフォルトのエンコーダーに設定してみます(問題ないとは思いますが)。

まさか TSTask が原因だとは思いもよらず、検証やデバッグ等で多大な苦労をお掛けしてしまい、本当に申し訳ありませんでした。
Issue の本題の件も含め私だけではまず解決できなかった問題なので、本当に感謝してもしきれません。ありがとうございました…!
これにて話題を変えつつ1ヶ月続いてしまった一連の問題も、ようやく一件落着です。

あとは他の環境でどうなるかですね…
私の環境では QSVEncC でも NVEncC と同等の安定性で全く問題ありませんが、このまま正式リリースにするのは心もとないので、一度ベータ版としてユーザーの皆さんにテストして頂いてからにするつもりです。
それと、手元に VCEEncC を動かせる環境がないので、VCEEncC で問題なく動くかどうかも気になります。

再度になりますが、本当にありがとうございました!

@rigaya
Copy link
Owner

rigaya commented May 23, 2021

改良版の TSTask の導入と PR して頂いた TSTask-tvrp.ini の設定変更を行った状態で QSVEncC にて検証したところ、以前 EpgDataCap_Bon (ポート 22000 ~ 22999) で検証した際の状態と同じく、非常に安定してエンコードできるようになりました…!!!!

よかったです!!安心しました。やっと「これだ!」という原因を見つけてすっきりできた気持ちです。さすがにちょっと疲れましたです、はい…。

お力になれましたらば幸いでした。

まさか TSTask 側の不具合が直るとは思ってもみませんでした

もうQSVEncC側ではどうしようもないので、TSTask側をさわるしかないかなと思いました。

そちらの環境では改良した TSTask で QSVEncC でのブロックノイズは起きなくなっているのでしょうか?

そうですね、開始数秒後にわりと高い頻度(3,4回に1回程度)でかなり大きな帯状のブロックノイズが出る問題は完全に(30回ぐらいは試してゼロ)出なくなりました。

TSTask が起動してから 1 秒以内にエンコーダーが受信できる状態になっていないとパケットロスする状態になっていたということなのでしょうか…?

いえ、TSTask起動から1秒以内でエンコーダーが受信できる必要はないです。今回はそのあとの問題で、エンコーダーが受信できる状態になりTCP接続を確立してから送受信をしている途中で、送受信の間隔が1秒以上空いてしまうことがあると問題になるようです。

QSVEncCはエンコーダ等を初期化するにも入力ファイルの情報が必要なので、まず--input-probesizeまたは--input-analyzeに相当するデータの2倍を解析用に読み込み解析します。そのあとGPUデバイスやらデコーダ・エンコーダ等の初期化を行するのですが、QSVEncCはそこに時間がかかり、またこの初期化の間読み込みを行わないので、読み込みの間隔が空いてしまうのかなと推測しています。

そういった動作はTSTaskでは想定していないのかもしれませんが、retry回数を指定できるのだからその分はちゃんとretryしてほしいなあということで今回の修正となりました。

実際にデバッグ文を入れて動作させてみて、修正前dropしていた箇所で修正後はdropしなくなったことを確認しました。

TS パケット数の拡大が行われていますが、これはデフォルトの 256 の方が好ましいのでしょうか。

これは、drop被害にあうパケット数を減らすためにそちらのほうでデフォルトから縮小されたのかなと思い、ただ今回drop問題が解消したのでデフォルトに戻せばよいかなと思っただけで、あまり深い意味はありません。


それと、手元に VCEEncC を動かせる環境がないので、VCEEncC で問題なく動くかどうかも気になります。

VCEEncC + TVRemotePlusを初めて試してみました。まず、わたしのドキュメントの誤りで、--preset defaultでなく、--preset balancedと設定する必要がありました。ドキュメントに誤りがあり、申し訳ありません。修正案をPRさせていただきました

まずほとんどの場合、ffmpegやNV/QSVEncC同様に安定して切り替え、字幕表示でき、またブロックノイズも出ないことを確認しました。

一方、たまに(10回に1回ぐらい?)エンコード開始時にVCEEncCが固まってしまう問題が発生します。ただ、これはファイル読みでもちょっとdropがあるだけで発生しますので、今回のTVRemotePlusの変更によるものではありません。

VCEのハードウェアデコードはこれは以前からエラー耐性がQSVより低く、厄介なことにちょっとしたdropでもすぐ固まります(HWデコーダがなにもいわずにフレームを返さなくなる)。残念ながらアプリ側(VCEEncC側)ではどうしようもないので、現状ではデコーダを監視して固まったのを検知したらエラー終了するようにしています。このあたり、将来的にはVCEEncC側でどうにかしたいですが、すぐには改善できそうになく、またユーザー数がNVEncCやQSVEncCより少なそうなのもあって、現状手をつけられていません。

申し訳ありませんが、安定性重視ならVCEEncCだけは--avswに切り替えていただいたほうがよいかもしれません。--avswであれば、こうした問題は発生せず(もちろんブロックノイズもなく)、安定することを確認しました。

tsukumijima added a commit to tsukumijima/TVRemotePlus that referenced this issue May 23, 2021
VCE の HW デコーダーはちょっとしたドロップでもフリーズするなどエラー耐性が低く TS を扱う用途では不安定なため、安定性を優先する
reference: rigaya/NVEnc#335 (comment)
@tsukumijima
Copy link
Author

tsukumijima commented May 23, 2021

よかったです!!安心しました。やっと「これだ!」という原因を見つけてすっきりできた気持ちです。さすがにちょっと疲れましたです、はい…。

私も同感です…。
私も正直かなり疲れたのですが、それ以上に rigaya さんと monyone さんを大いに巻き込んでしまい申し訳ない気持ちでいます。
当初は長くても 1 週間程度でなんとかなると思っていただけに、ここまで根が深い問題だとは全く想定外でした。

相当な試行錯誤の上とはいえ、何はともあれ万事解決できたのが幸いです。

開始数秒後にわりと高い頻度(3,4回に1回程度)でかなり大きな帯状のブロックノイズが出る問題は完全に(30回ぐらいは試してゼロ)出なくなりました。

私の環境でも「かなり大きな帯状のブロックノイズ」でした。横に長くて灰色っぽいやつ…
そちらの環境で 30 回試して出ないのであれば問題ないと言って良いと思います。

いえ、TSTask起動から1秒以内でエンコーダーが受信できる必要はないです。今回はそのあとの問題で、エンコーダーが受信できる状態になりTCP接続を確立してから送受信をしている途中で、送受信の間隔が1秒以上空いてしまうことがあると問題になるようです。

  • QSVEncC が一度ストリームを読み込んだ後初期化する際にしばらく TCP 受信を受け付けなくなるので、受信を受け付けなくなっていた間のパケットが抜け落ちてしまう
  • だから、受信を受け付けるようになった後に受信できなかった分のパケットを TSTask から再送してもらう必要がある
  • しかし、TSTask はパケットの再送をしてくれないようになっていた

という事なのでしょうか。
厳密には arib-subtitle-timedmetadater 側で TCP 受信をしているはずですが、その場合でも同様な理屈がまだ理解できていません(理解が悪くてすみません…)。

これは、drop被害にあうパケット数を減らすためにそちらのほうでデフォルトから縮小されたのかなと思い、ただ今回drop問題が解消したのでデフォルトに戻せばよいかなと思っただけで、あまり深い意味はありません。

私としては「もしかすると TS パケットのサイズである 188 に合わせたほうがドロップしないかもしれない」という意図で設定していました。深い意味はありませんので、256 のままにしておきます。

まず、わたしのドキュメントの誤りで、--preset defaultでなく、--preset balancedと設定する必要がありました。ドキュメントに誤りがあり、申し訳ありません。修正案をPRさせていただきました。

問題なさそうでしたのでマージしました。報告ありがとうございました。

まずほとんどの場合、ffmpegやNV/QSVEncC同様に安定して切り替え、字幕表示でき、またブロックノイズも出ないことを確認しました。

それはよかったです。これでようやくリリースが出せそうです…。

一方、たまに(10回に1回ぐらい?)エンコード開始時にVCEEncCが固まってしまう問題が発生します。ただ、これはファイル読みでもちょっとdropがあるだけで発生しますので、今回のTVRemotePlusの変更によるものではありません。

申し訳ありませんが、安定性重視ならVCEEncCだけは--avswに切り替えていただいたほうがよいかもしれません。--avswであれば、こうした問題は発生せず(もちろんブロックノイズもなく)、安定することを確認しました。

そうなんですね…了解です。頻度は比較的低いとはいえ、ちょっとしたドロップでもすぐ固まるのはしんどいですね…
--avsw だと多少 CPU を消費するとは思いますが、GPU に Radeon を使っている PC をお持ちの方は大抵比較的高スペックな CPU を使われていそうですし(偏見)、そこまで問題でもないように思います。

tsukumijima/TVRemotePlus@12a6464 にて、VCEEncC のみ --avsw に変更しました。
ユーザーの目線で考えると、CPU 使用率が少し高くなることよりも今見ていたい番組が途中で止まってしまう事の方が遥かにストレスだと考えているので、ひとまず --avsw に変更した上で、VCEEncC ユーザーの方の反応を見たいと思います(もっとも、VCE ユーザーがそこまで多くないのであれですが…)。
これは1ヶ月にも及んだ一連の件において「途中で妥協して諦める」ではなくなんとか解決できないか取り組んだ理由の1つでもあります。

重ね重ねになりますが、長きに渡り対応してくださり本当にありがとうございました!

@monyone
Copy link

monyone commented Jun 3, 2021

@tsukumijima @rigaya
この度は、自作の arib-subtitle-timedmetadater の導入によって、非常に時間を割かせてしまい、申し訳ありませんでした。
以下の問題に関して、原因が解明できましたので、閉じられていますが追記いたします。

  • 現状 arib-subtitle-timedmetadater でパケットロスなく TSTask の TCP or UDP ストリームを受信できない
    • ffmpeg で UDP 受信する場合と異なり、エンコード当初になぜか大きめのパケットロスが起きる
    • TCP 受信では継続的に小さめのパケットロスが起きる

原因は、エンコーダとの受け渡しに標準入出力を利用していたため、
標準入出力のバッファを超えてしまうとドロップしてしまう ためでした。

以下の 2 つの仮定を置いていたため、気づくのに遅れてしまい、把握するまでに時間がかかってしまいました。
このような初歩的な問題に気が付かず、TCP で大丈夫だろうと思っていたため、申し訳ありません。

  1. エンコーダが停止なく標準入力を読むと仮定していました
    • 実際には probe する際に入力を読まない状態なっていました
  2. TCP ならフロー制御が働き、標準入出力のバッファの影響を回避できると仮定していました
    • TSTask は非同期でリトライする形で TCP 通信を行い、実質的にフロー制御が役に立たなくなっていました
    • 再送自体は手動で行っていますが、再送のリミットを超えてしまう場合がごくたまにあるようです

また、自分の環境でTVRemotePlus を導入した限りでは TCP での受信は、時たま出来る、程度の安定性になっています。
全然安定しておらず、特に同じストリームの切り替えの場合は受信が全くできません。
(TSTask の問題なのか、libavformat と node.js の問題なのか判断がつかないですが...)
UDP では安定しての動作を確認しています。

実質的に TCP 受信でのフロー制御が機能していない以上、接続が切れても関係ない UDP の方がメリットが大きいと思います。
作業して頂いて申し訳ないのですが、UDP に戻したほうが利便性、リトライに関しては上になります。
UDP で問題なければ、元のまま UDP に戻して頂きたいです。少なくとも、僕の環境では動かないです...。

@rigaya
申し訳ないのですが、最新版の TVRemotePlus では EDBC 付属の asyncbuf を用いるようにして
2秒受信が停止しても保持できるように 50M分のバッファを循環バッファで保持するようにしました。
この環境でいままで問題のあった UDP で問題が出てないか、そちらの環境でも確認して頂ければと存じます。
(tsukumijima さんには確認いただきましたが、そちらの環境でも UDP で障害が起こらないか確認したいです)

tsukumijima added a commit to tsukumijima/TVRemotePlus that referenced this issue Jun 3, 2021
TCP 送信でもうまく行っていたが、なぜか一部の環境で TSTask との TCP 通信ができない場合があるようで、ひとまず UDP に変更してみる
asyncbuf.exe を間に挟んだおかげで今までのドロップはなくなったはず
reference: rigaya/NVEnc#335 (comment)
@rigaya
Copy link
Owner

rigaya commented Jun 4, 2021

こちらではTSTaskの修正後はTCP受信でも非常に安定していましたが、ダメなケースもあるということなのですね。

標準入出力のバッファを超えてしまうとドロップしてしまう

送信側がstdoutに流す場合、受け取り側が受け取らなくてバッファを超えてしまうと、受け取り側が受信を再開するまで送信側も書き込みのところで処理が止まるという認識でしたが、stdoutへの書き込みが非同期処理になっているというようなイメージでしょうか。

ともかくUDPに再変更されたものでもQSVEncCを用いて試しましたが、asyncbufを挟んだおかげか、UDPでも問題なさそうなことを確認しました。

@monyone
Copy link

monyone commented Jun 4, 2021

ご確認ありがとうございます。
UDP でも問題ないとのことで、このまま UDP で大丈夫そうですね。

送信側がstdoutに流す場合、受け取り側が受け取らなくてバッファを超えてしまうと、受け取り側が受信を再開するまで送信側も書き込みのところで処理が止まるという認識でしたが、stdoutへの書き込みが非同期処理になっているというようなイメージでしょうか。

これに関しては、同期処理で stdout に流した際に処理が止まってしまう、同期書き込みにしています。
この時のブロッキング中にネットワークからデータが大量に来た場合が問題になります。

  • UDP だとバッファ分を超えたらドロップします。
  • TCP だとOS のウィンドウサイズを超えたら NACK を返すようになるはず (未確認)

この挙動で、stdout への書き込みが止まった際に、受信が止まると困った事態になってしまうのが、原因になります。
要するに、パイプライン処理できない部分がある事を前提としていなかったという事です。

@xtne6f
Copy link

xtne6f commented Jun 7, 2021

失礼します。
asyncbuf については xtne6f/EDCB/a375241 において EDCB 付属の WebUI でエンコードの失速を回避する目的で導入したものです。この WebUI では

ffmpeg の出力をパイプで読み込む → HTTP のレスポンスに書き込む

という処理がループするのですが、HTTP のレスポンスに書き込むはネットワークなのでしばしば長いウェイトが発生し、この間に ffmpeg の出力側が詰まってエンコードが失速、という事態を避けるため、

ffmpeg の出力を asyncbuf で読み込む + asyncbuf をパイプで読み込む → HTTP のレスポンスに書き込む

とすることで失速を回避するものです。
こういう代物なので、受信が失速しないことで UDP のドロップを軽減できる、というスジはとても納得がいくのですが、TCP や標準入出力がドロップするというのは「うーん?」という感じです。

そこで、
@monyone
使用した TSTask は @tsukumijima 氏の最新のものでしょうか?
もし最新のものなら、自分は TSTask にまだ何か問題があると考えるほうが自然に感じます。

@tsukumijima
Copy link
Author

ffmpeg の出力を asyncbuf で読み込む + asyncbuf をパイプで読み込む → HTTP のレスポンスに書き込む とすることで失速を回避するものです。

もともとそういう用途だったんですね。EMWUI の方には「再生のむらを吸収します」としか書かれておらず、EDCB でどういった使われ方をしているのかよく理解できていませんでした。

こういう代物なので、受信が失速しないことで UDP のドロップを軽減できる、というスジはとても納得がいくのですが、TCP や標準入出力がドロップするというのは「うーん?」という感じです。

私の環境でも TCP でとても安定しているので、monyone 氏の環境でそうなるのがよく分からないな…という印象です。
聞いたところによると高い確率で TSTask との TCP 接続自体に失敗するらしく(何のデータも降ってこない)、これは arib-subtitle-timedmetadater でもエンコーダーでの直接受信でも両方同じだそうです。TSTask は最新版を使っていると仰っていました。

TVTest (BonDriver_TCP) ならうまくいくそうなので何かしら TSTask に問題があるのだとは思いますが、おそらく環境依存な上に UDP なら全ての環境でうまく行っている以上、この問題にこれ以上リソースを割かなくても…という気持ちもあります。

@monyone
Copy link

monyone commented Jun 9, 2021

@xtne6f この度は自作ツールの導入でご迷惑をおかけし申し訳ありません。
ツールに手を入れてもらい申し訳なく、重ね重ねお詫び申し上げます。

使用した TSTask は @tsukumijima 氏の最新のものでしょうか?
TVRemotePlus の master に付属していた最新のものになります。

TCP では自分の環境固有に問題 (Bondriver_Mirakurun と TSTask の相性が悪い?) のかとも思っています。
ffmpeg では接続がタイムアウトが頻発し、ほぼ失敗するような状態です。

この Issue が混沌としすぎていて、rigaya さんにも迷惑なのではと思っていますので
UDP で安定で結論をつけて、この Issue にからは離れて、
TSTask の TCP 送信については、必要であれば TSTask の fork に Issue を立てて追いたいです。

(WinSock に詳しくないので、お役には立てないかと思いますが...)

@rigaya
Copy link
Owner

rigaya commented Jun 10, 2021

@monyone
Mirakurun は使ったことがないのでわかりませんが、結構環境が違うのかなと思うとTCPでうまくいかないのはそうした環境依存でTSTaskが起こすなにかしらの問題があるのかもしれませんね。

@tsukumijima

TVTest (BonDriver_TCP) ならうまくいくそうなので何かしら TSTask に問題があるのだとは思いますが、おそらく環境依存な上に UDP なら全ての環境でうまく行っている以上、この問題にこれ以上リソースを割かなくても…という気持ちもあります。

そうですね、わたしがいうことではないかもしれませんが、個人的には UDP+asyncbuf の方法でより多くの環境で安定して動作し、必要な機能が実現できているのを確認できているので、特にほかに問題なければ UDP+asyncbuf を使用するのがよいのではないかなと思います。(わたしからTSTaskに手を出しといてなんですが、TSTaskのデバッグが目的ではないと思うので)

@xtne6f
Copy link

xtne6f commented Jun 10, 2021

@tsukumijima @monyone 返答ありがとうございます。

TVRemotePlus の master に付属していた最新のものになります。

おおよそ6月3日の最新ってことで、TVRemotePlus/44468a9 あたりだと思いますが、このバージョンなら TSTask も更新されているようなので問題なさそうです。

TCP では自分の環境固有に問題 (Bondriver_Mirakurun と TSTask の相性が悪い?) のかとも思っています。

とのことなので Mirakurun/BonDriver_Mirakurun を一通り弄ってみましたが、こちらの環境では問題ないです。
強いて言えば Bondriver_Mirakurun のチャンネル変更かなり遅い?ですが、TCP がタイムアウトするほどかと言えばそんなことはないです。
迷宮入りです。表題からもかなり脱線してるので引っ張るのもアレですね…。UDP で問題ないならそれで了解です。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants