Apollo 11.0
自动驾驶开放平台
frame_processor.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2019 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <fstream>
20#include <memory>
21#include <sstream>
22
23#include "absl/strings/str_cat.h"
24#include "cyber/common/log.h"
26
27namespace apollo {
28namespace drivers {
29namespace video {
30
31FrameProcessor::FrameProcessor(const std::string& input_video_file,
32 const std::string& output_jpg_dir)
33 : output_jpg_dir_(output_jpg_dir) {
34 std::ifstream video_file(input_video_file, std::ios::binary);
35 std::istreambuf_iterator<char> buf_begin(video_file), buf_end;
36 while (buf_begin != buf_end) {
37 input_video_buffer_.emplace_back(*buf_begin++);
38 }
39}
40
42 if (input_video_buffer_.empty()) {
43 AERROR << "error: failed to read from input video file";
44 return false;
45 }
46 AVCodecParserContext* codec_parser = av_parser_init(AV_CODEC_ID_H265);
47 if (codec_parser == nullptr) {
48 AERROR << "error: failed to init AVCodecParserContext";
49 return false;
50 }
51 AVPacket apt;
52 av_init_packet(&apt);
53 const std::unique_ptr<H265Decoder> decoder(new H265Decoder());
54 if (!decoder->Init()) {
55 AERROR << "error: failed to init decoder";
56 return false;
57 }
58 uint32_t local_size = static_cast<uint32_t>(input_video_buffer_.size());
59 uint8_t* local_data = const_cast<uint8_t*>(input_video_buffer_.data());
60 AINFO << "decoding: video size = " << local_size;
61 int frame_num = 0;
62 int warn_frame_num = 0;
63 std::vector<uint8_t> jpeg_buffer;
64 while (local_size > 0) {
65 int frame_len = av_parser_parse2(
66 codec_parser, decoder->GetCodecCtxH265(), &(apt.data), &(apt.size),
67 local_data, local_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);
68 if (apt.data == nullptr) {
69 apt.data = local_data;
70 apt.size = local_size;
71 }
72 AINFO << "frame " << frame_num << ": frame_len=" << frame_len
73 << ". left_size=" << local_size;
74 const auto decoding_result =
75 decoder->Process(apt.data, apt.size, &jpeg_buffer);
76 if (decoding_result != H265Decoder::DecodingResult::WARN) {
77 // Write to output even if failed to convert, in order to
78 // maintain the order of frames
79 WriteOutputJpgFile(jpeg_buffer, GetOutputFile(frame_num));
80 ++frame_num;
81 } else {
82 // Retry later if returns warn, which indicates reading more from buffer
83 ++warn_frame_num;
84 }
85 local_data += frame_len;
86 local_size -= frame_len;
87 }
88 // Decode the left over frames from buffer exactly warning times
89 for (int i = warn_frame_num; i > 0; --i) {
90 // When retry to decode from buffer, we do not care if it succeeds or not
91 decoder->Process(nullptr, 0, &jpeg_buffer);
92 WriteOutputJpgFile(jpeg_buffer, GetOutputFile(frame_num));
93 AINFO << "frame " << frame_num << ": read from buffer";
94 ++frame_num;
95 }
96 AINFO << "total frames: " << frame_num;
97 av_parser_close(codec_parser);
98 return true;
99}
100
101std::string FrameProcessor::GetOutputFile(const int frame_num) const {
102 static constexpr int kSuffixLen = 5;
103 std::stringstream jpg_suffix;
104 jpg_suffix.fill('0');
105 jpg_suffix.width(kSuffixLen);
106 jpg_suffix << frame_num;
107 return absl::StrCat(output_jpg_dir_, "/", jpg_suffix.str(), ".jpg");
108}
109
110void FrameProcessor::WriteOutputJpgFile(
111 const std::vector<uint8_t>& jpeg_buffer,
112 const std::string& output_jpg_file) const {
113 std::ofstream out(output_jpg_file, std::ios::binary);
114 for (const uint8_t current : jpeg_buffer) {
115 out << static_cast<char>(current);
116 }
117}
118
119} // namespace video
120} // namespace drivers
121} // namespace apollo
FrameProcessor(const std::string &input_video_file, const std::string &output_jpg_dir)
H265Decoder is a class to actually decode videos.
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
class register implement
Definition arena_queue.h:37