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