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

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

Issue 2335573002: V4L2VideoDecodeAccelerator: destroy buffers in decoder thread. (Closed)
Patch Set: rebase Created 4 years, 3 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 "media/gpu/v4l2_video_decode_accelerator.h" 5 #include "media/gpu/v4l2_video_decode_accelerator.h"
6 6
7 #include <dlfcn.h> 7 #include <dlfcn.h>
8 #include <errno.h> 8 #include <errno.h>
9 #include <fcntl.h> 9 #include <fcntl.h>
10 #include <linux/videodev2.h> 10 #include <linux/videodev2.h>
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 egl_image_format_fourcc_(0), 179 egl_image_format_fourcc_(0),
180 egl_image_planes_count_(0), 180 egl_image_planes_count_(0),
181 weak_this_factory_(this) { 181 weak_this_factory_(this) {
182 weak_this_ = weak_this_factory_.GetWeakPtr(); 182 weak_this_ = weak_this_factory_.GetWeakPtr();
183 } 183 }
184 184
185 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() { 185 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() {
186 DCHECK(!decoder_thread_.IsRunning()); 186 DCHECK(!decoder_thread_.IsRunning());
187 DCHECK(!device_poll_thread_.IsRunning()); 187 DCHECK(!device_poll_thread_.IsRunning());
188 188
189 DestroyInputBuffers();
190 DestroyOutputBuffers();
191
192 // These maps have members that should be manually destroyed, e.g. file 189 // These maps have members that should be manually destroyed, e.g. file
193 // descriptors, mmap() segments, etc. 190 // descriptors, mmap() segments, etc.
194 DCHECK(input_buffer_map_.empty()); 191 DCHECK(input_buffer_map_.empty());
195 DCHECK(output_buffer_map_.empty()); 192 DCHECK(output_buffer_map_.empty());
196 } 193 }
197 194
198 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, 195 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config,
199 Client* client) { 196 Client* client) {
200 DVLOGF(3) << "profile: " << config.profile; 197 DVLOGF(3) << "profile: " << config.profile;
201 DCHECK(child_task_runner_->BelongsToCurrentThread()); 198 DCHECK(child_task_runner_->BelongsToCurrentThread());
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 } 422 }
426 423
427 EGLImageKHR egl_image = egl_image_device_->CreateEGLImage( 424 EGLImageKHR egl_image = egl_image_device_->CreateEGLImage(
428 egl_display_, gl_context->GetHandle(), buffers[i].texture_ids()[0], 425 egl_display_, gl_context->GetHandle(), buffers[i].texture_ids()[0],
429 buffers[i].size(), i, egl_image_format_fourcc_, dmabuf_fds); 426 buffers[i].size(), i, egl_image_format_fourcc_, dmabuf_fds);
430 if (egl_image == EGL_NO_IMAGE_KHR) { 427 if (egl_image == EGL_NO_IMAGE_KHR) {
431 LOGF(ERROR) << "could not create EGLImageKHR," 428 LOGF(ERROR) << "could not create EGLImageKHR,"
432 << " index=" << i 429 << " index=" << i
433 << " texture_id=" << buffers[i].texture_ids()[0]; 430 << " texture_id=" << buffers[i].texture_ids()[0];
434 for (EGLImageKHR image : egl_images) { 431 for (EGLImageKHR image : egl_images) {
435 if (egl_image_device_->DestroyEGLImage(egl_display_, image) != EGL_TRUE) 432 egl_image_device_->DestroyEGLImage(egl_display_, image);
436 DVLOGF(1) << "DestroyEGLImage failed.";
437 } 433 }
438 NOTIFY_ERROR(PLATFORM_FAILURE); 434 NOTIFY_ERROR(PLATFORM_FAILURE);
439 return; 435 return;
440 } 436 }
441 egl_images.push_back(egl_image); 437 egl_images.push_back(egl_image);
442 } 438 }
443 439
444 decoder_thread_.task_runner()->PostTask( 440 decoder_thread_.task_runner()->PostTask(
445 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::AssignEGLImages, 441 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::AssignEGLImages,
446 base::Unretained(this), buffers, egl_images)); 442 base::Unretained(this), buffers, egl_images));
(...skipping 1122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 decoder_frames_at_client_ = 0; 1565 decoder_frames_at_client_ = 0;
1570 while (!decoder_input_queue_.empty()) 1566 while (!decoder_input_queue_.empty())
1571 decoder_input_queue_.pop(); 1567 decoder_input_queue_.pop();
1572 decoder_flushing_ = false; 1568 decoder_flushing_ = false;
1573 1569
1574 if (image_processor_) 1570 if (image_processor_)
1575 image_processor_.release()->Destroy(); 1571 image_processor_.release()->Destroy();
1576 1572
1577 // Set our state to kError. Just in case. 1573 // Set our state to kError. Just in case.
1578 decoder_state_ = kError; 1574 decoder_state_ = kError;
1575
1576 DestroyInputBuffers();
1577 DestroyOutputBuffers();
1579 } 1578 }
1580 1579
1581 bool V4L2VideoDecodeAccelerator::StartDevicePoll() { 1580 bool V4L2VideoDecodeAccelerator::StartDevicePoll() {
1582 DVLOGF(3); 1581 DVLOGF(3);
1583 DCHECK(!device_poll_thread_.IsRunning()); 1582 DCHECK(!device_poll_thread_.IsRunning());
1584 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 1583 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
1585 1584
1586 // Start up the device poll thread and schedule its first DevicePollTask(). 1585 // Start up the device poll thread and schedule its first DevicePollTask().
1587 if (!device_poll_thread_.Start()) { 1586 if (!device_poll_thread_.Start()) {
1588 LOGF(ERROR) << "Device thread failed to start"; 1587 LOGF(ERROR) << "Device thread failed to start";
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1682 decoder_state_ = kChangingResolution; 1681 decoder_state_ = kChangingResolution;
1683 1682
1684 if (!image_processor_bitstream_buffer_ids_.empty()) { 1683 if (!image_processor_bitstream_buffer_ids_.empty()) {
1685 DVLOGF(3) << "Wait image processor to finish before destroying buffers."; 1684 DVLOGF(3) << "Wait image processor to finish before destroying buffers.";
1686 return; 1685 return;
1687 } 1686 }
1688 1687
1689 if (image_processor_) 1688 if (image_processor_)
1690 image_processor_.release()->Destroy(); 1689 image_processor_.release()->Destroy();
1691 1690
1692 // Post a task to clean up buffers on child thread. This will also ensure 1691 if (!DestroyOutputBuffers()) {
1693 // that we won't accept ReusePictureBuffer() anymore after that. 1692 LOGF(ERROR) << "Failed destroying output buffers.";
1694 child_task_runner_->PostTask( 1693 NOTIFY_ERROR(PLATFORM_FAILURE);
1695 FROM_HERE, 1694 return;
1696 base::Bind(&V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers, 1695 }
1697 weak_this_)); 1696
1697 FinishResolutionChange();
1698 } 1698 }
1699 1699
1700 void V4L2VideoDecodeAccelerator::FinishResolutionChange() { 1700 void V4L2VideoDecodeAccelerator::FinishResolutionChange() {
1701 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 1701 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
1702 DCHECK_EQ(decoder_state_, kChangingResolution); 1702 DCHECK_EQ(decoder_state_, kChangingResolution);
1703 DVLOGF(3); 1703 DVLOGF(3);
1704 1704
1705 if (decoder_state_ == kError) { 1705 if (decoder_state_ == kError) {
1706 DVLOGF(2) << "early out: kError state"; 1706 DVLOGF(2) << "early out: kError state";
1707 return; 1707 return;
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
2117 // done with this one. After we get the buffers, we'll go back into kIdle and 2117 // done with this one. After we get the buffers, we'll go back into kIdle and
2118 // kick off further event processing, and eventually go back into kDecoding 2118 // kick off further event processing, and eventually go back into kDecoding
2119 // once no more events are pending (if any). 2119 // once no more events are pending (if any).
2120 decoder_state_ = kAwaitingPictureBuffers; 2120 decoder_state_ = kAwaitingPictureBuffers;
2121 2121
2122 return true; 2122 return true;
2123 } 2123 }
2124 2124
2125 void V4L2VideoDecodeAccelerator::DestroyInputBuffers() { 2125 void V4L2VideoDecodeAccelerator::DestroyInputBuffers() {
2126 DVLOGF(3); 2126 DVLOGF(3);
2127 DCHECK(child_task_runner_->BelongsToCurrentThread()); 2127 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
2128 DCHECK(!input_streamon_); 2128 DCHECK(!input_streamon_);
2129 2129
2130 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { 2130 for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
2131 if (input_buffer_map_[i].address != NULL) { 2131 if (input_buffer_map_[i].address != NULL) {
2132 device_->Munmap(input_buffer_map_[i].address, 2132 device_->Munmap(input_buffer_map_[i].address,
2133 input_buffer_map_[i].length); 2133 input_buffer_map_[i].length);
2134 } 2134 }
2135 } 2135 }
2136 2136
2137 struct v4l2_requestbuffers reqbufs; 2137 struct v4l2_requestbuffers reqbufs;
2138 memset(&reqbufs, 0, sizeof(reqbufs)); 2138 memset(&reqbufs, 0, sizeof(reqbufs));
2139 reqbufs.count = 0; 2139 reqbufs.count = 0;
2140 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 2140 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2141 reqbufs.memory = V4L2_MEMORY_MMAP; 2141 reqbufs.memory = V4L2_MEMORY_MMAP;
2142 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); 2142 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
2143 2143
2144 input_buffer_map_.clear(); 2144 input_buffer_map_.clear();
2145 free_input_buffers_.clear(); 2145 free_input_buffers_.clear();
2146 } 2146 }
2147 2147
2148 bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() { 2148 bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() {
2149 DVLOGF(3); 2149 DVLOGF(3);
2150 DCHECK(child_task_runner_->BelongsToCurrentThread()); 2150 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
2151 DCHECK(!output_streamon_); 2151 DCHECK(!output_streamon_);
2152 bool success = true; 2152 bool success = true;
2153 2153
2154 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { 2154 for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
2155 OutputRecord& output_record = output_buffer_map_[i]; 2155 OutputRecord& output_record = output_buffer_map_[i];
2156 2156
2157 if (output_record.egl_image != EGL_NO_IMAGE_KHR) { 2157 if (output_record.egl_image != EGL_NO_IMAGE_KHR) {
2158 if (egl_image_device_->DestroyEGLImage( 2158 child_task_runner_->PostTask(
2159 egl_display_, output_record.egl_image) != EGL_TRUE) { 2159 FROM_HERE,
2160 DVLOGF(1) << "DestroyEGLImage failed."; 2160 base::Bind(base::IgnoreResult(&V4L2Device::DestroyEGLImage), device_,
2161 success = false; 2161 egl_display_, output_record.egl_image));
2162 }
2163 } 2162 }
2164 2163
2165 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { 2164 if (output_record.egl_sync != EGL_NO_SYNC_KHR) {
2166 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) { 2165 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) {
2167 DVLOGF(1) << "eglDestroySyncKHR failed."; 2166 DVLOGF(1) << "eglDestroySyncKHR failed.";
2168 success = false; 2167 success = false;
2169 } 2168 }
2170 } 2169 }
2171 2170
2172 DVLOGF(1) << "dismissing PictureBuffer id=" << output_record.picture_id; 2171 DVLOGF(1) << "dismissing PictureBuffer id=" << output_record.picture_id;
(...skipping 16 matching lines...) Expand all
2189 while (!free_output_buffers_.empty()) 2188 while (!free_output_buffers_.empty())
2190 free_output_buffers_.pop(); 2189 free_output_buffers_.pop();
2191 output_buffer_queued_count_ = 0; 2190 output_buffer_queued_count_ = 0;
2192 // The client may still hold some buffers. The texture holds a reference to 2191 // The client may still hold some buffers. The texture holds a reference to
2193 // the buffer. It is OK to free the buffer and destroy EGLImage here. 2192 // the buffer. It is OK to free the buffer and destroy EGLImage here.
2194 decoder_frames_at_client_ = 0; 2193 decoder_frames_at_client_ = 0;
2195 2194
2196 return success; 2195 return success;
2197 } 2196 }
2198 2197
2199 void V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers() {
2200 DCHECK(child_task_runner_->BelongsToCurrentThread());
2201 DVLOGF(3);
2202
2203 if (!DestroyOutputBuffers()) {
2204 LOGF(ERROR) << "Failed destroying output buffers.";
2205 NOTIFY_ERROR(PLATFORM_FAILURE);
2206 return;
2207 }
2208
2209 // Finish resolution change on decoder thread.
2210 decoder_thread_.task_runner()->PostTask(
2211 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::FinishResolutionChange,
2212 base::Unretained(this)));
2213 }
2214
2215 void V4L2VideoDecodeAccelerator::SendPictureReady() { 2198 void V4L2VideoDecodeAccelerator::SendPictureReady() {
2216 DVLOGF(3); 2199 DVLOGF(3);
2217 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 2200 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
2218 bool resetting_or_flushing = 2201 bool resetting_or_flushing =
2219 (decoder_state_ == kResetting || decoder_flushing_); 2202 (decoder_state_ == kResetting || decoder_flushing_);
2220 while (pending_picture_ready_.size() > 0) { 2203 while (pending_picture_ready_.size() > 0) {
2221 bool cleared = pending_picture_ready_.front().cleared; 2204 bool cleared = pending_picture_ready_.front().cleared;
2222 const Picture& picture = pending_picture_ready_.front().picture; 2205 const Picture& picture = pending_picture_ready_.front().picture;
2223 if (cleared && picture_clearing_count_ == 0) { 2206 if (cleared && picture_clearing_count_ == 0) {
2224 // This picture is cleared. It can be posted to a thread different than 2207 // This picture is cleared. It can be posted to a thread different than
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
2294 StartResolutionChange(); 2277 StartResolutionChange();
2295 } 2278 }
2296 } 2279 }
2297 2280
2298 void V4L2VideoDecodeAccelerator::ImageProcessorError() { 2281 void V4L2VideoDecodeAccelerator::ImageProcessorError() {
2299 LOGF(ERROR) << "Image processor error"; 2282 LOGF(ERROR) << "Image processor error";
2300 NOTIFY_ERROR(PLATFORM_FAILURE); 2283 NOTIFY_ERROR(PLATFORM_FAILURE);
2301 } 2284 }
2302 2285
2303 } // namespace media 2286 } // namespace media
OLDNEW
« media/gpu/v4l2_video_decode_accelerator.h ('K') | « media/gpu/v4l2_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698