| 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 |
| 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 |