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 |