| Index: media/filters/ffmpeg_demuxer.cc
 | 
| diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
 | 
| index 6d907d5052c9fa0eddb783052e19eca4491a82dc..56db9177ce4a72cb096b686f7ba38b2c1e726df1 100644
 | 
| --- a/media/filters/ffmpeg_demuxer.cc
 | 
| +++ b/media/filters/ffmpeg_demuxer.cc
 | 
| @@ -276,20 +276,24 @@ base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp(
 | 
|  //
 | 
|  // FFmpegDemuxer
 | 
|  //
 | 
| -FFmpegDemuxer::FFmpegDemuxer(MessageLoop* message_loop, bool local_source)
 | 
| +FFmpegDemuxer::FFmpegDemuxer(
 | 
| +    MessageLoop* message_loop,
 | 
| +    const scoped_refptr<DataSource>& data_source,
 | 
| +    bool local_source)
 | 
|      : message_loop_(message_loop),
 | 
|        local_source_(local_source),
 | 
|        format_context_(NULL),
 | 
| +      data_source_(data_source),
 | 
|        read_event_(false, false),
 | 
|        read_has_failed_(false),
 | 
|        last_read_bytes_(0),
 | 
|        read_position_(0),
 | 
| -      max_duration_(base::TimeDelta::FromMicroseconds(-1)),
 | 
| -      deferred_status_(PIPELINE_OK),
 | 
| +      bitrate_(0),
 | 
|        first_seek_hack_(true),
 | 
|        start_time_(kNoTimestamp()),
 | 
|        audio_disabled_(false) {
 | 
|    DCHECK(message_loop_);
 | 
| +  DCHECK(data_source_);
 | 
|  }
 | 
|  
 | 
|  FFmpegDemuxer::~FFmpegDemuxer() {
 | 
| @@ -329,11 +333,6 @@ void FFmpegDemuxer::SetPlaybackRate(float playback_rate) {
 | 
|    data_source_->SetPlaybackRate(playback_rate);
 | 
|  }
 | 
|  
 | 
| -void FFmpegDemuxer::SetPreload(Preload preload) {
 | 
| -  DCHECK(data_source_.get());
 | 
| -  data_source_->SetPreload(preload);
 | 
| -}
 | 
| -
 | 
|  void FFmpegDemuxer::OnAudioRendererDisabled() {
 | 
|    message_loop_->PostTask(FROM_HERE, base::Bind(
 | 
|        &FFmpegDemuxer::DisableAudioStreamTask, this));
 | 
| @@ -341,22 +340,12 @@ void FFmpegDemuxer::OnAudioRendererDisabled() {
 | 
|  
 | 
|  void FFmpegDemuxer::set_host(DemuxerHost* demuxer_host) {
 | 
|    Demuxer::set_host(demuxer_host);
 | 
| -  if (data_source_)
 | 
| -    data_source_->set_host(demuxer_host);
 | 
| -  if (max_duration_.InMicroseconds() >= 0)
 | 
| -    host()->SetDuration(max_duration_);
 | 
| -  if (read_position_ > 0)
 | 
| -    host()->SetCurrentReadPosition(read_position_);
 | 
| -  if (deferred_status_ != PIPELINE_OK)
 | 
| -    host()->OnDemuxerError(deferred_status_);
 | 
| +  data_source_->set_host(demuxer_host);
 | 
|  }
 | 
|  
 | 
| -void FFmpegDemuxer::Initialize(DataSource* data_source,
 | 
| -                               const PipelineStatusCB& status_cb) {
 | 
| -  message_loop_->PostTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&FFmpegDemuxer::InitializeTask, this,
 | 
| -                 make_scoped_refptr(data_source), status_cb));
 | 
| +void FFmpegDemuxer::Initialize(const PipelineStatusCB& status_cb) {
 | 
| +  message_loop_->PostTask(FROM_HERE, base::Bind(
 | 
| +      &FFmpegDemuxer::InitializeTask, this, status_cb));
 | 
|  }
 | 
|  
 | 
|  scoped_refptr<DemuxerStream> FFmpegDemuxer::GetStream(
 | 
| @@ -397,19 +386,14 @@ size_t FFmpegDemuxer::Read(size_t size, uint8* data) {
 | 
|    // let FFmpeg demuxer methods to run on.
 | 
|    int last_read_bytes = WaitForRead();
 | 
|    if (last_read_bytes == DataSource::kReadError) {
 | 
| -    if (host())
 | 
| -      host()->OnDemuxerError(PIPELINE_ERROR_READ);
 | 
| -    else
 | 
| -      deferred_status_ = PIPELINE_ERROR_READ;
 | 
| +    host()->OnDemuxerError(PIPELINE_ERROR_READ);
 | 
|  
 | 
|      // Returns with a negative number to signal an error to FFmpeg.
 | 
|      read_has_failed_ = true;
 | 
|      return AVERROR(EIO);
 | 
|    }
 | 
|    read_position_ += last_read_bytes;
 | 
| -
 | 
| -  if (host())
 | 
| -    host()->SetCurrentReadPosition(read_position_);
 | 
| +  host()->SetCurrentReadPosition(read_position_);
 | 
|  
 | 
|    return last_read_bytes;
 | 
|  }
 | 
| @@ -448,13 +432,44 @@ MessageLoop* FFmpegDemuxer::message_loop() {
 | 
|    return message_loop_;
 | 
|  }
 | 
|  
 | 
| -void FFmpegDemuxer::InitializeTask(DataSource* data_source,
 | 
| -                                   const PipelineStatusCB& status_cb) {
 | 
| -  DCHECK_EQ(MessageLoop::current(), message_loop_);
 | 
| +// Helper for calculating the bitrate of the media based on information stored
 | 
| +// in |format_context| or failing that the size and duration of the media.
 | 
| +//
 | 
| +// Returns 0 if a bitrate could not be determined.
 | 
| +static int CalculateBitrate(
 | 
| +    AVFormatContext* format_context,
 | 
| +    const base::TimeDelta& duration,
 | 
| +    int64 filesize_in_bytes) {
 | 
| +  // If there is a bitrate set on the container, use it.
 | 
| +  if (format_context->bit_rate > 0)
 | 
| +    return format_context->bit_rate;
 | 
|  
 | 
| -  data_source_ = data_source;
 | 
| -  if (host())
 | 
| -    data_source_->set_host(host());
 | 
| +  // Then try to sum the bitrates individually per stream.
 | 
| +  int bitrate = 0;
 | 
| +  for (size_t i = 0; i < format_context->nb_streams; ++i) {
 | 
| +    AVCodecContext* codec_context = format_context->streams[i]->codec;
 | 
| +    bitrate += codec_context->bit_rate;
 | 
| +  }
 | 
| +  if (bitrate > 0)
 | 
| +    return bitrate;
 | 
| +
 | 
| +  // See if we can approximate the bitrate as long as we have a filesize and
 | 
| +  // valid duration.
 | 
| +  if (duration.InMicroseconds() <= 0 ||
 | 
| +      duration == kInfiniteDuration() ||
 | 
| +      filesize_in_bytes == 0) {
 | 
| +    return 0;
 | 
| +  }
 | 
| +
 | 
| +  // Do math in floating point as we'd overflow an int64 if the filesize was
 | 
| +  // larger than ~1073GB.
 | 
| +  double bytes = filesize_in_bytes;
 | 
| +  double duration_us = duration.InMicroseconds();
 | 
| +  return bytes * 8000000.0 / duration_us;
 | 
| +}
 | 
| +
 | 
| +void FFmpegDemuxer::InitializeTask(const PipelineStatusCB& status_cb) {
 | 
| +  DCHECK_EQ(MessageLoop::current(), message_loop_);
 | 
|  
 | 
|    // Add ourself to Protocol list and get our unique key.
 | 
|    std::string key = FFmpegGlue::GetInstance()->AddProtocol(this);
 | 
| @@ -543,47 +558,21 @@ void FFmpegDemuxer::InitializeTask(DataSource* data_source,
 | 
|  
 | 
|    // Good to go: set the duration and bitrate and notify we're done
 | 
|    // initializing.
 | 
| -  if (host())
 | 
| -    host()->SetDuration(max_duration);
 | 
| -  max_duration_ = max_duration;
 | 
| +  host()->SetDuration(max_duration);
 | 
|  
 | 
| -  int bitrate = GetBitrate();
 | 
| -  if (bitrate > 0)
 | 
| -    data_source_->SetBitrate(bitrate);
 | 
| +  int64 filesize_in_bytes = 0;
 | 
| +  GetSize(&filesize_in_bytes);
 | 
| +  bitrate_ = CalculateBitrate(format_context_, max_duration, filesize_in_bytes);
 | 
| +  if (bitrate_ > 0)
 | 
| +    data_source_->SetBitrate(bitrate_);
 | 
|  
 | 
|    status_cb.Run(PIPELINE_OK);
 | 
|  }
 | 
|  
 | 
| -int FFmpegDemuxer::GetBitrate() {
 | 
| -  DCHECK(format_context_);
 | 
| -
 | 
| -  // If there is a bitrate set on the container, use it.
 | 
| -  if (format_context_->bit_rate > 0)
 | 
| -    return format_context_->bit_rate;
 | 
| -
 | 
| -  // Then try to sum the bitrates individually per stream.
 | 
| -  int bitrate = 0;
 | 
| -  for (size_t i = 0; i < format_context_->nb_streams; ++i) {
 | 
| -    AVCodecContext* codec_context = format_context_->streams[i]->codec;
 | 
| -    bitrate += codec_context->bit_rate;
 | 
| -  }
 | 
| -  if (bitrate > 0)
 | 
| -    return bitrate;
 | 
| -
 | 
| -  // See if we can approximate the bitrate as long as we have a filesize and
 | 
| -  // valid duration.
 | 
| -  int64 filesize_in_bytes;
 | 
| -  if (max_duration_.InMicroseconds() <= 0 ||
 | 
| -      max_duration_ == kInfiniteDuration() ||
 | 
| -      !GetSize(&filesize_in_bytes)) {
 | 
| -    return 0;
 | 
| -  }
 | 
|  
 | 
| -  // Do math in floating point as we'd overflow an int64 if the filesize was
 | 
| -  // larger than ~1073GB.
 | 
| -  double bytes = filesize_in_bytes;
 | 
| -  double duration = max_duration_.InMicroseconds();
 | 
| -  return bytes * 8000000.0 / duration;
 | 
| +int FFmpegDemuxer::GetBitrate() {
 | 
| +  DCHECK(format_context_) << "Initialize() has not been called";
 | 
| +  return bitrate_;
 | 
|  }
 | 
|  
 | 
|  bool FFmpegDemuxer::IsLocalSource() {
 | 
| 
 |