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 <memory> | 8 #include <memory> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 } | 246 } |
247 | 247 |
248 MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created video stream, config " | 248 MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created video stream, config " |
249 << video_config->AsHumanReadableString(); | 249 << video_config->AsHumanReadableString(); |
250 } | 250 } |
251 | 251 |
252 return base::WrapUnique(new FFmpegDemuxerStream( | 252 return base::WrapUnique(new FFmpegDemuxerStream( |
253 demuxer, stream, std::move(audio_config), std::move(video_config))); | 253 demuxer, stream, std::move(audio_config), std::move(video_config))); |
254 } | 254 } |
255 | 255 |
| 256 static void UnmarkEndOfStream(AVFormatContext* format_context) { |
| 257 format_context->pb->eof_reached = 0; |
| 258 } |
| 259 |
256 // | 260 // |
257 // FFmpegDemuxerStream | 261 // FFmpegDemuxerStream |
258 // | 262 // |
259 FFmpegDemuxerStream::FFmpegDemuxerStream( | 263 FFmpegDemuxerStream::FFmpegDemuxerStream( |
260 FFmpegDemuxer* demuxer, | 264 FFmpegDemuxer* demuxer, |
261 AVStream* stream, | 265 AVStream* stream, |
262 std::unique_ptr<AudioDecoderConfig> audio_config, | 266 std::unique_ptr<AudioDecoderConfig> audio_config, |
263 std::unique_ptr<VideoDecoderConfig> video_config) | 267 std::unique_ptr<VideoDecoderConfig> video_config) |
264 : demuxer_(demuxer), | 268 : demuxer_(demuxer), |
265 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 269 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 // Reset bitstream for converter to do so. | 590 // Reset bitstream for converter to do so. |
587 // This is related to chromium issue 140371 (http://crbug.com/140371). | 591 // This is related to chromium issue 140371 (http://crbug.com/140371). |
588 ResetBitstreamConverter(); | 592 ResetBitstreamConverter(); |
589 | 593 |
590 buffer_queue_.Clear(); | 594 buffer_queue_.Clear(); |
591 end_of_stream_ = false; | 595 end_of_stream_ = false; |
592 last_packet_timestamp_ = kNoTimestamp; | 596 last_packet_timestamp_ = kNoTimestamp; |
593 last_packet_duration_ = kNoTimestamp; | 597 last_packet_duration_ = kNoTimestamp; |
594 } | 598 } |
595 | 599 |
| 600 void FFmpegDemuxerStream::Abort() { |
| 601 if (!read_cb_.is_null()) |
| 602 base::ResetAndReturn(&read_cb_).Run(DemuxerStream::kAborted, nullptr); |
| 603 } |
| 604 |
596 void FFmpegDemuxerStream::Stop() { | 605 void FFmpegDemuxerStream::Stop() { |
597 DCHECK(task_runner_->BelongsToCurrentThread()); | 606 DCHECK(task_runner_->BelongsToCurrentThread()); |
598 buffer_queue_.Clear(); | 607 buffer_queue_.Clear(); |
599 if (!read_cb_.is_null()) { | 608 if (!read_cb_.is_null()) { |
600 base::ResetAndReturn(&read_cb_).Run( | 609 base::ResetAndReturn(&read_cb_).Run( |
601 DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()); | 610 DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()); |
602 } | 611 } |
603 demuxer_ = NULL; | 612 demuxer_ = NULL; |
604 stream_ = NULL; | 613 stream_ = NULL; |
605 end_of_stream_ = true; | 614 end_of_stream_ = true; |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
814 FFmpegDemuxer::FFmpegDemuxer( | 823 FFmpegDemuxer::FFmpegDemuxer( |
815 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 824 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
816 DataSource* data_source, | 825 DataSource* data_source, |
817 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, | 826 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, |
818 const MediaTracksUpdatedCB& media_tracks_updated_cb, | 827 const MediaTracksUpdatedCB& media_tracks_updated_cb, |
819 const scoped_refptr<MediaLog>& media_log) | 828 const scoped_refptr<MediaLog>& media_log) |
820 : host_(NULL), | 829 : host_(NULL), |
821 task_runner_(task_runner), | 830 task_runner_(task_runner), |
822 blocking_thread_("FFmpegDemuxer"), | 831 blocking_thread_("FFmpegDemuxer"), |
823 pending_read_(false), | 832 pending_read_(false), |
824 pending_seek_(false), | |
825 data_source_(data_source), | 833 data_source_(data_source), |
826 media_log_(media_log), | 834 media_log_(media_log), |
827 bitrate_(0), | 835 bitrate_(0), |
828 start_time_(kNoTimestamp), | 836 start_time_(kNoTimestamp), |
829 text_enabled_(false), | 837 text_enabled_(false), |
830 duration_known_(false), | 838 duration_known_(false), |
831 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), | 839 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), |
832 media_tracks_updated_cb_(media_tracks_updated_cb), | 840 media_tracks_updated_cb_(media_tracks_updated_cb), |
833 weak_factory_(this) { | 841 weak_factory_(this) { |
834 DCHECK(task_runner_.get()); | 842 DCHECK(task_runner_.get()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 | 881 |
874 // Open the AVFormatContext using our glue layer. | 882 // Open the AVFormatContext using our glue layer. |
875 CHECK(blocking_thread_.Start()); | 883 CHECK(blocking_thread_.Start()); |
876 base::PostTaskAndReplyWithResult( | 884 base::PostTaskAndReplyWithResult( |
877 blocking_thread_.task_runner().get(), FROM_HERE, | 885 blocking_thread_.task_runner().get(), FROM_HERE, |
878 base::Bind(&FFmpegGlue::OpenContext, base::Unretained(glue_.get())), | 886 base::Bind(&FFmpegGlue::OpenContext, base::Unretained(glue_.get())), |
879 base::Bind(&FFmpegDemuxer::OnOpenContextDone, weak_factory_.GetWeakPtr(), | 887 base::Bind(&FFmpegDemuxer::OnOpenContextDone, weak_factory_.GetWeakPtr(), |
880 status_cb)); | 888 status_cb)); |
881 } | 889 } |
882 | 890 |
| 891 void FFmpegDemuxer::AbortPendingReads() { |
| 892 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 893 |
| 894 // This should only be called after the demuxer has been initialized. |
| 895 DCHECK(blocking_thread_.IsRunning()); |
| 896 DCHECK_GT(streams_.size(), 0u); |
| 897 |
| 898 // Abort all outstanding reads. |
| 899 for (auto* stream : streams_) { |
| 900 if (stream) |
| 901 stream->Abort(); |
| 902 } |
| 903 |
| 904 // It's important to invalidate read/seek completion callbacks to avoid any |
| 905 // errors that occur because of the data source abort. |
| 906 weak_factory_.InvalidateWeakPtrs(); |
| 907 data_source_->Abort(); |
| 908 |
| 909 // Aborting the read may cause EOF to be marked, undo this. |
| 910 blocking_thread_.task_runner()->PostTask( |
| 911 FROM_HERE, base::Bind(&UnmarkEndOfStream, glue_->format_context())); |
| 912 pending_read_ = false; |
| 913 |
| 914 // TODO(dalecurtis): We probably should report PIPELINE_ERROR_ABORT here |
| 915 // instead to avoid any preroll work that may be started upon return, but |
| 916 // currently the PipelineImpl does not know how to handle this. |
| 917 if (!pending_seek_cb_.is_null()) |
| 918 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK); |
| 919 } |
| 920 |
883 void FFmpegDemuxer::Stop() { | 921 void FFmpegDemuxer::Stop() { |
884 DCHECK(task_runner_->BelongsToCurrentThread()); | 922 DCHECK(task_runner_->BelongsToCurrentThread()); |
885 | 923 |
886 // The order of Stop() and Abort() is important here. If Abort() is called | 924 // The order of Stop() and Abort() is important here. If Abort() is called |
887 // first, control may pass into FFmpeg where it can destruct buffers that are | 925 // first, control may pass into FFmpeg where it can destruct buffers that are |
888 // in the process of being fulfilled by the DataSource. | 926 // in the process of being fulfilled by the DataSource. |
889 data_source_->Stop(); | 927 data_source_->Stop(); |
890 url_protocol_->Abort(); | 928 url_protocol_->Abort(); |
891 | 929 |
892 // This will block until all tasks complete. Note that after this returns it's | 930 // This will block until all tasks complete. Note that after this returns it's |
(...skipping 10 matching lines...) Expand all Loading... |
903 | 941 |
904 data_source_ = NULL; | 942 data_source_ = NULL; |
905 | 943 |
906 // Invalidate WeakPtrs on |task_runner_|, destruction may happen on another | 944 // Invalidate WeakPtrs on |task_runner_|, destruction may happen on another |
907 // thread. | 945 // thread. |
908 weak_factory_.InvalidateWeakPtrs(); | 946 weak_factory_.InvalidateWeakPtrs(); |
909 } | 947 } |
910 | 948 |
911 void FFmpegDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) {} | 949 void FFmpegDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) {} |
912 | 950 |
913 void FFmpegDemuxer::CancelPendingSeek(base::TimeDelta seek_time) {} | 951 void FFmpegDemuxer::CancelPendingSeek(base::TimeDelta seek_time) { |
| 952 if (task_runner_->BelongsToCurrentThread()) { |
| 953 AbortPendingReads(); |
| 954 } else { |
| 955 task_runner_->PostTask(FROM_HERE, |
| 956 base::Bind(&FFmpegDemuxer::AbortPendingReads, |
| 957 weak_factory_.GetWeakPtr())); |
| 958 } |
| 959 } |
914 | 960 |
915 void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) { | 961 void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) { |
916 DCHECK(task_runner_->BelongsToCurrentThread()); | 962 DCHECK(task_runner_->BelongsToCurrentThread()); |
917 CHECK(!pending_seek_); | 963 CHECK(pending_seek_cb_.is_null()); |
918 | |
919 // TODO(scherkus): Inspect |pending_read_| and cancel IO via |blocking_url_|, | |
920 // otherwise we can end up waiting for a pre-seek read to complete even though | |
921 // we know we're going to drop it on the floor. | |
922 | 964 |
923 // FFmpeg requires seeks to be adjusted according to the lowest starting time. | 965 // FFmpeg requires seeks to be adjusted according to the lowest starting time. |
924 // Since EnqueuePacket() rebased negative timestamps by the start time, we | 966 // Since EnqueuePacket() rebased negative timestamps by the start time, we |
925 // must correct the shift here. | 967 // must correct the shift here. |
926 // | 968 // |
927 // Additionally, to workaround limitations in how we expose seekable ranges to | 969 // Additionally, to workaround limitations in how we expose seekable ranges to |
928 // Blink (http://crbug.com/137275), we also want to clamp seeks before the | 970 // Blink (http://crbug.com/137275), we also want to clamp seeks before the |
929 // start time to the start time. | 971 // start time to the start time. |
930 base::TimeDelta seek_time = start_time_ < base::TimeDelta() | 972 base::TimeDelta seek_time = start_time_ < base::TimeDelta() |
931 ? time + start_time_ | 973 ? time + start_time_ |
(...skipping 16 matching lines...) Expand all Loading... |
948 // given container will demux all packets after the seek point. Instead it | 990 // given container will demux all packets after the seek point. Instead it |
949 // only guarantees that all packets after the file position of the seek will | 991 // only guarantees that all packets after the file position of the seek will |
950 // be demuxed. It's an open question whether FFmpeg should fix this: | 992 // be demuxed. It's an open question whether FFmpeg should fix this: |
951 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html | 993 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html |
952 // Tracked by http://crbug.com/387996. | 994 // Tracked by http://crbug.com/387996. |
953 FFmpegDemuxerStream* demux_stream = FindPreferredStreamForSeeking(seek_time); | 995 FFmpegDemuxerStream* demux_stream = FindPreferredStreamForSeeking(seek_time); |
954 DCHECK(demux_stream); | 996 DCHECK(demux_stream); |
955 const AVStream* seeking_stream = demux_stream->av_stream(); | 997 const AVStream* seeking_stream = demux_stream->av_stream(); |
956 DCHECK(seeking_stream); | 998 DCHECK(seeking_stream); |
957 | 999 |
958 pending_seek_ = true; | 1000 pending_seek_cb_ = cb; |
959 base::PostTaskAndReplyWithResult( | 1001 base::PostTaskAndReplyWithResult( |
960 blocking_thread_.task_runner().get(), | 1002 blocking_thread_.task_runner().get(), FROM_HERE, |
961 FROM_HERE, | 1003 base::Bind(&av_seek_frame, glue_->format_context(), seeking_stream->index, |
962 base::Bind(&av_seek_frame, | |
963 glue_->format_context(), | |
964 seeking_stream->index, | |
965 ConvertToTimeBase(seeking_stream->time_base, seek_time), | 1004 ConvertToTimeBase(seeking_stream->time_base, seek_time), |
966 // Always seek to a timestamp <= to the desired timestamp. | 1005 // Always seek to a timestamp <= to the desired timestamp. |
967 AVSEEK_FLAG_BACKWARD), | 1006 AVSEEK_FLAG_BACKWARD), |
968 base::Bind( | 1007 base::Bind(&FFmpegDemuxer::OnSeekFrameDone, weak_factory_.GetWeakPtr())); |
969 &FFmpegDemuxer::OnSeekFrameDone, weak_factory_.GetWeakPtr(), cb)); | |
970 } | 1008 } |
971 | 1009 |
972 base::Time FFmpegDemuxer::GetTimelineOffset() const { | 1010 base::Time FFmpegDemuxer::GetTimelineOffset() const { |
973 return timeline_offset_; | 1011 return timeline_offset_; |
974 } | 1012 } |
975 | 1013 |
976 DemuxerStream* FFmpegDemuxer::GetStream(DemuxerStream::Type type) { | 1014 DemuxerStream* FFmpegDemuxer::GetStream(DemuxerStream::Type type) { |
977 DCHECK(task_runner_->BelongsToCurrentThread()); | 1015 DCHECK(task_runner_->BelongsToCurrentThread()); |
978 return GetFFmpegStream(type); | 1016 return GetFFmpegStream(type); |
979 } | 1017 } |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1499 lowest_start_time_stream->start_time() <= seek_time) { | 1537 lowest_start_time_stream->start_time() <= seek_time) { |
1500 return lowest_start_time_stream; | 1538 return lowest_start_time_stream; |
1501 } | 1539 } |
1502 | 1540 |
1503 // If we couldn't find any streams with the start time lower than |seek_time| | 1541 // If we couldn't find any streams with the start time lower than |seek_time| |
1504 // then use either video (if one exists) or any audio stream. | 1542 // then use either video (if one exists) or any audio stream. |
1505 return video_stream ? video_stream : static_cast<FFmpegDemuxerStream*>( | 1543 return video_stream ? video_stream : static_cast<FFmpegDemuxerStream*>( |
1506 GetStream(DemuxerStream::AUDIO)); | 1544 GetStream(DemuxerStream::AUDIO)); |
1507 } | 1545 } |
1508 | 1546 |
1509 void FFmpegDemuxer::OnSeekFrameDone(const PipelineStatusCB& cb, int result) { | 1547 void FFmpegDemuxer::OnSeekFrameDone(int result) { |
1510 DCHECK(task_runner_->BelongsToCurrentThread()); | 1548 DCHECK(task_runner_->BelongsToCurrentThread()); |
1511 CHECK(pending_seek_); | 1549 CHECK(!pending_seek_cb_.is_null()); |
1512 pending_seek_ = false; | |
1513 | 1550 |
1514 if (!blocking_thread_.IsRunning()) { | 1551 if (!blocking_thread_.IsRunning()) { |
1515 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; | 1552 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; |
1516 cb.Run(PIPELINE_ERROR_ABORT); | 1553 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_ERROR_ABORT); |
1517 return; | 1554 return; |
1518 } | 1555 } |
1519 | 1556 |
1520 if (result < 0) { | 1557 if (result < 0) { |
1521 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being | 1558 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being |
1522 // captured from stdout and contaminates testing. | 1559 // captured from stdout and contaminates testing. |
1523 // TODO(scherkus): Implement this properly and signal error (BUG=23447). | 1560 // TODO(scherkus): Implement this properly and signal error (BUG=23447). |
1524 VLOG(1) << "Not implemented"; | 1561 VLOG(1) << "Not implemented"; |
1525 } | 1562 } |
1526 | 1563 |
1527 // Tell streams to flush buffers due to seeking. | 1564 // Tell streams to flush buffers due to seeking. |
1528 StreamVector::iterator iter; | 1565 StreamVector::iterator iter; |
1529 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 1566 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
1530 if (*iter) | 1567 if (*iter) |
1531 (*iter)->FlushBuffers(); | 1568 (*iter)->FlushBuffers(); |
1532 } | 1569 } |
1533 | 1570 |
1534 // Resume reading until capacity. | 1571 // Resume reading until capacity. |
1535 ReadFrameIfNeeded(); | 1572 ReadFrameIfNeeded(); |
1536 | 1573 |
1537 // Notify we're finished seeking. | 1574 // Notify we're finished seeking. |
1538 cb.Run(PIPELINE_OK); | 1575 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK); |
1539 } | 1576 } |
1540 | 1577 |
1541 void FFmpegDemuxer::OnEnabledAudioTracksChanged( | 1578 void FFmpegDemuxer::OnEnabledAudioTracksChanged( |
1542 const std::vector<MediaTrack::Id>& track_ids, | 1579 const std::vector<MediaTrack::Id>& track_ids, |
1543 base::TimeDelta currTime) { | 1580 base::TimeDelta currTime) { |
1544 DCHECK(task_runner_->BelongsToCurrentThread()); | 1581 DCHECK(task_runner_->BelongsToCurrentThread()); |
1545 bool enabled = false; | 1582 bool enabled = false; |
1546 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO); | 1583 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO); |
1547 CHECK(audio_stream); | 1584 CHECK(audio_stream); |
1548 if (track_ids.size() > 0) { | 1585 if (track_ids.size() > 0) { |
(...skipping 19 matching lines...) Expand all Loading... |
1568 DVLOG(1) << __func__ << ": " << (enabled ? "enabling" : "disabling") | 1605 DVLOG(1) << __func__ << ": " << (enabled ? "enabling" : "disabling") |
1569 << " video stream"; | 1606 << " video stream"; |
1570 video_stream->set_enabled(enabled, currTime); | 1607 video_stream->set_enabled(enabled, currTime); |
1571 } | 1608 } |
1572 | 1609 |
1573 void FFmpegDemuxer::ReadFrameIfNeeded() { | 1610 void FFmpegDemuxer::ReadFrameIfNeeded() { |
1574 DCHECK(task_runner_->BelongsToCurrentThread()); | 1611 DCHECK(task_runner_->BelongsToCurrentThread()); |
1575 | 1612 |
1576 // Make sure we have work to do before reading. | 1613 // Make sure we have work to do before reading. |
1577 if (!blocking_thread_.IsRunning() || !StreamsHaveAvailableCapacity() || | 1614 if (!blocking_thread_.IsRunning() || !StreamsHaveAvailableCapacity() || |
1578 pending_read_ || pending_seek_) { | 1615 pending_read_ || !pending_seek_cb_.is_null()) { |
1579 return; | 1616 return; |
1580 } | 1617 } |
1581 | 1618 |
1582 // Allocate and read an AVPacket from the media. Save |packet_ptr| since | 1619 // Allocate and read an AVPacket from the media. Save |packet_ptr| since |
1583 // evaluation order of packet.get() and base::Passed(&packet) is | 1620 // evaluation order of packet.get() and base::Passed(&packet) is |
1584 // undefined. | 1621 // undefined. |
1585 ScopedAVPacket packet(new AVPacket()); | 1622 ScopedAVPacket packet(new AVPacket()); |
1586 AVPacket* packet_ptr = packet.get(); | 1623 AVPacket* packet_ptr = packet.get(); |
1587 | 1624 |
1588 pending_read_ = true; | 1625 pending_read_ = true; |
1589 base::PostTaskAndReplyWithResult( | 1626 base::PostTaskAndReplyWithResult( |
1590 blocking_thread_.task_runner().get(), | 1627 blocking_thread_.task_runner().get(), |
1591 FROM_HERE, | 1628 FROM_HERE, |
1592 base::Bind(&av_read_frame, glue_->format_context(), packet_ptr), | 1629 base::Bind(&av_read_frame, glue_->format_context(), packet_ptr), |
1593 base::Bind(&FFmpegDemuxer::OnReadFrameDone, | 1630 base::Bind(&FFmpegDemuxer::OnReadFrameDone, |
1594 weak_factory_.GetWeakPtr(), | 1631 weak_factory_.GetWeakPtr(), |
1595 base::Passed(&packet))); | 1632 base::Passed(&packet))); |
1596 } | 1633 } |
1597 | 1634 |
1598 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { | 1635 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { |
1599 DCHECK(task_runner_->BelongsToCurrentThread()); | 1636 DCHECK(task_runner_->BelongsToCurrentThread()); |
1600 DCHECK(pending_read_); | 1637 DCHECK(pending_read_); |
1601 pending_read_ = false; | 1638 pending_read_ = false; |
1602 | 1639 |
1603 if (!blocking_thread_.IsRunning() || pending_seek_) { | 1640 if (!blocking_thread_.IsRunning() || !pending_seek_cb_.is_null()) |
1604 return; | 1641 return; |
1605 } | |
1606 | 1642 |
1607 // Consider the stream as ended if: | 1643 // Consider the stream as ended if: |
1608 // - either underlying ffmpeg returned an error | 1644 // - either underlying ffmpeg returned an error |
1609 // - or FFMpegDemuxer reached the maximum allowed memory usage. | 1645 // - or FFMpegDemuxer reached the maximum allowed memory usage. |
1610 if (result < 0 || IsMaxMemoryUsageReached()) { | 1646 if (result < 0 || IsMaxMemoryUsageReached()) { |
1611 LOG(ERROR) << __func__ << " result=" << result | 1647 DVLOG(1) << __func__ << " result=" << result |
1612 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached(); | 1648 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached(); |
1613 // Update the duration based on the highest elapsed time across all streams | 1649 // Update the duration based on the highest elapsed time across all streams |
1614 // if it was previously unknown. | 1650 // if it was previously unknown. |
1615 if (!duration_known_) { | 1651 if (!duration_known_) { |
1616 base::TimeDelta max_duration; | 1652 base::TimeDelta max_duration; |
1617 | 1653 |
1618 for (StreamVector::iterator iter = streams_.begin(); | 1654 for (StreamVector::iterator iter = streams_.begin(); |
1619 iter != streams_.end(); | 1655 iter != streams_.end(); |
1620 ++iter) { | 1656 ++iter) { |
1621 if (!*iter) | 1657 if (!*iter) |
1622 continue; | 1658 continue; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1713 | 1749 |
1714 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1750 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
1715 DCHECK(task_runner_->BelongsToCurrentThread()); | 1751 DCHECK(task_runner_->BelongsToCurrentThread()); |
1716 for (auto* stream : streams_) { | 1752 for (auto* stream : streams_) { |
1717 if (stream) | 1753 if (stream) |
1718 stream->SetLiveness(liveness); | 1754 stream->SetLiveness(liveness); |
1719 } | 1755 } |
1720 } | 1756 } |
1721 | 1757 |
1722 } // namespace media | 1758 } // namespace media |
OLD | NEW |