1 #include "yuv4mpeg.hpp"
2 #include "parseval.hpp"
4 #include "rendertext.hpp"
12 template<unsigned s
, bool xdiv
, bool ydiv
>
13 void do_crop_g(char* out
, char* content
, size_t fsize
, size_t height
, crop_params p
)
15 size_t off
= fsize
/ height
* (p
.y
>> (ydiv
? 1 : 0)) + s
* (p
.x
>> (xdiv
? 1 : 0));
16 size_t len
= s
* (p
.w
>> (xdiv
? 1 : 0));
17 size_t stride
= fsize
/ height
;
18 for(size_t i
= 0; i
< (p
.h
>> (ydiv
? 1 : 0)); i
++)
19 memcpy(out
+ len
* i
, content
+ off
+ stride
* i
, len
);
22 void do_crop(char* out
, char* content
, size_t fsize
, size_t height
, unsigned mode
, crop_params p
)
26 do_crop_g
<3, false, false>(out
, content
, fsize
, height
, p
);
27 } else if(mode
== 1) {
28 //Mode 1: YUV420 8-bit.
29 size_t psize
= fsize
* 2 / 3;
30 size_t psize2
= p
.w
* p
.h
;
31 do_crop_g
<1, false, false>(out
, content
, psize
, height
, p
);
32 do_crop_g
<1, true, true>(out
+ psize2
, content
+ psize
, psize
>> 2, height
>> 1, p
);
33 do_crop_g
<1, true, true>(out
+ psize2
+ (psize2
>> 2), content
+ psize
+ (psize
>> 2), psize
>> 2,
35 } else if(mode
== 2) {
36 //Mode 2: YUV420 16-bit.
37 size_t psize
= fsize
* 2 / 3;
38 size_t psize2
= p
.w
* p
.h
* 2;
39 do_crop_g
<2, false, false>(out
, content
, psize
, height
, p
);
40 do_crop_g
<2, true, true>(out
+ psize2
, content
+ psize
, psize
>> 2, height
>> 1, p
);
41 do_crop_g
<2, true, true>(out
+ psize2
+ (psize2
>> 2), content
+ psize
+ (psize
>> 2), psize
>> 2,
43 } else if(mode
== 3) {
44 //Mode 3: YUV422 8-bit.
45 size_t psize
= fsize
/ 2;
46 size_t psize2
= p
.w
* p
.h
;
47 do_crop_g
<1, false, false>(out
, content
, psize
, height
, p
);
48 do_crop_g
<1, false, true>(out
+ psize2
, content
+ psize
, psize
>> 1, height
>> 1, p
);
49 do_crop_g
<1, false, true>(out
+ psize2
+ (psize2
>> 1), content
+ psize
+ (psize
>> 1), psize
>> 1,
51 } else if(mode
== 4) {
52 //Mode 4: YUV422 16-bit.
53 size_t psize
= fsize
/ 2;
54 size_t psize2
= p
.w
* p
.h
* 2;
55 do_crop_g
<2, false, false>(out
, content
, psize
, height
, p
);
56 do_crop_g
<2, false, true>(out
+ psize2
, content
+ psize
, psize
>> 1, height
>> 1, p
);
57 do_crop_g
<2, false, true>(out
+ psize2
+ (psize2
>> 1), content
+ psize
+ (psize
>> 1), psize
>> 1,
59 } else if(mode
== 5) {
60 //Mode 5: YUV444 8-bit.
61 size_t psize
= fsize
/ 3;
62 size_t psize2
= p
.w
* p
.h
;
63 do_crop_g
<1, false, false>(out
, content
, psize
, height
, p
);
64 do_crop_g
<1, false, false>(out
+ psize2
, content
+ psize
, psize
, height
, p
);
65 do_crop_g
<1, false, false>(out
+ psize2
+ psize2
, content
+ psize
+ psize
, psize
, height
, p
);
66 } else if(mode
== 6) {
67 //Mode 6: YUV444 16-bit.
68 size_t psize
= fsize
/ 3;
69 size_t psize2
= p
.w
* p
.h
* 2;
70 do_crop_g
<2, false, false>(out
, content
, psize
, height
, p
);
71 do_crop_g
<2, false, false>(out
+ psize2
, content
+ psize
, psize
, height
, p
);
72 do_crop_g
<2, false, false>(out
+ psize2
+ psize2
, content
+ psize
+ psize
, psize
, height
, p
);
76 int main(int argc
, char** argv
)
81 cp
.x
= cp
.y
= cp
.w
= cp
.h
= 0;
83 size_t framesize2
= 0;
84 for(int i
= 1; i
< argc
; i
++) {
85 std::string arg
= argv
[i
];
88 if(r
= regex("--.*", arg
)) {
89 std::cerr
<< "crop: Unrecognized option '" << arg
<< "'" << std::endl
;
92 if(r
= regex("([0-9]+),([0-9]+)-([0-9]+),([0-9]+)", arg
)) {
93 cp
.x
= parse_value
<size_t>(r
[1]);
94 cp
.y
= parse_value
<size_t>(r
[2]);
95 cp
.w
= parse_value
<size_t>(r
[3]) - cp
.x
;
96 cp
.h
= parse_value
<size_t>(r
[4]) - cp
.y
;
97 } else if(r
= regex("([0-9]+),([0-9]+),([0-9]+),([0-9]+)", arg
)) {
98 cp
.x
= parse_value
<size_t>(r
[1]);
99 cp
.y
= parse_value
<size_t>(r
[2]);
100 cp
.w
= parse_value
<size_t>(r
[3]);
101 cp
.h
= parse_value
<size_t>(r
[4]);
103 std::cerr
<< "crop: Unrecognized option '" << arg
<< "'" << std::endl
;
107 } catch(std::exception
& e
) {
108 std::cerr
<< "crop: Error in option '" << arg
<< "': " << e
.what() << std::endl
;
114 std::cerr
<< "crop: 0x0 output not allowed" << std::endl
;
121 mark_pipe_as_binary(in
);
122 mark_pipe_as_binary(out
);
127 struct yuv4mpeg_stream_header
strmh(in
);
128 if(strmh
.chroma
== "rgb") {
129 framesize
= 3 * strmh
.width
* strmh
.height
;
130 framesize2
= 3 * cp
.w
* cp
.h
;
132 } else if(strmh
.chroma
== "420") {
133 framesize
= 3 * strmh
.width
* strmh
.height
/ 2;
134 framesize2
= 3 * cp
.w
* cp
.h
/ 2;
137 } else if(strmh
.chroma
== "420p16") {
138 framesize
= 6 * strmh
.width
* strmh
.height
/ 2;
139 framesize2
= 6 * cp
.w
* cp
.h
/ 2;
142 } else if(strmh
.chroma
== "422") {
143 framesize
= 2 * strmh
.width
* strmh
.height
;
144 framesize2
= 2 * cp
.w
* cp
.h
;
147 } else if(strmh
.chroma
== "422p16") {
148 framesize
= 4 * strmh
.width
* strmh
.height
;
149 framesize2
= 4 * cp
.w
* cp
.h
;
152 } else if(strmh
.chroma
== "444") {
153 framesize
= 3 * strmh
.width
* strmh
.height
;
154 framesize2
= 3 * cp
.w
* cp
.h
;
156 } else if(strmh
.chroma
== "444p16") {
157 framesize
= 6 * strmh
.width
* strmh
.height
;
158 framesize2
= 6 * cp
.w
* cp
.h
;
161 throw std::runtime_error("Unsupported input chroma type '" + strmh
.chroma
+ "'");
162 if(cp
.x
% xmod
|| cp
.y
% ymod
|| cp
.w
% xmod
|| cp
.h
% ymod
)
163 throw std::runtime_error("Target must be multiple of chroma subsampling'");
165 if(cp
.x
+ cp
.w
< cp
.x
|| cp
.x
+ cp
.w
> strmh
.width
|| cp
.y
+ cp
.h
< cp
.y
||
166 cp
.y
+ cp
.h
> strmh
.height
) {
167 std::cerr
<< "crop: Region out of image" << std::endl
;
172 size_t oheight
= strmh
.height
;
175 write_or_die(out
, static_cast<std::string
>(strmh
));
177 uint64_t curframe
= 0;
178 std::string _framh
, _framh2
;
179 std::vector
<char> buffer
;
180 std::vector
<char> buffer2
;
181 buffer
.resize(framesize
);
182 buffer2
.resize(framesize2
);
183 struct yuv4mpeg_frame_header framh
;
187 unsigned duration
= 1;
188 if(!read_line2(in
, _framh
))
190 framh
= yuv4mpeg_frame_header(_framh
);
191 read_or_die(in
, &buffer
[0], buffer
.size());
192 do_crop(&buffer2
[0], &buffer
[0], framesize
, oheight
, mode
, cp
);
193 write_or_die(out
, static_cast<std::string
>(framh
));
194 write_or_die(out
, &buffer2
[0], buffer2
.size());
195 curframe
+= duration
;
197 } catch(std::exception
& e
) {
198 std::cerr
<< "crop: Error: " << e
.what() << std::endl
;