summaryrefslogtreecommitdiff
path: root/avstream/avscamera/sys/Synthesizer.h
blob: 94506b1df5f189bf8c6c8b93a2a73cd7dfad6fe0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
/**************************************************************************

    A/V Stream Camera Sample

    Copyright (c) 2014, Microsoft Corporation.

    File:

        Synthesizer.h

    Abstract:

        This file contains the definition of CSynthesizer.

        The base image synthesis and overlay class.  These classes provide
        image synthesis (pixel, color-bar, etc...) onto buffers of various
        formats.

        Internally, all CSynthesizer objects represent a pixel as a 32 bit
        quantity with 8 bits per sample.  The base CSynthesizer implements
        all rendering functionality with this assumption in mind.  It
        simplifies rendering substantially and means we do not need to re-
        implement rendering functions for each format.  
        
        Most end formats can be synthesized from this uncompressed format 
        with overhead that is slightly worse than a copy.  Color spaces are
        handled by using a rendering palette that is unique for each.

    History:

        created 04/14/2014

**************************************************************************/

#pragma once

//
// COLOR:
//
// Pixel color for placement onto the synthesis buffer.
//
typedef enum
{

    BLACK = 0,
    WHITE,
    YELLOW,
    CYAN,
    GREEN,
    MAGENTA,
    RED,
    BLUE,
    GREY,

    TEXT_COLOR,           //  Used to offset text

    MAX_COLOR,
    TRANSPARENT,

} COLOR;

#define CHANNEL_YCrCb   ( MF_HISTOGRAM_CHANNEL_Y | MF_HISTOGRAM_CHANNEL_Cr | MF_HISTOGRAM_CHANNEL_Cb )
#define CHANNEL_RGB     ( MF_HISTOGRAM_CHANNEL_R | MF_HISTOGRAM_CHANNEL_G  | MF_HISTOGRAM_CHANNEL_B  )
#define CHANNEL_NONE    ( 0 )

//
// POSITION_CENTER:
//
// Only useful for text overlay.  This can be substituted for LocX or LocY
// in order to center the text screen on the synthesis buffer.
//
#define POSITION_CENTER ((ULONG)-1)

//
//  Initializer class for a KS_RGBQUAD
//
class CKsRgbQuad : public KS_RGBQUAD
{
public:
    //  Initializer ctor
    CKsRgbQuad(
        BYTE r=0,
        BYTE g=0,
        BYTE b=0 )
    {
        rgbBlue     = b;
        rgbGreen    = g;
        rgbRed      = r;
        rgbReserved = 0;
    }
};

/*************************************************

    CSynthesizer

    This class synthesizes images in various formats for output from the
    capture filter.  It is capable of performing various text overlays onto
    the image surface.

    The base synthesizer is essentially the XRGB Synthesizer.  For YUV, we
    repurpose the color primaries and provide a different definition for the
    color pallette.  A call to CSynthesizer::Commit(buffer) will reformat the
    internal representation and down-sample the color primaries, as necessary
    into the supplied buffer.

*************************************************/

typedef
UCHAR   UCHAR4[4];

class CSynthesizer :
    public CNonCopyable
{
public:
    enum Attribute
    {
        RelativePts,
        QpcTime,
        FrameNumber,
        MAX_Attribute
    };

protected:

    static
    const UCHAR m_FontData [2][256][8];
    static
    const COLOR m_ColorBars[8];

    //  These values are used by Synthesize() for display purposes.
    LONGLONG    m_Attrib[MAX_Attribute];

    //  This value is used to fudge a rotated image.
    AcpiPldRotation
                m_Rotation;

    //
    // The width and height the synthesizer is set to.
    //
    ULONG m_Width;
    ULONG m_Height;

    //
    //  The synthesis buffer:
    //
    //  This buffer points to an array of KS_RGBQUAD.  Internally we synthesize
    //  images in an uncompressed format, because it is at least as fast to
    //  composite an image in such a format and convert to the target compressed
    //  format in a final pass over the image.
    //
    //  An uncompressed format also has less loss of fidelity.  For instance,
    //  NV12 only contains 1 chroma sample per macro-pixel (2x2).  Once this
    //  macro pixel is rendered, compositing additional color information
    //  into it results in a loss of color precision / fidelity.
    //
    PUCHAR  m_Buffer;               //  pointer to pixel data
    ULONG   m_Length;               //  size of the buffer in bytes
    LONG    m_SynthesisStride;      //  size of scan line in bytes

    //
    //  The assumed stride of our output format.  Currently used by YUY2 and
    //  all image captures.  This value should be initialized by
    //  the derived classes.
    //
    LONG    m_OutputStride;

    //  Bitmap with a gradient applied for each color in the color pallet.
    CKsRgbQuad *m_GradientBmp;

    //
    // The default cursor.  This is a pointer into the synthesis buffer where
    // a non specific PutPixel will be placed.
    //
    PUCHAR m_Cursor;

    //
    //  A printable name identifying this format.
    //
    const CHAR *m_FormatName;

    //
    //  A color palette for this colorspace.
    //
    //  Specifying a unique color palette is a cheap method for switching
    //  between RGB and YUV color spaces.  A derived class is free to assign
    //  this to any table it chooses.  It can be used to either change the
    //  colors used for rendering, or it can be used to support a new (or
    //  slightly different) color space.
    //
    const UCHAR4    *m_Colors;

    //
    //  A bitset specifying the color primaries used by this format.
    //  (Used by Histogram.)
    //
    ULONG   m_ChannelMask;

    //
    //  Debugging values
    //
    LARGE_INTEGER   m_Frequency;
    LONGLONG    m_SynthesisTime;
    ULONG       m_SynthesisCount;
    LONGLONG    m_CommitTime;
    ULONG       m_CommitCount;
    ULONGLONG   m_StartTime;

public:

    //
    // DEFAULT CONSTRUCTOR
    //
    CSynthesizer(
        const CHAR *Name="[Unknown]",
        ULONG ChannelMask=0,
        ULONG Width=0,
        ULONG Height=0
    )
        : m_Width(Width)
        , m_Height(Height)
        , m_Buffer(nullptr)
        , m_Cursor(nullptr)
        , m_GradientBmp(nullptr)
        , m_SynthesisStride(m_Width * sizeof(KS_RGBQUAD))
        , m_OutputStride(0)
        , m_FormatName(Name)
        , m_ChannelMask(ChannelMask)
        , m_SynthesisCount(0)
        , m_SynthesisTime(0)
        , m_CommitCount(0)
        , m_CommitTime(0)
        , m_Rotation(AcpiPldRotation0)
        , m_Colors(nullptr)
        , m_StartTime(0)
    {
        m_Length = Height * m_SynthesisStride;
        KeQueryPerformanceCounter(&m_Frequency).QuadPart;
        for( ULONG i=0; i<MAX_Attribute; i++ )
        {
            m_Attrib[i]=0;
        }
    }

    //
    // DESTRUCTOR:
    //
    virtual
    ~CSynthesizer()
    {}

    //
    // PutPixel():
    //
    // Place a pixel at the default cursor location.  The cursor location
    // must be set via GetImageLocation(x, y).
    //
    virtual
    void
    PutPixel (
        COLOR Color
    );

    //
    // PutPixel():
    //
    // Place a pixel at the default cursor location.  The cursor location
    // must be set via GetImageLocation(x, y).
    //
    virtual
    void
    PutPixel (
        UCHAR colorR,
        UCHAR colorB,
        UCHAR colorG
    );

    //
    //  Create a horizontal color bar that slowly fades from the specified
    //  color to black.
    //
    //  Note: To generalize, this function could specify the height of the
    //        color bar instead of inferring it.
    //
    void
    ApplyGradient(
        _In_    ULONG LocY,
        _In_    COLOR Gradient
    );


    //
    // SetImageSize():
    //
    // Set the image size of the synthesis buffer.
    //
    void
    SetImageSize (
        _In_    ULONG Width,
        _In_    ULONG Height
    )
    {
        m_Width = Width;
        m_Height = Height;
    }

    //
    // Initialize()
    //
    //  Set the buffer the synthesizer generates images to.
    //  Override to do any additional processing you think is needed.
    //
    virtual
    BOOLEAN
    Initialize();

    //
    //  Destroy()
    //
    //  Clean up from initialize.
    //
    virtual
    void
    Destroy();

    //
    // SynthesizeBars():
    //
    // Synthesize EIA-189-A standard color bars.
    //
    virtual
    NTSTATUS
    SynthesizeBars();

    //
    //  Synthesize
    //
    //  Fill the image buffer with some base image. All h/w simulations will
    //  call this function to generate a base image
    //
    virtual
    NTSTATUS
    Synthesize();

    //
    //  Commit
    //
    //  Copy (and reformat, if necessary) pixels from the internal scratch
    //  buffer.  If the output format decimates chrominance, do it here.
    //
    virtual
    _Success_(return > 0)
    ULONG
    Commit(
        _Out_writes_bytes_(Size)
        PUCHAR  Buffer,
        _In_    ULONG   Size,
        _In_    ULONG   Stride
    )=0;

    //
    //  Commit
    //
    //  Note: The stride needs to be a function of the bits per pixel of the
    //        OUTPUT format - not the format we store it in.  The class ctor
    //        must initialize m_OutputStride to a default stride value.
    //
    _Success_(return > 0)
    ULONG
    Commit(
        _Out_writes_bytes_(Size)
        PUCHAR  Buffer,
        _In_    ULONG   Size
    )
    {
        return Commit( Buffer, Size, m_OutputStride );
    }

    //
    //  Histogram
    //
    //  Fill an array with histogram data.  Each parameter is optional.
    //
    void
    Histogram(
        _Out_writes_opt_(256)
        PULONG  HistogramP0,        //  rgbRed
        _Out_writes_opt_(256)
        PULONG  HistogramP1,        //  rgbGreen
        _Out_writes_opt_(256)
        PULONG  HistogramP2         //  rgbBlue
    );

    //
    //  Synthesize
    //
    //  Fill the image buffer with some base image. All h/w simulations will
    //  call this function to generate a base image
    //
    NTSTATUS
    DoSynthesize();

    //
    //  Commit
    //
    //  Copy (and reformat, if necessary) pixels from the internal scratch
    //  buffer.  If the output format decimates chrominance, do it here.
    //
    _Success_(return > 0)
    ULONG
    DoCommit(
        _Out_writes_bytes_(Size)
        PUCHAR  Buffer,
        _In_    ULONG   Size,
        _In_    ULONG   Stride
    );

    //
    //  DoCommit
    //
    //  Note: The stride needs to be a function of the bits per pixel of the
    //        OUTPUT format - not the format we store it in.  The class ctor
    //        must initialize m_OutputStride to a default stride value.
    //
    _Success_(return > 0)
    ULONG
    DoCommit(
        _Out_writes_bytes_(Size)
        PUCHAR  Buffer,
        _In_    ULONG   Size
    );

    //
    // OverlayText():
    //
    // Overlay a text string onto the image.
    //
    void
    OverlayText (
        _In_ ULONG LocX,
        _In_ ULONG LocY,
        _In_ ULONG Scaling,
        _In_ LPSTR Text,
        _In_ COLOR BgColor,
        _In_ COLOR FgColor
    );

    virtual
    void
    EncodeNumber(
        _In_ ULONG LocY,
        _In_ UINT32 Number,
        _In_ COLOR LowColor,
        _In_ COLOR HighColor
    );

    void
    Set( Attribute Attrib, LONGLONG Info )
    {
        m_Attrib[Attrib] = Info;
    }

    void
    SetRotation( AcpiPldRotation Rotation )
    {
        m_Rotation = Rotation;
    }

    //
    //  GetChannelMask
    //
    //  Get the color channel mask associated with this format.
    //
    ULONG
    GetChannelMask() const
    {
        return m_ChannelMask;
    }

protected:
    //
    //  GetPalette
    //
    //  Get a pointer to an array of palette colors.  Used mostly to handle
    //  different color primaries.  Location of the primary must agree with
    //  Commit().
    //
    virtual
    const UCHAR4 *
    GetPalette()
    {
        return nullptr;
    }

    //
    // GetImageLocation
    //
    // Get the location into the image buffer for a specific X/Y location.
    // This also sets the synthesizer's default cursor to the position
    // LocX, LocY.
    //
    PUCHAR
    GetImageLocation (
        _In_    ULONG LocX,
        _In_    ULONG LocY
    )
    {
        return
            m_Cursor =
                (m_Buffer + (sizeof(CKsRgbQuad) * LocX) + (LocY * m_SynthesisStride));
    }

};