| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/v4l2_slice_video_decode_accelerator.h" | 5 #include "media/gpu/v4l2_slice_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <linux/videodev2.h> | 9 #include <linux/videodev2.h> |
| 10 #include <poll.h> | 10 #include <poll.h> |
| 11 #include <string.h> | 11 #include <string.h> |
| 12 #include <sys/eventfd.h> | 12 #include <sys/eventfd.h> |
| 13 #include <sys/ioctl.h> | 13 #include <sys/ioctl.h> |
| 14 #include <sys/mman.h> | 14 #include <sys/mman.h> |
| 15 | 15 |
| 16 #include <memory> | 16 #include <memory> |
| 17 | 17 |
| 18 #include "base/bind.h" | 18 #include "base/bind.h" |
| 19 #include "base/bind_helpers.h" | 19 #include "base/bind_helpers.h" |
| 20 #include "base/callback.h" | 20 #include "base/callback.h" |
| 21 #include "base/callback_helpers.h" | 21 #include "base/callback_helpers.h" |
| 22 #include "base/command_line.h" | 22 #include "base/command_line.h" |
| 23 #include "base/macros.h" | 23 #include "base/macros.h" |
| 24 #include "base/memory/ptr_util.h" | 24 #include "base/memory/ptr_util.h" |
| 25 #include "base/numerics/safe_conversions.h" | 25 #include "base/numerics/safe_conversions.h" |
| 26 #include "base/strings/stringprintf.h" | 26 #include "base/strings/stringprintf.h" |
| 27 #include "content/common/gpu/media/shared_memory_region.h" | |
| 28 #include "media/base/bind_to_current_loop.h" | 27 #include "media/base/bind_to_current_loop.h" |
| 29 #include "media/base/media_switches.h" | 28 #include "media/base/media_switches.h" |
| 29 #include "media/gpu/shared_memory_region.h" |
| 30 #include "ui/gl/gl_context.h" | 30 #include "ui/gl/gl_context.h" |
| 31 #include "ui/gl/scoped_binders.h" | 31 #include "ui/gl/scoped_binders.h" |
| 32 | 32 |
| 33 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): " | 33 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): " |
| 34 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " | 34 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " |
| 35 | 35 |
| 36 #define NOTIFY_ERROR(x) \ | 36 #define NOTIFY_ERROR(x) \ |
| 37 do { \ | 37 do { \ |
| 38 LOG(ERROR) << "Setting error state:" << x; \ | 38 LOG(ERROR) << "Setting error state:" << x; \ |
| 39 SetErrorState(x); \ | 39 SetErrorState(x); \ |
| 40 } while (0) | 40 } while (0) |
| 41 | 41 |
| 42 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \ | 42 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \ |
| 43 do { \ | 43 do { \ |
| 44 if (device_->Ioctl(type, arg) != 0) { \ | 44 if (device_->Ioctl(type, arg) != 0) { \ |
| 45 PLOG(ERROR) << __FUNCTION__ << "(): ioctl() failed: " << type_str; \ | 45 PLOG(ERROR) << __FUNCTION__ << "(): ioctl() failed: " << type_str; \ |
| 46 return value; \ | 46 return value; \ |
| 47 } \ | 47 } \ |
| 48 } while (0) | 48 } while (0) |
| 49 | 49 |
| 50 #define IOCTL_OR_ERROR_RETURN(type, arg) \ | 50 #define IOCTL_OR_ERROR_RETURN(type, arg) \ |
| 51 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0), #type) | 51 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0), #type) |
| 52 | 52 |
| 53 #define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \ | 53 #define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \ |
| 54 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false, #type) | 54 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false, #type) |
| 55 | 55 |
| 56 #define IOCTL_OR_LOG_ERROR(type, arg) \ | 56 #define IOCTL_OR_LOG_ERROR(type, arg) \ |
| 57 do { \ | 57 do { \ |
| 58 if (device_->Ioctl(type, arg) != 0) \ | 58 if (device_->Ioctl(type, arg) != 0) \ |
| 59 PLOG(ERROR) << __FUNCTION__ << "(): ioctl() failed: " << #type; \ | 59 PLOG(ERROR) << __FUNCTION__ << "(): ioctl() failed: " << #type; \ |
| 60 } while (0) | 60 } while (0) |
| 61 | 61 |
| 62 namespace content { | 62 namespace media { |
| 63 | 63 |
| 64 // static | 64 // static |
| 65 const uint32_t V4L2SliceVideoDecodeAccelerator::supported_input_fourccs_[] = { | 65 const uint32_t V4L2SliceVideoDecodeAccelerator::supported_input_fourccs_[] = { |
| 66 V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME, | 66 V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME, |
| 67 }; | 67 }; |
| 68 | 68 |
| 69 class V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface | 69 class V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface |
| 70 : public base::RefCounted<V4L2DecodeSurface> { | 70 : public base::RefCounted<V4L2DecodeSurface> { |
| 71 public: | 71 public: |
| 72 using ReleaseCB = base::Callback<void(int)>; | 72 using ReleaseCB = base::Callback<void(int)>; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 base::StringAppendF(&out, " %d", ref->output_record()); | 152 base::StringAppendF(&out, " %d", ref->output_record()); |
| 153 } | 153 } |
| 154 return out; | 154 return out; |
| 155 } | 155 } |
| 156 | 156 |
| 157 V4L2SliceVideoDecodeAccelerator::InputRecord::InputRecord() | 157 V4L2SliceVideoDecodeAccelerator::InputRecord::InputRecord() |
| 158 : input_id(-1), | 158 : input_id(-1), |
| 159 address(nullptr), | 159 address(nullptr), |
| 160 length(0), | 160 length(0), |
| 161 bytes_used(0), | 161 bytes_used(0), |
| 162 at_device(false) { | 162 at_device(false) {} |
| 163 } | |
| 164 | 163 |
| 165 V4L2SliceVideoDecodeAccelerator::OutputRecord::OutputRecord() | 164 V4L2SliceVideoDecodeAccelerator::OutputRecord::OutputRecord() |
| 166 : at_device(false), | 165 : at_device(false), |
| 167 at_client(false), | 166 at_client(false), |
| 168 picture_id(-1), | 167 picture_id(-1), |
| 169 texture_id(0), | 168 texture_id(0), |
| 170 egl_image(EGL_NO_IMAGE_KHR), | 169 egl_image(EGL_NO_IMAGE_KHR), |
| 171 egl_sync(EGL_NO_SYNC_KHR), | 170 egl_sync(EGL_NO_SYNC_KHR), |
| 172 cleared(false) {} | 171 cleared(false) {} |
| 173 | 172 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 struct V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef { | 208 struct V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef { |
| 210 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); | 209 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); |
| 211 ~EGLSyncKHRRef(); | 210 ~EGLSyncKHRRef(); |
| 212 EGLDisplay const egl_display; | 211 EGLDisplay const egl_display; |
| 213 EGLSyncKHR egl_sync; | 212 EGLSyncKHR egl_sync; |
| 214 }; | 213 }; |
| 215 | 214 |
| 216 V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef( | 215 V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef( |
| 217 EGLDisplay egl_display, | 216 EGLDisplay egl_display, |
| 218 EGLSyncKHR egl_sync) | 217 EGLSyncKHR egl_sync) |
| 219 : egl_display(egl_display), egl_sync(egl_sync) { | 218 : egl_display(egl_display), egl_sync(egl_sync) {} |
| 220 } | |
| 221 | 219 |
| 222 V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() { | 220 V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() { |
| 223 // We don't check for eglDestroySyncKHR failures, because if we get here | 221 // We don't check for eglDestroySyncKHR failures, because if we get here |
| 224 // with a valid sync object, something went wrong and we are getting | 222 // with a valid sync object, something went wrong and we are getting |
| 225 // destroyed anyway. | 223 // destroyed anyway. |
| 226 if (egl_sync != EGL_NO_SYNC_KHR) | 224 if (egl_sync != EGL_NO_SYNC_KHR) |
| 227 eglDestroySyncKHR(egl_display, egl_sync); | 225 eglDestroySyncKHR(egl_display, egl_sync); |
| 228 } | 226 } |
| 229 | 227 |
| 230 struct V4L2SliceVideoDecodeAccelerator::PictureRecord { | 228 struct V4L2SliceVideoDecodeAccelerator::PictureRecord { |
| 231 PictureRecord(bool cleared, const media::Picture& picture); | 229 PictureRecord(bool cleared, const media::Picture& picture); |
| 232 ~PictureRecord(); | 230 ~PictureRecord(); |
| 233 bool cleared; // Whether the texture is cleared and safe to render from. | 231 bool cleared; // Whether the texture is cleared and safe to render from. |
| 234 media::Picture picture; // The decoded picture. | 232 media::Picture picture; // The decoded picture. |
| 235 }; | 233 }; |
| 236 | 234 |
| 237 V4L2SliceVideoDecodeAccelerator::PictureRecord::PictureRecord( | 235 V4L2SliceVideoDecodeAccelerator::PictureRecord::PictureRecord( |
| 238 bool cleared, | 236 bool cleared, |
| 239 const media::Picture& picture) | 237 const media::Picture& picture) |
| 240 : cleared(cleared), picture(picture) { | 238 : cleared(cleared), picture(picture) {} |
| 241 } | |
| 242 | 239 |
| 243 V4L2SliceVideoDecodeAccelerator::PictureRecord::~PictureRecord() { | 240 V4L2SliceVideoDecodeAccelerator::PictureRecord::~PictureRecord() {} |
| 244 } | |
| 245 | 241 |
| 246 class V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator | 242 class V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator |
| 247 : public H264Decoder::H264Accelerator { | 243 : public H264Decoder::H264Accelerator { |
| 248 public: | 244 public: |
| 249 V4L2H264Accelerator(V4L2SliceVideoDecodeAccelerator* v4l2_dec); | 245 V4L2H264Accelerator(V4L2SliceVideoDecodeAccelerator* v4l2_dec); |
| 250 ~V4L2H264Accelerator() override; | 246 ~V4L2H264Accelerator() override; |
| 251 | 247 |
| 252 // H264Decoder::H264Accelerator implementation. | 248 // H264Decoder::H264Accelerator implementation. |
| 253 scoped_refptr<H264Picture> CreateH264Picture() override; | 249 scoped_refptr<H264Picture> CreateH264Picture() override; |
| 254 | 250 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 | 316 |
| 321 V4L2SliceVideoDecodeAccelerator* v4l2_dec_; | 317 V4L2SliceVideoDecodeAccelerator* v4l2_dec_; |
| 322 | 318 |
| 323 DISALLOW_COPY_AND_ASSIGN(V4L2VP8Accelerator); | 319 DISALLOW_COPY_AND_ASSIGN(V4L2VP8Accelerator); |
| 324 }; | 320 }; |
| 325 | 321 |
| 326 // Codec-specific subclasses of software decoder picture classes. | 322 // Codec-specific subclasses of software decoder picture classes. |
| 327 // This allows us to keep decoders oblivious of our implementation details. | 323 // This allows us to keep decoders oblivious of our implementation details. |
| 328 class V4L2H264Picture : public H264Picture { | 324 class V4L2H264Picture : public H264Picture { |
| 329 public: | 325 public: |
| 330 V4L2H264Picture(const scoped_refptr< | 326 V4L2H264Picture( |
| 331 V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>& dec_surface); | 327 const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>& |
| 328 dec_surface); |
| 332 | 329 |
| 333 V4L2H264Picture* AsV4L2H264Picture() override { return this; } | 330 V4L2H264Picture* AsV4L2H264Picture() override { return this; } |
| 334 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> | 331 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> |
| 335 dec_surface() { | 332 dec_surface() { |
| 336 return dec_surface_; | 333 return dec_surface_; |
| 337 } | 334 } |
| 338 | 335 |
| 339 private: | 336 private: |
| 340 ~V4L2H264Picture() override; | 337 ~V4L2H264Picture() override; |
| 341 | 338 |
| 342 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> | 339 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> |
| 343 dec_surface_; | 340 dec_surface_; |
| 344 | 341 |
| 345 DISALLOW_COPY_AND_ASSIGN(V4L2H264Picture); | 342 DISALLOW_COPY_AND_ASSIGN(V4L2H264Picture); |
| 346 }; | 343 }; |
| 347 | 344 |
| 348 V4L2H264Picture::V4L2H264Picture(const scoped_refptr< | 345 V4L2H264Picture::V4L2H264Picture( |
| 349 V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>& dec_surface) | 346 const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>& |
| 350 : dec_surface_(dec_surface) { | 347 dec_surface) |
| 351 } | 348 : dec_surface_(dec_surface) {} |
| 352 | 349 |
| 353 V4L2H264Picture::~V4L2H264Picture() { | 350 V4L2H264Picture::~V4L2H264Picture() {} |
| 354 } | |
| 355 | 351 |
| 356 class V4L2VP8Picture : public VP8Picture { | 352 class V4L2VP8Picture : public VP8Picture { |
| 357 public: | 353 public: |
| 358 V4L2VP8Picture(const scoped_refptr< | 354 V4L2VP8Picture( |
| 359 V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>& dec_surface); | 355 const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>& |
| 356 dec_surface); |
| 360 | 357 |
| 361 V4L2VP8Picture* AsV4L2VP8Picture() override { return this; } | 358 V4L2VP8Picture* AsV4L2VP8Picture() override { return this; } |
| 362 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> | 359 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> |
| 363 dec_surface() { | 360 dec_surface() { |
| 364 return dec_surface_; | 361 return dec_surface_; |
| 365 } | 362 } |
| 366 | 363 |
| 367 private: | 364 private: |
| 368 ~V4L2VP8Picture() override; | 365 ~V4L2VP8Picture() override; |
| 369 | 366 |
| 370 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> | 367 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> |
| 371 dec_surface_; | 368 dec_surface_; |
| 372 | 369 |
| 373 DISALLOW_COPY_AND_ASSIGN(V4L2VP8Picture); | 370 DISALLOW_COPY_AND_ASSIGN(V4L2VP8Picture); |
| 374 }; | 371 }; |
| 375 | 372 |
| 376 V4L2VP8Picture::V4L2VP8Picture(const scoped_refptr< | 373 V4L2VP8Picture::V4L2VP8Picture( |
| 377 V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>& dec_surface) | 374 const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>& |
| 378 : dec_surface_(dec_surface) { | 375 dec_surface) |
| 379 } | 376 : dec_surface_(dec_surface) {} |
| 380 | 377 |
| 381 V4L2VP8Picture::~V4L2VP8Picture() { | 378 V4L2VP8Picture::~V4L2VP8Picture() {} |
| 382 } | |
| 383 | 379 |
| 384 V4L2SliceVideoDecodeAccelerator::V4L2SliceVideoDecodeAccelerator( | 380 V4L2SliceVideoDecodeAccelerator::V4L2SliceVideoDecodeAccelerator( |
| 385 const scoped_refptr<V4L2Device>& device, | 381 const scoped_refptr<V4L2Device>& device, |
| 386 EGLDisplay egl_display, | 382 EGLDisplay egl_display, |
| 387 const GetGLContextCallback& get_gl_context_cb, | 383 const GetGLContextCallback& get_gl_context_cb, |
| 388 const MakeGLContextCurrentCallback& make_context_current_cb) | 384 const MakeGLContextCurrentCallback& make_context_current_cb) |
| 389 : input_planes_count_(0), | 385 : input_planes_count_(0), |
| 390 output_planes_count_(0), | 386 output_planes_count_(0), |
| 391 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 387 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 392 device_(device), | 388 device_(device), |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 } else { | 506 } else { |
| 511 DVLOG(1) << "No GL callbacks provided, initializing without GL support"; | 507 DVLOG(1) << "No GL callbacks provided, initializing without GL support"; |
| 512 } | 508 } |
| 513 | 509 |
| 514 // Capabilities check. | 510 // Capabilities check. |
| 515 struct v4l2_capability caps; | 511 struct v4l2_capability caps; |
| 516 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; | 512 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; |
| 517 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); | 513 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); |
| 518 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { | 514 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { |
| 519 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" | 515 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" |
| 520 ", caps check failed: 0x" << std::hex << caps.capabilities; | 516 ", caps check failed: 0x" |
| 517 << std::hex << caps.capabilities; |
| 521 return false; | 518 return false; |
| 522 } | 519 } |
| 523 | 520 |
| 524 if (!SetupFormats()) | 521 if (!SetupFormats()) |
| 525 return false; | 522 return false; |
| 526 | 523 |
| 527 if (!decoder_thread_.Start()) { | 524 if (!decoder_thread_.Start()) { |
| 528 DLOG(ERROR) << "Initialize(): device thread failed to start"; | 525 DLOG(ERROR) << "Initialize(): device thread failed to start"; |
| 529 return false; | 526 return false; |
| 530 } | 527 } |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 struct v4l2_plane planes[VIDEO_MAX_PLANES]; | 691 struct v4l2_plane planes[VIDEO_MAX_PLANES]; |
| 695 struct v4l2_buffer buffer; | 692 struct v4l2_buffer buffer; |
| 696 memset(&buffer, 0, sizeof(buffer)); | 693 memset(&buffer, 0, sizeof(buffer)); |
| 697 memset(planes, 0, sizeof(planes)); | 694 memset(planes, 0, sizeof(planes)); |
| 698 buffer.index = i; | 695 buffer.index = i; |
| 699 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 696 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 700 buffer.memory = V4L2_MEMORY_MMAP; | 697 buffer.memory = V4L2_MEMORY_MMAP; |
| 701 buffer.m.planes = planes; | 698 buffer.m.planes = planes; |
| 702 buffer.length = input_planes_count_; | 699 buffer.length = input_planes_count_; |
| 703 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); | 700 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); |
| 704 void* address = device_->Mmap(nullptr, | 701 void* address = device_->Mmap(nullptr, buffer.m.planes[0].length, |
| 705 buffer.m.planes[0].length, | 702 PROT_READ | PROT_WRITE, MAP_SHARED, |
| 706 PROT_READ | PROT_WRITE, | |
| 707 MAP_SHARED, | |
| 708 buffer.m.planes[0].m.mem_offset); | 703 buffer.m.planes[0].m.mem_offset); |
| 709 if (address == MAP_FAILED) { | 704 if (address == MAP_FAILED) { |
| 710 PLOG(ERROR) << "CreateInputBuffers(): mmap() failed"; | 705 PLOG(ERROR) << "CreateInputBuffers(): mmap() failed"; |
| 711 return false; | 706 return false; |
| 712 } | 707 } |
| 713 input_buffer_map_[i].address = address; | 708 input_buffer_map_[i].address = address; |
| 714 input_buffer_map_[i].length = buffer.m.planes[0].length; | 709 input_buffer_map_[i].length = buffer.m.planes[0].length; |
| 715 } | 710 } |
| 716 | 711 |
| 717 return true; | 712 return true; |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 } | 851 } |
| 857 | 852 |
| 858 DVLOGF(4) << "Scheduling device poll task"; | 853 DVLOGF(4) << "Scheduling device poll task"; |
| 859 | 854 |
| 860 device_poll_thread_.message_loop()->PostTask( | 855 device_poll_thread_.message_loop()->PostTask( |
| 861 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DevicePollTask, | 856 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DevicePollTask, |
| 862 base::Unretained(this), true)); | 857 base::Unretained(this), true)); |
| 863 | 858 |
| 864 DVLOGF(2) << "buffer counts: " | 859 DVLOGF(2) << "buffer counts: " |
| 865 << "INPUT[" << decoder_input_queue_.size() << "]" | 860 << "INPUT[" << decoder_input_queue_.size() << "]" |
| 866 << " => DEVICE[" | 861 << " => DEVICE[" << free_input_buffers_.size() << "+" |
| 867 << free_input_buffers_.size() << "+" | 862 << input_buffer_queued_count_ << "/" << input_buffer_map_.size() |
| 868 << input_buffer_queued_count_ << "/" | 863 << "]->[" << free_output_buffers_.size() << "+" |
| 869 << input_buffer_map_.size() << "]->[" | 864 << output_buffer_queued_count_ << "/" << output_buffer_map_.size() |
| 870 << free_output_buffers_.size() << "+" | 865 << "]" |
| 871 << output_buffer_queued_count_ << "/" | |
| 872 << output_buffer_map_.size() << "]" | |
| 873 << " => DISPLAYQ[" << decoder_display_queue_.size() << "]" | 866 << " => DISPLAYQ[" << decoder_display_queue_.size() << "]" |
| 874 << " => CLIENT[" << surfaces_at_display_.size() << "]"; | 867 << " => CLIENT[" << surfaces_at_display_.size() << "]"; |
| 875 } | 868 } |
| 876 | 869 |
| 877 void V4L2SliceVideoDecodeAccelerator::Enqueue( | 870 void V4L2SliceVideoDecodeAccelerator::Enqueue( |
| 878 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { | 871 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { |
| 879 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 872 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 880 | 873 |
| 881 const int old_inputs_queued = input_buffer_queued_count_; | 874 const int old_inputs_queued = input_buffer_queued_count_; |
| 882 const int old_outputs_queued = output_buffer_queued_count_; | 875 const int old_outputs_queued = output_buffer_queued_count_; |
| 883 | 876 |
| 884 if (!EnqueueInputRecord(dec_surface->input_record(), | 877 if (!EnqueueInputRecord(dec_surface->input_record(), |
| 885 dec_surface->config_store())) { | 878 dec_surface->config_store())) { |
| 886 DVLOGF(1) << "Failed queueing an input buffer"; | 879 DVLOGF(1) << "Failed queueing an input buffer"; |
| 887 NOTIFY_ERROR(PLATFORM_FAILURE); | 880 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 888 return; | 881 return; |
| 889 } | 882 } |
| 890 | 883 |
| 891 if (!EnqueueOutputRecord(dec_surface->output_record())) { | 884 if (!EnqueueOutputRecord(dec_surface->output_record())) { |
| 892 DVLOGF(1) << "Failed queueing an output buffer"; | 885 DVLOGF(1) << "Failed queueing an output buffer"; |
| 893 NOTIFY_ERROR(PLATFORM_FAILURE); | 886 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 894 return; | 887 return; |
| 895 } | 888 } |
| 896 | 889 |
| 897 bool inserted = | 890 bool inserted = |
| 898 surfaces_at_device_.insert(std::make_pair(dec_surface->output_record(), | 891 surfaces_at_device_ |
| 899 dec_surface)).second; | 892 .insert(std::make_pair(dec_surface->output_record(), dec_surface)) |
| 893 .second; |
| 900 DCHECK(inserted); | 894 DCHECK(inserted); |
| 901 | 895 |
| 902 if (old_inputs_queued == 0 && old_outputs_queued == 0) | 896 if (old_inputs_queued == 0 && old_outputs_queued == 0) |
| 903 SchedulePollIfNeeded(); | 897 SchedulePollIfNeeded(); |
| 904 } | 898 } |
| 905 | 899 |
| 906 void V4L2SliceVideoDecodeAccelerator::Dequeue() { | 900 void V4L2SliceVideoDecodeAccelerator::Dequeue() { |
| 907 DVLOGF(3); | 901 DVLOGF(3); |
| 908 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 902 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 909 | 903 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 break; | 945 break; |
| 952 } | 946 } |
| 953 PLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF"; | 947 PLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF"; |
| 954 NOTIFY_ERROR(PLATFORM_FAILURE); | 948 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 955 return; | 949 return; |
| 956 } | 950 } |
| 957 OutputRecord& output_record = output_buffer_map_[dqbuf.index]; | 951 OutputRecord& output_record = output_buffer_map_[dqbuf.index]; |
| 958 DCHECK(output_record.at_device); | 952 DCHECK(output_record.at_device); |
| 959 output_record.at_device = false; | 953 output_record.at_device = false; |
| 960 output_buffer_queued_count_--; | 954 output_buffer_queued_count_--; |
| 961 DVLOGF(3) << "Dequeued output=" << dqbuf.index | 955 DVLOGF(3) << "Dequeued output=" << dqbuf.index << " count " |
| 962 << " count " << output_buffer_queued_count_; | 956 << output_buffer_queued_count_; |
| 963 | 957 |
| 964 V4L2DecodeSurfaceByOutputId::iterator it = | 958 V4L2DecodeSurfaceByOutputId::iterator it = |
| 965 surfaces_at_device_.find(dqbuf.index); | 959 surfaces_at_device_.find(dqbuf.index); |
| 966 if (it == surfaces_at_device_.end()) { | 960 if (it == surfaces_at_device_.end()) { |
| 967 DLOG(ERROR) << "Got invalid surface from device."; | 961 DLOG(ERROR) << "Got invalid surface from device."; |
| 968 NOTIFY_ERROR(PLATFORM_FAILURE); | 962 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 969 } | 963 } |
| 970 | 964 |
| 971 it->second->SetDecoded(); | 965 it->second->SetDecoded(); |
| 972 surfaces_at_device_.erase(it); | 966 surfaces_at_device_.erase(it); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 DVLOGF(4) << "Reusing input buffer, index=" << index; | 1019 DVLOGF(4) << "Reusing input buffer, index=" << index; |
| 1026 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1020 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1027 | 1021 |
| 1028 DCHECK_LT(index, static_cast<int>(input_buffer_map_.size())); | 1022 DCHECK_LT(index, static_cast<int>(input_buffer_map_.size())); |
| 1029 InputRecord& input_record = input_buffer_map_[index]; | 1023 InputRecord& input_record = input_buffer_map_[index]; |
| 1030 | 1024 |
| 1031 DCHECK(!input_record.at_device); | 1025 DCHECK(!input_record.at_device); |
| 1032 input_record.input_id = -1; | 1026 input_record.input_id = -1; |
| 1033 input_record.bytes_used = 0; | 1027 input_record.bytes_used = 0; |
| 1034 | 1028 |
| 1035 DCHECK_EQ(std::count(free_input_buffers_.begin(), free_input_buffers_.end(), | 1029 DCHECK_EQ( |
| 1036 index), 0); | 1030 std::count(free_input_buffers_.begin(), free_input_buffers_.end(), index), |
| 1031 0); |
| 1037 free_input_buffers_.push_back(index); | 1032 free_input_buffers_.push_back(index); |
| 1038 } | 1033 } |
| 1039 | 1034 |
| 1040 void V4L2SliceVideoDecodeAccelerator::ReuseOutputBuffer(int index) { | 1035 void V4L2SliceVideoDecodeAccelerator::ReuseOutputBuffer(int index) { |
| 1041 DVLOGF(4) << "Reusing output buffer, index=" << index; | 1036 DVLOGF(4) << "Reusing output buffer, index=" << index; |
| 1042 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1037 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1043 | 1038 |
| 1044 DCHECK_LT(index, static_cast<int>(output_buffer_map_.size())); | 1039 DCHECK_LT(index, static_cast<int>(output_buffer_map_.size())); |
| 1045 OutputRecord& output_record = output_buffer_map_[index]; | 1040 OutputRecord& output_record = output_buffer_map_[index]; |
| 1046 DCHECK(!output_record.at_device); | 1041 DCHECK(!output_record.at_device); |
| 1047 DCHECK(!output_record.at_client); | 1042 DCHECK(!output_record.at_client); |
| 1048 | 1043 |
| 1049 DCHECK_EQ(std::count(free_output_buffers_.begin(), free_output_buffers_.end(), | 1044 DCHECK_EQ(std::count(free_output_buffers_.begin(), free_output_buffers_.end(), |
| 1050 index), 0); | 1045 index), |
| 1046 0); |
| 1051 free_output_buffers_.push_back(index); | 1047 free_output_buffers_.push_back(index); |
| 1052 | 1048 |
| 1053 ScheduleDecodeBufferTaskIfNeeded(); | 1049 ScheduleDecodeBufferTaskIfNeeded(); |
| 1054 } | 1050 } |
| 1055 | 1051 |
| 1056 bool V4L2SliceVideoDecodeAccelerator::EnqueueInputRecord( | 1052 bool V4L2SliceVideoDecodeAccelerator::EnqueueInputRecord( |
| 1057 int index, | 1053 int index, |
| 1058 uint32_t config_store) { | 1054 uint32_t config_store) { |
| 1059 DVLOGF(3); | 1055 DVLOGF(3); |
| 1060 DCHECK_LT(index, static_cast<int>(input_buffer_map_.size())); | 1056 DCHECK_LT(index, static_cast<int>(input_buffer_map_.size())); |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1501 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffersTask( | 1497 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffersTask( |
| 1502 const std::vector<media::PictureBuffer>& buffers) { | 1498 const std::vector<media::PictureBuffer>& buffers) { |
| 1503 DVLOGF(3); | 1499 DVLOGF(3); |
| 1504 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1500 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1505 DCHECK_EQ(state_, kAwaitingPictureBuffers); | 1501 DCHECK_EQ(state_, kAwaitingPictureBuffers); |
| 1506 | 1502 |
| 1507 const uint32_t req_buffer_count = decoder_->GetRequiredNumOfPictures(); | 1503 const uint32_t req_buffer_count = decoder_->GetRequiredNumOfPictures(); |
| 1508 | 1504 |
| 1509 if (buffers.size() < req_buffer_count) { | 1505 if (buffers.size() < req_buffer_count) { |
| 1510 DLOG(ERROR) << "Failed to provide requested picture buffers. " | 1506 DLOG(ERROR) << "Failed to provide requested picture buffers. " |
| 1511 << "(Got " << buffers.size() | 1507 << "(Got " << buffers.size() << ", requested " |
| 1512 << ", requested " << req_buffer_count << ")"; | 1508 << req_buffer_count << ")"; |
| 1513 NOTIFY_ERROR(INVALID_ARGUMENT); | 1509 NOTIFY_ERROR(INVALID_ARGUMENT); |
| 1514 return; | 1510 return; |
| 1515 } | 1511 } |
| 1516 | 1512 |
| 1517 // Allocate the output buffers. | 1513 // Allocate the output buffers. |
| 1518 struct v4l2_requestbuffers reqbufs; | 1514 struct v4l2_requestbuffers reqbufs; |
| 1519 memset(&reqbufs, 0, sizeof(reqbufs)); | 1515 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1520 reqbufs.count = buffers.size(); | 1516 reqbufs.count = buffers.size(); |
| 1521 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1517 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1522 reqbufs.memory = | 1518 reqbufs.memory = |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1989 | 1985 |
| 1990 state_ = kError; | 1986 state_ = kError; |
| 1991 } | 1987 } |
| 1992 | 1988 |
| 1993 V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::V4L2H264Accelerator( | 1989 V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::V4L2H264Accelerator( |
| 1994 V4L2SliceVideoDecodeAccelerator* v4l2_dec) | 1990 V4L2SliceVideoDecodeAccelerator* v4l2_dec) |
| 1995 : num_slices_(0), v4l2_dec_(v4l2_dec) { | 1991 : num_slices_(0), v4l2_dec_(v4l2_dec) { |
| 1996 DCHECK(v4l2_dec_); | 1992 DCHECK(v4l2_dec_); |
| 1997 } | 1993 } |
| 1998 | 1994 |
| 1999 V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::~V4L2H264Accelerator() { | 1995 V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::~V4L2H264Accelerator() {} |
| 2000 } | |
| 2001 | 1996 |
| 2002 scoped_refptr<H264Picture> | 1997 scoped_refptr<H264Picture> |
| 2003 V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::CreateH264Picture() { | 1998 V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::CreateH264Picture() { |
| 2004 scoped_refptr<V4L2DecodeSurface> dec_surface = v4l2_dec_->CreateSurface(); | 1999 scoped_refptr<V4L2DecodeSurface> dec_surface = v4l2_dec_->CreateSurface(); |
| 2005 if (!dec_surface) | 2000 if (!dec_surface) |
| 2006 return nullptr; | 2001 return nullptr; |
| 2007 | 2002 |
| 2008 return new V4L2H264Picture(dec_surface); | 2003 return new V4L2H264Picture(dec_surface); |
| 2009 } | 2004 } |
| 2010 | 2005 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2058 const H264Picture::Vector& ref_pic_listp0, | 2053 const H264Picture::Vector& ref_pic_listp0, |
| 2059 const H264Picture::Vector& ref_pic_listb0, | 2054 const H264Picture::Vector& ref_pic_listb0, |
| 2060 const H264Picture::Vector& ref_pic_listb1, | 2055 const H264Picture::Vector& ref_pic_listb1, |
| 2061 const scoped_refptr<H264Picture>& pic) { | 2056 const scoped_refptr<H264Picture>& pic) { |
| 2062 struct v4l2_ext_control ctrl; | 2057 struct v4l2_ext_control ctrl; |
| 2063 std::vector<struct v4l2_ext_control> ctrls; | 2058 std::vector<struct v4l2_ext_control> ctrls; |
| 2064 | 2059 |
| 2065 struct v4l2_ctrl_h264_sps v4l2_sps; | 2060 struct v4l2_ctrl_h264_sps v4l2_sps; |
| 2066 memset(&v4l2_sps, 0, sizeof(v4l2_sps)); | 2061 memset(&v4l2_sps, 0, sizeof(v4l2_sps)); |
| 2067 v4l2_sps.constraint_set_flags = | 2062 v4l2_sps.constraint_set_flags = |
| 2068 sps->constraint_set0_flag ? V4L2_H264_SPS_CONSTRAINT_SET0_FLAG : 0 | | 2063 sps->constraint_set0_flag |
| 2069 sps->constraint_set1_flag ? V4L2_H264_SPS_CONSTRAINT_SET1_FLAG : 0 | | 2064 ? V4L2_H264_SPS_CONSTRAINT_SET0_FLAG |
| 2070 sps->constraint_set2_flag ? V4L2_H264_SPS_CONSTRAINT_SET2_FLAG : 0 | | 2065 : 0 | sps->constraint_set1_flag |
| 2071 sps->constraint_set3_flag ? V4L2_H264_SPS_CONSTRAINT_SET3_FLAG : 0 | | 2066 ? V4L2_H264_SPS_CONSTRAINT_SET1_FLAG |
| 2072 sps->constraint_set4_flag ? V4L2_H264_SPS_CONSTRAINT_SET4_FLAG : 0 | | 2067 : 0 | sps->constraint_set2_flag |
| 2073 sps->constraint_set5_flag ? V4L2_H264_SPS_CONSTRAINT_SET5_FLAG : 0; | 2068 ? V4L2_H264_SPS_CONSTRAINT_SET2_FLAG |
| 2069 : 0 | sps->constraint_set3_flag |
| 2070 ? V4L2_H264_SPS_CONSTRAINT_SET3_FLAG |
| 2071 : 0 | sps->constraint_set4_flag |
| 2072 ? V4L2_H264_SPS_CONSTRAINT_SET4_FLAG |
| 2073 : 0 | sps->constraint_set5_flag |
| 2074 ? V4L2_H264_SPS_CONSTRAINT_SET5_FLAG |
| 2075 : 0; |
| 2074 #define SPS_TO_V4L2SPS(a) v4l2_sps.a = sps->a | 2076 #define SPS_TO_V4L2SPS(a) v4l2_sps.a = sps->a |
| 2075 SPS_TO_V4L2SPS(profile_idc); | 2077 SPS_TO_V4L2SPS(profile_idc); |
| 2076 SPS_TO_V4L2SPS(level_idc); | 2078 SPS_TO_V4L2SPS(level_idc); |
| 2077 SPS_TO_V4L2SPS(seq_parameter_set_id); | 2079 SPS_TO_V4L2SPS(seq_parameter_set_id); |
| 2078 SPS_TO_V4L2SPS(chroma_format_idc); | 2080 SPS_TO_V4L2SPS(chroma_format_idc); |
| 2079 SPS_TO_V4L2SPS(bit_depth_luma_minus8); | 2081 SPS_TO_V4L2SPS(bit_depth_luma_minus8); |
| 2080 SPS_TO_V4L2SPS(bit_depth_chroma_minus8); | 2082 SPS_TO_V4L2SPS(bit_depth_chroma_minus8); |
| 2081 SPS_TO_V4L2SPS(log2_max_frame_num_minus4); | 2083 SPS_TO_V4L2SPS(log2_max_frame_num_minus4); |
| 2082 SPS_TO_V4L2SPS(pic_order_cnt_type); | 2084 SPS_TO_V4L2SPS(pic_order_cnt_type); |
| 2083 SPS_TO_V4L2SPS(log2_max_pic_order_cnt_lsb_minus4); | 2085 SPS_TO_V4L2SPS(log2_max_pic_order_cnt_lsb_minus4); |
| 2084 SPS_TO_V4L2SPS(offset_for_non_ref_pic); | 2086 SPS_TO_V4L2SPS(offset_for_non_ref_pic); |
| 2085 SPS_TO_V4L2SPS(offset_for_top_to_bottom_field); | 2087 SPS_TO_V4L2SPS(offset_for_top_to_bottom_field); |
| 2086 SPS_TO_V4L2SPS(num_ref_frames_in_pic_order_cnt_cycle); | 2088 SPS_TO_V4L2SPS(num_ref_frames_in_pic_order_cnt_cycle); |
| 2087 | 2089 |
| 2088 static_assert(arraysize(v4l2_sps.offset_for_ref_frame) == | 2090 static_assert(arraysize(v4l2_sps.offset_for_ref_frame) == |
| 2089 arraysize(sps->offset_for_ref_frame), | 2091 arraysize(sps->offset_for_ref_frame), |
| 2090 "offset_for_ref_frame arrays must be same size"); | 2092 "offset_for_ref_frame arrays must be same size"); |
| 2091 for (size_t i = 0; i < arraysize(v4l2_sps.offset_for_ref_frame); ++i) | 2093 for (size_t i = 0; i < arraysize(v4l2_sps.offset_for_ref_frame); ++i) |
| 2092 v4l2_sps.offset_for_ref_frame[i] = sps->offset_for_ref_frame[i]; | 2094 v4l2_sps.offset_for_ref_frame[i] = sps->offset_for_ref_frame[i]; |
| 2093 SPS_TO_V4L2SPS(max_num_ref_frames); | 2095 SPS_TO_V4L2SPS(max_num_ref_frames); |
| 2094 SPS_TO_V4L2SPS(pic_width_in_mbs_minus1); | 2096 SPS_TO_V4L2SPS(pic_width_in_mbs_minus1); |
| 2095 SPS_TO_V4L2SPS(pic_height_in_map_units_minus1); | 2097 SPS_TO_V4L2SPS(pic_height_in_map_units_minus1); |
| 2096 #undef SPS_TO_V4L2SPS | 2098 #undef SPS_TO_V4L2SPS |
| 2097 | 2099 |
| 2098 #define SET_V4L2_SPS_FLAG_IF(cond, flag) \ | 2100 #define SET_V4L2_SPS_FLAG_IF(cond, flag) \ |
| 2099 v4l2_sps.flags |= ((sps->cond) ? (flag) : 0) | 2101 v4l2_sps.flags |= ((sps->cond) ? (flag) : 0) |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2153 #undef SET_V4L2_PPS_FLAG_IF | 2155 #undef SET_V4L2_PPS_FLAG_IF |
| 2154 memset(&ctrl, 0, sizeof(ctrl)); | 2156 memset(&ctrl, 0, sizeof(ctrl)); |
| 2155 ctrl.id = V4L2_CID_MPEG_VIDEO_H264_PPS; | 2157 ctrl.id = V4L2_CID_MPEG_VIDEO_H264_PPS; |
| 2156 ctrl.size = sizeof(v4l2_pps); | 2158 ctrl.size = sizeof(v4l2_pps); |
| 2157 ctrl.p_h264_pps = &v4l2_pps; | 2159 ctrl.p_h264_pps = &v4l2_pps; |
| 2158 ctrls.push_back(ctrl); | 2160 ctrls.push_back(ctrl); |
| 2159 | 2161 |
| 2160 struct v4l2_ctrl_h264_scaling_matrix v4l2_scaling_matrix; | 2162 struct v4l2_ctrl_h264_scaling_matrix v4l2_scaling_matrix; |
| 2161 memset(&v4l2_scaling_matrix, 0, sizeof(v4l2_scaling_matrix)); | 2163 memset(&v4l2_scaling_matrix, 0, sizeof(v4l2_scaling_matrix)); |
| 2162 static_assert(arraysize(v4l2_scaling_matrix.scaling_list_4x4) <= | 2164 static_assert(arraysize(v4l2_scaling_matrix.scaling_list_4x4) <= |
| 2163 arraysize(pps->scaling_list4x4) && | 2165 arraysize(pps->scaling_list4x4) && |
| 2164 arraysize(v4l2_scaling_matrix.scaling_list_4x4[0]) <= | 2166 arraysize(v4l2_scaling_matrix.scaling_list_4x4[0]) <= |
| 2165 arraysize(pps->scaling_list4x4[0]) && | 2167 arraysize(pps->scaling_list4x4[0]) && |
| 2166 arraysize(v4l2_scaling_matrix.scaling_list_8x8) <= | 2168 arraysize(v4l2_scaling_matrix.scaling_list_8x8) <= |
| 2167 arraysize(pps->scaling_list8x8) && | 2169 arraysize(pps->scaling_list8x8) && |
| 2168 arraysize(v4l2_scaling_matrix.scaling_list_8x8[0]) <= | 2170 arraysize(v4l2_scaling_matrix.scaling_list_8x8[0]) <= |
| 2169 arraysize(pps->scaling_list8x8[0]), | 2171 arraysize(pps->scaling_list8x8[0]), |
| 2170 "scaling_lists must be of correct size"); | 2172 "scaling_lists must be of correct size"); |
| 2171 for (size_t i = 0; i < arraysize(v4l2_scaling_matrix.scaling_list_4x4); ++i) { | 2173 for (size_t i = 0; i < arraysize(v4l2_scaling_matrix.scaling_list_4x4); ++i) { |
| 2172 for (size_t j = 0; j < arraysize(v4l2_scaling_matrix.scaling_list_4x4[i]); | 2174 for (size_t j = 0; j < arraysize(v4l2_scaling_matrix.scaling_list_4x4[i]); |
| 2173 ++j) { | 2175 ++j) { |
| 2174 v4l2_scaling_matrix.scaling_list_4x4[i][j] = pps->scaling_list4x4[i][j]; | 2176 v4l2_scaling_matrix.scaling_list_4x4[i][j] = pps->scaling_list4x4[i][j]; |
| 2175 } | 2177 } |
| 2176 } | 2178 } |
| 2177 for (size_t i = 0; i < arraysize(v4l2_scaling_matrix.scaling_list_8x8); ++i) { | 2179 for (size_t i = 0; i < arraysize(v4l2_scaling_matrix.scaling_list_8x8); ++i) { |
| 2178 for (size_t j = 0; j < arraysize(v4l2_scaling_matrix.scaling_list_8x8[i]); | 2180 for (size_t j = 0; j < arraysize(v4l2_scaling_matrix.scaling_list_8x8[i]); |
| 2179 ++j) { | 2181 ++j) { |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2416 CHECK(v4l2_pic); | 2418 CHECK(v4l2_pic); |
| 2417 return v4l2_pic->dec_surface(); | 2419 return v4l2_pic->dec_surface(); |
| 2418 } | 2420 } |
| 2419 | 2421 |
| 2420 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::V4L2VP8Accelerator( | 2422 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::V4L2VP8Accelerator( |
| 2421 V4L2SliceVideoDecodeAccelerator* v4l2_dec) | 2423 V4L2SliceVideoDecodeAccelerator* v4l2_dec) |
| 2422 : v4l2_dec_(v4l2_dec) { | 2424 : v4l2_dec_(v4l2_dec) { |
| 2423 DCHECK(v4l2_dec_); | 2425 DCHECK(v4l2_dec_); |
| 2424 } | 2426 } |
| 2425 | 2427 |
| 2426 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::~V4L2VP8Accelerator() { | 2428 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::~V4L2VP8Accelerator() {} |
| 2427 } | |
| 2428 | 2429 |
| 2429 scoped_refptr<VP8Picture> | 2430 scoped_refptr<VP8Picture> |
| 2430 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::CreateVP8Picture() { | 2431 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::CreateVP8Picture() { |
| 2431 scoped_refptr<V4L2DecodeSurface> dec_surface = v4l2_dec_->CreateSurface(); | 2432 scoped_refptr<V4L2DecodeSurface> dec_surface = v4l2_dec_->CreateSurface(); |
| 2432 if (!dec_surface) | 2433 if (!dec_surface) |
| 2433 return nullptr; | 2434 return nullptr; |
| 2434 | 2435 |
| 2435 return new V4L2VP8Picture(dec_surface); | 2436 return new V4L2VP8Picture(dec_surface); |
| 2436 } | 2437 } |
| 2437 | 2438 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2499 | 2500 |
| 2500 static void FillV4L2EntropyHeader( | 2501 static void FillV4L2EntropyHeader( |
| 2501 const media::Vp8EntropyHeader& vp8_entropy_hdr, | 2502 const media::Vp8EntropyHeader& vp8_entropy_hdr, |
| 2502 struct v4l2_vp8_entropy_hdr* v4l2_entropy_hdr) { | 2503 struct v4l2_vp8_entropy_hdr* v4l2_entropy_hdr) { |
| 2503 ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->coeff_probs, | 2504 ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->coeff_probs, |
| 2504 vp8_entropy_hdr.coeff_probs); | 2505 vp8_entropy_hdr.coeff_probs); |
| 2505 ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->y_mode_probs, | 2506 ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->y_mode_probs, |
| 2506 vp8_entropy_hdr.y_mode_probs); | 2507 vp8_entropy_hdr.y_mode_probs); |
| 2507 ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->uv_mode_probs, | 2508 ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->uv_mode_probs, |
| 2508 vp8_entropy_hdr.uv_mode_probs); | 2509 vp8_entropy_hdr.uv_mode_probs); |
| 2509 ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->mv_probs, | 2510 ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->mv_probs, vp8_entropy_hdr.mv_probs); |
| 2510 vp8_entropy_hdr.mv_probs); | |
| 2511 } | 2511 } |
| 2512 | 2512 |
| 2513 bool V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::SubmitDecode( | 2513 bool V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::SubmitDecode( |
| 2514 const scoped_refptr<VP8Picture>& pic, | 2514 const scoped_refptr<VP8Picture>& pic, |
| 2515 const media::Vp8FrameHeader* frame_hdr, | 2515 const media::Vp8FrameHeader* frame_hdr, |
| 2516 const scoped_refptr<VP8Picture>& last_frame, | 2516 const scoped_refptr<VP8Picture>& last_frame, |
| 2517 const scoped_refptr<VP8Picture>& golden_frame, | 2517 const scoped_refptr<VP8Picture>& golden_frame, |
| 2518 const scoped_refptr<VP8Picture>& alt_frame) { | 2518 const scoped_refptr<VP8Picture>& alt_frame) { |
| 2519 struct v4l2_ctrl_vp8_frame_hdr v4l2_frame_hdr; | 2519 struct v4l2_ctrl_vp8_frame_hdr v4l2_frame_hdr; |
| 2520 memset(&v4l2_frame_hdr, 0, sizeof(v4l2_frame_hdr)); | 2520 memset(&v4l2_frame_hdr, 0, sizeof(v4l2_frame_hdr)); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2558 | 2558 |
| 2559 v4l2_frame_hdr.first_part_size = | 2559 v4l2_frame_hdr.first_part_size = |
| 2560 base::checked_cast<__u32>(frame_hdr->first_part_size); | 2560 base::checked_cast<__u32>(frame_hdr->first_part_size); |
| 2561 v4l2_frame_hdr.first_part_offset = | 2561 v4l2_frame_hdr.first_part_offset = |
| 2562 base::checked_cast<__u32>(frame_hdr->first_part_offset); | 2562 base::checked_cast<__u32>(frame_hdr->first_part_offset); |
| 2563 v4l2_frame_hdr.macroblock_bit_offset = | 2563 v4l2_frame_hdr.macroblock_bit_offset = |
| 2564 base::checked_cast<__u32>(frame_hdr->macroblock_bit_offset); | 2564 base::checked_cast<__u32>(frame_hdr->macroblock_bit_offset); |
| 2565 v4l2_frame_hdr.num_dct_parts = frame_hdr->num_of_dct_partitions; | 2565 v4l2_frame_hdr.num_dct_parts = frame_hdr->num_of_dct_partitions; |
| 2566 | 2566 |
| 2567 static_assert(arraysize(v4l2_frame_hdr.dct_part_sizes) == | 2567 static_assert(arraysize(v4l2_frame_hdr.dct_part_sizes) == |
| 2568 arraysize(frame_hdr->dct_partition_sizes), | 2568 arraysize(frame_hdr->dct_partition_sizes), |
| 2569 "DCT partition size arrays must have equal number of elements"); | 2569 "DCT partition size arrays must have equal number of elements"); |
| 2570 for (size_t i = 0; i < frame_hdr->num_of_dct_partitions && | 2570 for (size_t i = 0; i < frame_hdr->num_of_dct_partitions && |
| 2571 i < arraysize(v4l2_frame_hdr.dct_part_sizes); ++i) | 2571 i < arraysize(v4l2_frame_hdr.dct_part_sizes); |
| 2572 ++i) |
| 2572 v4l2_frame_hdr.dct_part_sizes[i] = frame_hdr->dct_partition_sizes[i]; | 2573 v4l2_frame_hdr.dct_part_sizes[i] = frame_hdr->dct_partition_sizes[i]; |
| 2573 | 2574 |
| 2574 scoped_refptr<V4L2DecodeSurface> dec_surface = | 2575 scoped_refptr<V4L2DecodeSurface> dec_surface = |
| 2575 VP8PictureToV4L2DecodeSurface(pic); | 2576 VP8PictureToV4L2DecodeSurface(pic); |
| 2576 std::vector<scoped_refptr<V4L2DecodeSurface>> ref_surfaces; | 2577 std::vector<scoped_refptr<V4L2DecodeSurface>> ref_surfaces; |
| 2577 | 2578 |
| 2578 if (last_frame) { | 2579 if (last_frame) { |
| 2579 scoped_refptr<V4L2DecodeSurface> last_frame_surface = | 2580 scoped_refptr<V4L2DecodeSurface> last_frame_surface = |
| 2580 VP8PictureToV4L2DecodeSurface(last_frame); | 2581 VP8PictureToV4L2DecodeSurface(last_frame); |
| 2581 v4l2_frame_hdr.last_frame = last_frame_surface->output_record(); | 2582 v4l2_frame_hdr.last_frame = last_frame_surface->output_record(); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2675 } | 2676 } |
| 2676 | 2677 |
| 2677 void V4L2SliceVideoDecodeAccelerator::OutputSurface( | 2678 void V4L2SliceVideoDecodeAccelerator::OutputSurface( |
| 2678 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { | 2679 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { |
| 2679 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 2680 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 2680 | 2681 |
| 2681 OutputRecord& output_record = | 2682 OutputRecord& output_record = |
| 2682 output_buffer_map_[dec_surface->output_record()]; | 2683 output_buffer_map_[dec_surface->output_record()]; |
| 2683 | 2684 |
| 2684 bool inserted = | 2685 bool inserted = |
| 2685 surfaces_at_display_.insert(std::make_pair(output_record.picture_id, | 2686 surfaces_at_display_ |
| 2686 dec_surface)).second; | 2687 .insert(std::make_pair(output_record.picture_id, dec_surface)) |
| 2688 .second; |
| 2687 DCHECK(inserted); | 2689 DCHECK(inserted); |
| 2688 | 2690 |
| 2689 DCHECK(!output_record.at_client); | 2691 DCHECK(!output_record.at_client); |
| 2690 DCHECK(!output_record.at_device); | 2692 DCHECK(!output_record.at_device); |
| 2691 DCHECK_NE(output_record.picture_id, -1); | 2693 DCHECK_NE(output_record.picture_id, -1); |
| 2692 output_record.at_client = true; | 2694 output_record.at_client = true; |
| 2693 | 2695 |
| 2694 // TODO(posciak): Use visible size from decoder here instead | 2696 // TODO(posciak): Use visible size from decoder here instead |
| 2695 // (crbug.com/402760). Passing (0, 0) results in the client using the | 2697 // (crbug.com/402760). Passing (0, 0) results in the client using the |
| 2696 // visible size extracted from the container instead. | 2698 // visible size extracted from the container instead. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2802 media::VideoDecodeAccelerator::SupportedProfiles | 2804 media::VideoDecodeAccelerator::SupportedProfiles |
| 2803 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { | 2805 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { |
| 2804 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); | 2806 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); |
| 2805 if (!device) | 2807 if (!device) |
| 2806 return SupportedProfiles(); | 2808 return SupportedProfiles(); |
| 2807 | 2809 |
| 2808 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), | 2810 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), |
| 2809 supported_input_fourccs_); | 2811 supported_input_fourccs_); |
| 2810 } | 2812 } |
| 2811 | 2813 |
| 2812 } // namespace content | 2814 } // namespace media |
| OLD | NEW |