Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / media / filters / blocking_url_protocol.cc
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/filters/blocking_url_protocol.h"
6
7 #include <stddef.h>
8
9 #include "base/bind.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/thread_restrictions.h"
12 #include "media/base/data_source.h"
13 #include "media/ffmpeg/ffmpeg_common.h"
14
15 namespace media {
16
17 BlockingUrlProtocol::BlockingUrlProtocol(DataSource* data_source,
18                                          const base::RepeatingClosure& error_cb)
19     : data_source_(data_source),
20       error_cb_(error_cb),
21       is_streaming_(data_source_->IsStreaming()),
22       aborted_(base::WaitableEvent::ResetPolicy::MANUAL,
23                base::WaitableEvent::InitialState::NOT_SIGNALED),  // We never
24                                                                   // want to
25                                                                   // reset
26                                                                   // |aborted_|.
27       read_complete_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
28                      base::WaitableEvent::InitialState::NOT_SIGNALED),
29       last_read_bytes_(0),
30       read_position_(0) {}
31
32 BlockingUrlProtocol::~BlockingUrlProtocol() = default;
33
34 void BlockingUrlProtocol::Abort() {
35   aborted_.Signal();
36   base::AutoLock lock(data_source_lock_);
37   data_source_ = nullptr;
38 }
39
40 int BlockingUrlProtocol::Read(int size, uint8_t* data) {
41   {
42     // Read errors are unrecoverable.
43     base::AutoLock lock(data_source_lock_);
44     if (!data_source_) {
45       DCHECK(aborted_.IsSignaled());
46       return AVERROR(EIO);
47     }
48
49     // Not sure this can happen, but it's unclear from the ffmpeg code, so guard
50     // against it.
51     if (size < 0)
52       return AVERROR(EIO);
53     if (!size)
54       return 0;
55
56     int64_t file_size;
57     if (data_source_->GetSize(&file_size) && read_position_ >= file_size)
58       return AVERROR_EOF;
59
60     // Blocking read from data source until either:
61     //   1) |last_read_bytes_| is set and |read_complete_| is signalled
62     //   2) |aborted_| is signalled
63     data_source_->Read(read_position_, size, data,
64                        base::BindOnce(&BlockingUrlProtocol::SignalReadCompleted,
65                                       base::Unretained(this)));
66   }
67
68   base::WaitableEvent* events[] = { &aborted_, &read_complete_ };
69   size_t index;
70   {
71     base::ScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
72     index = base::WaitableEvent::WaitMany(events, std::size(events));
73   }
74
75   if (events[index] == &aborted_)
76     return AVERROR(EIO);
77
78   if (last_read_bytes_ == DataSource::kReadError) {
79     aborted_.Signal();
80     error_cb_.Run();
81     return AVERROR(EIO);
82   }
83
84   if (last_read_bytes_ == DataSource::kAborted)
85     return AVERROR(EIO);
86
87   read_position_ += last_read_bytes_;
88   return last_read_bytes_;
89 }
90
91 bool BlockingUrlProtocol::GetPosition(int64_t* position_out) {
92   *position_out = read_position_;
93   return true;
94 }
95
96 bool BlockingUrlProtocol::SetPosition(int64_t position) {
97   base::AutoLock lock(data_source_lock_);
98   int64_t file_size;
99   if (!data_source_ ||
100       (data_source_->GetSize(&file_size) && position > file_size) ||
101       position < 0) {
102     return false;
103   }
104
105   read_position_ = position;
106   return true;
107 }
108
109 bool BlockingUrlProtocol::GetSize(int64_t* size_out) {
110   base::AutoLock lock(data_source_lock_);
111   return data_source_ ? data_source_->GetSize(size_out) : false;
112 }
113
114 bool BlockingUrlProtocol::IsStreaming() {
115   return is_streaming_;
116 }
117
118 void BlockingUrlProtocol::SignalReadCompleted(int size) {
119   last_read_bytes_ = size;
120   read_complete_.Signal();
121 }
122
123 }  // namespace media