Chromium Code Reviews| 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 "media/filters/ffmpeg_demuxer.h" | 5 #include "media/filters/ffmpeg_demuxer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 | 84 |
| 85 // | 85 // |
| 86 // FFmpegDemuxerStream | 86 // FFmpegDemuxerStream |
| 87 // | 87 // |
| 88 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, | 88 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, |
| 89 AVStream* stream) | 89 AVStream* stream) |
| 90 : demuxer_(demuxer), | 90 : demuxer_(demuxer), |
| 91 task_runner_(base::MessageLoopProxy::current()), | 91 task_runner_(base::MessageLoopProxy::current()), |
| 92 stream_(stream), | 92 stream_(stream), |
| 93 type_(UNKNOWN), | 93 type_(UNKNOWN), |
| 94 liveness_(LIVENESS_UNKNOWN), | |
| 94 end_of_stream_(false), | 95 end_of_stream_(false), |
| 95 last_packet_timestamp_(kNoTimestamp()), | 96 last_packet_timestamp_(kNoTimestamp()), |
| 96 last_packet_duration_(kNoTimestamp()), | 97 last_packet_duration_(kNoTimestamp()), |
| 97 video_rotation_(VIDEO_ROTATION_0), | 98 video_rotation_(VIDEO_ROTATION_0), |
| 98 bitstream_converter_enabled_(false), | 99 bitstream_converter_enabled_(false), |
| 99 fixup_negative_ogg_timestamps_(false) { | 100 fixup_negative_ogg_timestamps_(false) { |
| 100 DCHECK(demuxer_); | 101 DCHECK(demuxer_); |
| 101 | 102 |
| 102 bool is_encrypted = false; | 103 bool is_encrypted = false; |
| 103 int rotation = 0; | 104 int rotation = 0; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 base::Base64Decode(base64_key_id, &enc_key_id); | 168 base::Base64Decode(base64_key_id, &enc_key_id); |
| 168 DCHECK(!enc_key_id.empty()); | 169 DCHECK(!enc_key_id.empty()); |
| 169 if (enc_key_id.empty()) | 170 if (enc_key_id.empty()) |
| 170 return; | 171 return; |
| 171 | 172 |
| 172 encryption_key_id_.assign(enc_key_id); | 173 encryption_key_id_.assign(enc_key_id); |
| 173 demuxer_->FireNeedKey(kWebMInitDataType, enc_key_id); | 174 demuxer_->FireNeedKey(kWebMInitDataType, enc_key_id); |
| 174 } | 175 } |
| 175 } | 176 } |
| 176 | 177 |
| 178 FFmpegDemuxerStream::~FFmpegDemuxerStream() { | |
| 179 DCHECK(!demuxer_); | |
| 180 DCHECK(read_cb_.is_null()); | |
| 181 DCHECK(buffer_queue_.IsEmpty()); | |
| 182 } | |
| 183 | |
| 177 void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { | 184 void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { |
| 178 DCHECK(task_runner_->BelongsToCurrentThread()); | 185 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 179 | 186 |
| 180 if (!demuxer_ || end_of_stream_) { | 187 if (!demuxer_ || end_of_stream_) { |
| 181 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; | 188 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; |
| 182 return; | 189 return; |
| 183 } | 190 } |
| 184 | 191 |
| 185 #if defined(USE_PROPRIETARY_CODECS) | 192 #if defined(USE_PROPRIETARY_CODECS) |
| 186 // Convert the packet if there is a bitstream filter. | 193 // Convert the packet if there is a bitstream filter. |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 404 demuxer_ = NULL; | 411 demuxer_ = NULL; |
| 405 stream_ = NULL; | 412 stream_ = NULL; |
| 406 end_of_stream_ = true; | 413 end_of_stream_ = true; |
| 407 } | 414 } |
| 408 | 415 |
| 409 DemuxerStream::Type FFmpegDemuxerStream::type() { | 416 DemuxerStream::Type FFmpegDemuxerStream::type() { |
| 410 DCHECK(task_runner_->BelongsToCurrentThread()); | 417 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 411 return type_; | 418 return type_; |
| 412 } | 419 } |
| 413 | 420 |
| 421 DemuxerStream::Liveness FFmpegDemuxerStream::liveness() { | |
| 422 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 423 return liveness_; | |
| 424 } | |
| 425 | |
| 414 void FFmpegDemuxerStream::Read(const ReadCB& read_cb) { | 426 void FFmpegDemuxerStream::Read(const ReadCB& read_cb) { |
| 415 DCHECK(task_runner_->BelongsToCurrentThread()); | 427 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 416 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported"; | 428 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported"; |
| 417 read_cb_ = BindToCurrentLoop(read_cb); | 429 read_cb_ = BindToCurrentLoop(read_cb); |
| 418 | 430 |
| 419 // Don't accept any additional reads if we've been told to stop. | 431 // Don't accept any additional reads if we've been told to stop. |
| 420 // The |demuxer_| may have been destroyed in the pipeline thread. | 432 // The |demuxer_| may have been destroyed in the pipeline thread. |
| 421 // | 433 // |
| 422 // TODO(scherkus): it would be cleaner to reply with an error message. | 434 // TODO(scherkus): it would be cleaner to reply with an error message. |
| 423 if (!demuxer_) { | 435 if (!demuxer_) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 VideoDecoderConfig FFmpegDemuxerStream::video_decoder_config() { | 473 VideoDecoderConfig FFmpegDemuxerStream::video_decoder_config() { |
| 462 DCHECK(task_runner_->BelongsToCurrentThread()); | 474 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 463 CHECK_EQ(type_, VIDEO); | 475 CHECK_EQ(type_, VIDEO); |
| 464 return video_config_; | 476 return video_config_; |
| 465 } | 477 } |
| 466 | 478 |
| 467 VideoRotation FFmpegDemuxerStream::video_rotation() { | 479 VideoRotation FFmpegDemuxerStream::video_rotation() { |
| 468 return video_rotation_; | 480 return video_rotation_; |
| 469 } | 481 } |
| 470 | 482 |
| 471 FFmpegDemuxerStream::~FFmpegDemuxerStream() { | 483 void FFmpegDemuxerStream::SetLiveness(Liveness liveness) { |
| 472 DCHECK(!demuxer_); | 484 DCHECK_EQ(liveness_, LIVENESS_UNKNOWN); |
|
wolenetz
2014/11/11 23:48:07
nit: DCHECK we're on the right thread?
xhwang
2014/11/14 06:38:04
Done.
| |
| 473 DCHECK(read_cb_.is_null()); | 485 liveness_ = liveness; |
| 474 DCHECK(buffer_queue_.IsEmpty()); | |
| 475 } | 486 } |
| 476 | 487 |
| 477 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { | 488 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { |
| 478 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); | 489 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); |
| 479 } | 490 } |
| 480 | 491 |
| 481 Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const { | 492 Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const { |
| 482 return buffered_ranges_; | 493 return buffered_ranges_; |
| 483 } | 494 } |
| 484 | 495 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 559 task_runner_(task_runner), | 570 task_runner_(task_runner), |
| 560 blocking_thread_("FFmpegDemuxer"), | 571 blocking_thread_("FFmpegDemuxer"), |
| 561 pending_read_(false), | 572 pending_read_(false), |
| 562 pending_seek_(false), | 573 pending_seek_(false), |
| 563 data_source_(data_source), | 574 data_source_(data_source), |
| 564 media_log_(media_log), | 575 media_log_(media_log), |
| 565 bitrate_(0), | 576 bitrate_(0), |
| 566 start_time_(kNoTimestamp()), | 577 start_time_(kNoTimestamp()), |
| 567 preferred_stream_for_seeking_(-1, kNoTimestamp()), | 578 preferred_stream_for_seeking_(-1, kNoTimestamp()), |
| 568 fallback_stream_for_seeking_(-1, kNoTimestamp()), | 579 fallback_stream_for_seeking_(-1, kNoTimestamp()), |
| 569 liveness_(LIVENESS_UNKNOWN), | |
| 570 text_enabled_(false), | 580 text_enabled_(false), |
| 571 duration_known_(false), | 581 duration_known_(false), |
| 572 need_key_cb_(need_key_cb), | 582 need_key_cb_(need_key_cb), |
| 573 weak_factory_(this) { | 583 weak_factory_(this) { |
| 574 DCHECK(task_runner_.get()); | 584 DCHECK(task_runner_.get()); |
| 575 DCHECK(data_source_); | 585 DCHECK(data_source_); |
| 576 } | 586 } |
| 577 | 587 |
| 578 FFmpegDemuxer::~FFmpegDemuxer() {} | 588 FFmpegDemuxer::~FFmpegDemuxer() {} |
| 579 | 589 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 699 return *iter; | 709 return *iter; |
| 700 } | 710 } |
| 701 } | 711 } |
| 702 return NULL; | 712 return NULL; |
| 703 } | 713 } |
| 704 | 714 |
| 705 base::TimeDelta FFmpegDemuxer::GetStartTime() const { | 715 base::TimeDelta FFmpegDemuxer::GetStartTime() const { |
| 706 return std::max(start_time_, base::TimeDelta()); | 716 return std::max(start_time_, base::TimeDelta()); |
| 707 } | 717 } |
| 708 | 718 |
| 709 Demuxer::Liveness FFmpegDemuxer::GetLiveness() const { | |
| 710 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 711 return liveness_; | |
| 712 } | |
| 713 | |
| 714 void FFmpegDemuxer::AddTextStreams() { | 719 void FFmpegDemuxer::AddTextStreams() { |
| 715 DCHECK(task_runner_->BelongsToCurrentThread()); | 720 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 716 | 721 |
| 717 for (StreamVector::size_type idx = 0; idx < streams_.size(); ++idx) { | 722 for (StreamVector::size_type idx = 0; idx < streams_.size(); ++idx) { |
| 718 FFmpegDemuxerStream* stream = streams_[idx]; | 723 FFmpegDemuxerStream* stream = streams_[idx]; |
| 719 if (stream == NULL || stream->type() != DemuxerStream::TEXT) | 724 if (stream == NULL || stream->type() != DemuxerStream::TEXT) |
| 720 continue; | 725 continue; |
| 721 | 726 |
| 722 TextKind kind = stream->GetTextKind(); | 727 TextKind kind = stream->GetTextKind(); |
| 723 std::string title = stream->GetMetadata("title"); | 728 std::string title = stream->GetMetadata("title"); |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 976 // For testing purposes, don't overwrite the timeline offset if set already. | 981 // For testing purposes, don't overwrite the timeline offset if set already. |
| 977 if (timeline_offset_.is_null()) | 982 if (timeline_offset_.is_null()) |
| 978 timeline_offset_ = ExtractTimelineOffset(format_context); | 983 timeline_offset_ = ExtractTimelineOffset(format_context); |
| 979 | 984 |
| 980 // Since we're shifting the externally visible start time to zero, we need to | 985 // Since we're shifting the externally visible start time to zero, we need to |
| 981 // adjust the timeline offset to compensate. | 986 // adjust the timeline offset to compensate. |
| 982 if (!timeline_offset_.is_null() && start_time_ < base::TimeDelta()) | 987 if (!timeline_offset_.is_null() && start_time_ < base::TimeDelta()) |
| 983 timeline_offset_ += start_time_; | 988 timeline_offset_ += start_time_; |
| 984 | 989 |
| 985 if (max_duration == kInfiniteDuration() && !timeline_offset_.is_null()) { | 990 if (max_duration == kInfiniteDuration() && !timeline_offset_.is_null()) { |
| 986 liveness_ = LIVENESS_LIVE; | 991 SetLiveness(DemuxerStream::LIVENESS_LIVE); |
| 987 } else if (max_duration != kInfiniteDuration()) { | 992 } else if (max_duration != kInfiniteDuration()) { |
| 988 liveness_ = LIVENESS_RECORDED; | 993 SetLiveness(DemuxerStream::LIVENESS_RECORDED); |
| 989 } else { | 994 } else { |
| 990 liveness_ = LIVENESS_UNKNOWN; | 995 SetLiveness(DemuxerStream::LIVENESS_UNKNOWN); |
| 991 } | 996 } |
| 992 | 997 |
| 993 // Good to go: set the duration and bitrate and notify we're done | 998 // Good to go: set the duration and bitrate and notify we're done |
| 994 // initializing. | 999 // initializing. |
| 995 host_->SetDuration(max_duration); | 1000 host_->SetDuration(max_duration); |
| 996 duration_known_ = (max_duration != kInfiniteDuration()); | 1001 duration_known_ = (max_duration != kInfiniteDuration()); |
| 997 | 1002 |
| 998 int64 filesize_in_bytes = 0; | 1003 int64 filesize_in_bytes = 0; |
| 999 url_protocol_->GetSize(&filesize_in_bytes); | 1004 url_protocol_->GetSize(&filesize_in_bytes); |
| 1000 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); | 1005 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1263 buffered = video->GetBufferedRanges(); | 1268 buffered = video->GetBufferedRanges(); |
| 1264 } | 1269 } |
| 1265 for (size_t i = 0; i < buffered.size(); ++i) | 1270 for (size_t i = 0; i < buffered.size(); ++i) |
| 1266 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); | 1271 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); |
| 1267 } | 1272 } |
| 1268 | 1273 |
| 1269 void FFmpegDemuxer::OnDataSourceError() { | 1274 void FFmpegDemuxer::OnDataSourceError() { |
| 1270 host_->OnDemuxerError(PIPELINE_ERROR_READ); | 1275 host_->OnDemuxerError(PIPELINE_ERROR_READ); |
| 1271 } | 1276 } |
| 1272 | 1277 |
| 1278 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | |
| 1279 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. | |
|
wolenetz
2014/11/11 23:48:07
nit: DCHECK we're on the right thread?
xhwang
2014/11/14 06:38:04
Done.
| |
| 1280 if (stream) | |
| 1281 stream->SetLiveness(liveness); | |
| 1282 } | |
| 1283 } | |
| 1284 | |
| 1273 } // namespace media | 1285 } // namespace media |
| OLD | NEW |