1 #include "yuv4mpeg.hpp"
2 #include "parseval.hpp"
3 #include "fpschanger.hpp"
6 int main(int argc
, char** argv
)
8 std::vector
<std::string
> files
;
10 bool stdin_used
= false;
11 unsigned headernum
= 0;
13 for(int i
= 1; i
< argc
; i
++) {
14 std::string arg
= argv
[i
];
16 if(r
= regex("--primary-header=(0|[1-9][0-9]*)", arg
)) {
18 headernum
= parse_value
<unsigned>(r
[1]);
19 } catch(std::exception
& e
) {
20 std::cerr
<< "concatenate: Bad end '" << r
[1] << "'" << std::endl
;
23 } else if(r
= regex("--.*", arg
)) {
24 std::cerr
<< "concatenate: Unrecognized option '" << arg
<< "'" << std::endl
;
31 if(headernum
>= files
.size()) {
32 std::cerr
<< "concatenate: Invalid primary header number" << std::endl
;
38 mark_pipe_as_binary(out
);
42 std::cerr
<< "concatenate: Stdin can only be used once" << std::endl
;
47 mark_pipe_as_binary(stdin
);
49 FILE* _in
= fopen(i
.c_str(), "rb");
51 std::cerr
<< "concatenate: Can't open '" << i
<< "'" << std::endl
;
61 //Read all stream headers.
62 std::vector
<yuv4mpeg_stream_header
> strmhs
;
63 yuv4mpeg_stream_header phdr
;
65 struct yuv4mpeg_stream_header
strmh(i
);
66 strmhs
.push_back(strmh
);
68 phdr
= strmhs
[headernum
];
70 //Check that all headers are compatible.
71 for(auto i
: strmhs
) {
72 if(i
.width
!= phdr
.width
|| i
.height
!= phdr
.height
)
73 throw std::runtime_error("Streams must all have the same size");
74 if(i
.chroma
!= phdr
.chroma
)
75 throw std::runtime_error("Streams must all have the same chroma");
76 if(i
.interlace
!= phdr
.interlace
)
77 throw std::runtime_error("Streams must all have the same interlace");
81 if(phdr
.chroma
== "rgb")
82 framesize
= 3 * phdr
.width
* phdr
.height
;
83 else if(phdr
.chroma
== "420")
84 framesize
= 3 * phdr
.width
* phdr
.height
/ 2;
85 else if(phdr
.chroma
== "420p16")
86 framesize
= 6 * phdr
.width
* phdr
.height
/ 2;
87 else if(phdr
.chroma
== "422")
88 framesize
= 2 * phdr
.width
* phdr
.height
;
89 else if(phdr
.chroma
== "422p16")
90 framesize
= 4 * phdr
.width
* phdr
.height
;
91 else if(phdr
.chroma
== "444")
92 framesize
= 3 * phdr
.width
* phdr
.height
;
93 else if(phdr
.chroma
== "444p16")
94 framesize
= 6 * phdr
.width
* phdr
.height
;
96 throw std::runtime_error("Unsupported input chroma type '" + phdr
.chroma
+ "'");
98 write_or_die(out
, static_cast<std::string
>(phdr
));
101 std::vector
<char> buffer
;
102 buffer
.resize(framesize
);
104 fpschanger
timer(phdr
.fps_n
, phdr
.fps_d
, phdr
.fps_n
, phdr
.fps_d
);
105 bool tvfr
= phdr
.find_extension("VFR");
110 timer
.change_source_rate(strmhs
[index
].fps_n
, strmhs
[index
].fps_d
);
111 bool svfr
= strmhs
[index
].find_extension("VFR");
113 uint64_t duration
= 1;
114 if(!read_line2(i
, _framh
))
116 read_or_die(i
, &buffer
[0], buffer
.size());
117 struct yuv4mpeg_frame_header
framh(_framh
);
119 duration
= framh
.duration
;
120 duration
= timer
.duration(duration
);
122 framh
.duration
= duration
;
123 write_or_die(out
, framh
);
124 write_or_die(out
, &buffer
[0], buffer
.size());
127 for(uint64_t i
= 0; i
< duration
; i
++) {
128 write_or_die(out
, framh
);
129 write_or_die(out
, &buffer
[0], buffer
.size());
135 } catch(std::exception
& e
) {
136 std::cerr
<< "concatenate: Error: " << e
.what() << std::endl
;