OLD | NEW |
---|---|
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 "content/common/gpu/media/vaapi_video_decode_accelerator.h" | 5 #include "media/gpu/vaapi_video_decode_accelerator.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/macros.h" | 11 #include "base/macros.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
15 #include "base/synchronization/waitable_event.h" | 15 #include "base/synchronization/waitable_event.h" |
16 #include "base/trace_event/trace_event.h" | 16 #include "base/trace_event/trace_event.h" |
17 #include "content/common/gpu/media/accelerated_video_decoder.h" | |
18 #include "content/common/gpu/media/h264_decoder.h" | |
19 #include "content/common/gpu/media/vaapi_picture.h" | |
20 #include "content/common/gpu/media/vp8_decoder.h" | |
21 #include "content/common/gpu/media/vp9_decoder.h" | |
22 #include "gpu/ipc/service/gpu_channel.h" | 17 #include "gpu/ipc/service/gpu_channel.h" |
23 #include "media/base/bind_to_current_loop.h" | 18 #include "media/base/bind_to_current_loop.h" |
19 #include "media/gpu/accelerated_video_decoder.h" | |
20 #include "media/gpu/h264_decoder.h" | |
21 #include "media/gpu/vaapi_picture.h" | |
22 #include "media/gpu/vp8_decoder.h" | |
23 #include "media/gpu/vp9_decoder.h" | |
24 #include "media/video/picture.h" | 24 #include "media/video/picture.h" |
25 #include "third_party/libva/va/va_dec_vp8.h" | 25 #include "third_party/libva/va/va_dec_vp8.h" |
26 #include "ui/gl/gl_bindings.h" | 26 #include "ui/gl/gl_bindings.h" |
27 #include "ui/gl/gl_image.h" | 27 #include "ui/gl/gl_image.h" |
28 | 28 |
29 namespace content { | 29 namespace media { |
30 | 30 |
31 namespace { | 31 namespace { |
32 // UMA errors that the VaapiVideoDecodeAccelerator class reports. | 32 // UMA errors that the VaapiVideoDecodeAccelerator class reports. |
33 enum VAVDADecoderFailure { | 33 enum VAVDADecoderFailure { |
34 VAAPI_ERROR = 0, | 34 VAAPI_ERROR = 0, |
35 // UMA requires that max must be greater than 1. | 35 VAVDA_DECODER_FAILURES_MAX, |
36 VAVDA_DECODER_FAILURES_MAX = 2, | |
37 }; | 36 }; |
38 } | 37 } |
39 | 38 |
40 static void ReportToUMA(VAVDADecoderFailure failure) { | 39 static void ReportToUMA(VAVDADecoderFailure failure) { |
41 UMA_HISTOGRAM_ENUMERATION("Media.VAVDA.DecoderFailure", failure, | 40 UMA_HISTOGRAM_ENUMERATION("Media.VAVDA.DecoderFailure", failure, |
42 VAVDA_DECODER_FAILURES_MAX); | 41 VAVDA_DECODER_FAILURES_MAX + 1); |
43 } | 42 } |
44 | 43 |
45 #define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \ | 44 #define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \ |
46 do { \ | 45 do { \ |
47 if (!(result)) { \ | 46 if (!(result)) { \ |
48 LOG(ERROR) << log; \ | 47 LOG(ERROR) << log; \ |
49 NotifyError(error_code); \ | 48 NotifyError(error_code); \ |
50 return ret; \ | 49 return ret; \ |
51 } \ | 50 } \ |
52 } while (0) | 51 } while (0) |
53 | 52 |
54 class VaapiVideoDecodeAccelerator::VaapiDecodeSurface | 53 class VaapiVideoDecodeAccelerator::VaapiDecodeSurface |
55 : public base::RefCountedThreadSafe<VaapiDecodeSurface> { | 54 : public base::RefCountedThreadSafe<VaapiDecodeSurface> { |
56 public: | 55 public: |
57 VaapiDecodeSurface(int32_t bitstream_id, | 56 VaapiDecodeSurface(int32_t bitstream_id, |
58 const scoped_refptr<VASurface>& va_surface); | 57 const scoped_refptr<VASurface>& va_surface); |
59 | 58 |
60 int32_t bitstream_id() const { return bitstream_id_; } | 59 int32_t bitstream_id() const { return bitstream_id_; } |
61 scoped_refptr<VASurface> va_surface() { return va_surface_; } | 60 scoped_refptr<VASurface> va_surface() { return va_surface_; } |
62 | 61 |
63 private: | 62 private: |
64 friend class base::RefCountedThreadSafe<VaapiDecodeSurface>; | 63 friend class base::RefCountedThreadSafe<VaapiDecodeSurface>; |
65 ~VaapiDecodeSurface(); | 64 ~VaapiDecodeSurface(); |
66 | 65 |
67 int32_t bitstream_id_; | 66 int32_t bitstream_id_; |
68 scoped_refptr<VASurface> va_surface_; | 67 scoped_refptr<VASurface> va_surface_; |
69 }; | 68 }; |
70 | 69 |
71 VaapiVideoDecodeAccelerator::VaapiDecodeSurface::VaapiDecodeSurface( | 70 VaapiVideoDecodeAccelerator::VaapiDecodeSurface::VaapiDecodeSurface( |
72 int32_t bitstream_id, | 71 int32_t bitstream_id, |
73 const scoped_refptr<VASurface>& va_surface) | 72 const scoped_refptr<VASurface>& va_surface) |
74 : bitstream_id_(bitstream_id), va_surface_(va_surface) {} | 73 : bitstream_id_(bitstream_id), va_surface_(va_surface) {} |
75 | 74 |
76 VaapiVideoDecodeAccelerator::VaapiDecodeSurface::~VaapiDecodeSurface() { | 75 VaapiVideoDecodeAccelerator::VaapiDecodeSurface::~VaapiDecodeSurface() {} |
77 } | |
78 | 76 |
79 class VaapiH264Picture : public H264Picture { | 77 class VaapiH264Picture : public H264Picture { |
80 public: | 78 public: |
81 VaapiH264Picture(const scoped_refptr< | 79 VaapiH264Picture( |
82 VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& dec_surface); | 80 const scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& |
81 dec_surface); | |
83 | 82 |
84 VaapiH264Picture* AsVaapiH264Picture() override { return this; } | 83 VaapiH264Picture* AsVaapiH264Picture() override { return this; } |
85 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface() { | 84 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface() { |
86 return dec_surface_; | 85 return dec_surface_; |
87 } | 86 } |
88 | 87 |
89 private: | 88 private: |
90 ~VaapiH264Picture() override; | 89 ~VaapiH264Picture() override; |
91 | 90 |
92 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface_; | 91 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface_; |
93 | 92 |
94 DISALLOW_COPY_AND_ASSIGN(VaapiH264Picture); | 93 DISALLOW_COPY_AND_ASSIGN(VaapiH264Picture); |
95 }; | 94 }; |
96 | 95 |
97 VaapiH264Picture::VaapiH264Picture(const scoped_refptr< | 96 VaapiH264Picture::VaapiH264Picture( |
98 VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& dec_surface) | 97 const scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& |
99 : dec_surface_(dec_surface) { | 98 dec_surface) |
100 } | 99 : dec_surface_(dec_surface) {} |
101 | 100 |
102 VaapiH264Picture::~VaapiH264Picture() { | 101 VaapiH264Picture::~VaapiH264Picture() {} |
103 } | |
104 | 102 |
105 class VaapiVideoDecodeAccelerator::VaapiH264Accelerator | 103 class VaapiVideoDecodeAccelerator::VaapiH264Accelerator |
106 : public H264Decoder::H264Accelerator { | 104 : public H264Decoder::H264Accelerator { |
107 public: | 105 public: |
108 VaapiH264Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec, | 106 VaapiH264Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec, |
109 VaapiWrapper* vaapi_wrapper); | 107 VaapiWrapper* vaapi_wrapper); |
110 ~VaapiH264Accelerator() override; | 108 ~VaapiH264Accelerator() override; |
111 | 109 |
112 // H264Decoder::H264Accelerator implementation. | 110 // H264Decoder::H264Accelerator implementation. |
113 scoped_refptr<H264Picture> CreateH264Picture() override; | 111 scoped_refptr<H264Picture> CreateH264Picture() override; |
(...skipping 29 matching lines...) Expand all Loading... | |
143 int num_pics); | 141 int num_pics); |
144 | 142 |
145 VaapiWrapper* vaapi_wrapper_; | 143 VaapiWrapper* vaapi_wrapper_; |
146 VaapiVideoDecodeAccelerator* vaapi_dec_; | 144 VaapiVideoDecodeAccelerator* vaapi_dec_; |
147 | 145 |
148 DISALLOW_COPY_AND_ASSIGN(VaapiH264Accelerator); | 146 DISALLOW_COPY_AND_ASSIGN(VaapiH264Accelerator); |
149 }; | 147 }; |
150 | 148 |
151 class VaapiVP8Picture : public VP8Picture { | 149 class VaapiVP8Picture : public VP8Picture { |
152 public: | 150 public: |
153 VaapiVP8Picture(const scoped_refptr< | 151 VaapiVP8Picture( |
154 VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& dec_surface); | 152 const scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& |
153 dec_surface); | |
155 | 154 |
156 VaapiVP8Picture* AsVaapiVP8Picture() override { return this; } | 155 VaapiVP8Picture* AsVaapiVP8Picture() override { return this; } |
157 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface() { | 156 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface() { |
158 return dec_surface_; | 157 return dec_surface_; |
159 } | 158 } |
160 | 159 |
161 private: | 160 private: |
162 ~VaapiVP8Picture() override; | 161 ~VaapiVP8Picture() override; |
163 | 162 |
164 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface_; | 163 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface_; |
165 | 164 |
166 DISALLOW_COPY_AND_ASSIGN(VaapiVP8Picture); | 165 DISALLOW_COPY_AND_ASSIGN(VaapiVP8Picture); |
167 }; | 166 }; |
168 | 167 |
169 VaapiVP8Picture::VaapiVP8Picture(const scoped_refptr< | 168 VaapiVP8Picture::VaapiVP8Picture( |
170 VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& dec_surface) | 169 const scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& |
171 : dec_surface_(dec_surface) { | 170 dec_surface) |
172 } | 171 : dec_surface_(dec_surface) {} |
173 | 172 |
174 VaapiVP8Picture::~VaapiVP8Picture() { | 173 VaapiVP8Picture::~VaapiVP8Picture() {} |
175 } | |
176 | 174 |
177 class VaapiVideoDecodeAccelerator::VaapiVP8Accelerator | 175 class VaapiVideoDecodeAccelerator::VaapiVP8Accelerator |
178 : public VP8Decoder::VP8Accelerator { | 176 : public VP8Decoder::VP8Accelerator { |
179 public: | 177 public: |
180 VaapiVP8Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec, | 178 VaapiVP8Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec, |
181 VaapiWrapper* vaapi_wrapper); | 179 VaapiWrapper* vaapi_wrapper); |
182 ~VaapiVP8Accelerator() override; | 180 ~VaapiVP8Accelerator() override; |
183 | 181 |
184 // VP8Decoder::VP8Accelerator implementation. | 182 // VP8Decoder::VP8Accelerator implementation. |
185 scoped_refptr<VP8Picture> CreateVP8Picture() override; | 183 scoped_refptr<VP8Picture> CreateVP8Picture() override; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 const scoped_refptr<VP9Picture>& pic); | 249 const scoped_refptr<VP9Picture>& pic); |
252 | 250 |
253 VaapiWrapper* vaapi_wrapper_; | 251 VaapiWrapper* vaapi_wrapper_; |
254 VaapiVideoDecodeAccelerator* vaapi_dec_; | 252 VaapiVideoDecodeAccelerator* vaapi_dec_; |
255 | 253 |
256 DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator); | 254 DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator); |
257 }; | 255 }; |
258 | 256 |
259 VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0) {} | 257 VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0) {} |
260 | 258 |
261 VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() { | 259 VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {} |
262 } | |
263 | 260 |
264 void VaapiVideoDecodeAccelerator::NotifyError(Error error) { | 261 void VaapiVideoDecodeAccelerator::NotifyError(Error error) { |
265 if (message_loop_ != base::MessageLoop::current()) { | 262 if (message_loop_ != base::MessageLoop::current()) { |
266 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 263 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
267 message_loop_->PostTask(FROM_HERE, base::Bind( | 264 message_loop_->PostTask( |
268 &VaapiVideoDecodeAccelerator::NotifyError, weak_this_, error)); | 265 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::NotifyError, |
266 weak_this_, error)); | |
269 return; | 267 return; |
270 } | 268 } |
271 | 269 |
272 // Post Cleanup() as a task so we don't recursively acquire lock_. | 270 // Post Cleanup() as a task so we don't recursively acquire lock_. |
273 message_loop_->PostTask(FROM_HERE, base::Bind( | 271 message_loop_->PostTask( |
274 &VaapiVideoDecodeAccelerator::Cleanup, weak_this_)); | 272 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::Cleanup, weak_this_)); |
275 | 273 |
276 LOG(ERROR) << "Notifying of error " << error; | 274 LOG(ERROR) << "Notifying of error " << error; |
277 if (client_) { | 275 if (client_) { |
278 client_->NotifyError(error); | 276 client_->NotifyError(error); |
279 client_ptr_factory_.reset(); | 277 client_ptr_factory_.reset(); |
280 } | 278 } |
281 } | 279 } |
282 | 280 |
283 VaapiPicture* VaapiVideoDecodeAccelerator::PictureById( | 281 VaapiPicture* VaapiVideoDecodeAccelerator::PictureById( |
284 int32_t picture_buffer_id) { | 282 int32_t picture_buffer_id) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
386 } | 384 } |
387 | 385 |
388 void VaapiVideoDecodeAccelerator::OutputPicture( | 386 void VaapiVideoDecodeAccelerator::OutputPicture( |
389 const scoped_refptr<VASurface>& va_surface, | 387 const scoped_refptr<VASurface>& va_surface, |
390 int32_t input_id, | 388 int32_t input_id, |
391 VaapiPicture* picture) { | 389 VaapiPicture* picture) { |
392 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 390 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
393 | 391 |
394 int32_t output_id = picture->picture_buffer_id(); | 392 int32_t output_id = picture->picture_buffer_id(); |
395 | 393 |
396 TRACE_EVENT2("Video Decoder", "VAVDA::OutputSurface", | 394 TRACE_EVENT2("Video Decoder", "VAVDA::OutputSurface", "input_id", input_id, |
397 "input_id", input_id, | |
398 "output_id", output_id); | 395 "output_id", output_id); |
399 | 396 |
400 DVLOG(3) << "Outputting VASurface " << va_surface->id() | 397 DVLOG(3) << "Outputting VASurface " << va_surface->id() |
401 << " into pixmap bound to picture buffer id " << output_id; | 398 << " into pixmap bound to picture buffer id " << output_id; |
402 | 399 |
403 RETURN_AND_NOTIFY_ON_FAILURE(picture->DownloadFromSurface(va_surface), | 400 RETURN_AND_NOTIFY_ON_FAILURE(picture->DownloadFromSurface(va_surface), |
404 "Failed putting surface into pixmap", | 401 "Failed putting surface into pixmap", |
405 PLATFORM_FAILURE, ); | 402 PLATFORM_FAILURE, ); |
406 | 403 |
407 // Notify the client a picture is ready to be displayed. | 404 // Notify the client a picture is ready to be displayed. |
408 ++num_frames_at_client_; | 405 ++num_frames_at_client_; |
409 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); | 406 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); |
410 DVLOG(4) << "Notifying output picture id " << output_id | 407 DVLOG(4) << "Notifying output picture id " << output_id << " for input " |
411 << " for input "<< input_id << " is ready"; | 408 << input_id << " is ready"; |
412 // TODO(posciak): Use visible size from decoder here instead | 409 // TODO(posciak): Use visible size from decoder here instead |
413 // (crbug.com/402760). Passing (0, 0) results in the client using the | 410 // (crbug.com/402760). Passing (0, 0) results in the client using the |
414 // visible size extracted from the container instead. | 411 // visible size extracted from the container instead. |
415 if (client_) | 412 if (client_) |
416 client_->PictureReady(media::Picture(output_id, input_id, | 413 client_->PictureReady(media::Picture(output_id, input_id, gfx::Rect(0, 0), |
417 gfx::Rect(0, 0), | |
418 picture->AllowOverlay())); | 414 picture->AllowOverlay())); |
419 } | 415 } |
420 | 416 |
421 void VaapiVideoDecodeAccelerator::TryOutputSurface() { | 417 void VaapiVideoDecodeAccelerator::TryOutputSurface() { |
422 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 418 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
423 | 419 |
424 // Handle Destroy() arriving while pictures are queued for output. | 420 // Handle Destroy() arriving while pictures are queued for output. |
425 if (!client_) | 421 if (!client_) |
426 return; | 422 return; |
427 | 423 |
(...skipping 10 matching lines...) Expand all Loading... | |
438 output_cb.Run(picture); | 434 output_cb.Run(picture); |
439 | 435 |
440 if (finish_flush_pending_ && pending_output_cbs_.empty()) | 436 if (finish_flush_pending_ && pending_output_cbs_.empty()) |
441 FinishFlush(); | 437 FinishFlush(); |
442 } | 438 } |
443 | 439 |
444 void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( | 440 void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( |
445 const media::BitstreamBuffer& bitstream_buffer) { | 441 const media::BitstreamBuffer& bitstream_buffer) { |
446 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 442 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
447 TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id", | 443 TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id", |
448 bitstream_buffer.id()); | 444 bitstream_buffer.id()); |
449 | 445 |
450 DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id() | 446 DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id() |
451 << " size: " << (int)bitstream_buffer.size(); | 447 << " size: " << (int)bitstream_buffer.size(); |
452 | 448 |
453 std::unique_ptr<SharedMemoryRegion> shm( | 449 std::unique_ptr<SharedMemoryRegion> shm( |
454 new SharedMemoryRegion(bitstream_buffer, true)); | 450 new SharedMemoryRegion(bitstream_buffer, true)); |
455 RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(), "Failed to map input buffer", | 451 RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(), "Failed to map input buffer", |
456 UNREADABLE_INPUT, ); | 452 UNREADABLE_INPUT, ); |
457 | 453 |
458 base::AutoLock auto_lock(lock_); | 454 base::AutoLock auto_lock(lock_); |
(...skipping 25 matching lines...) Expand all Loading... | |
484 } | 480 } |
485 | 481 |
486 // We could have got woken up in a different state or never got to sleep | 482 // We could have got woken up in a different state or never got to sleep |
487 // due to current state; check for that. | 483 // due to current state; check for that. |
488 switch (state_) { | 484 switch (state_) { |
489 case kFlushing: | 485 case kFlushing: |
490 // Here we are only interested in finishing up decoding buffers that are | 486 // Here we are only interested in finishing up decoding buffers that are |
491 // already queued up. Otherwise will stop decoding. | 487 // already queued up. Otherwise will stop decoding. |
492 if (input_buffers_.empty()) | 488 if (input_buffers_.empty()) |
493 return false; | 489 return false; |
494 // else fallthrough | 490 // else fallthrough |
Pawel Osciak
2016/04/19 09:22:55
Please keep the original indent.
Mark Dittmer
2016/05/02 03:51:24
Done.
| |
495 case kDecoding: | 491 case kDecoding: |
496 case kIdle: | 492 case kIdle: |
497 DCHECK(!input_buffers_.empty()); | 493 DCHECK(!input_buffers_.empty()); |
498 | 494 |
499 curr_input_buffer_ = input_buffers_.front(); | 495 curr_input_buffer_ = input_buffers_.front(); |
500 input_buffers_.pop(); | 496 input_buffers_.pop(); |
501 | 497 |
502 DVLOG(4) << "New current bitstream buffer, id: " << curr_input_buffer_->id | 498 DVLOG(4) << "New current bitstream buffer, id: " << curr_input_buffer_->id |
503 << " size: " << curr_input_buffer_->shm->size(); | 499 << " size: " << curr_input_buffer_->shm->size(); |
504 | 500 |
(...skipping 10 matching lines...) Expand all Loading... | |
515 } | 511 } |
516 | 512 |
517 void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() { | 513 void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() { |
518 lock_.AssertAcquired(); | 514 lock_.AssertAcquired(); |
519 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 515 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
520 DCHECK(curr_input_buffer_.get()); | 516 DCHECK(curr_input_buffer_.get()); |
521 | 517 |
522 int32_t id = curr_input_buffer_->id; | 518 int32_t id = curr_input_buffer_->id; |
523 curr_input_buffer_.reset(); | 519 curr_input_buffer_.reset(); |
524 DVLOG(4) << "End of input buffer " << id; | 520 DVLOG(4) << "End of input buffer " << id; |
525 message_loop_->PostTask(FROM_HERE, base::Bind( | 521 message_loop_->PostTask( |
526 &Client::NotifyEndOfBitstreamBuffer, client_, id)); | 522 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, id)); |
527 | 523 |
528 --num_stream_bufs_at_decoder_; | 524 --num_stream_bufs_at_decoder_; |
529 TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder", | 525 TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder", |
530 num_stream_bufs_at_decoder_); | 526 num_stream_bufs_at_decoder_); |
531 } | 527 } |
532 | 528 |
533 // TODO(posciak): refactor the whole class to remove sleeping in wait for | 529 // TODO(posciak): refactor the whole class to remove sleeping in wait for |
534 // surfaces, and reschedule DecodeTask instead. | 530 // surfaces, and reschedule DecodeTask instead. |
535 bool VaapiVideoDecodeAccelerator::WaitForSurfaces_Locked() { | 531 bool VaapiVideoDecodeAccelerator::WaitForSurfaces_Locked() { |
536 lock_.AssertAcquired(); | 532 lock_.AssertAcquired(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
570 // This is the main decode function of the decoder and while keeping | 566 // This is the main decode function of the decoder and while keeping |
571 // the lock for its duration would be fine, it would defeat the purpose | 567 // the lock for its duration would be fine, it would defeat the purpose |
572 // of having a separate decoder thread. | 568 // of having a separate decoder thread. |
573 base::AutoUnlock auto_unlock(lock_); | 569 base::AutoUnlock auto_unlock(lock_); |
574 res = decoder_->Decode(); | 570 res = decoder_->Decode(); |
575 } | 571 } |
576 | 572 |
577 switch (res) { | 573 switch (res) { |
578 case AcceleratedVideoDecoder::kAllocateNewSurfaces: | 574 case AcceleratedVideoDecoder::kAllocateNewSurfaces: |
579 DVLOG(1) << "Decoder requesting a new set of surfaces"; | 575 DVLOG(1) << "Decoder requesting a new set of surfaces"; |
580 message_loop_->PostTask(FROM_HERE, base::Bind( | 576 message_loop_->PostTask( |
581 &VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange, weak_this_, | 577 FROM_HERE, |
582 decoder_->GetRequiredNumOfPictures(), | 578 base::Bind(&VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange, |
583 decoder_->GetPicSize())); | 579 weak_this_, decoder_->GetRequiredNumOfPictures(), |
580 decoder_->GetPicSize())); | |
584 // We'll get rescheduled once ProvidePictureBuffers() finishes. | 581 // We'll get rescheduled once ProvidePictureBuffers() finishes. |
585 return; | 582 return; |
586 | 583 |
587 case AcceleratedVideoDecoder::kRanOutOfStreamData: | 584 case AcceleratedVideoDecoder::kRanOutOfStreamData: |
588 ReturnCurrInputBuffer_Locked(); | 585 ReturnCurrInputBuffer_Locked(); |
589 break; | 586 break; |
590 | 587 |
591 case AcceleratedVideoDecoder::kRanOutOfSurfaces: | 588 case AcceleratedVideoDecoder::kRanOutOfSurfaces: |
592 // No more output buffers in the decoder, try getting more or go to | 589 // No more output buffers in the decoder, try getting more or go to |
593 // sleep waiting for them. | 590 // sleep waiting for them. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
632 | 629 |
633 if (!pending_output_cbs_.empty() || | 630 if (!pending_output_cbs_.empty() || |
634 pictures_.size() != available_va_surfaces_.size()) { | 631 pictures_.size() != available_va_surfaces_.size()) { |
635 // Either: | 632 // Either: |
636 // 1. Not all pending pending output callbacks have been executed yet. | 633 // 1. Not all pending pending output callbacks have been executed yet. |
637 // Wait for the client to return enough pictures and retry later. | 634 // Wait for the client to return enough pictures and retry later. |
638 // 2. The above happened and all surface release callbacks have been posted | 635 // 2. The above happened and all surface release callbacks have been posted |
639 // as the result, but not all have executed yet. Post ourselves after them | 636 // as the result, but not all have executed yet. Post ourselves after them |
640 // to let them release surfaces. | 637 // to let them release surfaces. |
641 DVLOG(2) << "Awaiting pending output/surface release callbacks to finish"; | 638 DVLOG(2) << "Awaiting pending output/surface release callbacks to finish"; |
642 message_loop_->PostTask(FROM_HERE, base::Bind( | 639 message_loop_->PostTask( |
643 &VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange, weak_this_)); | 640 FROM_HERE, |
641 base::Bind(&VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange, | |
642 weak_this_)); | |
644 return; | 643 return; |
645 } | 644 } |
646 | 645 |
647 // All surfaces released, destroy them and dismiss all PictureBuffers. | 646 // All surfaces released, destroy them and dismiss all PictureBuffers. |
648 awaiting_va_surfaces_recycle_ = false; | 647 awaiting_va_surfaces_recycle_ = false; |
649 available_va_surfaces_.clear(); | 648 available_va_surfaces_.clear(); |
650 vaapi_wrapper_->DestroySurfaces(); | 649 vaapi_wrapper_->DestroySurfaces(); |
651 | 650 |
652 for (Pictures::iterator iter = pictures_.begin(); iter != pictures_.end(); | 651 for (Pictures::iterator iter = pictures_.begin(); iter != pictures_.end(); |
653 ++iter) { | 652 ++iter) { |
654 DVLOG(2) << "Dismissing picture id: " << iter->first; | 653 DVLOG(2) << "Dismissing picture id: " << iter->first; |
655 if (client_) | 654 if (client_) |
656 client_->DismissPictureBuffer(iter->first); | 655 client_->DismissPictureBuffer(iter->first); |
657 } | 656 } |
658 pictures_.clear(); | 657 pictures_.clear(); |
659 | 658 |
660 // And ask for a new set as requested. | 659 // And ask for a new set as requested. |
661 DVLOG(1) << "Requesting " << requested_num_pics_ << " pictures of size: " | 660 DVLOG(1) << "Requesting " << requested_num_pics_ |
662 << requested_pic_size_.ToString(); | 661 << " pictures of size: " << requested_pic_size_.ToString(); |
663 | 662 |
664 message_loop_->PostTask( | 663 message_loop_->PostTask( |
665 FROM_HERE, | 664 FROM_HERE, |
666 base::Bind(&Client::ProvidePictureBuffers, client_, requested_num_pics_, | 665 base::Bind(&Client::ProvidePictureBuffers, client_, requested_num_pics_, |
667 1, requested_pic_size_, VaapiPicture::GetGLTextureTarget())); | 666 1, requested_pic_size_, VaapiPicture::GetGLTextureTarget())); |
668 } | 667 } |
669 | 668 |
670 void VaapiVideoDecodeAccelerator::Decode( | 669 void VaapiVideoDecodeAccelerator::Decode( |
671 const media::BitstreamBuffer& bitstream_buffer) { | 670 const media::BitstreamBuffer& bitstream_buffer) { |
672 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 671 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
(...skipping 13 matching lines...) Expand all Loading... | |
686 base::AutoLock auto_lock(lock_); | 685 base::AutoLock auto_lock(lock_); |
687 switch (state_) { | 686 switch (state_) { |
688 case kIdle: | 687 case kIdle: |
689 state_ = kDecoding; | 688 state_ = kDecoding; |
690 decoder_thread_task_runner_->PostTask( | 689 decoder_thread_task_runner_->PostTask( |
691 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, | 690 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, |
692 base::Unretained(this))); | 691 base::Unretained(this))); |
693 break; | 692 break; |
694 | 693 |
695 case kDecoding: | 694 case kDecoding: |
696 // Decoder already running, fallthrough. | 695 // Decoder already running, fallthrough. |
697 case kResetting: | 696 case kResetting: |
698 // When resetting, allow accumulating bitstream buffers, so that | 697 // When resetting, allow accumulating bitstream buffers, so that |
699 // the client can queue after-seek-buffers while we are finishing with | 698 // the client can queue after-seek-buffers while we are finishing with |
700 // the before-seek one. | 699 // the before-seek one. |
701 break; | 700 break; |
702 | 701 |
703 default: | 702 default: |
704 RETURN_AND_NOTIFY_ON_FAILURE(false, | 703 RETURN_AND_NOTIFY_ON_FAILURE( |
705 "Decode request from client in invalid state: " << state_, | 704 false, "Decode request from client in invalid state: " << state_, |
706 PLATFORM_FAILURE, ); | 705 PLATFORM_FAILURE, ); |
707 break; | 706 break; |
708 } | 707 } |
709 } | 708 } |
710 | 709 |
711 void VaapiVideoDecodeAccelerator::RecycleVASurfaceID( | 710 void VaapiVideoDecodeAccelerator::RecycleVASurfaceID( |
712 VASurfaceID va_surface_id) { | 711 VASurfaceID va_surface_id) { |
713 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 712 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
714 base::AutoLock auto_lock(lock_); | 713 base::AutoLock auto_lock(lock_); |
715 | 714 |
716 available_va_surfaces_.push_back(va_surface_id); | 715 available_va_surfaces_.push_back(va_surface_id); |
717 surfaces_available_.Signal(); | 716 surfaces_available_.Signal(); |
718 } | 717 } |
719 | 718 |
720 void VaapiVideoDecodeAccelerator::AssignPictureBuffers( | 719 void VaapiVideoDecodeAccelerator::AssignPictureBuffers( |
721 const std::vector<media::PictureBuffer>& buffers) { | 720 const std::vector<media::PictureBuffer>& buffers) { |
722 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 721 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
723 | 722 |
724 base::AutoLock auto_lock(lock_); | 723 base::AutoLock auto_lock(lock_); |
725 DCHECK(pictures_.empty()); | 724 DCHECK(pictures_.empty()); |
726 | 725 |
727 while (!output_buffers_.empty()) | 726 while (!output_buffers_.empty()) |
728 output_buffers_.pop(); | 727 output_buffers_.pop(); |
729 | 728 |
730 RETURN_AND_NOTIFY_ON_FAILURE( | 729 RETURN_AND_NOTIFY_ON_FAILURE(buffers.size() >= requested_num_pics_, |
731 buffers.size() >= requested_num_pics_, | 730 "Got an invalid number of picture buffers. (Got " |
732 "Got an invalid number of picture buffers. (Got " << buffers.size() | 731 << buffers.size() << ", requested " |
733 << ", requested " << requested_num_pics_ << ")", INVALID_ARGUMENT, ); | 732 << requested_num_pics_ << ")", |
733 INVALID_ARGUMENT, ); | |
734 DCHECK(requested_pic_size_ == buffers[0].size()); | 734 DCHECK(requested_pic_size_ == buffers[0].size()); |
735 | 735 |
736 std::vector<VASurfaceID> va_surface_ids; | 736 std::vector<VASurfaceID> va_surface_ids; |
737 RETURN_AND_NOTIFY_ON_FAILURE( | 737 RETURN_AND_NOTIFY_ON_FAILURE( |
738 vaapi_wrapper_->CreateSurfaces(VA_RT_FORMAT_YUV420, requested_pic_size_, | 738 vaapi_wrapper_->CreateSurfaces(VA_RT_FORMAT_YUV420, requested_pic_size_, |
739 buffers.size(), &va_surface_ids), | 739 buffers.size(), &va_surface_ids), |
740 "Failed creating VA Surfaces", PLATFORM_FAILURE, ); | 740 "Failed creating VA Surfaces", PLATFORM_FAILURE, ); |
741 DCHECK_EQ(va_surface_ids.size(), buffers.size()); | 741 DCHECK_EQ(va_surface_ids.size(), buffers.size()); |
742 | 742 |
743 for (size_t i = 0; i < buffers.size(); ++i) { | 743 for (size_t i = 0; i < buffers.size(); ++i) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
797 | 797 |
798 // First flush all the pictures that haven't been outputted, notifying the | 798 // First flush all the pictures that haven't been outputted, notifying the |
799 // client to output them. | 799 // client to output them. |
800 bool res = decoder_->Flush(); | 800 bool res = decoder_->Flush(); |
801 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", | 801 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", |
802 PLATFORM_FAILURE, ); | 802 PLATFORM_FAILURE, ); |
803 | 803 |
804 // Put the decoder in idle state, ready to resume. | 804 // Put the decoder in idle state, ready to resume. |
805 decoder_->Reset(); | 805 decoder_->Reset(); |
806 | 806 |
807 message_loop_->PostTask(FROM_HERE, base::Bind( | 807 message_loop_->PostTask( |
808 &VaapiVideoDecodeAccelerator::FinishFlush, weak_this_)); | 808 FROM_HERE, |
809 base::Bind(&VaapiVideoDecodeAccelerator::FinishFlush, weak_this_)); | |
809 } | 810 } |
810 | 811 |
811 void VaapiVideoDecodeAccelerator::Flush() { | 812 void VaapiVideoDecodeAccelerator::Flush() { |
812 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 813 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
813 DVLOG(1) << "Got flush request"; | 814 DVLOG(1) << "Got flush request"; |
814 | 815 |
815 base::AutoLock auto_lock(lock_); | 816 base::AutoLock auto_lock(lock_); |
816 state_ = kFlushing; | 817 state_ = kFlushing; |
817 // Queue a flush task after all existing decoding tasks to clean up. | 818 // Queue a flush task after all existing decoding tasks to clean up. |
818 decoder_thread_task_runner_->PostTask( | 819 decoder_thread_task_runner_->PostTask( |
(...skipping 17 matching lines...) Expand all Loading... | |
836 | 837 |
837 // Still waiting for textures from client to finish outputting all pending | 838 // Still waiting for textures from client to finish outputting all pending |
838 // frames. Try again later. | 839 // frames. Try again later. |
839 if (!pending_output_cbs_.empty()) { | 840 if (!pending_output_cbs_.empty()) { |
840 finish_flush_pending_ = true; | 841 finish_flush_pending_ = true; |
841 return; | 842 return; |
842 } | 843 } |
843 | 844 |
844 state_ = kIdle; | 845 state_ = kIdle; |
845 | 846 |
846 message_loop_->PostTask(FROM_HERE, base::Bind( | 847 message_loop_->PostTask(FROM_HERE, |
847 &Client::NotifyFlushDone, client_)); | 848 base::Bind(&Client::NotifyFlushDone, client_)); |
848 | 849 |
849 DVLOG(1) << "Flush finished"; | 850 DVLOG(1) << "Flush finished"; |
850 } | 851 } |
851 | 852 |
852 void VaapiVideoDecodeAccelerator::ResetTask() { | 853 void VaapiVideoDecodeAccelerator::ResetTask() { |
853 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 854 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
854 DVLOG(1) << "ResetTask"; | 855 DVLOG(1) << "ResetTask"; |
855 | 856 |
856 // All the decoding tasks from before the reset request from client are done | 857 // All the decoding tasks from before the reset request from client are done |
857 // by now, as this task was scheduled after them and client is expected not | 858 // by now, as this task was scheduled after them and client is expected not |
858 // to call Decode() after Reset() and before NotifyResetDone. | 859 // to call Decode() after Reset() and before NotifyResetDone. |
859 decoder_->Reset(); | 860 decoder_->Reset(); |
860 | 861 |
861 base::AutoLock auto_lock(lock_); | 862 base::AutoLock auto_lock(lock_); |
862 | 863 |
863 // Return current input buffer, if present. | 864 // Return current input buffer, if present. |
864 if (curr_input_buffer_.get()) | 865 if (curr_input_buffer_.get()) |
865 ReturnCurrInputBuffer_Locked(); | 866 ReturnCurrInputBuffer_Locked(); |
866 | 867 |
867 // And let client know that we are done with reset. | 868 // And let client know that we are done with reset. |
868 message_loop_->PostTask(FROM_HERE, base::Bind( | 869 message_loop_->PostTask( |
869 &VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); | 870 FROM_HERE, |
871 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); | |
870 } | 872 } |
871 | 873 |
872 void VaapiVideoDecodeAccelerator::Reset() { | 874 void VaapiVideoDecodeAccelerator::Reset() { |
873 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 875 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
874 DVLOG(1) << "Got reset request"; | 876 DVLOG(1) << "Got reset request"; |
875 | 877 |
876 // This will make any new decode tasks exit early. | 878 // This will make any new decode tasks exit early. |
877 base::AutoLock auto_lock(lock_); | 879 base::AutoLock auto_lock(lock_); |
878 state_ = kResetting; | 880 state_ = kResetting; |
879 finish_flush_pending_ = false; | 881 finish_flush_pending_ = false; |
880 | 882 |
881 // Drop all remaining input buffers, if present. | 883 // Drop all remaining input buffers, if present. |
882 while (!input_buffers_.empty()) { | 884 while (!input_buffers_.empty()) { |
883 message_loop_->PostTask(FROM_HERE, base::Bind( | 885 message_loop_->PostTask( |
884 &Client::NotifyEndOfBitstreamBuffer, client_, | 886 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, |
885 input_buffers_.front()->id)); | 887 input_buffers_.front()->id)); |
886 input_buffers_.pop(); | 888 input_buffers_.pop(); |
887 } | 889 } |
888 | 890 |
889 decoder_thread_task_runner_->PostTask( | 891 decoder_thread_task_runner_->PostTask( |
890 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, | 892 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, |
891 base::Unretained(this))); | 893 base::Unretained(this))); |
892 | 894 |
893 input_ready_.Signal(); | 895 input_ready_.Signal(); |
894 surfaces_available_.Signal(); | 896 surfaces_available_.Signal(); |
895 } | 897 } |
896 | 898 |
897 void VaapiVideoDecodeAccelerator::FinishReset() { | 899 void VaapiVideoDecodeAccelerator::FinishReset() { |
898 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 900 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
899 DVLOG(1) << "FinishReset"; | 901 DVLOG(1) << "FinishReset"; |
900 base::AutoLock auto_lock(lock_); | 902 base::AutoLock auto_lock(lock_); |
901 | 903 |
902 if (state_ != kResetting) { | 904 if (state_ != kResetting) { |
903 DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_; | 905 DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_; |
904 return; // We could've gotten destroyed already. | 906 return; // We could've gotten destroyed already. |
905 } | 907 } |
906 | 908 |
907 // Drop pending outputs. | 909 // Drop pending outputs. |
908 while (!pending_output_cbs_.empty()) | 910 while (!pending_output_cbs_.empty()) |
909 pending_output_cbs_.pop(); | 911 pending_output_cbs_.pop(); |
910 | 912 |
911 if (awaiting_va_surfaces_recycle_) { | 913 if (awaiting_va_surfaces_recycle_) { |
912 // Decoder requested a new surface set while we were waiting for it to | 914 // Decoder requested a new surface set while we were waiting for it to |
913 // finish the last DecodeTask, running at the time of Reset(). | 915 // finish the last DecodeTask, running at the time of Reset(). |
914 // Let the surface set change finish first before resetting. | 916 // Let the surface set change finish first before resetting. |
915 message_loop_->PostTask(FROM_HERE, base::Bind( | 917 message_loop_->PostTask( |
916 &VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); | 918 FROM_HERE, |
919 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); | |
917 return; | 920 return; |
918 } | 921 } |
919 | 922 |
920 num_stream_bufs_at_decoder_ = 0; | 923 num_stream_bufs_at_decoder_ = 0; |
921 state_ = kIdle; | 924 state_ = kIdle; |
922 | 925 |
923 message_loop_->PostTask(FROM_HERE, base::Bind( | 926 message_loop_->PostTask(FROM_HERE, |
924 &Client::NotifyResetDone, client_)); | 927 base::Bind(&Client::NotifyResetDone, client_)); |
925 | 928 |
926 // The client might have given us new buffers via Decode() while we were | 929 // The client might have given us new buffers via Decode() while we were |
927 // resetting and might be waiting for our move, and not call Decode() anymore | 930 // resetting and might be waiting for our move, and not call Decode() anymore |
928 // until we return something. Post a DecodeTask() so that we won't | 931 // until we return something. Post a DecodeTask() so that we won't |
929 // sleep forever waiting for Decode() in that case. Having two of them | 932 // sleep forever waiting for Decode() in that case. Having two of them |
930 // in the pipe is harmless, the additional one will return as soon as it sees | 933 // in the pipe is harmless, the additional one will return as soon as it sees |
931 // that we are back in kDecoding state. | 934 // that we are back in kDecoding state. |
932 if (!input_buffers_.empty()) { | 935 if (!input_buffers_.empty()) { |
933 state_ = kDecoding; | 936 state_ = kDecoding; |
934 decoder_thread_task_runner_->PostTask( | 937 decoder_thread_task_runner_->PostTask( |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1034 } | 1037 } |
1035 | 1038 |
1036 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::VaapiH264Accelerator( | 1039 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::VaapiH264Accelerator( |
1037 VaapiVideoDecodeAccelerator* vaapi_dec, | 1040 VaapiVideoDecodeAccelerator* vaapi_dec, |
1038 VaapiWrapper* vaapi_wrapper) | 1041 VaapiWrapper* vaapi_wrapper) |
1039 : vaapi_wrapper_(vaapi_wrapper), vaapi_dec_(vaapi_dec) { | 1042 : vaapi_wrapper_(vaapi_wrapper), vaapi_dec_(vaapi_dec) { |
1040 DCHECK(vaapi_wrapper_); | 1043 DCHECK(vaapi_wrapper_); |
1041 DCHECK(vaapi_dec_); | 1044 DCHECK(vaapi_dec_); |
1042 } | 1045 } |
1043 | 1046 |
1044 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::~VaapiH264Accelerator() { | 1047 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::~VaapiH264Accelerator() {} |
1045 } | |
1046 | 1048 |
1047 scoped_refptr<H264Picture> | 1049 scoped_refptr<H264Picture> |
1048 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::CreateH264Picture() { | 1050 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::CreateH264Picture() { |
1049 scoped_refptr<VaapiDecodeSurface> va_surface = vaapi_dec_->CreateSurface(); | 1051 scoped_refptr<VaapiDecodeSurface> va_surface = vaapi_dec_->CreateSurface(); |
1050 if (!va_surface) | 1052 if (!va_surface) |
1051 return nullptr; | 1053 return nullptr; |
1052 | 1054 |
1053 return new VaapiH264Picture(va_surface); | 1055 return new VaapiH264Picture(va_surface); |
1054 } | 1056 } |
1055 | 1057 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1134 for (int i = 0; i < 16; ++i) | 1136 for (int i = 0; i < 16; ++i) |
1135 InitVAPicture(&pic_param.ReferenceFrames[i]); | 1137 InitVAPicture(&pic_param.ReferenceFrames[i]); |
1136 | 1138 |
1137 // And fill it with picture info from DPB. | 1139 // And fill it with picture info from DPB. |
1138 FillVARefFramesFromDPB(dpb, pic_param.ReferenceFrames, | 1140 FillVARefFramesFromDPB(dpb, pic_param.ReferenceFrames, |
1139 arraysize(pic_param.ReferenceFrames)); | 1141 arraysize(pic_param.ReferenceFrames)); |
1140 | 1142 |
1141 pic_param.num_ref_frames = sps->max_num_ref_frames; | 1143 pic_param.num_ref_frames = sps->max_num_ref_frames; |
1142 | 1144 |
1143 if (!vaapi_wrapper_->SubmitBuffer(VAPictureParameterBufferType, | 1145 if (!vaapi_wrapper_->SubmitBuffer(VAPictureParameterBufferType, |
1144 sizeof(pic_param), | 1146 sizeof(pic_param), &pic_param)) |
1145 &pic_param)) | |
1146 return false; | 1147 return false; |
1147 | 1148 |
1148 VAIQMatrixBufferH264 iq_matrix_buf; | 1149 VAIQMatrixBufferH264 iq_matrix_buf; |
1149 memset(&iq_matrix_buf, 0, sizeof(iq_matrix_buf)); | 1150 memset(&iq_matrix_buf, 0, sizeof(iq_matrix_buf)); |
1150 | 1151 |
1151 if (pps->pic_scaling_matrix_present_flag) { | 1152 if (pps->pic_scaling_matrix_present_flag) { |
1152 for (int i = 0; i < 6; ++i) { | 1153 for (int i = 0; i < 6; ++i) { |
1153 for (int j = 0; j < 16; ++j) | 1154 for (int j = 0; j < 16; ++j) |
1154 iq_matrix_buf.ScalingList4x4[i][j] = pps->scaling_list4x4[i][j]; | 1155 iq_matrix_buf.ScalingList4x4[i][j] = pps->scaling_list4x4[i][j]; |
1155 } | 1156 } |
1156 | 1157 |
1157 for (int i = 0; i < 2; ++i) { | 1158 for (int i = 0; i < 2; ++i) { |
1158 for (int j = 0; j < 64; ++j) | 1159 for (int j = 0; j < 64; ++j) |
1159 iq_matrix_buf.ScalingList8x8[i][j] = pps->scaling_list8x8[i][j]; | 1160 iq_matrix_buf.ScalingList8x8[i][j] = pps->scaling_list8x8[i][j]; |
1160 } | 1161 } |
1161 } else { | 1162 } else { |
1162 for (int i = 0; i < 6; ++i) { | 1163 for (int i = 0; i < 6; ++i) { |
1163 for (int j = 0; j < 16; ++j) | 1164 for (int j = 0; j < 16; ++j) |
1164 iq_matrix_buf.ScalingList4x4[i][j] = sps->scaling_list4x4[i][j]; | 1165 iq_matrix_buf.ScalingList4x4[i][j] = sps->scaling_list4x4[i][j]; |
1165 } | 1166 } |
1166 | 1167 |
1167 for (int i = 0; i < 2; ++i) { | 1168 for (int i = 0; i < 2; ++i) { |
1168 for (int j = 0; j < 64; ++j) | 1169 for (int j = 0; j < 64; ++j) |
1169 iq_matrix_buf.ScalingList8x8[i][j] = sps->scaling_list8x8[i][j]; | 1170 iq_matrix_buf.ScalingList8x8[i][j] = sps->scaling_list8x8[i][j]; |
1170 } | 1171 } |
1171 } | 1172 } |
1172 | 1173 |
1173 return vaapi_wrapper_->SubmitBuffer(VAIQMatrixBufferType, | 1174 return vaapi_wrapper_->SubmitBuffer(VAIQMatrixBufferType, |
1174 sizeof(iq_matrix_buf), | 1175 sizeof(iq_matrix_buf), &iq_matrix_buf); |
1175 &iq_matrix_buf); | |
1176 } | 1176 } |
1177 | 1177 |
1178 bool VaapiVideoDecodeAccelerator::VaapiH264Accelerator::SubmitSlice( | 1178 bool VaapiVideoDecodeAccelerator::VaapiH264Accelerator::SubmitSlice( |
1179 const media::H264PPS* pps, | 1179 const media::H264PPS* pps, |
1180 const media::H264SliceHeader* slice_hdr, | 1180 const media::H264SliceHeader* slice_hdr, |
1181 const H264Picture::Vector& ref_pic_list0, | 1181 const H264Picture::Vector& ref_pic_list0, |
1182 const H264Picture::Vector& ref_pic_list1, | 1182 const H264Picture::Vector& ref_pic_list1, |
1183 const scoped_refptr<H264Picture>& pic, | 1183 const scoped_refptr<H264Picture>& pic, |
1184 const uint8_t* data, | 1184 const uint8_t* data, |
1185 size_t size) { | 1185 size_t size) { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1265 FillVAPicture(&slice_param.RefPicList0[i], ref_pic_list0[i]); | 1265 FillVAPicture(&slice_param.RefPicList0[i], ref_pic_list0[i]); |
1266 } | 1266 } |
1267 for (size_t i = 0; | 1267 for (size_t i = 0; |
1268 i < ref_pic_list1.size() && i < arraysize(slice_param.RefPicList1); | 1268 i < ref_pic_list1.size() && i < arraysize(slice_param.RefPicList1); |
1269 ++i) { | 1269 ++i) { |
1270 if (ref_pic_list1[i]) | 1270 if (ref_pic_list1[i]) |
1271 FillVAPicture(&slice_param.RefPicList1[i], ref_pic_list1[i]); | 1271 FillVAPicture(&slice_param.RefPicList1[i], ref_pic_list1[i]); |
1272 } | 1272 } |
1273 | 1273 |
1274 if (!vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType, | 1274 if (!vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType, |
1275 sizeof(slice_param), | 1275 sizeof(slice_param), &slice_param)) |
1276 &slice_param)) | |
1277 return false; | 1276 return false; |
1278 | 1277 |
1279 // Can't help it, blame libva... | 1278 // Can't help it, blame libva... |
1280 void* non_const_ptr = const_cast<uint8_t*>(data); | 1279 void* non_const_ptr = const_cast<uint8_t*>(data); |
1281 return vaapi_wrapper_->SubmitBuffer(VASliceDataBufferType, size, | 1280 return vaapi_wrapper_->SubmitBuffer(VASliceDataBufferType, size, |
1282 non_const_ptr); | 1281 non_const_ptr); |
1283 } | 1282 } |
1284 | 1283 |
1285 bool VaapiVideoDecodeAccelerator::VaapiH264Accelerator::SubmitDecode( | 1284 bool VaapiVideoDecodeAccelerator::VaapiH264Accelerator::SubmitDecode( |
1286 const scoped_refptr<H264Picture>& pic) { | 1285 const scoped_refptr<H264Picture>& pic) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1367 } | 1366 } |
1368 | 1367 |
1369 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::VaapiVP8Accelerator( | 1368 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::VaapiVP8Accelerator( |
1370 VaapiVideoDecodeAccelerator* vaapi_dec, | 1369 VaapiVideoDecodeAccelerator* vaapi_dec, |
1371 VaapiWrapper* vaapi_wrapper) | 1370 VaapiWrapper* vaapi_wrapper) |
1372 : vaapi_wrapper_(vaapi_wrapper), vaapi_dec_(vaapi_dec) { | 1371 : vaapi_wrapper_(vaapi_wrapper), vaapi_dec_(vaapi_dec) { |
1373 DCHECK(vaapi_wrapper_); | 1372 DCHECK(vaapi_wrapper_); |
1374 DCHECK(vaapi_dec_); | 1373 DCHECK(vaapi_dec_); |
1375 } | 1374 } |
1376 | 1375 |
1377 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::~VaapiVP8Accelerator() { | 1376 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::~VaapiVP8Accelerator() {} |
1378 } | |
1379 | 1377 |
1380 scoped_refptr<VP8Picture> | 1378 scoped_refptr<VP8Picture> |
1381 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::CreateVP8Picture() { | 1379 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::CreateVP8Picture() { |
1382 scoped_refptr<VaapiDecodeSurface> va_surface = vaapi_dec_->CreateSurface(); | 1380 scoped_refptr<VaapiDecodeSurface> va_surface = vaapi_dec_->CreateSurface(); |
1383 if (!va_surface) | 1381 if (!va_surface) |
1384 return nullptr; | 1382 return nullptr; |
1385 | 1383 |
1386 return new VaapiVP8Picture(va_surface); | 1384 return new VaapiVP8Picture(va_surface); |
1387 } | 1385 } |
1388 | 1386 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1423 "incorrect quantization matrix size"); | 1421 "incorrect quantization matrix size"); |
1424 iq_matrix_buf.quantization_index[i][0] = CLAMP_Q(q); | 1422 iq_matrix_buf.quantization_index[i][0] = CLAMP_Q(q); |
1425 iq_matrix_buf.quantization_index[i][1] = CLAMP_Q(q + quant_hdr.y_dc_delta); | 1423 iq_matrix_buf.quantization_index[i][1] = CLAMP_Q(q + quant_hdr.y_dc_delta); |
1426 iq_matrix_buf.quantization_index[i][2] = CLAMP_Q(q + quant_hdr.y2_dc_delta); | 1424 iq_matrix_buf.quantization_index[i][2] = CLAMP_Q(q + quant_hdr.y2_dc_delta); |
1427 iq_matrix_buf.quantization_index[i][3] = CLAMP_Q(q + quant_hdr.y2_ac_delta); | 1425 iq_matrix_buf.quantization_index[i][3] = CLAMP_Q(q + quant_hdr.y2_ac_delta); |
1428 iq_matrix_buf.quantization_index[i][4] = CLAMP_Q(q + quant_hdr.uv_dc_delta); | 1426 iq_matrix_buf.quantization_index[i][4] = CLAMP_Q(q + quant_hdr.uv_dc_delta); |
1429 iq_matrix_buf.quantization_index[i][5] = CLAMP_Q(q + quant_hdr.uv_ac_delta); | 1427 iq_matrix_buf.quantization_index[i][5] = CLAMP_Q(q + quant_hdr.uv_ac_delta); |
1430 #undef CLAMP_Q | 1428 #undef CLAMP_Q |
1431 } | 1429 } |
1432 | 1430 |
1433 if (!vaapi_wrapper_->SubmitBuffer(VAIQMatrixBufferType, | 1431 if (!vaapi_wrapper_->SubmitBuffer( |
1434 sizeof(VAIQMatrixBufferVP8), | 1432 VAIQMatrixBufferType, sizeof(VAIQMatrixBufferVP8), &iq_matrix_buf)) |
1435 &iq_matrix_buf)) | |
1436 return false; | 1433 return false; |
1437 | 1434 |
1438 VAProbabilityDataBufferVP8 prob_buf; | 1435 VAProbabilityDataBufferVP8 prob_buf; |
1439 memset(&prob_buf, 0, sizeof(VAProbabilityDataBufferVP8)); | 1436 memset(&prob_buf, 0, sizeof(VAProbabilityDataBufferVP8)); |
1440 | 1437 |
1441 const media::Vp8EntropyHeader& entr_hdr = frame_hdr->entropy_hdr; | 1438 const media::Vp8EntropyHeader& entr_hdr = frame_hdr->entropy_hdr; |
1442 ARRAY_MEMCPY_CHECKED(prob_buf.dct_coeff_probs, entr_hdr.coeff_probs); | 1439 ARRAY_MEMCPY_CHECKED(prob_buf.dct_coeff_probs, entr_hdr.coeff_probs); |
1443 | 1440 |
1444 if (!vaapi_wrapper_->SubmitBuffer(VAProbabilityBufferType, | 1441 if (!vaapi_wrapper_->SubmitBuffer(VAProbabilityBufferType, |
1445 sizeof(VAProbabilityDataBufferVP8), | 1442 sizeof(VAProbabilityDataBufferVP8), |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1510 lf_level = sgmnt_hdr.lf_update_value[i]; | 1507 lf_level = sgmnt_hdr.lf_update_value[i]; |
1511 else | 1508 else |
1512 lf_level += sgmnt_hdr.lf_update_value[i]; | 1509 lf_level += sgmnt_hdr.lf_update_value[i]; |
1513 } | 1510 } |
1514 | 1511 |
1515 // Clamp to [0..63] range. | 1512 // Clamp to [0..63] range. |
1516 lf_level = std::min(std::max(lf_level, 0), 63); | 1513 lf_level = std::min(std::max(lf_level, 0), 63); |
1517 pic_param.loop_filter_level[i] = lf_level; | 1514 pic_param.loop_filter_level[i] = lf_level; |
1518 } | 1515 } |
1519 | 1516 |
1520 static_assert(arraysize(lf_hdr.ref_frame_delta) == | 1517 static_assert( |
1521 arraysize(pic_param.loop_filter_deltas_ref_frame) && | 1518 arraysize(lf_hdr.ref_frame_delta) == |
1522 arraysize(lf_hdr.mb_mode_delta) == | 1519 arraysize(pic_param.loop_filter_deltas_ref_frame) && |
1523 arraysize(pic_param.loop_filter_deltas_mode) && | 1520 arraysize(lf_hdr.mb_mode_delta) == |
1524 arraysize(lf_hdr.ref_frame_delta) == | 1521 arraysize(pic_param.loop_filter_deltas_mode) && |
1525 arraysize(lf_hdr.mb_mode_delta), | 1522 arraysize(lf_hdr.ref_frame_delta) == arraysize(lf_hdr.mb_mode_delta), |
1526 "loop filter deltas arrays size mismatch"); | 1523 "loop filter deltas arrays size mismatch"); |
1527 for (size_t i = 0; i < arraysize(lf_hdr.ref_frame_delta); ++i) { | 1524 for (size_t i = 0; i < arraysize(lf_hdr.ref_frame_delta); ++i) { |
1528 pic_param.loop_filter_deltas_ref_frame[i] = lf_hdr.ref_frame_delta[i]; | 1525 pic_param.loop_filter_deltas_ref_frame[i] = lf_hdr.ref_frame_delta[i]; |
1529 pic_param.loop_filter_deltas_mode[i] = lf_hdr.mb_mode_delta[i]; | 1526 pic_param.loop_filter_deltas_mode[i] = lf_hdr.mb_mode_delta[i]; |
1530 } | 1527 } |
1531 | 1528 |
1532 #define FHDR_TO_PP(a) pic_param.a = frame_hdr->a | 1529 #define FHDR_TO_PP(a) pic_param.a = frame_hdr->a |
1533 FHDR_TO_PP(prob_skip_false); | 1530 FHDR_TO_PP(prob_skip_false); |
1534 FHDR_TO_PP(prob_intra); | 1531 FHDR_TO_PP(prob_intra); |
1535 FHDR_TO_PP(prob_last); | 1532 FHDR_TO_PP(prob_last); |
1536 FHDR_TO_PP(prob_gf); | 1533 FHDR_TO_PP(prob_gf); |
(...skipping 28 matching lines...) Expand all Loading... | |
1565 for (size_t i = 0; i < frame_hdr->num_of_dct_partitions; ++i) | 1562 for (size_t i = 0; i < frame_hdr->num_of_dct_partitions; ++i) |
1566 slice_param.partition_size[i + 1] = frame_hdr->dct_partition_sizes[i]; | 1563 slice_param.partition_size[i + 1] = frame_hdr->dct_partition_sizes[i]; |
1567 | 1564 |
1568 if (!vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType, | 1565 if (!vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType, |
1569 sizeof(VASliceParameterBufferVP8), | 1566 sizeof(VASliceParameterBufferVP8), |
1570 &slice_param)) | 1567 &slice_param)) |
1571 return false; | 1568 return false; |
1572 | 1569 |
1573 void* non_const_ptr = const_cast<uint8_t*>(frame_hdr->data); | 1570 void* non_const_ptr = const_cast<uint8_t*>(frame_hdr->data); |
1574 if (!vaapi_wrapper_->SubmitBuffer(VASliceDataBufferType, | 1571 if (!vaapi_wrapper_->SubmitBuffer(VASliceDataBufferType, |
1575 frame_hdr->frame_size, | 1572 frame_hdr->frame_size, non_const_ptr)) |
1576 non_const_ptr)) | |
1577 return false; | 1573 return false; |
1578 | 1574 |
1579 scoped_refptr<VaapiDecodeSurface> dec_surface = | 1575 scoped_refptr<VaapiDecodeSurface> dec_surface = |
1580 VP8PictureToVaapiDecodeSurface(pic); | 1576 VP8PictureToVaapiDecodeSurface(pic); |
1581 | 1577 |
1582 return vaapi_dec_->DecodeSurface(dec_surface); | 1578 return vaapi_dec_->DecodeSurface(dec_surface); |
1583 } | 1579 } |
1584 | 1580 |
1585 bool VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::OutputPicture( | 1581 bool VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::OutputPicture( |
1586 const scoped_refptr<VP8Picture>& pic) { | 1582 const scoped_refptr<VP8Picture>& pic) { |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1754 CHECK(vaapi_pic); | 1750 CHECK(vaapi_pic); |
1755 return vaapi_pic->dec_surface(); | 1751 return vaapi_pic->dec_surface(); |
1756 } | 1752 } |
1757 | 1753 |
1758 // static | 1754 // static |
1759 media::VideoDecodeAccelerator::SupportedProfiles | 1755 media::VideoDecodeAccelerator::SupportedProfiles |
1760 VaapiVideoDecodeAccelerator::GetSupportedProfiles() { | 1756 VaapiVideoDecodeAccelerator::GetSupportedProfiles() { |
1761 return VaapiWrapper::GetSupportedDecodeProfiles(); | 1757 return VaapiWrapper::GetSupportedDecodeProfiles(); |
1762 } | 1758 } |
1763 | 1759 |
1764 } // namespace content | 1760 } // namespace media |
OLD | NEW |