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

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

Issue 185403020: Make VEA client of command buffer; move sync. IPC to VDA/VEA::Initialize() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: f2a9ccb5 Rebase, posciak@ comments. 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 | Annotate | Revision Log
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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} 153 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {}
154 154
155 V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator( 155 V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator(
156 EGLDisplay egl_display, 156 EGLDisplay egl_display,
157 const base::WeakPtr<Client>& io_client, 157 const base::WeakPtr<Client>& io_client,
158 const base::Callback<bool(void)>& make_context_current, 158 const base::Callback<bool(void)>& make_context_current,
159 scoped_ptr<V4L2Device> device, 159 scoped_ptr<V4L2Device> device,
160 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) 160 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy)
161 : child_message_loop_proxy_(base::MessageLoopProxy::current()), 161 : child_message_loop_proxy_(base::MessageLoopProxy::current()),
162 io_message_loop_proxy_(io_message_loop_proxy), 162 io_message_loop_proxy_(io_message_loop_proxy),
163 weak_this_(base::AsWeakPtr(this)),
164 io_client_(io_client), 163 io_client_(io_client),
165 decoder_thread_("V4L2DecoderThread"), 164 decoder_thread_("V4L2DecoderThread"),
166 decoder_state_(kUninitialized), 165 decoder_state_(kUninitialized),
167 device_(device.Pass()), 166 device_(device.Pass()),
168 decoder_delay_bitstream_buffer_id_(-1), 167 decoder_delay_bitstream_buffer_id_(-1),
169 decoder_current_input_buffer_(-1), 168 decoder_current_input_buffer_(-1),
170 decoder_decode_buffer_tasks_scheduled_(0), 169 decoder_decode_buffer_tasks_scheduled_(0),
171 decoder_frames_at_client_(0), 170 decoder_frames_at_client_(0),
172 decoder_flushing_(false), 171 decoder_flushing_(false),
173 resolution_change_pending_(false), 172 resolution_change_pending_(false),
174 resolution_change_reset_pending_(false), 173 resolution_change_reset_pending_(false),
175 decoder_partial_frame_pending_(false), 174 decoder_partial_frame_pending_(false),
176 input_streamon_(false), 175 input_streamon_(false),
177 input_buffer_queued_count_(0), 176 input_buffer_queued_count_(0),
178 output_streamon_(false), 177 output_streamon_(false),
179 output_buffer_queued_count_(0), 178 output_buffer_queued_count_(0),
180 output_buffer_pixelformat_(0), 179 output_buffer_pixelformat_(0),
181 output_dpb_size_(0), 180 output_dpb_size_(0),
182 picture_clearing_count_(0), 181 picture_clearing_count_(0),
183 pictures_assigned_(false, false), 182 pictures_assigned_(false, false),
184 device_poll_thread_("V4L2DevicePollThread"), 183 device_poll_thread_("V4L2DevicePollThread"),
185 make_context_current_(make_context_current), 184 make_context_current_(make_context_current),
186 egl_display_(egl_display), 185 egl_display_(egl_display),
187 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {} 186 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN),
187 weak_this_factory_(this) {
188 weak_this_ = weak_this_factory_.GetWeakPtr();
189 }
188 190
189 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() { 191 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() {
190 DCHECK(!decoder_thread_.IsRunning()); 192 DCHECK(!decoder_thread_.IsRunning());
191 DCHECK(!device_poll_thread_.IsRunning()); 193 DCHECK(!device_poll_thread_.IsRunning());
192 194
193 DestroyInputBuffers(); 195 DestroyInputBuffers();
194 DestroyOutputBuffers(); 196 DestroyOutputBuffers();
195 197
196 // These maps have members that should be manually destroyed, e.g. file 198 // These maps have members that should be manually destroyed, e.g. file
197 // descriptors, mmap() segments, etc. 199 // descriptors, mmap() segments, etc.
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 decoder_h264_parser_.reset(new media::H264Parser()); 284 decoder_h264_parser_.reset(new media::H264Parser());
283 } 285 }
284 286
285 if (!decoder_thread_.Start()) { 287 if (!decoder_thread_.Start()) {
286 DLOG(ERROR) << "Initialize(): decoder thread failed to start"; 288 DLOG(ERROR) << "Initialize(): decoder thread failed to start";
287 NOTIFY_ERROR(PLATFORM_FAILURE); 289 NOTIFY_ERROR(PLATFORM_FAILURE);
288 return false; 290 return false;
289 } 291 }
290 292
291 SetDecoderState(kInitialized); 293 SetDecoderState(kInitialized);
292
293 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
294 &Client::NotifyInitializeDone, client_));
295 return true; 294 return true;
296 } 295 }
297 296
298 void V4L2VideoDecodeAccelerator::Decode( 297 void V4L2VideoDecodeAccelerator::Decode(
299 const media::BitstreamBuffer& bitstream_buffer) { 298 const media::BitstreamBuffer& bitstream_buffer) {
300 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() 299 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id()
301 << ", size=" << bitstream_buffer.size(); 300 << ", size=" << bitstream_buffer.size();
302 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 301 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
303 302
304 // DecodeTask() will take care of running a DecodeBufferTask(). 303 // DecodeTask() will take care of running a DecodeBufferTask().
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 420 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
422 &V4L2VideoDecodeAccelerator::ResetTask, base::Unretained(this))); 421 &V4L2VideoDecodeAccelerator::ResetTask, base::Unretained(this)));
423 } 422 }
424 423
425 void V4L2VideoDecodeAccelerator::Destroy() { 424 void V4L2VideoDecodeAccelerator::Destroy() {
426 DVLOG(3) << "Destroy()"; 425 DVLOG(3) << "Destroy()";
427 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); 426 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
428 427
429 // We're destroying; cancel all callbacks. 428 // We're destroying; cancel all callbacks.
430 client_ptr_factory_.reset(); 429 client_ptr_factory_.reset();
430 weak_this_factory_.InvalidateWeakPtrs();
431 431
432 // If the decoder thread is running, destroy using posted task. 432 // If the decoder thread is running, destroy using posted task.
433 if (decoder_thread_.IsRunning()) { 433 if (decoder_thread_.IsRunning()) {
434 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 434 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
435 &V4L2VideoDecodeAccelerator::DestroyTask, base::Unretained(this))); 435 &V4L2VideoDecodeAccelerator::DestroyTask, base::Unretained(this)));
436 pictures_assigned_.Signal(); 436 pictures_assigned_.Signal();
437 // DestroyTask() will cause the decoder_thread_ to flush all tasks. 437 // DestroyTask() will cause the decoder_thread_ to flush all tasks.
438 decoder_thread_.Stop(); 438 decoder_thread_.Stop();
439 } else { 439 } else {
440 // Otherwise, call the destroy task directly. 440 // Otherwise, call the destroy task directly.
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 748
749 // We expect to process the initial buffer once during stream init to 749 // We expect to process the initial buffer once during stream init to
750 // configure stream parameters, but will not consume the steam data on that 750 // configure stream parameters, but will not consume the steam data on that
751 // iteration. Subsequent iterations (including after reset) do not require 751 // iteration. Subsequent iterations (including after reset) do not require
752 // the stream init step. 752 // the stream init step.
753 *endpos = 0; 753 *endpos = 0;
754 } else { 754 } else {
755 *endpos = size; 755 *endpos = size;
756 } 756 }
757 757
758 // StartDevicePoll will raise the error if there is one. 758 if (!StartDevicePoll()) {
759 if (!StartDevicePoll()) 759 NOTIFY_ERROR(PLATFORM_FAILURE);
760 return false; 760 return false;
761 }
761 762
762 decoder_state_ = kDecoding; 763 decoder_state_ = kDecoding;
763 ScheduleDecodeBufferTaskIfNeeded(); 764 ScheduleDecodeBufferTaskIfNeeded();
764 return true; 765 return true;
765 } 766 }
766 767
767 bool V4L2VideoDecodeAccelerator::DecodeBufferContinue( 768 bool V4L2VideoDecodeAccelerator::DecodeBufferContinue(
768 const void* data, size_t size) { 769 const void* data, size_t size) {
769 DVLOG(3) << "DecodeBufferContinue(): data=" << data << ", size=" << size; 770 DVLOG(3) << "DecodeBufferContinue(): data=" << data << ", size=" << size;
770 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 771 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after
1277 1278
1278 // TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon 1279 // TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon
1279 // sequence after flush to continue, even if we are not resetting. This would 1280 // sequence after flush to continue, even if we are not resetting. This would
1280 // make sense, because we don't really want to resume from a non-resume point 1281 // make sense, because we don't really want to resume from a non-resume point
1281 // (e.g. not from an IDR) if we are flushed. 1282 // (e.g. not from an IDR) if we are flushed.
1282 // MSE player however triggers a Flush() on chunk end, but never Reset(). One 1283 // MSE player however triggers a Flush() on chunk end, but never Reset(). One
1283 // could argue either way, or even say that Flush() is not needed/harmful when 1284 // could argue either way, or even say that Flush() is not needed/harmful when
1284 // transitioning to next chunk. 1285 // transitioning to next chunk.
1285 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze 1286 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze
1286 // when doing MSE. This should be harmless otherwise. 1287 // when doing MSE. This should be harmless otherwise.
1287 if (!StopDevicePoll(false)) 1288 if (!StopDevicePoll(false)) {
1289 NOTIFY_ERROR(PLATFORM_FAILURE);
1288 return; 1290 return;
1291 }
1289 1292
1290 if (!StartDevicePoll()) 1293 if (!StartDevicePoll()) {
1294 NOTIFY_ERROR(PLATFORM_FAILURE);
1291 return; 1295 return;
1296 }
1292 1297
1293 decoder_delay_bitstream_buffer_id_ = -1; 1298 decoder_delay_bitstream_buffer_id_ = -1;
1294 decoder_flushing_ = false; 1299 decoder_flushing_ = false;
1295 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush"; 1300 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush";
1296 child_message_loop_proxy_->PostTask( 1301 child_message_loop_proxy_->PostTask(
1297 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); 1302 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_));
1298 1303
1299 // While we were flushing, we early-outed DecodeBufferTask()s. 1304 // While we were flushing, we early-outed DecodeBufferTask()s.
1300 ScheduleDecodeBufferTaskIfNeeded(); 1305 ScheduleDecodeBufferTaskIfNeeded();
1301 } 1306 }
(...skipping 13 matching lines...) Expand all
1315 // because input pipe is already stopped if we are changing resolution. 1320 // because input pipe is already stopped if we are changing resolution.
1316 // We will come back here after we are done with the resolution change. 1321 // We will come back here after we are done with the resolution change.
1317 DCHECK(!resolution_change_reset_pending_); 1322 DCHECK(!resolution_change_reset_pending_);
1318 if (resolution_change_pending_ || decoder_state_ == kChangingResolution) { 1323 if (resolution_change_pending_ || decoder_state_ == kChangingResolution) {
1319 resolution_change_reset_pending_ = true; 1324 resolution_change_reset_pending_ = true;
1320 return; 1325 return;
1321 } 1326 }
1322 1327
1323 // We stop streaming and clear buffer tracking info (not preserving inputs). 1328 // We stop streaming and clear buffer tracking info (not preserving inputs).
1324 // StopDevicePoll() unconditionally does _not_ destroy buffers, however. 1329 // StopDevicePoll() unconditionally does _not_ destroy buffers, however.
1325 if (!StopDevicePoll(false)) 1330 if (!StopDevicePoll(false)) {
1331 NOTIFY_ERROR(PLATFORM_FAILURE);
1326 return; 1332 return;
1333 }
1327 1334
1328 decoder_current_bitstream_buffer_.reset(); 1335 decoder_current_bitstream_buffer_.reset();
1329 while (!decoder_input_queue_.empty()) 1336 while (!decoder_input_queue_.empty())
1330 decoder_input_queue_.pop(); 1337 decoder_input_queue_.pop();
1331 1338
1332 decoder_current_input_buffer_ = -1; 1339 decoder_current_input_buffer_ = -1;
1333 1340
1334 // If we were flushing, we'll never return any more BitstreamBuffers or 1341 // If we were flushing, we'll never return any more BitstreamBuffers or
1335 // PictureBuffers; they have all been dropped and returned by now. 1342 // PictureBuffers; they have all been dropped and returned by now.
1336 NotifyFlushDoneIfNeeded(); 1343 NotifyFlushDoneIfNeeded();
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1406 } 1413 }
1407 1414
1408 bool V4L2VideoDecodeAccelerator::StartDevicePoll() { 1415 bool V4L2VideoDecodeAccelerator::StartDevicePoll() {
1409 DVLOG(3) << "StartDevicePoll()"; 1416 DVLOG(3) << "StartDevicePoll()";
1410 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1417 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1411 DCHECK(!device_poll_thread_.IsRunning()); 1418 DCHECK(!device_poll_thread_.IsRunning());
1412 1419
1413 // Start up the device poll thread and schedule its first DevicePollTask(). 1420 // Start up the device poll thread and schedule its first DevicePollTask().
1414 if (!device_poll_thread_.Start()) { 1421 if (!device_poll_thread_.Start()) {
1415 DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; 1422 DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start";
1416 NOTIFY_ERROR(PLATFORM_FAILURE);
1417 return false; 1423 return false;
1418 } 1424 }
1419 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 1425 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
1420 &V4L2VideoDecodeAccelerator::DevicePollTask, 1426 &V4L2VideoDecodeAccelerator::DevicePollTask,
1421 base::Unretained(this), 1427 base::Unretained(this),
1422 0)); 1428 0));
1423 1429
1424 return true; 1430 return true;
1425 } 1431 }
1426 1432
1427 bool V4L2VideoDecodeAccelerator::StopDevicePoll(bool keep_input_state) { 1433 bool V4L2VideoDecodeAccelerator::StopDevicePoll(bool keep_input_state) {
1428 DVLOG(3) << "StopDevicePoll()"; 1434 DVLOG(3) << "StopDevicePoll()";
1429 if (decoder_thread_.IsRunning()) 1435 if (decoder_thread_.IsRunning())
1430 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1436 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1431 1437
1432 // Signal the DevicePollTask() to stop, and stop the device poll thread. 1438 // Signal the DevicePollTask() to stop, and stop the device poll thread.
1433 if (!device_->SetDevicePollInterrupt()) { 1439 if (!device_->SetDevicePollInterrupt()) {
1434 DPLOG(ERROR) << "SetDevicePollInterrupt(): failed"; 1440 DPLOG(ERROR) << "SetDevicePollInterrupt(): failed";
1435 NOTIFY_ERROR(PLATFORM_FAILURE);
1436 return false; 1441 return false;
1437 } 1442 }
1438 device_poll_thread_.Stop(); 1443 device_poll_thread_.Stop();
1439 // Clear the interrupt now, to be sure. 1444 // Clear the interrupt now, to be sure.
1440 if (!device_->ClearDevicePollInterrupt()) { 1445 if (!device_->ClearDevicePollInterrupt()) {
1441 NOTIFY_ERROR(PLATFORM_FAILURE);
1442 return false; 1446 return false;
1443 } 1447 }
1444 1448
1445 // Stop streaming. 1449 // Stop streaming.
1446 if (!keep_input_state) { 1450 if (!keep_input_state) {
1447 if (input_streamon_) { 1451 if (input_streamon_) {
1448 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1452 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1449 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); 1453 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type);
1450 } 1454 }
1451 input_streamon_ = false; 1455 input_streamon_ = false;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1496 void V4L2VideoDecodeAccelerator::StartResolutionChangeIfNeeded() { 1500 void V4L2VideoDecodeAccelerator::StartResolutionChangeIfNeeded() {
1497 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1501 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1498 DCHECK_EQ(decoder_state_, kDecoding); 1502 DCHECK_EQ(decoder_state_, kDecoding);
1499 1503
1500 if (!resolution_change_pending_) 1504 if (!resolution_change_pending_)
1501 return; 1505 return;
1502 1506
1503 DVLOG(3) << "No more work, initiate resolution change"; 1507 DVLOG(3) << "No more work, initiate resolution change";
1504 1508
1505 // Keep input queue. 1509 // Keep input queue.
1506 if (!StopDevicePoll(true)) 1510 if (!StopDevicePoll(true)) {
1511 NOTIFY_ERROR(PLATFORM_FAILURE);
1507 return; 1512 return;
1513 }
1508 1514
1509 decoder_state_ = kChangingResolution; 1515 decoder_state_ = kChangingResolution;
1510 DCHECK(resolution_change_pending_); 1516 DCHECK(resolution_change_pending_);
1511 resolution_change_pending_ = false; 1517 resolution_change_pending_ = false;
1512 1518
1513 // Post a task to clean up buffers on child thread. This will also ensure 1519 // Post a task to clean up buffers on child thread. This will also ensure
1514 // that we won't accept ReusePictureBuffer() anymore after that. 1520 // that we won't accept ReusePictureBuffer() anymore after that.
1515 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( 1521 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
1516 &V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers, 1522 &V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers,
1517 weak_this_)); 1523 weak_this_));
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
1919 1925
1920 void V4L2VideoDecodeAccelerator::PictureCleared() { 1926 void V4L2VideoDecodeAccelerator::PictureCleared() {
1921 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; 1927 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_;
1922 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1928 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1923 DCHECK_GT(picture_clearing_count_, 0); 1929 DCHECK_GT(picture_clearing_count_, 0);
1924 picture_clearing_count_--; 1930 picture_clearing_count_--;
1925 SendPictureReady(); 1931 SendPictureReady();
1926 } 1932 }
1927 1933
1928 } // namespace content 1934 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698