linux/include/media/v4l2-tpg.h
<<
>>
Prefs
   1/*
   2 * v4l2-tpg.h - Test Pattern Generator
   3 *
   4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
   5 *
   6 * This program is free software; you may redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; version 2 of the License.
   9 *
  10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17 * SOFTWARE.
  18 */
  19
  20#ifndef _V4L2_TPG_H_
  21#define _V4L2_TPG_H_
  22
  23#include <linux/types.h>
  24#include <linux/errno.h>
  25#include <linux/random.h>
  26#include <linux/slab.h>
  27#include <linux/vmalloc.h>
  28#include <linux/videodev2.h>
  29#include <media/v4l2-tpg-colors.h>
  30
  31enum tpg_pattern {
  32        TPG_PAT_75_COLORBAR,
  33        TPG_PAT_100_COLORBAR,
  34        TPG_PAT_CSC_COLORBAR,
  35        TPG_PAT_100_HCOLORBAR,
  36        TPG_PAT_100_COLORSQUARES,
  37        TPG_PAT_BLACK,
  38        TPG_PAT_WHITE,
  39        TPG_PAT_RED,
  40        TPG_PAT_GREEN,
  41        TPG_PAT_BLUE,
  42        TPG_PAT_CHECKERS_16X16,
  43        TPG_PAT_CHECKERS_2X2,
  44        TPG_PAT_CHECKERS_1X1,
  45        TPG_PAT_COLOR_CHECKERS_2X2,
  46        TPG_PAT_COLOR_CHECKERS_1X1,
  47        TPG_PAT_ALTERNATING_HLINES,
  48        TPG_PAT_ALTERNATING_VLINES,
  49        TPG_PAT_CROSS_1_PIXEL,
  50        TPG_PAT_CROSS_2_PIXELS,
  51        TPG_PAT_CROSS_10_PIXELS,
  52        TPG_PAT_GRAY_RAMP,
  53
  54        /* Must be the last pattern */
  55        TPG_PAT_NOISE,
  56};
  57
  58extern const char * const tpg_pattern_strings[];
  59
  60enum tpg_quality {
  61        TPG_QUAL_COLOR,
  62        TPG_QUAL_GRAY,
  63        TPG_QUAL_NOISE
  64};
  65
  66enum tpg_video_aspect {
  67        TPG_VIDEO_ASPECT_IMAGE,
  68        TPG_VIDEO_ASPECT_4X3,
  69        TPG_VIDEO_ASPECT_14X9_CENTRE,
  70        TPG_VIDEO_ASPECT_16X9_CENTRE,
  71        TPG_VIDEO_ASPECT_16X9_ANAMORPHIC,
  72};
  73
  74enum tpg_pixel_aspect {
  75        TPG_PIXEL_ASPECT_SQUARE,
  76        TPG_PIXEL_ASPECT_NTSC,
  77        TPG_PIXEL_ASPECT_PAL,
  78};
  79
  80enum tpg_move_mode {
  81        TPG_MOVE_NEG_FAST,
  82        TPG_MOVE_NEG,
  83        TPG_MOVE_NEG_SLOW,
  84        TPG_MOVE_NONE,
  85        TPG_MOVE_POS_SLOW,
  86        TPG_MOVE_POS,
  87        TPG_MOVE_POS_FAST,
  88};
  89
  90enum tgp_color_enc {
  91        TGP_COLOR_ENC_RGB,
  92        TGP_COLOR_ENC_YCBCR,
  93        TGP_COLOR_ENC_HSV,
  94        TGP_COLOR_ENC_LUMA,
  95};
  96
  97extern const char * const tpg_aspect_strings[];
  98
  99#define TPG_MAX_PLANES 3
 100#define TPG_MAX_PAT_LINES 8
 101
 102struct tpg_data {
 103        /* Source frame size */
 104        unsigned                        src_width, src_height;
 105        /* Buffer height */
 106        unsigned                        buf_height;
 107        /* Scaled output frame size */
 108        unsigned                        scaled_width;
 109        u32                             field;
 110        bool                            field_alternate;
 111        /* crop coordinates are frame-based */
 112        struct v4l2_rect                crop;
 113        /* compose coordinates are format-based */
 114        struct v4l2_rect                compose;
 115        /* border and square coordinates are frame-based */
 116        struct v4l2_rect                border;
 117        struct v4l2_rect                square;
 118
 119        /* Color-related fields */
 120        enum tpg_quality                qual;
 121        unsigned                        qual_offset;
 122        u8                              alpha_component;
 123        bool                            alpha_red_only;
 124        u8                              brightness;
 125        u8                              contrast;
 126        u8                              saturation;
 127        s16                             hue;
 128        u32                             fourcc;
 129        enum tgp_color_enc              color_enc;
 130        u32                             colorspace;
 131        u32                             xfer_func;
 132        u32                             ycbcr_enc;
 133        u32                             hsv_enc;
 134        /*
 135         * Stores the actual transfer function, i.e. will never be
 136         * V4L2_XFER_FUNC_DEFAULT.
 137         */
 138        u32                             real_xfer_func;
 139        /*
 140         * Stores the actual Y'CbCr encoding, i.e. will never be
 141         * V4L2_YCBCR_ENC_DEFAULT.
 142         */
 143        u32                             real_hsv_enc;
 144        u32                             real_ycbcr_enc;
 145        u32                             quantization;
 146        /*
 147         * Stores the actual quantization, i.e. will never be
 148         * V4L2_QUANTIZATION_DEFAULT.
 149         */
 150        u32                             real_quantization;
 151        enum tpg_video_aspect           vid_aspect;
 152        enum tpg_pixel_aspect           pix_aspect;
 153        unsigned                        rgb_range;
 154        unsigned                        real_rgb_range;
 155        unsigned                        buffers;
 156        unsigned                        planes;
 157        bool                            interleaved;
 158        u8                              vdownsampling[TPG_MAX_PLANES];
 159        u8                              hdownsampling[TPG_MAX_PLANES];
 160        /*
 161         * horizontal positions must be ANDed with this value to enforce
 162         * correct boundaries for packed YUYV values.
 163         */
 164        unsigned                        hmask[TPG_MAX_PLANES];
 165        /* Used to store the colors in native format, either RGB or YUV */
 166        u8                              colors[TPG_COLOR_MAX][3];
 167        u8                              textfg[TPG_MAX_PLANES][8], textbg[TPG_MAX_PLANES][8];
 168        /* size in bytes for two pixels in each plane */
 169        unsigned                        twopixelsize[TPG_MAX_PLANES];
 170        unsigned                        bytesperline[TPG_MAX_PLANES];
 171
 172        /* Configuration */
 173        enum tpg_pattern                pattern;
 174        bool                            hflip;
 175        bool                            vflip;
 176        unsigned                        perc_fill;
 177        bool                            perc_fill_blank;
 178        bool                            show_border;
 179        bool                            show_square;
 180        bool                            insert_sav;
 181        bool                            insert_eav;
 182
 183        /* Test pattern movement */
 184        enum tpg_move_mode              mv_hor_mode;
 185        int                             mv_hor_count;
 186        int                             mv_hor_step;
 187        enum tpg_move_mode              mv_vert_mode;
 188        int                             mv_vert_count;
 189        int                             mv_vert_step;
 190
 191        bool                            recalc_colors;
 192        bool                            recalc_lines;
 193        bool                            recalc_square_border;
 194
 195        /* Used to store TPG_MAX_PAT_LINES lines, each with up to two planes */
 196        unsigned                        max_line_width;
 197        u8                              *lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES];
 198        u8                              *downsampled_lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES];
 199        u8                              *random_line[TPG_MAX_PLANES];
 200        u8                              *contrast_line[TPG_MAX_PLANES];
 201        u8                              *black_line[TPG_MAX_PLANES];
 202};
 203
 204void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h);
 205int tpg_alloc(struct tpg_data *tpg, unsigned max_w);
 206void tpg_free(struct tpg_data *tpg);
 207void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height,
 208                       u32 field);
 209void tpg_log_status(struct tpg_data *tpg);
 210
 211void tpg_set_font(const u8 *f);
 212void tpg_gen_text(const struct tpg_data *tpg,
 213                u8 *basep[TPG_MAX_PLANES][2], int y, int x, char *text);
 214void tpg_calc_text_basep(struct tpg_data *tpg,
 215                u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf);
 216unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line);
 217void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std,
 218                           unsigned p, u8 *vbuf);
 219void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std,
 220                    unsigned p, u8 *vbuf);
 221bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc);
 222void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop,
 223                const struct v4l2_rect *compose);
 224
 225static inline void tpg_s_pattern(struct tpg_data *tpg, enum tpg_pattern pattern)
 226{
 227        if (tpg->pattern == pattern)
 228                return;
 229        tpg->pattern = pattern;
 230        tpg->recalc_colors = true;
 231}
 232
 233static inline void tpg_s_quality(struct tpg_data *tpg,
 234                                    enum tpg_quality qual, unsigned qual_offset)
 235{
 236        if (tpg->qual == qual && tpg->qual_offset == qual_offset)
 237                return;
 238        tpg->qual = qual;
 239        tpg->qual_offset = qual_offset;
 240        tpg->recalc_colors = true;
 241}
 242
 243static inline enum tpg_quality tpg_g_quality(const struct tpg_data *tpg)
 244{
 245        return tpg->qual;
 246}
 247
 248static inline void tpg_s_alpha_component(struct tpg_data *tpg,
 249                                            u8 alpha_component)
 250{
 251        if (tpg->alpha_component == alpha_component)
 252                return;
 253        tpg->alpha_component = alpha_component;
 254        tpg->recalc_colors = true;
 255}
 256
 257static inline void tpg_s_alpha_mode(struct tpg_data *tpg,
 258                                            bool red_only)
 259{
 260        if (tpg->alpha_red_only == red_only)
 261                return;
 262        tpg->alpha_red_only = red_only;
 263        tpg->recalc_colors = true;
 264}
 265
 266static inline void tpg_s_brightness(struct tpg_data *tpg,
 267                                        u8 brightness)
 268{
 269        if (tpg->brightness == brightness)
 270                return;
 271        tpg->brightness = brightness;
 272        tpg->recalc_colors = true;
 273}
 274
 275static inline void tpg_s_contrast(struct tpg_data *tpg,
 276                                        u8 contrast)
 277{
 278        if (tpg->contrast == contrast)
 279                return;
 280        tpg->contrast = contrast;
 281        tpg->recalc_colors = true;
 282}
 283
 284static inline void tpg_s_saturation(struct tpg_data *tpg,
 285                                        u8 saturation)
 286{
 287        if (tpg->saturation == saturation)
 288                return;
 289        tpg->saturation = saturation;
 290        tpg->recalc_colors = true;
 291}
 292
 293static inline void tpg_s_hue(struct tpg_data *tpg,
 294                                        s16 hue)
 295{
 296        if (tpg->hue == hue)
 297                return;
 298        tpg->hue = hue;
 299        tpg->recalc_colors = true;
 300}
 301
 302static inline void tpg_s_rgb_range(struct tpg_data *tpg,
 303                                        unsigned rgb_range)
 304{
 305        if (tpg->rgb_range == rgb_range)
 306                return;
 307        tpg->rgb_range = rgb_range;
 308        tpg->recalc_colors = true;
 309}
 310
 311static inline void tpg_s_real_rgb_range(struct tpg_data *tpg,
 312                                        unsigned rgb_range)
 313{
 314        if (tpg->real_rgb_range == rgb_range)
 315                return;
 316        tpg->real_rgb_range = rgb_range;
 317        tpg->recalc_colors = true;
 318}
 319
 320static inline void tpg_s_colorspace(struct tpg_data *tpg, u32 colorspace)
 321{
 322        if (tpg->colorspace == colorspace)
 323                return;
 324        tpg->colorspace = colorspace;
 325        tpg->recalc_colors = true;
 326}
 327
 328static inline u32 tpg_g_colorspace(const struct tpg_data *tpg)
 329{
 330        return tpg->colorspace;
 331}
 332
 333static inline void tpg_s_ycbcr_enc(struct tpg_data *tpg, u32 ycbcr_enc)
 334{
 335        if (tpg->ycbcr_enc == ycbcr_enc)
 336                return;
 337        tpg->ycbcr_enc = ycbcr_enc;
 338        tpg->recalc_colors = true;
 339}
 340
 341static inline u32 tpg_g_ycbcr_enc(const struct tpg_data *tpg)
 342{
 343        return tpg->ycbcr_enc;
 344}
 345
 346static inline void tpg_s_hsv_enc(struct tpg_data *tpg, u32 hsv_enc)
 347{
 348        if (tpg->hsv_enc == hsv_enc)
 349                return;
 350        tpg->hsv_enc = hsv_enc;
 351        tpg->recalc_colors = true;
 352}
 353
 354static inline u32 tpg_g_hsv_enc(const struct tpg_data *tpg)
 355{
 356        return tpg->hsv_enc;
 357}
 358
 359static inline void tpg_s_xfer_func(struct tpg_data *tpg, u32 xfer_func)
 360{
 361        if (tpg->xfer_func == xfer_func)
 362                return;
 363        tpg->xfer_func = xfer_func;
 364        tpg->recalc_colors = true;
 365}
 366
 367static inline u32 tpg_g_xfer_func(const struct tpg_data *tpg)
 368{
 369        return tpg->xfer_func;
 370}
 371
 372static inline void tpg_s_quantization(struct tpg_data *tpg, u32 quantization)
 373{
 374        if (tpg->quantization == quantization)
 375                return;
 376        tpg->quantization = quantization;
 377        tpg->recalc_colors = true;
 378}
 379
 380static inline u32 tpg_g_quantization(const struct tpg_data *tpg)
 381{
 382        return tpg->quantization;
 383}
 384
 385static inline unsigned tpg_g_buffers(const struct tpg_data *tpg)
 386{
 387        return tpg->buffers;
 388}
 389
 390static inline unsigned tpg_g_planes(const struct tpg_data *tpg)
 391{
 392        return tpg->interleaved ? 1 : tpg->planes;
 393}
 394
 395static inline bool tpg_g_interleaved(const struct tpg_data *tpg)
 396{
 397        return tpg->interleaved;
 398}
 399
 400static inline unsigned tpg_g_twopixelsize(const struct tpg_data *tpg, unsigned plane)
 401{
 402        return tpg->twopixelsize[plane];
 403}
 404
 405static inline unsigned tpg_hdiv(const struct tpg_data *tpg,
 406                                  unsigned plane, unsigned x)
 407{
 408        return ((x / tpg->hdownsampling[plane]) & tpg->hmask[plane]) *
 409                tpg->twopixelsize[plane] / 2;
 410}
 411
 412static inline unsigned tpg_hscale(const struct tpg_data *tpg, unsigned x)
 413{
 414        return (x * tpg->scaled_width) / tpg->src_width;
 415}
 416
 417static inline unsigned tpg_hscale_div(const struct tpg_data *tpg,
 418                                      unsigned plane, unsigned x)
 419{
 420        return tpg_hdiv(tpg, plane, tpg_hscale(tpg, x));
 421}
 422
 423static inline unsigned tpg_g_bytesperline(const struct tpg_data *tpg, unsigned plane)
 424{
 425        return tpg->bytesperline[plane];
 426}
 427
 428static inline void tpg_s_bytesperline(struct tpg_data *tpg, unsigned plane, unsigned bpl)
 429{
 430        unsigned p;
 431
 432        if (tpg->buffers > 1) {
 433                tpg->bytesperline[plane] = bpl;
 434                return;
 435        }
 436
 437        for (p = 0; p < tpg_g_planes(tpg); p++) {
 438                unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0];
 439
 440                tpg->bytesperline[p] = plane_w / tpg->hdownsampling[p];
 441        }
 442        if (tpg_g_interleaved(tpg))
 443                tpg->bytesperline[1] = tpg->bytesperline[0];
 444}
 445
 446
 447static inline unsigned tpg_g_line_width(const struct tpg_data *tpg, unsigned plane)
 448{
 449        unsigned w = 0;
 450        unsigned p;
 451
 452        if (tpg->buffers > 1)
 453                return tpg_g_bytesperline(tpg, plane);
 454        for (p = 0; p < tpg_g_planes(tpg); p++) {
 455                unsigned plane_w = tpg_g_bytesperline(tpg, p);
 456
 457                w += plane_w / tpg->vdownsampling[p];
 458        }
 459        return w;
 460}
 461
 462static inline unsigned tpg_calc_line_width(const struct tpg_data *tpg,
 463                                           unsigned plane, unsigned bpl)
 464{
 465        unsigned w = 0;
 466        unsigned p;
 467
 468        if (tpg->buffers > 1)
 469                return bpl;
 470        for (p = 0; p < tpg_g_planes(tpg); p++) {
 471                unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0];
 472
 473                plane_w /= tpg->hdownsampling[p];
 474                w += plane_w / tpg->vdownsampling[p];
 475        }
 476        return w;
 477}
 478
 479static inline unsigned tpg_calc_plane_size(const struct tpg_data *tpg, unsigned plane)
 480{
 481        if (plane >= tpg_g_planes(tpg))
 482                return 0;
 483
 484        return tpg_g_bytesperline(tpg, plane) * tpg->buf_height /
 485               tpg->vdownsampling[plane];
 486}
 487
 488static inline void tpg_s_buf_height(struct tpg_data *tpg, unsigned h)
 489{
 490        tpg->buf_height = h;
 491}
 492
 493static inline void tpg_s_field(struct tpg_data *tpg, unsigned field, bool alternate)
 494{
 495        tpg->field = field;
 496        tpg->field_alternate = alternate;
 497}
 498
 499static inline void tpg_s_perc_fill(struct tpg_data *tpg,
 500                                      unsigned perc_fill)
 501{
 502        tpg->perc_fill = perc_fill;
 503}
 504
 505static inline unsigned tpg_g_perc_fill(const struct tpg_data *tpg)
 506{
 507        return tpg->perc_fill;
 508}
 509
 510static inline void tpg_s_perc_fill_blank(struct tpg_data *tpg,
 511                                         bool perc_fill_blank)
 512{
 513        tpg->perc_fill_blank = perc_fill_blank;
 514}
 515
 516static inline void tpg_s_video_aspect(struct tpg_data *tpg,
 517                                        enum tpg_video_aspect vid_aspect)
 518{
 519        if (tpg->vid_aspect == vid_aspect)
 520                return;
 521        tpg->vid_aspect = vid_aspect;
 522        tpg->recalc_square_border = true;
 523}
 524
 525static inline enum tpg_video_aspect tpg_g_video_aspect(const struct tpg_data *tpg)
 526{
 527        return tpg->vid_aspect;
 528}
 529
 530static inline void tpg_s_pixel_aspect(struct tpg_data *tpg,
 531                                        enum tpg_pixel_aspect pix_aspect)
 532{
 533        if (tpg->pix_aspect == pix_aspect)
 534                return;
 535        tpg->pix_aspect = pix_aspect;
 536        tpg->recalc_square_border = true;
 537}
 538
 539static inline void tpg_s_show_border(struct tpg_data *tpg,
 540                                        bool show_border)
 541{
 542        tpg->show_border = show_border;
 543}
 544
 545static inline void tpg_s_show_square(struct tpg_data *tpg,
 546                                        bool show_square)
 547{
 548        tpg->show_square = show_square;
 549}
 550
 551static inline void tpg_s_insert_sav(struct tpg_data *tpg, bool insert_sav)
 552{
 553        tpg->insert_sav = insert_sav;
 554}
 555
 556static inline void tpg_s_insert_eav(struct tpg_data *tpg, bool insert_eav)
 557{
 558        tpg->insert_eav = insert_eav;
 559}
 560
 561void tpg_update_mv_step(struct tpg_data *tpg);
 562
 563static inline void tpg_s_mv_hor_mode(struct tpg_data *tpg,
 564                                enum tpg_move_mode mv_hor_mode)
 565{
 566        tpg->mv_hor_mode = mv_hor_mode;
 567        tpg_update_mv_step(tpg);
 568}
 569
 570static inline void tpg_s_mv_vert_mode(struct tpg_data *tpg,
 571                                enum tpg_move_mode mv_vert_mode)
 572{
 573        tpg->mv_vert_mode = mv_vert_mode;
 574        tpg_update_mv_step(tpg);
 575}
 576
 577static inline void tpg_init_mv_count(struct tpg_data *tpg)
 578{
 579        tpg->mv_hor_count = tpg->mv_vert_count = 0;
 580}
 581
 582static inline void tpg_update_mv_count(struct tpg_data *tpg, bool frame_is_field)
 583{
 584        tpg->mv_hor_count += tpg->mv_hor_step * (frame_is_field ? 1 : 2);
 585        tpg->mv_vert_count += tpg->mv_vert_step * (frame_is_field ? 1 : 2);
 586}
 587
 588static inline void tpg_s_hflip(struct tpg_data *tpg, bool hflip)
 589{
 590        if (tpg->hflip == hflip)
 591                return;
 592        tpg->hflip = hflip;
 593        tpg_update_mv_step(tpg);
 594        tpg->recalc_lines = true;
 595}
 596
 597static inline bool tpg_g_hflip(const struct tpg_data *tpg)
 598{
 599        return tpg->hflip;
 600}
 601
 602static inline void tpg_s_vflip(struct tpg_data *tpg, bool vflip)
 603{
 604        tpg->vflip = vflip;
 605}
 606
 607static inline bool tpg_g_vflip(const struct tpg_data *tpg)
 608{
 609        return tpg->vflip;
 610}
 611
 612static inline bool tpg_pattern_is_static(const struct tpg_data *tpg)
 613{
 614        return tpg->pattern != TPG_PAT_NOISE &&
 615               tpg->mv_hor_mode == TPG_MOVE_NONE &&
 616               tpg->mv_vert_mode == TPG_MOVE_NONE;
 617}
 618
 619#endif
 620