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

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

Issue 2710133003: Replace FFmpegDemuxer thread per element with base::TaskScheduler. (Closed)
Patch Set: Comments. Fix flaky test. Created 3 years, 10 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
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 <set> 9 #include <set>
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/base64.h" 12 #include "base/base64.h"
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/callback_helpers.h" 14 #include "base/callback_helpers.h"
15 #include "base/macros.h" 15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
17 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.h"
18 #include "base/metrics/sparse_histogram.h" 18 #include "base/metrics/sparse_histogram.h"
19 #include "base/single_thread_task_runner.h" 19 #include "base/single_thread_task_runner.h"
20 #include "base/strings/string_number_conversions.h" 20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_util.h" 21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h" 22 #include "base/strings/stringprintf.h"
23 #include "base/sys_byteorder.h" 23 #include "base/sys_byteorder.h"
24 #include "base/task_runner_util.h" 24 #include "base/task_runner_util.h"
25 #include "base/task_scheduler/post_task.h"
26 #include "base/threading/sequenced_worker_pool.h"
25 #include "base/threading/thread_task_runner_handle.h" 27 #include "base/threading/thread_task_runner_handle.h"
26 #include "base/time/time.h" 28 #include "base/time/time.h"
27 #include "media/audio/sample_rates.h" 29 #include "media/audio/sample_rates.h"
28 #include "media/base/bind_to_current_loop.h" 30 #include "media/base/bind_to_current_loop.h"
29 #include "media/base/decrypt_config.h" 31 #include "media/base/decrypt_config.h"
30 #include "media/base/limits.h" 32 #include "media/base/limits.h"
31 #include "media/base/media_log.h" 33 #include "media/base/media_log.h"
32 #include "media/base/media_tracks.h" 34 #include "media/base/media_tracks.h"
33 #include "media/base/timestamp_constants.h" 35 #include "media/base/timestamp_constants.h"
34 #include "media/base/video_codecs.h" 36 #include "media/base/video_codecs.h"
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 // FFmpegDemuxer 840 // FFmpegDemuxer
839 // 841 //
840 FFmpegDemuxer::FFmpegDemuxer( 842 FFmpegDemuxer::FFmpegDemuxer(
841 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 843 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
842 DataSource* data_source, 844 DataSource* data_source,
843 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, 845 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
844 const MediaTracksUpdatedCB& media_tracks_updated_cb, 846 const MediaTracksUpdatedCB& media_tracks_updated_cb,
845 const scoped_refptr<MediaLog>& media_log) 847 const scoped_refptr<MediaLog>& media_log)
846 : host_(NULL), 848 : host_(NULL),
847 task_runner_(task_runner), 849 task_runner_(task_runner),
848 blocking_thread_("FFmpegDemuxer"), 850 // FFmpeg has no asynchronous API, so we use base::WaitableEvents inside
851 // the BlockingUrlProtocol to handle hops to the render thread for network
852 // reads and seeks.
853 blocking_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
854 base::TaskTraits().MayBlock().WithBaseSyncPrimitives().WithPriority(
855 base::TaskPriority::USER_VISIBLE))),
xhwang 2017/02/23 23:45:42 this is cool :)
856 stopped_(false),
849 pending_read_(false), 857 pending_read_(false),
850 data_source_(data_source), 858 data_source_(data_source),
851 media_log_(media_log), 859 media_log_(media_log),
852 bitrate_(0), 860 bitrate_(0),
853 start_time_(kNoTimestamp), 861 start_time_(kNoTimestamp),
854 text_enabled_(false), 862 text_enabled_(false),
855 duration_known_(false), 863 duration_known_(false),
856 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), 864 encrypted_media_init_data_cb_(encrypted_media_init_data_cb),
857 media_tracks_updated_cb_(media_tracks_updated_cb), 865 media_tracks_updated_cb_(media_tracks_updated_cb),
858 cancel_pending_seek_factory_(this), 866 cancel_pending_seek_factory_(this),
859 weak_factory_(this) { 867 weak_factory_(this) {
860 DCHECK(task_runner_.get()); 868 DCHECK(task_runner_.get());
861 DCHECK(data_source_); 869 DCHECK(data_source_);
862 DCHECK(!media_tracks_updated_cb_.is_null()); 870 DCHECK(!media_tracks_updated_cb_.is_null());
863 } 871 }
864 872
865 FFmpegDemuxer::~FFmpegDemuxer() { 873 FFmpegDemuxer::~FFmpegDemuxer() {
866 // NOTE: This class is not destroyed on |task_runner|, so we must ensure that 874 // NOTE: This class is not destroyed on |task_runner|, so we must ensure that
867 // there are no outstanding WeakPtrs by the time we reach here. 875 // there are no outstanding WeakPtrs by the time we reach here.
868 DCHECK(!weak_factory_.HasWeakPtrs()); 876 DCHECK(!weak_factory_.HasWeakPtrs());
877
878 // There may be outstanding tasks in the blocking pool which are trying to use
879 // these members, so release them in sequence with any outstanding calls. The
880 // earlier call to Abort() on |data_source_| prevents further access to it.
881 blocking_task_runner_->DeleteSoon(FROM_HERE, url_protocol_.release());
882 blocking_task_runner_->DeleteSoon(FROM_HERE, glue_.release());
869 } 883 }
870 884
871 std::string FFmpegDemuxer::GetDisplayName() const { 885 std::string FFmpegDemuxer::GetDisplayName() const {
872 return "FFmpegDemuxer"; 886 return "FFmpegDemuxer";
873 } 887 }
874 888
875 void FFmpegDemuxer::Initialize(DemuxerHost* host, 889 void FFmpegDemuxer::Initialize(DemuxerHost* host,
876 const PipelineStatusCB& status_cb, 890 const PipelineStatusCB& status_cb,
877 bool enable_text_tracks) { 891 bool enable_text_tracks) {
878 DCHECK(task_runner_->BelongsToCurrentThread()); 892 DCHECK(task_runner_->BelongsToCurrentThread());
(...skipping 13 matching lines...) Expand all
892 // available, so add a metadata entry to ensure some is always present. 906 // available, so add a metadata entry to ensure some is always present.
893 av_dict_set(&format_context->metadata, "skip_id3v1_tags", "", 0); 907 av_dict_set(&format_context->metadata, "skip_id3v1_tags", "", 0);
894 908
895 // Ensure ffmpeg doesn't give up too early while looking for stream params; 909 // Ensure ffmpeg doesn't give up too early while looking for stream params;
896 // this does not increase the amount of data downloaded. The default value 910 // this does not increase the amount of data downloaded. The default value
897 // is 5 AV_TIME_BASE units (1 second each), which prevents some oddly muxed 911 // is 5 AV_TIME_BASE units (1 second each), which prevents some oddly muxed
898 // streams from being detected properly; this value was chosen arbitrarily. 912 // streams from being detected properly; this value was chosen arbitrarily.
899 format_context->max_analyze_duration = 60 * AV_TIME_BASE; 913 format_context->max_analyze_duration = 60 * AV_TIME_BASE;
900 914
901 // Open the AVFormatContext using our glue layer. 915 // Open the AVFormatContext using our glue layer.
902 CHECK(blocking_thread_.Start());
903 base::PostTaskAndReplyWithResult( 916 base::PostTaskAndReplyWithResult(
904 blocking_thread_.task_runner().get(), FROM_HERE, 917 blocking_task_runner_.get(), FROM_HERE,
905 base::Bind(&FFmpegGlue::OpenContext, base::Unretained(glue_.get())), 918 base::Bind(&FFmpegGlue::OpenContext, base::Unretained(glue_.get())),
906 base::Bind(&FFmpegDemuxer::OnOpenContextDone, weak_factory_.GetWeakPtr(), 919 base::Bind(&FFmpegDemuxer::OnOpenContextDone, weak_factory_.GetWeakPtr(),
907 status_cb)); 920 status_cb));
908 } 921 }
909 922
910 void FFmpegDemuxer::AbortPendingReads() { 923 void FFmpegDemuxer::AbortPendingReads() {
911 DCHECK(task_runner_->BelongsToCurrentThread()); 924 DCHECK(task_runner_->BelongsToCurrentThread());
912 925
913 // If Stop() has been called, then drop this call. 926 // If Stop() has been called, then drop this call.
914 if (!blocking_thread_.IsRunning()) 927 if (stopped_)
915 return; 928 return;
916 929
917 // This should only be called after the demuxer has been initialized. 930 // This should only be called after the demuxer has been initialized.
918 DCHECK_GT(streams_.size(), 0u); 931 DCHECK_GT(streams_.size(), 0u);
919 932
920 // Abort all outstanding reads. 933 // Abort all outstanding reads.
921 for (const auto& stream : streams_) { 934 for (const auto& stream : streams_) {
922 if (stream) 935 if (stream)
923 stream->Abort(); 936 stream->Abort();
924 } 937 }
925 938
926 // It's important to invalidate read/seek completion callbacks to avoid any 939 // It's important to invalidate read/seek completion callbacks to avoid any
927 // errors that occur because of the data source abort. 940 // errors that occur because of the data source abort.
928 weak_factory_.InvalidateWeakPtrs(); 941 weak_factory_.InvalidateWeakPtrs();
929 data_source_->Abort(); 942 data_source_->Abort();
930 943
931 // Aborting the read may cause EOF to be marked, undo this. 944 // Aborting the read may cause EOF to be marked, undo this.
932 blocking_thread_.task_runner()->PostTask( 945 blocking_task_runner_->PostTask(
933 FROM_HERE, base::Bind(&UnmarkEndOfStream, glue_->format_context())); 946 FROM_HERE, base::Bind(&UnmarkEndOfStream, glue_->format_context()));
934 pending_read_ = false; 947 pending_read_ = false;
935 948
936 // TODO(dalecurtis): We probably should report PIPELINE_ERROR_ABORT here 949 // TODO(dalecurtis): We probably should report PIPELINE_ERROR_ABORT here
937 // instead to avoid any preroll work that may be started upon return, but 950 // instead to avoid any preroll work that may be started upon return, but
938 // currently the PipelineImpl does not know how to handle this. 951 // currently the PipelineImpl does not know how to handle this.
939 if (!pending_seek_cb_.is_null()) 952 if (!pending_seek_cb_.is_null())
940 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK); 953 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK);
941 } 954 }
942 955
943 void FFmpegDemuxer::Stop() { 956 void FFmpegDemuxer::Stop() {
944 DCHECK(task_runner_->BelongsToCurrentThread()); 957 DCHECK(task_runner_->BelongsToCurrentThread());
945 958
946 // The order of Stop() and Abort() is important here. If Abort() is called 959 // The order of Stop() and Abort() is important here. If Abort() is called
947 // first, control may pass into FFmpeg where it can destruct buffers that are 960 // first, control may pass into FFmpeg where it can destruct buffers that are
948 // in the process of being fulfilled by the DataSource. 961 // in the process of being fulfilled by the DataSource.
949 data_source_->Stop(); 962 data_source_->Stop();
950 url_protocol_->Abort(); 963 url_protocol_->Abort();
951 964
952 // This will block until all tasks complete. Note that after this returns it's
953 // possible for reply tasks (e.g., OnReadFrameDone()) to be queued on this
954 // thread. Each of the reply task methods must check whether we've stopped the
955 // thread and drop their results on the floor.
956 blocking_thread_.Stop();
957
958 for (const auto& stream : streams_) { 965 for (const auto& stream : streams_) {
959 if (stream) 966 if (stream)
960 stream->Stop(); 967 stream->Stop();
961 } 968 }
962 969
963 data_source_ = NULL; 970 data_source_ = NULL;
964 971
965 // Invalidate WeakPtrs on |task_runner_|, destruction may happen on another 972 // Invalidate WeakPtrs on |task_runner_|, destruction may happen on another
966 // thread. 973 // thread. We don't need to wait for any outstanding tasks since they will all
974 // fail to return after invalidating WeakPtrs.
975 stopped_ = true;
967 weak_factory_.InvalidateWeakPtrs(); 976 weak_factory_.InvalidateWeakPtrs();
968 cancel_pending_seek_factory_.InvalidateWeakPtrs(); 977 cancel_pending_seek_factory_.InvalidateWeakPtrs();
969 } 978 }
970 979
971 void FFmpegDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) {} 980 void FFmpegDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) {}
972 981
973 void FFmpegDemuxer::CancelPendingSeek(base::TimeDelta seek_time) { 982 void FFmpegDemuxer::CancelPendingSeek(base::TimeDelta seek_time) {
974 if (task_runner_->BelongsToCurrentThread()) { 983 if (task_runner_->BelongsToCurrentThread()) {
975 AbortPendingReads(); 984 AbortPendingReads();
976 } else { 985 } else {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 // be demuxed. It's an open question whether FFmpeg should fix this: 1024 // be demuxed. It's an open question whether FFmpeg should fix this:
1016 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html 1025 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html
1017 // Tracked by http://crbug.com/387996. 1026 // Tracked by http://crbug.com/387996.
1018 FFmpegDemuxerStream* demux_stream = FindPreferredStreamForSeeking(seek_time); 1027 FFmpegDemuxerStream* demux_stream = FindPreferredStreamForSeeking(seek_time);
1019 DCHECK(demux_stream); 1028 DCHECK(demux_stream);
1020 const AVStream* seeking_stream = demux_stream->av_stream(); 1029 const AVStream* seeking_stream = demux_stream->av_stream();
1021 DCHECK(seeking_stream); 1030 DCHECK(seeking_stream);
1022 1031
1023 pending_seek_cb_ = cb; 1032 pending_seek_cb_ = cb;
1024 base::PostTaskAndReplyWithResult( 1033 base::PostTaskAndReplyWithResult(
1025 blocking_thread_.task_runner().get(), FROM_HERE, 1034 blocking_task_runner_.get(), FROM_HERE,
1026 base::Bind(&av_seek_frame, glue_->format_context(), seeking_stream->index, 1035 base::Bind(&av_seek_frame, glue_->format_context(), seeking_stream->index,
1027 ConvertToTimeBase(seeking_stream->time_base, seek_time), 1036 ConvertToTimeBase(seeking_stream->time_base, seek_time),
1028 // Always seek to a timestamp <= to the desired timestamp. 1037 // Always seek to a timestamp <= to the desired timestamp.
1029 AVSEEK_FLAG_BACKWARD), 1038 AVSEEK_FLAG_BACKWARD),
1030 base::Bind(&FFmpegDemuxer::OnSeekFrameDone, weak_factory_.GetWeakPtr())); 1039 base::Bind(&FFmpegDemuxer::OnSeekFrameDone, weak_factory_.GetWeakPtr()));
1031 } 1040 }
1032 1041
1033 base::Time FFmpegDemuxer::GetTimelineOffset() const { 1042 base::Time FFmpegDemuxer::GetTimelineOffset() const {
1034 return timeline_offset_; 1043 return timeline_offset_;
1035 } 1044 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 // Do math in floating point as we'd overflow an int64_t if the filesize was 1161 // Do math in floating point as we'd overflow an int64_t if the filesize was
1153 // larger than ~1073GB. 1162 // larger than ~1073GB.
1154 double bytes = filesize_in_bytes; 1163 double bytes = filesize_in_bytes;
1155 double duration_us = duration.InMicroseconds(); 1164 double duration_us = duration.InMicroseconds();
1156 return bytes * 8000000.0 / duration_us; 1165 return bytes * 8000000.0 / duration_us;
1157 } 1166 }
1158 1167
1159 void FFmpegDemuxer::OnOpenContextDone(const PipelineStatusCB& status_cb, 1168 void FFmpegDemuxer::OnOpenContextDone(const PipelineStatusCB& status_cb,
1160 bool result) { 1169 bool result) {
1161 DCHECK(task_runner_->BelongsToCurrentThread()); 1170 DCHECK(task_runner_->BelongsToCurrentThread());
1162 if (!blocking_thread_.IsRunning()) { 1171 if (stopped_) {
1163 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1172 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1164 status_cb.Run(PIPELINE_ERROR_ABORT); 1173 status_cb.Run(PIPELINE_ERROR_ABORT);
1165 return; 1174 return;
1166 } 1175 }
1167 1176
1168 if (!result) { 1177 if (!result) {
1169 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": open context failed"; 1178 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": open context failed";
1170 status_cb.Run(DEMUXER_ERROR_COULD_NOT_OPEN); 1179 status_cb.Run(DEMUXER_ERROR_COULD_NOT_OPEN);
1171 return; 1180 return;
1172 } 1181 }
1173 1182
1174 // Fully initialize AVFormatContext by parsing the stream a little. 1183 // Fully initialize AVFormatContext by parsing the stream a little.
1175 base::PostTaskAndReplyWithResult( 1184 base::PostTaskAndReplyWithResult(
1176 blocking_thread_.task_runner().get(), 1185 blocking_task_runner_.get(), FROM_HERE,
1177 FROM_HERE, 1186 base::Bind(&avformat_find_stream_info, glue_->format_context(),
1178 base::Bind(&avformat_find_stream_info,
1179 glue_->format_context(),
1180 static_cast<AVDictionary**>(NULL)), 1187 static_cast<AVDictionary**>(NULL)),
1181 base::Bind(&FFmpegDemuxer::OnFindStreamInfoDone, 1188 base::Bind(&FFmpegDemuxer::OnFindStreamInfoDone,
1182 weak_factory_.GetWeakPtr(), 1189 weak_factory_.GetWeakPtr(), status_cb));
1183 status_cb));
1184 } 1190 }
1185 1191
1186 void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb, 1192 void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
1187 int result) { 1193 int result) {
1188 DCHECK(task_runner_->BelongsToCurrentThread()); 1194 DCHECK(task_runner_->BelongsToCurrentThread());
1189 if (!blocking_thread_.IsRunning() || !data_source_) { 1195 if (stopped_ || !data_source_) {
1190 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1196 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1191 status_cb.Run(PIPELINE_ERROR_ABORT); 1197 status_cb.Run(PIPELINE_ERROR_ABORT);
1192 return; 1198 return;
1193 } 1199 }
1194 1200
1195 if (result < 0) { 1201 if (result < 0) {
1196 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() 1202 MEDIA_LOG(ERROR, media_log_) << GetDisplayName()
1197 << ": find stream info failed"; 1203 << ": find stream info failed";
1198 status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE); 1204 status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE);
1199 return; 1205 return;
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
1599 } 1605 }
1600 1606
1601 NOTREACHED(); 1607 NOTREACHED();
1602 return nullptr; 1608 return nullptr;
1603 } 1609 }
1604 1610
1605 void FFmpegDemuxer::OnSeekFrameDone(int result) { 1611 void FFmpegDemuxer::OnSeekFrameDone(int result) {
1606 DCHECK(task_runner_->BelongsToCurrentThread()); 1612 DCHECK(task_runner_->BelongsToCurrentThread());
1607 CHECK(!pending_seek_cb_.is_null()); 1613 CHECK(!pending_seek_cb_.is_null());
1608 1614
1609 if (!blocking_thread_.IsRunning()) { 1615 if (stopped_) {
1610 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1616 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1611 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_ERROR_ABORT); 1617 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_ERROR_ABORT);
1612 return; 1618 return;
1613 } 1619 }
1614 1620
1615 if (result < 0) { 1621 if (result < 0) {
1616 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being 1622 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being
1617 // captured from stdout and contaminates testing. 1623 // captured from stdout and contaminates testing.
1618 // TODO(scherkus): Implement this properly and signal error (BUG=23447). 1624 // TODO(scherkus): Implement this properly and signal error (BUG=23447).
1619 VLOG(1) << "Not implemented"; 1625 VLOG(1) << "Not implemented";
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1686 if (selected_stream) { 1692 if (selected_stream) {
1687 DVLOG(1) << __func__ << ": enabling stream " << selected_stream; 1693 DVLOG(1) << __func__ << ": enabling stream " << selected_stream;
1688 selected_stream->set_enabled(true, currTime); 1694 selected_stream->set_enabled(true, currTime);
1689 } 1695 }
1690 } 1696 }
1691 1697
1692 void FFmpegDemuxer::ReadFrameIfNeeded() { 1698 void FFmpegDemuxer::ReadFrameIfNeeded() {
1693 DCHECK(task_runner_->BelongsToCurrentThread()); 1699 DCHECK(task_runner_->BelongsToCurrentThread());
1694 1700
1695 // Make sure we have work to do before reading. 1701 // Make sure we have work to do before reading.
1696 if (!blocking_thread_.IsRunning() || !StreamsHaveAvailableCapacity() || 1702 if (stopped_ || !StreamsHaveAvailableCapacity() || pending_read_ ||
1697 pending_read_ || !pending_seek_cb_.is_null()) { 1703 !pending_seek_cb_.is_null()) {
1698 return; 1704 return;
1699 } 1705 }
1700 1706
1701 // Allocate and read an AVPacket from the media. Save |packet_ptr| since 1707 // Allocate and read an AVPacket from the media. Save |packet_ptr| since
1702 // evaluation order of packet.get() and base::Passed(&packet) is 1708 // evaluation order of packet.get() and base::Passed(&packet) is
1703 // undefined. 1709 // undefined.
1704 ScopedAVPacket packet(new AVPacket()); 1710 ScopedAVPacket packet(new AVPacket());
1705 AVPacket* packet_ptr = packet.get(); 1711 AVPacket* packet_ptr = packet.get();
1706 1712
1707 pending_read_ = true; 1713 pending_read_ = true;
1708 base::PostTaskAndReplyWithResult( 1714 base::PostTaskAndReplyWithResult(
1709 blocking_thread_.task_runner().get(), 1715 blocking_task_runner_.get(), FROM_HERE,
1710 FROM_HERE,
1711 base::Bind(&av_read_frame, glue_->format_context(), packet_ptr), 1716 base::Bind(&av_read_frame, glue_->format_context(), packet_ptr),
1712 base::Bind(&FFmpegDemuxer::OnReadFrameDone, 1717 base::Bind(&FFmpegDemuxer::OnReadFrameDone, weak_factory_.GetWeakPtr(),
1713 weak_factory_.GetWeakPtr(),
1714 base::Passed(&packet))); 1718 base::Passed(&packet)));
1715 } 1719 }
1716 1720
1717 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { 1721 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) {
1718 DCHECK(task_runner_->BelongsToCurrentThread()); 1722 DCHECK(task_runner_->BelongsToCurrentThread());
1719 DCHECK(pending_read_); 1723 DCHECK(pending_read_);
1720 pending_read_ = false; 1724 pending_read_ = false;
1721 1725
1722 if (!blocking_thread_.IsRunning() || !pending_seek_cb_.is_null()) 1726 if (stopped_ || !pending_seek_cb_.is_null())
1723 return; 1727 return;
1724 1728
1725 // Consider the stream as ended if: 1729 // Consider the stream as ended if:
1726 // - either underlying ffmpeg returned an error 1730 // - either underlying ffmpeg returned an error
1727 // - or FFMpegDemuxer reached the maximum allowed memory usage. 1731 // - or FFMpegDemuxer reached the maximum allowed memory usage.
1728 if (result < 0 || IsMaxMemoryUsageReached()) { 1732 if (result < 0 || IsMaxMemoryUsageReached()) {
1729 DVLOG(1) << __func__ << " result=" << result 1733 DVLOG(1) << __func__ << " result=" << result
1730 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached(); 1734 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached();
1731 // Update the duration based on the highest elapsed time across all streams. 1735 // Update the duration based on the highest elapsed time across all streams.
1732 base::TimeDelta max_duration; 1736 base::TimeDelta max_duration;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1837 1841
1838 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { 1842 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) {
1839 DCHECK(task_runner_->BelongsToCurrentThread()); 1843 DCHECK(task_runner_->BelongsToCurrentThread());
1840 for (const auto& stream : streams_) { 1844 for (const auto& stream : streams_) {
1841 if (stream) 1845 if (stream)
1842 stream->SetLiveness(liveness); 1846 stream->SetLiveness(liveness);
1843 } 1847 }
1844 } 1848 }
1845 1849
1846 } // namespace media 1850 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698