Skip to content

Commit 847a8e1

Browse files
Sxian/clt 2304/implement remote audiovideo tracks videostream audiostream (#11)
* initial commit for video stream and other hooks * Get things functional, be able to publish remote audio / video tracks, and attach to AudioStream and VideoStream
1 parent 50c2397 commit 847a8e1

19 files changed

+1056
-63
lines changed

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ add_custom_command(
158158
add_library(livekit
159159
include/livekit/audio_frame.h
160160
include/livekit/audio_source.h
161+
include/livekit/audio_stream.h
161162
include/livekit/room.h
162163
include/livekit/room_delegate.h
163164
include/livekit/ffi_handle.h
@@ -166,6 +167,7 @@ add_library(livekit
166167
include/livekit/remote_audio_track.h
167168
include/livekit/participant.h
168169
include/livekit/local_participant.h
170+
include/livekit/remote_participant.h
169171
include/livekit/livekit.h
170172
include/livekit/stats.h
171173
include/livekit/track.h
@@ -174,10 +176,12 @@ add_library(livekit
174176
include/livekit/remote_track_publication.h
175177
include/livekit/video_frame.h
176178
include/livekit/video_source.h
179+
include/livekit/video_stream.h
177180
include/livekit/local_video_track.h
178181
include/livekit/remote_video_track.h
179182
src/audio_frame.cpp
180183
src/audio_source.cpp
184+
src/audio_stream.cpp
181185
src/ffi_handle.cpp
182186
src/ffi_client.cpp
183187
src/local_audio_track.cpp
@@ -186,6 +190,7 @@ add_library(livekit
186190
src/room_proto_converter.cpp
187191
src/room_proto_converter.h
188192
src/local_participant.cpp
193+
src/remote_participant.cpp
189194
src/stats.cpp
190195
src/track.cpp
191196
src/track_proto_converter.cpp
@@ -195,6 +200,7 @@ add_library(livekit
195200
src/remote_track_publication.cpp
196201
src/video_frame.cpp
197202
src/video_source.cpp
203+
src/video_stream.cpp
198204
src/local_video_track.cpp
199205
src/remote_video_track.cpp
200206
src/video_utils.cpp

include/livekit/audio_stream.h

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright 2025 LiveKit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an “AS IS” BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <condition_variable>
20+
#include <cstdint>
21+
#include <deque>
22+
#include <memory>
23+
#include <mutex>
24+
#include <optional>
25+
#include <string>
26+
27+
#include "audio_frame.h"
28+
#include "ffi_handle.h"
29+
#include "participant.h"
30+
#include "track.h"
31+
32+
namespace livekit {
33+
34+
namespace proto {
35+
class FfiEvent;
36+
}
37+
38+
struct AudioFrameEvent {
39+
AudioFrame frame;
40+
};
41+
42+
class AudioStream {
43+
public:
44+
struct Options {
45+
std::size_t capacity{0}; // 0 = unbounded
46+
int sample_rate{48000};
47+
int num_channels{1};
48+
std::string noise_cancellation_module; // empty = disabled
49+
std::string noise_cancellation_options_json; // empty = no options
50+
};
51+
52+
// Factory: create an AudioStream bound to a specific Track
53+
static std::unique_ptr<AudioStream>
54+
from_track(const std::shared_ptr<Track> &track, const Options &options);
55+
56+
// Factory: create an AudioStream from a Participant + TrackSource
57+
static std::unique_ptr<AudioStream> from_participant(Participant &participant,
58+
TrackSource track_source,
59+
const Options &options);
60+
61+
~AudioStream();
62+
63+
AudioStream(const AudioStream &) = delete;
64+
AudioStream &operator=(const AudioStream &) = delete;
65+
AudioStream(AudioStream &&) noexcept;
66+
AudioStream &operator=(AudioStream &&) noexcept;
67+
68+
/// Blocking read: returns true if a frame was delivered,
69+
/// false if the stream has ended (EOS or closed).
70+
bool read(AudioFrameEvent &out_event);
71+
72+
/// Signal that we are no longer interested in frames.
73+
/// Disposes the underlying FFI stream and removes the listener.
74+
void close();
75+
76+
private:
77+
AudioStream() = default;
78+
79+
void init_from_track(const std::shared_ptr<Track> &track,
80+
const Options &options);
81+
void init_from_participant(Participant &participant, TrackSource track_source,
82+
const Options &options);
83+
84+
// FFI event handler (registered with FfiClient)
85+
void on_ffi_event(const proto::FfiEvent &event);
86+
87+
// Queue helpers
88+
void push_frame(AudioFrameEvent &&ev);
89+
void push_eos();
90+
91+
mutable std::mutex mutex_;
92+
std::condition_variable cv_;
93+
std::deque<AudioFrameEvent> queue_;
94+
std::size_t capacity_{0};
95+
bool eof_{false};
96+
bool closed_{false};
97+
98+
Options options_;
99+
100+
// Underlying FFI audio stream handle
101+
FfiHandle stream_handle_;
102+
103+
// Listener id registered on FfiClient
104+
std::int64_t listener_id_{0};
105+
};
106+
107+
} // namespace livekit

include/livekit/livekit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "local_track_publication.h"
2222
#include "local_video_track.h"
2323
#include "participant.h"
24+
#include "remote_participant.h"
2425
#include "room.h"
2526
#include "room_delegate.h"
2627
#include "track_publication.h"

include/livekit/local_track_publication.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ class Track;
2828

2929
class LocalTrackPublication : public TrackPublication {
3030
public:
31-
/// Construct from an OwnedTrackPublication proto.
31+
/// Note, this RemoteTrackPublication is constructed internally only;
32+
/// safe to accept proto::OwnedTrackPublication.
3233
explicit LocalTrackPublication(const proto::OwnedTrackPublication &owned);
3334

3435
/// Typed accessor for the attached LocalTrack (if any).

include/livekit/participant.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Participant {
4141
metadata_(std::move(metadata)), attributes_(std::move(attributes)),
4242
kind_(kind), reason_(reason) {}
4343

44-
// Plain getters/setters (caller ensures threading)
44+
// Plain getters (caller ensures threading)
4545
const std::string &sid() const noexcept { return sid_; }
4646
const std::string &name() const noexcept { return name_; }
4747
const std::string &identity() const noexcept { return identity_; }
@@ -55,6 +55,24 @@ class Participant {
5555

5656
uintptr_t ffiHandleId() const noexcept { return handle_.get(); }
5757

58+
// Setters (caller ensures threading)
59+
void set_name(std::string name) noexcept { name_ = std::move(name); }
60+
void set_metadata(std::string metadata) noexcept {
61+
metadata_ = std::move(metadata);
62+
}
63+
void
64+
set_attributes(std::unordered_map<std::string, std::string> attrs) noexcept {
65+
attributes_ = std::move(attrs);
66+
}
67+
void set_attribute(const std::string &key, const std::string &value) {
68+
attributes_[key] = value;
69+
}
70+
void remove_attribute(const std::string &key) { attributes_.erase(key); }
71+
void set_kind(ParticipantKind kind) noexcept { kind_ = kind; }
72+
void set_disconnect_reason(DisconnectReason reason) noexcept {
73+
reason_ = reason;
74+
}
75+
5876
private:
5977
FfiHandle handle_;
6078
std::string sid_, name_, identity_, metadata_;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright 2025 LiveKit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an “AS IS” BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include "participant.h"
20+
21+
#include <memory>
22+
#include <string>
23+
#include <unordered_map>
24+
25+
namespace livekit {
26+
27+
class RemoteTrackPublication;
28+
29+
class RemoteParticipant : public Participant {
30+
public:
31+
using TrackPublicationMap =
32+
std::unordered_map<std::string, std::shared_ptr<RemoteTrackPublication>>;
33+
34+
RemoteParticipant(FfiHandle handle, std::string sid, std::string name,
35+
std::string identity, std::string metadata,
36+
std::unordered_map<std::string, std::string> attributes,
37+
ParticipantKind kind, DisconnectReason reason);
38+
39+
// A dictionary of track publications associated with the participant.
40+
const TrackPublicationMap &track_publications() const noexcept {
41+
return track_publications_;
42+
}
43+
44+
// Optional: non-const access if you want to mutate in-place.
45+
TrackPublicationMap &mutable_track_publications() noexcept {
46+
return track_publications_;
47+
}
48+
49+
// C++ equivalent of Python's __repr__
50+
std::string to_string() const;
51+
52+
private:
53+
TrackPublicationMap track_publications_;
54+
};
55+
56+
// Convenience for logging / streaming
57+
std::ostream &operator<<(std::ostream &os,
58+
const RemoteParticipant &participant);
59+
60+
} // namespace livekit

include/livekit/remote_track_publication.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class Track;
2828

2929
class RemoteTrackPublication : public TrackPublication {
3030
public:
31+
/// Note, this RemoteTrackPublication is constructed internally only;
32+
/// safe to accept proto::OwnedTrackPublication.
3133
explicit RemoteTrackPublication(const proto::OwnedTrackPublication &owned);
3234

3335
/// Typed accessor for the attached RemoteTrack (if any).

include/livekit/room.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class FfiEvent;
3232
}
3333

3434
class LocalParticipant;
35+
class RemoteParticipant;
3536

3637
class Room {
3738
public:
@@ -43,6 +44,7 @@ class Room {
4344
// Accessors
4445
RoomInfoData room_info() const;
4546
LocalParticipant *local_participant() const;
47+
RemoteParticipant *remote_participant(const std::string &identity) const;
4648

4749
private:
4850
mutable std::mutex lock_;
@@ -51,6 +53,8 @@ class Room {
5153
RoomInfoData room_info_;
5254
std::shared_ptr<FfiHandle> room_handle_;
5355
std::unique_ptr<LocalParticipant> local_participant_;
56+
std::unordered_map<std::string, std::unique_ptr<RemoteParticipant>>
57+
remote_participants_;
5458

5559
void OnEvent(const proto::FfiEvent &event);
5660
};

include/livekit/track_publication.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include <vector>
2323

2424
#include "livekit/ffi_handle.h"
25-
#include "livekit/track.h" // TrackKind, TrackSource, AudioTrackFeature
25+
#include "livekit/track.h"
2626

2727
namespace livekit {
2828

include/livekit/video_frame.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ struct VideoPlaneInfo {
4444
std::uint32_t size; // plane size in bytes
4545
};
4646

47+
namespace proto {
48+
class OwnedVideoBuffer;
49+
}
50+
4751
/**
4852
* Public SDK representation of a video frame.
4953
*
@@ -63,16 +67,6 @@ class LKVideoFrame {
6367
LKVideoFrame(LKVideoFrame &&) noexcept = default;
6468
LKVideoFrame &operator=(LKVideoFrame &&) noexcept = default;
6569

66-
/* LKVideoFrame(LKVideoFrame&& other) noexcept
67-
: width_(other.width_),
68-
height_(other.height_),
69-
type_(other.type_),
70-
data_(std::move(other.data_)) {
71-
other.width_ = 0;
72-
other.height_ = 0;
73-
}
74-
LKVideoFrame& operator=(LKVideoFrame&& other) noexcept;*/
75-
7670
/**
7771
* Allocate a new frame with the correct buffer size for the given format.
7872
* Data is zero-initialized.
@@ -123,6 +117,12 @@ class LKVideoFrame {
123117
*/
124118
LKVideoFrame convert(VideoBufferType dst, bool flip_y = false) const;
125119

120+
protected:
121+
friend class VideoStream;
122+
// Only internal classes (e.g., VideoStream)
123+
// should construct frames directly from FFI buffers.
124+
static LKVideoFrame fromOwnedInfo(const proto::OwnedVideoBuffer &owned);
125+
126126
private:
127127
int width_;
128128
int height_;

0 commit comments

Comments
 (0)