| 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 <string.h> | 9 #include <string.h> |
| 10 #include <sys/eventfd.h> | 10 #include <sys/eventfd.h> |
| 11 #include <sys/ioctl.h> | 11 #include <sys/ioctl.h> |
| 12 #include <sys/mman.h> | 12 #include <sys/mman.h> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
| 16 #include "base/callback.h" | 16 #include "base/callback.h" |
| 17 #include "base/callback_helpers.h" | 17 #include "base/callback_helpers.h" |
| 18 #include "base/command_line.h" | 18 #include "base/command_line.h" |
| 19 #include "base/macros.h" | 19 #include "base/macros.h" |
| 20 #include "base/numerics/safe_conversions.h" | 20 #include "base/numerics/safe_conversions.h" |
| 21 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
| 22 #include "content/common/gpu/media/shared_memory_region.h" |
| 22 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h" | 23 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h" |
| 23 #include "media/base/bind_to_current_loop.h" | 24 #include "media/base/bind_to_current_loop.h" |
| 24 #include "media/base/media_switches.h" | 25 #include "media/base/media_switches.h" |
| 25 #include "ui/gl/scoped_binders.h" | 26 #include "ui/gl/scoped_binders.h" |
| 26 | 27 |
| 27 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): " | 28 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): " |
| 28 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " | 29 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " |
| 29 | 30 |
| 30 #define NOTIFY_ERROR(x) \ | 31 #define NOTIFY_ERROR(x) \ |
| 31 do { \ | 32 do { \ |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 picture_id(-1), | 163 picture_id(-1), |
| 163 egl_image(EGL_NO_IMAGE_KHR), | 164 egl_image(EGL_NO_IMAGE_KHR), |
| 164 egl_sync(EGL_NO_SYNC_KHR), | 165 egl_sync(EGL_NO_SYNC_KHR), |
| 165 cleared(false) { | 166 cleared(false) { |
| 166 } | 167 } |
| 167 | 168 |
| 168 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef { | 169 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef { |
| 169 BitstreamBufferRef( | 170 BitstreamBufferRef( |
| 170 base::WeakPtr<VideoDecodeAccelerator::Client>& client, | 171 base::WeakPtr<VideoDecodeAccelerator::Client>& client, |
| 171 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, | 172 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
| 172 base::SharedMemory* shm, | 173 SharedMemoryRegion* shm, |
| 173 size_t size, | |
| 174 int32_t input_id); | 174 int32_t input_id); |
| 175 ~BitstreamBufferRef(); | 175 ~BitstreamBufferRef(); |
| 176 const base::WeakPtr<VideoDecodeAccelerator::Client> client; | 176 const base::WeakPtr<VideoDecodeAccelerator::Client> client; |
| 177 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner; | 177 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner; |
| 178 const scoped_ptr<base::SharedMemory> shm; | 178 const scoped_ptr<SharedMemoryRegion> shm; |
| 179 const size_t size; | |
| 180 off_t bytes_used; | 179 off_t bytes_used; |
| 181 const int32_t input_id; | 180 const int32_t input_id; |
| 182 }; | 181 }; |
| 183 | 182 |
| 184 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( | 183 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( |
| 185 base::WeakPtr<VideoDecodeAccelerator::Client>& client, | 184 base::WeakPtr<VideoDecodeAccelerator::Client>& client, |
| 186 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, | 185 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
| 187 base::SharedMemory* shm, | 186 SharedMemoryRegion* shm, |
| 188 size_t size, | |
| 189 int32_t input_id) | 187 int32_t input_id) |
| 190 : client(client), | 188 : client(client), |
| 191 client_task_runner(client_task_runner), | 189 client_task_runner(client_task_runner), |
| 192 shm(shm), | 190 shm(shm), |
| 193 size(size), | |
| 194 bytes_used(0), | 191 bytes_used(0), |
| 195 input_id(input_id) {} | 192 input_id(input_id) {} |
| 196 | 193 |
| 197 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { | 194 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { |
| 198 if (input_id >= 0) { | 195 if (input_id >= 0) { |
| 199 DVLOGF(5) << "returning input_id: " << input_id; | 196 DVLOGF(5) << "returning input_id: " << input_id; |
| 200 client_task_runner->PostTask( | 197 client_task_runner->PostTask( |
| 201 FROM_HERE, | 198 FROM_HERE, |
| 202 base::Bind(&VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, | 199 base::Bind(&VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, |
| 203 client, input_id)); | 200 client, input_id)); |
| (...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1204 } | 1201 } |
| 1205 | 1202 |
| 1206 void V4L2SliceVideoDecodeAccelerator::DecodeTask( | 1203 void V4L2SliceVideoDecodeAccelerator::DecodeTask( |
| 1207 const media::BitstreamBuffer& bitstream_buffer) { | 1204 const media::BitstreamBuffer& bitstream_buffer) { |
| 1208 DVLOGF(3) << "input_id=" << bitstream_buffer.id() | 1205 DVLOGF(3) << "input_id=" << bitstream_buffer.id() |
| 1209 << " size=" << bitstream_buffer.size(); | 1206 << " size=" << bitstream_buffer.size(); |
| 1210 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1207 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1211 | 1208 |
| 1212 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 1209 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
| 1213 io_client_, io_task_runner_, | 1210 io_client_, io_task_runner_, |
| 1214 new base::SharedMemory(bitstream_buffer.handle(), true), | 1211 new SharedMemoryRegion(bitstream_buffer, true), bitstream_buffer.id())); |
| 1215 bitstream_buffer.size(), bitstream_buffer.id())); | 1212 if (!bitstream_record->shm->Map()) { |
| 1216 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { | |
| 1217 LOGF(ERROR) << "Could not map bitstream_buffer"; | 1213 LOGF(ERROR) << "Could not map bitstream_buffer"; |
| 1218 NOTIFY_ERROR(UNREADABLE_INPUT); | 1214 NOTIFY_ERROR(UNREADABLE_INPUT); |
| 1219 return; | 1215 return; |
| 1220 } | 1216 } |
| 1221 DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory(); | 1217 DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory(); |
| 1222 | 1218 |
| 1223 decoder_input_queue_.push( | 1219 decoder_input_queue_.push( |
| 1224 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); | 1220 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); |
| 1225 | 1221 |
| 1226 ScheduleDecodeBufferTaskIfNeeded(); | 1222 ScheduleDecodeBufferTaskIfNeeded(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1238 decoder_input_queue_.pop(); | 1234 decoder_input_queue_.pop(); |
| 1239 | 1235 |
| 1240 if (decoder_current_bitstream_buffer_->input_id == kFlushBufferId) { | 1236 if (decoder_current_bitstream_buffer_->input_id == kFlushBufferId) { |
| 1241 // This is a buffer we queued for ourselves to trigger flush at this time. | 1237 // This is a buffer we queued for ourselves to trigger flush at this time. |
| 1242 InitiateFlush(); | 1238 InitiateFlush(); |
| 1243 return false; | 1239 return false; |
| 1244 } | 1240 } |
| 1245 | 1241 |
| 1246 const uint8_t* const data = reinterpret_cast<const uint8_t*>( | 1242 const uint8_t* const data = reinterpret_cast<const uint8_t*>( |
| 1247 decoder_current_bitstream_buffer_->shm->memory()); | 1243 decoder_current_bitstream_buffer_->shm->memory()); |
| 1248 const size_t data_size = decoder_current_bitstream_buffer_->size; | 1244 const size_t data_size = decoder_current_bitstream_buffer_->shm->size(); |
| 1249 decoder_->SetStream(data, data_size); | 1245 decoder_->SetStream(data, data_size); |
| 1250 | 1246 |
| 1251 return true; | 1247 return true; |
| 1252 } | 1248 } |
| 1253 | 1249 |
| 1254 void V4L2SliceVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { | 1250 void V4L2SliceVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { |
| 1255 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1251 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1256 if (state_ == kDecoding) { | 1252 if (state_ == kDecoding) { |
| 1257 decoder_thread_task_runner_->PostTask( | 1253 decoder_thread_task_runner_->PostTask( |
| 1258 FROM_HERE, | 1254 FROM_HERE, |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1638 | 1634 |
| 1639 void V4L2SliceVideoDecodeAccelerator::FlushTask() { | 1635 void V4L2SliceVideoDecodeAccelerator::FlushTask() { |
| 1640 DVLOGF(3); | 1636 DVLOGF(3); |
| 1641 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1637 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1642 | 1638 |
| 1643 if (!decoder_input_queue_.empty()) { | 1639 if (!decoder_input_queue_.empty()) { |
| 1644 // We are not done with pending inputs, so queue an empty buffer, | 1640 // We are not done with pending inputs, so queue an empty buffer, |
| 1645 // which - when reached - will trigger flush sequence. | 1641 // which - when reached - will trigger flush sequence. |
| 1646 decoder_input_queue_.push( | 1642 decoder_input_queue_.push( |
| 1647 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1643 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
| 1648 io_client_, io_task_runner_, nullptr, 0, kFlushBufferId))); | 1644 io_client_, io_task_runner_, nullptr, kFlushBufferId))); |
| 1649 return; | 1645 return; |
| 1650 } | 1646 } |
| 1651 | 1647 |
| 1652 // No more inputs pending, so just finish flushing here. | 1648 // No more inputs pending, so just finish flushing here. |
| 1653 InitiateFlush(); | 1649 InitiateFlush(); |
| 1654 } | 1650 } |
| 1655 | 1651 |
| 1656 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() { | 1652 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() { |
| 1657 DVLOGF(3); | 1653 DVLOGF(3); |
| 1658 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1654 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| (...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2608 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { | 2604 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { |
| 2609 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); | 2605 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); |
| 2610 if (!device) | 2606 if (!device) |
| 2611 return SupportedProfiles(); | 2607 return SupportedProfiles(); |
| 2612 | 2608 |
| 2613 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), | 2609 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), |
| 2614 supported_input_fourccs_); | 2610 supported_input_fourccs_); |
| 2615 } | 2611 } |
| 2616 | 2612 |
| 2617 } // namespace content | 2613 } // namespace content |
| OLD | NEW |