1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef MEDIA_BASE_TEXT_RENDERER_H_
6#define MEDIA_BASE_TEXT_RENDERER_H_
7
8#include <map>
9#include <set>
10
11#include "base/callback.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/memory/weak_ptr.h"
14#include "media/base/demuxer_stream.h"
15#include "media/base/media_export.h"
16#include "media/base/pipeline_status.h"
17#include "media/base/text_ranges.h"
18#include "media/base/text_track.h"
19
20namespace base {
21class SingleThreadTaskRunner;
22}
23
24namespace media {
25
26class TextCue;
27class TextTrackConfig;
28
29// Receives decoder buffers from the upstream demuxer, decodes them to text
30// cues, and then passes them onto the TextTrack object associated with each
31// demuxer text stream.
32class MEDIA_EXPORT TextRenderer {
33 public:
34  // |task_runner| is the thread on which TextRenderer will execute.
35  //
36  // |add_text_track_cb] is called when the demuxer requests (via its host)
37  // that a new text track be created.
38  TextRenderer(
39      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
40      const AddTextTrackCB& add_text_track_cb);
41  ~TextRenderer();
42
43  // |ended_cb| is executed when all of the text tracks have reached
44  // end of stream, following a play request.
45  void Initialize(const base::Closure& ended_cb);
46
47  // Start text track cue decoding and rendering, executing |callback| when
48  // playback is underway.
49  void Play(const base::Closure& callback);
50
51  // Temporarily suspend decoding and rendering, executing |callback| when
52  // playback has been suspended.
53  void Pause(const base::Closure& callback);
54
55  // Discard any text data, executing |callback| when completed.
56  void Flush(const base::Closure& callback);
57
58  // Stop all operations in preparation for being deleted, executing |callback|
59  // when complete.
60  void Stop(const base::Closure& callback);
61
62  // Add new |text_stream|, having the indicated |config|, to the text stream
63  // collection managed by this text renderer.
64  void AddTextStream(DemuxerStream* text_stream,
65                     const TextTrackConfig& config);
66
67  // Remove |text_stream| from the text stream collection.
68  void RemoveTextStream(DemuxerStream* text_stream);
69
70  // Returns true if there are extant text tracks.
71  bool HasTracks() const;
72
73 private:
74  struct TextTrackState {
75    // To determine read progress.
76    enum ReadState {
77      kReadIdle,
78      kReadPending
79    };
80
81    explicit TextTrackState(scoped_ptr<TextTrack> text_track);
82    ~TextTrackState();
83
84    ReadState read_state;
85    scoped_ptr<TextTrack> text_track;
86    TextRanges text_ranges_;
87  };
88
89  // Callback delivered by the demuxer |text_stream| when
90  // a read from the stream completes.
91  void BufferReady(DemuxerStream* text_stream,
92                   DemuxerStream::Status status,
93                   const scoped_refptr<DecoderBuffer>& input);
94
95  // Dispatches the decoded cue delivered on the demuxer's |text_stream|.
96  void CueReady(DemuxerStream* text_stream,
97                const scoped_refptr<TextCue>& text_cue);
98
99  // Dispatched when the AddTextTrackCB completes, after having created
100  // the TextTrack object associated with |text_stream|.
101  void OnAddTextTrackDone(DemuxerStream* text_stream,
102                          scoped_ptr<TextTrack> text_track);
103
104  // Utility function to post a read request on |text_stream|.
105  void Read(TextTrackState* state, DemuxerStream* text_stream);
106
107  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
108  const AddTextTrackCB add_text_track_cb_;
109
110  // Callbacks provided during Initialize().
111  base::Closure ended_cb_;
112
113  // Callback provided to Pause().
114  base::Closure pause_cb_;
115
116  // Callback provided to Stop().
117  base::Closure stop_cb_;
118
119  // Simple state tracking variable.
120  enum State {
121    kUninitialized,
122    kPausePending,
123    kPaused,
124    kPlaying,
125    kEnded,
126    kStopPending,
127    kStopped
128  };
129  State state_;
130
131  typedef std::map<DemuxerStream*, TextTrackState*> TextTrackStateMap;
132  TextTrackStateMap text_track_state_map_;
133
134  // Indicates how many read requests are in flight.
135  int pending_read_count_;
136
137  // Indicates which text streams have not delivered end-of-stream yet.
138  typedef std::set<DemuxerStream*> PendingEosSet;
139  PendingEosSet pending_eos_set_;
140
141  // NOTE: Weak pointers must be invalidated before all other member variables.
142  base::WeakPtrFactory<TextRenderer> weak_factory_;
143
144  DISALLOW_IMPLICIT_CONSTRUCTORS(TextRenderer);
145};
146
147}  // namespace media
148
149#endif  // MEDIA_BASE_TEXT_RENDERER_H_
150