| OLD | NEW |
| 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 <fcntl.h> | 5 #include <fcntl.h> |
| 6 #include <linux/videodev2.h> | 6 #include <linux/videodev2.h> |
| 7 #include <poll.h> | 7 #include <poll.h> |
| 8 #include <sys/eventfd.h> | 8 #include <sys/eventfd.h> |
| 9 #include <sys/ioctl.h> | 9 #include <sys/ioctl.h> |
| 10 #include <sys/mman.h> | 10 #include <sys/mman.h> |
| 11 | 11 |
| 12 #include "base/callback.h" | 12 #include "base/callback.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/message_loop/message_loop_proxy.h" | |
| 15 #include "base/numerics/safe_conversions.h" | 14 #include "base/numerics/safe_conversions.h" |
| 16 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 17 #include "content/common/gpu/media/v4l2_video_encode_accelerator.h" | 16 #include "content/common/gpu/media/v4l2_video_encode_accelerator.h" |
| 18 #include "content/public/common/content_switches.h" | 17 #include "content/public/common/content_switches.h" |
| 19 #include "media/base/bitstream_buffer.h" | 18 #include "media/base/bitstream_buffer.h" |
| 20 | 19 |
| 21 #define NOTIFY_ERROR(x) \ | 20 #define NOTIFY_ERROR(x) \ |
| 22 do { \ | 21 do { \ |
| 23 LOG(ERROR) << "Setting error state:" << x; \ | 22 LOG(ERROR) << "Setting error state:" << x; \ |
| 24 SetErrorState(x); \ | 23 SetErrorState(x); \ |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 | 62 |
| 64 V4L2VideoEncodeAccelerator::OutputRecord::OutputRecord() | 63 V4L2VideoEncodeAccelerator::OutputRecord::OutputRecord() |
| 65 : at_device(false), address(NULL), length(0) { | 64 : at_device(false), address(NULL), length(0) { |
| 66 } | 65 } |
| 67 | 66 |
| 68 V4L2VideoEncodeAccelerator::OutputRecord::~OutputRecord() { | 67 V4L2VideoEncodeAccelerator::OutputRecord::~OutputRecord() { |
| 69 } | 68 } |
| 70 | 69 |
| 71 V4L2VideoEncodeAccelerator::V4L2VideoEncodeAccelerator( | 70 V4L2VideoEncodeAccelerator::V4L2VideoEncodeAccelerator( |
| 72 const scoped_refptr<V4L2Device>& device) | 71 const scoped_refptr<V4L2Device>& device) |
| 73 : child_message_loop_proxy_(base::MessageLoopProxy::current()), | 72 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 74 output_buffer_byte_size_(0), | 73 output_buffer_byte_size_(0), |
| 75 device_input_format_(media::VideoFrame::UNKNOWN), | 74 device_input_format_(media::VideoFrame::UNKNOWN), |
| 76 input_planes_count_(0), | 75 input_planes_count_(0), |
| 77 output_format_fourcc_(0), | 76 output_format_fourcc_(0), |
| 78 encoder_state_(kUninitialized), | 77 encoder_state_(kUninitialized), |
| 79 stream_header_size_(0), | 78 stream_header_size_(0), |
| 80 device_(device), | 79 device_(device), |
| 81 input_streamon_(false), | 80 input_streamon_(false), |
| 82 input_buffer_queued_count_(0), | 81 input_buffer_queued_count_(0), |
| 83 input_memory_type_(V4L2_MEMORY_USERPTR), | 82 input_memory_type_(V4L2_MEMORY_USERPTR), |
| (...skipping 24 matching lines...) Expand all Loading... |
| 108 << media::VideoFrame::FormatToString(input_format) | 107 << media::VideoFrame::FormatToString(input_format) |
| 109 << ", input_visible_size=" << input_visible_size.ToString() | 108 << ", input_visible_size=" << input_visible_size.ToString() |
| 110 << ", output_profile=" << output_profile | 109 << ", output_profile=" << output_profile |
| 111 << ", initial_bitrate=" << initial_bitrate; | 110 << ", initial_bitrate=" << initial_bitrate; |
| 112 | 111 |
| 113 visible_size_ = input_visible_size; | 112 visible_size_ = input_visible_size; |
| 114 | 113 |
| 115 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 114 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
| 116 client_ = client_ptr_factory_->GetWeakPtr(); | 115 client_ = client_ptr_factory_->GetWeakPtr(); |
| 117 | 116 |
| 118 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 117 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 119 DCHECK_EQ(encoder_state_, kUninitialized); | 118 DCHECK_EQ(encoder_state_, kUninitialized); |
| 120 | 119 |
| 121 struct v4l2_capability caps; | 120 struct v4l2_capability caps; |
| 122 memset(&caps, 0, sizeof(caps)); | 121 memset(&caps, 0, sizeof(caps)); |
| 123 const __u32 kCapsRequired = V4L2_CAP_VIDEO_CAPTURE_MPLANE | | 122 const __u32 kCapsRequired = V4L2_CAP_VIDEO_CAPTURE_MPLANE | |
| 124 V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING; | 123 V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING; |
| 125 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); | 124 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); |
| 126 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { | 125 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { |
| 127 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: " | 126 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: " |
| 128 "caps check failed: 0x" << std::hex << caps.capabilities; | 127 "caps check failed: 0x" << std::hex << caps.capabilities; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 | 165 |
| 167 if (!encoder_thread_.Start()) { | 166 if (!encoder_thread_.Start()) { |
| 168 LOG(ERROR) << "Initialize(): encoder thread failed to start"; | 167 LOG(ERROR) << "Initialize(): encoder thread failed to start"; |
| 169 return false; | 168 return false; |
| 170 } | 169 } |
| 171 | 170 |
| 172 RequestEncodingParametersChange(initial_bitrate, kInitialFramerate); | 171 RequestEncodingParametersChange(initial_bitrate, kInitialFramerate); |
| 173 | 172 |
| 174 encoder_state_ = kInitialized; | 173 encoder_state_ = kInitialized; |
| 175 | 174 |
| 176 child_message_loop_proxy_->PostTask( | 175 child_task_runner_->PostTask( |
| 177 FROM_HERE, | 176 FROM_HERE, |
| 178 base::Bind(&Client::RequireBitstreamBuffers, | 177 base::Bind(&Client::RequireBitstreamBuffers, client_, kInputBufferCount, |
| 179 client_, | 178 image_processor_.get() |
| 180 kInputBufferCount, | 179 ? image_processor_->input_allocated_size() |
| 181 image_processor_.get() ? | 180 : input_allocated_size_, |
| 182 image_processor_->input_allocated_size() : | |
| 183 input_allocated_size_, | |
| 184 output_buffer_byte_size_)); | 181 output_buffer_byte_size_)); |
| 185 return true; | 182 return true; |
| 186 } | 183 } |
| 187 | 184 |
| 188 void V4L2VideoEncodeAccelerator::ImageProcessorError() { | 185 void V4L2VideoEncodeAccelerator::ImageProcessorError() { |
| 189 LOG(ERROR) << "Image processor error"; | 186 LOG(ERROR) << "Image processor error"; |
| 190 NOTIFY_ERROR(kPlatformFailureError); | 187 NOTIFY_ERROR(kPlatformFailureError); |
| 191 } | 188 } |
| 192 | 189 |
| 193 void V4L2VideoEncodeAccelerator::Encode( | 190 void V4L2VideoEncodeAccelerator::Encode( |
| 194 const scoped_refptr<media::VideoFrame>& frame, | 191 const scoped_refptr<media::VideoFrame>& frame, |
| 195 bool force_keyframe) { | 192 bool force_keyframe) { |
| 196 DVLOG(3) << "Encode(): force_keyframe=" << force_keyframe; | 193 DVLOG(3) << "Encode(): force_keyframe=" << force_keyframe; |
| 197 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 194 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 198 | 195 |
| 199 if (image_processor_) { | 196 if (image_processor_) { |
| 200 image_processor_->Process( | 197 image_processor_->Process( |
| 201 frame, | 198 frame, |
| 202 base::Bind(&V4L2VideoEncodeAccelerator::FrameProcessed, | 199 base::Bind(&V4L2VideoEncodeAccelerator::FrameProcessed, |
| 203 weak_this_, | 200 weak_this_, |
| 204 force_keyframe)); | 201 force_keyframe)); |
| 205 } else { | 202 } else { |
| 206 encoder_thread_.message_loop()->PostTask( | 203 encoder_thread_.message_loop()->PostTask( |
| 207 FROM_HERE, | 204 FROM_HERE, |
| 208 base::Bind(&V4L2VideoEncodeAccelerator::EncodeTask, | 205 base::Bind(&V4L2VideoEncodeAccelerator::EncodeTask, |
| 209 base::Unretained(this), | 206 base::Unretained(this), |
| 210 frame, | 207 frame, |
| 211 force_keyframe)); | 208 force_keyframe)); |
| 212 } | 209 } |
| 213 } | 210 } |
| 214 | 211 |
| 215 void V4L2VideoEncodeAccelerator::UseOutputBitstreamBuffer( | 212 void V4L2VideoEncodeAccelerator::UseOutputBitstreamBuffer( |
| 216 const media::BitstreamBuffer& buffer) { | 213 const media::BitstreamBuffer& buffer) { |
| 217 DVLOG(3) << "UseOutputBitstreamBuffer(): id=" << buffer.id(); | 214 DVLOG(3) << "UseOutputBitstreamBuffer(): id=" << buffer.id(); |
| 218 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 215 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 219 | 216 |
| 220 if (buffer.size() < output_buffer_byte_size_) { | 217 if (buffer.size() < output_buffer_byte_size_) { |
| 221 NOTIFY_ERROR(kInvalidArgumentError); | 218 NOTIFY_ERROR(kInvalidArgumentError); |
| 222 return; | 219 return; |
| 223 } | 220 } |
| 224 | 221 |
| 225 scoped_ptr<base::SharedMemory> shm( | 222 scoped_ptr<base::SharedMemory> shm( |
| 226 new base::SharedMemory(buffer.handle(), false)); | 223 new base::SharedMemory(buffer.handle(), false)); |
| 227 if (!shm->Map(buffer.size())) { | 224 if (!shm->Map(buffer.size())) { |
| 228 NOTIFY_ERROR(kPlatformFailureError); | 225 NOTIFY_ERROR(kPlatformFailureError); |
| 229 return; | 226 return; |
| 230 } | 227 } |
| 231 | 228 |
| 232 scoped_ptr<BitstreamBufferRef> buffer_ref( | 229 scoped_ptr<BitstreamBufferRef> buffer_ref( |
| 233 new BitstreamBufferRef(buffer.id(), shm.Pass(), buffer.size())); | 230 new BitstreamBufferRef(buffer.id(), shm.Pass(), buffer.size())); |
| 234 encoder_thread_.message_loop()->PostTask( | 231 encoder_thread_.message_loop()->PostTask( |
| 235 FROM_HERE, | 232 FROM_HERE, |
| 236 base::Bind(&V4L2VideoEncodeAccelerator::UseOutputBitstreamBufferTask, | 233 base::Bind(&V4L2VideoEncodeAccelerator::UseOutputBitstreamBufferTask, |
| 237 base::Unretained(this), | 234 base::Unretained(this), |
| 238 base::Passed(&buffer_ref))); | 235 base::Passed(&buffer_ref))); |
| 239 } | 236 } |
| 240 | 237 |
| 241 void V4L2VideoEncodeAccelerator::RequestEncodingParametersChange( | 238 void V4L2VideoEncodeAccelerator::RequestEncodingParametersChange( |
| 242 uint32 bitrate, | 239 uint32 bitrate, |
| 243 uint32 framerate) { | 240 uint32 framerate) { |
| 244 DVLOG(3) << "RequestEncodingParametersChange(): bitrate=" << bitrate | 241 DVLOG(3) << "RequestEncodingParametersChange(): bitrate=" << bitrate |
| 245 << ", framerate=" << framerate; | 242 << ", framerate=" << framerate; |
| 246 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 243 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 247 | 244 |
| 248 encoder_thread_.message_loop()->PostTask( | 245 encoder_thread_.message_loop()->PostTask( |
| 249 FROM_HERE, | 246 FROM_HERE, |
| 250 base::Bind( | 247 base::Bind( |
| 251 &V4L2VideoEncodeAccelerator::RequestEncodingParametersChangeTask, | 248 &V4L2VideoEncodeAccelerator::RequestEncodingParametersChangeTask, |
| 252 base::Unretained(this), | 249 base::Unretained(this), |
| 253 bitrate, | 250 bitrate, |
| 254 framerate)); | 251 framerate)); |
| 255 } | 252 } |
| 256 | 253 |
| 257 void V4L2VideoEncodeAccelerator::Destroy() { | 254 void V4L2VideoEncodeAccelerator::Destroy() { |
| 258 DVLOG(3) << "Destroy()"; | 255 DVLOG(3) << "Destroy()"; |
| 259 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 256 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 260 | 257 |
| 261 // We're destroying; cancel all callbacks. | 258 // We're destroying; cancel all callbacks. |
| 262 client_ptr_factory_.reset(); | 259 client_ptr_factory_.reset(); |
| 263 weak_this_ptr_factory_.InvalidateWeakPtrs(); | 260 weak_this_ptr_factory_.InvalidateWeakPtrs(); |
| 264 | 261 |
| 265 if (image_processor_.get()) | 262 if (image_processor_.get()) |
| 266 image_processor_.release()->Destroy(); | 263 image_processor_.release()->Destroy(); |
| 267 | 264 |
| 268 // If the encoder thread is running, destroy using posted task. | 265 // If the encoder thread is running, destroy using posted task. |
| 269 if (encoder_thread_.IsRunning()) { | 266 if (encoder_thread_.IsRunning()) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 break; | 311 break; |
| 315 } | 312 } |
| 316 } | 313 } |
| 317 | 314 |
| 318 return profiles; | 315 return profiles; |
| 319 } | 316 } |
| 320 | 317 |
| 321 void V4L2VideoEncodeAccelerator::FrameProcessed( | 318 void V4L2VideoEncodeAccelerator::FrameProcessed( |
| 322 bool force_keyframe, | 319 bool force_keyframe, |
| 323 const scoped_refptr<media::VideoFrame>& frame) { | 320 const scoped_refptr<media::VideoFrame>& frame) { |
| 324 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 321 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 325 DVLOG(3) << "FrameProcessed(): force_keyframe=" << force_keyframe; | 322 DVLOG(3) << "FrameProcessed(): force_keyframe=" << force_keyframe; |
| 326 | 323 |
| 327 encoder_thread_.message_loop()->PostTask( | 324 encoder_thread_.message_loop()->PostTask( |
| 328 FROM_HERE, | 325 FROM_HERE, |
| 329 base::Bind(&V4L2VideoEncodeAccelerator::EncodeTask, | 326 base::Bind(&V4L2VideoEncodeAccelerator::EncodeTask, |
| 330 base::Unretained(this), | 327 base::Unretained(this), |
| 331 frame, | 328 frame, |
| 332 force_keyframe)); | 329 force_keyframe)); |
| 333 } | 330 } |
| 334 | 331 |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 } else { | 574 } else { |
| 578 memcpy(target_data, output_data, output_size); | 575 memcpy(target_data, output_data, output_size); |
| 579 } | 576 } |
| 580 } else { | 577 } else { |
| 581 memcpy(target_data, output_data, output_size); | 578 memcpy(target_data, output_data, output_size); |
| 582 } | 579 } |
| 583 | 580 |
| 584 DVLOG(3) << "Dequeue(): returning " | 581 DVLOG(3) << "Dequeue(): returning " |
| 585 "bitstream_buffer_id=" << output_record.buffer_ref->id | 582 "bitstream_buffer_id=" << output_record.buffer_ref->id |
| 586 << ", size=" << output_size << ", key_frame=" << key_frame; | 583 << ", size=" << output_size << ", key_frame=" << key_frame; |
| 587 child_message_loop_proxy_->PostTask( | 584 child_task_runner_->PostTask( |
| 588 FROM_HERE, | 585 FROM_HERE, |
| 589 base::Bind(&Client::BitstreamBufferReady, | 586 base::Bind(&Client::BitstreamBufferReady, client_, |
| 590 client_, | 587 output_record.buffer_ref->id, output_size, key_frame)); |
| 591 output_record.buffer_ref->id, | |
| 592 output_size, | |
| 593 key_frame)); | |
| 594 output_record.at_device = false; | 588 output_record.at_device = false; |
| 595 output_record.buffer_ref.reset(); | 589 output_record.buffer_ref.reset(); |
| 596 free_output_buffers_.push_back(dqbuf.index); | 590 free_output_buffers_.push_back(dqbuf.index); |
| 597 output_buffer_queued_count_--; | 591 output_buffer_queued_count_--; |
| 598 } | 592 } |
| 599 } | 593 } |
| 600 | 594 |
| 601 bool V4L2VideoEncodeAccelerator::EnqueueInputRecord() { | 595 bool V4L2VideoEncodeAccelerator::EnqueueInputRecord() { |
| 602 DVLOG(3) << "EnqueueInputRecord()"; | 596 DVLOG(3) << "EnqueueInputRecord()"; |
| 603 DCHECK(!free_input_buffers_.empty()); | 597 DCHECK(!free_input_buffers_.empty()); |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 // touch encoder state from this thread. | 761 // touch encoder state from this thread. |
| 768 encoder_thread_.message_loop()->PostTask( | 762 encoder_thread_.message_loop()->PostTask( |
| 769 FROM_HERE, | 763 FROM_HERE, |
| 770 base::Bind(&V4L2VideoEncodeAccelerator::ServiceDeviceTask, | 764 base::Bind(&V4L2VideoEncodeAccelerator::ServiceDeviceTask, |
| 771 base::Unretained(this))); | 765 base::Unretained(this))); |
| 772 } | 766 } |
| 773 | 767 |
| 774 void V4L2VideoEncodeAccelerator::NotifyError(Error error) { | 768 void V4L2VideoEncodeAccelerator::NotifyError(Error error) { |
| 775 DVLOG(1) << "NotifyError(): error=" << error; | 769 DVLOG(1) << "NotifyError(): error=" << error; |
| 776 | 770 |
| 777 if (!child_message_loop_proxy_->BelongsToCurrentThread()) { | 771 if (!child_task_runner_->BelongsToCurrentThread()) { |
| 778 child_message_loop_proxy_->PostTask( | 772 child_task_runner_->PostTask( |
| 779 FROM_HERE, | 773 FROM_HERE, base::Bind(&V4L2VideoEncodeAccelerator::NotifyError, |
| 780 base::Bind( | 774 weak_this_, error)); |
| 781 &V4L2VideoEncodeAccelerator::NotifyError, weak_this_, error)); | |
| 782 return; | 775 return; |
| 783 } | 776 } |
| 784 | 777 |
| 785 if (client_) { | 778 if (client_) { |
| 786 client_->NotifyError(error); | 779 client_->NotifyError(error); |
| 787 client_ptr_factory_.reset(); | 780 client_ptr_factory_.reset(); |
| 788 } | 781 } |
| 789 } | 782 } |
| 790 | 783 |
| 791 void V4L2VideoEncodeAccelerator::SetErrorState(Error error) { | 784 void V4L2VideoEncodeAccelerator::SetErrorState(Error error) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 parms.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 829 parms.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 837 // Note that we are provided "frames per second" but V4L2 expects "time per | 830 // Note that we are provided "frames per second" but V4L2 expects "time per |
| 838 // frame"; hence we provide the reciprocal of the framerate here. | 831 // frame"; hence we provide the reciprocal of the framerate here. |
| 839 parms.parm.output.timeperframe.numerator = 1; | 832 parms.parm.output.timeperframe.numerator = 1; |
| 840 parms.parm.output.timeperframe.denominator = framerate; | 833 parms.parm.output.timeperframe.denominator = framerate; |
| 841 IOCTL_OR_ERROR_RETURN(VIDIOC_S_PARM, &parms); | 834 IOCTL_OR_ERROR_RETURN(VIDIOC_S_PARM, &parms); |
| 842 } | 835 } |
| 843 | 836 |
| 844 bool V4L2VideoEncodeAccelerator::SetOutputFormat( | 837 bool V4L2VideoEncodeAccelerator::SetOutputFormat( |
| 845 media::VideoCodecProfile output_profile) { | 838 media::VideoCodecProfile output_profile) { |
| 846 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 839 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 847 DCHECK(!input_streamon_); | 840 DCHECK(!input_streamon_); |
| 848 DCHECK(!output_streamon_); | 841 DCHECK(!output_streamon_); |
| 849 | 842 |
| 850 output_format_fourcc_ = | 843 output_format_fourcc_ = |
| 851 V4L2Device::VideoCodecProfileToV4L2PixFmt(output_profile, false); | 844 V4L2Device::VideoCodecProfileToV4L2PixFmt(output_profile, false); |
| 852 if (!output_format_fourcc_) { | 845 if (!output_format_fourcc_) { |
| 853 LOG(ERROR) << "Initialize(): invalid output_profile=" << output_profile; | 846 LOG(ERROR) << "Initialize(): invalid output_profile=" << output_profile; |
| 854 return false; | 847 return false; |
| 855 } | 848 } |
| 856 | 849 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 871 size_t adjusted_output_buffer_size = | 864 size_t adjusted_output_buffer_size = |
| 872 base::checked_cast<size_t>(format.fmt.pix_mp.plane_fmt[0].sizeimage); | 865 base::checked_cast<size_t>(format.fmt.pix_mp.plane_fmt[0].sizeimage); |
| 873 output_buffer_byte_size_ = adjusted_output_buffer_size; | 866 output_buffer_byte_size_ = adjusted_output_buffer_size; |
| 874 | 867 |
| 875 return true; | 868 return true; |
| 876 } | 869 } |
| 877 | 870 |
| 878 bool V4L2VideoEncodeAccelerator::NegotiateInputFormat( | 871 bool V4L2VideoEncodeAccelerator::NegotiateInputFormat( |
| 879 media::VideoFrame::Format input_format) { | 872 media::VideoFrame::Format input_format) { |
| 880 DVLOG(3) << "NegotiateInputFormat()"; | 873 DVLOG(3) << "NegotiateInputFormat()"; |
| 881 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 874 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 882 DCHECK(!input_streamon_); | 875 DCHECK(!input_streamon_); |
| 883 DCHECK(!output_streamon_); | 876 DCHECK(!output_streamon_); |
| 884 | 877 |
| 885 device_input_format_ = media::VideoFrame::UNKNOWN; | 878 device_input_format_ = media::VideoFrame::UNKNOWN; |
| 886 input_planes_count_ = 0; | 879 input_planes_count_ = 0; |
| 887 | 880 |
| 888 uint32 input_format_fourcc = | 881 uint32 input_format_fourcc = |
| 889 V4L2Device::VideoFrameFormatToV4L2PixFmt(input_format); | 882 V4L2Device::VideoFrameFormatToV4L2PixFmt(input_format); |
| 890 if (!input_format_fourcc) { | 883 if (!input_format_fourcc) { |
| 891 LOG(ERROR) << "Unsupported input format"; | 884 LOG(ERROR) << "Unsupported input format"; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 | 924 |
| 932 device_input_format_ = input_format; | 925 device_input_format_ = input_format; |
| 933 input_planes_count_ = input_planes_count; | 926 input_planes_count_ = input_planes_count; |
| 934 return true; | 927 return true; |
| 935 } | 928 } |
| 936 | 929 |
| 937 bool V4L2VideoEncodeAccelerator::SetFormats( | 930 bool V4L2VideoEncodeAccelerator::SetFormats( |
| 938 media::VideoFrame::Format input_format, | 931 media::VideoFrame::Format input_format, |
| 939 media::VideoCodecProfile output_profile) { | 932 media::VideoCodecProfile output_profile) { |
| 940 DVLOG(3) << "SetFormats()"; | 933 DVLOG(3) << "SetFormats()"; |
| 941 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 934 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 942 DCHECK(!input_streamon_); | 935 DCHECK(!input_streamon_); |
| 943 DCHECK(!output_streamon_); | 936 DCHECK(!output_streamon_); |
| 944 | 937 |
| 945 if (!SetOutputFormat(output_profile)) | 938 if (!SetOutputFormat(output_profile)) |
| 946 return false; | 939 return false; |
| 947 | 940 |
| 948 if (!NegotiateInputFormat(input_format)) | 941 if (!NegotiateInputFormat(input_format)) |
| 949 return false; | 942 return false; |
| 950 | 943 |
| 951 struct v4l2_crop crop; | 944 struct v4l2_crop crop; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1071 DCHECK(input_buffer_map_.empty()); | 1064 DCHECK(input_buffer_map_.empty()); |
| 1072 input_buffer_map_.resize(reqbufs.count); | 1065 input_buffer_map_.resize(reqbufs.count); |
| 1073 for (size_t i = 0; i < input_buffer_map_.size(); ++i) | 1066 for (size_t i = 0; i < input_buffer_map_.size(); ++i) |
| 1074 free_input_buffers_.push_back(i); | 1067 free_input_buffers_.push_back(i); |
| 1075 | 1068 |
| 1076 return true; | 1069 return true; |
| 1077 } | 1070 } |
| 1078 | 1071 |
| 1079 bool V4L2VideoEncodeAccelerator::CreateOutputBuffers() { | 1072 bool V4L2VideoEncodeAccelerator::CreateOutputBuffers() { |
| 1080 DVLOG(3) << "CreateOutputBuffers()"; | 1073 DVLOG(3) << "CreateOutputBuffers()"; |
| 1081 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1074 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 1082 DCHECK(!output_streamon_); | 1075 DCHECK(!output_streamon_); |
| 1083 | 1076 |
| 1084 struct v4l2_requestbuffers reqbufs; | 1077 struct v4l2_requestbuffers reqbufs; |
| 1085 memset(&reqbufs, 0, sizeof(reqbufs)); | 1078 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1086 reqbufs.count = kOutputBufferCount; | 1079 reqbufs.count = kOutputBufferCount; |
| 1087 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1080 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1088 reqbufs.memory = V4L2_MEMORY_MMAP; | 1081 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1089 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); | 1082 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); |
| 1090 | 1083 |
| 1091 DCHECK(output_buffer_map_.empty()); | 1084 DCHECK(output_buffer_map_.empty()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1113 output_buffer_map_[i].address = address; | 1106 output_buffer_map_[i].address = address; |
| 1114 output_buffer_map_[i].length = buffer.m.planes[0].length; | 1107 output_buffer_map_[i].length = buffer.m.planes[0].length; |
| 1115 free_output_buffers_.push_back(i); | 1108 free_output_buffers_.push_back(i); |
| 1116 } | 1109 } |
| 1117 | 1110 |
| 1118 return true; | 1111 return true; |
| 1119 } | 1112 } |
| 1120 | 1113 |
| 1121 void V4L2VideoEncodeAccelerator::DestroyInputBuffers() { | 1114 void V4L2VideoEncodeAccelerator::DestroyInputBuffers() { |
| 1122 DVLOG(3) << "DestroyInputBuffers()"; | 1115 DVLOG(3) << "DestroyInputBuffers()"; |
| 1123 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1116 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 1124 DCHECK(!input_streamon_); | 1117 DCHECK(!input_streamon_); |
| 1125 | 1118 |
| 1126 struct v4l2_requestbuffers reqbufs; | 1119 struct v4l2_requestbuffers reqbufs; |
| 1127 memset(&reqbufs, 0, sizeof(reqbufs)); | 1120 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1128 reqbufs.count = 0; | 1121 reqbufs.count = 0; |
| 1129 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1122 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1130 reqbufs.memory = input_memory_type_; | 1123 reqbufs.memory = input_memory_type_; |
| 1131 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); | 1124 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); |
| 1132 | 1125 |
| 1133 input_buffer_map_.clear(); | 1126 input_buffer_map_.clear(); |
| 1134 free_input_buffers_.clear(); | 1127 free_input_buffers_.clear(); |
| 1135 } | 1128 } |
| 1136 | 1129 |
| 1137 void V4L2VideoEncodeAccelerator::DestroyOutputBuffers() { | 1130 void V4L2VideoEncodeAccelerator::DestroyOutputBuffers() { |
| 1138 DVLOG(3) << "DestroyOutputBuffers()"; | 1131 DVLOG(3) << "DestroyOutputBuffers()"; |
| 1139 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1132 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 1140 DCHECK(!output_streamon_); | 1133 DCHECK(!output_streamon_); |
| 1141 | 1134 |
| 1142 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { | 1135 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
| 1143 if (output_buffer_map_[i].address != NULL) | 1136 if (output_buffer_map_[i].address != NULL) |
| 1144 device_->Munmap(output_buffer_map_[i].address, | 1137 device_->Munmap(output_buffer_map_[i].address, |
| 1145 output_buffer_map_[i].length); | 1138 output_buffer_map_[i].length); |
| 1146 } | 1139 } |
| 1147 | 1140 |
| 1148 struct v4l2_requestbuffers reqbufs; | 1141 struct v4l2_requestbuffers reqbufs; |
| 1149 memset(&reqbufs, 0, sizeof(reqbufs)); | 1142 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1150 reqbufs.count = 0; | 1143 reqbufs.count = 0; |
| 1151 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1144 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1152 reqbufs.memory = V4L2_MEMORY_MMAP; | 1145 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1153 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); | 1146 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); |
| 1154 | 1147 |
| 1155 output_buffer_map_.clear(); | 1148 output_buffer_map_.clear(); |
| 1156 free_output_buffers_.clear(); | 1149 free_output_buffers_.clear(); |
| 1157 } | 1150 } |
| 1158 | 1151 |
| 1159 } // namespace content | 1152 } // namespace content |
| OLD | NEW |