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