| 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 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 | 263 |
| 264 const VideoDecoderConfig& FFmpegDemuxerStream::video_decoder_config() { | 264 const VideoDecoderConfig& FFmpegDemuxerStream::video_decoder_config() { |
| 265 CHECK_EQ(type_, VIDEO); | 265 CHECK_EQ(type_, VIDEO); |
| 266 return video_config_; | 266 return video_config_; |
| 267 } | 267 } |
| 268 | 268 |
| 269 // static | 269 // static |
| 270 base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( | 270 base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( |
| 271 const AVRational& time_base, int64 timestamp) { | 271 const AVRational& time_base, int64 timestamp) { |
| 272 if (timestamp == static_cast<int64>(AV_NOPTS_VALUE)) | 272 if (timestamp == static_cast<int64>(AV_NOPTS_VALUE)) |
| 273 return kNoTimestamp; | 273 return kNoTimestamp(); |
| 274 | 274 |
| 275 return ConvertFromTimeBase(time_base, timestamp); | 275 return ConvertFromTimeBase(time_base, timestamp); |
| 276 } | 276 } |
| 277 | 277 |
| 278 // | 278 // |
| 279 // FFmpegDemuxer | 279 // FFmpegDemuxer |
| 280 // | 280 // |
| 281 FFmpegDemuxer::FFmpegDemuxer(MessageLoop* message_loop, bool local_source) | 281 FFmpegDemuxer::FFmpegDemuxer(MessageLoop* message_loop, bool local_source) |
| 282 : message_loop_(message_loop), | 282 : message_loop_(message_loop), |
| 283 local_source_(local_source), | 283 local_source_(local_source), |
| 284 format_context_(NULL), | 284 format_context_(NULL), |
| 285 read_event_(false, false), | 285 read_event_(false, false), |
| 286 read_has_failed_(false), | 286 read_has_failed_(false), |
| 287 last_read_bytes_(0), | 287 last_read_bytes_(0), |
| 288 read_position_(0), | 288 read_position_(0), |
| 289 max_duration_(base::TimeDelta::FromMicroseconds(-1)), | 289 max_duration_(base::TimeDelta::FromMicroseconds(-1)), |
| 290 deferred_status_(PIPELINE_OK), | 290 deferred_status_(PIPELINE_OK), |
| 291 first_seek_hack_(true), | 291 first_seek_hack_(true), |
| 292 start_time_(kNoTimestamp) { | 292 start_time_(kNoTimestamp()) { |
| 293 DCHECK(message_loop_); | 293 DCHECK(message_loop_); |
| 294 } | 294 } |
| 295 | 295 |
| 296 FFmpegDemuxer::~FFmpegDemuxer() { | 296 FFmpegDemuxer::~FFmpegDemuxer() { |
| 297 // In this destructor, we clean up resources held by FFmpeg. It is ugly to | 297 // In this destructor, we clean up resources held by FFmpeg. It is ugly to |
| 298 // close the codec contexts here because the corresponding codecs are opened | 298 // close the codec contexts here because the corresponding codecs are opened |
| 299 // in the decoder filters. By reaching this point, all filters should have | 299 // in the decoder filters. By reaching this point, all filters should have |
| 300 // stopped, so this is the only safe place to do the global clean up. | 300 // stopped, so this is the only safe place to do the global clean up. |
| 301 // TODO(hclam): close the codecs in the corresponding decoders. | 301 // TODO(hclam): close the codecs in the corresponding decoders. |
| 302 if (!format_context_) | 302 if (!format_context_) |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 AVStream* stream = format_context_->streams[i]; | 509 AVStream* stream = format_context_->streams[i]; |
| 510 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( | 510 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( |
| 511 new FFmpegDemuxerStream(this, stream)); | 511 new FFmpegDemuxerStream(this, stream)); |
| 512 | 512 |
| 513 streams_[i] = demuxer_stream; | 513 streams_[i] = demuxer_stream; |
| 514 max_duration = std::max(max_duration, demuxer_stream->duration()); | 514 max_duration = std::max(max_duration, demuxer_stream->duration()); |
| 515 | 515 |
| 516 if (stream->first_dts != static_cast<int64_t>(AV_NOPTS_VALUE)) { | 516 if (stream->first_dts != static_cast<int64_t>(AV_NOPTS_VALUE)) { |
| 517 const base::TimeDelta first_dts = ConvertFromTimeBase( | 517 const base::TimeDelta first_dts = ConvertFromTimeBase( |
| 518 stream->time_base, stream->first_dts); | 518 stream->time_base, stream->first_dts); |
| 519 if (start_time_ == kNoTimestamp || first_dts < start_time_) | 519 if (start_time_ == kNoTimestamp() || first_dts < start_time_) |
| 520 start_time_ = first_dts; | 520 start_time_ = first_dts; |
| 521 } | 521 } |
| 522 } | 522 } |
| 523 | 523 |
| 524 if (!found_audio_stream && !found_video_stream) { | 524 if (!found_audio_stream && !found_video_stream) { |
| 525 callback.Run(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); | 525 callback.Run(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); |
| 526 return; | 526 return; |
| 527 } | 527 } |
| 528 | 528 |
| 529 if (format_context_->duration != static_cast<int64_t>(AV_NOPTS_VALUE)) { | 529 if (format_context_->duration != static_cast<int64_t>(AV_NOPTS_VALUE)) { |
| 530 // If there is a duration value in the container use that to find the | 530 // If there is a duration value in the container use that to find the |
| 531 // maximum between it and the duration from A/V streams. | 531 // maximum between it and the duration from A/V streams. |
| 532 const AVRational av_time_base = {1, AV_TIME_BASE}; | 532 const AVRational av_time_base = {1, AV_TIME_BASE}; |
| 533 max_duration = | 533 max_duration = |
| 534 std::max(max_duration, | 534 std::max(max_duration, |
| 535 ConvertFromTimeBase(av_time_base, format_context_->duration)); | 535 ConvertFromTimeBase(av_time_base, format_context_->duration)); |
| 536 } else { | 536 } else { |
| 537 // The duration is unknown, in which case this is likely a live stream. | 537 // The duration is unknown, in which case this is likely a live stream. |
| 538 max_duration = kInfiniteDuration; | 538 max_duration = kInfiniteDuration(); |
| 539 } | 539 } |
| 540 | 540 |
| 541 // Some demuxers, like WAV, do not put timestamps on their frames. We | 541 // Some demuxers, like WAV, do not put timestamps on their frames. We |
| 542 // assume the the start time is 0. | 542 // assume the the start time is 0. |
| 543 if (start_time_ == kNoTimestamp) | 543 if (start_time_ == kNoTimestamp()) |
| 544 start_time_ = base::TimeDelta(); | 544 start_time_ = base::TimeDelta(); |
| 545 | 545 |
| 546 // Good to go: set the duration and bitrate and notify we're done | 546 // Good to go: set the duration and bitrate and notify we're done |
| 547 // initializing. | 547 // initializing. |
| 548 if (host()) | 548 if (host()) |
| 549 host()->SetDuration(max_duration); | 549 host()->SetDuration(max_duration); |
| 550 max_duration_ = max_duration; | 550 max_duration_ = max_duration; |
| 551 | 551 |
| 552 int bitrate = GetBitrate(); | 552 int bitrate = GetBitrate(); |
| 553 if (bitrate > 0) | 553 if (bitrate > 0) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 569 AVCodecContext* codec_context = format_context_->streams[i]->codec; | 569 AVCodecContext* codec_context = format_context_->streams[i]->codec; |
| 570 bitrate += codec_context->bit_rate; | 570 bitrate += codec_context->bit_rate; |
| 571 } | 571 } |
| 572 if (bitrate > 0) | 572 if (bitrate > 0) |
| 573 return bitrate; | 573 return bitrate; |
| 574 | 574 |
| 575 // See if we can approximate the bitrate as long as we have a filesize and | 575 // See if we can approximate the bitrate as long as we have a filesize and |
| 576 // valid duration. | 576 // valid duration. |
| 577 int64 filesize_in_bytes; | 577 int64 filesize_in_bytes; |
| 578 if (max_duration_.InMicroseconds() <= 0 || | 578 if (max_duration_.InMicroseconds() <= 0 || |
| 579 max_duration_ == kInfiniteDuration || | 579 max_duration_ == kInfiniteDuration() || |
| 580 !GetSize(&filesize_in_bytes)) { | 580 !GetSize(&filesize_in_bytes)) { |
| 581 return 0; | 581 return 0; |
| 582 } | 582 } |
| 583 | 583 |
| 584 // Do math in floating point as we'd overflow an int64 if the filesize was | 584 // Do math in floating point as we'd overflow an int64 if the filesize was |
| 585 // larger than ~1073GB. | 585 // larger than ~1073GB. |
| 586 double bytes = filesize_in_bytes; | 586 double bytes = filesize_in_bytes; |
| 587 double duration = max_duration_.InMicroseconds(); | 587 double duration = max_duration_.InMicroseconds(); |
| 588 return bytes * 8000000.0 / duration; | 588 return bytes * 8000000.0 / duration; |
| 589 } | 589 } |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 read_event_.Wait(); | 738 read_event_.Wait(); |
| 739 return last_read_bytes_; | 739 return last_read_bytes_; |
| 740 } | 740 } |
| 741 | 741 |
| 742 void FFmpegDemuxer::SignalReadCompleted(size_t size) { | 742 void FFmpegDemuxer::SignalReadCompleted(size_t size) { |
| 743 last_read_bytes_ = size; | 743 last_read_bytes_ = size; |
| 744 read_event_.Signal(); | 744 read_event_.Signal(); |
| 745 } | 745 } |
| 746 | 746 |
| 747 } // namespace media | 747 } // namespace media |
| OLD | NEW |