OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "media/video/capture/file_video_capture_device.h" | 5 #include "media/video/capture/file_video_capture_device.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 } | 103 } |
104 // Last video format semantic correctness check before sending it back. | 104 // Last video format semantic correctness check before sending it back. |
105 CHECK(video_format->IsValid()); | 105 CHECK(video_format->IsValid()); |
106 } | 106 } |
107 | 107 |
108 // Reads and parses the header of a Y4M |file|, returning the collected pixel | 108 // Reads and parses the header of a Y4M |file|, returning the collected pixel |
109 // format in |video_format|. Returns the index of the first byte of the first | 109 // format in |video_format|. Returns the index of the first byte of the first |
110 // video frame. | 110 // video frame. |
111 // Restrictions: Only trivial per-frame headers are supported. | 111 // Restrictions: Only trivial per-frame headers are supported. |
112 int64 ParseFileAndExtractVideoFormat( | 112 int64 ParseFileAndExtractVideoFormat( |
113 const base::PlatformFile& file, | 113 base::File* file, |
114 media::VideoCaptureFormat* video_format) { | 114 media::VideoCaptureFormat* video_format) { |
115 std::string header(kY4MHeaderMaxSize, 0); | 115 std::string header(kY4MHeaderMaxSize, 0); |
116 base::ReadPlatformFile(file, 0, &header[0], kY4MHeaderMaxSize - 1); | 116 file->Read(0, &header[0], kY4MHeaderMaxSize - 1); |
117 | 117 |
118 size_t header_end = header.find(kY4MSimpleFrameDelimiter); | 118 size_t header_end = header.find(kY4MSimpleFrameDelimiter); |
119 CHECK_NE(header_end, header.npos); | 119 CHECK_NE(header_end, header.npos); |
120 | 120 |
121 ParseY4MTags(header, video_format); | 121 ParseY4MTags(header, video_format); |
122 return header_end + kY4MSimpleFrameDelimiterSize; | 122 return header_end + kY4MSimpleFrameDelimiterSize; |
123 } | 123 } |
124 | 124 |
125 // Opens a given file for reading, and returns the file to the caller, who is | 125 // Opens a given file for reading, and returns the file to the caller, who is |
126 // responsible for closing it. | 126 // responsible for closing it. |
127 base::PlatformFile OpenFileForRead(const base::FilePath& file_path) { | 127 base::File OpenFileForRead(const base::FilePath& file_path) { |
128 base::PlatformFileError file_error; | 128 base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); |
129 base::PlatformFile file = base::CreatePlatformFile( | 129 CHECK(file.IsValid()); |
130 file_path, | 130 return file.Pass(); |
131 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, | |
132 NULL, | |
133 &file_error); | |
134 CHECK_EQ(file_error, base::PLATFORM_FILE_OK); | |
135 return file; | |
136 } | 131 } |
137 | 132 |
138 // Inspects the command line and retrieves the file path parameter. | 133 // Inspects the command line and retrieves the file path parameter. |
139 base::FilePath GetFilePathFromCommandLine() { | 134 base::FilePath GetFilePathFromCommandLine() { |
140 base::FilePath command_line_file_path = | 135 base::FilePath command_line_file_path = |
141 CommandLine::ForCurrentProcess()->GetSwitchValuePath( | 136 CommandLine::ForCurrentProcess()->GetSwitchValuePath( |
142 switches::kUseFileForFakeVideoCapture); | 137 switches::kUseFileForFakeVideoCapture); |
143 CHECK(!command_line_file_path.empty()); | 138 CHECK(!command_line_file_path.empty()); |
144 return command_line_file_path; | 139 return command_line_file_path; |
145 } | 140 } |
146 | 141 |
147 void FileVideoCaptureDevice::GetDeviceNames(Names* const device_names) { | 142 void FileVideoCaptureDevice::GetDeviceNames(Names* const device_names) { |
148 DCHECK(device_names->empty()); | 143 DCHECK(device_names->empty()); |
149 base::FilePath command_line_file_path = GetFilePathFromCommandLine(); | 144 base::FilePath command_line_file_path = GetFilePathFromCommandLine(); |
150 #if defined(OS_WIN) | 145 #if defined(OS_WIN) |
151 device_names->push_back( | 146 device_names->push_back( |
152 Name(base::SysWideToUTF8(command_line_file_path.value()), | 147 Name(base::SysWideToUTF8(command_line_file_path.value()), |
153 kFileVideoCaptureDeviceName)); | 148 kFileVideoCaptureDeviceName)); |
154 #else | 149 #else |
155 device_names->push_back(Name(command_line_file_path.value(), | 150 device_names->push_back(Name(command_line_file_path.value(), |
156 kFileVideoCaptureDeviceName)); | 151 kFileVideoCaptureDeviceName)); |
157 #endif // OS_WIN | 152 #endif // OS_WIN |
158 } | 153 } |
159 | 154 |
160 void FileVideoCaptureDevice::GetDeviceSupportedFormats( | 155 void FileVideoCaptureDevice::GetDeviceSupportedFormats( |
161 const Name& device, | 156 const Name& device, |
162 VideoCaptureFormats* supported_formats) { | 157 VideoCaptureFormats* supported_formats) { |
163 base::PlatformFile file = OpenFileForRead(GetFilePathFromCommandLine()); | 158 base::File file = OpenFileForRead(GetFilePathFromCommandLine()); |
164 VideoCaptureFormat capture_format; | 159 VideoCaptureFormat capture_format; |
165 ParseFileAndExtractVideoFormat(file, &capture_format); | 160 ParseFileAndExtractVideoFormat(&file, &capture_format); |
166 supported_formats->push_back(capture_format); | 161 supported_formats->push_back(capture_format); |
167 | |
168 CHECK(base::ClosePlatformFile(file)); | |
169 } | 162 } |
170 | 163 |
171 VideoCaptureDevice* FileVideoCaptureDevice::Create(const Name& device_name) { | 164 VideoCaptureDevice* FileVideoCaptureDevice::Create(const Name& device_name) { |
172 #if defined(OS_WIN) | 165 #if defined(OS_WIN) |
173 return new FileVideoCaptureDevice( | 166 return new FileVideoCaptureDevice( |
174 base::FilePath(base::SysUTF8ToWide(device_name.name()))); | 167 base::FilePath(base::SysUTF8ToWide(device_name.name()))); |
175 #else | 168 #else |
176 return new FileVideoCaptureDevice(base::FilePath(device_name.name())); | 169 return new FileVideoCaptureDevice(base::FilePath(device_name.name())); |
177 #endif // OS_WIN | 170 #endif // OS_WIN |
178 } | 171 } |
179 | 172 |
180 FileVideoCaptureDevice::FileVideoCaptureDevice(const base::FilePath& file_path) | 173 FileVideoCaptureDevice::FileVideoCaptureDevice(const base::FilePath& file_path) |
181 : capture_thread_("CaptureThread"), | 174 : capture_thread_("CaptureThread"), |
182 file_path_(file_path), | 175 file_path_(file_path), |
183 file_(base::kInvalidPlatformFileValue), | |
184 frame_size_(0), | 176 frame_size_(0), |
185 current_byte_index_(0), | 177 current_byte_index_(0), |
186 first_frame_byte_index_(0) {} | 178 first_frame_byte_index_(0) {} |
187 | 179 |
188 FileVideoCaptureDevice::~FileVideoCaptureDevice() { | 180 FileVideoCaptureDevice::~FileVideoCaptureDevice() { |
189 DCHECK(thread_checker_.CalledOnValidThread()); | 181 DCHECK(thread_checker_.CalledOnValidThread()); |
190 // Check if the thread is running. | 182 // Check if the thread is running. |
191 // This means that the device have not been DeAllocated properly. | 183 // This means that the device have not been DeAllocated properly. |
192 CHECK(!capture_thread_.IsRunning()); | 184 CHECK(!capture_thread_.IsRunning()); |
193 } | 185 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 } | 217 } |
226 | 218 |
227 void FileVideoCaptureDevice::OnAllocateAndStart( | 219 void FileVideoCaptureDevice::OnAllocateAndStart( |
228 const VideoCaptureParams& params, | 220 const VideoCaptureParams& params, |
229 scoped_ptr<VideoCaptureDevice::Client> client) { | 221 scoped_ptr<VideoCaptureDevice::Client> client) { |
230 DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current()); | 222 DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current()); |
231 | 223 |
232 client_ = client.Pass(); | 224 client_ = client.Pass(); |
233 | 225 |
234 // Open the file and parse the header. Get frame size and format. | 226 // Open the file and parse the header. Get frame size and format. |
235 DCHECK_EQ(file_, base::kInvalidPlatformFileValue); | 227 DCHECK(file_.IsValid()); |
236 file_ = OpenFileForRead(file_path_); | 228 file_ = OpenFileForRead(file_path_); |
237 first_frame_byte_index_ = | 229 first_frame_byte_index_ = |
238 ParseFileAndExtractVideoFormat(file_, &capture_format_); | 230 ParseFileAndExtractVideoFormat(&file_, &capture_format_); |
239 current_byte_index_ = first_frame_byte_index_; | 231 current_byte_index_ = first_frame_byte_index_; |
240 DVLOG(1) << "Opened video file " << capture_format_.frame_size.ToString() | 232 DVLOG(1) << "Opened video file " << capture_format_.frame_size.ToString() |
241 << ", fps: " << capture_format_.frame_rate; | 233 << ", fps: " << capture_format_.frame_rate; |
242 | 234 |
243 frame_size_ = CalculateFrameSize(); | 235 frame_size_ = CalculateFrameSize(); |
244 video_frame_.reset(new uint8[frame_size_]); | 236 video_frame_.reset(new uint8[frame_size_]); |
245 | 237 |
246 capture_thread_.message_loop()->PostTask( | 238 capture_thread_.message_loop()->PostTask( |
247 FROM_HERE, | 239 FROM_HERE, |
248 base::Bind(&FileVideoCaptureDevice::OnCaptureTask, | 240 base::Bind(&FileVideoCaptureDevice::OnCaptureTask, |
249 base::Unretained(this))); | 241 base::Unretained(this))); |
250 } | 242 } |
251 | 243 |
252 void FileVideoCaptureDevice::OnStopAndDeAllocate() { | 244 void FileVideoCaptureDevice::OnStopAndDeAllocate() { |
253 DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current()); | 245 DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current()); |
254 CHECK(base::ClosePlatformFile(file_)); | 246 file_.Close(); |
255 client_.reset(); | 247 client_.reset(); |
256 current_byte_index_ = 0; | 248 current_byte_index_ = 0; |
257 first_frame_byte_index_ = 0; | 249 first_frame_byte_index_ = 0; |
258 frame_size_ = 0; | 250 frame_size_ = 0; |
259 video_frame_.reset(); | 251 video_frame_.reset(); |
260 } | 252 } |
261 | 253 |
262 void FileVideoCaptureDevice::OnCaptureTask() { | 254 void FileVideoCaptureDevice::OnCaptureTask() { |
263 DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current()); | 255 DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current()); |
264 if (!client_) | 256 if (!client_) |
265 return; | 257 return; |
266 int result = | 258 int result = file_.Read(current_byte_index_, |
267 base::ReadPlatformFile(file_, | 259 reinterpret_cast<char*>(video_frame_.get()), |
268 current_byte_index_, | 260 frame_size_); |
269 reinterpret_cast<char*>(video_frame_.get()), | |
270 frame_size_); | |
271 | 261 |
272 // If we passed EOF to PlatformFile, it will return 0 read characters. In that | 262 // If we passed EOF to base::File, it will return 0 read characters. In that |
273 // case, reset the pointer and read again. | 263 // case, reset the pointer and read again. |
274 if (result != frame_size_) { | 264 if (result != frame_size_) { |
275 CHECK_EQ(result, 0); | 265 CHECK_EQ(result, 0); |
276 current_byte_index_ = first_frame_byte_index_; | 266 current_byte_index_ = first_frame_byte_index_; |
277 CHECK_EQ(base::ReadPlatformFile(file_, | 267 CHECK_EQ(file_.Read(current_byte_index_, |
278 current_byte_index_, | 268 reinterpret_cast<char*>(video_frame_.get()), |
279 reinterpret_cast<char*>(video_frame_.get()), | 269 frame_size_), |
280 frame_size_), | |
281 frame_size_); | 270 frame_size_); |
282 } else { | 271 } else { |
283 current_byte_index_ += frame_size_ + kY4MSimpleFrameDelimiterSize; | 272 current_byte_index_ += frame_size_ + kY4MSimpleFrameDelimiterSize; |
284 } | 273 } |
285 | 274 |
286 // Give the captured frame to the client. | 275 // Give the captured frame to the client. |
287 client_->OnIncomingCapturedFrame(video_frame_.get(), | 276 client_->OnIncomingCapturedFrame(video_frame_.get(), |
288 frame_size_, | 277 frame_size_, |
289 base::TimeTicks::Now(), | 278 base::TimeTicks::Now(), |
290 0, | 279 0, |
291 capture_format_); | 280 capture_format_); |
292 // Reschedule next CaptureTask. | 281 // Reschedule next CaptureTask. |
293 base::MessageLoop::current()->PostDelayedTask( | 282 base::MessageLoop::current()->PostDelayedTask( |
294 FROM_HERE, | 283 FROM_HERE, |
295 base::Bind(&FileVideoCaptureDevice::OnCaptureTask, | 284 base::Bind(&FileVideoCaptureDevice::OnCaptureTask, |
296 base::Unretained(this)), | 285 base::Unretained(this)), |
297 base::TimeDelta::FromSeconds(1) / capture_format_.frame_rate); | 286 base::TimeDelta::FromSeconds(1) / capture_format_.frame_rate); |
298 } | 287 } |
299 | 288 |
300 } // namespace media | 289 } // namespace media |
OLD | NEW |