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/mojo/clients/mojo_video_decoder.cc

Issue 2429723006: MojoVideoDecoder: Plumb metadata methods. (Closed)
Patch Set: Created 4 years, 2 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/mojo/clients/mojo_video_decoder.h" 5 #include "media/mojo/clients/mojo_video_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/location.h" 10 #include "base/location.h"
(...skipping 14 matching lines...) Expand all
25 : task_runner_(task_runner), 25 : task_runner_(task_runner),
26 gpu_factories_(gpu_factories), 26 gpu_factories_(gpu_factories),
27 remote_decoder_info_(remote_decoder.PassInterface()), 27 remote_decoder_info_(remote_decoder.PassInterface()),
28 client_binding_(this) { 28 client_binding_(this) {
29 (void)gpu_factories_; 29 (void)gpu_factories_;
30 DVLOG(1) << __FUNCTION__; 30 DVLOG(1) << __FUNCTION__;
31 } 31 }
32 32
33 MojoVideoDecoder::~MojoVideoDecoder() { 33 MojoVideoDecoder::~MojoVideoDecoder() {
34 DVLOG(1) << __FUNCTION__; 34 DVLOG(1) << __FUNCTION__;
35 Stop();
35 } 36 }
36 37
37 std::string MojoVideoDecoder::GetDisplayName() const { 38 std::string MojoVideoDecoder::GetDisplayName() const {
39 // TODO(sandersd): Build the name including information from the remote end.
38 return "MojoVideoDecoder"; 40 return "MojoVideoDecoder";
39 } 41 }
40 42
41 void MojoVideoDecoder::Initialize(const VideoDecoderConfig& config, 43 void MojoVideoDecoder::Initialize(const VideoDecoderConfig& config,
42 bool low_delay, 44 bool low_delay,
43 CdmContext* cdm_context, 45 CdmContext* cdm_context,
44 const InitCB& init_cb, 46 const InitCB& init_cb,
45 const OutputCB& output_cb) { 47 const OutputCB& output_cb) {
46 DVLOG(1) << __FUNCTION__; 48 DVLOG(1) << __FUNCTION__;
47 DCHECK(task_runner_->BelongsToCurrentThread()); 49 DCHECK(task_runner_->BelongsToCurrentThread());
48 DCHECK(!cdm_context); 50 DCHECK(!cdm_context);
49 51
50 if (!remote_decoder_bound_) 52 if (!remote_decoder_bound_)
51 BindRemoteDecoder(); 53 BindRemoteDecoder();
52 54
53 if (has_connection_error_) { 55 if (has_connection_error_) {
54 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false)); 56 task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false));
55 return; 57 return;
56 } 58 }
57 59
60 initialized_ = false;
58 init_cb_ = init_cb; 61 init_cb_ = init_cb;
59 output_cb_ = output_cb; 62 output_cb_ = output_cb;
60 remote_decoder_->Initialize( 63 remote_decoder_->Initialize(
61 mojom::VideoDecoderConfig::From(config), low_delay, 64 mojom::VideoDecoderConfig::From(config), low_delay,
62 base::Bind(&MojoVideoDecoder::OnInitializeDone, base::Unretained(this))); 65 base::Bind(&MojoVideoDecoder::OnInitializeDone, base::Unretained(this)));
63 } 66 }
64 67
65 // TODO(sandersd): Remove this indirection once a working decoder has been 68 void MojoVideoDecoder::OnInitializeDone(bool status,
66 // brought up. 69 bool needs_bitstream_conversion,
67 void MojoVideoDecoder::OnInitializeDone(bool status) { 70 int32_t max_decode_requests) {
68 DVLOG(1) << __FUNCTION__; 71 DVLOG(1) << __FUNCTION__;
69 DCHECK(task_runner_->BelongsToCurrentThread()); 72 DCHECK(task_runner_->BelongsToCurrentThread());
73 initialized_ = true;
74 needs_bitstream_conversion_ = needs_bitstream_conversion;
75 max_decode_requests_ = max_decode_requests;
76 can_read_without_stalling_ = true;
70 base::ResetAndReturn(&init_cb_).Run(status); 77 base::ResetAndReturn(&init_cb_).Run(status);
71 } 78 }
72 79
73 void MojoVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, 80 void MojoVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
74 const DecodeCB& decode_cb) { 81 const DecodeCB& decode_cb) {
75 DVLOG(1) << __FUNCTION__; 82 DVLOG(2) << __FUNCTION__;
76 DCHECK(task_runner_->BelongsToCurrentThread()); 83 DCHECK(task_runner_->BelongsToCurrentThread());
77 84
78 if (has_connection_error_) { 85 if (has_connection_error_) {
79 task_runner_->PostTask(FROM_HERE, 86 task_runner_->PostTask(FROM_HERE,
80 base::Bind(decode_cb, DecodeStatus::DECODE_ERROR)); 87 base::Bind(decode_cb, DecodeStatus::DECODE_ERROR));
81 return; 88 return;
82 } 89 }
83 90
84 mojom::DecoderBufferPtr mojo_buffer = 91 mojom::DecoderBufferPtr mojo_buffer =
85 mojo_decoder_buffer_writer_->WriteDecoderBuffer(buffer); 92 mojo_decoder_buffer_writer_->WriteDecoderBuffer(buffer);
86 if (!mojo_buffer) { 93 if (!mojo_buffer) {
87 task_runner_->PostTask(FROM_HERE, 94 task_runner_->PostTask(FROM_HERE,
88 base::Bind(decode_cb, DecodeStatus::DECODE_ERROR)); 95 base::Bind(decode_cb, DecodeStatus::DECODE_ERROR));
89 return; 96 return;
90 } 97 }
91 98
92 // TODO(sandersd): Support more than one decode at a time. 99 uint64_t decode_id = decode_counter_++;
93 decode_cb_ = decode_cb; 100 pending_decodes_[decode_id] = decode_cb;
slan 2016/10/18 20:46:25 What if we bind |decode_cb| directly to OnDecodeDo
slan 2016/10/18 20:49:41 Sorry, this is a typo, you know what I mean :)
sandersd (OOO until July 31) 2016/10/18 21:09:56 The problem this solves is having a list of outsta
slan 2016/10/18 22:06:44 Right, I overlooked that bit. Your method SGTM.
94 remote_decoder_->Decode( 101 remote_decoder_->Decode(std::move(mojo_buffer),
95 std::move(mojo_buffer), 102 base::Bind(&MojoVideoDecoder::OnDecodeDone,
96 base::Bind(&MojoVideoDecoder::OnDecodeDone, base::Unretained(this))); 103 base::Unretained(this), decode_id));
dcheng 2016/10/18 20:39:05 Can we just bind the callback directly instead of
dcheng 2016/10/19 02:42:39 OK, thanks for the explanation. +rockot, do you kn
Ken Rockot(use gerrit already) 2016/10/19 05:50:34 It's not a pattern that has come up often. This ap
97 } 104 }
98 105
99 void MojoVideoDecoder::OnVideoFrameDecoded(mojom::VideoFramePtr frame) { 106 void MojoVideoDecoder::OnVideoFrameDecoded(mojom::VideoFramePtr frame) {
100 DVLOG(1) << __FUNCTION__; 107 DVLOG(2) << __FUNCTION__;
101 DCHECK(task_runner_->BelongsToCurrentThread()); 108 DCHECK(task_runner_->BelongsToCurrentThread());
102 output_cb_.Run(frame.To<scoped_refptr<VideoFrame>>()); 109 output_cb_.Run(frame.To<scoped_refptr<VideoFrame>>());
103 } 110 }
104 111
105 void MojoVideoDecoder::OnDecodeDone(DecodeStatus status) { 112 void MojoVideoDecoder::OnDecodeDone(uint64_t decode_id,
106 DVLOG(1) << __FUNCTION__; 113 DecodeStatus status,
114 bool can_read_without_stalling) {
115 DVLOG(2) << __FUNCTION__;
107 DCHECK(task_runner_->BelongsToCurrentThread()); 116 DCHECK(task_runner_->BelongsToCurrentThread());
108 base::ResetAndReturn(&decode_cb_).Run(status); 117 DCHECK(pending_decodes_.count(decode_id));
118 DCHECK(pending_decodes_.size() > 1 || can_read_without_stalling);
dcheng 2016/10/18 20:39:05 Should these actually be DCHECKs? Presumably, the
sandersd (OOO until July 31) 2016/10/18 21:09:56 In fact it lives in a more privileged process (the
dcheng 2016/10/19 02:42:39 Hmm, can you link to the GpuVideoDecoder you're re
sandersd (OOO until July 31) 2016/10/19 17:51:24 https://cs.chromium.org/chromium/src/media/filters
119 can_read_without_stalling_ = can_read_without_stalling;
120 DecodeCB decode_cb = pending_decodes_[decode_id];
121 pending_decodes_.erase(decode_id);
122 decode_cb.Run(status);
109 } 123 }
110 124
111 void MojoVideoDecoder::Reset(const base::Closure& reset_cb) { 125 void MojoVideoDecoder::Reset(const base::Closure& reset_cb) {
112 DVLOG(1) << __FUNCTION__; 126 DVLOG(1) << __FUNCTION__;
113 DCHECK(task_runner_->BelongsToCurrentThread()); 127 DCHECK(task_runner_->BelongsToCurrentThread());
114 128
115 if (has_connection_error_) { 129 if (has_connection_error_) {
116 task_runner_->PostTask(FROM_HERE, reset_cb); 130 task_runner_->PostTask(FROM_HERE, reset_cb);
117 return; 131 return;
118 } 132 }
119 133
120 reset_cb_ = reset_cb; 134 reset_cb_ = reset_cb;
121 remote_decoder_->Reset( 135 remote_decoder_->Reset(
122 base::Bind(&MojoVideoDecoder::OnResetDone, base::Unretained(this))); 136 base::Bind(&MojoVideoDecoder::OnResetDone, base::Unretained(this)));
123 } 137 }
124 138
125 void MojoVideoDecoder::OnResetDone() { 139 void MojoVideoDecoder::OnResetDone() {
126 DVLOG(1) << __FUNCTION__; 140 DVLOG(1) << __FUNCTION__;
127 DCHECK(task_runner_->BelongsToCurrentThread()); 141 DCHECK(task_runner_->BelongsToCurrentThread());
142 can_read_without_stalling_ = true;
128 base::ResetAndReturn(&reset_cb_).Run(); 143 base::ResetAndReturn(&reset_cb_).Run();
129 } 144 }
130 145
131 bool MojoVideoDecoder::NeedsBitstreamConversion() const { 146 bool MojoVideoDecoder::NeedsBitstreamConversion() const {
132 DVLOG(1) << __FUNCTION__; 147 DVLOG(3) << __FUNCTION__;
133 return false; 148 DCHECK(initialized_);
149 return needs_bitstream_conversion_;
134 } 150 }
135 151
136 bool MojoVideoDecoder::CanReadWithoutStalling() const { 152 bool MojoVideoDecoder::CanReadWithoutStalling() const {
137 DVLOG(1) << __FUNCTION__; 153 DVLOG(3) << __FUNCTION__;
138 return true; 154 DCHECK(initialized_);
155 return can_read_without_stalling_;
139 } 156 }
140 157
141 int MojoVideoDecoder::GetMaxDecodeRequests() const { 158 int MojoVideoDecoder::GetMaxDecodeRequests() const {
142 DVLOG(1) << __FUNCTION__; 159 DVLOG(3) << __FUNCTION__;
143 return 1; 160 DCHECK(initialized_);
161 return max_decode_requests_;
144 } 162 }
145 163
146 void MojoVideoDecoder::BindRemoteDecoder() { 164 void MojoVideoDecoder::BindRemoteDecoder() {
147 DVLOG(1) << __FUNCTION__; 165 DVLOG(3) << __FUNCTION__;
148 DCHECK(task_runner_->BelongsToCurrentThread()); 166 DCHECK(task_runner_->BelongsToCurrentThread());
149 DCHECK(!remote_decoder_bound_); 167 DCHECK(!remote_decoder_bound_);
150 168
151 remote_decoder_.Bind(std::move(remote_decoder_info_)); 169 remote_decoder_.Bind(std::move(remote_decoder_info_));
152 remote_decoder_bound_ = true; 170 remote_decoder_bound_ = true;
153 171
154 remote_decoder_.set_connection_error_handler( 172 remote_decoder_.set_connection_error_handler(
155 base::Bind(&MojoVideoDecoder::OnConnectionError, base::Unretained(this))); 173 base::Bind(&MojoVideoDecoder::Stop, base::Unretained(this)));
156 174
175 // TODO(sandersd): Does this need its own error handler?
157 mojom::VideoDecoderClientAssociatedPtrInfo client_ptr_info; 176 mojom::VideoDecoderClientAssociatedPtrInfo client_ptr_info;
158 client_binding_.Bind(&client_ptr_info, remote_decoder_.associated_group()); 177 client_binding_.Bind(&client_ptr_info, remote_decoder_.associated_group());
159 178
160 // TODO(sandersd): Better buffer sizing. 179 // TODO(sandersd): Better buffer sizing.
161 mojo::ScopedDataPipeConsumerHandle remote_consumer_handle; 180 mojo::ScopedDataPipeConsumerHandle remote_consumer_handle;
162 mojo_decoder_buffer_writer_ = MojoDecoderBufferWriter::Create( 181 mojo_decoder_buffer_writer_ = MojoDecoderBufferWriter::Create(
163 DemuxerStream::VIDEO, &remote_consumer_handle); 182 DemuxerStream::VIDEO, &remote_consumer_handle);
164 183
165 remote_decoder_->Construct(std::move(client_ptr_info), 184 remote_decoder_->Construct(std::move(client_ptr_info),
166 std::move(remote_consumer_handle)); 185 std::move(remote_consumer_handle));
167 } 186 }
168 187
169 void MojoVideoDecoder::OnConnectionError() { 188 void MojoVideoDecoder::Stop() {
170 DVLOG(1) << __FUNCTION__; 189 DVLOG(2) << __FUNCTION__;
171 DCHECK(task_runner_->BelongsToCurrentThread()); 190 DCHECK(task_runner_->BelongsToCurrentThread());
172 191
173 has_connection_error_ = true; 192 has_connection_error_ = true;
174 193
175 // TODO(sandersd): Write a wrapper class (like BindToCurrentLoop) that handles
176 // the lifetime of callbacks like this.
177 if (!init_cb_.is_null()) 194 if (!init_cb_.is_null())
178 base::ResetAndReturn(&init_cb_).Run(false); 195 base::ResetAndReturn(&init_cb_).Run(false);
179 // TODO(sandersd): If there is a pending reset, should these be aborted? 196
180 if (!decode_cb_.is_null()) 197 for (const auto& pending_decode : pending_decodes_)
181 base::ResetAndReturn(&decode_cb_).Run(DecodeStatus::DECODE_ERROR); 198 pending_decode.second.Run(DecodeStatus::DECODE_ERROR);
199 pending_decodes_.clear();
200
182 if (!reset_cb_.is_null()) 201 if (!reset_cb_.is_null())
183 base::ResetAndReturn(&reset_cb_).Run(); 202 base::ResetAndReturn(&reset_cb_).Run();
184 } 203 }
185 204
186 } // namespace media 205 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698