Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Unified Diff: media/capture/video/file_video_capture_device.cc

Issue 2143903003: [WIP] Move media/capture to device/capture (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/capture/video/file_video_capture_device.cc
diff --git a/media/capture/video/file_video_capture_device.cc b/media/capture/video/file_video_capture_device.cc
deleted file mode 100644
index 10b3710f53fdf9775cda8682174c3ae5faf2aa84..0000000000000000000000000000000000000000
--- a/media/capture/video/file_video_capture_device.cc
+++ /dev/null
@@ -1,394 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/capture/video/file_video_capture_device.h"
-
-#include <stddef.h>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "media/base/video_capture_types.h"
-#include "media/filters/jpeg_parser.h"
-
-namespace media {
-
-static const int kY4MHeaderMaxSize = 200;
-static const char kY4MSimpleFrameDelimiter[] = "FRAME";
-static const int kY4MSimpleFrameDelimiterSize = 6;
-static const float kMJpegFrameRate = 30.0f;
-
-int ParseY4MInt(const base::StringPiece& token) {
- int temp_int;
- CHECK(base::StringToInt(token, &temp_int)) << token;
- return temp_int;
-}
-
-// Extract numerator and denominator out of a token that must have the aspect
-// numerator:denominator, both integer numbers.
-void ParseY4MRational(const base::StringPiece& token,
- int* numerator, int* denominator) {
- size_t index_divider = token.find(':');
- CHECK_NE(index_divider, token.npos);
- *numerator = ParseY4MInt(token.substr(0, index_divider));
- *denominator = ParseY4MInt(token.substr(index_divider + 1, token.length()));
- CHECK(*denominator);
-}
-
-// This function parses the ASCII string in |header| as belonging to a Y4M file,
-// returning the collected format in |video_format|. For a non authoritative
-// explanation of the header format, check
-// http://wiki.multimedia.cx/index.php?title=YUV4MPEG2
-// Restrictions: Only interlaced I420 pixel format is supported, and pixel
-// aspect ratio is ignored.
-// Implementation notes: Y4M header should end with an ASCII 0x20 (whitespace)
-// character, however all examples mentioned in the Y4M header description end
-// with a newline character instead. Also, some headers do _not_ specify pixel
-// format, in this case it means I420.
-// This code was inspired by third_party/libvpx/.../y4minput.* .
-void ParseY4MTags(const std::string& file_header,
- media::VideoCaptureFormat* video_format) {
- media::VideoCaptureFormat format;
- format.pixel_format = media::PIXEL_FORMAT_I420;
- size_t index = 0;
- size_t blank_position = 0;
- base::StringPiece token;
- while ((blank_position = file_header.find_first_of("\n ", index)) !=
- std::string::npos) {
- // Every token is supposed to have an identifier letter and a bunch of
- // information immediately after, which we extract into a |token| here.
- token =
- base::StringPiece(&file_header[index + 1], blank_position - index - 1);
- CHECK(!token.empty());
- switch (file_header[index]) {
- case 'W':
- format.frame_size.set_width(ParseY4MInt(token));
- break;
- case 'H':
- format.frame_size.set_height(ParseY4MInt(token));
- break;
- case 'F': {
- // If the token is "FRAME", it means we have finished with the header.
- if (token[0] == 'R')
- break;
- int fps_numerator, fps_denominator;
- ParseY4MRational(token, &fps_numerator, &fps_denominator);
- format.frame_rate = fps_numerator / fps_denominator;
- break;
- }
- case 'I':
- // Interlacing is ignored, but we don't like mixed modes.
- CHECK_NE(token[0], 'm');
- break;
- case 'A':
- // Pixel aspect ratio ignored.
- break;
- case 'C':
- CHECK(token == "420" || token == "420jpeg" || token == "420paldv")
- << token; // Only I420 is supported, and we fudge the variants.
- break;
- default:
- break;
- }
- // We're done if we have found a newline character right after the token.
- if (file_header[blank_position] == '\n')
- break;
- index = blank_position + 1;
- }
- // Last video format semantic correctness check before sending it back.
- CHECK(format.IsValid());
- *video_format = format;
-}
-
-class VideoFileParser {
- public:
- explicit VideoFileParser(const base::FilePath& file_path);
- virtual ~VideoFileParser();
-
- // Parses file header and collects format information in |capture_format|.
- virtual bool Initialize(media::VideoCaptureFormat* capture_format) = 0;
-
- // Gets the start pointer of next frame and stores current frame size in
- // |frame_size|.
- virtual const uint8_t* GetNextFrame(int* frame_size) = 0;
-
- protected:
- const base::FilePath file_path_;
- int frame_size_;
- size_t current_byte_index_;
- size_t first_frame_byte_index_;
-};
-
-class Y4mFileParser final : public VideoFileParser {
- public:
- explicit Y4mFileParser(const base::FilePath& file_path);
-
- // VideoFileParser implementation, class methods.
- ~Y4mFileParser() override;
- bool Initialize(media::VideoCaptureFormat* capture_format) override;
- const uint8_t* GetNextFrame(int* frame_size) override;
-
- private:
- std::unique_ptr<base::File> file_;
- std::unique_ptr<uint8_t[]> video_frame_;
-
- DISALLOW_COPY_AND_ASSIGN(Y4mFileParser);
-};
-
-class MjpegFileParser final : public VideoFileParser {
- public:
- explicit MjpegFileParser(const base::FilePath& file_path);
-
- // VideoFileParser implementation, class methods.
- ~MjpegFileParser() override;
- bool Initialize(media::VideoCaptureFormat* capture_format) override;
- const uint8_t* GetNextFrame(int* frame_size) override;
-
- private:
- std::unique_ptr<base::MemoryMappedFile> mapped_file_;
-
- DISALLOW_COPY_AND_ASSIGN(MjpegFileParser);
-};
-
-VideoFileParser::VideoFileParser(const base::FilePath& file_path)
- : file_path_(file_path),
- frame_size_(0),
- current_byte_index_(0),
- first_frame_byte_index_(0) {}
-
-VideoFileParser::~VideoFileParser() {}
-
-Y4mFileParser::Y4mFileParser(const base::FilePath& file_path)
- : VideoFileParser(file_path) {}
-
-Y4mFileParser::~Y4mFileParser() {}
-
-bool Y4mFileParser::Initialize(media::VideoCaptureFormat* capture_format) {
- file_.reset(new base::File(file_path_,
- base::File::FLAG_OPEN | base::File::FLAG_READ));
- if (!file_->IsValid()) {
- DLOG(ERROR) << file_path_.value() << ", error: "
- << base::File::ErrorToString(file_->error_details());
- return false;
- }
-
- std::string header(kY4MHeaderMaxSize, '\0');
- file_->Read(0, &header[0], header.size());
- const size_t header_end = header.find(kY4MSimpleFrameDelimiter);
- CHECK_NE(header_end, header.npos);
-
- ParseY4MTags(header, capture_format);
- first_frame_byte_index_ = header_end + kY4MSimpleFrameDelimiterSize;
- current_byte_index_ = first_frame_byte_index_;
- frame_size_ = capture_format->ImageAllocationSize();
- return true;
-}
-
-const uint8_t* Y4mFileParser::GetNextFrame(int* frame_size) {
- if (!video_frame_)
- video_frame_.reset(new uint8_t[frame_size_]);
- int result =
- file_->Read(current_byte_index_,
- reinterpret_cast<char*>(video_frame_.get()), frame_size_);
-
- // If we passed EOF to base::File, it will return 0 read characters. In that
- // case, reset the pointer and read again.
- if (result != frame_size_) {
- CHECK_EQ(result, 0);
- current_byte_index_ = first_frame_byte_index_;
- CHECK_EQ(
- file_->Read(current_byte_index_,
- reinterpret_cast<char*>(video_frame_.get()), frame_size_),
- frame_size_);
- } else {
- current_byte_index_ += frame_size_ + kY4MSimpleFrameDelimiterSize;
- }
- *frame_size = frame_size_;
- return video_frame_.get();
-}
-
-MjpegFileParser::MjpegFileParser(const base::FilePath& file_path)
- : VideoFileParser(file_path) {}
-
-MjpegFileParser::~MjpegFileParser() {}
-
-bool MjpegFileParser::Initialize(media::VideoCaptureFormat* capture_format) {
- mapped_file_.reset(new base::MemoryMappedFile());
-
- if (!mapped_file_->Initialize(file_path_) || !mapped_file_->IsValid()) {
- LOG(ERROR) << "File memory map error: " << file_path_.value();
- return false;
- }
-
- JpegParseResult result;
- if (!ParseJpegStream(mapped_file_->data(), mapped_file_->length(), &result))
- return false;
-
- frame_size_ = result.image_size;
- if (frame_size_ > static_cast<int>(mapped_file_->length())) {
- LOG(ERROR) << "File is incomplete";
- return false;
- }
-
- VideoCaptureFormat format;
- format.pixel_format = media::PIXEL_FORMAT_MJPEG;
- format.frame_size.set_width(result.frame_header.visible_width);
- format.frame_size.set_height(result.frame_header.visible_height);
- format.frame_rate = kMJpegFrameRate;
- if (!format.IsValid())
- return false;
- *capture_format = format;
- return true;
-}
-
-const uint8_t* MjpegFileParser::GetNextFrame(int* frame_size) {
- const uint8_t* buf_ptr = mapped_file_->data() + current_byte_index_;
-
- JpegParseResult result;
- if (!ParseJpegStream(buf_ptr, mapped_file_->length() - current_byte_index_,
- &result)) {
- return nullptr;
- }
- *frame_size = frame_size_ = result.image_size;
- current_byte_index_ += frame_size_;
- // Reset the pointer to play repeatedly.
- if (current_byte_index_ >= mapped_file_->length())
- current_byte_index_ = first_frame_byte_index_;
- return buf_ptr;
-}
-
-// static
-bool FileVideoCaptureDevice::GetVideoCaptureFormat(
- const base::FilePath& file_path,
- media::VideoCaptureFormat* video_format) {
- std::unique_ptr<VideoFileParser> file_parser =
- GetVideoFileParser(file_path, video_format);
- return file_parser != nullptr;
-}
-
-// static
-std::unique_ptr<VideoFileParser> FileVideoCaptureDevice::GetVideoFileParser(
- const base::FilePath& file_path,
- media::VideoCaptureFormat* video_format) {
- std::unique_ptr<VideoFileParser> file_parser;
- std::string file_name(file_path.value().begin(), file_path.value().end());
-
- if (base::EndsWith(file_name, "y4m",
- base::CompareCase::INSENSITIVE_ASCII)) {
- file_parser.reset(new Y4mFileParser(file_path));
- } else if (base::EndsWith(file_name, "mjpeg",
- base::CompareCase::INSENSITIVE_ASCII)) {
- file_parser.reset(new MjpegFileParser(file_path));
- } else {
- LOG(ERROR) << "Unsupported file format.";
- return file_parser;
- }
-
- if (!file_parser->Initialize(video_format)) {
- file_parser.reset();
- }
- return file_parser;
-}
-
-FileVideoCaptureDevice::FileVideoCaptureDevice(const base::FilePath& file_path)
- : capture_thread_("CaptureThread"), file_path_(file_path) {}
-
-FileVideoCaptureDevice::~FileVideoCaptureDevice() {
- DCHECK(thread_checker_.CalledOnValidThread());
- // Check if the thread is running.
- // This means that the device have not been DeAllocated properly.
- CHECK(!capture_thread_.IsRunning());
-}
-
-void FileVideoCaptureDevice::AllocateAndStart(
- const VideoCaptureParams& params,
- std::unique_ptr<VideoCaptureDevice::Client> client) {
- DCHECK(thread_checker_.CalledOnValidThread());
- CHECK(!capture_thread_.IsRunning());
-
- capture_thread_.Start();
- capture_thread_.task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&FileVideoCaptureDevice::OnAllocateAndStart,
- base::Unretained(this), params, base::Passed(&client)));
-}
-
-void FileVideoCaptureDevice::StopAndDeAllocate() {
- DCHECK(thread_checker_.CalledOnValidThread());
- CHECK(capture_thread_.IsRunning());
-
- capture_thread_.task_runner()->PostTask(
- FROM_HERE, base::Bind(&FileVideoCaptureDevice::OnStopAndDeAllocate,
- base::Unretained(this)));
- capture_thread_.Stop();
-}
-
-void FileVideoCaptureDevice::OnAllocateAndStart(
- const VideoCaptureParams& params,
- std::unique_ptr<VideoCaptureDevice::Client> client) {
- DCHECK(capture_thread_.task_runner()->BelongsToCurrentThread());
-
- client_ = std::move(client);
-
- DCHECK(!file_parser_);
- file_parser_ = GetVideoFileParser(file_path_, &capture_format_);
- if (!file_parser_) {
- client_->OnError(FROM_HERE, "Could not open Video file");
- return;
- }
-
- DVLOG(1) << "Opened video file " << capture_format_.frame_size.ToString()
- << ", fps: " << capture_format_.frame_rate;
-
- capture_thread_.task_runner()->PostTask(
- FROM_HERE, base::Bind(&FileVideoCaptureDevice::OnCaptureTask,
- base::Unretained(this)));
-}
-
-void FileVideoCaptureDevice::OnStopAndDeAllocate() {
- DCHECK(capture_thread_.task_runner()->BelongsToCurrentThread());
- file_parser_.reset();
- client_.reset();
- next_frame_time_ = base::TimeTicks();
-}
-
-void FileVideoCaptureDevice::OnCaptureTask() {
- DCHECK(capture_thread_.task_runner()->BelongsToCurrentThread());
- if (!client_)
- return;
-
- // Give the captured frame to the client.
- int frame_size = 0;
- const uint8_t* frame_ptr = file_parser_->GetNextFrame(&frame_size);
- DCHECK(frame_size);
- CHECK(frame_ptr);
- const base::TimeTicks current_time = base::TimeTicks::Now();
- if (first_ref_time_.is_null())
- first_ref_time_ = current_time;
- client_->OnIncomingCapturedData(frame_ptr, frame_size, capture_format_, 0,
- current_time, current_time - first_ref_time_);
- // Reschedule next CaptureTask.
- const base::TimeDelta frame_interval =
- base::TimeDelta::FromMicroseconds(1E6 / capture_format_.frame_rate);
- if (next_frame_time_.is_null()) {
- next_frame_time_ = current_time + frame_interval;
- } else {
- next_frame_time_ += frame_interval;
- // Don't accumulate any debt if we are lagging behind - just post next frame
- // immediately and continue as normal.
- if (next_frame_time_ < current_time)
- next_frame_time_ = current_time;
- }
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&FileVideoCaptureDevice::OnCaptureTask,
- base::Unretained(this)),
- next_frame_time_ - current_time);
-}
-
-} // namespace media
« no previous file with comments | « media/capture/video/file_video_capture_device.h ('k') | media/capture/video/file_video_capture_device_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698