Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(789)

Side by Side Diff: media/filters/ffmpeg_demuxer.cc

Issue 2267963002: Add support for cancellation of demuxer reads. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix and add tests. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698