Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: content/common/gpu/media/v4l2_video_decode_accelerator.cc

Issue 137023008: Add support for Tegra V4L2 VDA (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed a small issue Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 <dlfcn.h> 5 #include <dlfcn.h>
6 #include <errno.h> 6 #include <errno.h>
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <libdrm/drm_fourcc.h> 8 #include <libdrm/drm_fourcc.h>
9 #include <linux/videodev2.h> 9 #include <linux/videodev2.h>
10 #include <poll.h> 10 #include <poll.h>
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 return false; 260 return false;
261 } 261 }
262 262
263 if (!CreateInputBuffers()) 263 if (!CreateInputBuffers())
264 return false; 264 return false;
265 265
266 // Output format has to be setup before streaming starts. 266 // Output format has to be setup before streaming starts.
267 struct v4l2_format format; 267 struct v4l2_format format;
268 memset(&format, 0, sizeof(format)); 268 memset(&format, 0, sizeof(format));
269 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 269 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
270 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; 270 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;
Pawel Osciak 2014/03/25 08:21:08 I think we discussed before that this should be fi
271 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); 271 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
272 272
273 memset(&current_format_, 0, sizeof(current_format_));
274
273 // Subscribe to the resolution change event. 275 // Subscribe to the resolution change event.
274 struct v4l2_event_subscription sub; 276 struct v4l2_event_subscription sub;
275 memset(&sub, 0, sizeof(sub)); 277 memset(&sub, 0, sizeof(sub));
276 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; 278 sub.type = V4L2_EVENT_RESOLUTION_CHANGE;
277 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub); 279 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub);
278 280
279 // Initialize format-specific bits. 281 // Initialize format-specific bits.
280 if (video_profile_ >= media::H264PROFILE_MIN && 282 if (video_profile_ >= media::H264PROFILE_MIN &&
281 video_profile_ <= media::H264PROFILE_MAX) { 283 video_profile_ <= media::H264PROFILE_MAX) {
282 decoder_h264_parser_.reset(new media::H264Parser()); 284 decoder_h264_parser_.reset(new media::H264Parser());
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); 355 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
354 DCHECK_EQ(output_record.picture_id, -1); 356 DCHECK_EQ(output_record.picture_id, -1);
355 DCHECK_EQ(output_record.cleared, false); 357 DCHECK_EQ(output_record.cleared, false);
356 358
357 attrs[7] = output_record.fds[0]; 359 attrs[7] = output_record.fds[0];
358 attrs[9] = 0; 360 attrs[9] = 0;
359 attrs[11] = frame_buffer_size_.width(); 361 attrs[11] = frame_buffer_size_.width();
360 attrs[13] = output_record.fds[1]; 362 attrs[13] = output_record.fds[1];
361 attrs[15] = 0; 363 attrs[15] = 0;
362 attrs[17] = frame_buffer_size_.width(); 364 attrs[17] = frame_buffer_size_.width();
363 365 EGLImageKHR egl_image = device_->CreateEGLImage(
364 EGLImageKHR egl_image = eglCreateImageKHR( 366 egl_display_, attrs, buffers[i].texture_id(), i);
365 egl_display_, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrs);
366 if (egl_image == EGL_NO_IMAGE_KHR) { 367 if (egl_image == EGL_NO_IMAGE_KHR) {
367 DLOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; 368 DLOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR";
368 // Ownership of EGLImages allocated in previous iterations of this loop 369 // Ownership of EGLImages allocated in previous iterations of this loop
369 // has been transferred to output_buffer_map_. After we error-out here 370 // has been transferred to output_buffer_map_. After we error-out here
370 // the destructor will handle their cleanup. 371 // the destructor will handle their cleanup.
371 NOTIFY_ERROR(PLATFORM_FAILURE); 372 NOTIFY_ERROR(PLATFORM_FAILURE);
372 return; 373 return;
373 } 374 }
374 375
375 glBindTexture(GL_TEXTURE_EXTERNAL_OES, buffers[i].texture_id());
376 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image);
377
378 output_record.egl_image = egl_image; 376 output_record.egl_image = egl_image;
379 output_record.picture_id = buffers[i].id(); 377 output_record.picture_id = buffers[i].id();
380 free_output_buffers_.push(i); 378 free_output_buffers_.push(i);
381 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i 379 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i
382 << "]: picture_id=" << output_record.picture_id; 380 << "]: picture_id=" << output_record.picture_id;
383 } 381 }
384 382
385 pictures_assigned_.Signal(); 383 pictures_assigned_.Signal();
386 } 384 }
387 385
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 735
738 if (again) { 736 if (again) {
739 // Need more stream to decode format, return true and schedule next buffer. 737 // Need more stream to decode format, return true and schedule next buffer.
740 *endpos = size; 738 *endpos = size;
741 return true; 739 return true;
742 } 740 }
743 741
744 // Run this initialization only on first startup. 742 // Run this initialization only on first startup.
745 if (decoder_state_ == kInitialized) { 743 if (decoder_state_ == kInitialized) {
746 DVLOG(3) << "DecodeBufferInitial(): running initialization"; 744 DVLOG(3) << "DecodeBufferInitial(): running initialization";
745 current_format_ = format;
Pawel Osciak 2014/03/25 08:21:08 Please move this to the CreateBuffersForFormat cal
747 // Success! Setup our parameters. 746 // Success! Setup our parameters.
748 if (!CreateBuffersForFormat(format)) 747 if (!CreateBuffersForFormat(format))
749 return false; 748 return false;
750 749
751 // We expect to process the initial buffer once during stream init to 750 // We expect to process the initial buffer once during stream init to
752 // configure stream parameters, but will not consume the steam data on that 751 // configure stream parameters, but will not consume the steam data on that
753 // iteration. Subsequent iterations (including after reset) do not require 752 // iteration. Subsequent iterations (including after reset) do not require
754 // the stream init step. 753 // the stream init step.
755 *endpos = 0; 754 *endpos = 0;
756 } else { 755 } else {
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 DCHECK_NE(decoder_state_, kUninitialized); 997 DCHECK_NE(decoder_state_, kUninitialized);
999 DVLOG(3) << "DequeueEvents()"; 998 DVLOG(3) << "DequeueEvents()";
1000 999
1001 struct v4l2_event ev; 1000 struct v4l2_event ev;
1002 memset(&ev, 0, sizeof(ev)); 1001 memset(&ev, 0, sizeof(ev));
1003 1002
1004 while (device_->Ioctl(VIDIOC_DQEVENT, &ev) == 0) { 1003 while (device_->Ioctl(VIDIOC_DQEVENT, &ev) == 0) {
1005 if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) { 1004 if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) {
1006 DVLOG(3) << "DequeueEvents(): got resolution change event."; 1005 DVLOG(3) << "DequeueEvents(): got resolution change event.";
1007 DCHECK(!resolution_change_pending_); 1006 DCHECK(!resolution_change_pending_);
1008 resolution_change_pending_ = true; 1007 // Check if we already have current_format_ set or this is an event
Pawel Osciak 2014/03/25 08:21:08 s/or this/or if this/
shivdasp 2014/03/25 10:36:40 Done.
1008 // to trigger decoder initialization.
1009 if ((current_format_.fmt.pix_mp.width == 0) ||
Pawel Osciak 2014/03/25 08:21:08 Since you are using the format only for size, I th
shivdasp 2014/03/25 10:36:40 Done.
1010 (current_format_.fmt.pix_mp.height == 0)) {
1011 DVLOG(3) << "DequeueEvents(): Decoder init through resolution change ";
1012 resolution_change_pending_ = true;
1013 } else if (IsResolutionChangeNecessary()) {
Pawel Osciak 2014/03/25 08:21:08 Also, IsResolutionChangeNecessary() should handle
1014 DVLOG(3) << "DequeueEvents(): Resolution change event detected ";
1015 resolution_change_pending_ = true;
1016 }
1009 } else { 1017 } else {
1010 DLOG(FATAL) << "DequeueEvents(): got an event (" << ev.type 1018 DLOG(FATAL) << "DequeueEvents(): got an event (" << ev.type
1011 << ") we haven't subscribed to."; 1019 << ") we haven't subscribed to.";
1012 } 1020 }
1013 } 1021 }
1014 } 1022 }
1015 1023
1016 void V4L2VideoDecodeAccelerator::Dequeue() { 1024 void V4L2VideoDecodeAccelerator::Dequeue() {
1017 DVLOG(3) << "Dequeue()"; 1025 DVLOG(3) << "Dequeue()";
1018 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1026 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after
1529 } 1537 }
1530 1538
1531 struct v4l2_format format; 1539 struct v4l2_format format;
1532 bool again; 1540 bool again;
1533 bool ret = GetFormatInfo(&format, &again); 1541 bool ret = GetFormatInfo(&format, &again);
1534 if (!ret || again) { 1542 if (!ret || again) {
1535 DVLOG(3) << "Couldn't get format information after resolution change"; 1543 DVLOG(3) << "Couldn't get format information after resolution change";
1536 NOTIFY_ERROR(PLATFORM_FAILURE); 1544 NOTIFY_ERROR(PLATFORM_FAILURE);
1537 return; 1545 return;
1538 } 1546 }
1539 1547 // Store this new format.
1548 current_format_ = format;
1540 if (!CreateBuffersForFormat(format)) { 1549 if (!CreateBuffersForFormat(format)) {
1541 DVLOG(3) << "Couldn't reallocate buffers after resolution change"; 1550 DVLOG(3) << "Couldn't reallocate buffers after resolution change";
1542 NOTIFY_ERROR(PLATFORM_FAILURE); 1551 NOTIFY_ERROR(PLATFORM_FAILURE);
1543 return; 1552 return;
1544 } 1553 }
1545 1554
1546 decoder_state_ = kDecoding; 1555 decoder_state_ = kDecoding;
1547 1556
1548 if (resolution_change_reset_pending_) { 1557 if (resolution_change_reset_pending_) {
1549 resolution_change_reset_pending_ = false; 1558 resolution_change_reset_pending_ = false;
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1752 1761
1753 DVLOG(3) << "CreateOutputBuffers(): ProvidePictureBuffers(): " 1762 DVLOG(3) << "CreateOutputBuffers(): ProvidePictureBuffers(): "
1754 << "buffer_count=" << output_buffer_map_.size() 1763 << "buffer_count=" << output_buffer_map_.size()
1755 << ", width=" << frame_buffer_size_.width() 1764 << ", width=" << frame_buffer_size_.width()
1756 << ", height=" << frame_buffer_size_.height(); 1765 << ", height=" << frame_buffer_size_.height();
1757 child_message_loop_proxy_->PostTask(FROM_HERE, 1766 child_message_loop_proxy_->PostTask(FROM_HERE,
1758 base::Bind(&Client::ProvidePictureBuffers, 1767 base::Bind(&Client::ProvidePictureBuffers,
1759 client_, 1768 client_,
1760 output_buffer_map_.size(), 1769 output_buffer_map_.size(),
1761 frame_buffer_size_, 1770 frame_buffer_size_,
1762 GL_TEXTURE_EXTERNAL_OES)); 1771 device_->GetTextureTarget()));
1763 1772
1764 // Wait for the client to call AssignPictureBuffers() on the Child thread. 1773 // Wait for the client to call AssignPictureBuffers() on the Child thread.
1765 // We do this, because if we continue decoding without finishing buffer 1774 // We do this, because if we continue decoding without finishing buffer
1766 // allocation, we may end up Resetting before AssignPictureBuffers arrives, 1775 // allocation, we may end up Resetting before AssignPictureBuffers arrives,
1767 // resulting in unnecessary complications and subtle bugs. 1776 // resulting in unnecessary complications and subtle bugs.
1768 // For example, if the client calls Decode(Input1), Reset(), Decode(Input2) 1777 // For example, if the client calls Decode(Input1), Reset(), Decode(Input2)
1769 // in a sequence, and Decode(Input1) results in us getting here and exiting 1778 // in a sequence, and Decode(Input1) results in us getting here and exiting
1770 // without waiting, we might end up running Reset{,Done}Task() before 1779 // without waiting, we might end up running Reset{,Done}Task() before
1771 // AssignPictureBuffers is scheduled, thus cleaning up and pushing buffers 1780 // AssignPictureBuffers is scheduled, thus cleaning up and pushing buffers
1772 // to the free_output_buffers_ map twice. If we somehow marked buffers as 1781 // to the free_output_buffers_ map twice. If we somehow marked buffers as
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1919 } 1928 }
1920 1929
1921 void V4L2VideoDecodeAccelerator::PictureCleared() { 1930 void V4L2VideoDecodeAccelerator::PictureCleared() {
1922 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; 1931 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_;
1923 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1932 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1924 DCHECK_GT(picture_clearing_count_, 0); 1933 DCHECK_GT(picture_clearing_count_, 0);
1925 picture_clearing_count_--; 1934 picture_clearing_count_--;
1926 SendPictureReady(); 1935 SendPictureReady();
1927 } 1936 }
1928 1937
1938 bool V4L2VideoDecodeAccelerator::IsResolutionChangeNecessary() {
1939 DVLOG(3) << "IsResolutionChangeNecessary() ";
1940 struct v4l2_control ctrl;
1941 memset(&ctrl, 0, sizeof(ctrl));
1942 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
1943 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_CTRL, &ctrl);
1944 if (ctrl.value != output_dpb_size_)
1945 return true;
1946 struct v4l2_format format;
1947 bool again = false;
1948 bool ret = GetFormatInfo(&format, &again);
1949 if (!ret || again) {
1950 DVLOG(3) << "IsResolutionChangeNecessary(): GetFormatInfo() failed";
1951 NOTIFY_ERROR(PLATFORM_FAILURE);
Pawel Osciak 2014/03/25 08:21:08 This means we will send NOTIFY_ERROR twice in case
shivdasp 2014/03/25 10:36:40 Since GetFormatInfo() does NOTIFY_ERROR already I
1952 return false;
1953 }
1954 if ((format.fmt.pix_mp.width != current_format_.fmt.pix_mp.width) ||
1955 (format.fmt.pix_mp.height != current_format_.fmt.pix_mp.height)) {
1956 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected";
1957 current_format_ = format;
Pawel Osciak 2014/03/25 08:21:08 If you are doing this here, then there is no need
1958 return true;
1959 } else {
1960 DVLOG(3) << "IsResolutionChangeNecessary(): Dropping resolution change";
Pawel Osciak 2014/03/25 08:21:08 No need for the else clause, just move it out plea
shivdasp 2014/03/25 10:36:40 Done.
1961 }
1962 return false;
1963 }
1964
1929 } // namespace content 1965 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698