34
34
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35
35
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
36
*/
37
+ /**
38
+ * @file
39
+ * @todo
40
+ * * support for RGB formats
41
+ */
37
42
38
43
#include <errno.h> // for errno
44
+ #include <stdbool.h> // for bool, false, true
45
+ #include <stdint.h> // for uint16_t
39
46
#include <stdlib.h> // for NULL, free, calloc
40
47
#include <string.h> // for strcmp, memcpy
41
48
42
49
#include "capture_filter.h" // for CAPTURE_FILTER_AB...
43
50
#include "debug.h" // for LOG_LEVEL_ERROR, MSG
44
51
#include "lib_common.h" // for REGISTER_MODULE
52
+ #include "pixfmt_conv.h" // for get_decoder_from_to
45
53
#include "types.h" // for tile, video_frame
46
54
#include "utils/color_out.h" // for color_printf, TBOLD
47
55
#include "utils/macros.h" // for STR_LEN, snprintf_ch
@@ -67,6 +75,8 @@ struct state_capture_filter_matrix2 {
67
75
double transform_matrix [MATRIX_VOL ];
68
76
void * vo_pp_out_buffer ; ///< buffer to write to if we use vo_pp wrapper
69
77
///< (otherwise unused)
78
+ void * y416_tmp_buffer ;
79
+ size_t y416_tmp_buffer_sz ;
70
80
};
71
81
72
82
static void
@@ -83,7 +93,9 @@ usage(void)
83
93
"matrix [a b c; d e f; g h i], decimals.\n"
84
94
"Coefficients are applied to unpacked pixels (eg. on Y Cb "
85
95
"and Cr channels of UYVY).\n" );
86
- color_printf ("\nCurrently only " TBOLD ("UYVY" ) " is supported.\n" );
96
+ color_printf ("\n" TBOLD ("Note: " ) "Currently only " TBOLD (
97
+ "YCbCr" ) " codecs are supported. "
98
+ "Let us know if interested in " TBOLD ("RGB" ) " ones.\n" );
87
99
color_printf (
88
100
"\nSee also " TBOLD ("matrix" ) " capture filter/postprocessor.\n" );
89
101
color_printf ("\n" );
@@ -146,26 +158,15 @@ init(struct module *parent, const char *cfg, void **state)
146
158
static void
147
159
done (void * state )
148
160
{
161
+ struct state_capture_filter_matrix2 * s = state ;
162
+ free (s -> y416_tmp_buffer );
149
163
free (state );
150
164
}
151
165
152
- static struct video_frame *
153
- filter (void * state , struct video_frame * in )
166
+ static void
167
+ apply_to_uyvy (struct state_capture_filter_matrix2 * s , struct video_frame * in ,
168
+ struct video_frame * out )
154
169
{
155
- struct state_capture_filter_matrix2 * s = state ;
156
- struct video_desc desc = video_desc_from_frame (in );
157
- struct video_frame * out = vf_alloc_desc (desc );
158
- if (s -> vo_pp_out_buffer ) {
159
- out -> tiles [0 ].data = s -> vo_pp_out_buffer ;
160
- } else {
161
- out -> tiles [0 ].data = malloc (out -> tiles [0 ].data_len );
162
- out -> callbacks .data_deleter = vf_data_deleter ;
163
- }
164
- out -> callbacks .dispose = vf_free ;
165
-
166
- if (in -> color_spec != UYVY ) {
167
- MSG (ERROR , "Sorry, only UYVY supported by now.\n" );
168
- }
169
170
unsigned char * in_data = (unsigned char * ) in -> tiles [0 ].data ;
170
171
unsigned char * out_data = (unsigned char * ) out -> tiles [0 ].data ;
171
172
@@ -192,9 +193,83 @@ filter(void *state, struct video_frame *in)
192
193
s -> transform_matrix [1 ] * u +
193
194
s -> transform_matrix [2 ] * v ;
194
195
}
196
+ }
195
197
196
- VIDEO_FRAME_DISPOSE (in );
198
+ static bool
199
+ convert_apply_y416 (struct state_capture_filter_matrix2 * s ,
200
+ struct video_frame * in , struct video_frame * out )
201
+ {
202
+ decoder_t from = get_decoder_from_to (in -> color_spec , Y416 );
203
+ decoder_t to = get_decoder_from_to (Y416 , in -> color_spec );
204
+ if (from == NULL || to == NULL ) {
205
+ return false;
206
+ }
207
+
208
+ const size_t tmp_len =
209
+ vc_get_datalen (in -> tiles [0 ].width , in -> tiles [0 ].height , Y416 );
210
+ if (s -> y416_tmp_buffer_sz <= tmp_len ) {
211
+ free (s -> y416_tmp_buffer );
212
+ s -> y416_tmp_buffer = malloc (tmp_len );
213
+ s -> y416_tmp_buffer_sz = tmp_len ;
214
+ }
215
+ from ((unsigned char * ) s -> y416_tmp_buffer ,
216
+ (unsigned char * ) in -> tiles [0 ].data , (int ) tmp_len , 0 , 0 , 0 );
217
+ uint16_t * data = s -> y416_tmp_buffer ;
218
+ for (unsigned int i = 0 ; i < tmp_len ; i += 8 ) {
219
+ double u = data [0 ] - (1 << 15 );
220
+ double y = data [1 ] - (1 << 12 );
221
+ double v = data [2 ] - (1 << 15 );
222
+ // U
223
+ * data ++ = (1 << 15 ) + s -> transform_matrix [3 ] * y +
224
+ s -> transform_matrix [4 ] * u +
225
+ s -> transform_matrix [5 ] * v ;
226
+ // Y
227
+ * data ++ = (1 << 12 ) + s -> transform_matrix [0 ] * y +
228
+ s -> transform_matrix [1 ] * u +
229
+ s -> transform_matrix [2 ] * v ;
230
+ // V
231
+ * data ++ = (1 << 15 ) + s -> transform_matrix [6 ] * y +
232
+ s -> transform_matrix [7 ] * u +
233
+ s -> transform_matrix [8 ] * v ;
234
+ // A
235
+ * data ++ = 0xFFFF ;
236
+ }
237
+
238
+ to ((unsigned char * ) out -> tiles [0 ].data ,
239
+ (unsigned char * ) s -> y416_tmp_buffer , (int ) tmp_len , DEFAULT_R_SHIFT ,
240
+ DEFAULT_G_SHIFT , DEFAULT_B_SHIFT );
241
+ return true;
242
+ }
243
+
244
+ static struct video_frame *
245
+ filter (void * state , struct video_frame * in )
246
+ {
247
+ struct state_capture_filter_matrix2 * s = state ;
248
+ struct video_desc desc = video_desc_from_frame (in );
249
+ struct video_frame * out = vf_alloc_desc (desc );
250
+ if (s -> vo_pp_out_buffer ) {
251
+ out -> tiles [0 ].data = s -> vo_pp_out_buffer ;
252
+ } else {
253
+ out -> tiles [0 ].data = malloc (out -> tiles [0 ].data_len );
254
+ out -> callbacks .data_deleter = vf_data_deleter ;
255
+ }
256
+ out -> callbacks .dispose = vf_free ;
257
+
258
+ if (in -> color_spec == UYVY ) {
259
+ apply_to_uyvy (s , in , out );
260
+ } else {
261
+ if (codec_is_a_rgb (in -> color_spec ) ||
262
+ !convert_apply_y416 (s , in , out )) {
263
+ MSG (ERROR ,
264
+ "Sorry, only UYVY and YCbCr modes convertible to "
265
+ "and from Y416 are supported by now (have %s).\n" ,
266
+ get_codec_name (in -> color_spec ));
267
+ VIDEO_FRAME_DISPOSE (in );
268
+ return out ;
269
+ }
270
+ }
197
271
272
+ VIDEO_FRAME_DISPOSE (in );
198
273
return out ;
199
274
}
200
275
0 commit comments