| 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 <errno.h> | 5 #include <errno.h> |
| 6 #include <fcntl.h> | 6 #include <fcntl.h> |
| 7 #include <linux/videodev2.h> | 7 #include <linux/videodev2.h> |
| 8 #include <poll.h> | 8 #include <poll.h> |
| 9 #include <sys/eventfd.h> | 9 #include <sys/eventfd.h> |
| 10 #include <sys/ioctl.h> | 10 #include <sys/ioctl.h> |
| 11 #include <sys/mman.h> | 11 #include <sys/mman.h> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
| 15 #include "base/callback.h" | 15 #include "base/callback.h" |
| 16 #include "base/callback_helpers.h" | 16 #include "base/callback_helpers.h" |
| 17 #include "base/command_line.h" | 17 #include "base/command_line.h" |
| 18 #include "base/numerics/safe_conversions.h" | 18 #include "base/numerics/safe_conversions.h" |
| 19 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
| 20 #include "content/common/gpu/media/shared_memory_region.h" |
| 20 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h" | 21 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h" |
| 21 #include "media/base/bind_to_current_loop.h" | 22 #include "media/base/bind_to_current_loop.h" |
| 22 #include "media/base/media_switches.h" | 23 #include "media/base/media_switches.h" |
| 23 #include "ui/gl/scoped_binders.h" | 24 #include "ui/gl/scoped_binders.h" |
| 24 | 25 |
| 25 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): " | 26 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): " |
| 26 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " | 27 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " |
| 27 | 28 |
| 28 #define NOTIFY_ERROR(x) \ | 29 #define NOTIFY_ERROR(x) \ |
| 29 do { \ | 30 do { \ |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 picture_id(-1), | 157 picture_id(-1), |
| 157 egl_image(EGL_NO_IMAGE_KHR), | 158 egl_image(EGL_NO_IMAGE_KHR), |
| 158 egl_sync(EGL_NO_SYNC_KHR), | 159 egl_sync(EGL_NO_SYNC_KHR), |
| 159 cleared(false) { | 160 cleared(false) { |
| 160 } | 161 } |
| 161 | 162 |
| 162 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef { | 163 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef { |
| 163 BitstreamBufferRef( | 164 BitstreamBufferRef( |
| 164 base::WeakPtr<VideoDecodeAccelerator::Client>& client, | 165 base::WeakPtr<VideoDecodeAccelerator::Client>& client, |
| 165 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, | 166 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
| 166 base::SharedMemory* shm, | 167 SharedMemoryRegion* shm, |
| 167 size_t size, | |
| 168 int32 input_id); | 168 int32 input_id); |
| 169 ~BitstreamBufferRef(); | 169 ~BitstreamBufferRef(); |
| 170 const base::WeakPtr<VideoDecodeAccelerator::Client> client; | 170 const base::WeakPtr<VideoDecodeAccelerator::Client> client; |
| 171 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner; | 171 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner; |
| 172 const scoped_ptr<base::SharedMemory> shm; | 172 const scoped_ptr<SharedMemoryRegion> shm; |
| 173 const size_t size; | |
| 174 off_t bytes_used; | 173 off_t bytes_used; |
| 175 const int32 input_id; | 174 const int32 input_id; |
| 176 }; | 175 }; |
| 177 | 176 |
| 178 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( | 177 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( |
| 179 base::WeakPtr<VideoDecodeAccelerator::Client>& client, | 178 base::WeakPtr<VideoDecodeAccelerator::Client>& client, |
| 180 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, | 179 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
| 181 base::SharedMemory* shm, | 180 SharedMemoryRegion* shm, |
| 182 size_t size, | |
| 183 int32 input_id) | 181 int32 input_id) |
| 184 : client(client), | 182 : client(client), |
| 185 client_task_runner(client_task_runner), | 183 client_task_runner(client_task_runner), |
| 186 shm(shm), | 184 shm(shm), |
| 187 size(size), | |
| 188 bytes_used(0), | 185 bytes_used(0), |
| 189 input_id(input_id) { | 186 input_id(input_id) {} |
| 190 } | |
| 191 | 187 |
| 192 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { | 188 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { |
| 193 if (input_id >= 0) { | 189 if (input_id >= 0) { |
| 194 DVLOGF(5) << "returning input_id: " << input_id; | 190 DVLOGF(5) << "returning input_id: " << input_id; |
| 195 client_task_runner->PostTask( | 191 client_task_runner->PostTask( |
| 196 FROM_HERE, | 192 FROM_HERE, |
| 197 base::Bind(&VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, | 193 base::Bind(&VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, |
| 198 client, input_id)); | 194 client, input_id)); |
| 199 } | 195 } |
| 200 } | 196 } |
| (...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1181 } | 1177 } |
| 1182 | 1178 |
| 1183 void V4L2SliceVideoDecodeAccelerator::DecodeTask( | 1179 void V4L2SliceVideoDecodeAccelerator::DecodeTask( |
| 1184 const media::BitstreamBuffer& bitstream_buffer) { | 1180 const media::BitstreamBuffer& bitstream_buffer) { |
| 1185 DVLOGF(3) << "input_id=" << bitstream_buffer.id() | 1181 DVLOGF(3) << "input_id=" << bitstream_buffer.id() |
| 1186 << " size=" << bitstream_buffer.size(); | 1182 << " size=" << bitstream_buffer.size(); |
| 1187 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1183 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1188 | 1184 |
| 1189 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 1185 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
| 1190 io_client_, io_task_runner_, | 1186 io_client_, io_task_runner_, |
| 1191 new base::SharedMemory(bitstream_buffer.handle(), true), | 1187 new SharedMemoryRegion(bitstream_buffer, true), bitstream_buffer.id())); |
| 1192 bitstream_buffer.size(), bitstream_buffer.id())); | 1188 if (!bitstream_record->shm->Map()) { |
| 1193 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { | |
| 1194 LOGF(ERROR) << "Could not map bitstream_buffer"; | 1189 LOGF(ERROR) << "Could not map bitstream_buffer"; |
| 1195 NOTIFY_ERROR(UNREADABLE_INPUT); | 1190 NOTIFY_ERROR(UNREADABLE_INPUT); |
| 1196 return; | 1191 return; |
| 1197 } | 1192 } |
| 1198 DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory(); | 1193 DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory(); |
| 1199 | 1194 |
| 1200 decoder_input_queue_.push( | 1195 decoder_input_queue_.push( |
| 1201 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); | 1196 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); |
| 1202 | 1197 |
| 1203 ScheduleDecodeBufferTaskIfNeeded(); | 1198 ScheduleDecodeBufferTaskIfNeeded(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1215 decoder_input_queue_.pop(); | 1210 decoder_input_queue_.pop(); |
| 1216 | 1211 |
| 1217 if (decoder_current_bitstream_buffer_->input_id == kFlushBufferId) { | 1212 if (decoder_current_bitstream_buffer_->input_id == kFlushBufferId) { |
| 1218 // This is a buffer we queued for ourselves to trigger flush at this time. | 1213 // This is a buffer we queued for ourselves to trigger flush at this time. |
| 1219 InitiateFlush(); | 1214 InitiateFlush(); |
| 1220 return false; | 1215 return false; |
| 1221 } | 1216 } |
| 1222 | 1217 |
| 1223 const uint8_t* const data = reinterpret_cast<const uint8_t*>( | 1218 const uint8_t* const data = reinterpret_cast<const uint8_t*>( |
| 1224 decoder_current_bitstream_buffer_->shm->memory()); | 1219 decoder_current_bitstream_buffer_->shm->memory()); |
| 1225 const size_t data_size = decoder_current_bitstream_buffer_->size; | 1220 const size_t data_size = decoder_current_bitstream_buffer_->shm->size(); |
| 1226 decoder_->SetStream(data, data_size); | 1221 decoder_->SetStream(data, data_size); |
| 1227 | 1222 |
| 1228 return true; | 1223 return true; |
| 1229 } | 1224 } |
| 1230 | 1225 |
| 1231 void V4L2SliceVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { | 1226 void V4L2SliceVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { |
| 1232 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1227 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1233 if (state_ == kDecoding) { | 1228 if (state_ == kDecoding) { |
| 1234 decoder_thread_task_runner_->PostTask( | 1229 decoder_thread_task_runner_->PostTask( |
| 1235 FROM_HERE, | 1230 FROM_HERE, |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1571 | 1566 |
| 1572 void V4L2SliceVideoDecodeAccelerator::FlushTask() { | 1567 void V4L2SliceVideoDecodeAccelerator::FlushTask() { |
| 1573 DVLOGF(3); | 1568 DVLOGF(3); |
| 1574 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1569 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1575 | 1570 |
| 1576 if (!decoder_input_queue_.empty()) { | 1571 if (!decoder_input_queue_.empty()) { |
| 1577 // We are not done with pending inputs, so queue an empty buffer, | 1572 // We are not done with pending inputs, so queue an empty buffer, |
| 1578 // which - when reached - will trigger flush sequence. | 1573 // which - when reached - will trigger flush sequence. |
| 1579 decoder_input_queue_.push( | 1574 decoder_input_queue_.push( |
| 1580 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1575 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
| 1581 io_client_, io_task_runner_, nullptr, 0, kFlushBufferId))); | 1576 io_client_, io_task_runner_, nullptr, kFlushBufferId))); |
| 1582 return; | 1577 return; |
| 1583 } | 1578 } |
| 1584 | 1579 |
| 1585 // No more inputs pending, so just finish flushing here. | 1580 // No more inputs pending, so just finish flushing here. |
| 1586 InitiateFlush(); | 1581 InitiateFlush(); |
| 1587 } | 1582 } |
| 1588 | 1583 |
| 1589 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() { | 1584 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() { |
| 1590 DVLOGF(3); | 1585 DVLOGF(3); |
| 1591 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1586 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| (...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2543 if (!device) | 2538 if (!device) |
| 2544 return SupportedProfiles(); | 2539 return SupportedProfiles(); |
| 2545 | 2540 |
| 2546 const uint32_t supported_formats[] = { | 2541 const uint32_t supported_formats[] = { |
| 2547 V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME}; | 2542 V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME}; |
| 2548 return device->GetSupportedDecodeProfiles(arraysize(supported_formats), | 2543 return device->GetSupportedDecodeProfiles(arraysize(supported_formats), |
| 2549 supported_formats); | 2544 supported_formats); |
| 2550 } | 2545 } |
| 2551 | 2546 |
| 2552 } // namespace content | 2547 } // namespace content |
| OLD | NEW |