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

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

Issue 2710133003: Replace FFmpegDemuxer thread per element with base::TaskScheduler. (Closed)
Patch Set: 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/threading/sequenced_worker_pool.h"
25 #include "base/threading/thread_task_runner_handle.h" 26 #include "base/threading/thread_task_runner_handle.h"
26 #include "base/time/time.h" 27 #include "base/time/time.h"
27 #include "media/audio/sample_rates.h" 28 #include "media/audio/sample_rates.h"
28 #include "media/base/bind_to_current_loop.h" 29 #include "media/base/bind_to_current_loop.h"
29 #include "media/base/decrypt_config.h" 30 #include "media/base/decrypt_config.h"
30 #include "media/base/limits.h" 31 #include "media/base/limits.h"
31 #include "media/base/media_log.h" 32 #include "media/base/media_log.h"
32 #include "media/base/media_tracks.h" 33 #include "media/base/media_tracks.h"
33 #include "media/base/timestamp_constants.h" 34 #include "media/base/timestamp_constants.h"
34 #include "media/base/video_codecs.h" 35 #include "media/base/video_codecs.h"
35 #include "media/ffmpeg/ffmpeg_common.h" 36 #include "media/ffmpeg/ffmpeg_common.h"
36 #include "media/filters/ffmpeg_aac_bitstream_converter.h" 37 #include "media/filters/ffmpeg_aac_bitstream_converter.h"
37 #include "media/filters/ffmpeg_bitstream_converter.h" 38 #include "media/filters/ffmpeg_bitstream_converter.h"
38 #include "media/filters/ffmpeg_glue.h" 39 #include "media/filters/ffmpeg_glue.h"
39 #include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h" 40 #include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h"
40 #include "media/filters/webvtt_util.h" 41 #include "media/filters/webvtt_util.h"
41 #include "media/formats/webm/webm_crypto_helpers.h" 42 #include "media/formats/webm/webm_crypto_helpers.h"
42 #include "media/media_features.h" 43 #include "media/media_features.h"
43 44
44 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) 45 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
45 #include "media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.h" 46 #include "media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.h"
46 #endif 47 #endif
47 48
48 namespace media { 49 namespace media {
49 50
51 static scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner() {
52 // We cap the worker pool to 6 threads since there are at most 6 connections
53 // allowed per-origin.
54 // TODO(dalecurtis): This may be a bit restrictive if there are many videos
55 // from different origins on a page; is this common in practice?
56 // TODO(dalecurtis): Instead of being leaky, should we have a PoolManager type
57 // object which drops the pool when the last FFmpegDemuxer goes away?
58 static scoped_refptr<base::SequencedWorkerPool> pool(
59 new base::SequencedWorkerPool(6, "FFmpegDemuxer",
60 base::TaskPriority::USER_VISIBLE));
61 return pool->GetSequencedTaskRunner(
62 base::SequencedWorkerPool::GetSequenceToken());
63 }
64
50 static base::Time ExtractTimelineOffset(AVFormatContext* format_context) { 65 static base::Time ExtractTimelineOffset(AVFormatContext* format_context) {
51 if (strstr(format_context->iformat->name, "webm") || 66 if (strstr(format_context->iformat->name, "webm") ||
52 strstr(format_context->iformat->name, "matroska")) { 67 strstr(format_context->iformat->name, "matroska")) {
53 const AVDictionaryEntry* entry = 68 const AVDictionaryEntry* entry =
54 av_dict_get(format_context->metadata, "creation_time", NULL, 0); 69 av_dict_get(format_context->metadata, "creation_time", NULL, 0);
55 70
56 base::Time timeline_offset; 71 base::Time timeline_offset;
57 72
58 // FFmpegDemuxerTests assume base::Time::FromUTCString() is used here. 73 // FFmpegDemuxerTests assume base::Time::FromUTCString() is used here.
59 if (entry != NULL && entry->value != NULL && 74 if (entry != NULL && entry->value != NULL &&
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 // FFmpegDemuxer 853 // FFmpegDemuxer
839 // 854 //
840 FFmpegDemuxer::FFmpegDemuxer( 855 FFmpegDemuxer::FFmpegDemuxer(
841 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 856 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
842 DataSource* data_source, 857 DataSource* data_source,
843 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, 858 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
844 const MediaTracksUpdatedCB& media_tracks_updated_cb, 859 const MediaTracksUpdatedCB& media_tracks_updated_cb,
845 const scoped_refptr<MediaLog>& media_log) 860 const scoped_refptr<MediaLog>& media_log)
846 : host_(NULL), 861 : host_(NULL),
847 task_runner_(task_runner), 862 task_runner_(task_runner),
848 blocking_thread_("FFmpegDemuxer"), 863 blocking_task_runner_(GetSequencedTaskRunner()),
864 stopped_(false),
849 pending_read_(false), 865 pending_read_(false),
850 data_source_(data_source), 866 data_source_(data_source),
851 media_log_(media_log), 867 media_log_(media_log),
852 bitrate_(0), 868 bitrate_(0),
853 start_time_(kNoTimestamp), 869 start_time_(kNoTimestamp),
854 text_enabled_(false), 870 text_enabled_(false),
855 duration_known_(false), 871 duration_known_(false),
856 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), 872 encrypted_media_init_data_cb_(encrypted_media_init_data_cb),
857 media_tracks_updated_cb_(media_tracks_updated_cb), 873 media_tracks_updated_cb_(media_tracks_updated_cb),
858 cancel_pending_seek_factory_(this), 874 cancel_pending_seek_factory_(this),
859 weak_factory_(this) { 875 weak_factory_(this) {
860 DCHECK(task_runner_.get()); 876 DCHECK(task_runner_.get());
861 DCHECK(data_source_); 877 DCHECK(data_source_);
862 DCHECK(!media_tracks_updated_cb_.is_null()); 878 DCHECK(!media_tracks_updated_cb_.is_null());
863 } 879 }
864 880
865 FFmpegDemuxer::~FFmpegDemuxer() { 881 FFmpegDemuxer::~FFmpegDemuxer() {
866 // NOTE: This class is not destroyed on |task_runner|, so we must ensure that 882 // 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. 883 // there are no outstanding WeakPtrs by the time we reach here.
868 DCHECK(!weak_factory_.HasWeakPtrs()); 884 DCHECK(!weak_factory_.HasWeakPtrs());
885
886 // There may be outstanding tasks in the blocking pool which are trying to use
887 // these members, so release them in sequence with any outstanding calls. The
888 // earlier call to Abort() on |data_source_| prevents further access to it.
889 blocking_task_runner_->DeleteSoon(FROM_HERE, url_protocol_.release());
890 blocking_task_runner_->DeleteSoon(FROM_HERE, glue_.release());
869 } 891 }
870 892
871 std::string FFmpegDemuxer::GetDisplayName() const { 893 std::string FFmpegDemuxer::GetDisplayName() const {
872 return "FFmpegDemuxer"; 894 return "FFmpegDemuxer";
873 } 895 }
874 896
875 void FFmpegDemuxer::Initialize(DemuxerHost* host, 897 void FFmpegDemuxer::Initialize(DemuxerHost* host,
876 const PipelineStatusCB& status_cb, 898 const PipelineStatusCB& status_cb,
877 bool enable_text_tracks) { 899 bool enable_text_tracks) {
878 DCHECK(task_runner_->BelongsToCurrentThread()); 900 DCHECK(task_runner_->BelongsToCurrentThread());
(...skipping 13 matching lines...) Expand all
892 // available, so add a metadata entry to ensure some is always present. 914 // available, so add a metadata entry to ensure some is always present.
893 av_dict_set(&format_context->metadata, "skip_id3v1_tags", "", 0); 915 av_dict_set(&format_context->metadata, "skip_id3v1_tags", "", 0);
894 916
895 // Ensure ffmpeg doesn't give up too early while looking for stream params; 917 // 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 918 // 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 919 // 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. 920 // streams from being detected properly; this value was chosen arbitrarily.
899 format_context->max_analyze_duration = 60 * AV_TIME_BASE; 921 format_context->max_analyze_duration = 60 * AV_TIME_BASE;
900 922
901 // Open the AVFormatContext using our glue layer. 923 // Open the AVFormatContext using our glue layer.
902 CHECK(blocking_thread_.Start());
903 base::PostTaskAndReplyWithResult( 924 base::PostTaskAndReplyWithResult(
904 blocking_thread_.task_runner().get(), FROM_HERE, 925 blocking_task_runner_.get(), FROM_HERE,
905 base::Bind(&FFmpegGlue::OpenContext, base::Unretained(glue_.get())), 926 base::Bind(&FFmpegGlue::OpenContext, base::Unretained(glue_.get())),
906 base::Bind(&FFmpegDemuxer::OnOpenContextDone, weak_factory_.GetWeakPtr(), 927 base::Bind(&FFmpegDemuxer::OnOpenContextDone, weak_factory_.GetWeakPtr(),
907 status_cb)); 928 status_cb));
908 } 929 }
909 930
910 void FFmpegDemuxer::AbortPendingReads() { 931 void FFmpegDemuxer::AbortPendingReads() {
911 DCHECK(task_runner_->BelongsToCurrentThread()); 932 DCHECK(task_runner_->BelongsToCurrentThread());
912 933
913 // If Stop() has been called, then drop this call. 934 // If Stop() has been called, then drop this call.
914 if (!blocking_thread_.IsRunning()) 935 if (stopped_)
915 return; 936 return;
916 937
917 // This should only be called after the demuxer has been initialized. 938 // This should only be called after the demuxer has been initialized.
918 DCHECK_GT(streams_.size(), 0u); 939 DCHECK_GT(streams_.size(), 0u);
919 940
920 // Abort all outstanding reads. 941 // Abort all outstanding reads.
921 for (const auto& stream : streams_) { 942 for (const auto& stream : streams_) {
922 if (stream) 943 if (stream)
923 stream->Abort(); 944 stream->Abort();
924 } 945 }
925 946
926 // It's important to invalidate read/seek completion callbacks to avoid any 947 // It's important to invalidate read/seek completion callbacks to avoid any
927 // errors that occur because of the data source abort. 948 // errors that occur because of the data source abort.
928 weak_factory_.InvalidateWeakPtrs(); 949 weak_factory_.InvalidateWeakPtrs();
929 data_source_->Abort(); 950 data_source_->Abort();
930 951
931 // Aborting the read may cause EOF to be marked, undo this. 952 // Aborting the read may cause EOF to be marked, undo this.
932 blocking_thread_.task_runner()->PostTask( 953 blocking_task_runner_->PostTask(
933 FROM_HERE, base::Bind(&UnmarkEndOfStream, glue_->format_context())); 954 FROM_HERE, base::Bind(&UnmarkEndOfStream, glue_->format_context()));
934 pending_read_ = false; 955 pending_read_ = false;
935 956
936 // TODO(dalecurtis): We probably should report PIPELINE_ERROR_ABORT here 957 // TODO(dalecurtis): We probably should report PIPELINE_ERROR_ABORT here
937 // instead to avoid any preroll work that may be started upon return, but 958 // instead to avoid any preroll work that may be started upon return, but
938 // currently the PipelineImpl does not know how to handle this. 959 // currently the PipelineImpl does not know how to handle this.
939 if (!pending_seek_cb_.is_null()) 960 if (!pending_seek_cb_.is_null())
940 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK); 961 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK);
941 } 962 }
942 963
943 void FFmpegDemuxer::Stop() { 964 void FFmpegDemuxer::Stop() {
944 DCHECK(task_runner_->BelongsToCurrentThread()); 965 DCHECK(task_runner_->BelongsToCurrentThread());
945 966
946 // The order of Stop() and Abort() is important here. If Abort() is called 967 // 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 968 // first, control may pass into FFmpeg where it can destruct buffers that are
948 // in the process of being fulfilled by the DataSource. 969 // in the process of being fulfilled by the DataSource.
949 data_source_->Stop(); 970 data_source_->Stop();
950 url_protocol_->Abort(); 971 url_protocol_->Abort();
951 972
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_) { 973 for (const auto& stream : streams_) {
959 if (stream) 974 if (stream)
960 stream->Stop(); 975 stream->Stop();
961 } 976 }
962 977
963 data_source_ = NULL; 978 data_source_ = NULL;
964 979
965 // Invalidate WeakPtrs on |task_runner_|, destruction may happen on another 980 // Invalidate WeakPtrs on |task_runner_|, destruction may happen on another
966 // thread. 981 // thread. We don't need to wait for any outstanding tasks since they will all
982 // fail to return after invalidating WeakPtrs.
983 stopped_ = true;
967 weak_factory_.InvalidateWeakPtrs(); 984 weak_factory_.InvalidateWeakPtrs();
968 cancel_pending_seek_factory_.InvalidateWeakPtrs(); 985 cancel_pending_seek_factory_.InvalidateWeakPtrs();
969 } 986 }
970 987
971 void FFmpegDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) {} 988 void FFmpegDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) {}
972 989
973 void FFmpegDemuxer::CancelPendingSeek(base::TimeDelta seek_time) { 990 void FFmpegDemuxer::CancelPendingSeek(base::TimeDelta seek_time) {
974 if (task_runner_->BelongsToCurrentThread()) { 991 if (task_runner_->BelongsToCurrentThread()) {
975 AbortPendingReads(); 992 AbortPendingReads();
976 } else { 993 } 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: 1032 // be demuxed. It's an open question whether FFmpeg should fix this:
1016 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html 1033 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html
1017 // Tracked by http://crbug.com/387996. 1034 // Tracked by http://crbug.com/387996.
1018 FFmpegDemuxerStream* demux_stream = FindPreferredStreamForSeeking(seek_time); 1035 FFmpegDemuxerStream* demux_stream = FindPreferredStreamForSeeking(seek_time);
1019 DCHECK(demux_stream); 1036 DCHECK(demux_stream);
1020 const AVStream* seeking_stream = demux_stream->av_stream(); 1037 const AVStream* seeking_stream = demux_stream->av_stream();
1021 DCHECK(seeking_stream); 1038 DCHECK(seeking_stream);
1022 1039
1023 pending_seek_cb_ = cb; 1040 pending_seek_cb_ = cb;
1024 base::PostTaskAndReplyWithResult( 1041 base::PostTaskAndReplyWithResult(
1025 blocking_thread_.task_runner().get(), FROM_HERE, 1042 blocking_task_runner_.get(), FROM_HERE,
1026 base::Bind(&av_seek_frame, glue_->format_context(), seeking_stream->index, 1043 base::Bind(&av_seek_frame, glue_->format_context(), seeking_stream->index,
1027 ConvertToTimeBase(seeking_stream->time_base, seek_time), 1044 ConvertToTimeBase(seeking_stream->time_base, seek_time),
1028 // Always seek to a timestamp <= to the desired timestamp. 1045 // Always seek to a timestamp <= to the desired timestamp.
1029 AVSEEK_FLAG_BACKWARD), 1046 AVSEEK_FLAG_BACKWARD),
1030 base::Bind(&FFmpegDemuxer::OnSeekFrameDone, weak_factory_.GetWeakPtr())); 1047 base::Bind(&FFmpegDemuxer::OnSeekFrameDone, weak_factory_.GetWeakPtr()));
1031 } 1048 }
1032 1049
1033 base::Time FFmpegDemuxer::GetTimelineOffset() const { 1050 base::Time FFmpegDemuxer::GetTimelineOffset() const {
1034 return timeline_offset_; 1051 return timeline_offset_;
1035 } 1052 }
(...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 1169 // Do math in floating point as we'd overflow an int64_t if the filesize was
1153 // larger than ~1073GB. 1170 // larger than ~1073GB.
1154 double bytes = filesize_in_bytes; 1171 double bytes = filesize_in_bytes;
1155 double duration_us = duration.InMicroseconds(); 1172 double duration_us = duration.InMicroseconds();
1156 return bytes * 8000000.0 / duration_us; 1173 return bytes * 8000000.0 / duration_us;
1157 } 1174 }
1158 1175
1159 void FFmpegDemuxer::OnOpenContextDone(const PipelineStatusCB& status_cb, 1176 void FFmpegDemuxer::OnOpenContextDone(const PipelineStatusCB& status_cb,
1160 bool result) { 1177 bool result) {
1161 DCHECK(task_runner_->BelongsToCurrentThread()); 1178 DCHECK(task_runner_->BelongsToCurrentThread());
1162 if (!blocking_thread_.IsRunning()) { 1179 if (stopped_) {
1163 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1180 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1164 status_cb.Run(PIPELINE_ERROR_ABORT); 1181 status_cb.Run(PIPELINE_ERROR_ABORT);
1165 return; 1182 return;
1166 } 1183 }
1167 1184
1168 if (!result) { 1185 if (!result) {
1169 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": open context failed"; 1186 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": open context failed";
1170 status_cb.Run(DEMUXER_ERROR_COULD_NOT_OPEN); 1187 status_cb.Run(DEMUXER_ERROR_COULD_NOT_OPEN);
1171 return; 1188 return;
1172 } 1189 }
1173 1190
1174 // Fully initialize AVFormatContext by parsing the stream a little. 1191 // Fully initialize AVFormatContext by parsing the stream a little.
1175 base::PostTaskAndReplyWithResult( 1192 base::PostTaskAndReplyWithResult(
1176 blocking_thread_.task_runner().get(), 1193 blocking_task_runner_.get(), FROM_HERE,
1177 FROM_HERE, 1194 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)), 1195 static_cast<AVDictionary**>(NULL)),
1181 base::Bind(&FFmpegDemuxer::OnFindStreamInfoDone, 1196 base::Bind(&FFmpegDemuxer::OnFindStreamInfoDone,
1182 weak_factory_.GetWeakPtr(), 1197 weak_factory_.GetWeakPtr(), status_cb));
1183 status_cb));
1184 } 1198 }
1185 1199
1186 void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb, 1200 void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
1187 int result) { 1201 int result) {
1188 DCHECK(task_runner_->BelongsToCurrentThread()); 1202 DCHECK(task_runner_->BelongsToCurrentThread());
1189 if (!blocking_thread_.IsRunning() || !data_source_) { 1203 if (stopped_ || !data_source_) {
1190 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1204 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1191 status_cb.Run(PIPELINE_ERROR_ABORT); 1205 status_cb.Run(PIPELINE_ERROR_ABORT);
1192 return; 1206 return;
1193 } 1207 }
1194 1208
1195 if (result < 0) { 1209 if (result < 0) {
1196 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() 1210 MEDIA_LOG(ERROR, media_log_) << GetDisplayName()
1197 << ": find stream info failed"; 1211 << ": find stream info failed";
1198 status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE); 1212 status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE);
1199 return; 1213 return;
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
1599 } 1613 }
1600 1614
1601 NOTREACHED(); 1615 NOTREACHED();
1602 return nullptr; 1616 return nullptr;
1603 } 1617 }
1604 1618
1605 void FFmpegDemuxer::OnSeekFrameDone(int result) { 1619 void FFmpegDemuxer::OnSeekFrameDone(int result) {
1606 DCHECK(task_runner_->BelongsToCurrentThread()); 1620 DCHECK(task_runner_->BelongsToCurrentThread());
1607 CHECK(!pending_seek_cb_.is_null()); 1621 CHECK(!pending_seek_cb_.is_null());
1608 1622
1609 if (!blocking_thread_.IsRunning()) { 1623 if (stopped_) {
1610 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1624 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1611 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_ERROR_ABORT); 1625 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_ERROR_ABORT);
1612 return; 1626 return;
1613 } 1627 }
1614 1628
1615 if (result < 0) { 1629 if (result < 0) {
1616 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being 1630 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being
1617 // captured from stdout and contaminates testing. 1631 // captured from stdout and contaminates testing.
1618 // TODO(scherkus): Implement this properly and signal error (BUG=23447). 1632 // TODO(scherkus): Implement this properly and signal error (BUG=23447).
1619 VLOG(1) << "Not implemented"; 1633 VLOG(1) << "Not implemented";
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1686 if (selected_stream) { 1700 if (selected_stream) {
1687 DVLOG(1) << __func__ << ": enabling stream " << selected_stream; 1701 DVLOG(1) << __func__ << ": enabling stream " << selected_stream;
1688 selected_stream->set_enabled(true, currTime); 1702 selected_stream->set_enabled(true, currTime);
1689 } 1703 }
1690 } 1704 }
1691 1705
1692 void FFmpegDemuxer::ReadFrameIfNeeded() { 1706 void FFmpegDemuxer::ReadFrameIfNeeded() {
1693 DCHECK(task_runner_->BelongsToCurrentThread()); 1707 DCHECK(task_runner_->BelongsToCurrentThread());
1694 1708
1695 // Make sure we have work to do before reading. 1709 // Make sure we have work to do before reading.
1696 if (!blocking_thread_.IsRunning() || !StreamsHaveAvailableCapacity() || 1710 if (stopped_ || !StreamsHaveAvailableCapacity() || pending_read_ ||
1697 pending_read_ || !pending_seek_cb_.is_null()) { 1711 !pending_seek_cb_.is_null()) {
1698 return; 1712 return;
1699 } 1713 }
1700 1714
1701 // 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
1702 // evaluation order of packet.get() and base::Passed(&packet) is 1716 // evaluation order of packet.get() and base::Passed(&packet) is
1703 // undefined. 1717 // undefined.
1704 ScopedAVPacket packet(new AVPacket()); 1718 ScopedAVPacket packet(new AVPacket());
1705 AVPacket* packet_ptr = packet.get(); 1719 AVPacket* packet_ptr = packet.get();
1706 1720
1707 pending_read_ = true; 1721 pending_read_ = true;
1708 base::PostTaskAndReplyWithResult( 1722 base::PostTaskAndReplyWithResult(
1709 blocking_thread_.task_runner().get(), 1723 blocking_task_runner_.get(), FROM_HERE,
1710 FROM_HERE,
1711 base::Bind(&av_read_frame, glue_->format_context(), packet_ptr), 1724 base::Bind(&av_read_frame, glue_->format_context(), packet_ptr),
1712 base::Bind(&FFmpegDemuxer::OnReadFrameDone, 1725 base::Bind(&FFmpegDemuxer::OnReadFrameDone, weak_factory_.GetWeakPtr(),
1713 weak_factory_.GetWeakPtr(),
1714 base::Passed(&packet))); 1726 base::Passed(&packet)));
1715 } 1727 }
1716 1728
1717 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { 1729 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) {
1718 DCHECK(task_runner_->BelongsToCurrentThread()); 1730 DCHECK(task_runner_->BelongsToCurrentThread());
1719 DCHECK(pending_read_); 1731 DCHECK(pending_read_);
1720 pending_read_ = false; 1732 pending_read_ = false;
1721 1733
1722 if (!blocking_thread_.IsRunning() || !pending_seek_cb_.is_null()) 1734 if (stopped_ || !pending_seek_cb_.is_null())
1723 return; 1735 return;
1724 1736
1725 // Consider the stream as ended if: 1737 // Consider the stream as ended if:
1726 // - either underlying ffmpeg returned an error 1738 // - either underlying ffmpeg returned an error
1727 // - or FFMpegDemuxer reached the maximum allowed memory usage. 1739 // - or FFMpegDemuxer reached the maximum allowed memory usage.
1728 if (result < 0 || IsMaxMemoryUsageReached()) { 1740 if (result < 0 || IsMaxMemoryUsageReached()) {
1729 DVLOG(1) << __func__ << " result=" << result 1741 DVLOG(1) << __func__ << " result=" << result
1730 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached(); 1742 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached();
1731 // 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.
1732 base::TimeDelta max_duration; 1744 base::TimeDelta max_duration;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1837 1849
1838 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { 1850 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) {
1839 DCHECK(task_runner_->BelongsToCurrentThread()); 1851 DCHECK(task_runner_->BelongsToCurrentThread());
1840 for (const auto& stream : streams_) { 1852 for (const auto& stream : streams_) {
1841 if (stream) 1853 if (stream)
1842 stream->SetLiveness(liveness); 1854 stream->SetLiveness(liveness);
1843 } 1855 }
1844 } 1856 }
1845 1857
1846 } // namespace media 1858 } // namespace media
OLDNEW
« media/filters/blocking_url_protocol.cc ('K') | « media/filters/ffmpeg_demuxer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698