feat: add codec id to meta file

- в meta файл добавлена информация о кодеке видео файла
- испрвлено сохранение meta файла при остановке приложения
This commit is contained in:
amazing-hash 2024-05-08 13:58:49 +04:00
parent a988364443
commit 20d503f59b
9 changed files with 51 additions and 16 deletions

View File

@ -1,4 +1,10 @@
### va
Набор утилит для работы с видео камерами:
- захват видео и сохранение в файлы
- инференс видео файлов и сохранение результатов
- просмотр архива и live видео по протоколу HLS
Поддерживаемые операционные системы: Linux
### va-record

View File

@ -9,6 +9,7 @@ namespace va {
namespace utils {
struct Metatada {
double duration;
std::string codec_id;
bool is_valid = false;
};
#pragma GCC diagnostic push
@ -17,19 +18,24 @@ namespace va {
std::ifstream in(path);
std::string start_marker, end_marker;
double duration;
std::string codec_id;
in >> start_marker;
if (!in) {
return {0, false};
return {0, "", false};
}
in >> duration;
if (!in) {
return {0, false};
return {0, "", false};
}
in >> codec_id;
if (!in) {
return {duration, "", false};
}
in >> end_marker;
if (in && start_marker == "START_DATA" && end_marker == "END_DATA") {
return {duration, true};
return {duration, codec_id, true};
}
return {0, false};
return {0, "", false};
}
static std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;

View File

@ -22,15 +22,18 @@ namespace va {
ofs << "START_DATA" << std::endl;
ofs << static_cast<double>((current_pts_pkt_ - start_pts_pkt_)) * time_base.num / time_base.den
<< std::endl;
ofs << codec_id() << std::endl;
ofs << "END_DATA";
} else {
// TODO: Предполагаю длительность файла равна duration_file_
size_t extension_pos{current_file_.rfind(".ts")};
auto tmp = std::string(current_file_.begin(), current_file_.end());
fs::path path{tmp.replace(extension_pos, 3, ".meta")};
std::ofstream ofs(path);
ofs << static_cast<double>(duration_file_);
ofs << "START_DATA" << std::endl;
ofs << static_cast<double>(duration_file_) << std::endl;
ofs << codec_id() << std::endl;
ofs << "END_DATA";
}
if (pkt->pts != AV_NOPTS_VALUE) {
start_pts_pkt_ = pkt->pts;

View File

@ -16,8 +16,9 @@ namespace fs = std::filesystem;
namespace va {
class Archive final {
public:
Archive(std::string &prefix_path, int64_t duration, std::vector<const AVCodecParameters *> params_list)
: prefix_path_(prefix_path), duration_file_(duration), params_list_(params_list) {
Archive(std::string &prefix_path, int64_t duration, std::vector<const AVCodecParameters *> params_list,
ssize_t video_idx)
: prefix_path_(prefix_path), duration_file_(duration), params_list_(params_list), video_idx_(video_idx) {
}
~Archive() {
if (ctx_) {
@ -29,14 +30,20 @@ namespace va {
auto tmp = std::string(current_file_.begin(), current_file_.end());
fs::path path{tmp.replace(extention_pos, 3, ".meta")};
std::ofstream ofs(path);
ofs << "START_DATA" << std::endl;
ofs << static_cast<double>((current_pts_pkt_ - start_pts_pkt_)) * time_base.num / time_base.den;
ofs << codec_id() << std::endl;
ofs << "END_DATA";
} else {
// TODO: Предполагаю длительность файла равна duration_file_
size_t extension_pos{current_file_.find(".ts")};
auto tmp = std::string(current_file_.begin(), current_file_.end());
fs::path path{tmp.replace(extension_pos, 3, ".meta")};
std::ofstream ofs(path);
ofs << static_cast<double>(duration_file_);
ofs << "START_DATA" << std::endl;
ofs << static_cast<double>(duration_file_) << std::endl;
ofs << codec_id() << std::endl;
ofs << "END_DATA";
}
}
}
@ -46,6 +53,13 @@ namespace va {
Archive &operator=(Archive &&) = delete;
void send_pkt(AVPacket *pkt, AVFormatContext *ctx_in);
const char *codec_id() {
if (video_idx_ == -1) {
return "Undefined";
}
return avcodec_get_name(params_list_[static_cast<size_t>(video_idx_)]->codec_id);
}
private:
std::chrono::steady_clock::time_point time_point_;
std::string prefix_path_;
@ -55,6 +69,7 @@ namespace va {
int64_t current_pts_pkt_ = AV_NOPTS_VALUE;
std::optional<AVRational> time_base_;
std::vector<const AVCodecParameters *> params_list_;
ssize_t video_idx_;
std::unique_ptr<AVFormatContext, void (*)(AVFormatContext *ctx)> ctx_ = va_avformat_null_alloc_output_context();
};
} // namespace va

View File

@ -63,7 +63,8 @@ namespace va {
sleep_and_test(stoken, 5);
continue;
}
auto params_list = stream_params(ctx.get(), source_.id());
ssize_t video_idx = -1;
auto params_list = stream_params(ctx.get(), source_.id(), video_idx);
if (params_list.empty()) {
auto err_msg = std::format("not found audio and video channels for stream ({})", source_.id());
BOOST_LOG_TRIVIAL(error) << err_msg;
@ -71,7 +72,7 @@ namespace va {
continue;
}
try {
Archive archive(prefix_archive_path, duration, params_list);
Archive archive(prefix_archive_path, duration, params_list, video_idx);
const auto pkt = va::va_avpacket_alloc();
while (!stoken.stop_requested() && av_read_frame(ctx.get(), pkt.get()) == 0) {
archive.send_pkt(pkt.get(), ctx.get());

View File

@ -3,12 +3,14 @@
#include <format>
namespace va {
std::vector<const AVCodecParameters *> stream_params(AVFormatContext *ctx, const std::string &id) {
std::vector<const AVCodecParameters *> stream_params(AVFormatContext *ctx, const std::string &id,
ssize_t &video_idx) {
std::vector<const AVCodecParameters *> params_list;
for (size_t idx = 0; idx < ctx->nb_streams; ++idx) {
auto codec_params = ctx->streams[idx]->codecpar;
auto media_type = codec_params->codec_type;
if (media_type == AVMediaType::AVMEDIA_TYPE_VIDEO) {
video_idx = static_cast<ssize_t>(idx);
auto info_msg = std::format("video stream {}, width {}, height {}, codec {}", id, codec_params->width,
codec_params->height, avcodec_get_name(codec_params->codec_id));
BOOST_LOG_TRIVIAL(info) << info_msg;

View File

@ -6,5 +6,6 @@ extern "C" {
}
namespace va {
std::vector<const AVCodecParameters *> stream_params(AVFormatContext *ctx, const std::string &id);
std::vector<const AVCodecParameters *> stream_params(AVFormatContext *ctx, const std::string &id,
ssize_t &video_idx);
} // namespace va

View File

@ -25,7 +25,8 @@ namespace va {
source.id());
throw std::runtime_error(err_msg);
}
return std::format("{}{}:{}@{}", url.substr(0, pos + 3), username, password, url.substr(pos + 3));
std::string_view view{url};
return std::format("{}{}:{}@{}", view.substr(0, pos + 3), username, password, view.substr(pos + 3));
}
std::string format_datetime_to_path(time_t seconds) {
char buffer[buffer_len];

View File

@ -3,7 +3,7 @@
#define PROJECT_NAME "va"
#define VERSION_MAJOR "0"
#define VERSION_MINOR "4"
#define VERSION_PATCH "1"
#define VERSION_MINOR "5"
#define VERSION_PATCH "0"
#endif