15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/pipeline.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_helpers.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/command_line.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/location.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/metrics/histogram.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/single_thread_task_runner.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/condition_variable.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media_log.h" 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/base/media_switches.h" 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/base/renderer.h" 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/base/text_renderer.h" 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/base/text_track_config.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_decoder_config.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Pipeline::Pipeline( 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MediaLog* media_log) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : task_runner_(task_runner), 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media_log_(media_log), 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) running_(false), 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) did_loading_progress_(false), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) volume_(1.0f), 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playback_rate_(0.0f), 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_(PIPELINE_OK), 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_initialized_(false), 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_(kCreated), 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer_ended_(false), 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci text_renderer_ended_(false), 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) demuxer_(NULL), 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_factory_(this) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media_log_->AddEvent( 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Pipeline::~Pipeline() { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Pipeline must be destroyed on same thread that created it"; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!running_) << "Stop() must complete before destroying object"; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(stop_cb_.is_null()); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(seek_cb_.is_null()); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media_log_->AddEvent( 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Pipeline::Start(Demuxer* demuxer, 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<Renderer> renderer, 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Closure& ended_cb, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PipelineStatusCB& error_cb, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PipelineStatusCB& seek_cb, 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const PipelineMetadataCB& metadata_cb, 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const BufferingStateCB& buffering_state_cb, 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::Closure& duration_change_cb, 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const AddTextTrackCB& add_text_track_cb) { 73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!ended_cb.is_null()); 74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!error_cb.is_null()); 75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!seek_cb.is_null()); 76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!metadata_cb.is_null()); 77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!buffering_state_cb.is_null()); 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!running_) << "Media pipeline is already running"; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) running_ = true; 82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci demuxer_ = demuxer; 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer_ = renderer.Pass(); 85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ended_cb_ = ended_cb; 86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch error_cb_ = error_cb; 87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch seek_cb_ = seek_cb; 88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch metadata_cb_ = metadata_cb; 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch buffering_state_cb_ = buffering_state_cb; 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch duration_change_cb_ = duration_change_cb; 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci add_text_track_cb_ = add_text_track_cb; 92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch task_runner_->PostTask( 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, base::Bind(&Pipeline::StartTask, weak_factory_.GetWeakPtr())); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::Stop(const base::Closure& stop_cb) { 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DVLOG(2) << __FUNCTION__; 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) task_runner_->PostTask( 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&Pipeline::StopTask, weak_factory_.GetWeakPtr(), stop_cb)); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!running_) { 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek()."; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) task_runner_->PostTask( 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind( 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &Pipeline::SeekTask, weak_factory_.GetWeakPtr(), time, seek_cb)); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Pipeline::IsRunning() const { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return running_; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float Pipeline::GetPlaybackRate() const { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return playback_rate_; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::SetPlaybackRate(float playback_rate) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (playback_rate < 0.0f) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playback_rate_ = playback_rate; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (running_) { 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) task_runner_->PostTask(FROM_HERE, 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&Pipeline::PlaybackRateChangedTask, 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_factory_.GetWeakPtr(), 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) playback_rate)); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float Pipeline::GetVolume() const { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return volume_; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::SetVolume(float volume) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (volume < 0.0f || volume > 1.0f) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) volume_ = volume; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (running_) { 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) task_runner_->PostTask( 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind( 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &Pipeline::VolumeChangedTask, weak_factory_.GetWeakPtr(), volume)); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeDelta Pipeline::GetMediaTime() const { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!renderer_) 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return TimeDelta(); 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TimeDelta media_time = renderer_->GetMediaTime(); 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return std::min(media_time, duration_); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return buffered_time_ranges_; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeDelta Pipeline::GetMediaDuration() const { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return duration_; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool Pipeline::DidLoadingProgress() { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ret = did_loading_progress_; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) did_loading_progress_ = false; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PipelineStatistics Pipeline::GetStatistics() const { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return statistics_; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::SetErrorForTesting(PipelineStatus status) { 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnError(status); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool Pipeline::HasWeakPtrsForTesting() const { 1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return weak_factory_.HasWeakPtrs(); 1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::SetState(State next_state) { 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DVLOG(1) << GetStateString(state_) << " -> " << GetStateString(next_state); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = next_state; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state)); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RETURN_STRING(state) case state: return #state; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* Pipeline::GetStateString(State state) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RETURN_STRING(kCreated); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RETURN_STRING(kInitDemuxer); 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RETURN_STRING(kInitRenderer); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RETURN_STRING(kSeeking); 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RETURN_STRING(kPlaying); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RETURN_STRING(kStopping); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RETURN_STRING(kStopped); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "INVALID"; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef RETURN_STRING 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Pipeline::State Pipeline::GetNextState() const { 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(stop_cb_.is_null()) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "State transitions don't happen when stopping"; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(status_, PIPELINE_OK) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "State transitions don't happen when there's an error: " << status_; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state_) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kCreated: 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kInitDemuxer; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInitDemuxer: 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return kInitRenderer; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case kInitRenderer: 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kSeeking: 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return kPlaying; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case kPlaying: 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kStopping: 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kStopped: 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "State has no transition: " << state_; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return state_; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::OnDemuxerError(PipelineStatus error) { 2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) task_runner_->PostTask(FROM_HERE, 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&Pipeline::ErrorChangedTask, 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_factory_.GetWeakPtr(), 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error)); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Pipeline::AddTextStream(DemuxerStream* text_stream, 260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const TextTrackConfig& config) { 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) task_runner_->PostTask(FROM_HERE, 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&Pipeline::AddTextStreamTask, 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_factory_.GetWeakPtr(), 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) text_stream, 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) config)); 266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Pipeline::RemoveTextStream(DemuxerStream* text_stream) { 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) task_runner_->PostTask(FROM_HERE, 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&Pipeline::RemoveTextStreamTask, 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_factory_.GetWeakPtr(), 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) text_stream)); 273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void Pipeline::OnError(PipelineStatus error) { 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsRunning()); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(PIPELINE_OK, error); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Media pipeline error: " << error; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) task_runner_->PostTask(FROM_HERE, base::Bind( 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &Pipeline::ErrorChangedTask, weak_factory_.GetWeakPtr(), error)); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::SetDuration(TimeDelta duration) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsRunning()); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media_log_->AddEvent( 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media_log_->CreateTimeEvent( 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MediaLogEvent::DURATION_SET, "duration", duration)); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch duration_ = duration; 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!duration_change_cb_.is_null()) 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) duration_change_cb_.Run(); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::OnStateTransition(PipelineStatus status) { 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force post to process state transitions after current execution frame. 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) task_runner_->PostTask( 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind( 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &Pipeline::StateTransitionTask, weak_factory_.GetWeakPtr(), status)); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::StateTransitionTask(PipelineStatus status) { 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No-op any state transitions if we're stopping. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == kStopping || state_ == kStopped) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Preserve existing abnormal status, otherwise update based on the result of 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the previous operation. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = (status_ != PIPELINE_OK ? status_ : status); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_ != PIPELINE_OK) { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorChangedTask(status_); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Guard against accidentally clearing |pending_callbacks_| for states that 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use it as well as states that should not be using it. 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(pending_callbacks_.get() != NULL, state_ == kSeeking); 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_callbacks_.reset(); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PipelineStatusCB done_cb = 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&Pipeline::OnStateTransition, weak_factory_.GetWeakPtr()); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Switch states, performing any entrance actions for the new state as well. 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(GetNextState()); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state_) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInitDemuxer: 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InitializeDemuxer(done_cb); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case kInitRenderer: 3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return InitializeRenderer(base::Bind(done_cb, PIPELINE_OK)); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case kPlaying: 3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Report metadata the first time we enter the playing state. 3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!is_initialized_) { 3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_initialized_ = true; 3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReportMetadata(); 3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci start_timestamp_ = demuxer_->GetStartTime(); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); 350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(start_timestamp_ >= base::TimeDelta()); 3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer_->StartPlayingFrom(start_timestamp_); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (text_renderer_) 355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch text_renderer_->StartPlaying(); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PlaybackRateChangedTask(GetPlaybackRate()); 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) VolumeChangedTask(GetVolume()); 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kStopping: 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kStopped: 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kCreated: 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kSeeking: 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "State has no transition: " << state_; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Note that the usage of base::Unretained() with the renderers is considered 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// safe as they are owned by |pending_callbacks_| and share the same lifetime. 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// That being said, deleting the renderers while keeping |pending_callbacks_| 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// running on the media thread would result in crashes. 3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Pipeline::DoSeek(TimeDelta seek_timestamp, 3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const PipelineStatusCB& done_cb) { 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!pending_callbacks_.get()); 3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(state_, kSeeking); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SerialRunner::Queue bound_fns; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pause. 383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (text_renderer_) { 384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bound_fns.Push(base::Bind( 385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &TextRenderer::Pause, base::Unretained(text_renderer_.get()))); 386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Flush. 3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(renderer_); 3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bound_fns.Push( 3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&Renderer::Flush, base::Unretained(renderer_.get()))); 392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (text_renderer_) { 394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bound_fns.Push(base::Bind( 395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &TextRenderer::Flush, base::Unretained(text_renderer_.get()))); 396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Seek demuxer. 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound_fns.Push(base::Bind( 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp)); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::DoStop(const PipelineStatusCB& done_cb) { 4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DVLOG(2) << __FUNCTION__; 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!pending_callbacks_.get()); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(scherkus): Enforce that Renderer is only called on a single thread, 4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // even for accessing media time http://crbug.com/370634 4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<Renderer> renderer; 4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci { 4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::AutoLock auto_lock(lock_); 4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer.swap(renderer_); 4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer.reset(); 4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) text_renderer_.reset(); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (demuxer_) { 4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci demuxer_->Stop(); 4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci demuxer_ = NULL; 423f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::OnStopCompleted(PipelineStatus status) { 4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DVLOG(2) << __FUNCTION__; 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, kStopping); 4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!renderer_); 4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(!text_renderer_); 4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::AutoLock auto_lock(lock_); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) running_ = false; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(kStopped); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) demuxer_ = NULL; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we stop during initialization/seeking we want to run |seek_cb_| 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // followed by |stop_cb_| so we don't leave outstanding callbacks around. 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!seek_cb_.is_null()) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ResetAndReturn(&seek_cb_).Run(status_); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_cb_.Reset(); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!stop_cb_.is_null()) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_cb_.Reset(); 4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Invalid all weak pointers so it's safe to destroy |this| on the render 4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // main thread. 4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::ResetAndReturn(&stop_cb_).Run(); 457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // NOTE: pipeline may be deleted at this point in time as a result of 459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // executing |stop_cb_|. 460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!error_cb_.is_null()) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(status_, PIPELINE_OK); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ResetAndReturn(&error_cb_).Run(status_); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Pipeline::AddBufferedTimeRange(TimeDelta start, TimeDelta end) { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsRunning()); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_time_ranges_.Add(start, end); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) did_loading_progress_ = true; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called from any thread. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) { 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statistics_.video_bytes_decoded += stats.video_bytes_decoded; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statistics_.video_frames_decoded += stats.video_frames_decoded; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statistics_.video_frames_dropped += stats.video_frames_dropped; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 484effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid Pipeline::StartTask() { 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(kCreated, state_) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Media pipeline cannot be started more than once"; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci text_renderer_ = CreateTextRenderer(); 491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (text_renderer_) { 492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) text_renderer_->Initialize( 4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&Pipeline::OnTextRendererEnded, weak_factory_.GetWeakPtr())); 494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 495f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StateTransitionTask(PIPELINE_OK); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::StopTask(const base::Closure& stop_cb) { 5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(stop_cb_.is_null()); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == kStopped) { 5046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Invalid all weak pointers so it's safe to destroy |this| on the render 5056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // main thread. 5066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 5076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // NOTE: pipeline may be deleted at this point in time as a result of 5096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // executing |stop_cb|. 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stop_cb.Run(); 5116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stop_cb_ = stop_cb; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // We may already be stopping due to a runtime error. 5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (state_ == kStopping) 5193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Do not report statistics if the pipeline is not fully initialized. 5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ == kSeeking || state_ == kPlaying) { 5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PipelineStatistics stats = GetStatistics(); 5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (renderer_->HasVideo() && stats.video_frames_decoded > 0) { 5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UMA_HISTOGRAM_COUNTS("Media.DroppedFrameCount", 5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci stats.video_frames_dropped); 5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) SetState(kStopping); 5313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pending_callbacks_.reset(); 5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DoStop(base::Bind(&Pipeline::OnStopCompleted, weak_factory_.GetWeakPtr())); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::ErrorChangedTask(PipelineStatus error) { 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); 5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == kStopping || state_ == kStopped) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(kStopping); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_callbacks_.reset(); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = error; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DoStop(base::Bind(&Pipeline::OnStopCompleted, weak_factory_.GetWeakPtr())); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::PlaybackRateChangedTask(float playback_rate) { 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Playback rate changes are only carried out while playing. 555cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (state_ != kPlaying) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer_->SetPlaybackRate(playback_rate); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::VolumeChangedTask(float volume) { 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Volume changes are only carried out while playing. 565cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (state_ != kPlaying) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer_->SetVolume(volume); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { 5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(stop_cb_.is_null()); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Suppress seeking if we're not fully started. 576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (state_ != kPlaying) { 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(state_ == kStopping || state_ == kStopped) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Receive extra seek in unexpected state: " << state_; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(scherkus): should we run the callback? I'm tempted to say the API 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will only execute the first Seek() request. 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Media pipeline has not started, ignoring seek to " 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << time.InMicroseconds() << " (current state: " << state_ << ")"; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(seek_cb_.is_null()); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::TimeDelta seek_timestamp = 5901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::max(time, demuxer_->GetStartTime()); 5911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(kSeeking); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) seek_cb_ = seek_cb; 5941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer_ended_ = false; 5951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci text_renderer_ended_ = false; 5961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci start_timestamp_ = seek_timestamp; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DoSeek(seek_timestamp, 5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&Pipeline::OnStateTransition, weak_factory_.GetWeakPtr())); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Pipeline::OnRendererEnded() { 6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 606cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (state_ != kPlaying) 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!renderer_ended_); 6101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer_ended_ = true; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunEndedCallbackIfNeeded(); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void Pipeline::OnTextRendererEnded() { 6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 6175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::TEXT_ENDED)); 618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 619cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (state_ != kPlaying) 620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 6221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!text_renderer_ended_); 6231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci text_renderer_ended_ = true; 624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) RunEndedCallbackIfNeeded(); 626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Pipeline::RunEndedCallbackIfNeeded() { 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (renderer_ && !renderer_ended_) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (text_renderer_ && text_renderer_->HasTracks() && !text_renderer_ended_) 635f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(status_, PIPELINE_OK); 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ended_cb_.Run(); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<TextRenderer> Pipeline::CreateTextRenderer() { 6421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(task_runner_->BelongsToCurrentThread()); 6431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 6451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!cmd_line->HasSwitch(switches::kEnableInbandTextTracks)) 6461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return scoped_ptr<media::TextRenderer>(); 6471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return scoped_ptr<media::TextRenderer>(new media::TextRenderer( 6491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task_runner_, 6501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&Pipeline::OnAddTextTrack, weak_factory_.GetWeakPtr()))); 6511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 653f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Pipeline::AddTextStreamTask(DemuxerStream* text_stream, 654f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const TextTrackConfig& config) { 6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // TODO(matthewjheaney): fix up text_ended_ when text stream 657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // is added (http://crbug.com/321446). 6581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (text_renderer_) 6591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci text_renderer_->AddTextStream(text_stream, config); 660f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 661f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 662f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Pipeline::RemoveTextStreamTask(DemuxerStream* text_stream) { 6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 6641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (text_renderer_) 6651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci text_renderer_->RemoveTextStream(text_stream); 666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 667f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 6681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Pipeline::OnAddTextTrack(const TextTrackConfig& config, 6691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const AddTextTrackDoneCB& done_cb) { 6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 6711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci add_text_track_cb_.Run(config, done_cb); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Pipeline::InitializeDemuxer(const PipelineStatusCB& done_cb) { 6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 6761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci demuxer_->Initialize(this, done_cb, text_renderer_); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Pipeline::InitializeRenderer(const base::Closure& done_cb) { 6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!demuxer_->GetStream(DemuxerStream::AUDIO) && 6831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !demuxer_->GetStream(DemuxerStream::VIDEO)) { 6841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci { 6851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::AutoLock auto_lock(lock_); 6861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer_.reset(); 6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnError(PIPELINE_ERROR_COULD_NOT_RENDER); 6891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 6901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::WeakPtr<Pipeline> weak_this = weak_factory_.GetWeakPtr(); 6931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer_->Initialize( 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_cb, 6955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&Pipeline::OnUpdateStatistics, weak_this), 6961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&Pipeline::OnRendererEnded, weak_this), 6975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&Pipeline::OnError, weak_this), 6981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&Pipeline::BufferingStateChanged, weak_this)); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Pipeline::ReportMetadata() { 702cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(task_runner_->BelongsToCurrentThread()); 7031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PipelineMetadata metadata; 7041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci metadata.has_audio = renderer_->HasAudio(); 7051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci metadata.has_video = renderer_->HasVideo(); 7061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci metadata.timeline_offset = demuxer_->GetTimelineOffset(); 7071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); 7081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (stream) { 7091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci metadata.natural_size = stream->video_decoder_config().natural_size(); 7101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci metadata.video_rotation = stream->video_rotation(); 711116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 7121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci metadata_cb_.Run(metadata); 713cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 714cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Pipeline::BufferingStateChanged(BufferingState new_buffering_state) { 7161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DVLOG(1) << __FUNCTION__ << "(" << new_buffering_state << ") "; 717116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(task_runner_->BelongsToCurrentThread()); 7181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buffering_state_cb_.Run(new_buffering_state); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 722