1 #include "yuv4mpeg.hpp"
2 #include "parseval.hpp"
5 uint64_t not_valid
= 0xFFFFFFFFFFFFFFFFULL
;
7 uint64_t nscale
[7] = {1000000, 100000, 10000, 1000, 100, 10, 1};
11 redup_logic(FILE* _tc
, uint32_t _fps_n
, uint64_t _fps_d
)
17 fgets(buffer
, 512, tc
);
18 if(!regex_match(buffer
, "# timecode format v2\r?\n"))
19 throw std::runtime_error("Not valid TC file (header)");
20 current_frame
= not_valid
;
25 current_frame
= next_frame
;
26 next_frame
= read_framenum();
27 return (next_frame
> current_frame
) ? (next_frame
- current_frame
) : 0;
30 uint64_t read_framenum()
33 if(fgets(buffer
, 512, tc
) && buffer
[0])
34 return _read_framenum(buffer
);
36 return current_frame
+ 1;
38 uint64_t _read_framenum(const char* buf
)
40 regex_results r
= regex("([0-9]+)(\\.([0-9]+))?\r?\n", buf
);
42 throw std::runtime_error("Not valid TC file (value)");
43 uint64_t nanosec
= parse_value
<uint64_t>(r
[1]) * 1000000ULL;
45 nanosec
+= parse_value
<uint64_t>(r
[3].substr(0, 6));
46 else if(r
[3].length() > 0)
47 nanosec
+= parse_value
<uint64_t>(r
[3]) * nscale
[r
[3].length()];
48 uint64_t blocklen
= fps_d
* 1000000000ULL;
49 uint64_t blocks
= nanosec
/ blocklen
;
51 return blocks
* fps_n
+ (nanosec
/ 1000000000.0 * fps_n
/ fps_d
);
56 uint64_t current_frame
;
60 int main(int argc
, char** argv
)
71 for(int i
= 1; i
< argc
; i
++) {
72 std::string arg
= argv
[i
];
74 if(r
= regex("--fps=([1-9][0-9]*)", arg
)) {
76 fps_n
= parse_value
<unsigned>(r
[1]);
78 } catch(std::exception
& e
) {
79 std::cerr
<< "redup: Bad fps '" << r
[1] << "'" << std::endl
;
82 } else if(r
= regex("--fps=([1-9][0-9]*)/([1-9][0-9]*)", arg
)) {
84 fps_n
= parse_value
<unsigned>(r
[1]);
85 fps_d
= parse_value
<unsigned>(r
[2]);
86 } catch(std::exception
& e
) {
87 std::cerr
<< "redup: Bad fps '" << r
[1] << "/" << r
[2] << "'" << std::endl
;
90 } else if(r
= regex("--.*", arg
)) {
91 std::cerr
<< "redup: Unrecognized option '" << arg
<< "'" << std::endl
;
95 std::cerr
<< "redup: Only one TC file may be specified." << std::endl
;
103 std::cerr
<< "redup: TC file must be specified." << std::endl
;
110 FILE* tc
= fopen(tcfile
.c_str(), "r");
111 mark_pipe_as_binary(in
);
112 mark_pipe_as_binary(out
);
115 std::cerr
<< "redup: Can't open TC file '" << tcfile
<< "'." << std::endl
;
122 struct yuv4mpeg_stream_header
strmh(in
);
123 if(strmh
.chroma
== "rgb")
124 framesize
= 3 * strmh
.width
* strmh
.height
;
125 else if(strmh
.chroma
== "420")
126 framesize
= 3 * strmh
.width
* strmh
.height
/ 2;
127 else if(strmh
.chroma
== "420p16")
128 framesize
= 6 * strmh
.width
* strmh
.height
/ 2;
129 else if(strmh
.chroma
== "422")
130 framesize
= 2 * strmh
.width
* strmh
.height
;
131 else if(strmh
.chroma
== "422p16")
132 framesize
= 4 * strmh
.width
* strmh
.height
;
133 else if(strmh
.chroma
== "444")
134 framesize
= 3 * strmh
.width
* strmh
.height
;
135 else if(strmh
.chroma
== "444p16")
136 framesize
= 6 * strmh
.width
* strmh
.height
;
138 throw std::runtime_error("Unsupported input chroma type '" + strmh
.chroma
+ "'");
139 if(strmh
.fps_n
&& strmh
.fps_d
) {
140 ofps_n
= strmh
.fps_n
;
141 ofps_d
= strmh
.fps_d
;
150 strmh
.delete_extensions("VFR");
151 std::string _strmh
= std::string(strmh
);
152 write_or_die(out
, _strmh
);
155 std::string _framh
, _framh2
;
156 std::vector
<char> buffer
;
157 buffer
.resize(framesize
);
158 struct yuv4mpeg_frame_header framh
;
159 struct redup_logic
rdl(tc
, fps_n
, fps_d
);
163 //Initial black frame.
165 for(size_t i
= 0; i
< count
; i
++) {
167 std::string _framh2
= framh
;
168 write_or_die(out
, _framh2
);
169 write_or_die(out
, &buffer
[0], framesize
);
174 if(!read_line2(in
, _framh
))
176 framh
= yuv4mpeg_frame_header(_framh
);
178 read_or_die(in
, &buffer
[0], buffer
.size());
183 for(size_t i
= 0; i
< count
; i
++) {
185 std::string _framh2
= framh
;
186 write_or_die(out
, _framh2
);
187 write_or_die(out
, &buffer
[0], framesize
);
190 } catch(std::exception
& e
) {
191 std::cerr
<< "redup: Error: " << e
.what() << std::endl
;
195 std::cerr
<< "redup: Read " << infr
<< " frames, wrote " << outfr
<< " frames." << std::endl
;
196 std::cerr
<< "redup: Lost " << lost
<< " frames." << std::endl
;