1 #include "yuv4mpeg.hpp"
2 #include "parseval.hpp"
7 void compute_scale_factors(size_t w
, size_t h
, double sar
, size_t& fx
, size_t& fy
)
9 //sar is ratio between DAR and native DAR.
12 while(sar
<= sqrt(0.5)) {
16 while(sar
> sqrt(2)) {
20 while(w
* fx
< 1920 && h
* fy
< 1080) {
38 outwidth
= inwidth
* factor_x
;
39 outheight
= inheight
* factor_y
;
40 bool subsample_x
= false;
41 bool subsample_y
= false;
48 } else if(chroma
== "420") {
56 } else if(chroma
== "420p16") {
64 } else if(chroma
== "422") {
71 } else if(chroma
== "422p16") {
78 } else if(chroma
== "444") {
84 } else if(chroma
== "444p16") {
91 throw std::runtime_error("Unsupported input chroma type '" + chroma
+ "'");
92 insize
= pfourths
* inwidth
* inheight
/ 4;
93 outsize
= pfourths
* outwidth
* outheight
/ 4;
94 inplane1_size
= p1fourths
* inwidth
* inheight
/ 4;
95 outplane1_size
= p1fourths
* outwidth
* outheight
/ 4;
96 inplanen_size
= pnfourths
* inwidth
* inheight
/ 4;
97 outplanen_size
= pnfourths
* outwidth
* outheight
/ 4;
98 inplane1_stride
= p1fourths
* inwidth
/ 4;
99 outplane1_stride
= p1fourths
* outwidth
/ 4;
100 inplanen_stride
= pnfourths
* inwidth
/ 4;
101 outplanen_stride
= pnfourths
* outwidth
/ 4;
102 if(subsample_x
&& (inwidth
| outwidth
) & 1)
103 throw std::runtime_error("420 and 422 modes must have even width");
104 if(subsample_y
&& (inheight
| outheight
) & 1)
105 throw std::runtime_error("420 modes must have even height");
106 inplanen_width
= inwidth
/ (subsample_x
? 2 : 1);
107 inplanen_height
= inheight
/ (subsample_y
? 2 : 1);
108 outplanen_width
= outwidth
/ (subsample_x
? 2 : 1);
109 outplanen_height
= outheight
/ (subsample_y
? 2 : 1);
116 size_t inplane1_size
;
117 size_t inplanen_size
;
118 size_t outplane1_size
;
119 size_t outplanen_size
;
120 size_t inplane1_stride
;
121 size_t inplanen_stride
;
122 size_t outplane1_stride
;
123 size_t outplanen_stride
;
124 size_t inplanen_width
;
125 size_t inplanen_height
;
126 size_t outplanen_width
;
127 size_t outplanen_height
;
131 void do_resize_rgb(char* out
, const char* in
, struct scale_params
& s
)
133 //TODO: Optimize this.
134 for(size_t y
= 0; y
< s
.inheight
; y
++) {
135 for(size_t x
= 0; x
< s
.inwidth
; x
++) {
136 for(size_t i
= 0; i
< s
.factor_x
; i
++) {
137 out
[3 * s
.factor_x
* x
+ 3 * i
+ 0] = in
[3 * x
+ 0];
138 out
[3 * s
.factor_x
* x
+ 3 * i
+ 1] = in
[3 * x
+ 1];
139 out
[3 * s
.factor_x
* x
+ 3 * i
+ 2] = in
[3 * x
+ 2];
142 for(size_t x
= 1; x
< s
.factor_y
; x
++)
143 memcpy(out
+ x
* s
.outplane1_stride
, out
, s
.outplane1_stride
);
144 in
+= s
.inplane1_stride
;
145 out
+= s
.factor_y
* s
.outplane1_stride
;
150 void do_resize_Y(T
* out
, const T
* in
, struct scale_params
& s
)
152 //TODO: Optimize this.
153 for(size_t y
= 0; y
< s
.inheight
; y
++) {
154 for(size_t x
= 0; x
< s
.inwidth
; x
++)
155 for(size_t i
= 0; i
< s
.factor_x
; i
++)
156 out
[s
.factor_x
* x
+ i
] = in
[x
];
157 for(size_t x
= 1; x
< s
.factor_y
; x
++)
158 memcpy(out
+ x
* s
.outplane1_stride
, out
, s
.outplane1_stride
);
159 in
+= s
.inplane1_stride
;
160 out
+= s
.factor_y
* s
.outplane1_stride
;
165 void do_resize_C(T
* out
, const T
* in
, struct scale_params
& s
)
167 //TODO: Optimize this.
168 for(size_t y
= 0; y
< s
.inplanen_height
; y
++) {
169 for(size_t x
= 0; x
< s
.inplanen_width
; x
++)
170 for(size_t i
= 0; i
< s
.factor_x
; i
++)
171 out
[s
.factor_x
* x
+ i
] = in
[x
];
172 for(size_t x
= 1; x
< s
.factor_y
; x
++)
173 memcpy(out
+ x
* s
.outplanen_stride
, out
, s
.outplanen_stride
);
174 in
+= s
.inplanen_stride
;
175 out
+= s
.factor_y
* s
.outplanen_stride
;
179 void do_resize(char* out
, const char* in
, struct scale_params
& s
)
182 do_resize_rgb(out
, in
, s
);
183 } else if(s
.mode
== 1) {
184 do_resize_Y(reinterpret_cast<uint8_t*>(out
), reinterpret_cast<const uint8_t*>(in
), s
);
185 for(unsigned i
= 0; i
< s
.planes
- 1; i
++)
186 do_resize_C(reinterpret_cast<uint8_t*>(out
+ s
.outplane1_size
+ i
* s
.outplanen_size
),
187 reinterpret_cast<const uint8_t*>(in
+ s
.inplane1_size
+ i
* s
.inplanen_size
),
189 } else if(s
.mode
== 2) {
190 do_resize_Y(reinterpret_cast<uint16_t*>(out
), reinterpret_cast<const uint16_t*>(in
), s
);
191 for(unsigned i
= 0; i
< s
.planes
- 1; i
++)
192 do_resize_C(reinterpret_cast<uint16_t*>(out
+ s
.outplane1_size
+ i
*
193 s
.outplanen_size
), reinterpret_cast<const uint16_t*>(in
+ s
.inplane1_size
+
194 i
* s
.inplanen_size
), s
);
199 int main(int argc
, char** argv
)
205 for(int i
= 1; i
< argc
; i
++) {
206 std::string arg
= argv
[i
];
210 std::cerr
<< "hdify: Unrecognized option '" << arg
<< "'" << std::endl
;
218 mark_pipe_as_binary(in
);
219 mark_pipe_as_binary(out
);
224 struct yuv4mpeg_stream_header
strmh(in
);
225 s
.inwidth
= strmh
.width
;
226 s
.inheight
= strmh
.height
;
228 if(strmh
.sar_n
&& strmh
.sar_d
)
229 sar
= 1.0 * strmh
.sar_n
/ strmh
.sar_d
;
230 compute_scale_factors(s
.inwidth
, s
.inheight
, sar
, s
.factor_x
, s
.factor_y
);
236 s
.chroma
= strmh
.chroma
;
238 strmh
.width
= s
.outwidth
;
239 strmh
.height
= s
.outheight
;
243 std::string _strmh
= std::string(strmh
);
244 write_or_die(out
, _strmh
);
246 std::vector
<char> buffer
;
247 std::vector
<char> buffer2
;
248 buffer
.resize(s
.insize
+ 128);
249 buffer2
.resize(s
.outsize
+ 128);
252 if(!read_line2(in
, _framh
))
254 read_or_die(in
, &buffer
[0], s
.insize
);
255 do_resize(&buffer2
[0], &buffer
[0], s
);
256 write_or_die(out
, _framh
);
257 write_or_die(out
, &buffer2
[0], s
.outsize
);
260 } catch(std::exception
& e
) {
261 std::cerr
<< "hdify: Error: " << e
.what() << std::endl
;