UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
convert.cpp
Go to the documentation of this file.
1#include <cassert>
2#include <chrono>
3#include <cstring>
4#include <fstream>
5#include <iostream>
6#include <string>
7#include <vector>
8
10#include "../src/video_codec.h"
11#include "../src/video_frame.h"
12
13using std::chrono::duration_cast;
14using std::chrono::high_resolution_clock;
15using std::chrono::microseconds;
16using std::cout;
17using std::cerr;
18using std::exception;
19using std::ifstream;
20using std::ofstream;
21using std::stoi;
22using std::string;
23using std::vector;
24
25static void benchmark() {
26 int width = 3840;
27 int height = 2160;
28 vector<unsigned char> in(width * height * MAX_BPS + MAX_PADDING);
29 vector<unsigned char> out(width * height * MAX_BPS + MAX_PADDING);
30 for (int i = 0; i < VIDEO_CODEC_END; ++i) {
31 bool src_print = false;
32 for (int j = 0; j < VIDEO_CODEC_END; ++j) {
33 codec_t inc = static_cast<codec_t>(i);
34 codec_t outc = static_cast<codec_t>(j);
35 decoder_t conv = nullptr;
36 if ((conv = get_decoder_from_to(inc, outc)) == nullptr || i == j) {
37 continue;
38 }
39 auto t0 = high_resolution_clock::now();
40 conv(out.data(), in.data(), vc_get_linesize(width, outc) * height, DEFAULT_R_SHIFT, DEFAULT_G_SHIFT, DEFAULT_B_SHIFT);
41 auto t1 = high_resolution_clock::now();
42 cout << get_codec_name(inc) << "->" << get_codec_name(outc) << ": " << duration_cast<microseconds>(t1 - t0).count() / 1000.0 << " ms\n";
43 }
44 }
45}
46
47static void print_conversions() {
48 for (int i = 0; i < VIDEO_CODEC_END; ++i) {
49 bool src_print = false;
50 for (int j = 0; j < VIDEO_CODEC_END; ++j) {
51 if (get_decoder_from_to(static_cast<codec_t>(i), static_cast<codec_t>(j)) == nullptr || i == j) {
52 continue;
53 }
54 if (!src_print) {
55 cout << get_codec_name(static_cast<codec_t>(i)) << " ->\n";
56 src_print = true;
57 }
58 cout << "\t" << get_codec_name(static_cast<codec_t>(j)) << "\n";
59 }
60 }
61}
62
63static int
64write_to_container(int width, int height, const char *in_f,
65 const char *out_fname)
66{
67 const char *ext = strrchr(in_f, '.');
68 if (ext == nullptr) {
69 fprintf(stderr, "File with no extension!\n");
70 return 1;
71 }
73 if (c == VIDEO_CODEC_NONE) {
74 fprintf(stderr, "wrong extension: %s!\n", ext);
75 return 1;
76 }
77 struct video_frame *f = load_video_frame(in_f, c, width, height);
78 if (f == nullptr) {
79 return 1;
80 }
81 save_video_frame(f, out_fname, false);
82 return 0;
83}
84
85int main(int argc, char *argv[]) {
86 if (argc == 2 && string("list-conversions") == argv[1]) {
88 return 0;
89 }
90 if (argc == 2 && string("benchmark") == argv[1]) {
91 benchmark();
92 return 0;
93 }
94 if (argc != 5 && argc != 7) {
95 cout << "Tool to convert between UltraGrid raw pixel format with supported conversions.\n\n"
96 "Usage:\n"
97 "\t" << argv[0] << " benchmark | help | list-conversions\n\n"
98 "\t" << argv[0] << " <width> <height> <in_codec> <out_codec> <in_file> <out_file>\n"
99 "\t\t" << "Eg.: " << argv[0] << " 1920 1080 UYVY RGB 00000001.yuv out.rgb\n\n"
100 "\t" << argv[0] << " <width> <height> <in_file> <oname_wo_ext>\n"
101 "\t\t- converts to output Y4M or PNM file (depending on in_file extension color space)\n"
102 "\t\t" << "Eg.: " << argv[0] << " 1920 1080 00000001.yuv out # creates out.y4m\n\n"
103 "\n"
104 "where\n"
105 "\t" << "benchmark - benchmark conversions\n"
106 "\t" << "help - show this help\n"
107 "\t" << "list-conversions - prints valid conversion pairs\n";
108 return (argc == 1 || argc == 2 && string("help") == argv[1]) ? 0 : 1;
109 }
110 int width = stoi(argv[1]);
111 int height = stoi(argv[2]);
112 if (argc == 5) {
113 return write_to_container(width, height, argv[3], argv[4]);
114 }
115 codec_t in_codec = get_codec_from_name(argv[3]);
116 codec_t out_codec = get_codec_from_name(argv[4]);
117 ifstream in(argv[5], ifstream::ate | ifstream::binary);
118 std::ofstream out(argv[6], ofstream::binary);
119 try {
120 in.exceptions(ifstream::failbit | ifstream::badbit | ifstream::eofbit);
121 out.exceptions(ofstream::failbit | ofstream::badbit);
122
123 assert (width && height && in_codec && out_codec && in && out);
124
125 size_t in_size = vc_get_datalen(width, height, in_codec);
126 assert(in.tellg() >= in_size);
127 in.seekg (0, ifstream::beg);
128
129 vector<char> in_data(in_size);
130 in.read(in_data.data(), in_size);
131 vector<char> out_data(vc_get_datalen(width, height, out_codec));
132
133 auto *decode = get_decoder_from_to(in_codec, out_codec);
134 if (decode == nullptr) {
135 cerr << "Cannot find decoder from " << argv[3] << " to " << argv[4] << "! See '" << argv[0] << " list-conversions'\n";
136 return 1;
137 }
138
139 size_t dst_linesize = vc_get_linesize(width, out_codec);
140 for (int y = 0; y < height; ++y) {
141 decode(reinterpret_cast<unsigned char *>(&out_data[y * dst_linesize]),
142 reinterpret_cast<unsigned char *>(&in_data[y * vc_get_linesize(width, in_codec)]),
143 dst_linesize, 0, 8, 16);
144 }
145 out.write(out_data.data(), out_data.size());
146 } catch (exception &e) {
147 cerr << "ERROR: " << e.what() << ": " << strerror(errno) << "\n";
148 }
149}
int vc_get_linesize(unsigned int width, codec_t codec)
const char * get_codec_name(codec_t codec)
codec_t get_codec_from_name(const char *name)
static int write_to_container(int width, int height, const char *in_f, const char *out_fname)
Definition convert.cpp:64
static void print_conversions()
Definition convert.cpp:47
static void benchmark()
Definition convert.cpp:25
decoder_t get_decoder_from_to(codec_t in, codec_t out)
#define DEFAULT_B_SHIFT
Definition pixfmt_conv.h:72
#define DEFAULT_R_SHIFT
Definition pixfmt_conv.h:70
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
#define DEFAULT_G_SHIFT
Definition pixfmt_conv.h:71
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
codec_t
Definition types.h:65
@ VIDEO_CODEC_NONE
dummy color spec
Definition types.h:66
@ VIDEO_CODEC_END
Definition types.h:111
size_t vc_get_datalen(unsigned int width, unsigned int height, codec_t codec)
codec_t get_codec_from_file_extension(const char *ext)
#define MAX_BPS
maximal (average) number of pixels per know pixel formats (up-round if needed)
Definition video_codec.h:62
#define MAX_PADDING
Definition video_codec.h:63
const char * save_video_frame(struct video_frame *frame, const char *name, bool raw)
struct video_frame * load_video_frame(const char *name, codec_t codec, int width, int height)