| 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 |