VLink  2.0.0
A high-performance communication middleware
vcap_reader.h
浏览该文件的文档.
1 /*
2  * Copyright (C) 2026 by Thun Lu. All rights reserved.
3  * Author: Thun Lu <thun.lu@zohomail.cn>
4  * Repo: https://github.com/thun-res/vlink
5  * _ __ __ _ __
6  * | | / / / / (_) ____ / /__
7  * | | / / / / / / / __ \ / //_/
8  * | |/ / / /___ / / / / / / / ,<
9  * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 
24 /**
25  * @file vcap_reader.h
26  * @brief Indexed playback of MCAP-format bag files (@c .vcap / @c .vcapx).
27  *
28  * @details
29  * @c VCAPReader concretises @c BagReader for the MCAP container used by Foxglove Studio and
30  * other MCAP-compatible visualisers. Splits captured into @c .vcapx manifests are followed
31  * transparently; @c reindex() and @c fix() resolve to @c false because MCAP itself owns the
32  * footer index and does not support in-place repair through this implementation.
33  *
34  * @par VCAP file format
35  * @code
36  * +---------------------------------------------------------------+
37  * | MCAP magic + header |
38  * +---------------------------------------------------------------+
39  * | schemas (encoded SchemaData) | <- detect_schema() enumerates these
40  * +---------------------------------------------------------------+
41  * | channels (topic url -> schema) |
42  * +---------------------------------------------------------------+
43  * | message chunks (optionally Zstd compressed) | <- streamed during play()
44  * +---------------------------------------------------------------+
45  * | attachments / metadata |
46  * +---------------------------------------------------------------+
47  * | summary section (message + chunk + channel + schema indexes) | <- used for fast seek / jump
48  * +---------------------------------------------------------------+
49  * | footer (offset of summary section) |
50  * +---------------------------------------------------------------+
51  * @endcode
52  *
53  * @par Reader states
54  * @code
55  * +---------+ play() +---------+ pause() +---------+
56  * | stopped | --------------> | playing | --------------> | paused |
57  * +---------+ +---------+ +---------+
58  * ^ | ^ |
59  * | | | resume() / pause_to_next()|
60  * +--- stop() or EOF -------+ +--------------------------+
61  * |
62  * | jump(time, rate, times)
63  * v
64  * +---------+
65  * | seeking | briefly during random access
66  * +---------+
67  * @endcode
68  *
69  * @par Example
70  * @code
71  * auto reader = vlink::BagReader::create("/data/recording.vcap");
72  *
73  * reader->register_output_callback([](const vlink::Frame& frame) {
74  * VLOG_I(frame.timestamp, " ", frame.url, " bytes=", frame.data.size());
75  * });
76  *
77  * reader->async_run();
78  * reader->play({});
79  * @endcode
80  *
81  * @see BagReader, VDBReader
82  */
83 
84 #pragma once
85 
86 #include <future>
87 #include <memory>
88 #include <string>
89 #include <vector>
90 
91 #include "./bag_reader.h"
92 
93 namespace vlink {
94 
95 /**
96  * @class VCAPReader
97  * @brief Concrete MCAP-format @c BagReader implementation with index-driven seek.
98  *
99  * @details
100  * Prefer @c BagReader::create() for format-agnostic instantiation; instantiate this class
101  * directly only when an MCAP-specific feature is required.
102  */
103 class VLINK_EXPORT VCAPReader final : public BagReader {
104  public:
105  /**
106  * @brief Opens an MCAP file for playback.
107  *
108  * @param path Filesystem path of the @c .vcap or @c .vcapx file.
109  * @param read_only @c true blocks any in-place modification (default).
110  * @param try_to_fix @c true enables a fallback summary scan when the indexed summary is unreadable.
111  */
112  explicit VCAPReader(const std::string& path, bool read_only = true, bool try_to_fix = false);
113 
114  /**
115  * @brief Stops playback and releases the MCAP file handle.
116  */
117  ~VCAPReader() override;
118 
119  /**
120  * @brief Attaches a @c BagPluginInterface for custom URL or type rewriting.
121  *
122  * @param plugin_interface Plugin instance; pass @c nullptr to detach.
123  */
124  void bind_plugin_interface(const std::shared_ptr<BagPluginInterface>& plugin_interface) override;
125 
126  /**
127  * @brief Registers a callback invoked on every playback state transition.
128  *
129  * @param status_callback Receives the new @c Status value.
130  */
131  void register_status_callback(StatusCallback&& status_callback) override;
132 
133  /**
134  * @brief Registers a callback fired once the file is open, parsed, and ready to play.
135  *
136  * @param ready_callback Invoked when the reader transitions out of opening state.
137  */
138  void register_ready_callback(ReadyCallback&& ready_callback) override;
139 
140  /**
141  * @brief Registers a callback fired when playback ends naturally or is interrupted.
142  *
143  * @param finish_callback Receives a flag indicating whether playback was interrupted.
144  */
145  void register_finish_callback(FinishCallback&& finish_callback) override;
146 
147  /**
148  * @brief Registers the message-delivery callback consumed during playback.
149  *
150  * @param output_callback Invoked for each replayed message.
151  */
152  void register_output_callback(OutputCallback&& output_callback) override;
153 
154  /**
155  * @brief Starts playback with the given configuration.
156  *
157  * @param config Playback configuration (start / end times, rate, filters, loop count).
158  */
159  void play(const Config& config) override;
160 
161  /**
162  * @brief Stops playback and rewinds to the recording start.
163  */
164  void stop() override;
165 
166  /**
167  * @brief Pauses playback at the current position.
168  */
169  void pause() override;
170 
171  /**
172  * @brief Resumes paused playback from the current position.
173  */
174  void resume() override;
175 
176  /**
177  * @brief Emits one more message and then pauses again.
178  */
179  void pause_to_next() override;
180 
181  /**
182  * @brief Seeks to @p begin_time and resumes playback at the new position.
183  *
184  * @param begin_time Target timestamp in milliseconds, relative to recording start.
185  * @param rate Playback rate multiplier applied after the seek.
186  * @param times Number of loop iterations after the jump.
187  * @param force_to_play @c true forces play state even if currently paused.
188  */
189  void jump(int64_t begin_time, double rate, int times, bool force_to_play = false) override;
190 
191  /**
192  * @brief Verifies the integrity of the MCAP file asynchronously.
193  *
194  * @return Future resolving to @c true when the file passes the integrity check.
195  */
196  std::future<bool> check() override;
197 
198  /**
199  * @brief Unsupported MCAP reindex operation.
200  *
201  * @return Future that always resolves to @c false.
202  */
203  std::future<bool> reindex() override;
204 
205  /**
206  * @brief Unsupported MCAP repair operation.
207  *
208  * @param rebuild Ignored.
209  * @return Future that always resolves to @c false.
210  */
211  std::future<bool> fix(bool rebuild = false) override;
212 
213  /**
214  * @brief Updates the @c .vcapx manifest tag. Single @c .vcap files are left untouched.
215  *
216  * @param tag_name New tag string.
217  */
218  void tag(const std::string& tag_name) override;
219 
220  /**
221  * @brief Returns the current playback cursor in milliseconds.
222  *
223  * @return Position relative to the recording start.
224  */
225  [[nodiscard]] int64_t get_timestamp() const override;
226 
227  /**
228  * @brief Returns the timestamp of the last delivered message.
229  *
230  * @return Last data timestamp in milliseconds, or @c 0 when stopped.
231  */
232  [[nodiscard]] int64_t get_real_timestamp() const override;
233 
234  /**
235  * @brief Returns the playback status.
236  *
237  * @return One of @c kStopped, @c kPaused, or @c kPlaying.
238  */
239  [[nodiscard]] Status get_status() const override;
240 
241  /**
242  * @brief Returns the bag metadata populated when the file was opened.
243  *
244  * @return Const reference to the @c Info struct.
245  */
246  [[nodiscard]] const Info& get_info() const override;
247 
248  /**
249  * @brief Enumerates every schema embedded in the MCAP file.
250  *
251  * @return Vector of @c SchemaData descriptors.
252  */
253  [[nodiscard]] std::vector<SchemaData> detect_schema() override;
254 
255  /**
256  * @brief Reports whether the bag is split across multiple @c .vcap files.
257  *
258  * @return @c true when reading a @c .vcapx manifest with multiple parts.
259  */
260  [[nodiscard]] bool is_split_mode() const override;
261 
262  /**
263  * @brief Returns the index of the split part currently under playback.
264  *
265  * @return Zero-based split index.
266  */
267  [[nodiscard]] int get_split_index() const override;
268 
269  /**
270  * @brief Reports whether a @c jump() seek is currently being processed.
271  *
272  * @return @c true while a seek is in flight.
273  */
274  [[nodiscard]] bool is_jumping() const override;
275 
276  protected:
277  size_t get_max_task_count() const override;
278 
279  void on_begin() override;
280 
281  void on_end() override;
282 
283  bool do_open_cursor(const Config& config) override;
284 
285  bool do_read_next(Frame& out, bool& is_error) override;
286 
287  private:
288  bool prepare_cursor_view(int file_index);
289 
290  void update_status(Status status);
291 
292  void do_stop();
293 
294  void do_pause();
295 
296  bool prepare_file(void* file);
297 
298  void open(const std::string& path);
299 
300  void close();
301 
302  int get_reset_index(const Config& config);
303 
304  void read(const Config& config);
305 
306  struct Impl;
307  std::unique_ptr<Impl> impl_;
308 
310 };
311 
312 } // namespace vlink
Abstract player for VLink bag recordings with seek, loop and rate control.
#define VLINK_EXPORT
Definition: macros.h:81
#define VLINK_DISALLOW_COPY_AND_ASSIGN(classname)
Deletes the copy constructor and copy-assignment operator of classname.
Definition: macros.h:174