Replies: 2 comments 4 replies
-
Hi,
In the case of "WebRTC server" (although it's a very broad term, so let's assume an SFU), we usually only forward media from one peer to another, so there's no need to decode and reencode video, as it's a quite computationally intensive task. Correct me if I didn't understand you, I'll try to answer any further questions :) |
Beta Was this translation helpful? Give feedback.
-
It is "it needs the preceding packets to rebuild a frame (== image). Sorry for this late response and awful vocabulary and late response. The header has a marker that represent an event in the stream, such as the end of a frame. I want to play with the frame (Evision or Vix) so I need to decode it (probably only 1 out of n). Now, you de-VP8 (or at least it's the name of the function), but what if it is not vp8? Regex.scan(~r/a=rtpmap:([a-zA-Z0-9\s]*)/, PeerConnection.get_remote_description(pc).sdp)
["a=rtpmap:96 H264", "96 H264"],
["a=rtpmap:97 rtx", "97 rtx"],
["a=rtpmap:98 H264", "98 H264"],
["a=rtpmap:99 rtx", "99 rtx"],
["a=rtpmap:100 H264", "100 H264"],
["a=rtpmap:101 rtx", "101 rtx"],
["a=rtpmap:102 H264", "102 H264"],
["a=rtpmap:103 rtx", "103 rtx"],
["a=rtpmap:104 VP8", "104 VP8"],
["a=rtpmap:105 rtx", "105 rtx"],
["a=rtpmap:106 VP9", "106 VP9"]
....
] So H.264 is the first, thus preferred (?) codec, not VP8? def handle_info(
{:ex_webrtc, pc, {:rtp, client_track_id, packet}},
%{client_video_track: %{id: client_track_id, kind: :video}} = state
) do
PeerConnection.send_rtp(pc, state.serv_video_track.id, packet)
state = handle_paquet(packet, state)
{:noreply, state}
end
defp handle_paquet(packet, state) do
case VP8Depayloader.write(state.video_depayloader, packet) do
{:ok, d} ->
%{state | video_depayloader: d}
{:ok, _frame, d} ->
# do something with the frame, or every n frame....
^^^
%{state | video_depayloader: d}
_ ->
state
end
end For the posterity, the RTP packet has the following format: <<version::2, padding::1, extension::1, cc::4, marker::1, payload_type::7, sequence_number::16,
timestamp::32, ssrc::32, payload::binary>> = packet so when marker == 1, you received the last fragment of the current frame, thus you get a frame by joining the payloads of the current buffer. 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X| CC |M| PT | sequence number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| contributing source (CSRC) identifiers |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ You have this bit marker: marker (M): 1 bit
The interpretation of the marker is defined by a profile. It is
intended to allow significant events such as frame boundaries to
be marked in the packet stream. A profile MAY define additional
marker bits or specify that there is no marker bit by changing the
number of bits in the payload type field (see [Section 5.3](https://datatracker.ietf.org/doc/html/rfc3550#section-5.3)). |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
https://github.com/elixir-webrtc/apps/blob/b1e182a7cc5ab30dba6c19993ed8085339753fc8/reco/lib/reco/room.ex#L113
I assume every (video) RTP packet that ExWEBRTC receives is a video frame encoded/encapsulated in VP8, which means it needs some preceding frames to rebuild an image from it.
In the Reco example, you do:
{:ok, frame, d} = VP8Depayloader.write
, then youXav.decode(frame)
it to get an Nx tensor, but you use Xav.Since one big interest of using a WebRTC server is being able to transform back the images, I have a question probably as old as WebRTC: how do people deal with this? (in the Elixir/Erlang world).
Note: I tried to FFMPEG a "depayloaded" frame, which I believe reassembles payload chunks, but this fails as FFMPEG expects a stream, not a single frame.
Beta Was this translation helpful? Give feedback.
All reactions