2 * Copyright (C) 2010 David Schleef <ds@schleef.org>
3 * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
32 #include "video-converter.h"
38 #include <gst/allocators/gsttizenmemory.h>
40 #include <gst/base/base.h>
42 #include "video-orc.h"
45 * SECTION:videoconverter
46 * @title: GstVideoConverter
47 * @short_description: Generic video conversion
49 * This object is used to convert video frames from one format to another.
50 * The object can perform conversion of:
62 * (c) (convert Y'CbCr to R'G'B')
65 * (f) colorspace convert through XYZ
68 * (i) (convert R'G'B' to Y'CbCr)
69 * (j) chroma downsample
74 * (a) range truncate, range expand
75 * (b) full upsample, 1-1 non-cosited upsample, no upsample
83 * (j) 1-1 cosited downsample, no downsample
87 * 1 : a -> -> -> -> e -> f -> g -> -> -> -> k
88 * 2 : a -> -> -> -> e -> f* -> g -> -> -> -> k
89 * 3 : a -> -> -> -> e* -> f* -> g* -> -> -> -> k
90 * 4 : a -> b -> -> -> e -> f -> g -> -> -> j -> k
91 * 5 : a -> b -> -> -> e* -> f* -> g* -> -> -> j -> k
92 * 6 : a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k
93 * 7 : a -> b -> c -> d -> e* -> f* -> g* -> h -> i -> j -> k
95 * 8 : a -> b -> c -> d -> e* -> f* -> g* -> h -> i -> j -> k
96 * 9 : a -> b -> c -> d -> e* -> f* -> g* -> h -> i -> j -> k
97 * 10 : a -> b -> c -> d -> e* -> f* -> g* -> h -> i -> j -> k
100 #ifndef GST_DISABLE_GST_DEBUG
101 #define GST_CAT_DEFAULT ensure_debug_category()
102 static GstDebugCategory *
103 ensure_debug_category (void)
105 static gsize cat_gonce = 0;
107 if (g_once_init_enter (&cat_gonce)) {
110 cat_done = (gsize) _gst_debug_category_new ("video-converter", 0,
111 "video-converter object");
113 g_once_init_leave (&cat_gonce, cat_done);
116 return (GstDebugCategory *) cat_gonce;
119 #define ensure_debug_category() /* NOOP */
120 #endif /* GST_DISABLE_GST_DEBUG */
122 typedef void (*GstParallelizedTaskFunc) (gpointer user_data);
124 typedef struct _GstParallelizedTaskRunner GstParallelizedTaskRunner;
125 typedef struct _GstParallelizedWorkItem GstParallelizedWorkItem;
127 struct _GstParallelizedWorkItem
129 GstParallelizedTaskRunner *self;
130 GstParallelizedTaskFunc func;
134 struct _GstParallelizedTaskRunner
140 GstQueueArray *tasks;
141 GstQueueArray *work_items;
145 gboolean async_tasks;
149 gst_parallelized_task_thread_func (gpointer data)
151 GstParallelizedTaskRunner *runner = data;
152 GstParallelizedWorkItem *work_item;
154 g_mutex_lock (&runner->lock);
155 work_item = gst_queue_array_pop_head (runner->work_items);
156 g_mutex_unlock (&runner->lock);
158 g_assert (work_item != NULL);
159 g_assert (work_item->func != NULL);
162 work_item->func (work_item->user_data);
163 if (runner->async_tasks)
168 gst_parallelized_task_runner_join (GstParallelizedTaskRunner * self)
170 gboolean joined = FALSE;
173 g_mutex_lock (&self->lock);
174 if (!(joined = gst_queue_array_is_empty (self->tasks))) {
175 gpointer task = gst_queue_array_pop_head (self->tasks);
176 g_mutex_unlock (&self->lock);
177 gst_task_pool_join (self->pool, task);
179 g_mutex_unlock (&self->lock);
185 gst_parallelized_task_runner_free (GstParallelizedTaskRunner * self)
187 gst_parallelized_task_runner_join (self);
189 gst_queue_array_free (self->work_items);
190 gst_queue_array_free (self->tasks);
192 gst_task_pool_cleanup (self->pool);
193 gst_object_unref (self->pool);
194 g_mutex_clear (&self->lock);
198 static GstParallelizedTaskRunner *
199 gst_parallelized_task_runner_new (guint n_threads, GstTaskPool * pool,
200 gboolean async_tasks)
202 GstParallelizedTaskRunner *self;
205 n_threads = g_get_num_processors ();
207 self = g_new0 (GstParallelizedTaskRunner, 1);
210 self->pool = g_object_ref (pool);
211 self->own_pool = FALSE;
213 /* No reason to split up the work between more threads than the
215 if (GST_IS_SHARED_TASK_POOL (pool))
218 gst_shared_task_pool_get_max_threads (GST_SHARED_TASK_POOL (pool)));
220 self->pool = gst_shared_task_pool_new ();
221 self->own_pool = TRUE;
222 gst_shared_task_pool_set_max_threads (GST_SHARED_TASK_POOL (self->pool),
224 gst_task_pool_prepare (self->pool, NULL);
227 self->tasks = gst_queue_array_new (n_threads);
228 self->work_items = gst_queue_array_new (n_threads);
230 self->n_threads = n_threads;
232 g_mutex_init (&self->lock);
234 /* Set when scheduling a job */
235 self->async_tasks = async_tasks;
241 gst_parallelized_task_runner_finish (GstParallelizedTaskRunner * self)
243 gst_parallelized_task_runner_join (self);
247 gst_parallelized_task_runner_run (GstParallelizedTaskRunner * self,
248 GstParallelizedTaskFunc func, gpointer * task_data)
250 guint n_threads = self->n_threads;
252 if (n_threads > 1 || self->async_tasks) {
254 g_mutex_lock (&self->lock);
255 if (!self->async_tasks) {
256 /* if not async, perform one of the functions in the current thread */
259 for (; i < n_threads; i++) {
261 GstParallelizedWorkItem *work_item;
263 if (!self->async_tasks)
264 work_item = g_newa (GstParallelizedWorkItem, 1);
266 work_item = g_new0 (GstParallelizedWorkItem, 1);
268 work_item->self = self;
269 work_item->func = func;
270 work_item->user_data = task_data[i];
271 gst_queue_array_push_tail (self->work_items, work_item);
274 gst_task_pool_push (self->pool, gst_parallelized_task_thread_func,
277 /* The return value of push() is unfortunately nullable, and we can't deal with that */
278 g_assert (task != NULL);
279 gst_queue_array_push_tail (self->tasks, task);
281 g_mutex_unlock (&self->lock);
284 if (!self->async_tasks) {
287 gst_parallelized_task_runner_finish (self);
291 typedef struct _GstLineCache GstLineCache;
294 #define SCALE_F ((float) (1 << SCALE))
296 typedef struct _MatrixData MatrixData;
311 void (*matrix_func) (MatrixData * data, gpointer pixels);
314 typedef struct _GammaData GammaData;
318 gpointer gamma_table;
320 void (*gamma_func) (GammaData * data, gpointer dest, gpointer src);
326 ALPHA_MODE_COPY = (1 << 0),
327 ALPHA_MODE_SET = (1 << 1),
328 ALPHA_MODE_MULT = (1 << 2)
338 GDestroyNotify notify;
341 typedef void (*FastConvertFunc) (GstVideoConverter * convert,
342 const GstVideoFrame * src, GstVideoFrame * dest, gint plane);
344 struct _GstVideoConverter
348 GstVideoInfo in_info;
349 GstVideoInfo out_info;
364 gint current_pstride;
367 GstVideoFormat current_format;
370 GstStructure *config;
372 GstParallelizedTaskRunner *conversion_runner;
376 gboolean fill_border;
381 AlphaMode alpha_mode;
383 void (*convert) (GstVideoConverter * convert, const GstVideoFrame * src,
384 GstVideoFrame * dest);
386 /* data for unpack */
387 GstLineCache **unpack_lines;
388 GstVideoFormat unpack_format;
391 gboolean identity_unpack;
394 /* chroma upsample */
395 GstLineCache **upsample_lines;
396 GstVideoChromaResample **upsample;
397 GstVideoChromaResample **upsample_p;
398 GstVideoChromaResample **upsample_i;
403 GstLineCache **to_RGB_lines;
404 MatrixData to_RGB_matrix;
409 GstLineCache **hscale_lines;
410 GstVideoScaler **h_scaler;
412 GstLineCache **vscale_lines;
413 GstVideoScaler **v_scaler;
414 GstVideoScaler **v_scaler_p;
415 GstVideoScaler **v_scaler_i;
419 /* color space conversion */
420 GstLineCache **convert_lines;
421 MatrixData convert_matrix;
425 /* alpha correction */
426 GstLineCache **alpha_lines;
427 void (*alpha_func) (GstVideoConverter * convert, gpointer pixels, gint width);
432 GstLineCache **to_YUV_lines;
433 MatrixData to_YUV_matrix;
435 /* chroma downsample */
436 GstLineCache **downsample_lines;
437 GstVideoChromaResample **downsample;
438 GstVideoChromaResample **downsample_p;
439 GstVideoChromaResample **downsample_i;
444 GstLineCache **dither_lines;
445 GstVideoDither **dither;
448 GstLineCache **pack_lines;
450 GstVideoFormat pack_format;
453 gboolean identity_pack;
455 gconstpointer pack_pal;
458 const GstVideoFrame *src;
462 GstVideoFormat fformat[4];
474 GstVideoScaler **scaler;
478 GstVideoScaler **scaler;
480 FastConvertFunc fconvert[4];
482 /* for parallel async running */
487 typedef gpointer (*GstLineCacheAllocLineFunc) (GstLineCache * cache, gint idx,
489 typedef gboolean (*GstLineCacheNeedLineFunc) (GstLineCache * cache, gint idx,
490 gint out_line, gint in_line, gpointer user_data);
499 gboolean write_input;
501 gboolean alloc_writable;
503 GstLineCacheNeedLineFunc need_line;
505 gpointer need_line_data;
506 GDestroyNotify need_line_notify;
510 GstLineCacheAllocLineFunc alloc_line;
511 gpointer alloc_line_data;
512 GDestroyNotify alloc_line_notify;
515 static GstLineCache *
516 gst_line_cache_new (GstLineCache * prev)
518 GstLineCache *result;
520 result = g_slice_new0 (GstLineCache);
521 result->lines = g_ptr_array_new ();
528 gst_line_cache_clear (GstLineCache * cache)
530 g_return_if_fail (cache != NULL);
532 g_ptr_array_set_size (cache->lines, 0);
537 gst_line_cache_free (GstLineCache * cache)
539 if (cache->need_line_notify)
540 cache->need_line_notify (cache->need_line_data);
541 if (cache->alloc_line_notify)
542 cache->alloc_line_notify (cache->alloc_line_data);
543 gst_line_cache_clear (cache);
544 g_ptr_array_unref (cache->lines);
545 g_slice_free (GstLineCache, cache);
549 gst_line_cache_set_need_line_func (GstLineCache * cache,
550 GstLineCacheNeedLineFunc need_line, gint idx, gpointer user_data,
551 GDestroyNotify notify)
553 cache->need_line = need_line;
554 cache->need_line_idx = idx;
555 cache->need_line_data = user_data;
556 cache->need_line_notify = notify;
560 gst_line_cache_set_alloc_line_func (GstLineCache * cache,
561 GstLineCacheAllocLineFunc alloc_line, gpointer user_data,
562 GDestroyNotify notify)
564 cache->alloc_line = alloc_line;
565 cache->alloc_line_data = user_data;
566 cache->alloc_line_notify = notify;
569 /* keep this much backlog for interlaced video */
573 gst_line_cache_get_lines (GstLineCache * cache, gint idx, gint out_line,
574 gint in_line, gint n_lines)
576 if (cache->first + cache->backlog < in_line) {
578 MIN (in_line - (cache->first + cache->backlog), cache->lines->len);
580 g_ptr_array_remove_range (cache->lines, 0, to_remove);
582 cache->first += to_remove;
583 } else if (in_line < cache->first) {
584 gst_line_cache_clear (cache);
585 cache->first = in_line;
591 if (cache->first <= in_line
592 && in_line + n_lines <= cache->first + (gint) cache->lines->len) {
593 return cache->lines->pdata + (in_line - cache->first);
596 if (cache->need_line == NULL)
599 /* We may be able to skip ahead to the earliest line needed */
600 if (cache->lines->len == 0 && cache->first + cache->backlog < in_line)
601 cache->first = in_line - cache->backlog;
603 oline = out_line + cache->first + cache->lines->len - in_line;
605 if (!cache->need_line (cache, idx, oline, cache->first + cache->lines->len,
606 cache->need_line_data))
609 GST_DEBUG ("no lines");
614 gst_line_cache_add_line (GstLineCache * cache, gint idx, gpointer line)
616 if (cache->first + cache->lines->len != idx) {
617 gst_line_cache_clear (cache);
620 g_ptr_array_add (cache->lines, line);
624 gst_line_cache_alloc_line (GstLineCache * cache, gint idx)
628 if (cache->alloc_line)
629 res = cache->alloc_line (cache, idx, cache->alloc_line_data);
636 static void video_converter_generic (GstVideoConverter * convert,
637 const GstVideoFrame * src, GstVideoFrame * dest);
638 static gboolean video_converter_lookup_fastpath (GstVideoConverter * convert);
639 static void video_converter_compute_matrix (GstVideoConverter * convert);
640 static void video_converter_compute_resample (GstVideoConverter * convert,
643 static gpointer get_dest_line (GstLineCache * cache, gint idx,
646 static gboolean do_unpack_lines (GstLineCache * cache, gint idx, gint out_line,
647 gint in_line, gpointer user_data);
648 static gboolean do_downsample_lines (GstLineCache * cache, gint idx,
649 gint out_line, gint in_line, gpointer user_data);
650 static gboolean do_convert_to_RGB_lines (GstLineCache * cache, gint idx,
651 gint out_line, gint in_line, gpointer user_data);
652 static gboolean do_convert_lines (GstLineCache * cache, gint idx, gint out_line,
653 gint in_line, gpointer user_data);
654 static gboolean do_alpha_lines (GstLineCache * cache, gint idx, gint out_line,
655 gint in_line, gpointer user_data);
656 static gboolean do_convert_to_YUV_lines (GstLineCache * cache, gint idx,
657 gint out_line, gint in_line, gpointer user_data);
658 static gboolean do_upsample_lines (GstLineCache * cache, gint idx,
659 gint out_line, gint in_line, gpointer user_data);
660 static gboolean do_vscale_lines (GstLineCache * cache, gint idx, gint out_line,
661 gint in_line, gpointer user_data);
662 static gboolean do_hscale_lines (GstLineCache * cache, gint idx, gint out_line,
663 gint in_line, gpointer user_data);
664 static gboolean do_dither_lines (GstLineCache * cache, gint idx, gint out_line,
665 gint in_line, gpointer user_data);
667 static ConverterAlloc *
668 converter_alloc_new (guint stride, guint n_lines, gpointer user_data,
669 GDestroyNotify notify)
671 ConverterAlloc *alloc;
673 GST_DEBUG ("stride %d, n_lines %d", stride, n_lines);
674 alloc = g_slice_new0 (ConverterAlloc);
675 alloc->data = g_malloc (stride * n_lines);
676 alloc->stride = stride;
677 alloc->n_lines = n_lines;
679 alloc->user_data = user_data;
680 alloc->notify = notify;
686 converter_alloc_free (ConverterAlloc * alloc)
689 alloc->notify (alloc->user_data);
690 g_free (alloc->data);
691 g_slice_free (ConverterAlloc, alloc);
695 setup_border_alloc (GstVideoConverter * convert, ConverterAlloc * alloc)
699 if (convert->borderline) {
700 for (i = 0; i < alloc->n_lines; i++)
701 memcpy (&alloc->data[i * alloc->stride], convert->borderline,
707 get_temp_line (GstLineCache * cache, gint idx, gpointer user_data)
709 ConverterAlloc *alloc = user_data;
712 GST_DEBUG ("get temp line %d (%p %d)", idx, alloc, alloc->idx);
713 tmpline = &alloc->data[alloc->stride * alloc->idx];
714 alloc->idx = (alloc->idx + 1) % alloc->n_lines;
720 get_border_temp_line (GstLineCache * cache, gint idx, gpointer user_data)
722 ConverterAlloc *alloc = user_data;
723 GstVideoConverter *convert = alloc->user_data;
726 GST_DEBUG ("get temp line %d (%p %d)", idx, alloc, alloc->idx);
727 tmpline = &alloc->data[alloc->stride * alloc->idx] +
728 (convert->out_x * convert->pack_pstride);
729 alloc->idx = (alloc->idx + 1) % alloc->n_lines;
735 get_opt_int (GstVideoConverter * convert, const gchar * opt, gint def)
738 if (!gst_structure_get_int (convert->config, opt, &res))
744 get_opt_uint (GstVideoConverter * convert, const gchar * opt, guint def)
747 if (!gst_structure_get_uint (convert->config, opt, &res))
753 get_opt_double (GstVideoConverter * convert, const gchar * opt, gdouble def)
756 if (!gst_structure_get_double (convert->config, opt, &res))
762 get_opt_bool (GstVideoConverter * convert, const gchar * opt, gboolean def)
765 if (!gst_structure_get_boolean (convert->config, opt, &res))
771 get_opt_enum (GstVideoConverter * convert, const gchar * opt, GType type,
775 if (!gst_structure_get_enum (convert->config, opt, type, &res))
780 #define DEFAULT_OPT_FILL_BORDER TRUE
781 #define DEFAULT_OPT_ALPHA_VALUE 1.0
782 /* options copy, set, mult */
783 #define DEFAULT_OPT_ALPHA_MODE GST_VIDEO_ALPHA_MODE_COPY
784 #define DEFAULT_OPT_BORDER_ARGB 0xff000000
785 /* options full, input-only, output-only, none */
786 #define DEFAULT_OPT_MATRIX_MODE GST_VIDEO_MATRIX_MODE_FULL
788 #define DEFAULT_OPT_GAMMA_MODE GST_VIDEO_GAMMA_MODE_NONE
789 /* none, merge-only, fast */
790 #define DEFAULT_OPT_PRIMARIES_MODE GST_VIDEO_PRIMARIES_MODE_NONE
791 /* options full, upsample-only, downsample-only, none */
792 #define DEFAULT_OPT_CHROMA_MODE GST_VIDEO_CHROMA_MODE_FULL
793 #define DEFAULT_OPT_RESAMPLER_METHOD GST_VIDEO_RESAMPLER_METHOD_CUBIC
794 #define DEFAULT_OPT_CHROMA_RESAMPLER_METHOD GST_VIDEO_RESAMPLER_METHOD_LINEAR
795 #define DEFAULT_OPT_RESAMPLER_TAPS 0
796 #define DEFAULT_OPT_DITHER_METHOD GST_VIDEO_DITHER_BAYER
797 #define DEFAULT_OPT_DITHER_QUANTIZATION 1
798 #define DEFAULT_OPT_ASYNC_TASKS FALSE
800 #define GET_OPT_FILL_BORDER(c) get_opt_bool(c, \
801 GST_VIDEO_CONVERTER_OPT_FILL_BORDER, DEFAULT_OPT_FILL_BORDER)
802 #define GET_OPT_ALPHA_VALUE(c) get_opt_double(c, \
803 GST_VIDEO_CONVERTER_OPT_ALPHA_VALUE, DEFAULT_OPT_ALPHA_VALUE)
804 #define GET_OPT_ALPHA_MODE(c) get_opt_enum(c, \
805 GST_VIDEO_CONVERTER_OPT_ALPHA_MODE, GST_TYPE_VIDEO_ALPHA_MODE, DEFAULT_OPT_ALPHA_MODE)
806 #define GET_OPT_BORDER_ARGB(c) get_opt_uint(c, \
807 GST_VIDEO_CONVERTER_OPT_BORDER_ARGB, DEFAULT_OPT_BORDER_ARGB)
808 #define GET_OPT_MATRIX_MODE(c) get_opt_enum(c, \
809 GST_VIDEO_CONVERTER_OPT_MATRIX_MODE, GST_TYPE_VIDEO_MATRIX_MODE, DEFAULT_OPT_MATRIX_MODE)
810 #define GET_OPT_GAMMA_MODE(c) get_opt_enum(c, \
811 GST_VIDEO_CONVERTER_OPT_GAMMA_MODE, GST_TYPE_VIDEO_GAMMA_MODE, DEFAULT_OPT_GAMMA_MODE)
812 #define GET_OPT_PRIMARIES_MODE(c) get_opt_enum(c, \
813 GST_VIDEO_CONVERTER_OPT_PRIMARIES_MODE, GST_TYPE_VIDEO_PRIMARIES_MODE, DEFAULT_OPT_PRIMARIES_MODE)
814 #define GET_OPT_CHROMA_MODE(c) get_opt_enum(c, \
815 GST_VIDEO_CONVERTER_OPT_CHROMA_MODE, GST_TYPE_VIDEO_CHROMA_MODE, DEFAULT_OPT_CHROMA_MODE)
816 #define GET_OPT_RESAMPLER_METHOD(c) get_opt_enum(c, \
817 GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, \
818 DEFAULT_OPT_RESAMPLER_METHOD)
819 #define GET_OPT_CHROMA_RESAMPLER_METHOD(c) get_opt_enum(c, \
820 GST_VIDEO_CONVERTER_OPT_CHROMA_RESAMPLER_METHOD, GST_TYPE_VIDEO_RESAMPLER_METHOD, \
821 DEFAULT_OPT_CHROMA_RESAMPLER_METHOD)
822 #define GET_OPT_RESAMPLER_TAPS(c) get_opt_uint(c, \
823 GST_VIDEO_CONVERTER_OPT_RESAMPLER_TAPS, DEFAULT_OPT_RESAMPLER_TAPS)
824 #define GET_OPT_DITHER_METHOD(c) get_opt_enum(c, \
825 GST_VIDEO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_VIDEO_DITHER_METHOD, \
826 DEFAULT_OPT_DITHER_METHOD)
827 #define GET_OPT_DITHER_QUANTIZATION(c) get_opt_uint(c, \
828 GST_VIDEO_CONVERTER_OPT_DITHER_QUANTIZATION, DEFAULT_OPT_DITHER_QUANTIZATION)
829 #define GET_OPT_ASYNC_TASKS(c) get_opt_bool(c, \
830 GST_VIDEO_CONVERTER_OPT_ASYNC_TASKS, DEFAULT_OPT_ASYNC_TASKS)
832 #define CHECK_ALPHA_COPY(c) (GET_OPT_ALPHA_MODE(c) == GST_VIDEO_ALPHA_MODE_COPY)
833 #define CHECK_ALPHA_SET(c) (GET_OPT_ALPHA_MODE(c) == GST_VIDEO_ALPHA_MODE_SET)
834 #define CHECK_ALPHA_MULT(c) (GET_OPT_ALPHA_MODE(c) == GST_VIDEO_ALPHA_MODE_MULT)
836 #define CHECK_MATRIX_FULL(c) (GET_OPT_MATRIX_MODE(c) == GST_VIDEO_MATRIX_MODE_FULL)
837 #define CHECK_MATRIX_INPUT(c) (GET_OPT_MATRIX_MODE(c) == GST_VIDEO_MATRIX_MODE_INPUT_ONLY)
838 #define CHECK_MATRIX_OUTPUT(c) (GET_OPT_MATRIX_MODE(c) == GST_VIDEO_MATRIX_MODE_OUTPUT_ONLY)
839 #define CHECK_MATRIX_NONE(c) (GET_OPT_MATRIX_MODE(c) == GST_VIDEO_MATRIX_MODE_NONE)
841 #define CHECK_GAMMA_NONE(c) (GET_OPT_GAMMA_MODE(c) == GST_VIDEO_GAMMA_MODE_NONE)
842 #define CHECK_GAMMA_REMAP(c) (GET_OPT_GAMMA_MODE(c) == GST_VIDEO_GAMMA_MODE_REMAP)
844 #define CHECK_PRIMARIES_NONE(c) (GET_OPT_PRIMARIES_MODE(c) == GST_VIDEO_PRIMARIES_MODE_NONE)
845 #define CHECK_PRIMARIES_MERGE(c) (GET_OPT_PRIMARIES_MODE(c) == GST_VIDEO_PRIMARIES_MODE_MERGE_ONLY)
846 #define CHECK_PRIMARIES_FAST(c) (GET_OPT_PRIMARIES_MODE(c) == GST_VIDEO_PRIMARIES_MODE_FAST)
848 #define CHECK_CHROMA_FULL(c) (GET_OPT_CHROMA_MODE(c) == GST_VIDEO_CHROMA_MODE_FULL)
849 #define CHECK_CHROMA_UPSAMPLE(c) (GET_OPT_CHROMA_MODE(c) == GST_VIDEO_CHROMA_MODE_UPSAMPLE_ONLY)
850 #define CHECK_CHROMA_DOWNSAMPLE(c) (GET_OPT_CHROMA_MODE(c) == GST_VIDEO_CHROMA_MODE_DOWNSAMPLE_ONLY)
851 #define CHECK_CHROMA_NONE(c) (GET_OPT_CHROMA_MODE(c) == GST_VIDEO_CHROMA_MODE_NONE)
853 static GstLineCache *
854 chain_unpack_line (GstVideoConverter * convert, gint idx)
859 info = &convert->in_info;
861 convert->current_format = convert->unpack_format;
862 convert->current_bits = convert->unpack_bits;
863 convert->current_pstride = convert->current_bits >> 1;
865 convert->unpack_pstride = convert->current_pstride;
866 convert->identity_unpack = (convert->current_format == info->finfo->format);
868 GST_DEBUG ("chain unpack line format %s, pstride %d, identity_unpack %d",
869 gst_video_format_to_string (convert->current_format),
870 convert->current_pstride, convert->identity_unpack);
872 prev = convert->unpack_lines[idx] = gst_line_cache_new (NULL);
873 prev->write_input = FALSE;
874 prev->pass_alloc = FALSE;
876 prev->stride = convert->current_pstride * convert->current_width;
877 gst_line_cache_set_need_line_func (prev, do_unpack_lines, idx, convert, NULL);
882 static GstLineCache *
883 chain_upsample (GstVideoConverter * convert, GstLineCache * prev, gint idx)
885 video_converter_compute_resample (convert, idx);
887 if (convert->upsample_p[idx] || convert->upsample_i[idx]) {
888 GST_DEBUG ("chain upsample");
889 prev = convert->upsample_lines[idx] = gst_line_cache_new (prev);
890 prev->write_input = TRUE;
891 prev->pass_alloc = TRUE;
892 /* XXX: why this hardcoded value? */
894 prev->stride = convert->current_pstride * convert->current_width;
895 gst_line_cache_set_need_line_func (prev,
896 do_upsample_lines, idx, convert, NULL);
902 color_matrix_set_identity (MatrixData * m)
906 for (i = 0; i < 4; i++) {
907 for (j = 0; j < 4; j++) {
908 m->dm[i][j] = (i == j);
914 color_matrix_copy (MatrixData * d, const MatrixData * s)
918 for (i = 0; i < 4; i++)
919 for (j = 0; j < 4; j++)
920 d->dm[i][j] = s->dm[i][j];
923 /* Perform 4x4 matrix multiplication:
924 * - @dst@ = @a@ * @b@
925 * - @dst@ may be a pointer to @a@ andor @b@
928 color_matrix_multiply (MatrixData * dst, MatrixData * a, MatrixData * b)
933 for (i = 0; i < 4; i++) {
934 for (j = 0; j < 4; j++) {
936 for (k = 0; k < 4; k++) {
937 x += a->dm[i][k] * b->dm[k][j];
942 color_matrix_copy (dst, &tmp);
946 color_matrix_invert (MatrixData * d, MatrixData * s)
952 color_matrix_set_identity (&tmp);
953 for (j = 0; j < 3; j++) {
954 for (i = 0; i < 3; i++) {
956 s->dm[(i + 1) % 3][(j + 1) % 3] * s->dm[(i + 2) % 3][(j + 2) % 3] -
957 s->dm[(i + 1) % 3][(j + 2) % 3] * s->dm[(i + 2) % 3][(j + 1) % 3];
961 tmp.dm[0][0] * s->dm[0][0] + tmp.dm[0][1] * s->dm[1][0] +
962 tmp.dm[0][2] * s->dm[2][0];
963 for (j = 0; j < 3; j++) {
964 for (i = 0; i < 3; i++) {
968 color_matrix_copy (d, &tmp);
972 color_matrix_offset_components (MatrixData * m, double a1, double a2, double a3)
976 color_matrix_set_identity (&a);
980 color_matrix_multiply (m, &a, m);
984 color_matrix_scale_components (MatrixData * m, double a1, double a2, double a3)
988 color_matrix_set_identity (&a);
992 color_matrix_multiply (m, &a, m);
996 color_matrix_debug (const MatrixData * s)
998 GST_DEBUG ("[%f %f %f %f]", s->dm[0][0], s->dm[0][1], s->dm[0][2],
1000 GST_DEBUG ("[%f %f %f %f]", s->dm[1][0], s->dm[1][1], s->dm[1][2],
1002 GST_DEBUG ("[%f %f %f %f]", s->dm[2][0], s->dm[2][1], s->dm[2][2],
1004 GST_DEBUG ("[%f %f %f %f]", s->dm[3][0], s->dm[3][1], s->dm[3][2],
1009 color_matrix_convert (MatrixData * s)
1013 for (i = 0; i < 4; i++)
1014 for (j = 0; j < 4; j++)
1015 s->im[i][j] = rint (s->dm[i][j]);
1017 GST_DEBUG ("[%6d %6d %6d %6d]", s->im[0][0], s->im[0][1], s->im[0][2],
1019 GST_DEBUG ("[%6d %6d %6d %6d]", s->im[1][0], s->im[1][1], s->im[1][2],
1021 GST_DEBUG ("[%6d %6d %6d %6d]", s->im[2][0], s->im[2][1], s->im[2][2],
1023 GST_DEBUG ("[%6d %6d %6d %6d]", s->im[3][0], s->im[3][1], s->im[3][2],
1028 color_matrix_YCbCr_to_RGB (MatrixData * m, double Kr, double Kb)
1030 double Kg = 1.0 - Kr - Kb;
1033 {1., 0., 2 * (1 - Kr), 0.},
1034 {1., -2 * Kb * (1 - Kb) / Kg, -2 * Kr * (1 - Kr) / Kg, 0.},
1035 {1., 2 * (1 - Kb), 0., 0.},
1040 color_matrix_multiply (m, &k, m);
1044 color_matrix_RGB_to_YCbCr (MatrixData * m, double Kr, double Kb)
1046 double Kg = 1.0 - Kr - Kb;
1055 x = 1 / (2 * (1 - Kb));
1056 k.dm[1][0] = -x * Kr;
1057 k.dm[1][1] = -x * Kg;
1058 k.dm[1][2] = x * (1 - Kb);
1061 x = 1 / (2 * (1 - Kr));
1062 k.dm[2][0] = x * (1 - Kr);
1063 k.dm[2][1] = -x * Kg;
1064 k.dm[2][2] = -x * Kb;
1072 color_matrix_multiply (m, &k, m);
1076 color_matrix_RGB_to_XYZ (MatrixData * dst, double Rx, double Ry, double Gx,
1077 double Gy, double Bx, double By, double Wx, double Wy)
1083 color_matrix_set_identity (&m);
1087 m.dm[2][0] = (1.0 - Rx - Ry);
1090 m.dm[2][1] = (1.0 - Gx - Gy);
1093 m.dm[2][2] = (1.0 - Bx - By);
1095 color_matrix_invert (&im, &m);
1099 wz = (1.0 - Wx - Wy) / Wy;
1101 sx = im.dm[0][0] * wx + im.dm[0][1] * wy + im.dm[0][2] * wz;
1102 sy = im.dm[1][0] * wx + im.dm[1][1] * wy + im.dm[1][2] * wz;
1103 sz = im.dm[2][0] * wx + im.dm[2][1] * wy + im.dm[2][2] * wz;
1115 color_matrix_copy (dst, &m);
1119 videoconvert_convert_init_tables (MatrixData * data)
1123 data->t_r = g_new (gint64, 256);
1124 data->t_g = g_new (gint64, 256);
1125 data->t_b = g_new (gint64, 256);
1127 for (i = 0; i < 256; i++) {
1128 gint64 r = 0, g = 0, b = 0;
1130 for (j = 0; j < 3; j++) {
1131 r = (r << 16) + data->im[j][0] * i;
1132 g = (g << 16) + data->im[j][1] * i;
1133 b = (b << 16) + data->im[j][2] * i;
1139 data->t_c = ((gint64) data->im[0][3] << 32)
1140 + ((gint64) data->im[1][3] << 16)
1141 + ((gint64) data->im[2][3] << 0);
1145 _custom_video_orc_matrix8 (guint8 * ORC_RESTRICT d1,
1146 const guint8 * ORC_RESTRICT s1, orc_int64 p1, orc_int64 p2, orc_int64 p3,
1147 orc_int64 p4, int n)
1152 gint a00, a01, a02, a03;
1153 gint a10, a11, a12, a13;
1154 gint a20, a21, a22, a23;
1156 a00 = (gint16) (p1 >> 16);
1157 a01 = (gint16) (p2 >> 16);
1158 a02 = (gint16) (p3 >> 16);
1159 a03 = (gint16) (p4 >> 16);
1160 a10 = (gint16) (p1 >> 32);
1161 a11 = (gint16) (p2 >> 32);
1162 a12 = (gint16) (p3 >> 32);
1163 a13 = (gint16) (p4 >> 32);
1164 a20 = (gint16) (p1 >> 48);
1165 a21 = (gint16) (p2 >> 48);
1166 a22 = (gint16) (p3 >> 48);
1167 a23 = (gint16) (p4 >> 48);
1169 for (i = 0; i < n; i++) {
1174 y = ((a00 * r + a01 * g + a02 * b) >> SCALE) + a03;
1175 u = ((a10 * r + a11 * g + a12 * b) >> SCALE) + a13;
1176 v = ((a20 * r + a21 * g + a22 * b) >> SCALE) + a23;
1178 d1[i * 4 + 1] = CLAMP (y, 0, 255);
1179 d1[i * 4 + 2] = CLAMP (u, 0, 255);
1180 d1[i * 4 + 3] = CLAMP (v, 0, 255);
1185 video_converter_matrix8 (MatrixData * data, gpointer pixels)
1187 gpointer d = pixels;
1188 video_orc_matrix8 (d, pixels, data->orc_p1, data->orc_p2,
1189 data->orc_p3, data->orc_p4, data->width);
1193 video_converter_matrix8_table (MatrixData * data, gpointer pixels)
1195 gint i, width = data->width * 4;
1197 gint64 c = data->t_c;
1201 for (i = 0; i < width; i += 4) {
1206 x = data->t_r[r] + data->t_g[g] + data->t_b[b] + c;
1208 p[i + 1] = x >> (32 + SCALE);
1209 p[i + 2] = x >> (16 + SCALE);
1210 p[i + 3] = x >> (0 + SCALE);
1215 video_converter_matrix8_AYUV_ARGB (MatrixData * data, gpointer pixels)
1217 gpointer d = pixels;
1219 video_orc_convert_AYUV_ARGB (d, 0, pixels, 0,
1220 data->im[0][0], data->im[0][2],
1221 data->im[2][1], data->im[1][1], data->im[1][2], data->width, 1);
1225 is_ayuv_to_rgb_matrix (MatrixData * data)
1227 if (data->im[0][0] != data->im[1][0] || data->im[1][0] != data->im[2][0])
1230 if (data->im[0][1] != 0 || data->im[2][2] != 0)
1237 is_identity_matrix (MatrixData * data)
1240 gint c = data->im[0][0];
1242 /* not really checking identity because of rounding errors but given
1243 * the conversions we do we just check for anything that looks like:
1250 for (i = 0; i < 4; i++) {
1251 for (j = 0; j < 4; j++) {
1253 if (i == 3 && data->im[i][j] != 1)
1255 else if (data->im[i][j] != c)
1257 } else if (data->im[i][j] != 0)
1265 is_no_clip_matrix (MatrixData * data)
1268 static const guint8 test[8][3] = {
1279 for (i = 0; i < 8; i++) {
1287 y = (data->im[0][0] * r + data->im[0][1] * g +
1288 data->im[0][2] * b + data->im[0][3]) >> SCALE;
1289 u = (data->im[1][0] * r + data->im[1][1] * g +
1290 data->im[1][2] * b + data->im[1][3]) >> SCALE;
1291 v = (data->im[2][0] * r + data->im[2][1] * g +
1292 data->im[2][2] * b + data->im[2][3]) >> SCALE;
1294 if (y != CLAMP (y, 0, 255) || u != CLAMP (u, 0, 255)
1295 || v != CLAMP (v, 0, 255))
1302 video_converter_matrix16 (MatrixData * data, gpointer pixels)
1307 guint16 *p = pixels;
1308 gint width = data->width;
1310 for (i = 0; i < width; i++) {
1315 y = (data->im[0][0] * r + data->im[0][1] * g +
1316 data->im[0][2] * b + data->im[0][3]) >> SCALE;
1317 u = (data->im[1][0] * r + data->im[1][1] * g +
1318 data->im[1][2] * b + data->im[1][3]) >> SCALE;
1319 v = (data->im[2][0] * r + data->im[2][1] * g +
1320 data->im[2][2] * b + data->im[2][3]) >> SCALE;
1322 p[i * 4 + 1] = CLAMP (y, 0, 65535);
1323 p[i * 4 + 2] = CLAMP (u, 0, 65535);
1324 p[i * 4 + 3] = CLAMP (v, 0, 65535);
1330 prepare_matrix (GstVideoConverter * convert, MatrixData * data)
1332 if (is_identity_matrix (data))
1335 color_matrix_scale_components (data, SCALE_F, SCALE_F, SCALE_F);
1336 color_matrix_convert (data);
1338 data->width = convert->current_width;
1340 if (convert->current_bits == 8) {
1341 if (!convert->unpack_rgb && convert->pack_rgb
1342 && is_ayuv_to_rgb_matrix (data)) {
1343 GST_DEBUG ("use fast AYUV -> RGB matrix");
1344 data->matrix_func = video_converter_matrix8_AYUV_ARGB;
1345 } else if (is_no_clip_matrix (data)) {
1346 GST_DEBUG ("use 8bit table");
1347 data->matrix_func = video_converter_matrix8_table;
1348 videoconvert_convert_init_tables (data);
1352 GST_DEBUG ("use 8bit matrix");
1353 data->matrix_func = video_converter_matrix8;
1355 data->orc_p1 = (((guint64) (guint16) data->im[2][0]) << 48) |
1356 (((guint64) (guint16) data->im[1][0]) << 32) |
1357 (((guint64) (guint16) data->im[0][0]) << 16);
1358 data->orc_p2 = (((guint64) (guint16) data->im[2][1]) << 48) |
1359 (((guint64) (guint16) data->im[1][1]) << 32) |
1360 (((guint64) (guint16) data->im[0][1]) << 16);
1361 data->orc_p3 = (((guint64) (guint16) data->im[2][2]) << 48) |
1362 (((guint64) (guint16) data->im[1][2]) << 32) |
1363 (((guint64) (guint16) data->im[0][2]) << 16);
1365 a03 = data->im[0][3] >> SCALE;
1366 a13 = data->im[1][3] >> SCALE;
1367 a23 = data->im[2][3] >> SCALE;
1369 data->orc_p4 = (((guint64) (guint16) a23) << 48) |
1370 (((guint64) (guint16) a13) << 32) | (((guint64) (guint16) a03) << 16);
1373 GST_DEBUG ("use 16bit matrix");
1374 data->matrix_func = video_converter_matrix16;
1379 compute_matrix_to_RGB (GstVideoConverter * convert, MatrixData * data)
1382 gdouble Kr = 0, Kb = 0;
1384 info = &convert->in_info;
1387 const GstVideoFormatInfo *uinfo;
1388 gint offset[4], scale[4];
1390 uinfo = gst_video_format_get_info (convert->unpack_format);
1392 /* bring color components to [0..1.0] range */
1393 gst_video_color_range_offsets (info->colorimetry.range, uinfo, offset,
1396 color_matrix_offset_components (data, -offset[0], -offset[1], -offset[2]);
1397 color_matrix_scale_components (data, 1 / ((float) scale[0]),
1398 1 / ((float) scale[1]), 1 / ((float) scale[2]));
1401 if (!convert->unpack_rgb && !CHECK_MATRIX_NONE (convert)) {
1402 if (CHECK_MATRIX_OUTPUT (convert))
1403 info = &convert->out_info;
1405 /* bring components to R'G'B' space */
1406 if (gst_video_color_matrix_get_Kr_Kb (info->colorimetry.matrix, &Kr, &Kb))
1407 color_matrix_YCbCr_to_RGB (data, Kr, Kb);
1409 color_matrix_debug (data);
1413 compute_matrix_to_YUV (GstVideoConverter * convert, MatrixData * data,
1417 gdouble Kr = 0, Kb = 0;
1419 if (force || (!convert->pack_rgb && !CHECK_MATRIX_NONE (convert))) {
1420 if (CHECK_MATRIX_INPUT (convert))
1421 info = &convert->in_info;
1423 info = &convert->out_info;
1425 /* bring components to YCbCr space */
1426 if (gst_video_color_matrix_get_Kr_Kb (info->colorimetry.matrix, &Kr, &Kb))
1427 color_matrix_RGB_to_YCbCr (data, Kr, Kb);
1430 info = &convert->out_info;
1433 const GstVideoFormatInfo *uinfo;
1434 gint offset[4], scale[4];
1436 uinfo = gst_video_format_get_info (convert->pack_format);
1438 /* bring color components to nominal range */
1439 gst_video_color_range_offsets (info->colorimetry.range, uinfo, offset,
1442 color_matrix_scale_components (data, (float) scale[0], (float) scale[1],
1444 color_matrix_offset_components (data, offset[0], offset[1], offset[2]);
1447 color_matrix_debug (data);
1452 gamma_convert_u8_u16 (GammaData * data, gpointer dest, gpointer src)
1457 guint16 *table = data->gamma_table;
1458 gint width = data->width * 4;
1460 for (i = 0; i < width; i += 4) {
1461 d[i + 0] = (s[i] << 8) | s[i];
1462 d[i + 1] = table[s[i + 1]];
1463 d[i + 2] = table[s[i + 2]];
1464 d[i + 3] = table[s[i + 3]];
1469 gamma_convert_u16_u8 (GammaData * data, gpointer dest, gpointer src)
1474 guint8 *table = data->gamma_table;
1475 gint width = data->width * 4;
1477 for (i = 0; i < width; i += 4) {
1478 d[i + 0] = s[i] >> 8;
1479 d[i + 1] = table[s[i + 1]];
1480 d[i + 2] = table[s[i + 2]];
1481 d[i + 3] = table[s[i + 3]];
1486 gamma_convert_u16_u16 (GammaData * data, gpointer dest, gpointer src)
1491 guint16 *table = data->gamma_table;
1492 gint width = data->width * 4;
1494 for (i = 0; i < width; i += 4) {
1496 d[i + 1] = table[s[i + 1]];
1497 d[i + 2] = table[s[i + 2]];
1498 d[i + 3] = table[s[i + 3]];
1503 setup_gamma_decode (GstVideoConverter * convert)
1505 GstVideoTransferFunction func;
1509 func = convert->in_info.colorimetry.transfer;
1511 convert->gamma_dec.width = convert->current_width;
1512 if (convert->gamma_dec.gamma_table) {
1513 GST_DEBUG ("gamma decode already set up");
1514 } else if (convert->current_bits == 8) {
1515 GST_DEBUG ("gamma decode 8->16: %d", func);
1516 convert->gamma_dec.gamma_func = gamma_convert_u8_u16;
1517 t = convert->gamma_dec.gamma_table = g_malloc (sizeof (guint16) * 256);
1519 for (i = 0; i < 256; i++)
1521 rint (gst_video_transfer_function_decode (func, i / 255.0) * 65535.0);
1523 GST_DEBUG ("gamma decode 16->16: %d", func);
1524 convert->gamma_dec.gamma_func = gamma_convert_u16_u16;
1525 t = convert->gamma_dec.gamma_table = g_malloc (sizeof (guint16) * 65536);
1527 for (i = 0; i < 65536; i++)
1529 rint (gst_video_transfer_function_decode (func,
1530 i / 65535.0) * 65535.0);
1532 convert->current_bits = 16;
1533 convert->current_pstride = 8;
1534 convert->current_format = GST_VIDEO_FORMAT_ARGB64;
1538 setup_gamma_encode (GstVideoConverter * convert, gint target_bits)
1540 GstVideoTransferFunction func;
1543 func = convert->out_info.colorimetry.transfer;
1545 convert->gamma_enc.width = convert->current_width;
1546 if (convert->gamma_enc.gamma_table) {
1547 GST_DEBUG ("gamma encode already set up");
1548 } else if (target_bits == 8) {
1551 GST_DEBUG ("gamma encode 16->8: %d", func);
1552 convert->gamma_enc.gamma_func = gamma_convert_u16_u8;
1553 t = convert->gamma_enc.gamma_table = g_malloc (sizeof (guint8) * 65536);
1555 for (i = 0; i < 65536; i++)
1557 rint (gst_video_transfer_function_encode (func, i / 65535.0) * 255.0);
1561 GST_DEBUG ("gamma encode 16->16: %d", func);
1562 convert->gamma_enc.gamma_func = gamma_convert_u16_u16;
1563 t = convert->gamma_enc.gamma_table = g_malloc (sizeof (guint16) * 65536);
1565 for (i = 0; i < 65536; i++)
1567 rint (gst_video_transfer_function_encode (func,
1568 i / 65535.0) * 65535.0);
1572 static GstLineCache *
1573 chain_convert_to_RGB (GstVideoConverter * convert, GstLineCache * prev,
1578 do_gamma = CHECK_GAMMA_REMAP (convert);
1583 /* Set up conversion matrices if needed, but only for the first thread */
1584 if (idx == 0 && !convert->unpack_rgb) {
1585 color_matrix_set_identity (&convert->to_RGB_matrix);
1586 compute_matrix_to_RGB (convert, &convert->to_RGB_matrix);
1588 /* matrix is in 0..1 range, scale to current bits */
1589 GST_DEBUG ("chain RGB convert");
1590 scale = 1 << convert->current_bits;
1591 color_matrix_scale_components (&convert->to_RGB_matrix,
1592 (float) scale, (float) scale, (float) scale);
1594 prepare_matrix (convert, &convert->to_RGB_matrix);
1596 if (convert->current_bits == 8)
1597 convert->current_format = GST_VIDEO_FORMAT_ARGB;
1599 convert->current_format = GST_VIDEO_FORMAT_ARGB64;
1602 prev = convert->to_RGB_lines[idx] = gst_line_cache_new (prev);
1603 prev->write_input = TRUE;
1604 prev->pass_alloc = FALSE;
1606 prev->stride = convert->current_pstride * convert->current_width;
1607 gst_line_cache_set_need_line_func (prev,
1608 do_convert_to_RGB_lines, idx, convert, NULL);
1610 GST_DEBUG ("chain gamma decode");
1611 setup_gamma_decode (convert);
1616 static GstLineCache *
1617 chain_hscale (GstVideoConverter * convert, GstLineCache * prev, gint idx)
1622 method = GET_OPT_RESAMPLER_METHOD (convert);
1623 taps = GET_OPT_RESAMPLER_TAPS (convert);
1625 convert->h_scaler[idx] =
1626 gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
1627 convert->in_width, convert->out_width, convert->config);
1629 gst_video_scaler_get_coeff (convert->h_scaler[idx], 0, NULL, &taps);
1631 GST_DEBUG ("chain hscale %d->%d, taps %d, method %d",
1632 convert->in_width, convert->out_width, taps, method);
1634 convert->current_width = convert->out_width;
1635 convert->h_scale_format = convert->current_format;
1637 prev = convert->hscale_lines[idx] = gst_line_cache_new (prev);
1638 prev->write_input = FALSE;
1639 prev->pass_alloc = FALSE;
1641 prev->stride = convert->current_pstride * convert->current_width;
1642 gst_line_cache_set_need_line_func (prev, do_hscale_lines, idx, convert, NULL);
1647 static GstLineCache *
1648 chain_vscale (GstVideoConverter * convert, GstLineCache * prev, gint idx)
1651 guint taps, taps_i = 0;
1654 method = GET_OPT_RESAMPLER_METHOD (convert);
1655 taps = GET_OPT_RESAMPLER_TAPS (convert);
1657 if (GST_VIDEO_INFO_IS_INTERLACED (&convert->in_info)
1658 && (GST_VIDEO_INFO_INTERLACE_MODE (&convert->in_info) !=
1659 GST_VIDEO_INTERLACE_MODE_ALTERNATE)) {
1660 convert->v_scaler_i[idx] =
1661 gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_INTERLACED, taps,
1662 convert->in_height, convert->out_height, convert->config);
1664 gst_video_scaler_get_coeff (convert->v_scaler_i[idx], 0, NULL, &taps_i);
1667 convert->v_scaler_p[idx] =
1668 gst_video_scaler_new (method, 0, taps, convert->in_height,
1669 convert->out_height, convert->config);
1670 convert->v_scale_width = convert->current_width;
1671 convert->v_scale_format = convert->current_format;
1672 convert->current_height = convert->out_height;
1674 gst_video_scaler_get_coeff (convert->v_scaler_p[idx], 0, NULL, &taps);
1676 GST_DEBUG ("chain vscale %d->%d, taps %d, method %d, backlog %d",
1677 convert->in_height, convert->out_height, taps, method, backlog);
1679 prev->backlog = backlog;
1680 prev = convert->vscale_lines[idx] = gst_line_cache_new (prev);
1681 prev->pass_alloc = (taps == 1);
1682 prev->write_input = FALSE;
1683 prev->n_lines = MAX (taps_i, taps);
1684 prev->stride = convert->current_pstride * convert->current_width;
1685 gst_line_cache_set_need_line_func (prev, do_vscale_lines, idx, convert, NULL);
1690 static GstLineCache *
1691 chain_scale (GstVideoConverter * convert, GstLineCache * prev, gboolean force,
1694 gint s0, s1, s2, s3;
1696 s0 = convert->current_width * convert->current_height;
1697 s3 = convert->out_width * convert->out_height;
1699 GST_DEBUG ("in pixels %d <> out pixels %d", s0, s3);
1701 if (s3 <= s0 || force) {
1702 /* we are making the image smaller or are forced to resample */
1703 s1 = convert->out_width * convert->current_height;
1704 s2 = convert->current_width * convert->out_height;
1706 GST_DEBUG ("%d <> %d", s1, s2);
1709 /* h scaling first produces less pixels */
1710 if (convert->current_width != convert->out_width)
1711 prev = chain_hscale (convert, prev, idx);
1712 if (convert->current_height != convert->out_height)
1713 prev = chain_vscale (convert, prev, idx);
1715 /* v scaling first produces less pixels */
1716 if (convert->current_height != convert->out_height)
1717 prev = chain_vscale (convert, prev, idx);
1718 if (convert->current_width != convert->out_width)
1719 prev = chain_hscale (convert, prev, idx);
1725 static GstLineCache *
1726 chain_convert (GstVideoConverter * convert, GstLineCache * prev, gint idx)
1728 gboolean do_gamma, do_conversion, pass_alloc = FALSE;
1729 gboolean same_matrix, same_primaries, same_bits;
1732 same_bits = convert->unpack_bits == convert->pack_bits;
1733 if (CHECK_MATRIX_NONE (convert)) {
1737 convert->in_info.colorimetry.matrix ==
1738 convert->out_info.colorimetry.matrix;
1741 if (CHECK_PRIMARIES_NONE (convert)) {
1742 same_primaries = TRUE;
1745 convert->in_info.colorimetry.primaries ==
1746 convert->out_info.colorimetry.primaries;
1749 GST_DEBUG ("matrix %d -> %d (%d)", convert->in_info.colorimetry.matrix,
1750 convert->out_info.colorimetry.matrix, same_matrix);
1751 GST_DEBUG ("bits %d -> %d (%d)", convert->unpack_bits, convert->pack_bits,
1753 GST_DEBUG ("primaries %d -> %d (%d)", convert->in_info.colorimetry.primaries,
1754 convert->out_info.colorimetry.primaries, same_primaries);
1756 color_matrix_set_identity (&convert->convert_matrix);
1758 if (!same_primaries) {
1759 const GstVideoColorPrimariesInfo *pi;
1761 /* Convert from RGB_input to RGB_output via XYZ
1762 * res = XYZ_to_RGB_output ( RGB_to_XYZ_input ( input ) )
1763 * or in matricial form:
1764 * RGB_output = XYZ_to_RGB_output_matrix * RGB_TO_XYZ_input_matrix * RGB_input
1766 * The RGB_input is the pre-existing convert_matrix
1767 * The convert_matrix will become the RGB_output
1770 /* Convert input RGB to XYZ */
1771 pi = gst_video_color_primaries_get_info (convert->in_info.colorimetry.
1773 /* Get the RGB_TO_XYZ_input_matrix */
1774 color_matrix_RGB_to_XYZ (&p1, pi->Rx, pi->Ry, pi->Gx, pi->Gy, pi->Bx,
1775 pi->By, pi->Wx, pi->Wy);
1776 GST_DEBUG ("to XYZ matrix");
1777 color_matrix_debug (&p1);
1778 GST_DEBUG ("current matrix");
1779 /* convert_matrix = RGB_TO_XYZ_input_matrix * input_RGB */
1780 color_matrix_multiply (&convert->convert_matrix, &convert->convert_matrix,
1782 color_matrix_debug (&convert->convert_matrix);
1784 /* Convert XYZ to output RGB */
1785 pi = gst_video_color_primaries_get_info (convert->out_info.colorimetry.
1787 /* Calculate the XYZ_to_RGB_output_matrix
1788 * * Get the RGB_TO_XYZ_output_matrix
1792 color_matrix_RGB_to_XYZ (&p2, pi->Rx, pi->Ry, pi->Gx, pi->Gy, pi->Bx,
1793 pi->By, pi->Wx, pi->Wy);
1794 color_matrix_invert (&p2, &p2);
1795 GST_DEBUG ("to RGB matrix");
1796 color_matrix_debug (&p2);
1798 * convert_matrix = XYZ_to_RGB_output_matrix * RGB_TO_XYZ_input_matrix * RGB_input
1799 * = XYZ_to_RGB_output_matrix * convert_matrix
1800 * = p2 * convert_matrix
1802 color_matrix_multiply (&convert->convert_matrix, &p2,
1803 &convert->convert_matrix);
1804 GST_DEBUG ("current matrix");
1805 color_matrix_debug (&convert->convert_matrix);
1808 do_gamma = CHECK_GAMMA_REMAP (convert);
1811 convert->in_bits = convert->unpack_bits;
1812 convert->out_bits = convert->pack_bits;
1814 if (!same_bits || !same_matrix || !same_primaries) {
1815 /* no gamma, combine all conversions into 1 */
1816 if (convert->in_bits < convert->out_bits) {
1817 gint scale = 1 << (convert->out_bits - convert->in_bits);
1818 color_matrix_scale_components (&convert->convert_matrix,
1819 1 / (float) scale, 1 / (float) scale, 1 / (float) scale);
1821 GST_DEBUG ("to RGB matrix");
1822 compute_matrix_to_RGB (convert, &convert->convert_matrix);
1823 GST_DEBUG ("current matrix");
1824 color_matrix_debug (&convert->convert_matrix);
1826 GST_DEBUG ("to YUV matrix");
1827 compute_matrix_to_YUV (convert, &convert->convert_matrix, FALSE);
1828 GST_DEBUG ("current matrix");
1829 color_matrix_debug (&convert->convert_matrix);
1830 if (convert->in_bits > convert->out_bits) {
1831 gint scale = 1 << (convert->in_bits - convert->out_bits);
1832 color_matrix_scale_components (&convert->convert_matrix,
1833 (float) scale, (float) scale, (float) scale);
1835 convert->current_bits = MAX (convert->in_bits, convert->out_bits);
1837 do_conversion = TRUE;
1838 if (!same_matrix || !same_primaries) {
1840 prepare_matrix (convert, &convert->convert_matrix);
1842 if (convert->in_bits == convert->out_bits)
1845 do_conversion = FALSE;
1847 convert->current_bits = convert->pack_bits;
1848 convert->current_format = convert->pack_format;
1849 convert->current_pstride = convert->current_bits >> 1;
1851 /* we did gamma, just do colorspace conversion if needed */
1852 if (same_primaries) {
1853 do_conversion = FALSE;
1856 prepare_matrix (convert, &convert->convert_matrix);
1857 convert->in_bits = convert->out_bits = 16;
1859 do_conversion = TRUE;
1863 if (do_conversion) {
1864 GST_DEBUG ("chain conversion");
1865 prev = convert->convert_lines[idx] = gst_line_cache_new (prev);
1866 prev->write_input = TRUE;
1867 prev->pass_alloc = pass_alloc;
1869 prev->stride = convert->current_pstride * convert->current_width;
1870 gst_line_cache_set_need_line_func (prev,
1871 do_convert_lines, idx, convert, NULL);
1877 convert_set_alpha_u8 (GstVideoConverter * convert, gpointer pixels, gint width)
1880 guint8 alpha = MIN (convert->alpha_value, 255);
1883 for (i = 0; i < width; i++)
1888 convert_set_alpha_u16 (GstVideoConverter * convert, gpointer pixels, gint width)
1890 guint16 *p = pixels;
1894 alpha = MIN (convert->alpha_value, 255);
1895 alpha |= alpha << 8;
1897 for (i = 0; i < width; i++)
1902 convert_mult_alpha_u8 (GstVideoConverter * convert, gpointer pixels, gint width)
1905 guint alpha = convert->alpha_value;
1908 for (i = 0; i < width; i++) {
1909 gint a = (p[i * 4] * alpha) / 255;
1910 p[i * 4] = CLAMP (a, 0, 255);
1915 convert_mult_alpha_u16 (GstVideoConverter * convert, gpointer pixels,
1918 guint16 *p = pixels;
1919 guint alpha = convert->alpha_value;
1922 for (i = 0; i < width; i++) {
1923 gint a = (p[i * 4] * alpha) / 255;
1924 p[i * 4] = CLAMP (a, 0, 65535);
1928 static GstLineCache *
1929 chain_alpha (GstVideoConverter * convert, GstLineCache * prev, gint idx)
1931 switch (convert->alpha_mode) {
1932 case ALPHA_MODE_NONE:
1933 case ALPHA_MODE_COPY:
1936 case ALPHA_MODE_SET:
1937 if (convert->current_bits == 8)
1938 convert->alpha_func = convert_set_alpha_u8;
1940 convert->alpha_func = convert_set_alpha_u16;
1942 case ALPHA_MODE_MULT:
1943 if (convert->current_bits == 8)
1944 convert->alpha_func = convert_mult_alpha_u8;
1946 convert->alpha_func = convert_mult_alpha_u16;
1950 GST_DEBUG ("chain alpha mode %d", convert->alpha_mode);
1951 prev = convert->alpha_lines[idx] = gst_line_cache_new (prev);
1952 prev->write_input = TRUE;
1953 prev->pass_alloc = TRUE;
1955 prev->stride = convert->current_pstride * convert->current_width;
1956 gst_line_cache_set_need_line_func (prev, do_alpha_lines, idx, convert, NULL);
1961 static GstLineCache *
1962 chain_convert_to_YUV (GstVideoConverter * convert, GstLineCache * prev,
1967 do_gamma = CHECK_GAMMA_REMAP (convert);
1972 GST_DEBUG ("chain gamma encode");
1973 setup_gamma_encode (convert, convert->pack_bits);
1975 convert->current_bits = convert->pack_bits;
1976 convert->current_pstride = convert->current_bits >> 1;
1978 if (idx == 0 && !convert->pack_rgb) {
1979 color_matrix_set_identity (&convert->to_YUV_matrix);
1980 compute_matrix_to_YUV (convert, &convert->to_YUV_matrix, FALSE);
1982 /* matrix is in 0..255 range, scale to pack bits */
1983 GST_DEBUG ("chain YUV convert");
1984 scale = 1 << convert->pack_bits;
1985 color_matrix_scale_components (&convert->to_YUV_matrix,
1986 1 / (float) scale, 1 / (float) scale, 1 / (float) scale);
1987 prepare_matrix (convert, &convert->to_YUV_matrix);
1989 convert->current_format = convert->pack_format;
1991 prev = convert->to_YUV_lines[idx] = gst_line_cache_new (prev);
1992 prev->write_input = FALSE;
1993 prev->pass_alloc = FALSE;
1995 prev->stride = convert->current_pstride * convert->current_width;
1996 gst_line_cache_set_need_line_func (prev,
1997 do_convert_to_YUV_lines, idx, convert, NULL);
2003 static GstLineCache *
2004 chain_downsample (GstVideoConverter * convert, GstLineCache * prev, gint idx)
2006 if (convert->downsample_p[idx] || convert->downsample_i[idx]) {
2007 GST_DEBUG ("chain downsample");
2008 prev = convert->downsample_lines[idx] = gst_line_cache_new (prev);
2009 prev->write_input = TRUE;
2010 prev->pass_alloc = TRUE;
2011 /* XXX: why this hardcoded value? */
2013 prev->stride = convert->current_pstride * convert->current_width;
2014 gst_line_cache_set_need_line_func (prev,
2015 do_downsample_lines, idx, convert, NULL);
2020 static GstLineCache *
2021 chain_dither (GstVideoConverter * convert, GstLineCache * prev, gint idx)
2024 gboolean do_dither = FALSE;
2025 GstVideoDitherFlags flags = 0;
2026 GstVideoDitherMethod method;
2027 guint quant[4], target_quant;
2029 method = GET_OPT_DITHER_METHOD (convert);
2030 if (method == GST_VIDEO_DITHER_NONE)
2033 target_quant = GET_OPT_DITHER_QUANTIZATION (convert);
2034 GST_DEBUG ("method %d, target-quantization %d", method, target_quant);
2036 if (convert->pack_pal) {
2043 for (i = 0; i < GST_VIDEO_MAX_COMPONENTS; i++) {
2046 depth = convert->out_info.finfo->depth[i];
2053 if (convert->current_bits >= depth) {
2054 quant[i] = 1 << (convert->current_bits - depth);
2055 if (target_quant > quant[i]) {
2056 flags |= GST_VIDEO_DITHER_FLAG_QUANTIZE;
2057 quant[i] = target_quant;
2068 GST_DEBUG ("chain dither");
2070 convert->dither[idx] = gst_video_dither_new (method,
2071 flags, convert->pack_format, quant, convert->current_width);
2073 prev = convert->dither_lines[idx] = gst_line_cache_new (prev);
2074 prev->write_input = TRUE;
2075 prev->pass_alloc = TRUE;
2077 prev->stride = convert->current_pstride * convert->current_width;
2078 gst_line_cache_set_need_line_func (prev, do_dither_lines, idx, convert,
2084 static GstLineCache *
2085 chain_pack (GstVideoConverter * convert, GstLineCache * prev, gint idx)
2087 convert->pack_nlines = convert->out_info.finfo->pack_lines;
2088 convert->pack_pstride = convert->current_pstride;
2089 convert->identity_pack =
2090 (convert->out_info.finfo->format ==
2091 convert->out_info.finfo->unpack_format);
2092 GST_DEBUG ("chain pack line format %s, pstride %d, identity_pack %d (%d %d)",
2093 gst_video_format_to_string (convert->current_format),
2094 convert->current_pstride, convert->identity_pack,
2095 convert->out_info.finfo->format, convert->out_info.finfo->unpack_format);
2101 setup_allocators (GstVideoConverter * convert)
2103 GstLineCache *cache, *prev;
2104 GstLineCacheAllocLineFunc alloc_line;
2105 gboolean alloc_writable;
2107 GDestroyNotify notify;
2111 width = MAX (convert->in_maxwidth, convert->out_maxwidth);
2112 width += convert->out_x;
2114 for (i = 0; i < convert->conversion_runner->n_threads; i++) {
2115 /* start with using dest lines if we can directly write into it */
2116 if (convert->identity_pack) {
2117 alloc_line = get_dest_line;
2118 alloc_writable = TRUE;
2119 user_data = convert;
2123 converter_alloc_new (sizeof (guint16) * width * 4, 4 + BACKLOG,
2125 setup_border_alloc (convert, user_data);
2126 notify = (GDestroyNotify) converter_alloc_free;
2127 alloc_line = get_border_temp_line;
2128 /* when we add a border, we need to write */
2129 alloc_writable = convert->borderline != NULL;
2132 /* First step, try to calculate how many temp lines we need. Go backwards,
2133 * keep track of the maximum number of lines we need for each intermediate
2135 for (prev = cache = convert->pack_lines[i]; cache; cache = cache->prev) {
2136 GST_DEBUG ("looking at cache %p, %d lines, %d backlog", cache,
2137 cache->n_lines, cache->backlog);
2138 prev->n_lines = MAX (prev->n_lines, cache->n_lines);
2139 if (!cache->pass_alloc) {
2140 GST_DEBUG ("cache %p, needs %d lines", prev, prev->n_lines);
2145 /* now walk backwards, we try to write into the dest lines directly
2146 * and keep track if the source needs to be writable */
2147 for (cache = convert->pack_lines[i]; cache; cache = cache->prev) {
2148 gst_line_cache_set_alloc_line_func (cache, alloc_line, user_data, notify);
2149 cache->alloc_writable = alloc_writable;
2151 /* make sure only one cache frees the allocator */
2154 if (!cache->pass_alloc) {
2155 /* can't pass allocator, make new temp line allocator */
2157 converter_alloc_new (sizeof (guint16) * width * 4,
2158 cache->n_lines + cache->backlog, convert, NULL);
2159 notify = (GDestroyNotify) converter_alloc_free;
2160 alloc_line = get_temp_line;
2161 alloc_writable = FALSE;
2163 /* if someone writes to the input, we need a writable line from the
2165 if (cache->write_input)
2166 alloc_writable = TRUE;
2168 /* free leftover allocator */
2175 setup_borderline (GstVideoConverter * convert)
2179 width = MAX (convert->in_maxwidth, convert->out_maxwidth);
2180 width += convert->out_x;
2182 if (convert->fill_border && (convert->out_height < convert->out_maxheight ||
2183 convert->out_width < convert->out_maxwidth)) {
2186 const GstVideoFormatInfo *out_finfo;
2187 gpointer planes[GST_VIDEO_MAX_PLANES];
2188 gint strides[GST_VIDEO_MAX_PLANES];
2190 convert->borderline = g_malloc0 (sizeof (guint16) * width * 4);
2192 out_finfo = convert->out_info.finfo;
2194 if (GST_VIDEO_INFO_IS_YUV (&convert->out_info)) {
2199 /* Get Color matrix. */
2200 color_matrix_set_identity (&cm);
2201 compute_matrix_to_YUV (convert, &cm, TRUE);
2202 color_matrix_convert (&cm);
2204 border_val = GINT32_FROM_BE (convert->border_argb);
2206 b = (0xFF000000 & border_val) >> 24;
2207 g = (0x00FF0000 & border_val) >> 16;
2208 r = (0x0000FF00 & border_val) >> 8;
2209 a = (0x000000FF & border_val);
2211 y = 16 + ((r * cm.im[0][0] + g * cm.im[0][1] + b * cm.im[0][2]) >> 8);
2212 u = 128 + ((r * cm.im[1][0] + g * cm.im[1][1] + b * cm.im[1][2]) >> 8);
2213 v = 128 + ((r * cm.im[2][0] + g * cm.im[2][1] + b * cm.im[2][2]) >> 8);
2215 a = CLAMP (a, 0, 255);
2216 y = CLAMP (y, 0, 255);
2217 u = CLAMP (u, 0, 255);
2218 v = CLAMP (v, 0, 255);
2220 border_val = a | (y << 8) | (u << 16) | ((guint32) v << 24);
2222 border_val = GINT32_FROM_BE (convert->border_argb);
2224 if (convert->pack_bits == 8)
2225 video_orc_splat_u32 (convert->borderline, border_val, width);
2227 video_orc_splat2_u64 (convert->borderline, border_val, width);
2229 /* convert pixels */
2230 for (i = 0; i < out_finfo->n_planes; i++) {
2231 planes[i] = &convert->borders[i];
2232 strides[i] = sizeof (guint64);
2235 if (out_finfo->n_planes == 1) {
2236 /* for packed formats, convert based on subsampling so that we
2237 * get a complete group of pixels */
2238 for (i = 0; i < out_finfo->n_components; i++) {
2239 w_sub = MAX (w_sub, out_finfo->w_sub[i]);
2242 out_finfo->pack_func (out_finfo, GST_VIDEO_PACK_FLAG_NONE,
2243 convert->borderline, 0, planes, strides,
2244 GST_VIDEO_CHROMA_SITE_UNKNOWN, 0, 1 << w_sub);
2246 convert->borderline = NULL;
2251 convert_get_alpha_mode (GstVideoConverter * convert)
2253 gboolean in_alpha, out_alpha;
2255 in_alpha = GST_VIDEO_INFO_HAS_ALPHA (&convert->in_info);
2256 out_alpha = GST_VIDEO_INFO_HAS_ALPHA (&convert->out_info);
2258 /* no output alpha, do nothing */
2260 return ALPHA_MODE_NONE;
2264 if (CHECK_ALPHA_COPY (convert))
2265 return ALPHA_MODE_COPY;
2267 if (CHECK_ALPHA_MULT (convert)) {
2268 if (GET_OPT_ALPHA_VALUE (convert) == 1.0)
2269 return ALPHA_MODE_COPY;
2271 return ALPHA_MODE_MULT;
2274 /* nothing special, this is what unpack etc does automatically */
2275 if (GET_OPT_ALPHA_VALUE (convert) == 1.0)
2276 return ALPHA_MODE_NONE;
2278 /* everything else becomes SET */
2279 return ALPHA_MODE_SET;
2283 * gst_video_converter_new_with_pool: (skip)
2284 * @in_info: a #GstVideoInfo
2285 * @out_info: a #GstVideoInfo
2286 * @config: (transfer full): a #GstStructure with configuration options
2287 * @pool: (nullable): a #GstTaskPool to spawn threads from
2289 * Create a new converter object to convert between @in_info and @out_info
2292 * The optional @pool can be used to spawn threads, this is useful when
2293 * creating new converters rapidly, for example when updating cropping.
2295 * Returns: a #GstVideoConverter or %NULL if conversion is not possible.
2300 gst_video_converter_new_with_pool (const GstVideoInfo * in_info,
2301 const GstVideoInfo * out_info, GstStructure * config, GstTaskPool * pool)
2303 GstVideoConverter *convert;
2305 const GstVideoFormatInfo *fin, *fout, *finfo;
2306 gdouble alpha_value;
2308 gboolean async_tasks;
2310 g_return_val_if_fail (in_info != NULL, NULL);
2311 g_return_val_if_fail (out_info != NULL, NULL);
2312 /* we won't ever do framerate conversion */
2313 g_return_val_if_fail (in_info->fps_n == out_info->fps_n, NULL);
2314 g_return_val_if_fail (in_info->fps_d == out_info->fps_d, NULL);
2315 /* we won't ever do deinterlace */
2316 g_return_val_if_fail (in_info->interlace_mode == out_info->interlace_mode,
2319 convert = g_slice_new0 (GstVideoConverter);
2321 fin = in_info->finfo;
2322 fout = out_info->finfo;
2324 convert->in_info = *in_info;
2325 convert->out_info = *out_info;
2327 /* default config */
2328 convert->config = gst_structure_new_empty ("GstVideoConverter");
2330 gst_video_converter_set_config (convert, config);
2332 convert->in_maxwidth = GST_VIDEO_INFO_WIDTH (in_info);
2333 convert->in_maxheight = GST_VIDEO_INFO_FIELD_HEIGHT (in_info);
2334 convert->out_maxwidth = GST_VIDEO_INFO_WIDTH (out_info);
2335 convert->out_maxheight = GST_VIDEO_INFO_FIELD_HEIGHT (out_info);
2337 convert->in_x = get_opt_int (convert, GST_VIDEO_CONVERTER_OPT_SRC_X, 0);
2338 convert->in_y = get_opt_int (convert, GST_VIDEO_CONVERTER_OPT_SRC_Y, 0);
2339 convert->in_x &= ~((1 << fin->w_sub[1]) - 1);
2340 convert->in_y &= ~((1 << fin->h_sub[1]) - 1);
2342 convert->in_width = get_opt_int (convert,
2343 GST_VIDEO_CONVERTER_OPT_SRC_WIDTH, convert->in_maxwidth - convert->in_x);
2344 convert->in_height = get_opt_int (convert,
2345 GST_VIDEO_CONVERTER_OPT_SRC_HEIGHT,
2346 convert->in_maxheight - convert->in_y);
2349 MIN (convert->in_width, convert->in_maxwidth - convert->in_x);
2350 if (convert->in_width + convert->in_x < 0 ||
2351 convert->in_width + convert->in_x > convert->in_maxwidth) {
2352 convert->in_width = 0;
2355 convert->in_height =
2356 MIN (convert->in_height, convert->in_maxheight - convert->in_y);
2357 if (convert->in_height + convert->in_y < 0 ||
2358 convert->in_height + convert->in_y > convert->in_maxheight) {
2359 convert->in_height = 0;
2362 convert->out_x = get_opt_int (convert, GST_VIDEO_CONVERTER_OPT_DEST_X, 0);
2363 convert->out_y = get_opt_int (convert, GST_VIDEO_CONVERTER_OPT_DEST_Y, 0);
2364 convert->out_x &= ~((1 << fout->w_sub[1]) - 1);
2365 convert->out_y &= ~((1 << fout->h_sub[1]) - 1);
2367 convert->out_width = get_opt_int (convert,
2368 GST_VIDEO_CONVERTER_OPT_DEST_WIDTH,
2369 convert->out_maxwidth - convert->out_x);
2370 convert->out_height =
2371 get_opt_int (convert, GST_VIDEO_CONVERTER_OPT_DEST_HEIGHT,
2372 convert->out_maxheight - convert->out_y);
2374 if (convert->out_width > convert->out_maxwidth - convert->out_x)
2375 convert->out_width = convert->out_maxwidth - convert->out_x;
2376 convert->out_width = CLAMP (convert->out_width, 0, convert->out_maxwidth);
2378 /* Check if completely outside the framebuffer */
2379 if (convert->out_width + convert->out_x < 0 ||
2380 convert->out_width + convert->out_x > convert->out_maxwidth) {
2381 convert->out_width = 0;
2384 /* Same for height */
2385 if (convert->out_height > convert->out_maxheight - convert->out_y)
2386 convert->out_height = convert->out_maxheight - convert->out_y;
2387 convert->out_height = CLAMP (convert->out_height, 0, convert->out_maxheight);
2389 if (convert->out_height + convert->out_y < 0 ||
2390 convert->out_height + convert->out_y > convert->out_maxheight) {
2391 convert->out_height = 0;
2394 convert->fill_border = GET_OPT_FILL_BORDER (convert);
2395 convert->border_argb = get_opt_uint (convert,
2396 GST_VIDEO_CONVERTER_OPT_BORDER_ARGB, DEFAULT_OPT_BORDER_ARGB);
2398 alpha_value = GET_OPT_ALPHA_VALUE (convert);
2399 convert->alpha_value = 255 * alpha_value;
2400 convert->alpha_mode = convert_get_alpha_mode (convert);
2402 convert->unpack_format = in_info->finfo->unpack_format;
2403 finfo = gst_video_format_get_info (convert->unpack_format);
2404 convert->unpack_bits = GST_VIDEO_FORMAT_INFO_DEPTH (finfo, 0);
2405 convert->unpack_rgb = GST_VIDEO_FORMAT_INFO_IS_RGB (finfo);
2406 if (convert->unpack_rgb
2407 && in_info->colorimetry.matrix != GST_VIDEO_COLOR_MATRIX_RGB) {
2408 /* force identity matrix for RGB input */
2409 GST_WARNING ("invalid matrix %d for input RGB format, using RGB",
2410 in_info->colorimetry.matrix);
2411 convert->in_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB;
2414 convert->pack_format = out_info->finfo->unpack_format;
2415 finfo = gst_video_format_get_info (convert->pack_format);
2416 convert->pack_bits = GST_VIDEO_FORMAT_INFO_DEPTH (finfo, 0);
2417 convert->pack_rgb = GST_VIDEO_FORMAT_INFO_IS_RGB (finfo);
2419 gst_video_format_get_palette (GST_VIDEO_INFO_FORMAT (out_info),
2420 &convert->pack_palsize);
2421 if (convert->pack_rgb
2422 && out_info->colorimetry.matrix != GST_VIDEO_COLOR_MATRIX_RGB) {
2423 /* force identity matrix for RGB output */
2424 GST_WARNING ("invalid matrix %d for output RGB format, using RGB",
2425 out_info->colorimetry.matrix);
2426 convert->out_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB;
2429 n_threads = get_opt_uint (convert, GST_VIDEO_CONVERTER_OPT_THREADS, 1);
2430 if (n_threads == 0 || n_threads > g_get_num_processors ())
2431 n_threads = g_get_num_processors ();
2432 /* Magic number of 200 lines */
2433 if (MAX (convert->out_height, convert->in_height) / n_threads < 200)
2434 n_threads = (MAX (convert->out_height, convert->in_height) + 199) / 200;
2438 async_tasks = GET_OPT_ASYNC_TASKS (convert);
2439 convert->conversion_runner =
2440 gst_parallelized_task_runner_new (n_threads, pool, async_tasks);
2442 if (video_converter_lookup_fastpath (convert))
2445 if (in_info->finfo->unpack_func == NULL)
2446 goto no_unpack_func;
2448 if (out_info->finfo->pack_func == NULL)
2451 convert->convert = video_converter_generic;
2453 convert->upsample_p = g_new0 (GstVideoChromaResample *, n_threads);
2454 convert->upsample_i = g_new0 (GstVideoChromaResample *, n_threads);
2455 convert->downsample_p = g_new0 (GstVideoChromaResample *, n_threads);
2456 convert->downsample_i = g_new0 (GstVideoChromaResample *, n_threads);
2457 convert->v_scaler_p = g_new0 (GstVideoScaler *, n_threads);
2458 convert->v_scaler_i = g_new0 (GstVideoScaler *, n_threads);
2459 convert->h_scaler = g_new0 (GstVideoScaler *, n_threads);
2460 convert->unpack_lines = g_new0 (GstLineCache *, n_threads);
2461 convert->pack_lines = g_new0 (GstLineCache *, n_threads);
2462 convert->upsample_lines = g_new0 (GstLineCache *, n_threads);
2463 convert->to_RGB_lines = g_new0 (GstLineCache *, n_threads);
2464 convert->hscale_lines = g_new0 (GstLineCache *, n_threads);
2465 convert->vscale_lines = g_new0 (GstLineCache *, n_threads);
2466 convert->convert_lines = g_new0 (GstLineCache *, n_threads);
2467 convert->alpha_lines = g_new0 (GstLineCache *, n_threads);
2468 convert->to_YUV_lines = g_new0 (GstLineCache *, n_threads);
2469 convert->downsample_lines = g_new0 (GstLineCache *, n_threads);
2470 convert->dither_lines = g_new0 (GstLineCache *, n_threads);
2471 convert->dither = g_new0 (GstVideoDither *, n_threads);
2473 if (convert->in_width > 0 && convert->out_width > 0 && convert->in_height > 0
2474 && convert->out_height > 0) {
2475 for (i = 0; i < n_threads; i++) {
2476 convert->current_format = GST_VIDEO_INFO_FORMAT (in_info);
2477 convert->current_width = convert->in_width;
2478 convert->current_height = convert->in_height;
2481 prev = chain_unpack_line (convert, i);
2482 /* upsample chroma */
2483 prev = chain_upsample (convert, prev, i);
2484 /* convert to gamma decoded RGB */
2485 prev = chain_convert_to_RGB (convert, prev, i);
2486 /* do all downscaling */
2487 prev = chain_scale (convert, prev, FALSE, i);
2488 /* do conversion between color spaces */
2489 prev = chain_convert (convert, prev, i);
2490 /* do alpha channels */
2491 prev = chain_alpha (convert, prev, i);
2492 /* do all remaining (up)scaling */
2493 prev = chain_scale (convert, prev, TRUE, i);
2494 /* convert to gamma encoded Y'Cb'Cr' */
2495 prev = chain_convert_to_YUV (convert, prev, i);
2496 /* downsample chroma */
2497 prev = chain_downsample (convert, prev, i);
2499 prev = chain_dither (convert, prev, i);
2500 /* pack into final format */
2501 convert->pack_lines[i] = chain_pack (convert, prev, i);
2505 setup_borderline (convert);
2506 /* now figure out allocators */
2507 setup_allocators (convert);
2515 GST_ERROR ("no unpack_func for format %s",
2516 gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info)));
2517 gst_video_converter_free (convert);
2522 GST_ERROR ("no pack_func for format %s",
2523 gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (out_info)));
2524 gst_video_converter_free (convert);
2530 * gst_video_converter_new: (skip)
2531 * @in_info: a #GstVideoInfo
2532 * @out_info: a #GstVideoInfo
2533 * @config: (transfer full): a #GstStructure with configuration options
2535 * Create a new converter object to convert between @in_info and @out_info
2538 * Returns: a #GstVideoConverter or %NULL if conversion is not possible.
2543 gst_video_converter_new (const GstVideoInfo * in_info,
2544 const GstVideoInfo * out_info, GstStructure * config)
2546 return gst_video_converter_new_with_pool (in_info, out_info, config, NULL);
2550 clear_matrix_data (MatrixData * data)
2558 * gst_video_converter_free:
2559 * @convert: a #GstVideoConverter
2566 gst_video_converter_free (GstVideoConverter * convert)
2570 g_return_if_fail (convert != NULL);
2572 for (i = 0; i < convert->conversion_runner->n_threads; i++) {
2573 if (convert->upsample_p && convert->upsample_p[i])
2574 gst_video_chroma_resample_free (convert->upsample_p[i]);
2575 if (convert->upsample_i && convert->upsample_i[i])
2576 gst_video_chroma_resample_free (convert->upsample_i[i]);
2577 if (convert->downsample_p && convert->downsample_p[i])
2578 gst_video_chroma_resample_free (convert->downsample_p[i]);
2579 if (convert->downsample_i && convert->downsample_i[i])
2580 gst_video_chroma_resample_free (convert->downsample_i[i]);
2581 if (convert->v_scaler_p && convert->v_scaler_p[i])
2582 gst_video_scaler_free (convert->v_scaler_p[i]);
2583 if (convert->v_scaler_i && convert->v_scaler_i[i])
2584 gst_video_scaler_free (convert->v_scaler_i[i]);
2585 if (convert->h_scaler && convert->h_scaler[i])
2586 gst_video_scaler_free (convert->h_scaler[i]);
2587 if (convert->unpack_lines && convert->unpack_lines[i])
2588 gst_line_cache_free (convert->unpack_lines[i]);
2589 if (convert->upsample_lines && convert->upsample_lines[i])
2590 gst_line_cache_free (convert->upsample_lines[i]);
2591 if (convert->to_RGB_lines && convert->to_RGB_lines[i])
2592 gst_line_cache_free (convert->to_RGB_lines[i]);
2593 if (convert->hscale_lines && convert->hscale_lines[i])
2594 gst_line_cache_free (convert->hscale_lines[i]);
2595 if (convert->vscale_lines && convert->vscale_lines[i])
2596 gst_line_cache_free (convert->vscale_lines[i]);
2597 if (convert->convert_lines && convert->convert_lines[i])
2598 gst_line_cache_free (convert->convert_lines[i]);
2599 if (convert->alpha_lines && convert->alpha_lines[i])
2600 gst_line_cache_free (convert->alpha_lines[i]);
2601 if (convert->to_YUV_lines && convert->to_YUV_lines[i])
2602 gst_line_cache_free (convert->to_YUV_lines[i]);
2603 if (convert->downsample_lines && convert->downsample_lines[i])
2604 gst_line_cache_free (convert->downsample_lines[i]);
2605 if (convert->dither_lines && convert->dither_lines[i])
2606 gst_line_cache_free (convert->dither_lines[i]);
2607 if (convert->dither && convert->dither[i])
2608 gst_video_dither_free (convert->dither[i]);
2610 g_free (convert->upsample_p);
2611 g_free (convert->upsample_i);
2612 g_free (convert->downsample_p);
2613 g_free (convert->downsample_i);
2614 g_free (convert->v_scaler_p);
2615 g_free (convert->v_scaler_i);
2616 g_free (convert->h_scaler);
2617 g_free (convert->unpack_lines);
2618 g_free (convert->pack_lines);
2619 g_free (convert->upsample_lines);
2620 g_free (convert->to_RGB_lines);
2621 g_free (convert->hscale_lines);
2622 g_free (convert->vscale_lines);
2623 g_free (convert->convert_lines);
2624 g_free (convert->alpha_lines);
2625 g_free (convert->to_YUV_lines);
2626 g_free (convert->downsample_lines);
2627 g_free (convert->dither_lines);
2628 g_free (convert->dither);
2630 g_free (convert->gamma_dec.gamma_table);
2631 g_free (convert->gamma_enc.gamma_table);
2633 if (convert->tmpline) {
2634 for (i = 0; i < convert->conversion_runner->n_threads; i++)
2635 g_free (convert->tmpline[i]);
2636 g_free (convert->tmpline);
2639 g_free (convert->borderline);
2641 if (convert->config)
2642 gst_structure_free (convert->config);
2644 for (i = 0; i < 4; i++) {
2645 for (j = 0; j < convert->conversion_runner->n_threads; j++) {
2646 if (convert->fv_scaler[i].scaler)
2647 gst_video_scaler_free (convert->fv_scaler[i].scaler[j]);
2648 if (convert->fh_scaler[i].scaler)
2649 gst_video_scaler_free (convert->fh_scaler[i].scaler[j]);
2651 g_free (convert->fv_scaler[i].scaler);
2652 g_free (convert->fh_scaler[i].scaler);
2655 if (convert->conversion_runner)
2656 gst_parallelized_task_runner_free (convert->conversion_runner);
2658 clear_matrix_data (&convert->to_RGB_matrix);
2659 clear_matrix_data (&convert->convert_matrix);
2660 clear_matrix_data (&convert->to_YUV_matrix);
2662 for (i = 0; i < 4; i++) {
2663 g_free (convert->tasks[i]);
2664 g_free (convert->tasks_p[i]);
2667 g_slice_free (GstVideoConverter, convert);
2671 copy_config (GQuark field_id, const GValue * value, gpointer user_data)
2673 GstVideoConverter *convert = user_data;
2675 gst_structure_id_set_value (convert->config, field_id, value);
2681 * gst_video_converter_set_config:
2682 * @convert: a #GstVideoConverter
2683 * @config: (transfer full): a #GstStructure
2685 * Set @config as extra configuration for @convert.
2687 * If the parameters in @config can not be set exactly, this function returns
2688 * %FALSE and will try to update as much state as possible. The new state can
2689 * then be retrieved and refined with gst_video_converter_get_config().
2691 * Look at the `GST_VIDEO_CONVERTER_OPT_*` fields to check valid configuration
2692 * option and values.
2694 * Returns: %TRUE when @config could be set.
2699 gst_video_converter_set_config (GstVideoConverter * convert,
2700 GstStructure * config)
2702 g_return_val_if_fail (convert != NULL, FALSE);
2703 g_return_val_if_fail (config != NULL, FALSE);
2705 gst_structure_foreach (config, copy_config, convert);
2706 gst_structure_free (config);
2712 * gst_video_converter_get_config:
2713 * @convert: a #GstVideoConverter
2715 * Get the current configuration of @convert.
2717 * Returns: a #GstStructure that remains valid for as long as @convert is valid
2718 * or until gst_video_converter_set_config() is called.
2720 const GstStructure *
2721 gst_video_converter_get_config (GstVideoConverter * convert)
2723 g_return_val_if_fail (convert != NULL, NULL);
2725 return convert->config;
2729 * gst_video_converter_frame:
2730 * @convert: a #GstVideoConverter
2731 * @dest: a #GstVideoFrame
2732 * @src: a #GstVideoFrame
2734 * Convert the pixels of @src into @dest using @convert.
2736 * If #GST_VIDEO_CONVERTER_OPT_ASYNC_TASKS is %TRUE then this function will
2737 * return immediately and needs to be followed by a call to
2738 * gst_video_converter_frame_finish().
2743 gst_video_converter_frame (GstVideoConverter * convert,
2744 const GstVideoFrame * src, GstVideoFrame * dest)
2746 g_return_if_fail (convert != NULL);
2747 g_return_if_fail (src != NULL);
2748 g_return_if_fail (dest != NULL);
2750 /* Check the frames we've been passed match the layout
2751 * we were configured for or we might go out of bounds */
2752 if (G_UNLIKELY (GST_VIDEO_INFO_FORMAT (&convert->in_info) !=
2753 GST_VIDEO_FRAME_FORMAT (src)
2754 || GST_VIDEO_INFO_WIDTH (&convert->in_info) >
2755 GST_VIDEO_FRAME_WIDTH (src)
2756 || GST_VIDEO_INFO_FIELD_HEIGHT (&convert->in_info) >
2757 GST_VIDEO_FRAME_HEIGHT (src))) {
2758 g_critical ("Input video frame does not match configuration");
2761 if (G_UNLIKELY (GST_VIDEO_INFO_FORMAT (&convert->out_info) !=
2762 GST_VIDEO_FRAME_FORMAT (dest)
2763 || GST_VIDEO_INFO_WIDTH (&convert->out_info) >
2764 GST_VIDEO_FRAME_WIDTH (dest)
2765 || GST_VIDEO_INFO_FIELD_HEIGHT (&convert->out_info) >
2766 GST_VIDEO_FRAME_HEIGHT (dest))) {
2767 g_critical ("Output video frame does not match configuration");
2771 if (G_UNLIKELY (convert->in_width == 0 || convert->in_height == 0 ||
2772 convert->out_width == 0 || convert->out_height == 0))
2775 convert->convert (convert, src, dest);
2779 * gst_video_converter_frame_finish:
2780 * @convert: a #GstVideoConverter
2782 * Wait for a previous async conversion performed using
2783 * gst_video_converter_frame() to complete.
2788 gst_video_converter_frame_finish (GstVideoConverter * convert)
2790 g_return_if_fail (convert);
2791 g_return_if_fail (convert->conversion_runner);
2792 g_return_if_fail (convert->conversion_runner->async_tasks);
2794 gst_parallelized_task_runner_finish (convert->conversion_runner);
2798 video_converter_compute_matrix (GstVideoConverter * convert)
2800 MatrixData *dst = &convert->convert_matrix;
2802 color_matrix_set_identity (dst);
2803 compute_matrix_to_RGB (convert, dst);
2804 compute_matrix_to_YUV (convert, dst, FALSE);
2806 convert->current_bits = 8;
2807 prepare_matrix (convert, dst);
2811 video_converter_compute_resample (GstVideoConverter * convert, gint idx)
2813 GstVideoInfo *in_info, *out_info;
2814 const GstVideoFormatInfo *sfinfo, *dfinfo;
2816 if (CHECK_CHROMA_NONE (convert))
2819 in_info = &convert->in_info;
2820 out_info = &convert->out_info;
2822 sfinfo = in_info->finfo;
2823 dfinfo = out_info->finfo;
2825 GST_DEBUG ("site: %d->%d, w_sub: %d->%d, h_sub: %d->%d", in_info->chroma_site,
2826 out_info->chroma_site, sfinfo->w_sub[2], dfinfo->w_sub[2],
2827 sfinfo->h_sub[2], dfinfo->h_sub[2]);
2829 if (sfinfo->w_sub[2] != dfinfo->w_sub[2] ||
2830 sfinfo->h_sub[2] != dfinfo->h_sub[2] ||
2831 in_info->chroma_site != out_info->chroma_site ||
2832 in_info->width != out_info->width ||
2833 in_info->height != out_info->height) {
2834 if (GST_VIDEO_INFO_IS_INTERLACED (in_info)
2835 && GST_VIDEO_INFO_INTERLACE_MODE (in_info) !=
2836 GST_VIDEO_INTERLACE_MODE_ALTERNATE) {
2837 if (!CHECK_CHROMA_DOWNSAMPLE (convert))
2838 convert->upsample_i[idx] = gst_video_chroma_resample_new (0,
2839 in_info->chroma_site, GST_VIDEO_CHROMA_FLAG_INTERLACED,
2840 sfinfo->unpack_format, sfinfo->w_sub[2], sfinfo->h_sub[2]);
2841 if (!CHECK_CHROMA_UPSAMPLE (convert))
2842 convert->downsample_i[idx] =
2843 gst_video_chroma_resample_new (0, out_info->chroma_site,
2844 GST_VIDEO_CHROMA_FLAG_INTERLACED, dfinfo->unpack_format,
2845 -dfinfo->w_sub[2], -dfinfo->h_sub[2]);
2847 if (!CHECK_CHROMA_DOWNSAMPLE (convert))
2848 convert->upsample_p[idx] = gst_video_chroma_resample_new (0,
2849 in_info->chroma_site, 0, sfinfo->unpack_format, sfinfo->w_sub[2],
2851 if (!CHECK_CHROMA_UPSAMPLE (convert))
2852 convert->downsample_p[idx] = gst_video_chroma_resample_new (0,
2853 out_info->chroma_site, 0, dfinfo->unpack_format, -dfinfo->w_sub[2],
2858 #define FRAME_GET_PLANE_STRIDE(frame, plane) \
2859 GST_VIDEO_FRAME_PLANE_STRIDE (frame, plane)
2860 #define FRAME_GET_PLANE_LINE(frame, plane, line) \
2861 (gpointer)(((guint8*)(GST_VIDEO_FRAME_PLANE_DATA (frame, plane))) + \
2862 FRAME_GET_PLANE_STRIDE (frame, plane) * (line))
2864 #define FRAME_GET_COMP_STRIDE(frame, comp) \
2865 GST_VIDEO_FRAME_COMP_STRIDE (frame, comp)
2866 #define FRAME_GET_COMP_LINE(frame, comp, line) \
2867 (gpointer)(((guint8*)(GST_VIDEO_FRAME_COMP_DATA (frame, comp))) + \
2868 FRAME_GET_COMP_STRIDE (frame, comp) * (line))
2870 #define FRAME_GET_STRIDE(frame) FRAME_GET_PLANE_STRIDE (frame, 0)
2871 #define FRAME_GET_LINE(frame,line) FRAME_GET_PLANE_LINE (frame, 0, line)
2873 #define FRAME_GET_Y_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_Y, line)
2874 #define FRAME_GET_U_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_U, line)
2875 #define FRAME_GET_V_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_V, line)
2876 #define FRAME_GET_A_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_A, line)
2878 #define FRAME_GET_Y_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_Y)
2879 #define FRAME_GET_U_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_U)
2880 #define FRAME_GET_V_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_V)
2881 #define FRAME_GET_A_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_A)
2884 #define UNPACK_FRAME(frame,dest,line,x,width) \
2885 frame->info.finfo->unpack_func (frame->info.finfo, \
2886 (GST_VIDEO_FRAME_IS_INTERLACED (frame) ? \
2887 GST_VIDEO_PACK_FLAG_INTERLACED : \
2888 GST_VIDEO_PACK_FLAG_NONE), \
2889 dest, frame->data, frame->info.stride, x, \
2891 #define PACK_FRAME(frame,src,line,width) \
2892 frame->info.finfo->pack_func (frame->info.finfo, \
2893 (GST_VIDEO_FRAME_IS_INTERLACED (frame) ? \
2894 GST_VIDEO_PACK_FLAG_INTERLACED : \
2895 GST_VIDEO_PACK_FLAG_NONE), \
2896 src, 0, frame->data, frame->info.stride, \
2897 frame->info.chroma_site, line, width);
2900 get_dest_line (GstLineCache * cache, gint idx, gpointer user_data)
2902 GstVideoConverter *convert = user_data;
2904 gint pstride = convert->pack_pstride;
2905 gint out_x = convert->out_x;
2908 cline = CLAMP (idx, 0, convert->out_maxheight - 1);
2910 line = FRAME_GET_LINE (convert->dest, cline);
2911 GST_DEBUG ("get dest line %d %p", cline, line);
2913 if (convert->borderline) {
2914 gint r_border = (out_x + convert->out_width) * pstride;
2915 gint rb_width = convert->out_maxwidth * pstride - r_border;
2916 gint lb_width = out_x * pstride;
2918 memcpy (line, convert->borderline, lb_width);
2919 memcpy (line + r_border, convert->borderline, rb_width);
2921 line += out_x * pstride;
2927 do_unpack_lines (GstLineCache * cache, gint idx, gint out_line, gint in_line,
2930 GstVideoConverter *convert = user_data;
2934 cline = CLAMP (in_line + convert->in_y, 0, convert->in_maxheight - 1);
2936 if (cache->alloc_writable || !convert->identity_unpack) {
2937 tmpline = gst_line_cache_alloc_line (cache, out_line);
2938 GST_DEBUG ("unpack line %d (%u) %p", in_line, cline, tmpline);
2939 UNPACK_FRAME (convert->src, tmpline, cline, convert->in_x,
2942 tmpline = ((guint8 *) FRAME_GET_LINE (convert->src, cline)) +
2943 convert->in_x * convert->unpack_pstride;
2944 GST_DEBUG ("get src line %d (%u) %p", in_line, cline, tmpline);
2946 gst_line_cache_add_line (cache, in_line, tmpline);
2952 do_upsample_lines (GstLineCache * cache, gint idx, gint out_line, gint in_line,
2955 GstVideoConverter *convert = user_data;
2957 gint i, start_line, n_lines;
2959 n_lines = convert->up_n_lines;
2960 start_line = in_line;
2961 if (start_line < n_lines + convert->up_offset) {
2962 start_line += convert->up_offset;
2963 out_line += convert->up_offset;
2966 /* get the lines needed for chroma upsample */
2968 gst_line_cache_get_lines (cache->prev, idx, out_line, start_line,
2971 if (convert->upsample[idx]) {
2972 GST_DEBUG ("doing upsample %d-%d %p", start_line, start_line + n_lines - 1,
2974 gst_video_chroma_resample (convert->upsample[idx], lines,
2978 for (i = 0; i < n_lines; i++)
2979 gst_line_cache_add_line (cache, start_line + i, lines[i]);
2985 do_convert_to_RGB_lines (GstLineCache * cache, gint idx, gint out_line,
2986 gint in_line, gpointer user_data)
2988 GstVideoConverter *convert = user_data;
2989 MatrixData *data = &convert->to_RGB_matrix;
2990 gpointer *lines, destline;
2992 lines = gst_line_cache_get_lines (cache->prev, idx, out_line, in_line, 1);
2993 destline = lines[0];
2995 if (data->matrix_func) {
2996 GST_DEBUG ("to RGB line %d %p", in_line, destline);
2997 data->matrix_func (data, destline);
2999 if (convert->gamma_dec.gamma_func) {
3000 destline = gst_line_cache_alloc_line (cache, out_line);
3002 GST_DEBUG ("gamma decode line %d %p->%p", in_line, lines[0], destline);
3003 convert->gamma_dec.gamma_func (&convert->gamma_dec, destline, lines[0]);
3005 gst_line_cache_add_line (cache, in_line, destline);
3011 do_hscale_lines (GstLineCache * cache, gint idx, gint out_line, gint in_line,
3014 GstVideoConverter *convert = user_data;
3015 gpointer *lines, destline;
3017 lines = gst_line_cache_get_lines (cache->prev, idx, out_line, in_line, 1);
3019 destline = gst_line_cache_alloc_line (cache, out_line);
3021 GST_DEBUG ("hresample line %d %p->%p", in_line, lines[0], destline);
3022 gst_video_scaler_horizontal (convert->h_scaler[idx], convert->h_scale_format,
3023 lines[0], destline, 0, convert->out_width);
3025 gst_line_cache_add_line (cache, in_line, destline);
3031 do_vscale_lines (GstLineCache * cache, gint idx, gint out_line, gint in_line,
3034 GstVideoConverter *convert = user_data;
3035 gpointer *lines, destline;
3036 guint sline, n_lines;
3039 cline = CLAMP (in_line, 0, convert->out_height - 1);
3041 gst_video_scaler_get_coeff (convert->v_scaler[idx], cline, &sline, &n_lines);
3042 lines = gst_line_cache_get_lines (cache->prev, idx, out_line, sline, n_lines);
3044 destline = gst_line_cache_alloc_line (cache, out_line);
3046 GST_DEBUG ("vresample line %d %d-%d %p->%p", in_line, sline,
3047 sline + n_lines - 1, lines[0], destline);
3048 gst_video_scaler_vertical (convert->v_scaler[idx], convert->v_scale_format,
3049 lines, destline, cline, convert->v_scale_width);
3051 gst_line_cache_add_line (cache, in_line, destline);
3057 do_convert_lines (GstLineCache * cache, gint idx, gint out_line, gint in_line,
3060 GstVideoConverter *convert = user_data;
3061 MatrixData *data = &convert->convert_matrix;
3062 gpointer *lines, destline;
3063 guint in_bits, out_bits;
3066 lines = gst_line_cache_get_lines (cache->prev, idx, out_line, in_line, 1);
3068 destline = lines[0];
3070 in_bits = convert->in_bits;
3071 out_bits = convert->out_bits;
3073 width = MIN (convert->in_width, convert->out_width);
3075 if (out_bits == 16 || in_bits == 16) {
3076 gpointer srcline = lines[0];
3078 if (out_bits != in_bits)
3079 destline = gst_line_cache_alloc_line (cache, out_line);
3081 /* FIXME, we can scale in the conversion matrix */
3083 GST_DEBUG ("8->16 line %d %p->%p", in_line, srcline, destline);
3084 video_orc_convert_u8_to_u16 (destline, srcline, width * 4);
3088 if (data->matrix_func) {
3089 GST_DEBUG ("matrix line %d %p", in_line, srcline);
3090 data->matrix_func (data, srcline);
3093 /* FIXME, dither here */
3094 if (out_bits == 8) {
3095 GST_DEBUG ("16->8 line %d %p->%p", in_line, srcline, destline);
3096 video_orc_convert_u16_to_u8 (destline, srcline, width * 4);
3099 if (data->matrix_func) {
3100 GST_DEBUG ("matrix line %d %p", in_line, destline);
3101 data->matrix_func (data, destline);
3104 gst_line_cache_add_line (cache, in_line, destline);
3110 do_alpha_lines (GstLineCache * cache, gint idx, gint out_line, gint in_line,
3113 gpointer *lines, destline;
3114 GstVideoConverter *convert = user_data;
3115 gint width = MIN (convert->in_width, convert->out_width);
3117 lines = gst_line_cache_get_lines (cache->prev, idx, out_line, in_line, 1);
3118 destline = lines[0];
3120 GST_DEBUG ("alpha line %d %p", in_line, destline);
3121 convert->alpha_func (convert, destline, width);
3123 gst_line_cache_add_line (cache, in_line, destline);
3129 do_convert_to_YUV_lines (GstLineCache * cache, gint idx, gint out_line,
3130 gint in_line, gpointer user_data)
3132 GstVideoConverter *convert = user_data;
3133 MatrixData *data = &convert->to_YUV_matrix;
3134 gpointer *lines, destline;
3136 lines = gst_line_cache_get_lines (cache->prev, idx, out_line, in_line, 1);
3137 destline = lines[0];
3139 if (convert->gamma_enc.gamma_func) {
3140 destline = gst_line_cache_alloc_line (cache, out_line);
3142 GST_DEBUG ("gamma encode line %d %p->%p", in_line, lines[0], destline);
3143 convert->gamma_enc.gamma_func (&convert->gamma_enc, destline, lines[0]);
3145 if (data->matrix_func) {
3146 GST_DEBUG ("to YUV line %d %p", in_line, destline);
3147 data->matrix_func (data, destline);
3149 gst_line_cache_add_line (cache, in_line, destline);
3155 do_downsample_lines (GstLineCache * cache, gint idx, gint out_line,
3156 gint in_line, gpointer user_data)
3158 GstVideoConverter *convert = user_data;
3160 gint i, start_line, n_lines;
3162 n_lines = convert->down_n_lines;
3163 start_line = in_line;
3164 if (start_line < n_lines + convert->down_offset)
3165 start_line += convert->down_offset;
3167 /* get the lines needed for chroma downsample */
3169 gst_line_cache_get_lines (cache->prev, idx, out_line, start_line,
3172 if (convert->downsample[idx]) {
3173 GST_DEBUG ("downsample line %d %d-%d %p", in_line, start_line,
3174 start_line + n_lines - 1, lines[0]);
3175 gst_video_chroma_resample (convert->downsample[idx], lines,
3176 convert->out_width);
3179 for (i = 0; i < n_lines; i++)
3180 gst_line_cache_add_line (cache, start_line + i, lines[i]);
3186 do_dither_lines (GstLineCache * cache, gint idx, gint out_line, gint in_line,
3189 GstVideoConverter *convert = user_data;
3190 gpointer *lines, destline;
3192 lines = gst_line_cache_get_lines (cache->prev, idx, out_line, in_line, 1);
3193 destline = lines[0];
3195 if (convert->dither[idx]) {
3196 GST_DEBUG ("Dither line %d %p", in_line, destline);
3197 gst_video_dither_line (convert->dither[idx], destline, 0, out_line,
3198 convert->out_width);
3200 gst_line_cache_add_line (cache, in_line, destline);
3207 GstLineCache *pack_lines;
3210 gint pack_lines_count;
3212 gboolean identity_pack;
3213 gint lb_width, out_maxwidth;
3214 GstVideoFrame *dest;
3218 convert_generic_task (ConvertTask * task)
3222 for (i = task->h_0; i < task->h_1; i += task->pack_lines_count) {
3225 /* load the lines needed to pack */
3227 gst_line_cache_get_lines (task->pack_lines, task->idx, i + task->out_y,
3228 i, task->pack_lines_count);
3230 if (!task->identity_pack) {
3231 /* take away the border */
3232 guint8 *l = ((guint8 *) lines[0]) - task->lb_width;
3233 /* and pack into destination */
3234 GST_DEBUG ("pack line %d %p (%p)", i + task->out_y, lines[0], l);
3235 PACK_FRAME (task->dest, l, i + task->out_y, task->out_maxwidth);
3241 video_converter_generic (GstVideoConverter * convert, const GstVideoFrame * src,
3242 GstVideoFrame * dest)
3245 gint out_maxwidth, out_maxheight;
3246 gint out_x, out_y, out_height;
3247 gint pack_lines, pstride;
3250 ConvertTask **tasks_p;
3252 gint lines_per_thread;
3254 out_height = convert->out_height;
3255 out_maxwidth = convert->out_maxwidth;
3256 out_maxheight = convert->out_maxheight;
3258 out_x = convert->out_x;
3259 out_y = convert->out_y;
3262 convert->dest = dest;
3264 if (GST_VIDEO_FRAME_IS_INTERLACED (src)) {
3265 GST_DEBUG ("setup interlaced frame");
3266 convert->upsample = convert->upsample_i;
3267 convert->downsample = convert->downsample_i;
3268 convert->v_scaler = convert->v_scaler_i;
3270 GST_DEBUG ("setup progressive frame");
3271 convert->upsample = convert->upsample_p;
3272 convert->downsample = convert->downsample_p;
3273 convert->v_scaler = convert->v_scaler_p;
3275 if (convert->upsample[0]) {
3276 gst_video_chroma_resample_get_info (convert->upsample[0],
3277 &convert->up_n_lines, &convert->up_offset);
3279 convert->up_n_lines = 1;
3280 convert->up_offset = 0;
3282 if (convert->downsample[0]) {
3283 gst_video_chroma_resample_get_info (convert->downsample[0],
3284 &convert->down_n_lines, &convert->down_offset);
3286 convert->down_n_lines = 1;
3287 convert->down_offset = 0;
3290 pack_lines = convert->pack_nlines; /* only 1 for now */
3291 pstride = convert->pack_pstride;
3293 lb_width = out_x * pstride;
3295 if (convert->borderline) {
3296 /* FIXME we should try to avoid PACK_FRAME */
3297 for (i = 0; i < out_y; i++)
3298 PACK_FRAME (dest, convert->borderline, i, out_maxwidth);
3301 n_threads = convert->conversion_runner->n_threads;
3302 tasks = convert->tasks[0] =
3303 g_renew (ConvertTask, convert->tasks[0], n_threads);
3304 tasks_p = convert->tasks_p[0] =
3305 g_renew (ConvertTask *, convert->tasks_p[0], n_threads);
3308 GST_ROUND_UP_N ((out_height + n_threads - 1) / n_threads, pack_lines);
3310 for (i = 0; i < n_threads; i++) {
3311 tasks[i].dest = dest;
3312 tasks[i].pack_lines = convert->pack_lines[i];
3314 tasks[i].pack_lines_count = pack_lines;
3315 tasks[i].out_y = out_y;
3316 tasks[i].identity_pack = convert->identity_pack;
3317 tasks[i].lb_width = lb_width;
3318 tasks[i].out_maxwidth = out_maxwidth;
3320 tasks[i].h_0 = i * lines_per_thread;
3321 tasks[i].h_1 = MIN ((i + 1) * lines_per_thread, out_height);
3323 tasks_p[i] = &tasks[i];
3326 gst_parallelized_task_runner_run (convert->conversion_runner,
3327 (GstParallelizedTaskFunc) convert_generic_task, (gpointer) tasks_p);
3329 if (convert->borderline) {
3330 for (i = out_y + out_height; i < out_maxheight; i++)
3331 PACK_FRAME (dest, convert->borderline, i, out_maxwidth);
3333 if (convert->pack_pal) {
3334 memcpy (GST_VIDEO_FRAME_PLANE_DATA (dest, 1), convert->pack_pal,
3335 convert->pack_palsize);
3339 static void convert_fill_border (GstVideoConverter * convert,
3340 GstVideoFrame * dest);
3344 #define GET_LINE_OFFSETS(interlaced,line,l1,l2) \
3346 l1 = (line & 2 ? line - 1 : line); \
3355 const GstVideoFrame *src;
3356 GstVideoFrame *dest;
3357 gint height_0, height_1;
3360 gboolean interlaced;
3370 convert_I420_YUY2_task (FConvertTask * task)
3375 for (i = task->height_0; i < task->height_1; i += 2) {
3376 GET_LINE_OFFSETS (task->interlaced, i, l1, l2);
3378 video_orc_convert_I420_YUY2 (FRAME_GET_LINE (task->dest, l1),
3379 FRAME_GET_LINE (task->dest, l2),
3380 FRAME_GET_Y_LINE (task->src, l1),
3381 FRAME_GET_Y_LINE (task->src, l2),
3382 FRAME_GET_U_LINE (task->src, i >> 1),
3383 FRAME_GET_V_LINE (task->src, i >> 1), (task->width + 1) / 2);
3388 convert_I420_YUY2 (GstVideoConverter * convert, const GstVideoFrame * src,
3389 GstVideoFrame * dest)
3392 gint width = convert->in_width;
3393 gint height = convert->in_height;
3394 gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src)
3395 && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) !=
3396 GST_VIDEO_INTERLACE_MODE_ALTERNATE);
3398 FConvertTask *tasks;
3399 FConvertTask **tasks_p;
3401 gint lines_per_thread;
3403 /* I420 has half as many chroma lines, as such we have to
3404 * always merge two into one. For non-interlaced these are
3405 * the two next to each other, for interlaced one is skipped
3408 h2 = GST_ROUND_DOWN_4 (height);
3410 h2 = GST_ROUND_DOWN_2 (height);
3412 n_threads = convert->conversion_runner->n_threads;
3413 tasks = convert->tasks[0] =
3414 g_renew (FConvertTask, convert->tasks[0], n_threads);
3415 tasks_p = convert->tasks_p[0] =
3416 g_renew (FConvertTask *, convert->tasks_p[0], n_threads);
3418 lines_per_thread = GST_ROUND_UP_2 ((h2 + n_threads - 1) / n_threads);
3420 for (i = 0; i < n_threads; i++) {
3422 tasks[i].dest = dest;
3424 tasks[i].interlaced = interlaced;
3425 tasks[i].width = width;
3427 tasks[i].height_0 = i * lines_per_thread;
3428 tasks[i].height_1 = tasks[i].height_0 + lines_per_thread;
3429 tasks[i].height_1 = MIN (h2, tasks[i].height_1);
3431 tasks_p[i] = &tasks[i];
3434 gst_parallelized_task_runner_run (convert->conversion_runner,
3435 (GstParallelizedTaskFunc) convert_I420_YUY2_task, (gpointer) tasks_p);
3437 /* now handle last lines. For interlaced these are up to 3 */
3439 for (i = h2; i < height; i++) {
3440 UNPACK_FRAME (src, convert->tmpline[0], i, convert->in_x, width);
3441 PACK_FRAME (dest, convert->tmpline[0], i, width);
3447 convert_I420_UYVY_task (FConvertTask * task)
3452 for (i = task->height_0; i < task->height_1; i += 2) {
3453 GET_LINE_OFFSETS (task->interlaced, i, l1, l2);
3455 video_orc_convert_I420_UYVY (FRAME_GET_LINE (task->dest, l1),
3456 FRAME_GET_LINE (task->dest, l2),
3457 FRAME_GET_Y_LINE (task->src, l1),
3458 FRAME_GET_Y_LINE (task->src, l2),
3459 FRAME_GET_U_LINE (task->src, i >> 1),
3460 FRAME_GET_V_LINE (task->src, i >> 1), (task->width + 1) / 2);
3465 convert_I420_UYVY (GstVideoConverter * convert, const GstVideoFrame * src,
3466 GstVideoFrame * dest)
3469 gint width = convert->in_width;
3470 gint height = convert->in_height;
3471 gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src)
3472 && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) !=
3473 GST_VIDEO_INTERLACE_MODE_ALTERNATE);
3475 FConvertTask *tasks;
3476 FConvertTask **tasks_p;
3478 gint lines_per_thread;
3480 /* I420 has half as many chroma lines, as such we have to
3481 * always merge two into one. For non-interlaced these are
3482 * the two next to each other, for interlaced one is skipped
3485 h2 = GST_ROUND_DOWN_4 (height);
3487 h2 = GST_ROUND_DOWN_2 (height);
3489 n_threads = convert->conversion_runner->n_threads;
3490 tasks = convert->tasks[0] =
3491 g_renew (FConvertTask, convert->tasks[0], n_threads);
3492 tasks_p = convert->tasks_p[0] =
3493 g_renew (FConvertTask *, convert->tasks_p[0], n_threads);
3495 lines_per_thread = GST_ROUND_UP_2 ((h2 + n_threads - 1) / n_threads);
3497 for (i = 0; i < n_threads; i++) {
3499 tasks[i].dest = dest;
3501 tasks[i].interlaced = interlaced;
3502 tasks[i].width = width;
3504 tasks[i].height_0 = i * lines_per_thread;
3505 tasks[i].height_1 = tasks[i].height_0 + lines_per_thread;
3506 tasks[i].height_1 = MIN (h2, tasks[i].height_1);
3508 tasks_p[i] = &tasks[i];
3511 gst_parallelized_task_runner_run (convert->conversion_runner,
3512 (GstParallelizedTaskFunc) convert_I420_UYVY_task, (gpointer) tasks_p);
3514 /* now handle last lines. For interlaced these are up to 3 */
3516 for (i = h2; i < height; i++) {
3517 UNPACK_FRAME (src, convert->tmpline[0], i, convert->in_x, width);
3518 PACK_FRAME (dest, convert->tmpline[0], i, width);
3524 convert_I420_AYUV_task (FConvertTask * task)
3529 for (i = task->height_0; i < task->height_1; i += 2) {
3530 GET_LINE_OFFSETS (task->interlaced, i, l1, l2);
3532 video_orc_convert_I420_AYUV (FRAME_GET_LINE (task->dest, l1),
3533 FRAME_GET_LINE (task->dest, l2),
3534 FRAME_GET_Y_LINE (task->src, l1),
3535 FRAME_GET_Y_LINE (task->src, l2),
3536 FRAME_GET_U_LINE (task->src, i >> 1), FRAME_GET_V_LINE (task->src,
3537 i >> 1), task->alpha, task->width);
3542 convert_I420_AYUV (GstVideoConverter * convert, const GstVideoFrame * src,
3543 GstVideoFrame * dest)
3546 gint width = convert->in_width;
3547 gint height = convert->in_height;
3548 gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src)
3549 && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) !=
3550 GST_VIDEO_INTERLACE_MODE_ALTERNATE);
3551 guint8 alpha = MIN (convert->alpha_value, 255);
3553 FConvertTask *tasks;
3554 FConvertTask **tasks_p;
3556 gint lines_per_thread;
3558 /* I420 has half as many chroma lines, as such we have to
3559 * always merge two into one. For non-interlaced these are
3560 * the two next to each other, for interlaced one is skipped
3563 h2 = GST_ROUND_DOWN_4 (height);
3565 h2 = GST_ROUND_DOWN_2 (height);
3568 n_threads = convert->conversion_runner->n_threads;
3569 tasks = convert->tasks[0] =
3570 g_renew (FConvertTask, convert->tasks[0], n_threads);
3571 tasks_p = convert->tasks_p[0] =
3572 g_renew (FConvertTask *, convert->tasks_p[0], n_threads);
3574 lines_per_thread = GST_ROUND_UP_2 ((h2 + n_threads - 1) / n_threads);
3576 for (i = 0; i < n_threads; i++) {
3578 tasks[i].dest = dest;
3580 tasks[i].interlaced = interlaced;
3581 tasks[i].width = width;
3582 tasks[i].alpha = alpha;
3584 tasks[i].height_0 = i * lines_per_thread;
3585 tasks[i].height_1 = tasks[i].height_0 + lines_per_thread;
3586 tasks[i].height_1 = MIN (h2, tasks[i].height_1);
3588 tasks_p[i] = &tasks[i];
3591 gst_parallelized_task_runner_run (convert->conversion_runner,
3592 (GstParallelizedTaskFunc) convert_I420_AYUV_task, (gpointer) tasks_p);
3594 /* now handle last lines. For interlaced these are up to 3 */
3596 for (i = h2; i < height; i++) {
3597 UNPACK_FRAME (src, convert->tmpline[0], i, convert->in_x, width);
3599 convert_set_alpha_u8 (convert, convert->tmpline[0], width);
3600 PACK_FRAME (dest, convert->tmpline[0], i, width);
3606 convert_YUY2_I420_task (FConvertTask * task)
3611 for (i = task->height_0; i < task->height_1; i += 2) {
3612 GET_LINE_OFFSETS (task->interlaced, i, l1, l2);
3614 video_orc_convert_YUY2_I420 (FRAME_GET_Y_LINE (task->dest, l1),
3615 FRAME_GET_Y_LINE (task->dest, l2),
3616 FRAME_GET_U_LINE (task->dest, i >> 1),
3617 FRAME_GET_V_LINE (task->dest, i >> 1),
3618 FRAME_GET_LINE (task->src, l1), FRAME_GET_LINE (task->src, l2),
3619 (task->width + 1) / 2);
3624 convert_YUY2_I420 (GstVideoConverter * convert, const GstVideoFrame * src,
3625 GstVideoFrame * dest)
3628 gint width = convert->in_width;
3629 gint height = convert->in_height;
3630 gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src)
3631 && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) !=
3632 GST_VIDEO_INTERLACE_MODE_ALTERNATE);
3634 FConvertTask *tasks;
3635 FConvertTask **tasks_p;
3637 gint lines_per_thread;
3639 /* I420 has half as many chroma lines, as such we have to
3640 * always merge two into one. For non-interlaced these are
3641 * the two next to each other, for interlaced one is skipped
3644 h2 = GST_ROUND_DOWN_4 (height);
3646 h2 = GST_ROUND_DOWN_2 (height);
3648 n_threads = convert->conversion_runner->n_threads;
3649 tasks = convert->tasks[0] =
3650 g_renew (FConvertTask, convert->tasks[0], n_threads);
3651 tasks_p = convert->tasks_p[0] =
3652 g_renew (FConvertTask *, convert->tasks_p[0], n_threads);
3654 lines_per_thread = GST_ROUND_UP_2 ((h2 + n_threads - 1) / n_threads);
3656 for (i = 0; i < n_threads; i++) {
3658 tasks[i].dest = dest;
3660 tasks[i].interlaced = interlaced;
3661 tasks[i].width = width;
3663 tasks[i].height_0 = i * lines_per_thread;
3664 tasks[i].height_1 = tasks[i].height_0 + lines_per_thread;
3665 tasks[i].height_1 = MIN (h2, tasks[i].height_1);
3667 tasks_p[i] = &tasks[i];
3670 gst_parallelized_task_runner_run (convert->conversion_runner,
3671 (GstParallelizedTaskFunc) convert_YUY2_I420_task, (gpointer) tasks_p);
3673 /* now handle last lines. For interlaced these are up to 3 */
3675 for (i = h2; i < height; i++) {
3676 UNPACK_FRAME (src, convert->tmpline[0], i, convert->in_x, width);
3677 PACK_FRAME (dest, convert->tmpline[0], i, width);
3683 convert_v210_I420_task (FConvertTask * task)
3687 guint8 *d_y1, *d_y2, *d_u, *d_v;
3688 const guint8 *s1, *s2;
3689 guint32 a0, a1, a2, a3;
3690 guint16 y0_1, y1_1, y2_1, y3_1, y4_1, y5_1;
3691 guint16 u0_1, u2_1, u4_1;
3692 guint16 v0_1, v2_1, v4_1;
3693 guint16 y0_2, y1_2, y2_2, y3_2, y4_2, y5_2;
3694 guint16 u0_2, u2_2, u4_2;
3695 guint16 v0_2, v2_2, v4_2;
3697 for (i = task->height_0; i < task->height_1; i += 2) {
3698 GET_LINE_OFFSETS (task->interlaced, i, l1, l2);
3700 d_y1 = FRAME_GET_Y_LINE (task->dest, l1);
3701 d_y2 = FRAME_GET_Y_LINE (task->dest, l2);
3702 d_u = FRAME_GET_U_LINE (task->dest, i >> 1);
3703 d_v = FRAME_GET_V_LINE (task->dest, i >> 1);
3705 s1 = FRAME_GET_LINE (task->src, l1);
3706 s2 = FRAME_GET_LINE (task->src, l2);
3708 for (j = 0; j < task->width; j += 6) {
3709 a0 = GST_READ_UINT32_LE (s1 + (j / 6) * 16 + 0);
3710 a1 = GST_READ_UINT32_LE (s1 + (j / 6) * 16 + 4);
3711 a2 = GST_READ_UINT32_LE (s1 + (j / 6) * 16 + 8);
3712 a3 = GST_READ_UINT32_LE (s1 + (j / 6) * 16 + 12);
3714 u0_1 = ((a0 >> 0) & 0x3ff) >> 2;
3715 y0_1 = ((a0 >> 10) & 0x3ff) >> 2;
3716 v0_1 = ((a0 >> 20) & 0x3ff) >> 2;
3717 y1_1 = ((a1 >> 0) & 0x3ff) >> 2;
3719 u2_1 = ((a1 >> 10) & 0x3ff) >> 2;
3720 y2_1 = ((a1 >> 20) & 0x3ff) >> 2;
3721 v2_1 = ((a2 >> 0) & 0x3ff) >> 2;
3722 y3_1 = ((a2 >> 10) & 0x3ff) >> 2;
3724 u4_1 = ((a2 >> 20) & 0x3ff) >> 2;
3725 y4_1 = ((a3 >> 0) & 0x3ff) >> 2;
3726 v4_1 = ((a3 >> 10) & 0x3ff) >> 2;
3727 y5_1 = ((a3 >> 20) & 0x3ff) >> 2;
3729 a0 = GST_READ_UINT32_LE (s2 + (j / 6) * 16 + 0);
3730 a1 = GST_READ_UINT32_LE (s2 + (j / 6) * 16 + 4);
3731 a2 = GST_READ_UINT32_LE (s2 + (j / 6) * 16 + 8);
3732 a3 = GST_READ_UINT32_LE (s2 + (j / 6) * 16 + 12);
3734 u0_2 = ((a0 >> 0) & 0x3ff) >> 2;
3735 y0_2 = ((a0 >> 10) & 0x3ff) >> 2;
3736 v0_2 = ((a0 >> 20) & 0x3ff) >> 2;
3737 y1_2 = ((a1 >> 0) & 0x3ff) >> 2;
3739 u2_2 = ((a1 >> 10) & 0x3ff) >> 2;
3740 y2_2 = ((a1 >> 20) & 0x3ff) >> 2;
3741 v2_2 = ((a2 >> 0) & 0x3ff) >> 2;
3742 y3_2 = ((a2 >> 10) & 0x3ff) >> 2;
3744 u4_2 = ((a2 >> 20) & 0x3ff) >> 2;
3745 y4_2 = ((a3 >> 0) & 0x3ff) >> 2;
3746 v4_2 = ((a3 >> 10) & 0x3ff) >> 2;
3747 y5_2 = ((a3 >> 20) & 0x3ff) >> 2;
3751 d_u[j / 2] = (u0_1 + u0_2) / 2;
3752 d_v[j / 2] = (v0_1 + v0_2) / 2;
3754 if (j < task->width - 1) {
3759 if (j < task->width - 2) {
3762 d_u[j / 2 + 1] = (u2_1 + u2_2) / 2;
3763 d_v[j / 2 + 1] = (v2_1 + v2_2) / 2;
3766 if (j < task->width - 3) {
3771 if (j < task->width - 4) {
3774 d_u[j / 2 + 2] = (u4_1 + u4_2) / 2;
3775 d_v[j / 2 + 2] = (v4_1 + v4_2) / 2;
3778 if (j < task->width - 5) {
3787 convert_v210_I420 (GstVideoConverter * convert, const GstVideoFrame * src,
3788 GstVideoFrame * dest)
3791 gint width = convert->in_width;
3792 gint height = convert->in_height;
3793 gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src)
3794 && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) !=
3795 GST_VIDEO_INTERLACE_MODE_ALTERNATE);
3797 FConvertTask *tasks;
3798 FConvertTask **tasks_p;
3800 gint lines_per_thread;
3802 /* I420 has half as many chroma lines, as such we have to
3803 * always merge two into one. For non-interlaced these are
3804 * the two next to each other, for interlaced one is skipped
3807 h2 = GST_ROUND_DOWN_4 (height);
3809 h2 = GST_ROUND_DOWN_2 (height);
3811 n_threads = convert->conversion_runner->n_threads;
3812 tasks = convert->tasks[0] =
3813 g_renew (FConvertTask, convert->tasks[0], n_threads);
3814 tasks_p = convert->tasks_p[0] =
3815 g_renew (FConvertTask *, convert->tasks_p[0], n_threads);
3817 lines_per_thread = GST_ROUND_UP_2 ((h2 + n_threads - 1) / n_threads);
3819 for (i = 0; i < n_threads; i++) {
3821 tasks[i].dest = dest;
3823 tasks[i].interlaced = interlaced;
3824 tasks[i].width = width;
3826 tasks[i].height_0 = i * lines_per_thread;
3827 tasks[i].height_1 = tasks[i].height_0 + lines_per_thread;
3828 tasks[i].height_1 = MIN (h2, tasks[i].height_1);
3830 tasks_p[i] = &tasks[i];
3833 gst_parallelized_task_runner_run (convert->conversion_runner,
3834 (GstParallelizedTaskFunc) convert_v210_I420_task, (gpointer) tasks_p);
3836 /* now handle last lines. For interlaced these are up to 3 */
3838 for (i = h2; i < height; i++) {
3839 UNPACK_FRAME (src, convert->tmpline[0], i, convert->in_x, width);
3840 PACK_FRAME (dest, convert->tmpline[0], i, width);
3847 const guint8 *s, *s2, *su, *sv;
3848 guint8 *d, *d2, *du, *dv;
3849 gint sstride, sustride, svstride;
3850 gint dstride, dustride, dvstride;
3854 } FConvertPlaneTask;
3857 convert_YUY2_AYUV_task (FConvertPlaneTask * task)
3859 video_orc_convert_YUY2_AYUV (task->d, task->dstride, task->s,
3860 task->sstride, task->alpha, (task->width + 1) / 2, task->height);
3864 convert_YUY2_AYUV (GstVideoConverter * convert, const GstVideoFrame * src,
3865 GstVideoFrame * dest)
3867 gint width = convert->in_width;
3868 gint height = convert->in_height;
3870 guint8 alpha = MIN (convert->alpha_value, 255);
3871 FConvertPlaneTask *tasks;
3872 FConvertPlaneTask **tasks_p;
3874 gint lines_per_thread;
3877 s = FRAME_GET_LINE (src, convert->in_y);
3878 s += (GST_ROUND_UP_2 (convert->in_x) * 2);
3879 d = FRAME_GET_LINE (dest, convert->out_y);
3880 d += (convert->out_x * 4);
3882 n_threads = convert->conversion_runner->n_threads;
3883 tasks = convert->tasks[0] =
3884 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
3885 tasks_p = convert->tasks_p[0] =
3886 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
3888 lines_per_thread = (height + n_threads - 1) / n_threads;
3890 for (i = 0; i < n_threads; i++) {
3891 tasks[i].dstride = FRAME_GET_STRIDE (dest);
3892 tasks[i].sstride = FRAME_GET_STRIDE (src);
3893 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
3894 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
3896 tasks[i].width = width;
3897 tasks[i].height = (i + 1) * lines_per_thread;
3898 tasks[i].height = MIN (tasks[i].height, height);
3899 tasks[i].height -= i * lines_per_thread;
3900 tasks[i].alpha = alpha;
3902 tasks_p[i] = &tasks[i];
3905 gst_parallelized_task_runner_run (convert->conversion_runner,
3906 (GstParallelizedTaskFunc) convert_YUY2_AYUV_task, (gpointer) tasks_p);
3908 convert_fill_border (convert, dest);
3912 convert_YUY2_Y42B_task (FConvertPlaneTask * task)
3914 video_orc_convert_YUY2_Y42B (task->d, task->dstride, task->du,
3915 task->dustride, task->dv, task->dvstride,
3916 task->s, task->sstride, (task->width + 1) / 2, task->height);
3920 convert_YUY2_Y42B (GstVideoConverter * convert, const GstVideoFrame * src,
3921 GstVideoFrame * dest)
3923 gint width = convert->in_width;
3924 gint height = convert->in_height;
3925 guint8 *s, *dy, *du, *dv;
3926 FConvertPlaneTask *tasks;
3927 FConvertPlaneTask **tasks_p;
3929 gint lines_per_thread;
3932 s = FRAME_GET_LINE (src, convert->in_y);
3933 s += (GST_ROUND_UP_2 (convert->in_x) * 2);
3935 dy = FRAME_GET_Y_LINE (dest, convert->out_y);
3936 dy += convert->out_x;
3937 du = FRAME_GET_U_LINE (dest, convert->out_y);
3938 du += convert->out_x >> 1;
3939 dv = FRAME_GET_V_LINE (dest, convert->out_y);
3940 dv += convert->out_x >> 1;
3942 n_threads = convert->conversion_runner->n_threads;
3943 tasks = convert->tasks[0] =
3944 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
3945 tasks_p = convert->tasks_p[0] =
3946 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
3948 lines_per_thread = (height + n_threads - 1) / n_threads;
3950 for (i = 0; i < n_threads; i++) {
3951 tasks[i].dstride = FRAME_GET_Y_STRIDE (dest);
3952 tasks[i].dustride = FRAME_GET_U_STRIDE (dest);
3953 tasks[i].dvstride = FRAME_GET_V_STRIDE (dest);
3954 tasks[i].sstride = FRAME_GET_STRIDE (src);
3955 tasks[i].d = dy + i * lines_per_thread * tasks[i].dstride;
3956 tasks[i].du = du + i * lines_per_thread * tasks[i].dustride;
3957 tasks[i].dv = dv + i * lines_per_thread * tasks[i].dvstride;
3958 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
3960 tasks[i].width = width;
3961 tasks[i].height = (i + 1) * lines_per_thread;
3962 tasks[i].height = MIN (tasks[i].height, height);
3963 tasks[i].height -= i * lines_per_thread;
3965 tasks_p[i] = &tasks[i];
3968 gst_parallelized_task_runner_run (convert->conversion_runner,
3969 (GstParallelizedTaskFunc) convert_YUY2_Y42B_task, (gpointer) tasks_p);
3971 convert_fill_border (convert, dest);
3975 convert_YUY2_Y444_task (FConvertPlaneTask * task)
3977 video_orc_convert_YUY2_Y444 (task->d,
3978 task->dstride, task->du,
3979 task->dustride, task->dv,
3980 task->dvstride, task->s,
3981 task->sstride, (task->width + 1) / 2, task->height);
3985 convert_YUY2_Y444 (GstVideoConverter * convert, const GstVideoFrame * src,
3986 GstVideoFrame * dest)
3988 gint width = convert->in_width;
3989 gint height = convert->in_height;
3990 guint8 *s, *dy, *du, *dv;
3991 FConvertPlaneTask *tasks;
3992 FConvertPlaneTask **tasks_p;
3994 gint lines_per_thread;
3997 s = FRAME_GET_LINE (src, convert->in_y);
3998 s += (GST_ROUND_UP_2 (convert->in_x) * 2);
4000 dy = FRAME_GET_Y_LINE (dest, convert->out_y);
4001 dy += convert->out_x;
4002 du = FRAME_GET_U_LINE (dest, convert->out_y);
4003 du += convert->out_x;
4004 dv = FRAME_GET_V_LINE (dest, convert->out_y);
4005 dv += convert->out_x;
4007 n_threads = convert->conversion_runner->n_threads;
4008 tasks = convert->tasks[0] =
4009 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4010 tasks_p = convert->tasks_p[0] =
4011 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4013 lines_per_thread = (height + n_threads - 1) / n_threads;
4015 for (i = 0; i < n_threads; i++) {
4016 tasks[i].dstride = FRAME_GET_Y_STRIDE (dest);
4017 tasks[i].dustride = FRAME_GET_U_STRIDE (dest);
4018 tasks[i].dvstride = FRAME_GET_V_STRIDE (dest);
4019 tasks[i].sstride = FRAME_GET_STRIDE (src);
4020 tasks[i].d = dy + i * lines_per_thread * tasks[i].dstride;
4021 tasks[i].du = du + i * lines_per_thread * tasks[i].dustride;
4022 tasks[i].dv = dv + i * lines_per_thread * tasks[i].dvstride;
4023 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4025 tasks[i].width = width;
4026 tasks[i].height = (i + 1) * lines_per_thread;
4027 tasks[i].height = MIN (tasks[i].height, height);
4028 tasks[i].height -= i * lines_per_thread;
4030 tasks_p[i] = &tasks[i];
4033 gst_parallelized_task_runner_run (convert->conversion_runner,
4034 (GstParallelizedTaskFunc) convert_YUY2_Y444_task, (gpointer) tasks_p);
4036 convert_fill_border (convert, dest);
4040 convert_v210_Y42B_task (FConvertPlaneTask * task)
4043 guint8 *d_y, *d_u, *d_v;
4045 guint32 a0, a1, a2, a3;
4046 guint16 y0, y1, y2, y3, y4, y5;
4050 for (i = 0; i < task->height; i++) {
4051 d_y = task->d + i * task->dstride;
4052 d_u = task->du + i * task->dustride;
4053 d_v = task->dv + i * task->dvstride;
4054 s = task->s + i * task->sstride;
4056 for (j = 0; j < task->width; j += 6) {
4057 a0 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 0);
4058 a1 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 4);
4059 a2 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 8);
4060 a3 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 12);
4062 u0 = ((a0 >> 0) & 0x3ff) >> 2;
4063 y0 = ((a0 >> 10) & 0x3ff) >> 2;
4064 v0 = ((a0 >> 20) & 0x3ff) >> 2;
4065 y1 = ((a1 >> 0) & 0x3ff) >> 2;
4067 u2 = ((a1 >> 10) & 0x3ff) >> 2;
4068 y2 = ((a1 >> 20) & 0x3ff) >> 2;
4069 v2 = ((a2 >> 0) & 0x3ff) >> 2;
4070 y3 = ((a2 >> 10) & 0x3ff) >> 2;
4072 u4 = ((a2 >> 20) & 0x3ff) >> 2;
4073 y4 = ((a3 >> 0) & 0x3ff) >> 2;
4074 v4 = ((a3 >> 10) & 0x3ff) >> 2;
4075 y5 = ((a3 >> 20) & 0x3ff) >> 2;
4081 if (j < task->width - 1) {
4085 if (j < task->width - 2) {
4087 d_u[j / 2 + 1] = u2;
4088 d_v[j / 2 + 1] = v2;
4091 if (j < task->width - 3) {
4095 if (j < task->width - 4) {
4097 d_u[j / 2 + 2] = u4;
4098 d_v[j / 2 + 2] = v4;
4101 if (j < task->width - 5) {
4109 convert_v210_Y42B (GstVideoConverter * convert, const GstVideoFrame * src,
4110 GstVideoFrame * dest)
4112 gint width = convert->in_width;
4113 gint height = convert->in_height;
4114 guint8 *s, *dy, *du, *dv;
4115 FConvertPlaneTask *tasks;
4116 FConvertPlaneTask **tasks_p;
4118 gint lines_per_thread;
4121 s = FRAME_GET_LINE (src, convert->in_y);
4122 s += (GST_ROUND_UP_2 (convert->in_x) * 2);
4124 dy = FRAME_GET_Y_LINE (dest, convert->out_y);
4125 dy += convert->out_x;
4126 du = FRAME_GET_U_LINE (dest, convert->out_y);
4127 du += convert->out_x >> 1;
4128 dv = FRAME_GET_V_LINE (dest, convert->out_y);
4129 dv += convert->out_x >> 1;
4131 n_threads = convert->conversion_runner->n_threads;
4132 tasks = convert->tasks[0] =
4133 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4134 tasks_p = convert->tasks_p[0] =
4135 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4137 lines_per_thread = (height + n_threads - 1) / n_threads;
4139 for (i = 0; i < n_threads; i++) {
4140 tasks[i].dstride = FRAME_GET_Y_STRIDE (dest);
4141 tasks[i].dustride = FRAME_GET_U_STRIDE (dest);
4142 tasks[i].dvstride = FRAME_GET_V_STRIDE (dest);
4143 tasks[i].sstride = FRAME_GET_STRIDE (src);
4144 tasks[i].d = dy + i * lines_per_thread * tasks[i].dstride;
4145 tasks[i].du = du + i * lines_per_thread * tasks[i].dustride;
4146 tasks[i].dv = dv + i * lines_per_thread * tasks[i].dvstride;
4147 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4149 tasks[i].width = width;
4150 tasks[i].height = (i + 1) * lines_per_thread;
4151 tasks[i].height = MIN (tasks[i].height, height);
4152 tasks[i].height -= i * lines_per_thread;
4154 tasks_p[i] = &tasks[i];
4157 gst_parallelized_task_runner_run (convert->conversion_runner,
4158 (GstParallelizedTaskFunc) convert_v210_Y42B_task, (gpointer) tasks_p);
4160 convert_fill_border (convert, dest);
4164 convert_UYVY_I420_task (FConvertTask * task)
4169 for (i = task->height_0; i < task->height_1; i += 2) {
4170 GET_LINE_OFFSETS (task->interlaced, i, l1, l2);
4172 video_orc_convert_UYVY_I420 (FRAME_GET_COMP_LINE (task->dest, 0, l1),
4173 FRAME_GET_COMP_LINE (task->dest, 0, l2),
4174 FRAME_GET_COMP_LINE (task->dest, 1, i >> 1),
4175 FRAME_GET_COMP_LINE (task->dest, 2, i >> 1),
4176 FRAME_GET_LINE (task->src, l1), FRAME_GET_LINE (task->src, l2),
4177 (task->width + 1) / 2);
4182 convert_UYVY_I420 (GstVideoConverter * convert, const GstVideoFrame * src,
4183 GstVideoFrame * dest)
4186 gint width = convert->in_width;
4187 gint height = convert->in_height;
4188 gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src)
4189 && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) !=
4190 GST_VIDEO_INTERLACE_MODE_ALTERNATE);
4192 FConvertTask *tasks;
4193 FConvertTask **tasks_p;
4195 gint lines_per_thread;
4197 /* I420 has half as many chroma lines, as such we have to
4198 * always merge two into one. For non-interlaced these are
4199 * the two next to each other, for interlaced one is skipped
4202 h2 = GST_ROUND_DOWN_4 (height);
4204 h2 = GST_ROUND_DOWN_2 (height);
4206 n_threads = convert->conversion_runner->n_threads;
4207 tasks = convert->tasks[0] =
4208 g_renew (FConvertTask, convert->tasks[0], n_threads);
4209 tasks_p = convert->tasks_p[0] =
4210 g_renew (FConvertTask *, convert->tasks_p[0], n_threads);
4212 lines_per_thread = GST_ROUND_UP_2 ((h2 + n_threads - 1) / n_threads);
4214 for (i = 0; i < n_threads; i++) {
4216 tasks[i].dest = dest;
4218 tasks[i].interlaced = interlaced;
4219 tasks[i].width = width;
4221 tasks[i].height_0 = i * lines_per_thread;
4222 tasks[i].height_1 = tasks[i].height_0 + lines_per_thread;
4223 tasks[i].height_1 = MIN (h2, tasks[i].height_1);
4225 tasks_p[i] = &tasks[i];
4228 gst_parallelized_task_runner_run (convert->conversion_runner,
4229 (GstParallelizedTaskFunc) convert_UYVY_I420_task, (gpointer) tasks_p);
4231 /* now handle last lines. For interlaced these are up to 3 */
4233 for (i = h2; i < height; i++) {
4234 UNPACK_FRAME (src, convert->tmpline[0], i, convert->in_x, width);
4235 PACK_FRAME (dest, convert->tmpline[0], i, width);
4241 convert_UYVY_AYUV_task (FConvertPlaneTask * task)
4243 video_orc_convert_UYVY_AYUV (task->d, task->dstride, task->s,
4244 task->sstride, task->alpha, (task->width + 1) / 2, task->height);
4248 convert_UYVY_AYUV (GstVideoConverter * convert, const GstVideoFrame * src,
4249 GstVideoFrame * dest)
4251 gint width = convert->in_width;
4252 gint height = convert->in_height;
4254 guint8 alpha = MIN (convert->alpha_value, 255);
4255 FConvertPlaneTask *tasks;
4256 FConvertPlaneTask **tasks_p;
4258 gint lines_per_thread;
4261 s = FRAME_GET_LINE (src, convert->in_y);
4262 s += (GST_ROUND_UP_2 (convert->in_x) * 2);
4263 d = FRAME_GET_LINE (dest, convert->out_y);
4264 d += (convert->out_x * 4);
4266 n_threads = convert->conversion_runner->n_threads;
4267 tasks = convert->tasks[0] =
4268 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4269 tasks_p = convert->tasks_p[0] =
4270 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4272 lines_per_thread = (height + n_threads - 1) / n_threads;
4274 for (i = 0; i < n_threads; i++) {
4275 tasks[i].dstride = FRAME_GET_STRIDE (dest);
4276 tasks[i].sstride = FRAME_GET_STRIDE (src);
4277 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
4278 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4280 tasks[i].width = width;
4281 tasks[i].height = (i + 1) * lines_per_thread;
4282 tasks[i].height = MIN (tasks[i].height, height);
4283 tasks[i].height -= i * lines_per_thread;
4284 tasks[i].alpha = alpha;
4286 tasks_p[i] = &tasks[i];
4289 gst_parallelized_task_runner_run (convert->conversion_runner,
4290 (GstParallelizedTaskFunc) convert_UYVY_AYUV_task, (gpointer) tasks_p);
4292 convert_fill_border (convert, dest);
4296 convert_UYVY_YUY2_task (FConvertPlaneTask * task)
4298 video_orc_convert_UYVY_YUY2 (task->d, task->dstride, task->s,
4299 task->sstride, (task->width + 1) / 2, task->height);
4303 convert_UYVY_YUY2 (GstVideoConverter * convert, const GstVideoFrame * src,
4304 GstVideoFrame * dest)
4306 gint width = convert->in_width;
4307 gint height = convert->in_height;
4309 FConvertPlaneTask *tasks;
4310 FConvertPlaneTask **tasks_p;
4312 gint lines_per_thread;
4315 s = FRAME_GET_LINE (src, convert->in_y);
4316 s += (GST_ROUND_UP_2 (convert->in_x) * 2);
4317 d = FRAME_GET_LINE (dest, convert->out_y);
4318 d += (GST_ROUND_UP_2 (convert->out_x) * 2);
4320 n_threads = convert->conversion_runner->n_threads;
4321 tasks = convert->tasks[0] =
4322 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4323 tasks_p = convert->tasks_p[0] =
4324 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4326 lines_per_thread = (height + n_threads - 1) / n_threads;
4328 for (i = 0; i < n_threads; i++) {
4329 tasks[i].dstride = FRAME_GET_STRIDE (dest);
4330 tasks[i].sstride = FRAME_GET_STRIDE (src);
4331 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
4332 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4334 tasks[i].width = width;
4335 tasks[i].height = (i + 1) * lines_per_thread;
4336 tasks[i].height = MIN (tasks[i].height, height);
4337 tasks[i].height -= i * lines_per_thread;
4339 tasks_p[i] = &tasks[i];
4342 gst_parallelized_task_runner_run (convert->conversion_runner,
4343 (GstParallelizedTaskFunc) convert_UYVY_YUY2_task, (gpointer) tasks_p);
4345 convert_fill_border (convert, dest);
4349 convert_v210_UYVY_task (FConvertPlaneTask * task)
4354 guint32 a0, a1, a2, a3;
4355 guint16 y0, y1, y2, y3, y4, y5;
4359 for (i = 0; i < task->height; i++) {
4360 d = task->d + i * task->dstride;
4361 s = task->s + i * task->sstride;
4363 for (j = 0; j < task->width; j += 6) {
4364 a0 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 0);
4365 a1 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 4);
4366 a2 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 8);
4367 a3 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 12);
4369 u0 = ((a0 >> 0) & 0x3ff) >> 2;
4370 y0 = ((a0 >> 10) & 0x3ff) >> 2;
4371 v0 = ((a0 >> 20) & 0x3ff) >> 2;
4372 y1 = ((a1 >> 0) & 0x3ff) >> 2;
4374 u2 = ((a1 >> 10) & 0x3ff) >> 2;
4375 y2 = ((a1 >> 20) & 0x3ff) >> 2;
4376 v2 = ((a2 >> 0) & 0x3ff) >> 2;
4377 y3 = ((a2 >> 10) & 0x3ff) >> 2;
4379 u4 = ((a2 >> 20) & 0x3ff) >> 2;
4380 y4 = ((a3 >> 0) & 0x3ff) >> 2;
4381 v4 = ((a3 >> 10) & 0x3ff) >> 2;
4382 y5 = ((a3 >> 20) & 0x3ff) >> 2;
4388 if (j < task->width - 1) {
4392 if (j < task->width - 2) {
4398 if (j < task->width - 3) {
4402 if (j < task->width - 4) {
4408 if (j < task->width - 5) {
4416 convert_v210_UYVY (GstVideoConverter * convert, const GstVideoFrame * src,
4417 GstVideoFrame * dest)
4419 gint width = convert->in_width;
4420 gint height = convert->in_height;
4422 FConvertPlaneTask *tasks;
4423 FConvertPlaneTask **tasks_p;
4425 gint lines_per_thread;
4428 s = FRAME_GET_LINE (src, convert->in_y);
4429 s += (GST_ROUND_UP_2 (convert->in_x) * 2);
4430 d = FRAME_GET_LINE (dest, convert->out_y);
4431 d += (GST_ROUND_UP_2 (convert->out_x) * 2);
4433 n_threads = convert->conversion_runner->n_threads;
4434 tasks = convert->tasks[0] =
4435 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4436 tasks_p = convert->tasks_p[0] =
4437 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4439 lines_per_thread = (height + n_threads - 1) / n_threads;
4441 for (i = 0; i < n_threads; i++) {
4442 tasks[i].dstride = FRAME_GET_STRIDE (dest);
4443 tasks[i].sstride = FRAME_GET_STRIDE (src);
4444 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
4445 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4447 tasks[i].width = width;
4448 tasks[i].height = (i + 1) * lines_per_thread;
4449 tasks[i].height = MIN (tasks[i].height, height);
4450 tasks[i].height -= i * lines_per_thread;
4452 tasks_p[i] = &tasks[i];
4455 gst_parallelized_task_runner_run (convert->conversion_runner,
4456 (GstParallelizedTaskFunc) convert_v210_UYVY_task, (gpointer) tasks_p);
4458 convert_fill_border (convert, dest);
4462 convert_v210_YUY2_task (FConvertPlaneTask * task)
4467 guint32 a0, a1, a2, a3;
4468 guint16 y0, y1, y2, y3, y4, y5;
4472 for (i = 0; i < task->height; i++) {
4473 d = task->d + i * task->dstride;
4474 s = task->s + i * task->sstride;
4476 for (j = 0; j < task->width; j += 6) {
4477 a0 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 0);
4478 a1 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 4);
4479 a2 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 8);
4480 a3 = GST_READ_UINT32_LE (s + (j / 6) * 16 + 12);
4482 u0 = ((a0 >> 0) & 0x3ff) >> 2;
4483 y0 = ((a0 >> 10) & 0x3ff) >> 2;
4484 v0 = ((a0 >> 20) & 0x3ff) >> 2;
4485 y1 = ((a1 >> 0) & 0x3ff) >> 2;
4487 u2 = ((a1 >> 10) & 0x3ff) >> 2;
4488 y2 = ((a1 >> 20) & 0x3ff) >> 2;
4489 v2 = ((a2 >> 0) & 0x3ff) >> 2;
4490 y3 = ((a2 >> 10) & 0x3ff) >> 2;
4492 u4 = ((a2 >> 20) & 0x3ff) >> 2;
4493 y4 = ((a3 >> 0) & 0x3ff) >> 2;
4494 v4 = ((a3 >> 10) & 0x3ff) >> 2;
4495 y5 = ((a3 >> 20) & 0x3ff) >> 2;
4501 if (j < task->width - 1) {
4505 if (j < task->width - 2) {
4511 if (j < task->width - 3) {
4515 if (j < task->width - 4) {
4521 if (j < task->width - 5) {
4529 convert_v210_YUY2 (GstVideoConverter * convert, const GstVideoFrame * src,
4530 GstVideoFrame * dest)
4532 gint width = convert->in_width;
4533 gint height = convert->in_height;
4535 FConvertPlaneTask *tasks;
4536 FConvertPlaneTask **tasks_p;
4538 gint lines_per_thread;
4541 s = FRAME_GET_LINE (src, convert->in_y);
4542 s += (GST_ROUND_UP_2 (convert->in_x) * 2);
4543 d = FRAME_GET_LINE (dest, convert->out_y);
4544 d += (GST_ROUND_UP_2 (convert->out_x) * 2);
4546 n_threads = convert->conversion_runner->n_threads;
4547 tasks = convert->tasks[0] =
4548 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4549 tasks_p = convert->tasks_p[0] =
4550 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4552 lines_per_thread = (height + n_threads - 1) / n_threads;
4554 for (i = 0; i < n_threads; i++) {
4555 tasks[i].dstride = FRAME_GET_STRIDE (dest);
4556 tasks[i].sstride = FRAME_GET_STRIDE (src);
4557 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
4558 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4560 tasks[i].width = width;
4561 tasks[i].height = (i + 1) * lines_per_thread;
4562 tasks[i].height = MIN (tasks[i].height, height);
4563 tasks[i].height -= i * lines_per_thread;
4565 tasks_p[i] = &tasks[i];
4568 gst_parallelized_task_runner_run (convert->conversion_runner,
4569 (GstParallelizedTaskFunc) convert_v210_YUY2_task, (gpointer) tasks_p);
4571 convert_fill_border (convert, dest);
4575 convert_UYVY_Y42B_task (FConvertPlaneTask * task)
4577 video_orc_convert_UYVY_Y42B (task->d, task->dstride, task->du,
4578 task->dustride, task->dv, task->dvstride,
4579 task->s, task->sstride, (task->width + 1) / 2, task->height);
4583 convert_UYVY_Y42B (GstVideoConverter * convert, const GstVideoFrame * src,
4584 GstVideoFrame * dest)
4586 gint width = convert->in_width;
4587 gint height = convert->in_height;
4588 guint8 *s, *dy, *du, *dv;
4589 FConvertPlaneTask *tasks;
4590 FConvertPlaneTask **tasks_p;
4592 gint lines_per_thread;
4595 s = FRAME_GET_LINE (src, convert->in_y);
4596 s += (GST_ROUND_UP_2 (convert->in_x) * 2);
4598 dy = FRAME_GET_Y_LINE (dest, convert->out_y);
4599 dy += convert->out_x;
4600 du = FRAME_GET_U_LINE (dest, convert->out_y);
4601 du += convert->out_x >> 1;
4602 dv = FRAME_GET_V_LINE (dest, convert->out_y);
4603 dv += convert->out_x >> 1;
4605 n_threads = convert->conversion_runner->n_threads;
4606 tasks = convert->tasks[0] =
4607 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4608 tasks_p = convert->tasks_p[0] =
4609 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4611 lines_per_thread = (height + n_threads - 1) / n_threads;
4613 for (i = 0; i < n_threads; i++) {
4614 tasks[i].dstride = FRAME_GET_Y_STRIDE (dest);
4615 tasks[i].dustride = FRAME_GET_U_STRIDE (dest);
4616 tasks[i].dvstride = FRAME_GET_V_STRIDE (dest);
4617 tasks[i].sstride = FRAME_GET_STRIDE (src);
4618 tasks[i].d = dy + i * lines_per_thread * tasks[i].dstride;
4619 tasks[i].du = du + i * lines_per_thread * tasks[i].dustride;
4620 tasks[i].dv = dv + i * lines_per_thread * tasks[i].dvstride;
4621 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4623 tasks[i].width = width;
4624 tasks[i].height = (i + 1) * lines_per_thread;
4625 tasks[i].height = MIN (tasks[i].height, height);
4626 tasks[i].height -= i * lines_per_thread;
4628 tasks_p[i] = &tasks[i];
4631 gst_parallelized_task_runner_run (convert->conversion_runner,
4632 (GstParallelizedTaskFunc) convert_UYVY_Y42B_task, (gpointer) tasks_p);
4634 convert_fill_border (convert, dest);
4638 convert_UYVY_Y444_task (FConvertPlaneTask * task)
4640 video_orc_convert_UYVY_Y444 (task->d,
4641 task->dstride, task->du,
4642 task->dustride, task->dv,
4643 task->dvstride, task->s,
4644 task->sstride, (task->width + 1) / 2, task->height);
4648 convert_UYVY_Y444 (GstVideoConverter * convert, const GstVideoFrame * src,
4649 GstVideoFrame * dest)
4651 gint width = convert->in_width;
4652 gint height = convert->in_height;
4653 guint8 *s, *dy, *du, *dv;
4654 FConvertPlaneTask *tasks;
4655 FConvertPlaneTask **tasks_p;
4657 gint lines_per_thread;
4660 s = FRAME_GET_LINE (src, convert->in_y);
4661 s += (GST_ROUND_UP_2 (convert->in_x) * 2);
4663 dy = FRAME_GET_Y_LINE (dest, convert->out_y);
4664 dy += convert->out_x;
4665 du = FRAME_GET_U_LINE (dest, convert->out_y);
4666 du += convert->out_x;
4667 dv = FRAME_GET_V_LINE (dest, convert->out_y);
4668 dv += convert->out_x;
4670 n_threads = convert->conversion_runner->n_threads;
4671 tasks = convert->tasks[0] =
4672 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4673 tasks_p = convert->tasks_p[0] =
4674 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4676 lines_per_thread = (height + n_threads - 1) / n_threads;
4678 for (i = 0; i < n_threads; i++) {
4679 tasks[i].dstride = FRAME_GET_Y_STRIDE (dest);
4680 tasks[i].dustride = FRAME_GET_U_STRIDE (dest);
4681 tasks[i].dvstride = FRAME_GET_V_STRIDE (dest);
4682 tasks[i].sstride = FRAME_GET_STRIDE (src);
4683 tasks[i].d = dy + i * lines_per_thread * tasks[i].dstride;
4684 tasks[i].du = du + i * lines_per_thread * tasks[i].dustride;
4685 tasks[i].dv = dv + i * lines_per_thread * tasks[i].dvstride;
4686 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4688 tasks[i].width = width;
4689 tasks[i].height = (i + 1) * lines_per_thread;
4690 tasks[i].height = MIN (tasks[i].height, height);
4691 tasks[i].height -= i * lines_per_thread;
4693 tasks_p[i] = &tasks[i];
4696 gst_parallelized_task_runner_run (convert->conversion_runner,
4697 (GstParallelizedTaskFunc) convert_UYVY_Y444_task, (gpointer) tasks_p);
4699 convert_fill_border (convert, dest);
4703 convert_UYVY_GRAY8_task (FConvertPlaneTask * task)
4705 video_orc_convert_UYVY_GRAY8 (task->d, task->dstride, (guint16 *) task->s,
4706 task->sstride, task->width, task->height);
4710 convert_UYVY_GRAY8 (GstVideoConverter * convert, const GstVideoFrame * src,
4711 GstVideoFrame * dest)
4713 gint width = convert->in_width;
4714 gint height = convert->in_height;
4717 FConvertPlaneTask *tasks;
4718 FConvertPlaneTask **tasks_p;
4720 gint lines_per_thread;
4723 s = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
4724 d = GST_VIDEO_FRAME_PLANE_DATA (dest, 0);
4726 n_threads = convert->conversion_runner->n_threads;
4727 tasks = convert->tasks[0] =
4728 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4729 tasks_p = convert->tasks_p[0] =
4730 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4732 lines_per_thread = (height + n_threads - 1) / n_threads;
4734 for (i = 0; i < n_threads; i++) {
4735 tasks[i].dstride = FRAME_GET_STRIDE (dest);
4736 tasks[i].sstride = FRAME_GET_STRIDE (src);
4737 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
4738 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4740 tasks[i].width = width;
4741 tasks[i].height = (i + 1) * lines_per_thread;
4742 tasks[i].height = MIN (tasks[i].height, height);
4743 tasks[i].height -= i * lines_per_thread;
4745 tasks_p[i] = &tasks[i];
4748 gst_parallelized_task_runner_run (convert->conversion_runner,
4749 (GstParallelizedTaskFunc) convert_UYVY_GRAY8_task, (gpointer) tasks_p);
4751 convert_fill_border (convert, dest);
4755 convert_AYUV_I420_task (FConvertPlaneTask * task)
4757 video_orc_convert_AYUV_I420 (task->d,
4758 2 * task->dstride, task->d2,
4759 2 * task->dstride, task->du,
4760 task->dustride, task->dv,
4761 task->dvstride, task->s,
4762 2 * task->sstride, task->s2,
4763 2 * task->sstride, task->width / 2, task->height / 2);
4767 convert_AYUV_I420 (GstVideoConverter * convert, const GstVideoFrame * src,
4768 GstVideoFrame * dest)
4770 gint width = convert->in_width;
4771 gint height = convert->in_height;
4772 guint8 *s1, *s2, *dy1, *dy2, *du, *dv;
4773 FConvertPlaneTask *tasks;
4774 FConvertPlaneTask **tasks_p;
4776 gint lines_per_thread;
4779 s1 = FRAME_GET_LINE (src, convert->in_y + 0);
4780 s1 += convert->in_x * 4;
4781 s2 = FRAME_GET_LINE (src, convert->in_y + 1);
4782 s2 += convert->in_x * 4;
4784 dy1 = FRAME_GET_Y_LINE (dest, convert->out_y + 0);
4785 dy1 += convert->out_x;
4786 dy2 = FRAME_GET_Y_LINE (dest, convert->out_y + 1);
4787 dy2 += convert->out_x;
4788 du = FRAME_GET_U_LINE (dest, convert->out_y >> 1);
4789 du += convert->out_x >> 1;
4790 dv = FRAME_GET_V_LINE (dest, convert->out_y >> 1);
4791 dv += convert->out_x >> 1;
4793 /* only for even width/height */
4795 n_threads = convert->conversion_runner->n_threads;
4796 tasks = convert->tasks[0] =
4797 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4798 tasks_p = convert->tasks_p[0] =
4799 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4801 lines_per_thread = GST_ROUND_UP_2 ((height + n_threads - 1) / n_threads);
4803 for (i = 0; i < n_threads; i++) {
4804 tasks[i].dstride = FRAME_GET_Y_STRIDE (dest);
4805 tasks[i].dustride = FRAME_GET_U_STRIDE (dest);
4806 tasks[i].dvstride = FRAME_GET_V_STRIDE (dest);
4807 tasks[i].sstride = FRAME_GET_STRIDE (src);
4808 tasks[i].d = dy1 + i * lines_per_thread * tasks[i].dstride;
4809 tasks[i].d2 = dy2 + i * lines_per_thread * tasks[i].dstride;
4810 tasks[i].du = du + i * lines_per_thread * tasks[i].dustride / 2;
4811 tasks[i].dv = dv + i * lines_per_thread * tasks[i].dvstride / 2;
4812 tasks[i].s = s1 + i * lines_per_thread * tasks[i].sstride;
4813 tasks[i].s2 = s2 + i * lines_per_thread * tasks[i].sstride;
4815 tasks[i].width = width;
4816 tasks[i].height = (i + 1) * lines_per_thread;
4817 tasks[i].height = MIN (tasks[i].height, height);
4818 tasks[i].height -= i * lines_per_thread;
4820 tasks_p[i] = &tasks[i];
4823 gst_parallelized_task_runner_run (convert->conversion_runner,
4824 (GstParallelizedTaskFunc) convert_AYUV_I420_task, (gpointer) tasks_p);
4826 convert_fill_border (convert, dest);
4830 convert_AYUV_YUY2_task (FConvertPlaneTask * task)
4832 video_orc_convert_AYUV_YUY2 (task->d, task->dstride, task->s,
4833 task->sstride, task->width / 2, task->height);
4837 convert_AYUV_YUY2 (GstVideoConverter * convert, const GstVideoFrame * src,
4838 GstVideoFrame * dest)
4840 gint width = convert->in_width;
4841 gint height = convert->in_height;
4843 FConvertPlaneTask *tasks;
4844 FConvertPlaneTask **tasks_p;
4846 gint lines_per_thread;
4849 s = FRAME_GET_LINE (src, convert->in_y);
4850 s += convert->in_x * 4;
4851 d = FRAME_GET_LINE (dest, convert->out_y);
4852 d += (GST_ROUND_UP_2 (convert->out_x) * 2);
4854 /* only for even width */
4855 n_threads = convert->conversion_runner->n_threads;
4856 tasks = convert->tasks[0] =
4857 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4858 tasks_p = convert->tasks_p[0] =
4859 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4861 lines_per_thread = (height + n_threads - 1) / n_threads;
4863 for (i = 0; i < n_threads; i++) {
4864 tasks[i].dstride = FRAME_GET_STRIDE (dest);
4865 tasks[i].sstride = FRAME_GET_STRIDE (src);
4866 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
4867 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4869 tasks[i].width = width;
4870 tasks[i].height = (i + 1) * lines_per_thread;
4871 tasks[i].height = MIN (tasks[i].height, height);
4872 tasks[i].height -= i * lines_per_thread;
4874 tasks_p[i] = &tasks[i];
4877 gst_parallelized_task_runner_run (convert->conversion_runner,
4878 (GstParallelizedTaskFunc) convert_AYUV_YUY2_task, (gpointer) tasks_p);
4880 convert_fill_border (convert, dest);
4884 convert_AYUV_UYVY_task (FConvertPlaneTask * task)
4886 video_orc_convert_AYUV_UYVY (task->d, task->dstride, task->s,
4887 task->sstride, task->width / 2, task->height);
4891 convert_AYUV_UYVY (GstVideoConverter * convert, const GstVideoFrame * src,
4892 GstVideoFrame * dest)
4894 gint width = convert->in_width;
4895 gint height = convert->in_height;
4897 FConvertPlaneTask *tasks;
4898 FConvertPlaneTask **tasks_p;
4900 gint lines_per_thread;
4903 s = FRAME_GET_LINE (src, convert->in_y);
4904 s += convert->in_x * 4;
4905 d = FRAME_GET_LINE (dest, convert->out_y);
4906 d += (GST_ROUND_UP_2 (convert->out_x) * 2);
4908 /* only for even width */
4909 n_threads = convert->conversion_runner->n_threads;
4910 tasks = convert->tasks[0] =
4911 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4912 tasks_p = convert->tasks_p[0] =
4913 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4915 lines_per_thread = (height + n_threads - 1) / n_threads;
4917 for (i = 0; i < n_threads; i++) {
4918 tasks[i].dstride = FRAME_GET_STRIDE (dest);
4919 tasks[i].sstride = FRAME_GET_STRIDE (src);
4920 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
4921 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4923 tasks[i].width = width;
4924 tasks[i].height = (i + 1) * lines_per_thread;
4925 tasks[i].height = MIN (tasks[i].height, height);
4926 tasks[i].height -= i * lines_per_thread;
4928 tasks_p[i] = &tasks[i];
4931 gst_parallelized_task_runner_run (convert->conversion_runner,
4932 (GstParallelizedTaskFunc) convert_AYUV_UYVY_task, (gpointer) tasks_p);
4934 convert_fill_border (convert, dest);
4938 convert_AYUV_Y42B_task (FConvertPlaneTask * task)
4940 video_orc_convert_AYUV_Y42B (task->d, task->dstride, task->du,
4941 task->dustride, task->dv, task->dvstride,
4942 task->s, task->sstride, task->width / 2, task->height);
4946 convert_AYUV_Y42B (GstVideoConverter * convert, const GstVideoFrame * src,
4947 GstVideoFrame * dest)
4949 gint width = convert->in_width;
4950 gint height = convert->in_height;
4951 guint8 *s, *dy, *du, *dv;
4952 FConvertPlaneTask *tasks;
4953 FConvertPlaneTask **tasks_p;
4955 gint lines_per_thread;
4958 s = FRAME_GET_LINE (src, convert->in_y);
4959 s += convert->in_x * 4;
4961 dy = FRAME_GET_Y_LINE (dest, convert->out_y);
4962 dy += convert->out_x;
4963 du = FRAME_GET_U_LINE (dest, convert->out_y);
4964 du += convert->out_x >> 1;
4965 dv = FRAME_GET_V_LINE (dest, convert->out_y);
4966 dv += convert->out_x >> 1;
4968 /* only works for even width */
4969 n_threads = convert->conversion_runner->n_threads;
4970 tasks = convert->tasks[0] =
4971 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
4972 tasks_p = convert->tasks_p[0] =
4973 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
4975 lines_per_thread = (height + n_threads - 1) / n_threads;
4977 for (i = 0; i < n_threads; i++) {
4978 tasks[i].dstride = FRAME_GET_Y_STRIDE (dest);
4979 tasks[i].dustride = FRAME_GET_U_STRIDE (dest);
4980 tasks[i].dvstride = FRAME_GET_V_STRIDE (dest);
4981 tasks[i].sstride = FRAME_GET_STRIDE (src);
4982 tasks[i].d = dy + i * lines_per_thread * tasks[i].dstride;
4983 tasks[i].du = du + i * lines_per_thread * tasks[i].dustride;
4984 tasks[i].dv = dv + i * lines_per_thread * tasks[i].dvstride;
4985 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
4987 tasks[i].width = width;
4988 tasks[i].height = (i + 1) * lines_per_thread;
4989 tasks[i].height = MIN (tasks[i].height, height);
4990 tasks[i].height -= i * lines_per_thread;
4992 tasks_p[i] = &tasks[i];
4995 gst_parallelized_task_runner_run (convert->conversion_runner,
4996 (GstParallelizedTaskFunc) convert_AYUV_Y42B_task, (gpointer) tasks_p);
4998 convert_fill_border (convert, dest);
5002 convert_AYUV_Y444_task (FConvertPlaneTask * task)
5004 video_orc_convert_AYUV_Y444 (task->d, task->dstride, task->du,
5005 task->dustride, task->dv, task->dvstride,
5006 task->s, task->sstride, task->width, task->height);
5010 convert_AYUV_Y444 (GstVideoConverter * convert, const GstVideoFrame * src,
5011 GstVideoFrame * dest)
5013 gint width = convert->in_width;
5014 gint height = convert->in_height;
5015 guint8 *s, *dy, *du, *dv;
5016 FConvertPlaneTask *tasks;
5017 FConvertPlaneTask **tasks_p;
5019 gint lines_per_thread;
5022 s = FRAME_GET_LINE (src, convert->in_y);
5023 s += convert->in_x * 4;
5025 dy = FRAME_GET_Y_LINE (dest, convert->out_y);
5026 dy += convert->out_x;
5027 du = FRAME_GET_U_LINE (dest, convert->out_y);
5028 du += convert->out_x;
5029 dv = FRAME_GET_V_LINE (dest, convert->out_y);
5030 dv += convert->out_x;
5032 n_threads = convert->conversion_runner->n_threads;
5033 tasks = convert->tasks[0] =
5034 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
5035 tasks_p = convert->tasks_p[0] =
5036 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
5038 lines_per_thread = (height + n_threads - 1) / n_threads;
5040 for (i = 0; i < n_threads; i++) {
5041 tasks[i].dstride = FRAME_GET_Y_STRIDE (dest);
5042 tasks[i].dustride = FRAME_GET_U_STRIDE (dest);
5043 tasks[i].dvstride = FRAME_GET_V_STRIDE (dest);
5044 tasks[i].sstride = FRAME_GET_STRIDE (src);
5045 tasks[i].d = dy + i * lines_per_thread * tasks[i].dstride;
5046 tasks[i].du = du + i * lines_per_thread * tasks[i].dustride;
5047 tasks[i].dv = dv + i * lines_per_thread * tasks[i].dvstride;
5048 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
5050 tasks[i].width = width;
5051 tasks[i].height = (i + 1) * lines_per_thread;
5052 tasks[i].height = MIN (tasks[i].height, height);
5053 tasks[i].height -= i * lines_per_thread;
5055 tasks_p[i] = &tasks[i];
5058 gst_parallelized_task_runner_run (convert->conversion_runner,
5059 (GstParallelizedTaskFunc) convert_AYUV_Y444_task, (gpointer) tasks_p);
5060 convert_fill_border (convert, dest);
5064 convert_Y42B_YUY2_task (FConvertPlaneTask * task)
5066 video_orc_convert_Y42B_YUY2 (task->d, task->dstride,
5067 task->s, task->sstride,
5068 task->su, task->sustride,
5069 task->sv, task->svstride, (task->width + 1) / 2, task->height);
5073 convert_Y42B_YUY2 (GstVideoConverter * convert, const GstVideoFrame * src,
5074 GstVideoFrame * dest)
5076 gint width = convert->in_width;
5077 gint height = convert->in_height;
5078 guint8 *sy, *su, *sv, *d;
5079 FConvertPlaneTask *tasks;
5080 FConvertPlaneTask **tasks_p;
5082 gint lines_per_thread;
5085 sy = FRAME_GET_Y_LINE (src, convert->in_y);
5086 sy += convert->in_x;
5087 su = FRAME_GET_U_LINE (src, convert->in_y);
5088 su += convert->in_x >> 1;
5089 sv = FRAME_GET_V_LINE (src, convert->in_y);
5090 sv += convert->in_x >> 1;
5092 d = FRAME_GET_LINE (dest, convert->out_y);
5093 d += (GST_ROUND_UP_2 (convert->out_x) * 2);
5095 n_threads = convert->conversion_runner->n_threads;
5096 tasks = convert->tasks[0] =
5097 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
5098 tasks_p = convert->tasks_p[0] =
5099 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
5101 lines_per_thread = (height + n_threads - 1) / n_threads;
5103 for (i = 0; i < n_threads; i++) {
5104 tasks[i].dstride = FRAME_GET_STRIDE (dest);
5105 tasks[i].sstride = FRAME_GET_Y_STRIDE (src);
5106 tasks[i].sustride = FRAME_GET_U_STRIDE (src);
5107 tasks[i].svstride = FRAME_GET_V_STRIDE (src);
5108 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
5109 tasks[i].s = sy + i * lines_per_thread * tasks[i].sstride;
5110 tasks[i].su = su + i * lines_per_thread * tasks[i].sustride;
5111 tasks[i].sv = sv + i * lines_per_thread * tasks[i].svstride;
5113 tasks[i].width = width;
5114 tasks[i].height = (i + 1) * lines_per_thread;
5115 tasks[i].height = MIN (tasks[i].height, height);
5116 tasks[i].height -= i * lines_per_thread;
5118 tasks_p[i] = &tasks[i];
5121 gst_parallelized_task_runner_run (convert->conversion_runner,
5122 (GstParallelizedTaskFunc) convert_Y42B_YUY2_task, (gpointer) tasks_p);
5124 convert_fill_border (convert, dest);
5128 convert_Y42B_UYVY_task (FConvertPlaneTask * task)
5130 video_orc_convert_Y42B_UYVY (task->d, task->dstride,
5131 task->s, task->sstride,
5132 task->su, task->sustride,
5133 task->sv, task->svstride, (task->width + 1) / 2, task->height);
5137 convert_Y42B_UYVY (GstVideoConverter * convert, const GstVideoFrame * src,
5138 GstVideoFrame * dest)
5140 gint width = convert->in_width;
5141 gint height = convert->in_height;
5142 guint8 *sy, *su, *sv, *d;
5143 FConvertPlaneTask *tasks;
5144 FConvertPlaneTask **tasks_p;
5146 gint lines_per_thread;
5149 sy = FRAME_GET_Y_LINE (src, convert->in_y);
5150 sy += convert->in_x;
5151 su = FRAME_GET_U_LINE (src, convert->in_y);
5152 su += convert->in_x >> 1;
5153 sv = FRAME_GET_V_LINE (src, convert->in_y);
5154 sv += convert->in_x >> 1;
5156 d = FRAME_GET_LINE (dest, convert->out_y);
5157 d += (GST_ROUND_UP_2 (convert->out_x) * 2);
5159 n_threads = convert->conversion_runner->n_threads;
5160 tasks = convert->tasks[0] =
5161 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
5162 tasks_p = convert->tasks_p[0] =
5163 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
5165 lines_per_thread = (height + n_threads - 1) / n_threads;
5167 for (i = 0; i < n_threads; i++) {
5168 tasks[i].dstride = FRAME_GET_STRIDE (dest);
5169 tasks[i].sstride = FRAME_GET_Y_STRIDE (src);
5170 tasks[i].sustride = FRAME_GET_U_STRIDE (src);
5171 tasks[i].svstride = FRAME_GET_V_STRIDE (src);
5172 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
5173 tasks[i].s = sy + i * lines_per_thread * tasks[i].sstride;
5174 tasks[i].su = su + i * lines_per_thread * tasks[i].sustride;
5175 tasks[i].sv = sv + i * lines_per_thread * tasks[i].svstride;
5177 tasks[i].width = width;
5178 tasks[i].height = (i + 1) * lines_per_thread;
5179 tasks[i].height = MIN (tasks[i].height, height);
5180 tasks[i].height -= i * lines_per_thread;
5182 tasks_p[i] = &tasks[i];
5185 gst_parallelized_task_runner_run (convert->conversion_runner,
5186 (GstParallelizedTaskFunc) convert_Y42B_UYVY_task, (gpointer) tasks_p);
5188 convert_fill_border (convert, dest);
5192 convert_Y42B_AYUV_task (FConvertPlaneTask * task)
5194 video_orc_convert_Y42B_AYUV (task->d, task->dstride, task->s,
5198 task->sv, task->svstride, task->alpha, task->width / 2, task->height);
5202 convert_Y42B_AYUV (GstVideoConverter * convert, const GstVideoFrame * src,
5203 GstVideoFrame * dest)
5205 gint width = convert->in_width;
5206 gint height = convert->in_height;
5207 guint8 *sy, *su, *sv, *d;
5208 guint8 alpha = MIN (convert->alpha_value, 255);
5209 FConvertPlaneTask *tasks;
5210 FConvertPlaneTask **tasks_p;
5212 gint lines_per_thread;
5215 sy = FRAME_GET_Y_LINE (src, convert->in_y);
5216 sy += convert->in_x;
5217 su = FRAME_GET_U_LINE (src, convert->in_y);
5218 su += convert->in_x >> 1;
5219 sv = FRAME_GET_V_LINE (src, convert->in_y);
5220 sv += convert->in_x >> 1;
5222 d = FRAME_GET_LINE (dest, convert->out_y);
5223 d += convert->out_x * 4;
5225 /* only for even width */
5226 n_threads = convert->conversion_runner->n_threads;
5227 tasks = convert->tasks[0] =
5228 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
5229 tasks_p = convert->tasks_p[0] =
5230 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
5232 lines_per_thread = (height + n_threads - 1) / n_threads;
5234 for (i = 0; i < n_threads; i++) {
5235 tasks[i].dstride = FRAME_GET_STRIDE (dest);
5236 tasks[i].sstride = FRAME_GET_Y_STRIDE (src);
5237 tasks[i].sustride = FRAME_GET_U_STRIDE (src);
5238 tasks[i].svstride = FRAME_GET_V_STRIDE (src);
5239 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
5240 tasks[i].s = sy + i * lines_per_thread * tasks[i].sstride;
5241 tasks[i].su = su + i * lines_per_thread * tasks[i].sustride;
5242 tasks[i].sv = sv + i * lines_per_thread * tasks[i].svstride;
5244 tasks[i].width = width;
5245 tasks[i].height = (i + 1) * lines_per_thread;
5246 tasks[i].height = MIN (tasks[i].height, height);
5247 tasks[i].height -= i * lines_per_thread;
5248 tasks[i].alpha = alpha;
5250 tasks_p[i] = &tasks[i];
5253 gst_parallelized_task_runner_run (convert->conversion_runner,
5254 (GstParallelizedTaskFunc) convert_Y42B_AYUV_task, (gpointer) tasks_p);
5256 convert_fill_border (convert, dest);
5260 convert_Y444_YUY2_task (FConvertPlaneTask * task)
5262 video_orc_convert_Y444_YUY2 (task->d, task->dstride, task->s,
5265 task->sustride, task->sv, task->svstride, task->width / 2, task->height);
5269 convert_Y444_YUY2 (GstVideoConverter * convert, const GstVideoFrame * src,
5270 GstVideoFrame * dest)
5272 gint width = convert->in_width;
5273 gint height = convert->in_height;
5274 guint8 *sy, *su, *sv, *d;
5275 FConvertPlaneTask *tasks;
5276 FConvertPlaneTask **tasks_p;
5278 gint lines_per_thread;
5281 sy = FRAME_GET_Y_LINE (src, convert->in_y);
5282 sy += convert->in_x;
5283 su = FRAME_GET_U_LINE (src, convert->in_y);
5284 su += convert->in_x;
5285 sv = FRAME_GET_V_LINE (src, convert->in_y);
5286 sv += convert->in_x;
5288 d = FRAME_GET_LINE (dest, convert->out_y);
5289 d += (GST_ROUND_UP_2 (convert->out_x) * 2);
5291 n_threads = convert->conversion_runner->n_threads;
5292 tasks = convert->tasks[0] =
5293 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
5294 tasks_p = convert->tasks_p[0] =
5295 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
5297 lines_per_thread = (height + n_threads - 1) / n_threads;
5299 for (i = 0; i < n_threads; i++) {
5300 tasks[i].dstride = FRAME_GET_STRIDE (dest);
5301 tasks[i].sstride = FRAME_GET_Y_STRIDE (src);
5302 tasks[i].sustride = FRAME_GET_U_STRIDE (src);
5303 tasks[i].svstride = FRAME_GET_V_STRIDE (src);
5304 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
5305 tasks[i].s = sy + i * lines_per_thread * tasks[i].sstride;
5306 tasks[i].su = su + i * lines_per_thread * tasks[i].sustride;
5307 tasks[i].sv = sv + i * lines_per_thread * tasks[i].svstride;
5309 tasks[i].width = width;
5310 tasks[i].height = (i + 1) * lines_per_thread;
5311 tasks[i].height = MIN (tasks[i].height, height);
5312 tasks[i].height -= i * lines_per_thread;
5314 tasks_p[i] = &tasks[i];
5317 gst_parallelized_task_runner_run (convert->conversion_runner,
5318 (GstParallelizedTaskFunc) convert_Y444_YUY2_task, (gpointer) tasks_p);
5320 convert_fill_border (convert, dest);
5324 convert_Y444_UYVY_task (FConvertPlaneTask * task)
5326 video_orc_convert_Y444_UYVY (task->d, task->dstride, task->s,
5329 task->sustride, task->sv, task->svstride, task->width / 2, task->height);
5333 convert_Y444_UYVY (GstVideoConverter * convert, const GstVideoFrame * src,
5334 GstVideoFrame * dest)
5336 gint width = convert->in_width;
5337 gint height = convert->in_height;
5338 guint8 *sy, *su, *sv, *d;
5339 FConvertPlaneTask *tasks;
5340 FConvertPlaneTask **tasks_p;
5342 gint lines_per_thread;
5345 sy = FRAME_GET_Y_LINE (src, convert->in_y);
5346 sy += convert->in_x;
5347 su = FRAME_GET_U_LINE (src, convert->in_y);
5348 su += convert->in_x;
5349 sv = FRAME_GET_V_LINE (src, convert->in_y);
5350 sv += convert->in_x;
5352 d = FRAME_GET_LINE (dest, convert->out_y);
5353 d += (GST_ROUND_UP_2 (convert->out_x) * 2);
5355 n_threads = convert->conversion_runner->n_threads;
5356 tasks = convert->tasks[0] =
5357 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
5358 tasks_p = convert->tasks_p[0] =
5359 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
5361 lines_per_thread = (height + n_threads - 1) / n_threads;
5363 for (i = 0; i < n_threads; i++) {
5364 tasks[i].dstride = FRAME_GET_STRIDE (dest);
5365 tasks[i].sstride = FRAME_GET_Y_STRIDE (src);
5366 tasks[i].sustride = FRAME_GET_U_STRIDE (src);
5367 tasks[i].svstride = FRAME_GET_V_STRIDE (src);
5368 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
5369 tasks[i].s = sy + i * lines_per_thread * tasks[i].sstride;
5370 tasks[i].su = su + i * lines_per_thread * tasks[i].sustride;
5371 tasks[i].sv = sv + i * lines_per_thread * tasks[i].svstride;
5373 tasks[i].width = width;
5374 tasks[i].height = (i + 1) * lines_per_thread;
5375 tasks[i].height = MIN (tasks[i].height, height);
5376 tasks[i].height -= i * lines_per_thread;
5378 tasks_p[i] = &tasks[i];
5381 gst_parallelized_task_runner_run (convert->conversion_runner,
5382 (GstParallelizedTaskFunc) convert_Y444_UYVY_task, (gpointer) tasks_p);
5384 convert_fill_border (convert, dest);
5388 convert_Y444_AYUV_task (FConvertPlaneTask * task)
5390 video_orc_convert_Y444_AYUV (task->d, task->dstride, task->s,
5394 task->sv, task->svstride, task->alpha, task->width, task->height);
5398 convert_Y444_AYUV (GstVideoConverter * convert, const GstVideoFrame * src,
5399 GstVideoFrame * dest)
5401 gint width = convert->in_width;
5402 gint height = convert->in_height;
5403 guint8 *sy, *su, *sv, *d;
5404 guint8 alpha = MIN (convert->alpha_value, 255);
5405 FConvertPlaneTask *tasks;
5406 FConvertPlaneTask **tasks_p;
5408 gint lines_per_thread;
5411 sy = FRAME_GET_Y_LINE (src, convert->in_y);
5412 sy += convert->in_x;
5413 su = FRAME_GET_U_LINE (src, convert->in_y);
5414 su += convert->in_x;
5415 sv = FRAME_GET_V_LINE (src, convert->in_y);
5416 sv += convert->in_x;
5418 d = FRAME_GET_LINE (dest, convert->out_y);
5419 d += convert->out_x * 4;
5421 n_threads = convert->conversion_runner->n_threads;
5422 tasks = convert->tasks[0] =
5423 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
5424 tasks_p = convert->tasks_p[0] =
5425 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
5427 lines_per_thread = (height + n_threads - 1) / n_threads;
5429 for (i = 0; i < n_threads; i++) {
5430 tasks[i].dstride = FRAME_GET_STRIDE (dest);
5431 tasks[i].sstride = FRAME_GET_Y_STRIDE (src);
5432 tasks[i].sustride = FRAME_GET_U_STRIDE (src);
5433 tasks[i].svstride = FRAME_GET_V_STRIDE (src);
5434 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
5435 tasks[i].s = sy + i * lines_per_thread * tasks[i].sstride;
5436 tasks[i].su = su + i * lines_per_thread * tasks[i].sustride;
5437 tasks[i].sv = sv + i * lines_per_thread * tasks[i].svstride;
5439 tasks[i].width = width;
5440 tasks[i].height = (i + 1) * lines_per_thread;
5441 tasks[i].height = MIN (tasks[i].height, height);
5442 tasks[i].height -= i * lines_per_thread;
5443 tasks[i].alpha = alpha;
5445 tasks_p[i] = &tasks[i];
5448 gst_parallelized_task_runner_run (convert->conversion_runner,
5449 (GstParallelizedTaskFunc) convert_Y444_AYUV_task, (gpointer) tasks_p);
5451 convert_fill_border (convert, dest);
5454 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
5456 convert_AYUV_ARGB_task (FConvertPlaneTask * task)
5458 video_orc_convert_AYUV_ARGB (task->d, task->dstride, task->s,
5459 task->sstride, task->data->im[0][0], task->data->im[0][2],
5460 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5461 task->width, task->height);
5465 convert_AYUV_ARGB (GstVideoConverter * convert, const GstVideoFrame * src,
5466 GstVideoFrame * dest)
5468 gint width = convert->in_width;
5469 gint height = convert->in_height;
5470 MatrixData *data = &convert->convert_matrix;
5472 FConvertPlaneTask *tasks;
5473 FConvertPlaneTask **tasks_p;
5475 gint lines_per_thread;
5478 s = FRAME_GET_LINE (src, convert->in_y);
5479 s += (convert->in_x * 4);
5480 d = FRAME_GET_LINE (dest, convert->out_y);
5481 d += (convert->out_x * 4);
5483 n_threads = convert->conversion_runner->n_threads;
5484 tasks = convert->tasks[0] =
5485 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
5486 tasks_p = convert->tasks_p[0] =
5487 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
5489 lines_per_thread = (height + n_threads - 1) / n_threads;
5491 for (i = 0; i < n_threads; i++) {
5492 tasks[i].dstride = FRAME_GET_STRIDE (dest);
5493 tasks[i].sstride = FRAME_GET_STRIDE (src);
5494 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
5495 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
5497 tasks[i].width = width;
5498 tasks[i].height = (i + 1) * lines_per_thread;
5499 tasks[i].height = MIN (tasks[i].height, height);
5500 tasks[i].height -= i * lines_per_thread;
5501 tasks[i].data = data;
5503 tasks_p[i] = &tasks[i];
5506 gst_parallelized_task_runner_run (convert->conversion_runner,
5507 (GstParallelizedTaskFunc) convert_AYUV_ARGB_task, (gpointer) tasks_p);
5509 convert_fill_border (convert, dest);
5513 convert_AYUV_BGRA_task (FConvertPlaneTask * task)
5515 video_orc_convert_AYUV_BGRA (task->d, task->dstride, task->s,
5516 task->sstride, task->data->im[0][0], task->data->im[0][2],
5517 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5518 task->width, task->height);
5522 convert_AYUV_BGRA (GstVideoConverter * convert, const GstVideoFrame * src,
5523 GstVideoFrame * dest)
5525 gint width = convert->in_width;
5526 gint height = convert->in_height;
5527 MatrixData *data = &convert->convert_matrix;
5529 FConvertPlaneTask *tasks;
5530 FConvertPlaneTask **tasks_p;
5532 gint lines_per_thread;
5535 s = FRAME_GET_LINE (src, convert->in_y);
5536 s += (convert->in_x * 4);
5537 d = FRAME_GET_LINE (dest, convert->out_y);
5538 d += (convert->out_x * 4);
5540 n_threads = convert->conversion_runner->n_threads;
5541 tasks = convert->tasks[0] =
5542 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
5543 tasks_p = convert->tasks_p[0] =
5544 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
5546 lines_per_thread = (height + n_threads - 1) / n_threads;
5548 for (i = 0; i < n_threads; i++) {
5549 tasks[i].dstride = FRAME_GET_STRIDE (dest);
5550 tasks[i].sstride = FRAME_GET_STRIDE (src);
5551 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
5552 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
5554 tasks[i].width = width;
5555 tasks[i].height = (i + 1) * lines_per_thread;
5556 tasks[i].height = MIN (tasks[i].height, height);
5557 tasks[i].height -= i * lines_per_thread;
5558 tasks[i].data = data;
5560 tasks_p[i] = &tasks[i];
5563 gst_parallelized_task_runner_run (convert->conversion_runner,
5564 (GstParallelizedTaskFunc) convert_AYUV_BGRA_task, (gpointer) tasks_p);
5566 convert_fill_border (convert, dest);
5570 convert_AYUV_ABGR_task (FConvertPlaneTask * task)
5572 video_orc_convert_AYUV_ABGR (task->d, task->dstride, task->s,
5573 task->sstride, task->data->im[0][0], task->data->im[0][2],
5574 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5575 task->width, task->height);
5579 convert_AYUV_ABGR (GstVideoConverter * convert, const GstVideoFrame * src,
5580 GstVideoFrame * dest)
5582 gint width = convert->in_width;
5583 gint height = convert->in_height;
5584 MatrixData *data = &convert->convert_matrix;
5586 FConvertPlaneTask *tasks;
5587 FConvertPlaneTask **tasks_p;
5589 gint lines_per_thread;
5592 s = FRAME_GET_LINE (src, convert->in_y);
5593 s += (convert->in_x * 4);
5594 d = FRAME_GET_LINE (dest, convert->out_y);
5595 d += (convert->out_x * 4);
5597 n_threads = convert->conversion_runner->n_threads;
5598 tasks = convert->tasks[0] =
5599 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
5600 tasks_p = convert->tasks_p[0] =
5601 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
5603 lines_per_thread = (height + n_threads - 1) / n_threads;
5605 for (i = 0; i < n_threads; i++) {
5606 tasks[i].dstride = FRAME_GET_STRIDE (dest);
5607 tasks[i].sstride = FRAME_GET_STRIDE (src);
5608 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
5609 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
5611 tasks[i].width = width;
5612 tasks[i].height = (i + 1) * lines_per_thread;
5613 tasks[i].height = MIN (tasks[i].height, height);
5614 tasks[i].height -= i * lines_per_thread;
5615 tasks[i].data = data;
5617 tasks_p[i] = &tasks[i];
5620 gst_parallelized_task_runner_run (convert->conversion_runner,
5621 (GstParallelizedTaskFunc) convert_AYUV_ABGR_task, (gpointer) tasks_p);
5623 convert_fill_border (convert, dest);
5627 convert_AYUV_RGBA_task (FConvertPlaneTask * task)
5629 video_orc_convert_AYUV_RGBA (task->d, task->dstride, task->s,
5630 task->sstride, task->data->im[0][0], task->data->im[0][2],
5631 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5632 task->width, task->height);
5636 convert_AYUV_RGBA (GstVideoConverter * convert, const GstVideoFrame * src,
5637 GstVideoFrame * dest)
5639 gint width = convert->in_width;
5640 gint height = convert->in_height;
5641 MatrixData *data = &convert->convert_matrix;
5643 FConvertPlaneTask *tasks;
5644 FConvertPlaneTask **tasks_p;
5646 gint lines_per_thread;
5649 s = FRAME_GET_LINE (src, convert->in_y);
5650 s += (convert->in_x * 4);
5651 d = FRAME_GET_LINE (dest, convert->out_y);
5652 d += (convert->out_x * 4);
5654 n_threads = convert->conversion_runner->n_threads;
5655 tasks = convert->tasks[0] =
5656 g_renew (FConvertPlaneTask, convert->tasks[0], n_threads);
5657 tasks_p = convert->tasks_p[0] =
5658 g_renew (FConvertPlaneTask *, convert->tasks_p[0], n_threads);
5660 lines_per_thread = (height + n_threads - 1) / n_threads;
5662 for (i = 0; i < n_threads; i++) {
5663 tasks[i].dstride = FRAME_GET_STRIDE (dest);
5664 tasks[i].sstride = FRAME_GET_STRIDE (src);
5665 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
5666 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
5668 tasks[i].width = width;
5669 tasks[i].height = (i + 1) * lines_per_thread;
5670 tasks[i].height = MIN (tasks[i].height, height);
5671 tasks[i].height -= i * lines_per_thread;
5672 tasks[i].data = data;
5674 tasks_p[i] = &tasks[i];
5677 gst_parallelized_task_runner_run (convert->conversion_runner,
5678 (GstParallelizedTaskFunc) convert_AYUV_RGBA_task, (gpointer) tasks_p);
5680 convert_fill_border (convert, dest);
5685 convert_I420_BGRA_task (FConvertTask * task)
5689 for (i = task->height_0; i < task->height_1; i++) {
5690 guint8 *sy, *su, *sv, *d;
5692 d = FRAME_GET_LINE (task->dest, i + task->out_y);
5693 d += (task->out_x * 4);
5694 sy = FRAME_GET_Y_LINE (task->src, i + task->in_y);
5696 su = FRAME_GET_U_LINE (task->src, (i + task->in_y) >> 1);
5697 su += (task->in_x >> 1);
5698 sv = FRAME_GET_V_LINE (task->src, (i + task->in_y) >> 1);
5699 sv += (task->in_x >> 1);
5701 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
5702 video_orc_convert_I420_BGRA (d, sy, su, sv,
5703 task->data->im[0][0], task->data->im[0][2],
5704 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5707 video_orc_convert_I420_ARGB (d, sy, su, sv,
5708 task->data->im[0][0], task->data->im[0][2],
5709 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5716 convert_I420_BGRA (GstVideoConverter * convert, const GstVideoFrame * src,
5717 GstVideoFrame * dest)
5720 gint width = convert->in_width;
5721 gint height = convert->in_height;
5722 MatrixData *data = &convert->convert_matrix;
5723 FConvertTask *tasks;
5724 FConvertTask **tasks_p;
5726 gint lines_per_thread;
5728 n_threads = convert->conversion_runner->n_threads;
5729 tasks = convert->tasks[0] =
5730 g_renew (FConvertTask, convert->tasks[0], n_threads);
5731 tasks_p = convert->tasks_p[0] =
5732 g_renew (FConvertTask *, convert->tasks_p[0], n_threads);
5734 lines_per_thread = (height + n_threads - 1) / n_threads;
5736 for (i = 0; i < n_threads; i++) {
5738 tasks[i].dest = dest;
5740 tasks[i].width = width;
5741 tasks[i].data = data;
5742 tasks[i].in_x = convert->in_x;
5743 tasks[i].in_y = convert->in_y;
5744 tasks[i].out_x = convert->out_x;
5745 tasks[i].out_y = convert->out_y;
5747 tasks[i].height_0 = i * lines_per_thread;
5748 tasks[i].height_1 = tasks[i].height_0 + lines_per_thread;
5749 tasks[i].height_1 = MIN (height, tasks[i].height_1);
5751 tasks_p[i] = &tasks[i];
5754 gst_parallelized_task_runner_run (convert->conversion_runner,
5755 (GstParallelizedTaskFunc) convert_I420_BGRA_task, (gpointer) tasks_p);
5757 convert_fill_border (convert, dest);
5761 convert_I420_ARGB_task (FConvertTask * task)
5765 for (i = task->height_0; i < task->height_1; i++) {
5766 guint8 *sy, *su, *sv, *d;
5768 d = FRAME_GET_LINE (task->dest, i + task->out_y);
5769 d += (task->out_x * 4);
5770 sy = FRAME_GET_Y_LINE (task->src, i + task->in_y);
5772 su = FRAME_GET_U_LINE (task->src, (i + task->in_y) >> 1);
5773 su += (task->in_x >> 1);
5774 sv = FRAME_GET_V_LINE (task->src, (i + task->in_y) >> 1);
5775 sv += (task->in_x >> 1);
5777 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
5778 video_orc_convert_I420_ARGB (d, sy, su, sv,
5779 task->data->im[0][0], task->data->im[0][2],
5780 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5783 video_orc_convert_I420_BGRA (d, sy, su, sv,
5784 task->data->im[0][0], task->data->im[0][2],
5785 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5792 convert_I420_ARGB (GstVideoConverter * convert, const GstVideoFrame * src,
5793 GstVideoFrame * dest)
5796 gint width = convert->in_width;
5797 gint height = convert->in_height;
5798 MatrixData *data = &convert->convert_matrix;
5799 FConvertTask *tasks;
5800 FConvertTask **tasks_p;
5802 gint lines_per_thread;
5804 n_threads = convert->conversion_runner->n_threads;
5805 tasks = convert->tasks[0] =
5806 g_renew (FConvertTask, convert->tasks[0], n_threads);
5807 tasks_p = convert->tasks_p[0] =
5808 g_renew (FConvertTask *, convert->tasks_p[0], n_threads);
5810 lines_per_thread = (height + n_threads - 1) / n_threads;
5812 for (i = 0; i < n_threads; i++) {
5814 tasks[i].dest = dest;
5816 tasks[i].width = width;
5817 tasks[i].data = data;
5818 tasks[i].in_x = convert->in_x;
5819 tasks[i].in_y = convert->in_y;
5820 tasks[i].out_x = convert->out_x;
5821 tasks[i].out_y = convert->out_y;
5823 tasks[i].height_0 = i * lines_per_thread;
5824 tasks[i].height_1 = tasks[i].height_0 + lines_per_thread;
5825 tasks[i].height_1 = MIN (height, tasks[i].height_1);
5827 tasks_p[i] = &tasks[i];
5830 gst_parallelized_task_runner_run (convert->conversion_runner,
5831 (GstParallelizedTaskFunc) convert_I420_ARGB_task, (gpointer) tasks_p);
5833 convert_fill_border (convert, dest);
5837 convert_I420_pack_ARGB_task (FConvertTask * task)
5840 gpointer d[GST_VIDEO_MAX_PLANES];
5842 d[0] = FRAME_GET_LINE (task->dest, 0);
5845 task->out_x * GST_VIDEO_FORMAT_INFO_PSTRIDE (task->dest->info.finfo, 0);
5847 for (i = task->height_0; i < task->height_1; i++) {
5848 guint8 *sy, *su, *sv;
5850 sy = FRAME_GET_Y_LINE (task->src, i + task->in_y);
5852 su = FRAME_GET_U_LINE (task->src, (i + task->in_y) >> 1);
5853 su += (task->in_x >> 1);
5854 sv = FRAME_GET_V_LINE (task->src, (i + task->in_y) >> 1);
5855 sv += (task->in_x >> 1);
5857 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
5858 video_orc_convert_I420_ARGB (task->tmpline, sy, su, sv,
5859 task->data->im[0][0], task->data->im[0][2],
5860 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5863 video_orc_convert_I420_BGRA (task->tmpline, sy, su, sv,
5864 task->data->im[0][0], task->data->im[0][2],
5865 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5868 task->dest->info.finfo->pack_func (task->dest->info.finfo,
5869 (GST_VIDEO_FRAME_IS_INTERLACED (task->dest) ?
5870 GST_VIDEO_PACK_FLAG_INTERLACED :
5871 GST_VIDEO_PACK_FLAG_NONE),
5872 task->tmpline, 0, d, task->dest->info.stride,
5873 task->dest->info.chroma_site, i + task->out_y, task->width);
5878 convert_I420_pack_ARGB (GstVideoConverter * convert, const GstVideoFrame * src,
5879 GstVideoFrame * dest)
5882 gint width = convert->in_width;
5883 gint height = convert->in_height;
5884 MatrixData *data = &convert->convert_matrix;
5885 FConvertTask *tasks;
5886 FConvertTask **tasks_p;
5888 gint lines_per_thread;
5890 n_threads = convert->conversion_runner->n_threads;
5891 tasks = convert->tasks[0] =
5892 g_renew (FConvertTask, convert->tasks[0], n_threads);
5893 tasks_p = convert->tasks_p[0] =
5894 g_renew (FConvertTask *, convert->tasks_p[0], n_threads);
5896 lines_per_thread = (height + n_threads - 1) / n_threads;
5898 for (i = 0; i < n_threads; i++) {
5900 tasks[i].dest = dest;
5902 tasks[i].width = width;
5903 tasks[i].data = data;
5904 tasks[i].in_x = convert->in_x;
5905 tasks[i].in_y = convert->in_y;
5906 tasks[i].out_x = convert->out_x;
5907 tasks[i].out_y = convert->out_y;
5908 tasks[i].tmpline = convert->tmpline[i];
5910 tasks[i].height_0 = i * lines_per_thread;
5911 tasks[i].height_1 = tasks[i].height_0 + lines_per_thread;
5912 tasks[i].height_1 = MIN (height, tasks[i].height_1);
5914 tasks_p[i] = &tasks[i];
5917 gst_parallelized_task_runner_run (convert->conversion_runner,
5918 (GstParallelizedTaskFunc) convert_I420_pack_ARGB_task,
5919 (gpointer) tasks_p);
5921 convert_fill_border (convert, dest);
5925 convert_A420_pack_ARGB_task (FConvertTask * task)
5928 gpointer d[GST_VIDEO_MAX_PLANES];
5930 d[0] = FRAME_GET_LINE (task->dest, 0);
5933 task->out_x * GST_VIDEO_FORMAT_INFO_PSTRIDE (task->dest->info.finfo, 0);
5935 for (i = task->height_0; i < task->height_1; i++) {
5936 guint8 *sy, *su, *sv, *sa;
5938 sy = FRAME_GET_Y_LINE (task->src, i + task->in_y);
5940 su = FRAME_GET_U_LINE (task->src, (i + task->in_y) >> 1);
5941 su += (task->in_x >> 1);
5942 sv = FRAME_GET_V_LINE (task->src, (i + task->in_y) >> 1);
5943 sv += (task->in_x >> 1);
5944 sa = FRAME_GET_A_LINE (task->src, i + task->in_y);
5947 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
5948 video_orc_convert_A420_ARGB (task->tmpline, sy, su, sv, sa,
5949 task->data->im[0][0], task->data->im[0][2],
5950 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5953 video_orc_convert_A420_BGRA (task->tmpline, sy, su, sv, sa,
5954 task->data->im[0][0], task->data->im[0][2],
5955 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
5959 task->dest->info.finfo->pack_func (task->dest->info.finfo,
5960 (GST_VIDEO_FRAME_IS_INTERLACED (task->dest) ?
5961 GST_VIDEO_PACK_FLAG_INTERLACED :
5962 GST_VIDEO_PACK_FLAG_NONE),
5963 task->tmpline, 0, d, task->dest->info.stride,
5964 task->dest->info.chroma_site, i + task->out_y, task->width);
5969 convert_A420_pack_ARGB (GstVideoConverter * convert, const GstVideoFrame * src,
5970 GstVideoFrame * dest)
5973 gint width = convert->in_width;
5974 gint height = convert->in_height;
5975 MatrixData *data = &convert->convert_matrix;
5976 FConvertTask *tasks;
5977 FConvertTask **tasks_p;
5979 gint lines_per_thread;
5981 n_threads = convert->conversion_runner->n_threads;
5982 tasks = convert->tasks[0] =
5983 g_renew (FConvertTask, convert->tasks[0], n_threads);
5984 tasks_p = convert->tasks_p[0] =
5985 g_renew (FConvertTask *, convert->tasks_p[0], n_threads);
5987 lines_per_thread = (height + n_threads - 1) / n_threads;
5989 for (i = 0; i < n_threads; i++) {
5991 tasks[i].dest = dest;
5993 tasks[i].width = width;
5994 tasks[i].data = data;
5995 tasks[i].in_x = convert->in_x;
5996 tasks[i].in_y = convert->in_y;
5997 tasks[i].out_x = convert->out_x;
5998 tasks[i].out_y = convert->out_y;
5999 tasks[i].tmpline = convert->tmpline[i];
6001 tasks[i].height_0 = i * lines_per_thread;
6002 tasks[i].height_1 = tasks[i].height_0 + lines_per_thread;
6003 tasks[i].height_1 = MIN (height, tasks[i].height_1);
6005 tasks_p[i] = &tasks[i];
6008 gst_parallelized_task_runner_run (convert->conversion_runner,
6009 (GstParallelizedTaskFunc) convert_A420_pack_ARGB_task,
6010 (gpointer) tasks_p);
6012 convert_fill_border (convert, dest);
6016 convert_A420_BGRA_task (FConvertTask * task)
6020 for (i = task->height_0; i < task->height_1; i++) {
6021 guint8 *sy, *su, *sv, *sa, *d;
6023 d = FRAME_GET_LINE (task->dest, i + task->out_y);
6024 d += (task->out_x * 4);
6025 sy = FRAME_GET_Y_LINE (task->src, i + task->in_y);
6027 su = FRAME_GET_U_LINE (task->src, (i + task->in_y) >> 1);
6028 su += (task->in_x >> 1);
6029 sv = FRAME_GET_V_LINE (task->src, (i + task->in_y) >> 1);
6030 sv += (task->in_x >> 1);
6031 sa = FRAME_GET_A_LINE (task->src, i + task->in_y);
6034 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
6035 video_orc_convert_A420_BGRA (d, sy, su, sv, sa,
6036 task->data->im[0][0], task->data->im[0][2],
6037 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
6040 video_orc_convert_A420_ARGB (d, sy, su, sv, sa,
6041 task->data->im[0][0], task->data->im[0][2],
6042 task->data->im[2][1], task->data->im[1][1], task->data->im[1][2],
6049 convert_A420_BGRA (GstVideoConverter * convert, const GstVideoFrame * src,
6050 GstVideoFrame * dest)
6053 gint width = convert->in_width;
6054 gint height = convert->in_height;
6055 MatrixData *data = &convert->convert_matrix;
6056 FConvertTask *tasks;
6057 FConvertTask **tasks_p;
6059 gint lines_per_thread;
6061 n_threads = convert->conversion_runner->n_threads;
6062 tasks = convert->tasks[0] =
6063 g_renew (FConvertTask, convert->tasks[0], n_threads);
6064 tasks_p = convert->tasks_p[0] =
6065 g_renew (FConvertTask *, convert->tasks_p[0], n_threads);
6067 lines_per_thread = (height + n_threads - 1) / n_threads;
6069 for (i = 0; i < n_threads; i++) {
6071 tasks[i].dest = dest;
6073 tasks[i].width = width;
6074 tasks[i].data = data;
6075 tasks[i].in_x = convert->in_x;
6076 tasks[i].in_y = convert->in_y;
6077 tasks[i].out_x = convert->out_x;
6078 tasks[i].out_y = convert->out_y;
6080 tasks[i].height_0 = i * lines_per_thread;
6081 tasks[i].height_1 = tasks[i].height_0 + lines_per_thread;
6082 tasks[i].height_1 = MIN (height, tasks[i].height_1);
6084 tasks_p[i] = &tasks[i];
6087 gst_parallelized_task_runner_run (convert->conversion_runner,
6088 (GstParallelizedTaskFunc) convert_A420_BGRA_task, (gpointer) tasks_p);
6090 convert_fill_border (convert, dest);
6094 memset_u24 (guint8 * data, guint8 col[3], unsigned int n)
6098 for (i = 0; i < n; i++) {
6107 memset_u32_16 (guint8 * data, guint8 col[4], unsigned int n)
6111 for (i = 0; i < n; i += 2) {
6122 #define MAKE_BORDER_FUNC(func) \
6123 for (i = 0; i < out_y; i++) \
6124 func (FRAME_GET_PLANE_LINE (dest, k, i), col, out_maxwidth); \
6125 if (rb_width || lb_width) { \
6126 for (i = 0; i < out_height; i++) { \
6127 guint8 *d = FRAME_GET_PLANE_LINE (dest, k, i + out_y); \
6129 func (d, col, lb_width); \
6131 func (d + (pstride * r_border), col, rb_width); \
6134 for (i = out_y + out_height; i < out_maxheight; i++) \
6135 func (FRAME_GET_PLANE_LINE (dest, k, i), col, out_maxwidth); \
6138 convert_fill_border (GstVideoConverter * convert, GstVideoFrame * dest)
6141 const GstVideoFormatInfo *out_finfo;
6143 if (!convert->fill_border || !convert->borderline)
6146 out_finfo = convert->out_info.finfo;
6148 n_planes = GST_VIDEO_FRAME_N_PLANES (dest);
6150 for (k = 0; k < n_planes; k++) {
6151 gint comp[GST_VIDEO_MAX_COMPONENTS];
6152 gint i, out_x, out_y, out_width, out_height, pstride, pgroup;
6153 gint r_border, lb_width, rb_width;
6154 gint out_maxwidth, out_maxheight;
6157 gst_video_format_info_component (out_finfo, k, comp);
6158 out_x = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo, comp[0],
6160 out_y = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_finfo, comp[0],
6162 out_width = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo, comp[0],
6163 convert->out_width);
6164 out_height = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_finfo, comp[0],
6165 convert->out_height);
6166 out_maxwidth = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo, comp[0],
6167 convert->out_maxwidth);
6168 out_maxheight = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_finfo, comp[0],
6169 convert->out_maxheight);
6171 pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (out_finfo, comp[0]);
6173 switch (GST_VIDEO_FORMAT_INFO_FORMAT (out_finfo)) {
6174 case GST_VIDEO_FORMAT_YUY2:
6175 case GST_VIDEO_FORMAT_YVYU:
6176 case GST_VIDEO_FORMAT_UYVY:
6178 out_maxwidth = GST_ROUND_UP_2 (out_maxwidth);
6185 r_border = out_x + out_width;
6186 rb_width = out_maxwidth - r_border;
6189 borders = &convert->borders[k];
6194 guint8 col = ((guint8 *) borders)[0];
6195 MAKE_BORDER_FUNC (memset);
6200 guint16 col = ((guint16 *) borders)[0];
6201 MAKE_BORDER_FUNC (video_orc_splat_u16);
6207 col[0] = ((guint8 *) borders)[0];
6208 col[1] = ((guint8 *) borders)[1];
6209 col[2] = ((guint8 *) borders)[2];
6210 MAKE_BORDER_FUNC (memset_u24);
6215 guint32 col = ((guint32 *) borders)[0];
6216 MAKE_BORDER_FUNC (video_orc_splat_u32);
6221 guint64 col = ((guint64 *) borders)[0];
6222 MAKE_BORDER_FUNC (video_orc_splat_u64);
6228 col[0] = ((guint8 *) borders)[0];
6229 col[2] = ((guint8 *) borders)[2];
6230 col[1] = ((guint8 *) borders)[r_border & 1 ? 3 : 1];
6231 col[3] = ((guint8 *) borders)[r_border & 1 ? 1 : 3];
6232 MAKE_BORDER_FUNC (memset_u32_16);
6243 const guint8 *s, *s2;
6245 gint sstride, dstride;
6251 convert_plane_fill_task (FSimpleScaleTask * task)
6253 video_orc_memset_2d (task->d, task->dstride,
6254 task->fill, task->width, task->height);
6258 convert_plane_fill (GstVideoConverter * convert,
6259 const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
6262 FSimpleScaleTask *tasks;
6263 FSimpleScaleTask **tasks_p;
6265 gint lines_per_thread;
6268 d = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
6269 d += convert->fout_x[plane];
6271 n_threads = convert->conversion_runner->n_threads;
6272 tasks = convert->tasks[plane] =
6273 g_renew (FSimpleScaleTask, convert->tasks[plane], n_threads);
6274 tasks_p = convert->tasks_p[plane] =
6275 g_renew (FSimpleScaleTask *, convert->tasks_p[plane], n_threads);
6276 lines_per_thread = (convert->fout_height[plane] + n_threads - 1) / n_threads;
6278 for (i = 0; i < n_threads; i++) {
6279 tasks[i].d = d + i * lines_per_thread * convert->fout_width[plane];
6281 tasks[i].fill = convert->ffill[plane];
6282 tasks[i].width = convert->fout_width[plane];
6283 tasks[i].height = (i + 1) * lines_per_thread;
6284 tasks[i].height = MIN (tasks[i].height, convert->fout_height[plane]);
6285 tasks[i].height -= i * lines_per_thread;
6286 tasks[i].dstride = FRAME_GET_PLANE_STRIDE (dest, plane);
6288 tasks_p[i] = &tasks[i];
6291 gst_parallelized_task_runner_run (convert->conversion_runner,
6292 (GstParallelizedTaskFunc) convert_plane_fill_task, (gpointer) tasks_p);
6296 convert_plane_h_double_task (FSimpleScaleTask * task)
6298 video_orc_planar_chroma_422_444 (task->d,
6299 task->dstride, task->s, task->sstride, task->width / 2, task->height);
6303 convert_plane_h_double (GstVideoConverter * convert,
6304 const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
6307 gint splane = convert->fsplane[plane];
6308 FSimpleScaleTask *tasks;
6309 FSimpleScaleTask **tasks_p;
6311 gint lines_per_thread;
6314 s = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
6315 s += convert->fin_x[splane];
6316 d = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
6317 d += convert->fout_x[plane];
6319 n_threads = convert->conversion_runner->n_threads;
6320 tasks = convert->tasks[plane] =
6321 g_renew (FSimpleScaleTask, convert->tasks[plane], n_threads);
6322 tasks_p = convert->tasks_p[plane] =
6323 g_renew (FSimpleScaleTask *, convert->tasks_p[plane], n_threads);
6324 lines_per_thread = (convert->fout_height[plane] + n_threads - 1) / n_threads;
6326 for (i = 0; i < n_threads; i++) {
6327 tasks[i].dstride = FRAME_GET_PLANE_STRIDE (dest, plane);
6328 tasks[i].sstride = FRAME_GET_PLANE_STRIDE (src, splane);
6330 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
6331 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
6333 tasks[i].width = convert->fout_width[plane];
6334 tasks[i].height = (i + 1) * lines_per_thread;
6335 tasks[i].height = MIN (tasks[i].height, convert->fout_height[plane]);
6336 tasks[i].height -= i * lines_per_thread;
6338 tasks_p[i] = &tasks[i];
6341 gst_parallelized_task_runner_run (convert->conversion_runner,
6342 (GstParallelizedTaskFunc) convert_plane_h_double_task,
6343 (gpointer) tasks_p);
6347 convert_plane_h_halve_task (FSimpleScaleTask * task)
6349 video_orc_planar_chroma_444_422 (task->d,
6350 task->dstride, task->s, task->sstride, task->width, task->height);
6354 convert_plane_h_halve (GstVideoConverter * convert,
6355 const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
6358 gint splane = convert->fsplane[plane];
6359 FSimpleScaleTask *tasks;
6360 FSimpleScaleTask **tasks_p;
6362 gint lines_per_thread;
6365 s = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
6366 s += convert->fin_x[splane];
6367 d = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
6368 d += convert->fout_x[plane];
6370 n_threads = convert->conversion_runner->n_threads;
6371 tasks = convert->tasks[plane] =
6372 g_renew (FSimpleScaleTask, convert->tasks[plane], n_threads);
6373 tasks_p = convert->tasks_p[plane] =
6374 g_renew (FSimpleScaleTask *, convert->tasks_p[plane], n_threads);
6375 lines_per_thread = (convert->fout_height[plane] + n_threads - 1) / n_threads;
6377 for (i = 0; i < n_threads; i++) {
6378 tasks[i].dstride = FRAME_GET_PLANE_STRIDE (dest, plane);
6379 tasks[i].sstride = FRAME_GET_PLANE_STRIDE (src, splane);
6381 tasks[i].d = d + i * lines_per_thread * tasks[i].dstride;
6382 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride;
6384 tasks[i].width = convert->fout_width[plane];
6385 tasks[i].height = (i + 1) * lines_per_thread;
6386 tasks[i].height = MIN (tasks[i].height, convert->fout_height[plane]);
6387 tasks[i].height -= i * lines_per_thread;
6389 tasks_p[i] = &tasks[i];
6392 gst_parallelized_task_runner_run (convert->conversion_runner,
6393 (GstParallelizedTaskFunc) convert_plane_h_halve_task, (gpointer) tasks_p);
6397 convert_plane_v_double_task (FSimpleScaleTask * task)
6399 video_orc_planar_chroma_420_422 (task->d, 2 * task->dstride, task->d2,
6400 2 * task->dstride, task->s, task->sstride, task->width, task->height / 2);
6404 convert_plane_v_double (GstVideoConverter * convert,
6405 const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
6407 guint8 *s, *d1, *d2;
6408 gint ds, splane = convert->fsplane[plane];
6409 FSimpleScaleTask *tasks;
6410 FSimpleScaleTask **tasks_p;
6412 gint lines_per_thread;
6415 s = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
6416 s += convert->fin_x[splane];
6417 d1 = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
6418 d1 += convert->fout_x[plane];
6419 d2 = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane] + 1);
6420 d2 += convert->fout_x[plane];
6421 ds = FRAME_GET_PLANE_STRIDE (dest, plane);
6423 n_threads = convert->conversion_runner->n_threads;
6424 tasks = convert->tasks[plane] =
6425 g_renew (FSimpleScaleTask, convert->tasks[plane], n_threads);
6426 tasks_p = convert->tasks_p[plane] =
6427 g_renew (FSimpleScaleTask *, convert->tasks_p[plane], n_threads);
6429 GST_ROUND_UP_2 ((convert->fout_height[plane] + n_threads -
6432 for (i = 0; i < n_threads; i++) {
6433 tasks[i].d = d1 + i * lines_per_thread * ds;
6434 tasks[i].d2 = d2 + i * lines_per_thread * ds;
6435 tasks[i].dstride = ds;
6436 tasks[i].sstride = FRAME_GET_PLANE_STRIDE (src, splane);
6437 tasks[i].s = s + i * lines_per_thread * tasks[i].sstride / 2;
6439 tasks[i].width = convert->fout_width[plane];
6440 tasks[i].height = (i + 1) * lines_per_thread;
6441 tasks[i].height = MIN (tasks[i].height, convert->fout_height[plane]);
6442 tasks[i].height -= i * lines_per_thread;
6444 tasks_p[i] = &tasks[i];
6447 gst_parallelized_task_runner_run (convert->conversion_runner,
6448 (GstParallelizedTaskFunc) convert_plane_v_double_task,
6449 (gpointer) tasks_p);
6453 convert_plane_v_halve_task (FSimpleScaleTask * task)
6455 video_orc_planar_chroma_422_420 (task->d, task->dstride, task->s,
6456 2 * task->sstride, task->s2, 2 * task->sstride, task->width,
6461 convert_plane_v_halve (GstVideoConverter * convert,
6462 const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
6464 guint8 *s1, *s2, *d;
6465 gint ss, ds, splane = convert->fsplane[plane];
6466 FSimpleScaleTask *tasks;
6467 FSimpleScaleTask **tasks_p;
6469 gint lines_per_thread;
6472 s1 = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
6473 s1 += convert->fin_x[splane];
6474 s2 = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane] + 1);
6475 s2 += convert->fin_x[splane];
6476 d = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
6477 d += convert->fout_x[plane];
6479 ss = FRAME_GET_PLANE_STRIDE (src, splane);
6480 ds = FRAME_GET_PLANE_STRIDE (dest, plane);
6482 n_threads = convert->conversion_runner->n_threads;
6483 tasks = convert->tasks[plane] =
6484 g_renew (FSimpleScaleTask, convert->tasks[plane], n_threads);
6485 tasks_p = convert->tasks_p[plane] =
6486 g_renew (FSimpleScaleTask *, convert->tasks_p[plane], n_threads);
6487 lines_per_thread = (convert->fout_height[plane] + n_threads - 1) / n_threads;
6489 for (i = 0; i < n_threads; i++) {
6490 tasks[i].d = d + i * lines_per_thread * ds;
6491 tasks[i].dstride = ds;
6492 tasks[i].s = s1 + i * lines_per_thread * ss * 2;
6493 tasks[i].s2 = s2 + i * lines_per_thread * ss * 2;
6494 tasks[i].sstride = ss;
6496 tasks[i].width = convert->fout_width[plane];
6497 tasks[i].height = (i + 1) * lines_per_thread;
6498 tasks[i].height = MIN (tasks[i].height, convert->fout_height[plane]);
6499 tasks[i].height -= i * lines_per_thread;
6501 tasks_p[i] = &tasks[i];
6504 gst_parallelized_task_runner_run (convert->conversion_runner,
6505 (GstParallelizedTaskFunc) convert_plane_v_halve_task, (gpointer) tasks_p);
6509 convert_plane_hv_double_task (FSimpleScaleTask * task)
6511 video_orc_planar_chroma_420_444 (task->d, 2 * task->dstride, task->d2,
6512 2 * task->dstride, task->s, task->sstride, (task->width + 1) / 2,
6517 convert_plane_hv_double (GstVideoConverter * convert,
6518 const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
6520 guint8 *s, *d1, *d2;
6521 gint ss, ds, splane = convert->fsplane[plane];
6522 FSimpleScaleTask *tasks;
6523 FSimpleScaleTask **tasks_p;
6525 gint lines_per_thread;
6528 s = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
6529 s += convert->fin_x[splane];
6530 d1 = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
6531 d1 += convert->fout_x[plane];
6532 d2 = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane] + 1);
6533 d2 += convert->fout_x[plane];
6534 ss = FRAME_GET_PLANE_STRIDE (src, splane);
6535 ds = FRAME_GET_PLANE_STRIDE (dest, plane);
6537 n_threads = convert->conversion_runner->n_threads;
6538 tasks = convert->tasks[plane] =
6539 g_renew (FSimpleScaleTask, convert->tasks[plane], n_threads);
6540 tasks_p = convert->tasks_p[plane] =
6541 g_renew (FSimpleScaleTask *, convert->tasks_p[plane], n_threads);
6543 GST_ROUND_UP_2 ((convert->fout_height[plane] + n_threads -
6546 for (i = 0; i < n_threads; i++) {
6547 tasks[i].d = d1 + i * lines_per_thread * ds;
6548 tasks[i].d2 = d2 + i * lines_per_thread * ds;
6549 tasks[i].dstride = ds;
6550 tasks[i].sstride = ss;
6551 tasks[i].s = s + i * lines_per_thread * ss / 2;
6553 tasks[i].width = convert->fout_width[plane];
6554 tasks[i].height = (i + 1) * lines_per_thread;
6555 tasks[i].height = MIN (tasks[i].height, convert->fout_height[plane]);
6556 tasks[i].height -= i * lines_per_thread;
6558 tasks_p[i] = &tasks[i];
6561 gst_parallelized_task_runner_run (convert->conversion_runner,
6562 (GstParallelizedTaskFunc) convert_plane_hv_double_task,
6563 (gpointer) tasks_p);
6567 convert_plane_hv_halve_task (FSimpleScaleTask * task)
6569 video_orc_planar_chroma_444_420 (task->d, task->dstride, task->s,
6570 2 * task->sstride, task->s2, 2 * task->sstride, task->width,
6575 convert_plane_hv_halve (GstVideoConverter * convert,
6576 const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
6578 guint8 *s1, *s2, *d;
6579 gint ss, ds, splane = convert->fsplane[plane];
6580 FSimpleScaleTask *tasks;
6581 FSimpleScaleTask **tasks_p;
6583 gint lines_per_thread;
6586 s1 = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
6587 s1 += convert->fin_x[splane];
6588 s2 = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane] + 1);
6589 s2 += convert->fin_x[splane];
6590 d = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
6591 d += convert->fout_x[plane];
6592 ss = FRAME_GET_PLANE_STRIDE (src, splane);
6593 ds = FRAME_GET_PLANE_STRIDE (dest, plane);
6595 n_threads = convert->conversion_runner->n_threads;
6596 tasks = convert->tasks[plane] =
6597 g_renew (FSimpleScaleTask, convert->tasks[plane], n_threads);
6598 tasks_p = convert->tasks_p[plane] =
6599 g_renew (FSimpleScaleTask *, convert->tasks_p[plane], n_threads);
6600 lines_per_thread = (convert->fout_height[plane] + n_threads - 1) / n_threads;
6602 for (i = 0; i < n_threads; i++) {
6603 tasks[i].d = d + i * lines_per_thread * ds;
6604 tasks[i].dstride = ds;
6605 tasks[i].s = s1 + i * lines_per_thread * ss * 2;
6606 tasks[i].s2 = s2 + i * lines_per_thread * ss * 2;
6607 tasks[i].sstride = ss;
6609 tasks[i].width = convert->fout_width[plane];
6610 tasks[i].height = (i + 1) * lines_per_thread;
6611 tasks[i].height = MIN (tasks[i].height, convert->fout_height[plane]);
6612 tasks[i].height -= i * lines_per_thread;
6614 tasks_p[i] = &tasks[i];
6617 gst_parallelized_task_runner_run (convert->conversion_runner,
6618 (GstParallelizedTaskFunc) convert_plane_hv_halve_task,
6619 (gpointer) tasks_p);
6624 GstVideoScaler *h_scaler, *v_scaler;
6625 GstVideoFormat format;
6628 gint sstride, dstride;
6633 convert_plane_hv_task (FScaleTask * task)
6635 gst_video_scaler_2d (task->h_scaler, task->v_scaler, task->format,
6636 (guint8 *) task->s, task->sstride,
6637 task->d, task->dstride, task->x, task->y, task->w, task->h);
6641 convert_plane_hv (GstVideoConverter * convert,
6642 const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
6644 gint in_x, in_y, out_x, out_y, out_width, out_height;
6645 GstVideoFormat format;
6646 gint splane = convert->fsplane[plane];
6648 gint sstride, dstride;
6650 FScaleTask **tasks_p;
6651 gint i, n_threads, lines_per_thread;
6653 in_x = convert->fin_x[splane];
6654 in_y = convert->fin_y[splane];
6655 out_x = convert->fout_x[plane];
6656 out_y = convert->fout_y[plane];
6657 out_width = convert->fout_width[plane];
6658 out_height = convert->fout_height[plane];
6659 format = convert->fformat[plane];
6661 s = FRAME_GET_PLANE_LINE (src, splane, in_y);
6663 d = FRAME_GET_PLANE_LINE (dest, plane, out_y);
6666 sstride = FRAME_GET_PLANE_STRIDE (src, splane);
6667 dstride = FRAME_GET_PLANE_STRIDE (dest, plane);
6669 n_threads = convert->conversion_runner->n_threads;
6670 tasks = convert->tasks[plane] =
6671 g_renew (FScaleTask, convert->tasks[plane], n_threads);
6672 tasks_p = convert->tasks_p[plane] =
6673 g_renew (FScaleTask *, convert->tasks_p[plane], n_threads);
6675 lines_per_thread = (out_height + n_threads - 1) / n_threads;
6677 for (i = 0; i < n_threads; i++) {
6679 convert->fh_scaler[plane].scaler ? convert->
6680 fh_scaler[plane].scaler[i] : NULL;
6682 convert->fv_scaler[plane].scaler ? convert->
6683 fv_scaler[plane].scaler[i] : NULL;
6684 tasks[i].format = format;
6687 tasks[i].sstride = sstride;
6688 tasks[i].dstride = dstride;
6691 tasks[i].w = out_width;
6693 tasks[i].y = i * lines_per_thread;
6694 tasks[i].h = tasks[i].y + lines_per_thread;
6695 tasks[i].h = MIN (out_height, tasks[i].h);
6697 tasks_p[i] = &tasks[i];
6700 gst_parallelized_task_runner_run (convert->conversion_runner,
6701 (GstParallelizedTaskFunc) convert_plane_hv_task, (gpointer) tasks_p);
6705 convert_scale_planes (GstVideoConverter * convert,
6706 const GstVideoFrame * src, GstVideoFrame * dest)
6710 n_planes = GST_VIDEO_FRAME_N_PLANES (dest);
6711 for (i = 0; i < n_planes; i++) {
6712 if (convert->fconvert[i])
6713 convert->fconvert[i] (convert, src, dest, i);
6715 convert_fill_border (convert, dest);
6720 convert_I420_SN12 (GstVideoConverter * convert, const GstVideoFrame * src,
6721 GstVideoFrame * dst)
6723 guint8 *src_Y = NULL;
6724 guint8 *src_U = NULL;
6725 guint8 *src_V = NULL;
6726 guint8 *dst_Y = NULL;
6727 guint8 *dst_UV = NULL;
6731 gint width = convert->in_width;
6732 gint height = convert->in_height;
6733 gint loop_count_Y = GST_ROUND_DOWN_2 (height);
6734 gint loop_count_UV = GST_ROUND_UP_2 (width) >> 1;
6736 gint src_stride_Y = GST_VIDEO_FRAME_PLANE_STRIDE (src, 0);
6737 gint src_stride_U = GST_VIDEO_FRAME_PLANE_STRIDE (src, 1);
6738 gint src_stride_diff = src_stride_U - loop_count_UV;
6740 gint dst_stride_Y = GST_VIDEO_FRAME_PLANE_STRIDE (dst, 0);
6741 gint dst_stride_UV = GST_VIDEO_FRAME_PLANE_STRIDE (dst, 1);
6742 gint dst_stride_diff = GST_ROUND_DOWN_2 (dst_stride_UV - width);
6744 src_Y = GST_VIDEO_FRAME_PLANE_DATA (src, 0);
6745 src_U = GST_VIDEO_FRAME_PLANE_DATA (src, 1);
6746 src_V = GST_VIDEO_FRAME_PLANE_DATA (src, 2);
6748 dst_Y = GST_VIDEO_FRAME_PLANE_DATA (dst, 0);
6749 dst_UV = GST_VIDEO_FRAME_PLANE_DATA (dst, 1);
6751 GST_DEBUG_OBJECT (convert, "size %dx%d, stride src[0:%d,1:%d], dst[0:%d,1:%d]",
6752 width, height, src_stride_Y, src_stride_U, dst_stride_Y, dst_stride_UV);
6754 for (i = 0 ; i < loop_count_Y ; i += 2) {
6755 memcpy (dst_Y, src_Y, width);
6756 src_Y += src_stride_Y;
6757 dst_Y += dst_stride_Y;
6759 memcpy (dst_Y, src_Y, width);
6760 src_Y += src_stride_Y;
6761 dst_Y += dst_stride_Y;
6763 for (j = 0 ; j < loop_count_UV ; j++) {
6764 *dst_UV++ = *src_U++;
6765 *dst_UV++ = *src_V++;
6767 src_U += src_stride_diff;
6768 src_V += src_stride_diff;
6769 dst_UV += dst_stride_diff;
6774 static GstVideoFormat
6775 get_scale_format (GstVideoFormat format, gint plane)
6777 GstVideoFormat res = GST_VIDEO_FORMAT_UNKNOWN;
6780 case GST_VIDEO_FORMAT_I420:
6781 case GST_VIDEO_FORMAT_YV12:
6782 case GST_VIDEO_FORMAT_Y41B:
6783 case GST_VIDEO_FORMAT_Y42B:
6784 case GST_VIDEO_FORMAT_Y444:
6785 case GST_VIDEO_FORMAT_GRAY8:
6786 case GST_VIDEO_FORMAT_A420:
6787 case GST_VIDEO_FORMAT_YUV9:
6788 case GST_VIDEO_FORMAT_YVU9:
6789 case GST_VIDEO_FORMAT_GBR:
6790 case GST_VIDEO_FORMAT_GBRA:
6791 case GST_VIDEO_FORMAT_RGBP:
6792 case GST_VIDEO_FORMAT_BGRP:
6793 res = GST_VIDEO_FORMAT_GRAY8;
6795 case GST_VIDEO_FORMAT_GRAY16_BE:
6796 case GST_VIDEO_FORMAT_GRAY16_LE:
6797 res = GST_VIDEO_FORMAT_GRAY16_BE;
6799 case GST_VIDEO_FORMAT_YUY2:
6800 case GST_VIDEO_FORMAT_UYVY:
6801 case GST_VIDEO_FORMAT_VYUY:
6802 case GST_VIDEO_FORMAT_YVYU:
6803 case GST_VIDEO_FORMAT_AYUV:
6804 case GST_VIDEO_FORMAT_VUYA:
6805 case GST_VIDEO_FORMAT_RGBx:
6806 case GST_VIDEO_FORMAT_BGRx:
6807 case GST_VIDEO_FORMAT_xRGB:
6808 case GST_VIDEO_FORMAT_xBGR:
6809 case GST_VIDEO_FORMAT_RGBA:
6810 case GST_VIDEO_FORMAT_BGRA:
6811 case GST_VIDEO_FORMAT_ARGB:
6812 case GST_VIDEO_FORMAT_ABGR:
6813 case GST_VIDEO_FORMAT_RGB:
6814 case GST_VIDEO_FORMAT_BGR:
6815 case GST_VIDEO_FORMAT_v308:
6816 case GST_VIDEO_FORMAT_IYU2:
6817 case GST_VIDEO_FORMAT_ARGB64:
6818 case GST_VIDEO_FORMAT_AYUV64:
6821 case GST_VIDEO_FORMAT_RGB15:
6822 case GST_VIDEO_FORMAT_BGR15:
6823 case GST_VIDEO_FORMAT_RGB16:
6824 case GST_VIDEO_FORMAT_BGR16:
6825 res = GST_VIDEO_FORMAT_NV12;
6827 case GST_VIDEO_FORMAT_NV12:
6828 case GST_VIDEO_FORMAT_NV21:
6829 case GST_VIDEO_FORMAT_NV16:
6830 case GST_VIDEO_FORMAT_NV61:
6831 case GST_VIDEO_FORMAT_NV24:
6832 res = plane == 0 ? GST_VIDEO_FORMAT_GRAY8 : GST_VIDEO_FORMAT_NV12;
6834 case GST_VIDEO_FORMAT_AV12:
6836 || plane == 2) ? GST_VIDEO_FORMAT_GRAY8 : GST_VIDEO_FORMAT_NV12;
6838 case GST_VIDEO_FORMAT_UNKNOWN:
6839 case GST_VIDEO_FORMAT_ENCODED:
6840 case GST_VIDEO_FORMAT_v210:
6841 case GST_VIDEO_FORMAT_v216:
6842 case GST_VIDEO_FORMAT_Y210:
6843 case GST_VIDEO_FORMAT_Y410:
6844 case GST_VIDEO_FORMAT_UYVP:
6845 case GST_VIDEO_FORMAT_RGB8P:
6846 case GST_VIDEO_FORMAT_IYU1:
6847 case GST_VIDEO_FORMAT_r210:
6848 case GST_VIDEO_FORMAT_I420_10BE:
6849 case GST_VIDEO_FORMAT_I420_10LE:
6850 case GST_VIDEO_FORMAT_I422_10BE:
6851 case GST_VIDEO_FORMAT_I422_10LE:
6852 case GST_VIDEO_FORMAT_Y444_10BE:
6853 case GST_VIDEO_FORMAT_Y444_10LE:
6854 case GST_VIDEO_FORMAT_I420_12BE:
6855 case GST_VIDEO_FORMAT_I420_12LE:
6856 case GST_VIDEO_FORMAT_I422_12BE:
6857 case GST_VIDEO_FORMAT_I422_12LE:
6858 case GST_VIDEO_FORMAT_Y444_12BE:
6859 case GST_VIDEO_FORMAT_Y444_12LE:
6860 case GST_VIDEO_FORMAT_GBR_10BE:
6861 case GST_VIDEO_FORMAT_GBR_10LE:
6862 case GST_VIDEO_FORMAT_GBRA_10BE:
6863 case GST_VIDEO_FORMAT_GBRA_10LE:
6864 case GST_VIDEO_FORMAT_GBR_12BE:
6865 case GST_VIDEO_FORMAT_GBR_12LE:
6866 case GST_VIDEO_FORMAT_GBRA_12BE:
6867 case GST_VIDEO_FORMAT_GBRA_12LE:
6868 case GST_VIDEO_FORMAT_NV12_64Z32:
6869 case GST_VIDEO_FORMAT_NV12_4L4:
6870 case GST_VIDEO_FORMAT_NV12_32L32:
6871 case GST_VIDEO_FORMAT_A420_10BE:
6872 case GST_VIDEO_FORMAT_A420_10LE:
6873 case GST_VIDEO_FORMAT_A422_10BE:
6874 case GST_VIDEO_FORMAT_A422_10LE:
6875 case GST_VIDEO_FORMAT_A444_10BE:
6876 case GST_VIDEO_FORMAT_A444_10LE:
6877 case GST_VIDEO_FORMAT_P010_10BE:
6878 case GST_VIDEO_FORMAT_P010_10LE:
6879 case GST_VIDEO_FORMAT_GRAY10_LE32:
6880 case GST_VIDEO_FORMAT_NV12_10LE32:
6881 case GST_VIDEO_FORMAT_NV16_10LE32:
6882 case GST_VIDEO_FORMAT_NV12_10LE40:
6883 case GST_VIDEO_FORMAT_BGR10A2_LE:
6885 case GST_VIDEO_FORMAT_SN12:
6886 case GST_VIDEO_FORMAT_ST12:
6888 case GST_VIDEO_FORMAT_RGB10A2_LE:
6889 case GST_VIDEO_FORMAT_Y444_16BE:
6890 case GST_VIDEO_FORMAT_Y444_16LE:
6891 case GST_VIDEO_FORMAT_P016_BE:
6892 case GST_VIDEO_FORMAT_P016_LE:
6893 case GST_VIDEO_FORMAT_P012_BE:
6894 case GST_VIDEO_FORMAT_P012_LE:
6895 case GST_VIDEO_FORMAT_Y212_BE:
6896 case GST_VIDEO_FORMAT_Y212_LE:
6897 case GST_VIDEO_FORMAT_Y412_BE:
6898 case GST_VIDEO_FORMAT_Y412_LE:
6900 g_assert_not_reached ();
6902 #ifdef TIZEN_FEATURE_VIDEO_MODIFICATION
6911 is_merge_yuv (GstVideoInfo * info)
6913 switch (GST_VIDEO_INFO_FORMAT (info)) {
6914 case GST_VIDEO_FORMAT_YUY2:
6915 case GST_VIDEO_FORMAT_YVYU:
6916 case GST_VIDEO_FORMAT_UYVY:
6917 case GST_VIDEO_FORMAT_VYUY:
6925 setup_scale (GstVideoConverter * convert)
6928 gint method, cr_method, in_width, in_height, out_width, out_height;
6930 GstVideoInfo *in_info, *out_info;
6931 const GstVideoFormatInfo *in_finfo, *out_finfo;
6932 GstVideoFormat in_format, out_format;
6933 gboolean interlaced;
6934 guint n_threads = convert->conversion_runner->n_threads;
6936 in_info = &convert->in_info;
6937 out_info = &convert->out_info;
6939 in_finfo = in_info->finfo;
6940 out_finfo = out_info->finfo;
6942 n_planes = GST_VIDEO_INFO_N_PLANES (out_info);
6944 interlaced = GST_VIDEO_INFO_IS_INTERLACED (&convert->in_info)
6945 && GST_VIDEO_INFO_INTERLACE_MODE (&convert->in_info) !=
6946 GST_VIDEO_INTERLACE_MODE_ALTERNATE;
6948 method = GET_OPT_RESAMPLER_METHOD (convert);
6949 if (method == GST_VIDEO_RESAMPLER_METHOD_NEAREST)
6952 cr_method = GET_OPT_CHROMA_RESAMPLER_METHOD (convert);
6953 taps = GET_OPT_RESAMPLER_TAPS (convert);
6955 in_format = GST_VIDEO_INFO_FORMAT (in_info);
6956 out_format = GST_VIDEO_INFO_FORMAT (out_info);
6959 if(out_format == GST_VIDEO_FORMAT_SN12) {
6960 /* do nothing for SN12 output format */
6964 switch (in_format) {
6965 case GST_VIDEO_FORMAT_RGB15:
6966 case GST_VIDEO_FORMAT_RGB16:
6967 case GST_VIDEO_FORMAT_BGR15:
6968 case GST_VIDEO_FORMAT_BGR16:
6969 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
6970 case GST_VIDEO_FORMAT_GRAY16_BE:
6972 case GST_VIDEO_FORMAT_GRAY16_LE:
6974 if (method != GST_VIDEO_RESAMPLER_METHOD_NEAREST) {
6975 GST_DEBUG ("%s only with nearest resampling",
6976 gst_video_format_to_string (in_format));
6981 case GST_VIDEO_FORMAT_SN12:
6982 return TRUE; /* do nothing for SN12 format */
6988 in_width = convert->in_width;
6989 in_height = convert->in_height;
6990 out_width = convert->out_width;
6991 out_height = convert->out_height;
6993 if (n_planes == 1 && !GST_VIDEO_FORMAT_INFO_IS_GRAY (out_finfo)) {
6997 if (is_merge_yuv (in_info)) {
6998 GstVideoScaler *y_scaler, *uv_scaler;
7000 if (in_width != out_width) {
7001 convert->fh_scaler[0].scaler = g_new (GstVideoScaler *, n_threads);
7002 for (j = 0; j < n_threads; j++) {
7004 gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
7005 GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, GST_VIDEO_COMP_Y,
7006 in_width), GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo,
7007 GST_VIDEO_COMP_Y, out_width), convert->config);
7009 gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE,
7010 gst_video_scaler_get_max_taps (y_scaler),
7011 GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, GST_VIDEO_COMP_U,
7012 in_width), GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo,
7013 GST_VIDEO_COMP_U, out_width), convert->config);
7015 convert->fh_scaler[0].scaler[j] =
7016 gst_video_scaler_combine_packed_YUV (y_scaler, uv_scaler,
7017 in_format, out_format);
7019 gst_video_scaler_free (y_scaler);
7020 gst_video_scaler_free (uv_scaler);
7023 convert->fh_scaler[0].scaler = NULL;
7026 pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (out_finfo, GST_VIDEO_COMP_Y);
7027 convert->fin_x[0] = GST_ROUND_UP_2 (convert->in_x) * pstride;
7028 convert->fout_x[0] = GST_ROUND_UP_2 (convert->out_x) * pstride;
7031 if (in_width != out_width && in_width != 0 && out_width != 0) {
7032 convert->fh_scaler[0].scaler = g_new (GstVideoScaler *, n_threads);
7033 for (j = 0; j < n_threads; j++) {
7034 convert->fh_scaler[0].scaler[j] =
7035 gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
7036 in_width, out_width, convert->config);
7039 convert->fh_scaler[0].scaler = NULL;
7042 pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (out_finfo, GST_VIDEO_COMP_R);
7043 convert->fin_x[0] = convert->in_x * pstride;
7044 convert->fout_x[0] = convert->out_x * pstride;
7047 if (in_height != out_height && in_height != 0 && out_height != 0) {
7048 convert->fv_scaler[0].scaler = g_new (GstVideoScaler *, n_threads);
7050 for (j = 0; j < n_threads; j++) {
7051 convert->fv_scaler[0].scaler[j] =
7052 gst_video_scaler_new (method,
7054 GST_VIDEO_SCALER_FLAG_INTERLACED : GST_VIDEO_SCALER_FLAG_NONE, taps,
7055 in_height, out_height, convert->config);
7058 convert->fv_scaler[0].scaler = NULL;
7061 convert->fin_y[0] = convert->in_y;
7062 convert->fout_y[0] = convert->out_y;
7063 convert->fout_width[0] = out_width;
7064 convert->fout_height[0] = out_height;
7065 convert->fconvert[0] = convert_plane_hv;
7066 convert->fformat[0] = get_scale_format (in_format, 0);
7067 convert->fsplane[0] = 0;
7069 for (i = 0; i < n_planes; i++) {
7070 gint out_comp[GST_VIDEO_MAX_COMPONENTS];
7071 gint comp, j, iw, ih, ow, oh, pstride;
7072 gboolean need_v_scaler, need_h_scaler;
7073 GstStructure *config;
7074 gint resample_method;
7076 gst_video_format_info_component (out_finfo, i, out_comp);
7077 ow = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo, out_comp[0],
7079 oh = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_finfo, out_comp[0],
7081 pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (out_finfo, out_comp[0]);
7083 /* find the component in this plane and map it to the plane of
7085 if (out_comp[0] < GST_VIDEO_FORMAT_INFO_N_COMPONENTS (in_finfo)) {
7087 iw = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, comp, in_width);
7088 ih = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (in_finfo, comp, in_height);
7089 convert->fin_x[i] = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, comp,
7091 convert->fin_x[i] *= pstride;
7092 convert->fin_y[i] = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (in_finfo, comp,
7095 /* we will use a fill instead, setting the parameters to an invalid
7096 * size to reduce confusion */
7099 convert->fin_x[i] = -1;
7100 convert->fin_y[i] = -1;
7103 convert->fout_width[i] = ow;
7104 convert->fout_height[i] = oh;
7106 convert->fout_x[i] = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo,
7107 out_comp[0], convert->out_x);
7108 convert->fout_x[i] *= pstride;
7109 convert->fout_y[i] = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_finfo,
7110 out_comp[0], convert->out_y);
7112 GST_DEBUG ("plane %d: %dx%d -> %dx%d", i, iw, ih, ow, oh);
7113 GST_DEBUG ("plane %d: pstride %d", i, pstride);
7114 GST_DEBUG ("plane %d: in_x %d, in_y %d", i, convert->fin_x[i],
7116 GST_DEBUG ("plane %d: out_x %d, out_y %d", i, convert->fout_x[i],
7117 convert->fout_y[i]);
7120 convert->fconvert[i] = convert_plane_fill;
7121 if (GST_VIDEO_INFO_IS_YUV (out_info)) {
7123 convert->ffill[i] = convert->alpha_value;
7125 convert->ffill[i] = 0x00;
7127 convert->ffill[i] = 0x80;
7130 convert->ffill[i] = convert->alpha_value;
7132 convert->ffill[i] = 0x00;
7134 GST_DEBUG ("plane %d fill %02x", i, convert->ffill[i]);
7137 convert->fsplane[i] = GST_VIDEO_FORMAT_INFO_PLANE (in_finfo, comp);
7138 GST_DEBUG ("plane %d -> %d (comp %d)", i, convert->fsplane[i], comp);
7141 config = gst_structure_copy (convert->config);
7143 resample_method = (i == 0 ? method : cr_method);
7145 need_v_scaler = FALSE;
7146 need_h_scaler = FALSE;
7148 if (!interlaced && ih == oh) {
7149 convert->fconvert[i] = convert_plane_hv;
7150 GST_DEBUG ("plane %d: copy", i);
7151 } else if (!interlaced && ih == 2 * oh && pstride == 1
7152 && resample_method == GST_VIDEO_RESAMPLER_METHOD_LINEAR) {
7153 convert->fconvert[i] = convert_plane_v_halve;
7154 GST_DEBUG ("plane %d: vertical halve", i);
7155 } else if (!interlaced && 2 * ih == oh && pstride == 1
7156 && resample_method == GST_VIDEO_RESAMPLER_METHOD_NEAREST) {
7157 convert->fconvert[i] = convert_plane_v_double;
7158 GST_DEBUG ("plane %d: vertical double", i);
7160 convert->fconvert[i] = convert_plane_hv;
7161 GST_DEBUG ("plane %d: vertical scale", i);
7162 need_v_scaler = TRUE;
7164 } else if (ih == oh) {
7165 if (!interlaced && iw == 2 * ow && pstride == 1
7166 && resample_method == GST_VIDEO_RESAMPLER_METHOD_LINEAR) {
7167 convert->fconvert[i] = convert_plane_h_halve;
7168 GST_DEBUG ("plane %d: horizontal halve", i);
7169 } else if (!interlaced && 2 * iw == ow && pstride == 1
7170 && resample_method == GST_VIDEO_RESAMPLER_METHOD_NEAREST) {
7171 convert->fconvert[i] = convert_plane_h_double;
7172 GST_DEBUG ("plane %d: horizontal double", i);
7174 convert->fconvert[i] = convert_plane_hv;
7175 GST_DEBUG ("plane %d: horizontal scale", i);
7176 need_h_scaler = TRUE;
7179 if (!interlaced && iw == 2 * ow && ih == 2 * oh && pstride == 1
7180 && resample_method == GST_VIDEO_RESAMPLER_METHOD_LINEAR) {
7181 convert->fconvert[i] = convert_plane_hv_halve;
7182 GST_DEBUG ("plane %d: horizontal/vertical halve", i);
7183 } else if (!interlaced && 2 * iw == ow && 2 * ih == oh && pstride == 1
7184 && resample_method == GST_VIDEO_RESAMPLER_METHOD_NEAREST) {
7185 convert->fconvert[i] = convert_plane_hv_double;
7186 GST_DEBUG ("plane %d: horizontal/vertical double", i);
7188 convert->fconvert[i] = convert_plane_hv;
7189 GST_DEBUG ("plane %d: horizontal/vertical scale", i);
7190 need_v_scaler = TRUE;
7191 need_h_scaler = TRUE;
7195 if (need_h_scaler && iw != 0 && ow != 0) {
7196 convert->fh_scaler[i].scaler = g_new (GstVideoScaler *, n_threads);
7198 for (j = 0; j < n_threads; j++) {
7199 convert->fh_scaler[i].scaler[j] =
7200 gst_video_scaler_new (resample_method, GST_VIDEO_SCALER_FLAG_NONE,
7201 taps, iw, ow, config);
7204 convert->fh_scaler[i].scaler = NULL;
7207 if (need_v_scaler && ih != 0 && oh != 0) {
7208 convert->fv_scaler[i].scaler = g_new (GstVideoScaler *, n_threads);
7210 for (j = 0; j < n_threads; j++) {
7211 convert->fv_scaler[i].scaler[j] =
7212 gst_video_scaler_new (resample_method,
7214 GST_VIDEO_SCALER_FLAG_INTERLACED : GST_VIDEO_SCALER_FLAG_NONE,
7215 taps, ih, oh, config);
7218 convert->fv_scaler[i].scaler = NULL;
7221 gst_structure_free (config);
7222 convert->fformat[i] = get_scale_format (in_format, i);
7233 GstVideoFormat in_format;
7234 GstVideoFormat out_format;
7235 gboolean keeps_interlaced;
7236 gboolean needs_color_matrix;
7237 gboolean keeps_size;
7240 gboolean alpha_copy;
7242 gboolean alpha_mult;
7243 gint width_align, height_align;
7244 void (*convert) (GstVideoConverter * convert, const GstVideoFrame * src,
7245 GstVideoFrame * dest);
7248 static const VideoTransform transforms[] = {
7249 /* planar -> packed */
7250 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_YUY2, TRUE, FALSE, TRUE, FALSE,
7251 FALSE, FALSE, FALSE, FALSE, 0, 0, convert_I420_YUY2},
7252 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_UYVY, TRUE, FALSE, TRUE, FALSE,
7253 FALSE, FALSE, FALSE, FALSE, 0, 0, convert_I420_UYVY},
7254 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_AYUV, TRUE, FALSE, TRUE, FALSE,
7255 FALSE, FALSE, TRUE, FALSE, 0, 0, convert_I420_AYUV},
7257 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_YUY2, TRUE, FALSE, TRUE, FALSE,
7258 FALSE, FALSE, FALSE, FALSE, 0, 0, convert_I420_YUY2},
7259 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_UYVY, TRUE, FALSE, TRUE, FALSE,
7260 FALSE, FALSE, FALSE, FALSE, 0, 0, convert_I420_UYVY},
7261 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_AYUV, TRUE, FALSE, TRUE, FALSE,
7262 FALSE, FALSE, TRUE, FALSE, 0, 0, convert_I420_AYUV},
7264 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_YUY2, TRUE, FALSE, TRUE, TRUE,
7265 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_Y42B_YUY2},
7266 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_UYVY, TRUE, FALSE, TRUE, TRUE,
7267 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_Y42B_UYVY},
7268 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_AYUV, TRUE, FALSE, TRUE, TRUE,
7269 TRUE, FALSE, TRUE, FALSE, 1, 0, convert_Y42B_AYUV},
7271 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_YUY2, TRUE, FALSE, TRUE, TRUE,
7272 TRUE, FALSE, FALSE, FALSE, 1, 0, convert_Y444_YUY2},
7273 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_UYVY, TRUE, FALSE, TRUE, TRUE,
7274 TRUE, FALSE, FALSE, FALSE, 1, 0, convert_Y444_UYVY},
7275 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_AYUV, TRUE, FALSE, TRUE, TRUE,
7276 TRUE, FALSE, TRUE, FALSE, 0, 0, convert_Y444_AYUV},
7278 /* packed -> packed */
7279 {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_YUY2, TRUE, FALSE, FALSE, TRUE,
7280 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7281 {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_UYVY, TRUE, FALSE, TRUE, TRUE,
7282 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_UYVY_YUY2}, /* alias */
7283 {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_AYUV, TRUE, FALSE, TRUE, TRUE,
7284 TRUE, FALSE, TRUE, FALSE, 1, 0, convert_YUY2_AYUV},
7286 {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_UYVY, TRUE, FALSE, FALSE, TRUE,
7287 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7288 {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_YUY2, TRUE, FALSE, TRUE, TRUE,
7289 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_UYVY_YUY2},
7290 {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_AYUV, TRUE, FALSE, TRUE, TRUE,
7291 TRUE, FALSE, TRUE, FALSE, 0, 0, convert_UYVY_AYUV},
7293 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_AYUV, TRUE, FALSE, FALSE, TRUE, TRUE,
7294 TRUE, FALSE, FALSE, 0, 0, convert_scale_planes},
7295 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_YUY2, TRUE, FALSE, TRUE, TRUE,
7296 TRUE, FALSE, FALSE, FALSE, 1, 0, convert_AYUV_YUY2},
7297 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_UYVY, TRUE, FALSE, TRUE, TRUE,
7298 TRUE, FALSE, FALSE, FALSE, 1, 0, convert_AYUV_UYVY},
7300 {GST_VIDEO_FORMAT_v210, GST_VIDEO_FORMAT_UYVY, TRUE, FALSE, TRUE, FALSE,
7301 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_v210_UYVY},
7302 {GST_VIDEO_FORMAT_v210, GST_VIDEO_FORMAT_YUY2, TRUE, FALSE, TRUE, FALSE,
7303 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_v210_YUY2},
7305 /* packed -> planar */
7306 {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_I420, TRUE, FALSE, TRUE, FALSE,
7307 FALSE, FALSE, FALSE, FALSE, 0, 0, convert_YUY2_I420},
7308 {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_YV12, TRUE, FALSE, TRUE, FALSE,
7309 FALSE, FALSE, FALSE, FALSE, 0, 0, convert_YUY2_I420},
7310 {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_Y42B, TRUE, FALSE, TRUE, TRUE,
7311 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_YUY2_Y42B},
7312 {GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_Y444, TRUE, FALSE, TRUE, TRUE,
7313 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_YUY2_Y444},
7314 {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_GRAY8, TRUE, TRUE, TRUE, TRUE,
7315 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_UYVY_GRAY8},
7317 {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_I420, TRUE, FALSE, TRUE, FALSE,
7318 FALSE, FALSE, FALSE, FALSE, 0, 0, convert_UYVY_I420},
7319 {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_YV12, TRUE, FALSE, TRUE, FALSE,
7320 FALSE, FALSE, FALSE, FALSE, 0, 0, convert_UYVY_I420},
7321 {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_Y42B, TRUE, FALSE, TRUE, TRUE,
7322 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_UYVY_Y42B},
7323 {GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_Y444, TRUE, FALSE, TRUE, TRUE,
7324 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_UYVY_Y444},
7326 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_I420, FALSE, FALSE, TRUE, TRUE,
7327 TRUE, FALSE, FALSE, FALSE, 1, 1, convert_AYUV_I420},
7328 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, TRUE, TRUE,
7329 TRUE, FALSE, FALSE, FALSE, 1, 1, convert_AYUV_I420},
7330 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_Y42B, TRUE, FALSE, TRUE, TRUE,
7331 TRUE, FALSE, FALSE, FALSE, 1, 0, convert_AYUV_Y42B},
7332 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_Y444, TRUE, FALSE, TRUE, TRUE,
7333 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_AYUV_Y444},
7335 {GST_VIDEO_FORMAT_v210, GST_VIDEO_FORMAT_I420, TRUE, FALSE, TRUE, FALSE,
7336 FALSE, FALSE, FALSE, FALSE, 0, 0, convert_v210_I420},
7337 {GST_VIDEO_FORMAT_v210, GST_VIDEO_FORMAT_YV12, TRUE, FALSE, TRUE, FALSE,
7338 FALSE, FALSE, FALSE, FALSE, 0, 0, convert_v210_I420},
7339 {GST_VIDEO_FORMAT_v210, GST_VIDEO_FORMAT_Y42B, TRUE, FALSE, TRUE, FALSE,
7340 FALSE, FALSE, FALSE, FALSE, 0, 0, convert_v210_Y42B},
7342 /* planar -> planar */
7343 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_I420, TRUE, FALSE, FALSE, TRUE,
7344 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7345 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_YV12, TRUE, FALSE, FALSE, TRUE,
7346 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7347 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_Y41B, FALSE, FALSE, FALSE, TRUE,
7348 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7349 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, FALSE, TRUE,
7350 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7351 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, FALSE, TRUE,
7352 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7354 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_SN12, FALSE, FALSE, FALSE, TRUE,
7355 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_SN12},
7357 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_GRAY8, FALSE, FALSE, FALSE, TRUE,
7358 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7359 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_A420, FALSE, FALSE, FALSE, TRUE,
7360 TRUE, FALSE, TRUE, FALSE, 0, 0, convert_scale_planes},
7361 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_YUV9, FALSE, FALSE, FALSE, TRUE,
7362 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7363 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_YVU9, FALSE, FALSE, FALSE, TRUE,
7364 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7366 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_I420, TRUE, FALSE, FALSE, TRUE,
7367 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7368 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_YV12, TRUE, FALSE, FALSE, TRUE,
7369 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7370 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_Y41B, FALSE, FALSE, FALSE, TRUE,
7371 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7372 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, FALSE, TRUE,
7373 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7374 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, FALSE, TRUE,
7375 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7376 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_GRAY8, FALSE, FALSE, FALSE, TRUE,
7377 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7378 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_A420, FALSE, FALSE, FALSE, TRUE,
7379 TRUE, FALSE, TRUE, FALSE, 0, 0, convert_scale_planes},
7380 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_YUV9, FALSE, FALSE, FALSE, TRUE,
7381 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7382 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_YVU9, FALSE, FALSE, FALSE, TRUE,
7383 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7385 {GST_VIDEO_FORMAT_Y41B, GST_VIDEO_FORMAT_I420, FALSE, FALSE, FALSE, TRUE,
7386 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7387 {GST_VIDEO_FORMAT_Y41B, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, FALSE, TRUE,
7388 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7389 {GST_VIDEO_FORMAT_Y41B, GST_VIDEO_FORMAT_Y41B, TRUE, FALSE, FALSE, TRUE,
7390 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7391 {GST_VIDEO_FORMAT_Y41B, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, FALSE, TRUE,
7392 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7393 {GST_VIDEO_FORMAT_Y41B, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, FALSE, TRUE,
7394 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7395 {GST_VIDEO_FORMAT_Y41B, GST_VIDEO_FORMAT_GRAY8, FALSE, FALSE, FALSE, TRUE,
7396 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7397 {GST_VIDEO_FORMAT_Y41B, GST_VIDEO_FORMAT_A420, FALSE, FALSE, FALSE, TRUE,
7398 TRUE, FALSE, TRUE, FALSE, 0, 0, convert_scale_planes},
7399 {GST_VIDEO_FORMAT_Y41B, GST_VIDEO_FORMAT_YUV9, FALSE, FALSE, FALSE, TRUE,
7400 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7401 {GST_VIDEO_FORMAT_Y41B, GST_VIDEO_FORMAT_YVU9, FALSE, FALSE, FALSE, TRUE,
7402 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7404 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_I420, FALSE, FALSE, FALSE, TRUE,
7405 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7406 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, FALSE, TRUE,
7407 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7408 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_Y41B, FALSE, FALSE, FALSE, TRUE,
7409 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7410 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_Y42B, TRUE, FALSE, FALSE, TRUE,
7411 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7412 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, FALSE, TRUE,
7413 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7414 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_GRAY8, FALSE, FALSE, FALSE, TRUE,
7415 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7416 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_A420, FALSE, FALSE, FALSE, TRUE,
7417 TRUE, FALSE, TRUE, FALSE, 0, 0, convert_scale_planes},
7418 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_YUV9, FALSE, FALSE, FALSE, TRUE,
7419 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7420 {GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_YVU9, FALSE, FALSE, FALSE, TRUE,
7421 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7423 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_I420, FALSE, FALSE, FALSE, TRUE,
7424 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7425 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, FALSE, TRUE,
7426 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7427 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_Y41B, FALSE, FALSE, FALSE, TRUE,
7428 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7429 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, FALSE, TRUE,
7430 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7431 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_Y444, TRUE, FALSE, FALSE, TRUE,
7432 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7433 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_GRAY8, FALSE, FALSE, FALSE, TRUE,
7434 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7435 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_A420, FALSE, FALSE, FALSE, TRUE,
7436 TRUE, FALSE, TRUE, FALSE, 0, 0, convert_scale_planes},
7437 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_YUV9, FALSE, FALSE, FALSE, TRUE,
7438 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7439 {GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_YVU9, FALSE, FALSE, FALSE, TRUE,
7440 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7442 {GST_VIDEO_FORMAT_GRAY8, GST_VIDEO_FORMAT_I420, FALSE, FALSE, FALSE, TRUE,
7443 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7444 {GST_VIDEO_FORMAT_GRAY8, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, FALSE, TRUE,
7445 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7446 {GST_VIDEO_FORMAT_GRAY8, GST_VIDEO_FORMAT_Y41B, FALSE, FALSE, FALSE, TRUE,
7447 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7448 {GST_VIDEO_FORMAT_GRAY8, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, FALSE, TRUE,
7449 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7450 {GST_VIDEO_FORMAT_GRAY8, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, FALSE, TRUE,
7451 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7452 {GST_VIDEO_FORMAT_GRAY8, GST_VIDEO_FORMAT_GRAY8, TRUE, FALSE, FALSE, TRUE,
7453 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7454 {GST_VIDEO_FORMAT_GRAY8, GST_VIDEO_FORMAT_A420, FALSE, FALSE, FALSE, TRUE,
7455 TRUE, FALSE, TRUE, FALSE, 0, 0, convert_scale_planes},
7456 {GST_VIDEO_FORMAT_GRAY8, GST_VIDEO_FORMAT_YUV9, FALSE, FALSE, FALSE, TRUE,
7457 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7458 {GST_VIDEO_FORMAT_GRAY8, GST_VIDEO_FORMAT_YVU9, FALSE, FALSE, FALSE, TRUE,
7459 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7461 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_I420, FALSE, FALSE, FALSE, TRUE,
7462 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7463 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, FALSE, TRUE,
7464 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7465 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_Y41B, FALSE, FALSE, FALSE, TRUE,
7466 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7467 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, FALSE, TRUE,
7468 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7469 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, FALSE, TRUE,
7470 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7471 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_GRAY8, FALSE, FALSE, FALSE, TRUE,
7472 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7473 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_A420, TRUE, FALSE, FALSE, TRUE,
7474 TRUE, TRUE, FALSE, FALSE, 0, 0, convert_scale_planes},
7475 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_YUV9, FALSE, FALSE, FALSE, TRUE,
7476 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7477 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_YVU9, FALSE, FALSE, FALSE, TRUE,
7478 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7480 {GST_VIDEO_FORMAT_YUV9, GST_VIDEO_FORMAT_I420, FALSE, FALSE, FALSE, TRUE,
7481 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7482 {GST_VIDEO_FORMAT_YUV9, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, FALSE, TRUE,
7483 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7484 {GST_VIDEO_FORMAT_YUV9, GST_VIDEO_FORMAT_Y41B, FALSE, FALSE, FALSE, TRUE,
7485 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7486 {GST_VIDEO_FORMAT_YUV9, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, FALSE, TRUE,
7487 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7488 {GST_VIDEO_FORMAT_YUV9, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, FALSE, TRUE,
7489 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7490 {GST_VIDEO_FORMAT_YUV9, GST_VIDEO_FORMAT_GRAY8, FALSE, FALSE, FALSE, TRUE,
7491 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7492 {GST_VIDEO_FORMAT_YUV9, GST_VIDEO_FORMAT_A420, FALSE, FALSE, FALSE, TRUE,
7493 TRUE, FALSE, TRUE, FALSE, 0, 0, convert_scale_planes},
7494 {GST_VIDEO_FORMAT_YUV9, GST_VIDEO_FORMAT_YUV9, TRUE, FALSE, FALSE, TRUE,
7495 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7496 {GST_VIDEO_FORMAT_YUV9, GST_VIDEO_FORMAT_YVU9, TRUE, FALSE, FALSE, TRUE,
7497 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7499 {GST_VIDEO_FORMAT_YVU9, GST_VIDEO_FORMAT_I420, FALSE, FALSE, FALSE, TRUE,
7500 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7501 {GST_VIDEO_FORMAT_YVU9, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, FALSE, TRUE,
7502 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7503 {GST_VIDEO_FORMAT_YVU9, GST_VIDEO_FORMAT_Y41B, FALSE, FALSE, FALSE, TRUE,
7504 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7505 {GST_VIDEO_FORMAT_YVU9, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, FALSE, TRUE,
7506 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7507 {GST_VIDEO_FORMAT_YVU9, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, FALSE, TRUE,
7508 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7509 {GST_VIDEO_FORMAT_YVU9, GST_VIDEO_FORMAT_GRAY8, FALSE, FALSE, FALSE, TRUE,
7510 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7511 {GST_VIDEO_FORMAT_YVU9, GST_VIDEO_FORMAT_A420, FALSE, FALSE, FALSE, TRUE,
7512 TRUE, FALSE, TRUE, FALSE, 0, 0, convert_scale_planes},
7513 {GST_VIDEO_FORMAT_YVU9, GST_VIDEO_FORMAT_YUV9, TRUE, FALSE, FALSE, TRUE,
7514 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7515 {GST_VIDEO_FORMAT_YVU9, GST_VIDEO_FORMAT_YVU9, TRUE, FALSE, FALSE, TRUE,
7516 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7518 /* sempiplanar -> semiplanar */
7519 {GST_VIDEO_FORMAT_NV12, GST_VIDEO_FORMAT_NV12, TRUE, FALSE, FALSE, TRUE,
7520 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7521 {GST_VIDEO_FORMAT_NV12, GST_VIDEO_FORMAT_NV16, TRUE, FALSE, FALSE, TRUE,
7522 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7523 {GST_VIDEO_FORMAT_NV12, GST_VIDEO_FORMAT_NV24, TRUE, FALSE, FALSE, TRUE,
7524 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7526 {GST_VIDEO_FORMAT_NV21, GST_VIDEO_FORMAT_NV21, TRUE, FALSE, FALSE, TRUE,
7527 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7529 {GST_VIDEO_FORMAT_NV16, GST_VIDEO_FORMAT_NV12, TRUE, FALSE, FALSE, TRUE,
7530 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7531 {GST_VIDEO_FORMAT_NV16, GST_VIDEO_FORMAT_NV16, TRUE, FALSE, FALSE, TRUE,
7532 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7533 {GST_VIDEO_FORMAT_NV16, GST_VIDEO_FORMAT_NV24, TRUE, FALSE, FALSE, TRUE,
7534 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7536 {GST_VIDEO_FORMAT_NV61, GST_VIDEO_FORMAT_NV61, TRUE, FALSE, FALSE, TRUE,
7537 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7539 {GST_VIDEO_FORMAT_NV24, GST_VIDEO_FORMAT_NV12, TRUE, FALSE, FALSE, TRUE,
7540 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7541 {GST_VIDEO_FORMAT_NV24, GST_VIDEO_FORMAT_NV16, TRUE, FALSE, FALSE, TRUE,
7542 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7543 {GST_VIDEO_FORMAT_NV24, GST_VIDEO_FORMAT_NV24, TRUE, FALSE, FALSE, TRUE,
7544 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7546 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
7547 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_ARGB, TRUE, TRUE, TRUE, TRUE, TRUE,
7548 TRUE, FALSE, FALSE, 0, 0, convert_AYUV_ARGB},
7549 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_BGRA, TRUE, TRUE, TRUE, TRUE, TRUE,
7550 TRUE, FALSE, FALSE, 0, 0, convert_AYUV_BGRA},
7551 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_xRGB, TRUE, TRUE, TRUE, TRUE, TRUE,
7552 FALSE, FALSE, FALSE, 0, 0, convert_AYUV_ARGB}, /* alias */
7553 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_BGRx, TRUE, TRUE, TRUE, TRUE, TRUE,
7554 FALSE, FALSE, FALSE, 0, 0, convert_AYUV_BGRA}, /* alias */
7555 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_ABGR, TRUE, TRUE, TRUE, TRUE, TRUE,
7556 TRUE, FALSE, FALSE, 0, 0, convert_AYUV_ABGR},
7557 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_RGBA, TRUE, TRUE, TRUE, TRUE, TRUE,
7558 TRUE, FALSE, FALSE, 0, 0, convert_AYUV_RGBA},
7559 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_xBGR, TRUE, TRUE, TRUE, TRUE, TRUE,
7560 FALSE, FALSE, FALSE, 0, 0, convert_AYUV_ABGR}, /* alias */
7561 {GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_RGBx, TRUE, TRUE, TRUE, TRUE, TRUE,
7562 FALSE, FALSE, FALSE, 0, 0, convert_AYUV_RGBA}, /* alias */
7565 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_BGRA, FALSE, TRUE, TRUE, TRUE,
7566 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_BGRA},
7567 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_BGRx, FALSE, TRUE, TRUE, TRUE,
7568 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_BGRA},
7569 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_BGRA, FALSE, TRUE, TRUE, TRUE,
7570 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_BGRA},
7571 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_BGRx, FALSE, TRUE, TRUE, TRUE,
7572 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_BGRA},
7574 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_ARGB, FALSE, TRUE, TRUE, TRUE,
7575 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_ARGB},
7576 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_xRGB, FALSE, TRUE, TRUE, TRUE,
7577 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_ARGB},
7578 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_ARGB, FALSE, TRUE, TRUE, TRUE,
7579 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_ARGB},
7580 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_xRGB, FALSE, TRUE, TRUE, TRUE,
7581 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_ARGB},
7583 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_ABGR, FALSE, TRUE, TRUE, TRUE,
7584 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7585 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_xBGR, FALSE, TRUE, TRUE, TRUE,
7586 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7587 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_RGBA, FALSE, TRUE, TRUE, TRUE,
7588 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7589 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_RGBx, FALSE, TRUE, TRUE, TRUE,
7590 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7591 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_RGB, FALSE, TRUE, TRUE, TRUE,
7592 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7593 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_BGR, FALSE, TRUE, TRUE, TRUE,
7594 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7595 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_RGB15, FALSE, TRUE, TRUE, TRUE,
7596 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7597 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_BGR15, FALSE, TRUE, TRUE, TRUE,
7598 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7599 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_RGB16, FALSE, TRUE, TRUE, TRUE,
7600 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7601 {GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_BGR16, FALSE, TRUE, TRUE, TRUE,
7602 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7604 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_ABGR, FALSE, TRUE, TRUE, TRUE,
7605 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7606 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_xBGR, FALSE, TRUE, TRUE, TRUE,
7607 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7608 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_RGBA, FALSE, TRUE, TRUE, TRUE,
7609 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7610 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_RGBx, FALSE, TRUE, TRUE, TRUE,
7611 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7612 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_RGB, FALSE, TRUE, TRUE, TRUE,
7613 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7614 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_BGR, FALSE, TRUE, TRUE, TRUE,
7615 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7616 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_RGB15, FALSE, TRUE, TRUE, TRUE,
7617 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7618 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_BGR15, FALSE, TRUE, TRUE, TRUE,
7619 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7620 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_RGB16, FALSE, TRUE, TRUE, TRUE,
7621 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7622 {GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_BGR16, FALSE, TRUE, TRUE, TRUE,
7623 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7625 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_ABGR, FALSE, TRUE, TRUE, TRUE,
7626 TRUE, TRUE, FALSE, FALSE, 0, 0, convert_A420_pack_ARGB},
7627 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_RGBA, FALSE, TRUE, TRUE, TRUE,
7628 TRUE, TRUE, FALSE, FALSE, 0, 0, convert_A420_pack_ARGB},
7629 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_BGRA, FALSE, TRUE, TRUE, TRUE,
7630 TRUE, TRUE, FALSE, FALSE, 0, 0, convert_A420_BGRA},
7631 /* A420 to non-alpha RGB formats, reuse I420_* method */
7632 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_BGRx, FALSE, TRUE, TRUE, TRUE,
7633 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_BGRA},
7634 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_xBGR, FALSE, TRUE, TRUE, TRUE,
7635 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7636 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_RGBx, FALSE, TRUE, TRUE, TRUE,
7637 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7638 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_RGB, FALSE, TRUE, TRUE, TRUE,
7639 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7640 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_BGR, FALSE, TRUE, TRUE, TRUE,
7641 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7642 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_RGB15, FALSE, TRUE, TRUE, TRUE,
7643 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7644 {GST_VIDEO_FORMAT_A420, GST_VIDEO_FORMAT_BGR16, FALSE, TRUE, TRUE, TRUE,
7645 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_I420_pack_ARGB},
7648 {GST_VIDEO_FORMAT_GBR, GST_VIDEO_FORMAT_GBR, TRUE, FALSE, FALSE, TRUE,
7649 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7650 {GST_VIDEO_FORMAT_GBRA, GST_VIDEO_FORMAT_GBRA, TRUE, FALSE, FALSE, TRUE,
7651 TRUE, TRUE, FALSE, FALSE, 0, 0, convert_scale_planes},
7652 {GST_VIDEO_FORMAT_RGBP, GST_VIDEO_FORMAT_RGBP, TRUE, FALSE, FALSE, TRUE,
7653 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7654 {GST_VIDEO_FORMAT_BGRP, GST_VIDEO_FORMAT_BGRP, TRUE, FALSE, FALSE, TRUE,
7655 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7657 {GST_VIDEO_FORMAT_YVYU, GST_VIDEO_FORMAT_YVYU, TRUE, FALSE, FALSE, TRUE,
7658 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7660 {GST_VIDEO_FORMAT_RGB15, GST_VIDEO_FORMAT_RGB15, TRUE, FALSE, FALSE, TRUE,
7661 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7662 {GST_VIDEO_FORMAT_RGB16, GST_VIDEO_FORMAT_RGB16, TRUE, FALSE, FALSE, TRUE,
7663 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7664 {GST_VIDEO_FORMAT_BGR15, GST_VIDEO_FORMAT_BGR15, TRUE, FALSE, FALSE, TRUE,
7665 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7666 {GST_VIDEO_FORMAT_BGR16, GST_VIDEO_FORMAT_BGR16, TRUE, FALSE, FALSE, TRUE,
7667 TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7669 {GST_VIDEO_FORMAT_RGB, GST_VIDEO_FORMAT_RGB, TRUE, FALSE, FALSE, TRUE, TRUE,
7670 FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7671 {GST_VIDEO_FORMAT_BGR, GST_VIDEO_FORMAT_BGR, TRUE, FALSE, FALSE, TRUE, TRUE,
7672 FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7673 {GST_VIDEO_FORMAT_v308, GST_VIDEO_FORMAT_v308, TRUE, FALSE, FALSE, TRUE, TRUE,
7674 FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7675 {GST_VIDEO_FORMAT_IYU2, GST_VIDEO_FORMAT_IYU2, TRUE, FALSE, FALSE, TRUE, TRUE,
7676 FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7678 {GST_VIDEO_FORMAT_ARGB, GST_VIDEO_FORMAT_ARGB, TRUE, FALSE, FALSE, TRUE, TRUE,
7679 TRUE, FALSE, FALSE, 0, 0, convert_scale_planes},
7680 {GST_VIDEO_FORMAT_xRGB, GST_VIDEO_FORMAT_xRGB, TRUE, FALSE, FALSE, TRUE, TRUE,
7681 FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7682 {GST_VIDEO_FORMAT_ABGR, GST_VIDEO_FORMAT_ABGR, TRUE, FALSE, FALSE, TRUE, TRUE,
7683 TRUE, FALSE, FALSE, 0, 0, convert_scale_planes},
7684 {GST_VIDEO_FORMAT_xBGR, GST_VIDEO_FORMAT_xBGR, TRUE, FALSE, FALSE, TRUE, TRUE,
7685 FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7686 {GST_VIDEO_FORMAT_RGBA, GST_VIDEO_FORMAT_RGBA, TRUE, FALSE, FALSE, TRUE, TRUE,
7687 TRUE, FALSE, FALSE, 0, 0, convert_scale_planes},
7688 {GST_VIDEO_FORMAT_RGBx, GST_VIDEO_FORMAT_RGBx, TRUE, FALSE, FALSE, TRUE, TRUE,
7689 FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7690 {GST_VIDEO_FORMAT_BGRA, GST_VIDEO_FORMAT_BGRA, TRUE, FALSE, FALSE, TRUE, TRUE,
7691 TRUE, FALSE, FALSE, 0, 0, convert_scale_planes},
7692 {GST_VIDEO_FORMAT_BGRx, GST_VIDEO_FORMAT_BGRx, TRUE, FALSE, FALSE, TRUE, TRUE,
7693 FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7695 {GST_VIDEO_FORMAT_ARGB64, GST_VIDEO_FORMAT_ARGB64, TRUE, FALSE, FALSE, TRUE,
7696 TRUE, TRUE, FALSE, FALSE, 0, 0, convert_scale_planes},
7697 {GST_VIDEO_FORMAT_AYUV64, GST_VIDEO_FORMAT_AYUV64, TRUE, FALSE, FALSE, TRUE,
7698 TRUE, TRUE, FALSE, FALSE, 0, 0, convert_scale_planes},
7700 {GST_VIDEO_FORMAT_GRAY16_LE, GST_VIDEO_FORMAT_GRAY16_LE, TRUE, FALSE, FALSE,
7701 TRUE, TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7702 {GST_VIDEO_FORMAT_GRAY16_BE, GST_VIDEO_FORMAT_GRAY16_BE, TRUE, FALSE, FALSE,
7703 TRUE, TRUE, FALSE, FALSE, FALSE, 0, 0, convert_scale_planes},
7707 video_converter_lookup_fastpath (GstVideoConverter * convert)
7710 GstVideoFormat in_format, out_format;
7711 GstVideoTransferFunction in_transf, out_transf;
7712 gboolean interlaced, same_matrix, same_primaries, same_size, crop, border;
7713 gboolean need_copy, need_set, need_mult;
7715 guint in_bpp, out_bpp;
7717 width = GST_VIDEO_INFO_WIDTH (&convert->in_info);
7718 height = GST_VIDEO_INFO_FIELD_HEIGHT (&convert->in_info);
7720 if (GET_OPT_DITHER_QUANTIZATION (convert) != 1)
7723 in_bpp = convert->in_info.finfo->bits;
7724 out_bpp = convert->out_info.finfo->bits;
7726 /* we don't do gamma conversion in fastpath */
7727 in_transf = convert->in_info.colorimetry.transfer;
7728 out_transf = convert->out_info.colorimetry.transfer;
7730 same_size = (width == convert->out_width && height == convert->out_height);
7732 /* fastpaths don't do gamma */
7733 if (CHECK_GAMMA_REMAP (convert) && (!same_size
7734 || !gst_video_transfer_function_is_equivalent (in_transf, in_bpp,
7735 out_transf, out_bpp)))
7738 need_copy = (convert->alpha_mode & ALPHA_MODE_COPY) == ALPHA_MODE_COPY;
7739 need_set = (convert->alpha_mode & ALPHA_MODE_SET) == ALPHA_MODE_SET;
7740 need_mult = (convert->alpha_mode & ALPHA_MODE_MULT) == ALPHA_MODE_MULT;
7741 GST_DEBUG ("alpha copy %d, set %d, mult %d", need_copy, need_set, need_mult);
7743 in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
7744 out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
7746 if (CHECK_MATRIX_NONE (convert)) {
7749 GstVideoColorMatrix in_matrix, out_matrix;
7751 in_matrix = convert->in_info.colorimetry.matrix;
7752 out_matrix = convert->out_info.colorimetry.matrix;
7753 same_matrix = in_matrix == out_matrix;
7756 if (CHECK_PRIMARIES_NONE (convert)) {
7757 same_primaries = TRUE;
7759 GstVideoColorPrimaries in_primaries, out_primaries;
7761 in_primaries = convert->in_info.colorimetry.primaries;
7762 out_primaries = convert->out_info.colorimetry.primaries;
7763 same_primaries = in_primaries == out_primaries;
7766 interlaced = GST_VIDEO_INFO_IS_INTERLACED (&convert->in_info);
7767 interlaced |= GST_VIDEO_INFO_IS_INTERLACED (&convert->out_info);
7769 crop = convert->in_x || convert->in_y
7770 || convert->in_width < convert->in_maxwidth
7771 || convert->in_height < convert->in_maxheight;
7772 border = convert->out_x || convert->out_y
7773 || convert->out_width < convert->out_maxwidth
7774 || convert->out_height < convert->out_maxheight;
7776 for (i = 0; i < G_N_ELEMENTS (transforms); i++) {
7777 if (transforms[i].in_format == in_format &&
7778 transforms[i].out_format == out_format &&
7779 (transforms[i].keeps_interlaced || !interlaced) &&
7780 (transforms[i].needs_color_matrix || (same_matrix && same_primaries))
7781 && (!transforms[i].keeps_size || same_size)
7782 && (transforms[i].width_align & width) == 0
7783 && (transforms[i].height_align & height) == 0
7784 && (transforms[i].do_crop || !crop)
7785 && (transforms[i].do_border || !border)
7786 && (transforms[i].alpha_copy || !need_copy)
7787 && (transforms[i].alpha_set || !need_set)
7788 && (transforms[i].alpha_mult || !need_mult)) {
7791 GST_DEBUG ("using fastpath");
7792 if (transforms[i].needs_color_matrix)
7793 video_converter_compute_matrix (convert);
7794 convert->convert = transforms[i].convert;
7797 g_new (guint16 *, convert->conversion_runner->n_threads);
7798 for (j = 0; j < convert->conversion_runner->n_threads; j++)
7799 convert->tmpline[j] = g_malloc0 (sizeof (guint16) * (width + 8) * 4);
7801 if (!transforms[i].keeps_size)
7802 if (!setup_scale (convert))
7805 setup_borderline (convert);
7809 GST_DEBUG ("no fastpath found");