[M120 Migration][MM][CAPI] Fix the logic for media using capi player.
[platform/framework/web/chromium-efl.git] / media / mojo / services / mojo_video_encode_accelerator_service.cc
1 // Copyright 2017 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/mojo/services/mojo_video_encode_accelerator_service.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/logging.h"
11 #include "base/task/bind_post_task.h"
12 #include "base/task/sequenced_task_runner.h"
13 #include "base/trace_event/trace_event.h"
14 #include "media/base/bitstream_buffer.h"
15 #include "media/base/limits.h"
16 #include "media/base/media_util.h"
17 #include "media/mojo/mojom/video_encoder_info.mojom.h"
18 #include "media/mojo/services/mojo_media_log.h"
19 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
20 #include "mojo/public/cpp/system/platform_handle.h"
21
22 namespace media {
23
24 // static
25 void MojoVideoEncodeAcceleratorService::Create(
26     mojo::PendingReceiver<mojom::VideoEncodeAccelerator> receiver,
27     CreateAndInitializeVideoEncodeAcceleratorCallback create_vea_callback,
28     const gpu::GpuPreferences& gpu_preferences,
29     const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
30     const gpu::GPUInfo::GPUDevice& gpu_device) {
31   mojo::MakeSelfOwnedReceiver(
32       std::make_unique<MojoVideoEncodeAcceleratorService>(
33           std::move(create_vea_callback), gpu_preferences, gpu_workarounds,
34           gpu_device),
35       std::move(receiver));
36 }
37
38 MojoVideoEncodeAcceleratorService::MojoVideoEncodeAcceleratorService(
39     CreateAndInitializeVideoEncodeAcceleratorCallback create_vea_callback,
40     const gpu::GpuPreferences& gpu_preferences,
41     const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
42     const gpu::GPUInfo::GPUDevice& gpu_device)
43     : create_vea_callback_(std::move(create_vea_callback)),
44       gpu_preferences_(gpu_preferences),
45       gpu_workarounds_(gpu_workarounds),
46       gpu_device_(gpu_device),
47       output_buffer_size_(0),
48       timestamps_(128) {
49   DVLOG(1) << __func__;
50   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
51 }
52
53 MojoVideoEncodeAcceleratorService::~MojoVideoEncodeAcceleratorService() {
54   DVLOG(1) << __func__;
55   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
56 }
57
58 void MojoVideoEncodeAcceleratorService::Initialize(
59     const media::VideoEncodeAccelerator::Config& config,
60     mojo::PendingAssociatedRemote<mojom::VideoEncodeAcceleratorClient> client,
61     mojo::PendingRemote<mojom::MediaLog> media_log,
62     InitializeCallback success_callback) {
63   DVLOG(1) << __func__ << " " << config.AsHumanReadableString();
64   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
65   DCHECK(config.input_format == PIXEL_FORMAT_I420 ||
66          config.input_format == PIXEL_FORMAT_NV12)
67       << "Only I420 or NV12 format supported, got "
68       << VideoPixelFormatToString(config.input_format);
69   TRACE_EVENT1("media", "MojoVideoEncodeAcceleratorService::Initialize",
70                "config", config.AsHumanReadableString());
71
72   media_log_ = std::make_unique<MojoMediaLog>(
73       std::move(media_log), base::SequencedTaskRunner::GetCurrentDefault());
74
75   if (gpu_workarounds_.disable_accelerated_vp8_encode &&
76       config.output_profile == VP8PROFILE_ANY) {
77     MEDIA_LOG(ERROR, media_log_.get())
78         << __func__ << " VP8 encoding disabled by GPU policy";
79     std::move(success_callback).Run(false);
80     return;
81   }
82
83   if (gpu_workarounds_.disable_accelerated_vp9_encode &&
84       config.output_profile >= VP9PROFILE_PROFILE0 &&
85       config.output_profile <= VP9PROFILE_PROFILE3) {
86     MEDIA_LOG(ERROR, media_log_.get())
87         << __func__ << " VP9 encoding disabled by GPU policy";
88     std::move(success_callback).Run(false);
89     return;
90   }
91
92   if (gpu_workarounds_.disable_accelerated_h264_encode &&
93       config.output_profile >= H264PROFILE_MIN &&
94       config.output_profile <= H264PROFILE_MAX) {
95     MEDIA_LOG(ERROR, media_log_.get())
96         << __func__ << " H.264 encoding disabled by GPU policy";
97     std::move(success_callback).Run(false);
98     return;
99   }
100
101   if (encoder_) {
102     MEDIA_LOG(ERROR, media_log_.get())
103         << __func__ << " VEA is already initialized";
104     std::move(success_callback).Run(false);
105     return;
106   }
107
108   if (!client) {
109     MEDIA_LOG(ERROR, media_log_.get()) << __func__ << "null |client|";
110     std::move(success_callback).Run(false);
111     return;
112   }
113   vea_client_.Bind(std::move(client));
114
115   if (config.input_visible_size.width() > limits::kMaxDimension ||
116       config.input_visible_size.height() > limits::kMaxDimension ||
117       config.input_visible_size.GetArea() > limits::kMaxCanvas) {
118     MEDIA_LOG(ERROR, media_log_.get())
119         << __func__ << "too large input_visible_size "
120         << config.input_visible_size.ToString();
121     std::move(success_callback).Run(false);
122     return;
123   }
124
125   encoder_ = std::move(create_vea_callback_)
126                  .Run(config, this, gpu_preferences_, gpu_workarounds_,
127                       gpu_device_, media_log_->Clone());
128   if (!encoder_) {
129     MEDIA_LOG(ERROR, media_log_.get())
130         << __func__ << " Error creating or initializing VEA";
131     std::move(success_callback).Run(false);
132     return;
133   }
134
135   std::move(success_callback).Run(true);
136   return;
137 }
138
139 void MojoVideoEncodeAcceleratorService::Encode(
140     const scoped_refptr<VideoFrame>& frame,
141     const media::VideoEncoder::EncodeOptions& options,
142     EncodeCallback callback) {
143   DVLOG(2) << __func__ << " tstamp=" << frame->timestamp();
144   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
145   TRACE_EVENT2("media", "MojoVideoEncodeAcceleratorService::Encode",
146                "timestamp", frame->timestamp().InMicroseconds(), "keyframe",
147                options.key_frame);
148   if (!encoder_) {
149     DLOG(ERROR) << __func__ << " Failed to encode, the encoder is invalid";
150     std::move(callback).Run();
151     return;
152   }
153
154   if (frame->coded_size() != input_coded_size_ &&
155       frame->storage_type() != media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
156     NotifyErrorStatus({EncoderStatus::Codes::kInvalidInputFrame,
157                        "wrong input coded size, expected " +
158                            input_coded_size_.ToString() + ", got " +
159                            frame->coded_size().ToString()});
160     std::move(callback).Run();
161     return;
162   }
163
164   if (MediaTraceIsEnabled()) {
165     timestamps_.Put(frame->timestamp().InMicroseconds(),
166                     base::TimeTicks::Now());
167   }
168
169   frame->AddDestructionObserver(
170       base::BindPostTaskToCurrentDefault(std::move(callback)));
171   encoder_->Encode(frame, options);
172 }
173
174 void MojoVideoEncodeAcceleratorService::UseOutputBitstreamBuffer(
175     int32_t bitstream_buffer_id,
176     base::UnsafeSharedMemoryRegion region) {
177   DVLOG(2) << __func__ << " bitstream_buffer_id=" << bitstream_buffer_id;
178   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
179   TRACE_EVENT1("media",
180                "MojoVideoEncodeAcceleratorService::UseOutputBitstreamBuffer",
181                "id", bitstream_buffer_id);
182   if (!encoder_)
183     return;
184   if (!region.IsValid()) {
185     NotifyErrorStatus({EncoderStatus::Codes::kInvalidOutputBuffer,
186                        "invalid shared memory region"});
187     return;
188   }
189   if (bitstream_buffer_id < 0) {
190     NotifyErrorStatus(
191         {EncoderStatus::Codes::kInvalidOutputBuffer,
192          "bitstream_buffer_id=" + base::NumberToString(bitstream_buffer_id) +
193              " must be >= 0"});
194     return;
195   }
196
197   auto memory_size = region.GetSize();
198   if (memory_size < output_buffer_size_) {
199     NotifyErrorStatus(
200         {EncoderStatus::Codes::kInvalidOutputBuffer,
201          "bitstream_buffer_id=" + base::NumberToString(bitstream_buffer_id) +
202              " has a size of " + base::NumberToString(memory_size) +
203              "B, different from expected " +
204              base::NumberToString(output_buffer_size_) + "B"});
205     return;
206   }
207
208   encoder_->UseOutputBitstreamBuffer(
209       BitstreamBuffer(bitstream_buffer_id, std::move(region), memory_size));
210 }
211
212 void MojoVideoEncodeAcceleratorService::
213     RequestEncodingParametersChangeWithLayers(
214         const media::VideoBitrateAllocation& bitrate_allocation,
215         uint32_t framerate) {
216   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
217   TRACE_EVENT2("media",
218                "MojoVideoEncodeAcceleratorService::"
219                "RequestEncodingParametersChangeWithLayers",
220                "bitrate_allocation", bitrate_allocation.ToString(), "framerate",
221                framerate);
222
223   if (!encoder_)
224     return;
225
226   DVLOG(2) << __func__ << " bitrate=" << bitrate_allocation.GetSumBps()
227            << " framerate=" << framerate;
228
229   encoder_->RequestEncodingParametersChange(bitrate_allocation, framerate);
230 }
231
232 void MojoVideoEncodeAcceleratorService::
233     RequestEncodingParametersChangeWithBitrate(const media::Bitrate& bitrate,
234                                                uint32_t framerate) {
235   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
236   TRACE_EVENT2("media",
237                "MojoVideoEncodeAcceleratorService::"
238                "RequestEncodingParametersChangeWithBitrate",
239                "bitrate", bitrate.ToString(), "framerate", framerate);
240   if (!encoder_)
241     return;
242
243   DVLOG(2) << __func__ << " bitrate=" << bitrate.target_bps()
244            << " framerate=" << framerate;
245
246   encoder_->RequestEncodingParametersChange(bitrate, framerate);
247 }
248
249 void MojoVideoEncodeAcceleratorService::IsFlushSupported(
250     IsFlushSupportedCallback callback) {
251   DVLOG(2) << __func__;
252   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
253
254   if (!encoder_) {
255     DLOG(ERROR) << __func__
256                 << " Failed to detect flush support, the encoder is invalid";
257     std::move(callback).Run(false);
258     return;
259   }
260
261   bool flush_support = encoder_->IsFlushSupported();
262   std::move(callback).Run(flush_support);
263 }
264
265 void MojoVideoEncodeAcceleratorService::Flush(FlushCallback callback) {
266   DVLOG(2) << __func__;
267   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
268
269   if (!encoder_) {
270     DLOG(ERROR) << __func__ << " Failed to flush, the encoder is invalid";
271     std::move(callback).Run(false);
272     return;
273   }
274
275   encoder_->Flush(std::move(callback));
276 }
277
278 void MojoVideoEncodeAcceleratorService::RequireBitstreamBuffers(
279     unsigned int input_count,
280     const gfx::Size& input_coded_size,
281     size_t output_buffer_size) {
282   DVLOG(2) << __func__ << " input_count=" << input_count
283            << " input_coded_size=" << input_coded_size.ToString()
284            << " output_buffer_size=" << output_buffer_size;
285   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
286   TRACE_EVENT2("media",
287                "MojoVideoEncodeAcceleratorService::RequireBitstreamBuffers",
288                "input_coded_size", input_coded_size.ToString(),
289                "output_buffer_size", output_buffer_size);
290
291   if (!vea_client_)
292     return;
293
294   output_buffer_size_ = output_buffer_size;
295   input_coded_size_ = input_coded_size;
296
297   vea_client_->RequireBitstreamBuffers(input_count, input_coded_size,
298                                        output_buffer_size);
299 }
300
301 void MojoVideoEncodeAcceleratorService::BitstreamBufferReady(
302     int32_t bitstream_buffer_id,
303     const media::BitstreamBufferMetadata& metadata) {
304   DVLOG(2) << __func__ << " bitstream_buffer_id=" << bitstream_buffer_id
305            << ", payload_size=" << metadata.payload_size_bytes
306            << "B,  key_frame=" << metadata.key_frame;
307   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
308   TRACE_EVENT2("media",
309                "MojoVideoEncodeAcceleratorService::BitstreamBufferReady",
310                "timestamp", metadata.timestamp.InMicroseconds(),
311                "bitstream_buffer_id", bitstream_buffer_id);
312   if (MediaTraceIsEnabled() && metadata.end_of_picture()) {
313     int64_t timestamp = metadata.timestamp.InMicroseconds();
314     const auto timestamp_it = timestamps_.Peek(timestamp);
315     if (timestamp_it != timestamps_.end()) {
316       TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
317           "media", "MojoVEAService::EncodingFrameDuration", timestamp,
318           timestamp_it->second);
319       TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP1(
320           "media", "MojoVEAService::EncodingFrameDuration", timestamp,
321           base::TimeTicks::Now(), "timestamp", timestamp);
322     }
323   }
324
325   if (!vea_client_)
326     return;
327
328   vea_client_->BitstreamBufferReady(bitstream_buffer_id, metadata);
329 }
330
331 void MojoVideoEncodeAcceleratorService::NotifyErrorStatus(
332     const EncoderStatus& status) {
333   DVLOG(1) << __func__;
334   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
335   CHECK(!status.is_ok());
336   if (!vea_client_)
337     return;
338   LOG(ERROR) << "Call NotifyErrorStatus(): code="
339              << static_cast<int>(status.code())
340              << ", message=" << status.message();
341   vea_client_->NotifyErrorStatus(status);
342 }
343
344 void MojoVideoEncodeAcceleratorService::NotifyEncoderInfoChange(
345     const ::media::VideoEncoderInfo& info) {
346   DVLOG(4) << __func__;
347   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
348   if (!vea_client_)
349     return;
350
351   vea_client_->NotifyEncoderInfoChange(info);
352 }
353
354 }  // namespace media