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

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

Issue 2710133003: Replace FFmpegDemuxer thread per element with base::TaskScheduler. (Closed)
Patch Set: Give WeakPtr to URLProtocol. Created 3 years, 9 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 <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_BLOCKING))),
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());
879 host_ = host; 893 host_ = host;
880 text_enabled_ = enable_text_tracks; 894 text_enabled_ = enable_text_tracks;
881 weak_this_ = cancel_pending_seek_factory_.GetWeakPtr(); 895 weak_this_ = cancel_pending_seek_factory_.GetWeakPtr();
882 896
897 // Give a WeakPtr to BlockingUrlProtocol since we'll need to release it on the
898 // blocking thread pool.
883 url_protocol_.reset(new BlockingUrlProtocol( 899 url_protocol_.reset(new BlockingUrlProtocol(
884 data_source_, 900 data_source_, BindToCurrentLoop(base::Bind(
885 BindToCurrentLoop(base::Bind(&FFmpegDemuxer::OnDataSourceError, 901 &FFmpegDemuxer::OnDataSourceError, weak_this_))));
xhwang 2017/03/02 22:05:01 We have mixed use of weak_this_ and weak_factory_.
DaleCurtis 2017/03/02 22:48:53 weak_this_ is bound to a factory which should only
xhwang 2017/03/02 23:07:13 Ah, that's tricky and I didn't even notice it. A f
886 base::Unretained(this)))));
887 glue_.reset(new FFmpegGlue(url_protocol_.get())); 902 glue_.reset(new FFmpegGlue(url_protocol_.get()));
888 AVFormatContext* format_context = glue_->format_context(); 903 AVFormatContext* format_context = glue_->format_context();
889 904
890 // Disable ID3v1 tag reading to avoid costly seeks to end of file for data we 905 // Disable ID3v1 tag reading to avoid costly seeks to end of file for data we
891 // don't use. FFmpeg will only read ID3v1 tags if no other metadata is 906 // don't use. FFmpeg will only read ID3v1 tags if no other metadata is
892 // available, so add a metadata entry to ensure some is always present. 907 // available, so add a metadata entry to ensure some is always present.
893 av_dict_set(&format_context->metadata, "skip_id3v1_tags", "", 0); 908 av_dict_set(&format_context->metadata, "skip_id3v1_tags", "", 0);
894 909
895 // Ensure ffmpeg doesn't give up too early while looking for stream params; 910 // 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 911 // 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 912 // 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. 913 // streams from being detected properly; this value was chosen arbitrarily.
899 format_context->max_analyze_duration = 60 * AV_TIME_BASE; 914 format_context->max_analyze_duration = 60 * AV_TIME_BASE;
900 915
901 // Open the AVFormatContext using our glue layer. 916 // Open the AVFormatContext using our glue layer.
902 CHECK(blocking_thread_.Start());
903 base::PostTaskAndReplyWithResult( 917 base::PostTaskAndReplyWithResult(
904 blocking_thread_.task_runner().get(), FROM_HERE, 918 blocking_task_runner_.get(), FROM_HERE,
905 base::Bind(&FFmpegGlue::OpenContext, base::Unretained(glue_.get())), 919 base::Bind(&FFmpegGlue::OpenContext, base::Unretained(glue_.get())),
906 base::Bind(&FFmpegDemuxer::OnOpenContextDone, weak_factory_.GetWeakPtr(), 920 base::Bind(&FFmpegDemuxer::OnOpenContextDone, weak_factory_.GetWeakPtr(),
907 status_cb)); 921 status_cb));
908 } 922 }
909 923
910 void FFmpegDemuxer::AbortPendingReads() { 924 void FFmpegDemuxer::AbortPendingReads() {
911 DCHECK(task_runner_->BelongsToCurrentThread()); 925 DCHECK(task_runner_->BelongsToCurrentThread());
912 926
913 // If Stop() has been called, then drop this call. 927 // If Stop() has been called, then drop this call.
914 if (!blocking_thread_.IsRunning()) 928 if (stopped_)
915 return; 929 return;
916 930
917 // This should only be called after the demuxer has been initialized. 931 // This should only be called after the demuxer has been initialized.
918 DCHECK_GT(streams_.size(), 0u); 932 DCHECK_GT(streams_.size(), 0u);
919 933
920 // Abort all outstanding reads. 934 // Abort all outstanding reads.
921 for (const auto& stream : streams_) { 935 for (const auto& stream : streams_) {
922 if (stream) 936 if (stream)
923 stream->Abort(); 937 stream->Abort();
924 } 938 }
925 939
926 // It's important to invalidate read/seek completion callbacks to avoid any 940 // It's important to invalidate read/seek completion callbacks to avoid any
927 // errors that occur because of the data source abort. 941 // errors that occur because of the data source abort.
928 weak_factory_.InvalidateWeakPtrs(); 942 weak_factory_.InvalidateWeakPtrs();
929 data_source_->Abort(); 943 data_source_->Abort();
930 944
931 // Aborting the read may cause EOF to be marked, undo this. 945 // Aborting the read may cause EOF to be marked, undo this.
932 blocking_thread_.task_runner()->PostTask( 946 blocking_task_runner_->PostTask(
933 FROM_HERE, base::Bind(&UnmarkEndOfStream, glue_->format_context())); 947 FROM_HERE, base::Bind(&UnmarkEndOfStream, glue_->format_context()));
934 pending_read_ = false; 948 pending_read_ = false;
935 949
936 // TODO(dalecurtis): We probably should report PIPELINE_ERROR_ABORT here 950 // TODO(dalecurtis): We probably should report PIPELINE_ERROR_ABORT here
937 // instead to avoid any preroll work that may be started upon return, but 951 // instead to avoid any preroll work that may be started upon return, but
938 // currently the PipelineImpl does not know how to handle this. 952 // currently the PipelineImpl does not know how to handle this.
939 if (!pending_seek_cb_.is_null()) 953 if (!pending_seek_cb_.is_null())
940 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK); 954 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK);
941 } 955 }
942 956
943 void FFmpegDemuxer::Stop() { 957 void FFmpegDemuxer::Stop() {
944 DCHECK(task_runner_->BelongsToCurrentThread()); 958 DCHECK(task_runner_->BelongsToCurrentThread());
945 959
946 // The order of Stop() and Abort() is important here. If Abort() is called 960 // 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 961 // first, control may pass into FFmpeg where it can destruct buffers that are
948 // in the process of being fulfilled by the DataSource. 962 // in the process of being fulfilled by the DataSource.
949 data_source_->Stop(); 963 data_source_->Stop();
950 url_protocol_->Abort(); 964 url_protocol_->Abort();
951 965
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_) { 966 for (const auto& stream : streams_) {
959 if (stream) 967 if (stream)
960 stream->Stop(); 968 stream->Stop();
961 } 969 }
962 970
963 data_source_ = NULL; 971 data_source_ = NULL;
964 972
965 // Invalidate WeakPtrs on |task_runner_|, destruction may happen on another 973 // Invalidate WeakPtrs on |task_runner_|, destruction may happen on another
966 // thread. 974 // thread. We don't need to wait for any outstanding tasks since they will all
975 // fail to return after invalidating WeakPtrs.
976 stopped_ = true;
967 weak_factory_.InvalidateWeakPtrs(); 977 weak_factory_.InvalidateWeakPtrs();
968 cancel_pending_seek_factory_.InvalidateWeakPtrs(); 978 cancel_pending_seek_factory_.InvalidateWeakPtrs();
969 } 979 }
970 980
971 void FFmpegDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) {} 981 void FFmpegDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) {}
972 982
973 void FFmpegDemuxer::CancelPendingSeek(base::TimeDelta seek_time) { 983 void FFmpegDemuxer::CancelPendingSeek(base::TimeDelta seek_time) {
974 if (task_runner_->BelongsToCurrentThread()) { 984 if (task_runner_->BelongsToCurrentThread()) {
975 AbortPendingReads(); 985 AbortPendingReads();
976 } else { 986 } 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: 1025 // be demuxed. It's an open question whether FFmpeg should fix this:
1016 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html 1026 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html
1017 // Tracked by http://crbug.com/387996. 1027 // Tracked by http://crbug.com/387996.
1018 FFmpegDemuxerStream* demux_stream = FindPreferredStreamForSeeking(seek_time); 1028 FFmpegDemuxerStream* demux_stream = FindPreferredStreamForSeeking(seek_time);
1019 DCHECK(demux_stream); 1029 DCHECK(demux_stream);
1020 const AVStream* seeking_stream = demux_stream->av_stream(); 1030 const AVStream* seeking_stream = demux_stream->av_stream();
1021 DCHECK(seeking_stream); 1031 DCHECK(seeking_stream);
1022 1032
1023 pending_seek_cb_ = cb; 1033 pending_seek_cb_ = cb;
1024 base::PostTaskAndReplyWithResult( 1034 base::PostTaskAndReplyWithResult(
1025 blocking_thread_.task_runner().get(), FROM_HERE, 1035 blocking_task_runner_.get(), FROM_HERE,
1026 base::Bind(&av_seek_frame, glue_->format_context(), seeking_stream->index, 1036 base::Bind(&av_seek_frame, glue_->format_context(), seeking_stream->index,
1027 ConvertToTimeBase(seeking_stream->time_base, seek_time), 1037 ConvertToTimeBase(seeking_stream->time_base, seek_time),
1028 // Always seek to a timestamp <= to the desired timestamp. 1038 // Always seek to a timestamp <= to the desired timestamp.
1029 AVSEEK_FLAG_BACKWARD), 1039 AVSEEK_FLAG_BACKWARD),
1030 base::Bind(&FFmpegDemuxer::OnSeekFrameDone, weak_factory_.GetWeakPtr())); 1040 base::Bind(&FFmpegDemuxer::OnSeekFrameDone, weak_factory_.GetWeakPtr()));
1031 } 1041 }
1032 1042
1033 base::Time FFmpegDemuxer::GetTimelineOffset() const { 1043 base::Time FFmpegDemuxer::GetTimelineOffset() const {
1034 return timeline_offset_; 1044 return timeline_offset_;
1035 } 1045 }
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 // Do math in floating point as we'd overflow an int64_t if the filesize was 1170 // Do math in floating point as we'd overflow an int64_t if the filesize was
1161 // larger than ~1073GB. 1171 // larger than ~1073GB.
1162 double bytes = filesize_in_bytes; 1172 double bytes = filesize_in_bytes;
1163 double duration_us = duration.InMicroseconds(); 1173 double duration_us = duration.InMicroseconds();
1164 return bytes * 8000000.0 / duration_us; 1174 return bytes * 8000000.0 / duration_us;
1165 } 1175 }
1166 1176
1167 void FFmpegDemuxer::OnOpenContextDone(const PipelineStatusCB& status_cb, 1177 void FFmpegDemuxer::OnOpenContextDone(const PipelineStatusCB& status_cb,
1168 bool result) { 1178 bool result) {
1169 DCHECK(task_runner_->BelongsToCurrentThread()); 1179 DCHECK(task_runner_->BelongsToCurrentThread());
1170 if (!blocking_thread_.IsRunning()) { 1180 if (stopped_) {
1171 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1181 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1172 status_cb.Run(PIPELINE_ERROR_ABORT); 1182 status_cb.Run(PIPELINE_ERROR_ABORT);
1173 return; 1183 return;
1174 } 1184 }
1175 1185
1176 if (!result) { 1186 if (!result) {
1177 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": open context failed"; 1187 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": open context failed";
1178 status_cb.Run(DEMUXER_ERROR_COULD_NOT_OPEN); 1188 status_cb.Run(DEMUXER_ERROR_COULD_NOT_OPEN);
1179 return; 1189 return;
1180 } 1190 }
1181 1191
1182 // Fully initialize AVFormatContext by parsing the stream a little. 1192 // Fully initialize AVFormatContext by parsing the stream a little.
1183 base::PostTaskAndReplyWithResult( 1193 base::PostTaskAndReplyWithResult(
1184 blocking_thread_.task_runner().get(), 1194 blocking_task_runner_.get(), FROM_HERE,
1185 FROM_HERE, 1195 base::Bind(&avformat_find_stream_info, glue_->format_context(),
1186 base::Bind(&avformat_find_stream_info,
1187 glue_->format_context(),
1188 static_cast<AVDictionary**>(NULL)), 1196 static_cast<AVDictionary**>(NULL)),
1189 base::Bind(&FFmpegDemuxer::OnFindStreamInfoDone, 1197 base::Bind(&FFmpegDemuxer::OnFindStreamInfoDone,
1190 weak_factory_.GetWeakPtr(), 1198 weak_factory_.GetWeakPtr(), status_cb));
1191 status_cb));
1192 } 1199 }
1193 1200
1194 void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb, 1201 void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
1195 int result) { 1202 int result) {
1196 DCHECK(task_runner_->BelongsToCurrentThread()); 1203 DCHECK(task_runner_->BelongsToCurrentThread());
1197 if (!blocking_thread_.IsRunning() || !data_source_) { 1204 if (stopped_ || !data_source_) {
1198 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1205 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1199 status_cb.Run(PIPELINE_ERROR_ABORT); 1206 status_cb.Run(PIPELINE_ERROR_ABORT);
1200 return; 1207 return;
1201 } 1208 }
1202 1209
1203 if (result < 0) { 1210 if (result < 0) {
1204 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() 1211 MEDIA_LOG(ERROR, media_log_) << GetDisplayName()
1205 << ": find stream info failed"; 1212 << ": find stream info failed";
1206 status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE); 1213 status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE);
1207 return; 1214 return;
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
1607 } 1614 }
1608 1615
1609 NOTREACHED(); 1616 NOTREACHED();
1610 return nullptr; 1617 return nullptr;
1611 } 1618 }
1612 1619
1613 void FFmpegDemuxer::OnSeekFrameDone(int result) { 1620 void FFmpegDemuxer::OnSeekFrameDone(int result) {
1614 DCHECK(task_runner_->BelongsToCurrentThread()); 1621 DCHECK(task_runner_->BelongsToCurrentThread());
1615 CHECK(!pending_seek_cb_.is_null()); 1622 CHECK(!pending_seek_cb_.is_null());
1616 1623
1617 if (!blocking_thread_.IsRunning()) { 1624 if (stopped_) {
1618 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1625 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1619 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_ERROR_ABORT); 1626 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_ERROR_ABORT);
1620 return; 1627 return;
1621 } 1628 }
1622 1629
1623 if (result < 0) { 1630 if (result < 0) {
1624 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being 1631 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being
1625 // captured from stdout and contaminates testing. 1632 // captured from stdout and contaminates testing.
1626 // TODO(scherkus): Implement this properly and signal error (BUG=23447). 1633 // TODO(scherkus): Implement this properly and signal error (BUG=23447).
1627 VLOG(1) << "Not implemented"; 1634 VLOG(1) << "Not implemented";
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1693 if (selected_stream) { 1700 if (selected_stream) {
1694 DVLOG(1) << __func__ << ": enabling stream " << selected_stream; 1701 DVLOG(1) << __func__ << ": enabling stream " << selected_stream;
1695 selected_stream->set_enabled(true, curr_time); 1702 selected_stream->set_enabled(true, curr_time);
1696 } 1703 }
1697 } 1704 }
1698 1705
1699 void FFmpegDemuxer::ReadFrameIfNeeded() { 1706 void FFmpegDemuxer::ReadFrameIfNeeded() {
1700 DCHECK(task_runner_->BelongsToCurrentThread()); 1707 DCHECK(task_runner_->BelongsToCurrentThread());
1701 1708
1702 // Make sure we have work to do before reading. 1709 // Make sure we have work to do before reading.
1703 if (!blocking_thread_.IsRunning() || !StreamsHaveAvailableCapacity() || 1710 if (stopped_ || !StreamsHaveAvailableCapacity() || pending_read_ ||
1704 pending_read_ || !pending_seek_cb_.is_null()) { 1711 !pending_seek_cb_.is_null()) {
1705 return; 1712 return;
1706 } 1713 }
1707 1714
1708 // Allocate and read an AVPacket from the media. Save |packet_ptr| since 1715 // Allocate and read an AVPacket from the media. Save |packet_ptr| since
1709 // evaluation order of packet.get() and base::Passed(&packet) is 1716 // evaluation order of packet.get() and base::Passed(&packet) is
1710 // undefined. 1717 // undefined.
1711 ScopedAVPacket packet(new AVPacket()); 1718 ScopedAVPacket packet(new AVPacket());
1712 AVPacket* packet_ptr = packet.get(); 1719 AVPacket* packet_ptr = packet.get();
1713 1720
1714 pending_read_ = true; 1721 pending_read_ = true;
1715 base::PostTaskAndReplyWithResult( 1722 base::PostTaskAndReplyWithResult(
1716 blocking_thread_.task_runner().get(), 1723 blocking_task_runner_.get(), FROM_HERE,
1717 FROM_HERE,
1718 base::Bind(&av_read_frame, glue_->format_context(), packet_ptr), 1724 base::Bind(&av_read_frame, glue_->format_context(), packet_ptr),
1719 base::Bind(&FFmpegDemuxer::OnReadFrameDone, 1725 base::Bind(&FFmpegDemuxer::OnReadFrameDone, weak_factory_.GetWeakPtr(),
1720 weak_factory_.GetWeakPtr(),
1721 base::Passed(&packet))); 1726 base::Passed(&packet)));
1722 } 1727 }
1723 1728
1724 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { 1729 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) {
1725 DCHECK(task_runner_->BelongsToCurrentThread()); 1730 DCHECK(task_runner_->BelongsToCurrentThread());
1726 DCHECK(pending_read_); 1731 DCHECK(pending_read_);
1727 pending_read_ = false; 1732 pending_read_ = false;
1728 1733
1729 if (!blocking_thread_.IsRunning() || !pending_seek_cb_.is_null()) 1734 if (stopped_ || !pending_seek_cb_.is_null())
1730 return; 1735 return;
1731 1736
1732 // Consider the stream as ended if: 1737 // Consider the stream as ended if:
1733 // - either underlying ffmpeg returned an error 1738 // - either underlying ffmpeg returned an error
1734 // - or FFMpegDemuxer reached the maximum allowed memory usage. 1739 // - or FFMpegDemuxer reached the maximum allowed memory usage.
1735 if (result < 0 || IsMaxMemoryUsageReached()) { 1740 if (result < 0 || IsMaxMemoryUsageReached()) {
1736 DVLOG(1) << __func__ << " result=" << result 1741 DVLOG(1) << __func__ << " result=" << result
1737 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached(); 1742 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached();
1738 // Update the duration based on the highest elapsed time across all streams. 1743 // Update the duration based on the highest elapsed time across all streams.
1739 base::TimeDelta max_duration; 1744 base::TimeDelta max_duration;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1844 1849
1845 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { 1850 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) {
1846 DCHECK(task_runner_->BelongsToCurrentThread()); 1851 DCHECK(task_runner_->BelongsToCurrentThread());
1847 for (const auto& stream : streams_) { 1852 for (const auto& stream : streams_) {
1848 if (stream) 1853 if (stream)
1849 stream->SetLiveness(liveness); 1854 stream->SetLiveness(liveness);
1850 } 1855 }
1851 } 1856 }
1852 1857
1853 } // namespace media 1858 } // 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