| 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 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 picture_id(-1), | 158 picture_id(-1), |
| 158 egl_image(EGL_NO_IMAGE_KHR), | 159 egl_image(EGL_NO_IMAGE_KHR), |
| 159 egl_sync(EGL_NO_SYNC_KHR), | 160 egl_sync(EGL_NO_SYNC_KHR), |
| 160 cleared(false) { | 161 cleared(false) { |
| 161 } | 162 } |
| 162 | 163 |
| 163 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef { | 164 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef { |
| 164 BitstreamBufferRef( | 165 BitstreamBufferRef( |
| 165 base::WeakPtr<VideoDecodeAccelerator::Client>& client, | 166 base::WeakPtr<VideoDecodeAccelerator::Client>& client, |
| 166 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, | 167 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
| 167 base::SharedMemory* shm, | 168 SharedMemoryRegion* shm, |
| 168 size_t size, | |
| 169 int32_t input_id); | 169 int32_t input_id); |
| 170 ~BitstreamBufferRef(); | 170 ~BitstreamBufferRef(); |
| 171 const base::WeakPtr<VideoDecodeAccelerator::Client> client; | 171 const base::WeakPtr<VideoDecodeAccelerator::Client> client; |
| 172 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner; | 172 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner; |
| 173 const scoped_ptr<base::SharedMemory> shm; | 173 const scoped_ptr<SharedMemoryRegion> shm; |
| 174 const size_t size; | |
| 175 off_t bytes_used; | 174 off_t bytes_used; |
| 176 const int32_t input_id; | 175 const int32_t input_id; |
| 177 }; | 176 }; |
| 178 | 177 |
| 179 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( | 178 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( |
| 180 base::WeakPtr<VideoDecodeAccelerator::Client>& client, | 179 base::WeakPtr<VideoDecodeAccelerator::Client>& client, |
| 181 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, | 180 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
| 182 base::SharedMemory* shm, | 181 SharedMemoryRegion* shm, |
| 183 size_t size, | |
| 184 int32_t input_id) | 182 int32_t input_id) |
| 185 : client(client), | 183 : client(client), |
| 186 client_task_runner(client_task_runner), | 184 client_task_runner(client_task_runner), |
| 187 shm(shm), | 185 shm(shm), |
| 188 size(size), | |
| 189 bytes_used(0), | 186 bytes_used(0), |
| 190 input_id(input_id) {} | 187 input_id(input_id) {} |
| 191 | 188 |
| 192 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { | 189 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { |
| 193 if (input_id >= 0) { | 190 if (input_id >= 0) { |
| 194 DVLOGF(5) << "returning input_id: " << input_id; | 191 DVLOGF(5) << "returning input_id: " << input_id; |
| 195 client_task_runner->PostTask( | 192 client_task_runner->PostTask( |
| 196 FROM_HERE, | 193 FROM_HERE, |
| 197 base::Bind(&VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, | 194 base::Bind(&VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, |
| 198 client, input_id)); | 195 client, input_id)); |
| (...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1178 } | 1175 } |
| 1179 | 1176 |
| 1180 void V4L2SliceVideoDecodeAccelerator::DecodeTask( | 1177 void V4L2SliceVideoDecodeAccelerator::DecodeTask( |
| 1181 const media::BitstreamBuffer& bitstream_buffer) { | 1178 const media::BitstreamBuffer& bitstream_buffer) { |
| 1182 DVLOGF(3) << "input_id=" << bitstream_buffer.id() | 1179 DVLOGF(3) << "input_id=" << bitstream_buffer.id() |
| 1183 << " size=" << bitstream_buffer.size(); | 1180 << " size=" << bitstream_buffer.size(); |
| 1184 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1181 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1185 | 1182 |
| 1186 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 1183 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
| 1187 io_client_, io_task_runner_, | 1184 io_client_, io_task_runner_, |
| 1188 new base::SharedMemory(bitstream_buffer.handle(), true), | 1185 new SharedMemoryRegion(bitstream_buffer, true), bitstream_buffer.id())); |
| 1189 bitstream_buffer.size(), bitstream_buffer.id())); | 1186 if (!bitstream_record->shm->Map()) { |
| 1190 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { | |
| 1191 LOGF(ERROR) << "Could not map bitstream_buffer"; | 1187 LOGF(ERROR) << "Could not map bitstream_buffer"; |
| 1192 NOTIFY_ERROR(UNREADABLE_INPUT); | 1188 NOTIFY_ERROR(UNREADABLE_INPUT); |
| 1193 return; | 1189 return; |
| 1194 } | 1190 } |
| 1195 DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory(); | 1191 DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory(); |
| 1196 | 1192 |
| 1197 decoder_input_queue_.push( | 1193 decoder_input_queue_.push( |
| 1198 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); | 1194 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); |
| 1199 | 1195 |
| 1200 ScheduleDecodeBufferTaskIfNeeded(); | 1196 ScheduleDecodeBufferTaskIfNeeded(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1212 decoder_input_queue_.pop(); | 1208 decoder_input_queue_.pop(); |
| 1213 | 1209 |
| 1214 if (decoder_current_bitstream_buffer_->input_id == kFlushBufferId) { | 1210 if (decoder_current_bitstream_buffer_->input_id == kFlushBufferId) { |
| 1215 // This is a buffer we queued for ourselves to trigger flush at this time. | 1211 // This is a buffer we queued for ourselves to trigger flush at this time. |
| 1216 InitiateFlush(); | 1212 InitiateFlush(); |
| 1217 return false; | 1213 return false; |
| 1218 } | 1214 } |
| 1219 | 1215 |
| 1220 const uint8_t* const data = reinterpret_cast<const uint8_t*>( | 1216 const uint8_t* const data = reinterpret_cast<const uint8_t*>( |
| 1221 decoder_current_bitstream_buffer_->shm->memory()); | 1217 decoder_current_bitstream_buffer_->shm->memory()); |
| 1222 const size_t data_size = decoder_current_bitstream_buffer_->size; | 1218 const size_t data_size = decoder_current_bitstream_buffer_->shm->size(); |
| 1223 decoder_->SetStream(data, data_size); | 1219 decoder_->SetStream(data, data_size); |
| 1224 | 1220 |
| 1225 return true; | 1221 return true; |
| 1226 } | 1222 } |
| 1227 | 1223 |
| 1228 void V4L2SliceVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { | 1224 void V4L2SliceVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { |
| 1229 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1225 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1230 if (state_ == kDecoding) { | 1226 if (state_ == kDecoding) { |
| 1231 decoder_thread_task_runner_->PostTask( | 1227 decoder_thread_task_runner_->PostTask( |
| 1232 FROM_HERE, | 1228 FROM_HERE, |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1568 | 1564 |
| 1569 void V4L2SliceVideoDecodeAccelerator::FlushTask() { | 1565 void V4L2SliceVideoDecodeAccelerator::FlushTask() { |
| 1570 DVLOGF(3); | 1566 DVLOGF(3); |
| 1571 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1567 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1572 | 1568 |
| 1573 if (!decoder_input_queue_.empty()) { | 1569 if (!decoder_input_queue_.empty()) { |
| 1574 // We are not done with pending inputs, so queue an empty buffer, | 1570 // We are not done with pending inputs, so queue an empty buffer, |
| 1575 // which - when reached - will trigger flush sequence. | 1571 // which - when reached - will trigger flush sequence. |
| 1576 decoder_input_queue_.push( | 1572 decoder_input_queue_.push( |
| 1577 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1573 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
| 1578 io_client_, io_task_runner_, nullptr, 0, kFlushBufferId))); | 1574 io_client_, io_task_runner_, nullptr, kFlushBufferId))); |
| 1579 return; | 1575 return; |
| 1580 } | 1576 } |
| 1581 | 1577 |
| 1582 // No more inputs pending, so just finish flushing here. | 1578 // No more inputs pending, so just finish flushing here. |
| 1583 InitiateFlush(); | 1579 InitiateFlush(); |
| 1584 } | 1580 } |
| 1585 | 1581 |
| 1586 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() { | 1582 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() { |
| 1587 DVLOGF(3); | 1583 DVLOGF(3); |
| 1588 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1584 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| (...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2543 if (!device) | 2539 if (!device) |
| 2544 return SupportedProfiles(); | 2540 return SupportedProfiles(); |
| 2545 | 2541 |
| 2546 const uint32_t supported_formats[] = { | 2542 const uint32_t supported_formats[] = { |
| 2547 V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME}; | 2543 V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME}; |
| 2548 return device->GetSupportedDecodeProfiles(arraysize(supported_formats), | 2544 return device->GetSupportedDecodeProfiles(arraysize(supported_formats), |
| 2549 supported_formats); | 2545 supported_formats); |
| 2550 } | 2546 } |
| 2551 | 2547 |
| 2552 } // namespace content | 2548 } // namespace content |
| OLD | NEW |