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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 | 86 |
87 // | 87 // |
88 // FFmpegDemuxerStream | 88 // FFmpegDemuxerStream |
89 // | 89 // |
90 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, | 90 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, |
91 AVStream* stream) | 91 AVStream* stream) |
92 : demuxer_(demuxer), | 92 : demuxer_(demuxer), |
93 task_runner_(base::MessageLoopProxy::current()), | 93 task_runner_(base::MessageLoopProxy::current()), |
94 stream_(stream), | 94 stream_(stream), |
95 type_(UNKNOWN), | 95 type_(UNKNOWN), |
| 96 liveness_(LIVENESS_UNKNOWN), |
96 end_of_stream_(false), | 97 end_of_stream_(false), |
97 last_packet_timestamp_(kNoTimestamp()), | 98 last_packet_timestamp_(kNoTimestamp()), |
98 last_packet_duration_(kNoTimestamp()), | 99 last_packet_duration_(kNoTimestamp()), |
99 video_rotation_(VIDEO_ROTATION_0), | 100 video_rotation_(VIDEO_ROTATION_0), |
100 fixup_negative_ogg_timestamps_(false) { | 101 fixup_negative_ogg_timestamps_(false) { |
101 DCHECK(demuxer_); | 102 DCHECK(demuxer_); |
102 | 103 |
103 bool is_encrypted = false; | 104 bool is_encrypted = false; |
104 int rotation = 0; | 105 int rotation = 0; |
105 AVDictionaryEntry* rotation_entry = NULL; | 106 AVDictionaryEntry* rotation_entry = NULL; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 base::Base64Decode(base64_key_id, &enc_key_id); | 162 base::Base64Decode(base64_key_id, &enc_key_id); |
162 DCHECK(!enc_key_id.empty()); | 163 DCHECK(!enc_key_id.empty()); |
163 if (enc_key_id.empty()) | 164 if (enc_key_id.empty()) |
164 return; | 165 return; |
165 | 166 |
166 encryption_key_id_.assign(enc_key_id); | 167 encryption_key_id_.assign(enc_key_id); |
167 demuxer_->FireNeedKey(kWebMInitDataType, enc_key_id); | 168 demuxer_->FireNeedKey(kWebMInitDataType, enc_key_id); |
168 } | 169 } |
169 } | 170 } |
170 | 171 |
| 172 FFmpegDemuxerStream::~FFmpegDemuxerStream() { |
| 173 DCHECK(!demuxer_); |
| 174 DCHECK(read_cb_.is_null()); |
| 175 DCHECK(buffer_queue_.IsEmpty()); |
| 176 } |
| 177 |
171 void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { | 178 void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { |
172 DCHECK(task_runner_->BelongsToCurrentThread()); | 179 DCHECK(task_runner_->BelongsToCurrentThread()); |
173 | 180 |
174 if (!demuxer_ || end_of_stream_) { | 181 if (!demuxer_ || end_of_stream_) { |
175 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; | 182 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; |
176 return; | 183 return; |
177 } | 184 } |
178 | 185 |
179 #if defined(USE_PROPRIETARY_CODECS) | 186 #if defined(USE_PROPRIETARY_CODECS) |
180 // Convert the packet if there is a bitstream filter. | 187 // Convert the packet if there is a bitstream filter. |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 buffer_queue_.Clear(); | 403 buffer_queue_.Clear(); |
397 if (!read_cb_.is_null()) { | 404 if (!read_cb_.is_null()) { |
398 base::ResetAndReturn(&read_cb_).Run( | 405 base::ResetAndReturn(&read_cb_).Run( |
399 DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()); | 406 DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()); |
400 } | 407 } |
401 demuxer_ = NULL; | 408 demuxer_ = NULL; |
402 stream_ = NULL; | 409 stream_ = NULL; |
403 end_of_stream_ = true; | 410 end_of_stream_ = true; |
404 } | 411 } |
405 | 412 |
406 DemuxerStream::Type FFmpegDemuxerStream::type() { | 413 DemuxerStream::Type FFmpegDemuxerStream::type() const { |
407 DCHECK(task_runner_->BelongsToCurrentThread()); | 414 DCHECK(task_runner_->BelongsToCurrentThread()); |
408 return type_; | 415 return type_; |
409 } | 416 } |
410 | 417 |
| 418 DemuxerStream::Liveness FFmpegDemuxerStream::liveness() const { |
| 419 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 420 return liveness_; |
| 421 } |
| 422 |
411 void FFmpegDemuxerStream::Read(const ReadCB& read_cb) { | 423 void FFmpegDemuxerStream::Read(const ReadCB& read_cb) { |
412 DCHECK(task_runner_->BelongsToCurrentThread()); | 424 DCHECK(task_runner_->BelongsToCurrentThread()); |
413 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported"; | 425 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported"; |
414 read_cb_ = BindToCurrentLoop(read_cb); | 426 read_cb_ = BindToCurrentLoop(read_cb); |
415 | 427 |
416 // Don't accept any additional reads if we've been told to stop. | 428 // Don't accept any additional reads if we've been told to stop. |
417 // The |demuxer_| may have been destroyed in the pipeline thread. | 429 // The |demuxer_| may have been destroyed in the pipeline thread. |
418 // | 430 // |
419 // TODO(scherkus): it would be cleaner to reply with an error message. | 431 // TODO(scherkus): it would be cleaner to reply with an error message. |
420 if (!demuxer_) { | 432 if (!demuxer_) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 VideoDecoderConfig FFmpegDemuxerStream::video_decoder_config() { | 478 VideoDecoderConfig FFmpegDemuxerStream::video_decoder_config() { |
467 DCHECK(task_runner_->BelongsToCurrentThread()); | 479 DCHECK(task_runner_->BelongsToCurrentThread()); |
468 CHECK_EQ(type_, VIDEO); | 480 CHECK_EQ(type_, VIDEO); |
469 return video_config_; | 481 return video_config_; |
470 } | 482 } |
471 | 483 |
472 VideoRotation FFmpegDemuxerStream::video_rotation() { | 484 VideoRotation FFmpegDemuxerStream::video_rotation() { |
473 return video_rotation_; | 485 return video_rotation_; |
474 } | 486 } |
475 | 487 |
476 FFmpegDemuxerStream::~FFmpegDemuxerStream() { | 488 void FFmpegDemuxerStream::SetLiveness(Liveness liveness) { |
477 DCHECK(!demuxer_); | 489 DCHECK(task_runner_->BelongsToCurrentThread()); |
478 DCHECK(read_cb_.is_null()); | 490 DCHECK_EQ(liveness_, LIVENESS_UNKNOWN); |
479 DCHECK(buffer_queue_.IsEmpty()); | 491 liveness_ = liveness; |
480 } | 492 } |
481 | 493 |
482 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { | 494 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { |
483 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); | 495 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); |
484 } | 496 } |
485 | 497 |
486 Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const { | 498 Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const { |
487 return buffered_ranges_; | 499 return buffered_ranges_; |
488 } | 500 } |
489 | 501 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 task_runner_(task_runner), | 576 task_runner_(task_runner), |
565 blocking_thread_("FFmpegDemuxer"), | 577 blocking_thread_("FFmpegDemuxer"), |
566 pending_read_(false), | 578 pending_read_(false), |
567 pending_seek_(false), | 579 pending_seek_(false), |
568 data_source_(data_source), | 580 data_source_(data_source), |
569 media_log_(media_log), | 581 media_log_(media_log), |
570 bitrate_(0), | 582 bitrate_(0), |
571 start_time_(kNoTimestamp()), | 583 start_time_(kNoTimestamp()), |
572 preferred_stream_for_seeking_(-1, kNoTimestamp()), | 584 preferred_stream_for_seeking_(-1, kNoTimestamp()), |
573 fallback_stream_for_seeking_(-1, kNoTimestamp()), | 585 fallback_stream_for_seeking_(-1, kNoTimestamp()), |
574 liveness_(LIVENESS_UNKNOWN), | |
575 text_enabled_(false), | 586 text_enabled_(false), |
576 duration_known_(false), | 587 duration_known_(false), |
577 need_key_cb_(need_key_cb), | 588 need_key_cb_(need_key_cb), |
578 weak_factory_(this) { | 589 weak_factory_(this) { |
579 DCHECK(task_runner_.get()); | 590 DCHECK(task_runner_.get()); |
580 DCHECK(data_source_); | 591 DCHECK(data_source_); |
581 } | 592 } |
582 | 593 |
583 FFmpegDemuxer::~FFmpegDemuxer() {} | 594 FFmpegDemuxer::~FFmpegDemuxer() {} |
584 | 595 |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
704 return *iter; | 715 return *iter; |
705 } | 716 } |
706 } | 717 } |
707 return NULL; | 718 return NULL; |
708 } | 719 } |
709 | 720 |
710 base::TimeDelta FFmpegDemuxer::GetStartTime() const { | 721 base::TimeDelta FFmpegDemuxer::GetStartTime() const { |
711 return std::max(start_time_, base::TimeDelta()); | 722 return std::max(start_time_, base::TimeDelta()); |
712 } | 723 } |
713 | 724 |
714 Demuxer::Liveness FFmpegDemuxer::GetLiveness() const { | |
715 DCHECK(task_runner_->BelongsToCurrentThread()); | |
716 return liveness_; | |
717 } | |
718 | |
719 void FFmpegDemuxer::AddTextStreams() { | 725 void FFmpegDemuxer::AddTextStreams() { |
720 DCHECK(task_runner_->BelongsToCurrentThread()); | 726 DCHECK(task_runner_->BelongsToCurrentThread()); |
721 | 727 |
722 for (StreamVector::size_type idx = 0; idx < streams_.size(); ++idx) { | 728 for (StreamVector::size_type idx = 0; idx < streams_.size(); ++idx) { |
723 FFmpegDemuxerStream* stream = streams_[idx]; | 729 FFmpegDemuxerStream* stream = streams_[idx]; |
724 if (stream == NULL || stream->type() != DemuxerStream::TEXT) | 730 if (stream == NULL || stream->type() != DemuxerStream::TEXT) |
725 continue; | 731 continue; |
726 | 732 |
727 TextKind kind = stream->GetTextKind(); | 733 TextKind kind = stream->GetTextKind(); |
728 std::string title = stream->GetMetadata("title"); | 734 std::string title = stream->GetMetadata("title"); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 // For testing purposes, don't overwrite the timeline offset if set already. | 987 // For testing purposes, don't overwrite the timeline offset if set already. |
982 if (timeline_offset_.is_null()) | 988 if (timeline_offset_.is_null()) |
983 timeline_offset_ = ExtractTimelineOffset(format_context); | 989 timeline_offset_ = ExtractTimelineOffset(format_context); |
984 | 990 |
985 // Since we're shifting the externally visible start time to zero, we need to | 991 // Since we're shifting the externally visible start time to zero, we need to |
986 // adjust the timeline offset to compensate. | 992 // adjust the timeline offset to compensate. |
987 if (!timeline_offset_.is_null() && start_time_ < base::TimeDelta()) | 993 if (!timeline_offset_.is_null() && start_time_ < base::TimeDelta()) |
988 timeline_offset_ += start_time_; | 994 timeline_offset_ += start_time_; |
989 | 995 |
990 if (max_duration == kInfiniteDuration() && !timeline_offset_.is_null()) { | 996 if (max_duration == kInfiniteDuration() && !timeline_offset_.is_null()) { |
991 liveness_ = LIVENESS_LIVE; | 997 SetLiveness(DemuxerStream::LIVENESS_LIVE); |
992 } else if (max_duration != kInfiniteDuration()) { | 998 } else if (max_duration != kInfiniteDuration()) { |
993 liveness_ = LIVENESS_RECORDED; | 999 SetLiveness(DemuxerStream::LIVENESS_RECORDED); |
994 } else { | 1000 } else { |
995 liveness_ = LIVENESS_UNKNOWN; | 1001 SetLiveness(DemuxerStream::LIVENESS_UNKNOWN); |
996 } | 1002 } |
997 | 1003 |
998 // Good to go: set the duration and bitrate and notify we're done | 1004 // Good to go: set the duration and bitrate and notify we're done |
999 // initializing. | 1005 // initializing. |
1000 host_->SetDuration(max_duration); | 1006 host_->SetDuration(max_duration); |
1001 duration_known_ = (max_duration != kInfiniteDuration()); | 1007 duration_known_ = (max_duration != kInfiniteDuration()); |
1002 | 1008 |
1003 int64 filesize_in_bytes = 0; | 1009 int64 filesize_in_bytes = 0; |
1004 url_protocol_->GetSize(&filesize_in_bytes); | 1010 url_protocol_->GetSize(&filesize_in_bytes); |
1005 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); | 1011 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1268 buffered = video->GetBufferedRanges(); | 1274 buffered = video->GetBufferedRanges(); |
1269 } | 1275 } |
1270 for (size_t i = 0; i < buffered.size(); ++i) | 1276 for (size_t i = 0; i < buffered.size(); ++i) |
1271 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); | 1277 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); |
1272 } | 1278 } |
1273 | 1279 |
1274 void FFmpegDemuxer::OnDataSourceError() { | 1280 void FFmpegDemuxer::OnDataSourceError() { |
1275 host_->OnDemuxerError(PIPELINE_ERROR_READ); | 1281 host_->OnDemuxerError(PIPELINE_ERROR_READ); |
1276 } | 1282 } |
1277 | 1283 |
| 1284 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
| 1285 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 1286 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. |
| 1287 if (stream) |
| 1288 stream->SetLiveness(liveness); |
| 1289 } |
| 1290 } |
| 1291 |
1278 } // namespace media | 1292 } // namespace media |
OLD | NEW |