1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
media / filters / chunk_demuxer.h [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_FILTERS_CHUNK_DEMUXER_H_
#define MEDIA_FILTERS_CHUNK_DEMUXER_H_
#include <stddef.h>
#include <stdint.h>
#include <map>
#include <set>
#include <string>
#include <vector>
#include "base/containers/circular_deque.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/raw_ptr.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "base/time/time.h"
#include "media/base/demuxer.h"
#include "media/base/demuxer_stream.h"
#include "media/base/media_tracks.h"
#include "media/base/ranges.h"
#include "media/base/stream_parser.h"
#include "media/filters/source_buffer_parse_warnings.h"
#include "media/filters/source_buffer_state.h"
#include "media/filters/source_buffer_stream.h"
#include "media/filters/stream_parser_factory.h"
namespace media {
class SourceBufferStream;
class AudioDecoderConfig;
class VideoDecoderConfig;
class MEDIA_EXPORT ChunkDemuxerStream : public DemuxerStream {
public:
using BufferQueue = base::circular_deque<scoped_refptr<StreamParserBuffer>>;
ChunkDemuxerStream() = delete;
ChunkDemuxerStream(Type type, MediaTrack::Id media_track_id);
ChunkDemuxerStream(const ChunkDemuxerStream&) = delete;
ChunkDemuxerStream& operator=(const ChunkDemuxerStream&) = delete;
~ChunkDemuxerStream() override;
// ChunkDemuxerStream control methods.
void StartReturningData();
void AbortReads();
void CompletePendingReadIfPossible();
void Shutdown();
// SourceBufferStream manipulation methods.
void Seek(base::TimeDelta time);
bool IsSeekWaitingForData() const;
// Add buffers to this stream. Buffers are stored in SourceBufferStreams,
// which handle ordering and overlap resolution.
// Returns true if buffers were successfully added.
bool Append(const StreamParser::BufferQueue& buffers);
// Removes buffers between |start| and |end| according to the steps
// in the "Coded Frame Removal Algorithm" in the Media Source
// Extensions Spec.
// https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-coded-frame-removal
//
// |duration| is the current duration of the presentation. It is
// required by the computation outlined in the spec.
void Remove(base::TimeDelta start, base::TimeDelta end,
base::TimeDelta duration);
// If the buffer is full, attempts to try to free up space, as specified in
// the "Coded Frame Eviction Algorithm" in the Media Source Extensions Spec.
// Returns false iff buffer is still full after running eviction.
// https://w3c.github.io/media-source/#sourcebuffer-coded-frame-eviction
bool EvictCodedFrames(base::TimeDelta media_time, size_t newDataSize);
void OnMemoryPressure(
base::TimeDelta media_time,
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level,
bool force_instant_gc);
// Signal to the stream that duration has changed to |duration|.
void OnSetDuration(base::TimeDelta duration);
// Returns the range of buffered data in this stream, capped at |duration|.
Ranges<base::TimeDelta> GetBufferedRanges(base::TimeDelta duration) const;
// Returns the lowest PTS of the buffered data.
// Returns base::TimeDelta() if the stream has no buffered data.
base::TimeDelta GetLowestPresentationTimestamp() const;
// Returns the highest PTS of the buffered data.
// Returns base::TimeDelta() if the stream has no buffered data.
base::TimeDelta GetHighestPresentationTimestamp() const;
// Returns the duration of the buffered data.
// Returns base::TimeDelta() if the stream has no buffered data.
base::TimeDelta GetBufferedDuration() const;
// Returns the memory usage of the buffered data in bytes.
size_t GetMemoryUsage() const;
// Signal to the stream that buffers handed in through subsequent calls to
// Append() belong to a coded frame group that starts at |start_pts|.
// |start_dts| is used only to help tests verify correctness of calls to this
// method. If |group_start_observer_cb_| is set, first invokes this test-only
// callback with |start_dts| and |start_pts| to assist test verification.
void OnStartOfCodedFrameGroup(DecodeTimestamp start_dts,
base::TimeDelta start_pts);
// Called when midstream config updates occur.
// For audio and video, if the codec is allowed to change, the caller should
// set |allow_codec_change| to true.
// Returns true if the new config is accepted.
// Returns false if the new config should trigger an error.
bool UpdateAudioConfig(const AudioDecoderConfig& config,
bool allow_codec_change,
MediaLog* media_log);
bool UpdateVideoConfig(const VideoDecoderConfig& config,
bool allow_codec_change,
MediaLog* media_log);
void MarkEndOfStream();
void UnmarkEndOfStream();
// DemuxerStream methods.
void Read(uint32_t count, ReadCB read_cb) override;
Type type() const override;
StreamLiveness liveness() const override;
AudioDecoderConfig audio_decoder_config() override;
VideoDecoderConfig video_decoder_config() override;
bool SupportsConfigChanges() override;
bool IsEnabled() const;
void SetEnabled(bool enabled, base::TimeDelta timestamp);
// Sets the memory limit, in bytes, on the SourceBufferStream.
void SetStreamMemoryLimit(size_t memory_limit);
void SetLiveness(StreamLiveness liveness);
MediaTrack::Id media_track_id() const { return media_track_id_; }
// Allows tests to verify invocations of Append().
using AppendObserverCB = base::RepeatingCallback<void(const BufferQueue*)>;
void set_append_observer_for_testing(AppendObserverCB append_observer_cb) {
append_observer_cb_ = std::move(append_observer_cb);
}
// Allows tests to verify invocations of OnStartOfCodedFrameGroup().
using GroupStartObserverCB =
base::RepeatingCallback<void(DecodeTimestamp, base::TimeDelta)>;
void set_group_start_observer_for_testing(
GroupStartObserverCB group_start_observer_cb) {
group_start_observer_cb_ = std::move(group_start_observer_cb);
}
private:
enum State {
UNINITIALIZED,
RETURNING_DATA_FOR_READS,
RETURNING_ABORT_FOR_READS,
SHUTDOWN,
};
// Assigns |state_| to |state|
void ChangeState_Locked(State state) EXCLUSIVE_LOCKS_REQUIRED(lock_);
void CompletePendingReadIfPossible_Locked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
std::pair<SourceBufferStreamStatus, DemuxerStream::DecoderBufferVector>
GetPendingBuffers_Locked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
// Specifies the type of the stream.
const Type type_;
StreamLiveness liveness_ GUARDED_BY(lock_);
std::unique_ptr<SourceBufferStream> stream_ GUARDED_BY(lock_);
const MediaTrack::Id media_track_id_;
// Test-only callbacks to assist verification of Append() and
// OnStartOfCodedFrameGroup() calls, respectively.
AppendObserverCB append_observer_cb_;
GroupStartObserverCB group_start_observer_cb_;
// Requested buffer count. The actual returned buffer count could be less
// according to DemuxerStream::Read() API.
uint32_t requested_buffer_count_ = 0;
mutable base::Lock lock_;
State state_ GUARDED_BY(lock_);
ReadCB read_cb_ GUARDED_BY(lock_);
bool is_enabled_ GUARDED_BY(lock_);
};
// Demuxer implementation that allows chunks of media data to be passed
// from JavaScript to the media stack.
class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
public:
enum Status {
kOk, // ID added w/o error.
kNotSupported, // Type specified is not supported.
kReachedIdLimit, // Reached ID limit. We can't handle any more IDs.
};
// |open_cb| Run when Initialize() is called to signal that the demuxer
// is ready to receive media data via AppendToParseBuffer()/AppendChunks().
// |progress_cb| Run each time data is appended.
// |encrypted_media_init_data_cb| Run when the demuxer determines that an
// encryption key is needed to decrypt the content.
// |media_log| Used to report content and engine debug messages.
ChunkDemuxer(base::OnceClosure open_cb,
base::RepeatingClosure progress_cb,
EncryptedMediaInitDataCB encrypted_media_init_data_cb,
MediaLog* media_log);
ChunkDemuxer(const ChunkDemuxer&) = delete;
ChunkDemuxer& operator=(const ChunkDemuxer&) = delete;
~ChunkDemuxer() override;
// Demuxer implementation.
std::string GetDisplayName() const override;
DemuxerType GetDemuxerType() const override;
void Initialize(DemuxerHost* host, PipelineStatusCallback init_cb) override;
void Stop() override;
void Seek(base::TimeDelta time, PipelineStatusCallback cb) override;
bool IsSeekable() const override;
base::Time GetTimelineOffset() const override;
std::vector<DemuxerStream*> GetAllStreams() override;
base::TimeDelta GetStartTime() const override;
int64_t GetMemoryUsage() const override;
std::optional<container_names::MediaContainerName> GetContainerForMetrics()
const override;
void AbortPendingReads() override;
// ChunkDemuxer reads are abortable. StartWaitingForSeek() and
// CancelPendingSeek() always abort pending and future reads until the
// expected seek occurs, so that ChunkDemuxer can stay synchronized with the
// associated JS method calls.
void StartWaitingForSeek(base::TimeDelta seek_time) override;
void CancelPendingSeek(base::TimeDelta seek_time) override;
// Registers a new `id` to use for AppendToParseBuffer(),
// RunSegmentParserLoop(), AppendChunks(), etc calls. `content_type` indicates
// the MIME type's ContentType and `codecs` indicates the MIME type's "codecs"
// parameter string (if any) for the data that we intend to append for this
// ID. kOk is returned if the demuxer has enough resources to support another
// ID and supports the format indicated by `content_type` and `codecs`.
// kReachedIdLimit is returned if the demuxer cannot handle another ID right
// now. kNotSupported is returned if `content_type` and `codecs` is not a
// supported format.
// The `audio_config` and `video_config` overloads behave similarly, except
// the caller must provide valid, supported decoder configs; those overloads'
// usage indicates that we intend to append WebCodecs encoded audio or video
// chunks for this ID.
[[nodiscard]] Status AddId(const std::string& id,
const std::string& content_type,
const std::string& codecs);
[[nodiscard]] Status AddId(const std::string& id,
std::unique_ptr<AudioDecoderConfig> audio_config);
[[nodiscard]] Status AddId(const std::string& id,
std::unique_ptr<VideoDecoderConfig> video_config);
// `AddAutoDetectedCodecsId` operates similarly to the `AddId` methods, except
// that it creates parsers which are capable of auto-detecting the codecs
// present. It is used internally by the HLS demuxer.
#if BUILDFLAG(ENABLE_HLS_DEMUXER)
[[nodiscard]] Status AddAutoDetectedCodecsId(
const std::string& id,
RelaxedParserSupportedType mime_type);
#endif
// Notifies a caller via `tracks_updated_cb` that the set of media tracks
// for a given `id` has changed. This callback must be set before any calls to
// AppendToParseBuffer() for this `id`.
void SetTracksWatcher(const std::string& id,
MediaTracksUpdatedCB tracks_updated_cb);
// Notifies a caller via `parse_warning_cb` of a parse warning. This callback
// must be set before any calls to AppendToParseBuffer() for this `id`.
void SetParseWarningCallback(const std::string& id,
SourceBufferParseWarningCB parse_warning_cb);
// Removed an ID & associated resources that were previously added with
// AddId().
void RemoveId(const std::string& id);
// Gets the currently buffered ranges for the specified ID.
Ranges<base::TimeDelta> GetBufferedRanges(const std::string& id) const;
// Gets the lowest buffered PTS for the specified |id|. If there is nothing
// buffered, returns base::TimeDelta().
base::TimeDelta GetLowestPresentationTimestamp(const std::string& id) const;
// Gets the highest buffered PTS for the specified |id|. If there is nothing
// buffered, returns base::TimeDelta().
base::TimeDelta GetHighestPresentationTimestamp(const std::string& id) const;
void OnEnabledAudioTracksChanged(const std::vector<MediaTrack::Id>& track_ids,
base::TimeDelta curr_time,
TrackChangeCB change_completed_cb) override;
void OnSelectedVideoTrackChanged(const std::vector<MediaTrack::Id>& track_ids,
base::TimeDelta curr_time,
TrackChangeCB change_completed_cb) override;
void SetPlaybackRate(double rate) override {}
void DisableCanChangeType() override;
// Appends media data to the source buffer's stream parser associated with
// `id`. No parsing is done, just buffering the media data for future parsing
// via RunSegmentParserLoop calls. Returns true on success. Returns false if
// the parser was unable to allocate resources; content in `data` is not
// copied as a result, and this failure is reported (through various layers)
// up to the SourceBuffer's implementation of appendBuffer(), which should
// then notify the app of append failure using a `QuotaExceededErr` exception
// per the MSE specification. App could use a back-off and retry strategy or
// otherwise alter their behavior to attempt to buffer media for further
// playback.
[[nodiscard]] bool AppendToParseBuffer(const std::string& id,
base::span<const uint8_t> data);
// Tells the stream parser for the source buffer associated with `id` to parse
// more of the data previously sent to it from this object's
// AppendToParseBuffer(). This operation applies and possibly updates
// `*timestamp_offset` during coded frame processing. `append_window_start`
// and `append_window_end` correspond to the MSE spec's similarly named source
// buffer attributes that are used in coded frame processing.
// Returns kSuccess if the segment parser loop iteration succeeded and all
// previously provided data from AppendToParseBuffer() has been inspected.
// Returns kSuccessHasMoreData if the segment parser loop iteration succeeded,
// yet there remains uninspected data remaining from AppendToParseBuffer();
// more call(s) to this method are necessary for the parser to attempt
// inspection of that data.
// Returns kFailed if the segment parser loop iteration hit error and the
// caller needs to run the append error algorithm with decode error parameter
// set to true.
[[nodiscard]] StreamParser::ParseStatus RunSegmentParserLoop(
const std::string& id,
base::TimeDelta append_window_start,
base::TimeDelta append_window_end,
base::TimeDelta* timestamp_offset);
// Appends webcodecs encoded chunks (already converted by caller into a
// BufferQueue of StreamParserBuffers) to the source buffer associated with
// |id|, with same semantic for other parameters and return value as
// RunSegmentParserLoop().
[[nodiscard]] bool AppendChunks(
const std::string& id,
std::unique_ptr<StreamParser::BufferQueue> buffer_queue,
base::TimeDelta append_window_start,
base::TimeDelta append_window_end,
base::TimeDelta* timestamp_offset);
// Aborts parsing the current segment and reset the parser to a state where
// it can accept a new segment.
// Some pending frames can be emitted during that process. These frames are
// applied |timestamp_offset|.
void ResetParserState(const std::string& id,
base::TimeDelta append_window_start,
base::TimeDelta append_window_end,
base::TimeDelta* timestamp_offset);
// Remove buffers between |start| and |end| for the source buffer
// associated with |id|.
void Remove(const std::string& id, base::TimeDelta start,
base::TimeDelta end);
// Returns whether or not the source buffer associated with |id| can change
// its parser type to one which parses |content_type| and |codecs|.
// |content_type| indicates the ContentType of the MIME type for the data that
// we intend to append for this |id|; |codecs| similarly indicates the MIME
// type's "codecs" parameter, if any.
bool CanChangeType(const std::string& id,
const std::string& content_type,
const std::string& codecs);
// For the source buffer associated with |id|, changes its parser type to one
// which parses |content_type| and |codecs|. |content_type| indicates the
// ContentType of the MIME type for the data that we intend to append for this
// |id|; |codecs| similarly indicates the MIME type's "codecs" parameter, if
// any. Caller must first ensure CanChangeType() returns true for the same
// parameters. Caller must also ensure that ResetParserState() is done before
// calling this, to flush any pending frames.
void ChangeType(const std::string& id,
const std::string& content_type,
const std::string& codecs);
// If the buffer is full, attempts to try to free up space, as specified in
// the "Coded Frame Eviction Algorithm" in the Media Source Extensions Spec.
// Returns false iff buffer is still full after running eviction.
// https://w3c.github.io/media-source/#sourcebuffer-coded-frame-eviction
[[nodiscard]] bool EvictCodedFrames(const std::string& id,
base::TimeDelta currentMediaTime,
size_t newDataSize);
void OnMemoryPressure(
base::TimeDelta currentMediaTime,
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level,
bool force_instant_gc);
// Returns the current presentation duration.
double GetDuration();
double GetDuration_Locked();
// Notifies the demuxer that the duration of the media has changed to
// |duration|.
void SetDuration(double duration);
// Returns true if the source buffer associated with |id| is currently parsing
// a media segment, or false otherwise.
bool IsParsingMediaSegment(const std::string& id);
// Returns the 'Generate Timestamps Flag', as described in the MSE Byte Stream
// Format Registry, for the source buffer associated with |id|.
bool GetGenerateTimestampsFlag(const std::string& id);
// Set the append mode to be applied to subsequent buffers appended to the
// source buffer associated with |id|. If |sequence_mode| is true, caller
// is requesting "sequence" mode. Otherwise, caller is requesting "segments"
// mode.
void SetSequenceMode(const std::string& id, bool sequence_mode);
// Signals the coded frame processor for the source buffer associated with
// |id| to update its group start timestamp to be |timestamp_offset| if it is
// in sequence append mode.
void SetGroupStartTimestampIfInSequenceMode(const std::string& id,
base::TimeDelta timestamp_offset);
// Called to signal changes in the "end of stream"
// state. UnmarkEndOfStream() must not be called if a matching
// MarkEndOfStream() has not come before it.
void MarkEndOfStream(PipelineStatus status);
void UnmarkEndOfStream();
void Shutdown();
// Sets the memory limit on each stream of a specific type.
// |memory_limit| is the maximum number of bytes each stream of type |type|
// is allowed to hold in its buffer.
void SetMemoryLimitsForTest(DemuxerStream::Type type, size_t memory_limit);
// Returns the ranges representing the buffered data in the demuxer.
// TODO(wolenetz): Remove this method once MediaSourceDelegate no longer
// requires it for doing hack browser seeks to I-frame on Android. See
// http://crbug.com/304234.
Ranges<base::TimeDelta> GetBufferedRanges() const;
private:
enum State {
WAITING_FOR_INIT = 0,
INITIALIZING,
INITIALIZED,
ENDED,
// Any State at or beyond PARSE_ERROR cannot be changed to a state before
// this. See ChangeState_Locked.
PARSE_ERROR,
SHUTDOWN,
};
// Helper for AddId's creation of FrameProcessor, and
// SourceBufferState creation, initialization and tracking in
// source_state_map_.
ChunkDemuxer::Status AddIdInternal(
const std::string& id,
std::unique_ptr<media::StreamParser> stream_parser,
std::optional<std::string_view> expected_codecs);
// Helper for video and audio track changing. For the `track_type`, enables
// tracks associated with `track_ids` and disables the rest. Fires
// `change_completed_cb` when the operation is completed.
void FindAndEnableProperTracks(const std::vector<MediaTrack::Id>& track_ids,
base::TimeDelta curr_time,
DemuxerStream::Type track_type,
TrackChangeCB change_completed_cb);
void ChangeState_Locked(State new_state);
// Reports an error and puts the demuxer in a state where it won't accept more
// data.
void ReportError_Locked(PipelineStatus error);
// Returns true if any stream has seeked to a time without buffered data.
bool IsSeekWaitingForData_Locked() const;
// Returns true if all streams can successfully call EndOfStream,
// false if any can not.
bool CanEndOfStream_Locked() const;
// SourceBufferState callbacks.
void OnSourceInitDone(const std::string& source_id,
const StreamParser::InitParameters& params);
// Creates a DemuxerStream of the specified |type| for the SourceBufferState
// with the given |source_id|.
// Returns a pointer to a new ChunkDemuxerStream instance, which is owned by
// ChunkDemuxer.
ChunkDemuxerStream* CreateDemuxerStream(const std::string& source_id,
DemuxerStream::Type type);
// Returns true if |source_id| is valid, false otherwise.
bool IsValidId_Locked(const std::string& source_id) const;
// Increases |duration_| to |new_duration|, if |new_duration| is higher.
void IncreaseDurationIfNecessary(base::TimeDelta new_duration);
// Decreases |duration_| if the buffered region is less than |duration_| when
// EndOfStream() is called.
void DecreaseDurationIfNecessary();
// Sets |duration_| to |new_duration|, sets |user_specified_duration_| to -1
// and notifies |host_|.
void UpdateDuration(base::TimeDelta new_duration);
// Returns the ranges representing the buffered data in the demuxer.
Ranges<base::TimeDelta> GetBufferedRanges_Locked() const;
// Start returning data on all DemuxerStreams.
void StartReturningData();
void AbortPendingReads_Locked();
// Completes any pending reads if it is possible to do so.
void CompletePendingReadsIfPossible();
// Seeks all SourceBufferStreams to |seek_time|.
void SeekAllSources(base::TimeDelta seek_time);
// Generates and returns a unique media track id.
static MediaTrack::Id GenerateMediaTrackId();
// Shuts down all DemuxerStreams by calling Shutdown() on
// all objects in |source_state_map_|.
void ShutdownAllStreams();
// Executes |init_cb_| with |status| and closes out the async trace.
void RunInitCB_Locked(PipelineStatus status);
// Executes |seek_cb_| with |status| and closes out the async trace.
void RunSeekCB_Locked(PipelineStatus status);
mutable base::Lock lock_;
State state_ = WAITING_FOR_INIT;
bool cancel_next_seek_ = false;
// Found dangling on `linux-rel` in
// `benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.
// system_health.memory_desktop/browse:media:youtubetv:2019`.
raw_ptr<DemuxerHost, DanglingUntriaged> host_ = nullptr;
base::OnceClosure open_cb_;
const base::RepeatingClosure progress_cb_;
EncryptedMediaInitDataCB encrypted_media_init_data_cb_;
// MediaLog for reporting messages and properties to debug content and engine.
raw_ptr<MediaLog> media_log_;
PipelineStatusCallback init_cb_;
// Callback to execute upon seek completion.
// TODO(wolenetz/acolwell): Protect against possible double-locking by first
// releasing |lock_| before executing this callback. See
// http://crbug.com/308226
PipelineStatusCallback seek_cb_;
using OwnedChunkDemuxerStreamVector =
std::vector<std::unique_ptr<ChunkDemuxerStream>>;
OwnedChunkDemuxerStreamVector audio_streams_;
OwnedChunkDemuxerStreamVector video_streams_;
// Keep track of which ids still remain uninitialized so that we transition
// into the INITIALIZED only after all ids/SourceBuffers got init segment.
std::set<std::string> pending_source_init_ids_;
base::TimeDelta duration_ = kNoTimestamp;
// The duration passed to the last SetDuration(). If SetDuration() is never
// called or a RunSegmentParserLoop()/AppendChunks() call or a EndOfStream()
// call changes `duration_`, then this variable is set to < 0 to indicate that
// the `duration_` represents the actual duration instead of a user specified
// value.
double user_specified_duration_ = -1;
base::Time timeline_offset_;
StreamLiveness liveness_ = StreamLiveness::kUnknown;
std::map<std::string, std::unique_ptr<SourceBufferState>> source_state_map_;
std::map<std::string, std::vector<ChunkDemuxerStream*>> id_to_streams_map_;
// Used to hold alive the demuxer streams that were created for removed /
// released SourceBufferState objects. Demuxer clients might still have
// references to these streams, so we need to keep them alive. But they'll be
// in a shut down state, so reading from them will return EOS.
std::vector<std::unique_ptr<ChunkDemuxerStream>> removed_streams_;
std::map<MediaTrack::Id, raw_ptr<ChunkDemuxerStream, CtnExperimental>>
track_id_to_demux_stream_map_;
bool supports_change_type_ = true;
};
} // namespace media
#endif // MEDIA_FILTERS_CHUNK_DEMUXER_H_