| 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 |