| 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 <memory> | 9 #include <memory> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 17 #include "base/synchronization/waitable_event.h" | 17 #include "base/synchronization/waitable_event.h" |
| 18 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" |
| 19 #include "content/common/gpu/media/accelerated_video_decoder.h" | |
| 20 #include "content/common/gpu/media/h264_decoder.h" | |
| 21 #include "content/common/gpu/media/vaapi_picture.h" | |
| 22 #include "content/common/gpu/media/vp8_decoder.h" | |
| 23 #include "content/common/gpu/media/vp9_decoder.h" | |
| 24 #include "gpu/ipc/service/gpu_channel.h" | 19 #include "gpu/ipc/service/gpu_channel.h" |
| 25 #include "media/base/bind_to_current_loop.h" | 20 #include "media/base/bind_to_current_loop.h" |
| 21 #include "media/gpu/accelerated_video_decoder.h" |
| 22 #include "media/gpu/h264_decoder.h" |
| 23 #include "media/gpu/vaapi_picture.h" |
| 24 #include "media/gpu/vp8_decoder.h" |
| 25 #include "media/gpu/vp9_decoder.h" |
| 26 #include "media/video/picture.h" | 26 #include "media/video/picture.h" |
| 27 #include "third_party/libva/va/va_dec_vp8.h" | 27 #include "third_party/libva/va/va_dec_vp8.h" |
| 28 #include "ui/gl/gl_bindings.h" | 28 #include "ui/gl/gl_bindings.h" |
| 29 #include "ui/gl/gl_image.h" | 29 #include "ui/gl/gl_image.h" |
| 30 | 30 |
| 31 namespace content { | 31 namespace media { |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 // UMA errors that the VaapiVideoDecodeAccelerator class reports. | 34 // UMA errors that the VaapiVideoDecodeAccelerator class reports. |
| 35 enum VAVDADecoderFailure { | 35 enum VAVDADecoderFailure { |
| 36 VAAPI_ERROR = 0, | 36 VAAPI_ERROR = 0, |
| 37 // UMA requires that max must be greater than 1. | 37 VAVDA_DECODER_FAILURES_MAX, |
| 38 VAVDA_DECODER_FAILURES_MAX = 2, | |
| 39 }; | 38 }; |
| 40 } | 39 } |
| 41 | 40 |
| 42 static void ReportToUMA(VAVDADecoderFailure failure) { | 41 static void ReportToUMA(VAVDADecoderFailure failure) { |
| 43 UMA_HISTOGRAM_ENUMERATION("Media.VAVDA.DecoderFailure", failure, | 42 UMA_HISTOGRAM_ENUMERATION("Media.VAVDA.DecoderFailure", failure, |
| 44 VAVDA_DECODER_FAILURES_MAX); | 43 VAVDA_DECODER_FAILURES_MAX + 1); |
| 45 } | 44 } |
| 46 | 45 |
| 47 #define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \ | 46 #define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \ |
| 48 do { \ | 47 do { \ |
| 49 if (!(result)) { \ | 48 if (!(result)) { \ |
| 50 LOG(ERROR) << log; \ | 49 LOG(ERROR) << log; \ |
| 51 NotifyError(error_code); \ | 50 NotifyError(error_code); \ |
| 52 return ret; \ | 51 return ret; \ |
| 53 } \ | 52 } \ |
| 54 } while (0) | 53 } while (0) |
| 55 | 54 |
| 56 class VaapiVideoDecodeAccelerator::VaapiDecodeSurface | 55 class VaapiVideoDecodeAccelerator::VaapiDecodeSurface |
| 57 : public base::RefCountedThreadSafe<VaapiDecodeSurface> { | 56 : public base::RefCountedThreadSafe<VaapiDecodeSurface> { |
| 58 public: | 57 public: |
| 59 VaapiDecodeSurface(int32_t bitstream_id, | 58 VaapiDecodeSurface(int32_t bitstream_id, |
| 60 const scoped_refptr<VASurface>& va_surface); | 59 const scoped_refptr<VASurface>& va_surface); |
| 61 | 60 |
| 62 int32_t bitstream_id() const { return bitstream_id_; } | 61 int32_t bitstream_id() const { return bitstream_id_; } |
| 63 scoped_refptr<VASurface> va_surface() { return va_surface_; } | 62 scoped_refptr<VASurface> va_surface() { return va_surface_; } |
| 64 | 63 |
| 65 private: | 64 private: |
| 66 friend class base::RefCountedThreadSafe<VaapiDecodeSurface>; | 65 friend class base::RefCountedThreadSafe<VaapiDecodeSurface>; |
| 67 ~VaapiDecodeSurface(); | 66 ~VaapiDecodeSurface(); |
| 68 | 67 |
| 69 int32_t bitstream_id_; | 68 int32_t bitstream_id_; |
| 70 scoped_refptr<VASurface> va_surface_; | 69 scoped_refptr<VASurface> va_surface_; |
| 71 }; | 70 }; |
| 72 | 71 |
| 73 VaapiVideoDecodeAccelerator::VaapiDecodeSurface::VaapiDecodeSurface( | 72 VaapiVideoDecodeAccelerator::VaapiDecodeSurface::VaapiDecodeSurface( |
| 74 int32_t bitstream_id, | 73 int32_t bitstream_id, |
| 75 const scoped_refptr<VASurface>& va_surface) | 74 const scoped_refptr<VASurface>& va_surface) |
| 76 : bitstream_id_(bitstream_id), va_surface_(va_surface) {} | 75 : bitstream_id_(bitstream_id), va_surface_(va_surface) {} |
| 77 | 76 |
| 78 VaapiVideoDecodeAccelerator::VaapiDecodeSurface::~VaapiDecodeSurface() { | 77 VaapiVideoDecodeAccelerator::VaapiDecodeSurface::~VaapiDecodeSurface() {} |
| 79 } | |
| 80 | 78 |
| 81 class VaapiH264Picture : public H264Picture { | 79 class VaapiH264Picture : public H264Picture { |
| 82 public: | 80 public: |
| 83 VaapiH264Picture(const scoped_refptr< | 81 VaapiH264Picture( |
| 84 VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& dec_surface); | 82 const scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& |
| 83 dec_surface); |
| 85 | 84 |
| 86 VaapiH264Picture* AsVaapiH264Picture() override { return this; } | 85 VaapiH264Picture* AsVaapiH264Picture() override { return this; } |
| 87 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface() { | 86 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface() { |
| 88 return dec_surface_; | 87 return dec_surface_; |
| 89 } | 88 } |
| 90 | 89 |
| 91 private: | 90 private: |
| 92 ~VaapiH264Picture() override; | 91 ~VaapiH264Picture() override; |
| 93 | 92 |
| 94 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface_; | 93 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface_; |
| 95 | 94 |
| 96 DISALLOW_COPY_AND_ASSIGN(VaapiH264Picture); | 95 DISALLOW_COPY_AND_ASSIGN(VaapiH264Picture); |
| 97 }; | 96 }; |
| 98 | 97 |
| 99 VaapiH264Picture::VaapiH264Picture(const scoped_refptr< | 98 VaapiH264Picture::VaapiH264Picture( |
| 100 VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& dec_surface) | 99 const scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& |
| 101 : dec_surface_(dec_surface) { | 100 dec_surface) |
| 102 } | 101 : dec_surface_(dec_surface) {} |
| 103 | 102 |
| 104 VaapiH264Picture::~VaapiH264Picture() { | 103 VaapiH264Picture::~VaapiH264Picture() {} |
| 105 } | |
| 106 | 104 |
| 107 class VaapiVideoDecodeAccelerator::VaapiH264Accelerator | 105 class VaapiVideoDecodeAccelerator::VaapiH264Accelerator |
| 108 : public H264Decoder::H264Accelerator { | 106 : public H264Decoder::H264Accelerator { |
| 109 public: | 107 public: |
| 110 VaapiH264Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec, | 108 VaapiH264Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec, |
| 111 VaapiWrapper* vaapi_wrapper); | 109 VaapiWrapper* vaapi_wrapper); |
| 112 ~VaapiH264Accelerator() override; | 110 ~VaapiH264Accelerator() override; |
| 113 | 111 |
| 114 // H264Decoder::H264Accelerator implementation. | 112 // H264Decoder::H264Accelerator implementation. |
| 115 scoped_refptr<H264Picture> CreateH264Picture() override; | 113 scoped_refptr<H264Picture> CreateH264Picture() override; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 145 int num_pics); | 143 int num_pics); |
| 146 | 144 |
| 147 VaapiWrapper* vaapi_wrapper_; | 145 VaapiWrapper* vaapi_wrapper_; |
| 148 VaapiVideoDecodeAccelerator* vaapi_dec_; | 146 VaapiVideoDecodeAccelerator* vaapi_dec_; |
| 149 | 147 |
| 150 DISALLOW_COPY_AND_ASSIGN(VaapiH264Accelerator); | 148 DISALLOW_COPY_AND_ASSIGN(VaapiH264Accelerator); |
| 151 }; | 149 }; |
| 152 | 150 |
| 153 class VaapiVP8Picture : public VP8Picture { | 151 class VaapiVP8Picture : public VP8Picture { |
| 154 public: | 152 public: |
| 155 VaapiVP8Picture(const scoped_refptr< | 153 VaapiVP8Picture( |
| 156 VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& dec_surface); | 154 const scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& |
| 155 dec_surface); |
| 157 | 156 |
| 158 VaapiVP8Picture* AsVaapiVP8Picture() override { return this; } | 157 VaapiVP8Picture* AsVaapiVP8Picture() override { return this; } |
| 159 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface() { | 158 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface() { |
| 160 return dec_surface_; | 159 return dec_surface_; |
| 161 } | 160 } |
| 162 | 161 |
| 163 private: | 162 private: |
| 164 ~VaapiVP8Picture() override; | 163 ~VaapiVP8Picture() override; |
| 165 | 164 |
| 166 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface_; | 165 scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface> dec_surface_; |
| 167 | 166 |
| 168 DISALLOW_COPY_AND_ASSIGN(VaapiVP8Picture); | 167 DISALLOW_COPY_AND_ASSIGN(VaapiVP8Picture); |
| 169 }; | 168 }; |
| 170 | 169 |
| 171 VaapiVP8Picture::VaapiVP8Picture(const scoped_refptr< | 170 VaapiVP8Picture::VaapiVP8Picture( |
| 172 VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& dec_surface) | 171 const scoped_refptr<VaapiVideoDecodeAccelerator::VaapiDecodeSurface>& |
| 173 : dec_surface_(dec_surface) { | 172 dec_surface) |
| 174 } | 173 : dec_surface_(dec_surface) {} |
| 175 | 174 |
| 176 VaapiVP8Picture::~VaapiVP8Picture() { | 175 VaapiVP8Picture::~VaapiVP8Picture() {} |
| 177 } | |
| 178 | 176 |
| 179 class VaapiVideoDecodeAccelerator::VaapiVP8Accelerator | 177 class VaapiVideoDecodeAccelerator::VaapiVP8Accelerator |
| 180 : public VP8Decoder::VP8Accelerator { | 178 : public VP8Decoder::VP8Accelerator { |
| 181 public: | 179 public: |
| 182 VaapiVP8Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec, | 180 VaapiVP8Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec, |
| 183 VaapiWrapper* vaapi_wrapper); | 181 VaapiWrapper* vaapi_wrapper); |
| 184 ~VaapiVP8Accelerator() override; | 182 ~VaapiVP8Accelerator() override; |
| 185 | 183 |
| 186 // VP8Decoder::VP8Accelerator implementation. | 184 // VP8Decoder::VP8Accelerator implementation. |
| 187 scoped_refptr<VP8Picture> CreateVP8Picture() override; | 185 scoped_refptr<VP8Picture> CreateVP8Picture() override; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 const scoped_refptr<VP9Picture>& pic); | 251 const scoped_refptr<VP9Picture>& pic); |
| 254 | 252 |
| 255 VaapiWrapper* vaapi_wrapper_; | 253 VaapiWrapper* vaapi_wrapper_; |
| 256 VaapiVideoDecodeAccelerator* vaapi_dec_; | 254 VaapiVideoDecodeAccelerator* vaapi_dec_; |
| 257 | 255 |
| 258 DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator); | 256 DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator); |
| 259 }; | 257 }; |
| 260 | 258 |
| 261 VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0) {} | 259 VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0) {} |
| 262 | 260 |
| 263 VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() { | 261 VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {} |
| 264 } | |
| 265 | 262 |
| 266 void VaapiVideoDecodeAccelerator::NotifyError(Error error) { | 263 void VaapiVideoDecodeAccelerator::NotifyError(Error error) { |
| 267 if (message_loop_ != base::MessageLoop::current()) { | 264 if (message_loop_ != base::MessageLoop::current()) { |
| 268 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 265 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 269 message_loop_->PostTask(FROM_HERE, base::Bind( | 266 message_loop_->PostTask( |
| 270 &VaapiVideoDecodeAccelerator::NotifyError, weak_this_, error)); | 267 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::NotifyError, |
| 268 weak_this_, error)); |
| 271 return; | 269 return; |
| 272 } | 270 } |
| 273 | 271 |
| 274 // Post Cleanup() as a task so we don't recursively acquire lock_. | 272 // Post Cleanup() as a task so we don't recursively acquire lock_. |
| 275 message_loop_->PostTask(FROM_HERE, base::Bind( | 273 message_loop_->PostTask( |
| 276 &VaapiVideoDecodeAccelerator::Cleanup, weak_this_)); | 274 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::Cleanup, weak_this_)); |
| 277 | 275 |
| 278 LOG(ERROR) << "Notifying of error " << error; | 276 LOG(ERROR) << "Notifying of error " << error; |
| 279 if (client_) { | 277 if (client_) { |
| 280 client_->NotifyError(error); | 278 client_->NotifyError(error); |
| 281 client_ptr_factory_.reset(); | 279 client_ptr_factory_.reset(); |
| 282 } | 280 } |
| 283 } | 281 } |
| 284 | 282 |
| 285 VaapiPicture* VaapiVideoDecodeAccelerator::PictureById( | 283 VaapiPicture* VaapiVideoDecodeAccelerator::PictureById( |
| 286 int32_t picture_buffer_id) { | 284 int32_t picture_buffer_id) { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 } | 391 } |
| 394 | 392 |
| 395 void VaapiVideoDecodeAccelerator::OutputPicture( | 393 void VaapiVideoDecodeAccelerator::OutputPicture( |
| 396 const scoped_refptr<VASurface>& va_surface, | 394 const scoped_refptr<VASurface>& va_surface, |
| 397 int32_t input_id, | 395 int32_t input_id, |
| 398 VaapiPicture* picture) { | 396 VaapiPicture* picture) { |
| 399 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 397 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 400 | 398 |
| 401 int32_t output_id = picture->picture_buffer_id(); | 399 int32_t output_id = picture->picture_buffer_id(); |
| 402 | 400 |
| 403 TRACE_EVENT2("Video Decoder", "VAVDA::OutputSurface", | 401 TRACE_EVENT2("Video Decoder", "VAVDA::OutputSurface", "input_id", input_id, |
| 404 "input_id", input_id, | |
| 405 "output_id", output_id); | 402 "output_id", output_id); |
| 406 | 403 |
| 407 DVLOG(3) << "Outputting VASurface " << va_surface->id() | 404 DVLOG(3) << "Outputting VASurface " << va_surface->id() |
| 408 << " into pixmap bound to picture buffer id " << output_id; | 405 << " into pixmap bound to picture buffer id " << output_id; |
| 409 | 406 |
| 410 RETURN_AND_NOTIFY_ON_FAILURE(picture->DownloadFromSurface(va_surface), | 407 RETURN_AND_NOTIFY_ON_FAILURE(picture->DownloadFromSurface(va_surface), |
| 411 "Failed putting surface into pixmap", | 408 "Failed putting surface into pixmap", |
| 412 PLATFORM_FAILURE, ); | 409 PLATFORM_FAILURE, ); |
| 413 | 410 |
| 414 // Notify the client a picture is ready to be displayed. | 411 // Notify the client a picture is ready to be displayed. |
| 415 ++num_frames_at_client_; | 412 ++num_frames_at_client_; |
| 416 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); | 413 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); |
| 417 DVLOG(4) << "Notifying output picture id " << output_id | 414 DVLOG(4) << "Notifying output picture id " << output_id << " for input " |
| 418 << " for input "<< input_id << " is ready"; | 415 << input_id << " is ready"; |
| 419 // TODO(posciak): Use visible size from decoder here instead | 416 // TODO(posciak): Use visible size from decoder here instead |
| 420 // (crbug.com/402760). Passing (0, 0) results in the client using the | 417 // (crbug.com/402760). Passing (0, 0) results in the client using the |
| 421 // visible size extracted from the container instead. | 418 // visible size extracted from the container instead. |
| 422 if (client_) | 419 if (client_) |
| 423 client_->PictureReady(media::Picture(output_id, input_id, | 420 client_->PictureReady(media::Picture(output_id, input_id, gfx::Rect(0, 0), |
| 424 gfx::Rect(0, 0), | |
| 425 picture->AllowOverlay())); | 421 picture->AllowOverlay())); |
| 426 } | 422 } |
| 427 | 423 |
| 428 void VaapiVideoDecodeAccelerator::TryOutputSurface() { | 424 void VaapiVideoDecodeAccelerator::TryOutputSurface() { |
| 429 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 425 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 430 | 426 |
| 431 // Handle Destroy() arriving while pictures are queued for output. | 427 // Handle Destroy() arriving while pictures are queued for output. |
| 432 if (!client_) | 428 if (!client_) |
| 433 return; | 429 return; |
| 434 | 430 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 445 output_cb.Run(picture); | 441 output_cb.Run(picture); |
| 446 | 442 |
| 447 if (finish_flush_pending_ && pending_output_cbs_.empty()) | 443 if (finish_flush_pending_ && pending_output_cbs_.empty()) |
| 448 FinishFlush(); | 444 FinishFlush(); |
| 449 } | 445 } |
| 450 | 446 |
| 451 void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( | 447 void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( |
| 452 const media::BitstreamBuffer& bitstream_buffer) { | 448 const media::BitstreamBuffer& bitstream_buffer) { |
| 453 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 449 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 454 TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id", | 450 TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id", |
| 455 bitstream_buffer.id()); | 451 bitstream_buffer.id()); |
| 456 | 452 |
| 457 DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id() | 453 DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id() |
| 458 << " size: " << (int)bitstream_buffer.size(); | 454 << " size: " << (int)bitstream_buffer.size(); |
| 459 | 455 |
| 460 std::unique_ptr<SharedMemoryRegion> shm( | 456 std::unique_ptr<SharedMemoryRegion> shm( |
| 461 new SharedMemoryRegion(bitstream_buffer, true)); | 457 new SharedMemoryRegion(bitstream_buffer, true)); |
| 462 | 458 |
| 463 // Skip empty buffers. | 459 // Skip empty buffers. |
| 464 if (bitstream_buffer.size() == 0) { | 460 if (bitstream_buffer.size() == 0) { |
| 465 if (client_) | 461 if (client_) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 } | 495 } |
| 500 | 496 |
| 501 // We could have got woken up in a different state or never got to sleep | 497 // We could have got woken up in a different state or never got to sleep |
| 502 // due to current state; check for that. | 498 // due to current state; check for that. |
| 503 switch (state_) { | 499 switch (state_) { |
| 504 case kFlushing: | 500 case kFlushing: |
| 505 // Here we are only interested in finishing up decoding buffers that are | 501 // Here we are only interested in finishing up decoding buffers that are |
| 506 // already queued up. Otherwise will stop decoding. | 502 // already queued up. Otherwise will stop decoding. |
| 507 if (input_buffers_.empty()) | 503 if (input_buffers_.empty()) |
| 508 return false; | 504 return false; |
| 509 // else fallthrough | 505 // else fallthrough |
| 510 case kDecoding: | 506 case kDecoding: |
| 511 case kIdle: | 507 case kIdle: |
| 512 DCHECK(!input_buffers_.empty()); | 508 DCHECK(!input_buffers_.empty()); |
| 513 | 509 |
| 514 curr_input_buffer_ = input_buffers_.front(); | 510 curr_input_buffer_ = input_buffers_.front(); |
| 515 input_buffers_.pop(); | 511 input_buffers_.pop(); |
| 516 | 512 |
| 517 DVLOG(4) << "New current bitstream buffer, id: " << curr_input_buffer_->id | 513 DVLOG(4) << "New current bitstream buffer, id: " << curr_input_buffer_->id |
| 518 << " size: " << curr_input_buffer_->shm->size(); | 514 << " size: " << curr_input_buffer_->shm->size(); |
| 519 | 515 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 530 } | 526 } |
| 531 | 527 |
| 532 void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() { | 528 void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() { |
| 533 lock_.AssertAcquired(); | 529 lock_.AssertAcquired(); |
| 534 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 530 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 535 DCHECK(curr_input_buffer_.get()); | 531 DCHECK(curr_input_buffer_.get()); |
| 536 | 532 |
| 537 int32_t id = curr_input_buffer_->id; | 533 int32_t id = curr_input_buffer_->id; |
| 538 curr_input_buffer_.reset(); | 534 curr_input_buffer_.reset(); |
| 539 DVLOG(4) << "End of input buffer " << id; | 535 DVLOG(4) << "End of input buffer " << id; |
| 540 message_loop_->PostTask(FROM_HERE, base::Bind( | 536 message_loop_->PostTask( |
| 541 &Client::NotifyEndOfBitstreamBuffer, client_, id)); | 537 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, id)); |
| 542 | 538 |
| 543 --num_stream_bufs_at_decoder_; | 539 --num_stream_bufs_at_decoder_; |
| 544 TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder", | 540 TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder", |
| 545 num_stream_bufs_at_decoder_); | 541 num_stream_bufs_at_decoder_); |
| 546 } | 542 } |
| 547 | 543 |
| 548 // TODO(posciak): refactor the whole class to remove sleeping in wait for | 544 // TODO(posciak): refactor the whole class to remove sleeping in wait for |
| 549 // surfaces, and reschedule DecodeTask instead. | 545 // surfaces, and reschedule DecodeTask instead. |
| 550 bool VaapiVideoDecodeAccelerator::WaitForSurfaces_Locked() { | 546 bool VaapiVideoDecodeAccelerator::WaitForSurfaces_Locked() { |
| 551 lock_.AssertAcquired(); | 547 lock_.AssertAcquired(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 // This is the main decode function of the decoder and while keeping | 581 // This is the main decode function of the decoder and while keeping |
| 586 // the lock for its duration would be fine, it would defeat the purpose | 582 // the lock for its duration would be fine, it would defeat the purpose |
| 587 // of having a separate decoder thread. | 583 // of having a separate decoder thread. |
| 588 base::AutoUnlock auto_unlock(lock_); | 584 base::AutoUnlock auto_unlock(lock_); |
| 589 res = decoder_->Decode(); | 585 res = decoder_->Decode(); |
| 590 } | 586 } |
| 591 | 587 |
| 592 switch (res) { | 588 switch (res) { |
| 593 case AcceleratedVideoDecoder::kAllocateNewSurfaces: | 589 case AcceleratedVideoDecoder::kAllocateNewSurfaces: |
| 594 DVLOG(1) << "Decoder requesting a new set of surfaces"; | 590 DVLOG(1) << "Decoder requesting a new set of surfaces"; |
| 595 message_loop_->PostTask(FROM_HERE, base::Bind( | 591 message_loop_->PostTask( |
| 596 &VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange, weak_this_, | 592 FROM_HERE, |
| 597 decoder_->GetRequiredNumOfPictures(), | 593 base::Bind(&VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange, |
| 598 decoder_->GetPicSize())); | 594 weak_this_, decoder_->GetRequiredNumOfPictures(), |
| 595 decoder_->GetPicSize())); |
| 599 // We'll get rescheduled once ProvidePictureBuffers() finishes. | 596 // We'll get rescheduled once ProvidePictureBuffers() finishes. |
| 600 return; | 597 return; |
| 601 | 598 |
| 602 case AcceleratedVideoDecoder::kRanOutOfStreamData: | 599 case AcceleratedVideoDecoder::kRanOutOfStreamData: |
| 603 ReturnCurrInputBuffer_Locked(); | 600 ReturnCurrInputBuffer_Locked(); |
| 604 break; | 601 break; |
| 605 | 602 |
| 606 case AcceleratedVideoDecoder::kRanOutOfSurfaces: | 603 case AcceleratedVideoDecoder::kRanOutOfSurfaces: |
| 607 // No more output buffers in the decoder, try getting more or go to | 604 // No more output buffers in the decoder, try getting more or go to |
| 608 // sleep waiting for them. | 605 // sleep waiting for them. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 | 644 |
| 648 if (!pending_output_cbs_.empty() || | 645 if (!pending_output_cbs_.empty() || |
| 649 pictures_.size() != available_va_surfaces_.size()) { | 646 pictures_.size() != available_va_surfaces_.size()) { |
| 650 // Either: | 647 // Either: |
| 651 // 1. Not all pending pending output callbacks have been executed yet. | 648 // 1. Not all pending pending output callbacks have been executed yet. |
| 652 // Wait for the client to return enough pictures and retry later. | 649 // Wait for the client to return enough pictures and retry later. |
| 653 // 2. The above happened and all surface release callbacks have been posted | 650 // 2. The above happened and all surface release callbacks have been posted |
| 654 // as the result, but not all have executed yet. Post ourselves after them | 651 // as the result, but not all have executed yet. Post ourselves after them |
| 655 // to let them release surfaces. | 652 // to let them release surfaces. |
| 656 DVLOG(2) << "Awaiting pending output/surface release callbacks to finish"; | 653 DVLOG(2) << "Awaiting pending output/surface release callbacks to finish"; |
| 657 message_loop_->PostTask(FROM_HERE, base::Bind( | 654 message_loop_->PostTask( |
| 658 &VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange, weak_this_)); | 655 FROM_HERE, |
| 656 base::Bind(&VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange, |
| 657 weak_this_)); |
| 659 return; | 658 return; |
| 660 } | 659 } |
| 661 | 660 |
| 662 // All surfaces released, destroy them and dismiss all PictureBuffers. | 661 // All surfaces released, destroy them and dismiss all PictureBuffers. |
| 663 awaiting_va_surfaces_recycle_ = false; | 662 awaiting_va_surfaces_recycle_ = false; |
| 664 available_va_surfaces_.clear(); | 663 available_va_surfaces_.clear(); |
| 665 vaapi_wrapper_->DestroySurfaces(); | 664 vaapi_wrapper_->DestroySurfaces(); |
| 666 | 665 |
| 667 for (Pictures::iterator iter = pictures_.begin(); iter != pictures_.end(); | 666 for (Pictures::iterator iter = pictures_.begin(); iter != pictures_.end(); |
| 668 ++iter) { | 667 ++iter) { |
| 669 DVLOG(2) << "Dismissing picture id: " << iter->first; | 668 DVLOG(2) << "Dismissing picture id: " << iter->first; |
| 670 if (client_) | 669 if (client_) |
| 671 client_->DismissPictureBuffer(iter->first); | 670 client_->DismissPictureBuffer(iter->first); |
| 672 } | 671 } |
| 673 pictures_.clear(); | 672 pictures_.clear(); |
| 674 | 673 |
| 675 // And ask for a new set as requested. | 674 // And ask for a new set as requested. |
| 676 DVLOG(1) << "Requesting " << requested_num_pics_ << " pictures of size: " | 675 DVLOG(1) << "Requesting " << requested_num_pics_ |
| 677 << requested_pic_size_.ToString(); | 676 << " pictures of size: " << requested_pic_size_.ToString(); |
| 678 | 677 |
| 679 message_loop_->PostTask( | 678 message_loop_->PostTask( |
| 680 FROM_HERE, | 679 FROM_HERE, |
| 681 base::Bind(&Client::ProvidePictureBuffers, client_, requested_num_pics_, | 680 base::Bind(&Client::ProvidePictureBuffers, client_, requested_num_pics_, |
| 682 1, requested_pic_size_, VaapiPicture::GetGLTextureTarget())); | 681 1, requested_pic_size_, VaapiPicture::GetGLTextureTarget())); |
| 683 } | 682 } |
| 684 | 683 |
| 685 void VaapiVideoDecodeAccelerator::Decode( | 684 void VaapiVideoDecodeAccelerator::Decode( |
| 686 const media::BitstreamBuffer& bitstream_buffer) { | 685 const media::BitstreamBuffer& bitstream_buffer) { |
| 687 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 686 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 703 base::AutoLock auto_lock(lock_); | 702 base::AutoLock auto_lock(lock_); |
| 704 switch (state_) { | 703 switch (state_) { |
| 705 case kIdle: | 704 case kIdle: |
| 706 state_ = kDecoding; | 705 state_ = kDecoding; |
| 707 decoder_thread_task_runner_->PostTask( | 706 decoder_thread_task_runner_->PostTask( |
| 708 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, | 707 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, |
| 709 base::Unretained(this))); | 708 base::Unretained(this))); |
| 710 break; | 709 break; |
| 711 | 710 |
| 712 case kDecoding: | 711 case kDecoding: |
| 713 // Decoder already running, fallthrough. | 712 // Decoder already running, fallthrough. |
| 714 case kResetting: | 713 case kResetting: |
| 715 // When resetting, allow accumulating bitstream buffers, so that | 714 // When resetting, allow accumulating bitstream buffers, so that |
| 716 // the client can queue after-seek-buffers while we are finishing with | 715 // the client can queue after-seek-buffers while we are finishing with |
| 717 // the before-seek one. | 716 // the before-seek one. |
| 718 break; | 717 break; |
| 719 | 718 |
| 720 default: | 719 default: |
| 721 RETURN_AND_NOTIFY_ON_FAILURE(false, | 720 RETURN_AND_NOTIFY_ON_FAILURE( |
| 722 "Decode request from client in invalid state: " << state_, | 721 false, "Decode request from client in invalid state: " << state_, |
| 723 PLATFORM_FAILURE, ); | 722 PLATFORM_FAILURE, ); |
| 724 break; | 723 break; |
| 725 } | 724 } |
| 726 } | 725 } |
| 727 | 726 |
| 728 void VaapiVideoDecodeAccelerator::RecycleVASurfaceID( | 727 void VaapiVideoDecodeAccelerator::RecycleVASurfaceID( |
| 729 VASurfaceID va_surface_id) { | 728 VASurfaceID va_surface_id) { |
| 730 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 729 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 731 base::AutoLock auto_lock(lock_); | 730 base::AutoLock auto_lock(lock_); |
| 732 | 731 |
| 733 available_va_surfaces_.push_back(va_surface_id); | 732 available_va_surfaces_.push_back(va_surface_id); |
| 734 surfaces_available_.Signal(); | 733 surfaces_available_.Signal(); |
| 735 } | 734 } |
| 736 | 735 |
| 737 void VaapiVideoDecodeAccelerator::AssignPictureBuffers( | 736 void VaapiVideoDecodeAccelerator::AssignPictureBuffers( |
| 738 const std::vector<media::PictureBuffer>& buffers) { | 737 const std::vector<media::PictureBuffer>& buffers) { |
| 739 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 738 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 740 | 739 |
| 741 base::AutoLock auto_lock(lock_); | 740 base::AutoLock auto_lock(lock_); |
| 742 DCHECK(pictures_.empty()); | 741 DCHECK(pictures_.empty()); |
| 743 | 742 |
| 744 while (!output_buffers_.empty()) | 743 while (!output_buffers_.empty()) |
| 745 output_buffers_.pop(); | 744 output_buffers_.pop(); |
| 746 | 745 |
| 747 RETURN_AND_NOTIFY_ON_FAILURE( | 746 RETURN_AND_NOTIFY_ON_FAILURE(buffers.size() >= requested_num_pics_, |
| 748 buffers.size() >= requested_num_pics_, | 747 "Got an invalid number of picture buffers. (Got " |
| 749 "Got an invalid number of picture buffers. (Got " << buffers.size() | 748 << buffers.size() << ", requested " |
| 750 << ", requested " << requested_num_pics_ << ")", INVALID_ARGUMENT, ); | 749 << requested_num_pics_ << ")", |
| 750 INVALID_ARGUMENT, ); |
| 751 DCHECK(requested_pic_size_ == buffers[0].size()); | 751 DCHECK(requested_pic_size_ == buffers[0].size()); |
| 752 | 752 |
| 753 std::vector<VASurfaceID> va_surface_ids; | 753 std::vector<VASurfaceID> va_surface_ids; |
| 754 RETURN_AND_NOTIFY_ON_FAILURE( | 754 RETURN_AND_NOTIFY_ON_FAILURE( |
| 755 vaapi_wrapper_->CreateSurfaces(VA_RT_FORMAT_YUV420, requested_pic_size_, | 755 vaapi_wrapper_->CreateSurfaces(VA_RT_FORMAT_YUV420, requested_pic_size_, |
| 756 buffers.size(), &va_surface_ids), | 756 buffers.size(), &va_surface_ids), |
| 757 "Failed creating VA Surfaces", PLATFORM_FAILURE, ); | 757 "Failed creating VA Surfaces", PLATFORM_FAILURE, ); |
| 758 DCHECK_EQ(va_surface_ids.size(), buffers.size()); | 758 DCHECK_EQ(va_surface_ids.size(), buffers.size()); |
| 759 | 759 |
| 760 for (size_t i = 0; i < buffers.size(); ++i) { | 760 for (size_t i = 0; i < buffers.size(); ++i) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 | 813 |
| 814 // First flush all the pictures that haven't been outputted, notifying the | 814 // First flush all the pictures that haven't been outputted, notifying the |
| 815 // client to output them. | 815 // client to output them. |
| 816 bool res = decoder_->Flush(); | 816 bool res = decoder_->Flush(); |
| 817 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", | 817 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", |
| 818 PLATFORM_FAILURE, ); | 818 PLATFORM_FAILURE, ); |
| 819 | 819 |
| 820 // Put the decoder in idle state, ready to resume. | 820 // Put the decoder in idle state, ready to resume. |
| 821 decoder_->Reset(); | 821 decoder_->Reset(); |
| 822 | 822 |
| 823 message_loop_->PostTask(FROM_HERE, base::Bind( | 823 message_loop_->PostTask( |
| 824 &VaapiVideoDecodeAccelerator::FinishFlush, weak_this_)); | 824 FROM_HERE, |
| 825 base::Bind(&VaapiVideoDecodeAccelerator::FinishFlush, weak_this_)); |
| 825 } | 826 } |
| 826 | 827 |
| 827 void VaapiVideoDecodeAccelerator::Flush() { | 828 void VaapiVideoDecodeAccelerator::Flush() { |
| 828 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 829 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 829 DVLOG(1) << "Got flush request"; | 830 DVLOG(1) << "Got flush request"; |
| 830 | 831 |
| 831 base::AutoLock auto_lock(lock_); | 832 base::AutoLock auto_lock(lock_); |
| 832 state_ = kFlushing; | 833 state_ = kFlushing; |
| 833 // Queue a flush task after all existing decoding tasks to clean up. | 834 // Queue a flush task after all existing decoding tasks to clean up. |
| 834 decoder_thread_task_runner_->PostTask( | 835 decoder_thread_task_runner_->PostTask( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 852 | 853 |
| 853 // Still waiting for textures from client to finish outputting all pending | 854 // Still waiting for textures from client to finish outputting all pending |
| 854 // frames. Try again later. | 855 // frames. Try again later. |
| 855 if (!pending_output_cbs_.empty()) { | 856 if (!pending_output_cbs_.empty()) { |
| 856 finish_flush_pending_ = true; | 857 finish_flush_pending_ = true; |
| 857 return; | 858 return; |
| 858 } | 859 } |
| 859 | 860 |
| 860 state_ = kIdle; | 861 state_ = kIdle; |
| 861 | 862 |
| 862 message_loop_->PostTask(FROM_HERE, base::Bind( | 863 message_loop_->PostTask(FROM_HERE, |
| 863 &Client::NotifyFlushDone, client_)); | 864 base::Bind(&Client::NotifyFlushDone, client_)); |
| 864 | 865 |
| 865 DVLOG(1) << "Flush finished"; | 866 DVLOG(1) << "Flush finished"; |
| 866 } | 867 } |
| 867 | 868 |
| 868 void VaapiVideoDecodeAccelerator::ResetTask() { | 869 void VaapiVideoDecodeAccelerator::ResetTask() { |
| 869 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 870 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 870 DVLOG(1) << "ResetTask"; | 871 DVLOG(1) << "ResetTask"; |
| 871 | 872 |
| 872 // All the decoding tasks from before the reset request from client are done | 873 // All the decoding tasks from before the reset request from client are done |
| 873 // by now, as this task was scheduled after them and client is expected not | 874 // by now, as this task was scheduled after them and client is expected not |
| 874 // to call Decode() after Reset() and before NotifyResetDone. | 875 // to call Decode() after Reset() and before NotifyResetDone. |
| 875 decoder_->Reset(); | 876 decoder_->Reset(); |
| 876 | 877 |
| 877 base::AutoLock auto_lock(lock_); | 878 base::AutoLock auto_lock(lock_); |
| 878 | 879 |
| 879 // Return current input buffer, if present. | 880 // Return current input buffer, if present. |
| 880 if (curr_input_buffer_.get()) | 881 if (curr_input_buffer_.get()) |
| 881 ReturnCurrInputBuffer_Locked(); | 882 ReturnCurrInputBuffer_Locked(); |
| 882 | 883 |
| 883 // And let client know that we are done with reset. | 884 // And let client know that we are done with reset. |
| 884 message_loop_->PostTask(FROM_HERE, base::Bind( | 885 message_loop_->PostTask( |
| 885 &VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); | 886 FROM_HERE, |
| 887 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); |
| 886 } | 888 } |
| 887 | 889 |
| 888 void VaapiVideoDecodeAccelerator::Reset() { | 890 void VaapiVideoDecodeAccelerator::Reset() { |
| 889 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 891 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 890 DVLOG(1) << "Got reset request"; | 892 DVLOG(1) << "Got reset request"; |
| 891 | 893 |
| 892 // This will make any new decode tasks exit early. | 894 // This will make any new decode tasks exit early. |
| 893 base::AutoLock auto_lock(lock_); | 895 base::AutoLock auto_lock(lock_); |
| 894 state_ = kResetting; | 896 state_ = kResetting; |
| 895 finish_flush_pending_ = false; | 897 finish_flush_pending_ = false; |
| 896 | 898 |
| 897 // Drop all remaining input buffers, if present. | 899 // Drop all remaining input buffers, if present. |
| 898 while (!input_buffers_.empty()) { | 900 while (!input_buffers_.empty()) { |
| 899 message_loop_->PostTask(FROM_HERE, base::Bind( | 901 message_loop_->PostTask( |
| 900 &Client::NotifyEndOfBitstreamBuffer, client_, | 902 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, |
| 901 input_buffers_.front()->id)); | 903 input_buffers_.front()->id)); |
| 902 input_buffers_.pop(); | 904 input_buffers_.pop(); |
| 903 } | 905 } |
| 904 | 906 |
| 905 decoder_thread_task_runner_->PostTask( | 907 decoder_thread_task_runner_->PostTask( |
| 906 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, | 908 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, |
| 907 base::Unretained(this))); | 909 base::Unretained(this))); |
| 908 | 910 |
| 909 input_ready_.Signal(); | 911 input_ready_.Signal(); |
| 910 surfaces_available_.Signal(); | 912 surfaces_available_.Signal(); |
| 911 } | 913 } |
| 912 | 914 |
| 913 void VaapiVideoDecodeAccelerator::FinishReset() { | 915 void VaapiVideoDecodeAccelerator::FinishReset() { |
| 914 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 916 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 915 DVLOG(1) << "FinishReset"; | 917 DVLOG(1) << "FinishReset"; |
| 916 base::AutoLock auto_lock(lock_); | 918 base::AutoLock auto_lock(lock_); |
| 917 | 919 |
| 918 if (state_ != kResetting) { | 920 if (state_ != kResetting) { |
| 919 DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_; | 921 DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_; |
| 920 return; // We could've gotten destroyed already. | 922 return; // We could've gotten destroyed already. |
| 921 } | 923 } |
| 922 | 924 |
| 923 // Drop pending outputs. | 925 // Drop pending outputs. |
| 924 while (!pending_output_cbs_.empty()) | 926 while (!pending_output_cbs_.empty()) |
| 925 pending_output_cbs_.pop(); | 927 pending_output_cbs_.pop(); |
| 926 | 928 |
| 927 if (awaiting_va_surfaces_recycle_) { | 929 if (awaiting_va_surfaces_recycle_) { |
| 928 // Decoder requested a new surface set while we were waiting for it to | 930 // Decoder requested a new surface set while we were waiting for it to |
| 929 // finish the last DecodeTask, running at the time of Reset(). | 931 // finish the last DecodeTask, running at the time of Reset(). |
| 930 // Let the surface set change finish first before resetting. | 932 // Let the surface set change finish first before resetting. |
| 931 message_loop_->PostTask(FROM_HERE, base::Bind( | 933 message_loop_->PostTask( |
| 932 &VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); | 934 FROM_HERE, |
| 935 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); |
| 933 return; | 936 return; |
| 934 } | 937 } |
| 935 | 938 |
| 936 num_stream_bufs_at_decoder_ = 0; | 939 num_stream_bufs_at_decoder_ = 0; |
| 937 state_ = kIdle; | 940 state_ = kIdle; |
| 938 | 941 |
| 939 message_loop_->PostTask(FROM_HERE, base::Bind( | 942 message_loop_->PostTask(FROM_HERE, |
| 940 &Client::NotifyResetDone, client_)); | 943 base::Bind(&Client::NotifyResetDone, client_)); |
| 941 | 944 |
| 942 // The client might have given us new buffers via Decode() while we were | 945 // The client might have given us new buffers via Decode() while we were |
| 943 // resetting and might be waiting for our move, and not call Decode() anymore | 946 // resetting and might be waiting for our move, and not call Decode() anymore |
| 944 // until we return something. Post a DecodeTask() so that we won't | 947 // until we return something. Post a DecodeTask() so that we won't |
| 945 // sleep forever waiting for Decode() in that case. Having two of them | 948 // sleep forever waiting for Decode() in that case. Having two of them |
| 946 // in the pipe is harmless, the additional one will return as soon as it sees | 949 // in the pipe is harmless, the additional one will return as soon as it sees |
| 947 // that we are back in kDecoding state. | 950 // that we are back in kDecoding state. |
| 948 if (!input_buffers_.empty()) { | 951 if (!input_buffers_.empty()) { |
| 949 state_ = kDecoding; | 952 state_ = kDecoding; |
| 950 decoder_thread_task_runner_->PostTask( | 953 decoder_thread_task_runner_->PostTask( |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 } | 1053 } |
| 1051 | 1054 |
| 1052 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::VaapiH264Accelerator( | 1055 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::VaapiH264Accelerator( |
| 1053 VaapiVideoDecodeAccelerator* vaapi_dec, | 1056 VaapiVideoDecodeAccelerator* vaapi_dec, |
| 1054 VaapiWrapper* vaapi_wrapper) | 1057 VaapiWrapper* vaapi_wrapper) |
| 1055 : vaapi_wrapper_(vaapi_wrapper), vaapi_dec_(vaapi_dec) { | 1058 : vaapi_wrapper_(vaapi_wrapper), vaapi_dec_(vaapi_dec) { |
| 1056 DCHECK(vaapi_wrapper_); | 1059 DCHECK(vaapi_wrapper_); |
| 1057 DCHECK(vaapi_dec_); | 1060 DCHECK(vaapi_dec_); |
| 1058 } | 1061 } |
| 1059 | 1062 |
| 1060 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::~VaapiH264Accelerator() { | 1063 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::~VaapiH264Accelerator() {} |
| 1061 } | |
| 1062 | 1064 |
| 1063 scoped_refptr<H264Picture> | 1065 scoped_refptr<H264Picture> |
| 1064 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::CreateH264Picture() { | 1066 VaapiVideoDecodeAccelerator::VaapiH264Accelerator::CreateH264Picture() { |
| 1065 scoped_refptr<VaapiDecodeSurface> va_surface = vaapi_dec_->CreateSurface(); | 1067 scoped_refptr<VaapiDecodeSurface> va_surface = vaapi_dec_->CreateSurface(); |
| 1066 if (!va_surface) | 1068 if (!va_surface) |
| 1067 return nullptr; | 1069 return nullptr; |
| 1068 | 1070 |
| 1069 return new VaapiH264Picture(va_surface); | 1071 return new VaapiH264Picture(va_surface); |
| 1070 } | 1072 } |
| 1071 | 1073 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1150 for (int i = 0; i < 16; ++i) | 1152 for (int i = 0; i < 16; ++i) |
| 1151 InitVAPicture(&pic_param.ReferenceFrames[i]); | 1153 InitVAPicture(&pic_param.ReferenceFrames[i]); |
| 1152 | 1154 |
| 1153 // And fill it with picture info from DPB. | 1155 // And fill it with picture info from DPB. |
| 1154 FillVARefFramesFromDPB(dpb, pic_param.ReferenceFrames, | 1156 FillVARefFramesFromDPB(dpb, pic_param.ReferenceFrames, |
| 1155 arraysize(pic_param.ReferenceFrames)); | 1157 arraysize(pic_param.ReferenceFrames)); |
| 1156 | 1158 |
| 1157 pic_param.num_ref_frames = sps->max_num_ref_frames; | 1159 pic_param.num_ref_frames = sps->max_num_ref_frames; |
| 1158 | 1160 |
| 1159 if (!vaapi_wrapper_->SubmitBuffer(VAPictureParameterBufferType, | 1161 if (!vaapi_wrapper_->SubmitBuffer(VAPictureParameterBufferType, |
| 1160 sizeof(pic_param), | 1162 sizeof(pic_param), &pic_param)) |
| 1161 &pic_param)) | |
| 1162 return false; | 1163 return false; |
| 1163 | 1164 |
| 1164 VAIQMatrixBufferH264 iq_matrix_buf; | 1165 VAIQMatrixBufferH264 iq_matrix_buf; |
| 1165 memset(&iq_matrix_buf, 0, sizeof(iq_matrix_buf)); | 1166 memset(&iq_matrix_buf, 0, sizeof(iq_matrix_buf)); |
| 1166 | 1167 |
| 1167 if (pps->pic_scaling_matrix_present_flag) { | 1168 if (pps->pic_scaling_matrix_present_flag) { |
| 1168 for (int i = 0; i < 6; ++i) { | 1169 for (int i = 0; i < 6; ++i) { |
| 1169 for (int j = 0; j < 16; ++j) | 1170 for (int j = 0; j < 16; ++j) |
| 1170 iq_matrix_buf.ScalingList4x4[i][j] = pps->scaling_list4x4[i][j]; | 1171 iq_matrix_buf.ScalingList4x4[i][j] = pps->scaling_list4x4[i][j]; |
| 1171 } | 1172 } |
| 1172 | 1173 |
| 1173 for (int i = 0; i < 2; ++i) { | 1174 for (int i = 0; i < 2; ++i) { |
| 1174 for (int j = 0; j < 64; ++j) | 1175 for (int j = 0; j < 64; ++j) |
| 1175 iq_matrix_buf.ScalingList8x8[i][j] = pps->scaling_list8x8[i][j]; | 1176 iq_matrix_buf.ScalingList8x8[i][j] = pps->scaling_list8x8[i][j]; |
| 1176 } | 1177 } |
| 1177 } else { | 1178 } else { |
| 1178 for (int i = 0; i < 6; ++i) { | 1179 for (int i = 0; i < 6; ++i) { |
| 1179 for (int j = 0; j < 16; ++j) | 1180 for (int j = 0; j < 16; ++j) |
| 1180 iq_matrix_buf.ScalingList4x4[i][j] = sps->scaling_list4x4[i][j]; | 1181 iq_matrix_buf.ScalingList4x4[i][j] = sps->scaling_list4x4[i][j]; |
| 1181 } | 1182 } |
| 1182 | 1183 |
| 1183 for (int i = 0; i < 2; ++i) { | 1184 for (int i = 0; i < 2; ++i) { |
| 1184 for (int j = 0; j < 64; ++j) | 1185 for (int j = 0; j < 64; ++j) |
| 1185 iq_matrix_buf.ScalingList8x8[i][j] = sps->scaling_list8x8[i][j]; | 1186 iq_matrix_buf.ScalingList8x8[i][j] = sps->scaling_list8x8[i][j]; |
| 1186 } | 1187 } |
| 1187 } | 1188 } |
| 1188 | 1189 |
| 1189 return vaapi_wrapper_->SubmitBuffer(VAIQMatrixBufferType, | 1190 return vaapi_wrapper_->SubmitBuffer(VAIQMatrixBufferType, |
| 1190 sizeof(iq_matrix_buf), | 1191 sizeof(iq_matrix_buf), &iq_matrix_buf); |
| 1191 &iq_matrix_buf); | |
| 1192 } | 1192 } |
| 1193 | 1193 |
| 1194 bool VaapiVideoDecodeAccelerator::VaapiH264Accelerator::SubmitSlice( | 1194 bool VaapiVideoDecodeAccelerator::VaapiH264Accelerator::SubmitSlice( |
| 1195 const media::H264PPS* pps, | 1195 const media::H264PPS* pps, |
| 1196 const media::H264SliceHeader* slice_hdr, | 1196 const media::H264SliceHeader* slice_hdr, |
| 1197 const H264Picture::Vector& ref_pic_list0, | 1197 const H264Picture::Vector& ref_pic_list0, |
| 1198 const H264Picture::Vector& ref_pic_list1, | 1198 const H264Picture::Vector& ref_pic_list1, |
| 1199 const scoped_refptr<H264Picture>& pic, | 1199 const scoped_refptr<H264Picture>& pic, |
| 1200 const uint8_t* data, | 1200 const uint8_t* data, |
| 1201 size_t size) { | 1201 size_t size) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1281 FillVAPicture(&slice_param.RefPicList0[i], ref_pic_list0[i]); | 1281 FillVAPicture(&slice_param.RefPicList0[i], ref_pic_list0[i]); |
| 1282 } | 1282 } |
| 1283 for (size_t i = 0; | 1283 for (size_t i = 0; |
| 1284 i < ref_pic_list1.size() && i < arraysize(slice_param.RefPicList1); | 1284 i < ref_pic_list1.size() && i < arraysize(slice_param.RefPicList1); |
| 1285 ++i) { | 1285 ++i) { |
| 1286 if (ref_pic_list1[i]) | 1286 if (ref_pic_list1[i]) |
| 1287 FillVAPicture(&slice_param.RefPicList1[i], ref_pic_list1[i]); | 1287 FillVAPicture(&slice_param.RefPicList1[i], ref_pic_list1[i]); |
| 1288 } | 1288 } |
| 1289 | 1289 |
| 1290 if (!vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType, | 1290 if (!vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType, |
| 1291 sizeof(slice_param), | 1291 sizeof(slice_param), &slice_param)) |
| 1292 &slice_param)) | |
| 1293 return false; | 1292 return false; |
| 1294 | 1293 |
| 1295 // Can't help it, blame libva... | 1294 // Can't help it, blame libva... |
| 1296 void* non_const_ptr = const_cast<uint8_t*>(data); | 1295 void* non_const_ptr = const_cast<uint8_t*>(data); |
| 1297 return vaapi_wrapper_->SubmitBuffer(VASliceDataBufferType, size, | 1296 return vaapi_wrapper_->SubmitBuffer(VASliceDataBufferType, size, |
| 1298 non_const_ptr); | 1297 non_const_ptr); |
| 1299 } | 1298 } |
| 1300 | 1299 |
| 1301 bool VaapiVideoDecodeAccelerator::VaapiH264Accelerator::SubmitDecode( | 1300 bool VaapiVideoDecodeAccelerator::VaapiH264Accelerator::SubmitDecode( |
| 1302 const scoped_refptr<H264Picture>& pic) { | 1301 const scoped_refptr<H264Picture>& pic) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1383 } | 1382 } |
| 1384 | 1383 |
| 1385 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::VaapiVP8Accelerator( | 1384 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::VaapiVP8Accelerator( |
| 1386 VaapiVideoDecodeAccelerator* vaapi_dec, | 1385 VaapiVideoDecodeAccelerator* vaapi_dec, |
| 1387 VaapiWrapper* vaapi_wrapper) | 1386 VaapiWrapper* vaapi_wrapper) |
| 1388 : vaapi_wrapper_(vaapi_wrapper), vaapi_dec_(vaapi_dec) { | 1387 : vaapi_wrapper_(vaapi_wrapper), vaapi_dec_(vaapi_dec) { |
| 1389 DCHECK(vaapi_wrapper_); | 1388 DCHECK(vaapi_wrapper_); |
| 1390 DCHECK(vaapi_dec_); | 1389 DCHECK(vaapi_dec_); |
| 1391 } | 1390 } |
| 1392 | 1391 |
| 1393 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::~VaapiVP8Accelerator() { | 1392 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::~VaapiVP8Accelerator() {} |
| 1394 } | |
| 1395 | 1393 |
| 1396 scoped_refptr<VP8Picture> | 1394 scoped_refptr<VP8Picture> |
| 1397 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::CreateVP8Picture() { | 1395 VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::CreateVP8Picture() { |
| 1398 scoped_refptr<VaapiDecodeSurface> va_surface = vaapi_dec_->CreateSurface(); | 1396 scoped_refptr<VaapiDecodeSurface> va_surface = vaapi_dec_->CreateSurface(); |
| 1399 if (!va_surface) | 1397 if (!va_surface) |
| 1400 return nullptr; | 1398 return nullptr; |
| 1401 | 1399 |
| 1402 return new VaapiVP8Picture(va_surface); | 1400 return new VaapiVP8Picture(va_surface); |
| 1403 } | 1401 } |
| 1404 | 1402 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1439 "incorrect quantization matrix size"); | 1437 "incorrect quantization matrix size"); |
| 1440 iq_matrix_buf.quantization_index[i][0] = CLAMP_Q(q); | 1438 iq_matrix_buf.quantization_index[i][0] = CLAMP_Q(q); |
| 1441 iq_matrix_buf.quantization_index[i][1] = CLAMP_Q(q + quant_hdr.y_dc_delta); | 1439 iq_matrix_buf.quantization_index[i][1] = CLAMP_Q(q + quant_hdr.y_dc_delta); |
| 1442 iq_matrix_buf.quantization_index[i][2] = CLAMP_Q(q + quant_hdr.y2_dc_delta); | 1440 iq_matrix_buf.quantization_index[i][2] = CLAMP_Q(q + quant_hdr.y2_dc_delta); |
| 1443 iq_matrix_buf.quantization_index[i][3] = CLAMP_Q(q + quant_hdr.y2_ac_delta); | 1441 iq_matrix_buf.quantization_index[i][3] = CLAMP_Q(q + quant_hdr.y2_ac_delta); |
| 1444 iq_matrix_buf.quantization_index[i][4] = CLAMP_Q(q + quant_hdr.uv_dc_delta); | 1442 iq_matrix_buf.quantization_index[i][4] = CLAMP_Q(q + quant_hdr.uv_dc_delta); |
| 1445 iq_matrix_buf.quantization_index[i][5] = CLAMP_Q(q + quant_hdr.uv_ac_delta); | 1443 iq_matrix_buf.quantization_index[i][5] = CLAMP_Q(q + quant_hdr.uv_ac_delta); |
| 1446 #undef CLAMP_Q | 1444 #undef CLAMP_Q |
| 1447 } | 1445 } |
| 1448 | 1446 |
| 1449 if (!vaapi_wrapper_->SubmitBuffer(VAIQMatrixBufferType, | 1447 if (!vaapi_wrapper_->SubmitBuffer( |
| 1450 sizeof(VAIQMatrixBufferVP8), | 1448 VAIQMatrixBufferType, sizeof(VAIQMatrixBufferVP8), &iq_matrix_buf)) |
| 1451 &iq_matrix_buf)) | |
| 1452 return false; | 1449 return false; |
| 1453 | 1450 |
| 1454 VAProbabilityDataBufferVP8 prob_buf; | 1451 VAProbabilityDataBufferVP8 prob_buf; |
| 1455 memset(&prob_buf, 0, sizeof(VAProbabilityDataBufferVP8)); | 1452 memset(&prob_buf, 0, sizeof(VAProbabilityDataBufferVP8)); |
| 1456 | 1453 |
| 1457 const media::Vp8EntropyHeader& entr_hdr = frame_hdr->entropy_hdr; | 1454 const media::Vp8EntropyHeader& entr_hdr = frame_hdr->entropy_hdr; |
| 1458 ARRAY_MEMCPY_CHECKED(prob_buf.dct_coeff_probs, entr_hdr.coeff_probs); | 1455 ARRAY_MEMCPY_CHECKED(prob_buf.dct_coeff_probs, entr_hdr.coeff_probs); |
| 1459 | 1456 |
| 1460 if (!vaapi_wrapper_->SubmitBuffer(VAProbabilityBufferType, | 1457 if (!vaapi_wrapper_->SubmitBuffer(VAProbabilityBufferType, |
| 1461 sizeof(VAProbabilityDataBufferVP8), | 1458 sizeof(VAProbabilityDataBufferVP8), |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1526 lf_level = sgmnt_hdr.lf_update_value[i]; | 1523 lf_level = sgmnt_hdr.lf_update_value[i]; |
| 1527 else | 1524 else |
| 1528 lf_level += sgmnt_hdr.lf_update_value[i]; | 1525 lf_level += sgmnt_hdr.lf_update_value[i]; |
| 1529 } | 1526 } |
| 1530 | 1527 |
| 1531 // Clamp to [0..63] range. | 1528 // Clamp to [0..63] range. |
| 1532 lf_level = std::min(std::max(lf_level, 0), 63); | 1529 lf_level = std::min(std::max(lf_level, 0), 63); |
| 1533 pic_param.loop_filter_level[i] = lf_level; | 1530 pic_param.loop_filter_level[i] = lf_level; |
| 1534 } | 1531 } |
| 1535 | 1532 |
| 1536 static_assert(arraysize(lf_hdr.ref_frame_delta) == | 1533 static_assert( |
| 1537 arraysize(pic_param.loop_filter_deltas_ref_frame) && | 1534 arraysize(lf_hdr.ref_frame_delta) == |
| 1538 arraysize(lf_hdr.mb_mode_delta) == | 1535 arraysize(pic_param.loop_filter_deltas_ref_frame) && |
| 1539 arraysize(pic_param.loop_filter_deltas_mode) && | 1536 arraysize(lf_hdr.mb_mode_delta) == |
| 1540 arraysize(lf_hdr.ref_frame_delta) == | 1537 arraysize(pic_param.loop_filter_deltas_mode) && |
| 1541 arraysize(lf_hdr.mb_mode_delta), | 1538 arraysize(lf_hdr.ref_frame_delta) == arraysize(lf_hdr.mb_mode_delta), |
| 1542 "loop filter deltas arrays size mismatch"); | 1539 "loop filter deltas arrays size mismatch"); |
| 1543 for (size_t i = 0; i < arraysize(lf_hdr.ref_frame_delta); ++i) { | 1540 for (size_t i = 0; i < arraysize(lf_hdr.ref_frame_delta); ++i) { |
| 1544 pic_param.loop_filter_deltas_ref_frame[i] = lf_hdr.ref_frame_delta[i]; | 1541 pic_param.loop_filter_deltas_ref_frame[i] = lf_hdr.ref_frame_delta[i]; |
| 1545 pic_param.loop_filter_deltas_mode[i] = lf_hdr.mb_mode_delta[i]; | 1542 pic_param.loop_filter_deltas_mode[i] = lf_hdr.mb_mode_delta[i]; |
| 1546 } | 1543 } |
| 1547 | 1544 |
| 1548 #define FHDR_TO_PP(a) pic_param.a = frame_hdr->a | 1545 #define FHDR_TO_PP(a) pic_param.a = frame_hdr->a |
| 1549 FHDR_TO_PP(prob_skip_false); | 1546 FHDR_TO_PP(prob_skip_false); |
| 1550 FHDR_TO_PP(prob_intra); | 1547 FHDR_TO_PP(prob_intra); |
| 1551 FHDR_TO_PP(prob_last); | 1548 FHDR_TO_PP(prob_last); |
| 1552 FHDR_TO_PP(prob_gf); | 1549 FHDR_TO_PP(prob_gf); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1581 for (size_t i = 0; i < frame_hdr->num_of_dct_partitions; ++i) | 1578 for (size_t i = 0; i < frame_hdr->num_of_dct_partitions; ++i) |
| 1582 slice_param.partition_size[i + 1] = frame_hdr->dct_partition_sizes[i]; | 1579 slice_param.partition_size[i + 1] = frame_hdr->dct_partition_sizes[i]; |
| 1583 | 1580 |
| 1584 if (!vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType, | 1581 if (!vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType, |
| 1585 sizeof(VASliceParameterBufferVP8), | 1582 sizeof(VASliceParameterBufferVP8), |
| 1586 &slice_param)) | 1583 &slice_param)) |
| 1587 return false; | 1584 return false; |
| 1588 | 1585 |
| 1589 void* non_const_ptr = const_cast<uint8_t*>(frame_hdr->data); | 1586 void* non_const_ptr = const_cast<uint8_t*>(frame_hdr->data); |
| 1590 if (!vaapi_wrapper_->SubmitBuffer(VASliceDataBufferType, | 1587 if (!vaapi_wrapper_->SubmitBuffer(VASliceDataBufferType, |
| 1591 frame_hdr->frame_size, | 1588 frame_hdr->frame_size, non_const_ptr)) |
| 1592 non_const_ptr)) | |
| 1593 return false; | 1589 return false; |
| 1594 | 1590 |
| 1595 scoped_refptr<VaapiDecodeSurface> dec_surface = | 1591 scoped_refptr<VaapiDecodeSurface> dec_surface = |
| 1596 VP8PictureToVaapiDecodeSurface(pic); | 1592 VP8PictureToVaapiDecodeSurface(pic); |
| 1597 | 1593 |
| 1598 return vaapi_dec_->DecodeSurface(dec_surface); | 1594 return vaapi_dec_->DecodeSurface(dec_surface); |
| 1599 } | 1595 } |
| 1600 | 1596 |
| 1601 bool VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::OutputPicture( | 1597 bool VaapiVideoDecodeAccelerator::VaapiVP8Accelerator::OutputPicture( |
| 1602 const scoped_refptr<VP8Picture>& pic) { | 1598 const scoped_refptr<VP8Picture>& pic) { |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1770 CHECK(vaapi_pic); | 1766 CHECK(vaapi_pic); |
| 1771 return vaapi_pic->dec_surface(); | 1767 return vaapi_pic->dec_surface(); |
| 1772 } | 1768 } |
| 1773 | 1769 |
| 1774 // static | 1770 // static |
| 1775 media::VideoDecodeAccelerator::SupportedProfiles | 1771 media::VideoDecodeAccelerator::SupportedProfiles |
| 1776 VaapiVideoDecodeAccelerator::GetSupportedProfiles() { | 1772 VaapiVideoDecodeAccelerator::GetSupportedProfiles() { |
| 1777 return VaapiWrapper::GetSupportedDecodeProfiles(); | 1773 return VaapiWrapper::GetSupportedDecodeProfiles(); |
| 1778 } | 1774 } |
| 1779 | 1775 |
| 1780 } // namespace content | 1776 } // namespace media |
| OLD | NEW |