diff --git a/mediapipe/calculators/video/BUILD b/mediapipe/calculators/video/BUILD index 2244ad0dc..b48990c15 100644 --- a/mediapipe/calculators/video/BUILD +++ b/mediapipe/calculators/video/BUILD @@ -113,6 +113,29 @@ cc_library( alwayslink = 1, ) +cc_library( + name = "opencv_video_imshow_calculator", + srcs = ["opencv_video_imshow_calculator.cc"], + visibility = ["//visibility:public"], + deps = [ + ":opencv_video_encoder_calculator_cc_proto", + "//mediapipe/framework:calculator_framework", + "//mediapipe/framework/formats:image_frame", + "//mediapipe/framework/formats:image_frame_opencv", + "//mediapipe/framework/formats:video_stream_header", + "//mediapipe/framework/port:file_helpers", + "//mediapipe/framework/port:opencv_highgui", + "//mediapipe/framework/port:opencv_imgproc", + "//mediapipe/framework/port:opencv_video", + "//mediapipe/framework/port:ret_check", + "//mediapipe/framework/port:source_location", + "//mediapipe/framework/port:status", + "//mediapipe/framework/tool:status_util", + "@com_google_absl//absl/strings", + ], + alwayslink = 1, +) + cc_library( name = "tvl1_optical_flow_calculator", srcs = ["tvl1_optical_flow_calculator.cc"], diff --git a/mediapipe/calculators/video/opencv_video_decoder_calculator.cc b/mediapipe/calculators/video/opencv_video_decoder_calculator.cc index 2b1f205c5..b8ca8970f 100644 --- a/mediapipe/calculators/video/opencv_video_decoder_calculator.cc +++ b/mediapipe/calculators/video/opencv_video_decoder_calculator.cc @@ -85,15 +85,17 @@ class OpenCvVideoDecoderCalculator : public CalculatorBase { return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC) << "Fail to open video file at " << input_file_path; } - width_ = static_cast(cap_->get(cv::CAP_PROP_FRAME_WIDTH)); - height_ = static_cast(cap_->get(cv::CAP_PROP_FRAME_HEIGHT)); - double fps = static_cast(cap_->get(cv::CAP_PROP_FPS)); - frame_count_ = static_cast(cap_->get(cv::CAP_PROP_FRAME_COUNT)); + // Unfortunately, cap_->get(cv::CAP_PROP_FORMAT) always returns CV_8UC1 // back. To get correct image format, we read the first frame from the video // and get the number of channels. cv::Mat frame; cap_->read(frame); + width_ = static_cast(cap_->get(cv::CAP_PROP_FRAME_WIDTH)); + height_ = static_cast(cap_->get(cv::CAP_PROP_FRAME_HEIGHT)); + double fps = static_cast(cap_->get(cv::CAP_PROP_FPS)); + frame_count_ = static_cast(cap_->get(cv::CAP_PROP_FRAME_COUNT)); + if (frame.empty()) { return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC) << "Fail to read any frames from the video file at " @@ -106,11 +108,16 @@ class OpenCvVideoDecoderCalculator : public CalculatorBase { << input_file_path; } - if (fps <= 0 || frame_count_ <= 0 || width_ <= 0 || height_ <= 0) { + if (fps <= 0 || frame_count_ == 0 || width_ <= 0 || height_ <= 0) { return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC) << "Fail to make video header due to the incorrect metadata from " "the video file at " - << input_file_path; + << input_file_path + << ", format:" << format_ + << ", fps:" << fps + << ", frame count:" << frame_count_ + << ", width:" << width_ + << ", height:" << height_; } auto header = absl::make_unique(); header->format = format_; diff --git a/mediapipe/calculators/video/opencv_video_imshow_calculator.cc b/mediapipe/calculators/video/opencv_video_imshow_calculator.cc new file mode 100644 index 000000000..29038cb6c --- /dev/null +++ b/mediapipe/calculators/video/opencv_video_imshow_calculator.cc @@ -0,0 +1,168 @@ +// Copyright 2019 The MediaPipe Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include "absl/strings/str_split.h" +#include "mediapipe/calculators/video/opencv_video_encoder_calculator.pb.h" +#include "mediapipe/framework/calculator_framework.h" +#include "mediapipe/framework/formats/image_frame.h" +#include "mediapipe/framework/formats/image_frame_opencv.h" +#include "mediapipe/framework/formats/video_stream_header.h" +#include "mediapipe/framework/port/file_helpers.h" +#include "mediapipe/framework/port/opencv_highgui_inc.h" +#include "mediapipe/framework/port/opencv_imgproc_inc.h" +#include "mediapipe/framework/port/opencv_video_inc.h" +#include "mediapipe/framework/port/ret_check.h" +#include "mediapipe/framework/port/source_location.h" +#include "mediapipe/framework/port/status.h" +#include "mediapipe/framework/port/status_builder.h" +#include "mediapipe/framework/tool/status_util.h" + +namespace mediapipe { + +// Encodes the input video stream and produces a media file. +// The media file can be output to the output_file_path specified as a side +// packet. Currently, the calculator only supports one video stream (in +// mediapipe::ImageFrame). +// +// Example config to generate the output video file: +// +// node { +// calculator: "OpenCvVideoImShowCalculator" +// input_stream: "VIDEO:video" +// input_stream: "VIDEO_PRESTREAM:video_header" +// input_side_packet: "OUTPUT_FILE_PATH:output_file_path" +// node_options { +// [type.googleapis.com/mediapipe.OpenCvVideoImShowCalculatorOptions]: { +// codec: "avc1" +// video_format: "mp4" +// } +// } +// } +class OpenCvVideoImShowCalculator : public CalculatorBase { + public: + static ::mediapipe::Status GetContract(CalculatorContract* cc); + ::mediapipe::Status Open(CalculatorContext* cc) override; + ::mediapipe::Status Process(CalculatorContext* cc) override; + ::mediapipe::Status Close(CalculatorContext* cc) override; + + private: + ::mediapipe::Status SetUpVideoWriter(); + + std::string output_file_path_; + int four_cc_; + + std::unique_ptr writer_; +}; + +::mediapipe::Status OpenCvVideoImShowCalculator::GetContract( + CalculatorContract* cc) { + RET_CHECK(cc->Inputs().HasTag("VIDEO")); + cc->Inputs().Tag("VIDEO").Set(); + if (cc->Inputs().HasTag("VIDEO_PRESTREAM")) { + cc->Inputs().Tag("VIDEO_PRESTREAM").Set(); + } + //RET_CHECK(cc->InputSidePackets().HasTag("OUTPUT_FILE_PATH")); + //cc->InputSidePackets().Tag("OUTPUT_FILE_PATH").Set(); + return ::mediapipe::OkStatus(); +} + +::mediapipe::Status OpenCvVideoImShowCalculator::Open(CalculatorContext* cc) { + OpenCvVideoEncoderCalculatorOptions options = + cc->Options(); + RET_CHECK(options.has_codec() && options.codec().length() == 4) + << "A 4-character codec code must be specified in " + "OpenCvVideoEncoderCalculatorOptions"; + const char* codec_array = options.codec().c_str(); + four_cc_ = mediapipe::fourcc(codec_array[0], codec_array[1], codec_array[2], + codec_array[3]); + RET_CHECK(!options.video_format().empty()) + << "Video format must be specified in " + "OpenCvVideoEncoderCalculatorOptions"; + /* output_file_path_ = + cc->InputSidePackets().Tag("OUTPUT_FILE_PATH").Get(); + std::vector splited_file_path = + absl::StrSplit(output_file_path_, '.'); + RET_CHECK(splited_file_path.size() >= 2 && + splited_file_path[splited_file_path.size() - 1] == + options.video_format()) + << "The output file path is invalid.";*/ + // If the video header will be available, the video metadata will be fetched + // from the video header directly. The calculator will receive the video + // header packet at timestamp prestream. + if (cc->Inputs().HasTag("VIDEO_PRESTREAM")) { + return ::mediapipe::OkStatus(); + } + return SetUpVideoWriter(); +} + +::mediapipe::Status OpenCvVideoImShowCalculator::Process( + CalculatorContext* cc) { + if (cc->InputTimestamp() == Timestamp::PreStream()) { + //const VideoHeader& video_header = + // cc->Inputs().Tag("VIDEO_PRESTREAM").Get(); + return SetUpVideoWriter(); + } + + const ImageFrame& image_frame = + cc->Inputs().Tag("VIDEO").Value().Get(); + ImageFormat::Format format = image_frame.Format(); + cv::Mat frame; + if (format == ImageFormat::GRAY8) { + frame = formats::MatView(&image_frame); + if (frame.empty()) { + return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC) + << "Receive empty frame at timestamp " + << cc->Inputs().Tag("VIDEO").Value().Timestamp() + << " in OpenCvVideoImShowCalculator::Process()"; + } + } else { + cv::Mat tmp_frame = formats::MatView(&image_frame); + if (tmp_frame.empty()) { + return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC) + << "Receive empty frame at timestamp " + << cc->Inputs().Tag("VIDEO").Value().Timestamp() + << " in OpenCvVideoImShowCalculator::Process()"; + } + if (format == ImageFormat::SRGB) { + cv::cvtColor(tmp_frame, frame, cv::COLOR_RGB2BGR); + } else if (format == ImageFormat::SRGBA) { + cv::cvtColor(tmp_frame, frame, cv::COLOR_RGBA2BGR); + } else { + return ::mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC) + << "Unsupported image format: " << format; + } + } + cv::imshow("MediaPipe",frame); + cv::waitKey(25); + + return ::mediapipe::OkStatus(); +} + +::mediapipe::Status OpenCvVideoImShowCalculator::Close(CalculatorContext* cc) { + //cv::destroyAllWindows(); + return ::mediapipe::OkStatus(); +} + +::mediapipe::Status OpenCvVideoImShowCalculator::SetUpVideoWriter() { + + cv::namedWindow("MediaPipe",cv::WINDOW_GUI_EXPANDED); + return ::mediapipe::OkStatus(); +} + +REGISTER_CALCULATOR(OpenCvVideoImShowCalculator); +} // namespace mediapipe diff --git a/mediapipe/examples/desktop/simpleIO/BUILD b/mediapipe/examples/desktop/simpleIO/BUILD new file mode 100644 index 000000000..14b5292b7 --- /dev/null +++ b/mediapipe/examples/desktop/simpleIO/BUILD @@ -0,0 +1,27 @@ +# Copyright 2019 The MediaPipe Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +licenses(["notice"]) # Apache 2.0 + +package(default_visibility = ["//mediapipe/examples:__subpackages__"]) + + + +cc_binary( + name = "simple_io_tflite", + deps = [ + "//mediapipe/examples/desktop:simple_run_graph_main", + "//mediapipe/graphs/simple_io:desktop_tflite_calculators", + ], +) diff --git a/mediapipe/examples/desktop/simpleIO/README.md b/mediapipe/examples/desktop/simpleIO/README.md new file mode 100644 index 000000000..cc9b32356 --- /dev/null +++ b/mediapipe/examples/desktop/simpleIO/README.md @@ -0,0 +1,33 @@ + + +$ bazel build -c opt --define MEDIAPIPE_DISABLE_GPU=1 \ + mediapipe/examples/desktop/simpleIO:simple_io_tflite + +# It should print: +# Target //mediapipe/examples/desktop/simpleIO:simple_io_tflite up-to-date: +# bazel-bin/mediapipe/examples/desktop/simpleIO/simple_io_tflite +# INFO: Elapsed time: 36.417s, Critical Path: 23.22s +# INFO: 711 processes: 710 linux-sandbox, 1 local. +# INFO: Build completed successfully, 734 total actions + +$ export GLOG_logtostderr=1 + +# INPUT= file, OUTPUT=file +# Replace and . +# You can find a test video in mediapipe/examples/desktop/simpleIO. +$ bazel-bin/mediapipe/examples/desktop/simpleIO/simple_io_tflite \ + --calculator_graph_config_file=mediapipe/graphs/simple_io/simple_io_graph.pbtxt \ + --input_side_packets=input_video_path=./mediapipe/examples/desktop/simpleIO/test_video.mp4,output_video_path=./mediapipe/examples/desktop/simpleIO/output_video.mp4 + +# INPUT= file, OUTPUT=screen + +$ bazel-bin/mediapipe/examples/desktop/simpleIO/simple_io_tflite \ + --calculator_graph_config_file=mediapipe/graphs/simple_io/simple_media_to_screen_graph.pbtxt \ + --input_side_packets=input_video_path=./mediapipe/examples/desktop/simpleIO/test_video.mp4 + + +# INPUT= Stream , OUTPUT=screen + +$ bazel-bin/mediapipe/examples/desktop/simpleIO/simple_io_tflite \ + --calculator_graph_config_file=mediapipe/graphs/simple_io/simple_media_to_screen_graph.pbtxt \ + --input_side_packets=input_video_path=rtp://0.0.0.0:5000 \ No newline at end of file diff --git a/mediapipe/examples/desktop/simpleIO/simple_run_graph_main.cc b/mediapipe/examples/desktop/simpleIO/simple_run_graph_main.cc new file mode 100644 index 000000000..7fc93142c --- /dev/null +++ b/mediapipe/examples/desktop/simpleIO/simple_run_graph_main.cc @@ -0,0 +1,70 @@ +// Copyright 2019 The MediaPipe Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// A simple main function to run a MediaPipe graph. + +#include "absl/strings/str_split.h" +#include "mediapipe/framework/calculator_framework.h" +#include "mediapipe/framework/port/commandlineflags.h" +#include "mediapipe/framework/port/file_helpers.h" +#include "mediapipe/framework/port/map_util.h" +#include "mediapipe/framework/port/parse_text_proto.h" +#include "mediapipe/framework/port/status.h" + +DEFINE_string( + calculator_graph_config_file, "", + "Name of file containing text format CalculatorGraphConfig proto."); + +DEFINE_string(input_side_packets, "", + "Comma-separated list of key=value pairs specifying side packets " + "for the CalculatorGraph. All values will be treated as the " + "string type even if they represent doubles, floats, etc."); + +::mediapipe::Status RunMPPGraph() { + std::string calculator_graph_config_contents; + RETURN_IF_ERROR(mediapipe::file::GetContents( + FLAGS_calculator_graph_config_file, &calculator_graph_config_contents)); + LOG(INFO) << "Get calculator graph config contents: " + << calculator_graph_config_contents; + mediapipe::CalculatorGraphConfig config = + mediapipe::ParseTextProtoOrDie( + calculator_graph_config_contents); + std::map input_side_packets; + std::vector kv_pairs = + absl::StrSplit(FLAGS_input_side_packets, ','); + for (const std::string& kv_pair : kv_pairs) { + std::vector name_and_value = absl::StrSplit(kv_pair, '='); + RET_CHECK(name_and_value.size() == 2); + RET_CHECK(!::mediapipe::ContainsKey(input_side_packets, name_and_value[0])); + input_side_packets[name_and_value[0]] = + ::mediapipe::MakePacket(name_and_value[1]); + } + LOG(INFO) << "Initialize the calculator graph."; + mediapipe::CalculatorGraph graph; + RETURN_IF_ERROR(graph.Initialize(config, input_side_packets)); + LOG(INFO) << "Start running the calculator graph."; + return graph.Run(); +} + +int main(int argc, char** argv) { + google::InitGoogleLogging(argv[0]); + gflags::ParseCommandLineFlags(&argc, &argv, true); + ::mediapipe::Status run_status = RunMPPGraph(); + if (!run_status.ok()) { + LOG(ERROR) << "Failed to run the graph: " << run_status.message(); + } else { + LOG(INFO) << "Success!"; + } + return 0; +} diff --git a/mediapipe/examples/desktop/simpleIO/test_video.mp4 b/mediapipe/examples/desktop/simpleIO/test_video.mp4 new file mode 100644 index 000000000..c706232d3 Binary files /dev/null and b/mediapipe/examples/desktop/simpleIO/test_video.mp4 differ diff --git a/mediapipe/graphs/object_detection/BUILD b/mediapipe/graphs/object_detection/BUILD index cd1d1b6be..c0186f512 100644 --- a/mediapipe/graphs/object_detection/BUILD +++ b/mediapipe/graphs/object_detection/BUILD @@ -50,6 +50,7 @@ cc_library( "//mediapipe/calculators/util:non_max_suppression_calculator", "//mediapipe/calculators/video:opencv_video_decoder_calculator", "//mediapipe/calculators/video:opencv_video_encoder_calculator", + "//mediapipe/calculators/video:opencv_video_imshow_calculator", ], ) @@ -67,6 +68,7 @@ cc_library( "//mediapipe/calculators/util:non_max_suppression_calculator", "//mediapipe/calculators/video:opencv_video_decoder_calculator", "//mediapipe/calculators/video:opencv_video_encoder_calculator", + "//mediapipe/calculators/video:opencv_video_imshow_calculator", ], ) diff --git a/mediapipe/graphs/object_detection/object_detection_desktop_tflite_graph.pbtxt b/mediapipe/graphs/object_detection/object_detection_desktop_tflite_graph.pbtxt old mode 100644 new mode 100755 index 575d933a8..d79d10d01 --- a/mediapipe/graphs/object_detection/object_detection_desktop_tflite_graph.pbtxt +++ b/mediapipe/graphs/object_detection/object_detection_desktop_tflite_graph.pbtxt @@ -151,7 +151,7 @@ node { node_options: { [type.googleapis.com/mediapipe.DetectionsToRenderDataCalculatorOptions] { thickness: 4.0 - color { r: 255 g: 0 b: 0 } + color { r: 0 g: 255 b: 0 } } } } diff --git a/mediapipe/graphs/simple_io/BUILD b/mediapipe/graphs/simple_io/BUILD new file mode 100644 index 000000000..c0186f512 --- /dev/null +++ b/mediapipe/graphs/simple_io/BUILD @@ -0,0 +1,92 @@ +# Copyright 2019 The MediaPipe Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +licenses(["notice"]) # Apache 2.0 + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "mobile_calculators", + deps = [ + "//mediapipe/calculators/core:flow_limiter_calculator", + "//mediapipe/calculators/image:image_transformation_calculator", + "//mediapipe/calculators/tflite:ssd_anchors_calculator", + "//mediapipe/calculators/tflite:tflite_converter_calculator", + "//mediapipe/calculators/tflite:tflite_inference_calculator", + "//mediapipe/calculators/tflite:tflite_tensors_to_detections_calculator", + "//mediapipe/calculators/util:annotation_overlay_calculator", + "//mediapipe/calculators/util:detection_label_id_to_text_calculator", + "//mediapipe/calculators/util:detection_letterbox_removal_calculator", + "//mediapipe/calculators/util:detections_to_render_data_calculator", + "//mediapipe/calculators/util:non_max_suppression_calculator", + "//mediapipe/gpu:gpu_buffer_to_image_frame_calculator", + "//mediapipe/gpu:image_frame_to_gpu_buffer_calculator", + ], +) + +cc_library( + name = "desktop_tensorflow_calculators", + deps = [ + "//mediapipe/calculators/tensorflow:image_frame_to_tensor_calculator", + "//mediapipe/calculators/tensorflow:lapped_tensor_buffer_calculator", + "//mediapipe/calculators/tensorflow:object_detection_tensors_to_detections_calculator", + "//mediapipe/calculators/tensorflow:tensor_squeeze_dimensions_calculator", + "//mediapipe/calculators/tensorflow:tensorflow_inference_calculator", + "//mediapipe/calculators/tensorflow:tensorflow_session_from_saved_model_calculator", + "//mediapipe/calculators/util:annotation_overlay_calculator", + "//mediapipe/calculators/util:detection_label_id_to_text_calculator", + "//mediapipe/calculators/util:detections_to_render_data_calculator", + "//mediapipe/calculators/util:non_max_suppression_calculator", + "//mediapipe/calculators/video:opencv_video_decoder_calculator", + "//mediapipe/calculators/video:opencv_video_encoder_calculator", + "//mediapipe/calculators/video:opencv_video_imshow_calculator", + ], +) + +cc_library( + name = "desktop_tflite_calculators", + deps = [ + "//mediapipe/calculators/image:image_transformation_calculator", + "//mediapipe/calculators/tflite:ssd_anchors_calculator", + "//mediapipe/calculators/tflite:tflite_converter_calculator", + "//mediapipe/calculators/tflite:tflite_inference_calculator", + "//mediapipe/calculators/tflite:tflite_tensors_to_detections_calculator", + "//mediapipe/calculators/util:annotation_overlay_calculator", + "//mediapipe/calculators/util:detection_label_id_to_text_calculator", + "//mediapipe/calculators/util:detections_to_render_data_calculator", + "//mediapipe/calculators/util:non_max_suppression_calculator", + "//mediapipe/calculators/video:opencv_video_decoder_calculator", + "//mediapipe/calculators/video:opencv_video_encoder_calculator", + "//mediapipe/calculators/video:opencv_video_imshow_calculator", + ], +) + +load( + "//mediapipe/framework/tool:mediapipe_graph.bzl", + "mediapipe_binary_graph", +) + +mediapipe_binary_graph( + name = "mobile_cpu_binary_graph", + graph = "object_detection_mobile_cpu.pbtxt", + output_name = "mobile_cpu.binarypb", + deps = [":mobile_calculators"], +) + +mediapipe_binary_graph( + name = "mobile_gpu_binary_graph", + graph = "object_detection_mobile_gpu.pbtxt", + output_name = "mobile_gpu.binarypb", + deps = [":mobile_calculators"], +) diff --git a/mediapipe/graphs/simple_io/simple_io_graph.pbtxt b/mediapipe/graphs/simple_io/simple_io_graph.pbtxt new file mode 100644 index 000000000..a7689174e --- /dev/null +++ b/mediapipe/graphs/simple_io/simple_io_graph.pbtxt @@ -0,0 +1,27 @@ +# MediaPipe graph, simple input and output video +# on CPU. +# Used in the example in +# mediapipie/examples/desktop/object_detection:object_detection_tensorflow. + +# Decodes an input video file into images and a video header. +node { + calculator: "OpenCvVideoDecoderCalculator" + input_side_packet: "INPUT_FILE_PATH:input_video_path" + output_stream: "VIDEO:input_video" + output_stream: "VIDEO_PRESTREAM:input_video_header" +} + +# Encodes the annotated images into a video file, adopting properties specified +# in the input video header, e.g., video framerate. +node { + calculator: "OpenCvVideoEncoderCalculator" + input_stream: "VIDEO:input_video" + input_stream: "VIDEO_PRESTREAM:input_video_header" + input_side_packet: "OUTPUT_FILE_PATH:output_video_path" + node_options: { + [type.googleapis.com/mediapipe.OpenCvVideoEncoderCalculatorOptions]: { + codec: "avc1" + video_format: "mp4" + } + } +} diff --git a/mediapipe/graphs/simple_io/simple_media_to_screen_graph.pbtxt b/mediapipe/graphs/simple_io/simple_media_to_screen_graph.pbtxt new file mode 100644 index 000000000..0e3ecf9fd --- /dev/null +++ b/mediapipe/graphs/simple_io/simple_media_to_screen_graph.pbtxt @@ -0,0 +1,26 @@ +# MediaPipe graph, simple input and output video +# on CPU. +# Used in the example in +# mediapipie/examples/desktop/object_detection:object_detection_tensorflow. + +# Decodes an input video file into images and a video header. +node { + calculator: "OpenCvVideoDecoderCalculator" + input_side_packet: "INPUT_FILE_PATH:input_video_path" + output_stream: "VIDEO:input_video" + output_stream: "VIDEO_PRESTREAM:input_video_header" +} + +# Encodes the annotated images into a video file, adopting properties specified +# in the input video header, e.g., video framerate. +node { + calculator: "OpenCvVideoImShowCalculator" + input_stream: "VIDEO:input_video" + input_stream: "VIDEO_PRESTREAM:input_video_header" + node_options: { + [type.googleapis.com/mediapipe.OpenCvVideoEncoderCalculatorOptions]: { + codec: "avc1" + video_format: "mp4" + } + } +}