Fix integer overflow in ft_rendered_size_line
[ilaris-y4m-tools.git] / truncate.cpp
blobd42f8d65fd0ba2b87c27dd65da385c293ed4292d
1 #include "yuv4mpeg.hpp"
2 #include "parseval.hpp"
3 #include "marker.hpp"
4 #include <iostream>
6 int main(int argc, char** argv)
8 timemarker start, end;
9 size_t framesize = 0;
10 for(int i = 1; i < argc; i++) {
11 std::string arg = argv[i];
12 regex_results r;
13 if(r = regex("--end=(.*)", arg)) {
14 try {
15 end = timemarker(r[1]);
16 } catch(std::exception& e) {
17 std::cerr << "truncate: Bad end '" << r[1] << "'" << std::endl;
18 return 1;
20 } else if(r = regex("--start=(.*)", arg)) {
21 try {
22 start = timemarker(r[1]);
23 } catch(std::exception& e) {
24 std::cerr << "truncate: Bad start '" << r[1] << "'" << std::endl;
25 return 1;
27 } else {
28 std::cerr << "truncate: Unrecognized option '" << arg << "'" << std::endl;
29 return 1;
33 //Open files.
34 FILE* in = stdin;
35 FILE* out = stdout;
36 mark_pipe_as_binary(in);
37 mark_pipe_as_binary(out);
39 //Fixup header.
40 try {
41 regex_results r;
42 double fps = 25;
43 struct yuv4mpeg_stream_header strmh(in);
44 if(strmh.chroma == "rgb")
45 framesize = 3 * strmh.width * strmh.height;
46 else if(strmh.chroma == "420")
47 framesize = 3 * strmh.width * strmh.height / 2;
48 else if(strmh.chroma == "420p16")
49 framesize = 6 * strmh.width * strmh.height / 2;
50 else if(strmh.chroma == "422")
51 framesize = 2 * strmh.width * strmh.height;
52 else if(strmh.chroma == "422p16")
53 framesize = 4 * strmh.width * strmh.height;
54 else if(strmh.chroma == "444")
55 framesize = 3 * strmh.width * strmh.height;
56 else if(strmh.chroma == "444p16")
57 framesize = 6 * strmh.width * strmh.height;
58 else
59 throw std::runtime_error("Unsupported input chroma type '" + strmh.chroma + "'");
60 if(strmh.fps_n && strmh.fps_d) {
61 fps = 1.0 * strmh.fps_n / strmh.fps_d;
63 uint64_t startframe = start.get_frame(fps, 0);
64 uint64_t endframe = end.get_frame(fps, 0xFFFFFFFFFFFFFFFFULL);
65 if(startframe > endframe)
66 throw std::runtime_error("Startpoint is after endpoint");
67 write_or_die(out, static_cast<std::string>(strmh));
69 uint64_t curframe = 0;
70 std::string _framh, _framh2;
71 std::vector<char> buffer;
72 buffer.resize(framesize);
73 struct yuv4mpeg_frame_header framh;
75 //Frame loop.
76 while(true) {
77 unsigned duration = 1;
78 if(!read_line2(in, _framh))
79 return 0; //End.
80 framh = yuv4mpeg_frame_header(_framh);
81 read_or_die(in, &buffer[0], buffer.size());
82 duration = framh.duration;
83 uint64_t nextframe = curframe + duration;
84 if(curframe > endframe)
85 break;
86 if(nextframe < startframe) {
87 curframe = nextframe;
88 continue;
90 bool stradle_start = (curframe < startframe);
91 bool stradle_end = (nextframe > endframe);
92 if(stradle_start && stradle_end)
93 duration = endframe - startframe;
94 else if(stradle_start)
95 duration = nextframe - startframe;
96 else if(stradle_end)
97 duration = endframe - curframe;
98 framh.duration = duration;
99 write_or_die(out, static_cast<std::string>(framh));
100 write_or_die(out, &buffer[0], buffer.size());
101 curframe = nextframe;
103 } catch(std::exception& e) {
104 std::cerr << "truncate: Error: " << e.what() << std::endl;
105 return 1;
107 return 0;