ffmpegでRTPでストリーミングしてみた

ffmpegでRTPで映像と音声をストリーミングしてみた。実験なのでlocalhost上で送信と受信を行う。
使用したffmpeg はMac用の4.1

# うまくいった方法

## SDPファイルの生成

```
ffmpeg -re -i input.mp4 \
 -c:v copy -an -f rtp rtp://localhost:30002 \
 -c:a copy -vn -f rtp rtp://localhost:30004 \
 -sdp_file out2.sdp
```

起動したらすぐに^Cで止めてOK。
生成できたSDPファイルは以下の通り。

```out2.sdp
SDP:
v=0
o=- 0 0 IN IP4 127.0.0.1
s=Big Buck Bunny
t=0 0
a=tool:libavformat 58.20.100
m=video 30002 RTP/AVP 96
c=IN IP6 ::1
b=AS:1495
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=J0LgHqkQFAX/LgDUGAQa23oA9ID1XvfAQA==,KN4JyA==; profile-level-id=42E01E
m=audio 30004 RTP/AVP 97
c=IN IP6 ::1
b=AS:127
a=rtpmap:97 MPEG4-GENERIC/44100/2
a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=1210
```

## 受信側

```
ffplay -protocol_whitelist "file,rtp,udp" out2.sdp 
```

## 送信側

```
ffmpeg -re -i input.mp4 \
 -c:v copy -an -f rtp rtp://localhost:30002 \
 -c:a copy -vn -f rtp rtp://localhost:30004
```

受信側を先に起動してから、送信側を実行する。


# 失敗の記録

最初に試したのはこれ。

```
ffmpeg -re -i input.mp4 \
 -c:v copy -c:a copy -f rtp rtp://localhost:30002 \
 -sdp_file out.sdp
```

これを実行すると

```
...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
  Metadata:
    major_brand     : M4V 
    minor_version   : 1
    compatible_brands: M4V M4A mp42isom
    creation_time   : 2008-06-03T05:23:28.000000Z
    copyright       : © 2008 Blender Foundation | www.bigbuckbunny.org
    title           : Big Buck Bunny
    artist          : Peach Open Movie Team
    composer        : Sacha Goedegebure / Ton Roosendaal
    date            : 2008
  Duration: 00:09:56.46, start: 0.000000, bitrate: 1626 kb/s
    Stream #0:0(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 127 kb/s (default)
    Metadata:
      creation_time   : 2008-06-03T05:23:28.000000Z
      handler_name    : Apple Sound Media Handler
    Stream #0:1(eng): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, smpte170m/smpte170m/bt709), 640x359, 1495 kb/s, 24 fps, 24 tbr, 2400 tbn, 4800 tbc (default)
    Metadata:
      creation_time   : 2008-06-03T05:23:28.000000Z
      handler_name    : Apple Video Media Handler
[rtp @ 0x7feb2d82d800] Only one stream supported in the RTP muxer
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
Stream mapping:
  Stream #0:1 -> #0:0 (copy)
  Stream #0:0 -> #0:1 (copy)
    Last message repeated 1 times
```

`Only one stream supported in the RTP muxer` というエラー。
映像か音声のどちらか片方だけにすると、このエラーは起こらない。

RTPとしては映像と音声を一つのポートで送ることができるが、ffmpegではそれをサポートしていない様子。
映像と音声をそれぞれ別々のポートで送るようにしてみた。

```
ffmpeg -re -i input.mp4 \
 -c:v copy -an -f rtp rtp://localhost:30002 \
 -c:a copy -vn -f rtp rtp://localhost:30003 \
 -sdp_file out2.sdp
```

これでSDPファイルは生成できた。
しかし、やってみると受信側で以下のエラーが発生する。

```
ffplay -protocol_whitelist "file,rtp,udp" out2.sdp 
```

```
[udp @ 0x7f81d2614300] bind failed: Address already in use
out2.sdp: Invalid data found when processing input
```

ffmpegのドキュメントを見直すと
https://ffmpeg.org/ffmpeg-protocols.html#toc-rtp

```
If rtcpport is not set the RTCP port will be set to the RTP port value plus 1. 
```

rtcp のポートとしてRTP +1 のポートが使用される。
なので、映像と音声の2つのRTPポートは連続した値でなくて、一つ離す必要がある。
今回の場合は、30002と30003でなくて、30002と30004 を指定する。
この変更をして、うまくいったものが冒頭のもの。