1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/base/text_renderer.h"
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/bind.h"
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/callback_helpers.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/stl_util.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/base/bind_to_loop.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/base/decoder_buffer.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/base/demuxer.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/base/demuxer_stream.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/base/text_cue.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace media {
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TextRenderer::TextRenderer(
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const scoped_refptr<base::MessageLoopProxy>& message_loop,
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const AddTextTrackCB& add_text_track_cb)
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : message_loop_(message_loop),
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      weak_factory_(this),
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      add_text_track_cb_(add_text_track_cb),
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      state_(kUninitialized),
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pending_read_count_(0) {
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TextRenderer::~TextRenderer() {
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(state_ == kUninitialized ||
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         state_ == kStopped) << "state_ " << state_;
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(pending_read_count_, 0);
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  STLDeleteValues(&text_track_state_map_);
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextRenderer::Initialize(const base::Closure& ended_cb) {
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!ended_cb.is_null());
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(kUninitialized, state_)  << "state_ " << state_;
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(text_track_state_map_.empty());
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(pending_read_count_, 0);
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(pending_eos_set_.empty());
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(ended_cb_.is_null());
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  weak_this_ = weak_factory_.GetWeakPtr();
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ended_cb_ = ended_cb;
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state_ = kPaused;
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextRenderer::Play(const base::Closure& callback) {
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(state_, kPaused) << "state_ " << state_;
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (TextTrackStateMap::iterator itr = text_track_state_map_.begin();
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       itr != text_track_state_map_.end(); ++itr) {
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    TextTrackState* state = itr->second;
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (state->read_state == TextTrackState::kReadPending) {
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DCHECK_GT(pending_read_count_, 0);
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      continue;
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Read(state, itr->first);
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state_ = kPlaying;
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  callback.Run();
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextRenderer::Pause(const base::Closure& callback) {
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(state_ == kPlaying || state_ == kEnded) << "state_ " << state_;
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_GE(pending_read_count_, 0);
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pause_cb_ = callback;
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (pending_read_count_ == 0) {
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    state_ = kPaused;
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::ResetAndReturn(&pause_cb_).Run();
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state_ = kPausePending;
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextRenderer::Flush(const base::Closure& callback) {
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(pending_read_count_, 0);
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(state_ == kPaused) << "state_ " << state_;
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (TextTrackStateMap::iterator itr = text_track_state_map_.begin();
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       itr != text_track_state_map_.end(); ++itr) {
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    pending_eos_set_.insert(itr->first);
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(pending_eos_set_.size(), text_track_state_map_.size());
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  callback.Run();
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextRenderer::Stop(const base::Closure& cb) {
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!cb.is_null());
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(state_ == kPlaying ||
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         state_ == kPausePending ||
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         state_ == kPaused ||
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         state_ == kEnded) << "state_ " << state_;
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_GE(pending_read_count_, 0);
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  stop_cb_ = cb;
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (pending_read_count_ == 0) {
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    state_ = kStopped;
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::ResetAndReturn(&stop_cb_).Run();
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state_ = kStopPending;
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextRenderer::AddTextStream(DemuxerStream* text_stream,
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 const TextTrackConfig& config) {
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(state_ != kUninitialized) << "state_ " << state_;
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_NE(state_, kStopPending);
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_NE(state_, kStopped);
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(text_track_state_map_.find(text_stream) ==
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         text_track_state_map_.end());
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(pending_eos_set_.find(text_stream) ==
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         pending_eos_set_.end());
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  media::AddTextTrackDoneCB done_cb =
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      media::BindToLoop(message_loop_,
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        base::Bind(&TextRenderer::OnAddTextTrackDone,
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                   weak_this_,
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                   text_stream));
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  add_text_track_cb_.Run(config, done_cb);
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextRenderer::RemoveTextStream(DemuxerStream* text_stream) {
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TextTrackStateMap::iterator itr = text_track_state_map_.find(text_stream);
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(itr != text_track_state_map_.end());
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TextTrackState* state = itr->second;
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(state->read_state, TextTrackState::kReadIdle);
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  delete state;
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  text_track_state_map_.erase(itr);
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_eos_set_.erase(text_stream);
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool TextRenderer::HasTracks() const {
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return !text_track_state_map_.empty();
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextRenderer::BufferReady(
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DemuxerStream* stream,
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DemuxerStream::Status status,
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const scoped_refptr<DecoderBuffer>& input) {
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_NE(status, DemuxerStream::kConfigChanged);
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (status == DemuxerStream::kAborted) {
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(!input);
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK_GT(pending_read_count_, 0);
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(pending_eos_set_.find(stream) != pending_eos_set_.end());
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    TextTrackStateMap::iterator itr = text_track_state_map_.find(stream);
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(itr != text_track_state_map_.end());
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    TextTrackState* state = itr->second;
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK_EQ(state->read_state, TextTrackState::kReadPending);
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    --pending_read_count_;
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    state->read_state = TextTrackState::kReadIdle;
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    switch (state_) {
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case kPlaying:
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return;
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case kPausePending:
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (pending_read_count_ == 0) {
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          state_ = kPaused;
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          base::ResetAndReturn(&pause_cb_).Run();
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        }
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return;
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case kStopPending:
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (pending_read_count_ == 0) {
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          state_ = kStopped;
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          base::ResetAndReturn(&stop_cb_).Run();
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        }
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return;
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case kPaused:
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case kStopped:
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case kUninitialized:
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case kEnded:
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        NOTREACHED();
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return;
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NOTREACHED();
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (input->end_of_stream()) {
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CueReady(stream, NULL);
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(status, DemuxerStream::kOk);
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_GE(input->side_data_size(), 2);
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The side data contains both the cue id and cue settings,
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // each terminated with a NUL.
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const char* id_ptr = reinterpret_cast<const char*>(input->side_data());
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  size_t id_len = strlen(id_ptr);
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string id(id_ptr, id_len);
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const char* settings_ptr = id_ptr + id_len + 1;
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  size_t settings_len = strlen(settings_ptr);
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string settings(settings_ptr, settings_len);
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The cue payload is stored in the data-part of the input buffer.
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string text(input->data(), input->data() + input->data_size());
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_refptr<TextCue> text_cue(
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new TextCue(input->timestamp(),
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  input->duration(),
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  id,
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  settings,
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  text));
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CueReady(stream, text_cue);
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextRenderer::CueReady(
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DemuxerStream* text_stream,
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const scoped_refptr<TextCue>& text_cue) {
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(state_ != kUninitialized &&
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         state_ != kStopped) << "state_ " << state_;
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_GT(pending_read_count_, 0);
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(pending_eos_set_.find(text_stream) != pending_eos_set_.end());
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TextTrackStateMap::iterator itr = text_track_state_map_.find(text_stream);
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(itr != text_track_state_map_.end());
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TextTrackState* state = itr->second;
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(state->read_state, TextTrackState::kReadPending);
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(state->text_track);
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  --pending_read_count_;
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state->read_state = TextTrackState::kReadIdle;
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  switch (state_) {
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case kPlaying: {
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (text_cue)
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        break;
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const size_t count = pending_eos_set_.erase(text_stream);
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DCHECK_EQ(count, 1U);
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (pending_eos_set_.empty()) {
269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        DCHECK_EQ(pending_read_count_, 0);
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        state_ = kEnded;
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        ended_cb_.Run();
272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return;
273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DCHECK_GT(pending_read_count_, 0);
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case kPausePending: {
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (text_cue)
280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        break;
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const size_t count = pending_eos_set_.erase(text_stream);
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DCHECK_EQ(count, 1U);
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (pending_read_count_ > 0) {
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        DCHECK(!pending_eos_set_.empty());
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return;
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      state_ = kPaused;
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::ResetAndReturn(&pause_cb_).Run();
292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case kStopPending:
296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (pending_read_count_ == 0) {
297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        state_ = kStopped;
298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::ResetAndReturn(&stop_cb_).Run();
299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case kPaused:
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case kStopped:
305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case kUninitialized:
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case kEnded:
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      NOTREACHED();
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::TimeDelta start = text_cue->timestamp();
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::TimeDelta end = start + text_cue->duration();
313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state->text_track->addWebVTTCue(start, end,
315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  text_cue->id(),
316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  text_cue->text(),
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  text_cue->settings());
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (state_ == kPlaying) {
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Read(state, text_stream);
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (pending_read_count_ == 0) {
325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DCHECK_EQ(state_, kPausePending) << "state_ " << state_;
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      state_ = kPaused;
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::ResetAndReturn(&pause_cb_).Run();
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextRenderer::OnAddTextTrackDone(DemuxerStream* text_stream,
332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                      scoped_ptr<TextTrack> text_track) {
333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(state_ != kUninitialized &&
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         state_ != kStopped &&
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         state_ != kStopPending) << "state_ " << state_;
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(text_stream);
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(text_track);
339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<TextTrackState> state(new TextTrackState(text_track.Pass()));
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  text_track_state_map_[text_stream] = state.release();
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_eos_set_.insert(text_stream);
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (state_ == kPlaying)
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Read(text_track_state_map_[text_stream], text_stream);
346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TextRenderer::Read(
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    TextTrackState* state,
350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DemuxerStream* text_stream) {
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_NE(state->read_state, TextTrackState::kReadPending);
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state->read_state = TextTrackState::kReadPending;
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ++pending_read_count_;
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  text_stream->Read(base::Bind(&TextRenderer::BufferReady,
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                weak_this_,
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                text_stream));
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TextRenderer::TextTrackState::TextTrackState(scoped_ptr<TextTrack> tt)
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : read_state(kReadIdle),
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      text_track(tt.Pass()) {
364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TextRenderer::TextTrackState::~TextTrackState() {
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace media
370