OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/bind.h" | 5 #include "base/bind.h" |
6 #include "base/callback.h" | 6 #include "base/callback.h" |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 return ConvertFromTimeBase(time_base, timestamp); | 273 return ConvertFromTimeBase(time_base, timestamp); |
274 } | 274 } |
275 | 275 |
276 // | 276 // |
277 // FFmpegDemuxer | 277 // FFmpegDemuxer |
278 // | 278 // |
279 FFmpegDemuxer::FFmpegDemuxer( | 279 FFmpegDemuxer::FFmpegDemuxer( |
280 MessageLoop* message_loop, | 280 MessageLoop* message_loop, |
281 const scoped_refptr<DataSource>& data_source, | 281 const scoped_refptr<DataSource>& data_source, |
282 bool local_source) | 282 bool local_source) |
283 : message_loop_(message_loop), | 283 : host_(NULL), |
284 message_loop_(message_loop), | |
284 local_source_(local_source), | 285 local_source_(local_source), |
285 format_context_(NULL), | 286 format_context_(NULL), |
286 data_source_(data_source), | 287 data_source_(data_source), |
287 read_event_(false, false), | 288 read_event_(false, false), |
288 read_has_failed_(false), | 289 read_has_failed_(false), |
289 last_read_bytes_(0), | 290 last_read_bytes_(0), |
290 read_position_(0), | 291 read_position_(0), |
291 bitrate_(0), | 292 bitrate_(0), |
292 first_seek_hack_(true), | 293 first_seek_hack_(true), |
293 start_time_(kNoTimestamp()), | 294 start_time_(kNoTimestamp()), |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
331 void FFmpegDemuxer::SetPlaybackRate(float playback_rate) { | 332 void FFmpegDemuxer::SetPlaybackRate(float playback_rate) { |
332 DCHECK(data_source_.get()); | 333 DCHECK(data_source_.get()); |
333 data_source_->SetPlaybackRate(playback_rate); | 334 data_source_->SetPlaybackRate(playback_rate); |
334 } | 335 } |
335 | 336 |
336 void FFmpegDemuxer::OnAudioRendererDisabled() { | 337 void FFmpegDemuxer::OnAudioRendererDisabled() { |
337 message_loop_->PostTask(FROM_HERE, base::Bind( | 338 message_loop_->PostTask(FROM_HERE, base::Bind( |
338 &FFmpegDemuxer::DisableAudioStreamTask, this)); | 339 &FFmpegDemuxer::DisableAudioStreamTask, this)); |
339 } | 340 } |
340 | 341 |
341 void FFmpegDemuxer::set_host(DemuxerHost* demuxer_host) { | 342 void FFmpegDemuxer::Initialize(DemuxerHost* host, |
342 Demuxer::set_host(demuxer_host); | 343 const PipelineStatusCB& status_cb) { |
343 data_source_->set_host(demuxer_host); | |
344 } | |
345 | |
346 void FFmpegDemuxer::Initialize(const PipelineStatusCB& status_cb) { | |
347 message_loop_->PostTask(FROM_HERE, base::Bind( | 344 message_loop_->PostTask(FROM_HERE, base::Bind( |
348 &FFmpegDemuxer::InitializeTask, this, status_cb)); | 345 &FFmpegDemuxer::InitializeTask, this, host, status_cb)); |
349 } | 346 } |
350 | 347 |
351 scoped_refptr<DemuxerStream> FFmpegDemuxer::GetStream( | 348 scoped_refptr<DemuxerStream> FFmpegDemuxer::GetStream( |
352 DemuxerStream::Type type) { | 349 DemuxerStream::Type type) { |
353 StreamVector::iterator iter; | 350 StreamVector::iterator iter; |
354 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 351 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
355 if (*iter && (*iter)->type() == type) { | 352 if (*iter && (*iter)->type() == type) { |
356 return *iter; | 353 return *iter; |
357 } | 354 } |
358 } | 355 } |
(...skipping 20 matching lines...) Expand all Loading... | |
379 | 376 |
380 // Asynchronous read from data source. | 377 // Asynchronous read from data source. |
381 data_source_->Read(read_position_, size, data, base::Bind( | 378 data_source_->Read(read_position_, size, data, base::Bind( |
382 &FFmpegDemuxer::SignalReadCompleted, this)); | 379 &FFmpegDemuxer::SignalReadCompleted, this)); |
383 | 380 |
384 // TODO(hclam): The method is called on the demuxer thread and this method | 381 // TODO(hclam): The method is called on the demuxer thread and this method |
385 // call will block the thread. We need to implemented an additional thread to | 382 // call will block the thread. We need to implemented an additional thread to |
386 // let FFmpeg demuxer methods to run on. | 383 // let FFmpeg demuxer methods to run on. |
387 int last_read_bytes = WaitForRead(); | 384 int last_read_bytes = WaitForRead(); |
388 if (last_read_bytes == DataSource::kReadError) { | 385 if (last_read_bytes == DataSource::kReadError) { |
389 host()->OnDemuxerError(PIPELINE_ERROR_READ); | 386 host_->OnDemuxerError(PIPELINE_ERROR_READ); |
390 | 387 |
391 // Returns with a negative number to signal an error to FFmpeg. | 388 // Returns with a negative number to signal an error to FFmpeg. |
392 read_has_failed_ = true; | 389 read_has_failed_ = true; |
393 return AVERROR(EIO); | 390 return AVERROR(EIO); |
394 } | 391 } |
395 read_position_ += last_read_bytes; | 392 read_position_ += last_read_bytes; |
396 host()->SetCurrentReadPosition(read_position_); | 393 host_->SetCurrentReadPosition(read_position_); |
397 | 394 |
398 return last_read_bytes; | 395 return last_read_bytes; |
399 } | 396 } |
400 | 397 |
401 bool FFmpegDemuxer::GetPosition(int64* position_out) { | 398 bool FFmpegDemuxer::GetPosition(int64* position_out) { |
402 *position_out = read_position_; | 399 *position_out = read_position_; |
403 return true; | 400 return true; |
404 } | 401 } |
405 | 402 |
406 bool FFmpegDemuxer::SetPosition(int64 position) { | 403 bool FFmpegDemuxer::SetPosition(int64 position) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
461 return 0; | 458 return 0; |
462 } | 459 } |
463 | 460 |
464 // Do math in floating point as we'd overflow an int64 if the filesize was | 461 // Do math in floating point as we'd overflow an int64 if the filesize was |
465 // larger than ~1073GB. | 462 // larger than ~1073GB. |
466 double bytes = filesize_in_bytes; | 463 double bytes = filesize_in_bytes; |
467 double duration_us = duration.InMicroseconds(); | 464 double duration_us = duration.InMicroseconds(); |
468 return bytes * 8000000.0 / duration_us; | 465 return bytes * 8000000.0 / duration_us; |
469 } | 466 } |
470 | 467 |
471 void FFmpegDemuxer::InitializeTask(const PipelineStatusCB& status_cb) { | 468 void FFmpegDemuxer::InitializeTask(DemuxerHost* host, |
469 const PipelineStatusCB& status_cb) { | |
472 DCHECK_EQ(MessageLoop::current(), message_loop_); | 470 DCHECK_EQ(MessageLoop::current(), message_loop_); |
471 host_ = host; | |
472 data_source_->set_host(host); | |
acolwell GONE FROM CHROMIUM
2012/04/04 16:01:00
This guy is next... ;)
scherkus (not reviewing)
2012/04/05 01:54:53
http://crbug.com/122071 added
| |
473 | 473 |
474 // Add ourself to Protocol list and get our unique key. | 474 // Add ourself to Protocol list and get our unique key. |
475 std::string key = FFmpegGlue::GetInstance()->AddProtocol(this); | 475 std::string key = FFmpegGlue::GetInstance()->AddProtocol(this); |
476 | 476 |
477 // Open FFmpeg AVFormatContext. | 477 // Open FFmpeg AVFormatContext. |
478 DCHECK(!format_context_); | 478 DCHECK(!format_context_); |
479 AVFormatContext* context = NULL; | 479 AVFormatContext* context = NULL; |
480 int result = avformat_open_input(&context, key.c_str(), NULL, NULL); | 480 int result = avformat_open_input(&context, key.c_str(), NULL, NULL); |
481 | 481 |
482 // Remove ourself from protocol list. | 482 // Remove ourself from protocol list. |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
551 max_duration = kInfiniteDuration(); | 551 max_duration = kInfiniteDuration(); |
552 } | 552 } |
553 | 553 |
554 // Some demuxers, like WAV, do not put timestamps on their frames. We | 554 // Some demuxers, like WAV, do not put timestamps on their frames. We |
555 // assume the the start time is 0. | 555 // assume the the start time is 0. |
556 if (start_time_ == kNoTimestamp()) | 556 if (start_time_ == kNoTimestamp()) |
557 start_time_ = base::TimeDelta(); | 557 start_time_ = base::TimeDelta(); |
558 | 558 |
559 // Good to go: set the duration and bitrate and notify we're done | 559 // Good to go: set the duration and bitrate and notify we're done |
560 // initializing. | 560 // initializing. |
561 host()->SetDuration(max_duration); | 561 host_->SetDuration(max_duration); |
562 | 562 |
563 int64 filesize_in_bytes = 0; | 563 int64 filesize_in_bytes = 0; |
564 GetSize(&filesize_in_bytes); | 564 GetSize(&filesize_in_bytes); |
565 bitrate_ = CalculateBitrate(format_context_, max_duration, filesize_in_bytes); | 565 bitrate_ = CalculateBitrate(format_context_, max_duration, filesize_in_bytes); |
566 if (bitrate_ > 0) | 566 if (bitrate_ > 0) |
567 data_source_->SetBitrate(bitrate_); | 567 data_source_->SetBitrate(bitrate_); |
568 | 568 |
569 status_cb.Run(PIPELINE_OK); | 569 status_cb.Run(PIPELINE_OK); |
570 } | 570 } |
571 | 571 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
726 read_event_.Wait(); | 726 read_event_.Wait(); |
727 return last_read_bytes_; | 727 return last_read_bytes_; |
728 } | 728 } |
729 | 729 |
730 void FFmpegDemuxer::SignalReadCompleted(int size) { | 730 void FFmpegDemuxer::SignalReadCompleted(int size) { |
731 last_read_bytes_ = size; | 731 last_read_bytes_ = size; |
732 read_event_.Signal(); | 732 read_event_.Signal(); |
733 } | 733 } |
734 | 734 |
735 } // namespace media | 735 } // namespace media |
OLD | NEW |