1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef MEDIA_FILTERS_HLS_DATA_SOURCE_PROVIDER_H_
6 #define MEDIA_FILTERS_HLS_DATA_SOURCE_PROVIDER_H_
11 #include "base/functional/callback.h"
12 #include "base/strings/string_piece_forward.h"
13 #include "base/types/id_type.h"
14 #include "media/base/media_export.h"
15 #include "media/base/status.h"
16 #include "media/formats/hls/types.h"
17 #include "third_party/abseil-cpp/absl/types/optional.h"
22 class HlsDataSourceStream;
24 // Interface which can provide data sources, given a URI and an optional
25 // byterange. This interface should be used via `base::SequenceBound` to proxy
26 // requests across the media thread and the main thread.
27 class MEDIA_EXPORT HlsDataSourceProvider {
29 virtual ~HlsDataSourceProvider() = 0;
31 struct ReadStatusTraits {
32 enum class Codes : StatusCodeType {
36 static constexpr StatusGroupType Group() {
37 return "HlsDataSourceProvider::ReadStatus";
41 using ReadStatus = TypedStatus<ReadStatusTraits>;
42 using ReadResult = ReadStatus::Or<std::unique_ptr<HlsDataSourceStream>>;
43 using ReadCb = base::OnceCallback<void(ReadResult)>;
45 // Kicks off a read from the given url and the optional constrained byterange
46 // and replies with a stream reference, which can be use to continue reading
47 // and to extract already fetched data.
48 virtual void ReadFromUrl(GURL uri,
49 absl::optional<hls::types::ByteRange> range,
52 // Continues to read from an existing stream.
53 virtual void ReadFromExistingStream(
54 std::unique_ptr<HlsDataSourceStream> stream,
57 // Aborts all pending reads and calls `callback` when finished.
58 virtual void AbortPendingReads(base::OnceClosure callback) = 0;
61 // A buffer-owning wrapper for an HlsDataSource which can be instructed to
62 // read an entire data source, or to retrieve it in chunks.
63 class MEDIA_EXPORT HlsDataSourceStream {
65 // The response to a stream read includes a raw pointer back to the stream
66 // which allows accessing the data from a read as well as caching a partially
67 // read stream handle for continued downloading.
68 using StreamId = base::IdType32<HlsDataSourceStream>;
70 // Create a stream where `on_destructed_cb` is used to give notice that this
71 // class is being destroyed. This class isn't safe to access from anything
72 // except for an ownership-holding smart pointer, as the destruction cb may
73 // do work across threads.
74 HlsDataSourceStream(StreamId stream_id,
75 base::OnceClosure on_destructed_cb,
76 absl::optional<hls::types::ByteRange> range);
77 ~HlsDataSourceStream();
79 // Streams use an ID associated with a MultiBufferDataSource without
81 StreamId stream_id() const { return stream_id_; }
83 // This is the byte position in the MultiBufferDataSource where new data
84 // will be read from. This only ever goes up, because these streams are not
86 size_t read_position() const { return read_position_; }
88 size_t buffer_size() const { return buffer_.size(); }
90 absl::optional<size_t> max_read_position() const {
91 return max_read_position_;
94 const uint8_t* raw_data() const { return buffer_.data(); }
96 // Often the network data for HLS consists of plain-text manifest files, so
97 // this supports accessing the fetched data as a string view.
98 std::string_view AsString() const;
100 // Has the stream read all possible data?
101 bool CanReadMore() const;
103 // Clears the internal buffer of data. Continual reads will refill the buffer
104 // and reading without clearing will append to the end of the buffer.
107 // Used by a HlsDataSourceProvider implementation to finish adding data to
108 // the internal buffer.
109 void UnlockStreamPostWrite(int read_size, bool end_of_stream);
111 // Used by a HlsDataSourceProvider implementation to start adding new data,
112 // which means ensuring that there is enough space for the expected write, as
113 // well as returning the correct buffer address to write into.
114 uint8_t* LockStreamForWriting(int ensure_minimum_space);
117 const StreamId stream_id_;
119 // Active buffer data. Reading without clearing will append new data
120 // to the end of the buffer. Clearing will not reset the read-head, but will
121 // empty this buffer.
122 // TODO(crbug/1266991): Consider swapping out the vector with a more
123 // size-flexible data structure to avoid resizing.
124 std::vector<uint8_t> buffer_;
126 size_t read_position_ = 0;
128 // The write index into `buffer_`. This gets reset on flush.
129 size_t write_index_ = 0;
131 // If this optional value is set, then data can't be read past this maximum
133 absl::optional<size_t> max_read_position_;
135 // The data source read response indicated that the stream has ended.
136 bool reached_end_of_stream_ = false;
138 // The stream is unable to start a second write or clear until it is unlocked
139 // by UnlockStreamPostWrite.
140 bool stream_locked_ = false;
142 base::OnceClosure on_destructed_cb_;
144 SEQUENCE_CHECKER(sequence_checker_);
145 base::WeakPtrFactory<HlsDataSourceStream> weak_factory_{this};
150 #endif // MEDIA_FILTERS_HLS_DATA_SOURCE_PROVIDER_H_